aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorDave Jones <davej@redhat.com>2006-04-18 18:19:55 -0400
committerDave Jones <davej@redhat.com>2006-04-18 18:19:55 -0400
commitf1f76afd71e0f17af9a35fcb649f4bab53304a4d (patch)
treea56257b13a0eda4a9b7e950c3b85adad16341b80 /drivers/net/wireless
parent530515a06f90c0831732709efee4a99497bd2b7c (diff)
parent385910f2b275a636238f70844f1b6da9fda6f2da (diff)
Merge ../linus
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/Kconfig9
-rw-r--r--drivers/net/wireless/Makefile1
-rw-r--r--drivers/net/wireless/airo_cs.c158
-rw-r--r--drivers/net/wireless/atmel_cs.c162
-rw-r--r--drivers/net/wireless/bcm43xx/Kconfig62
-rw-r--r--drivers/net/wireless/bcm43xx/Makefile12
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx.h926
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c499
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_debugfs.h117
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_dma.c968
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_dma.h218
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_ethtool.c50
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_ethtool.h8
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_ilt.c337
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_ilt.h32
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_leds.c293
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_leds.h56
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_main.c3973
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_main.h168
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_phy.c2345
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_phy.h74
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_pio.c606
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_pio.h138
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_power.c358
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_power.h47
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_radio.c2026
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_radio.h99
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c322
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_sysfs.h25
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_wx.c1002
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_wx.h36
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_xmit.c582
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_xmit.h156
-rw-r--r--drivers/net/wireless/hostap/hostap_80211.h2
-rw-r--r--drivers/net/wireless/hostap/hostap_80211_tx.c9
-rw-r--r--drivers/net/wireless/hostap/hostap_cs.c198
-rw-r--r--drivers/net/wireless/ipw2200.c9
-rw-r--r--drivers/net/wireless/netwave_cs.c127
-rw-r--r--drivers/net/wireless/orinoco_cs.c187
-rw-r--r--drivers/net/wireless/ray_cs.c279
-rw-r--r--drivers/net/wireless/ray_cs.h2
-rw-r--r--drivers/net/wireless/spectrum_cs.c173
-rw-r--r--drivers/net/wireless/wavelan_cs.c189
-rw-r--r--drivers/net/wireless/wavelan_cs.p.h6
-rw-r--r--drivers/net/wireless/wl3501.h1
-rw-r--r--drivers/net/wireless/wl3501_cs.c178
46 files changed, 16165 insertions, 1060 deletions
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index fd17aa8491b6..bad09ebdb50b 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -309,7 +309,10 @@ config APPLE_AIRPORT
309 Say Y here to support the Airport 802.11b wireless Ethernet hardware 309 Say Y here to support the Airport 802.11b wireless Ethernet hardware
310 built into the Macintosh iBook and other recent PowerPC-based 310 built into the Macintosh iBook and other recent PowerPC-based
311 Macintosh machines. This is essentially a Lucent Orinoco card with 311 Macintosh machines. This is essentially a Lucent Orinoco card with
312 a non-standard interface 312 a non-standard interface.
313
314 This driver does not support the Airport Extreme (802.11b/g). Use
315 the BCM43xx driver for Airport Extreme cards.
313 316
314config PLX_HERMES 317config PLX_HERMES
315 tristate "Hermes in PLX9052 based PCI adaptor support (Netgear MA301 etc.)" 318 tristate "Hermes in PLX9052 based PCI adaptor support (Netgear MA301 etc.)"
@@ -353,7 +356,7 @@ config PCI_HERMES
353 356
354config ATMEL 357config ATMEL
355 tristate "Atmel at76c50x chipset 802.11b support" 358 tristate "Atmel at76c50x chipset 802.11b support"
356 depends on NET_RADIO 359 depends on NET_RADIO && (PCI || PCMCIA)
357 select FW_LOADER 360 select FW_LOADER
358 select CRC32 361 select CRC32
359 ---help--- 362 ---help---
@@ -401,6 +404,7 @@ config PCMCIA_HERMES
401config PCMCIA_SPECTRUM 404config PCMCIA_SPECTRUM
402 tristate "Symbol Spectrum24 Trilogy PCMCIA card support" 405 tristate "Symbol Spectrum24 Trilogy PCMCIA card support"
403 depends on NET_RADIO && PCMCIA && HERMES 406 depends on NET_RADIO && PCMCIA && HERMES
407 select FW_LOADER
404 ---help--- 408 ---help---
405 409
406 This is a driver for 802.11b cards using RAM-loadable Symbol 410 This is a driver for 802.11b cards using RAM-loadable Symbol
@@ -500,6 +504,7 @@ config PRISM54
500 will be called prism54.ko. 504 will be called prism54.ko.
501 505
502source "drivers/net/wireless/hostap/Kconfig" 506source "drivers/net/wireless/hostap/Kconfig"
507source "drivers/net/wireless/bcm43xx/Kconfig"
503 508
504# yes, this works even when no drivers are selected 509# yes, this works even when no drivers are selected
505config NET_WIRELESS 510config NET_WIRELESS
diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile
index 3a6f7ba326ca..c86779879361 100644
--- a/drivers/net/wireless/Makefile
+++ b/drivers/net/wireless/Makefile
@@ -35,6 +35,7 @@ obj-$(CONFIG_PCMCIA_ATMEL) += atmel_cs.o
35obj-$(CONFIG_PRISM54) += prism54/ 35obj-$(CONFIG_PRISM54) += prism54/
36 36
37obj-$(CONFIG_HOSTAP) += hostap/ 37obj-$(CONFIG_HOSTAP) += hostap/
38obj-$(CONFIG_BCM43XX) += bcm43xx/
38 39
39# 16-bit wireless PCMCIA client drivers 40# 16-bit wireless PCMCIA client drivers
40obj-$(CONFIG_PCMCIA_RAYCS) += ray_cs.o 41obj-$(CONFIG_PCMCIA_RAYCS) += ray_cs.o
diff --git a/drivers/net/wireless/airo_cs.c b/drivers/net/wireless/airo_cs.c
index a496460ce224..af0cbb6c5c0c 100644
--- a/drivers/net/wireless/airo_cs.c
+++ b/drivers/net/wireless/airo_cs.c
@@ -80,8 +80,8 @@ MODULE_SUPPORTED_DEVICE("Aironet 4500, 4800 and Cisco 340 PCMCIA cards");
80 event handler. 80 event handler.
81*/ 81*/
82 82
83static void airo_config(dev_link_t *link); 83static int airo_config(struct pcmcia_device *link);
84static void airo_release(dev_link_t *link); 84static void airo_release(struct pcmcia_device *link);
85 85
86/* 86/*
87 The attach() and detach() entry points are used to create and destroy 87 The attach() and detach() entry points are used to create and destroy
@@ -101,10 +101,10 @@ static void airo_detach(struct pcmcia_device *p_dev);
101/* 101/*
102 A linked list of "instances" of the aironet device. Each actual 102 A linked list of "instances" of the aironet device. Each actual
103 PCMCIA card corresponds to one device instance, and is described 103 PCMCIA card corresponds to one device instance, and is described
104 by one dev_link_t structure (defined in ds.h). 104 by one struct pcmcia_device structure (defined in ds.h).
105 105
106 You may not want to use a linked list for this -- for example, the 106 You may not want to use a linked list for this -- for example, the
107 memory card driver uses an array of dev_link_t pointers, where minor 107 memory card driver uses an array of struct pcmcia_device pointers, where minor
108 device numbers are used to derive the corresponding array index. 108 device numbers are used to derive the corresponding array index.
109*/ 109*/
110 110
@@ -114,7 +114,7 @@ static void airo_detach(struct pcmcia_device *p_dev);
114 example, ethernet cards, modems). In other cases, there may be 114 example, ethernet cards, modems). In other cases, there may be
115 many actual or logical devices (SCSI adapters, memory cards with 115 many actual or logical devices (SCSI adapters, memory cards with
116 multiple partitions). The dev_node_t structures need to be kept 116 multiple partitions). The dev_node_t structures need to be kept
117 in a linked list starting at the 'dev' field of a dev_link_t 117 in a linked list starting at the 'dev' field of a struct pcmcia_device
118 structure. We allocate them in the card's private data structure, 118 structure. We allocate them in the card's private data structure,
119 because they generally shouldn't be allocated dynamically. 119 because they generally shouldn't be allocated dynamically.
120 120
@@ -141,24 +141,16 @@ typedef struct local_info_t {
141 141
142 ======================================================================*/ 142 ======================================================================*/
143 143
144static int airo_attach(struct pcmcia_device *p_dev) 144static int airo_probe(struct pcmcia_device *p_dev)
145{ 145{
146 dev_link_t *link;
147 local_info_t *local; 146 local_info_t *local;
148 147
149 DEBUG(0, "airo_attach()\n"); 148 DEBUG(0, "airo_attach()\n");
150 149
151 /* Initialize the dev_link_t structure */
152 link = kzalloc(sizeof(struct dev_link_t), GFP_KERNEL);
153 if (!link) {
154 printk(KERN_ERR "airo_cs: no memory for new device\n");
155 return -ENOMEM;
156 }
157
158 /* Interrupt setup */ 150 /* Interrupt setup */
159 link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; 151 p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
160 link->irq.IRQInfo1 = IRQ_LEVEL_ID; 152 p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID;
161 link->irq.Handler = NULL; 153 p_dev->irq.Handler = NULL;
162 154
163 /* 155 /*
164 General socket configuration defaults can go here. In this 156 General socket configuration defaults can go here. In this
@@ -167,26 +159,18 @@ static int airo_attach(struct pcmcia_device *p_dev)
167 and attributes of IO windows) are fixed by the nature of the 159 and attributes of IO windows) are fixed by the nature of the
168 device, and can be hard-wired here. 160 device, and can be hard-wired here.
169 */ 161 */
170 link->conf.Attributes = 0; 162 p_dev->conf.Attributes = 0;
171 link->conf.Vcc = 50; 163 p_dev->conf.IntType = INT_MEMORY_AND_IO;
172 link->conf.IntType = INT_MEMORY_AND_IO;
173 164
174 /* Allocate space for private device-specific data */ 165 /* Allocate space for private device-specific data */
175 local = kzalloc(sizeof(local_info_t), GFP_KERNEL); 166 local = kzalloc(sizeof(local_info_t), GFP_KERNEL);
176 if (!local) { 167 if (!local) {
177 printk(KERN_ERR "airo_cs: no memory for new device\n"); 168 printk(KERN_ERR "airo_cs: no memory for new device\n");
178 kfree (link);
179 return -ENOMEM; 169 return -ENOMEM;
180 } 170 }
181 link->priv = local; 171 p_dev->priv = local;
182 172
183 link->handle = p_dev; 173 return airo_config(p_dev);
184 p_dev->instance = link;
185
186 link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
187 airo_config(link);
188
189 return 0;
190} /* airo_attach */ 174} /* airo_attach */
191 175
192/*====================================================================== 176/*======================================================================
@@ -198,14 +182,11 @@ static int airo_attach(struct pcmcia_device *p_dev)
198 182
199 ======================================================================*/ 183 ======================================================================*/
200 184
201static void airo_detach(struct pcmcia_device *p_dev) 185static void airo_detach(struct pcmcia_device *link)
202{ 186{
203 dev_link_t *link = dev_to_instance(p_dev);
204
205 DEBUG(0, "airo_detach(0x%p)\n", link); 187 DEBUG(0, "airo_detach(0x%p)\n", link);
206 188
207 if (link->state & DEV_CONFIG) 189 airo_release(link);
208 airo_release(link);
209 190
210 if ( ((local_info_t*)link->priv)->eth_dev ) { 191 if ( ((local_info_t*)link->priv)->eth_dev ) {
211 stop_airo_card( ((local_info_t*)link->priv)->eth_dev, 0 ); 192 stop_airo_card( ((local_info_t*)link->priv)->eth_dev, 0 );
@@ -213,7 +194,6 @@ static void airo_detach(struct pcmcia_device *p_dev)
213 ((local_info_t*)link->priv)->eth_dev = NULL; 194 ((local_info_t*)link->priv)->eth_dev = NULL;
214 195
215 kfree(link->priv); 196 kfree(link->priv);
216 kfree(link);
217} /* airo_detach */ 197} /* airo_detach */
218 198
219/*====================================================================== 199/*======================================================================
@@ -227,9 +207,8 @@ static void airo_detach(struct pcmcia_device *p_dev)
227#define CS_CHECK(fn, ret) \ 207#define CS_CHECK(fn, ret) \
228do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) 208do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
229 209
230static void airo_config(dev_link_t *link) 210static int airo_config(struct pcmcia_device *link)
231{ 211{
232 client_handle_t handle;
233 tuple_t tuple; 212 tuple_t tuple;
234 cisparse_t parse; 213 cisparse_t parse;
235 local_info_t *dev; 214 local_info_t *dev;
@@ -237,8 +216,7 @@ static void airo_config(dev_link_t *link)
237 u_char buf[64]; 216 u_char buf[64];
238 win_req_t req; 217 win_req_t req;
239 memreq_t map; 218 memreq_t map;
240 219
241 handle = link->handle;
242 dev = link->priv; 220 dev = link->priv;
243 221
244 DEBUG(0, "airo_config(0x%p)\n", link); 222 DEBUG(0, "airo_config(0x%p)\n", link);
@@ -252,15 +230,12 @@ static void airo_config(dev_link_t *link)
252 tuple.TupleData = buf; 230 tuple.TupleData = buf;
253 tuple.TupleDataMax = sizeof(buf); 231 tuple.TupleDataMax = sizeof(buf);
254 tuple.TupleOffset = 0; 232 tuple.TupleOffset = 0;
255 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); 233 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
256 CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); 234 CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
257 CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); 235 CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
258 link->conf.ConfigBase = parse.config.base; 236 link->conf.ConfigBase = parse.config.base;
259 link->conf.Present = parse.config.rmask[0]; 237 link->conf.Present = parse.config.rmask[0];
260 238
261 /* Configure card */
262 link->state |= DEV_CONFIG;
263
264 /* 239 /*
265 In this loop, we scan the CIS for configuration table entries, 240 In this loop, we scan the CIS for configuration table entries,
266 each of which describes a valid card configuration, including 241 each of which describes a valid card configuration, including
@@ -274,12 +249,12 @@ static void airo_config(dev_link_t *link)
274 will only use the CIS to fill in implementation-defined details. 249 will only use the CIS to fill in implementation-defined details.
275 */ 250 */
276 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; 251 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
277 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); 252 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
278 while (1) { 253 while (1) {
279 cistpl_cftable_entry_t dflt = { 0 }; 254 cistpl_cftable_entry_t dflt = { 0 };
280 cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); 255 cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
281 if (pcmcia_get_tuple_data(handle, &tuple) != 0 || 256 if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
282 pcmcia_parse_tuple(handle, &tuple, &parse) != 0) 257 pcmcia_parse_tuple(link, &tuple, &parse) != 0)
283 goto next_entry; 258 goto next_entry;
284 259
285 if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg; 260 if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg;
@@ -294,16 +269,11 @@ static void airo_config(dev_link_t *link)
294 269
295 /* Use power settings for Vcc and Vpp if present */ 270 /* Use power settings for Vcc and Vpp if present */
296 /* Note that the CIS values need to be rescaled */ 271 /* Note that the CIS values need to be rescaled */
297 if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM))
298 link->conf.Vcc = cfg->vcc.param[CISTPL_POWER_VNOM]/10000;
299 else if (dflt.vcc.present & (1<<CISTPL_POWER_VNOM))
300 link->conf.Vcc = dflt.vcc.param[CISTPL_POWER_VNOM]/10000;
301
302 if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM)) 272 if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
303 link->conf.Vpp1 = link->conf.Vpp2 = 273 link->conf.Vpp =
304 cfg->vpp1.param[CISTPL_POWER_VNOM]/10000; 274 cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
305 else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM)) 275 else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM))
306 link->conf.Vpp1 = link->conf.Vpp2 = 276 link->conf.Vpp =
307 dflt.vpp1.param[CISTPL_POWER_VNOM]/10000; 277 dflt.vpp1.param[CISTPL_POWER_VNOM]/10000;
308 278
309 /* Do we need to allocate an interrupt? */ 279 /* Do we need to allocate an interrupt? */
@@ -329,12 +299,12 @@ static void airo_config(dev_link_t *link)
329 } 299 }
330 300
331 /* This reserves IO space but doesn't actually enable it */ 301 /* This reserves IO space but doesn't actually enable it */
332 if (pcmcia_request_io(link->handle, &link->io) != 0) 302 if (pcmcia_request_io(link, &link->io) != 0)
333 goto next_entry; 303 goto next_entry;
334 304
335 /* 305 /*
336 Now set up a common memory window, if needed. There is room 306 Now set up a common memory window, if needed. There is room
337 in the dev_link_t structure for one memory window handle, 307 in the struct pcmcia_device structure for one memory window handle,
338 but if the base addresses need to be saved, or if multiple 308 but if the base addresses need to be saved, or if multiple
339 windows are needed, the info should go in the private data 309 windows are needed, the info should go in the private data
340 structure for this device. 310 structure for this device.
@@ -350,7 +320,7 @@ static void airo_config(dev_link_t *link)
350 req.Base = mem->win[0].host_addr; 320 req.Base = mem->win[0].host_addr;
351 req.Size = mem->win[0].len; 321 req.Size = mem->win[0].len;
352 req.AccessSpeed = 0; 322 req.AccessSpeed = 0;
353 if (pcmcia_request_window(&link->handle, &req, &link->win) != 0) 323 if (pcmcia_request_window(&link, &req, &link->win) != 0)
354 goto next_entry; 324 goto next_entry;
355 map.Page = 0; map.CardOffset = mem->win[0].card_addr; 325 map.Page = 0; map.CardOffset = mem->win[0].card_addr;
356 if (pcmcia_map_mem_page(link->win, &map) != 0) 326 if (pcmcia_map_mem_page(link->win, &map) != 0)
@@ -360,7 +330,7 @@ static void airo_config(dev_link_t *link)
360 break; 330 break;
361 331
362 next_entry: 332 next_entry:
363 CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple)); 333 CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
364 } 334 }
365 335
366 /* 336 /*
@@ -369,33 +339,32 @@ static void airo_config(dev_link_t *link)
369 irq structure is initialized. 339 irq structure is initialized.
370 */ 340 */
371 if (link->conf.Attributes & CONF_ENABLE_IRQ) 341 if (link->conf.Attributes & CONF_ENABLE_IRQ)
372 CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq)); 342 CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
373 343
374 /* 344 /*
375 This actually configures the PCMCIA socket -- setting up 345 This actually configures the PCMCIA socket -- setting up
376 the I/O windows and the interrupt mapping, and putting the 346 the I/O windows and the interrupt mapping, and putting the
377 card and host interface into "Memory and IO" mode. 347 card and host interface into "Memory and IO" mode.
378 */ 348 */
379 CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf)); 349 CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
380 ((local_info_t*)link->priv)->eth_dev = 350 ((local_info_t*)link->priv)->eth_dev =
381 init_airo_card( link->irq.AssignedIRQ, 351 init_airo_card( link->irq.AssignedIRQ,
382 link->io.BasePort1, 1, &handle_to_dev(handle) ); 352 link->io.BasePort1, 1, &handle_to_dev(link) );
383 if (!((local_info_t*)link->priv)->eth_dev) goto cs_failed; 353 if (!((local_info_t*)link->priv)->eth_dev) goto cs_failed;
384 354
385 /* 355 /*
386 At this point, the dev_node_t structure(s) need to be 356 At this point, the dev_node_t structure(s) need to be
387 initialized and arranged in a linked list at link->dev. 357 initialized and arranged in a linked list at link->dev_node.
388 */ 358 */
389 strcpy(dev->node.dev_name, ((local_info_t*)link->priv)->eth_dev->name ); 359 strcpy(dev->node.dev_name, ((local_info_t*)link->priv)->eth_dev->name );
390 dev->node.major = dev->node.minor = 0; 360 dev->node.major = dev->node.minor = 0;
391 link->dev = &dev->node; 361 link->dev_node = &dev->node;
392 362
393 /* Finally, report what we've done */ 363 /* Finally, report what we've done */
394 printk(KERN_INFO "%s: index 0x%02x: Vcc %d.%d", 364 printk(KERN_INFO "%s: index 0x%02x: ",
395 dev->node.dev_name, link->conf.ConfigIndex, 365 dev->node.dev_name, link->conf.ConfigIndex);
396 link->conf.Vcc/10, link->conf.Vcc%10); 366 if (link->conf.Vpp)
397 if (link->conf.Vpp1) 367 printk(", Vpp %d.%d", link->conf.Vpp/10, link->conf.Vpp%10);
398 printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10);
399 if (link->conf.Attributes & CONF_ENABLE_IRQ) 368 if (link->conf.Attributes & CONF_ENABLE_IRQ)
400 printk(", irq %d", link->irq.AssignedIRQ); 369 printk(", irq %d", link->irq.AssignedIRQ);
401 if (link->io.NumPorts1) 370 if (link->io.NumPorts1)
@@ -408,14 +377,12 @@ static void airo_config(dev_link_t *link)
408 printk(", mem 0x%06lx-0x%06lx", req.Base, 377 printk(", mem 0x%06lx-0x%06lx", req.Base,
409 req.Base+req.Size-1); 378 req.Base+req.Size-1);
410 printk("\n"); 379 printk("\n");
411 380 return 0;
412 link->state &= ~DEV_CONFIG_PENDING; 381
413 return;
414
415 cs_failed: 382 cs_failed:
416 cs_error(link->handle, last_fn, last_ret); 383 cs_error(link, last_fn, last_ret);
417 airo_release(link); 384 airo_release(link);
418 385 return -ENODEV;
419} /* airo_config */ 386} /* airo_config */
420 387
421/*====================================================================== 388/*======================================================================
@@ -426,51 +393,26 @@ static void airo_config(dev_link_t *link)
426 393
427 ======================================================================*/ 394 ======================================================================*/
428 395
429static void airo_release(dev_link_t *link) 396static void airo_release(struct pcmcia_device *link)
430{ 397{
431 DEBUG(0, "airo_release(0x%p)\n", link); 398 DEBUG(0, "airo_release(0x%p)\n", link);
432 399 pcmcia_disable_device(link);
433 /* Unlink the device chain */
434 link->dev = NULL;
435
436 /*
437 In a normal driver, additional code may be needed to release
438 other kernel data structures associated with this device.
439 */
440
441 /* Don't bother checking to see if these succeed or not */
442 if (link->win)
443 pcmcia_release_window(link->win);
444 pcmcia_release_configuration(link->handle);
445 if (link->io.NumPorts1)
446 pcmcia_release_io(link->handle, &link->io);
447 if (link->irq.AssignedIRQ)
448 pcmcia_release_irq(link->handle, &link->irq);
449 link->state &= ~DEV_CONFIG;
450} 400}
451 401
452static int airo_suspend(struct pcmcia_device *p_dev) 402static int airo_suspend(struct pcmcia_device *link)
453{ 403{
454 dev_link_t *link = dev_to_instance(p_dev);
455 local_info_t *local = link->priv; 404 local_info_t *local = link->priv;
456 405
457 link->state |= DEV_SUSPEND; 406 netif_device_detach(local->eth_dev);
458 if (link->state & DEV_CONFIG) {
459 netif_device_detach(local->eth_dev);
460 pcmcia_release_configuration(link->handle);
461 }
462 407
463 return 0; 408 return 0;
464} 409}
465 410
466static int airo_resume(struct pcmcia_device *p_dev) 411static int airo_resume(struct pcmcia_device *link)
467{ 412{
468 dev_link_t *link = dev_to_instance(p_dev);
469 local_info_t *local = link->priv; 413 local_info_t *local = link->priv;
470 414
471 link->state &= ~DEV_SUSPEND; 415 if (link->open) {
472 if (link->state & DEV_CONFIG) {
473 pcmcia_request_configuration(link->handle, &link->conf);
474 reset_airo_card(local->eth_dev); 416 reset_airo_card(local->eth_dev);
475 netif_device_attach(local->eth_dev); 417 netif_device_attach(local->eth_dev);
476 } 418 }
@@ -492,7 +434,7 @@ static struct pcmcia_driver airo_driver = {
492 .drv = { 434 .drv = {
493 .name = "airo_cs", 435 .name = "airo_cs",
494 }, 436 },
495 .probe = airo_attach, 437 .probe = airo_probe,
496 .remove = airo_detach, 438 .remove = airo_detach,
497 .id_table = airo_ids, 439 .id_table = airo_ids,
498 .suspend = airo_suspend, 440 .suspend = airo_suspend,
diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c
index d6f4a5a3e55a..26bf1127524d 100644
--- a/drivers/net/wireless/atmel_cs.c
+++ b/drivers/net/wireless/atmel_cs.c
@@ -91,8 +91,8 @@ MODULE_SUPPORTED_DEVICE("Atmel at76c50x PCMCIA cards");
91 event handler. 91 event handler.
92*/ 92*/
93 93
94static void atmel_config(dev_link_t *link); 94static int atmel_config(struct pcmcia_device *link);
95static void atmel_release(dev_link_t *link); 95static void atmel_release(struct pcmcia_device *link);
96 96
97/* 97/*
98 The attach() and detach() entry points are used to create and destroy 98 The attach() and detach() entry points are used to create and destroy
@@ -112,10 +112,10 @@ static void atmel_detach(struct pcmcia_device *p_dev);
112/* 112/*
113 A linked list of "instances" of the atmelnet device. Each actual 113 A linked list of "instances" of the atmelnet device. Each actual
114 PCMCIA card corresponds to one device instance, and is described 114 PCMCIA card corresponds to one device instance, and is described
115 by one dev_link_t structure (defined in ds.h). 115 by one struct pcmcia_device structure (defined in ds.h).
116 116
117 You may not want to use a linked list for this -- for example, the 117 You may not want to use a linked list for this -- for example, the
118 memory card driver uses an array of dev_link_t pointers, where minor 118 memory card driver uses an array of struct pcmcia_device pointers, where minor
119 device numbers are used to derive the corresponding array index. 119 device numbers are used to derive the corresponding array index.
120*/ 120*/
121 121
@@ -125,7 +125,7 @@ static void atmel_detach(struct pcmcia_device *p_dev);
125 example, ethernet cards, modems). In other cases, there may be 125 example, ethernet cards, modems). In other cases, there may be
126 many actual or logical devices (SCSI adapters, memory cards with 126 many actual or logical devices (SCSI adapters, memory cards with
127 multiple partitions). The dev_node_t structures need to be kept 127 multiple partitions). The dev_node_t structures need to be kept
128 in a linked list starting at the 'dev' field of a dev_link_t 128 in a linked list starting at the 'dev' field of a struct pcmcia_device
129 structure. We allocate them in the card's private data structure, 129 structure. We allocate them in the card's private data structure,
130 because they generally shouldn't be allocated dynamically. 130 because they generally shouldn't be allocated dynamically.
131 131
@@ -152,24 +152,16 @@ typedef struct local_info_t {
152 152
153 ======================================================================*/ 153 ======================================================================*/
154 154
155static int atmel_attach(struct pcmcia_device *p_dev) 155static int atmel_probe(struct pcmcia_device *p_dev)
156{ 156{
157 dev_link_t *link;
158 local_info_t *local; 157 local_info_t *local;
159 158
160 DEBUG(0, "atmel_attach()\n"); 159 DEBUG(0, "atmel_attach()\n");
161 160
162 /* Initialize the dev_link_t structure */
163 link = kzalloc(sizeof(struct dev_link_t), GFP_KERNEL);
164 if (!link) {
165 printk(KERN_ERR "atmel_cs: no memory for new device\n");
166 return -ENOMEM;
167 }
168
169 /* Interrupt setup */ 161 /* Interrupt setup */
170 link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; 162 p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
171 link->irq.IRQInfo1 = IRQ_LEVEL_ID; 163 p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID;
172 link->irq.Handler = NULL; 164 p_dev->irq.Handler = NULL;
173 165
174 /* 166 /*
175 General socket configuration defaults can go here. In this 167 General socket configuration defaults can go here. In this
@@ -178,26 +170,18 @@ static int atmel_attach(struct pcmcia_device *p_dev)
178 and attributes of IO windows) are fixed by the nature of the 170 and attributes of IO windows) are fixed by the nature of the
179 device, and can be hard-wired here. 171 device, and can be hard-wired here.
180 */ 172 */
181 link->conf.Attributes = 0; 173 p_dev->conf.Attributes = 0;
182 link->conf.Vcc = 50; 174 p_dev->conf.IntType = INT_MEMORY_AND_IO;
183 link->conf.IntType = INT_MEMORY_AND_IO;
184 175
185 /* Allocate space for private device-specific data */ 176 /* Allocate space for private device-specific data */
186 local = kzalloc(sizeof(local_info_t), GFP_KERNEL); 177 local = kzalloc(sizeof(local_info_t), GFP_KERNEL);
187 if (!local) { 178 if (!local) {
188 printk(KERN_ERR "atmel_cs: no memory for new device\n"); 179 printk(KERN_ERR "atmel_cs: no memory for new device\n");
189 kfree (link);
190 return -ENOMEM; 180 return -ENOMEM;
191 } 181 }
192 link->priv = local; 182 p_dev->priv = local;
193 183
194 link->handle = p_dev; 184 return atmel_config(p_dev);
195 p_dev->instance = link;
196
197 link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
198 atmel_config(link);
199
200 return 0;
201} /* atmel_attach */ 185} /* atmel_attach */
202 186
203/*====================================================================== 187/*======================================================================
@@ -209,17 +193,13 @@ static int atmel_attach(struct pcmcia_device *p_dev)
209 193
210 ======================================================================*/ 194 ======================================================================*/
211 195
212static void atmel_detach(struct pcmcia_device *p_dev) 196static void atmel_detach(struct pcmcia_device *link)
213{ 197{
214 dev_link_t *link = dev_to_instance(p_dev);
215
216 DEBUG(0, "atmel_detach(0x%p)\n", link); 198 DEBUG(0, "atmel_detach(0x%p)\n", link);
217 199
218 if (link->state & DEV_CONFIG) 200 atmel_release(link);
219 atmel_release(link);
220 201
221 kfree(link->priv); 202 kfree(link->priv);
222 kfree(link);
223} 203}
224 204
225/*====================================================================== 205/*======================================================================
@@ -236,19 +216,17 @@ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
236/* Call-back function to interrogate PCMCIA-specific information 216/* Call-back function to interrogate PCMCIA-specific information
237 about the current existance of the card */ 217 about the current existance of the card */
238static int card_present(void *arg) 218static int card_present(void *arg)
239{ 219{
240 dev_link_t *link = (dev_link_t *)arg; 220 struct pcmcia_device *link = (struct pcmcia_device *)arg;
241 if (link->state & DEV_SUSPEND) 221
242 return 0; 222 if (pcmcia_dev_present(link))
243 else if (link->state & DEV_PRESENT)
244 return 1; 223 return 1;
245 224
246 return 0; 225 return 0;
247} 226}
248 227
249static void atmel_config(dev_link_t *link) 228static int atmel_config(struct pcmcia_device *link)
250{ 229{
251 client_handle_t handle;
252 tuple_t tuple; 230 tuple_t tuple;
253 cisparse_t parse; 231 cisparse_t parse;
254 local_info_t *dev; 232 local_info_t *dev;
@@ -256,9 +234,8 @@ static void atmel_config(dev_link_t *link)
256 u_char buf[64]; 234 u_char buf[64];
257 struct pcmcia_device_id *did; 235 struct pcmcia_device_id *did;
258 236
259 handle = link->handle;
260 dev = link->priv; 237 dev = link->priv;
261 did = handle_to_dev(handle).driver_data; 238 did = handle_to_dev(link).driver_data;
262 239
263 DEBUG(0, "atmel_config(0x%p)\n", link); 240 DEBUG(0, "atmel_config(0x%p)\n", link);
264 241
@@ -272,15 +249,12 @@ static void atmel_config(dev_link_t *link)
272 registers. 249 registers.
273 */ 250 */
274 tuple.DesiredTuple = CISTPL_CONFIG; 251 tuple.DesiredTuple = CISTPL_CONFIG;
275 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); 252 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
276 CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); 253 CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
277 CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); 254 CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
278 link->conf.ConfigBase = parse.config.base; 255 link->conf.ConfigBase = parse.config.base;
279 link->conf.Present = parse.config.rmask[0]; 256 link->conf.Present = parse.config.rmask[0];
280 257
281 /* Configure card */
282 link->state |= DEV_CONFIG;
283
284 /* 258 /*
285 In this loop, we scan the CIS for configuration table entries, 259 In this loop, we scan the CIS for configuration table entries,
286 each of which describes a valid card configuration, including 260 each of which describes a valid card configuration, including
@@ -294,12 +268,12 @@ static void atmel_config(dev_link_t *link)
294 will only use the CIS to fill in implementation-defined details. 268 will only use the CIS to fill in implementation-defined details.
295 */ 269 */
296 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; 270 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
297 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); 271 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
298 while (1) { 272 while (1) {
299 cistpl_cftable_entry_t dflt = { 0 }; 273 cistpl_cftable_entry_t dflt = { 0 };
300 cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); 274 cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
301 if (pcmcia_get_tuple_data(handle, &tuple) != 0 || 275 if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
302 pcmcia_parse_tuple(handle, &tuple, &parse) != 0) 276 pcmcia_parse_tuple(link, &tuple, &parse) != 0)
303 goto next_entry; 277 goto next_entry;
304 278
305 if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg; 279 if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg;
@@ -314,16 +288,11 @@ static void atmel_config(dev_link_t *link)
314 288
315 /* Use power settings for Vcc and Vpp if present */ 289 /* Use power settings for Vcc and Vpp if present */
316 /* Note that the CIS values need to be rescaled */ 290 /* Note that the CIS values need to be rescaled */
317 if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM))
318 link->conf.Vcc = cfg->vcc.param[CISTPL_POWER_VNOM]/10000;
319 else if (dflt.vcc.present & (1<<CISTPL_POWER_VNOM))
320 link->conf.Vcc = dflt.vcc.param[CISTPL_POWER_VNOM]/10000;
321
322 if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM)) 291 if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
323 link->conf.Vpp1 = link->conf.Vpp2 = 292 link->conf.Vpp =
324 cfg->vpp1.param[CISTPL_POWER_VNOM]/10000; 293 cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
325 else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM)) 294 else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM))
326 link->conf.Vpp1 = link->conf.Vpp2 = 295 link->conf.Vpp =
327 dflt.vpp1.param[CISTPL_POWER_VNOM]/10000; 296 dflt.vpp1.param[CISTPL_POWER_VNOM]/10000;
328 297
329 /* Do we need to allocate an interrupt? */ 298 /* Do we need to allocate an interrupt? */
@@ -349,14 +318,14 @@ static void atmel_config(dev_link_t *link)
349 } 318 }
350 319
351 /* This reserves IO space but doesn't actually enable it */ 320 /* This reserves IO space but doesn't actually enable it */
352 if (pcmcia_request_io(link->handle, &link->io) != 0) 321 if (pcmcia_request_io(link, &link->io) != 0)
353 goto next_entry; 322 goto next_entry;
354 323
355 /* If we got this far, we're cool! */ 324 /* If we got this far, we're cool! */
356 break; 325 break;
357 326
358 next_entry: 327 next_entry:
359 CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple)); 328 CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
360 } 329 }
361 330
362 /* 331 /*
@@ -365,14 +334,14 @@ static void atmel_config(dev_link_t *link)
365 irq structure is initialized. 334 irq structure is initialized.
366 */ 335 */
367 if (link->conf.Attributes & CONF_ENABLE_IRQ) 336 if (link->conf.Attributes & CONF_ENABLE_IRQ)
368 CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq)); 337 CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
369 338
370 /* 339 /*
371 This actually configures the PCMCIA socket -- setting up 340 This actually configures the PCMCIA socket -- setting up
372 the I/O windows and the interrupt mapping, and putting the 341 the I/O windows and the interrupt mapping, and putting the
373 card and host interface into "Memory and IO" mode. 342 card and host interface into "Memory and IO" mode.
374 */ 343 */
375 CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf)); 344 CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
376 345
377 if (link->irq.AssignedIRQ == 0) { 346 if (link->irq.AssignedIRQ == 0) {
378 printk(KERN_ALERT 347 printk(KERN_ALERT
@@ -384,7 +353,7 @@ static void atmel_config(dev_link_t *link)
384 init_atmel_card(link->irq.AssignedIRQ, 353 init_atmel_card(link->irq.AssignedIRQ,
385 link->io.BasePort1, 354 link->io.BasePort1,
386 did ? did->driver_info : ATMEL_FW_TYPE_NONE, 355 did ? did->driver_info : ATMEL_FW_TYPE_NONE,
387 &handle_to_dev(handle), 356 &handle_to_dev(link),
388 card_present, 357 card_present,
389 link); 358 link);
390 if (!((local_info_t*)link->priv)->eth_dev) 359 if (!((local_info_t*)link->priv)->eth_dev)
@@ -393,18 +362,18 @@ static void atmel_config(dev_link_t *link)
393 362
394 /* 363 /*
395 At this point, the dev_node_t structure(s) need to be 364 At this point, the dev_node_t structure(s) need to be
396 initialized and arranged in a linked list at link->dev. 365 initialized and arranged in a linked list at link->dev_node.
397 */ 366 */
398 strcpy(dev->node.dev_name, ((local_info_t*)link->priv)->eth_dev->name ); 367 strcpy(dev->node.dev_name, ((local_info_t*)link->priv)->eth_dev->name );
399 dev->node.major = dev->node.minor = 0; 368 dev->node.major = dev->node.minor = 0;
400 link->dev = &dev->node; 369 link->dev_node = &dev->node;
401 370
402 link->state &= ~DEV_CONFIG_PENDING; 371 return 0;
403 return; 372
404
405 cs_failed: 373 cs_failed:
406 cs_error(link->handle, last_fn, last_ret); 374 cs_error(link, last_fn, last_ret);
407 atmel_release(link); 375 atmel_release(link);
376 return -ENODEV;
408} 377}
409 378
410/*====================================================================== 379/*======================================================================
@@ -415,53 +384,34 @@ static void atmel_config(dev_link_t *link)
415 384
416 ======================================================================*/ 385 ======================================================================*/
417 386
418static void atmel_release(dev_link_t *link) 387static void atmel_release(struct pcmcia_device *link)
419{ 388{
420 struct net_device *dev = ((local_info_t*)link->priv)->eth_dev; 389 struct net_device *dev = ((local_info_t*)link->priv)->eth_dev;
421 390
422 DEBUG(0, "atmel_release(0x%p)\n", link); 391 DEBUG(0, "atmel_release(0x%p)\n", link);
423 392
424 /* Unlink the device chain */ 393 if (dev)
425 link->dev = NULL;
426
427 if (dev)
428 stop_atmel_card(dev); 394 stop_atmel_card(dev);
429 ((local_info_t*)link->priv)->eth_dev = NULL; 395 ((local_info_t*)link->priv)->eth_dev = NULL;
430 396
431 /* Don't bother checking to see if these succeed or not */ 397 pcmcia_disable_device(link);
432 pcmcia_release_configuration(link->handle);
433 if (link->io.NumPorts1)
434 pcmcia_release_io(link->handle, &link->io);
435 if (link->irq.AssignedIRQ)
436 pcmcia_release_irq(link->handle, &link->irq);
437 link->state &= ~DEV_CONFIG;
438} 398}
439 399
440static int atmel_suspend(struct pcmcia_device *dev) 400static int atmel_suspend(struct pcmcia_device *link)
441{ 401{
442 dev_link_t *link = dev_to_instance(dev);
443 local_info_t *local = link->priv; 402 local_info_t *local = link->priv;
444 403
445 link->state |= DEV_SUSPEND; 404 netif_device_detach(local->eth_dev);
446 if (link->state & DEV_CONFIG) {
447 netif_device_detach(local->eth_dev);
448 pcmcia_release_configuration(link->handle);
449 }
450 405
451 return 0; 406 return 0;
452} 407}
453 408
454static int atmel_resume(struct pcmcia_device *dev) 409static int atmel_resume(struct pcmcia_device *link)
455{ 410{
456 dev_link_t *link = dev_to_instance(dev);
457 local_info_t *local = link->priv; 411 local_info_t *local = link->priv;
458 412
459 link->state &= ~DEV_SUSPEND; 413 atmel_open(local->eth_dev);
460 if (link->state & DEV_CONFIG) { 414 netif_device_attach(local->eth_dev);
461 pcmcia_request_configuration(link->handle, &link->conf);
462 atmel_open(local->eth_dev);
463 netif_device_attach(local->eth_dev);
464 }
465 415
466 return 0; 416 return 0;
467} 417}
@@ -515,7 +465,7 @@ static struct pcmcia_driver atmel_driver = {
515 .drv = { 465 .drv = {
516 .name = "atmel_cs", 466 .name = "atmel_cs",
517 }, 467 },
518 .probe = atmel_attach, 468 .probe = atmel_probe,
519 .remove = atmel_detach, 469 .remove = atmel_detach,
520 .id_table = atmel_ids, 470 .id_table = atmel_ids,
521 .suspend = atmel_suspend, 471 .suspend = atmel_suspend,
diff --git a/drivers/net/wireless/bcm43xx/Kconfig b/drivers/net/wireless/bcm43xx/Kconfig
new file mode 100644
index 000000000000..418465600a77
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/Kconfig
@@ -0,0 +1,62 @@
1config BCM43XX
2 tristate "Broadcom BCM43xx wireless support"
3 depends on PCI && IEEE80211 && IEEE80211_SOFTMAC && NET_RADIO && EXPERIMENTAL
4 select FW_LOADER
5 ---help---
6 This is an experimental driver for the Broadcom 43xx wireless chip,
7 found in the Apple Airport Extreme and various other devices.
8
9config BCM43XX_DEBUG
10 bool "Broadcom BCM43xx debugging (RECOMMENDED)"
11 depends on BCM43XX
12 default y
13 ---help---
14 Broadcom 43xx debugging messages.
15 Say Y, because the driver is still very experimental and
16 this will help you get it running.
17
18config BCM43XX_DMA
19 bool
20config BCM43XX_PIO
21 bool
22
23choice
24 prompt "BCM43xx data transfer mode"
25 depends on BCM43XX
26 default BCM43XX_DMA_AND_PIO_MODE
27
28config BCM43XX_DMA_AND_PIO_MODE
29 bool "DMA + PIO"
30 select BCM43XX_DMA
31 select BCM43XX_PIO
32 ---help---
33 Include both, Direct Memory Access (DMA) and Programmed I/O (PIO)
34 data transfer modes.
35 The actually used mode is selectable through the module
36 parameter "pio". If the module parameter is pio=0, DMA is used.
37 Otherwise PIO is used. DMA is default.
38
39 If unsure, choose this option.
40
41config BCM43XX_DMA_MODE
42 bool "DMA (Direct Memory Access) only"
43 select BCM43XX_DMA
44 ---help---
45 Only include Direct Memory Access (DMA).
46 This reduces the size of the driver module, by omitting the PIO code.
47
48config BCM43XX_PIO_MODE
49 bool "PIO (Programmed I/O) only"
50 select BCM43XX_PIO
51 ---help---
52 Only include Programmed I/O (PIO).
53 This reduces the size of the driver module, by omitting the DMA code.
54 Please note that PIO transfers are slow (compared to DMA).
55
56 Also note that not all devices of the 43xx series support PIO.
57 The 4306 (Apple Airport Extreme and others) supports PIO, while
58 the 4318 is known to _not_ support PIO.
59
60 Only use PIO, if DMA does not work for you.
61
62endchoice
diff --git a/drivers/net/wireless/bcm43xx/Makefile b/drivers/net/wireless/bcm43xx/Makefile
new file mode 100644
index 000000000000..bb5220c629d2
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/Makefile
@@ -0,0 +1,12 @@
1obj-$(CONFIG_BCM43XX) += bcm43xx.o
2bcm43xx-obj-$(CONFIG_BCM43XX_DEBUG) += bcm43xx_debugfs.o
3
4bcm43xx-obj-$(CONFIG_BCM43XX_DMA) += bcm43xx_dma.o
5bcm43xx-obj-$(CONFIG_BCM43XX_PIO) += bcm43xx_pio.o
6
7bcm43xx-objs := bcm43xx_main.o bcm43xx_ilt.o \
8 bcm43xx_radio.o bcm43xx_phy.o \
9 bcm43xx_power.o bcm43xx_wx.o \
10 bcm43xx_leds.o bcm43xx_ethtool.o \
11 bcm43xx_xmit.o bcm43xx_sysfs.o \
12 $(bcm43xx-obj-y)
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h
new file mode 100644
index 000000000000..dcadd295de4f
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx.h
@@ -0,0 +1,926 @@
1#ifndef BCM43xx_H_
2#define BCM43xx_H_
3
4#include <linux/version.h>
5#include <linux/kernel.h>
6#include <linux/spinlock.h>
7#include <linux/interrupt.h>
8#include <linux/stringify.h>
9#include <linux/pci.h>
10#include <net/ieee80211.h>
11#include <net/ieee80211softmac.h>
12#include <asm/atomic.h>
13#include <asm/io.h>
14
15
16#include "bcm43xx_debugfs.h"
17#include "bcm43xx_leds.h"
18#include "bcm43xx_sysfs.h"
19
20
21#define PFX KBUILD_MODNAME ": "
22
23#define BCM43xx_SWITCH_CORE_MAX_RETRIES 50
24#define BCM43xx_IRQWAIT_MAX_RETRIES 50
25
26#define BCM43xx_IO_SIZE 8192
27
28/* Active Core PCI Configuration Register. */
29#define BCM43xx_PCICFG_ACTIVE_CORE 0x80
30/* SPROM control register. */
31#define BCM43xx_PCICFG_SPROMCTL 0x88
32/* Interrupt Control PCI Configuration Register. (Only on PCI cores with rev >= 6) */
33#define BCM43xx_PCICFG_ICR 0x94
34
35/* MMIO offsets */
36#define BCM43xx_MMIO_DMA1_REASON 0x20
37#define BCM43xx_MMIO_DMA1_IRQ_MASK 0x24
38#define BCM43xx_MMIO_DMA2_REASON 0x28
39#define BCM43xx_MMIO_DMA2_IRQ_MASK 0x2C
40#define BCM43xx_MMIO_DMA3_REASON 0x30
41#define BCM43xx_MMIO_DMA3_IRQ_MASK 0x34
42#define BCM43xx_MMIO_DMA4_REASON 0x38
43#define BCM43xx_MMIO_DMA4_IRQ_MASK 0x3C
44#define BCM43xx_MMIO_STATUS_BITFIELD 0x120
45#define BCM43xx_MMIO_STATUS2_BITFIELD 0x124
46#define BCM43xx_MMIO_GEN_IRQ_REASON 0x128
47#define BCM43xx_MMIO_GEN_IRQ_MASK 0x12C
48#define BCM43xx_MMIO_RAM_CONTROL 0x130
49#define BCM43xx_MMIO_RAM_DATA 0x134
50#define BCM43xx_MMIO_PS_STATUS 0x140
51#define BCM43xx_MMIO_RADIO_HWENABLED_HI 0x158
52#define BCM43xx_MMIO_SHM_CONTROL 0x160
53#define BCM43xx_MMIO_SHM_DATA 0x164
54#define BCM43xx_MMIO_SHM_DATA_UNALIGNED 0x166
55#define BCM43xx_MMIO_XMITSTAT_0 0x170
56#define BCM43xx_MMIO_XMITSTAT_1 0x174
57#define BCM43xx_MMIO_REV3PLUS_TSF_LOW 0x180 /* core rev >= 3 only */
58#define BCM43xx_MMIO_REV3PLUS_TSF_HIGH 0x184 /* core rev >= 3 only */
59#define BCM43xx_MMIO_DMA1_BASE 0x200
60#define BCM43xx_MMIO_DMA2_BASE 0x220
61#define BCM43xx_MMIO_DMA3_BASE 0x240
62#define BCM43xx_MMIO_DMA4_BASE 0x260
63#define BCM43xx_MMIO_PIO1_BASE 0x300
64#define BCM43xx_MMIO_PIO2_BASE 0x310
65#define BCM43xx_MMIO_PIO3_BASE 0x320
66#define BCM43xx_MMIO_PIO4_BASE 0x330
67#define BCM43xx_MMIO_PHY_VER 0x3E0
68#define BCM43xx_MMIO_PHY_RADIO 0x3E2
69#define BCM43xx_MMIO_ANTENNA 0x3E8
70#define BCM43xx_MMIO_CHANNEL 0x3F0
71#define BCM43xx_MMIO_CHANNEL_EXT 0x3F4
72#define BCM43xx_MMIO_RADIO_CONTROL 0x3F6
73#define BCM43xx_MMIO_RADIO_DATA_HIGH 0x3F8
74#define BCM43xx_MMIO_RADIO_DATA_LOW 0x3FA
75#define BCM43xx_MMIO_PHY_CONTROL 0x3FC
76#define BCM43xx_MMIO_PHY_DATA 0x3FE
77#define BCM43xx_MMIO_MACFILTER_CONTROL 0x420
78#define BCM43xx_MMIO_MACFILTER_DATA 0x422
79#define BCM43xx_MMIO_RADIO_HWENABLED_LO 0x49A
80#define BCM43xx_MMIO_GPIO_CONTROL 0x49C
81#define BCM43xx_MMIO_GPIO_MASK 0x49E
82#define BCM43xx_MMIO_TSF_0 0x632 /* core rev < 3 only */
83#define BCM43xx_MMIO_TSF_1 0x634 /* core rev < 3 only */
84#define BCM43xx_MMIO_TSF_2 0x636 /* core rev < 3 only */
85#define BCM43xx_MMIO_TSF_3 0x638 /* core rev < 3 only */
86#define BCM43xx_MMIO_POWERUP_DELAY 0x6A8
87
88/* SPROM offsets. */
89#define BCM43xx_SPROM_BASE 0x1000
90#define BCM43xx_SPROM_BOARDFLAGS2 0x1c
91#define BCM43xx_SPROM_IL0MACADDR 0x24
92#define BCM43xx_SPROM_ET0MACADDR 0x27
93#define BCM43xx_SPROM_ET1MACADDR 0x2a
94#define BCM43xx_SPROM_ETHPHY 0x2d
95#define BCM43xx_SPROM_BOARDREV 0x2e
96#define BCM43xx_SPROM_PA0B0 0x2f
97#define BCM43xx_SPROM_PA0B1 0x30
98#define BCM43xx_SPROM_PA0B2 0x31
99#define BCM43xx_SPROM_WL0GPIO0 0x32
100#define BCM43xx_SPROM_WL0GPIO2 0x33
101#define BCM43xx_SPROM_MAXPWR 0x34
102#define BCM43xx_SPROM_PA1B0 0x35
103#define BCM43xx_SPROM_PA1B1 0x36
104#define BCM43xx_SPROM_PA1B2 0x37
105#define BCM43xx_SPROM_IDL_TSSI_TGT 0x38
106#define BCM43xx_SPROM_BOARDFLAGS 0x39
107#define BCM43xx_SPROM_ANTENNA_GAIN 0x3a
108#define BCM43xx_SPROM_VERSION 0x3f
109
110/* BCM43xx_SPROM_BOARDFLAGS values */
111#define BCM43xx_BFL_BTCOEXIST 0x0001 /* implements Bluetooth coexistance */
112#define BCM43xx_BFL_PACTRL 0x0002 /* GPIO 9 controlling the PA */
113#define BCM43xx_BFL_AIRLINEMODE 0x0004 /* implements GPIO 13 radio disable indication */
114#define BCM43xx_BFL_RSSI 0x0008 /* software calculates nrssi slope. */
115#define BCM43xx_BFL_ENETSPI 0x0010 /* has ephy roboswitch spi */
116#define BCM43xx_BFL_XTAL_NOSLOW 0x0020 /* no slow clock available */
117#define BCM43xx_BFL_CCKHIPWR 0x0040 /* can do high power CCK transmission */
118#define BCM43xx_BFL_ENETADM 0x0080 /* has ADMtek switch */
119#define BCM43xx_BFL_ENETVLAN 0x0100 /* can do vlan */
120#define BCM43xx_BFL_AFTERBURNER 0x0200 /* supports Afterburner mode */
121#define BCM43xx_BFL_NOPCI 0x0400 /* leaves PCI floating */
122#define BCM43xx_BFL_FEM 0x0800 /* supports the Front End Module */
123#define BCM43xx_BFL_EXTLNA 0x1000 /* has an external LNA */
124#define BCM43xx_BFL_HGPA 0x2000 /* had high gain PA */
125#define BCM43xx_BFL_BTCMOD 0x4000 /* BFL_BTCOEXIST is given in alternate GPIOs */
126#define BCM43xx_BFL_ALTIQ 0x8000 /* alternate I/Q settings */
127
128/* GPIO register offset, in both ChipCommon and PCI core. */
129#define BCM43xx_GPIO_CONTROL 0x6c
130
131/* SHM Routing */
132#define BCM43xx_SHM_SHARED 0x0001
133#define BCM43xx_SHM_WIRELESS 0x0002
134#define BCM43xx_SHM_PCM 0x0003
135#define BCM43xx_SHM_HWMAC 0x0004
136#define BCM43xx_SHM_UCODE 0x0300
137
138/* MacFilter offsets. */
139#define BCM43xx_MACFILTER_SELF 0x0000
140#define BCM43xx_MACFILTER_ASSOC 0x0003
141
142/* Chipcommon registers. */
143#define BCM43xx_CHIPCOMMON_CAPABILITIES 0x04
144#define BCM43xx_CHIPCOMMON_PLLONDELAY 0xB0
145#define BCM43xx_CHIPCOMMON_FREFSELDELAY 0xB4
146#define BCM43xx_CHIPCOMMON_SLOWCLKCTL 0xB8
147#define BCM43xx_CHIPCOMMON_SYSCLKCTL 0xC0
148
149/* PCI core specific registers. */
150#define BCM43xx_PCICORE_BCAST_ADDR 0x50
151#define BCM43xx_PCICORE_BCAST_DATA 0x54
152#define BCM43xx_PCICORE_SBTOPCI2 0x108
153
154/* SBTOPCI2 values. */
155#define BCM43xx_SBTOPCI2_PREFETCH 0x4
156#define BCM43xx_SBTOPCI2_BURST 0x8
157
158/* Chipcommon capabilities. */
159#define BCM43xx_CAPABILITIES_PCTL 0x00040000
160#define BCM43xx_CAPABILITIES_PLLMASK 0x00030000
161#define BCM43xx_CAPABILITIES_PLLSHIFT 16
162#define BCM43xx_CAPABILITIES_FLASHMASK 0x00000700
163#define BCM43xx_CAPABILITIES_FLASHSHIFT 8
164#define BCM43xx_CAPABILITIES_EXTBUSPRESENT 0x00000040
165#define BCM43xx_CAPABILITIES_UARTGPIO 0x00000020
166#define BCM43xx_CAPABILITIES_UARTCLOCKMASK 0x00000018
167#define BCM43xx_CAPABILITIES_UARTCLOCKSHIFT 3
168#define BCM43xx_CAPABILITIES_MIPSBIGENDIAN 0x00000004
169#define BCM43xx_CAPABILITIES_NRUARTSMASK 0x00000003
170
171/* PowerControl */
172#define BCM43xx_PCTL_IN 0xB0
173#define BCM43xx_PCTL_OUT 0xB4
174#define BCM43xx_PCTL_OUTENABLE 0xB8
175#define BCM43xx_PCTL_XTAL_POWERUP 0x40
176#define BCM43xx_PCTL_PLL_POWERDOWN 0x80
177
178/* PowerControl Clock Modes */
179#define BCM43xx_PCTL_CLK_FAST 0x00
180#define BCM43xx_PCTL_CLK_SLOW 0x01
181#define BCM43xx_PCTL_CLK_DYNAMIC 0x02
182
183#define BCM43xx_PCTL_FORCE_SLOW 0x0800
184#define BCM43xx_PCTL_FORCE_PLL 0x1000
185#define BCM43xx_PCTL_DYN_XTAL 0x2000
186
187/* COREIDs */
188#define BCM43xx_COREID_CHIPCOMMON 0x800
189#define BCM43xx_COREID_ILINE20 0x801
190#define BCM43xx_COREID_SDRAM 0x803
191#define BCM43xx_COREID_PCI 0x804
192#define BCM43xx_COREID_MIPS 0x805
193#define BCM43xx_COREID_ETHERNET 0x806
194#define BCM43xx_COREID_V90 0x807
195#define BCM43xx_COREID_USB11_HOSTDEV 0x80a
196#define BCM43xx_COREID_IPSEC 0x80b
197#define BCM43xx_COREID_PCMCIA 0x80d
198#define BCM43xx_COREID_EXT_IF 0x80f
199#define BCM43xx_COREID_80211 0x812
200#define BCM43xx_COREID_MIPS_3302 0x816
201#define BCM43xx_COREID_USB11_HOST 0x817
202#define BCM43xx_COREID_USB11_DEV 0x818
203#define BCM43xx_COREID_USB20_HOST 0x819
204#define BCM43xx_COREID_USB20_DEV 0x81a
205#define BCM43xx_COREID_SDIO_HOST 0x81b
206
207/* Core Information Registers */
208#define BCM43xx_CIR_BASE 0xf00
209#define BCM43xx_CIR_SBTPSFLAG (BCM43xx_CIR_BASE + 0x18)
210#define BCM43xx_CIR_SBIMSTATE (BCM43xx_CIR_BASE + 0x90)
211#define BCM43xx_CIR_SBINTVEC (BCM43xx_CIR_BASE + 0x94)
212#define BCM43xx_CIR_SBTMSTATELOW (BCM43xx_CIR_BASE + 0x98)
213#define BCM43xx_CIR_SBTMSTATEHIGH (BCM43xx_CIR_BASE + 0x9c)
214#define BCM43xx_CIR_SBIMCONFIGLOW (BCM43xx_CIR_BASE + 0xa8)
215#define BCM43xx_CIR_SB_ID_HI (BCM43xx_CIR_BASE + 0xfc)
216
217/* Mask to get the Backplane Flag Number from SBTPSFLAG. */
218#define BCM43xx_BACKPLANE_FLAG_NR_MASK 0x3f
219
220/* SBIMCONFIGLOW values/masks. */
221#define BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_MASK 0x00000007
222#define BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_SHIFT 0
223#define BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_MASK 0x00000070
224#define BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_SHIFT 4
225#define BCM43xx_SBIMCONFIGLOW_CONNID_MASK 0x00ff0000
226#define BCM43xx_SBIMCONFIGLOW_CONNID_SHIFT 16
227
228/* sbtmstatelow state flags */
229#define BCM43xx_SBTMSTATELOW_RESET 0x01
230#define BCM43xx_SBTMSTATELOW_REJECT 0x02
231#define BCM43xx_SBTMSTATELOW_CLOCK 0x10000
232#define BCM43xx_SBTMSTATELOW_FORCE_GATE_CLOCK 0x20000
233
234/* sbtmstatehigh state flags */
235#define BCM43xx_SBTMSTATEHIGH_SERROR 0x1
236#define BCM43xx_SBTMSTATEHIGH_BUSY 0x4
237
238/* sbimstate flags */
239#define BCM43xx_SBIMSTATE_IB_ERROR 0x20000
240#define BCM43xx_SBIMSTATE_TIMEOUT 0x40000
241
242/* PHYVersioning */
243#define BCM43xx_PHYTYPE_A 0x00
244#define BCM43xx_PHYTYPE_B 0x01
245#define BCM43xx_PHYTYPE_G 0x02
246
247/* PHYRegisters */
248#define BCM43xx_PHY_ILT_A_CTRL 0x0072
249#define BCM43xx_PHY_ILT_A_DATA1 0x0073
250#define BCM43xx_PHY_ILT_A_DATA2 0x0074
251#define BCM43xx_PHY_G_LO_CONTROL 0x0810
252#define BCM43xx_PHY_ILT_G_CTRL 0x0472
253#define BCM43xx_PHY_ILT_G_DATA1 0x0473
254#define BCM43xx_PHY_ILT_G_DATA2 0x0474
255#define BCM43xx_PHY_A_PCTL 0x007B
256#define BCM43xx_PHY_G_PCTL 0x0029
257#define BCM43xx_PHY_A_CRS 0x0029
258#define BCM43xx_PHY_RADIO_BITFIELD 0x0401
259#define BCM43xx_PHY_G_CRS 0x0429
260#define BCM43xx_PHY_NRSSILT_CTRL 0x0803
261#define BCM43xx_PHY_NRSSILT_DATA 0x0804
262
263/* RadioRegisters */
264#define BCM43xx_RADIOCTL_ID 0x01
265
266/* StatusBitField */
267#define BCM43xx_SBF_MAC_ENABLED 0x00000001
268#define BCM43xx_SBF_2 0x00000002 /*FIXME: fix name*/
269#define BCM43xx_SBF_CORE_READY 0x00000004
270#define BCM43xx_SBF_400 0x00000400 /*FIXME: fix name*/
271#define BCM43xx_SBF_4000 0x00004000 /*FIXME: fix name*/
272#define BCM43xx_SBF_8000 0x00008000 /*FIXME: fix name*/
273#define BCM43xx_SBF_XFER_REG_BYTESWAP 0x00010000
274#define BCM43xx_SBF_MODE_NOTADHOC 0x00020000
275#define BCM43xx_SBF_MODE_AP 0x00040000
276#define BCM43xx_SBF_RADIOREG_LOCK 0x00080000
277#define BCM43xx_SBF_MODE_MONITOR 0x00400000
278#define BCM43xx_SBF_MODE_PROMISC 0x01000000
279#define BCM43xx_SBF_PS1 0x02000000
280#define BCM43xx_SBF_PS2 0x04000000
281#define BCM43xx_SBF_NO_SSID_BCAST 0x08000000
282#define BCM43xx_SBF_TIME_UPDATE 0x10000000
283#define BCM43xx_SBF_80000000 0x80000000 /*FIXME: fix name*/
284
285/* MicrocodeFlagsBitfield (addr + lo-word values?)*/
286#define BCM43xx_UCODEFLAGS_OFFSET 0x005E
287
288#define BCM43xx_UCODEFLAG_AUTODIV 0x0001
289#define BCM43xx_UCODEFLAG_UNKBGPHY 0x0002
290#define BCM43xx_UCODEFLAG_UNKBPHY 0x0004
291#define BCM43xx_UCODEFLAG_UNKGPHY 0x0020
292#define BCM43xx_UCODEFLAG_UNKPACTRL 0x0040
293#define BCM43xx_UCODEFLAG_JAPAN 0x0080
294
295/* Generic-Interrupt reasons. */
296#define BCM43xx_IRQ_READY (1 << 0)
297#define BCM43xx_IRQ_BEACON (1 << 1)
298#define BCM43xx_IRQ_PS (1 << 2)
299#define BCM43xx_IRQ_REG124 (1 << 5)
300#define BCM43xx_IRQ_PMQ (1 << 6)
301#define BCM43xx_IRQ_PIO_WORKAROUND (1 << 8)
302#define BCM43xx_IRQ_XMIT_ERROR (1 << 11)
303#define BCM43xx_IRQ_RX (1 << 15)
304#define BCM43xx_IRQ_SCAN (1 << 16)
305#define BCM43xx_IRQ_NOISE (1 << 18)
306#define BCM43xx_IRQ_XMIT_STATUS (1 << 29)
307
308#define BCM43xx_IRQ_ALL 0xffffffff
309#define BCM43xx_IRQ_INITIAL (BCM43xx_IRQ_PS | \
310 BCM43xx_IRQ_REG124 | \
311 BCM43xx_IRQ_PMQ | \
312 BCM43xx_IRQ_XMIT_ERROR | \
313 BCM43xx_IRQ_RX | \
314 BCM43xx_IRQ_SCAN | \
315 BCM43xx_IRQ_NOISE | \
316 BCM43xx_IRQ_XMIT_STATUS)
317
318
319/* Initial default iw_mode */
320#define BCM43xx_INITIAL_IWMODE IW_MODE_INFRA
321
322/* Bus type PCI. */
323#define BCM43xx_BUSTYPE_PCI 0
324/* Bus type Silicone Backplane Bus. */
325#define BCM43xx_BUSTYPE_SB 1
326/* Bus type PCMCIA. */
327#define BCM43xx_BUSTYPE_PCMCIA 2
328
329/* Threshold values. */
330#define BCM43xx_MIN_RTS_THRESHOLD 1U
331#define BCM43xx_MAX_RTS_THRESHOLD 2304U
332#define BCM43xx_DEFAULT_RTS_THRESHOLD BCM43xx_MAX_RTS_THRESHOLD
333
334#define BCM43xx_DEFAULT_SHORT_RETRY_LIMIT 7
335#define BCM43xx_DEFAULT_LONG_RETRY_LIMIT 4
336
337/* Max size of a security key */
338#define BCM43xx_SEC_KEYSIZE 16
339/* Security algorithms. */
340enum {
341 BCM43xx_SEC_ALGO_NONE = 0, /* unencrypted, as of TX header. */
342 BCM43xx_SEC_ALGO_WEP,
343 BCM43xx_SEC_ALGO_UNKNOWN,
344 BCM43xx_SEC_ALGO_AES,
345 BCM43xx_SEC_ALGO_WEP104,
346 BCM43xx_SEC_ALGO_TKIP,
347};
348
349#ifdef assert
350# undef assert
351#endif
352#ifdef CONFIG_BCM43XX_DEBUG
353#define assert(expr) \
354 do { \
355 if (unlikely(!(expr))) { \
356 printk(KERN_ERR PFX "ASSERTION FAILED (%s) at: %s:%d:%s()\n", \
357 #expr, __FILE__, __LINE__, __FUNCTION__); \
358 } \
359 } while (0)
360#else
361#define assert(expr) do { /* nothing */ } while (0)
362#endif
363
364/* rate limited printk(). */
365#ifdef printkl
366# undef printkl
367#endif
368#define printkl(f, x...) do { if (printk_ratelimit()) printk(f ,##x); } while (0)
369/* rate limited printk() for debugging */
370#ifdef dprintkl
371# undef dprintkl
372#endif
373#ifdef CONFIG_BCM43XX_DEBUG
374# define dprintkl printkl
375#else
376# define dprintkl(f, x...) do { /* nothing */ } while (0)
377#endif
378
379/* Helper macro for if branches.
380 * An if branch marked with this macro is only taken in DEBUG mode.
381 * Example:
382 * if (DEBUG_ONLY(foo == bar)) {
383 * do something
384 * }
385 * In DEBUG mode, the branch will be taken if (foo == bar).
386 * In non-DEBUG mode, the branch will never be taken.
387 */
388#ifdef DEBUG_ONLY
389# undef DEBUG_ONLY
390#endif
391#ifdef CONFIG_BCM43XX_DEBUG
392# define DEBUG_ONLY(x) (x)
393#else
394# define DEBUG_ONLY(x) 0
395#endif
396
397/* debugging printk() */
398#ifdef dprintk
399# undef dprintk
400#endif
401#ifdef CONFIG_BCM43XX_DEBUG
402# define dprintk(f, x...) do { printk(f ,##x); } while (0)
403#else
404# define dprintk(f, x...) do { /* nothing */ } while (0)
405#endif
406
407
408struct net_device;
409struct pci_dev;
410struct bcm43xx_dmaring;
411struct bcm43xx_pioqueue;
412
413struct bcm43xx_initval {
414 u16 offset;
415 u16 size;
416 u32 value;
417} __attribute__((__packed__));
418
419/* Values for bcm430x_sprominfo.locale */
420enum {
421 BCM43xx_LOCALE_WORLD = 0,
422 BCM43xx_LOCALE_THAILAND,
423 BCM43xx_LOCALE_ISRAEL,
424 BCM43xx_LOCALE_JORDAN,
425 BCM43xx_LOCALE_CHINA,
426 BCM43xx_LOCALE_JAPAN,
427 BCM43xx_LOCALE_USA_CANADA_ANZ,
428 BCM43xx_LOCALE_EUROPE,
429 BCM43xx_LOCALE_USA_LOW,
430 BCM43xx_LOCALE_JAPAN_HIGH,
431 BCM43xx_LOCALE_ALL,
432 BCM43xx_LOCALE_NONE,
433};
434
435#define BCM43xx_SPROM_SIZE 64 /* in 16-bit words. */
436struct bcm43xx_sprominfo {
437 u16 boardflags2;
438 u8 il0macaddr[6];
439 u8 et0macaddr[6];
440 u8 et1macaddr[6];
441 u8 et0phyaddr:5;
442 u8 et1phyaddr:5;
443 u8 et0mdcport:1;
444 u8 et1mdcport:1;
445 u8 boardrev;
446 u8 locale:4;
447 u8 antennas_aphy:2;
448 u8 antennas_bgphy:2;
449 u16 pa0b0;
450 u16 pa0b1;
451 u16 pa0b2;
452 u8 wl0gpio0;
453 u8 wl0gpio1;
454 u8 wl0gpio2;
455 u8 wl0gpio3;
456 u8 maxpower_aphy;
457 u8 maxpower_bgphy;
458 u16 pa1b0;
459 u16 pa1b1;
460 u16 pa1b2;
461 u8 idle_tssi_tgt_aphy;
462 u8 idle_tssi_tgt_bgphy;
463 u16 boardflags;
464 u16 antennagain_aphy;
465 u16 antennagain_bgphy;
466};
467
468/* Value pair to measure the LocalOscillator. */
469struct bcm43xx_lopair {
470 s8 low;
471 s8 high;
472 u8 used:1;
473};
474#define BCM43xx_LO_COUNT (14*4)
475
476struct bcm43xx_phyinfo {
477 /* Hardware Data */
478 u8 version;
479 u8 type;
480 u8 rev;
481 u16 antenna_diversity;
482 u16 savedpctlreg;
483 u16 minlowsig[2];
484 u16 minlowsigpos[2];
485 u8 connected:1,
486 calibrated:1,
487 is_locked:1, /* used in bcm43xx_phy_{un}lock() */
488 dyn_tssi_tbl:1; /* used in bcm43xx_phy_init_tssi2dbm_table() */
489 /* LO Measurement Data.
490 * Use bcm43xx_get_lopair() to get a value.
491 */
492 struct bcm43xx_lopair *_lo_pairs;
493
494 /* TSSI to dBm table in use */
495 const s8 *tssi2dbm;
496 /* idle TSSI value */
497 s8 idle_tssi;
498
499 /* Values from bcm43xx_calc_loopback_gain() */
500 u16 loopback_gain[2];
501
502 /* PHY lock for core.rev < 3
503 * This lock is only used by bcm43xx_phy_{un}lock()
504 */
505 spinlock_t lock;
506};
507
508
509struct bcm43xx_radioinfo {
510 u16 manufact;
511 u16 version;
512 u8 revision;
513
514 /* Desired TX power in dBm Q5.2 */
515 u16 txpower_desired;
516 /* TX Power control values. */
517 union {
518 /* B/G PHY */
519 struct {
520 u16 baseband_atten;
521 u16 radio_atten;
522 u16 txctl1;
523 u16 txctl2;
524 };
525 /* A PHY */
526 struct {
527 u16 txpwr_offset;
528 };
529 };
530
531 /* Current Interference Mitigation mode */
532 int interfmode;
533 /* Stack of saved values from the Interference Mitigation code.
534 * Each value in the stack is layed out as follows:
535 * bit 0-11: offset
536 * bit 12-15: register ID
537 * bit 16-32: value
538 * register ID is: 0x1 PHY, 0x2 Radio, 0x3 ILT
539 */
540#define BCM43xx_INTERFSTACK_SIZE 26
541 u32 interfstack[BCM43xx_INTERFSTACK_SIZE];
542
543 /* Saved values from the NRSSI Slope calculation */
544 s16 nrssi[2];
545 s32 nrssislope;
546 /* In memory nrssi lookup table. */
547 s8 nrssi_lt[64];
548
549 /* current channel */
550 u8 channel;
551 u8 initial_channel;
552
553 u16 lofcal;
554
555 u16 initval;
556
557 u8 enabled:1;
558 /* ACI (adjacent channel interference) flags. */
559 u8 aci_enable:1,
560 aci_wlan_automatic:1,
561 aci_hw_rssi:1;
562};
563
564/* Data structures for DMA transmission, per 80211 core. */
565struct bcm43xx_dma {
566 struct bcm43xx_dmaring *tx_ring0;
567 struct bcm43xx_dmaring *tx_ring1;
568 struct bcm43xx_dmaring *tx_ring2;
569 struct bcm43xx_dmaring *tx_ring3;
570 struct bcm43xx_dmaring *rx_ring0;
571 struct bcm43xx_dmaring *rx_ring1; /* only available on core.rev < 5 */
572};
573
574/* Data structures for PIO transmission, per 80211 core. */
575struct bcm43xx_pio {
576 struct bcm43xx_pioqueue *queue0;
577 struct bcm43xx_pioqueue *queue1;
578 struct bcm43xx_pioqueue *queue2;
579 struct bcm43xx_pioqueue *queue3;
580};
581
582#define BCM43xx_MAX_80211_CORES 2
583
584#ifdef CONFIG_BCM947XX
585#define core_offset(bcm) (bcm)->current_core_offset
586#else
587#define core_offset(bcm) 0
588#endif
589
590/* Generic information about a core. */
591struct bcm43xx_coreinfo {
592 u8 available:1,
593 enabled:1,
594 initialized:1;
595 /** core_id ID number */
596 u16 id;
597 /** core_rev revision number */
598 u8 rev;
599 /** Index number for _switch_core() */
600 u8 index;
601};
602
603/* Additional information for each 80211 core. */
604struct bcm43xx_coreinfo_80211 {
605 /* PHY device. */
606 struct bcm43xx_phyinfo phy;
607 /* Radio device. */
608 struct bcm43xx_radioinfo radio;
609 union {
610 /* DMA context. */
611 struct bcm43xx_dma dma;
612 /* PIO context. */
613 struct bcm43xx_pio pio;
614 };
615};
616
617/* Context information for a noise calculation (Link Quality). */
618struct bcm43xx_noise_calculation {
619 struct bcm43xx_coreinfo *core_at_start;
620 u8 channel_at_start;
621 u8 calculation_running:1;
622 u8 nr_samples;
623 s8 samples[8][4];
624};
625
626struct bcm43xx_stats {
627 u8 link_quality;
628 u8 noise;
629 struct iw_statistics wstats;
630 /* Store the last TX/RX times here for updating the leds. */
631 unsigned long last_tx;
632 unsigned long last_rx;
633};
634
635struct bcm43xx_key {
636 u8 enabled:1;
637 u8 algorithm;
638};
639
640struct bcm43xx_private {
641 struct bcm43xx_sysfs sysfs;
642
643 struct ieee80211_device *ieee;
644 struct ieee80211softmac_device *softmac;
645
646 struct net_device *net_dev;
647 struct pci_dev *pci_dev;
648 unsigned int irq;
649
650 void __iomem *mmio_addr;
651 unsigned int mmio_len;
652
653 /* Do not use the lock directly. Use the bcm43xx_lock* helper
654 * functions, to be MMIO-safe. */
655 spinlock_t _lock;
656
657 /* Driver status flags. */
658 u32 initialized:1, /* init_board() succeed */
659 was_initialized:1, /* for PCI suspend/resume. */
660 shutting_down:1, /* free_board() in progress */
661 __using_pio:1, /* Internal, use bcm43xx_using_pio(). */
662 bad_frames_preempt:1, /* Use "Bad Frames Preemption" (default off) */
663 reg124_set_0x4:1, /* Some variable to keep track of IRQ stuff. */
664 powersaving:1, /* TRUE if we are in PowerSaving mode. FALSE otherwise. */
665 short_preamble:1, /* TRUE, if short preamble is enabled. */
666 firmware_norelease:1; /* Do not release the firmware. Used on suspend. */
667
668 struct bcm43xx_stats stats;
669
670 /* Bus type we are connected to.
671 * This is currently always BCM43xx_BUSTYPE_PCI
672 */
673 u8 bustype;
674
675 u16 board_vendor;
676 u16 board_type;
677 u16 board_revision;
678
679 u16 chip_id;
680 u8 chip_rev;
681 u8 chip_package;
682
683 struct bcm43xx_sprominfo sprom;
684#define BCM43xx_NR_LEDS 4
685 struct bcm43xx_led leds[BCM43xx_NR_LEDS];
686
687 /* The currently active core. */
688 struct bcm43xx_coreinfo *current_core;
689#ifdef CONFIG_BCM947XX
690 /** current core memory offset */
691 u32 current_core_offset;
692#endif
693 struct bcm43xx_coreinfo *active_80211_core;
694 /* coreinfo structs for all possible cores follow.
695 * Note that a core might not exist.
696 * So check the coreinfo flags before using it.
697 */
698 struct bcm43xx_coreinfo core_chipcommon;
699 struct bcm43xx_coreinfo core_pci;
700 struct bcm43xx_coreinfo core_80211[ BCM43xx_MAX_80211_CORES ];
701 /* Additional information, specific to the 80211 cores. */
702 struct bcm43xx_coreinfo_80211 core_80211_ext[ BCM43xx_MAX_80211_CORES ];
703 /* Index of the current 80211 core. If current_core is not
704 * an 80211 core, this is -1.
705 */
706 int current_80211_core_idx;
707 /* Number of available 80211 cores. */
708 int nr_80211_available;
709
710 u32 chipcommon_capabilities;
711
712 /* Reason code of the last interrupt. */
713 u32 irq_reason;
714 u32 dma_reason[4];
715 /* saved irq enable/disable state bitfield. */
716 u32 irq_savedstate;
717 /* Link Quality calculation context. */
718 struct bcm43xx_noise_calculation noisecalc;
719
720 /* Threshold values. */
721 //TODO: The RTS thr has to be _used_. Currently, it is only set via WX.
722 u32 rts_threshold;
723
724 /* Interrupt Service Routine tasklet (bottom-half) */
725 struct tasklet_struct isr_tasklet;
726
727 /* Periodic tasks */
728 struct timer_list periodic_tasks;
729 unsigned int periodic_state;
730
731 struct work_struct restart_work;
732
733 /* Informational stuff. */
734 char nick[IW_ESSID_MAX_SIZE + 1];
735
736 /* encryption/decryption */
737 u16 security_offset;
738 struct bcm43xx_key key[54];
739 u8 default_key_idx;
740
741 /* Firmware. */
742 const struct firmware *ucode;
743 const struct firmware *pcm;
744 const struct firmware *initvals0;
745 const struct firmware *initvals1;
746
747 /* Debugging stuff follows. */
748#ifdef CONFIG_BCM43XX_DEBUG
749 struct bcm43xx_dfsentry *dfsentry;
750#endif
751};
752
753/* bcm43xx_(un)lock() protect struct bcm43xx_private.
754 * Note that _NO_ MMIO writes are allowed. If you want to
755 * write to the device through MMIO in the critical section, use
756 * the *_mmio lock functions.
757 * MMIO read-access is allowed, though.
758 */
759#define bcm43xx_lock(bcm, flags) spin_lock_irqsave(&(bcm)->_lock, flags)
760#define bcm43xx_unlock(bcm, flags) spin_unlock_irqrestore(&(bcm)->_lock, flags)
761/* bcm43xx_(un)lock_mmio() protect struct bcm43xx_private and MMIO.
762 * MMIO write-access to the device is allowed.
763 * All MMIO writes are flushed on unlock, so it is guaranteed to not
764 * interfere with other threads writing MMIO registers.
765 */
766#define bcm43xx_lock_mmio(bcm, flags) bcm43xx_lock(bcm, flags)
767#define bcm43xx_unlock_mmio(bcm, flags) do { mmiowb(); bcm43xx_unlock(bcm, flags); } while (0)
768
769static inline
770struct bcm43xx_private * bcm43xx_priv(struct net_device *dev)
771{
772 return ieee80211softmac_priv(dev);
773}
774
775
776/* Helper function, which returns a boolean.
777 * TRUE, if PIO is used; FALSE, if DMA is used.
778 */
779#if defined(CONFIG_BCM43XX_DMA) && defined(CONFIG_BCM43XX_PIO)
780static inline
781int bcm43xx_using_pio(struct bcm43xx_private *bcm)
782{
783 return bcm->__using_pio;
784}
785#elif defined(CONFIG_BCM43XX_DMA)
786static inline
787int bcm43xx_using_pio(struct bcm43xx_private *bcm)
788{
789 return 0;
790}
791#elif defined(CONFIG_BCM43XX_PIO)
792static inline
793int bcm43xx_using_pio(struct bcm43xx_private *bcm)
794{
795 return 1;
796}
797#else
798# error "Using neither DMA nor PIO? Confused..."
799#endif
800
801/* Helper functions to access data structures private to the 80211 cores.
802 * Note that we _must_ have an 80211 core mapped when calling
803 * any of these functions.
804 */
805static inline
806struct bcm43xx_pio * bcm43xx_current_pio(struct bcm43xx_private *bcm)
807{
808 assert(bcm43xx_using_pio(bcm));
809 assert(bcm->current_80211_core_idx >= 0);
810 assert(bcm->current_80211_core_idx < BCM43xx_MAX_80211_CORES);
811 return &(bcm->core_80211_ext[bcm->current_80211_core_idx].pio);
812}
813static inline
814struct bcm43xx_dma * bcm43xx_current_dma(struct bcm43xx_private *bcm)
815{
816 assert(!bcm43xx_using_pio(bcm));
817 assert(bcm->current_80211_core_idx >= 0);
818 assert(bcm->current_80211_core_idx < BCM43xx_MAX_80211_CORES);
819 return &(bcm->core_80211_ext[bcm->current_80211_core_idx].dma);
820}
821static inline
822struct bcm43xx_phyinfo * bcm43xx_current_phy(struct bcm43xx_private *bcm)
823{
824 assert(bcm->current_80211_core_idx >= 0);
825 assert(bcm->current_80211_core_idx < BCM43xx_MAX_80211_CORES);
826 return &(bcm->core_80211_ext[bcm->current_80211_core_idx].phy);
827}
828static inline
829struct bcm43xx_radioinfo * bcm43xx_current_radio(struct bcm43xx_private *bcm)
830{
831 assert(bcm->current_80211_core_idx >= 0);
832 assert(bcm->current_80211_core_idx < BCM43xx_MAX_80211_CORES);
833 return &(bcm->core_80211_ext[bcm->current_80211_core_idx].radio);
834}
835
836/* Are we running in init_board() context? */
837static inline
838int bcm43xx_is_initializing(struct bcm43xx_private *bcm)
839{
840 if (bcm->initialized)
841 return 0;
842 if (bcm->shutting_down)
843 return 0;
844 return 1;
845}
846
847static inline
848struct bcm43xx_lopair * bcm43xx_get_lopair(struct bcm43xx_phyinfo *phy,
849 u16 radio_attenuation,
850 u16 baseband_attenuation)
851{
852 return phy->_lo_pairs + (radio_attenuation + 14 * (baseband_attenuation / 2));
853}
854
855
856static inline
857u16 bcm43xx_read16(struct bcm43xx_private *bcm, u16 offset)
858{
859 return ioread16(bcm->mmio_addr + core_offset(bcm) + offset);
860}
861
862static inline
863void bcm43xx_write16(struct bcm43xx_private *bcm, u16 offset, u16 value)
864{
865 iowrite16(value, bcm->mmio_addr + core_offset(bcm) + offset);
866}
867
868static inline
869u32 bcm43xx_read32(struct bcm43xx_private *bcm, u16 offset)
870{
871 return ioread32(bcm->mmio_addr + core_offset(bcm) + offset);
872}
873
874static inline
875void bcm43xx_write32(struct bcm43xx_private *bcm, u16 offset, u32 value)
876{
877 iowrite32(value, bcm->mmio_addr + core_offset(bcm) + offset);
878}
879
880static inline
881int bcm43xx_pci_read_config16(struct bcm43xx_private *bcm, int offset, u16 *value)
882{
883 return pci_read_config_word(bcm->pci_dev, offset, value);
884}
885
886static inline
887int bcm43xx_pci_read_config32(struct bcm43xx_private *bcm, int offset, u32 *value)
888{
889 return pci_read_config_dword(bcm->pci_dev, offset, value);
890}
891
892static inline
893int bcm43xx_pci_write_config16(struct bcm43xx_private *bcm, int offset, u16 value)
894{
895 return pci_write_config_word(bcm->pci_dev, offset, value);
896}
897
898static inline
899int bcm43xx_pci_write_config32(struct bcm43xx_private *bcm, int offset, u32 value)
900{
901 return pci_write_config_dword(bcm->pci_dev, offset, value);
902}
903
904/** Limit a value between two limits */
905#ifdef limit_value
906# undef limit_value
907#endif
908#define limit_value(value, min, max) \
909 ({ \
910 typeof(value) __value = (value); \
911 typeof(value) __min = (min); \
912 typeof(value) __max = (max); \
913 if (__value < __min) \
914 __value = __min; \
915 else if (__value > __max) \
916 __value = __max; \
917 __value; \
918 })
919
920/** Helpers to print MAC addresses. */
921#define BCM43xx_MACFMT "%02x:%02x:%02x:%02x:%02x:%02x"
922#define BCM43xx_MACARG(x) ((u8*)(x))[0], ((u8*)(x))[1], \
923 ((u8*)(x))[2], ((u8*)(x))[3], \
924 ((u8*)(x))[4], ((u8*)(x))[5]
925
926#endif /* BCM43xx_H_ */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c
new file mode 100644
index 000000000000..d2c3401e9b70
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c
@@ -0,0 +1,499 @@
1/*
2
3 Broadcom BCM43xx wireless driver
4
5 debugfs driver debugging code
6
7 Copyright (c) 2005 Michael Buesch <mbuesch@freenet.de>
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; see the file COPYING. If not, write to
21 the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
22 Boston, MA 02110-1301, USA.
23
24*/
25
26
27
28#include <linux/fs.h>
29#include <linux/debugfs.h>
30#include <linux/slab.h>
31#include <linux/netdevice.h>
32#include <linux/pci.h>
33#include <asm/io.h>
34
35#include "bcm43xx.h"
36#include "bcm43xx_main.h"
37#include "bcm43xx_debugfs.h"
38#include "bcm43xx_dma.h"
39#include "bcm43xx_pio.h"
40#include "bcm43xx_xmit.h"
41
42#define REALLY_BIG_BUFFER_SIZE (1024*256)
43
44static struct bcm43xx_debugfs fs;
45static char really_big_buffer[REALLY_BIG_BUFFER_SIZE];
46static DECLARE_MUTEX(big_buffer_sem);
47
48
49static ssize_t write_file_dummy(struct file *file, const char __user *buf,
50 size_t count, loff_t *ppos)
51{
52 return count;
53}
54
55static int open_file_generic(struct inode *inode, struct file *file)
56{
57 file->private_data = inode->u.generic_ip;
58 return 0;
59}
60
61#define fappend(fmt, x...) pos += snprintf(buf + pos, len - pos, fmt , ##x)
62
63static ssize_t devinfo_read_file(struct file *file, char __user *userbuf,
64 size_t count, loff_t *ppos)
65{
66 const size_t len = REALLY_BIG_BUFFER_SIZE;
67
68 struct bcm43xx_private *bcm = file->private_data;
69 char *buf = really_big_buffer;
70 size_t pos = 0;
71 ssize_t res;
72 struct net_device *net_dev;
73 struct pci_dev *pci_dev;
74 unsigned long flags;
75 u16 tmp16;
76 int i;
77
78 down(&big_buffer_sem);
79
80 bcm43xx_lock_mmio(bcm, flags);
81 if (!bcm->initialized) {
82 fappend("Board not initialized.\n");
83 goto out;
84 }
85 net_dev = bcm->net_dev;
86 pci_dev = bcm->pci_dev;
87
88 /* This is where the information is written to the "devinfo" file */
89 fappend("*** %s devinfo ***\n", net_dev->name);
90 fappend("vendor: 0x%04x device: 0x%04x\n",
91 pci_dev->vendor, pci_dev->device);
92 fappend("subsystem_vendor: 0x%04x subsystem_device: 0x%04x\n",
93 pci_dev->subsystem_vendor, pci_dev->subsystem_device);
94 fappend("IRQ: %d\n", bcm->irq);
95 fappend("mmio_addr: 0x%p mmio_len: %u\n", bcm->mmio_addr, bcm->mmio_len);
96 fappend("chip_id: 0x%04x chip_rev: 0x%02x\n", bcm->chip_id, bcm->chip_rev);
97 if ((bcm->core_80211[0].rev >= 3) && (bcm43xx_read32(bcm, 0x0158) & (1 << 16)))
98 fappend("Radio disabled by hardware!\n");
99 if ((bcm->core_80211[0].rev < 3) && !(bcm43xx_read16(bcm, 0x049A) & (1 << 4)))
100 fappend("Radio disabled by hardware!\n");
101 fappend("board_vendor: 0x%04x board_type: 0x%04x\n", bcm->board_vendor,
102 bcm->board_type);
103
104 fappend("\nCores:\n");
105#define fappend_core(name, info) fappend("core \"" name "\" %s, %s, id: 0x%04x, " \
106 "rev: 0x%02x, index: 0x%02x\n", \
107 (info).available \
108 ? "available" : "nonavailable", \
109 (info).enabled \
110 ? "enabled" : "disabled", \
111 (info).id, (info).rev, (info).index)
112 fappend_core("CHIPCOMMON", bcm->core_chipcommon);
113 fappend_core("PCI", bcm->core_pci);
114 fappend_core("first 80211", bcm->core_80211[0]);
115 fappend_core("second 80211", bcm->core_80211[1]);
116#undef fappend_core
117 tmp16 = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL);
118 fappend("LEDs: ");
119 for (i = 0; i < BCM43xx_NR_LEDS; i++)
120 fappend("%d ", !!(tmp16 & (1 << i)));
121 fappend("\n");
122
123out:
124 bcm43xx_unlock_mmio(bcm, flags);
125 res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
126 up(&big_buffer_sem);
127 return res;
128}
129
130static ssize_t drvinfo_read_file(struct file *file, char __user *userbuf,
131 size_t count, loff_t *ppos)
132{
133 const size_t len = REALLY_BIG_BUFFER_SIZE;
134
135 char *buf = really_big_buffer;
136 size_t pos = 0;
137 ssize_t res;
138
139 down(&big_buffer_sem);
140
141 /* This is where the information is written to the "driver" file */
142 fappend(KBUILD_MODNAME " driver\n");
143 fappend("Compiled at: %s %s\n", __DATE__, __TIME__);
144
145 res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
146 up(&big_buffer_sem);
147 return res;
148}
149
150static ssize_t spromdump_read_file(struct file *file, char __user *userbuf,
151 size_t count, loff_t *ppos)
152{
153 const size_t len = REALLY_BIG_BUFFER_SIZE;
154
155 struct bcm43xx_private *bcm = file->private_data;
156 char *buf = really_big_buffer;
157 size_t pos = 0;
158 ssize_t res;
159 unsigned long flags;
160
161 down(&big_buffer_sem);
162 bcm43xx_lock_mmio(bcm, flags);
163 if (!bcm->initialized) {
164 fappend("Board not initialized.\n");
165 goto out;
166 }
167
168 /* This is where the information is written to the "sprom_dump" file */
169 fappend("boardflags: 0x%04x\n", bcm->sprom.boardflags);
170
171out:
172 bcm43xx_unlock_mmio(bcm, flags);
173 res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
174 up(&big_buffer_sem);
175 return res;
176}
177
178static ssize_t tsf_read_file(struct file *file, char __user *userbuf,
179 size_t count, loff_t *ppos)
180{
181 const size_t len = REALLY_BIG_BUFFER_SIZE;
182
183 struct bcm43xx_private *bcm = file->private_data;
184 char *buf = really_big_buffer;
185 size_t pos = 0;
186 ssize_t res;
187 unsigned long flags;
188 u64 tsf;
189
190 down(&big_buffer_sem);
191 bcm43xx_lock_mmio(bcm, flags);
192 if (!bcm->initialized) {
193 fappend("Board not initialized.\n");
194 goto out;
195 }
196 bcm43xx_tsf_read(bcm, &tsf);
197 fappend("0x%08x%08x\n",
198 (unsigned int)((tsf & 0xFFFFFFFF00000000ULL) >> 32),
199 (unsigned int)(tsf & 0xFFFFFFFFULL));
200
201out:
202 bcm43xx_unlock_mmio(bcm, flags);
203 res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
204 up(&big_buffer_sem);
205 return res;
206}
207
208static ssize_t tsf_write_file(struct file *file, const char __user *user_buf,
209 size_t count, loff_t *ppos)
210{
211 struct bcm43xx_private *bcm = file->private_data;
212 char *buf = really_big_buffer;
213 ssize_t buf_size;
214 ssize_t res;
215 unsigned long flags;
216 u64 tsf;
217
218 buf_size = min(count, sizeof (really_big_buffer) - 1);
219 down(&big_buffer_sem);
220 if (copy_from_user(buf, user_buf, buf_size)) {
221 res = -EFAULT;
222 goto out_up;
223 }
224 bcm43xx_lock_mmio(bcm, flags);
225 if (!bcm->initialized) {
226 printk(KERN_INFO PFX "debugfs: Board not initialized.\n");
227 res = -EFAULT;
228 goto out_unlock;
229 }
230 if (sscanf(buf, "%lli", &tsf) != 1) {
231 printk(KERN_INFO PFX "debugfs: invalid values for \"tsf\"\n");
232 res = -EINVAL;
233 goto out_unlock;
234 }
235 bcm43xx_tsf_write(bcm, tsf);
236 res = buf_size;
237
238out_unlock:
239 bcm43xx_unlock_mmio(bcm, flags);
240out_up:
241 up(&big_buffer_sem);
242 return res;
243}
244
245static ssize_t txstat_read_file(struct file *file, char __user *userbuf,
246 size_t count, loff_t *ppos)
247{
248 const size_t len = REALLY_BIG_BUFFER_SIZE;
249
250 struct bcm43xx_private *bcm = file->private_data;
251 char *buf = really_big_buffer;
252 size_t pos = 0;
253 ssize_t res;
254 unsigned long flags;
255 struct bcm43xx_dfsentry *e;
256 struct bcm43xx_xmitstatus *status;
257 int i, cnt, j = 0;
258
259 down(&big_buffer_sem);
260 bcm43xx_lock(bcm, flags);
261
262 fappend("Last %d logged xmitstatus blobs (Latest first):\n\n",
263 BCM43xx_NR_LOGGED_XMITSTATUS);
264 e = bcm->dfsentry;
265 if (e->xmitstatus_printing == 0) {
266 /* At the beginning, make a copy of all data to avoid
267 * concurrency, as this function is called multiple
268 * times for big logs. Without copying, the data might
269 * change between reads. This would result in total trash.
270 */
271 e->xmitstatus_printing = 1;
272 e->saved_xmitstatus_ptr = e->xmitstatus_ptr;
273 e->saved_xmitstatus_cnt = e->xmitstatus_cnt;
274 memcpy(e->xmitstatus_print_buffer, e->xmitstatus_buffer,
275 BCM43xx_NR_LOGGED_XMITSTATUS * sizeof(*(e->xmitstatus_buffer)));
276 }
277 i = e->saved_xmitstatus_ptr - 1;
278 if (i < 0)
279 i = BCM43xx_NR_LOGGED_XMITSTATUS - 1;
280 cnt = e->saved_xmitstatus_cnt;
281 while (cnt) {
282 status = e->xmitstatus_print_buffer + i;
283 fappend("0x%02x: cookie: 0x%04x, flags: 0x%02x, "
284 "cnt1: 0x%02x, cnt2: 0x%02x, seq: 0x%04x, "
285 "unk: 0x%04x\n", j,
286 status->cookie, status->flags,
287 status->cnt1, status->cnt2, status->seq,
288 status->unknown);
289 j++;
290 cnt--;
291 i--;
292 if (i < 0)
293 i = BCM43xx_NR_LOGGED_XMITSTATUS - 1;
294 }
295
296 bcm43xx_unlock(bcm, flags);
297 res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
298 bcm43xx_lock(bcm, flags);
299 if (*ppos == pos) {
300 /* Done. Drop the copied data. */
301 e->xmitstatus_printing = 0;
302 }
303 bcm43xx_unlock(bcm, flags);
304 up(&big_buffer_sem);
305 return res;
306}
307
308#undef fappend
309
310
311static struct file_operations devinfo_fops = {
312 .read = devinfo_read_file,
313 .write = write_file_dummy,
314 .open = open_file_generic,
315};
316
317static struct file_operations spromdump_fops = {
318 .read = spromdump_read_file,
319 .write = write_file_dummy,
320 .open = open_file_generic,
321};
322
323static struct file_operations drvinfo_fops = {
324 .read = drvinfo_read_file,
325 .write = write_file_dummy,
326 .open = open_file_generic,
327};
328
329static struct file_operations tsf_fops = {
330 .read = tsf_read_file,
331 .write = tsf_write_file,
332 .open = open_file_generic,
333};
334
335static struct file_operations txstat_fops = {
336 .read = txstat_read_file,
337 .write = write_file_dummy,
338 .open = open_file_generic,
339};
340
341
342void bcm43xx_debugfs_add_device(struct bcm43xx_private *bcm)
343{
344 struct bcm43xx_dfsentry *e;
345 char devdir[IFNAMSIZ];
346
347 assert(bcm);
348 e = kzalloc(sizeof(*e), GFP_KERNEL);
349 if (!e) {
350 printk(KERN_ERR PFX "out of memory\n");
351 return;
352 }
353 e->bcm = bcm;
354 e->xmitstatus_buffer = kzalloc(BCM43xx_NR_LOGGED_XMITSTATUS
355 * sizeof(*(e->xmitstatus_buffer)),
356 GFP_KERNEL);
357 if (!e->xmitstatus_buffer) {
358 printk(KERN_ERR PFX "out of memory\n");
359 kfree(e);
360 return;
361 }
362 e->xmitstatus_print_buffer = kzalloc(BCM43xx_NR_LOGGED_XMITSTATUS
363 * sizeof(*(e->xmitstatus_buffer)),
364 GFP_KERNEL);
365 if (!e->xmitstatus_print_buffer) {
366 printk(KERN_ERR PFX "out of memory\n");
367 kfree(e);
368 return;
369 }
370
371
372 bcm->dfsentry = e;
373
374 strncpy(devdir, bcm->net_dev->name, ARRAY_SIZE(devdir));
375 e->subdir = debugfs_create_dir(devdir, fs.root);
376 e->dentry_devinfo = debugfs_create_file("devinfo", 0444, e->subdir,
377 bcm, &devinfo_fops);
378 if (!e->dentry_devinfo)
379 printk(KERN_ERR PFX "debugfs: creating \"devinfo\" for \"%s\" failed!\n", devdir);
380 e->dentry_spromdump = debugfs_create_file("sprom_dump", 0444, e->subdir,
381 bcm, &spromdump_fops);
382 if (!e->dentry_spromdump)
383 printk(KERN_ERR PFX "debugfs: creating \"sprom_dump\" for \"%s\" failed!\n", devdir);
384 e->dentry_tsf = debugfs_create_file("tsf", 0666, e->subdir,
385 bcm, &tsf_fops);
386 if (!e->dentry_tsf)
387 printk(KERN_ERR PFX "debugfs: creating \"tsf\" for \"%s\" failed!\n", devdir);
388 e->dentry_txstat = debugfs_create_file("tx_status", 0444, e->subdir,
389 bcm, &txstat_fops);
390 if (!e->dentry_txstat)
391 printk(KERN_ERR PFX "debugfs: creating \"tx_status\" for \"%s\" failed!\n", devdir);
392}
393
394void bcm43xx_debugfs_remove_device(struct bcm43xx_private *bcm)
395{
396 struct bcm43xx_dfsentry *e;
397
398 if (!bcm)
399 return;
400
401 e = bcm->dfsentry;
402 assert(e);
403 debugfs_remove(e->dentry_spromdump);
404 debugfs_remove(e->dentry_devinfo);
405 debugfs_remove(e->dentry_tsf);
406 debugfs_remove(e->dentry_txstat);
407 debugfs_remove(e->subdir);
408 kfree(e->xmitstatus_buffer);
409 kfree(e->xmitstatus_print_buffer);
410 kfree(e);
411}
412
413void bcm43xx_debugfs_log_txstat(struct bcm43xx_private *bcm,
414 struct bcm43xx_xmitstatus *status)
415{
416 struct bcm43xx_dfsentry *e;
417 struct bcm43xx_xmitstatus *savedstatus;
418
419 /* This is protected by bcm->_lock */
420 e = bcm->dfsentry;
421 assert(e);
422 savedstatus = e->xmitstatus_buffer + e->xmitstatus_ptr;
423 memcpy(savedstatus, status, sizeof(*status));
424 e->xmitstatus_ptr++;
425 if (e->xmitstatus_ptr >= BCM43xx_NR_LOGGED_XMITSTATUS)
426 e->xmitstatus_ptr = 0;
427 if (e->xmitstatus_cnt < BCM43xx_NR_LOGGED_XMITSTATUS)
428 e->xmitstatus_cnt++;
429}
430
431void bcm43xx_debugfs_init(void)
432{
433 memset(&fs, 0, sizeof(fs));
434 fs.root = debugfs_create_dir(KBUILD_MODNAME, NULL);
435 if (!fs.root)
436 printk(KERN_ERR PFX "debugfs: creating \"" KBUILD_MODNAME "\" subdir failed!\n");
437 fs.dentry_driverinfo = debugfs_create_file("driver", 0444, fs.root, NULL, &drvinfo_fops);
438 if (!fs.dentry_driverinfo)
439 printk(KERN_ERR PFX "debugfs: creating \"" KBUILD_MODNAME "/driver\" failed!\n");
440}
441
442void bcm43xx_debugfs_exit(void)
443{
444 debugfs_remove(fs.dentry_driverinfo);
445 debugfs_remove(fs.root);
446}
447
448void bcm43xx_printk_dump(const char *data,
449 size_t size,
450 const char *description)
451{
452 size_t i;
453 char c;
454
455 printk(KERN_INFO PFX "Data dump (%s, %u bytes):",
456 description, size);
457 for (i = 0; i < size; i++) {
458 c = data[i];
459 if (i % 8 == 0)
460 printk("\n" KERN_INFO PFX "0x%08x: 0x%02x, ", i, c & 0xff);
461 else
462 printk("0x%02x, ", c & 0xff);
463 }
464 printk("\n");
465}
466
467void bcm43xx_printk_bitdump(const unsigned char *data,
468 size_t bytes, int msb_to_lsb,
469 const char *description)
470{
471 size_t i;
472 int j;
473 const unsigned char *d;
474
475 printk(KERN_INFO PFX "*** Bitdump (%s, %u bytes, %s) ***",
476 description, bytes, msb_to_lsb ? "MSB to LSB" : "LSB to MSB");
477 for (i = 0; i < bytes; i++) {
478 d = data + i;
479 if (i % 8 == 0)
480 printk("\n" KERN_INFO PFX "0x%08x: ", i);
481 if (msb_to_lsb) {
482 for (j = 7; j >= 0; j--) {
483 if (*d & (1 << j))
484 printk("1");
485 else
486 printk("0");
487 }
488 } else {
489 for (j = 0; j < 8; j++) {
490 if (*d & (1 << j))
491 printk("1");
492 else
493 printk("0");
494 }
495 }
496 printk(" ");
497 }
498 printk("\n");
499}
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.h b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.h
new file mode 100644
index 000000000000..50ce267f794d
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.h
@@ -0,0 +1,117 @@
1#ifndef BCM43xx_DEBUGFS_H_
2#define BCM43xx_DEBUGFS_H_
3
4struct bcm43xx_private;
5struct bcm43xx_xmitstatus;
6
7#ifdef CONFIG_BCM43XX_DEBUG
8
9#include <linux/list.h>
10#include <asm/semaphore.h>
11
12struct dentry;
13
14/* limited by the size of the "really_big_buffer" */
15#define BCM43xx_NR_LOGGED_XMITSTATUS 100
16
17struct bcm43xx_dfsentry {
18 struct dentry *subdir;
19 struct dentry *dentry_devinfo;
20 struct dentry *dentry_spromdump;
21 struct dentry *dentry_tsf;
22 struct dentry *dentry_txstat;
23
24 struct bcm43xx_private *bcm;
25
26 /* saved xmitstatus. */
27 struct bcm43xx_xmitstatus *xmitstatus_buffer;
28 int xmitstatus_ptr;
29 int xmitstatus_cnt;
30 /* We need a seperate buffer while printing to avoid
31 * concurrency issues. (New xmitstatus can arrive
32 * while we are printing).
33 */
34 struct bcm43xx_xmitstatus *xmitstatus_print_buffer;
35 int saved_xmitstatus_ptr;
36 int saved_xmitstatus_cnt;
37 int xmitstatus_printing;
38};
39
40struct bcm43xx_debugfs {
41 struct dentry *root;
42 struct dentry *dentry_driverinfo;
43};
44
45void bcm43xx_debugfs_init(void);
46void bcm43xx_debugfs_exit(void);
47void bcm43xx_debugfs_add_device(struct bcm43xx_private *bcm);
48void bcm43xx_debugfs_remove_device(struct bcm43xx_private *bcm);
49void bcm43xx_debugfs_log_txstat(struct bcm43xx_private *bcm,
50 struct bcm43xx_xmitstatus *status);
51
52/* Debug helper: Dump binary data through printk. */
53void bcm43xx_printk_dump(const char *data,
54 size_t size,
55 const char *description);
56/* Debug helper: Dump bitwise binary data through printk. */
57void bcm43xx_printk_bitdump(const unsigned char *data,
58 size_t bytes, int msb_to_lsb,
59 const char *description);
60#define bcm43xx_printk_bitdumpt(pointer, msb_to_lsb, description) \
61 do { \
62 bcm43xx_printk_bitdump((const unsigned char *)(pointer), \
63 sizeof(*(pointer)), \
64 (msb_to_lsb), \
65 (description)); \
66 } while (0)
67
68#else /* CONFIG_BCM43XX_DEBUG*/
69
70static inline
71void bcm43xx_debugfs_init(void) { }
72static inline
73void bcm43xx_debugfs_exit(void) { }
74static inline
75void bcm43xx_debugfs_add_device(struct bcm43xx_private *bcm) { }
76static inline
77void bcm43xx_debugfs_remove_device(struct bcm43xx_private *bcm) { }
78static inline
79void bcm43xx_debugfs_log_txstat(struct bcm43xx_private *bcm,
80 struct bcm43xx_xmitstatus *status) { }
81
82static inline
83void bcm43xx_printk_dump(const char *data,
84 size_t size,
85 const char *description)
86{
87}
88static inline
89void bcm43xx_printk_bitdump(const unsigned char *data,
90 size_t bytes, int msb_to_lsb,
91 const char *description)
92{
93}
94#define bcm43xx_printk_bitdumpt(pointer, msb_to_lsb, description) do { /* nothing */ } while (0)
95
96#endif /* CONFIG_BCM43XX_DEBUG*/
97
98/* Ugly helper macros to make incomplete code more verbose on runtime */
99#ifdef TODO
100# undef TODO
101#endif
102#define TODO() \
103 do { \
104 printk(KERN_INFO PFX "TODO: Incomplete code in %s() at %s:%d\n", \
105 __FUNCTION__, __FILE__, __LINE__); \
106 } while (0)
107
108#ifdef FIXME
109# undef FIXME
110#endif
111#define FIXME() \
112 do { \
113 printk(KERN_INFO PFX "FIXME: Possibly broken code in %s() at %s:%d\n", \
114 __FUNCTION__, __FILE__, __LINE__); \
115 } while (0)
116
117#endif /* BCM43xx_DEBUGFS_H_ */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c
new file mode 100644
index 000000000000..c3681b8f09b4
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c
@@ -0,0 +1,968 @@
1/*
2
3 Broadcom BCM43xx wireless driver
4
5 DMA ringbuffer and descriptor allocation/management
6
7 Copyright (c) 2005 Michael Buesch <mbuesch@freenet.de>
8
9 Some code in this file is derived from the b44.c driver
10 Copyright (C) 2002 David S. Miller
11 Copyright (C) Pekka Pietikainen
12
13 This program is free software; you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation; either version 2 of the License, or
16 (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; see the file COPYING. If not, write to
25 the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
26 Boston, MA 02110-1301, USA.
27
28*/
29
30#include "bcm43xx.h"
31#include "bcm43xx_dma.h"
32#include "bcm43xx_main.h"
33#include "bcm43xx_debugfs.h"
34#include "bcm43xx_power.h"
35#include "bcm43xx_xmit.h"
36
37#include <linux/dma-mapping.h>
38#include <linux/pci.h>
39#include <linux/delay.h>
40#include <linux/skbuff.h>
41
42
43static inline int free_slots(struct bcm43xx_dmaring *ring)
44{
45 return (ring->nr_slots - ring->used_slots);
46}
47
48static inline int next_slot(struct bcm43xx_dmaring *ring, int slot)
49{
50 assert(slot >= -1 && slot <= ring->nr_slots - 1);
51 if (slot == ring->nr_slots - 1)
52 return 0;
53 return slot + 1;
54}
55
56static inline int prev_slot(struct bcm43xx_dmaring *ring, int slot)
57{
58 assert(slot >= 0 && slot <= ring->nr_slots - 1);
59 if (slot == 0)
60 return ring->nr_slots - 1;
61 return slot - 1;
62}
63
64/* Request a slot for usage. */
65static inline
66int request_slot(struct bcm43xx_dmaring *ring)
67{
68 int slot;
69
70 assert(ring->tx);
71 assert(!ring->suspended);
72 assert(free_slots(ring) != 0);
73
74 slot = next_slot(ring, ring->current_slot);
75 ring->current_slot = slot;
76 ring->used_slots++;
77
78 /* Check the number of available slots and suspend TX,
79 * if we are running low on free slots.
80 */
81 if (unlikely(free_slots(ring) < ring->suspend_mark)) {
82 netif_stop_queue(ring->bcm->net_dev);
83 ring->suspended = 1;
84 }
85#ifdef CONFIG_BCM43XX_DEBUG
86 if (ring->used_slots > ring->max_used_slots)
87 ring->max_used_slots = ring->used_slots;
88#endif /* CONFIG_BCM43XX_DEBUG*/
89
90 return slot;
91}
92
93/* Return a slot to the free slots. */
94static inline
95void return_slot(struct bcm43xx_dmaring *ring, int slot)
96{
97 assert(ring->tx);
98
99 ring->used_slots--;
100
101 /* Check if TX is suspended and check if we have
102 * enough free slots to resume it again.
103 */
104 if (unlikely(ring->suspended)) {
105 if (free_slots(ring) >= ring->resume_mark) {
106 ring->suspended = 0;
107 netif_wake_queue(ring->bcm->net_dev);
108 }
109 }
110}
111
112static inline
113dma_addr_t map_descbuffer(struct bcm43xx_dmaring *ring,
114 unsigned char *buf,
115 size_t len,
116 int tx)
117{
118 dma_addr_t dmaaddr;
119
120 if (tx) {
121 dmaaddr = dma_map_single(&ring->bcm->pci_dev->dev,
122 buf, len,
123 DMA_TO_DEVICE);
124 } else {
125 dmaaddr = dma_map_single(&ring->bcm->pci_dev->dev,
126 buf, len,
127 DMA_FROM_DEVICE);
128 }
129
130 return dmaaddr;
131}
132
133static inline
134void unmap_descbuffer(struct bcm43xx_dmaring *ring,
135 dma_addr_t addr,
136 size_t len,
137 int tx)
138{
139 if (tx) {
140 dma_unmap_single(&ring->bcm->pci_dev->dev,
141 addr, len,
142 DMA_TO_DEVICE);
143 } else {
144 dma_unmap_single(&ring->bcm->pci_dev->dev,
145 addr, len,
146 DMA_FROM_DEVICE);
147 }
148}
149
150static inline
151void sync_descbuffer_for_cpu(struct bcm43xx_dmaring *ring,
152 dma_addr_t addr,
153 size_t len)
154{
155 assert(!ring->tx);
156
157 dma_sync_single_for_cpu(&ring->bcm->pci_dev->dev,
158 addr, len, DMA_FROM_DEVICE);
159}
160
161static inline
162void sync_descbuffer_for_device(struct bcm43xx_dmaring *ring,
163 dma_addr_t addr,
164 size_t len)
165{
166 assert(!ring->tx);
167
168 dma_sync_single_for_device(&ring->bcm->pci_dev->dev,
169 addr, len, DMA_FROM_DEVICE);
170}
171
172/* Unmap and free a descriptor buffer. */
173static inline
174void free_descriptor_buffer(struct bcm43xx_dmaring *ring,
175 struct bcm43xx_dmadesc *desc,
176 struct bcm43xx_dmadesc_meta *meta,
177 int irq_context)
178{
179 assert(meta->skb);
180 if (irq_context)
181 dev_kfree_skb_irq(meta->skb);
182 else
183 dev_kfree_skb(meta->skb);
184 meta->skb = NULL;
185}
186
187static int alloc_ringmemory(struct bcm43xx_dmaring *ring)
188{
189 struct device *dev = &(ring->bcm->pci_dev->dev);
190
191 ring->vbase = dma_alloc_coherent(dev, BCM43xx_DMA_RINGMEMSIZE,
192 &(ring->dmabase), GFP_KERNEL);
193 if (!ring->vbase) {
194 printk(KERN_ERR PFX "DMA ringmemory allocation failed\n");
195 return -ENOMEM;
196 }
197 if (ring->dmabase + BCM43xx_DMA_RINGMEMSIZE > BCM43xx_DMA_BUSADDRMAX) {
198 printk(KERN_ERR PFX ">>>FATAL ERROR<<< DMA RINGMEMORY >1G "
199 "(0x%08x, len: %lu)\n",
200 ring->dmabase, BCM43xx_DMA_RINGMEMSIZE);
201 dma_free_coherent(dev, BCM43xx_DMA_RINGMEMSIZE,
202 ring->vbase, ring->dmabase);
203 return -ENOMEM;
204 }
205 assert(!(ring->dmabase & 0x000003FF));
206 memset(ring->vbase, 0, BCM43xx_DMA_RINGMEMSIZE);
207
208 return 0;
209}
210
211static void free_ringmemory(struct bcm43xx_dmaring *ring)
212{
213 struct device *dev = &(ring->bcm->pci_dev->dev);
214
215 dma_free_coherent(dev, BCM43xx_DMA_RINGMEMSIZE,
216 ring->vbase, ring->dmabase);
217}
218
219/* Reset the RX DMA channel */
220int bcm43xx_dmacontroller_rx_reset(struct bcm43xx_private *bcm,
221 u16 mmio_base)
222{
223 int i;
224 u32 value;
225
226 bcm43xx_write32(bcm,
227 mmio_base + BCM43xx_DMA_RX_CONTROL,
228 0x00000000);
229 for (i = 0; i < 1000; i++) {
230 value = bcm43xx_read32(bcm,
231 mmio_base + BCM43xx_DMA_RX_STATUS);
232 value &= BCM43xx_DMA_RXSTAT_STAT_MASK;
233 if (value == BCM43xx_DMA_RXSTAT_STAT_DISABLED) {
234 i = -1;
235 break;
236 }
237 udelay(10);
238 }
239 if (i != -1) {
240 printk(KERN_ERR PFX "Error: Wait on DMA RX status timed out.\n");
241 return -ENODEV;
242 }
243
244 return 0;
245}
246
247/* Reset the RX DMA channel */
248int bcm43xx_dmacontroller_tx_reset(struct bcm43xx_private *bcm,
249 u16 mmio_base)
250{
251 int i;
252 u32 value;
253
254 for (i = 0; i < 1000; i++) {
255 value = bcm43xx_read32(bcm,
256 mmio_base + BCM43xx_DMA_TX_STATUS);
257 value &= BCM43xx_DMA_TXSTAT_STAT_MASK;
258 if (value == BCM43xx_DMA_TXSTAT_STAT_DISABLED ||
259 value == BCM43xx_DMA_TXSTAT_STAT_IDLEWAIT ||
260 value == BCM43xx_DMA_TXSTAT_STAT_STOPPED)
261 break;
262 udelay(10);
263 }
264 bcm43xx_write32(bcm,
265 mmio_base + BCM43xx_DMA_TX_CONTROL,
266 0x00000000);
267 for (i = 0; i < 1000; i++) {
268 value = bcm43xx_read32(bcm,
269 mmio_base + BCM43xx_DMA_TX_STATUS);
270 value &= BCM43xx_DMA_TXSTAT_STAT_MASK;
271 if (value == BCM43xx_DMA_TXSTAT_STAT_DISABLED) {
272 i = -1;
273 break;
274 }
275 udelay(10);
276 }
277 if (i != -1) {
278 printk(KERN_ERR PFX "Error: Wait on DMA TX status timed out.\n");
279 return -ENODEV;
280 }
281 /* ensure the reset is completed. */
282 udelay(300);
283
284 return 0;
285}
286
287static int setup_rx_descbuffer(struct bcm43xx_dmaring *ring,
288 struct bcm43xx_dmadesc *desc,
289 struct bcm43xx_dmadesc_meta *meta,
290 gfp_t gfp_flags)
291{
292 struct bcm43xx_rxhdr *rxhdr;
293 dma_addr_t dmaaddr;
294 u32 desc_addr;
295 u32 desc_ctl;
296 const int slot = (int)(desc - ring->vbase);
297 struct sk_buff *skb;
298
299 assert(slot >= 0 && slot < ring->nr_slots);
300 assert(!ring->tx);
301
302 skb = __dev_alloc_skb(ring->rx_buffersize, gfp_flags);
303 if (unlikely(!skb))
304 return -ENOMEM;
305 dmaaddr = map_descbuffer(ring, skb->data, ring->rx_buffersize, 0);
306 if (unlikely(dmaaddr + ring->rx_buffersize > BCM43xx_DMA_BUSADDRMAX)) {
307 unmap_descbuffer(ring, dmaaddr, ring->rx_buffersize, 0);
308 dev_kfree_skb_any(skb);
309 printk(KERN_ERR PFX ">>>FATAL ERROR<<< DMA RX SKB >1G "
310 "(0x%08x, len: %u)\n",
311 dmaaddr, ring->rx_buffersize);
312 return -ENOMEM;
313 }
314 meta->skb = skb;
315 meta->dmaaddr = dmaaddr;
316 skb->dev = ring->bcm->net_dev;
317 desc_addr = (u32)(dmaaddr + ring->memoffset);
318 desc_ctl = (BCM43xx_DMADTOR_BYTECNT_MASK &
319 (u32)(ring->rx_buffersize - ring->frameoffset));
320 if (slot == ring->nr_slots - 1)
321 desc_ctl |= BCM43xx_DMADTOR_DTABLEEND;
322 set_desc_addr(desc, desc_addr);
323 set_desc_ctl(desc, desc_ctl);
324
325 rxhdr = (struct bcm43xx_rxhdr *)(skb->data);
326 rxhdr->frame_length = 0;
327 rxhdr->flags1 = 0;
328
329 return 0;
330}
331
332/* Allocate the initial descbuffers.
333 * This is used for an RX ring only.
334 */
335static int alloc_initial_descbuffers(struct bcm43xx_dmaring *ring)
336{
337 int i, err = -ENOMEM;
338 struct bcm43xx_dmadesc *desc;
339 struct bcm43xx_dmadesc_meta *meta;
340
341 for (i = 0; i < ring->nr_slots; i++) {
342 desc = ring->vbase + i;
343 meta = ring->meta + i;
344
345 err = setup_rx_descbuffer(ring, desc, meta, GFP_KERNEL);
346 if (err)
347 goto err_unwind;
348 }
349 ring->used_slots = ring->nr_slots;
350 err = 0;
351out:
352 return err;
353
354err_unwind:
355 for (i--; i >= 0; i--) {
356 desc = ring->vbase + i;
357 meta = ring->meta + i;
358
359 unmap_descbuffer(ring, meta->dmaaddr, ring->rx_buffersize, 0);
360 dev_kfree_skb(meta->skb);
361 }
362 goto out;
363}
364
365/* Do initial setup of the DMA controller.
366 * Reset the controller, write the ring busaddress
367 * and switch the "enable" bit on.
368 */
369static int dmacontroller_setup(struct bcm43xx_dmaring *ring)
370{
371 int err = 0;
372 u32 value;
373
374 if (ring->tx) {
375 /* Set Transmit Control register to "transmit enable" */
376 bcm43xx_dma_write(ring, BCM43xx_DMA_TX_CONTROL,
377 BCM43xx_DMA_TXCTRL_ENABLE);
378 /* Set Transmit Descriptor ring address. */
379 bcm43xx_dma_write(ring, BCM43xx_DMA_TX_DESC_RING,
380 ring->dmabase + ring->memoffset);
381 } else {
382 err = alloc_initial_descbuffers(ring);
383 if (err)
384 goto out;
385 /* Set Receive Control "receive enable" and frame offset */
386 value = (ring->frameoffset << BCM43xx_DMA_RXCTRL_FRAMEOFF_SHIFT);
387 value |= BCM43xx_DMA_RXCTRL_ENABLE;
388 bcm43xx_dma_write(ring, BCM43xx_DMA_RX_CONTROL, value);
389 /* Set Receive Descriptor ring address. */
390 bcm43xx_dma_write(ring, BCM43xx_DMA_RX_DESC_RING,
391 ring->dmabase + ring->memoffset);
392 /* Init the descriptor pointer. */
393 bcm43xx_dma_write(ring, BCM43xx_DMA_RX_DESC_INDEX, 200);
394 }
395
396out:
397 return err;
398}
399
400/* Shutdown the DMA controller. */
401static void dmacontroller_cleanup(struct bcm43xx_dmaring *ring)
402{
403 if (ring->tx) {
404 bcm43xx_dmacontroller_tx_reset(ring->bcm, ring->mmio_base);
405 /* Zero out Transmit Descriptor ring address. */
406 bcm43xx_dma_write(ring, BCM43xx_DMA_TX_DESC_RING, 0);
407 } else {
408 bcm43xx_dmacontroller_rx_reset(ring->bcm, ring->mmio_base);
409 /* Zero out Receive Descriptor ring address. */
410 bcm43xx_dma_write(ring, BCM43xx_DMA_RX_DESC_RING, 0);
411 }
412}
413
414static void free_all_descbuffers(struct bcm43xx_dmaring *ring)
415{
416 struct bcm43xx_dmadesc *desc;
417 struct bcm43xx_dmadesc_meta *meta;
418 int i;
419
420 if (!ring->used_slots)
421 return;
422 for (i = 0; i < ring->nr_slots; i++) {
423 desc = ring->vbase + i;
424 meta = ring->meta + i;
425
426 if (!meta->skb) {
427 assert(ring->tx);
428 continue;
429 }
430 if (ring->tx) {
431 unmap_descbuffer(ring, meta->dmaaddr,
432 meta->skb->len, 1);
433 } else {
434 unmap_descbuffer(ring, meta->dmaaddr,
435 ring->rx_buffersize, 0);
436 }
437 free_descriptor_buffer(ring, desc, meta, 0);
438 }
439}
440
441/* Main initialization function. */
442static
443struct bcm43xx_dmaring * bcm43xx_setup_dmaring(struct bcm43xx_private *bcm,
444 u16 dma_controller_base,
445 int nr_descriptor_slots,
446 int tx)
447{
448 struct bcm43xx_dmaring *ring;
449 int err;
450
451 ring = kzalloc(sizeof(*ring), GFP_KERNEL);
452 if (!ring)
453 goto out;
454
455 ring->meta = kzalloc(sizeof(*ring->meta) * nr_descriptor_slots,
456 GFP_KERNEL);
457 if (!ring->meta)
458 goto err_kfree_ring;
459
460 ring->memoffset = BCM43xx_DMA_DMABUSADDROFFSET;
461#ifdef CONFIG_BCM947XX
462 if (bcm->pci_dev->bus->number == 0)
463 ring->memoffset = 0;
464#endif
465
466 ring->bcm = bcm;
467 ring->nr_slots = nr_descriptor_slots;
468 ring->suspend_mark = ring->nr_slots * BCM43xx_TXSUSPEND_PERCENT / 100;
469 ring->resume_mark = ring->nr_slots * BCM43xx_TXRESUME_PERCENT / 100;
470 assert(ring->suspend_mark < ring->resume_mark);
471 ring->mmio_base = dma_controller_base;
472 if (tx) {
473 ring->tx = 1;
474 ring->current_slot = -1;
475 } else {
476 switch (dma_controller_base) {
477 case BCM43xx_MMIO_DMA1_BASE:
478 ring->rx_buffersize = BCM43xx_DMA1_RXBUFFERSIZE;
479 ring->frameoffset = BCM43xx_DMA1_RX_FRAMEOFFSET;
480 break;
481 case BCM43xx_MMIO_DMA4_BASE:
482 ring->rx_buffersize = BCM43xx_DMA4_RXBUFFERSIZE;
483 ring->frameoffset = BCM43xx_DMA4_RX_FRAMEOFFSET;
484 break;
485 default:
486 assert(0);
487 }
488 }
489
490 err = alloc_ringmemory(ring);
491 if (err)
492 goto err_kfree_meta;
493 err = dmacontroller_setup(ring);
494 if (err)
495 goto err_free_ringmemory;
496
497out:
498 return ring;
499
500err_free_ringmemory:
501 free_ringmemory(ring);
502err_kfree_meta:
503 kfree(ring->meta);
504err_kfree_ring:
505 kfree(ring);
506 ring = NULL;
507 goto out;
508}
509
510/* Main cleanup function. */
511static void bcm43xx_destroy_dmaring(struct bcm43xx_dmaring *ring)
512{
513 if (!ring)
514 return;
515
516 dprintk(KERN_INFO PFX "DMA 0x%04x (%s) max used slots: %d/%d\n",
517 ring->mmio_base,
518 (ring->tx) ? "TX" : "RX",
519 ring->max_used_slots, ring->nr_slots);
520 /* Device IRQs are disabled prior entering this function,
521 * so no need to take care of concurrency with rx handler stuff.
522 */
523 dmacontroller_cleanup(ring);
524 free_all_descbuffers(ring);
525 free_ringmemory(ring);
526
527 kfree(ring->meta);
528 kfree(ring);
529}
530
531void bcm43xx_dma_free(struct bcm43xx_private *bcm)
532{
533 struct bcm43xx_dma *dma;
534
535 if (bcm43xx_using_pio(bcm))
536 return;
537 dma = bcm43xx_current_dma(bcm);
538
539 bcm43xx_destroy_dmaring(dma->rx_ring1);
540 dma->rx_ring1 = NULL;
541 bcm43xx_destroy_dmaring(dma->rx_ring0);
542 dma->rx_ring0 = NULL;
543 bcm43xx_destroy_dmaring(dma->tx_ring3);
544 dma->tx_ring3 = NULL;
545 bcm43xx_destroy_dmaring(dma->tx_ring2);
546 dma->tx_ring2 = NULL;
547 bcm43xx_destroy_dmaring(dma->tx_ring1);
548 dma->tx_ring1 = NULL;
549 bcm43xx_destroy_dmaring(dma->tx_ring0);
550 dma->tx_ring0 = NULL;
551}
552
553int bcm43xx_dma_init(struct bcm43xx_private *bcm)
554{
555 struct bcm43xx_dma *dma = bcm43xx_current_dma(bcm);
556 struct bcm43xx_dmaring *ring;
557 int err = -ENOMEM;
558
559 /* setup TX DMA channels. */
560 ring = bcm43xx_setup_dmaring(bcm, BCM43xx_MMIO_DMA1_BASE,
561 BCM43xx_TXRING_SLOTS, 1);
562 if (!ring)
563 goto out;
564 dma->tx_ring0 = ring;
565
566 ring = bcm43xx_setup_dmaring(bcm, BCM43xx_MMIO_DMA2_BASE,
567 BCM43xx_TXRING_SLOTS, 1);
568 if (!ring)
569 goto err_destroy_tx0;
570 dma->tx_ring1 = ring;
571
572 ring = bcm43xx_setup_dmaring(bcm, BCM43xx_MMIO_DMA3_BASE,
573 BCM43xx_TXRING_SLOTS, 1);
574 if (!ring)
575 goto err_destroy_tx1;
576 dma->tx_ring2 = ring;
577
578 ring = bcm43xx_setup_dmaring(bcm, BCM43xx_MMIO_DMA4_BASE,
579 BCM43xx_TXRING_SLOTS, 1);
580 if (!ring)
581 goto err_destroy_tx2;
582 dma->tx_ring3 = ring;
583
584 /* setup RX DMA channels. */
585 ring = bcm43xx_setup_dmaring(bcm, BCM43xx_MMIO_DMA1_BASE,
586 BCM43xx_RXRING_SLOTS, 0);
587 if (!ring)
588 goto err_destroy_tx3;
589 dma->rx_ring0 = ring;
590
591 if (bcm->current_core->rev < 5) {
592 ring = bcm43xx_setup_dmaring(bcm, BCM43xx_MMIO_DMA4_BASE,
593 BCM43xx_RXRING_SLOTS, 0);
594 if (!ring)
595 goto err_destroy_rx0;
596 dma->rx_ring1 = ring;
597 }
598
599 dprintk(KERN_INFO PFX "DMA initialized\n");
600 err = 0;
601out:
602 return err;
603
604err_destroy_rx0:
605 bcm43xx_destroy_dmaring(dma->rx_ring0);
606 dma->rx_ring0 = NULL;
607err_destroy_tx3:
608 bcm43xx_destroy_dmaring(dma->tx_ring3);
609 dma->tx_ring3 = NULL;
610err_destroy_tx2:
611 bcm43xx_destroy_dmaring(dma->tx_ring2);
612 dma->tx_ring2 = NULL;
613err_destroy_tx1:
614 bcm43xx_destroy_dmaring(dma->tx_ring1);
615 dma->tx_ring1 = NULL;
616err_destroy_tx0:
617 bcm43xx_destroy_dmaring(dma->tx_ring0);
618 dma->tx_ring0 = NULL;
619 goto out;
620}
621
622/* Generate a cookie for the TX header. */
623static u16 generate_cookie(struct bcm43xx_dmaring *ring,
624 int slot)
625{
626 u16 cookie = 0x0000;
627
628 /* Use the upper 4 bits of the cookie as
629 * DMA controller ID and store the slot number
630 * in the lower 12 bits
631 */
632 switch (ring->mmio_base) {
633 default:
634 assert(0);
635 case BCM43xx_MMIO_DMA1_BASE:
636 break;
637 case BCM43xx_MMIO_DMA2_BASE:
638 cookie = 0x1000;
639 break;
640 case BCM43xx_MMIO_DMA3_BASE:
641 cookie = 0x2000;
642 break;
643 case BCM43xx_MMIO_DMA4_BASE:
644 cookie = 0x3000;
645 break;
646 }
647 assert(((u16)slot & 0xF000) == 0x0000);
648 cookie |= (u16)slot;
649
650 return cookie;
651}
652
653/* Inspect a cookie and find out to which controller/slot it belongs. */
654static
655struct bcm43xx_dmaring * parse_cookie(struct bcm43xx_private *bcm,
656 u16 cookie, int *slot)
657{
658 struct bcm43xx_dma *dma = bcm43xx_current_dma(bcm);
659 struct bcm43xx_dmaring *ring = NULL;
660
661 switch (cookie & 0xF000) {
662 case 0x0000:
663 ring = dma->tx_ring0;
664 break;
665 case 0x1000:
666 ring = dma->tx_ring1;
667 break;
668 case 0x2000:
669 ring = dma->tx_ring2;
670 break;
671 case 0x3000:
672 ring = dma->tx_ring3;
673 break;
674 default:
675 assert(0);
676 }
677 *slot = (cookie & 0x0FFF);
678 assert(*slot >= 0 && *slot < ring->nr_slots);
679
680 return ring;
681}
682
683static void dmacontroller_poke_tx(struct bcm43xx_dmaring *ring,
684 int slot)
685{
686 /* Everything is ready to start. Buffers are DMA mapped and
687 * associated with slots.
688 * "slot" is the last slot of the new frame we want to transmit.
689 * Close your seat belts now, please.
690 */
691 wmb();
692 slot = next_slot(ring, slot);
693 bcm43xx_dma_write(ring, BCM43xx_DMA_TX_DESC_INDEX,
694 (u32)(slot * sizeof(struct bcm43xx_dmadesc)));
695}
696
697static int dma_tx_fragment(struct bcm43xx_dmaring *ring,
698 struct sk_buff *skb,
699 u8 cur_frag)
700{
701 int slot;
702 struct bcm43xx_dmadesc *desc;
703 struct bcm43xx_dmadesc_meta *meta;
704 u32 desc_ctl;
705 u32 desc_addr;
706
707 assert(skb_shinfo(skb)->nr_frags == 0);
708
709 slot = request_slot(ring);
710 desc = ring->vbase + slot;
711 meta = ring->meta + slot;
712
713 /* Add a device specific TX header. */
714 assert(skb_headroom(skb) >= sizeof(struct bcm43xx_txhdr));
715 /* Reserve enough headroom for the device tx header. */
716 __skb_push(skb, sizeof(struct bcm43xx_txhdr));
717 /* Now calculate and add the tx header.
718 * The tx header includes the PLCP header.
719 */
720 bcm43xx_generate_txhdr(ring->bcm,
721 (struct bcm43xx_txhdr *)skb->data,
722 skb->data + sizeof(struct bcm43xx_txhdr),
723 skb->len - sizeof(struct bcm43xx_txhdr),
724 (cur_frag == 0),
725 generate_cookie(ring, slot));
726
727 meta->skb = skb;
728 meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1);
729 if (unlikely(meta->dmaaddr + skb->len > BCM43xx_DMA_BUSADDRMAX)) {
730 return_slot(ring, slot);
731 printk(KERN_ERR PFX ">>>FATAL ERROR<<< DMA TX SKB >1G "
732 "(0x%08x, len: %u)\n",
733 meta->dmaaddr, skb->len);
734 return -ENOMEM;
735 }
736
737 desc_addr = (u32)(meta->dmaaddr + ring->memoffset);
738 desc_ctl = BCM43xx_DMADTOR_FRAMESTART | BCM43xx_DMADTOR_FRAMEEND;
739 desc_ctl |= BCM43xx_DMADTOR_COMPIRQ;
740 desc_ctl |= (BCM43xx_DMADTOR_BYTECNT_MASK &
741 (u32)(meta->skb->len - ring->frameoffset));
742 if (slot == ring->nr_slots - 1)
743 desc_ctl |= BCM43xx_DMADTOR_DTABLEEND;
744
745 set_desc_ctl(desc, desc_ctl);
746 set_desc_addr(desc, desc_addr);
747 /* Now transfer the whole frame. */
748 dmacontroller_poke_tx(ring, slot);
749
750 return 0;
751}
752
753int bcm43xx_dma_tx(struct bcm43xx_private *bcm,
754 struct ieee80211_txb *txb)
755{
756 /* We just received a packet from the kernel network subsystem.
757 * Add headers and DMA map the memory. Poke
758 * the device to send the stuff.
759 * Note that this is called from atomic context.
760 */
761 struct bcm43xx_dmaring *ring = bcm43xx_current_dma(bcm)->tx_ring1;
762 u8 i;
763 struct sk_buff *skb;
764
765 assert(ring->tx);
766 if (unlikely(free_slots(ring) < txb->nr_frags)) {
767 /* The queue should be stopped,
768 * if we are low on free slots.
769 * If this ever triggers, we have to lower the suspend_mark.
770 */
771 dprintkl(KERN_ERR PFX "Out of DMA descriptor slots!\n");
772 return -ENOMEM;
773 }
774
775 for (i = 0; i < txb->nr_frags; i++) {
776 skb = txb->fragments[i];
777 /* Take skb from ieee80211_txb_free */
778 txb->fragments[i] = NULL;
779 dma_tx_fragment(ring, skb, i);
780 //TODO: handle failure of dma_tx_fragment
781 }
782 ieee80211_txb_free(txb);
783
784 return 0;
785}
786
787void bcm43xx_dma_handle_xmitstatus(struct bcm43xx_private *bcm,
788 struct bcm43xx_xmitstatus *status)
789{
790 struct bcm43xx_dmaring *ring;
791 struct bcm43xx_dmadesc *desc;
792 struct bcm43xx_dmadesc_meta *meta;
793 int is_last_fragment;
794 int slot;
795
796 ring = parse_cookie(bcm, status->cookie, &slot);
797 assert(ring);
798 assert(ring->tx);
799 assert(get_desc_ctl(ring->vbase + slot) & BCM43xx_DMADTOR_FRAMESTART);
800 while (1) {
801 assert(slot >= 0 && slot < ring->nr_slots);
802 desc = ring->vbase + slot;
803 meta = ring->meta + slot;
804
805 is_last_fragment = !!(get_desc_ctl(desc) & BCM43xx_DMADTOR_FRAMEEND);
806 unmap_descbuffer(ring, meta->dmaaddr, meta->skb->len, 1);
807 free_descriptor_buffer(ring, desc, meta, 1);
808 /* Everything belonging to the slot is unmapped
809 * and freed, so we can return it.
810 */
811 return_slot(ring, slot);
812
813 if (is_last_fragment)
814 break;
815 slot = next_slot(ring, slot);
816 }
817 bcm->stats.last_tx = jiffies;
818}
819
820static void dma_rx(struct bcm43xx_dmaring *ring,
821 int *slot)
822{
823 struct bcm43xx_dmadesc *desc;
824 struct bcm43xx_dmadesc_meta *meta;
825 struct bcm43xx_rxhdr *rxhdr;
826 struct sk_buff *skb;
827 u16 len;
828 int err;
829 dma_addr_t dmaaddr;
830
831 desc = ring->vbase + *slot;
832 meta = ring->meta + *slot;
833
834 sync_descbuffer_for_cpu(ring, meta->dmaaddr, ring->rx_buffersize);
835 skb = meta->skb;
836
837 if (ring->mmio_base == BCM43xx_MMIO_DMA4_BASE) {
838 /* We received an xmit status. */
839 struct bcm43xx_hwxmitstatus *hw = (struct bcm43xx_hwxmitstatus *)skb->data;
840 struct bcm43xx_xmitstatus stat;
841
842 stat.cookie = le16_to_cpu(hw->cookie);
843 stat.flags = hw->flags;
844 stat.cnt1 = hw->cnt1;
845 stat.cnt2 = hw->cnt2;
846 stat.seq = le16_to_cpu(hw->seq);
847 stat.unknown = le16_to_cpu(hw->unknown);
848
849 bcm43xx_debugfs_log_txstat(ring->bcm, &stat);
850 bcm43xx_dma_handle_xmitstatus(ring->bcm, &stat);
851 /* recycle the descriptor buffer. */
852 sync_descbuffer_for_device(ring, meta->dmaaddr, ring->rx_buffersize);
853
854 return;
855 }
856 rxhdr = (struct bcm43xx_rxhdr *)skb->data;
857 len = le16_to_cpu(rxhdr->frame_length);
858 if (len == 0) {
859 int i = 0;
860
861 do {
862 udelay(2);
863 barrier();
864 len = le16_to_cpu(rxhdr->frame_length);
865 } while (len == 0 && i++ < 5);
866 if (unlikely(len == 0)) {
867 /* recycle the descriptor buffer. */
868 sync_descbuffer_for_device(ring, meta->dmaaddr,
869 ring->rx_buffersize);
870 goto drop;
871 }
872 }
873 if (unlikely(len > ring->rx_buffersize)) {
874 /* The data did not fit into one descriptor buffer
875 * and is split over multiple buffers.
876 * This should never happen, as we try to allocate buffers
877 * big enough. So simply ignore this packet.
878 */
879 int cnt = 0;
880 s32 tmp = len;
881
882 while (1) {
883 desc = ring->vbase + *slot;
884 meta = ring->meta + *slot;
885 /* recycle the descriptor buffer. */
886 sync_descbuffer_for_device(ring, meta->dmaaddr,
887 ring->rx_buffersize);
888 *slot = next_slot(ring, *slot);
889 cnt++;
890 tmp -= ring->rx_buffersize;
891 if (tmp <= 0)
892 break;
893 }
894 printkl(KERN_ERR PFX "DMA RX buffer too small "
895 "(len: %u, buffer: %u, nr-dropped: %d)\n",
896 len, ring->rx_buffersize, cnt);
897 goto drop;
898 }
899 len -= IEEE80211_FCS_LEN;
900
901 dmaaddr = meta->dmaaddr;
902 err = setup_rx_descbuffer(ring, desc, meta, GFP_ATOMIC);
903 if (unlikely(err)) {
904 dprintkl(KERN_ERR PFX "DMA RX: setup_rx_descbuffer() failed\n");
905 sync_descbuffer_for_device(ring, dmaaddr,
906 ring->rx_buffersize);
907 goto drop;
908 }
909
910 unmap_descbuffer(ring, dmaaddr, ring->rx_buffersize, 0);
911 skb_put(skb, len + ring->frameoffset);
912 skb_pull(skb, ring->frameoffset);
913
914 err = bcm43xx_rx(ring->bcm, skb, rxhdr);
915 if (err) {
916 dev_kfree_skb_irq(skb);
917 goto drop;
918 }
919
920drop:
921 return;
922}
923
924void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring)
925{
926 u32 status;
927 u16 descptr;
928 int slot, current_slot;
929#ifdef CONFIG_BCM43XX_DEBUG
930 int used_slots = 0;
931#endif
932
933 assert(!ring->tx);
934 status = bcm43xx_dma_read(ring, BCM43xx_DMA_RX_STATUS);
935 descptr = (status & BCM43xx_DMA_RXSTAT_DPTR_MASK);
936 current_slot = descptr / sizeof(struct bcm43xx_dmadesc);
937 assert(current_slot >= 0 && current_slot < ring->nr_slots);
938
939 slot = ring->current_slot;
940 for ( ; slot != current_slot; slot = next_slot(ring, slot)) {
941 dma_rx(ring, &slot);
942#ifdef CONFIG_BCM43XX_DEBUG
943 if (++used_slots > ring->max_used_slots)
944 ring->max_used_slots = used_slots;
945#endif
946 }
947 bcm43xx_dma_write(ring, BCM43xx_DMA_RX_DESC_INDEX,
948 (u32)(slot * sizeof(struct bcm43xx_dmadesc)));
949 ring->current_slot = slot;
950}
951
952void bcm43xx_dma_tx_suspend(struct bcm43xx_dmaring *ring)
953{
954 assert(ring->tx);
955 bcm43xx_power_saving_ctl_bits(ring->bcm, -1, 1);
956 bcm43xx_dma_write(ring, BCM43xx_DMA_TX_CONTROL,
957 bcm43xx_dma_read(ring, BCM43xx_DMA_TX_CONTROL)
958 | BCM43xx_DMA_TXCTRL_SUSPEND);
959}
960
961void bcm43xx_dma_tx_resume(struct bcm43xx_dmaring *ring)
962{
963 assert(ring->tx);
964 bcm43xx_dma_write(ring, BCM43xx_DMA_TX_CONTROL,
965 bcm43xx_dma_read(ring, BCM43xx_DMA_TX_CONTROL)
966 & ~BCM43xx_DMA_TXCTRL_SUSPEND);
967 bcm43xx_power_saving_ctl_bits(ring->bcm, -1, -1);
968}
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.h b/drivers/net/wireless/bcm43xx/bcm43xx_dma.h
new file mode 100644
index 000000000000..2d520e4b0276
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.h
@@ -0,0 +1,218 @@
1#ifndef BCM43xx_DMA_H_
2#define BCM43xx_DMA_H_
3
4#include <linux/list.h>
5#include <linux/spinlock.h>
6#include <linux/workqueue.h>
7#include <linux/linkage.h>
8#include <asm/atomic.h>
9
10
11/* DMA-Interrupt reasons. */
12#define BCM43xx_DMAIRQ_FATALMASK ((1 << 10) | (1 << 11) | (1 << 12) \
13 | (1 << 14) | (1 << 15))
14#define BCM43xx_DMAIRQ_NONFATALMASK (1 << 13)
15#define BCM43xx_DMAIRQ_RX_DONE (1 << 16)
16
17/* DMA controller register offsets. (relative to BCM43xx_DMA#_BASE) */
18#define BCM43xx_DMA_TX_CONTROL 0x00
19#define BCM43xx_DMA_TX_DESC_RING 0x04
20#define BCM43xx_DMA_TX_DESC_INDEX 0x08
21#define BCM43xx_DMA_TX_STATUS 0x0c
22#define BCM43xx_DMA_RX_CONTROL 0x10
23#define BCM43xx_DMA_RX_DESC_RING 0x14
24#define BCM43xx_DMA_RX_DESC_INDEX 0x18
25#define BCM43xx_DMA_RX_STATUS 0x1c
26
27/* DMA controller channel control word values. */
28#define BCM43xx_DMA_TXCTRL_ENABLE (1 << 0)
29#define BCM43xx_DMA_TXCTRL_SUSPEND (1 << 1)
30#define BCM43xx_DMA_TXCTRL_LOOPBACK (1 << 2)
31#define BCM43xx_DMA_TXCTRL_FLUSH (1 << 4)
32#define BCM43xx_DMA_RXCTRL_ENABLE (1 << 0)
33#define BCM43xx_DMA_RXCTRL_FRAMEOFF_MASK 0x000000fe
34#define BCM43xx_DMA_RXCTRL_FRAMEOFF_SHIFT 1
35#define BCM43xx_DMA_RXCTRL_PIO (1 << 8)
36/* DMA controller channel status word values. */
37#define BCM43xx_DMA_TXSTAT_DPTR_MASK 0x00000fff
38#define BCM43xx_DMA_TXSTAT_STAT_MASK 0x0000f000
39#define BCM43xx_DMA_TXSTAT_STAT_DISABLED 0x00000000
40#define BCM43xx_DMA_TXSTAT_STAT_ACTIVE 0x00001000
41#define BCM43xx_DMA_TXSTAT_STAT_IDLEWAIT 0x00002000
42#define BCM43xx_DMA_TXSTAT_STAT_STOPPED 0x00003000
43#define BCM43xx_DMA_TXSTAT_STAT_SUSP 0x00004000
44#define BCM43xx_DMA_TXSTAT_ERROR_MASK 0x000f0000
45#define BCM43xx_DMA_TXSTAT_FLUSHED (1 << 20)
46#define BCM43xx_DMA_RXSTAT_DPTR_MASK 0x00000fff
47#define BCM43xx_DMA_RXSTAT_STAT_MASK 0x0000f000
48#define BCM43xx_DMA_RXSTAT_STAT_DISABLED 0x00000000
49#define BCM43xx_DMA_RXSTAT_STAT_ACTIVE 0x00001000
50#define BCM43xx_DMA_RXSTAT_STAT_IDLEWAIT 0x00002000
51#define BCM43xx_DMA_RXSTAT_STAT_RESERVED 0x00003000
52#define BCM43xx_DMA_RXSTAT_STAT_ERRORS 0x00004000
53#define BCM43xx_DMA_RXSTAT_ERROR_MASK 0x000f0000
54
55/* DMA descriptor control field values. */
56#define BCM43xx_DMADTOR_BYTECNT_MASK 0x00001fff
57#define BCM43xx_DMADTOR_DTABLEEND (1 << 28) /* End of descriptor table */
58#define BCM43xx_DMADTOR_COMPIRQ (1 << 29) /* IRQ on completion request */
59#define BCM43xx_DMADTOR_FRAMEEND (1 << 30)
60#define BCM43xx_DMADTOR_FRAMESTART (1 << 31)
61
62/* Misc DMA constants */
63#define BCM43xx_DMA_RINGMEMSIZE PAGE_SIZE
64#define BCM43xx_DMA_BUSADDRMAX 0x3FFFFFFF
65#define BCM43xx_DMA_DMABUSADDROFFSET (1 << 30)
66#define BCM43xx_DMA1_RX_FRAMEOFFSET 30
67#define BCM43xx_DMA4_RX_FRAMEOFFSET 0
68
69/* DMA engine tuning knobs */
70#define BCM43xx_TXRING_SLOTS 512
71#define BCM43xx_RXRING_SLOTS 64
72#define BCM43xx_DMA1_RXBUFFERSIZE (2304 + 100)
73#define BCM43xx_DMA4_RXBUFFERSIZE 16
74/* Suspend the tx queue, if less than this percent slots are free. */
75#define BCM43xx_TXSUSPEND_PERCENT 20
76/* Resume the tx queue, if more than this percent slots are free. */
77#define BCM43xx_TXRESUME_PERCENT 50
78
79
80
81#ifdef CONFIG_BCM43XX_DMA
82
83
84struct sk_buff;
85struct bcm43xx_private;
86struct bcm43xx_xmitstatus;
87
88
89struct bcm43xx_dmadesc {
90 __le32 _control;
91 __le32 _address;
92} __attribute__((__packed__));
93
94/* Macros to access the bcm43xx_dmadesc struct */
95#define get_desc_ctl(desc) le32_to_cpu((desc)->_control)
96#define set_desc_ctl(desc, ctl) do { (desc)->_control = cpu_to_le32(ctl); } while (0)
97#define get_desc_addr(desc) le32_to_cpu((desc)->_address)
98#define set_desc_addr(desc, addr) do { (desc)->_address = cpu_to_le32(addr); } while (0)
99
100struct bcm43xx_dmadesc_meta {
101 /* The kernel DMA-able buffer. */
102 struct sk_buff *skb;
103 /* DMA base bus-address of the descriptor buffer. */
104 dma_addr_t dmaaddr;
105};
106
107struct bcm43xx_dmaring {
108 struct bcm43xx_private *bcm;
109 /* Kernel virtual base address of the ring memory. */
110 struct bcm43xx_dmadesc *vbase;
111 /* DMA memory offset */
112 dma_addr_t memoffset;
113 /* (Unadjusted) DMA base bus-address of the ring memory. */
114 dma_addr_t dmabase;
115 /* Meta data about all descriptors. */
116 struct bcm43xx_dmadesc_meta *meta;
117 /* Number of descriptor slots in the ring. */
118 int nr_slots;
119 /* Number of used descriptor slots. */
120 int used_slots;
121 /* Currently used slot in the ring. */
122 int current_slot;
123 /* Marks to suspend/resume the queue. */
124 int suspend_mark;
125 int resume_mark;
126 /* Frameoffset in octets. */
127 u32 frameoffset;
128 /* Descriptor buffer size. */
129 u16 rx_buffersize;
130 /* The MMIO base register of the DMA controller, this
131 * ring is posted to.
132 */
133 u16 mmio_base;
134 u8 tx:1, /* TRUE, if this is a TX ring. */
135 suspended:1; /* TRUE, if transfers are suspended on this ring. */
136#ifdef CONFIG_BCM43XX_DEBUG
137 /* Maximum number of used slots. */
138 int max_used_slots;
139#endif /* CONFIG_BCM43XX_DEBUG*/
140};
141
142
143static inline
144u32 bcm43xx_dma_read(struct bcm43xx_dmaring *ring,
145 u16 offset)
146{
147 return bcm43xx_read32(ring->bcm, ring->mmio_base + offset);
148}
149
150static inline
151void bcm43xx_dma_write(struct bcm43xx_dmaring *ring,
152 u16 offset, u32 value)
153{
154 bcm43xx_write32(ring->bcm, ring->mmio_base + offset, value);
155}
156
157
158int bcm43xx_dma_init(struct bcm43xx_private *bcm);
159void bcm43xx_dma_free(struct bcm43xx_private *bcm);
160
161int bcm43xx_dmacontroller_rx_reset(struct bcm43xx_private *bcm,
162 u16 dmacontroller_mmio_base);
163int bcm43xx_dmacontroller_tx_reset(struct bcm43xx_private *bcm,
164 u16 dmacontroller_mmio_base);
165
166void bcm43xx_dma_tx_suspend(struct bcm43xx_dmaring *ring);
167void bcm43xx_dma_tx_resume(struct bcm43xx_dmaring *ring);
168
169void bcm43xx_dma_handle_xmitstatus(struct bcm43xx_private *bcm,
170 struct bcm43xx_xmitstatus *status);
171
172int bcm43xx_dma_tx(struct bcm43xx_private *bcm,
173 struct ieee80211_txb *txb);
174void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring);
175
176
177#else /* CONFIG_BCM43XX_DMA */
178
179
180static inline
181int bcm43xx_dma_init(struct bcm43xx_private *bcm)
182{
183 return 0;
184}
185static inline
186void bcm43xx_dma_free(struct bcm43xx_private *bcm)
187{
188}
189static inline
190int bcm43xx_dmacontroller_rx_reset(struct bcm43xx_private *bcm,
191 u16 dmacontroller_mmio_base)
192{
193 return 0;
194}
195static inline
196int bcm43xx_dmacontroller_tx_reset(struct bcm43xx_private *bcm,
197 u16 dmacontroller_mmio_base)
198{
199 return 0;
200}
201static inline
202int bcm43xx_dma_tx(struct bcm43xx_private *bcm,
203 struct ieee80211_txb *txb)
204{
205 return 0;
206}
207static inline
208void bcm43xx_dma_handle_xmitstatus(struct bcm43xx_private *bcm,
209 struct bcm43xx_xmitstatus *status)
210{
211}
212static inline
213void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring)
214{
215}
216
217#endif /* CONFIG_BCM43XX_DMA */
218#endif /* BCM43xx_DMA_H_ */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.c b/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.c
new file mode 100644
index 000000000000..b3ffcf501311
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.c
@@ -0,0 +1,50 @@
1/*
2
3 Broadcom BCM43xx wireless driver
4
5 ethtool support
6
7 Copyright (c) 2006 Jason Lunz <lunz@falooley.org>
8
9 Some code in this file is derived from the 8139too.c driver
10 Copyright (C) 2002 Jeff Garzik
11
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
16
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with this program; see the file COPYING. If not, write to
24 the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
25 Boston, MA 02110-1301, USA.
26
27*/
28
29#include "bcm43xx.h"
30#include "bcm43xx_ethtool.h"
31
32#include <linux/netdevice.h>
33#include <linux/pci.h>
34#include <linux/string.h>
35#include <linux/version.h>
36
37
38static void bcm43xx_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
39{
40 struct bcm43xx_private *bcm = bcm43xx_priv(dev);
41
42 strncpy(info->driver, KBUILD_MODNAME, sizeof(info->driver));
43 strncpy(info->version, UTS_RELEASE, sizeof(info->version));
44 strncpy(info->bus_info, pci_name(bcm->pci_dev), ETHTOOL_BUSINFO_LEN);
45}
46
47struct ethtool_ops bcm43xx_ethtool_ops = {
48 .get_drvinfo = bcm43xx_get_drvinfo,
49 .get_link = ethtool_op_get_link,
50};
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.h b/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.h
new file mode 100644
index 000000000000..813704991f62
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.h
@@ -0,0 +1,8 @@
1#ifndef BCM43xx_ETHTOOL_H_
2#define BCM43xx_ETHTOOL_H_
3
4#include <linux/ethtool.h>
5
6extern struct ethtool_ops bcm43xx_ethtool_ops;
7
8#endif /* BCM43xx_ETHTOOL_H_ */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_ilt.c b/drivers/net/wireless/bcm43xx/bcm43xx_ilt.c
new file mode 100644
index 000000000000..ad8e569d1faf
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_ilt.c
@@ -0,0 +1,337 @@
1/*
2
3 Broadcom BCM43xx wireless driver
4
5 Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
6 Stefano Brivio <st3@riseup.net>
7 Michael Buesch <mbuesch@freenet.de>
8 Danny van Dyk <kugelfang@gentoo.org>
9 Andreas Jaggi <andreas.jaggi@waterwave.ch>
10
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2 of the License, or
14 (at your option) any later version.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with this program; see the file COPYING. If not, write to
23 the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
24 Boston, MA 02110-1301, USA.
25
26*/
27
28#include "bcm43xx.h"
29#include "bcm43xx_ilt.h"
30#include "bcm43xx_phy.h"
31
32
33/**** Initial Internal Lookup Tables ****/
34
35const u32 bcm43xx_ilt_rotor[BCM43xx_ILT_ROTOR_SIZE] = {
36 0xFEB93FFD, 0xFEC63FFD, /* 0 */
37 0xFED23FFD, 0xFEDF3FFD,
38 0xFEEC3FFE, 0xFEF83FFE,
39 0xFF053FFE, 0xFF113FFE,
40 0xFF1E3FFE, 0xFF2A3FFF, /* 8 */
41 0xFF373FFF, 0xFF443FFF,
42 0xFF503FFF, 0xFF5D3FFF,
43 0xFF693FFF, 0xFF763FFF,
44 0xFF824000, 0xFF8F4000, /* 16 */
45 0xFF9B4000, 0xFFA84000,
46 0xFFB54000, 0xFFC14000,
47 0xFFCE4000, 0xFFDA4000,
48 0xFFE74000, 0xFFF34000, /* 24 */
49 0x00004000, 0x000D4000,
50 0x00194000, 0x00264000,
51 0x00324000, 0x003F4000,
52 0x004B4000, 0x00584000, /* 32 */
53 0x00654000, 0x00714000,
54 0x007E4000, 0x008A3FFF,
55 0x00973FFF, 0x00A33FFF,
56 0x00B03FFF, 0x00BC3FFF, /* 40 */
57 0x00C93FFF, 0x00D63FFF,
58 0x00E23FFE, 0x00EF3FFE,
59 0x00FB3FFE, 0x01083FFE,
60 0x01143FFE, 0x01213FFD, /* 48 */
61 0x012E3FFD, 0x013A3FFD,
62 0x01473FFD,
63};
64
65const u32 bcm43xx_ilt_retard[BCM43xx_ILT_RETARD_SIZE] = {
66 0xDB93CB87, 0xD666CF64, /* 0 */
67 0xD1FDD358, 0xCDA6D826,
68 0xCA38DD9F, 0xC729E2B4,
69 0xC469E88E, 0xC26AEE2B,
70 0xC0DEF46C, 0xC073FA62, /* 8 */
71 0xC01D00D5, 0xC0760743,
72 0xC1560D1E, 0xC2E51369,
73 0xC4ED18FF, 0xC7AC1ED7,
74 0xCB2823B2, 0xCEFA28D9, /* 16 */
75 0xD2F62D3F, 0xD7BB3197,
76 0xDCE53568, 0xE1FE3875,
77 0xE7D13B35, 0xED663D35,
78 0xF39B3EC4, 0xF98E3FA7, /* 24 */
79 0x00004000, 0x06723FA7,
80 0x0C653EC4, 0x129A3D35,
81 0x182F3B35, 0x1E023875,
82 0x231B3568, 0x28453197, /* 32 */
83 0x2D0A2D3F, 0x310628D9,
84 0x34D823B2, 0x38541ED7,
85 0x3B1318FF, 0x3D1B1369,
86 0x3EAA0D1E, 0x3F8A0743, /* 40 */
87 0x3FE300D5, 0x3F8DFA62,
88 0x3F22F46C, 0x3D96EE2B,
89 0x3B97E88E, 0x38D7E2B4,
90 0x35C8DD9F, 0x325AD826, /* 48 */
91 0x2E03D358, 0x299ACF64,
92 0x246DCB87,
93};
94
95const u16 bcm43xx_ilt_finefreqa[BCM43xx_ILT_FINEFREQA_SIZE] = {
96 0x0082, 0x0082, 0x0102, 0x0182, /* 0 */
97 0x0202, 0x0282, 0x0302, 0x0382,
98 0x0402, 0x0482, 0x0502, 0x0582,
99 0x05E2, 0x0662, 0x06E2, 0x0762,
100 0x07E2, 0x0842, 0x08C2, 0x0942, /* 16 */
101 0x09C2, 0x0A22, 0x0AA2, 0x0B02,
102 0x0B82, 0x0BE2, 0x0C62, 0x0CC2,
103 0x0D42, 0x0DA2, 0x0E02, 0x0E62,
104 0x0EE2, 0x0F42, 0x0FA2, 0x1002, /* 32 */
105 0x1062, 0x10C2, 0x1122, 0x1182,
106 0x11E2, 0x1242, 0x12A2, 0x12E2,
107 0x1342, 0x13A2, 0x1402, 0x1442,
108 0x14A2, 0x14E2, 0x1542, 0x1582, /* 48 */
109 0x15E2, 0x1622, 0x1662, 0x16C1,
110 0x1701, 0x1741, 0x1781, 0x17E1,
111 0x1821, 0x1861, 0x18A1, 0x18E1,
112 0x1921, 0x1961, 0x19A1, 0x19E1, /* 64 */
113 0x1A21, 0x1A61, 0x1AA1, 0x1AC1,
114 0x1B01, 0x1B41, 0x1B81, 0x1BA1,
115 0x1BE1, 0x1C21, 0x1C41, 0x1C81,
116 0x1CA1, 0x1CE1, 0x1D01, 0x1D41, /* 80 */
117 0x1D61, 0x1DA1, 0x1DC1, 0x1E01,
118 0x1E21, 0x1E61, 0x1E81, 0x1EA1,
119 0x1EE1, 0x1F01, 0x1F21, 0x1F41,
120 0x1F81, 0x1FA1, 0x1FC1, 0x1FE1, /* 96 */
121 0x2001, 0x2041, 0x2061, 0x2081,
122 0x20A1, 0x20C1, 0x20E1, 0x2101,
123 0x2121, 0x2141, 0x2161, 0x2181,
124 0x21A1, 0x21C1, 0x21E1, 0x2201, /* 112 */
125 0x2221, 0x2241, 0x2261, 0x2281,
126 0x22A1, 0x22C1, 0x22C1, 0x22E1,
127 0x2301, 0x2321, 0x2341, 0x2361,
128 0x2361, 0x2381, 0x23A1, 0x23C1, /* 128 */
129 0x23E1, 0x23E1, 0x2401, 0x2421,
130 0x2441, 0x2441, 0x2461, 0x2481,
131 0x2481, 0x24A1, 0x24C1, 0x24C1,
132 0x24E1, 0x2501, 0x2501, 0x2521, /* 144 */
133 0x2541, 0x2541, 0x2561, 0x2561,
134 0x2581, 0x25A1, 0x25A1, 0x25C1,
135 0x25C1, 0x25E1, 0x2601, 0x2601,
136 0x2621, 0x2621, 0x2641, 0x2641, /* 160 */
137 0x2661, 0x2661, 0x2681, 0x2681,
138 0x26A1, 0x26A1, 0x26C1, 0x26C1,
139 0x26E1, 0x26E1, 0x2701, 0x2701,
140 0x2721, 0x2721, 0x2740, 0x2740, /* 176 */
141 0x2760, 0x2760, 0x2780, 0x2780,
142 0x2780, 0x27A0, 0x27A0, 0x27C0,
143 0x27C0, 0x27E0, 0x27E0, 0x27E0,
144 0x2800, 0x2800, 0x2820, 0x2820, /* 192 */
145 0x2820, 0x2840, 0x2840, 0x2840,
146 0x2860, 0x2860, 0x2880, 0x2880,
147 0x2880, 0x28A0, 0x28A0, 0x28A0,
148 0x28C0, 0x28C0, 0x28C0, 0x28E0, /* 208 */
149 0x28E0, 0x28E0, 0x2900, 0x2900,
150 0x2900, 0x2920, 0x2920, 0x2920,
151 0x2940, 0x2940, 0x2940, 0x2960,
152 0x2960, 0x2960, 0x2960, 0x2980, /* 224 */
153 0x2980, 0x2980, 0x29A0, 0x29A0,
154 0x29A0, 0x29A0, 0x29C0, 0x29C0,
155 0x29C0, 0x29E0, 0x29E0, 0x29E0,
156 0x29E0, 0x2A00, 0x2A00, 0x2A00, /* 240 */
157 0x2A00, 0x2A20, 0x2A20, 0x2A20,
158 0x2A20, 0x2A40, 0x2A40, 0x2A40,
159 0x2A40, 0x2A60, 0x2A60, 0x2A60,
160};
161
162const u16 bcm43xx_ilt_finefreqg[BCM43xx_ILT_FINEFREQG_SIZE] = {
163 0x0089, 0x02E9, 0x0409, 0x04E9, /* 0 */
164 0x05A9, 0x0669, 0x0709, 0x0789,
165 0x0829, 0x08A9, 0x0929, 0x0989,
166 0x0A09, 0x0A69, 0x0AC9, 0x0B29,
167 0x0BA9, 0x0BE9, 0x0C49, 0x0CA9, /* 16 */
168 0x0D09, 0x0D69, 0x0DA9, 0x0E09,
169 0x0E69, 0x0EA9, 0x0F09, 0x0F49,
170 0x0FA9, 0x0FE9, 0x1029, 0x1089,
171 0x10C9, 0x1109, 0x1169, 0x11A9, /* 32 */
172 0x11E9, 0x1229, 0x1289, 0x12C9,
173 0x1309, 0x1349, 0x1389, 0x13C9,
174 0x1409, 0x1449, 0x14A9, 0x14E9,
175 0x1529, 0x1569, 0x15A9, 0x15E9, /* 48 */
176 0x1629, 0x1669, 0x16A9, 0x16E8,
177 0x1728, 0x1768, 0x17A8, 0x17E8,
178 0x1828, 0x1868, 0x18A8, 0x18E8,
179 0x1928, 0x1968, 0x19A8, 0x19E8, /* 64 */
180 0x1A28, 0x1A68, 0x1AA8, 0x1AE8,
181 0x1B28, 0x1B68, 0x1BA8, 0x1BE8,
182 0x1C28, 0x1C68, 0x1CA8, 0x1CE8,
183 0x1D28, 0x1D68, 0x1DC8, 0x1E08, /* 80 */
184 0x1E48, 0x1E88, 0x1EC8, 0x1F08,
185 0x1F48, 0x1F88, 0x1FE8, 0x2028,
186 0x2068, 0x20A8, 0x2108, 0x2148,
187 0x2188, 0x21C8, 0x2228, 0x2268, /* 96 */
188 0x22C8, 0x2308, 0x2348, 0x23A8,
189 0x23E8, 0x2448, 0x24A8, 0x24E8,
190 0x2548, 0x25A8, 0x2608, 0x2668,
191 0x26C8, 0x2728, 0x2787, 0x27E7, /* 112 */
192 0x2847, 0x28C7, 0x2947, 0x29A7,
193 0x2A27, 0x2AC7, 0x2B47, 0x2BE7,
194 0x2CA7, 0x2D67, 0x2E47, 0x2F67,
195 0x3247, 0x3526, 0x3646, 0x3726, /* 128 */
196 0x3806, 0x38A6, 0x3946, 0x39E6,
197 0x3A66, 0x3AE6, 0x3B66, 0x3BC6,
198 0x3C45, 0x3CA5, 0x3D05, 0x3D85,
199 0x3DE5, 0x3E45, 0x3EA5, 0x3EE5, /* 144 */
200 0x3F45, 0x3FA5, 0x4005, 0x4045,
201 0x40A5, 0x40E5, 0x4145, 0x4185,
202 0x41E5, 0x4225, 0x4265, 0x42C5,
203 0x4305, 0x4345, 0x43A5, 0x43E5, /* 160 */
204 0x4424, 0x4464, 0x44C4, 0x4504,
205 0x4544, 0x4584, 0x45C4, 0x4604,
206 0x4644, 0x46A4, 0x46E4, 0x4724,
207 0x4764, 0x47A4, 0x47E4, 0x4824, /* 176 */
208 0x4864, 0x48A4, 0x48E4, 0x4924,
209 0x4964, 0x49A4, 0x49E4, 0x4A24,
210 0x4A64, 0x4AA4, 0x4AE4, 0x4B23,
211 0x4B63, 0x4BA3, 0x4BE3, 0x4C23, /* 192 */
212 0x4C63, 0x4CA3, 0x4CE3, 0x4D23,
213 0x4D63, 0x4DA3, 0x4DE3, 0x4E23,
214 0x4E63, 0x4EA3, 0x4EE3, 0x4F23,
215 0x4F63, 0x4FC3, 0x5003, 0x5043, /* 208 */
216 0x5083, 0x50C3, 0x5103, 0x5143,
217 0x5183, 0x51E2, 0x5222, 0x5262,
218 0x52A2, 0x52E2, 0x5342, 0x5382,
219 0x53C2, 0x5402, 0x5462, 0x54A2, /* 224 */
220 0x5502, 0x5542, 0x55A2, 0x55E2,
221 0x5642, 0x5682, 0x56E2, 0x5722,
222 0x5782, 0x57E1, 0x5841, 0x58A1,
223 0x5901, 0x5961, 0x59C1, 0x5A21, /* 240 */
224 0x5AA1, 0x5B01, 0x5B81, 0x5BE1,
225 0x5C61, 0x5D01, 0x5D80, 0x5E20,
226 0x5EE0, 0x5FA0, 0x6080, 0x61C0,
227};
228
229const u16 bcm43xx_ilt_noisea2[BCM43xx_ILT_NOISEA2_SIZE] = {
230 0x0001, 0x0001, 0x0001, 0xFFFE,
231 0xFFFE, 0x3FFF, 0x1000, 0x0393,
232};
233
234const u16 bcm43xx_ilt_noisea3[BCM43xx_ILT_NOISEA3_SIZE] = {
235 0x4C4C, 0x4C4C, 0x4C4C, 0x2D36,
236 0x4C4C, 0x4C4C, 0x4C4C, 0x2D36,
237};
238
239const u16 bcm43xx_ilt_noiseg1[BCM43xx_ILT_NOISEG1_SIZE] = {
240 0x013C, 0x01F5, 0x031A, 0x0631,
241 0x0001, 0x0001, 0x0001, 0x0001,
242};
243
244const u16 bcm43xx_ilt_noiseg2[BCM43xx_ILT_NOISEG2_SIZE] = {
245 0x5484, 0x3C40, 0x0000, 0x0000,
246 0x0000, 0x0000, 0x0000, 0x0000,
247};
248
249const u16 bcm43xx_ilt_noisescaleg1[BCM43xx_ILT_NOISESCALEG_SIZE] = {
250 0x6C77, 0x5162, 0x3B40, 0x3335, /* 0 */
251 0x2F2D, 0x2A2A, 0x2527, 0x1F21,
252 0x1A1D, 0x1719, 0x1616, 0x1414,
253 0x1414, 0x1400, 0x1414, 0x1614,
254 0x1716, 0x1A19, 0x1F1D, 0x2521, /* 16 */
255 0x2A27, 0x2F2A, 0x332D, 0x3B35,
256 0x5140, 0x6C62, 0x0077,
257};
258
259const u16 bcm43xx_ilt_noisescaleg2[BCM43xx_ILT_NOISESCALEG_SIZE] = {
260 0xD8DD, 0xCBD4, 0xBCC0, 0XB6B7, /* 0 */
261 0xB2B0, 0xADAD, 0xA7A9, 0x9FA1,
262 0x969B, 0x9195, 0x8F8F, 0x8A8A,
263 0x8A8A, 0x8A00, 0x8A8A, 0x8F8A,
264 0x918F, 0x9695, 0x9F9B, 0xA7A1, /* 16 */
265 0xADA9, 0xB2AD, 0xB6B0, 0xBCB7,
266 0xCBC0, 0xD8D4, 0x00DD,
267};
268
269const u16 bcm43xx_ilt_noisescaleg3[BCM43xx_ILT_NOISESCALEG_SIZE] = {
270 0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4, /* 0 */
271 0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4,
272 0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4,
273 0xA4A4, 0xA400, 0xA4A4, 0xA4A4,
274 0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4, /* 16 */
275 0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4,
276 0xA4A4, 0xA4A4, 0x00A4,
277};
278
279const u16 bcm43xx_ilt_sigmasqr1[BCM43xx_ILT_SIGMASQR_SIZE] = {
280 0x007A, 0x0075, 0x0071, 0x006C, /* 0 */
281 0x0067, 0x0063, 0x005E, 0x0059,
282 0x0054, 0x0050, 0x004B, 0x0046,
283 0x0042, 0x003D, 0x003D, 0x003D,
284 0x003D, 0x003D, 0x003D, 0x003D, /* 16 */
285 0x003D, 0x003D, 0x003D, 0x003D,
286 0x003D, 0x003D, 0x0000, 0x003D,
287 0x003D, 0x003D, 0x003D, 0x003D,
288 0x003D, 0x003D, 0x003D, 0x003D, /* 32 */
289 0x003D, 0x003D, 0x003D, 0x003D,
290 0x0042, 0x0046, 0x004B, 0x0050,
291 0x0054, 0x0059, 0x005E, 0x0063,
292 0x0067, 0x006C, 0x0071, 0x0075, /* 48 */
293 0x007A,
294};
295
296const u16 bcm43xx_ilt_sigmasqr2[BCM43xx_ILT_SIGMASQR_SIZE] = {
297 0x00DE, 0x00DC, 0x00DA, 0x00D8, /* 0 */
298 0x00D6, 0x00D4, 0x00D2, 0x00CF,
299 0x00CD, 0x00CA, 0x00C7, 0x00C4,
300 0x00C1, 0x00BE, 0x00BE, 0x00BE,
301 0x00BE, 0x00BE, 0x00BE, 0x00BE, /* 16 */
302 0x00BE, 0x00BE, 0x00BE, 0x00BE,
303 0x00BE, 0x00BE, 0x0000, 0x00BE,
304 0x00BE, 0x00BE, 0x00BE, 0x00BE,
305 0x00BE, 0x00BE, 0x00BE, 0x00BE, /* 32 */
306 0x00BE, 0x00BE, 0x00BE, 0x00BE,
307 0x00C1, 0x00C4, 0x00C7, 0x00CA,
308 0x00CD, 0x00CF, 0x00D2, 0x00D4,
309 0x00D6, 0x00D8, 0x00DA, 0x00DC, /* 48 */
310 0x00DE,
311};
312
313/**** Helper functions to access the device Internal Lookup Tables ****/
314
315void bcm43xx_ilt_write(struct bcm43xx_private *bcm, u16 offset, u16 val)
316{
317 if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A) {
318 bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_CTRL, offset);
319 mmiowb();
320 bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, val);
321 } else {
322 bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_CTRL, offset);
323 mmiowb();
324 bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_DATA1, val);
325 }
326}
327
328u16 bcm43xx_ilt_read(struct bcm43xx_private *bcm, u16 offset)
329{
330 if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A) {
331 bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_CTRL, offset);
332 return bcm43xx_phy_read(bcm, BCM43xx_PHY_ILT_A_DATA1);
333 } else {
334 bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_CTRL, offset);
335 return bcm43xx_phy_read(bcm, BCM43xx_PHY_ILT_G_DATA1);
336 }
337}
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_ilt.h b/drivers/net/wireless/bcm43xx/bcm43xx_ilt.h
new file mode 100644
index 000000000000..464521abf73c
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_ilt.h
@@ -0,0 +1,32 @@
1#ifndef BCM43xx_ILT_H_
2#define BCM43xx_ILT_H_
3
4#define BCM43xx_ILT_ROTOR_SIZE 53
5extern const u32 bcm43xx_ilt_rotor[BCM43xx_ILT_ROTOR_SIZE];
6#define BCM43xx_ILT_RETARD_SIZE 53
7extern const u32 bcm43xx_ilt_retard[BCM43xx_ILT_RETARD_SIZE];
8#define BCM43xx_ILT_FINEFREQA_SIZE 256
9extern const u16 bcm43xx_ilt_finefreqa[BCM43xx_ILT_FINEFREQA_SIZE];
10#define BCM43xx_ILT_FINEFREQG_SIZE 256
11extern const u16 bcm43xx_ilt_finefreqg[BCM43xx_ILT_FINEFREQG_SIZE];
12#define BCM43xx_ILT_NOISEA2_SIZE 8
13extern const u16 bcm43xx_ilt_noisea2[BCM43xx_ILT_NOISEA2_SIZE];
14#define BCM43xx_ILT_NOISEA3_SIZE 8
15extern const u16 bcm43xx_ilt_noisea3[BCM43xx_ILT_NOISEA3_SIZE];
16#define BCM43xx_ILT_NOISEG1_SIZE 8
17extern const u16 bcm43xx_ilt_noiseg1[BCM43xx_ILT_NOISEG1_SIZE];
18#define BCM43xx_ILT_NOISEG2_SIZE 8
19extern const u16 bcm43xx_ilt_noiseg2[BCM43xx_ILT_NOISEG2_SIZE];
20#define BCM43xx_ILT_NOISESCALEG_SIZE 27
21extern const u16 bcm43xx_ilt_noisescaleg1[BCM43xx_ILT_NOISESCALEG_SIZE];
22extern const u16 bcm43xx_ilt_noisescaleg2[BCM43xx_ILT_NOISESCALEG_SIZE];
23extern const u16 bcm43xx_ilt_noisescaleg3[BCM43xx_ILT_NOISESCALEG_SIZE];
24#define BCM43xx_ILT_SIGMASQR_SIZE 53
25extern const u16 bcm43xx_ilt_sigmasqr1[BCM43xx_ILT_SIGMASQR_SIZE];
26extern const u16 bcm43xx_ilt_sigmasqr2[BCM43xx_ILT_SIGMASQR_SIZE];
27
28
29void bcm43xx_ilt_write(struct bcm43xx_private *bcm, u16 offset, u16 val);
30u16 bcm43xx_ilt_read(struct bcm43xx_private *bcm, u16 offset);
31
32#endif /* BCM43xx_ILT_H_ */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_leds.c b/drivers/net/wireless/bcm43xx/bcm43xx_leds.c
new file mode 100644
index 000000000000..4b2c02c0b31e
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_leds.c
@@ -0,0 +1,293 @@
1/*
2
3 Broadcom BCM43xx wireless driver
4
5 Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
6 Stefano Brivio <st3@riseup.net>
7 Michael Buesch <mbuesch@freenet.de>
8 Danny van Dyk <kugelfang@gentoo.org>
9 Andreas Jaggi <andreas.jaggi@waterwave.ch>
10
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2 of the License, or
14 (at your option) any later version.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with this program; see the file COPYING. If not, write to
23 the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
24 Boston, MA 02110-1301, USA.
25
26*/
27
28#include "bcm43xx_leds.h"
29#include "bcm43xx.h"
30
31#include <asm/bitops.h>
32
33
34static void bcm43xx_led_changestate(struct bcm43xx_led *led)
35{
36 struct bcm43xx_private *bcm = led->bcm;
37 const int index = bcm43xx_led_index(led);
38 const u16 mask = (1 << index);
39 u16 ledctl;
40
41 assert(index >= 0 && index < BCM43xx_NR_LEDS);
42 assert(led->blink_interval);
43 ledctl = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL);
44 ledctl = (ledctl & mask) ? (ledctl & ~mask) : (ledctl | mask);
45 bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl);
46}
47
48static void bcm43xx_led_blink(unsigned long d)
49{
50 struct bcm43xx_led *led = (struct bcm43xx_led *)d;
51 struct bcm43xx_private *bcm = led->bcm;
52 unsigned long flags;
53
54 bcm43xx_lock_mmio(bcm, flags);
55 if (led->blink_interval) {
56 bcm43xx_led_changestate(led);
57 mod_timer(&led->blink_timer, jiffies + led->blink_interval);
58 }
59 bcm43xx_unlock_mmio(bcm, flags);
60}
61
62static void bcm43xx_led_blink_start(struct bcm43xx_led *led,
63 unsigned long interval)
64{
65 if (led->blink_interval)
66 return;
67 led->blink_interval = interval;
68 bcm43xx_led_changestate(led);
69 led->blink_timer.expires = jiffies + interval;
70 add_timer(&led->blink_timer);
71}
72
73static void bcm43xx_led_blink_stop(struct bcm43xx_led *led, int sync)
74{
75 struct bcm43xx_private *bcm = led->bcm;
76 const int index = bcm43xx_led_index(led);
77 u16 ledctl;
78
79 if (!led->blink_interval)
80 return;
81 if (unlikely(sync))
82 del_timer_sync(&led->blink_timer);
83 else
84 del_timer(&led->blink_timer);
85 led->blink_interval = 0;
86
87 /* Make sure the LED is turned off. */
88 assert(index >= 0 && index < BCM43xx_NR_LEDS);
89 ledctl = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL);
90 if (led->activelow)
91 ledctl |= (1 << index);
92 else
93 ledctl &= ~(1 << index);
94 bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl);
95}
96
97static void bcm43xx_led_init_hardcoded(struct bcm43xx_private *bcm,
98 struct bcm43xx_led *led,
99 int led_index)
100{
101 /* This function is called, if the behaviour (and activelow)
102 * information for a LED is missing in the SPROM.
103 * We hardcode the behaviour values for various devices here.
104 * Note that the BCM43xx_LED_TEST_XXX behaviour values can
105 * be used to figure out which led is mapped to which index.
106 */
107
108 switch (led_index) {
109 case 0:
110 led->behaviour = BCM43xx_LED_ACTIVITY;
111 if (bcm->board_vendor == PCI_VENDOR_ID_COMPAQ)
112 led->behaviour = BCM43xx_LED_RADIO_ALL;
113 break;
114 case 1:
115 led->behaviour = BCM43xx_LED_RADIO_B;
116 if (bcm->board_vendor == PCI_VENDOR_ID_ASUSTEK)
117 led->behaviour = BCM43xx_LED_ASSOC;
118 break;
119 case 2:
120 led->behaviour = BCM43xx_LED_RADIO_A;
121 break;
122 case 3:
123 led->behaviour = BCM43xx_LED_OFF;
124 break;
125 default:
126 assert(0);
127 }
128}
129
130int bcm43xx_leds_init(struct bcm43xx_private *bcm)
131{
132 struct bcm43xx_led *led;
133 u8 sprom[4];
134 int i;
135
136 sprom[0] = bcm->sprom.wl0gpio0;
137 sprom[1] = bcm->sprom.wl0gpio1;
138 sprom[2] = bcm->sprom.wl0gpio2;
139 sprom[3] = bcm->sprom.wl0gpio3;
140
141 for (i = 0; i < BCM43xx_NR_LEDS; i++) {
142 led = &(bcm->leds[i]);
143 led->bcm = bcm;
144 setup_timer(&led->blink_timer,
145 bcm43xx_led_blink,
146 (unsigned long)led);
147
148 if (sprom[i] == 0xFF) {
149 bcm43xx_led_init_hardcoded(bcm, led, i);
150 } else {
151 led->behaviour = sprom[i] & BCM43xx_LED_BEHAVIOUR;
152 led->activelow = !!(sprom[i] & BCM43xx_LED_ACTIVELOW);
153 }
154 }
155
156 return 0;
157}
158
159void bcm43xx_leds_exit(struct bcm43xx_private *bcm)
160{
161 struct bcm43xx_led *led;
162 int i;
163
164 for (i = 0; i < BCM43xx_NR_LEDS; i++) {
165 led = &(bcm->leds[i]);
166 bcm43xx_led_blink_stop(led, 1);
167 }
168 bcm43xx_leds_switch_all(bcm, 0);
169}
170
171void bcm43xx_leds_update(struct bcm43xx_private *bcm, int activity)
172{
173 struct bcm43xx_led *led;
174 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
175 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
176 const int transferring = (jiffies - bcm->stats.last_tx) < BCM43xx_LED_XFER_THRES;
177 int i, turn_on;
178 unsigned long interval = 0;
179 u16 ledctl;
180
181 ledctl = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL);
182 for (i = 0; i < BCM43xx_NR_LEDS; i++) {
183 led = &(bcm->leds[i]);
184
185 turn_on = 0;
186 switch (led->behaviour) {
187 case BCM43xx_LED_INACTIVE:
188 continue;
189 case BCM43xx_LED_OFF:
190 break;
191 case BCM43xx_LED_ON:
192 turn_on = 1;
193 break;
194 case BCM43xx_LED_ACTIVITY:
195 turn_on = activity;
196 break;
197 case BCM43xx_LED_RADIO_ALL:
198 turn_on = radio->enabled;
199 break;
200 case BCM43xx_LED_RADIO_A:
201 turn_on = (radio->enabled && phy->type == BCM43xx_PHYTYPE_A);
202 break;
203 case BCM43xx_LED_RADIO_B:
204 turn_on = (radio->enabled &&
205 (phy->type == BCM43xx_PHYTYPE_B ||
206 phy->type == BCM43xx_PHYTYPE_G));
207 break;
208 case BCM43xx_LED_MODE_BG:
209 if (phy->type == BCM43xx_PHYTYPE_G &&
210 1/*FIXME: using G rates.*/)
211 turn_on = 1;
212 break;
213 case BCM43xx_LED_TRANSFER:
214 if (transferring)
215 bcm43xx_led_blink_start(led, BCM43xx_LEDBLINK_MEDIUM);
216 else
217 bcm43xx_led_blink_stop(led, 0);
218 continue;
219 case BCM43xx_LED_APTRANSFER:
220 if (bcm->ieee->iw_mode == IW_MODE_MASTER) {
221 if (transferring) {
222 interval = BCM43xx_LEDBLINK_FAST;
223 turn_on = 1;
224 }
225 } else {
226 turn_on = 1;
227 if (0/*TODO: not assoc*/)
228 interval = BCM43xx_LEDBLINK_SLOW;
229 else if (transferring)
230 interval = BCM43xx_LEDBLINK_FAST;
231 else
232 turn_on = 0;
233 }
234 if (turn_on)
235 bcm43xx_led_blink_start(led, interval);
236 else
237 bcm43xx_led_blink_stop(led, 0);
238 continue;
239 case BCM43xx_LED_WEIRD:
240 //TODO
241 break;
242 case BCM43xx_LED_ASSOC:
243 if (bcm->softmac->associated)
244 turn_on = 1;
245 break;
246#ifdef CONFIG_BCM43XX_DEBUG
247 case BCM43xx_LED_TEST_BLINKSLOW:
248 bcm43xx_led_blink_start(led, BCM43xx_LEDBLINK_SLOW);
249 continue;
250 case BCM43xx_LED_TEST_BLINKMEDIUM:
251 bcm43xx_led_blink_start(led, BCM43xx_LEDBLINK_MEDIUM);
252 continue;
253 case BCM43xx_LED_TEST_BLINKFAST:
254 bcm43xx_led_blink_start(led, BCM43xx_LEDBLINK_FAST);
255 continue;
256#endif /* CONFIG_BCM43XX_DEBUG */
257 default:
258 assert(0);
259 };
260
261 if (led->activelow)
262 turn_on = !turn_on;
263 if (turn_on)
264 ledctl |= (1 << i);
265 else
266 ledctl &= ~(1 << i);
267 }
268 bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl);
269}
270
271void bcm43xx_leds_switch_all(struct bcm43xx_private *bcm, int on)
272{
273 struct bcm43xx_led *led;
274 u16 ledctl;
275 int i;
276 int bit_on;
277
278 ledctl = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL);
279 for (i = 0; i < BCM43xx_NR_LEDS; i++) {
280 led = &(bcm->leds[i]);
281 if (led->behaviour == BCM43xx_LED_INACTIVE)
282 continue;
283 if (on)
284 bit_on = led->activelow ? 0 : 1;
285 else
286 bit_on = led->activelow ? 1 : 0;
287 if (bit_on)
288 ledctl |= (1 << i);
289 else
290 ledctl &= ~(1 << i);
291 }
292 bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl);
293}
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_leds.h b/drivers/net/wireless/bcm43xx/bcm43xx_leds.h
new file mode 100644
index 000000000000..d3716cf3aebc
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_leds.h
@@ -0,0 +1,56 @@
1#ifndef BCM43xx_LEDS_H_
2#define BCM43xx_LEDS_H_
3
4#include <linux/types.h>
5#include <linux/timer.h>
6
7
8struct bcm43xx_led {
9 u8 behaviour:7;
10 u8 activelow:1;
11
12 struct bcm43xx_private *bcm;
13 struct timer_list blink_timer;
14 unsigned long blink_interval;
15};
16#define bcm43xx_led_index(led) ((int)((led) - (led)->bcm->leds))
17
18/* Delay between state changes when blinking in jiffies */
19#define BCM43xx_LEDBLINK_SLOW (HZ / 1)
20#define BCM43xx_LEDBLINK_MEDIUM (HZ / 4)
21#define BCM43xx_LEDBLINK_FAST (HZ / 8)
22
23#define BCM43xx_LED_XFER_THRES (HZ / 100)
24
25#define BCM43xx_LED_BEHAVIOUR 0x7F
26#define BCM43xx_LED_ACTIVELOW 0x80
27enum { /* LED behaviour values */
28 BCM43xx_LED_OFF,
29 BCM43xx_LED_ON,
30 BCM43xx_LED_ACTIVITY,
31 BCM43xx_LED_RADIO_ALL,
32 BCM43xx_LED_RADIO_A,
33 BCM43xx_LED_RADIO_B,
34 BCM43xx_LED_MODE_BG,
35 BCM43xx_LED_TRANSFER,
36 BCM43xx_LED_APTRANSFER,
37 BCM43xx_LED_WEIRD,//FIXME
38 BCM43xx_LED_ASSOC,
39 BCM43xx_LED_INACTIVE,
40
41 /* Behaviour values for testing.
42 * With these values it is easier to figure out
43 * the real behaviour of leds, in case the SPROM
44 * is missing information.
45 */
46 BCM43xx_LED_TEST_BLINKSLOW,
47 BCM43xx_LED_TEST_BLINKMEDIUM,
48 BCM43xx_LED_TEST_BLINKFAST,
49};
50
51int bcm43xx_leds_init(struct bcm43xx_private *bcm);
52void bcm43xx_leds_exit(struct bcm43xx_private *bcm);
53void bcm43xx_leds_update(struct bcm43xx_private *bcm, int activity);
54void bcm43xx_leds_switch_all(struct bcm43xx_private *bcm, int on);
55
56#endif /* BCM43xx_LEDS_H_ */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
new file mode 100644
index 000000000000..c37371fc9e01
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
@@ -0,0 +1,3973 @@
1/*
2
3 Broadcom BCM43xx wireless driver
4
5 Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
6 Stefano Brivio <st3@riseup.net>
7 Michael Buesch <mbuesch@freenet.de>
8 Danny van Dyk <kugelfang@gentoo.org>
9 Andreas Jaggi <andreas.jaggi@waterwave.ch>
10
11 Some parts of the code in this file are derived from the ipw2200
12 driver Copyright(c) 2003 - 2004 Intel Corporation.
13
14 This program is free software; you can redistribute it and/or modify
15 it under the terms of the GNU General Public License as published by
16 the Free Software Foundation; either version 2 of the License, or
17 (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; see the file COPYING. If not, write to
26 the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
27 Boston, MA 02110-1301, USA.
28
29*/
30
31#include <linux/delay.h>
32#include <linux/init.h>
33#include <linux/moduleparam.h>
34#include <linux/if_arp.h>
35#include <linux/etherdevice.h>
36#include <linux/version.h>
37#include <linux/firmware.h>
38#include <linux/wireless.h>
39#include <linux/workqueue.h>
40#include <linux/skbuff.h>
41#include <linux/dma-mapping.h>
42#include <net/iw_handler.h>
43
44#include "bcm43xx.h"
45#include "bcm43xx_main.h"
46#include "bcm43xx_debugfs.h"
47#include "bcm43xx_radio.h"
48#include "bcm43xx_phy.h"
49#include "bcm43xx_dma.h"
50#include "bcm43xx_pio.h"
51#include "bcm43xx_power.h"
52#include "bcm43xx_wx.h"
53#include "bcm43xx_ethtool.h"
54#include "bcm43xx_xmit.h"
55
56
57MODULE_DESCRIPTION("Broadcom BCM43xx wireless driver");
58MODULE_AUTHOR("Martin Langer");
59MODULE_AUTHOR("Stefano Brivio");
60MODULE_AUTHOR("Michael Buesch");
61MODULE_LICENSE("GPL");
62
63#ifdef CONFIG_BCM947XX
64extern char *nvram_get(char *name);
65#endif
66
67#if defined(CONFIG_BCM43XX_DMA) && defined(CONFIG_BCM43XX_PIO)
68static int modparam_pio;
69module_param_named(pio, modparam_pio, int, 0444);
70MODULE_PARM_DESC(pio, "enable(1) / disable(0) PIO mode");
71#elif defined(CONFIG_BCM43XX_DMA)
72# define modparam_pio 0
73#elif defined(CONFIG_BCM43XX_PIO)
74# define modparam_pio 1
75#endif
76
77static int modparam_bad_frames_preempt;
78module_param_named(bad_frames_preempt, modparam_bad_frames_preempt, int, 0444);
79MODULE_PARM_DESC(bad_frames_preempt, "enable(1) / disable(0) Bad Frames Preemption");
80
81static int modparam_short_retry = BCM43xx_DEFAULT_SHORT_RETRY_LIMIT;
82module_param_named(short_retry, modparam_short_retry, int, 0444);
83MODULE_PARM_DESC(short_retry, "Short-Retry-Limit (0 - 15)");
84
85static int modparam_long_retry = BCM43xx_DEFAULT_LONG_RETRY_LIMIT;
86module_param_named(long_retry, modparam_long_retry, int, 0444);
87MODULE_PARM_DESC(long_retry, "Long-Retry-Limit (0 - 15)");
88
89static int modparam_locale = -1;
90module_param_named(locale, modparam_locale, int, 0444);
91MODULE_PARM_DESC(country, "Select LocaleCode 0-11 (For travelers)");
92
93static int modparam_noleds;
94module_param_named(noleds, modparam_noleds, int, 0444);
95MODULE_PARM_DESC(noleds, "Turn off all LED activity");
96
97#ifdef CONFIG_BCM43XX_DEBUG
98static char modparam_fwpostfix[64];
99module_param_string(fwpostfix, modparam_fwpostfix, 64, 0444);
100MODULE_PARM_DESC(fwpostfix, "Postfix for .fw files. Useful for debugging.");
101#else
102# define modparam_fwpostfix ""
103#endif /* CONFIG_BCM43XX_DEBUG*/
104
105
106/* If you want to debug with just a single device, enable this,
107 * where the string is the pci device ID (as given by the kernel's
108 * pci_name function) of the device to be used.
109 */
110//#define DEBUG_SINGLE_DEVICE_ONLY "0001:11:00.0"
111
112/* If you want to enable printing of each MMIO access, enable this. */
113//#define DEBUG_ENABLE_MMIO_PRINT
114
115/* If you want to enable printing of MMIO access within
116 * ucode/pcm upload, initvals write, enable this.
117 */
118//#define DEBUG_ENABLE_UCODE_MMIO_PRINT
119
120/* If you want to enable printing of PCI Config Space access, enable this */
121//#define DEBUG_ENABLE_PCILOG
122
123
124/* Detailed list maintained at:
125 * http://openfacts.berlios.de/index-en.phtml?title=Bcm43xxDevices
126 */
127 static struct pci_device_id bcm43xx_pci_tbl[] = {
128 /* Broadcom 4303 802.11b */
129 { PCI_VENDOR_ID_BROADCOM, 0x4301, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
130 /* Broadcom 4307 802.11b */
131 { PCI_VENDOR_ID_BROADCOM, 0x4307, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
132 /* Broadcom 4318 802.11b/g */
133 { PCI_VENDOR_ID_BROADCOM, 0x4318, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
134 /* Broadcom 4306 802.11b/g */
135 { PCI_VENDOR_ID_BROADCOM, 0x4320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
136 /* Broadcom 4306 802.11a */
137// { PCI_VENDOR_ID_BROADCOM, 0x4321, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
138 /* Broadcom 4309 802.11a/b/g */
139 { PCI_VENDOR_ID_BROADCOM, 0x4324, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
140 /* Broadcom 43XG 802.11b/g */
141 { PCI_VENDOR_ID_BROADCOM, 0x4325, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
142#ifdef CONFIG_BCM947XX
143 /* SB bus on BCM947xx */
144 { PCI_VENDOR_ID_BROADCOM, 0x0800, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
145#endif
146 { 0 },
147};
148MODULE_DEVICE_TABLE(pci, bcm43xx_pci_tbl);
149
150static void bcm43xx_ram_write(struct bcm43xx_private *bcm, u16 offset, u32 val)
151{
152 u32 status;
153
154 status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
155 if (!(status & BCM43xx_SBF_XFER_REG_BYTESWAP))
156 val = swab32(val);
157
158 bcm43xx_write32(bcm, BCM43xx_MMIO_RAM_CONTROL, offset);
159 mmiowb();
160 bcm43xx_write32(bcm, BCM43xx_MMIO_RAM_DATA, val);
161}
162
163static inline
164void bcm43xx_shm_control_word(struct bcm43xx_private *bcm,
165 u16 routing, u16 offset)
166{
167 u32 control;
168
169 /* "offset" is the WORD offset. */
170
171 control = routing;
172 control <<= 16;
173 control |= offset;
174 bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_CONTROL, control);
175}
176
177u32 bcm43xx_shm_read32(struct bcm43xx_private *bcm,
178 u16 routing, u16 offset)
179{
180 u32 ret;
181
182 if (routing == BCM43xx_SHM_SHARED) {
183 if (offset & 0x0003) {
184 /* Unaligned access */
185 bcm43xx_shm_control_word(bcm, routing, offset >> 2);
186 ret = bcm43xx_read16(bcm, BCM43xx_MMIO_SHM_DATA_UNALIGNED);
187 ret <<= 16;
188 bcm43xx_shm_control_word(bcm, routing, (offset >> 2) + 1);
189 ret |= bcm43xx_read16(bcm, BCM43xx_MMIO_SHM_DATA);
190
191 return ret;
192 }
193 offset >>= 2;
194 }
195 bcm43xx_shm_control_word(bcm, routing, offset);
196 ret = bcm43xx_read32(bcm, BCM43xx_MMIO_SHM_DATA);
197
198 return ret;
199}
200
201u16 bcm43xx_shm_read16(struct bcm43xx_private *bcm,
202 u16 routing, u16 offset)
203{
204 u16 ret;
205
206 if (routing == BCM43xx_SHM_SHARED) {
207 if (offset & 0x0003) {
208 /* Unaligned access */
209 bcm43xx_shm_control_word(bcm, routing, offset >> 2);
210 ret = bcm43xx_read16(bcm, BCM43xx_MMIO_SHM_DATA_UNALIGNED);
211
212 return ret;
213 }
214 offset >>= 2;
215 }
216 bcm43xx_shm_control_word(bcm, routing, offset);
217 ret = bcm43xx_read16(bcm, BCM43xx_MMIO_SHM_DATA);
218
219 return ret;
220}
221
222void bcm43xx_shm_write32(struct bcm43xx_private *bcm,
223 u16 routing, u16 offset,
224 u32 value)
225{
226 if (routing == BCM43xx_SHM_SHARED) {
227 if (offset & 0x0003) {
228 /* Unaligned access */
229 bcm43xx_shm_control_word(bcm, routing, offset >> 2);
230 mmiowb();
231 bcm43xx_write16(bcm, BCM43xx_MMIO_SHM_DATA_UNALIGNED,
232 (value >> 16) & 0xffff);
233 mmiowb();
234 bcm43xx_shm_control_word(bcm, routing, (offset >> 2) + 1);
235 mmiowb();
236 bcm43xx_write16(bcm, BCM43xx_MMIO_SHM_DATA,
237 value & 0xffff);
238 return;
239 }
240 offset >>= 2;
241 }
242 bcm43xx_shm_control_word(bcm, routing, offset);
243 mmiowb();
244 bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_DATA, value);
245}
246
247void bcm43xx_shm_write16(struct bcm43xx_private *bcm,
248 u16 routing, u16 offset,
249 u16 value)
250{
251 if (routing == BCM43xx_SHM_SHARED) {
252 if (offset & 0x0003) {
253 /* Unaligned access */
254 bcm43xx_shm_control_word(bcm, routing, offset >> 2);
255 mmiowb();
256 bcm43xx_write16(bcm, BCM43xx_MMIO_SHM_DATA_UNALIGNED,
257 value);
258 return;
259 }
260 offset >>= 2;
261 }
262 bcm43xx_shm_control_word(bcm, routing, offset);
263 mmiowb();
264 bcm43xx_write16(bcm, BCM43xx_MMIO_SHM_DATA, value);
265}
266
267void bcm43xx_tsf_read(struct bcm43xx_private *bcm, u64 *tsf)
268{
269 /* We need to be careful. As we read the TSF from multiple
270 * registers, we should take care of register overflows.
271 * In theory, the whole tsf read process should be atomic.
272 * We try to be atomic here, by restaring the read process,
273 * if any of the high registers changed (overflew).
274 */
275 if (bcm->current_core->rev >= 3) {
276 u32 low, high, high2;
277
278 do {
279 high = bcm43xx_read32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_HIGH);
280 low = bcm43xx_read32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_LOW);
281 high2 = bcm43xx_read32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_HIGH);
282 } while (unlikely(high != high2));
283
284 *tsf = high;
285 *tsf <<= 32;
286 *tsf |= low;
287 } else {
288 u64 tmp;
289 u16 v0, v1, v2, v3;
290 u16 test1, test2, test3;
291
292 do {
293 v3 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_3);
294 v2 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_2);
295 v1 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_1);
296 v0 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_0);
297
298 test3 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_3);
299 test2 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_2);
300 test1 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_1);
301 } while (v3 != test3 || v2 != test2 || v1 != test1);
302
303 *tsf = v3;
304 *tsf <<= 48;
305 tmp = v2;
306 tmp <<= 32;
307 *tsf |= tmp;
308 tmp = v1;
309 tmp <<= 16;
310 *tsf |= tmp;
311 *tsf |= v0;
312 }
313}
314
315void bcm43xx_tsf_write(struct bcm43xx_private *bcm, u64 tsf)
316{
317 u32 status;
318
319 status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
320 status |= BCM43xx_SBF_TIME_UPDATE;
321 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status);
322 mmiowb();
323
324 /* Be careful with the in-progress timer.
325 * First zero out the low register, so we have a full
326 * register-overflow duration to complete the operation.
327 */
328 if (bcm->current_core->rev >= 3) {
329 u32 lo = (tsf & 0x00000000FFFFFFFFULL);
330 u32 hi = (tsf & 0xFFFFFFFF00000000ULL) >> 32;
331
332 bcm43xx_write32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_LOW, 0);
333 mmiowb();
334 bcm43xx_write32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_HIGH, hi);
335 mmiowb();
336 bcm43xx_write32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_LOW, lo);
337 } else {
338 u16 v0 = (tsf & 0x000000000000FFFFULL);
339 u16 v1 = (tsf & 0x00000000FFFF0000ULL) >> 16;
340 u16 v2 = (tsf & 0x0000FFFF00000000ULL) >> 32;
341 u16 v3 = (tsf & 0xFFFF000000000000ULL) >> 48;
342
343 bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_0, 0);
344 mmiowb();
345 bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_3, v3);
346 mmiowb();
347 bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_2, v2);
348 mmiowb();
349 bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_1, v1);
350 mmiowb();
351 bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_0, v0);
352 }
353
354 status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
355 status &= ~BCM43xx_SBF_TIME_UPDATE;
356 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status);
357}
358
359static
360void bcm43xx_macfilter_set(struct bcm43xx_private *bcm,
361 u16 offset,
362 const u8 *mac)
363{
364 u16 data;
365
366 offset |= 0x0020;
367 bcm43xx_write16(bcm, BCM43xx_MMIO_MACFILTER_CONTROL, offset);
368
369 data = mac[0];
370 data |= mac[1] << 8;
371 bcm43xx_write16(bcm, BCM43xx_MMIO_MACFILTER_DATA, data);
372 data = mac[2];
373 data |= mac[3] << 8;
374 bcm43xx_write16(bcm, BCM43xx_MMIO_MACFILTER_DATA, data);
375 data = mac[4];
376 data |= mac[5] << 8;
377 bcm43xx_write16(bcm, BCM43xx_MMIO_MACFILTER_DATA, data);
378}
379
380static void bcm43xx_macfilter_clear(struct bcm43xx_private *bcm,
381 u16 offset)
382{
383 const u8 zero_addr[ETH_ALEN] = { 0 };
384
385 bcm43xx_macfilter_set(bcm, offset, zero_addr);
386}
387
388static void bcm43xx_write_mac_bssid_templates(struct bcm43xx_private *bcm)
389{
390 const u8 *mac = (const u8 *)(bcm->net_dev->dev_addr);
391 const u8 *bssid = (const u8 *)(bcm->ieee->bssid);
392 u8 mac_bssid[ETH_ALEN * 2];
393 int i;
394
395 memcpy(mac_bssid, mac, ETH_ALEN);
396 memcpy(mac_bssid + ETH_ALEN, bssid, ETH_ALEN);
397
398 /* Write our MAC address and BSSID to template ram */
399 for (i = 0; i < ARRAY_SIZE(mac_bssid); i += sizeof(u32))
400 bcm43xx_ram_write(bcm, 0x20 + i, *((u32 *)(mac_bssid + i)));
401 for (i = 0; i < ARRAY_SIZE(mac_bssid); i += sizeof(u32))
402 bcm43xx_ram_write(bcm, 0x78 + i, *((u32 *)(mac_bssid + i)));
403 for (i = 0; i < ARRAY_SIZE(mac_bssid); i += sizeof(u32))
404 bcm43xx_ram_write(bcm, 0x478 + i, *((u32 *)(mac_bssid + i)));
405}
406
407//FIXME: Well, we should probably call them from somewhere.
408#if 0
409static void bcm43xx_set_slot_time(struct bcm43xx_private *bcm, u16 slot_time)
410{
411 /* slot_time is in usec. */
412 if (bcm43xx_current_phy(bcm)->type != BCM43xx_PHYTYPE_G)
413 return;
414 bcm43xx_write16(bcm, 0x684, 510 + slot_time);
415 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0010, slot_time);
416}
417
418static void bcm43xx_short_slot_timing_enable(struct bcm43xx_private *bcm)
419{
420 bcm43xx_set_slot_time(bcm, 9);
421}
422
423static void bcm43xx_short_slot_timing_disable(struct bcm43xx_private *bcm)
424{
425 bcm43xx_set_slot_time(bcm, 20);
426}
427#endif
428
429/* FIXME: To get the MAC-filter working, we need to implement the
430 * following functions (and rename them :)
431 */
432#if 0
433static void bcm43xx_disassociate(struct bcm43xx_private *bcm)
434{
435 bcm43xx_mac_suspend(bcm);
436 bcm43xx_macfilter_clear(bcm, BCM43xx_MACFILTER_ASSOC);
437
438 bcm43xx_ram_write(bcm, 0x0026, 0x0000);
439 bcm43xx_ram_write(bcm, 0x0028, 0x0000);
440 bcm43xx_ram_write(bcm, 0x007E, 0x0000);
441 bcm43xx_ram_write(bcm, 0x0080, 0x0000);
442 bcm43xx_ram_write(bcm, 0x047E, 0x0000);
443 bcm43xx_ram_write(bcm, 0x0480, 0x0000);
444
445 if (bcm->current_core->rev < 3) {
446 bcm43xx_write16(bcm, 0x0610, 0x8000);
447 bcm43xx_write16(bcm, 0x060E, 0x0000);
448 } else
449 bcm43xx_write32(bcm, 0x0188, 0x80000000);
450
451 bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0004, 0x000003ff);
452
453 if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_G &&
454 ieee80211_is_ofdm_rate(bcm->softmac->txrates.default_rate))
455 bcm43xx_short_slot_timing_enable(bcm);
456
457 bcm43xx_mac_enable(bcm);
458}
459
460static void bcm43xx_associate(struct bcm43xx_private *bcm,
461 const u8 *mac)
462{
463 memcpy(bcm->ieee->bssid, mac, ETH_ALEN);
464
465 bcm43xx_mac_suspend(bcm);
466 bcm43xx_macfilter_set(bcm, BCM43xx_MACFILTER_ASSOC, mac);
467 bcm43xx_write_mac_bssid_templates(bcm);
468 bcm43xx_mac_enable(bcm);
469}
470#endif
471
472/* Enable a Generic IRQ. "mask" is the mask of which IRQs to enable.
473 * Returns the _previously_ enabled IRQ mask.
474 */
475static inline u32 bcm43xx_interrupt_enable(struct bcm43xx_private *bcm, u32 mask)
476{
477 u32 old_mask;
478
479 old_mask = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK);
480 bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK, old_mask | mask);
481
482 return old_mask;
483}
484
485/* Disable a Generic IRQ. "mask" is the mask of which IRQs to disable.
486 * Returns the _previously_ enabled IRQ mask.
487 */
488static inline u32 bcm43xx_interrupt_disable(struct bcm43xx_private *bcm, u32 mask)
489{
490 u32 old_mask;
491
492 old_mask = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK);
493 bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK, old_mask & ~mask);
494
495 return old_mask;
496}
497
498/* Make sure we don't receive more data from the device. */
499static int bcm43xx_disable_interrupts_sync(struct bcm43xx_private *bcm, u32 *oldstate)
500{
501 u32 old;
502 unsigned long flags;
503
504 bcm43xx_lock_mmio(bcm, flags);
505 if (bcm43xx_is_initializing(bcm) || bcm->shutting_down) {
506 bcm43xx_unlock_mmio(bcm, flags);
507 return -EBUSY;
508 }
509 old = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
510 tasklet_disable(&bcm->isr_tasklet);
511 bcm43xx_unlock_mmio(bcm, flags);
512 if (oldstate)
513 *oldstate = old;
514
515 return 0;
516}
517
518static int bcm43xx_read_radioinfo(struct bcm43xx_private *bcm)
519{
520 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
521 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
522 u32 radio_id;
523 u16 manufact;
524 u16 version;
525 u8 revision;
526 s8 i;
527
528 if (bcm->chip_id == 0x4317) {
529 if (bcm->chip_rev == 0x00)
530 radio_id = 0x3205017F;
531 else if (bcm->chip_rev == 0x01)
532 radio_id = 0x4205017F;
533 else
534 radio_id = 0x5205017F;
535 } else {
536 bcm43xx_write16(bcm, BCM43xx_MMIO_RADIO_CONTROL, BCM43xx_RADIOCTL_ID);
537 radio_id = bcm43xx_read16(bcm, BCM43xx_MMIO_RADIO_DATA_HIGH);
538 radio_id <<= 16;
539 bcm43xx_write16(bcm, BCM43xx_MMIO_RADIO_CONTROL, BCM43xx_RADIOCTL_ID);
540 radio_id |= bcm43xx_read16(bcm, BCM43xx_MMIO_RADIO_DATA_LOW);
541 }
542
543 manufact = (radio_id & 0x00000FFF);
544 version = (radio_id & 0x0FFFF000) >> 12;
545 revision = (radio_id & 0xF0000000) >> 28;
546
547 dprintk(KERN_INFO PFX "Detected Radio: ID: %x (Manuf: %x Ver: %x Rev: %x)\n",
548 radio_id, manufact, version, revision);
549
550 switch (phy->type) {
551 case BCM43xx_PHYTYPE_A:
552 if ((version != 0x2060) || (revision != 1) || (manufact != 0x17f))
553 goto err_unsupported_radio;
554 break;
555 case BCM43xx_PHYTYPE_B:
556 if ((version & 0xFFF0) != 0x2050)
557 goto err_unsupported_radio;
558 break;
559 case BCM43xx_PHYTYPE_G:
560 if (version != 0x2050)
561 goto err_unsupported_radio;
562 break;
563 }
564
565 radio->manufact = manufact;
566 radio->version = version;
567 radio->revision = revision;
568
569 /* Set default attenuation values. */
570 radio->baseband_atten = bcm43xx_default_baseband_attenuation(bcm);
571 radio->radio_atten = bcm43xx_default_radio_attenuation(bcm);
572 radio->txctl1 = bcm43xx_default_txctl1(bcm);
573 radio->txctl2 = 0xFFFF;
574 if (phy->type == BCM43xx_PHYTYPE_A)
575 radio->txpower_desired = bcm->sprom.maxpower_aphy;
576 else
577 radio->txpower_desired = bcm->sprom.maxpower_bgphy;
578
579 /* Initialize the in-memory nrssi Lookup Table. */
580 for (i = 0; i < 64; i++)
581 radio->nrssi_lt[i] = i;
582
583 return 0;
584
585err_unsupported_radio:
586 printk(KERN_ERR PFX "Unsupported Radio connected to the PHY!\n");
587 return -ENODEV;
588}
589
590static const char * bcm43xx_locale_iso(u8 locale)
591{
592 /* ISO 3166-1 country codes.
593 * Note that there aren't ISO 3166-1 codes for
594 * all or locales. (Not all locales are countries)
595 */
596 switch (locale) {
597 case BCM43xx_LOCALE_WORLD:
598 case BCM43xx_LOCALE_ALL:
599 return "XX";
600 case BCM43xx_LOCALE_THAILAND:
601 return "TH";
602 case BCM43xx_LOCALE_ISRAEL:
603 return "IL";
604 case BCM43xx_LOCALE_JORDAN:
605 return "JO";
606 case BCM43xx_LOCALE_CHINA:
607 return "CN";
608 case BCM43xx_LOCALE_JAPAN:
609 case BCM43xx_LOCALE_JAPAN_HIGH:
610 return "JP";
611 case BCM43xx_LOCALE_USA_CANADA_ANZ:
612 case BCM43xx_LOCALE_USA_LOW:
613 return "US";
614 case BCM43xx_LOCALE_EUROPE:
615 return "EU";
616 case BCM43xx_LOCALE_NONE:
617 return " ";
618 }
619 assert(0);
620 return " ";
621}
622
623static const char * bcm43xx_locale_string(u8 locale)
624{
625 switch (locale) {
626 case BCM43xx_LOCALE_WORLD:
627 return "World";
628 case BCM43xx_LOCALE_THAILAND:
629 return "Thailand";
630 case BCM43xx_LOCALE_ISRAEL:
631 return "Israel";
632 case BCM43xx_LOCALE_JORDAN:
633 return "Jordan";
634 case BCM43xx_LOCALE_CHINA:
635 return "China";
636 case BCM43xx_LOCALE_JAPAN:
637 return "Japan";
638 case BCM43xx_LOCALE_USA_CANADA_ANZ:
639 return "USA/Canada/ANZ";
640 case BCM43xx_LOCALE_EUROPE:
641 return "Europe";
642 case BCM43xx_LOCALE_USA_LOW:
643 return "USAlow";
644 case BCM43xx_LOCALE_JAPAN_HIGH:
645 return "JapanHigh";
646 case BCM43xx_LOCALE_ALL:
647 return "All";
648 case BCM43xx_LOCALE_NONE:
649 return "None";
650 }
651 assert(0);
652 return "";
653}
654
655static inline u8 bcm43xx_crc8(u8 crc, u8 data)
656{
657 static const u8 t[] = {
658 0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B,
659 0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21,
660 0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF,
661 0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5,
662 0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14,
663 0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E,
664 0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80,
665 0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA,
666 0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95,
667 0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF,
668 0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01,
669 0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B,
670 0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA,
671 0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0,
672 0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E,
673 0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34,
674 0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0,
675 0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A,
676 0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54,
677 0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E,
678 0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF,
679 0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5,
680 0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B,
681 0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61,
682 0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E,
683 0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74,
684 0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA,
685 0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0,
686 0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41,
687 0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B,
688 0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5,
689 0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F,
690 };
691 return t[crc ^ data];
692}
693
694static u8 bcm43xx_sprom_crc(const u16 *sprom)
695{
696 int word;
697 u8 crc = 0xFF;
698
699 for (word = 0; word < BCM43xx_SPROM_SIZE - 1; word++) {
700 crc = bcm43xx_crc8(crc, sprom[word] & 0x00FF);
701 crc = bcm43xx_crc8(crc, (sprom[word] & 0xFF00) >> 8);
702 }
703 crc = bcm43xx_crc8(crc, sprom[BCM43xx_SPROM_VERSION] & 0x00FF);
704 crc ^= 0xFF;
705
706 return crc;
707}
708
709int bcm43xx_sprom_read(struct bcm43xx_private *bcm, u16 *sprom)
710{
711 int i;
712 u8 crc, expected_crc;
713
714 for (i = 0; i < BCM43xx_SPROM_SIZE; i++)
715 sprom[i] = bcm43xx_read16(bcm, BCM43xx_SPROM_BASE + (i * 2));
716 /* CRC-8 check. */
717 crc = bcm43xx_sprom_crc(sprom);
718 expected_crc = (sprom[BCM43xx_SPROM_VERSION] & 0xFF00) >> 8;
719 if (crc != expected_crc) {
720 printk(KERN_WARNING PFX "WARNING: Invalid SPROM checksum "
721 "(0x%02X, expected: 0x%02X)\n",
722 crc, expected_crc);
723 return -EINVAL;
724 }
725
726 return 0;
727}
728
729int bcm43xx_sprom_write(struct bcm43xx_private *bcm, const u16 *sprom)
730{
731 int i, err;
732 u8 crc, expected_crc;
733 u32 spromctl;
734
735 /* CRC-8 validation of the input data. */
736 crc = bcm43xx_sprom_crc(sprom);
737 expected_crc = (sprom[BCM43xx_SPROM_VERSION] & 0xFF00) >> 8;
738 if (crc != expected_crc) {
739 printk(KERN_ERR PFX "SPROM input data: Invalid CRC\n");
740 return -EINVAL;
741 }
742
743 printk(KERN_INFO PFX "Writing SPROM. Do NOT turn off the power! Please stand by...\n");
744 err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCICFG_SPROMCTL, &spromctl);
745 if (err)
746 goto err_ctlreg;
747 spromctl |= 0x10; /* SPROM WRITE enable. */
748 bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_SPROMCTL, spromctl);
749 if (err)
750 goto err_ctlreg;
751 /* We must burn lots of CPU cycles here, but that does not
752 * really matter as one does not write the SPROM every other minute...
753 */
754 printk(KERN_INFO PFX "[ 0%%");
755 mdelay(500);
756 for (i = 0; i < BCM43xx_SPROM_SIZE; i++) {
757 if (i == 16)
758 printk("25%%");
759 else if (i == 32)
760 printk("50%%");
761 else if (i == 48)
762 printk("75%%");
763 else if (i % 2)
764 printk(".");
765 bcm43xx_write16(bcm, BCM43xx_SPROM_BASE + (i * 2), sprom[i]);
766 mmiowb();
767 mdelay(20);
768 }
769 spromctl &= ~0x10; /* SPROM WRITE enable. */
770 bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_SPROMCTL, spromctl);
771 if (err)
772 goto err_ctlreg;
773 mdelay(500);
774 printk("100%% ]\n");
775 printk(KERN_INFO PFX "SPROM written.\n");
776 bcm43xx_controller_restart(bcm, "SPROM update");
777
778 return 0;
779err_ctlreg:
780 printk(KERN_ERR PFX "Could not access SPROM control register.\n");
781 return -ENODEV;
782}
783
784static int bcm43xx_sprom_extract(struct bcm43xx_private *bcm)
785{
786 u16 value;
787 u16 *sprom;
788#ifdef CONFIG_BCM947XX
789 char *c;
790#endif
791
792 sprom = kzalloc(BCM43xx_SPROM_SIZE * sizeof(u16),
793 GFP_KERNEL);
794 if (!sprom) {
795 printk(KERN_ERR PFX "sprom_extract OOM\n");
796 return -ENOMEM;
797 }
798#ifdef CONFIG_BCM947XX
799 sprom[BCM43xx_SPROM_BOARDFLAGS2] = atoi(nvram_get("boardflags2"));
800 sprom[BCM43xx_SPROM_BOARDFLAGS] = atoi(nvram_get("boardflags"));
801
802 if ((c = nvram_get("il0macaddr")) != NULL)
803 e_aton(c, (char *) &(sprom[BCM43xx_SPROM_IL0MACADDR]));
804
805 if ((c = nvram_get("et1macaddr")) != NULL)
806 e_aton(c, (char *) &(sprom[BCM43xx_SPROM_ET1MACADDR]));
807
808 sprom[BCM43xx_SPROM_PA0B0] = atoi(nvram_get("pa0b0"));
809 sprom[BCM43xx_SPROM_PA0B1] = atoi(nvram_get("pa0b1"));
810 sprom[BCM43xx_SPROM_PA0B2] = atoi(nvram_get("pa0b2"));
811
812 sprom[BCM43xx_SPROM_PA1B0] = atoi(nvram_get("pa1b0"));
813 sprom[BCM43xx_SPROM_PA1B1] = atoi(nvram_get("pa1b1"));
814 sprom[BCM43xx_SPROM_PA1B2] = atoi(nvram_get("pa1b2"));
815
816 sprom[BCM43xx_SPROM_BOARDREV] = atoi(nvram_get("boardrev"));
817#else
818 bcm43xx_sprom_read(bcm, sprom);
819#endif
820
821 /* boardflags2 */
822 value = sprom[BCM43xx_SPROM_BOARDFLAGS2];
823 bcm->sprom.boardflags2 = value;
824
825 /* il0macaddr */
826 value = sprom[BCM43xx_SPROM_IL0MACADDR + 0];
827 *(((u16 *)bcm->sprom.il0macaddr) + 0) = cpu_to_be16(value);
828 value = sprom[BCM43xx_SPROM_IL0MACADDR + 1];
829 *(((u16 *)bcm->sprom.il0macaddr) + 1) = cpu_to_be16(value);
830 value = sprom[BCM43xx_SPROM_IL0MACADDR + 2];
831 *(((u16 *)bcm->sprom.il0macaddr) + 2) = cpu_to_be16(value);
832
833 /* et0macaddr */
834 value = sprom[BCM43xx_SPROM_ET0MACADDR + 0];
835 *(((u16 *)bcm->sprom.et0macaddr) + 0) = cpu_to_be16(value);
836 value = sprom[BCM43xx_SPROM_ET0MACADDR + 1];
837 *(((u16 *)bcm->sprom.et0macaddr) + 1) = cpu_to_be16(value);
838 value = sprom[BCM43xx_SPROM_ET0MACADDR + 2];
839 *(((u16 *)bcm->sprom.et0macaddr) + 2) = cpu_to_be16(value);
840
841 /* et1macaddr */
842 value = sprom[BCM43xx_SPROM_ET1MACADDR + 0];
843 *(((u16 *)bcm->sprom.et1macaddr) + 0) = cpu_to_be16(value);
844 value = sprom[BCM43xx_SPROM_ET1MACADDR + 1];
845 *(((u16 *)bcm->sprom.et1macaddr) + 1) = cpu_to_be16(value);
846 value = sprom[BCM43xx_SPROM_ET1MACADDR + 2];
847 *(((u16 *)bcm->sprom.et1macaddr) + 2) = cpu_to_be16(value);
848
849 /* ethernet phy settings */
850 value = sprom[BCM43xx_SPROM_ETHPHY];
851 bcm->sprom.et0phyaddr = (value & 0x001F);
852 bcm->sprom.et1phyaddr = (value & 0x03E0) >> 5;
853 bcm->sprom.et0mdcport = (value & (1 << 14)) >> 14;
854 bcm->sprom.et1mdcport = (value & (1 << 15)) >> 15;
855
856 /* boardrev, antennas, locale */
857 value = sprom[BCM43xx_SPROM_BOARDREV];
858 bcm->sprom.boardrev = (value & 0x00FF);
859 bcm->sprom.locale = (value & 0x0F00) >> 8;
860 bcm->sprom.antennas_aphy = (value & 0x3000) >> 12;
861 bcm->sprom.antennas_bgphy = (value & 0xC000) >> 14;
862 if (modparam_locale != -1) {
863 if (modparam_locale >= 0 && modparam_locale <= 11) {
864 bcm->sprom.locale = modparam_locale;
865 printk(KERN_WARNING PFX "Operating with modified "
866 "LocaleCode %u (%s)\n",
867 bcm->sprom.locale,
868 bcm43xx_locale_string(bcm->sprom.locale));
869 } else {
870 printk(KERN_WARNING PFX "Module parameter \"locale\" "
871 "invalid value. (0 - 11)\n");
872 }
873 }
874
875 /* pa0b* */
876 value = sprom[BCM43xx_SPROM_PA0B0];
877 bcm->sprom.pa0b0 = value;
878 value = sprom[BCM43xx_SPROM_PA0B1];
879 bcm->sprom.pa0b1 = value;
880 value = sprom[BCM43xx_SPROM_PA0B2];
881 bcm->sprom.pa0b2 = value;
882
883 /* wl0gpio* */
884 value = sprom[BCM43xx_SPROM_WL0GPIO0];
885 if (value == 0x0000)
886 value = 0xFFFF;
887 bcm->sprom.wl0gpio0 = value & 0x00FF;
888 bcm->sprom.wl0gpio1 = (value & 0xFF00) >> 8;
889 value = sprom[BCM43xx_SPROM_WL0GPIO2];
890 if (value == 0x0000)
891 value = 0xFFFF;
892 bcm->sprom.wl0gpio2 = value & 0x00FF;
893 bcm->sprom.wl0gpio3 = (value & 0xFF00) >> 8;
894
895 /* maxpower */
896 value = sprom[BCM43xx_SPROM_MAXPWR];
897 bcm->sprom.maxpower_aphy = (value & 0xFF00) >> 8;
898 bcm->sprom.maxpower_bgphy = value & 0x00FF;
899
900 /* pa1b* */
901 value = sprom[BCM43xx_SPROM_PA1B0];
902 bcm->sprom.pa1b0 = value;
903 value = sprom[BCM43xx_SPROM_PA1B1];
904 bcm->sprom.pa1b1 = value;
905 value = sprom[BCM43xx_SPROM_PA1B2];
906 bcm->sprom.pa1b2 = value;
907
908 /* idle tssi target */
909 value = sprom[BCM43xx_SPROM_IDL_TSSI_TGT];
910 bcm->sprom.idle_tssi_tgt_aphy = value & 0x00FF;
911 bcm->sprom.idle_tssi_tgt_bgphy = (value & 0xFF00) >> 8;
912
913 /* boardflags */
914 value = sprom[BCM43xx_SPROM_BOARDFLAGS];
915 if (value == 0xFFFF)
916 value = 0x0000;
917 bcm->sprom.boardflags = value;
918 /* boardflags workarounds */
919 if (bcm->board_vendor == PCI_VENDOR_ID_DELL &&
920 bcm->chip_id == 0x4301 &&
921 bcm->board_revision == 0x74)
922 bcm->sprom.boardflags |= BCM43xx_BFL_BTCOEXIST;
923 if (bcm->board_vendor == PCI_VENDOR_ID_APPLE &&
924 bcm->board_type == 0x4E &&
925 bcm->board_revision > 0x40)
926 bcm->sprom.boardflags |= BCM43xx_BFL_PACTRL;
927
928 /* antenna gain */
929 value = sprom[BCM43xx_SPROM_ANTENNA_GAIN];
930 if (value == 0x0000 || value == 0xFFFF)
931 value = 0x0202;
932 /* convert values to Q5.2 */
933 bcm->sprom.antennagain_aphy = ((value & 0xFF00) >> 8) * 4;
934 bcm->sprom.antennagain_bgphy = (value & 0x00FF) * 4;
935
936 kfree(sprom);
937
938 return 0;
939}
940
941static void bcm43xx_geo_init(struct bcm43xx_private *bcm)
942{
943 struct ieee80211_geo geo;
944 struct ieee80211_channel *chan;
945 int have_a = 0, have_bg = 0;
946 int i;
947 u8 channel;
948 struct bcm43xx_phyinfo *phy;
949 const char *iso_country;
950
951 memset(&geo, 0, sizeof(geo));
952 for (i = 0; i < bcm->nr_80211_available; i++) {
953 phy = &(bcm->core_80211_ext[i].phy);
954 switch (phy->type) {
955 case BCM43xx_PHYTYPE_B:
956 case BCM43xx_PHYTYPE_G:
957 have_bg = 1;
958 break;
959 case BCM43xx_PHYTYPE_A:
960 have_a = 1;
961 break;
962 default:
963 assert(0);
964 }
965 }
966 iso_country = bcm43xx_locale_iso(bcm->sprom.locale);
967
968 if (have_a) {
969 for (i = 0, channel = 0; channel < 201; channel++) {
970 chan = &geo.a[i++];
971 chan->freq = bcm43xx_channel_to_freq_a(channel);
972 chan->channel = channel;
973 }
974 geo.a_channels = i;
975 }
976 if (have_bg) {
977 for (i = 0, channel = 1; channel < 15; channel++) {
978 chan = &geo.bg[i++];
979 chan->freq = bcm43xx_channel_to_freq_bg(channel);
980 chan->channel = channel;
981 }
982 geo.bg_channels = i;
983 }
984 memcpy(geo.name, iso_country, 2);
985 if (0 /*TODO: Outdoor use only */)
986 geo.name[2] = 'O';
987 else if (0 /*TODO: Indoor use only */)
988 geo.name[2] = 'I';
989 else
990 geo.name[2] = ' ';
991 geo.name[3] = '\0';
992
993 ieee80211_set_geo(bcm->ieee, &geo);
994}
995
996/* DummyTransmission function, as documented on
997 * http://bcm-specs.sipsolutions.net/DummyTransmission
998 */
999void bcm43xx_dummy_transmission(struct bcm43xx_private *bcm)
1000{
1001 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
1002 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
1003 unsigned int i, max_loop;
1004 u16 value = 0;
1005 u32 buffer[5] = {
1006 0x00000000,
1007 0x0000D400,
1008 0x00000000,
1009 0x00000001,
1010 0x00000000,
1011 };
1012
1013 switch (phy->type) {
1014 case BCM43xx_PHYTYPE_A:
1015 max_loop = 0x1E;
1016 buffer[0] = 0xCC010200;
1017 break;
1018 case BCM43xx_PHYTYPE_B:
1019 case BCM43xx_PHYTYPE_G:
1020 max_loop = 0xFA;
1021 buffer[0] = 0x6E840B00;
1022 break;
1023 default:
1024 assert(0);
1025 return;
1026 }
1027
1028 for (i = 0; i < 5; i++)
1029 bcm43xx_ram_write(bcm, i * 4, buffer[i]);
1030
1031 bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* dummy read */
1032
1033 bcm43xx_write16(bcm, 0x0568, 0x0000);
1034 bcm43xx_write16(bcm, 0x07C0, 0x0000);
1035 bcm43xx_write16(bcm, 0x050C, ((phy->type == BCM43xx_PHYTYPE_A) ? 1 : 0));
1036 bcm43xx_write16(bcm, 0x0508, 0x0000);
1037 bcm43xx_write16(bcm, 0x050A, 0x0000);
1038 bcm43xx_write16(bcm, 0x054C, 0x0000);
1039 bcm43xx_write16(bcm, 0x056A, 0x0014);
1040 bcm43xx_write16(bcm, 0x0568, 0x0826);
1041 bcm43xx_write16(bcm, 0x0500, 0x0000);
1042 bcm43xx_write16(bcm, 0x0502, 0x0030);
1043
1044 if (radio->version == 0x2050 && radio->revision <= 0x5)
1045 bcm43xx_radio_write16(bcm, 0x0051, 0x0017);
1046 for (i = 0x00; i < max_loop; i++) {
1047 value = bcm43xx_read16(bcm, 0x050E);
1048 if (value & 0x0080)
1049 break;
1050 udelay(10);
1051 }
1052 for (i = 0x00; i < 0x0A; i++) {
1053 value = bcm43xx_read16(bcm, 0x050E);
1054 if (value & 0x0400)
1055 break;
1056 udelay(10);
1057 }
1058 for (i = 0x00; i < 0x0A; i++) {
1059 value = bcm43xx_read16(bcm, 0x0690);
1060 if (!(value & 0x0100))
1061 break;
1062 udelay(10);
1063 }
1064 if (radio->version == 0x2050 && radio->revision <= 0x5)
1065 bcm43xx_radio_write16(bcm, 0x0051, 0x0037);
1066}
1067
1068static void key_write(struct bcm43xx_private *bcm,
1069 u8 index, u8 algorithm, const u16 *key)
1070{
1071 unsigned int i, basic_wep = 0;
1072 u32 offset;
1073 u16 value;
1074
1075 /* Write associated key information */
1076 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x100 + (index * 2),
1077 ((index << 4) | (algorithm & 0x0F)));
1078
1079 /* The first 4 WEP keys need extra love */
1080 if (((algorithm == BCM43xx_SEC_ALGO_WEP) ||
1081 (algorithm == BCM43xx_SEC_ALGO_WEP104)) && (index < 4))
1082 basic_wep = 1;
1083
1084 /* Write key payload, 8 little endian words */
1085 offset = bcm->security_offset + (index * BCM43xx_SEC_KEYSIZE);
1086 for (i = 0; i < (BCM43xx_SEC_KEYSIZE / sizeof(u16)); i++) {
1087 value = cpu_to_le16(key[i]);
1088 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED,
1089 offset + (i * 2), value);
1090
1091 if (!basic_wep)
1092 continue;
1093
1094 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED,
1095 offset + (i * 2) + 4 * BCM43xx_SEC_KEYSIZE,
1096 value);
1097 }
1098}
1099
1100static void keymac_write(struct bcm43xx_private *bcm,
1101 u8 index, const u32 *addr)
1102{
1103 /* for keys 0-3 there is no associated mac address */
1104 if (index < 4)
1105 return;
1106
1107 index -= 4;
1108 if (bcm->current_core->rev >= 5) {
1109 bcm43xx_shm_write32(bcm,
1110 BCM43xx_SHM_HWMAC,
1111 index * 2,
1112 cpu_to_be32(*addr));
1113 bcm43xx_shm_write16(bcm,
1114 BCM43xx_SHM_HWMAC,
1115 (index * 2) + 1,
1116 cpu_to_be16(*((u16 *)(addr + 1))));
1117 } else {
1118 if (index < 8) {
1119 TODO(); /* Put them in the macaddress filter */
1120 } else {
1121 TODO();
1122 /* Put them BCM43xx_SHM_SHARED, stating index 0x0120.
1123 Keep in mind to update the count of keymacs in 0x003E as well! */
1124 }
1125 }
1126}
1127
1128static int bcm43xx_key_write(struct bcm43xx_private *bcm,
1129 u8 index, u8 algorithm,
1130 const u8 *_key, int key_len,
1131 const u8 *mac_addr)
1132{
1133 u8 key[BCM43xx_SEC_KEYSIZE] = { 0 };
1134
1135 if (index >= ARRAY_SIZE(bcm->key))
1136 return -EINVAL;
1137 if (key_len > ARRAY_SIZE(key))
1138 return -EINVAL;
1139 if (algorithm < 1 || algorithm > 5)
1140 return -EINVAL;
1141
1142 memcpy(key, _key, key_len);
1143 key_write(bcm, index, algorithm, (const u16 *)key);
1144 keymac_write(bcm, index, (const u32 *)mac_addr);
1145
1146 bcm->key[index].algorithm = algorithm;
1147
1148 return 0;
1149}
1150
1151static void bcm43xx_clear_keys(struct bcm43xx_private *bcm)
1152{
1153 static const u32 zero_mac[2] = { 0 };
1154 unsigned int i,j, nr_keys = 54;
1155 u16 offset;
1156
1157 if (bcm->current_core->rev < 5)
1158 nr_keys = 16;
1159 assert(nr_keys <= ARRAY_SIZE(bcm->key));
1160
1161 for (i = 0; i < nr_keys; i++) {
1162 bcm->key[i].enabled = 0;
1163 /* returns for i < 4 immediately */
1164 keymac_write(bcm, i, zero_mac);
1165 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED,
1166 0x100 + (i * 2), 0x0000);
1167 for (j = 0; j < 8; j++) {
1168 offset = bcm->security_offset + (j * 4) + (i * BCM43xx_SEC_KEYSIZE);
1169 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED,
1170 offset, 0x0000);
1171 }
1172 }
1173 dprintk(KERN_INFO PFX "Keys cleared\n");
1174}
1175
1176/* Lowlevel core-switch function. This is only to be used in
1177 * bcm43xx_switch_core() and bcm43xx_probe_cores()
1178 */
1179static int _switch_core(struct bcm43xx_private *bcm, int core)
1180{
1181 int err;
1182 int attempts = 0;
1183 u32 current_core;
1184
1185 assert(core >= 0);
1186 while (1) {
1187 err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_ACTIVE_CORE,
1188 (core * 0x1000) + 0x18000000);
1189 if (unlikely(err))
1190 goto error;
1191 err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCICFG_ACTIVE_CORE,
1192 &current_core);
1193 if (unlikely(err))
1194 goto error;
1195 current_core = (current_core - 0x18000000) / 0x1000;
1196 if (current_core == core)
1197 break;
1198
1199 if (unlikely(attempts++ > BCM43xx_SWITCH_CORE_MAX_RETRIES))
1200 goto error;
1201 udelay(10);
1202 }
1203#ifdef CONFIG_BCM947XX
1204 if (bcm->pci_dev->bus->number == 0)
1205 bcm->current_core_offset = 0x1000 * core;
1206 else
1207 bcm->current_core_offset = 0;
1208#endif
1209
1210 return 0;
1211error:
1212 printk(KERN_ERR PFX "Failed to switch to core %d\n", core);
1213 return -ENODEV;
1214}
1215
1216int bcm43xx_switch_core(struct bcm43xx_private *bcm, struct bcm43xx_coreinfo *new_core)
1217{
1218 int err;
1219
1220 if (unlikely(!new_core))
1221 return 0;
1222 if (!new_core->available)
1223 return -ENODEV;
1224 if (bcm->current_core == new_core)
1225 return 0;
1226 err = _switch_core(bcm, new_core->index);
1227 if (unlikely(err))
1228 goto out;
1229
1230 bcm->current_core = new_core;
1231 bcm->current_80211_core_idx = -1;
1232 if (new_core->id == BCM43xx_COREID_80211)
1233 bcm->current_80211_core_idx = (int)(new_core - &(bcm->core_80211[0]));
1234
1235out:
1236 return err;
1237}
1238
1239static int bcm43xx_core_enabled(struct bcm43xx_private *bcm)
1240{
1241 u32 value;
1242
1243 value = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
1244 value &= BCM43xx_SBTMSTATELOW_CLOCK | BCM43xx_SBTMSTATELOW_RESET
1245 | BCM43xx_SBTMSTATELOW_REJECT;
1246
1247 return (value == BCM43xx_SBTMSTATELOW_CLOCK);
1248}
1249
1250/* disable current core */
1251static int bcm43xx_core_disable(struct bcm43xx_private *bcm, u32 core_flags)
1252{
1253 u32 sbtmstatelow;
1254 u32 sbtmstatehigh;
1255 int i;
1256
1257 /* fetch sbtmstatelow from core information registers */
1258 sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
1259
1260 /* core is already in reset */
1261 if (sbtmstatelow & BCM43xx_SBTMSTATELOW_RESET)
1262 goto out;
1263
1264 if (sbtmstatelow & BCM43xx_SBTMSTATELOW_CLOCK) {
1265 sbtmstatelow = BCM43xx_SBTMSTATELOW_CLOCK |
1266 BCM43xx_SBTMSTATELOW_REJECT;
1267 bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
1268
1269 for (i = 0; i < 1000; i++) {
1270 sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
1271 if (sbtmstatelow & BCM43xx_SBTMSTATELOW_REJECT) {
1272 i = -1;
1273 break;
1274 }
1275 udelay(10);
1276 }
1277 if (i != -1) {
1278 printk(KERN_ERR PFX "Error: core_disable() REJECT timeout!\n");
1279 return -EBUSY;
1280 }
1281
1282 for (i = 0; i < 1000; i++) {
1283 sbtmstatehigh = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH);
1284 if (!(sbtmstatehigh & BCM43xx_SBTMSTATEHIGH_BUSY)) {
1285 i = -1;
1286 break;
1287 }
1288 udelay(10);
1289 }
1290 if (i != -1) {
1291 printk(KERN_ERR PFX "Error: core_disable() BUSY timeout!\n");
1292 return -EBUSY;
1293 }
1294
1295 sbtmstatelow = BCM43xx_SBTMSTATELOW_FORCE_GATE_CLOCK |
1296 BCM43xx_SBTMSTATELOW_REJECT |
1297 BCM43xx_SBTMSTATELOW_RESET |
1298 BCM43xx_SBTMSTATELOW_CLOCK |
1299 core_flags;
1300 bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
1301 udelay(10);
1302 }
1303
1304 sbtmstatelow = BCM43xx_SBTMSTATELOW_RESET |
1305 BCM43xx_SBTMSTATELOW_REJECT |
1306 core_flags;
1307 bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
1308
1309out:
1310 bcm->current_core->enabled = 0;
1311
1312 return 0;
1313}
1314
1315/* enable (reset) current core */
1316static int bcm43xx_core_enable(struct bcm43xx_private *bcm, u32 core_flags)
1317{
1318 u32 sbtmstatelow;
1319 u32 sbtmstatehigh;
1320 u32 sbimstate;
1321 int err;
1322
1323 err = bcm43xx_core_disable(bcm, core_flags);
1324 if (err)
1325 goto out;
1326
1327 sbtmstatelow = BCM43xx_SBTMSTATELOW_CLOCK |
1328 BCM43xx_SBTMSTATELOW_RESET |
1329 BCM43xx_SBTMSTATELOW_FORCE_GATE_CLOCK |
1330 core_flags;
1331 bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
1332 udelay(1);
1333
1334 sbtmstatehigh = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH);
1335 if (sbtmstatehigh & BCM43xx_SBTMSTATEHIGH_SERROR) {
1336 sbtmstatehigh = 0x00000000;
1337 bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATEHIGH, sbtmstatehigh);
1338 }
1339
1340 sbimstate = bcm43xx_read32(bcm, BCM43xx_CIR_SBIMSTATE);
1341 if (sbimstate & (BCM43xx_SBIMSTATE_IB_ERROR | BCM43xx_SBIMSTATE_TIMEOUT)) {
1342 sbimstate &= ~(BCM43xx_SBIMSTATE_IB_ERROR | BCM43xx_SBIMSTATE_TIMEOUT);
1343 bcm43xx_write32(bcm, BCM43xx_CIR_SBIMSTATE, sbimstate);
1344 }
1345
1346 sbtmstatelow = BCM43xx_SBTMSTATELOW_CLOCK |
1347 BCM43xx_SBTMSTATELOW_FORCE_GATE_CLOCK |
1348 core_flags;
1349 bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
1350 udelay(1);
1351
1352 sbtmstatelow = BCM43xx_SBTMSTATELOW_CLOCK | core_flags;
1353 bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
1354 udelay(1);
1355
1356 bcm->current_core->enabled = 1;
1357 assert(err == 0);
1358out:
1359 return err;
1360}
1361
1362/* http://bcm-specs.sipsolutions.net/80211CoreReset */
1363void bcm43xx_wireless_core_reset(struct bcm43xx_private *bcm, int connect_phy)
1364{
1365 u32 flags = 0x00040000;
1366
1367 if ((bcm43xx_core_enabled(bcm)) &&
1368 !bcm43xx_using_pio(bcm)) {
1369//FIXME: Do we _really_ want #ifndef CONFIG_BCM947XX here?
1370#ifndef CONFIG_BCM947XX
1371 /* reset all used DMA controllers. */
1372 bcm43xx_dmacontroller_tx_reset(bcm, BCM43xx_MMIO_DMA1_BASE);
1373 bcm43xx_dmacontroller_tx_reset(bcm, BCM43xx_MMIO_DMA2_BASE);
1374 bcm43xx_dmacontroller_tx_reset(bcm, BCM43xx_MMIO_DMA3_BASE);
1375 bcm43xx_dmacontroller_tx_reset(bcm, BCM43xx_MMIO_DMA4_BASE);
1376 bcm43xx_dmacontroller_rx_reset(bcm, BCM43xx_MMIO_DMA1_BASE);
1377 if (bcm->current_core->rev < 5)
1378 bcm43xx_dmacontroller_rx_reset(bcm, BCM43xx_MMIO_DMA4_BASE);
1379#endif
1380 }
1381 if (bcm->shutting_down) {
1382 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
1383 bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD)
1384 & ~(BCM43xx_SBF_MAC_ENABLED | 0x00000002));
1385 } else {
1386 if (connect_phy)
1387 flags |= 0x20000000;
1388 bcm43xx_phy_connect(bcm, connect_phy);
1389 bcm43xx_core_enable(bcm, flags);
1390 bcm43xx_write16(bcm, 0x03E6, 0x0000);
1391 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
1392 bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD)
1393 | BCM43xx_SBF_400);
1394 }
1395}
1396
1397static void bcm43xx_wireless_core_disable(struct bcm43xx_private *bcm)
1398{
1399 bcm43xx_radio_turn_off(bcm);
1400 bcm43xx_write16(bcm, 0x03E6, 0x00F4);
1401 bcm43xx_core_disable(bcm, 0);
1402}
1403
1404/* Mark the current 80211 core inactive.
1405 * "active_80211_core" is the other 80211 core, which is used.
1406 */
1407static int bcm43xx_wireless_core_mark_inactive(struct bcm43xx_private *bcm,
1408 struct bcm43xx_coreinfo *active_80211_core)
1409{
1410 u32 sbtmstatelow;
1411 struct bcm43xx_coreinfo *old_core;
1412 int err = 0;
1413
1414 bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
1415 bcm43xx_radio_turn_off(bcm);
1416 sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
1417 sbtmstatelow &= ~0x200a0000;
1418 sbtmstatelow |= 0xa0000;
1419 bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
1420 udelay(1);
1421 sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
1422 sbtmstatelow &= ~0xa0000;
1423 sbtmstatelow |= 0x80000;
1424 bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
1425 udelay(1);
1426
1427 if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_G) {
1428 old_core = bcm->current_core;
1429 err = bcm43xx_switch_core(bcm, active_80211_core);
1430 if (err)
1431 goto out;
1432 sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
1433 sbtmstatelow &= ~0x20000000;
1434 sbtmstatelow |= 0x20000000;
1435 bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
1436 err = bcm43xx_switch_core(bcm, old_core);
1437 }
1438
1439out:
1440 return err;
1441}
1442
1443static void handle_irq_transmit_status(struct bcm43xx_private *bcm)
1444{
1445 u32 v0, v1;
1446 u16 tmp;
1447 struct bcm43xx_xmitstatus stat;
1448
1449 while (1) {
1450 v0 = bcm43xx_read32(bcm, BCM43xx_MMIO_XMITSTAT_0);
1451 if (!v0)
1452 break;
1453 v1 = bcm43xx_read32(bcm, BCM43xx_MMIO_XMITSTAT_1);
1454
1455 stat.cookie = (v0 >> 16) & 0x0000FFFF;
1456 tmp = (u16)((v0 & 0xFFF0) | ((v0 & 0xF) >> 1));
1457 stat.flags = tmp & 0xFF;
1458 stat.cnt1 = (tmp & 0x0F00) >> 8;
1459 stat.cnt2 = (tmp & 0xF000) >> 12;
1460 stat.seq = (u16)(v1 & 0xFFFF);
1461 stat.unknown = (u16)((v1 >> 16) & 0xFF);
1462
1463 bcm43xx_debugfs_log_txstat(bcm, &stat);
1464
1465 if (stat.flags & BCM43xx_TXSTAT_FLAG_IGNORE)
1466 continue;
1467 if (!(stat.flags & BCM43xx_TXSTAT_FLAG_ACK)) {
1468 //TODO: packet was not acked (was lost)
1469 }
1470 //TODO: There are more (unknown) flags to test. see bcm43xx_main.h
1471
1472 if (bcm43xx_using_pio(bcm))
1473 bcm43xx_pio_handle_xmitstatus(bcm, &stat);
1474 else
1475 bcm43xx_dma_handle_xmitstatus(bcm, &stat);
1476 }
1477}
1478
1479static void bcm43xx_generate_noise_sample(struct bcm43xx_private *bcm)
1480{
1481 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x408, 0x7F7F);
1482 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x40A, 0x7F7F);
1483 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD,
1484 bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD) | (1 << 4));
1485 assert(bcm->noisecalc.core_at_start == bcm->current_core);
1486 assert(bcm->noisecalc.channel_at_start == bcm43xx_current_radio(bcm)->channel);
1487}
1488
1489static void bcm43xx_calculate_link_quality(struct bcm43xx_private *bcm)
1490{
1491 /* Top half of Link Quality calculation. */
1492
1493 if (bcm->noisecalc.calculation_running)
1494 return;
1495 bcm->noisecalc.core_at_start = bcm->current_core;
1496 bcm->noisecalc.channel_at_start = bcm43xx_current_radio(bcm)->channel;
1497 bcm->noisecalc.calculation_running = 1;
1498 bcm->noisecalc.nr_samples = 0;
1499
1500 bcm43xx_generate_noise_sample(bcm);
1501}
1502
1503static void handle_irq_noise(struct bcm43xx_private *bcm)
1504{
1505 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
1506 u16 tmp;
1507 u8 noise[4];
1508 u8 i, j;
1509 s32 average;
1510
1511 /* Bottom half of Link Quality calculation. */
1512
1513 assert(bcm->noisecalc.calculation_running);
1514 if (bcm->noisecalc.core_at_start != bcm->current_core ||
1515 bcm->noisecalc.channel_at_start != radio->channel)
1516 goto drop_calculation;
1517 tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x408);
1518 noise[0] = (tmp & 0x00FF);
1519 noise[1] = (tmp & 0xFF00) >> 8;
1520 tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x40A);
1521 noise[2] = (tmp & 0x00FF);
1522 noise[3] = (tmp & 0xFF00) >> 8;
1523 if (noise[0] == 0x7F || noise[1] == 0x7F ||
1524 noise[2] == 0x7F || noise[3] == 0x7F)
1525 goto generate_new;
1526
1527 /* Get the noise samples. */
1528 assert(bcm->noisecalc.nr_samples <= 8);
1529 i = bcm->noisecalc.nr_samples;
1530 noise[0] = limit_value(noise[0], 0, ARRAY_SIZE(radio->nrssi_lt) - 1);
1531 noise[1] = limit_value(noise[1], 0, ARRAY_SIZE(radio->nrssi_lt) - 1);
1532 noise[2] = limit_value(noise[2], 0, ARRAY_SIZE(radio->nrssi_lt) - 1);
1533 noise[3] = limit_value(noise[3], 0, ARRAY_SIZE(radio->nrssi_lt) - 1);
1534 bcm->noisecalc.samples[i][0] = radio->nrssi_lt[noise[0]];
1535 bcm->noisecalc.samples[i][1] = radio->nrssi_lt[noise[1]];
1536 bcm->noisecalc.samples[i][2] = radio->nrssi_lt[noise[2]];
1537 bcm->noisecalc.samples[i][3] = radio->nrssi_lt[noise[3]];
1538 bcm->noisecalc.nr_samples++;
1539 if (bcm->noisecalc.nr_samples == 8) {
1540 /* Calculate the Link Quality by the noise samples. */
1541 average = 0;
1542 for (i = 0; i < 8; i++) {
1543 for (j = 0; j < 4; j++)
1544 average += bcm->noisecalc.samples[i][j];
1545 }
1546 average /= (8 * 4);
1547 average *= 125;
1548 average += 64;
1549 average /= 128;
1550
1551 tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x40C);
1552 tmp = (tmp / 128) & 0x1F;
1553 if (tmp >= 8)
1554 average += 2;
1555 else
1556 average -= 25;
1557 if (tmp == 8)
1558 average -= 72;
1559 else
1560 average -= 48;
1561
1562/* FIXME: This is wrong, but people want fancy stats. well... */
1563bcm->stats.noise = average;
1564 if (average > -65)
1565 bcm->stats.link_quality = 0;
1566 else if (average > -75)
1567 bcm->stats.link_quality = 1;
1568 else if (average > -85)
1569 bcm->stats.link_quality = 2;
1570 else
1571 bcm->stats.link_quality = 3;
1572// dprintk(KERN_INFO PFX "Link Quality: %u (avg was %d)\n", bcm->stats.link_quality, average);
1573drop_calculation:
1574 bcm->noisecalc.calculation_running = 0;
1575 return;
1576 }
1577generate_new:
1578 bcm43xx_generate_noise_sample(bcm);
1579}
1580
1581static void handle_irq_ps(struct bcm43xx_private *bcm)
1582{
1583 if (bcm->ieee->iw_mode == IW_MODE_MASTER) {
1584 ///TODO: PS TBTT
1585 } else {
1586 if (1/*FIXME: the last PSpoll frame was sent successfully */)
1587 bcm43xx_power_saving_ctl_bits(bcm, -1, -1);
1588 }
1589 if (bcm->ieee->iw_mode == IW_MODE_ADHOC)
1590 bcm->reg124_set_0x4 = 1;
1591 //FIXME else set to false?
1592}
1593
1594static void handle_irq_reg124(struct bcm43xx_private *bcm)
1595{
1596 if (!bcm->reg124_set_0x4)
1597 return;
1598 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD,
1599 bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD)
1600 | 0x4);
1601 //FIXME: reset reg124_set_0x4 to false?
1602}
1603
1604static void handle_irq_pmq(struct bcm43xx_private *bcm)
1605{
1606 u32 tmp;
1607
1608 //TODO: AP mode.
1609
1610 while (1) {
1611 tmp = bcm43xx_read32(bcm, BCM43xx_MMIO_PS_STATUS);
1612 if (!(tmp & 0x00000008))
1613 break;
1614 }
1615 /* 16bit write is odd, but correct. */
1616 bcm43xx_write16(bcm, BCM43xx_MMIO_PS_STATUS, 0x0002);
1617}
1618
1619static void bcm43xx_generate_beacon_template(struct bcm43xx_private *bcm,
1620 u16 ram_offset, u16 shm_size_offset)
1621{
1622 u32 value;
1623 u16 size = 0;
1624
1625 /* Timestamp. */
1626 //FIXME: assumption: The chip sets the timestamp
1627 value = 0;
1628 bcm43xx_ram_write(bcm, ram_offset++, value);
1629 bcm43xx_ram_write(bcm, ram_offset++, value);
1630 size += 8;
1631
1632 /* Beacon Interval / Capability Information */
1633 value = 0x0000;//FIXME: Which interval?
1634 value |= (1 << 0) << 16; /* ESS */
1635 value |= (1 << 2) << 16; /* CF Pollable */ //FIXME?
1636 value |= (1 << 3) << 16; /* CF Poll Request */ //FIXME?
1637 if (!bcm->ieee->open_wep)
1638 value |= (1 << 4) << 16; /* Privacy */
1639 bcm43xx_ram_write(bcm, ram_offset++, value);
1640 size += 4;
1641
1642 /* SSID */
1643 //TODO
1644
1645 /* FH Parameter Set */
1646 //TODO
1647
1648 /* DS Parameter Set */
1649 //TODO
1650
1651 /* CF Parameter Set */
1652 //TODO
1653
1654 /* TIM */
1655 //TODO
1656
1657 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, shm_size_offset, size);
1658}
1659
1660static void handle_irq_beacon(struct bcm43xx_private *bcm)
1661{
1662 u32 status;
1663
1664 bcm->irq_savedstate &= ~BCM43xx_IRQ_BEACON;
1665 status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD);
1666
1667 if ((status & 0x1) && (status & 0x2)) {
1668 /* ACK beacon IRQ. */
1669 bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON,
1670 BCM43xx_IRQ_BEACON);
1671 bcm->irq_savedstate |= BCM43xx_IRQ_BEACON;
1672 return;
1673 }
1674 if (!(status & 0x1)) {
1675 bcm43xx_generate_beacon_template(bcm, 0x68, 0x18);
1676 status |= 0x1;
1677 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD, status);
1678 }
1679 if (!(status & 0x2)) {
1680 bcm43xx_generate_beacon_template(bcm, 0x468, 0x1A);
1681 status |= 0x2;
1682 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD, status);
1683 }
1684}
1685
1686/* Interrupt handler bottom-half */
1687static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm)
1688{
1689 u32 reason;
1690 u32 dma_reason[4];
1691 int activity = 0;
1692 unsigned long flags;
1693
1694#ifdef CONFIG_BCM43XX_DEBUG
1695 u32 _handled = 0x00000000;
1696# define bcmirq_handled(irq) do { _handled |= (irq); } while (0)
1697#else
1698# define bcmirq_handled(irq) do { /* nothing */ } while (0)
1699#endif /* CONFIG_BCM43XX_DEBUG*/
1700
1701 bcm43xx_lock_mmio(bcm, flags);
1702 reason = bcm->irq_reason;
1703 dma_reason[0] = bcm->dma_reason[0];
1704 dma_reason[1] = bcm->dma_reason[1];
1705 dma_reason[2] = bcm->dma_reason[2];
1706 dma_reason[3] = bcm->dma_reason[3];
1707
1708 if (unlikely(reason & BCM43xx_IRQ_XMIT_ERROR)) {
1709 /* TX error. We get this when Template Ram is written in wrong endianess
1710 * in dummy_tx(). We also get this if something is wrong with the TX header
1711 * on DMA or PIO queues.
1712 * Maybe we get this in other error conditions, too.
1713 */
1714 printkl(KERN_ERR PFX "FATAL ERROR: BCM43xx_IRQ_XMIT_ERROR\n");
1715 bcmirq_handled(BCM43xx_IRQ_XMIT_ERROR);
1716 }
1717 if (unlikely((dma_reason[0] & BCM43xx_DMAIRQ_FATALMASK) |
1718 (dma_reason[1] & BCM43xx_DMAIRQ_FATALMASK) |
1719 (dma_reason[2] & BCM43xx_DMAIRQ_FATALMASK) |
1720 (dma_reason[3] & BCM43xx_DMAIRQ_FATALMASK))) {
1721 printkl(KERN_ERR PFX "FATAL ERROR: Fatal DMA error: "
1722 "0x%08X, 0x%08X, 0x%08X, 0x%08X\n",
1723 dma_reason[0], dma_reason[1],
1724 dma_reason[2], dma_reason[3]);
1725 bcm43xx_controller_restart(bcm, "DMA error");
1726 bcm43xx_unlock_mmio(bcm, flags);
1727 return;
1728 }
1729 if (unlikely((dma_reason[0] & BCM43xx_DMAIRQ_NONFATALMASK) |
1730 (dma_reason[1] & BCM43xx_DMAIRQ_NONFATALMASK) |
1731 (dma_reason[2] & BCM43xx_DMAIRQ_NONFATALMASK) |
1732 (dma_reason[3] & BCM43xx_DMAIRQ_NONFATALMASK))) {
1733 printkl(KERN_ERR PFX "DMA error: "
1734 "0x%08X, 0x%08X, 0x%08X, 0x%08X\n",
1735 dma_reason[0], dma_reason[1],
1736 dma_reason[2], dma_reason[3]);
1737 }
1738
1739 if (reason & BCM43xx_IRQ_PS) {
1740 handle_irq_ps(bcm);
1741 bcmirq_handled(BCM43xx_IRQ_PS);
1742 }
1743
1744 if (reason & BCM43xx_IRQ_REG124) {
1745 handle_irq_reg124(bcm);
1746 bcmirq_handled(BCM43xx_IRQ_REG124);
1747 }
1748
1749 if (reason & BCM43xx_IRQ_BEACON) {
1750 if (bcm->ieee->iw_mode == IW_MODE_MASTER)
1751 handle_irq_beacon(bcm);
1752 bcmirq_handled(BCM43xx_IRQ_BEACON);
1753 }
1754
1755 if (reason & BCM43xx_IRQ_PMQ) {
1756 handle_irq_pmq(bcm);
1757 bcmirq_handled(BCM43xx_IRQ_PMQ);
1758 }
1759
1760 if (reason & BCM43xx_IRQ_SCAN) {
1761 /*TODO*/
1762 //bcmirq_handled(BCM43xx_IRQ_SCAN);
1763 }
1764
1765 if (reason & BCM43xx_IRQ_NOISE) {
1766 handle_irq_noise(bcm);
1767 bcmirq_handled(BCM43xx_IRQ_NOISE);
1768 }
1769
1770 /* Check the DMA reason registers for received data. */
1771 assert(!(dma_reason[1] & BCM43xx_DMAIRQ_RX_DONE));
1772 assert(!(dma_reason[2] & BCM43xx_DMAIRQ_RX_DONE));
1773 if (dma_reason[0] & BCM43xx_DMAIRQ_RX_DONE) {
1774 if (bcm43xx_using_pio(bcm))
1775 bcm43xx_pio_rx(bcm43xx_current_pio(bcm)->queue0);
1776 else
1777 bcm43xx_dma_rx(bcm43xx_current_dma(bcm)->rx_ring0);
1778 /* We intentionally don't set "activity" to 1, here. */
1779 }
1780 if (dma_reason[3] & BCM43xx_DMAIRQ_RX_DONE) {
1781 if (bcm43xx_using_pio(bcm))
1782 bcm43xx_pio_rx(bcm43xx_current_pio(bcm)->queue3);
1783 else
1784 bcm43xx_dma_rx(bcm43xx_current_dma(bcm)->rx_ring1);
1785 activity = 1;
1786 }
1787 bcmirq_handled(BCM43xx_IRQ_RX);
1788
1789 if (reason & BCM43xx_IRQ_XMIT_STATUS) {
1790 handle_irq_transmit_status(bcm);
1791 activity = 1;
1792 //TODO: In AP mode, this also causes sending of powersave responses.
1793 bcmirq_handled(BCM43xx_IRQ_XMIT_STATUS);
1794 }
1795
1796 /* IRQ_PIO_WORKAROUND is handled in the top-half. */
1797 bcmirq_handled(BCM43xx_IRQ_PIO_WORKAROUND);
1798#ifdef CONFIG_BCM43XX_DEBUG
1799 if (unlikely(reason & ~_handled)) {
1800 printkl(KERN_WARNING PFX
1801 "Unhandled IRQ! Reason: 0x%08x, Unhandled: 0x%08x, "
1802 "DMA: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n",
1803 reason, (reason & ~_handled),
1804 dma_reason[0], dma_reason[1],
1805 dma_reason[2], dma_reason[3]);
1806 }
1807#endif
1808#undef bcmirq_handled
1809
1810 if (!modparam_noleds)
1811 bcm43xx_leds_update(bcm, activity);
1812 bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate);
1813 bcm43xx_unlock_mmio(bcm, flags);
1814}
1815
1816static void pio_irq_workaround(struct bcm43xx_private *bcm,
1817 u16 base, int queueidx)
1818{
1819 u16 rxctl;
1820
1821 rxctl = bcm43xx_read16(bcm, base + BCM43xx_PIO_RXCTL);
1822 if (rxctl & BCM43xx_PIO_RXCTL_DATAAVAILABLE)
1823 bcm->dma_reason[queueidx] |= BCM43xx_DMAIRQ_RX_DONE;
1824 else
1825 bcm->dma_reason[queueidx] &= ~BCM43xx_DMAIRQ_RX_DONE;
1826}
1827
1828static void bcm43xx_interrupt_ack(struct bcm43xx_private *bcm, u32 reason)
1829{
1830 if (bcm43xx_using_pio(bcm) &&
1831 (bcm->current_core->rev < 3) &&
1832 (!(reason & BCM43xx_IRQ_PIO_WORKAROUND))) {
1833 /* Apply a PIO specific workaround to the dma_reasons */
1834 pio_irq_workaround(bcm, BCM43xx_MMIO_PIO1_BASE, 0);
1835 pio_irq_workaround(bcm, BCM43xx_MMIO_PIO2_BASE, 1);
1836 pio_irq_workaround(bcm, BCM43xx_MMIO_PIO3_BASE, 2);
1837 pio_irq_workaround(bcm, BCM43xx_MMIO_PIO4_BASE, 3);
1838 }
1839
1840 bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, reason);
1841
1842 bcm43xx_write32(bcm, BCM43xx_MMIO_DMA1_REASON,
1843 bcm->dma_reason[0]);
1844 bcm43xx_write32(bcm, BCM43xx_MMIO_DMA2_REASON,
1845 bcm->dma_reason[1]);
1846 bcm43xx_write32(bcm, BCM43xx_MMIO_DMA3_REASON,
1847 bcm->dma_reason[2]);
1848 bcm43xx_write32(bcm, BCM43xx_MMIO_DMA4_REASON,
1849 bcm->dma_reason[3]);
1850}
1851
1852/* Interrupt handler top-half */
1853static irqreturn_t bcm43xx_interrupt_handler(int irq, void *dev_id, struct pt_regs *regs)
1854{
1855 irqreturn_t ret = IRQ_HANDLED;
1856 struct bcm43xx_private *bcm = dev_id;
1857 u32 reason;
1858
1859 if (!bcm)
1860 return IRQ_NONE;
1861
1862 spin_lock(&bcm->_lock);
1863
1864 reason = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
1865 if (reason == 0xffffffff) {
1866 /* irq not for us (shared irq) */
1867 ret = IRQ_NONE;
1868 goto out;
1869 }
1870 reason &= bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK);
1871 if (!reason)
1872 goto out;
1873
1874 bcm->dma_reason[0] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA1_REASON)
1875 & 0x0001dc00;
1876 bcm->dma_reason[1] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA2_REASON)
1877 & 0x0000dc00;
1878 bcm->dma_reason[2] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA3_REASON)
1879 & 0x0000dc00;
1880 bcm->dma_reason[3] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA4_REASON)
1881 & 0x0001dc00;
1882
1883 bcm43xx_interrupt_ack(bcm, reason);
1884
1885 /* Only accept IRQs, if we are initialized properly.
1886 * This avoids an RX race while initializing.
1887 * We should probably not enable IRQs before we are initialized
1888 * completely, but some careful work is needed to fix this. I think it
1889 * is best to stay with this cheap workaround for now... .
1890 */
1891 if (likely(bcm->initialized)) {
1892 /* disable all IRQs. They are enabled again in the bottom half. */
1893 bcm->irq_savedstate = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
1894 /* save the reason code and call our bottom half. */
1895 bcm->irq_reason = reason;
1896 tasklet_schedule(&bcm->isr_tasklet);
1897 }
1898
1899out:
1900 mmiowb();
1901 spin_unlock(&bcm->_lock);
1902
1903 return ret;
1904}
1905
1906static void bcm43xx_release_firmware(struct bcm43xx_private *bcm, int force)
1907{
1908 if (bcm->firmware_norelease && !force)
1909 return; /* Suspending or controller reset. */
1910 release_firmware(bcm->ucode);
1911 bcm->ucode = NULL;
1912 release_firmware(bcm->pcm);
1913 bcm->pcm = NULL;
1914 release_firmware(bcm->initvals0);
1915 bcm->initvals0 = NULL;
1916 release_firmware(bcm->initvals1);
1917 bcm->initvals1 = NULL;
1918}
1919
1920static int bcm43xx_request_firmware(struct bcm43xx_private *bcm)
1921{
1922 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
1923 u8 rev = bcm->current_core->rev;
1924 int err = 0;
1925 int nr;
1926 char buf[22 + sizeof(modparam_fwpostfix) - 1] = { 0 };
1927
1928 if (!bcm->ucode) {
1929 snprintf(buf, ARRAY_SIZE(buf), "bcm43xx_microcode%d%s.fw",
1930 (rev >= 5 ? 5 : rev),
1931 modparam_fwpostfix);
1932 err = request_firmware(&bcm->ucode, buf, &bcm->pci_dev->dev);
1933 if (err) {
1934 printk(KERN_ERR PFX
1935 "Error: Microcode \"%s\" not available or load failed.\n",
1936 buf);
1937 goto error;
1938 }
1939 }
1940
1941 if (!bcm->pcm) {
1942 snprintf(buf, ARRAY_SIZE(buf),
1943 "bcm43xx_pcm%d%s.fw",
1944 (rev < 5 ? 4 : 5),
1945 modparam_fwpostfix);
1946 err = request_firmware(&bcm->pcm, buf, &bcm->pci_dev->dev);
1947 if (err) {
1948 printk(KERN_ERR PFX
1949 "Error: PCM \"%s\" not available or load failed.\n",
1950 buf);
1951 goto error;
1952 }
1953 }
1954
1955 if (!bcm->initvals0) {
1956 if (rev == 2 || rev == 4) {
1957 switch (phy->type) {
1958 case BCM43xx_PHYTYPE_A:
1959 nr = 3;
1960 break;
1961 case BCM43xx_PHYTYPE_B:
1962 case BCM43xx_PHYTYPE_G:
1963 nr = 1;
1964 break;
1965 default:
1966 goto err_noinitval;
1967 }
1968
1969 } else if (rev >= 5) {
1970 switch (phy->type) {
1971 case BCM43xx_PHYTYPE_A:
1972 nr = 7;
1973 break;
1974 case BCM43xx_PHYTYPE_B:
1975 case BCM43xx_PHYTYPE_G:
1976 nr = 5;
1977 break;
1978 default:
1979 goto err_noinitval;
1980 }
1981 } else
1982 goto err_noinitval;
1983 snprintf(buf, ARRAY_SIZE(buf), "bcm43xx_initval%02d%s.fw",
1984 nr, modparam_fwpostfix);
1985
1986 err = request_firmware(&bcm->initvals0, buf, &bcm->pci_dev->dev);
1987 if (err) {
1988 printk(KERN_ERR PFX
1989 "Error: InitVals \"%s\" not available or load failed.\n",
1990 buf);
1991 goto error;
1992 }
1993 if (bcm->initvals0->size % sizeof(struct bcm43xx_initval)) {
1994 printk(KERN_ERR PFX "InitVals fileformat error.\n");
1995 goto error;
1996 }
1997 }
1998
1999 if (!bcm->initvals1) {
2000 if (rev >= 5) {
2001 u32 sbtmstatehigh;
2002
2003 switch (phy->type) {
2004 case BCM43xx_PHYTYPE_A:
2005 sbtmstatehigh = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH);
2006 if (sbtmstatehigh & 0x00010000)
2007 nr = 9;
2008 else
2009 nr = 10;
2010 break;
2011 case BCM43xx_PHYTYPE_B:
2012 case BCM43xx_PHYTYPE_G:
2013 nr = 6;
2014 break;
2015 default:
2016 goto err_noinitval;
2017 }
2018 snprintf(buf, ARRAY_SIZE(buf), "bcm43xx_initval%02d%s.fw",
2019 nr, modparam_fwpostfix);
2020
2021 err = request_firmware(&bcm->initvals1, buf, &bcm->pci_dev->dev);
2022 if (err) {
2023 printk(KERN_ERR PFX
2024 "Error: InitVals \"%s\" not available or load failed.\n",
2025 buf);
2026 goto error;
2027 }
2028 if (bcm->initvals1->size % sizeof(struct bcm43xx_initval)) {
2029 printk(KERN_ERR PFX "InitVals fileformat error.\n");
2030 goto error;
2031 }
2032 }
2033 }
2034
2035out:
2036 return err;
2037error:
2038 bcm43xx_release_firmware(bcm, 1);
2039 goto out;
2040err_noinitval:
2041 printk(KERN_ERR PFX "Error: No InitVals available!\n");
2042 err = -ENOENT;
2043 goto error;
2044}
2045
2046static void bcm43xx_upload_microcode(struct bcm43xx_private *bcm)
2047{
2048 const u32 *data;
2049 unsigned int i, len;
2050
2051 /* Upload Microcode. */
2052 data = (u32 *)(bcm->ucode->data);
2053 len = bcm->ucode->size / sizeof(u32);
2054 bcm43xx_shm_control_word(bcm, BCM43xx_SHM_UCODE, 0x0000);
2055 for (i = 0; i < len; i++) {
2056 bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_DATA,
2057 be32_to_cpu(data[i]));
2058 udelay(10);
2059 }
2060
2061 /* Upload PCM data. */
2062 data = (u32 *)(bcm->pcm->data);
2063 len = bcm->pcm->size / sizeof(u32);
2064 bcm43xx_shm_control_word(bcm, BCM43xx_SHM_PCM, 0x01ea);
2065 bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_DATA, 0x00004000);
2066 bcm43xx_shm_control_word(bcm, BCM43xx_SHM_PCM, 0x01eb);
2067 for (i = 0; i < len; i++) {
2068 bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_DATA,
2069 be32_to_cpu(data[i]));
2070 udelay(10);
2071 }
2072}
2073
2074static int bcm43xx_write_initvals(struct bcm43xx_private *bcm,
2075 const struct bcm43xx_initval *data,
2076 const unsigned int len)
2077{
2078 u16 offset, size;
2079 u32 value;
2080 unsigned int i;
2081
2082 for (i = 0; i < len; i++) {
2083 offset = be16_to_cpu(data[i].offset);
2084 size = be16_to_cpu(data[i].size);
2085 value = be32_to_cpu(data[i].value);
2086
2087 if (unlikely(offset >= 0x1000))
2088 goto err_format;
2089 if (size == 2) {
2090 if (unlikely(value & 0xFFFF0000))
2091 goto err_format;
2092 bcm43xx_write16(bcm, offset, (u16)value);
2093 } else if (size == 4) {
2094 bcm43xx_write32(bcm, offset, value);
2095 } else
2096 goto err_format;
2097 }
2098
2099 return 0;
2100
2101err_format:
2102 printk(KERN_ERR PFX "InitVals (bcm43xx_initvalXX.fw) file-format error. "
2103 "Please fix your bcm43xx firmware files.\n");
2104 return -EPROTO;
2105}
2106
2107static int bcm43xx_upload_initvals(struct bcm43xx_private *bcm)
2108{
2109 int err;
2110
2111 err = bcm43xx_write_initvals(bcm, (struct bcm43xx_initval *)bcm->initvals0->data,
2112 bcm->initvals0->size / sizeof(struct bcm43xx_initval));
2113 if (err)
2114 goto out;
2115 if (bcm->initvals1) {
2116 err = bcm43xx_write_initvals(bcm, (struct bcm43xx_initval *)bcm->initvals1->data,
2117 bcm->initvals1->size / sizeof(struct bcm43xx_initval));
2118 if (err)
2119 goto out;
2120 }
2121out:
2122 return err;
2123}
2124
2125static int bcm43xx_initialize_irq(struct bcm43xx_private *bcm)
2126{
2127 int res;
2128 unsigned int i;
2129 u32 data;
2130
2131 bcm->irq = bcm->pci_dev->irq;
2132#ifdef CONFIG_BCM947XX
2133 if (bcm->pci_dev->bus->number == 0) {
2134 struct pci_dev *d = NULL;
2135 /* FIXME: we will probably need more device IDs here... */
2136 d = pci_find_device(PCI_VENDOR_ID_BROADCOM, 0x4324, NULL);
2137 if (d != NULL) {
2138 bcm->irq = d->irq;
2139 }
2140 }
2141#endif
2142 res = request_irq(bcm->irq, bcm43xx_interrupt_handler,
2143 SA_SHIRQ, KBUILD_MODNAME, bcm);
2144 if (res) {
2145 printk(KERN_ERR PFX "Cannot register IRQ%d\n", bcm->irq);
2146 return -ENODEV;
2147 }
2148 bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, 0xffffffff);
2149 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, 0x00020402);
2150 i = 0;
2151 while (1) {
2152 data = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
2153 if (data == BCM43xx_IRQ_READY)
2154 break;
2155 i++;
2156 if (i >= BCM43xx_IRQWAIT_MAX_RETRIES) {
2157 printk(KERN_ERR PFX "Card IRQ register not responding. "
2158 "Giving up.\n");
2159 free_irq(bcm->irq, bcm);
2160 return -ENODEV;
2161 }
2162 udelay(10);
2163 }
2164 // dummy read
2165 bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
2166
2167 return 0;
2168}
2169
2170/* Switch to the core used to write the GPIO register.
2171 * This is either the ChipCommon, or the PCI core.
2172 */
2173static int switch_to_gpio_core(struct bcm43xx_private *bcm)
2174{
2175 int err;
2176
2177 /* Where to find the GPIO register depends on the chipset.
2178 * If it has a ChipCommon, its register at offset 0x6c is the GPIO
2179 * control register. Otherwise the register at offset 0x6c in the
2180 * PCI core is the GPIO control register.
2181 */
2182 err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon);
2183 if (err == -ENODEV) {
2184 err = bcm43xx_switch_core(bcm, &bcm->core_pci);
2185 if (unlikely(err == -ENODEV)) {
2186 printk(KERN_ERR PFX "gpio error: "
2187 "Neither ChipCommon nor PCI core available!\n");
2188 }
2189 }
2190
2191 return err;
2192}
2193
2194/* Initialize the GPIOs
2195 * http://bcm-specs.sipsolutions.net/GPIO
2196 */
2197static int bcm43xx_gpio_init(struct bcm43xx_private *bcm)
2198{
2199 struct bcm43xx_coreinfo *old_core;
2200 int err;
2201 u32 mask, set;
2202
2203 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
2204 bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD)
2205 & 0xFFFF3FFF);
2206
2207 bcm43xx_leds_switch_all(bcm, 0);
2208 bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_MASK,
2209 bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_MASK) | 0x000F);
2210
2211 mask = 0x0000001F;
2212 set = 0x0000000F;
2213 if (bcm->chip_id == 0x4301) {
2214 mask |= 0x0060;
2215 set |= 0x0060;
2216 }
2217 if (0 /* FIXME: conditional unknown */) {
2218 bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_MASK,
2219 bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_MASK)
2220 | 0x0100);
2221 mask |= 0x0180;
2222 set |= 0x0180;
2223 }
2224 if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL) {
2225 bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_MASK,
2226 bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_MASK)
2227 | 0x0200);
2228 mask |= 0x0200;
2229 set |= 0x0200;
2230 }
2231 if (bcm->current_core->rev >= 2)
2232 mask |= 0x0010; /* FIXME: This is redundant. */
2233
2234 old_core = bcm->current_core;
2235 err = switch_to_gpio_core(bcm);
2236 if (err)
2237 goto out;
2238 bcm43xx_write32(bcm, BCM43xx_GPIO_CONTROL,
2239 (bcm43xx_read32(bcm, BCM43xx_GPIO_CONTROL) & mask) | set);
2240 err = bcm43xx_switch_core(bcm, old_core);
2241out:
2242 return err;
2243}
2244
2245/* Turn off all GPIO stuff. Call this on module unload, for example. */
2246static int bcm43xx_gpio_cleanup(struct bcm43xx_private *bcm)
2247{
2248 struct bcm43xx_coreinfo *old_core;
2249 int err;
2250
2251 old_core = bcm->current_core;
2252 err = switch_to_gpio_core(bcm);
2253 if (err)
2254 return err;
2255 bcm43xx_write32(bcm, BCM43xx_GPIO_CONTROL, 0x00000000);
2256 err = bcm43xx_switch_core(bcm, old_core);
2257 assert(err == 0);
2258
2259 return 0;
2260}
2261
2262/* http://bcm-specs.sipsolutions.net/EnableMac */
2263void bcm43xx_mac_enable(struct bcm43xx_private *bcm)
2264{
2265 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
2266 bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD)
2267 | BCM43xx_SBF_MAC_ENABLED);
2268 bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, BCM43xx_IRQ_READY);
2269 bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* dummy read */
2270 bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */
2271 bcm43xx_power_saving_ctl_bits(bcm, -1, -1);
2272}
2273
2274/* http://bcm-specs.sipsolutions.net/SuspendMAC */
2275void bcm43xx_mac_suspend(struct bcm43xx_private *bcm)
2276{
2277 int i;
2278 u32 tmp;
2279
2280 bcm43xx_power_saving_ctl_bits(bcm, -1, 1);
2281 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
2282 bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD)
2283 & ~BCM43xx_SBF_MAC_ENABLED);
2284 bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */
2285 for (i = 100000; i; i--) {
2286 tmp = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
2287 if (tmp & BCM43xx_IRQ_READY)
2288 return;
2289 udelay(10);
2290 }
2291 printkl(KERN_ERR PFX "MAC suspend failed\n");
2292}
2293
2294void bcm43xx_set_iwmode(struct bcm43xx_private *bcm,
2295 int iw_mode)
2296{
2297 unsigned long flags;
2298 struct net_device *net_dev = bcm->net_dev;
2299 u32 status;
2300 u16 value;
2301
2302 spin_lock_irqsave(&bcm->ieee->lock, flags);
2303 bcm->ieee->iw_mode = iw_mode;
2304 spin_unlock_irqrestore(&bcm->ieee->lock, flags);
2305 if (iw_mode == IW_MODE_MONITOR)
2306 net_dev->type = ARPHRD_IEEE80211;
2307 else
2308 net_dev->type = ARPHRD_ETHER;
2309
2310 status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
2311 /* Reset status to infrastructured mode */
2312 status &= ~(BCM43xx_SBF_MODE_AP | BCM43xx_SBF_MODE_MONITOR);
2313 status &= ~BCM43xx_SBF_MODE_PROMISC;
2314 status |= BCM43xx_SBF_MODE_NOTADHOC;
2315
2316/* FIXME: Always enable promisc mode, until we get the MAC filters working correctly. */
2317status |= BCM43xx_SBF_MODE_PROMISC;
2318
2319 switch (iw_mode) {
2320 case IW_MODE_MONITOR:
2321 status |= BCM43xx_SBF_MODE_MONITOR;
2322 status |= BCM43xx_SBF_MODE_PROMISC;
2323 break;
2324 case IW_MODE_ADHOC:
2325 status &= ~BCM43xx_SBF_MODE_NOTADHOC;
2326 break;
2327 case IW_MODE_MASTER:
2328 status |= BCM43xx_SBF_MODE_AP;
2329 break;
2330 case IW_MODE_SECOND:
2331 case IW_MODE_REPEAT:
2332 TODO(); /* TODO */
2333 break;
2334 case IW_MODE_INFRA:
2335 /* nothing to be done here... */
2336 break;
2337 default:
2338 dprintk(KERN_ERR PFX "Unknown mode in set_iwmode: %d\n", iw_mode);
2339 }
2340 if (net_dev->flags & IFF_PROMISC)
2341 status |= BCM43xx_SBF_MODE_PROMISC;
2342 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status);
2343
2344 value = 0x0002;
2345 if (iw_mode != IW_MODE_ADHOC && iw_mode != IW_MODE_MASTER) {
2346 if (bcm->chip_id == 0x4306 && bcm->chip_rev == 3)
2347 value = 0x0064;
2348 else
2349 value = 0x0032;
2350 }
2351 bcm43xx_write16(bcm, 0x0612, value);
2352}
2353
2354/* This is the opposite of bcm43xx_chip_init() */
2355static void bcm43xx_chip_cleanup(struct bcm43xx_private *bcm)
2356{
2357 bcm43xx_radio_turn_off(bcm);
2358 if (!modparam_noleds)
2359 bcm43xx_leds_exit(bcm);
2360 bcm43xx_gpio_cleanup(bcm);
2361 free_irq(bcm->irq, bcm);
2362 bcm43xx_release_firmware(bcm, 0);
2363}
2364
2365/* Initialize the chip
2366 * http://bcm-specs.sipsolutions.net/ChipInit
2367 */
2368static int bcm43xx_chip_init(struct bcm43xx_private *bcm)
2369{
2370 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
2371 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
2372 int err;
2373 int tmp;
2374 u32 value32;
2375 u16 value16;
2376
2377 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
2378 BCM43xx_SBF_CORE_READY
2379 | BCM43xx_SBF_400);
2380
2381 err = bcm43xx_request_firmware(bcm);
2382 if (err)
2383 goto out;
2384 bcm43xx_upload_microcode(bcm);
2385
2386 err = bcm43xx_initialize_irq(bcm);
2387 if (err)
2388 goto err_release_fw;
2389
2390 err = bcm43xx_gpio_init(bcm);
2391 if (err)
2392 goto err_free_irq;
2393
2394 err = bcm43xx_upload_initvals(bcm);
2395 if (err)
2396 goto err_gpio_cleanup;
2397 bcm43xx_radio_turn_on(bcm);
2398
2399 bcm43xx_write16(bcm, 0x03E6, 0x0000);
2400 err = bcm43xx_phy_init(bcm);
2401 if (err)
2402 goto err_radio_off;
2403
2404 /* Select initial Interference Mitigation. */
2405 tmp = radio->interfmode;
2406 radio->interfmode = BCM43xx_RADIO_INTERFMODE_NONE;
2407 bcm43xx_radio_set_interference_mitigation(bcm, tmp);
2408
2409 bcm43xx_phy_set_antenna_diversity(bcm);
2410 bcm43xx_radio_set_txantenna(bcm, BCM43xx_RADIO_TXANTENNA_DEFAULT);
2411 if (phy->type == BCM43xx_PHYTYPE_B) {
2412 value16 = bcm43xx_read16(bcm, 0x005E);
2413 value16 |= 0x0004;
2414 bcm43xx_write16(bcm, 0x005E, value16);
2415 }
2416 bcm43xx_write32(bcm, 0x0100, 0x01000000);
2417 if (bcm->current_core->rev < 5)
2418 bcm43xx_write32(bcm, 0x010C, 0x01000000);
2419
2420 value32 = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
2421 value32 &= ~ BCM43xx_SBF_MODE_NOTADHOC;
2422 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value32);
2423 value32 = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
2424 value32 |= BCM43xx_SBF_MODE_NOTADHOC;
2425 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value32);
2426
2427 value32 = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
2428 value32 |= 0x100000;
2429 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value32);
2430
2431 if (bcm43xx_using_pio(bcm)) {
2432 bcm43xx_write32(bcm, 0x0210, 0x00000100);
2433 bcm43xx_write32(bcm, 0x0230, 0x00000100);
2434 bcm43xx_write32(bcm, 0x0250, 0x00000100);
2435 bcm43xx_write32(bcm, 0x0270, 0x00000100);
2436 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0034, 0x0000);
2437 }
2438
2439 /* Probe Response Timeout value */
2440 /* FIXME: Default to 0, has to be set by ioctl probably... :-/ */
2441 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0074, 0x0000);
2442
2443 /* Initially set the wireless operation mode. */
2444 bcm43xx_set_iwmode(bcm, bcm->ieee->iw_mode);
2445
2446 if (bcm->current_core->rev < 3) {
2447 bcm43xx_write16(bcm, 0x060E, 0x0000);
2448 bcm43xx_write16(bcm, 0x0610, 0x8000);
2449 bcm43xx_write16(bcm, 0x0604, 0x0000);
2450 bcm43xx_write16(bcm, 0x0606, 0x0200);
2451 } else {
2452 bcm43xx_write32(bcm, 0x0188, 0x80000000);
2453 bcm43xx_write32(bcm, 0x018C, 0x02000000);
2454 }
2455 bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, 0x00004000);
2456 bcm43xx_write32(bcm, BCM43xx_MMIO_DMA1_IRQ_MASK, 0x0001DC00);
2457 bcm43xx_write32(bcm, BCM43xx_MMIO_DMA2_IRQ_MASK, 0x0000DC00);
2458 bcm43xx_write32(bcm, BCM43xx_MMIO_DMA3_IRQ_MASK, 0x0000DC00);
2459 bcm43xx_write32(bcm, BCM43xx_MMIO_DMA4_IRQ_MASK, 0x0001DC00);
2460
2461 value32 = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
2462 value32 |= 0x00100000;
2463 bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, value32);
2464
2465 bcm43xx_write16(bcm, BCM43xx_MMIO_POWERUP_DELAY, bcm43xx_pctl_powerup_delay(bcm));
2466
2467 assert(err == 0);
2468 dprintk(KERN_INFO PFX "Chip initialized\n");
2469out:
2470 return err;
2471
2472err_radio_off:
2473 bcm43xx_radio_turn_off(bcm);
2474err_gpio_cleanup:
2475 bcm43xx_gpio_cleanup(bcm);
2476err_free_irq:
2477 free_irq(bcm->irq, bcm);
2478err_release_fw:
2479 bcm43xx_release_firmware(bcm, 1);
2480 goto out;
2481}
2482
2483/* Validate chip access
2484 * http://bcm-specs.sipsolutions.net/ValidateChipAccess */
2485static int bcm43xx_validate_chip(struct bcm43xx_private *bcm)
2486{
2487 u32 value;
2488 u32 shm_backup;
2489
2490 shm_backup = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, 0x0000);
2491 bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, 0x0000, 0xAA5555AA);
2492 if (bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, 0x0000) != 0xAA5555AA)
2493 goto error;
2494 bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, 0x0000, 0x55AAAA55);
2495 if (bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, 0x0000) != 0x55AAAA55)
2496 goto error;
2497 bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, 0x0000, shm_backup);
2498
2499 value = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
2500 if ((value | 0x80000000) != 0x80000400)
2501 goto error;
2502
2503 value = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
2504 if (value != 0x00000000)
2505 goto error;
2506
2507 return 0;
2508error:
2509 printk(KERN_ERR PFX "Failed to validate the chipaccess\n");
2510 return -ENODEV;
2511}
2512
2513static void bcm43xx_init_struct_phyinfo(struct bcm43xx_phyinfo *phy)
2514{
2515 /* Initialize a "phyinfo" structure. The structure is already
2516 * zeroed out.
2517 */
2518 phy->antenna_diversity = 0xFFFF;
2519 phy->savedpctlreg = 0xFFFF;
2520 phy->minlowsig[0] = 0xFFFF;
2521 phy->minlowsig[1] = 0xFFFF;
2522 spin_lock_init(&phy->lock);
2523}
2524
2525static void bcm43xx_init_struct_radioinfo(struct bcm43xx_radioinfo *radio)
2526{
2527 /* Initialize a "radioinfo" structure. The structure is already
2528 * zeroed out.
2529 */
2530 radio->interfmode = BCM43xx_RADIO_INTERFMODE_NONE;
2531 radio->channel = 0xFF;
2532 radio->initial_channel = 0xFF;
2533 radio->lofcal = 0xFFFF;
2534 radio->initval = 0xFFFF;
2535 radio->nrssi[0] = -1000;
2536 radio->nrssi[1] = -1000;
2537}
2538
2539static int bcm43xx_probe_cores(struct bcm43xx_private *bcm)
2540{
2541 int err, i;
2542 int current_core;
2543 u32 core_vendor, core_id, core_rev;
2544 u32 sb_id_hi, chip_id_32 = 0;
2545 u16 pci_device, chip_id_16;
2546 u8 core_count;
2547
2548 memset(&bcm->core_chipcommon, 0, sizeof(struct bcm43xx_coreinfo));
2549 memset(&bcm->core_pci, 0, sizeof(struct bcm43xx_coreinfo));
2550 memset(&bcm->core_80211, 0, sizeof(struct bcm43xx_coreinfo)
2551 * BCM43xx_MAX_80211_CORES);
2552 memset(&bcm->core_80211_ext, 0, sizeof(struct bcm43xx_coreinfo_80211)
2553 * BCM43xx_MAX_80211_CORES);
2554 bcm->current_80211_core_idx = -1;
2555 bcm->nr_80211_available = 0;
2556 bcm->current_core = NULL;
2557 bcm->active_80211_core = NULL;
2558
2559 /* map core 0 */
2560 err = _switch_core(bcm, 0);
2561 if (err)
2562 goto out;
2563
2564 /* fetch sb_id_hi from core information registers */
2565 sb_id_hi = bcm43xx_read32(bcm, BCM43xx_CIR_SB_ID_HI);
2566
2567 core_id = (sb_id_hi & 0xFFF0) >> 4;
2568 core_rev = (sb_id_hi & 0xF);
2569 core_vendor = (sb_id_hi & 0xFFFF0000) >> 16;
2570
2571 /* if present, chipcommon is always core 0; read the chipid from it */
2572 if (core_id == BCM43xx_COREID_CHIPCOMMON) {
2573 chip_id_32 = bcm43xx_read32(bcm, 0);
2574 chip_id_16 = chip_id_32 & 0xFFFF;
2575 bcm->core_chipcommon.available = 1;
2576 bcm->core_chipcommon.id = core_id;
2577 bcm->core_chipcommon.rev = core_rev;
2578 bcm->core_chipcommon.index = 0;
2579 /* While we are at it, also read the capabilities. */
2580 bcm->chipcommon_capabilities = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_CAPABILITIES);
2581 } else {
2582 /* without a chipCommon, use a hard coded table. */
2583 pci_device = bcm->pci_dev->device;
2584 if (pci_device == 0x4301)
2585 chip_id_16 = 0x4301;
2586 else if ((pci_device >= 0x4305) && (pci_device <= 0x4307))
2587 chip_id_16 = 0x4307;
2588 else if ((pci_device >= 0x4402) && (pci_device <= 0x4403))
2589 chip_id_16 = 0x4402;
2590 else if ((pci_device >= 0x4610) && (pci_device <= 0x4615))
2591 chip_id_16 = 0x4610;
2592 else if ((pci_device >= 0x4710) && (pci_device <= 0x4715))
2593 chip_id_16 = 0x4710;
2594#ifdef CONFIG_BCM947XX
2595 else if ((pci_device >= 0x4320) && (pci_device <= 0x4325))
2596 chip_id_16 = 0x4309;
2597#endif
2598 else {
2599 printk(KERN_ERR PFX "Could not determine Chip ID\n");
2600 return -ENODEV;
2601 }
2602 }
2603
2604 /* ChipCommon with Core Rev >=4 encodes number of cores,
2605 * otherwise consult hardcoded table */
2606 if ((core_id == BCM43xx_COREID_CHIPCOMMON) && (core_rev >= 4)) {
2607 core_count = (chip_id_32 & 0x0F000000) >> 24;
2608 } else {
2609 switch (chip_id_16) {
2610 case 0x4610:
2611 case 0x4704:
2612 case 0x4710:
2613 core_count = 9;
2614 break;
2615 case 0x4310:
2616 core_count = 8;
2617 break;
2618 case 0x5365:
2619 core_count = 7;
2620 break;
2621 case 0x4306:
2622 core_count = 6;
2623 break;
2624 case 0x4301:
2625 case 0x4307:
2626 core_count = 5;
2627 break;
2628 case 0x4402:
2629 core_count = 3;
2630 break;
2631 default:
2632 /* SOL if we get here */
2633 assert(0);
2634 core_count = 1;
2635 }
2636 }
2637
2638 bcm->chip_id = chip_id_16;
2639 bcm->chip_rev = (chip_id_32 & 0x000F0000) >> 16;
2640 bcm->chip_package = (chip_id_32 & 0x00F00000) >> 20;
2641
2642 dprintk(KERN_INFO PFX "Chip ID 0x%x, rev 0x%x\n",
2643 bcm->chip_id, bcm->chip_rev);
2644 dprintk(KERN_INFO PFX "Number of cores: %d\n", core_count);
2645 if (bcm->core_chipcommon.available) {
2646 dprintk(KERN_INFO PFX "Core 0: ID 0x%x, rev 0x%x, vendor 0x%x, %s\n",
2647 core_id, core_rev, core_vendor,
2648 bcm43xx_core_enabled(bcm) ? "enabled" : "disabled");
2649 }
2650
2651 if (bcm->core_chipcommon.available)
2652 current_core = 1;
2653 else
2654 current_core = 0;
2655 for ( ; current_core < core_count; current_core++) {
2656 struct bcm43xx_coreinfo *core;
2657 struct bcm43xx_coreinfo_80211 *ext_80211;
2658
2659 err = _switch_core(bcm, current_core);
2660 if (err)
2661 goto out;
2662 /* Gather information */
2663 /* fetch sb_id_hi from core information registers */
2664 sb_id_hi = bcm43xx_read32(bcm, BCM43xx_CIR_SB_ID_HI);
2665
2666 /* extract core_id, core_rev, core_vendor */
2667 core_id = (sb_id_hi & 0xFFF0) >> 4;
2668 core_rev = (sb_id_hi & 0xF);
2669 core_vendor = (sb_id_hi & 0xFFFF0000) >> 16;
2670
2671 dprintk(KERN_INFO PFX "Core %d: ID 0x%x, rev 0x%x, vendor 0x%x, %s\n",
2672 current_core, core_id, core_rev, core_vendor,
2673 bcm43xx_core_enabled(bcm) ? "enabled" : "disabled" );
2674
2675 core = NULL;
2676 switch (core_id) {
2677 case BCM43xx_COREID_PCI:
2678 core = &bcm->core_pci;
2679 if (core->available) {
2680 printk(KERN_WARNING PFX "Multiple PCI cores found.\n");
2681 continue;
2682 }
2683 break;
2684 case BCM43xx_COREID_80211:
2685 for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) {
2686 core = &(bcm->core_80211[i]);
2687 ext_80211 = &(bcm->core_80211_ext[i]);
2688 if (!core->available)
2689 break;
2690 core = NULL;
2691 }
2692 if (!core) {
2693 printk(KERN_WARNING PFX "More than %d cores of type 802.11 found.\n",
2694 BCM43xx_MAX_80211_CORES);
2695 continue;
2696 }
2697 if (i != 0) {
2698 /* More than one 80211 core is only supported
2699 * by special chips.
2700 * There are chips with two 80211 cores, but with
2701 * dangling pins on the second core. Be careful
2702 * and ignore these cores here.
2703 */
2704 if (bcm->pci_dev->device != 0x4324) {
2705 dprintk(KERN_INFO PFX "Ignoring additional 802.11 core.\n");
2706 continue;
2707 }
2708 }
2709 switch (core_rev) {
2710 case 2:
2711 case 4:
2712 case 5:
2713 case 6:
2714 case 7:
2715 case 9:
2716 break;
2717 default:
2718 printk(KERN_ERR PFX "Error: Unsupported 80211 core revision %u\n",
2719 core_rev);
2720 err = -ENODEV;
2721 goto out;
2722 }
2723 bcm->nr_80211_available++;
2724 bcm43xx_init_struct_phyinfo(&ext_80211->phy);
2725 bcm43xx_init_struct_radioinfo(&ext_80211->radio);
2726 break;
2727 case BCM43xx_COREID_CHIPCOMMON:
2728 printk(KERN_WARNING PFX "Multiple CHIPCOMMON cores found.\n");
2729 break;
2730 }
2731 if (core) {
2732 core->available = 1;
2733 core->id = core_id;
2734 core->rev = core_rev;
2735 core->index = current_core;
2736 }
2737 }
2738
2739 if (!bcm->core_80211[0].available) {
2740 printk(KERN_ERR PFX "Error: No 80211 core found!\n");
2741 err = -ENODEV;
2742 goto out;
2743 }
2744
2745 err = bcm43xx_switch_core(bcm, &bcm->core_80211[0]);
2746
2747 assert(err == 0);
2748out:
2749 return err;
2750}
2751
2752static void bcm43xx_gen_bssid(struct bcm43xx_private *bcm)
2753{
2754 const u8 *mac = (const u8*)(bcm->net_dev->dev_addr);
2755 u8 *bssid = bcm->ieee->bssid;
2756
2757 switch (bcm->ieee->iw_mode) {
2758 case IW_MODE_ADHOC:
2759 random_ether_addr(bssid);
2760 break;
2761 case IW_MODE_MASTER:
2762 case IW_MODE_INFRA:
2763 case IW_MODE_REPEAT:
2764 case IW_MODE_SECOND:
2765 case IW_MODE_MONITOR:
2766 memcpy(bssid, mac, ETH_ALEN);
2767 break;
2768 default:
2769 assert(0);
2770 }
2771}
2772
2773static void bcm43xx_rate_memory_write(struct bcm43xx_private *bcm,
2774 u16 rate,
2775 int is_ofdm)
2776{
2777 u16 offset;
2778
2779 if (is_ofdm) {
2780 offset = 0x480;
2781 offset += (bcm43xx_plcp_get_ratecode_ofdm(rate) & 0x000F) * 2;
2782 }
2783 else {
2784 offset = 0x4C0;
2785 offset += (bcm43xx_plcp_get_ratecode_cck(rate) & 0x000F) * 2;
2786 }
2787 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, offset + 0x20,
2788 bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, offset));
2789}
2790
2791static void bcm43xx_rate_memory_init(struct bcm43xx_private *bcm)
2792{
2793 switch (bcm43xx_current_phy(bcm)->type) {
2794 case BCM43xx_PHYTYPE_A:
2795 case BCM43xx_PHYTYPE_G:
2796 bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_6MB, 1);
2797 bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_12MB, 1);
2798 bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_18MB, 1);
2799 bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_24MB, 1);
2800 bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_36MB, 1);
2801 bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_48MB, 1);
2802 bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_54MB, 1);
2803 case BCM43xx_PHYTYPE_B:
2804 bcm43xx_rate_memory_write(bcm, IEEE80211_CCK_RATE_1MB, 0);
2805 bcm43xx_rate_memory_write(bcm, IEEE80211_CCK_RATE_2MB, 0);
2806 bcm43xx_rate_memory_write(bcm, IEEE80211_CCK_RATE_5MB, 0);
2807 bcm43xx_rate_memory_write(bcm, IEEE80211_CCK_RATE_11MB, 0);
2808 break;
2809 default:
2810 assert(0);
2811 }
2812}
2813
2814static void bcm43xx_wireless_core_cleanup(struct bcm43xx_private *bcm)
2815{
2816 bcm43xx_chip_cleanup(bcm);
2817 bcm43xx_pio_free(bcm);
2818 bcm43xx_dma_free(bcm);
2819
2820 bcm->current_core->initialized = 0;
2821}
2822
2823/* http://bcm-specs.sipsolutions.net/80211Init */
2824static int bcm43xx_wireless_core_init(struct bcm43xx_private *bcm)
2825{
2826 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
2827 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
2828 u32 ucodeflags;
2829 int err;
2830 u32 sbimconfiglow;
2831 u8 limit;
2832
2833 if (bcm->chip_rev < 5) {
2834 sbimconfiglow = bcm43xx_read32(bcm, BCM43xx_CIR_SBIMCONFIGLOW);
2835 sbimconfiglow &= ~ BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_MASK;
2836 sbimconfiglow &= ~ BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_MASK;
2837 if (bcm->bustype == BCM43xx_BUSTYPE_PCI)
2838 sbimconfiglow |= 0x32;
2839 else if (bcm->bustype == BCM43xx_BUSTYPE_SB)
2840 sbimconfiglow |= 0x53;
2841 else
2842 assert(0);
2843 bcm43xx_write32(bcm, BCM43xx_CIR_SBIMCONFIGLOW, sbimconfiglow);
2844 }
2845
2846 bcm43xx_phy_calibrate(bcm);
2847 err = bcm43xx_chip_init(bcm);
2848 if (err)
2849 goto out;
2850
2851 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0016, bcm->current_core->rev);
2852 ucodeflags = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, BCM43xx_UCODEFLAGS_OFFSET);
2853
2854 if (0 /*FIXME: which condition has to be used here? */)
2855 ucodeflags |= 0x00000010;
2856
2857 /* HW decryption needs to be set now */
2858 ucodeflags |= 0x40000000;
2859
2860 if (phy->type == BCM43xx_PHYTYPE_G) {
2861 ucodeflags |= BCM43xx_UCODEFLAG_UNKBGPHY;
2862 if (phy->rev == 1)
2863 ucodeflags |= BCM43xx_UCODEFLAG_UNKGPHY;
2864 if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL)
2865 ucodeflags |= BCM43xx_UCODEFLAG_UNKPACTRL;
2866 } else if (phy->type == BCM43xx_PHYTYPE_B) {
2867 ucodeflags |= BCM43xx_UCODEFLAG_UNKBGPHY;
2868 if (phy->rev >= 2 && radio->version == 0x2050)
2869 ucodeflags &= ~BCM43xx_UCODEFLAG_UNKGPHY;
2870 }
2871
2872 if (ucodeflags != bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED,
2873 BCM43xx_UCODEFLAGS_OFFSET)) {
2874 bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED,
2875 BCM43xx_UCODEFLAGS_OFFSET, ucodeflags);
2876 }
2877
2878 /* Short/Long Retry Limit.
2879 * The retry-limit is a 4-bit counter. Enforce this to avoid overflowing
2880 * the chip-internal counter.
2881 */
2882 limit = limit_value(modparam_short_retry, 0, 0xF);
2883 bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0006, limit);
2884 limit = limit_value(modparam_long_retry, 0, 0xF);
2885 bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0007, limit);
2886
2887 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0044, 3);
2888 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0046, 2);
2889
2890 bcm43xx_rate_memory_init(bcm);
2891
2892 /* Minimum Contention Window */
2893 if (phy->type == BCM43xx_PHYTYPE_B)
2894 bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0003, 0x0000001f);
2895 else
2896 bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0003, 0x0000000f);
2897 /* Maximum Contention Window */
2898 bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0004, 0x000003ff);
2899
2900 bcm43xx_gen_bssid(bcm);
2901 bcm43xx_write_mac_bssid_templates(bcm);
2902
2903 if (bcm->current_core->rev >= 5)
2904 bcm43xx_write16(bcm, 0x043C, 0x000C);
2905
2906 if (bcm43xx_using_pio(bcm))
2907 err = bcm43xx_pio_init(bcm);
2908 else
2909 err = bcm43xx_dma_init(bcm);
2910 if (err)
2911 goto err_chip_cleanup;
2912 bcm43xx_write16(bcm, 0x0612, 0x0050);
2913 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0416, 0x0050);
2914 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0414, 0x01F4);
2915
2916 bcm43xx_mac_enable(bcm);
2917 bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate);
2918
2919 bcm->current_core->initialized = 1;
2920out:
2921 return err;
2922
2923err_chip_cleanup:
2924 bcm43xx_chip_cleanup(bcm);
2925 goto out;
2926}
2927
2928static int bcm43xx_chipset_attach(struct bcm43xx_private *bcm)
2929{
2930 int err;
2931 u16 pci_status;
2932
2933 err = bcm43xx_pctl_set_crystal(bcm, 1);
2934 if (err)
2935 goto out;
2936 bcm43xx_pci_read_config16(bcm, PCI_STATUS, &pci_status);
2937 bcm43xx_pci_write_config16(bcm, PCI_STATUS, pci_status & ~PCI_STATUS_SIG_TARGET_ABORT);
2938
2939out:
2940 return err;
2941}
2942
2943static void bcm43xx_chipset_detach(struct bcm43xx_private *bcm)
2944{
2945 bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_SLOW);
2946 bcm43xx_pctl_set_crystal(bcm, 0);
2947}
2948
2949static void bcm43xx_pcicore_broadcast_value(struct bcm43xx_private *bcm,
2950 u32 address,
2951 u32 data)
2952{
2953 bcm43xx_write32(bcm, BCM43xx_PCICORE_BCAST_ADDR, address);
2954 bcm43xx_write32(bcm, BCM43xx_PCICORE_BCAST_DATA, data);
2955}
2956
2957static int bcm43xx_pcicore_commit_settings(struct bcm43xx_private *bcm)
2958{
2959 int err;
2960 struct bcm43xx_coreinfo *old_core;
2961
2962 old_core = bcm->current_core;
2963 err = bcm43xx_switch_core(bcm, &bcm->core_pci);
2964 if (err)
2965 goto out;
2966
2967 bcm43xx_pcicore_broadcast_value(bcm, 0xfd8, 0x00000000);
2968
2969 bcm43xx_switch_core(bcm, old_core);
2970 assert(err == 0);
2971out:
2972 return err;
2973}
2974
2975/* Make an I/O Core usable. "core_mask" is the bitmask of the cores to enable.
2976 * To enable core 0, pass a core_mask of 1<<0
2977 */
2978static int bcm43xx_setup_backplane_pci_connection(struct bcm43xx_private *bcm,
2979 u32 core_mask)
2980{
2981 u32 backplane_flag_nr;
2982 u32 value;
2983 struct bcm43xx_coreinfo *old_core;
2984 int err = 0;
2985
2986 value = bcm43xx_read32(bcm, BCM43xx_CIR_SBTPSFLAG);
2987 backplane_flag_nr = value & BCM43xx_BACKPLANE_FLAG_NR_MASK;
2988
2989 old_core = bcm->current_core;
2990 err = bcm43xx_switch_core(bcm, &bcm->core_pci);
2991 if (err)
2992 goto out;
2993
2994 if (bcm->core_pci.rev < 6) {
2995 value = bcm43xx_read32(bcm, BCM43xx_CIR_SBINTVEC);
2996 value |= (1 << backplane_flag_nr);
2997 bcm43xx_write32(bcm, BCM43xx_CIR_SBINTVEC, value);
2998 } else {
2999 err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCICFG_ICR, &value);
3000 if (err) {
3001 printk(KERN_ERR PFX "Error: ICR setup failure!\n");
3002 goto out_switch_back;
3003 }
3004 value |= core_mask << 8;
3005 err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_ICR, value);
3006 if (err) {
3007 printk(KERN_ERR PFX "Error: ICR setup failure!\n");
3008 goto out_switch_back;
3009 }
3010 }
3011
3012 value = bcm43xx_read32(bcm, BCM43xx_PCICORE_SBTOPCI2);
3013 value |= BCM43xx_SBTOPCI2_PREFETCH | BCM43xx_SBTOPCI2_BURST;
3014 bcm43xx_write32(bcm, BCM43xx_PCICORE_SBTOPCI2, value);
3015
3016 if (bcm->core_pci.rev < 5) {
3017 value = bcm43xx_read32(bcm, BCM43xx_CIR_SBIMCONFIGLOW);
3018 value |= (2 << BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_SHIFT)
3019 & BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_MASK;
3020 value |= (3 << BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_SHIFT)
3021 & BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_MASK;
3022 bcm43xx_write32(bcm, BCM43xx_CIR_SBIMCONFIGLOW, value);
3023 err = bcm43xx_pcicore_commit_settings(bcm);
3024 assert(err == 0);
3025 }
3026
3027out_switch_back:
3028 err = bcm43xx_switch_core(bcm, old_core);
3029out:
3030 return err;
3031}
3032
3033static void bcm43xx_softmac_init(struct bcm43xx_private *bcm)
3034{
3035 ieee80211softmac_start(bcm->net_dev);
3036}
3037
3038static void bcm43xx_periodic_every120sec(struct bcm43xx_private *bcm)
3039{
3040 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
3041
3042 if (phy->type != BCM43xx_PHYTYPE_G || phy->rev < 2)
3043 return;
3044
3045 bcm43xx_mac_suspend(bcm);
3046 bcm43xx_phy_lo_g_measure(bcm);
3047 bcm43xx_mac_enable(bcm);
3048}
3049
3050static void bcm43xx_periodic_every60sec(struct bcm43xx_private *bcm)
3051{
3052 bcm43xx_phy_lo_mark_all_unused(bcm);
3053 if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) {
3054 bcm43xx_mac_suspend(bcm);
3055 bcm43xx_calc_nrssi_slope(bcm);
3056 bcm43xx_mac_enable(bcm);
3057 }
3058}
3059
3060static void bcm43xx_periodic_every30sec(struct bcm43xx_private *bcm)
3061{
3062 /* Update device statistics. */
3063 bcm43xx_calculate_link_quality(bcm);
3064}
3065
3066static void bcm43xx_periodic_every15sec(struct bcm43xx_private *bcm)
3067{
3068 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
3069 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
3070
3071 if (phy->type == BCM43xx_PHYTYPE_G) {
3072 //TODO: update_aci_moving_average
3073 if (radio->aci_enable && radio->aci_wlan_automatic) {
3074 bcm43xx_mac_suspend(bcm);
3075 if (!radio->aci_enable && 1 /*TODO: not scanning? */) {
3076 if (0 /*TODO: bunch of conditions*/) {
3077 bcm43xx_radio_set_interference_mitigation(bcm,
3078 BCM43xx_RADIO_INTERFMODE_MANUALWLAN);
3079 }
3080 } else if (1/*TODO*/) {
3081 /*
3082 if ((aci_average > 1000) && !(bcm43xx_radio_aci_scan(bcm))) {
3083 bcm43xx_radio_set_interference_mitigation(bcm,
3084 BCM43xx_RADIO_INTERFMODE_NONE);
3085 }
3086 */
3087 }
3088 bcm43xx_mac_enable(bcm);
3089 } else if (radio->interfmode == BCM43xx_RADIO_INTERFMODE_NONWLAN &&
3090 phy->rev == 1) {
3091 //TODO: implement rev1 workaround
3092 }
3093 }
3094 bcm43xx_phy_xmitpower(bcm); //FIXME: unless scanning?
3095 //TODO for APHY (temperature?)
3096}
3097
3098static void bcm43xx_periodic_task_handler(unsigned long d)
3099{
3100 struct bcm43xx_private *bcm = (struct bcm43xx_private *)d;
3101 unsigned long flags;
3102 unsigned int state;
3103
3104 bcm43xx_lock_mmio(bcm, flags);
3105
3106 assert(bcm->initialized);
3107 state = bcm->periodic_state;
3108 if (state % 8 == 0)
3109 bcm43xx_periodic_every120sec(bcm);
3110 if (state % 4 == 0)
3111 bcm43xx_periodic_every60sec(bcm);
3112 if (state % 2 == 0)
3113 bcm43xx_periodic_every30sec(bcm);
3114 bcm43xx_periodic_every15sec(bcm);
3115 bcm->periodic_state = state + 1;
3116
3117 mod_timer(&bcm->periodic_tasks, jiffies + (HZ * 15));
3118
3119 bcm43xx_unlock_mmio(bcm, flags);
3120}
3121
3122static void bcm43xx_periodic_tasks_delete(struct bcm43xx_private *bcm)
3123{
3124 del_timer_sync(&bcm->periodic_tasks);
3125}
3126
3127static void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm)
3128{
3129 struct timer_list *timer = &(bcm->periodic_tasks);
3130
3131 assert(bcm->initialized);
3132 setup_timer(timer,
3133 bcm43xx_periodic_task_handler,
3134 (unsigned long)bcm);
3135 timer->expires = jiffies;
3136 add_timer(timer);
3137}
3138
3139static void bcm43xx_security_init(struct bcm43xx_private *bcm)
3140{
3141 bcm->security_offset = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED,
3142 0x0056) * 2;
3143 bcm43xx_clear_keys(bcm);
3144}
3145
3146/* This is the opposite of bcm43xx_init_board() */
3147static void bcm43xx_free_board(struct bcm43xx_private *bcm)
3148{
3149 int i, err;
3150 unsigned long flags;
3151
3152 bcm43xx_sysfs_unregister(bcm);
3153
3154 bcm43xx_periodic_tasks_delete(bcm);
3155
3156 bcm43xx_lock(bcm, flags);
3157 bcm->initialized = 0;
3158 bcm->shutting_down = 1;
3159 bcm43xx_unlock(bcm, flags);
3160
3161 for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) {
3162 if (!bcm->core_80211[i].available)
3163 continue;
3164 if (!bcm->core_80211[i].initialized)
3165 continue;
3166
3167 err = bcm43xx_switch_core(bcm, &bcm->core_80211[i]);
3168 assert(err == 0);
3169 bcm43xx_wireless_core_cleanup(bcm);
3170 }
3171
3172 bcm43xx_pctl_set_crystal(bcm, 0);
3173
3174 bcm43xx_lock(bcm, flags);
3175 bcm->shutting_down = 0;
3176 bcm43xx_unlock(bcm, flags);
3177}
3178
3179static int bcm43xx_init_board(struct bcm43xx_private *bcm)
3180{
3181 int i, err;
3182 int connect_phy;
3183 unsigned long flags;
3184
3185 might_sleep();
3186
3187 bcm43xx_lock(bcm, flags);
3188 bcm->initialized = 0;
3189 bcm->shutting_down = 0;
3190 bcm43xx_unlock(bcm, flags);
3191
3192 err = bcm43xx_pctl_set_crystal(bcm, 1);
3193 if (err)
3194 goto out;
3195 err = bcm43xx_pctl_init(bcm);
3196 if (err)
3197 goto err_crystal_off;
3198 err = bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_FAST);
3199 if (err)
3200 goto err_crystal_off;
3201
3202 tasklet_enable(&bcm->isr_tasklet);
3203 for (i = 0; i < bcm->nr_80211_available; i++) {
3204 err = bcm43xx_switch_core(bcm, &bcm->core_80211[i]);
3205 assert(err != -ENODEV);
3206 if (err)
3207 goto err_80211_unwind;
3208
3209 /* Enable the selected wireless core.
3210 * Connect PHY only on the first core.
3211 */
3212 if (!bcm43xx_core_enabled(bcm)) {
3213 if (bcm->nr_80211_available == 1) {
3214 connect_phy = bcm43xx_current_phy(bcm)->connected;
3215 } else {
3216 if (i == 0)
3217 connect_phy = 1;
3218 else
3219 connect_phy = 0;
3220 }
3221 bcm43xx_wireless_core_reset(bcm, connect_phy);
3222 }
3223
3224 if (i != 0)
3225 bcm43xx_wireless_core_mark_inactive(bcm, &bcm->core_80211[0]);
3226
3227 err = bcm43xx_wireless_core_init(bcm);
3228 if (err)
3229 goto err_80211_unwind;
3230
3231 if (i != 0) {
3232 bcm43xx_mac_suspend(bcm);
3233 bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
3234 bcm43xx_radio_turn_off(bcm);
3235 }
3236 }
3237 bcm->active_80211_core = &bcm->core_80211[0];
3238 if (bcm->nr_80211_available >= 2) {
3239 bcm43xx_switch_core(bcm, &bcm->core_80211[0]);
3240 bcm43xx_mac_enable(bcm);
3241 }
3242 bcm43xx_macfilter_clear(bcm, BCM43xx_MACFILTER_ASSOC);
3243 bcm43xx_macfilter_set(bcm, BCM43xx_MACFILTER_SELF, (u8 *)(bcm->net_dev->dev_addr));
3244 dprintk(KERN_INFO PFX "80211 cores initialized\n");
3245 bcm43xx_security_init(bcm);
3246 bcm43xx_softmac_init(bcm);
3247
3248 bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_DYNAMIC);
3249
3250 if (bcm43xx_current_radio(bcm)->initial_channel != 0xFF) {
3251 bcm43xx_mac_suspend(bcm);
3252 bcm43xx_radio_selectchannel(bcm, bcm43xx_current_radio(bcm)->initial_channel, 0);
3253 bcm43xx_mac_enable(bcm);
3254 }
3255
3256 /* Initialization of the board is done. Flag it as such. */
3257 bcm43xx_lock(bcm, flags);
3258 bcm->initialized = 1;
3259 bcm43xx_unlock(bcm, flags);
3260
3261 bcm43xx_periodic_tasks_setup(bcm);
3262 bcm43xx_sysfs_register(bcm);
3263 //FIXME: check for bcm43xx_sysfs_register failure. This function is a bit messy regarding unwinding, though...
3264
3265 assert(err == 0);
3266out:
3267 return err;
3268
3269err_80211_unwind:
3270 tasklet_disable(&bcm->isr_tasklet);
3271 /* unwind all 80211 initialization */
3272 for (i = 0; i < bcm->nr_80211_available; i++) {
3273 if (!bcm->core_80211[i].initialized)
3274 continue;
3275 bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
3276 bcm43xx_wireless_core_cleanup(bcm);
3277 }
3278err_crystal_off:
3279 bcm43xx_pctl_set_crystal(bcm, 0);
3280 goto out;
3281}
3282
3283static void bcm43xx_detach_board(struct bcm43xx_private *bcm)
3284{
3285 struct pci_dev *pci_dev = bcm->pci_dev;
3286 int i;
3287
3288 bcm43xx_chipset_detach(bcm);
3289 /* Do _not_ access the chip, after it is detached. */
3290 iounmap(bcm->mmio_addr);
3291
3292 pci_release_regions(pci_dev);
3293 pci_disable_device(pci_dev);
3294
3295 /* Free allocated structures/fields */
3296 for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) {
3297 kfree(bcm->core_80211_ext[i].phy._lo_pairs);
3298 if (bcm->core_80211_ext[i].phy.dyn_tssi_tbl)
3299 kfree(bcm->core_80211_ext[i].phy.tssi2dbm);
3300 }
3301}
3302
3303static int bcm43xx_read_phyinfo(struct bcm43xx_private *bcm)
3304{
3305 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
3306 u16 value;
3307 u8 phy_version;
3308 u8 phy_type;
3309 u8 phy_rev;
3310 int phy_rev_ok = 1;
3311 void *p;
3312
3313 value = bcm43xx_read16(bcm, BCM43xx_MMIO_PHY_VER);
3314
3315 phy_version = (value & 0xF000) >> 12;
3316 phy_type = (value & 0x0F00) >> 8;
3317 phy_rev = (value & 0x000F);
3318
3319 dprintk(KERN_INFO PFX "Detected PHY: Version: %x, Type %x, Revision %x\n",
3320 phy_version, phy_type, phy_rev);
3321
3322 switch (phy_type) {
3323 case BCM43xx_PHYTYPE_A:
3324 if (phy_rev >= 4)
3325 phy_rev_ok = 0;
3326 /*FIXME: We need to switch the ieee->modulation, etc.. flags,
3327 * if we switch 80211 cores after init is done.
3328 * As we do not implement on the fly switching between
3329 * wireless cores, I will leave this as a future task.
3330 */
3331 bcm->ieee->modulation = IEEE80211_OFDM_MODULATION;
3332 bcm->ieee->mode = IEEE_A;
3333 bcm->ieee->freq_band = IEEE80211_52GHZ_BAND |
3334 IEEE80211_24GHZ_BAND;
3335 break;
3336 case BCM43xx_PHYTYPE_B:
3337 if (phy_rev != 2 && phy_rev != 4 && phy_rev != 6 && phy_rev != 7)
3338 phy_rev_ok = 0;
3339 bcm->ieee->modulation = IEEE80211_CCK_MODULATION;
3340 bcm->ieee->mode = IEEE_B;
3341 bcm->ieee->freq_band = IEEE80211_24GHZ_BAND;
3342 break;
3343 case BCM43xx_PHYTYPE_G:
3344 if (phy_rev > 7)
3345 phy_rev_ok = 0;
3346 bcm->ieee->modulation = IEEE80211_OFDM_MODULATION |
3347 IEEE80211_CCK_MODULATION;
3348 bcm->ieee->mode = IEEE_G;
3349 bcm->ieee->freq_band = IEEE80211_24GHZ_BAND;
3350 break;
3351 default:
3352 printk(KERN_ERR PFX "Error: Unknown PHY Type %x\n",
3353 phy_type);
3354 return -ENODEV;
3355 };
3356 if (!phy_rev_ok) {
3357 printk(KERN_WARNING PFX "Invalid PHY Revision %x\n",
3358 phy_rev);
3359 }
3360
3361 phy->version = phy_version;
3362 phy->type = phy_type;
3363 phy->rev = phy_rev;
3364 if ((phy_type == BCM43xx_PHYTYPE_B) || (phy_type == BCM43xx_PHYTYPE_G)) {
3365 p = kzalloc(sizeof(struct bcm43xx_lopair) * BCM43xx_LO_COUNT,
3366 GFP_KERNEL);
3367 if (!p)
3368 return -ENOMEM;
3369 phy->_lo_pairs = p;
3370 }
3371
3372 return 0;
3373}
3374
3375static int bcm43xx_attach_board(struct bcm43xx_private *bcm)
3376{
3377 struct pci_dev *pci_dev = bcm->pci_dev;
3378 struct net_device *net_dev = bcm->net_dev;
3379 int err;
3380 int i;
3381 unsigned long mmio_start, mmio_flags, mmio_len;
3382 u32 coremask;
3383
3384 err = pci_enable_device(pci_dev);
3385 if (err) {
3386 printk(KERN_ERR PFX "unable to wake up pci device (%i)\n", err);
3387 goto out;
3388 }
3389 mmio_start = pci_resource_start(pci_dev, 0);
3390 mmio_flags = pci_resource_flags(pci_dev, 0);
3391 mmio_len = pci_resource_len(pci_dev, 0);
3392 if (!(mmio_flags & IORESOURCE_MEM)) {
3393 printk(KERN_ERR PFX
3394 "%s, region #0 not an MMIO resource, aborting\n",
3395 pci_name(pci_dev));
3396 err = -ENODEV;
3397 goto err_pci_disable;
3398 }
3399 err = pci_request_regions(pci_dev, KBUILD_MODNAME);
3400 if (err) {
3401 printk(KERN_ERR PFX
3402 "could not access PCI resources (%i)\n", err);
3403 goto err_pci_disable;
3404 }
3405 /* enable PCI bus-mastering */
3406 pci_set_master(pci_dev);
3407 bcm->mmio_addr = ioremap(mmio_start, mmio_len);
3408 if (!bcm->mmio_addr) {
3409 printk(KERN_ERR PFX "%s: cannot remap MMIO, aborting\n",
3410 pci_name(pci_dev));
3411 err = -EIO;
3412 goto err_pci_release;
3413 }
3414 bcm->mmio_len = mmio_len;
3415 net_dev->base_addr = (unsigned long)bcm->mmio_addr;
3416
3417 bcm43xx_pci_read_config16(bcm, PCI_SUBSYSTEM_VENDOR_ID,
3418 &bcm->board_vendor);
3419 bcm43xx_pci_read_config16(bcm, PCI_SUBSYSTEM_ID,
3420 &bcm->board_type);
3421 bcm43xx_pci_read_config16(bcm, PCI_REVISION_ID,
3422 &bcm->board_revision);
3423
3424 err = bcm43xx_chipset_attach(bcm);
3425 if (err)
3426 goto err_iounmap;
3427 err = bcm43xx_pctl_init(bcm);
3428 if (err)
3429 goto err_chipset_detach;
3430 err = bcm43xx_probe_cores(bcm);
3431 if (err)
3432 goto err_chipset_detach;
3433
3434 /* Attach all IO cores to the backplane. */
3435 coremask = 0;
3436 for (i = 0; i < bcm->nr_80211_available; i++)
3437 coremask |= (1 << bcm->core_80211[i].index);
3438 //FIXME: Also attach some non80211 cores?
3439 err = bcm43xx_setup_backplane_pci_connection(bcm, coremask);
3440 if (err) {
3441 printk(KERN_ERR PFX "Backplane->PCI connection failed!\n");
3442 goto err_chipset_detach;
3443 }
3444
3445 err = bcm43xx_sprom_extract(bcm);
3446 if (err)
3447 goto err_chipset_detach;
3448 err = bcm43xx_leds_init(bcm);
3449 if (err)
3450 goto err_chipset_detach;
3451
3452 for (i = 0; i < bcm->nr_80211_available; i++) {
3453 err = bcm43xx_switch_core(bcm, &bcm->core_80211[i]);
3454 assert(err != -ENODEV);
3455 if (err)
3456 goto err_80211_unwind;
3457
3458 /* Enable the selected wireless core.
3459 * Connect PHY only on the first core.
3460 */
3461 bcm43xx_wireless_core_reset(bcm, (i == 0));
3462
3463 err = bcm43xx_read_phyinfo(bcm);
3464 if (err && (i == 0))
3465 goto err_80211_unwind;
3466
3467 err = bcm43xx_read_radioinfo(bcm);
3468 if (err && (i == 0))
3469 goto err_80211_unwind;
3470
3471 err = bcm43xx_validate_chip(bcm);
3472 if (err && (i == 0))
3473 goto err_80211_unwind;
3474
3475 bcm43xx_radio_turn_off(bcm);
3476 err = bcm43xx_phy_init_tssi2dbm_table(bcm);
3477 if (err)
3478 goto err_80211_unwind;
3479 bcm43xx_wireless_core_disable(bcm);
3480 }
3481 bcm43xx_pctl_set_crystal(bcm, 0);
3482
3483 /* Set the MAC address in the networking subsystem */
3484 if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A)
3485 memcpy(bcm->net_dev->dev_addr, bcm->sprom.et1macaddr, 6);
3486 else
3487 memcpy(bcm->net_dev->dev_addr, bcm->sprom.il0macaddr, 6);
3488
3489 bcm43xx_geo_init(bcm);
3490
3491 snprintf(bcm->nick, IW_ESSID_MAX_SIZE,
3492 "Broadcom %04X", bcm->chip_id);
3493
3494 assert(err == 0);
3495out:
3496 return err;
3497
3498err_80211_unwind:
3499 for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) {
3500 kfree(bcm->core_80211_ext[i].phy._lo_pairs);
3501 if (bcm->core_80211_ext[i].phy.dyn_tssi_tbl)
3502 kfree(bcm->core_80211_ext[i].phy.tssi2dbm);
3503 }
3504err_chipset_detach:
3505 bcm43xx_chipset_detach(bcm);
3506err_iounmap:
3507 iounmap(bcm->mmio_addr);
3508err_pci_release:
3509 pci_release_regions(pci_dev);
3510err_pci_disable:
3511 pci_disable_device(pci_dev);
3512 goto out;
3513}
3514
3515/* Do the Hardware IO operations to send the txb */
3516static inline int bcm43xx_tx(struct bcm43xx_private *bcm,
3517 struct ieee80211_txb *txb)
3518{
3519 int err = -ENODEV;
3520
3521 if (bcm43xx_using_pio(bcm))
3522 err = bcm43xx_pio_tx(bcm, txb);
3523 else
3524 err = bcm43xx_dma_tx(bcm, txb);
3525
3526 return err;
3527}
3528
3529static void bcm43xx_ieee80211_set_chan(struct net_device *net_dev,
3530 u8 channel)
3531{
3532 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
3533 struct bcm43xx_radioinfo *radio;
3534 unsigned long flags;
3535
3536 bcm43xx_lock_mmio(bcm, flags);
3537 if (bcm->initialized) {
3538 bcm43xx_mac_suspend(bcm);
3539 bcm43xx_radio_selectchannel(bcm, channel, 0);
3540 bcm43xx_mac_enable(bcm);
3541 } else {
3542 radio = bcm43xx_current_radio(bcm);
3543 radio->initial_channel = channel;
3544 }
3545 bcm43xx_unlock_mmio(bcm, flags);
3546}
3547
3548/* set_security() callback in struct ieee80211_device */
3549static void bcm43xx_ieee80211_set_security(struct net_device *net_dev,
3550 struct ieee80211_security *sec)
3551{
3552 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
3553 struct ieee80211_security *secinfo = &bcm->ieee->sec;
3554 unsigned long flags;
3555 int keyidx;
3556
3557 dprintk(KERN_INFO PFX "set security called\n");
3558
3559 bcm43xx_lock_mmio(bcm, flags);
3560
3561 for (keyidx = 0; keyidx<WEP_KEYS; keyidx++)
3562 if (sec->flags & (1<<keyidx)) {
3563 secinfo->encode_alg[keyidx] = sec->encode_alg[keyidx];
3564 secinfo->key_sizes[keyidx] = sec->key_sizes[keyidx];
3565 memcpy(secinfo->keys[keyidx], sec->keys[keyidx], SCM_KEY_LEN);
3566 }
3567
3568 if (sec->flags & SEC_ACTIVE_KEY) {
3569 secinfo->active_key = sec->active_key;
3570 dprintk(KERN_INFO PFX " .active_key = %d\n", sec->active_key);
3571 }
3572 if (sec->flags & SEC_UNICAST_GROUP) {
3573 secinfo->unicast_uses_group = sec->unicast_uses_group;
3574 dprintk(KERN_INFO PFX " .unicast_uses_group = %d\n", sec->unicast_uses_group);
3575 }
3576 if (sec->flags & SEC_LEVEL) {
3577 secinfo->level = sec->level;
3578 dprintk(KERN_INFO PFX " .level = %d\n", sec->level);
3579 }
3580 if (sec->flags & SEC_ENABLED) {
3581 secinfo->enabled = sec->enabled;
3582 dprintk(KERN_INFO PFX " .enabled = %d\n", sec->enabled);
3583 }
3584 if (sec->flags & SEC_ENCRYPT) {
3585 secinfo->encrypt = sec->encrypt;
3586 dprintk(KERN_INFO PFX " .encrypt = %d\n", sec->encrypt);
3587 }
3588 if (bcm->initialized && !bcm->ieee->host_encrypt) {
3589 if (secinfo->enabled) {
3590 /* upload WEP keys to hardware */
3591 char null_address[6] = { 0 };
3592 u8 algorithm = 0;
3593 for (keyidx = 0; keyidx<WEP_KEYS; keyidx++) {
3594 if (!(sec->flags & (1<<keyidx)))
3595 continue;
3596 switch (sec->encode_alg[keyidx]) {
3597 case SEC_ALG_NONE: algorithm = BCM43xx_SEC_ALGO_NONE; break;
3598 case SEC_ALG_WEP:
3599 algorithm = BCM43xx_SEC_ALGO_WEP;
3600 if (secinfo->key_sizes[keyidx] == 13)
3601 algorithm = BCM43xx_SEC_ALGO_WEP104;
3602 break;
3603 case SEC_ALG_TKIP:
3604 FIXME();
3605 algorithm = BCM43xx_SEC_ALGO_TKIP;
3606 break;
3607 case SEC_ALG_CCMP:
3608 FIXME();
3609 algorithm = BCM43xx_SEC_ALGO_AES;
3610 break;
3611 default:
3612 assert(0);
3613 break;
3614 }
3615 bcm43xx_key_write(bcm, keyidx, algorithm, sec->keys[keyidx], secinfo->key_sizes[keyidx], &null_address[0]);
3616 bcm->key[keyidx].enabled = 1;
3617 bcm->key[keyidx].algorithm = algorithm;
3618 }
3619 } else
3620 bcm43xx_clear_keys(bcm);
3621 }
3622 bcm43xx_unlock_mmio(bcm, flags);
3623}
3624
3625/* hard_start_xmit() callback in struct ieee80211_device */
3626static int bcm43xx_ieee80211_hard_start_xmit(struct ieee80211_txb *txb,
3627 struct net_device *net_dev,
3628 int pri)
3629{
3630 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
3631 int err = -ENODEV;
3632 unsigned long flags;
3633
3634 bcm43xx_lock_mmio(bcm, flags);
3635 if (likely(bcm->initialized))
3636 err = bcm43xx_tx(bcm, txb);
3637 bcm43xx_unlock_mmio(bcm, flags);
3638
3639 return err;
3640}
3641
3642static struct net_device_stats * bcm43xx_net_get_stats(struct net_device *net_dev)
3643{
3644 return &(bcm43xx_priv(net_dev)->ieee->stats);
3645}
3646
3647static void bcm43xx_net_tx_timeout(struct net_device *net_dev)
3648{
3649 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
3650 unsigned long flags;
3651
3652 bcm43xx_lock_mmio(bcm, flags);
3653 bcm43xx_controller_restart(bcm, "TX timeout");
3654 bcm43xx_unlock_mmio(bcm, flags);
3655}
3656
3657#ifdef CONFIG_NET_POLL_CONTROLLER
3658static void bcm43xx_net_poll_controller(struct net_device *net_dev)
3659{
3660 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
3661 unsigned long flags;
3662
3663 local_irq_save(flags);
3664 bcm43xx_interrupt_handler(bcm->irq, bcm, NULL);
3665 local_irq_restore(flags);
3666}
3667#endif /* CONFIG_NET_POLL_CONTROLLER */
3668
3669static int bcm43xx_net_open(struct net_device *net_dev)
3670{
3671 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
3672
3673 return bcm43xx_init_board(bcm);
3674}
3675
3676static int bcm43xx_net_stop(struct net_device *net_dev)
3677{
3678 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
3679
3680 ieee80211softmac_stop(net_dev);
3681 bcm43xx_disable_interrupts_sync(bcm, NULL);
3682 bcm43xx_free_board(bcm);
3683
3684 return 0;
3685}
3686
3687static int bcm43xx_init_private(struct bcm43xx_private *bcm,
3688 struct net_device *net_dev,
3689 struct pci_dev *pci_dev)
3690{
3691 int err;
3692
3693 bcm->ieee = netdev_priv(net_dev);
3694 bcm->softmac = ieee80211_priv(net_dev);
3695 bcm->softmac->set_channel = bcm43xx_ieee80211_set_chan;
3696
3697 bcm->irq_savedstate = BCM43xx_IRQ_INITIAL;
3698 bcm->pci_dev = pci_dev;
3699 bcm->net_dev = net_dev;
3700 bcm->bad_frames_preempt = modparam_bad_frames_preempt;
3701 spin_lock_init(&bcm->_lock);
3702 tasklet_init(&bcm->isr_tasklet,
3703 (void (*)(unsigned long))bcm43xx_interrupt_tasklet,
3704 (unsigned long)bcm);
3705 tasklet_disable_nosync(&bcm->isr_tasklet);
3706 if (modparam_pio) {
3707 bcm->__using_pio = 1;
3708 } else {
3709 err = pci_set_dma_mask(pci_dev, DMA_30BIT_MASK);
3710 err |= pci_set_consistent_dma_mask(pci_dev, DMA_30BIT_MASK);
3711 if (err) {
3712#ifdef CONFIG_BCM43XX_PIO
3713 printk(KERN_WARNING PFX "DMA not supported. Falling back to PIO.\n");
3714 bcm->__using_pio = 1;
3715#else
3716 printk(KERN_ERR PFX "FATAL: DMA not supported and PIO not configured. "
3717 "Recompile the driver with PIO support, please.\n");
3718 return -ENODEV;
3719#endif /* CONFIG_BCM43XX_PIO */
3720 }
3721 }
3722 bcm->rts_threshold = BCM43xx_DEFAULT_RTS_THRESHOLD;
3723
3724 /* default to sw encryption for now */
3725 bcm->ieee->host_build_iv = 0;
3726 bcm->ieee->host_encrypt = 1;
3727 bcm->ieee->host_decrypt = 1;
3728
3729 bcm->ieee->iw_mode = BCM43xx_INITIAL_IWMODE;
3730 bcm->ieee->tx_headroom = sizeof(struct bcm43xx_txhdr);
3731 bcm->ieee->set_security = bcm43xx_ieee80211_set_security;
3732 bcm->ieee->hard_start_xmit = bcm43xx_ieee80211_hard_start_xmit;
3733
3734 return 0;
3735}
3736
3737static int __devinit bcm43xx_init_one(struct pci_dev *pdev,
3738 const struct pci_device_id *ent)
3739{
3740 struct net_device *net_dev;
3741 struct bcm43xx_private *bcm;
3742 int err;
3743
3744#ifdef CONFIG_BCM947XX
3745 if ((pdev->bus->number == 0) && (pdev->device != 0x0800))
3746 return -ENODEV;
3747#endif
3748
3749#ifdef DEBUG_SINGLE_DEVICE_ONLY
3750 if (strcmp(pci_name(pdev), DEBUG_SINGLE_DEVICE_ONLY))
3751 return -ENODEV;
3752#endif
3753
3754 net_dev = alloc_ieee80211softmac(sizeof(*bcm));
3755 if (!net_dev) {
3756 printk(KERN_ERR PFX
3757 "could not allocate ieee80211 device %s\n",
3758 pci_name(pdev));
3759 err = -ENOMEM;
3760 goto out;
3761 }
3762 /* initialize the net_device struct */
3763 SET_MODULE_OWNER(net_dev);
3764 SET_NETDEV_DEV(net_dev, &pdev->dev);
3765
3766 net_dev->open = bcm43xx_net_open;
3767 net_dev->stop = bcm43xx_net_stop;
3768 net_dev->get_stats = bcm43xx_net_get_stats;
3769 net_dev->tx_timeout = bcm43xx_net_tx_timeout;
3770#ifdef CONFIG_NET_POLL_CONTROLLER
3771 net_dev->poll_controller = bcm43xx_net_poll_controller;
3772#endif
3773 net_dev->wireless_handlers = &bcm43xx_wx_handlers_def;
3774 net_dev->irq = pdev->irq;
3775 SET_ETHTOOL_OPS(net_dev, &bcm43xx_ethtool_ops);
3776
3777 /* initialize the bcm43xx_private struct */
3778 bcm = bcm43xx_priv(net_dev);
3779 memset(bcm, 0, sizeof(*bcm));
3780 err = bcm43xx_init_private(bcm, net_dev, pdev);
3781 if (err)
3782 goto err_free_netdev;
3783
3784 pci_set_drvdata(pdev, net_dev);
3785
3786 err = bcm43xx_attach_board(bcm);
3787 if (err)
3788 goto err_free_netdev;
3789
3790 err = register_netdev(net_dev);
3791 if (err) {
3792 printk(KERN_ERR PFX "Cannot register net device, "
3793 "aborting.\n");
3794 err = -ENOMEM;
3795 goto err_detach_board;
3796 }
3797
3798 bcm43xx_debugfs_add_device(bcm);
3799
3800 assert(err == 0);
3801out:
3802 return err;
3803
3804err_detach_board:
3805 bcm43xx_detach_board(bcm);
3806err_free_netdev:
3807 free_ieee80211softmac(net_dev);
3808 goto out;
3809}
3810
3811static void __devexit bcm43xx_remove_one(struct pci_dev *pdev)
3812{
3813 struct net_device *net_dev = pci_get_drvdata(pdev);
3814 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
3815
3816 bcm43xx_debugfs_remove_device(bcm);
3817 unregister_netdev(net_dev);
3818 bcm43xx_detach_board(bcm);
3819 assert(bcm->ucode == NULL);
3820 free_ieee80211softmac(net_dev);
3821}
3822
3823/* Hard-reset the chip. Do not call this directly.
3824 * Use bcm43xx_controller_restart()
3825 */
3826static void bcm43xx_chip_reset(void *_bcm)
3827{
3828 struct bcm43xx_private *bcm = _bcm;
3829 struct net_device *net_dev = bcm->net_dev;
3830 struct pci_dev *pci_dev = bcm->pci_dev;
3831 int err;
3832 int was_initialized = bcm->initialized;
3833
3834 netif_stop_queue(bcm->net_dev);
3835 tasklet_disable(&bcm->isr_tasklet);
3836
3837 bcm->firmware_norelease = 1;
3838 if (was_initialized)
3839 bcm43xx_free_board(bcm);
3840 bcm->firmware_norelease = 0;
3841 bcm43xx_detach_board(bcm);
3842 err = bcm43xx_init_private(bcm, net_dev, pci_dev);
3843 if (err)
3844 goto failure;
3845 err = bcm43xx_attach_board(bcm);
3846 if (err)
3847 goto failure;
3848 if (was_initialized) {
3849 err = bcm43xx_init_board(bcm);
3850 if (err)
3851 goto failure;
3852 }
3853 netif_wake_queue(bcm->net_dev);
3854 printk(KERN_INFO PFX "Controller restarted\n");
3855
3856 return;
3857failure:
3858 printk(KERN_ERR PFX "Controller restart failed\n");
3859}
3860
3861/* Hard-reset the chip.
3862 * This can be called from interrupt or process context.
3863 * Make sure to _not_ re-enable device interrupts after this has been called.
3864*/
3865void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason)
3866{
3867 bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
3868 bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* dummy read */
3869 printk(KERN_ERR PFX "Controller RESET (%s) ...\n", reason);
3870 INIT_WORK(&bcm->restart_work, bcm43xx_chip_reset, bcm);
3871 schedule_work(&bcm->restart_work);
3872}
3873
3874#ifdef CONFIG_PM
3875
3876static int bcm43xx_suspend(struct pci_dev *pdev, pm_message_t state)
3877{
3878 struct net_device *net_dev = pci_get_drvdata(pdev);
3879 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
3880 unsigned long flags;
3881 int try_to_shutdown = 0, err;
3882
3883 dprintk(KERN_INFO PFX "Suspending...\n");
3884
3885 bcm43xx_lock(bcm, flags);
3886 bcm->was_initialized = bcm->initialized;
3887 if (bcm->initialized)
3888 try_to_shutdown = 1;
3889 bcm43xx_unlock(bcm, flags);
3890
3891 netif_device_detach(net_dev);
3892 if (try_to_shutdown) {
3893 ieee80211softmac_stop(net_dev);
3894 err = bcm43xx_disable_interrupts_sync(bcm, &bcm->irq_savedstate);
3895 if (unlikely(err)) {
3896 dprintk(KERN_ERR PFX "Suspend failed.\n");
3897 return -EAGAIN;
3898 }
3899 bcm->firmware_norelease = 1;
3900 bcm43xx_free_board(bcm);
3901 bcm->firmware_norelease = 0;
3902 }
3903 bcm43xx_chipset_detach(bcm);
3904
3905 pci_save_state(pdev);
3906 pci_disable_device(pdev);
3907 pci_set_power_state(pdev, pci_choose_state(pdev, state));
3908
3909 dprintk(KERN_INFO PFX "Device suspended.\n");
3910
3911 return 0;
3912}
3913
3914static int bcm43xx_resume(struct pci_dev *pdev)
3915{
3916 struct net_device *net_dev = pci_get_drvdata(pdev);
3917 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
3918 int err = 0;
3919
3920 dprintk(KERN_INFO PFX "Resuming...\n");
3921
3922 pci_set_power_state(pdev, 0);
3923 pci_enable_device(pdev);
3924 pci_restore_state(pdev);
3925
3926 bcm43xx_chipset_attach(bcm);
3927 if (bcm->was_initialized) {
3928 bcm->irq_savedstate = BCM43xx_IRQ_INITIAL;
3929 err = bcm43xx_init_board(bcm);
3930 }
3931 if (err) {
3932 printk(KERN_ERR PFX "Resume failed!\n");
3933 return err;
3934 }
3935
3936 netif_device_attach(net_dev);
3937
3938 /*FIXME: This should be handled by softmac instead. */
3939 schedule_work(&bcm->softmac->associnfo.work);
3940
3941 dprintk(KERN_INFO PFX "Device resumed.\n");
3942
3943 return 0;
3944}
3945
3946#endif /* CONFIG_PM */
3947
3948static struct pci_driver bcm43xx_pci_driver = {
3949 .name = KBUILD_MODNAME,
3950 .id_table = bcm43xx_pci_tbl,
3951 .probe = bcm43xx_init_one,
3952 .remove = __devexit_p(bcm43xx_remove_one),
3953#ifdef CONFIG_PM
3954 .suspend = bcm43xx_suspend,
3955 .resume = bcm43xx_resume,
3956#endif /* CONFIG_PM */
3957};
3958
3959static int __init bcm43xx_init(void)
3960{
3961 printk(KERN_INFO KBUILD_MODNAME " driver\n");
3962 bcm43xx_debugfs_init();
3963 return pci_register_driver(&bcm43xx_pci_driver);
3964}
3965
3966static void __exit bcm43xx_exit(void)
3967{
3968 pci_unregister_driver(&bcm43xx_pci_driver);
3969 bcm43xx_debugfs_exit();
3970}
3971
3972module_init(bcm43xx_init)
3973module_exit(bcm43xx_exit)
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.h b/drivers/net/wireless/bcm43xx/bcm43xx_main.h
new file mode 100644
index 000000000000..eca79a38594a
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.h
@@ -0,0 +1,168 @@
1/*
2
3 Broadcom BCM43xx wireless driver
4
5 Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
6 Stefano Brivio <st3@riseup.net>
7 Michael Buesch <mbuesch@freenet.de>
8 Danny van Dyk <kugelfang@gentoo.org>
9 Andreas Jaggi <andreas.jaggi@waterwave.ch>
10
11 Some parts of the code in this file are derived from the ipw2200
12 driver Copyright(c) 2003 - 2004 Intel Corporation.
13
14 This program is free software; you can redistribute it and/or modify
15 it under the terms of the GNU General Public License as published by
16 the Free Software Foundation; either version 2 of the License, or
17 (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; see the file COPYING. If not, write to
26 the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
27 Boston, MA 02110-1301, USA.
28
29*/
30
31#ifndef BCM43xx_MAIN_H_
32#define BCM43xx_MAIN_H_
33
34#include "bcm43xx.h"
35
36#ifdef CONFIG_BCM947XX
37#define atoi(str) simple_strtoul(((str != NULL) ? str : ""), NULL, 0)
38
39static inline void e_aton(char *str, char *dest)
40{
41 int i = 0;
42 u16 *d = (u16 *) dest;
43
44 for (;;) {
45 dest[i++] = (char) simple_strtoul(str, NULL, 16);
46 str += 2;
47 if (!*str++ || i == 6)
48 break;
49 }
50 for (i = 0; i < 3; i++)
51 d[i] = cpu_to_be16(d[i]);
52}
53#endif
54
55#define P4D_BYT3S(magic, nr_bytes) u8 __p4dding##magic[nr_bytes]
56#define P4D_BYTES(line, nr_bytes) P4D_BYT3S(line, nr_bytes)
57/* Magic helper macro to pad structures. Ignore those above. It's magic. */
58#define PAD_BYTES(nr_bytes) P4D_BYTES( __LINE__ , (nr_bytes))
59
60
61/* Lightweight function to convert a frequency (in Mhz) to a channel number. */
62static inline
63u8 bcm43xx_freq_to_channel_a(int freq)
64{
65 return ((freq - 5000) / 5);
66}
67static inline
68u8 bcm43xx_freq_to_channel_bg(int freq)
69{
70 u8 channel;
71
72 if (freq == 2484)
73 channel = 14;
74 else
75 channel = (freq - 2407) / 5;
76
77 return channel;
78}
79static inline
80u8 bcm43xx_freq_to_channel(struct bcm43xx_private *bcm,
81 int freq)
82{
83 if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A)
84 return bcm43xx_freq_to_channel_a(freq);
85 return bcm43xx_freq_to_channel_bg(freq);
86}
87
88/* Lightweight function to convert a channel number to a frequency (in Mhz). */
89static inline
90int bcm43xx_channel_to_freq_a(u8 channel)
91{
92 return (5000 + (5 * channel));
93}
94static inline
95int bcm43xx_channel_to_freq_bg(u8 channel)
96{
97 int freq;
98
99 if (channel == 14)
100 freq = 2484;
101 else
102 freq = 2407 + (5 * channel);
103
104 return freq;
105}
106static inline
107int bcm43xx_channel_to_freq(struct bcm43xx_private *bcm,
108 u8 channel)
109{
110 if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A)
111 return bcm43xx_channel_to_freq_a(channel);
112 return bcm43xx_channel_to_freq_bg(channel);
113}
114
115/* Lightweight function to check if a channel number is valid.
116 * Note that this does _NOT_ check for geographical restrictions!
117 */
118static inline
119int bcm43xx_is_valid_channel_a(u8 channel)
120{
121 return (channel <= 200);
122}
123static inline
124int bcm43xx_is_valid_channel_bg(u8 channel)
125{
126 return (channel >= 1 && channel <= 14);
127}
128static inline
129int bcm43xx_is_valid_channel(struct bcm43xx_private *bcm,
130 u8 channel)
131{
132 if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A)
133 return bcm43xx_is_valid_channel_a(channel);
134 return bcm43xx_is_valid_channel_bg(channel);
135}
136
137void bcm43xx_tsf_read(struct bcm43xx_private *bcm, u64 *tsf);
138void bcm43xx_tsf_write(struct bcm43xx_private *bcm, u64 tsf);
139
140void bcm43xx_set_iwmode(struct bcm43xx_private *bcm,
141 int iw_mode);
142
143u32 bcm43xx_shm_read32(struct bcm43xx_private *bcm,
144 u16 routing, u16 offset);
145u16 bcm43xx_shm_read16(struct bcm43xx_private *bcm,
146 u16 routing, u16 offset);
147void bcm43xx_shm_write32(struct bcm43xx_private *bcm,
148 u16 routing, u16 offset,
149 u32 value);
150void bcm43xx_shm_write16(struct bcm43xx_private *bcm,
151 u16 routing, u16 offset,
152 u16 value);
153
154void bcm43xx_dummy_transmission(struct bcm43xx_private *bcm);
155
156int bcm43xx_switch_core(struct bcm43xx_private *bcm, struct bcm43xx_coreinfo *new_core);
157
158void bcm43xx_wireless_core_reset(struct bcm43xx_private *bcm, int connect_phy);
159
160void bcm43xx_mac_suspend(struct bcm43xx_private *bcm);
161void bcm43xx_mac_enable(struct bcm43xx_private *bcm);
162
163void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason);
164
165int bcm43xx_sprom_read(struct bcm43xx_private *bcm, u16 *sprom);
166int bcm43xx_sprom_write(struct bcm43xx_private *bcm, const u16 *sprom);
167
168#endif /* BCM43xx_MAIN_H_ */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
new file mode 100644
index 000000000000..0a66f43ca0c0
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
@@ -0,0 +1,2345 @@
1/*
2
3 Broadcom BCM43xx wireless driver
4
5 Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
6 Stefano Brivio <st3@riseup.net>
7 Michael Buesch <mbuesch@freenet.de>
8 Danny van Dyk <kugelfang@gentoo.org>
9 Andreas Jaggi <andreas.jaggi@waterwave.ch>
10
11 Some parts of the code in this file are derived from the ipw2200
12 driver Copyright(c) 2003 - 2004 Intel Corporation.
13
14 This program is free software; you can redistribute it and/or modify
15 it under the terms of the GNU General Public License as published by
16 the Free Software Foundation; either version 2 of the License, or
17 (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; see the file COPYING. If not, write to
26 the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
27 Boston, MA 02110-1301, USA.
28
29*/
30
31#include <linux/delay.h>
32#include <linux/pci.h>
33#include <linux/types.h>
34
35#include "bcm43xx.h"
36#include "bcm43xx_phy.h"
37#include "bcm43xx_main.h"
38#include "bcm43xx_radio.h"
39#include "bcm43xx_ilt.h"
40#include "bcm43xx_power.h"
41
42
43static const s8 bcm43xx_tssi2dbm_b_table[] = {
44 0x4D, 0x4C, 0x4B, 0x4A,
45 0x4A, 0x49, 0x48, 0x47,
46 0x47, 0x46, 0x45, 0x45,
47 0x44, 0x43, 0x42, 0x42,
48 0x41, 0x40, 0x3F, 0x3E,
49 0x3D, 0x3C, 0x3B, 0x3A,
50 0x39, 0x38, 0x37, 0x36,
51 0x35, 0x34, 0x32, 0x31,
52 0x30, 0x2F, 0x2D, 0x2C,
53 0x2B, 0x29, 0x28, 0x26,
54 0x25, 0x23, 0x21, 0x1F,
55 0x1D, 0x1A, 0x17, 0x14,
56 0x10, 0x0C, 0x06, 0x00,
57 -7, -7, -7, -7,
58 -7, -7, -7, -7,
59 -7, -7, -7, -7,
60};
61
62static const s8 bcm43xx_tssi2dbm_g_table[] = {
63 77, 77, 77, 76,
64 76, 76, 75, 75,
65 74, 74, 73, 73,
66 73, 72, 72, 71,
67 71, 70, 70, 69,
68 68, 68, 67, 67,
69 66, 65, 65, 64,
70 63, 63, 62, 61,
71 60, 59, 58, 57,
72 56, 55, 54, 53,
73 52, 50, 49, 47,
74 45, 43, 40, 37,
75 33, 28, 22, 14,
76 5, -7, -20, -20,
77 -20, -20, -20, -20,
78 -20, -20, -20, -20,
79};
80
81static void bcm43xx_phy_initg(struct bcm43xx_private *bcm);
82
83
84void bcm43xx_raw_phy_lock(struct bcm43xx_private *bcm)
85{
86 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
87
88 assert(irqs_disabled());
89 if (bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD) == 0x00000000) {
90 phy->is_locked = 0;
91 return;
92 }
93 if (bcm->current_core->rev < 3) {
94 bcm43xx_mac_suspend(bcm);
95 spin_lock(&phy->lock);
96 } else {
97 if (bcm->ieee->iw_mode != IW_MODE_MASTER)
98 bcm43xx_power_saving_ctl_bits(bcm, -1, 1);
99 }
100 phy->is_locked = 1;
101}
102
103void bcm43xx_raw_phy_unlock(struct bcm43xx_private *bcm)
104{
105 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
106
107 assert(irqs_disabled());
108 if (bcm->current_core->rev < 3) {
109 if (phy->is_locked) {
110 spin_unlock(&phy->lock);
111 bcm43xx_mac_enable(bcm);
112 }
113 } else {
114 if (bcm->ieee->iw_mode != IW_MODE_MASTER)
115 bcm43xx_power_saving_ctl_bits(bcm, -1, -1);
116 }
117 phy->is_locked = 0;
118}
119
120u16 bcm43xx_phy_read(struct bcm43xx_private *bcm, u16 offset)
121{
122 bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_CONTROL, offset);
123 return bcm43xx_read16(bcm, BCM43xx_MMIO_PHY_DATA);
124}
125
126void bcm43xx_phy_write(struct bcm43xx_private *bcm, u16 offset, u16 val)
127{
128 bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_CONTROL, offset);
129 mmiowb();
130 bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_DATA, val);
131}
132
133void bcm43xx_phy_calibrate(struct bcm43xx_private *bcm)
134{
135 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
136 unsigned long flags;
137
138 bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* Dummy read. */
139 if (phy->calibrated)
140 return;
141 if (phy->type == BCM43xx_PHYTYPE_G && phy->rev == 1) {
142 /* We do not want to be preempted while calibrating
143 * the hardware.
144 */
145 local_irq_save(flags);
146
147 bcm43xx_wireless_core_reset(bcm, 0);
148 bcm43xx_phy_initg(bcm);
149 bcm43xx_wireless_core_reset(bcm, 1);
150
151 local_irq_restore(flags);
152 }
153 phy->calibrated = 1;
154}
155
156/* Connect the PHY
157 * http://bcm-specs.sipsolutions.net/SetPHY
158 */
159int bcm43xx_phy_connect(struct bcm43xx_private *bcm, int connect)
160{
161 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
162 u32 flags;
163
164 if (bcm->current_core->rev < 5)
165 goto out;
166
167 flags = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH);
168 if (connect) {
169 if (!(flags & 0x00010000))
170 return -ENODEV;
171 flags = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
172 flags |= (0x800 << 18);
173 bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, flags);
174 } else {
175 if (!(flags & 0x00020000))
176 return -ENODEV;
177 flags = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
178 flags &= ~(0x800 << 18);
179 bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, flags);
180 }
181out:
182 phy->connected = connect;
183 if (connect)
184 dprintk(KERN_INFO PFX "PHY connected\n");
185 else
186 dprintk(KERN_INFO PFX "PHY disconnected\n");
187
188 return 0;
189}
190
191/* intialize B PHY power control
192 * as described in http://bcm-specs.sipsolutions.net/InitPowerControl
193 */
194static void bcm43xx_phy_init_pctl(struct bcm43xx_private *bcm)
195{
196 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
197 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
198 u16 saved_batt = 0, saved_ratt = 0, saved_txctl1 = 0;
199 int must_reset_txpower = 0;
200
201 assert(phy->type != BCM43xx_PHYTYPE_A);
202 if ((bcm->board_vendor == PCI_VENDOR_ID_BROADCOM) &&
203 (bcm->board_type == 0x0416))
204 return;
205
206 bcm43xx_write16(bcm, 0x03E6, bcm43xx_read16(bcm, 0x03E6) & 0xFFDF);
207 bcm43xx_phy_write(bcm, 0x0028, 0x8018);
208
209 if (phy->type == BCM43xx_PHYTYPE_G) {
210 if (!phy->connected)
211 return;
212 bcm43xx_phy_write(bcm, 0x047A, 0xC111);
213 }
214 if (phy->savedpctlreg != 0xFFFF)
215 return;
216
217 if (phy->type == BCM43xx_PHYTYPE_B &&
218 phy->rev >= 2 &&
219 radio->version == 0x2050) {
220 bcm43xx_radio_write16(bcm, 0x0076,
221 bcm43xx_radio_read16(bcm, 0x0076) | 0x0084);
222 } else {
223 saved_batt = radio->baseband_atten;
224 saved_ratt = radio->radio_atten;
225 saved_txctl1 = radio->txctl1;
226 if ((radio->revision >= 6) && (radio->revision <= 8)
227 && /*FIXME: incomplete specs for 5 < revision < 9 */ 0)
228 bcm43xx_radio_set_txpower_bg(bcm, 0xB, 0x1F, 0);
229 else
230 bcm43xx_radio_set_txpower_bg(bcm, 0xB, 9, 0);
231 must_reset_txpower = 1;
232 }
233 bcm43xx_dummy_transmission(bcm);
234
235 phy->savedpctlreg = bcm43xx_phy_read(bcm, BCM43xx_PHY_G_PCTL);
236
237 if (must_reset_txpower)
238 bcm43xx_radio_set_txpower_bg(bcm, saved_batt, saved_ratt, saved_txctl1);
239 else
240 bcm43xx_radio_write16(bcm, 0x0076, bcm43xx_radio_read16(bcm, 0x0076) & 0xFF7B);
241 bcm43xx_radio_clear_tssi(bcm);
242}
243
244static void bcm43xx_phy_agcsetup(struct bcm43xx_private *bcm)
245{
246 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
247 u16 offset = 0x0000;
248
249 if (phy->rev == 1)
250 offset = 0x4C00;
251
252 bcm43xx_ilt_write(bcm, offset, 0x00FE);
253 bcm43xx_ilt_write(bcm, offset + 1, 0x000D);
254 bcm43xx_ilt_write(bcm, offset + 2, 0x0013);
255 bcm43xx_ilt_write(bcm, offset + 3, 0x0019);
256
257 if (phy->rev == 1) {
258 bcm43xx_ilt_write(bcm, 0x1800, 0x2710);
259 bcm43xx_ilt_write(bcm, 0x1801, 0x9B83);
260 bcm43xx_ilt_write(bcm, 0x1802, 0x9B83);
261 bcm43xx_ilt_write(bcm, 0x1803, 0x0F8D);
262 bcm43xx_phy_write(bcm, 0x0455, 0x0004);
263 }
264
265 bcm43xx_phy_write(bcm, 0x04A5, (bcm43xx_phy_read(bcm, 0x04A5) & 0x00FF) | 0x5700);
266 bcm43xx_phy_write(bcm, 0x041A, (bcm43xx_phy_read(bcm, 0x041A) & 0xFF80) | 0x000F);
267 bcm43xx_phy_write(bcm, 0x041A, (bcm43xx_phy_read(bcm, 0x041A) & 0xC07F) | 0x2B80);
268 bcm43xx_phy_write(bcm, 0x048C, (bcm43xx_phy_read(bcm, 0x048C) & 0xF0FF) | 0x0300);
269
270 bcm43xx_radio_write16(bcm, 0x007A, bcm43xx_radio_read16(bcm, 0x007A) | 0x0008);
271
272 bcm43xx_phy_write(bcm, 0x04A0, (bcm43xx_phy_read(bcm, 0x04A0) & 0xFFF0) | 0x0008);
273 bcm43xx_phy_write(bcm, 0x04A1, (bcm43xx_phy_read(bcm, 0x04A1) & 0xF0FF) | 0x0600);
274 bcm43xx_phy_write(bcm, 0x04A2, (bcm43xx_phy_read(bcm, 0x04A2) & 0xF0FF) | 0x0700);
275 bcm43xx_phy_write(bcm, 0x04A0, (bcm43xx_phy_read(bcm, 0x04A0) & 0xF0FF) | 0x0100);
276
277 if (phy->rev == 1)
278 bcm43xx_phy_write(bcm, 0x04A2, (bcm43xx_phy_read(bcm, 0x04A2) & 0xFFF0) | 0x0007);
279
280 bcm43xx_phy_write(bcm, 0x0488, (bcm43xx_phy_read(bcm, 0x0488) & 0xFF00) | 0x001C);
281 bcm43xx_phy_write(bcm, 0x0488, (bcm43xx_phy_read(bcm, 0x0488) & 0xC0FF) | 0x0200);
282 bcm43xx_phy_write(bcm, 0x0496, (bcm43xx_phy_read(bcm, 0x0496) & 0xFF00) | 0x001C);
283 bcm43xx_phy_write(bcm, 0x0489, (bcm43xx_phy_read(bcm, 0x0489) & 0xFF00) | 0x0020);
284 bcm43xx_phy_write(bcm, 0x0489, (bcm43xx_phy_read(bcm, 0x0489) & 0xC0FF) | 0x0200);
285 bcm43xx_phy_write(bcm, 0x0482, (bcm43xx_phy_read(bcm, 0x0482) & 0xFF00) | 0x002E);
286 bcm43xx_phy_write(bcm, 0x0496, (bcm43xx_phy_read(bcm, 0x0496) & 0x00FF) | 0x1A00);
287 bcm43xx_phy_write(bcm, 0x0481, (bcm43xx_phy_read(bcm, 0x0481) & 0xFF00) | 0x0028);
288 bcm43xx_phy_write(bcm, 0x0481, (bcm43xx_phy_read(bcm, 0x0481) & 0x00FF) | 0x2C00);
289
290 if (phy->rev == 1) {
291 bcm43xx_phy_write(bcm, 0x0430, 0x092B);
292 bcm43xx_phy_write(bcm, 0x041B, (bcm43xx_phy_read(bcm, 0x041B) & 0xFFE1) | 0x0002);
293 } else {
294 bcm43xx_phy_write(bcm, 0x041B, bcm43xx_phy_read(bcm, 0x041B) & 0xFFE1);
295 bcm43xx_phy_write(bcm, 0x041F, 0x287A);
296 bcm43xx_phy_write(bcm, 0x0420, (bcm43xx_phy_read(bcm, 0x0420) & 0xFFF0) | 0x0004);
297 }
298
299 if (phy->rev > 2) {
300 bcm43xx_phy_write(bcm, 0x0422, 0x287A);
301 bcm43xx_phy_write(bcm, 0x0420, (bcm43xx_phy_read(bcm, 0x0420) & 0x0FFF) | 0x3000);
302 }
303
304 bcm43xx_phy_write(bcm, 0x04A8, (bcm43xx_phy_read(bcm, 0x04A8) & 0x8080) | 0x7874);
305 bcm43xx_phy_write(bcm, 0x048E, 0x1C00);
306
307 if (phy->rev == 1) {
308 bcm43xx_phy_write(bcm, 0x04AB, (bcm43xx_phy_read(bcm, 0x04AB) & 0xF0FF) | 0x0600);
309 bcm43xx_phy_write(bcm, 0x048B, 0x005E);
310 bcm43xx_phy_write(bcm, 0x048C, (bcm43xx_phy_read(bcm, 0x048C) & 0xFF00) | 0x001E);
311 bcm43xx_phy_write(bcm, 0x048D, 0x0002);
312 }
313
314 bcm43xx_ilt_write(bcm, offset + 0x0800, 0);
315 bcm43xx_ilt_write(bcm, offset + 0x0801, 7);
316 bcm43xx_ilt_write(bcm, offset + 0x0802, 16);
317 bcm43xx_ilt_write(bcm, offset + 0x0803, 28);
318}
319
320static void bcm43xx_phy_setupg(struct bcm43xx_private *bcm)
321{
322 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
323 u16 i;
324
325 assert(phy->type == BCM43xx_PHYTYPE_G);
326 if (phy->rev == 1) {
327 bcm43xx_phy_write(bcm, 0x0406, 0x4F19);
328 bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
329 (bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & 0xFC3F) | 0x0340);
330 bcm43xx_phy_write(bcm, 0x042C, 0x005A);
331 bcm43xx_phy_write(bcm, 0x0427, 0x001A);
332
333 for (i = 0; i < BCM43xx_ILT_FINEFREQG_SIZE; i++)
334 bcm43xx_ilt_write(bcm, 0x5800 + i, bcm43xx_ilt_finefreqg[i]);
335 for (i = 0; i < BCM43xx_ILT_NOISEG1_SIZE; i++)
336 bcm43xx_ilt_write(bcm, 0x1800 + i, bcm43xx_ilt_noiseg1[i]);
337 for (i = 0; i < BCM43xx_ILT_ROTOR_SIZE; i++)
338 bcm43xx_ilt_write(bcm, 0x2000 + i, bcm43xx_ilt_rotor[i]);
339 } else {
340 /* nrssi values are signed 6-bit values. Not sure why we write 0x7654 here... */
341 bcm43xx_nrssi_hw_write(bcm, 0xBA98, (s16)0x7654);
342
343 if (phy->rev == 2) {
344 bcm43xx_phy_write(bcm, 0x04C0, 0x1861);
345 bcm43xx_phy_write(bcm, 0x04C1, 0x0271);
346 } else if (phy->rev > 2) {
347 bcm43xx_phy_write(bcm, 0x04C0, 0x0098);
348 bcm43xx_phy_write(bcm, 0x04C1, 0x0070);
349 bcm43xx_phy_write(bcm, 0x04C9, 0x0080);
350 }
351 bcm43xx_phy_write(bcm, 0x042B, bcm43xx_phy_read(bcm, 0x042B) | 0x800);
352
353 for (i = 0; i < 64; i++)
354 bcm43xx_ilt_write(bcm, 0x4000 + i, i);
355 for (i = 0; i < BCM43xx_ILT_NOISEG2_SIZE; i++)
356 bcm43xx_ilt_write(bcm, 0x1800 + i, bcm43xx_ilt_noiseg2[i]);
357 }
358
359 if (phy->rev <= 2)
360 for (i = 0; i < BCM43xx_ILT_NOISESCALEG_SIZE; i++)
361 bcm43xx_ilt_write(bcm, 0x1400 + i, bcm43xx_ilt_noisescaleg1[i]);
362 else if ((phy->rev == 7) && (bcm43xx_phy_read(bcm, 0x0449) & 0x0200))
363 for (i = 0; i < BCM43xx_ILT_NOISESCALEG_SIZE; i++)
364 bcm43xx_ilt_write(bcm, 0x1400 + i, bcm43xx_ilt_noisescaleg3[i]);
365 else
366 for (i = 0; i < BCM43xx_ILT_NOISESCALEG_SIZE; i++)
367 bcm43xx_ilt_write(bcm, 0x1400 + i, bcm43xx_ilt_noisescaleg2[i]);
368
369 if (phy->rev == 2)
370 for (i = 0; i < BCM43xx_ILT_SIGMASQR_SIZE; i++)
371 bcm43xx_ilt_write(bcm, 0x5000 + i, bcm43xx_ilt_sigmasqr1[i]);
372 else if ((phy->rev > 2) && (phy->rev <= 7))
373 for (i = 0; i < BCM43xx_ILT_SIGMASQR_SIZE; i++)
374 bcm43xx_ilt_write(bcm, 0x5000 + i, bcm43xx_ilt_sigmasqr2[i]);
375
376 if (phy->rev == 1) {
377 for (i = 0; i < BCM43xx_ILT_RETARD_SIZE; i++)
378 bcm43xx_ilt_write(bcm, 0x2400 + i, bcm43xx_ilt_retard[i]);
379 for (i = 0; i < 4; i++) {
380 bcm43xx_ilt_write(bcm, 0x5404 + i, 0x0020);
381 bcm43xx_ilt_write(bcm, 0x5408 + i, 0x0020);
382 bcm43xx_ilt_write(bcm, 0x540C + i, 0x0020);
383 bcm43xx_ilt_write(bcm, 0x5410 + i, 0x0020);
384 }
385 bcm43xx_phy_agcsetup(bcm);
386
387 if ((bcm->board_vendor == PCI_VENDOR_ID_BROADCOM) &&
388 (bcm->board_type == 0x0416) &&
389 (bcm->board_revision == 0x0017))
390 return;
391
392 bcm43xx_ilt_write(bcm, 0x5001, 0x0002);
393 bcm43xx_ilt_write(bcm, 0x5002, 0x0001);
394 } else {
395 for (i = 0; i <= 0x2F; i++)
396 bcm43xx_ilt_write(bcm, 0x1000 + i, 0x0820);
397 bcm43xx_phy_agcsetup(bcm);
398 bcm43xx_phy_read(bcm, 0x0400); /* dummy read */
399 bcm43xx_phy_write(bcm, 0x0403, 0x1000);
400 bcm43xx_ilt_write(bcm, 0x3C02, 0x000F);
401 bcm43xx_ilt_write(bcm, 0x3C03, 0x0014);
402
403 if ((bcm->board_vendor == PCI_VENDOR_ID_BROADCOM) &&
404 (bcm->board_type == 0x0416) &&
405 (bcm->board_revision == 0x0017))
406 return;
407
408 bcm43xx_ilt_write(bcm, 0x0401, 0x0002);
409 bcm43xx_ilt_write(bcm, 0x0402, 0x0001);
410 }
411}
412
413/* Initialize the noisescaletable for APHY */
414static void bcm43xx_phy_init_noisescaletbl(struct bcm43xx_private *bcm)
415{
416 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
417 int i;
418
419 bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_CTRL, 0x1400);
420 for (i = 0; i < 12; i++) {
421 if (phy->rev == 2)
422 bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x6767);
423 else
424 bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x2323);
425 }
426 if (phy->rev == 2)
427 bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x6700);
428 else
429 bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x2300);
430 for (i = 0; i < 11; i++) {
431 if (phy->rev == 2)
432 bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x6767);
433 else
434 bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x2323);
435 }
436 if (phy->rev == 2)
437 bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x0067);
438 else
439 bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x0023);
440}
441
442static void bcm43xx_phy_setupa(struct bcm43xx_private *bcm)
443{
444 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
445 u16 i;
446
447 assert(phy->type == BCM43xx_PHYTYPE_A);
448 switch (phy->rev) {
449 case 2:
450 bcm43xx_phy_write(bcm, 0x008E, 0x3800);
451 bcm43xx_phy_write(bcm, 0x0035, 0x03FF);
452 bcm43xx_phy_write(bcm, 0x0036, 0x0400);
453
454 bcm43xx_ilt_write(bcm, 0x3807, 0x0051);
455
456 bcm43xx_phy_write(bcm, 0x001C, 0x0FF9);
457 bcm43xx_phy_write(bcm, 0x0020, bcm43xx_phy_read(bcm, 0x0020) & 0xFF0F);
458 bcm43xx_ilt_write(bcm, 0x3C0C, 0x07BF);
459 bcm43xx_radio_write16(bcm, 0x0002, 0x07BF);
460
461 bcm43xx_phy_write(bcm, 0x0024, 0x4680);
462 bcm43xx_phy_write(bcm, 0x0020, 0x0003);
463 bcm43xx_phy_write(bcm, 0x001D, 0x0F40);
464 bcm43xx_phy_write(bcm, 0x001F, 0x1C00);
465
466 bcm43xx_phy_write(bcm, 0x002A, (bcm43xx_phy_read(bcm, 0x002A) & 0x00FF) | 0x0400);
467 bcm43xx_phy_write(bcm, 0x002B, bcm43xx_phy_read(bcm, 0x002B) & 0xFBFF);
468 bcm43xx_phy_write(bcm, 0x008E, 0x58C1);
469
470 bcm43xx_ilt_write(bcm, 0x0803, 0x000F);
471 bcm43xx_ilt_write(bcm, 0x0804, 0x001F);
472 bcm43xx_ilt_write(bcm, 0x0805, 0x002A);
473 bcm43xx_ilt_write(bcm, 0x0805, 0x0030);
474 bcm43xx_ilt_write(bcm, 0x0807, 0x003A);
475
476 bcm43xx_ilt_write(bcm, 0x0000, 0x0013);
477 bcm43xx_ilt_write(bcm, 0x0001, 0x0013);
478 bcm43xx_ilt_write(bcm, 0x0002, 0x0013);
479 bcm43xx_ilt_write(bcm, 0x0003, 0x0013);
480 bcm43xx_ilt_write(bcm, 0x0004, 0x0015);
481 bcm43xx_ilt_write(bcm, 0x0005, 0x0015);
482 bcm43xx_ilt_write(bcm, 0x0006, 0x0019);
483
484 bcm43xx_ilt_write(bcm, 0x0404, 0x0003);
485 bcm43xx_ilt_write(bcm, 0x0405, 0x0003);
486 bcm43xx_ilt_write(bcm, 0x0406, 0x0007);
487
488 for (i = 0; i < 16; i++)
489 bcm43xx_ilt_write(bcm, 0x4000 + i, (0x8 + i) & 0x000F);
490
491 bcm43xx_ilt_write(bcm, 0x3003, 0x1044);
492 bcm43xx_ilt_write(bcm, 0x3004, 0x7201);
493 bcm43xx_ilt_write(bcm, 0x3006, 0x0040);
494 bcm43xx_ilt_write(bcm, 0x3001, (bcm43xx_ilt_read(bcm, 0x3001) & 0x0010) | 0x0008);
495
496 for (i = 0; i < BCM43xx_ILT_FINEFREQA_SIZE; i++)
497 bcm43xx_ilt_write(bcm, 0x5800 + i, bcm43xx_ilt_finefreqa[i]);
498 for (i = 0; i < BCM43xx_ILT_NOISEA2_SIZE; i++)
499 bcm43xx_ilt_write(bcm, 0x1800 + i, bcm43xx_ilt_noisea2[i]);
500 for (i = 0; i < BCM43xx_ILT_ROTOR_SIZE; i++)
501 bcm43xx_ilt_write(bcm, 0x2000 + i, bcm43xx_ilt_rotor[i]);
502 bcm43xx_phy_init_noisescaletbl(bcm);
503 for (i = 0; i < BCM43xx_ILT_RETARD_SIZE; i++)
504 bcm43xx_ilt_write(bcm, 0x2400 + i, bcm43xx_ilt_retard[i]);
505 break;
506 case 3:
507 for (i = 0; i < 64; i++)
508 bcm43xx_ilt_write(bcm, 0x4000 + i, i);
509
510 bcm43xx_ilt_write(bcm, 0x3807, 0x0051);
511
512 bcm43xx_phy_write(bcm, 0x001C, 0x0FF9);
513 bcm43xx_phy_write(bcm, 0x0020, bcm43xx_phy_read(bcm, 0x0020) & 0xFF0F);
514 bcm43xx_radio_write16(bcm, 0x0002, 0x07BF);
515
516 bcm43xx_phy_write(bcm, 0x0024, 0x4680);
517 bcm43xx_phy_write(bcm, 0x0020, 0x0003);
518 bcm43xx_phy_write(bcm, 0x001D, 0x0F40);
519 bcm43xx_phy_write(bcm, 0x001F, 0x1C00);
520 bcm43xx_phy_write(bcm, 0x002A, (bcm43xx_phy_read(bcm, 0x002A) & 0x00FF) | 0x0400);
521
522 bcm43xx_ilt_write(bcm, 0x3001, (bcm43xx_ilt_read(bcm, 0x3001) & 0x0010) | 0x0008);
523 for (i = 0; i < BCM43xx_ILT_NOISEA3_SIZE; i++)
524 bcm43xx_ilt_write(bcm, 0x1800 + i, bcm43xx_ilt_noisea3[i]);
525 bcm43xx_phy_init_noisescaletbl(bcm);
526 for (i = 0; i < BCM43xx_ILT_SIGMASQR_SIZE; i++)
527 bcm43xx_ilt_write(bcm, 0x5000 + i, bcm43xx_ilt_sigmasqr1[i]);
528
529 bcm43xx_phy_write(bcm, 0x0003, 0x1808);
530
531 bcm43xx_ilt_write(bcm, 0x0803, 0x000F);
532 bcm43xx_ilt_write(bcm, 0x0804, 0x001F);
533 bcm43xx_ilt_write(bcm, 0x0805, 0x002A);
534 bcm43xx_ilt_write(bcm, 0x0805, 0x0030);
535 bcm43xx_ilt_write(bcm, 0x0807, 0x003A);
536
537 bcm43xx_ilt_write(bcm, 0x0000, 0x0013);
538 bcm43xx_ilt_write(bcm, 0x0001, 0x0013);
539 bcm43xx_ilt_write(bcm, 0x0002, 0x0013);
540 bcm43xx_ilt_write(bcm, 0x0003, 0x0013);
541 bcm43xx_ilt_write(bcm, 0x0004, 0x0015);
542 bcm43xx_ilt_write(bcm, 0x0005, 0x0015);
543 bcm43xx_ilt_write(bcm, 0x0006, 0x0019);
544
545 bcm43xx_ilt_write(bcm, 0x0404, 0x0003);
546 bcm43xx_ilt_write(bcm, 0x0405, 0x0003);
547 bcm43xx_ilt_write(bcm, 0x0406, 0x0007);
548
549 bcm43xx_ilt_write(bcm, 0x3C02, 0x000F);
550 bcm43xx_ilt_write(bcm, 0x3C03, 0x0014);
551 break;
552 default:
553 assert(0);
554 }
555}
556
557/* Initialize APHY. This is also called for the GPHY in some cases. */
558static void bcm43xx_phy_inita(struct bcm43xx_private *bcm)
559{
560 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
561 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
562 u16 tval;
563
564 if (phy->type == BCM43xx_PHYTYPE_A) {
565 bcm43xx_phy_setupa(bcm);
566 } else {
567 bcm43xx_phy_setupg(bcm);
568 if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL)
569 bcm43xx_phy_write(bcm, 0x046E, 0x03CF);
570 return;
571 }
572
573 bcm43xx_phy_write(bcm, BCM43xx_PHY_A_CRS,
574 (bcm43xx_phy_read(bcm, BCM43xx_PHY_A_CRS) & 0xF83C) | 0x0340);
575 bcm43xx_phy_write(bcm, 0x0034, 0x0001);
576
577 TODO();//TODO: RSSI AGC
578 bcm43xx_phy_write(bcm, BCM43xx_PHY_A_CRS,
579 bcm43xx_phy_read(bcm, BCM43xx_PHY_A_CRS) | (1 << 14));
580 bcm43xx_radio_init2060(bcm);
581
582 if ((bcm->board_vendor == PCI_VENDOR_ID_BROADCOM)
583 && ((bcm->board_type == 0x0416) || (bcm->board_type == 0x040A))) {
584 if (radio->lofcal == 0xFFFF) {
585 TODO();//TODO: LOF Cal
586 bcm43xx_radio_set_tx_iq(bcm);
587 } else
588 bcm43xx_radio_write16(bcm, 0x001E, radio->lofcal);
589 }
590
591 bcm43xx_phy_write(bcm, 0x007A, 0xF111);
592
593 if (phy->savedpctlreg == 0xFFFF) {
594 bcm43xx_radio_write16(bcm, 0x0019, 0x0000);
595 bcm43xx_radio_write16(bcm, 0x0017, 0x0020);
596
597 tval = bcm43xx_ilt_read(bcm, 0x3001);
598 if (phy->rev == 1) {
599 bcm43xx_ilt_write(bcm, 0x3001,
600 (bcm43xx_ilt_read(bcm, 0x3001) & 0xFF87)
601 | 0x0058);
602 } else {
603 bcm43xx_ilt_write(bcm, 0x3001,
604 (bcm43xx_ilt_read(bcm, 0x3001) & 0xFFC3)
605 | 0x002C);
606 }
607 bcm43xx_dummy_transmission(bcm);
608 phy->savedpctlreg = bcm43xx_phy_read(bcm, BCM43xx_PHY_A_PCTL);
609 bcm43xx_ilt_write(bcm, 0x3001, tval);
610
611 bcm43xx_radio_set_txpower_a(bcm, 0x0018);
612 }
613 bcm43xx_radio_clear_tssi(bcm);
614}
615
616static void bcm43xx_phy_initb2(struct bcm43xx_private *bcm)
617{
618 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
619 u16 offset, val;
620
621 bcm43xx_write16(bcm, 0x03EC, 0x3F22);
622 bcm43xx_phy_write(bcm, 0x0020, 0x301C);
623 bcm43xx_phy_write(bcm, 0x0026, 0x0000);
624 bcm43xx_phy_write(bcm, 0x0030, 0x00C6);
625 bcm43xx_phy_write(bcm, 0x0088, 0x3E00);
626 val = 0x3C3D;
627 for (offset = 0x0089; offset < 0x00A7; offset++) {
628 bcm43xx_phy_write(bcm, offset, val);
629 val -= 0x0202;
630 }
631 bcm43xx_phy_write(bcm, 0x03E4, 0x3000);
632 if (radio->channel == 0xFF)
633 bcm43xx_radio_selectchannel(bcm, BCM43xx_RADIO_DEFAULT_CHANNEL_BG, 0);
634 else
635 bcm43xx_radio_selectchannel(bcm, radio->channel, 0);
636 if (radio->version != 0x2050) {
637 bcm43xx_radio_write16(bcm, 0x0075, 0x0080);
638 bcm43xx_radio_write16(bcm, 0x0079, 0x0081);
639 }
640 bcm43xx_radio_write16(bcm, 0x0050, 0x0020);
641 bcm43xx_radio_write16(bcm, 0x0050, 0x0023);
642 if (radio->version == 0x2050) {
643 bcm43xx_radio_write16(bcm, 0x0050, 0x0020);
644 bcm43xx_radio_write16(bcm, 0x005A, 0x0070);
645 bcm43xx_radio_write16(bcm, 0x005B, 0x007B);
646 bcm43xx_radio_write16(bcm, 0x005C, 0x00B0);
647 bcm43xx_radio_write16(bcm, 0x007A, 0x000F);
648 bcm43xx_phy_write(bcm, 0x0038, 0x0677);
649 bcm43xx_radio_init2050(bcm);
650 }
651 bcm43xx_phy_write(bcm, 0x0014, 0x0080);
652 bcm43xx_phy_write(bcm, 0x0032, 0x00CA);
653 bcm43xx_phy_write(bcm, 0x0032, 0x00CC);
654 bcm43xx_phy_write(bcm, 0x0035, 0x07C2);
655 bcm43xx_phy_lo_b_measure(bcm);
656 bcm43xx_phy_write(bcm, 0x0026, 0xCC00);
657 if (radio->version != 0x2050)
658 bcm43xx_phy_write(bcm, 0x0026, 0xCE00);
659 bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, 0x1000);
660 bcm43xx_phy_write(bcm, 0x002A, 0x88A3);
661 if (radio->version != 0x2050)
662 bcm43xx_phy_write(bcm, 0x002A, 0x88C2);
663 bcm43xx_radio_set_txpower_bg(bcm, 0xFFFF, 0xFFFF, 0xFFFF);
664 bcm43xx_phy_init_pctl(bcm);
665}
666
667static void bcm43xx_phy_initb4(struct bcm43xx_private *bcm)
668{
669 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
670 u16 offset, val;
671
672 bcm43xx_write16(bcm, 0x03EC, 0x3F22);
673 bcm43xx_phy_write(bcm, 0x0020, 0x301C);
674 bcm43xx_phy_write(bcm, 0x0026, 0x0000);
675 bcm43xx_phy_write(bcm, 0x0030, 0x00C6);
676 bcm43xx_phy_write(bcm, 0x0088, 0x3E00);
677 val = 0x3C3D;
678 for (offset = 0x0089; offset < 0x00A7; offset++) {
679 bcm43xx_phy_write(bcm, offset, val);
680 val -= 0x0202;
681 }
682 bcm43xx_phy_write(bcm, 0x03E4, 0x3000);
683 if (radio->channel == 0xFF)
684 bcm43xx_radio_selectchannel(bcm, BCM43xx_RADIO_DEFAULT_CHANNEL_BG, 0);
685 else
686 bcm43xx_radio_selectchannel(bcm, radio->channel, 0);
687 if (radio->version != 0x2050) {
688 bcm43xx_radio_write16(bcm, 0x0075, 0x0080);
689 bcm43xx_radio_write16(bcm, 0x0079, 0x0081);
690 }
691 bcm43xx_radio_write16(bcm, 0x0050, 0x0020);
692 bcm43xx_radio_write16(bcm, 0x0050, 0x0023);
693 if (radio->version == 0x2050) {
694 bcm43xx_radio_write16(bcm, 0x0050, 0x0020);
695 bcm43xx_radio_write16(bcm, 0x005A, 0x0070);
696 bcm43xx_radio_write16(bcm, 0x005B, 0x007B);
697 bcm43xx_radio_write16(bcm, 0x005C, 0x00B0);
698 bcm43xx_radio_write16(bcm, 0x007A, 0x000F);
699 bcm43xx_phy_write(bcm, 0x0038, 0x0677);
700 bcm43xx_radio_init2050(bcm);
701 }
702 bcm43xx_phy_write(bcm, 0x0014, 0x0080);
703 bcm43xx_phy_write(bcm, 0x0032, 0x00CA);
704 if (radio->version == 0x2050)
705 bcm43xx_phy_write(bcm, 0x0032, 0x00E0);
706 bcm43xx_phy_write(bcm, 0x0035, 0x07C2);
707
708 bcm43xx_phy_lo_b_measure(bcm);
709
710 bcm43xx_phy_write(bcm, 0x0026, 0xCC00);
711 if (radio->version == 0x2050)
712 bcm43xx_phy_write(bcm, 0x0026, 0xCE00);
713 bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, 0x1100);
714 bcm43xx_phy_write(bcm, 0x002A, 0x88A3);
715 if (radio->version == 0x2050)
716 bcm43xx_phy_write(bcm, 0x002A, 0x88C2);
717 bcm43xx_radio_set_txpower_bg(bcm, 0xFFFF, 0xFFFF, 0xFFFF);
718 if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) {
719 bcm43xx_calc_nrssi_slope(bcm);
720 bcm43xx_calc_nrssi_threshold(bcm);
721 }
722 bcm43xx_phy_init_pctl(bcm);
723}
724
725static void bcm43xx_phy_initb5(struct bcm43xx_private *bcm)
726{
727 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
728 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
729 u16 offset;
730
731 if (phy->version == 1 &&
732 radio->version == 0x2050) {
733 bcm43xx_radio_write16(bcm, 0x007A,
734 bcm43xx_radio_read16(bcm, 0x007A)
735 | 0x0050);
736 }
737 if ((bcm->board_vendor != PCI_VENDOR_ID_BROADCOM) &&
738 (bcm->board_type != 0x0416)) {
739 for (offset = 0x00A8 ; offset < 0x00C7; offset++) {
740 bcm43xx_phy_write(bcm, offset,
741 (bcm43xx_phy_read(bcm, offset) + 0x2020)
742 & 0x3F3F);
743 }
744 }
745 bcm43xx_phy_write(bcm, 0x0035,
746 (bcm43xx_phy_read(bcm, 0x0035) & 0xF0FF)
747 | 0x0700);
748 if (radio->version == 0x2050)
749 bcm43xx_phy_write(bcm, 0x0038, 0x0667);
750
751 if (phy->connected) {
752 if (radio->version == 0x2050) {
753 bcm43xx_radio_write16(bcm, 0x007A,
754 bcm43xx_radio_read16(bcm, 0x007A)
755 | 0x0020);
756 bcm43xx_radio_write16(bcm, 0x0051,
757 bcm43xx_radio_read16(bcm, 0x0051)
758 | 0x0004);
759 }
760 bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_RADIO, 0x0000);
761
762 bcm43xx_phy_write(bcm, 0x0802, bcm43xx_phy_read(bcm, 0x0802) | 0x0100);
763 bcm43xx_phy_write(bcm, 0x042B, bcm43xx_phy_read(bcm, 0x042B) | 0x2000);
764
765 bcm43xx_phy_write(bcm, 0x001C, 0x186A);
766
767 bcm43xx_phy_write(bcm, 0x0013, (bcm43xx_phy_read(bcm, 0x0013) & 0x00FF) | 0x1900);
768 bcm43xx_phy_write(bcm, 0x0035, (bcm43xx_phy_read(bcm, 0x0035) & 0xFFC0) | 0x0064);
769 bcm43xx_phy_write(bcm, 0x005D, (bcm43xx_phy_read(bcm, 0x005D) & 0xFF80) | 0x000A);
770 }
771
772 if (bcm->bad_frames_preempt) {
773 bcm43xx_phy_write(bcm, BCM43xx_PHY_RADIO_BITFIELD,
774 bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD) | (1 << 11));
775 }
776
777 if (phy->version == 1 && radio->version == 0x2050) {
778 bcm43xx_phy_write(bcm, 0x0026, 0xCE00);
779 bcm43xx_phy_write(bcm, 0x0021, 0x3763);
780 bcm43xx_phy_write(bcm, 0x0022, 0x1BC3);
781 bcm43xx_phy_write(bcm, 0x0023, 0x06F9);
782 bcm43xx_phy_write(bcm, 0x0024, 0x037E);
783 } else
784 bcm43xx_phy_write(bcm, 0x0026, 0xCC00);
785 bcm43xx_phy_write(bcm, 0x0030, 0x00C6);
786 bcm43xx_write16(bcm, 0x03EC, 0x3F22);
787
788 if (phy->version == 1 && radio->version == 0x2050)
789 bcm43xx_phy_write(bcm, 0x0020, 0x3E1C);
790 else
791 bcm43xx_phy_write(bcm, 0x0020, 0x301C);
792
793 if (phy->version == 0)
794 bcm43xx_write16(bcm, 0x03E4, 0x3000);
795
796 /* Force to channel 7, even if not supported. */
797 bcm43xx_radio_selectchannel(bcm, 7, 0);
798
799 if (radio->version != 0x2050) {
800 bcm43xx_radio_write16(bcm, 0x0075, 0x0080);
801 bcm43xx_radio_write16(bcm, 0x0079, 0x0081);
802 }
803
804 bcm43xx_radio_write16(bcm, 0x0050, 0x0020);
805 bcm43xx_radio_write16(bcm, 0x0050, 0x0023);
806
807 if (radio->version == 0x2050) {
808 bcm43xx_radio_write16(bcm, 0x0050, 0x0020);
809 bcm43xx_radio_write16(bcm, 0x005A, 0x0070);
810 }
811
812 bcm43xx_radio_write16(bcm, 0x005B, 0x007B);
813 bcm43xx_radio_write16(bcm, 0x005C, 0x00B0);
814
815 bcm43xx_radio_write16(bcm, 0x007A, bcm43xx_radio_read16(bcm, 0x007A) | 0x0007);
816
817 bcm43xx_radio_selectchannel(bcm, BCM43xx_RADIO_DEFAULT_CHANNEL_BG, 0);
818
819 bcm43xx_phy_write(bcm, 0x0014, 0x0080);
820 bcm43xx_phy_write(bcm, 0x0032, 0x00CA);
821 bcm43xx_phy_write(bcm, 0x88A3, 0x002A);
822
823 bcm43xx_radio_set_txpower_bg(bcm, 0xFFFF, 0xFFFF, 0xFFFF);
824
825 if (radio->version == 0x2050)
826 bcm43xx_radio_write16(bcm, 0x005D, 0x000D);
827
828 bcm43xx_write16(bcm, 0x03E4, (bcm43xx_read16(bcm, 0x03E4) & 0xFFC0) | 0x0004);
829}
830
831static void bcm43xx_phy_initb6(struct bcm43xx_private *bcm)
832{
833 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
834 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
835 u16 offset, val;
836
837 bcm43xx_phy_write(bcm, 0x003E, 0x817A);
838 bcm43xx_radio_write16(bcm, 0x007A,
839 (bcm43xx_radio_read16(bcm, 0x007A) | 0x0058));
840 if ((radio->manufact == 0x17F) &&
841 (radio->version == 0x2050) &&
842 (radio->revision == 3 ||
843 radio->revision == 4 ||
844 radio->revision == 5)) {
845 bcm43xx_radio_write16(bcm, 0x0051, 0x001F);
846 bcm43xx_radio_write16(bcm, 0x0052, 0x0040);
847 bcm43xx_radio_write16(bcm, 0x0053, 0x005B);
848 bcm43xx_radio_write16(bcm, 0x0054, 0x0098);
849 bcm43xx_radio_write16(bcm, 0x005A, 0x0088);
850 bcm43xx_radio_write16(bcm, 0x005B, 0x0088);
851 bcm43xx_radio_write16(bcm, 0x005D, 0x0088);
852 bcm43xx_radio_write16(bcm, 0x005E, 0x0088);
853 bcm43xx_radio_write16(bcm, 0x007D, 0x0088);
854 }
855 if ((radio->manufact == 0x17F) &&
856 (radio->version == 0x2050) &&
857 (radio->revision == 6)) {
858 bcm43xx_radio_write16(bcm, 0x0051, 0x0000);
859 bcm43xx_radio_write16(bcm, 0x0052, 0x0040);
860 bcm43xx_radio_write16(bcm, 0x0053, 0x00B7);
861 bcm43xx_radio_write16(bcm, 0x0054, 0x0098);
862 bcm43xx_radio_write16(bcm, 0x005A, 0x0088);
863 bcm43xx_radio_write16(bcm, 0x005B, 0x008B);
864 bcm43xx_radio_write16(bcm, 0x005C, 0x00B5);
865 bcm43xx_radio_write16(bcm, 0x005D, 0x0088);
866 bcm43xx_radio_write16(bcm, 0x005E, 0x0088);
867 bcm43xx_radio_write16(bcm, 0x007D, 0x0088);
868 bcm43xx_radio_write16(bcm, 0x007C, 0x0001);
869 bcm43xx_radio_write16(bcm, 0x007E, 0x0008);
870 }
871 if ((radio->manufact == 0x17F) &&
872 (radio->version == 0x2050) &&
873 (radio->revision == 7)) {
874 bcm43xx_radio_write16(bcm, 0x0051, 0x0000);
875 bcm43xx_radio_write16(bcm, 0x0052, 0x0040);
876 bcm43xx_radio_write16(bcm, 0x0053, 0x00B7);
877 bcm43xx_radio_write16(bcm, 0x0054, 0x0098);
878 bcm43xx_radio_write16(bcm, 0x005A, 0x0088);
879 bcm43xx_radio_write16(bcm, 0x005B, 0x00A8);
880 bcm43xx_radio_write16(bcm, 0x005C, 0x0075);
881 bcm43xx_radio_write16(bcm, 0x005D, 0x00F5);
882 bcm43xx_radio_write16(bcm, 0x005E, 0x00B8);
883 bcm43xx_radio_write16(bcm, 0x007D, 0x00E8);
884 bcm43xx_radio_write16(bcm, 0x007C, 0x0001);
885 bcm43xx_radio_write16(bcm, 0x007E, 0x0008);
886 bcm43xx_radio_write16(bcm, 0x007B, 0x0000);
887 }
888 if ((radio->manufact == 0x17F) &&
889 (radio->version == 0x2050) &&
890 (radio->revision == 8)) {
891 bcm43xx_radio_write16(bcm, 0x0051, 0x0000);
892 bcm43xx_radio_write16(bcm, 0x0052, 0x0040);
893 bcm43xx_radio_write16(bcm, 0x0053, 0x00B7);
894 bcm43xx_radio_write16(bcm, 0x0054, 0x0098);
895 bcm43xx_radio_write16(bcm, 0x005A, 0x0088);
896 bcm43xx_radio_write16(bcm, 0x005B, 0x006B);
897 bcm43xx_radio_write16(bcm, 0x005C, 0x000F);
898 if (bcm->sprom.boardflags & 0x8000) {
899 bcm43xx_radio_write16(bcm, 0x005D, 0x00FA);
900 bcm43xx_radio_write16(bcm, 0x005E, 0x00D8);
901 } else {
902 bcm43xx_radio_write16(bcm, 0x005D, 0x00F5);
903 bcm43xx_radio_write16(bcm, 0x005E, 0x00B8);
904 }
905 bcm43xx_radio_write16(bcm, 0x0073, 0x0003);
906 bcm43xx_radio_write16(bcm, 0x007D, 0x00A8);
907 bcm43xx_radio_write16(bcm, 0x007C, 0x0001);
908 bcm43xx_radio_write16(bcm, 0x007E, 0x0008);
909 }
910 val = 0x1E1F;
911 for (offset = 0x0088; offset < 0x0098; offset++) {
912 bcm43xx_phy_write(bcm, offset, val);
913 val -= 0x0202;
914 }
915 val = 0x3E3F;
916 for (offset = 0x0098; offset < 0x00A8; offset++) {
917 bcm43xx_phy_write(bcm, offset, val);
918 val -= 0x0202;
919 }
920 val = 0x2120;
921 for (offset = 0x00A8; offset < 0x00C8; offset++) {
922 bcm43xx_phy_write(bcm, offset, (val & 0x3F3F));
923 val += 0x0202;
924 }
925 if (phy->type == BCM43xx_PHYTYPE_G) {
926 bcm43xx_radio_write16(bcm, 0x007A,
927 bcm43xx_radio_read16(bcm, 0x007A) | 0x0020);
928 bcm43xx_radio_write16(bcm, 0x0051,
929 bcm43xx_radio_read16(bcm, 0x0051) | 0x0004);
930 bcm43xx_phy_write(bcm, 0x0802,
931 bcm43xx_phy_read(bcm, 0x0802) | 0x0100);
932 bcm43xx_phy_write(bcm, 0x042B,
933 bcm43xx_phy_read(bcm, 0x042B) | 0x2000);
934 }
935
936 /* Force to channel 7, even if not supported. */
937 bcm43xx_radio_selectchannel(bcm, 7, 0);
938
939 bcm43xx_radio_write16(bcm, 0x0050, 0x0020);
940 bcm43xx_radio_write16(bcm, 0x0050, 0x0023);
941 udelay(40);
942 bcm43xx_radio_write16(bcm, 0x007C, (bcm43xx_radio_read16(bcm, 0x007C) | 0x0002));
943 bcm43xx_radio_write16(bcm, 0x0050, 0x0020);
944 if (radio->manufact == 0x17F &&
945 radio->version == 0x2050 &&
946 radio->revision <= 2) {
947 bcm43xx_radio_write16(bcm, 0x0050, 0x0020);
948 bcm43xx_radio_write16(bcm, 0x005A, 0x0070);
949 bcm43xx_radio_write16(bcm, 0x005B, 0x007B);
950 bcm43xx_radio_write16(bcm, 0x005C, 0x00B0);
951 }
952 bcm43xx_radio_write16(bcm, 0x007A,
953 (bcm43xx_radio_read16(bcm, 0x007A) & 0x00F8) | 0x0007);
954
955 bcm43xx_radio_selectchannel(bcm, BCM43xx_RADIO_DEFAULT_CHANNEL_BG, 0);
956
957 bcm43xx_phy_write(bcm, 0x0014, 0x0200);
958 if (radio->version == 0x2050){
959 if (radio->revision == 3 ||
960 radio->revision == 4 ||
961 radio->revision == 5)
962 bcm43xx_phy_write(bcm, 0x002A, 0x8AC0);
963 else
964 bcm43xx_phy_write(bcm, 0x002A, 0x88C2);
965 }
966 bcm43xx_phy_write(bcm, 0x0038, 0x0668);
967 bcm43xx_radio_set_txpower_bg(bcm, 0xFFFF, 0xFFFF, 0xFFFF);
968 if (radio->version == 0x2050) {
969 if (radio->revision == 3 ||
970 radio->revision == 4 ||
971 radio->revision == 5)
972 bcm43xx_phy_write(bcm, 0x005D, bcm43xx_phy_read(bcm, 0x005D) | 0x0003);
973 else if (radio->revision <= 2)
974 bcm43xx_radio_write16(bcm, 0x005D, 0x000D);
975 }
976
977 if (phy->rev == 4)
978 bcm43xx_phy_write(bcm, 0x0002, (bcm43xx_phy_read(bcm, 0x0002) & 0xFFC0) | 0x0004);
979 else
980 bcm43xx_write16(bcm, 0x03E4, 0x0009);
981 if (phy->type == BCM43xx_PHYTYPE_B) {
982 bcm43xx_write16(bcm, 0x03E6, 0x8140);
983 bcm43xx_phy_write(bcm, 0x0016, 0x0410);
984 bcm43xx_phy_write(bcm, 0x0017, 0x0820);
985 bcm43xx_phy_write(bcm, 0x0062, 0x0007);
986 (void) bcm43xx_radio_calibrationvalue(bcm);
987 bcm43xx_phy_lo_b_measure(bcm);
988 if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) {
989 bcm43xx_calc_nrssi_slope(bcm);
990 bcm43xx_calc_nrssi_threshold(bcm);
991 }
992 bcm43xx_phy_init_pctl(bcm);
993 } else
994 bcm43xx_write16(bcm, 0x03E6, 0x0);
995}
996
997static void bcm43xx_calc_loopback_gain(struct bcm43xx_private *bcm)
998{
999 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
1000 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
1001 u16 backup_phy[15];
1002 u16 backup_radio[3];
1003 u16 backup_bband;
1004 u16 i;
1005 u16 loop1_cnt, loop1_done, loop1_omitted;
1006 u16 loop2_done;
1007
1008 backup_phy[0] = bcm43xx_phy_read(bcm, 0x0429);
1009 backup_phy[1] = bcm43xx_phy_read(bcm, 0x0001);
1010 backup_phy[2] = bcm43xx_phy_read(bcm, 0x0811);
1011 backup_phy[3] = bcm43xx_phy_read(bcm, 0x0812);
1012 backup_phy[4] = bcm43xx_phy_read(bcm, 0x0814);
1013 backup_phy[5] = bcm43xx_phy_read(bcm, 0x0815);
1014 backup_phy[6] = bcm43xx_phy_read(bcm, 0x005A);
1015 backup_phy[7] = bcm43xx_phy_read(bcm, 0x0059);
1016 backup_phy[8] = bcm43xx_phy_read(bcm, 0x0058);
1017 backup_phy[9] = bcm43xx_phy_read(bcm, 0x000A);
1018 backup_phy[10] = bcm43xx_phy_read(bcm, 0x0003);
1019 backup_phy[11] = bcm43xx_phy_read(bcm, 0x080F);
1020 backup_phy[12] = bcm43xx_phy_read(bcm, 0x0810);
1021 backup_phy[13] = bcm43xx_phy_read(bcm, 0x002B);
1022 backup_phy[14] = bcm43xx_phy_read(bcm, 0x0015);
1023 bcm43xx_phy_read(bcm, 0x002D); /* dummy read */
1024 backup_bband = radio->baseband_atten;
1025 backup_radio[0] = bcm43xx_radio_read16(bcm, 0x0052);
1026 backup_radio[1] = bcm43xx_radio_read16(bcm, 0x0043);
1027 backup_radio[2] = bcm43xx_radio_read16(bcm, 0x007A);
1028
1029 bcm43xx_phy_write(bcm, 0x0429,
1030 bcm43xx_phy_read(bcm, 0x0429) & 0x3FFF);
1031 bcm43xx_phy_write(bcm, 0x0001,
1032 bcm43xx_phy_read(bcm, 0x0001) & 0x8000);
1033 bcm43xx_phy_write(bcm, 0x0811,
1034 bcm43xx_phy_read(bcm, 0x0811) | 0x0002);
1035 bcm43xx_phy_write(bcm, 0x0812,
1036 bcm43xx_phy_read(bcm, 0x0812) & 0xFFFD);
1037 bcm43xx_phy_write(bcm, 0x0811,
1038 bcm43xx_phy_read(bcm, 0x0811) | 0x0001);
1039 bcm43xx_phy_write(bcm, 0x0812,
1040 bcm43xx_phy_read(bcm, 0x0812) & 0xFFFE);
1041 bcm43xx_phy_write(bcm, 0x0814,
1042 bcm43xx_phy_read(bcm, 0x0814) | 0x0001);
1043 bcm43xx_phy_write(bcm, 0x0815,
1044 bcm43xx_phy_read(bcm, 0x0815) & 0xFFFE);
1045 bcm43xx_phy_write(bcm, 0x0814,
1046 bcm43xx_phy_read(bcm, 0x0814) | 0x0002);
1047 bcm43xx_phy_write(bcm, 0x0815,
1048 bcm43xx_phy_read(bcm, 0x0815) & 0xFFFD);
1049 bcm43xx_phy_write(bcm, 0x0811,
1050 bcm43xx_phy_read(bcm, 0x0811) | 0x000C);
1051 bcm43xx_phy_write(bcm, 0x0812,
1052 bcm43xx_phy_read(bcm, 0x0812) | 0x000C);
1053
1054 bcm43xx_phy_write(bcm, 0x0811,
1055 (bcm43xx_phy_read(bcm, 0x0811)
1056 & 0xFFCF) | 0x0030);
1057 bcm43xx_phy_write(bcm, 0x0812,
1058 (bcm43xx_phy_read(bcm, 0x0812)
1059 & 0xFFCF) | 0x0010);
1060
1061 bcm43xx_phy_write(bcm, 0x005A, 0x0780);
1062 bcm43xx_phy_write(bcm, 0x0059, 0xC810);
1063 bcm43xx_phy_write(bcm, 0x0058, 0x000D);
1064 if (phy->version == 0) {
1065 bcm43xx_phy_write(bcm, 0x0003, 0x0122);
1066 } else {
1067 bcm43xx_phy_write(bcm, 0x000A,
1068 bcm43xx_phy_read(bcm, 0x000A)
1069 | 0x2000);
1070 }
1071 bcm43xx_phy_write(bcm, 0x0814,
1072 bcm43xx_phy_read(bcm, 0x0814) | 0x0004);
1073 bcm43xx_phy_write(bcm, 0x0815,
1074 bcm43xx_phy_read(bcm, 0x0815) & 0xFFFB);
1075 bcm43xx_phy_write(bcm, 0x0003,
1076 (bcm43xx_phy_read(bcm, 0x0003)
1077 & 0xFF9F) | 0x0040);
1078 if (radio->version == 0x2050 && radio->revision == 2) {
1079 bcm43xx_radio_write16(bcm, 0x0052, 0x0000);
1080 bcm43xx_radio_write16(bcm, 0x0043,
1081 (bcm43xx_radio_read16(bcm, 0x0043)
1082 & 0xFFF0) | 0x0009);
1083 loop1_cnt = 9;
1084 } else if (radio->revision == 8) {
1085 bcm43xx_radio_write16(bcm, 0x0043, 0x000F);
1086 loop1_cnt = 15;
1087 } else
1088 loop1_cnt = 0;
1089
1090 bcm43xx_phy_set_baseband_attenuation(bcm, 11);
1091
1092 if (phy->rev >= 3)
1093 bcm43xx_phy_write(bcm, 0x080F, 0xC020);
1094 else
1095 bcm43xx_phy_write(bcm, 0x080F, 0x8020);
1096 bcm43xx_phy_write(bcm, 0x0810, 0x0000);
1097
1098 bcm43xx_phy_write(bcm, 0x002B,
1099 (bcm43xx_phy_read(bcm, 0x002B)
1100 & 0xFFC0) | 0x0001);
1101 bcm43xx_phy_write(bcm, 0x002B,
1102 (bcm43xx_phy_read(bcm, 0x002B)
1103 & 0xC0FF) | 0x0800);
1104 bcm43xx_phy_write(bcm, 0x0811,
1105 bcm43xx_phy_read(bcm, 0x0811) | 0x0100);
1106 bcm43xx_phy_write(bcm, 0x0812,
1107 bcm43xx_phy_read(bcm, 0x0812) & 0xCFFF);
1108 if (bcm->sprom.boardflags & BCM43xx_BFL_EXTLNA) {
1109 if (phy->rev >= 7) {
1110 bcm43xx_phy_write(bcm, 0x0811,
1111 bcm43xx_phy_read(bcm, 0x0811)
1112 | 0x0800);
1113 bcm43xx_phy_write(bcm, 0x0812,
1114 bcm43xx_phy_read(bcm, 0x0812)
1115 | 0x8000);
1116 }
1117 }
1118 bcm43xx_radio_write16(bcm, 0x007A,
1119 bcm43xx_radio_read16(bcm, 0x007A)
1120 & 0x00F7);
1121
1122 for (i = 0; i < loop1_cnt; i++) {
1123 bcm43xx_radio_write16(bcm, 0x0043, loop1_cnt);
1124 bcm43xx_phy_write(bcm, 0x0812,
1125 (bcm43xx_phy_read(bcm, 0x0812)
1126 & 0xF0FF) | (i << 8));
1127 bcm43xx_phy_write(bcm, 0x0015,
1128 (bcm43xx_phy_read(bcm, 0x0015)
1129 & 0x0FFF) | 0xA000);
1130 bcm43xx_phy_write(bcm, 0x0015,
1131 (bcm43xx_phy_read(bcm, 0x0015)
1132 & 0x0FFF) | 0xF000);
1133 udelay(20);
1134 if (bcm43xx_phy_read(bcm, 0x002D) >= 0x0DFC)
1135 break;
1136 }
1137 loop1_done = i;
1138 loop1_omitted = loop1_cnt - loop1_done;
1139
1140 loop2_done = 0;
1141 if (loop1_done >= 8) {
1142 bcm43xx_phy_write(bcm, 0x0812,
1143 bcm43xx_phy_read(bcm, 0x0812)
1144 | 0x0030);
1145 for (i = loop1_done - 8; i < 16; i++) {
1146 bcm43xx_phy_write(bcm, 0x0812,
1147 (bcm43xx_phy_read(bcm, 0x0812)
1148 & 0xF0FF) | (i << 8));
1149 bcm43xx_phy_write(bcm, 0x0015,
1150 (bcm43xx_phy_read(bcm, 0x0015)
1151 & 0x0FFF) | 0xA000);
1152 bcm43xx_phy_write(bcm, 0x0015,
1153 (bcm43xx_phy_read(bcm, 0x0015)
1154 & 0x0FFF) | 0xF000);
1155 udelay(20);
1156 if (bcm43xx_phy_read(bcm, 0x002D) >= 0x0DFC)
1157 break;
1158 }
1159 }
1160
1161 bcm43xx_phy_write(bcm, 0x0814, backup_phy[4]);
1162 bcm43xx_phy_write(bcm, 0x0815, backup_phy[5]);
1163 bcm43xx_phy_write(bcm, 0x005A, backup_phy[6]);
1164 bcm43xx_phy_write(bcm, 0x0059, backup_phy[7]);
1165 bcm43xx_phy_write(bcm, 0x0058, backup_phy[8]);
1166 bcm43xx_phy_write(bcm, 0x000A, backup_phy[9]);
1167 bcm43xx_phy_write(bcm, 0x0003, backup_phy[10]);
1168 bcm43xx_phy_write(bcm, 0x080F, backup_phy[11]);
1169 bcm43xx_phy_write(bcm, 0x0810, backup_phy[12]);
1170 bcm43xx_phy_write(bcm, 0x002B, backup_phy[13]);
1171 bcm43xx_phy_write(bcm, 0x0015, backup_phy[14]);
1172
1173 bcm43xx_phy_set_baseband_attenuation(bcm, backup_bband);
1174
1175 bcm43xx_radio_write16(bcm, 0x0052, backup_radio[0]);
1176 bcm43xx_radio_write16(bcm, 0x0043, backup_radio[1]);
1177 bcm43xx_radio_write16(bcm, 0x007A, backup_radio[2]);
1178
1179 bcm43xx_phy_write(bcm, 0x0811, backup_phy[2] | 0x0003);
1180 udelay(10);
1181 bcm43xx_phy_write(bcm, 0x0811, backup_phy[2]);
1182 bcm43xx_phy_write(bcm, 0x0812, backup_phy[3]);
1183 bcm43xx_phy_write(bcm, 0x0429, backup_phy[0]);
1184 bcm43xx_phy_write(bcm, 0x0001, backup_phy[1]);
1185
1186 phy->loopback_gain[0] = ((loop1_done * 6) - (loop1_omitted * 4)) - 11;
1187 phy->loopback_gain[1] = (24 - (3 * loop2_done)) * 2;
1188}
1189
1190static void bcm43xx_phy_initg(struct bcm43xx_private *bcm)
1191{
1192 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
1193 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
1194 u16 tmp;
1195
1196 if (phy->rev == 1)
1197 bcm43xx_phy_initb5(bcm);
1198 else if (phy->rev >= 2 && phy->rev <= 7)
1199 bcm43xx_phy_initb6(bcm);
1200 if (phy->rev >= 2 || phy->connected)
1201 bcm43xx_phy_inita(bcm);
1202
1203 if (phy->rev >= 2) {
1204 bcm43xx_phy_write(bcm, 0x0814, 0x0000);
1205 bcm43xx_phy_write(bcm, 0x0815, 0x0000);
1206 if (phy->rev == 2)
1207 bcm43xx_phy_write(bcm, 0x0811, 0x0000);
1208 else if (phy->rev >= 3)
1209 bcm43xx_phy_write(bcm, 0x0811, 0x0400);
1210 bcm43xx_phy_write(bcm, 0x0015, 0x00C0);
1211 if (phy->connected) {
1212 tmp = bcm43xx_phy_read(bcm, 0x0400) & 0xFF;
1213 if (tmp < 6) {
1214 bcm43xx_phy_write(bcm, 0x04C2, 0x1816);
1215 bcm43xx_phy_write(bcm, 0x04C3, 0x8006);
1216 if (tmp != 3) {
1217 bcm43xx_phy_write(bcm, 0x04CC,
1218 (bcm43xx_phy_read(bcm, 0x04CC)
1219 & 0x00FF) | 0x1F00);
1220 }
1221 }
1222 }
1223 }
1224 if (phy->rev < 3 && phy->connected)
1225 bcm43xx_phy_write(bcm, 0x047E, 0x0078);
1226 if (phy->rev >= 6 && phy->rev <= 8) {
1227 bcm43xx_phy_write(bcm, 0x0801, bcm43xx_phy_read(bcm, 0x0801) | 0x0080);
1228 bcm43xx_phy_write(bcm, 0x043E, bcm43xx_phy_read(bcm, 0x043E) | 0x0004);
1229 }
1230 if (phy->rev >= 2 && phy->connected)
1231 bcm43xx_calc_loopback_gain(bcm);
1232 if (radio->revision != 8) {
1233 if (radio->initval == 0xFFFF)
1234 radio->initval = bcm43xx_radio_init2050(bcm);
1235 else
1236 bcm43xx_radio_write16(bcm, 0x0078, radio->initval);
1237 }
1238 if (radio->txctl2 == 0xFFFF) {
1239 bcm43xx_phy_lo_g_measure(bcm);
1240 } else {
1241 if (radio->version == 0x2050 && radio->revision == 8) {
1242 //FIXME
1243 } else {
1244 bcm43xx_radio_write16(bcm, 0x0052,
1245 (bcm43xx_radio_read16(bcm, 0x0052)
1246 & 0xFFF0) | radio->txctl1);
1247 }
1248 if (phy->rev >= 6) {
1249 /*
1250 bcm43xx_phy_write(bcm, 0x0036,
1251 (bcm43xx_phy_read(bcm, 0x0036)
1252 & 0xF000) | (FIXME << 12));
1253 */
1254 }
1255 if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL)
1256 bcm43xx_phy_write(bcm, 0x002E, 0x8075);
1257 else
1258 bcm43xx_phy_write(bcm, 0x003E, 0x807F);
1259 if (phy->rev < 2)
1260 bcm43xx_phy_write(bcm, 0x002F, 0x0101);
1261 else
1262 bcm43xx_phy_write(bcm, 0x002F, 0x0202);
1263 }
1264 if (phy->connected) {
1265 bcm43xx_phy_lo_adjust(bcm, 0);
1266 bcm43xx_phy_write(bcm, 0x080F, 0x8078);
1267 }
1268
1269 if (!(bcm->sprom.boardflags & BCM43xx_BFL_RSSI)) {
1270 /* The specs state to update the NRSSI LT with
1271 * the value 0x7FFFFFFF here. I think that is some weird
1272 * compiler optimization in the original driver.
1273 * Essentially, what we do here is resetting all NRSSI LT
1274 * entries to -32 (see the limit_value() in nrssi_hw_update())
1275 */
1276 bcm43xx_nrssi_hw_update(bcm, 0xFFFF);
1277 bcm43xx_calc_nrssi_threshold(bcm);
1278 } else if (phy->connected) {
1279 if (radio->nrssi[0] == -1000) {
1280 assert(radio->nrssi[1] == -1000);
1281 bcm43xx_calc_nrssi_slope(bcm);
1282 } else {
1283 assert(radio->nrssi[1] != -1000);
1284 bcm43xx_calc_nrssi_threshold(bcm);
1285 }
1286 }
1287 if (radio->revision == 8)
1288 bcm43xx_phy_write(bcm, 0x0805, 0x3230);
1289 bcm43xx_phy_init_pctl(bcm);
1290 if (bcm->chip_id == 0x4306 && bcm->chip_package != 2) {
1291 bcm43xx_phy_write(bcm, 0x0429,
1292 bcm43xx_phy_read(bcm, 0x0429) & 0xBFFF);
1293 bcm43xx_phy_write(bcm, 0x04C3,
1294 bcm43xx_phy_read(bcm, 0x04C3) & 0x7FFF);
1295 }
1296}
1297
1298static u16 bcm43xx_phy_lo_b_r15_loop(struct bcm43xx_private *bcm)
1299{
1300 int i;
1301 u16 ret = 0;
1302
1303 for (i = 0; i < 10; i++){
1304 bcm43xx_phy_write(bcm, 0x0015, 0xAFA0);
1305 udelay(1);
1306 bcm43xx_phy_write(bcm, 0x0015, 0xEFA0);
1307 udelay(10);
1308 bcm43xx_phy_write(bcm, 0x0015, 0xFFA0);
1309 udelay(40);
1310 ret += bcm43xx_phy_read(bcm, 0x002C);
1311 }
1312
1313 return ret;
1314}
1315
1316void bcm43xx_phy_lo_b_measure(struct bcm43xx_private *bcm)
1317{
1318 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
1319 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
1320 u16 regstack[12] = { 0 };
1321 u16 mls;
1322 u16 fval;
1323 int i, j;
1324
1325 regstack[0] = bcm43xx_phy_read(bcm, 0x0015);
1326 regstack[1] = bcm43xx_radio_read16(bcm, 0x0052) & 0xFFF0;
1327
1328 if (radio->version == 0x2053) {
1329 regstack[2] = bcm43xx_phy_read(bcm, 0x000A);
1330 regstack[3] = bcm43xx_phy_read(bcm, 0x002A);
1331 regstack[4] = bcm43xx_phy_read(bcm, 0x0035);
1332 regstack[5] = bcm43xx_phy_read(bcm, 0x0003);
1333 regstack[6] = bcm43xx_phy_read(bcm, 0x0001);
1334 regstack[7] = bcm43xx_phy_read(bcm, 0x0030);
1335
1336 regstack[8] = bcm43xx_radio_read16(bcm, 0x0043);
1337 regstack[9] = bcm43xx_radio_read16(bcm, 0x007A);
1338 regstack[10] = bcm43xx_read16(bcm, 0x03EC);
1339 regstack[11] = bcm43xx_radio_read16(bcm, 0x0052) & 0x00F0;
1340
1341 bcm43xx_phy_write(bcm, 0x0030, 0x00FF);
1342 bcm43xx_write16(bcm, 0x03EC, 0x3F3F);
1343 bcm43xx_phy_write(bcm, 0x0035, regstack[4] & 0xFF7F);
1344 bcm43xx_radio_write16(bcm, 0x007A, regstack[9] & 0xFFF0);
1345 }
1346 bcm43xx_phy_write(bcm, 0x0015, 0xB000);
1347 bcm43xx_phy_write(bcm, 0x002B, 0x0004);
1348
1349 if (radio->version == 0x2053) {
1350 bcm43xx_phy_write(bcm, 0x002B, 0x0203);
1351 bcm43xx_phy_write(bcm, 0x002A, 0x08A3);
1352 }
1353
1354 phy->minlowsig[0] = 0xFFFF;
1355
1356 for (i = 0; i < 4; i++) {
1357 bcm43xx_radio_write16(bcm, 0x0052, regstack[1] | i);
1358 bcm43xx_phy_lo_b_r15_loop(bcm);
1359 }
1360 for (i = 0; i < 10; i++) {
1361 bcm43xx_radio_write16(bcm, 0x0052, regstack[1] | i);
1362 mls = bcm43xx_phy_lo_b_r15_loop(bcm) / 10;
1363 if (mls < phy->minlowsig[0]) {
1364 phy->minlowsig[0] = mls;
1365 phy->minlowsigpos[0] = i;
1366 }
1367 }
1368 bcm43xx_radio_write16(bcm, 0x0052, regstack[1] | phy->minlowsigpos[0]);
1369
1370 phy->minlowsig[1] = 0xFFFF;
1371
1372 for (i = -4; i < 5; i += 2) {
1373 for (j = -4; j < 5; j += 2) {
1374 if (j < 0)
1375 fval = (0x0100 * i) + j + 0x0100;
1376 else
1377 fval = (0x0100 * i) + j;
1378 bcm43xx_phy_write(bcm, 0x002F, fval);
1379 mls = bcm43xx_phy_lo_b_r15_loop(bcm) / 10;
1380 if (mls < phy->minlowsig[1]) {
1381 phy->minlowsig[1] = mls;
1382 phy->minlowsigpos[1] = fval;
1383 }
1384 }
1385 }
1386 phy->minlowsigpos[1] += 0x0101;
1387
1388 bcm43xx_phy_write(bcm, 0x002F, phy->minlowsigpos[1]);
1389 if (radio->version == 0x2053) {
1390 bcm43xx_phy_write(bcm, 0x000A, regstack[2]);
1391 bcm43xx_phy_write(bcm, 0x002A, regstack[3]);
1392 bcm43xx_phy_write(bcm, 0x0035, regstack[4]);
1393 bcm43xx_phy_write(bcm, 0x0003, regstack[5]);
1394 bcm43xx_phy_write(bcm, 0x0001, regstack[6]);
1395 bcm43xx_phy_write(bcm, 0x0030, regstack[7]);
1396
1397 bcm43xx_radio_write16(bcm, 0x0043, regstack[8]);
1398 bcm43xx_radio_write16(bcm, 0x007A, regstack[9]);
1399
1400 bcm43xx_radio_write16(bcm, 0x0052,
1401 (bcm43xx_radio_read16(bcm, 0x0052) & 0x000F)
1402 | regstack[11]);
1403
1404 bcm43xx_write16(bcm, 0x03EC, regstack[10]);
1405 }
1406 bcm43xx_phy_write(bcm, 0x0015, regstack[0]);
1407}
1408
1409static inline
1410u16 bcm43xx_phy_lo_g_deviation_subval(struct bcm43xx_private *bcm, u16 control)
1411{
1412 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
1413
1414 if (phy->connected) {
1415 bcm43xx_phy_write(bcm, 0x15, 0xE300);
1416 control <<= 8;
1417 bcm43xx_phy_write(bcm, 0x0812, control | 0x00B0);
1418 udelay(5);
1419 bcm43xx_phy_write(bcm, 0x0812, control | 0x00B2);
1420 udelay(2);
1421 bcm43xx_phy_write(bcm, 0x0812, control | 0x00B3);
1422 udelay(4);
1423 bcm43xx_phy_write(bcm, 0x0015, 0xF300);
1424 udelay(8);
1425 } else {
1426 bcm43xx_phy_write(bcm, 0x0015, control | 0xEFA0);
1427 udelay(2);
1428 bcm43xx_phy_write(bcm, 0x0015, control | 0xEFE0);
1429 udelay(4);
1430 bcm43xx_phy_write(bcm, 0x0015, control | 0xFFE0);
1431 udelay(8);
1432 }
1433
1434 return bcm43xx_phy_read(bcm, 0x002D);
1435}
1436
1437static u32 bcm43xx_phy_lo_g_singledeviation(struct bcm43xx_private *bcm, u16 control)
1438{
1439 int i;
1440 u32 ret = 0;
1441
1442 for (i = 0; i < 8; i++)
1443 ret += bcm43xx_phy_lo_g_deviation_subval(bcm, control);
1444
1445 return ret;
1446}
1447
1448/* Write the LocalOscillator CONTROL */
1449static inline
1450void bcm43xx_lo_write(struct bcm43xx_private *bcm,
1451 struct bcm43xx_lopair *pair)
1452{
1453 u16 value;
1454
1455 value = (u8)(pair->low);
1456 value |= ((u8)(pair->high)) << 8;
1457
1458#ifdef CONFIG_BCM43XX_DEBUG
1459 /* Sanity check. */
1460 if (pair->low < -8 || pair->low > 8 ||
1461 pair->high < -8 || pair->high > 8) {
1462 printk(KERN_WARNING PFX
1463 "WARNING: Writing invalid LOpair "
1464 "(low: %d, high: %d, index: %lu)\n",
1465 pair->low, pair->high,
1466 (unsigned long)(pair - bcm43xx_current_phy(bcm)->_lo_pairs));
1467 dump_stack();
1468 }
1469#endif
1470
1471 bcm43xx_phy_write(bcm, BCM43xx_PHY_G_LO_CONTROL, value);
1472}
1473
1474static inline
1475struct bcm43xx_lopair * bcm43xx_find_lopair(struct bcm43xx_private *bcm,
1476 u16 baseband_attenuation,
1477 u16 radio_attenuation,
1478 u16 tx)
1479{
1480 static const u8 dict[10] = { 11, 10, 11, 12, 13, 12, 13, 12, 13, 12 };
1481 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
1482
1483 if (baseband_attenuation > 6)
1484 baseband_attenuation = 6;
1485 assert(radio_attenuation < 10);
1486
1487 if (tx == 3) {
1488 return bcm43xx_get_lopair(phy,
1489 radio_attenuation,
1490 baseband_attenuation);
1491 }
1492 return bcm43xx_get_lopair(phy, dict[radio_attenuation], baseband_attenuation);
1493}
1494
1495static inline
1496struct bcm43xx_lopair * bcm43xx_current_lopair(struct bcm43xx_private *bcm)
1497{
1498 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
1499
1500 return bcm43xx_find_lopair(bcm,
1501 radio->baseband_atten,
1502 radio->radio_atten,
1503 radio->txctl1);
1504}
1505
1506/* Adjust B/G LO */
1507void bcm43xx_phy_lo_adjust(struct bcm43xx_private *bcm, int fixed)
1508{
1509 struct bcm43xx_lopair *pair;
1510
1511 if (fixed) {
1512 /* Use fixed values. Only for initialization. */
1513 pair = bcm43xx_find_lopair(bcm, 2, 3, 0);
1514 } else
1515 pair = bcm43xx_current_lopair(bcm);
1516 bcm43xx_lo_write(bcm, pair);
1517}
1518
1519static void bcm43xx_phy_lo_g_measure_txctl2(struct bcm43xx_private *bcm)
1520{
1521 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
1522 u16 txctl2 = 0, i;
1523 u32 smallest, tmp;
1524
1525 bcm43xx_radio_write16(bcm, 0x0052, 0x0000);
1526 udelay(10);
1527 smallest = bcm43xx_phy_lo_g_singledeviation(bcm, 0);
1528 for (i = 0; i < 16; i++) {
1529 bcm43xx_radio_write16(bcm, 0x0052, i);
1530 udelay(10);
1531 tmp = bcm43xx_phy_lo_g_singledeviation(bcm, 0);
1532 if (tmp < smallest) {
1533 smallest = tmp;
1534 txctl2 = i;
1535 }
1536 }
1537 radio->txctl2 = txctl2;
1538}
1539
1540static
1541void bcm43xx_phy_lo_g_state(struct bcm43xx_private *bcm,
1542 const struct bcm43xx_lopair *in_pair,
1543 struct bcm43xx_lopair *out_pair,
1544 u16 r27)
1545{
1546 static const struct bcm43xx_lopair transitions[8] = {
1547 { .high = 1, .low = 1, },
1548 { .high = 1, .low = 0, },
1549 { .high = 1, .low = -1, },
1550 { .high = 0, .low = -1, },
1551 { .high = -1, .low = -1, },
1552 { .high = -1, .low = 0, },
1553 { .high = -1, .low = 1, },
1554 { .high = 0, .low = 1, },
1555 };
1556 struct bcm43xx_lopair lowest_transition = {
1557 .high = in_pair->high,
1558 .low = in_pair->low,
1559 };
1560 struct bcm43xx_lopair tmp_pair;
1561 struct bcm43xx_lopair transition;
1562 int i = 12;
1563 int state = 0;
1564 int found_lower;
1565 int j, begin, end;
1566 u32 lowest_deviation;
1567 u32 tmp;
1568
1569 /* Note that in_pair and out_pair can point to the same pair. Be careful. */
1570
1571 bcm43xx_lo_write(bcm, &lowest_transition);
1572 lowest_deviation = bcm43xx_phy_lo_g_singledeviation(bcm, r27);
1573 do {
1574 found_lower = 0;
1575 assert(state >= 0 && state <= 8);
1576 if (state == 0) {
1577 begin = 1;
1578 end = 8;
1579 } else if (state % 2 == 0) {
1580 begin = state - 1;
1581 end = state + 1;
1582 } else {
1583 begin = state - 2;
1584 end = state + 2;
1585 }
1586 if (begin < 1)
1587 begin += 8;
1588 if (end > 8)
1589 end -= 8;
1590
1591 j = begin;
1592 tmp_pair.high = lowest_transition.high;
1593 tmp_pair.low = lowest_transition.low;
1594 while (1) {
1595 assert(j >= 1 && j <= 8);
1596 transition.high = tmp_pair.high + transitions[j - 1].high;
1597 transition.low = tmp_pair.low + transitions[j - 1].low;
1598 if ((abs(transition.low) < 9) && (abs(transition.high) < 9)) {
1599 bcm43xx_lo_write(bcm, &transition);
1600 tmp = bcm43xx_phy_lo_g_singledeviation(bcm, r27);
1601 if (tmp < lowest_deviation) {
1602 lowest_deviation = tmp;
1603 state = j;
1604 found_lower = 1;
1605
1606 lowest_transition.high = transition.high;
1607 lowest_transition.low = transition.low;
1608 }
1609 }
1610 if (j == end)
1611 break;
1612 if (j == 8)
1613 j = 1;
1614 else
1615 j++;
1616 }
1617 } while (i-- && found_lower);
1618
1619 out_pair->high = lowest_transition.high;
1620 out_pair->low = lowest_transition.low;
1621}
1622
1623/* Set the baseband attenuation value on chip. */
1624void bcm43xx_phy_set_baseband_attenuation(struct bcm43xx_private *bcm,
1625 u16 baseband_attenuation)
1626{
1627 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
1628 u16 value;
1629
1630 if (phy->version == 0) {
1631 value = (bcm43xx_read16(bcm, 0x03E6) & 0xFFF0);
1632 value |= (baseband_attenuation & 0x000F);
1633 bcm43xx_write16(bcm, 0x03E6, value);
1634 return;
1635 }
1636
1637 if (phy->version > 1) {
1638 value = bcm43xx_phy_read(bcm, 0x0060) & ~0x003C;
1639 value |= (baseband_attenuation << 2) & 0x003C;
1640 } else {
1641 value = bcm43xx_phy_read(bcm, 0x0060) & ~0x0078;
1642 value |= (baseband_attenuation << 3) & 0x0078;
1643 }
1644 bcm43xx_phy_write(bcm, 0x0060, value);
1645}
1646
1647/* http://bcm-specs.sipsolutions.net/LocalOscillator/Measure */
1648void bcm43xx_phy_lo_g_measure(struct bcm43xx_private *bcm)
1649{
1650 static const u8 pairorder[10] = { 3, 1, 5, 7, 9, 2, 0, 4, 6, 8 };
1651 const int is_initializing = bcm43xx_is_initializing(bcm);
1652 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
1653 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
1654 u16 h, i, oldi = 0, j;
1655 struct bcm43xx_lopair control;
1656 struct bcm43xx_lopair *tmp_control;
1657 u16 tmp;
1658 u16 regstack[16] = { 0 };
1659 u8 oldchannel;
1660
1661 //XXX: What are these?
1662 u8 r27 = 0, r31;
1663
1664 oldchannel = radio->channel;
1665 /* Setup */
1666 if (phy->connected) {
1667 regstack[0] = bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS);
1668 regstack[1] = bcm43xx_phy_read(bcm, 0x0802);
1669 bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, regstack[0] & 0x7FFF);
1670 bcm43xx_phy_write(bcm, 0x0802, regstack[1] & 0xFFFC);
1671 }
1672 regstack[3] = bcm43xx_read16(bcm, 0x03E2);
1673 bcm43xx_write16(bcm, 0x03E2, regstack[3] | 0x8000);
1674 regstack[4] = bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT);
1675 regstack[5] = bcm43xx_phy_read(bcm, 0x15);
1676 regstack[6] = bcm43xx_phy_read(bcm, 0x2A);
1677 regstack[7] = bcm43xx_phy_read(bcm, 0x35);
1678 regstack[8] = bcm43xx_phy_read(bcm, 0x60);
1679 regstack[9] = bcm43xx_radio_read16(bcm, 0x43);
1680 regstack[10] = bcm43xx_radio_read16(bcm, 0x7A);
1681 regstack[11] = bcm43xx_radio_read16(bcm, 0x52);
1682 if (phy->connected) {
1683 regstack[12] = bcm43xx_phy_read(bcm, 0x0811);
1684 regstack[13] = bcm43xx_phy_read(bcm, 0x0812);
1685 regstack[14] = bcm43xx_phy_read(bcm, 0x0814);
1686 regstack[15] = bcm43xx_phy_read(bcm, 0x0815);
1687 }
1688 bcm43xx_radio_selectchannel(bcm, 6, 0);
1689 if (phy->connected) {
1690 bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, regstack[0] & 0x7FFF);
1691 bcm43xx_phy_write(bcm, 0x0802, regstack[1] & 0xFFFC);
1692 bcm43xx_dummy_transmission(bcm);
1693 }
1694 bcm43xx_radio_write16(bcm, 0x0043, 0x0006);
1695
1696 bcm43xx_phy_set_baseband_attenuation(bcm, 2);
1697
1698 bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, 0x0000);
1699 bcm43xx_phy_write(bcm, 0x002E, 0x007F);
1700 bcm43xx_phy_write(bcm, 0x080F, 0x0078);
1701 bcm43xx_phy_write(bcm, 0x0035, regstack[7] & ~(1 << 7));
1702 bcm43xx_radio_write16(bcm, 0x007A, regstack[10] & 0xFFF0);
1703 bcm43xx_phy_write(bcm, 0x002B, 0x0203);
1704 bcm43xx_phy_write(bcm, 0x002A, 0x08A3);
1705 if (phy->connected) {
1706 bcm43xx_phy_write(bcm, 0x0814, regstack[14] | 0x0003);
1707 bcm43xx_phy_write(bcm, 0x0815, regstack[15] & 0xFFFC);
1708 bcm43xx_phy_write(bcm, 0x0811, 0x01B3);
1709 bcm43xx_phy_write(bcm, 0x0812, 0x00B2);
1710 }
1711 if (is_initializing)
1712 bcm43xx_phy_lo_g_measure_txctl2(bcm);
1713 bcm43xx_phy_write(bcm, 0x080F, 0x8078);
1714
1715 /* Measure */
1716 control.low = 0;
1717 control.high = 0;
1718 for (h = 0; h < 10; h++) {
1719 /* Loop over each possible RadioAttenuation (0-9) */
1720 i = pairorder[h];
1721 if (is_initializing) {
1722 if (i == 3) {
1723 control.low = 0;
1724 control.high = 0;
1725 } else if (((i % 2 == 1) && (oldi % 2 == 1)) ||
1726 ((i % 2 == 0) && (oldi % 2 == 0))) {
1727 tmp_control = bcm43xx_get_lopair(phy, oldi, 0);
1728 memcpy(&control, tmp_control, sizeof(control));
1729 } else {
1730 tmp_control = bcm43xx_get_lopair(phy, 3, 0);
1731 memcpy(&control, tmp_control, sizeof(control));
1732 }
1733 }
1734 /* Loop over each possible BasebandAttenuation/2 */
1735 for (j = 0; j < 4; j++) {
1736 if (is_initializing) {
1737 tmp = i * 2 + j;
1738 r27 = 0;
1739 r31 = 0;
1740 if (tmp > 14) {
1741 r31 = 1;
1742 if (tmp > 17)
1743 r27 = 1;
1744 if (tmp > 19)
1745 r27 = 2;
1746 }
1747 } else {
1748 tmp_control = bcm43xx_get_lopair(phy, i, j * 2);
1749 if (!tmp_control->used)
1750 continue;
1751 memcpy(&control, tmp_control, sizeof(control));
1752 r27 = 3;
1753 r31 = 0;
1754 }
1755 bcm43xx_radio_write16(bcm, 0x43, i);
1756 bcm43xx_radio_write16(bcm, 0x52, radio->txctl2);
1757 udelay(10);
1758
1759 bcm43xx_phy_set_baseband_attenuation(bcm, j * 2);
1760
1761 tmp = (regstack[10] & 0xFFF0);
1762 if (r31)
1763 tmp |= 0x0008;
1764 bcm43xx_radio_write16(bcm, 0x007A, tmp);
1765
1766 tmp_control = bcm43xx_get_lopair(phy, i, j * 2);
1767 bcm43xx_phy_lo_g_state(bcm, &control, tmp_control, r27);
1768 }
1769 oldi = i;
1770 }
1771 /* Loop over each possible RadioAttenuation (10-13) */
1772 for (i = 10; i < 14; i++) {
1773 /* Loop over each possible BasebandAttenuation/2 */
1774 for (j = 0; j < 4; j++) {
1775 if (is_initializing) {
1776 tmp_control = bcm43xx_get_lopair(phy, i - 9, j * 2);
1777 memcpy(&control, tmp_control, sizeof(control));
1778 tmp = (i - 9) * 2 + j - 5;//FIXME: This is wrong, as the following if statement can never trigger.
1779 r27 = 0;
1780 r31 = 0;
1781 if (tmp > 14) {
1782 r31 = 1;
1783 if (tmp > 17)
1784 r27 = 1;
1785 if (tmp > 19)
1786 r27 = 2;
1787 }
1788 } else {
1789 tmp_control = bcm43xx_get_lopair(phy, i - 9, j * 2);
1790 if (!tmp_control->used)
1791 continue;
1792 memcpy(&control, tmp_control, sizeof(control));
1793 r27 = 3;
1794 r31 = 0;
1795 }
1796 bcm43xx_radio_write16(bcm, 0x43, i - 9);
1797 bcm43xx_radio_write16(bcm, 0x52,
1798 radio->txctl2
1799 | (3/*txctl1*/ << 4));//FIXME: shouldn't txctl1 be zero here and 3 in the loop above?
1800 udelay(10);
1801
1802 bcm43xx_phy_set_baseband_attenuation(bcm, j * 2);
1803
1804 tmp = (regstack[10] & 0xFFF0);
1805 if (r31)
1806 tmp |= 0x0008;
1807 bcm43xx_radio_write16(bcm, 0x7A, tmp);
1808
1809 tmp_control = bcm43xx_get_lopair(phy, i, j * 2);
1810 bcm43xx_phy_lo_g_state(bcm, &control, tmp_control, r27);
1811 }
1812 }
1813
1814 /* Restoration */
1815 if (phy->connected) {
1816 bcm43xx_phy_write(bcm, 0x0015, 0xE300);
1817 bcm43xx_phy_write(bcm, 0x0812, (r27 << 8) | 0xA0);
1818 udelay(5);
1819 bcm43xx_phy_write(bcm, 0x0812, (r27 << 8) | 0xA2);
1820 udelay(2);
1821 bcm43xx_phy_write(bcm, 0x0812, (r27 << 8) | 0xA3);
1822 } else
1823 bcm43xx_phy_write(bcm, 0x0015, r27 | 0xEFA0);
1824 bcm43xx_phy_lo_adjust(bcm, is_initializing);
1825 bcm43xx_phy_write(bcm, 0x002E, 0x807F);
1826 if (phy->connected)
1827 bcm43xx_phy_write(bcm, 0x002F, 0x0202);
1828 else
1829 bcm43xx_phy_write(bcm, 0x002F, 0x0101);
1830 bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, regstack[4]);
1831 bcm43xx_phy_write(bcm, 0x0015, regstack[5]);
1832 bcm43xx_phy_write(bcm, 0x002A, regstack[6]);
1833 bcm43xx_phy_write(bcm, 0x0035, regstack[7]);
1834 bcm43xx_phy_write(bcm, 0x0060, regstack[8]);
1835 bcm43xx_radio_write16(bcm, 0x0043, regstack[9]);
1836 bcm43xx_radio_write16(bcm, 0x007A, regstack[10]);
1837 regstack[11] &= 0x00F0;
1838 regstack[11] |= (bcm43xx_radio_read16(bcm, 0x52) & 0x000F);
1839 bcm43xx_radio_write16(bcm, 0x52, regstack[11]);
1840 bcm43xx_write16(bcm, 0x03E2, regstack[3]);
1841 if (phy->connected) {
1842 bcm43xx_phy_write(bcm, 0x0811, regstack[12]);
1843 bcm43xx_phy_write(bcm, 0x0812, regstack[13]);
1844 bcm43xx_phy_write(bcm, 0x0814, regstack[14]);
1845 bcm43xx_phy_write(bcm, 0x0815, regstack[15]);
1846 bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, regstack[0]);
1847 bcm43xx_phy_write(bcm, 0x0802, regstack[1]);
1848 }
1849 bcm43xx_radio_selectchannel(bcm, oldchannel, 1);
1850
1851#ifdef CONFIG_BCM43XX_DEBUG
1852 {
1853 /* Sanity check for all lopairs. */
1854 for (i = 0; i < BCM43xx_LO_COUNT; i++) {
1855 tmp_control = phy->_lo_pairs + i;
1856 if (tmp_control->low < -8 || tmp_control->low > 8 ||
1857 tmp_control->high < -8 || tmp_control->high > 8) {
1858 printk(KERN_WARNING PFX
1859 "WARNING: Invalid LOpair (low: %d, high: %d, index: %d)\n",
1860 tmp_control->low, tmp_control->high, i);
1861 }
1862 }
1863 }
1864#endif /* CONFIG_BCM43XX_DEBUG */
1865}
1866
1867static
1868void bcm43xx_phy_lo_mark_current_used(struct bcm43xx_private *bcm)
1869{
1870 struct bcm43xx_lopair *pair;
1871
1872 pair = bcm43xx_current_lopair(bcm);
1873 pair->used = 1;
1874}
1875
1876void bcm43xx_phy_lo_mark_all_unused(struct bcm43xx_private *bcm)
1877{
1878 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
1879 struct bcm43xx_lopair *pair;
1880 int i;
1881
1882 for (i = 0; i < BCM43xx_LO_COUNT; i++) {
1883 pair = phy->_lo_pairs + i;
1884 pair->used = 0;
1885 }
1886}
1887
1888/* http://bcm-specs.sipsolutions.net/EstimatePowerOut
1889 * This function converts a TSSI value to dBm in Q5.2
1890 */
1891static s8 bcm43xx_phy_estimate_power_out(struct bcm43xx_private *bcm, s8 tssi)
1892{
1893 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
1894 s8 dbm = 0;
1895 s32 tmp;
1896
1897 tmp = phy->idle_tssi;
1898 tmp += tssi;
1899 tmp -= phy->savedpctlreg;
1900
1901 switch (phy->type) {
1902 case BCM43xx_PHYTYPE_A:
1903 tmp += 0x80;
1904 tmp = limit_value(tmp, 0x00, 0xFF);
1905 dbm = phy->tssi2dbm[tmp];
1906 TODO(); //TODO: There's a FIXME on the specs
1907 break;
1908 case BCM43xx_PHYTYPE_B:
1909 case BCM43xx_PHYTYPE_G:
1910 tmp = limit_value(tmp, 0x00, 0x3F);
1911 dbm = phy->tssi2dbm[tmp];
1912 break;
1913 default:
1914 assert(0);
1915 }
1916
1917 return dbm;
1918}
1919
1920/* http://bcm-specs.sipsolutions.net/RecalculateTransmissionPower */
1921void bcm43xx_phy_xmitpower(struct bcm43xx_private *bcm)
1922{
1923 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
1924 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
1925
1926 if (phy->savedpctlreg == 0xFFFF)
1927 return;
1928 if ((bcm->board_type == 0x0416) &&
1929 (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM))
1930 return;
1931
1932 switch (phy->type) {
1933 case BCM43xx_PHYTYPE_A: {
1934
1935 TODO(); //TODO: Nothing for A PHYs yet :-/
1936
1937 break;
1938 }
1939 case BCM43xx_PHYTYPE_B:
1940 case BCM43xx_PHYTYPE_G: {
1941 u16 tmp;
1942 u16 txpower;
1943 s8 v0, v1, v2, v3;
1944 s8 average;
1945 u8 max_pwr;
1946 s16 desired_pwr, estimated_pwr, pwr_adjust;
1947 s16 radio_att_delta, baseband_att_delta;
1948 s16 radio_attenuation, baseband_attenuation;
1949 unsigned long phylock_flags;
1950
1951 tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x0058);
1952 v0 = (s8)(tmp & 0x00FF);
1953 v1 = (s8)((tmp & 0xFF00) >> 8);
1954 tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x005A);
1955 v2 = (s8)(tmp & 0x00FF);
1956 v3 = (s8)((tmp & 0xFF00) >> 8);
1957 tmp = 0;
1958
1959 if (v0 == 0x7F || v1 == 0x7F || v2 == 0x7F || v3 == 0x7F) {
1960 tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x0070);
1961 v0 = (s8)(tmp & 0x00FF);
1962 v1 = (s8)((tmp & 0xFF00) >> 8);
1963 tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x0072);
1964 v2 = (s8)(tmp & 0x00FF);
1965 v3 = (s8)((tmp & 0xFF00) >> 8);
1966 if (v0 == 0x7F || v1 == 0x7F || v2 == 0x7F || v3 == 0x7F)
1967 return;
1968 v0 = (v0 + 0x20) & 0x3F;
1969 v1 = (v1 + 0x20) & 0x3F;
1970 v2 = (v2 + 0x20) & 0x3F;
1971 v3 = (v3 + 0x20) & 0x3F;
1972 tmp = 1;
1973 }
1974 bcm43xx_radio_clear_tssi(bcm);
1975
1976 average = (v0 + v1 + v2 + v3 + 2) / 4;
1977
1978 if (tmp && (bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x005E) & 0x8))
1979 average -= 13;
1980
1981 estimated_pwr = bcm43xx_phy_estimate_power_out(bcm, average);
1982
1983 max_pwr = bcm->sprom.maxpower_bgphy;
1984
1985 if ((bcm->sprom.boardflags & BCM43xx_BFL_PACTRL) &&
1986 (phy->type == BCM43xx_PHYTYPE_G))
1987 max_pwr -= 0x3;
1988
1989 /*TODO:
1990 max_pwr = min(REG - bcm->sprom.antennagain_bgphy - 0x6, max_pwr)
1991 where REG is the max power as per the regulatory domain
1992 */
1993
1994 desired_pwr = limit_value(radio->txpower_desired, 0, max_pwr);
1995 /* Check if we need to adjust the current power. */
1996 pwr_adjust = desired_pwr - estimated_pwr;
1997 radio_att_delta = -(pwr_adjust + 7) >> 3;
1998 baseband_att_delta = -(pwr_adjust >> 1) - (4 * radio_att_delta);
1999 if ((radio_att_delta == 0) && (baseband_att_delta == 0)) {
2000 bcm43xx_phy_lo_mark_current_used(bcm);
2001 return;
2002 }
2003
2004 /* Calculate the new attenuation values. */
2005 baseband_attenuation = radio->baseband_atten;
2006 baseband_attenuation += baseband_att_delta;
2007 radio_attenuation = radio->radio_atten;
2008 radio_attenuation += radio_att_delta;
2009
2010 /* Get baseband and radio attenuation values into their permitted ranges.
2011 * baseband 0-11, radio 0-9.
2012 * Radio attenuation affects power level 4 times as much as baseband.
2013 */
2014 if (radio_attenuation < 0) {
2015 baseband_attenuation -= (4 * -radio_attenuation);
2016 radio_attenuation = 0;
2017 } else if (radio_attenuation > 9) {
2018 baseband_attenuation += (4 * (radio_attenuation - 9));
2019 radio_attenuation = 9;
2020 } else {
2021 while (baseband_attenuation < 0 && radio_attenuation > 0) {
2022 baseband_attenuation += 4;
2023 radio_attenuation--;
2024 }
2025 while (baseband_attenuation > 11 && radio_attenuation < 9) {
2026 baseband_attenuation -= 4;
2027 radio_attenuation++;
2028 }
2029 }
2030 baseband_attenuation = limit_value(baseband_attenuation, 0, 11);
2031
2032 txpower = radio->txctl1;
2033 if ((radio->version == 0x2050) && (radio->revision == 2)) {
2034 if (radio_attenuation <= 1) {
2035 if (txpower == 0) {
2036 txpower = 3;
2037 radio_attenuation += 2;
2038 baseband_attenuation += 2;
2039 } else if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL) {
2040 baseband_attenuation += 4 * (radio_attenuation - 2);
2041 radio_attenuation = 2;
2042 }
2043 } else if (radio_attenuation > 4 && txpower != 0) {
2044 txpower = 0;
2045 if (baseband_attenuation < 3) {
2046 radio_attenuation -= 3;
2047 baseband_attenuation += 2;
2048 } else {
2049 radio_attenuation -= 2;
2050 baseband_attenuation -= 2;
2051 }
2052 }
2053 }
2054 radio->txctl1 = txpower;
2055 baseband_attenuation = limit_value(baseband_attenuation, 0, 11);
2056 radio_attenuation = limit_value(radio_attenuation, 0, 9);
2057
2058 bcm43xx_phy_lock(bcm, phylock_flags);
2059 bcm43xx_radio_lock(bcm);
2060 bcm43xx_radio_set_txpower_bg(bcm, baseband_attenuation,
2061 radio_attenuation, txpower);
2062 bcm43xx_phy_lo_mark_current_used(bcm);
2063 bcm43xx_radio_unlock(bcm);
2064 bcm43xx_phy_unlock(bcm, phylock_flags);
2065 break;
2066 }
2067 default:
2068 assert(0);
2069 }
2070}
2071
2072static inline
2073s32 bcm43xx_tssi2dbm_ad(s32 num, s32 den)
2074{
2075 if (num < 0)
2076 return num/den;
2077 else
2078 return (num+den/2)/den;
2079}
2080
2081static inline
2082s8 bcm43xx_tssi2dbm_entry(s8 entry [], u8 index, s16 pab0, s16 pab1, s16 pab2)
2083{
2084 s32 m1, m2, f = 256, q, delta;
2085 s8 i = 0;
2086
2087 m1 = bcm43xx_tssi2dbm_ad(16 * pab0 + index * pab1, 32);
2088 m2 = max(bcm43xx_tssi2dbm_ad(32768 + index * pab2, 256), 1);
2089 do {
2090 if (i > 15)
2091 return -EINVAL;
2092 q = bcm43xx_tssi2dbm_ad(f * 4096 -
2093 bcm43xx_tssi2dbm_ad(m2 * f, 16) * f, 2048);
2094 delta = abs(q - f);
2095 f = q;
2096 i++;
2097 } while (delta >= 2);
2098 entry[index] = limit_value(bcm43xx_tssi2dbm_ad(m1 * f, 8192), -127, 128);
2099 return 0;
2100}
2101
2102/* http://bcm-specs.sipsolutions.net/TSSI_to_DBM_Table */
2103int bcm43xx_phy_init_tssi2dbm_table(struct bcm43xx_private *bcm)
2104{
2105 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
2106 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
2107 s16 pab0, pab1, pab2;
2108 u8 idx;
2109 s8 *dyn_tssi2dbm;
2110
2111 if (phy->type == BCM43xx_PHYTYPE_A) {
2112 pab0 = (s16)(bcm->sprom.pa1b0);
2113 pab1 = (s16)(bcm->sprom.pa1b1);
2114 pab2 = (s16)(bcm->sprom.pa1b2);
2115 } else {
2116 pab0 = (s16)(bcm->sprom.pa0b0);
2117 pab1 = (s16)(bcm->sprom.pa0b1);
2118 pab2 = (s16)(bcm->sprom.pa0b2);
2119 }
2120
2121 if ((bcm->chip_id == 0x4301) && (radio->version != 0x2050)) {
2122 phy->idle_tssi = 0x34;
2123 phy->tssi2dbm = bcm43xx_tssi2dbm_b_table;
2124 return 0;
2125 }
2126
2127 if (pab0 != 0 && pab1 != 0 && pab2 != 0 &&
2128 pab0 != -1 && pab1 != -1 && pab2 != -1) {
2129 /* The pabX values are set in SPROM. Use them. */
2130 if (phy->type == BCM43xx_PHYTYPE_A) {
2131 if ((s8)bcm->sprom.idle_tssi_tgt_aphy != 0 &&
2132 (s8)bcm->sprom.idle_tssi_tgt_aphy != -1)
2133 phy->idle_tssi = (s8)(bcm->sprom.idle_tssi_tgt_aphy);
2134 else
2135 phy->idle_tssi = 62;
2136 } else {
2137 if ((s8)bcm->sprom.idle_tssi_tgt_bgphy != 0 &&
2138 (s8)bcm->sprom.idle_tssi_tgt_bgphy != -1)
2139 phy->idle_tssi = (s8)(bcm->sprom.idle_tssi_tgt_bgphy);
2140 else
2141 phy->idle_tssi = 62;
2142 }
2143 dyn_tssi2dbm = kmalloc(64, GFP_KERNEL);
2144 if (dyn_tssi2dbm == NULL) {
2145 printk(KERN_ERR PFX "Could not allocate memory"
2146 "for tssi2dbm table\n");
2147 return -ENOMEM;
2148 }
2149 for (idx = 0; idx < 64; idx++)
2150 if (bcm43xx_tssi2dbm_entry(dyn_tssi2dbm, idx, pab0, pab1, pab2)) {
2151 phy->tssi2dbm = NULL;
2152 printk(KERN_ERR PFX "Could not generate "
2153 "tssi2dBm table\n");
2154 return -ENODEV;
2155 }
2156 phy->tssi2dbm = dyn_tssi2dbm;
2157 phy->dyn_tssi_tbl = 1;
2158 } else {
2159 /* pabX values not set in SPROM. */
2160 switch (phy->type) {
2161 case BCM43xx_PHYTYPE_A:
2162 /* APHY needs a generated table. */
2163 phy->tssi2dbm = NULL;
2164 printk(KERN_ERR PFX "Could not generate tssi2dBm "
2165 "table (wrong SPROM info)!\n");
2166 return -ENODEV;
2167 case BCM43xx_PHYTYPE_B:
2168 phy->idle_tssi = 0x34;
2169 phy->tssi2dbm = bcm43xx_tssi2dbm_b_table;
2170 break;
2171 case BCM43xx_PHYTYPE_G:
2172 phy->idle_tssi = 0x34;
2173 phy->tssi2dbm = bcm43xx_tssi2dbm_g_table;
2174 break;
2175 }
2176 }
2177
2178 return 0;
2179}
2180
2181int bcm43xx_phy_init(struct bcm43xx_private *bcm)
2182{
2183 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
2184 int err = -ENODEV;
2185 unsigned long flags;
2186
2187 /* We do not want to be preempted while calibrating
2188 * the hardware.
2189 */
2190 local_irq_save(flags);
2191
2192 switch (phy->type) {
2193 case BCM43xx_PHYTYPE_A:
2194 if (phy->rev == 2 || phy->rev == 3) {
2195 bcm43xx_phy_inita(bcm);
2196 err = 0;
2197 }
2198 break;
2199 case BCM43xx_PHYTYPE_B:
2200 switch (phy->rev) {
2201 case 2:
2202 bcm43xx_phy_initb2(bcm);
2203 err = 0;
2204 break;
2205 case 4:
2206 bcm43xx_phy_initb4(bcm);
2207 err = 0;
2208 break;
2209 case 5:
2210 bcm43xx_phy_initb5(bcm);
2211 err = 0;
2212 break;
2213 case 6:
2214 bcm43xx_phy_initb6(bcm);
2215 err = 0;
2216 break;
2217 }
2218 break;
2219 case BCM43xx_PHYTYPE_G:
2220 bcm43xx_phy_initg(bcm);
2221 err = 0;
2222 break;
2223 }
2224 local_irq_restore(flags);
2225 if (err)
2226 printk(KERN_WARNING PFX "Unknown PHYTYPE found!\n");
2227
2228 return err;
2229}
2230
2231void bcm43xx_phy_set_antenna_diversity(struct bcm43xx_private *bcm)
2232{
2233 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
2234 u16 antennadiv;
2235 u16 offset;
2236 u16 value;
2237 u32 ucodeflags;
2238
2239 antennadiv = phy->antenna_diversity;
2240
2241 if (antennadiv == 0xFFFF)
2242 antennadiv = 3;
2243 assert(antennadiv <= 3);
2244
2245 ucodeflags = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED,
2246 BCM43xx_UCODEFLAGS_OFFSET);
2247 bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED,
2248 BCM43xx_UCODEFLAGS_OFFSET,
2249 ucodeflags & ~BCM43xx_UCODEFLAG_AUTODIV);
2250
2251 switch (phy->type) {
2252 case BCM43xx_PHYTYPE_A:
2253 case BCM43xx_PHYTYPE_G:
2254 if (phy->type == BCM43xx_PHYTYPE_A)
2255 offset = 0x0000;
2256 else
2257 offset = 0x0400;
2258
2259 if (antennadiv == 2)
2260 value = (3/*automatic*/ << 7);
2261 else
2262 value = (antennadiv << 7);
2263 bcm43xx_phy_write(bcm, offset + 1,
2264 (bcm43xx_phy_read(bcm, offset + 1)
2265 & 0x7E7F) | value);
2266
2267 if (antennadiv >= 2) {
2268 if (antennadiv == 2)
2269 value = (antennadiv << 7);
2270 else
2271 value = (0/*force0*/ << 7);
2272 bcm43xx_phy_write(bcm, offset + 0x2B,
2273 (bcm43xx_phy_read(bcm, offset + 0x2B)
2274 & 0xFEFF) | value);
2275 }
2276
2277 if (phy->type == BCM43xx_PHYTYPE_G) {
2278 if (antennadiv >= 2)
2279 bcm43xx_phy_write(bcm, 0x048C,
2280 bcm43xx_phy_read(bcm, 0x048C)
2281 | 0x2000);
2282 else
2283 bcm43xx_phy_write(bcm, 0x048C,
2284 bcm43xx_phy_read(bcm, 0x048C)
2285 & ~0x2000);
2286 if (phy->rev >= 2) {
2287 bcm43xx_phy_write(bcm, 0x0461,
2288 bcm43xx_phy_read(bcm, 0x0461)
2289 | 0x0010);
2290 bcm43xx_phy_write(bcm, 0x04AD,
2291 (bcm43xx_phy_read(bcm, 0x04AD)
2292 & 0x00FF) | 0x0015);
2293 if (phy->rev == 2)
2294 bcm43xx_phy_write(bcm, 0x0427, 0x0008);
2295 else
2296 bcm43xx_phy_write(bcm, 0x0427,
2297 (bcm43xx_phy_read(bcm, 0x0427)
2298 & 0x00FF) | 0x0008);
2299 }
2300 else if (phy->rev >= 6)
2301 bcm43xx_phy_write(bcm, 0x049B, 0x00DC);
2302 } else {
2303 if (phy->rev < 3)
2304 bcm43xx_phy_write(bcm, 0x002B,
2305 (bcm43xx_phy_read(bcm, 0x002B)
2306 & 0x00FF) | 0x0024);
2307 else {
2308 bcm43xx_phy_write(bcm, 0x0061,
2309 bcm43xx_phy_read(bcm, 0x0061)
2310 | 0x0010);
2311 if (phy->rev == 3) {
2312 bcm43xx_phy_write(bcm, 0x0093, 0x001D);
2313 bcm43xx_phy_write(bcm, 0x0027, 0x0008);
2314 } else {
2315 bcm43xx_phy_write(bcm, 0x0093, 0x003A);
2316 bcm43xx_phy_write(bcm, 0x0027,
2317 (bcm43xx_phy_read(bcm, 0x0027)
2318 & 0x00FF) | 0x0008);
2319 }
2320 }
2321 }
2322 break;
2323 case BCM43xx_PHYTYPE_B:
2324 if (bcm->current_core->rev == 2)
2325 value = (3/*automatic*/ << 7);
2326 else
2327 value = (antennadiv << 7);
2328 bcm43xx_phy_write(bcm, 0x03E2,
2329 (bcm43xx_phy_read(bcm, 0x03E2)
2330 & 0xFE7F) | value);
2331 break;
2332 default:
2333 assert(0);
2334 }
2335
2336 if (antennadiv >= 2) {
2337 ucodeflags = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED,
2338 BCM43xx_UCODEFLAGS_OFFSET);
2339 bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED,
2340 BCM43xx_UCODEFLAGS_OFFSET,
2341 ucodeflags | BCM43xx_UCODEFLAG_AUTODIV);
2342 }
2343
2344 phy->antenna_diversity = antennadiv;
2345}
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.h b/drivers/net/wireless/bcm43xx/bcm43xx_phy.h
new file mode 100644
index 000000000000..1f321ef42be8
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_phy.h
@@ -0,0 +1,74 @@
1/*
2
3 Broadcom BCM43xx wireless driver
4
5 Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
6 Stefano Brivio <st3@riseup.net>
7 Michael Buesch <mbuesch@freenet.de>
8 Danny van Dyk <kugelfang@gentoo.org>
9 Andreas Jaggi <andreas.jaggi@waterwave.ch>
10
11 Some parts of the code in this file are derived from the ipw2200
12 driver Copyright(c) 2003 - 2004 Intel Corporation.
13
14 This program is free software; you can redistribute it and/or modify
15 it under the terms of the GNU General Public License as published by
16 the Free Software Foundation; either version 2 of the License, or
17 (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; see the file COPYING. If not, write to
26 the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
27 Boston, MA 02110-1301, USA.
28
29*/
30
31#ifndef BCM43xx_PHY_H_
32#define BCM43xx_PHY_H_
33
34#include <linux/types.h>
35
36struct bcm43xx_private;
37
38void bcm43xx_raw_phy_lock(struct bcm43xx_private *bcm);
39#define bcm43xx_phy_lock(bcm, flags) \
40 do { \
41 local_irq_save(flags); \
42 bcm43xx_raw_phy_lock(bcm); \
43 } while (0)
44void bcm43xx_raw_phy_unlock(struct bcm43xx_private *bcm);
45#define bcm43xx_phy_unlock(bcm, flags) \
46 do { \
47 bcm43xx_raw_phy_unlock(bcm); \
48 local_irq_restore(flags); \
49 } while (0)
50
51u16 bcm43xx_phy_read(struct bcm43xx_private *bcm, u16 offset);
52void bcm43xx_phy_write(struct bcm43xx_private *bcm, u16 offset, u16 val);
53
54int bcm43xx_phy_init_tssi2dbm_table(struct bcm43xx_private *bcm);
55int bcm43xx_phy_init(struct bcm43xx_private *bcm);
56
57void bcm43xx_phy_set_antenna_diversity(struct bcm43xx_private *bcm);
58void bcm43xx_phy_calibrate(struct bcm43xx_private *bcm);
59int bcm43xx_phy_connect(struct bcm43xx_private *bcm, int connect);
60
61void bcm43xx_phy_lo_b_measure(struct bcm43xx_private *bcm);
62void bcm43xx_phy_lo_g_measure(struct bcm43xx_private *bcm);
63void bcm43xx_phy_xmitpower(struct bcm43xx_private *bcm);
64
65/* Adjust the LocalOscillator to the saved values.
66 * "fixed" is only set to 1 once in initialization. Set to 0 otherwise.
67 */
68void bcm43xx_phy_lo_adjust(struct bcm43xx_private *bcm, int fixed);
69void bcm43xx_phy_lo_mark_all_unused(struct bcm43xx_private *bcm);
70
71void bcm43xx_phy_set_baseband_attenuation(struct bcm43xx_private *bcm,
72 u16 baseband_attenuation);
73
74#endif /* BCM43xx_PHY_H_ */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c
new file mode 100644
index 000000000000..c59ddd40680d
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c
@@ -0,0 +1,606 @@
1/*
2
3 Broadcom BCM43xx wireless driver
4
5 PIO Transmission
6
7 Copyright (c) 2005 Michael Buesch <mbuesch@freenet.de>
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; see the file COPYING. If not, write to
21 the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
22 Boston, MA 02110-1301, USA.
23
24*/
25
26#include "bcm43xx.h"
27#include "bcm43xx_pio.h"
28#include "bcm43xx_main.h"
29#include "bcm43xx_xmit.h"
30
31#include <linux/delay.h>
32
33
34static void tx_start(struct bcm43xx_pioqueue *queue)
35{
36 bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
37 BCM43xx_PIO_TXCTL_INIT);
38}
39
40static void tx_octet(struct bcm43xx_pioqueue *queue,
41 u8 octet)
42{
43 if (queue->need_workarounds) {
44 bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA,
45 octet);
46 bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
47 BCM43xx_PIO_TXCTL_WRITEHI);
48 } else {
49 bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
50 BCM43xx_PIO_TXCTL_WRITEHI);
51 bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA,
52 octet);
53 }
54}
55
56static u16 tx_get_next_word(struct bcm43xx_txhdr *txhdr,
57 const u8 *packet,
58 unsigned int *pos)
59{
60 const u8 *source;
61 unsigned int i = *pos;
62 u16 ret;
63
64 if (i < sizeof(*txhdr)) {
65 source = (const u8 *)txhdr;
66 } else {
67 source = packet;
68 i -= sizeof(*txhdr);
69 }
70 ret = le16_to_cpu( *((u16 *)(source + i)) );
71 *pos += 2;
72
73 return ret;
74}
75
76static void tx_data(struct bcm43xx_pioqueue *queue,
77 struct bcm43xx_txhdr *txhdr,
78 const u8 *packet,
79 unsigned int octets)
80{
81 u16 data;
82 unsigned int i = 0;
83
84 if (queue->need_workarounds) {
85 data = tx_get_next_word(txhdr, packet, &i);
86 bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, data);
87 }
88 bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
89 BCM43xx_PIO_TXCTL_WRITELO |
90 BCM43xx_PIO_TXCTL_WRITEHI);
91 while (i < octets - 1) {
92 data = tx_get_next_word(txhdr, packet, &i);
93 bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, data);
94 }
95 if (octets % 2)
96 tx_octet(queue, packet[octets - sizeof(*txhdr) - 1]);
97}
98
99static void tx_complete(struct bcm43xx_pioqueue *queue,
100 struct sk_buff *skb)
101{
102 if (queue->need_workarounds) {
103 bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA,
104 skb->data[skb->len - 1]);
105 bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
106 BCM43xx_PIO_TXCTL_WRITEHI |
107 BCM43xx_PIO_TXCTL_COMPLETE);
108 } else {
109 bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
110 BCM43xx_PIO_TXCTL_COMPLETE);
111 }
112}
113
114static u16 generate_cookie(struct bcm43xx_pioqueue *queue,
115 int packetindex)
116{
117 u16 cookie = 0x0000;
118
119 /* We use the upper 4 bits for the PIO
120 * controller ID and the lower 12 bits
121 * for the packet index (in the cache).
122 */
123 switch (queue->mmio_base) {
124 case BCM43xx_MMIO_PIO1_BASE:
125 break;
126 case BCM43xx_MMIO_PIO2_BASE:
127 cookie = 0x1000;
128 break;
129 case BCM43xx_MMIO_PIO3_BASE:
130 cookie = 0x2000;
131 break;
132 case BCM43xx_MMIO_PIO4_BASE:
133 cookie = 0x3000;
134 break;
135 default:
136 assert(0);
137 }
138 assert(((u16)packetindex & 0xF000) == 0x0000);
139 cookie |= (u16)packetindex;
140
141 return cookie;
142}
143
144static
145struct bcm43xx_pioqueue * parse_cookie(struct bcm43xx_private *bcm,
146 u16 cookie,
147 struct bcm43xx_pio_txpacket **packet)
148{
149 struct bcm43xx_pio *pio = bcm43xx_current_pio(bcm);
150 struct bcm43xx_pioqueue *queue = NULL;
151 int packetindex;
152
153 switch (cookie & 0xF000) {
154 case 0x0000:
155 queue = pio->queue0;
156 break;
157 case 0x1000:
158 queue = pio->queue1;
159 break;
160 case 0x2000:
161 queue = pio->queue2;
162 break;
163 case 0x3000:
164 queue = pio->queue3;
165 break;
166 default:
167 assert(0);
168 }
169 packetindex = (cookie & 0x0FFF);
170 assert(packetindex >= 0 && packetindex < BCM43xx_PIO_MAXTXPACKETS);
171 *packet = &(queue->tx_packets_cache[packetindex]);
172
173 return queue;
174}
175
176static void pio_tx_write_fragment(struct bcm43xx_pioqueue *queue,
177 struct sk_buff *skb,
178 struct bcm43xx_pio_txpacket *packet)
179{
180 struct bcm43xx_txhdr txhdr;
181 unsigned int octets;
182
183 assert(skb_shinfo(skb)->nr_frags == 0);
184 bcm43xx_generate_txhdr(queue->bcm,
185 &txhdr, skb->data, skb->len,
186 (packet->xmitted_frags == 0),
187 generate_cookie(queue, pio_txpacket_getindex(packet)));
188
189 tx_start(queue);
190 octets = skb->len + sizeof(txhdr);
191 if (queue->need_workarounds)
192 octets--;
193 tx_data(queue, &txhdr, (u8 *)skb->data, octets);
194 tx_complete(queue, skb);
195}
196
197static void free_txpacket(struct bcm43xx_pio_txpacket *packet,
198 int irq_context)
199{
200 struct bcm43xx_pioqueue *queue = packet->queue;
201
202 ieee80211_txb_free(packet->txb);
203 list_move(&packet->list, &queue->txfree);
204 queue->nr_txfree++;
205
206 assert(queue->tx_devq_used >= packet->xmitted_octets);
207 assert(queue->tx_devq_packets >= packet->xmitted_frags);
208 queue->tx_devq_used -= packet->xmitted_octets;
209 queue->tx_devq_packets -= packet->xmitted_frags;
210}
211
212static int pio_tx_packet(struct bcm43xx_pio_txpacket *packet)
213{
214 struct bcm43xx_pioqueue *queue = packet->queue;
215 struct ieee80211_txb *txb = packet->txb;
216 struct sk_buff *skb;
217 u16 octets;
218 int i;
219
220 for (i = packet->xmitted_frags; i < txb->nr_frags; i++) {
221 skb = txb->fragments[i];
222
223 octets = (u16)skb->len + sizeof(struct bcm43xx_txhdr);
224 assert(queue->tx_devq_size >= octets);
225 assert(queue->tx_devq_packets <= BCM43xx_PIO_MAXTXDEVQPACKETS);
226 assert(queue->tx_devq_used <= queue->tx_devq_size);
227 /* Check if there is sufficient free space on the device
228 * TX queue. If not, return and let the TX tasklet
229 * retry later.
230 */
231 if (queue->tx_devq_packets == BCM43xx_PIO_MAXTXDEVQPACKETS)
232 return -EBUSY;
233 if (queue->tx_devq_used + octets > queue->tx_devq_size)
234 return -EBUSY;
235 /* Now poke the device. */
236 pio_tx_write_fragment(queue, skb, packet);
237
238 /* Account for the packet size.
239 * (We must not overflow the device TX queue)
240 */
241 queue->tx_devq_packets++;
242 queue->tx_devq_used += octets;
243
244 assert(packet->xmitted_frags <= packet->txb->nr_frags);
245 packet->xmitted_frags++;
246 packet->xmitted_octets += octets;
247 }
248 list_move_tail(&packet->list, &queue->txrunning);
249
250 return 0;
251}
252
253static void tx_tasklet(unsigned long d)
254{
255 struct bcm43xx_pioqueue *queue = (struct bcm43xx_pioqueue *)d;
256 struct bcm43xx_private *bcm = queue->bcm;
257 unsigned long flags;
258 struct bcm43xx_pio_txpacket *packet, *tmp_packet;
259 int err;
260
261 bcm43xx_lock_mmio(bcm, flags);
262 list_for_each_entry_safe(packet, tmp_packet, &queue->txqueue, list) {
263 assert(packet->xmitted_frags < packet->txb->nr_frags);
264 if (packet->xmitted_frags == 0) {
265 int i;
266 struct sk_buff *skb;
267
268 /* Check if the device queue is big
269 * enough for every fragment. If not, drop the
270 * whole packet.
271 */
272 for (i = 0; i < packet->txb->nr_frags; i++) {
273 skb = packet->txb->fragments[i];
274 if (unlikely(skb->len > queue->tx_devq_size)) {
275 dprintkl(KERN_ERR PFX "PIO TX device queue too small. "
276 "Dropping packet.\n");
277 free_txpacket(packet, 1);
278 goto next_packet;
279 }
280 }
281 }
282 /* Try to transmit the packet.
283 * This may not completely succeed.
284 */
285 err = pio_tx_packet(packet);
286 if (err)
287 break;
288 next_packet:
289 continue;
290 }
291 bcm43xx_unlock_mmio(bcm, flags);
292}
293
294static void setup_txqueues(struct bcm43xx_pioqueue *queue)
295{
296 struct bcm43xx_pio_txpacket *packet;
297 int i;
298
299 queue->nr_txfree = BCM43xx_PIO_MAXTXPACKETS;
300 for (i = 0; i < BCM43xx_PIO_MAXTXPACKETS; i++) {
301 packet = &(queue->tx_packets_cache[i]);
302
303 packet->queue = queue;
304 INIT_LIST_HEAD(&packet->list);
305
306 list_add(&packet->list, &queue->txfree);
307 }
308}
309
310static
311struct bcm43xx_pioqueue * bcm43xx_setup_pioqueue(struct bcm43xx_private *bcm,
312 u16 pio_mmio_base)
313{
314 struct bcm43xx_pioqueue *queue;
315 u32 value;
316 u16 qsize;
317
318 queue = kzalloc(sizeof(*queue), GFP_KERNEL);
319 if (!queue)
320 goto out;
321
322 queue->bcm = bcm;
323 queue->mmio_base = pio_mmio_base;
324 queue->need_workarounds = (bcm->current_core->rev < 3);
325
326 INIT_LIST_HEAD(&queue->txfree);
327 INIT_LIST_HEAD(&queue->txqueue);
328 INIT_LIST_HEAD(&queue->txrunning);
329 tasklet_init(&queue->txtask, tx_tasklet,
330 (unsigned long)queue);
331
332 value = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
333 value |= BCM43xx_SBF_XFER_REG_BYTESWAP;
334 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value);
335
336 qsize = bcm43xx_read16(bcm, queue->mmio_base + BCM43xx_PIO_TXQBUFSIZE);
337 if (qsize <= BCM43xx_PIO_TXQADJUST) {
338 printk(KERN_ERR PFX "PIO tx device-queue too small (%u)\n", qsize);
339 goto err_freequeue;
340 }
341 qsize -= BCM43xx_PIO_TXQADJUST;
342 queue->tx_devq_size = qsize;
343
344 setup_txqueues(queue);
345
346out:
347 return queue;
348
349err_freequeue:
350 kfree(queue);
351 queue = NULL;
352 goto out;
353}
354
355static void cancel_transfers(struct bcm43xx_pioqueue *queue)
356{
357 struct bcm43xx_pio_txpacket *packet, *tmp_packet;
358
359 netif_tx_disable(queue->bcm->net_dev);
360 assert(queue->bcm->shutting_down);
361 tasklet_disable(&queue->txtask);
362
363 list_for_each_entry_safe(packet, tmp_packet, &queue->txrunning, list)
364 free_txpacket(packet, 0);
365 list_for_each_entry_safe(packet, tmp_packet, &queue->txqueue, list)
366 free_txpacket(packet, 0);
367}
368
369static void bcm43xx_destroy_pioqueue(struct bcm43xx_pioqueue *queue)
370{
371 if (!queue)
372 return;
373
374 cancel_transfers(queue);
375 kfree(queue);
376}
377
378void bcm43xx_pio_free(struct bcm43xx_private *bcm)
379{
380 struct bcm43xx_pio *pio;
381
382 if (!bcm43xx_using_pio(bcm))
383 return;
384 pio = bcm43xx_current_pio(bcm);
385
386 bcm43xx_destroy_pioqueue(pio->queue3);
387 pio->queue3 = NULL;
388 bcm43xx_destroy_pioqueue(pio->queue2);
389 pio->queue2 = NULL;
390 bcm43xx_destroy_pioqueue(pio->queue1);
391 pio->queue1 = NULL;
392 bcm43xx_destroy_pioqueue(pio->queue0);
393 pio->queue0 = NULL;
394}
395
396int bcm43xx_pio_init(struct bcm43xx_private *bcm)
397{
398 struct bcm43xx_pio *pio = bcm43xx_current_pio(bcm);
399 struct bcm43xx_pioqueue *queue;
400 int err = -ENOMEM;
401
402 queue = bcm43xx_setup_pioqueue(bcm, BCM43xx_MMIO_PIO1_BASE);
403 if (!queue)
404 goto out;
405 pio->queue0 = queue;
406
407 queue = bcm43xx_setup_pioqueue(bcm, BCM43xx_MMIO_PIO2_BASE);
408 if (!queue)
409 goto err_destroy0;
410 pio->queue1 = queue;
411
412 queue = bcm43xx_setup_pioqueue(bcm, BCM43xx_MMIO_PIO3_BASE);
413 if (!queue)
414 goto err_destroy1;
415 pio->queue2 = queue;
416
417 queue = bcm43xx_setup_pioqueue(bcm, BCM43xx_MMIO_PIO4_BASE);
418 if (!queue)
419 goto err_destroy2;
420 pio->queue3 = queue;
421
422 if (bcm->current_core->rev < 3)
423 bcm->irq_savedstate |= BCM43xx_IRQ_PIO_WORKAROUND;
424
425 dprintk(KERN_INFO PFX "PIO initialized\n");
426 err = 0;
427out:
428 return err;
429
430err_destroy2:
431 bcm43xx_destroy_pioqueue(pio->queue2);
432 pio->queue2 = NULL;
433err_destroy1:
434 bcm43xx_destroy_pioqueue(pio->queue1);
435 pio->queue1 = NULL;
436err_destroy0:
437 bcm43xx_destroy_pioqueue(pio->queue0);
438 pio->queue0 = NULL;
439 goto out;
440}
441
442int bcm43xx_pio_tx(struct bcm43xx_private *bcm,
443 struct ieee80211_txb *txb)
444{
445 struct bcm43xx_pioqueue *queue = bcm43xx_current_pio(bcm)->queue1;
446 struct bcm43xx_pio_txpacket *packet;
447 u16 tmp;
448
449 assert(!queue->tx_suspended);
450 assert(!list_empty(&queue->txfree));
451
452 tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL);
453 if (tmp & BCM43xx_PIO_TXCTL_SUSPEND)
454 return -EBUSY;
455
456 packet = list_entry(queue->txfree.next, struct bcm43xx_pio_txpacket, list);
457 packet->txb = txb;
458 packet->xmitted_frags = 0;
459 packet->xmitted_octets = 0;
460 list_move_tail(&packet->list, &queue->txqueue);
461 queue->nr_txfree--;
462 assert(queue->nr_txfree < BCM43xx_PIO_MAXTXPACKETS);
463
464 /* Suspend TX, if we are out of packets in the "free" queue. */
465 if (unlikely(list_empty(&queue->txfree))) {
466 netif_stop_queue(queue->bcm->net_dev);
467 queue->tx_suspended = 1;
468 }
469
470 tasklet_schedule(&queue->txtask);
471
472 return 0;
473}
474
475void bcm43xx_pio_handle_xmitstatus(struct bcm43xx_private *bcm,
476 struct bcm43xx_xmitstatus *status)
477{
478 struct bcm43xx_pioqueue *queue;
479 struct bcm43xx_pio_txpacket *packet;
480
481 queue = parse_cookie(bcm, status->cookie, &packet);
482 assert(queue);
483//TODO
484if (!queue)
485return;
486 free_txpacket(packet, 1);
487 if (unlikely(queue->tx_suspended)) {
488 queue->tx_suspended = 0;
489 netif_wake_queue(queue->bcm->net_dev);
490 }
491 /* If there are packets on the txqueue, poke the tasklet. */
492 if (!list_empty(&queue->txqueue))
493 tasklet_schedule(&queue->txtask);
494}
495
496static void pio_rx_error(struct bcm43xx_pioqueue *queue,
497 int clear_buffers,
498 const char *error)
499{
500 int i;
501
502 printkl("PIO RX error: %s\n", error);
503 bcm43xx_pio_write(queue, BCM43xx_PIO_RXCTL,
504 BCM43xx_PIO_RXCTL_READY);
505 if (clear_buffers) {
506 assert(queue->mmio_base == BCM43xx_MMIO_PIO1_BASE);
507 for (i = 0; i < 15; i++) {
508 /* Dummy read. */
509 bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA);
510 }
511 }
512}
513
514void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue)
515{
516 u16 preamble[21] = { 0 };
517 struct bcm43xx_rxhdr *rxhdr;
518 u16 tmp, len, rxflags2;
519 int i, preamble_readwords;
520 struct sk_buff *skb;
521
522return;
523 tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXCTL);
524 if (!(tmp & BCM43xx_PIO_RXCTL_DATAAVAILABLE)) {
525 dprintkl(KERN_ERR PFX "PIO RX: No data available\n");//TODO: remove this printk.
526 return;
527 }
528 bcm43xx_pio_write(queue, BCM43xx_PIO_RXCTL,
529 BCM43xx_PIO_RXCTL_DATAAVAILABLE);
530
531 for (i = 0; i < 10; i++) {
532 tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXCTL);
533 if (tmp & BCM43xx_PIO_RXCTL_READY)
534 goto data_ready;
535 udelay(10);
536 }
537 dprintkl(KERN_ERR PFX "PIO RX timed out\n");
538 return;
539data_ready:
540
541//FIXME: endianess in this function.
542 len = le16_to_cpu(bcm43xx_pio_read(queue, BCM43xx_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 != BCM43xx_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 == BCM43xx_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 = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA);
558 preamble[i + 1] = cpu_to_be16(tmp);//FIXME?
559 }
560 rxhdr = (struct bcm43xx_rxhdr *)preamble;
561 rxflags2 = le16_to_cpu(rxhdr->flags2);
562 if (unlikely(rxflags2 & BCM43xx_RXHDR_FLAGS2_INVALIDFRAME)) {
563 pio_rx_error(queue,
564 (queue->mmio_base == BCM43xx_MMIO_PIO1_BASE),
565 "invalid frame");
566 return;
567 }
568 if (queue->mmio_base == BCM43xx_MMIO_PIO4_BASE) {
569 /* We received an xmit status. */
570 struct bcm43xx_hwxmitstatus *hw;
571 struct bcm43xx_xmitstatus stat;
572
573 hw = (struct bcm43xx_hwxmitstatus *)(preamble + 1);
574 stat.cookie = le16_to_cpu(hw->cookie);
575 stat.flags = hw->flags;
576 stat.cnt1 = hw->cnt1;
577 stat.cnt2 = hw->cnt2;
578 stat.seq = le16_to_cpu(hw->seq);
579 stat.unknown = le16_to_cpu(hw->unknown);
580
581 bcm43xx_debugfs_log_txstat(queue->bcm, &stat);
582 bcm43xx_pio_handle_xmitstatus(queue->bcm, &stat);
583
584 return;
585 }
586
587 skb = dev_alloc_skb(len);
588 if (unlikely(!skb)) {
589 pio_rx_error(queue, 1, "OOM");
590 return;
591 }
592 skb_put(skb, len);
593 for (i = 0; i < len - 1; i += 2) {
594 tmp = cpu_to_be16(bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA));
595 *((u16 *)(skb->data + i)) = tmp;
596 }
597 if (len % 2) {
598 tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA);
599 skb->data[len - 1] = (tmp & 0x00FF);
600 if (rxflags2 & BCM43xx_RXHDR_FLAGS2_TYPE2FRAME)
601 skb->data[0x20] = (tmp & 0xFF00) >> 8;
602 else
603 skb->data[0x1E] = (tmp & 0xFF00) >> 8;
604 }
605 bcm43xx_rx(queue->bcm, skb, rxhdr);
606}
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_pio.h b/drivers/net/wireless/bcm43xx/bcm43xx_pio.h
new file mode 100644
index 000000000000..970627bc1769
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_pio.h
@@ -0,0 +1,138 @@
1#ifndef BCM43xx_PIO_H_
2#define BCM43xx_PIO_H_
3
4#include "bcm43xx.h"
5
6#include <linux/interrupt.h>
7#include <linux/list.h>
8#include <linux/skbuff.h>
9
10
11#define BCM43xx_PIO_TXCTL 0x00
12#define BCM43xx_PIO_TXDATA 0x02
13#define BCM43xx_PIO_TXQBUFSIZE 0x04
14#define BCM43xx_PIO_RXCTL 0x08
15#define BCM43xx_PIO_RXDATA 0x0A
16
17#define BCM43xx_PIO_TXCTL_WRITEHI (1 << 0)
18#define BCM43xx_PIO_TXCTL_WRITELO (1 << 1)
19#define BCM43xx_PIO_TXCTL_COMPLETE (1 << 2)
20#define BCM43xx_PIO_TXCTL_INIT (1 << 3)
21#define BCM43xx_PIO_TXCTL_SUSPEND (1 << 7)
22
23#define BCM43xx_PIO_RXCTL_DATAAVAILABLE (1 << 0)
24#define BCM43xx_PIO_RXCTL_READY (1 << 1)
25
26/* PIO constants */
27#define BCM43xx_PIO_MAXTXDEVQPACKETS 31
28#define BCM43xx_PIO_TXQADJUST 80
29
30/* PIO tuning knobs */
31#define BCM43xx_PIO_MAXTXPACKETS 256
32
33
34
35#ifdef CONFIG_BCM43XX_PIO
36
37
38struct bcm43xx_pioqueue;
39struct bcm43xx_xmitstatus;
40
41struct bcm43xx_pio_txpacket {
42 struct bcm43xx_pioqueue *queue;
43 struct ieee80211_txb *txb;
44 struct list_head list;
45
46 u8 xmitted_frags;
47 u16 xmitted_octets;
48};
49
50#define pio_txpacket_getindex(packet) ((int)((packet) - (packet)->queue->tx_packets_cache))
51
52struct bcm43xx_pioqueue {
53 struct bcm43xx_private *bcm;
54 u16 mmio_base;
55
56 u8 tx_suspended:1,
57 need_workarounds:1; /* Workarounds needed for core.rev < 3 */
58
59 /* Adjusted size of the device internal TX buffer. */
60 u16 tx_devq_size;
61 /* Used octets of the device internal TX buffer. */
62 u16 tx_devq_used;
63 /* Used packet slots in the device internal TX buffer. */
64 u8 tx_devq_packets;
65 /* Packets from the txfree list can
66 * be taken on incoming TX requests.
67 */
68 struct list_head txfree;
69 unsigned int nr_txfree;
70 /* Packets on the txqueue are queued,
71 * but not completely written to the chip, yet.
72 */
73 struct list_head txqueue;
74 /* Packets on the txrunning queue are completely
75 * posted to the device. We are waiting for the txstatus.
76 */
77 struct list_head txrunning;
78 /* Total number or packets sent.
79 * (This counter can obviously wrap).
80 */
81 unsigned int nr_tx_packets;
82 struct tasklet_struct txtask;
83 struct bcm43xx_pio_txpacket tx_packets_cache[BCM43xx_PIO_MAXTXPACKETS];
84};
85
86static inline
87u16 bcm43xx_pio_read(struct bcm43xx_pioqueue *queue,
88 u16 offset)
89{
90 return bcm43xx_read16(queue->bcm, queue->mmio_base + offset);
91}
92
93static inline
94void bcm43xx_pio_write(struct bcm43xx_pioqueue *queue,
95 u16 offset, u16 value)
96{
97 bcm43xx_write16(queue->bcm, queue->mmio_base + offset, value);
98}
99
100
101int bcm43xx_pio_init(struct bcm43xx_private *bcm);
102void bcm43xx_pio_free(struct bcm43xx_private *bcm);
103
104int bcm43xx_pio_tx(struct bcm43xx_private *bcm,
105 struct ieee80211_txb *txb);
106void bcm43xx_pio_handle_xmitstatus(struct bcm43xx_private *bcm,
107 struct bcm43xx_xmitstatus *status);
108void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue);
109
110#else /* CONFIG_BCM43XX_PIO */
111
112static inline
113int bcm43xx_pio_init(struct bcm43xx_private *bcm)
114{
115 return 0;
116}
117static inline
118void bcm43xx_pio_free(struct bcm43xx_private *bcm)
119{
120}
121static inline
122int bcm43xx_pio_tx(struct bcm43xx_private *bcm,
123 struct ieee80211_txb *txb)
124{
125 return 0;
126}
127static inline
128void bcm43xx_pio_handle_xmitstatus(struct bcm43xx_private *bcm,
129 struct bcm43xx_xmitstatus *status)
130{
131}
132static inline
133void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue)
134{
135}
136
137#endif /* CONFIG_BCM43XX_PIO */
138#endif /* BCM43xx_PIO_H_ */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_power.c b/drivers/net/wireless/bcm43xx/bcm43xx_power.c
new file mode 100644
index 000000000000..3c92b62807c5
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_power.c
@@ -0,0 +1,358 @@
1/*
2
3 Broadcom BCM43xx wireless driver
4
5 Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
6 Stefano Brivio <st3@riseup.net>
7 Michael Buesch <mbuesch@freenet.de>
8 Danny van Dyk <kugelfang@gentoo.org>
9 Andreas Jaggi <andreas.jaggi@waterwave.ch>
10
11 Some parts of the code in this file are derived from the ipw2200
12 driver Copyright(c) 2003 - 2004 Intel Corporation.
13
14 This program is free software; you can redistribute it and/or modify
15 it under the terms of the GNU General Public License as published by
16 the Free Software Foundation; either version 2 of the License, or
17 (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; see the file COPYING. If not, write to
26 the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
27 Boston, MA 02110-1301, USA.
28
29*/
30
31#include <linux/delay.h>
32
33#include "bcm43xx.h"
34#include "bcm43xx_power.h"
35#include "bcm43xx_main.h"
36
37
38/* Get max/min slowclock frequency
39 * as described in http://bcm-specs.sipsolutions.net/PowerControl
40 */
41static int bcm43xx_pctl_clockfreqlimit(struct bcm43xx_private *bcm,
42 int get_max)
43{
44 int limit = 0;
45 int divisor;
46 int selection;
47 int err;
48 u32 tmp;
49 struct bcm43xx_coreinfo *old_core;
50
51 if (!(bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL))
52 goto out;
53 old_core = bcm->current_core;
54 err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon);
55 if (err)
56 goto out;
57
58 if (bcm->current_core->rev < 6) {
59 if ((bcm->bustype == BCM43xx_BUSTYPE_PCMCIA) ||
60 (bcm->bustype == BCM43xx_BUSTYPE_SB)) {
61 selection = 1;
62 divisor = 32;
63 } else {
64 err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCTL_OUT, &tmp);
65 if (err) {
66 printk(KERN_ERR PFX "clockfreqlimit pcicfg read failure\n");
67 goto out_switchback;
68 }
69 if (tmp & 0x10) {
70 /* PCI */
71 selection = 2;
72 divisor = 64;
73 } else {
74 /* XTAL */
75 selection = 1;
76 divisor = 32;
77 }
78 }
79 } else if (bcm->current_core->rev < 10) {
80 selection = (tmp & 0x07);
81 if (selection) {
82 tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL);
83 divisor = 4 * (1 + ((tmp & 0xFFFF0000) >> 16));
84 } else
85 divisor = 1;
86 } else {
87 tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SYSCLKCTL);
88 divisor = 4 * (1 + ((tmp & 0xFFFF0000) >> 16));
89 selection = 1;
90 }
91
92 switch (selection) {
93 case 0:
94 /* LPO */
95 if (get_max)
96 limit = 43000;
97 else
98 limit = 25000;
99 break;
100 case 1:
101 /* XTAL */
102 if (get_max)
103 limit = 20200000;
104 else
105 limit = 19800000;
106 break;
107 case 2:
108 /* PCI */
109 if (get_max)
110 limit = 34000000;
111 else
112 limit = 25000000;
113 break;
114 default:
115 assert(0);
116 }
117 limit /= divisor;
118
119out_switchback:
120 err = bcm43xx_switch_core(bcm, old_core);
121 assert(err == 0);
122
123out:
124 return limit;
125}
126
127/* init power control
128 * as described in http://bcm-specs.sipsolutions.net/PowerControl
129 */
130int bcm43xx_pctl_init(struct bcm43xx_private *bcm)
131{
132 int err, maxfreq;
133 struct bcm43xx_coreinfo *old_core;
134
135 if (!(bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL))
136 return 0;
137 old_core = bcm->current_core;
138 err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon);
139 if (err == -ENODEV)
140 return 0;
141 if (err)
142 goto out;
143
144 maxfreq = bcm43xx_pctl_clockfreqlimit(bcm, 1);
145 bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_PLLONDELAY,
146 (maxfreq * 150 + 999999) / 1000000);
147 bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_FREFSELDELAY,
148 (maxfreq * 15 + 999999) / 1000000);
149
150 err = bcm43xx_switch_core(bcm, old_core);
151 assert(err == 0);
152
153out:
154 return err;
155}
156
157u16 bcm43xx_pctl_powerup_delay(struct bcm43xx_private *bcm)
158{
159 u16 delay = 0;
160 int err;
161 u32 pll_on_delay;
162 struct bcm43xx_coreinfo *old_core;
163 int minfreq;
164
165 if (bcm->bustype != BCM43xx_BUSTYPE_PCI)
166 goto out;
167 if (!(bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL))
168 goto out;
169 old_core = bcm->current_core;
170 err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon);
171 if (err == -ENODEV)
172 goto out;
173
174 minfreq = bcm43xx_pctl_clockfreqlimit(bcm, 0);
175 pll_on_delay = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_PLLONDELAY);
176 delay = (((pll_on_delay + 2) * 1000000) + (minfreq - 1)) / minfreq;
177
178 err = bcm43xx_switch_core(bcm, old_core);
179 assert(err == 0);
180
181out:
182 return delay;
183}
184
185/* set the powercontrol clock
186 * as described in http://bcm-specs.sipsolutions.net/PowerControl
187 */
188int bcm43xx_pctl_set_clock(struct bcm43xx_private *bcm, u16 mode)
189{
190 int err;
191 struct bcm43xx_coreinfo *old_core;
192 u32 tmp;
193
194 old_core = bcm->current_core;
195 err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon);
196 if (err == -ENODEV)
197 return 0;
198 if (err)
199 goto out;
200
201 if (bcm->core_chipcommon.rev < 6) {
202 if (mode == BCM43xx_PCTL_CLK_FAST) {
203 err = bcm43xx_pctl_set_crystal(bcm, 1);
204 if (err)
205 goto out;
206 }
207 } else {
208 if ((bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL) &&
209 (bcm->core_chipcommon.rev < 10)) {
210 switch (mode) {
211 case BCM43xx_PCTL_CLK_FAST:
212 tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL);
213 tmp = (tmp & ~BCM43xx_PCTL_FORCE_SLOW) | BCM43xx_PCTL_FORCE_PLL;
214 bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL, tmp);
215 break;
216 case BCM43xx_PCTL_CLK_SLOW:
217 tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL);
218 tmp |= BCM43xx_PCTL_FORCE_SLOW;
219 bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL, tmp);
220 break;
221 case BCM43xx_PCTL_CLK_DYNAMIC:
222 tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL);
223 tmp &= ~BCM43xx_PCTL_FORCE_SLOW;
224 tmp |= BCM43xx_PCTL_FORCE_PLL;
225 tmp &= ~BCM43xx_PCTL_DYN_XTAL;
226 bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL, tmp);
227 }
228 }
229 }
230
231 err = bcm43xx_switch_core(bcm, old_core);
232 assert(err == 0);
233
234out:
235 return err;
236}
237
238int bcm43xx_pctl_set_crystal(struct bcm43xx_private *bcm, int on)
239{
240 int err;
241 u32 in, out, outenable;
242
243 err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCTL_IN, &in);
244 if (err)
245 goto err_pci;
246 err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCTL_OUT, &out);
247 if (err)
248 goto err_pci;
249 err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCTL_OUTENABLE, &outenable);
250 if (err)
251 goto err_pci;
252
253 outenable |= (BCM43xx_PCTL_XTAL_POWERUP | BCM43xx_PCTL_PLL_POWERDOWN);
254
255 if (on) {
256 if (in & 0x40)
257 return 0;
258
259 out |= (BCM43xx_PCTL_XTAL_POWERUP | BCM43xx_PCTL_PLL_POWERDOWN);
260
261 err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCTL_OUT, out);
262 if (err)
263 goto err_pci;
264 err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCTL_OUTENABLE, outenable);
265 if (err)
266 goto err_pci;
267 udelay(1000);
268
269 out &= ~BCM43xx_PCTL_PLL_POWERDOWN;
270 err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCTL_OUT, out);
271 if (err)
272 goto err_pci;
273 udelay(5000);
274 } else {
275 if (bcm->current_core->rev < 5)
276 return 0;
277 if (bcm->sprom.boardflags & BCM43xx_BFL_XTAL_NOSLOW)
278 return 0;
279
280/* XXX: Why BCM43xx_MMIO_RADIO_HWENABLED_xx can't be read at this time?
281 * err = bcm43xx_switch_core(bcm, bcm->active_80211_core);
282 * if (err)
283 * return err;
284 * if (((bcm->current_core->rev >= 3) &&
285 * (bcm43xx_read32(bcm, BCM43xx_MMIO_RADIO_HWENABLED_HI) & (1 << 16))) ||
286 * ((bcm->current_core->rev < 3) &&
287 * !(bcm43xx_read16(bcm, BCM43xx_MMIO_RADIO_HWENABLED_LO) & (1 << 4))))
288 * return 0;
289 * err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon);
290 * if (err)
291 * return err;
292 */
293
294 err = bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_SLOW);
295 if (err)
296 goto out;
297 out &= ~BCM43xx_PCTL_XTAL_POWERUP;
298 out |= BCM43xx_PCTL_PLL_POWERDOWN;
299 err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCTL_OUT, out);
300 if (err)
301 goto err_pci;
302 err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCTL_OUTENABLE, outenable);
303 if (err)
304 goto err_pci;
305 }
306
307out:
308 return err;
309
310err_pci:
311 printk(KERN_ERR PFX "Error: pctl_set_clock() could not access PCI config space!\n");
312 err = -EBUSY;
313 goto out;
314}
315
316/* Set the PowerSavingControlBits.
317 * Bitvalues:
318 * 0 => unset the bit
319 * 1 => set the bit
320 * -1 => calculate the bit
321 */
322void bcm43xx_power_saving_ctl_bits(struct bcm43xx_private *bcm,
323 int bit25, int bit26)
324{
325 int i;
326 u32 status;
327
328//FIXME: Force 25 to off and 26 to on for now:
329bit25 = 0;
330bit26 = 1;
331
332 if (bit25 == -1) {
333 //TODO: If powersave is not off and FIXME is not set and we are not in adhoc
334 // and thus is not an AP and we are associated, set bit 25
335 }
336 if (bit26 == -1) {
337 //TODO: If the device is awake or this is an AP, or we are scanning, or FIXME,
338 // or we are associated, or FIXME, or the latest PS-Poll packet sent was
339 // successful, set bit26
340 }
341 status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
342 if (bit25)
343 status |= BCM43xx_SBF_PS1;
344 else
345 status &= ~BCM43xx_SBF_PS1;
346 if (bit26)
347 status |= BCM43xx_SBF_PS2;
348 else
349 status &= ~BCM43xx_SBF_PS2;
350 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status);
351 if (bit26 && bcm->current_core->rev >= 5) {
352 for (i = 0; i < 100; i++) {
353 if (bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, 0x0040) != 4)
354 break;
355 udelay(10);
356 }
357 }
358}
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_power.h b/drivers/net/wireless/bcm43xx/bcm43xx_power.h
new file mode 100644
index 000000000000..5f63640810bd
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_power.h
@@ -0,0 +1,47 @@
1/*
2
3 Broadcom BCM43xx wireless driver
4
5 Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
6 Stefano Brivio <st3@riseup.net>
7 Michael Buesch <mbuesch@freenet.de>
8 Danny van Dyk <kugelfang@gentoo.org>
9 Andreas Jaggi <andreas.jaggi@waterwave.ch>
10
11 Some parts of the code in this file are derived from the ipw2200
12 driver Copyright(c) 2003 - 2004 Intel Corporation.
13
14 This program is free software; you can redistribute it and/or modify
15 it under the terms of the GNU General Public License as published by
16 the Free Software Foundation; either version 2 of the License, or
17 (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; see the file COPYING. If not, write to
26 the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
27 Boston, MA 02110-1301, USA.
28
29*/
30
31#ifndef BCM43xx_POWER_H_
32#define BCM43xx_POWER_H_
33
34#include <linux/types.h>
35
36
37struct bcm43xx_private;
38
39int bcm43xx_pctl_init(struct bcm43xx_private *bcm);
40int bcm43xx_pctl_set_clock(struct bcm43xx_private *bcm, u16 mode);
41int bcm43xx_pctl_set_crystal(struct bcm43xx_private *bcm, int on);
42u16 bcm43xx_pctl_powerup_delay(struct bcm43xx_private *bcm);
43
44void bcm43xx_power_saving_ctl_bits(struct bcm43xx_private *bcm,
45 int bit25, int bit26);
46
47#endif /* BCM43xx_POWER_H_ */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_radio.c b/drivers/net/wireless/bcm43xx/bcm43xx_radio.c
new file mode 100644
index 000000000000..af5c0bff1696
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_radio.c
@@ -0,0 +1,2026 @@
1/*
2
3 Broadcom BCM43xx wireless driver
4
5 Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
6 Stefano Brivio <st3@riseup.net>
7 Michael Buesch <mbuesch@freenet.de>
8 Danny van Dyk <kugelfang@gentoo.org>
9 Andreas Jaggi <andreas.jaggi@waterwave.ch>
10
11 Some parts of the code in this file are derived from the ipw2200
12 driver Copyright(c) 2003 - 2004 Intel Corporation.
13
14 This program is free software; you can redistribute it and/or modify
15 it under the terms of the GNU General Public License as published by
16 the Free Software Foundation; either version 2 of the License, or
17 (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; see the file COPYING. If not, write to
26 the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
27 Boston, MA 02110-1301, USA.
28
29*/
30
31#include <linux/delay.h>
32
33#include "bcm43xx.h"
34#include "bcm43xx_main.h"
35#include "bcm43xx_phy.h"
36#include "bcm43xx_radio.h"
37#include "bcm43xx_ilt.h"
38
39
40/* Table for bcm43xx_radio_calibrationvalue() */
41static const u16 rcc_table[16] = {
42 0x0002, 0x0003, 0x0001, 0x000F,
43 0x0006, 0x0007, 0x0005, 0x000F,
44 0x000A, 0x000B, 0x0009, 0x000F,
45 0x000E, 0x000F, 0x000D, 0x000F,
46};
47
48/* Reverse the bits of a 4bit value.
49 * Example: 1101 is flipped 1011
50 */
51static u16 flip_4bit(u16 value)
52{
53 u16 flipped = 0x0000;
54
55 assert((value & ~0x000F) == 0x0000);
56
57 flipped |= (value & 0x0001) << 3;
58 flipped |= (value & 0x0002) << 1;
59 flipped |= (value & 0x0004) >> 1;
60 flipped |= (value & 0x0008) >> 3;
61
62 return flipped;
63}
64
65/* Get the freq, as it has to be written to the device. */
66static inline
67u16 channel2freq_bg(u8 channel)
68{
69 /* Frequencies are given as frequencies_bg[index] + 2.4GHz
70 * Starting with channel 1
71 */
72 static const u16 frequencies_bg[14] = {
73 12, 17, 22, 27,
74 32, 37, 42, 47,
75 52, 57, 62, 67,
76 72, 84,
77 };
78
79 assert(channel >= 1 && channel <= 14);
80
81 return frequencies_bg[channel - 1];
82}
83
84/* Get the freq, as it has to be written to the device. */
85static inline
86u16 channel2freq_a(u8 channel)
87{
88 assert(channel <= 200);
89
90 return (5000 + 5 * channel);
91}
92
93void bcm43xx_radio_lock(struct bcm43xx_private *bcm)
94{
95 u32 status;
96
97 status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
98 status |= BCM43xx_SBF_RADIOREG_LOCK;
99 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status);
100 mmiowb();
101 udelay(10);
102}
103
104void bcm43xx_radio_unlock(struct bcm43xx_private *bcm)
105{
106 u32 status;
107
108 bcm43xx_read16(bcm, BCM43xx_MMIO_PHY_VER); /* dummy read */
109 status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
110 status &= ~BCM43xx_SBF_RADIOREG_LOCK;
111 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status);
112 mmiowb();
113}
114
115u16 bcm43xx_radio_read16(struct bcm43xx_private *bcm, u16 offset)
116{
117 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
118 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
119
120 switch (phy->type) {
121 case BCM43xx_PHYTYPE_A:
122 offset |= 0x0040;
123 break;
124 case BCM43xx_PHYTYPE_B:
125 if (radio->version == 0x2053) {
126 if (offset < 0x70)
127 offset += 0x80;
128 else if (offset < 0x80)
129 offset += 0x70;
130 } else if (radio->version == 0x2050) {
131 offset |= 0x80;
132 } else
133 assert(0);
134 break;
135 case BCM43xx_PHYTYPE_G:
136 offset |= 0x80;
137 break;
138 }
139
140 bcm43xx_write16(bcm, BCM43xx_MMIO_RADIO_CONTROL, offset);
141 return bcm43xx_read16(bcm, BCM43xx_MMIO_RADIO_DATA_LOW);
142}
143
144void bcm43xx_radio_write16(struct bcm43xx_private *bcm, u16 offset, u16 val)
145{
146 bcm43xx_write16(bcm, BCM43xx_MMIO_RADIO_CONTROL, offset);
147 mmiowb();
148 bcm43xx_write16(bcm, BCM43xx_MMIO_RADIO_DATA_LOW, val);
149}
150
151static void bcm43xx_set_all_gains(struct bcm43xx_private *bcm,
152 s16 first, s16 second, s16 third)
153{
154 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
155 u16 i;
156 u16 start = 0x08, end = 0x18;
157 u16 offset = 0x0400;
158 u16 tmp;
159
160 if (phy->rev <= 1) {
161 offset = 0x5000;
162 start = 0x10;
163 end = 0x20;
164 }
165
166 for (i = 0; i < 4; i++)
167 bcm43xx_ilt_write(bcm, offset + i, first);
168
169 for (i = start; i < end; i++)
170 bcm43xx_ilt_write(bcm, offset + i, second);
171
172 if (third != -1) {
173 tmp = ((u16)third << 14) | ((u16)third << 6);
174 bcm43xx_phy_write(bcm, 0x04A0,
175 (bcm43xx_phy_read(bcm, 0x04A0) & 0xBFBF) | tmp);
176 bcm43xx_phy_write(bcm, 0x04A1,
177 (bcm43xx_phy_read(bcm, 0x04A1) & 0xBFBF) | tmp);
178 bcm43xx_phy_write(bcm, 0x04A2,
179 (bcm43xx_phy_read(bcm, 0x04A2) & 0xBFBF) | tmp);
180 }
181 bcm43xx_dummy_transmission(bcm);
182}
183
184static void bcm43xx_set_original_gains(struct bcm43xx_private *bcm)
185{
186 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
187 u16 i, tmp;
188 u16 offset = 0x0400;
189 u16 start = 0x0008, end = 0x0018;
190
191 if (phy->rev <= 1) {
192 offset = 0x5000;
193 start = 0x0010;
194 end = 0x0020;
195 }
196
197 for (i = 0; i < 4; i++) {
198 tmp = (i & 0xFFFC);
199 tmp |= (i & 0x0001) << 1;
200 tmp |= (i & 0x0002) >> 1;
201
202 bcm43xx_ilt_write(bcm, offset + i, tmp);
203 }
204
205 for (i = start; i < end; i++)
206 bcm43xx_ilt_write(bcm, offset + i, i - start);
207
208 bcm43xx_phy_write(bcm, 0x04A0,
209 (bcm43xx_phy_read(bcm, 0x04A0) & 0xBFBF) | 0x4040);
210 bcm43xx_phy_write(bcm, 0x04A1,
211 (bcm43xx_phy_read(bcm, 0x04A1) & 0xBFBF) | 0x4040);
212 bcm43xx_phy_write(bcm, 0x04A2,
213 (bcm43xx_phy_read(bcm, 0x04A2) & 0xBFBF) | 0x4000);
214 bcm43xx_dummy_transmission(bcm);
215}
216
217/* Synthetic PU workaround */
218static void bcm43xx_synth_pu_workaround(struct bcm43xx_private *bcm, u8 channel)
219{
220 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
221
222 if (radio->version != 0x2050 || radio->revision >= 6) {
223 /* We do not need the workaround. */
224 return;
225 }
226
227 if (channel <= 10) {
228 bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL,
229 channel2freq_bg(channel + 4));
230 } else {
231 bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL,
232 channel2freq_bg(1));
233 }
234 udelay(100);
235 bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL,
236 channel2freq_bg(channel));
237}
238
239u8 bcm43xx_radio_aci_detect(struct bcm43xx_private *bcm, u8 channel)
240{
241 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
242 u8 ret = 0;
243 u16 saved, rssi, temp;
244 int i, j = 0;
245
246 saved = bcm43xx_phy_read(bcm, 0x0403);
247 bcm43xx_radio_selectchannel(bcm, channel, 0);
248 bcm43xx_phy_write(bcm, 0x0403, (saved & 0xFFF8) | 5);
249 if (radio->aci_hw_rssi)
250 rssi = bcm43xx_phy_read(bcm, 0x048A) & 0x3F;
251 else
252 rssi = saved & 0x3F;
253 /* clamp temp to signed 5bit */
254 if (rssi > 32)
255 rssi -= 64;
256 for (i = 0;i < 100; i++) {
257 temp = (bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x3F;
258 if (temp > 32)
259 temp -= 64;
260 if (temp < rssi)
261 j++;
262 if (j >= 20)
263 ret = 1;
264 }
265 bcm43xx_phy_write(bcm, 0x0403, saved);
266
267 return ret;
268}
269
270u8 bcm43xx_radio_aci_scan(struct bcm43xx_private *bcm)
271{
272 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
273 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
274 u8 ret[13];
275 unsigned int channel = radio->channel;
276 unsigned int i, j, start, end;
277 unsigned long phylock_flags;
278
279 if (!((phy->type == BCM43xx_PHYTYPE_G) && (phy->rev > 0)))
280 return 0;
281
282 bcm43xx_phy_lock(bcm, phylock_flags);
283 bcm43xx_radio_lock(bcm);
284 bcm43xx_phy_write(bcm, 0x0802,
285 bcm43xx_phy_read(bcm, 0x0802) & 0xFFFC);
286 bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
287 bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & 0x7FFF);
288 bcm43xx_set_all_gains(bcm, 3, 8, 1);
289
290 start = (channel - 5 > 0) ? channel - 5 : 1;
291 end = (channel + 5 < 14) ? channel + 5 : 13;
292
293 for (i = start; i <= end; i++) {
294 if (abs(channel - i) > 2)
295 ret[i-1] = bcm43xx_radio_aci_detect(bcm, i);
296 }
297 bcm43xx_radio_selectchannel(bcm, channel, 0);
298 bcm43xx_phy_write(bcm, 0x0802,
299 (bcm43xx_phy_read(bcm, 0x0802) & 0xFFFC) | 0x0003);
300 bcm43xx_phy_write(bcm, 0x0403,
301 bcm43xx_phy_read(bcm, 0x0403) & 0xFFF8);
302 bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
303 bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) | 0x8000);
304 bcm43xx_set_original_gains(bcm);
305 for (i = 0; i < 13; i++) {
306 if (!ret[i])
307 continue;
308 end = (i + 5 < 13) ? i + 5 : 13;
309 for (j = i; j < end; j++)
310 ret[j] = 1;
311 }
312 bcm43xx_radio_unlock(bcm);
313 bcm43xx_phy_unlock(bcm, phylock_flags);
314
315 return ret[channel - 1];
316}
317
318/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */
319void bcm43xx_nrssi_hw_write(struct bcm43xx_private *bcm, u16 offset, s16 val)
320{
321 bcm43xx_phy_write(bcm, BCM43xx_PHY_NRSSILT_CTRL, offset);
322 mmiowb();
323 bcm43xx_phy_write(bcm, BCM43xx_PHY_NRSSILT_DATA, (u16)val);
324}
325
326/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */
327s16 bcm43xx_nrssi_hw_read(struct bcm43xx_private *bcm, u16 offset)
328{
329 u16 val;
330
331 bcm43xx_phy_write(bcm, BCM43xx_PHY_NRSSILT_CTRL, offset);
332 val = bcm43xx_phy_read(bcm, BCM43xx_PHY_NRSSILT_DATA);
333
334 return (s16)val;
335}
336
337/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */
338void bcm43xx_nrssi_hw_update(struct bcm43xx_private *bcm, u16 val)
339{
340 u16 i;
341 s16 tmp;
342
343 for (i = 0; i < 64; i++) {
344 tmp = bcm43xx_nrssi_hw_read(bcm, i);
345 tmp -= val;
346 tmp = limit_value(tmp, -32, 31);
347 bcm43xx_nrssi_hw_write(bcm, i, tmp);
348 }
349}
350
351/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */
352void bcm43xx_nrssi_mem_update(struct bcm43xx_private *bcm)
353{
354 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
355 s16 i, delta;
356 s32 tmp;
357
358 delta = 0x1F - radio->nrssi[0];
359 for (i = 0; i < 64; i++) {
360 tmp = (i - delta) * radio->nrssislope;
361 tmp /= 0x10000;
362 tmp += 0x3A;
363 tmp = limit_value(tmp, 0, 0x3F);
364 radio->nrssi_lt[i] = tmp;
365 }
366}
367
368static void bcm43xx_calc_nrssi_offset(struct bcm43xx_private *bcm)
369{
370 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
371 u16 backup[20] = { 0 };
372 s16 v47F;
373 u16 i;
374 u16 saved = 0xFFFF;
375
376 backup[0] = bcm43xx_phy_read(bcm, 0x0001);
377 backup[1] = bcm43xx_phy_read(bcm, 0x0811);
378 backup[2] = bcm43xx_phy_read(bcm, 0x0812);
379 backup[3] = bcm43xx_phy_read(bcm, 0x0814);
380 backup[4] = bcm43xx_phy_read(bcm, 0x0815);
381 backup[5] = bcm43xx_phy_read(bcm, 0x005A);
382 backup[6] = bcm43xx_phy_read(bcm, 0x0059);
383 backup[7] = bcm43xx_phy_read(bcm, 0x0058);
384 backup[8] = bcm43xx_phy_read(bcm, 0x000A);
385 backup[9] = bcm43xx_phy_read(bcm, 0x0003);
386 backup[10] = bcm43xx_radio_read16(bcm, 0x007A);
387 backup[11] = bcm43xx_radio_read16(bcm, 0x0043);
388
389 bcm43xx_phy_write(bcm, 0x0429,
390 bcm43xx_phy_read(bcm, 0x0429) & 0x7FFF);
391 bcm43xx_phy_write(bcm, 0x0001,
392 (bcm43xx_phy_read(bcm, 0x0001) & 0x3FFF) | 0x4000);
393 bcm43xx_phy_write(bcm, 0x0811,
394 bcm43xx_phy_read(bcm, 0x0811) | 0x000C);
395 bcm43xx_phy_write(bcm, 0x0812,
396 (bcm43xx_phy_read(bcm, 0x0812) & 0xFFF3) | 0x0004);
397 bcm43xx_phy_write(bcm, 0x0802,
398 bcm43xx_phy_read(bcm, 0x0802) & ~(0x1 | 0x2));
399 if (phy->rev >= 6) {
400 backup[12] = bcm43xx_phy_read(bcm, 0x002E);
401 backup[13] = bcm43xx_phy_read(bcm, 0x002F);
402 backup[14] = bcm43xx_phy_read(bcm, 0x080F);
403 backup[15] = bcm43xx_phy_read(bcm, 0x0810);
404 backup[16] = bcm43xx_phy_read(bcm, 0x0801);
405 backup[17] = bcm43xx_phy_read(bcm, 0x0060);
406 backup[18] = bcm43xx_phy_read(bcm, 0x0014);
407 backup[19] = bcm43xx_phy_read(bcm, 0x0478);
408
409 bcm43xx_phy_write(bcm, 0x002E, 0);
410 bcm43xx_phy_write(bcm, 0x002F, 0);
411 bcm43xx_phy_write(bcm, 0x080F, 0);
412 bcm43xx_phy_write(bcm, 0x0810, 0);
413 bcm43xx_phy_write(bcm, 0x0478,
414 bcm43xx_phy_read(bcm, 0x0478) | 0x0100);
415 bcm43xx_phy_write(bcm, 0x0801,
416 bcm43xx_phy_read(bcm, 0x0801) | 0x0040);
417 bcm43xx_phy_write(bcm, 0x0060,
418 bcm43xx_phy_read(bcm, 0x0060) | 0x0040);
419 bcm43xx_phy_write(bcm, 0x0014,
420 bcm43xx_phy_read(bcm, 0x0014) | 0x0200);
421 }
422 bcm43xx_radio_write16(bcm, 0x007A,
423 bcm43xx_radio_read16(bcm, 0x007A) | 0x0070);
424 bcm43xx_radio_write16(bcm, 0x007A,
425 bcm43xx_radio_read16(bcm, 0x007A) | 0x0080);
426 udelay(30);
427
428 v47F = (s16)((bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x003F);
429 if (v47F >= 0x20)
430 v47F -= 0x40;
431 if (v47F == 31) {
432 for (i = 7; i >= 4; i--) {
433 bcm43xx_radio_write16(bcm, 0x007B, i);
434 udelay(20);
435 v47F = (s16)((bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x003F);
436 if (v47F >= 0x20)
437 v47F -= 0x40;
438 if (v47F < 31 && saved == 0xFFFF)
439 saved = i;
440 }
441 if (saved == 0xFFFF)
442 saved = 4;
443 } else {
444 bcm43xx_radio_write16(bcm, 0x007A,
445 bcm43xx_radio_read16(bcm, 0x007A) & 0x007F);
446 bcm43xx_phy_write(bcm, 0x0814,
447 bcm43xx_phy_read(bcm, 0x0814) | 0x0001);
448 bcm43xx_phy_write(bcm, 0x0815,
449 bcm43xx_phy_read(bcm, 0x0815) & 0xFFFE);
450 bcm43xx_phy_write(bcm, 0x0811,
451 bcm43xx_phy_read(bcm, 0x0811) | 0x000C);
452 bcm43xx_phy_write(bcm, 0x0812,
453 bcm43xx_phy_read(bcm, 0x0812) | 0x000C);
454 bcm43xx_phy_write(bcm, 0x0811,
455 bcm43xx_phy_read(bcm, 0x0811) | 0x0030);
456 bcm43xx_phy_write(bcm, 0x0812,
457 bcm43xx_phy_read(bcm, 0x0812) | 0x0030);
458 bcm43xx_phy_write(bcm, 0x005A, 0x0480);
459 bcm43xx_phy_write(bcm, 0x0059, 0x0810);
460 bcm43xx_phy_write(bcm, 0x0058, 0x000D);
461 if (phy->rev == 0) {
462 bcm43xx_phy_write(bcm, 0x0003, 0x0122);
463 } else {
464 bcm43xx_phy_write(bcm, 0x000A,
465 bcm43xx_phy_read(bcm, 0x000A)
466 | 0x2000);
467 }
468 bcm43xx_phy_write(bcm, 0x0814,
469 bcm43xx_phy_read(bcm, 0x0814) | 0x0004);
470 bcm43xx_phy_write(bcm, 0x0815,
471 bcm43xx_phy_read(bcm, 0x0815) & 0xFFFB);
472 bcm43xx_phy_write(bcm, 0x0003,
473 (bcm43xx_phy_read(bcm, 0x0003) & 0xFF9F)
474 | 0x0040);
475 bcm43xx_radio_write16(bcm, 0x007A,
476 bcm43xx_radio_read16(bcm, 0x007A) | 0x000F);
477 bcm43xx_set_all_gains(bcm, 3, 0, 1);
478 bcm43xx_radio_write16(bcm, 0x0043,
479 (bcm43xx_radio_read16(bcm, 0x0043)
480 & 0x00F0) | 0x000F);
481 udelay(30);
482 v47F = (s16)((bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x003F);
483 if (v47F >= 0x20)
484 v47F -= 0x40;
485 if (v47F == -32) {
486 for (i = 0; i < 4; i++) {
487 bcm43xx_radio_write16(bcm, 0x007B, i);
488 udelay(20);
489 v47F = (s16)((bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x003F);
490 if (v47F >= 0x20)
491 v47F -= 0x40;
492 if (v47F > -31 && saved == 0xFFFF)
493 saved = i;
494 }
495 if (saved == 0xFFFF)
496 saved = 3;
497 } else
498 saved = 0;
499 }
500 bcm43xx_radio_write16(bcm, 0x007B, saved);
501
502 if (phy->rev >= 6) {
503 bcm43xx_phy_write(bcm, 0x002E, backup[12]);
504 bcm43xx_phy_write(bcm, 0x002F, backup[13]);
505 bcm43xx_phy_write(bcm, 0x080F, backup[14]);
506 bcm43xx_phy_write(bcm, 0x0810, backup[15]);
507 }
508 bcm43xx_phy_write(bcm, 0x0814, backup[3]);
509 bcm43xx_phy_write(bcm, 0x0815, backup[4]);
510 bcm43xx_phy_write(bcm, 0x005A, backup[5]);
511 bcm43xx_phy_write(bcm, 0x0059, backup[6]);
512 bcm43xx_phy_write(bcm, 0x0058, backup[7]);
513 bcm43xx_phy_write(bcm, 0x000A, backup[8]);
514 bcm43xx_phy_write(bcm, 0x0003, backup[9]);
515 bcm43xx_radio_write16(bcm, 0x0043, backup[11]);
516 bcm43xx_radio_write16(bcm, 0x007A, backup[10]);
517 bcm43xx_phy_write(bcm, 0x0802,
518 bcm43xx_phy_read(bcm, 0x0802) | 0x1 | 0x2);
519 bcm43xx_phy_write(bcm, 0x0429,
520 bcm43xx_phy_read(bcm, 0x0429) | 0x8000);
521 bcm43xx_set_original_gains(bcm);
522 if (phy->rev >= 6) {
523 bcm43xx_phy_write(bcm, 0x0801, backup[16]);
524 bcm43xx_phy_write(bcm, 0x0060, backup[17]);
525 bcm43xx_phy_write(bcm, 0x0014, backup[18]);
526 bcm43xx_phy_write(bcm, 0x0478, backup[19]);
527 }
528 bcm43xx_phy_write(bcm, 0x0001, backup[0]);
529 bcm43xx_phy_write(bcm, 0x0812, backup[2]);
530 bcm43xx_phy_write(bcm, 0x0811, backup[1]);
531}
532
533void bcm43xx_calc_nrssi_slope(struct bcm43xx_private *bcm)
534{
535 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
536 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
537 u16 backup[18] = { 0 };
538 u16 tmp;
539 s16 nrssi0, nrssi1;
540
541 switch (phy->type) {
542 case BCM43xx_PHYTYPE_B:
543 backup[0] = bcm43xx_radio_read16(bcm, 0x007A);
544 backup[1] = bcm43xx_radio_read16(bcm, 0x0052);
545 backup[2] = bcm43xx_radio_read16(bcm, 0x0043);
546 backup[3] = bcm43xx_phy_read(bcm, 0x0030);
547 backup[4] = bcm43xx_phy_read(bcm, 0x0026);
548 backup[5] = bcm43xx_phy_read(bcm, 0x0015);
549 backup[6] = bcm43xx_phy_read(bcm, 0x002A);
550 backup[7] = bcm43xx_phy_read(bcm, 0x0020);
551 backup[8] = bcm43xx_phy_read(bcm, 0x005A);
552 backup[9] = bcm43xx_phy_read(bcm, 0x0059);
553 backup[10] = bcm43xx_phy_read(bcm, 0x0058);
554 backup[11] = bcm43xx_read16(bcm, 0x03E2);
555 backup[12] = bcm43xx_read16(bcm, 0x03E6);
556 backup[13] = bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT);
557
558 tmp = bcm43xx_radio_read16(bcm, 0x007A);
559 tmp &= (phy->rev >= 5) ? 0x007F : 0x000F;
560 bcm43xx_radio_write16(bcm, 0x007A, tmp);
561 bcm43xx_phy_write(bcm, 0x0030, 0x00FF);
562 bcm43xx_write16(bcm, 0x03EC, 0x7F7F);
563 bcm43xx_phy_write(bcm, 0x0026, 0x0000);
564 bcm43xx_phy_write(bcm, 0x0015,
565 bcm43xx_phy_read(bcm, 0x0015) | 0x0020);
566 bcm43xx_phy_write(bcm, 0x002A, 0x08A3);
567 bcm43xx_radio_write16(bcm, 0x007A,
568 bcm43xx_radio_read16(bcm, 0x007A) | 0x0080);
569
570 nrssi0 = (s16)bcm43xx_phy_read(bcm, 0x0027);
571 bcm43xx_radio_write16(bcm, 0x007A,
572 bcm43xx_radio_read16(bcm, 0x007A) & 0x007F);
573 if (phy->rev >= 2) {
574 bcm43xx_write16(bcm, 0x03E6, 0x0040);
575 } else if (phy->rev == 0) {
576 bcm43xx_write16(bcm, 0x03E6, 0x0122);
577 } else {
578 bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT,
579 bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT) & 0x2000);
580 }
581 bcm43xx_phy_write(bcm, 0x0020, 0x3F3F);
582 bcm43xx_phy_write(bcm, 0x0015, 0xF330);
583 bcm43xx_radio_write16(bcm, 0x005A, 0x0060);
584 bcm43xx_radio_write16(bcm, 0x0043,
585 bcm43xx_radio_read16(bcm, 0x0043) & 0x00F0);
586 bcm43xx_phy_write(bcm, 0x005A, 0x0480);
587 bcm43xx_phy_write(bcm, 0x0059, 0x0810);
588 bcm43xx_phy_write(bcm, 0x0058, 0x000D);
589 udelay(20);
590
591 nrssi1 = (s16)bcm43xx_phy_read(bcm, 0x0027);
592 bcm43xx_phy_write(bcm, 0x0030, backup[3]);
593 bcm43xx_radio_write16(bcm, 0x007A, backup[0]);
594 bcm43xx_write16(bcm, 0x03E2, backup[11]);
595 bcm43xx_phy_write(bcm, 0x0026, backup[4]);
596 bcm43xx_phy_write(bcm, 0x0015, backup[5]);
597 bcm43xx_phy_write(bcm, 0x002A, backup[6]);
598 bcm43xx_synth_pu_workaround(bcm, radio->channel);
599 if (phy->rev != 0)
600 bcm43xx_write16(bcm, 0x03F4, backup[13]);
601
602 bcm43xx_phy_write(bcm, 0x0020, backup[7]);
603 bcm43xx_phy_write(bcm, 0x005A, backup[8]);
604 bcm43xx_phy_write(bcm, 0x0059, backup[9]);
605 bcm43xx_phy_write(bcm, 0x0058, backup[10]);
606 bcm43xx_radio_write16(bcm, 0x0052, backup[1]);
607 bcm43xx_radio_write16(bcm, 0x0043, backup[2]);
608
609 if (nrssi0 == nrssi1)
610 radio->nrssislope = 0x00010000;
611 else
612 radio->nrssislope = 0x00400000 / (nrssi0 - nrssi1);
613
614 if (nrssi0 <= -4) {
615 radio->nrssi[0] = nrssi0;
616 radio->nrssi[1] = nrssi1;
617 }
618 break;
619 case BCM43xx_PHYTYPE_G:
620 if (radio->revision >= 9)
621 return;
622 if (radio->revision == 8)
623 bcm43xx_calc_nrssi_offset(bcm);
624
625 bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
626 bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & 0x7FFF);
627 bcm43xx_phy_write(bcm, 0x0802,
628 bcm43xx_phy_read(bcm, 0x0802) & 0xFFFC);
629 backup[7] = bcm43xx_read16(bcm, 0x03E2);
630 bcm43xx_write16(bcm, 0x03E2,
631 bcm43xx_read16(bcm, 0x03E2) | 0x8000);
632 backup[0] = bcm43xx_radio_read16(bcm, 0x007A);
633 backup[1] = bcm43xx_radio_read16(bcm, 0x0052);
634 backup[2] = bcm43xx_radio_read16(bcm, 0x0043);
635 backup[3] = bcm43xx_phy_read(bcm, 0x0015);
636 backup[4] = bcm43xx_phy_read(bcm, 0x005A);
637 backup[5] = bcm43xx_phy_read(bcm, 0x0059);
638 backup[6] = bcm43xx_phy_read(bcm, 0x0058);
639 backup[8] = bcm43xx_read16(bcm, 0x03E6);
640 backup[9] = bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT);
641 if (phy->rev >= 3) {
642 backup[10] = bcm43xx_phy_read(bcm, 0x002E);
643 backup[11] = bcm43xx_phy_read(bcm, 0x002F);
644 backup[12] = bcm43xx_phy_read(bcm, 0x080F);
645 backup[13] = bcm43xx_phy_read(bcm, BCM43xx_PHY_G_LO_CONTROL);
646 backup[14] = bcm43xx_phy_read(bcm, 0x0801);
647 backup[15] = bcm43xx_phy_read(bcm, 0x0060);
648 backup[16] = bcm43xx_phy_read(bcm, 0x0014);
649 backup[17] = bcm43xx_phy_read(bcm, 0x0478);
650 bcm43xx_phy_write(bcm, 0x002E, 0);
651 bcm43xx_phy_write(bcm, BCM43xx_PHY_G_LO_CONTROL, 0);
652 switch (phy->rev) {
653 case 4: case 6: case 7:
654 bcm43xx_phy_write(bcm, 0x0478,
655 bcm43xx_phy_read(bcm, 0x0478)
656 | 0x0100);
657 bcm43xx_phy_write(bcm, 0x0801,
658 bcm43xx_phy_read(bcm, 0x0801)
659 | 0x0040);
660 break;
661 case 3: case 5:
662 bcm43xx_phy_write(bcm, 0x0801,
663 bcm43xx_phy_read(bcm, 0x0801)
664 & 0xFFBF);
665 break;
666 }
667 bcm43xx_phy_write(bcm, 0x0060,
668 bcm43xx_phy_read(bcm, 0x0060)
669 | 0x0040);
670 bcm43xx_phy_write(bcm, 0x0014,
671 bcm43xx_phy_read(bcm, 0x0014)
672 | 0x0200);
673 }
674 bcm43xx_radio_write16(bcm, 0x007A,
675 bcm43xx_radio_read16(bcm, 0x007A) | 0x0070);
676 bcm43xx_set_all_gains(bcm, 0, 8, 0);
677 bcm43xx_radio_write16(bcm, 0x007A,
678 bcm43xx_radio_read16(bcm, 0x007A) & 0x00F7);
679 if (phy->rev >= 2) {
680 bcm43xx_phy_write(bcm, 0x0811,
681 (bcm43xx_phy_read(bcm, 0x0811) & 0xFFCF) | 0x0030);
682 bcm43xx_phy_write(bcm, 0x0812,
683 (bcm43xx_phy_read(bcm, 0x0812) & 0xFFCF) | 0x0010);
684 }
685 bcm43xx_radio_write16(bcm, 0x007A,
686 bcm43xx_radio_read16(bcm, 0x007A) | 0x0080);
687 udelay(20);
688
689 nrssi0 = (s16)((bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x003F);
690 if (nrssi0 >= 0x0020)
691 nrssi0 -= 0x0040;
692
693 bcm43xx_radio_write16(bcm, 0x007A,
694 bcm43xx_radio_read16(bcm, 0x007A) & 0x007F);
695 if (phy->rev >= 2) {
696 bcm43xx_phy_write(bcm, 0x0003,
697 (bcm43xx_phy_read(bcm, 0x0003)
698 & 0xFF9F) | 0x0040);
699 }
700
701 bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT,
702 bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT)
703 | 0x2000);
704 bcm43xx_radio_write16(bcm, 0x007A,
705 bcm43xx_radio_read16(bcm, 0x007A) | 0x000F);
706 bcm43xx_phy_write(bcm, 0x0015, 0xF330);
707 if (phy->rev >= 2) {
708 bcm43xx_phy_write(bcm, 0x0812,
709 (bcm43xx_phy_read(bcm, 0x0812) & 0xFFCF) | 0x0020);
710 bcm43xx_phy_write(bcm, 0x0811,
711 (bcm43xx_phy_read(bcm, 0x0811) & 0xFFCF) | 0x0020);
712 }
713
714 bcm43xx_set_all_gains(bcm, 3, 0, 1);
715 if (radio->revision == 8) {
716 bcm43xx_radio_write16(bcm, 0x0043, 0x001F);
717 } else {
718 tmp = bcm43xx_radio_read16(bcm, 0x0052) & 0xFF0F;
719 bcm43xx_radio_write16(bcm, 0x0052, tmp | 0x0060);
720 tmp = bcm43xx_radio_read16(bcm, 0x0043) & 0xFFF0;
721 bcm43xx_radio_write16(bcm, 0x0043, tmp | 0x0009);
722 }
723 bcm43xx_phy_write(bcm, 0x005A, 0x0480);
724 bcm43xx_phy_write(bcm, 0x0059, 0x0810);
725 bcm43xx_phy_write(bcm, 0x0058, 0x000D);
726 udelay(20);
727 nrssi1 = (s16)((bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x003F);
728 if (nrssi1 >= 0x0020)
729 nrssi1 -= 0x0040;
730 if (nrssi0 == nrssi1)
731 radio->nrssislope = 0x00010000;
732 else
733 radio->nrssislope = 0x00400000 / (nrssi0 - nrssi1);
734 if (nrssi0 >= -4) {
735 radio->nrssi[0] = nrssi1;
736 radio->nrssi[1] = nrssi0;
737 }
738 if (phy->rev >= 3) {
739 bcm43xx_phy_write(bcm, 0x002E, backup[10]);
740 bcm43xx_phy_write(bcm, 0x002F, backup[11]);
741 bcm43xx_phy_write(bcm, 0x080F, backup[12]);
742 bcm43xx_phy_write(bcm, BCM43xx_PHY_G_LO_CONTROL, backup[13]);
743 }
744 if (phy->rev >= 2) {
745 bcm43xx_phy_write(bcm, 0x0812,
746 bcm43xx_phy_read(bcm, 0x0812) & 0xFFCF);
747 bcm43xx_phy_write(bcm, 0x0811,
748 bcm43xx_phy_read(bcm, 0x0811) & 0xFFCF);
749 }
750
751 bcm43xx_radio_write16(bcm, 0x007A, backup[0]);
752 bcm43xx_radio_write16(bcm, 0x0052, backup[1]);
753 bcm43xx_radio_write16(bcm, 0x0043, backup[2]);
754 bcm43xx_write16(bcm, 0x03E2, backup[7]);
755 bcm43xx_write16(bcm, 0x03E6, backup[8]);
756 bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, backup[9]);
757 bcm43xx_phy_write(bcm, 0x0015, backup[3]);
758 bcm43xx_phy_write(bcm, 0x005A, backup[4]);
759 bcm43xx_phy_write(bcm, 0x0059, backup[5]);
760 bcm43xx_phy_write(bcm, 0x0058, backup[6]);
761 bcm43xx_synth_pu_workaround(bcm, radio->channel);
762 bcm43xx_phy_write(bcm, 0x0802,
763 bcm43xx_phy_read(bcm, 0x0802) | (0x0001 | 0x0002));
764 bcm43xx_set_original_gains(bcm);
765 bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
766 bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) | 0x8000);
767 if (phy->rev >= 3) {
768 bcm43xx_phy_write(bcm, 0x0801, backup[14]);
769 bcm43xx_phy_write(bcm, 0x0060, backup[15]);
770 bcm43xx_phy_write(bcm, 0x0014, backup[16]);
771 bcm43xx_phy_write(bcm, 0x0478, backup[17]);
772 }
773 bcm43xx_nrssi_mem_update(bcm);
774 bcm43xx_calc_nrssi_threshold(bcm);
775 break;
776 default:
777 assert(0);
778 }
779}
780
781void bcm43xx_calc_nrssi_threshold(struct bcm43xx_private *bcm)
782{
783 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
784 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
785 s32 threshold;
786 s32 a, b;
787 s16 tmp16;
788 u16 tmp_u16;
789
790 switch (phy->type) {
791 case BCM43xx_PHYTYPE_B: {
792 if (radio->version != 0x2050)
793 return;
794 if (!(bcm->sprom.boardflags & BCM43xx_BFL_RSSI))
795 return;
796
797 if (radio->revision >= 6) {
798 threshold = (radio->nrssi[1] - radio->nrssi[0]) * 32;
799 threshold += 20 * (radio->nrssi[0] + 1);
800 threshold /= 40;
801 } else
802 threshold = radio->nrssi[1] - 5;
803
804 threshold = limit_value(threshold, 0, 0x3E);
805 bcm43xx_phy_read(bcm, 0x0020); /* dummy read */
806 bcm43xx_phy_write(bcm, 0x0020, (((u16)threshold) << 8) | 0x001C);
807
808 if (radio->revision >= 6) {
809 bcm43xx_phy_write(bcm, 0x0087, 0x0E0D);
810 bcm43xx_phy_write(bcm, 0x0086, 0x0C0B);
811 bcm43xx_phy_write(bcm, 0x0085, 0x0A09);
812 bcm43xx_phy_write(bcm, 0x0084, 0x0808);
813 bcm43xx_phy_write(bcm, 0x0083, 0x0808);
814 bcm43xx_phy_write(bcm, 0x0082, 0x0604);
815 bcm43xx_phy_write(bcm, 0x0081, 0x0302);
816 bcm43xx_phy_write(bcm, 0x0080, 0x0100);
817 }
818 break;
819 }
820 case BCM43xx_PHYTYPE_G:
821 if (!phy->connected ||
822 !(bcm->sprom.boardflags & BCM43xx_BFL_RSSI)) {
823 tmp16 = bcm43xx_nrssi_hw_read(bcm, 0x20);
824 if (tmp16 >= 0x20)
825 tmp16 -= 0x40;
826 if (tmp16 < 3) {
827 bcm43xx_phy_write(bcm, 0x048A,
828 (bcm43xx_phy_read(bcm, 0x048A)
829 & 0xF000) | 0x09EB);
830 } else {
831 bcm43xx_phy_write(bcm, 0x048A,
832 (bcm43xx_phy_read(bcm, 0x048A)
833 & 0xF000) | 0x0AED);
834 }
835 } else {
836 if (radio->interfmode == BCM43xx_RADIO_INTERFMODE_NONWLAN) {
837 a = 0xE;
838 b = 0xA;
839 } else if (!radio->aci_wlan_automatic && radio->aci_enable) {
840 a = 0x13;
841 b = 0x12;
842 } else {
843 a = 0xE;
844 b = 0x11;
845 }
846
847 a = a * (radio->nrssi[1] - radio->nrssi[0]);
848 a += (radio->nrssi[0] << 6);
849 if (a < 32)
850 a += 31;
851 else
852 a += 32;
853 a = a >> 6;
854 a = limit_value(a, -31, 31);
855
856 b = b * (radio->nrssi[1] - radio->nrssi[0]);
857 b += (radio->nrssi[0] << 6);
858 if (b < 32)
859 b += 31;
860 else
861 b += 32;
862 b = b >> 6;
863 b = limit_value(b, -31, 31);
864
865 tmp_u16 = bcm43xx_phy_read(bcm, 0x048A) & 0xF000;
866 tmp_u16 |= ((u32)b & 0x0000003F);
867 tmp_u16 |= (((u32)a & 0x0000003F) << 6);
868 bcm43xx_phy_write(bcm, 0x048A, tmp_u16);
869 }
870 break;
871 default:
872 assert(0);
873 }
874}
875
876/* Stack implementation to save/restore values from the
877 * interference mitigation code.
878 * It is save to restore values in random order.
879 */
880static void _stack_save(u32 *_stackptr, size_t *stackidx,
881 u8 id, u16 offset, u16 value)
882{
883 u32 *stackptr = &(_stackptr[*stackidx]);
884
885 assert((offset & 0xF000) == 0x0000);
886 assert((id & 0xF0) == 0x00);
887 *stackptr = offset;
888 *stackptr |= ((u32)id) << 12;
889 *stackptr |= ((u32)value) << 16;
890 (*stackidx)++;
891 assert(*stackidx < BCM43xx_INTERFSTACK_SIZE);
892}
893
894static u16 _stack_restore(u32 *stackptr,
895 u8 id, u16 offset)
896{
897 size_t i;
898
899 assert((offset & 0xF000) == 0x0000);
900 assert((id & 0xF0) == 0x00);
901 for (i = 0; i < BCM43xx_INTERFSTACK_SIZE; i++, stackptr++) {
902 if ((*stackptr & 0x00000FFF) != offset)
903 continue;
904 if (((*stackptr & 0x0000F000) >> 12) != id)
905 continue;
906 return ((*stackptr & 0xFFFF0000) >> 16);
907 }
908 assert(0);
909
910 return 0;
911}
912
913#define phy_stacksave(offset) \
914 do { \
915 _stack_save(stack, &stackidx, 0x1, (offset), \
916 bcm43xx_phy_read(bcm, (offset))); \
917 } while (0)
918#define phy_stackrestore(offset) \
919 do { \
920 bcm43xx_phy_write(bcm, (offset), \
921 _stack_restore(stack, 0x1, \
922 (offset))); \
923 } while (0)
924#define radio_stacksave(offset) \
925 do { \
926 _stack_save(stack, &stackidx, 0x2, (offset), \
927 bcm43xx_radio_read16(bcm, (offset))); \
928 } while (0)
929#define radio_stackrestore(offset) \
930 do { \
931 bcm43xx_radio_write16(bcm, (offset), \
932 _stack_restore(stack, 0x2, \
933 (offset))); \
934 } while (0)
935#define ilt_stacksave(offset) \
936 do { \
937 _stack_save(stack, &stackidx, 0x3, (offset), \
938 bcm43xx_ilt_read(bcm, (offset))); \
939 } while (0)
940#define ilt_stackrestore(offset) \
941 do { \
942 bcm43xx_ilt_write(bcm, (offset), \
943 _stack_restore(stack, 0x3, \
944 (offset))); \
945 } while (0)
946
947static void
948bcm43xx_radio_interference_mitigation_enable(struct bcm43xx_private *bcm,
949 int mode)
950{
951 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
952 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
953 u16 tmp, flipped;
954 u32 tmp32;
955 size_t stackidx = 0;
956 u32 *stack = radio->interfstack;
957
958 switch (mode) {
959 case BCM43xx_RADIO_INTERFMODE_NONWLAN:
960 if (phy->rev != 1) {
961 bcm43xx_phy_write(bcm, 0x042B,
962 bcm43xx_phy_read(bcm, 0x042B) | 0x0800);
963 bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
964 bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & ~0x4000);
965 break;
966 }
967 radio_stacksave(0x0078);
968 tmp = (bcm43xx_radio_read16(bcm, 0x0078) & 0x001E);
969 flipped = flip_4bit(tmp);
970 if (flipped < 10 && flipped >= 8)
971 flipped = 7;
972 else if (flipped >= 10)
973 flipped -= 3;
974 flipped = flip_4bit(flipped);
975 flipped = (flipped << 1) | 0x0020;
976 bcm43xx_radio_write16(bcm, 0x0078, flipped);
977
978 bcm43xx_calc_nrssi_threshold(bcm);
979
980 phy_stacksave(0x0406);
981 bcm43xx_phy_write(bcm, 0x0406, 0x7E28);
982
983 bcm43xx_phy_write(bcm, 0x042B,
984 bcm43xx_phy_read(bcm, 0x042B) | 0x0800);
985 bcm43xx_phy_write(bcm, BCM43xx_PHY_RADIO_BITFIELD,
986 bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD) | 0x1000);
987
988 phy_stacksave(0x04A0);
989 bcm43xx_phy_write(bcm, 0x04A0,
990 (bcm43xx_phy_read(bcm, 0x04A0) & 0xC0C0) | 0x0008);
991 phy_stacksave(0x04A1);
992 bcm43xx_phy_write(bcm, 0x04A1,
993 (bcm43xx_phy_read(bcm, 0x04A1) & 0xC0C0) | 0x0605);
994 phy_stacksave(0x04A2);
995 bcm43xx_phy_write(bcm, 0x04A2,
996 (bcm43xx_phy_read(bcm, 0x04A2) & 0xC0C0) | 0x0204);
997 phy_stacksave(0x04A8);
998 bcm43xx_phy_write(bcm, 0x04A8,
999 (bcm43xx_phy_read(bcm, 0x04A8) & 0xC0C0) | 0x0803);
1000 phy_stacksave(0x04AB);
1001 bcm43xx_phy_write(bcm, 0x04AB,
1002 (bcm43xx_phy_read(bcm, 0x04AB) & 0xC0C0) | 0x0605);
1003
1004 phy_stacksave(0x04A7);
1005 bcm43xx_phy_write(bcm, 0x04A7, 0x0002);
1006 phy_stacksave(0x04A3);
1007 bcm43xx_phy_write(bcm, 0x04A3, 0x287A);
1008 phy_stacksave(0x04A9);
1009 bcm43xx_phy_write(bcm, 0x04A9, 0x2027);
1010 phy_stacksave(0x0493);
1011 bcm43xx_phy_write(bcm, 0x0493, 0x32F5);
1012 phy_stacksave(0x04AA);
1013 bcm43xx_phy_write(bcm, 0x04AA, 0x2027);
1014 phy_stacksave(0x04AC);
1015 bcm43xx_phy_write(bcm, 0x04AC, 0x32F5);
1016 break;
1017 case BCM43xx_RADIO_INTERFMODE_MANUALWLAN:
1018 if (bcm43xx_phy_read(bcm, 0x0033) & 0x0800)
1019 break;
1020
1021 radio->aci_enable = 1;
1022
1023 phy_stacksave(BCM43xx_PHY_RADIO_BITFIELD);
1024 phy_stacksave(BCM43xx_PHY_G_CRS);
1025 if (phy->rev < 2) {
1026 phy_stacksave(0x0406);
1027 } else {
1028 phy_stacksave(0x04C0);
1029 phy_stacksave(0x04C1);
1030 }
1031 phy_stacksave(0x0033);
1032 phy_stacksave(0x04A7);
1033 phy_stacksave(0x04A3);
1034 phy_stacksave(0x04A9);
1035 phy_stacksave(0x04AA);
1036 phy_stacksave(0x04AC);
1037 phy_stacksave(0x0493);
1038 phy_stacksave(0x04A1);
1039 phy_stacksave(0x04A0);
1040 phy_stacksave(0x04A2);
1041 phy_stacksave(0x048A);
1042 phy_stacksave(0x04A8);
1043 phy_stacksave(0x04AB);
1044 if (phy->rev == 2) {
1045 phy_stacksave(0x04AD);
1046 phy_stacksave(0x04AE);
1047 } else if (phy->rev >= 3) {
1048 phy_stacksave(0x04AD);
1049 phy_stacksave(0x0415);
1050 phy_stacksave(0x0416);
1051 phy_stacksave(0x0417);
1052 ilt_stacksave(0x1A00 + 0x2);
1053 ilt_stacksave(0x1A00 + 0x3);
1054 }
1055 phy_stacksave(0x042B);
1056 phy_stacksave(0x048C);
1057
1058 bcm43xx_phy_write(bcm, BCM43xx_PHY_RADIO_BITFIELD,
1059 bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD)
1060 & ~0x1000);
1061 bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
1062 (bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS)
1063 & 0xFFFC) | 0x0002);
1064
1065 bcm43xx_phy_write(bcm, 0x0033, 0x0800);
1066 bcm43xx_phy_write(bcm, 0x04A3, 0x2027);
1067 bcm43xx_phy_write(bcm, 0x04A9, 0x1CA8);
1068 bcm43xx_phy_write(bcm, 0x0493, 0x287A);
1069 bcm43xx_phy_write(bcm, 0x04AA, 0x1CA8);
1070 bcm43xx_phy_write(bcm, 0x04AC, 0x287A);
1071
1072 bcm43xx_phy_write(bcm, 0x04A0,
1073 (bcm43xx_phy_read(bcm, 0x04A0)
1074 & 0xFFC0) | 0x001A);
1075 bcm43xx_phy_write(bcm, 0x04A7, 0x000D);
1076
1077 if (phy->rev < 2) {
1078 bcm43xx_phy_write(bcm, 0x0406, 0xFF0D);
1079 } else if (phy->rev == 2) {
1080 bcm43xx_phy_write(bcm, 0x04C0, 0xFFFF);
1081 bcm43xx_phy_write(bcm, 0x04C1, 0x00A9);
1082 } else {
1083 bcm43xx_phy_write(bcm, 0x04C0, 0x00C1);
1084 bcm43xx_phy_write(bcm, 0x04C1, 0x0059);
1085 }
1086
1087 bcm43xx_phy_write(bcm, 0x04A1,
1088 (bcm43xx_phy_read(bcm, 0x04A1)
1089 & 0xC0FF) | 0x1800);
1090 bcm43xx_phy_write(bcm, 0x04A1,
1091 (bcm43xx_phy_read(bcm, 0x04A1)
1092 & 0xFFC0) | 0x0015);
1093 bcm43xx_phy_write(bcm, 0x04A8,
1094 (bcm43xx_phy_read(bcm, 0x04A8)
1095 & 0xCFFF) | 0x1000);
1096 bcm43xx_phy_write(bcm, 0x04A8,
1097 (bcm43xx_phy_read(bcm, 0x04A8)
1098 & 0xF0FF) | 0x0A00);
1099 bcm43xx_phy_write(bcm, 0x04AB,
1100 (bcm43xx_phy_read(bcm, 0x04AB)
1101 & 0xCFFF) | 0x1000);
1102 bcm43xx_phy_write(bcm, 0x04AB,
1103 (bcm43xx_phy_read(bcm, 0x04AB)
1104 & 0xF0FF) | 0x0800);
1105 bcm43xx_phy_write(bcm, 0x04AB,
1106 (bcm43xx_phy_read(bcm, 0x04AB)
1107 & 0xFFCF) | 0x0010);
1108 bcm43xx_phy_write(bcm, 0x04AB,
1109 (bcm43xx_phy_read(bcm, 0x04AB)
1110 & 0xFFF0) | 0x0005);
1111 bcm43xx_phy_write(bcm, 0x04A8,
1112 (bcm43xx_phy_read(bcm, 0x04A8)
1113 & 0xFFCF) | 0x0010);
1114 bcm43xx_phy_write(bcm, 0x04A8,
1115 (bcm43xx_phy_read(bcm, 0x04A8)
1116 & 0xFFF0) | 0x0006);
1117 bcm43xx_phy_write(bcm, 0x04A2,
1118 (bcm43xx_phy_read(bcm, 0x04A2)
1119 & 0xF0FF) | 0x0800);
1120 bcm43xx_phy_write(bcm, 0x04A0,
1121 (bcm43xx_phy_read(bcm, 0x04A0)
1122 & 0xF0FF) | 0x0500);
1123 bcm43xx_phy_write(bcm, 0x04A2,
1124 (bcm43xx_phy_read(bcm, 0x04A2)
1125 & 0xFFF0) | 0x000B);
1126
1127 if (phy->rev >= 3) {
1128 bcm43xx_phy_write(bcm, 0x048A,
1129 bcm43xx_phy_read(bcm, 0x048A)
1130 & ~0x8000);
1131 bcm43xx_phy_write(bcm, 0x0415,
1132 (bcm43xx_phy_read(bcm, 0x0415)
1133 & 0x8000) | 0x36D8);
1134 bcm43xx_phy_write(bcm, 0x0416,
1135 (bcm43xx_phy_read(bcm, 0x0416)
1136 & 0x8000) | 0x36D8);
1137 bcm43xx_phy_write(bcm, 0x0417,
1138 (bcm43xx_phy_read(bcm, 0x0417)
1139 & 0xFE00) | 0x016D);
1140 } else {
1141 bcm43xx_phy_write(bcm, 0x048A,
1142 bcm43xx_phy_read(bcm, 0x048A)
1143 | 0x1000);
1144 bcm43xx_phy_write(bcm, 0x048A,
1145 (bcm43xx_phy_read(bcm, 0x048A)
1146 & 0x9FFF) | 0x2000);
1147 tmp32 = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED,
1148 BCM43xx_UCODEFLAGS_OFFSET);
1149 if (!(tmp32 & 0x800)) {
1150 tmp32 |= 0x800;
1151 bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED,
1152 BCM43xx_UCODEFLAGS_OFFSET,
1153 tmp32);
1154 }
1155 }
1156 if (phy->rev >= 2) {
1157 bcm43xx_phy_write(bcm, 0x042B,
1158 bcm43xx_phy_read(bcm, 0x042B)
1159 | 0x0800);
1160 }
1161 bcm43xx_phy_write(bcm, 0x048C,
1162 (bcm43xx_phy_read(bcm, 0x048C)
1163 & 0xF0FF) | 0x0200);
1164 if (phy->rev == 2) {
1165 bcm43xx_phy_write(bcm, 0x04AE,
1166 (bcm43xx_phy_read(bcm, 0x04AE)
1167 & 0xFF00) | 0x007F);
1168 bcm43xx_phy_write(bcm, 0x04AD,
1169 (bcm43xx_phy_read(bcm, 0x04AD)
1170 & 0x00FF) | 0x1300);
1171 } else if (phy->rev >= 6) {
1172 bcm43xx_ilt_write(bcm, 0x1A00 + 0x3, 0x007F);
1173 bcm43xx_ilt_write(bcm, 0x1A00 + 0x2, 0x007F);
1174 bcm43xx_phy_write(bcm, 0x04AD,
1175 bcm43xx_phy_read(bcm, 0x04AD)
1176 & 0x00FF);
1177 }
1178 bcm43xx_calc_nrssi_slope(bcm);
1179 break;
1180 default:
1181 assert(0);
1182 }
1183}
1184
1185static void
1186bcm43xx_radio_interference_mitigation_disable(struct bcm43xx_private *bcm,
1187 int mode)
1188{
1189 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
1190 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
1191 u32 tmp32;
1192 u32 *stack = radio->interfstack;
1193
1194 switch (mode) {
1195 case BCM43xx_RADIO_INTERFMODE_NONWLAN:
1196 if (phy->rev != 1) {
1197 bcm43xx_phy_write(bcm, 0x042B,
1198 bcm43xx_phy_read(bcm, 0x042B) & ~0x0800);
1199 bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
1200 bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) | 0x4000);
1201 break;
1202 }
1203 phy_stackrestore(0x0078);
1204 bcm43xx_calc_nrssi_threshold(bcm);
1205 phy_stackrestore(0x0406);
1206 bcm43xx_phy_write(bcm, 0x042B,
1207 bcm43xx_phy_read(bcm, 0x042B) & ~0x0800);
1208 if (!bcm->bad_frames_preempt) {
1209 bcm43xx_phy_write(bcm, BCM43xx_PHY_RADIO_BITFIELD,
1210 bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD)
1211 & ~(1 << 11));
1212 }
1213 bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
1214 bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) | 0x4000);
1215 phy_stackrestore(0x04A0);
1216 phy_stackrestore(0x04A1);
1217 phy_stackrestore(0x04A2);
1218 phy_stackrestore(0x04A8);
1219 phy_stackrestore(0x04AB);
1220 phy_stackrestore(0x04A7);
1221 phy_stackrestore(0x04A3);
1222 phy_stackrestore(0x04A9);
1223 phy_stackrestore(0x0493);
1224 phy_stackrestore(0x04AA);
1225 phy_stackrestore(0x04AC);
1226 break;
1227 case BCM43xx_RADIO_INTERFMODE_MANUALWLAN:
1228 if (!(bcm43xx_phy_read(bcm, 0x0033) & 0x0800))
1229 break;
1230
1231 radio->aci_enable = 0;
1232
1233 phy_stackrestore(BCM43xx_PHY_RADIO_BITFIELD);
1234 phy_stackrestore(BCM43xx_PHY_G_CRS);
1235 phy_stackrestore(0x0033);
1236 phy_stackrestore(0x04A3);
1237 phy_stackrestore(0x04A9);
1238 phy_stackrestore(0x0493);
1239 phy_stackrestore(0x04AA);
1240 phy_stackrestore(0x04AC);
1241 phy_stackrestore(0x04A0);
1242 phy_stackrestore(0x04A7);
1243 if (phy->rev >= 2) {
1244 phy_stackrestore(0x04C0);
1245 phy_stackrestore(0x04C1);
1246 } else
1247 phy_stackrestore(0x0406);
1248 phy_stackrestore(0x04A1);
1249 phy_stackrestore(0x04AB);
1250 phy_stackrestore(0x04A8);
1251 if (phy->rev == 2) {
1252 phy_stackrestore(0x04AD);
1253 phy_stackrestore(0x04AE);
1254 } else if (phy->rev >= 3) {
1255 phy_stackrestore(0x04AD);
1256 phy_stackrestore(0x0415);
1257 phy_stackrestore(0x0416);
1258 phy_stackrestore(0x0417);
1259 ilt_stackrestore(0x1A00 + 0x2);
1260 ilt_stackrestore(0x1A00 + 0x3);
1261 }
1262 phy_stackrestore(0x04A2);
1263 phy_stackrestore(0x04A8);
1264 phy_stackrestore(0x042B);
1265 phy_stackrestore(0x048C);
1266 tmp32 = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED,
1267 BCM43xx_UCODEFLAGS_OFFSET);
1268 if (tmp32 & 0x800) {
1269 tmp32 &= ~0x800;
1270 bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED,
1271 BCM43xx_UCODEFLAGS_OFFSET,
1272 tmp32);
1273 }
1274 bcm43xx_calc_nrssi_slope(bcm);
1275 break;
1276 default:
1277 assert(0);
1278 }
1279}
1280
1281#undef phy_stacksave
1282#undef phy_stackrestore
1283#undef radio_stacksave
1284#undef radio_stackrestore
1285#undef ilt_stacksave
1286#undef ilt_stackrestore
1287
1288int bcm43xx_radio_set_interference_mitigation(struct bcm43xx_private *bcm,
1289 int mode)
1290{
1291 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
1292 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
1293 int currentmode;
1294
1295 if ((phy->type != BCM43xx_PHYTYPE_G) ||
1296 (phy->rev == 0) ||
1297 (!phy->connected))
1298 return -ENODEV;
1299
1300 radio->aci_wlan_automatic = 0;
1301 switch (mode) {
1302 case BCM43xx_RADIO_INTERFMODE_AUTOWLAN:
1303 radio->aci_wlan_automatic = 1;
1304 if (radio->aci_enable)
1305 mode = BCM43xx_RADIO_INTERFMODE_MANUALWLAN;
1306 else
1307 mode = BCM43xx_RADIO_INTERFMODE_NONE;
1308 break;
1309 case BCM43xx_RADIO_INTERFMODE_NONE:
1310 case BCM43xx_RADIO_INTERFMODE_NONWLAN:
1311 case BCM43xx_RADIO_INTERFMODE_MANUALWLAN:
1312 break;
1313 default:
1314 return -EINVAL;
1315 }
1316
1317 currentmode = radio->interfmode;
1318 if (currentmode == mode)
1319 return 0;
1320 if (currentmode != BCM43xx_RADIO_INTERFMODE_NONE)
1321 bcm43xx_radio_interference_mitigation_disable(bcm, currentmode);
1322
1323 if (mode == BCM43xx_RADIO_INTERFMODE_NONE) {
1324 radio->aci_enable = 0;
1325 radio->aci_hw_rssi = 0;
1326 } else
1327 bcm43xx_radio_interference_mitigation_enable(bcm, mode);
1328 radio->interfmode = mode;
1329
1330 return 0;
1331}
1332
1333u16 bcm43xx_radio_calibrationvalue(struct bcm43xx_private *bcm)
1334{
1335 u16 reg, index, ret;
1336
1337 reg = bcm43xx_radio_read16(bcm, 0x0060);
1338 index = (reg & 0x001E) >> 1;
1339 ret = rcc_table[index] << 1;
1340 ret |= (reg & 0x0001);
1341 ret |= 0x0020;
1342
1343 return ret;
1344}
1345
1346u16 bcm43xx_radio_init2050(struct bcm43xx_private *bcm)
1347{
1348 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
1349 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
1350 u16 backup[19] = { 0 };
1351 u16 ret;
1352 u16 i, j;
1353 u32 tmp1 = 0, tmp2 = 0;
1354
1355 backup[0] = bcm43xx_radio_read16(bcm, 0x0043);
1356 backup[14] = bcm43xx_radio_read16(bcm, 0x0051);
1357 backup[15] = bcm43xx_radio_read16(bcm, 0x0052);
1358 backup[1] = bcm43xx_phy_read(bcm, 0x0015);
1359 backup[16] = bcm43xx_phy_read(bcm, 0x005A);
1360 backup[17] = bcm43xx_phy_read(bcm, 0x0059);
1361 backup[18] = bcm43xx_phy_read(bcm, 0x0058);
1362 if (phy->type == BCM43xx_PHYTYPE_B) {
1363 backup[2] = bcm43xx_phy_read(bcm, 0x0030);
1364 backup[3] = bcm43xx_read16(bcm, 0x03EC);
1365 bcm43xx_phy_write(bcm, 0x0030, 0x00FF);
1366 bcm43xx_write16(bcm, 0x03EC, 0x3F3F);
1367 } else {
1368 if (phy->connected) {
1369 backup[4] = bcm43xx_phy_read(bcm, 0x0811);
1370 backup[5] = bcm43xx_phy_read(bcm, 0x0812);
1371 backup[6] = bcm43xx_phy_read(bcm, 0x0814);
1372 backup[7] = bcm43xx_phy_read(bcm, 0x0815);
1373 backup[8] = bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS);
1374 backup[9] = bcm43xx_phy_read(bcm, 0x0802);
1375 bcm43xx_phy_write(bcm, 0x0814,
1376 (bcm43xx_phy_read(bcm, 0x0814) | 0x0003));
1377 bcm43xx_phy_write(bcm, 0x0815,
1378 (bcm43xx_phy_read(bcm, 0x0815) & 0xFFFC));
1379 bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
1380 (bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & 0x7FFF));
1381 bcm43xx_phy_write(bcm, 0x0802,
1382 (bcm43xx_phy_read(bcm, 0x0802) & 0xFFFC));
1383 bcm43xx_phy_write(bcm, 0x0811, 0x01B3);
1384 bcm43xx_phy_write(bcm, 0x0812, 0x0FB2);
1385 }
1386 bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_RADIO,
1387 (bcm43xx_read16(bcm, BCM43xx_MMIO_PHY_RADIO) | 0x8000));
1388 }
1389 backup[10] = bcm43xx_phy_read(bcm, 0x0035);
1390 bcm43xx_phy_write(bcm, 0x0035,
1391 (bcm43xx_phy_read(bcm, 0x0035) & 0xFF7F));
1392 backup[11] = bcm43xx_read16(bcm, 0x03E6);
1393 backup[12] = bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT);
1394
1395 // Initialization
1396 if (phy->version == 0) {
1397 bcm43xx_write16(bcm, 0x03E6, 0x0122);
1398 } else {
1399 if (phy->version >= 2)
1400 bcm43xx_write16(bcm, 0x03E6, 0x0040);
1401 bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT,
1402 (bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT) | 0x2000));
1403 }
1404
1405 ret = bcm43xx_radio_calibrationvalue(bcm);
1406
1407 if (phy->type == BCM43xx_PHYTYPE_B)
1408 bcm43xx_radio_write16(bcm, 0x0078, 0x0003);
1409
1410 bcm43xx_phy_write(bcm, 0x0015, 0xBFAF);
1411 bcm43xx_phy_write(bcm, 0x002B, 0x1403);
1412 if (phy->connected)
1413 bcm43xx_phy_write(bcm, 0x0812, 0x00B2);
1414 bcm43xx_phy_write(bcm, 0x0015, 0xBFA0);
1415 bcm43xx_radio_write16(bcm, 0x0051,
1416 (bcm43xx_radio_read16(bcm, 0x0051) | 0x0004));
1417 bcm43xx_radio_write16(bcm, 0x0052, 0x0000);
1418 bcm43xx_radio_write16(bcm, 0x0043,
1419 bcm43xx_radio_read16(bcm, 0x0043) | 0x0009);
1420 bcm43xx_phy_write(bcm, 0x0058, 0x0000);
1421
1422 for (i = 0; i < 16; i++) {
1423 bcm43xx_phy_write(bcm, 0x005A, 0x0480);
1424 bcm43xx_phy_write(bcm, 0x0059, 0xC810);
1425 bcm43xx_phy_write(bcm, 0x0058, 0x000D);
1426 if (phy->connected)
1427 bcm43xx_phy_write(bcm, 0x0812, 0x30B2);
1428 bcm43xx_phy_write(bcm, 0x0015, 0xAFB0);
1429 udelay(10);
1430 if (phy->connected)
1431 bcm43xx_phy_write(bcm, 0x0812, 0x30B2);
1432 bcm43xx_phy_write(bcm, 0x0015, 0xEFB0);
1433 udelay(10);
1434 if (phy->connected)
1435 bcm43xx_phy_write(bcm, 0x0812, 0x30B2);
1436 bcm43xx_phy_write(bcm, 0x0015, 0xFFF0);
1437 udelay(10);
1438 tmp1 += bcm43xx_phy_read(bcm, 0x002D);
1439 bcm43xx_phy_write(bcm, 0x0058, 0x0000);
1440 if (phy->connected)
1441 bcm43xx_phy_write(bcm, 0x0812, 0x30B2);
1442 bcm43xx_phy_write(bcm, 0x0015, 0xAFB0);
1443 }
1444
1445 tmp1++;
1446 tmp1 >>= 9;
1447 udelay(10);
1448 bcm43xx_phy_write(bcm, 0x0058, 0x0000);
1449
1450 for (i = 0; i < 16; i++) {
1451 bcm43xx_radio_write16(bcm, 0x0078, (flip_4bit(i) << 1) | 0x0020);
1452 backup[13] = bcm43xx_radio_read16(bcm, 0x0078);
1453 udelay(10);
1454 for (j = 0; j < 16; j++) {
1455 bcm43xx_phy_write(bcm, 0x005A, 0x0D80);
1456 bcm43xx_phy_write(bcm, 0x0059, 0xC810);
1457 bcm43xx_phy_write(bcm, 0x0058, 0x000D);
1458 if (phy->connected)
1459 bcm43xx_phy_write(bcm, 0x0812, 0x30B2);
1460 bcm43xx_phy_write(bcm, 0x0015, 0xAFB0);
1461 udelay(10);
1462 if (phy->connected)
1463 bcm43xx_phy_write(bcm, 0x0812, 0x30B2);
1464 bcm43xx_phy_write(bcm, 0x0015, 0xEFB0);
1465 udelay(10);
1466 if (phy->connected)
1467 bcm43xx_phy_write(bcm, 0x0812, 0x30B3); /* 0x30B3 is not a typo */
1468 bcm43xx_phy_write(bcm, 0x0015, 0xFFF0);
1469 udelay(10);
1470 tmp2 += bcm43xx_phy_read(bcm, 0x002D);
1471 bcm43xx_phy_write(bcm, 0x0058, 0x0000);
1472 if (phy->connected)
1473 bcm43xx_phy_write(bcm, 0x0812, 0x30B2);
1474 bcm43xx_phy_write(bcm, 0x0015, 0xAFB0);
1475 }
1476 tmp2++;
1477 tmp2 >>= 8;
1478 if (tmp1 < tmp2)
1479 break;
1480 }
1481
1482 /* Restore the registers */
1483 bcm43xx_phy_write(bcm, 0x0015, backup[1]);
1484 bcm43xx_radio_write16(bcm, 0x0051, backup[14]);
1485 bcm43xx_radio_write16(bcm, 0x0052, backup[15]);
1486 bcm43xx_radio_write16(bcm, 0x0043, backup[0]);
1487 bcm43xx_phy_write(bcm, 0x005A, backup[16]);
1488 bcm43xx_phy_write(bcm, 0x0059, backup[17]);
1489 bcm43xx_phy_write(bcm, 0x0058, backup[18]);
1490 bcm43xx_write16(bcm, 0x03E6, backup[11]);
1491 if (phy->version != 0)
1492 bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, backup[12]);
1493 bcm43xx_phy_write(bcm, 0x0035, backup[10]);
1494 bcm43xx_radio_selectchannel(bcm, radio->channel, 1);
1495 if (phy->type == BCM43xx_PHYTYPE_B) {
1496 bcm43xx_phy_write(bcm, 0x0030, backup[2]);
1497 bcm43xx_write16(bcm, 0x03EC, backup[3]);
1498 } else {
1499 bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_RADIO,
1500 (bcm43xx_read16(bcm, BCM43xx_MMIO_PHY_RADIO) & 0x7FFF));
1501 if (phy->connected) {
1502 bcm43xx_phy_write(bcm, 0x0811, backup[4]);
1503 bcm43xx_phy_write(bcm, 0x0812, backup[5]);
1504 bcm43xx_phy_write(bcm, 0x0814, backup[6]);
1505 bcm43xx_phy_write(bcm, 0x0815, backup[7]);
1506 bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, backup[8]);
1507 bcm43xx_phy_write(bcm, 0x0802, backup[9]);
1508 }
1509 }
1510 if (i >= 15)
1511 ret = backup[13];
1512
1513 return ret;
1514}
1515
1516void bcm43xx_radio_init2060(struct bcm43xx_private *bcm)
1517{
1518 int err;
1519
1520 bcm43xx_radio_write16(bcm, 0x0004, 0x00C0);
1521 bcm43xx_radio_write16(bcm, 0x0005, 0x0008);
1522 bcm43xx_radio_write16(bcm, 0x0009, 0x0040);
1523 bcm43xx_radio_write16(bcm, 0x0005, 0x00AA);
1524 bcm43xx_radio_write16(bcm, 0x0032, 0x008F);
1525 bcm43xx_radio_write16(bcm, 0x0006, 0x008F);
1526 bcm43xx_radio_write16(bcm, 0x0034, 0x008F);
1527 bcm43xx_radio_write16(bcm, 0x002C, 0x0007);
1528 bcm43xx_radio_write16(bcm, 0x0082, 0x0080);
1529 bcm43xx_radio_write16(bcm, 0x0080, 0x0000);
1530 bcm43xx_radio_write16(bcm, 0x003F, 0x00DA);
1531 bcm43xx_radio_write16(bcm, 0x0005, bcm43xx_radio_read16(bcm, 0x0005) & ~0x0008);
1532 bcm43xx_radio_write16(bcm, 0x0081, bcm43xx_radio_read16(bcm, 0x0081) & ~0x0010);
1533 bcm43xx_radio_write16(bcm, 0x0081, bcm43xx_radio_read16(bcm, 0x0081) & ~0x0020);
1534 bcm43xx_radio_write16(bcm, 0x0081, bcm43xx_radio_read16(bcm, 0x0081) & ~0x0020);
1535 udelay(400);
1536
1537 bcm43xx_radio_write16(bcm, 0x0081, (bcm43xx_radio_read16(bcm, 0x0081) & ~0x0020) | 0x0010);
1538 udelay(400);
1539
1540 bcm43xx_radio_write16(bcm, 0x0005, (bcm43xx_radio_read16(bcm, 0x0005) & ~0x0008) | 0x0008);
1541 bcm43xx_radio_write16(bcm, 0x0085, bcm43xx_radio_read16(bcm, 0x0085) & ~0x0010);
1542 bcm43xx_radio_write16(bcm, 0x0005, bcm43xx_radio_read16(bcm, 0x0005) & ~0x0008);
1543 bcm43xx_radio_write16(bcm, 0x0081, bcm43xx_radio_read16(bcm, 0x0081) & ~0x0040);
1544 bcm43xx_radio_write16(bcm, 0x0081, (bcm43xx_radio_read16(bcm, 0x0081) & ~0x0040) | 0x0040);
1545 bcm43xx_radio_write16(bcm, 0x0005, (bcm43xx_radio_read16(bcm, 0x0081) & ~0x0008) | 0x0008);
1546 bcm43xx_phy_write(bcm, 0x0063, 0xDDC6);
1547 bcm43xx_phy_write(bcm, 0x0069, 0x07BE);
1548 bcm43xx_phy_write(bcm, 0x006A, 0x0000);
1549
1550 err = bcm43xx_radio_selectchannel(bcm, BCM43xx_RADIO_DEFAULT_CHANNEL_A, 0);
1551 assert(err == 0);
1552 udelay(1000);
1553}
1554
1555static inline
1556u16 freq_r3A_value(u16 frequency)
1557{
1558 u16 value;
1559
1560 if (frequency < 5091)
1561 value = 0x0040;
1562 else if (frequency < 5321)
1563 value = 0x0000;
1564 else if (frequency < 5806)
1565 value = 0x0080;
1566 else
1567 value = 0x0040;
1568
1569 return value;
1570}
1571
1572void bcm43xx_radio_set_tx_iq(struct bcm43xx_private *bcm)
1573{
1574 static const u8 data_high[5] = { 0x00, 0x40, 0x80, 0x90, 0xD0 };
1575 static const u8 data_low[5] = { 0x00, 0x01, 0x05, 0x06, 0x0A };
1576 u16 tmp = bcm43xx_radio_read16(bcm, 0x001E);
1577 int i, j;
1578
1579 for (i = 0; i < 5; i++) {
1580 for (j = 0; j < 5; j++) {
1581 if (tmp == (data_high[i] << 4 | data_low[j])) {
1582 bcm43xx_phy_write(bcm, 0x0069, (i - j) << 8 | 0x00C0);
1583 return;
1584 }
1585 }
1586 }
1587}
1588
1589int bcm43xx_radio_selectchannel(struct bcm43xx_private *bcm,
1590 u8 channel,
1591 int synthetic_pu_workaround)
1592{
1593 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
1594 u16 r8, tmp;
1595 u16 freq;
1596
1597 if ((radio->manufact == 0x17F) &&
1598 (radio->version == 0x2060) &&
1599 (radio->revision == 1)) {
1600 if (channel > 200)
1601 return -EINVAL;
1602 freq = channel2freq_a(channel);
1603
1604 r8 = bcm43xx_radio_read16(bcm, 0x0008);
1605 bcm43xx_write16(bcm, 0x03F0, freq);
1606 bcm43xx_radio_write16(bcm, 0x0008, r8);
1607
1608 TODO();//TODO: write max channel TX power? to Radio 0x2D
1609 tmp = bcm43xx_radio_read16(bcm, 0x002E);
1610 tmp &= 0x0080;
1611 TODO();//TODO: OR tmp with the Power out estimation for this channel?
1612 bcm43xx_radio_write16(bcm, 0x002E, tmp);
1613
1614 if (freq >= 4920 && freq <= 5500) {
1615 /*
1616 * r8 = (((freq * 15 * 0xE1FC780F) >> 32) / 29) & 0x0F;
1617 * = (freq * 0.025862069
1618 */
1619 r8 = 3 * freq / 116; /* is equal to r8 = freq * 0.025862 */
1620 }
1621 bcm43xx_radio_write16(bcm, 0x0007, (r8 << 4) | r8);
1622 bcm43xx_radio_write16(bcm, 0x0020, (r8 << 4) | r8);
1623 bcm43xx_radio_write16(bcm, 0x0021, (r8 << 4) | r8);
1624 bcm43xx_radio_write16(bcm, 0x0022,
1625 (bcm43xx_radio_read16(bcm, 0x0022)
1626 & 0x000F) | (r8 << 4));
1627 bcm43xx_radio_write16(bcm, 0x002A, (r8 << 4));
1628 bcm43xx_radio_write16(bcm, 0x002B, (r8 << 4));
1629 bcm43xx_radio_write16(bcm, 0x0008,
1630 (bcm43xx_radio_read16(bcm, 0x0008)
1631 & 0x00F0) | (r8 << 4));
1632 bcm43xx_radio_write16(bcm, 0x0029,
1633 (bcm43xx_radio_read16(bcm, 0x0029)
1634 & 0xFF0F) | 0x00B0);
1635 bcm43xx_radio_write16(bcm, 0x0035, 0x00AA);
1636 bcm43xx_radio_write16(bcm, 0x0036, 0x0085);
1637 bcm43xx_radio_write16(bcm, 0x003A,
1638 (bcm43xx_radio_read16(bcm, 0x003A)
1639 & 0xFF20) | freq_r3A_value(freq));
1640 bcm43xx_radio_write16(bcm, 0x003D,
1641 bcm43xx_radio_read16(bcm, 0x003D) & 0x00FF);
1642 bcm43xx_radio_write16(bcm, 0x0081,
1643 (bcm43xx_radio_read16(bcm, 0x0081)
1644 & 0xFF7F) | 0x0080);
1645 bcm43xx_radio_write16(bcm, 0x0035,
1646 bcm43xx_radio_read16(bcm, 0x0035) & 0xFFEF);
1647 bcm43xx_radio_write16(bcm, 0x0035,
1648 (bcm43xx_radio_read16(bcm, 0x0035)
1649 & 0xFFEF) | 0x0010);
1650 bcm43xx_radio_set_tx_iq(bcm);
1651 TODO(); //TODO: TSSI2dbm workaround
1652 bcm43xx_phy_xmitpower(bcm);//FIXME correct?
1653 } else {
1654 if ((channel < 1) || (channel > 14))
1655 return -EINVAL;
1656
1657 if (synthetic_pu_workaround)
1658 bcm43xx_synth_pu_workaround(bcm, channel);
1659
1660 bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL,
1661 channel2freq_bg(channel));
1662
1663 if (channel == 14) {
1664 if (bcm->sprom.locale == BCM43xx_LOCALE_JAPAN) {
1665 bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED,
1666 BCM43xx_UCODEFLAGS_OFFSET,
1667 bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED,
1668 BCM43xx_UCODEFLAGS_OFFSET)
1669 & ~(1 << 7));
1670 } else {
1671 bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED,
1672 BCM43xx_UCODEFLAGS_OFFSET,
1673 bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED,
1674 BCM43xx_UCODEFLAGS_OFFSET)
1675 | (1 << 7));
1676 }
1677 bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT,
1678 bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT)
1679 | (1 << 11));
1680 } else {
1681 bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT,
1682 bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT)
1683 & 0xF7BF);
1684 }
1685 }
1686
1687 radio->channel = channel;
1688 //XXX: Using the longer of 2 timeouts (8000 vs 2000 usecs). Specs states
1689 // that 2000 usecs might suffice.
1690 udelay(8000);
1691
1692 return 0;
1693}
1694
1695void bcm43xx_radio_set_txantenna(struct bcm43xx_private *bcm, u32 val)
1696{
1697 u16 tmp;
1698
1699 val <<= 8;
1700 tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x0022) & 0xFCFF;
1701 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0022, tmp | val);
1702 tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x03A8) & 0xFCFF;
1703 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x03A8, tmp | val);
1704 tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x0054) & 0xFCFF;
1705 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0054, tmp | val);
1706}
1707
1708/* http://bcm-specs.sipsolutions.net/TX_Gain_Base_Band */
1709static u16 bcm43xx_get_txgain_base_band(u16 txpower)
1710{
1711 u16 ret;
1712
1713 assert(txpower <= 63);
1714
1715 if (txpower >= 54)
1716 ret = 2;
1717 else if (txpower >= 49)
1718 ret = 4;
1719 else if (txpower >= 44)
1720 ret = 5;
1721 else
1722 ret = 6;
1723
1724 return ret;
1725}
1726
1727/* http://bcm-specs.sipsolutions.net/TX_Gain_Radio_Frequency_Power_Amplifier */
1728static u16 bcm43xx_get_txgain_freq_power_amp(u16 txpower)
1729{
1730 u16 ret;
1731
1732 assert(txpower <= 63);
1733
1734 if (txpower >= 32)
1735 ret = 0;
1736 else if (txpower >= 25)
1737 ret = 1;
1738 else if (txpower >= 20)
1739 ret = 2;
1740 else if (txpower >= 12)
1741 ret = 3;
1742 else
1743 ret = 4;
1744
1745 return ret;
1746}
1747
1748/* http://bcm-specs.sipsolutions.net/TX_Gain_Digital_Analog_Converter */
1749static u16 bcm43xx_get_txgain_dac(u16 txpower)
1750{
1751 u16 ret;
1752
1753 assert(txpower <= 63);
1754
1755 if (txpower >= 54)
1756 ret = txpower - 53;
1757 else if (txpower >= 49)
1758 ret = txpower - 42;
1759 else if (txpower >= 44)
1760 ret = txpower - 37;
1761 else if (txpower >= 32)
1762 ret = txpower - 32;
1763 else if (txpower >= 25)
1764 ret = txpower - 20;
1765 else if (txpower >= 20)
1766 ret = txpower - 13;
1767 else if (txpower >= 12)
1768 ret = txpower - 8;
1769 else
1770 ret = txpower;
1771
1772 return ret;
1773}
1774
1775void bcm43xx_radio_set_txpower_a(struct bcm43xx_private *bcm, u16 txpower)
1776{
1777 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
1778 u16 pamp, base, dac, ilt;
1779
1780 txpower = limit_value(txpower, 0, 63);
1781
1782 pamp = bcm43xx_get_txgain_freq_power_amp(txpower);
1783 pamp <<= 5;
1784 pamp &= 0x00E0;
1785 bcm43xx_phy_write(bcm, 0x0019, pamp);
1786
1787 base = bcm43xx_get_txgain_base_band(txpower);
1788 base &= 0x000F;
1789 bcm43xx_phy_write(bcm, 0x0017, base | 0x0020);
1790
1791 ilt = bcm43xx_ilt_read(bcm, 0x3001);
1792 ilt &= 0x0007;
1793
1794 dac = bcm43xx_get_txgain_dac(txpower);
1795 dac <<= 3;
1796 dac |= ilt;
1797
1798 bcm43xx_ilt_write(bcm, 0x3001, dac);
1799
1800 radio->txpwr_offset = txpower;
1801
1802 TODO();
1803 //TODO: FuncPlaceholder (Adjust BB loft cancel)
1804}
1805
1806void bcm43xx_radio_set_txpower_bg(struct bcm43xx_private *bcm,
1807 u16 baseband_attenuation, u16 radio_attenuation,
1808 u16 txpower)
1809{
1810 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
1811 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
1812
1813 if (baseband_attenuation == 0xFFFF)
1814 baseband_attenuation = radio->baseband_atten;
1815 if (radio_attenuation == 0xFFFF)
1816 radio_attenuation = radio->radio_atten;
1817 if (txpower == 0xFFFF)
1818 txpower = radio->txctl1;
1819 radio->baseband_atten = baseband_attenuation;
1820 radio->radio_atten = radio_attenuation;
1821 radio->txctl1 = txpower;
1822
1823 assert(/*baseband_attenuation >= 0 &&*/ baseband_attenuation <= 11);
1824 if (radio->revision < 6)
1825 assert(/*radio_attenuation >= 0 &&*/ radio_attenuation <= 9);
1826 else
1827 assert(/* radio_attenuation >= 0 &&*/ radio_attenuation <= 31);
1828 assert(/*txpower >= 0 &&*/ txpower <= 7);
1829
1830 bcm43xx_phy_set_baseband_attenuation(bcm, baseband_attenuation);
1831 bcm43xx_radio_write16(bcm, 0x0043, radio_attenuation);
1832 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0064, radio_attenuation);
1833 if (radio->version == 0x2050) {
1834 bcm43xx_radio_write16(bcm, 0x0052,
1835 (bcm43xx_radio_read16(bcm, 0x0052) & ~0x0070)
1836 | ((txpower << 4) & 0x0070));
1837 }
1838 //FIXME: The spec is very weird and unclear here.
1839 if (phy->type == BCM43xx_PHYTYPE_G)
1840 bcm43xx_phy_lo_adjust(bcm, 0);
1841}
1842
1843u16 bcm43xx_default_baseband_attenuation(struct bcm43xx_private *bcm)
1844{
1845 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
1846
1847 if (radio->version == 0x2050 && radio->revision < 6)
1848 return 0;
1849 return 2;
1850}
1851
1852u16 bcm43xx_default_radio_attenuation(struct bcm43xx_private *bcm)
1853{
1854 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
1855 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
1856 u16 att = 0xFFFF;
1857
1858 if (phy->type == BCM43xx_PHYTYPE_A)
1859 return 0x60;
1860
1861 switch (radio->version) {
1862 case 0x2053:
1863 switch (radio->revision) {
1864 case 1:
1865 att = 6;
1866 break;
1867 }
1868 break;
1869 case 0x2050:
1870 switch (radio->revision) {
1871 case 0:
1872 att = 5;
1873 break;
1874 case 1:
1875 if (phy->type == BCM43xx_PHYTYPE_G) {
1876 if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM &&
1877 bcm->board_type == 0x421 &&
1878 bcm->board_revision >= 30)
1879 att = 3;
1880 else if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM &&
1881 bcm->board_type == 0x416)
1882 att = 3;
1883 else
1884 att = 1;
1885 } else {
1886 if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM &&
1887 bcm->board_type == 0x421 &&
1888 bcm->board_revision >= 30)
1889 att = 7;
1890 else
1891 att = 6;
1892 }
1893 break;
1894 case 2:
1895 if (phy->type == BCM43xx_PHYTYPE_G) {
1896 if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM &&
1897 bcm->board_type == 0x421 &&
1898 bcm->board_revision >= 30)
1899 att = 3;
1900 else if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM &&
1901 bcm->board_type == 0x416)
1902 att = 5;
1903 else if (bcm->chip_id == 0x4320)
1904 att = 4;
1905 else
1906 att = 3;
1907 } else
1908 att = 6;
1909 break;
1910 case 3:
1911 att = 5;
1912 break;
1913 case 4:
1914 case 5:
1915 att = 1;
1916 break;
1917 case 6:
1918 case 7:
1919 att = 5;
1920 break;
1921 case 8:
1922 att = 0x1A;
1923 break;
1924 case 9:
1925 default:
1926 att = 5;
1927 }
1928 }
1929 if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM &&
1930 bcm->board_type == 0x421) {
1931 if (bcm->board_revision < 0x43)
1932 att = 2;
1933 else if (bcm->board_revision < 0x51)
1934 att = 3;
1935 }
1936 if (att == 0xFFFF)
1937 att = 5;
1938
1939 return att;
1940}
1941
1942u16 bcm43xx_default_txctl1(struct bcm43xx_private *bcm)
1943{
1944 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
1945
1946 if (radio->version != 0x2050)
1947 return 0;
1948 if (radio->revision == 1)
1949 return 3;
1950 if (radio->revision < 6)
1951 return 2;
1952 if (radio->revision == 8)
1953 return 1;
1954 return 0;
1955}
1956
1957void bcm43xx_radio_turn_on(struct bcm43xx_private *bcm)
1958{
1959 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
1960 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
1961 int err;
1962
1963 if (radio->enabled)
1964 return;
1965
1966 switch (phy->type) {
1967 case BCM43xx_PHYTYPE_A:
1968 bcm43xx_radio_write16(bcm, 0x0004, 0x00C0);
1969 bcm43xx_radio_write16(bcm, 0x0005, 0x0008);
1970 bcm43xx_phy_write(bcm, 0x0010, bcm43xx_phy_read(bcm, 0x0010) & 0xFFF7);
1971 bcm43xx_phy_write(bcm, 0x0011, bcm43xx_phy_read(bcm, 0x0011) & 0xFFF7);
1972 bcm43xx_radio_init2060(bcm);
1973 break;
1974 case BCM43xx_PHYTYPE_B:
1975 case BCM43xx_PHYTYPE_G:
1976 bcm43xx_phy_write(bcm, 0x0015, 0x8000);
1977 bcm43xx_phy_write(bcm, 0x0015, 0xCC00);
1978 bcm43xx_phy_write(bcm, 0x0015, (phy->connected ? 0x00C0 : 0x0000));
1979 err = bcm43xx_radio_selectchannel(bcm, BCM43xx_RADIO_DEFAULT_CHANNEL_BG, 1);
1980 assert(err == 0);
1981 break;
1982 default:
1983 assert(0);
1984 }
1985 radio->enabled = 1;
1986 dprintk(KERN_INFO PFX "Radio turned on\n");
1987}
1988
1989void bcm43xx_radio_turn_off(struct bcm43xx_private *bcm)
1990{
1991 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
1992 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
1993
1994 if (phy->type == BCM43xx_PHYTYPE_A) {
1995 bcm43xx_radio_write16(bcm, 0x0004, 0x00FF);
1996 bcm43xx_radio_write16(bcm, 0x0005, 0x00FB);
1997 bcm43xx_phy_write(bcm, 0x0010, bcm43xx_phy_read(bcm, 0x0010) | 0x0008);
1998 bcm43xx_phy_write(bcm, 0x0011, bcm43xx_phy_read(bcm, 0x0011) | 0x0008);
1999 }
2000 if (phy->type == BCM43xx_PHYTYPE_G && bcm->current_core->rev >= 5) {
2001 bcm43xx_phy_write(bcm, 0x0811, bcm43xx_phy_read(bcm, 0x0811) | 0x008C);
2002 bcm43xx_phy_write(bcm, 0x0812, bcm43xx_phy_read(bcm, 0x0812) & 0xFF73);
2003 } else
2004 bcm43xx_phy_write(bcm, 0x0015, 0xAA00);
2005 radio->enabled = 0;
2006 dprintk(KERN_INFO PFX "Radio turned off\n");
2007}
2008
2009void bcm43xx_radio_clear_tssi(struct bcm43xx_private *bcm)
2010{
2011 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
2012
2013 switch (phy->type) {
2014 case BCM43xx_PHYTYPE_A:
2015 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0068, 0x7F7F);
2016 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x006a, 0x7F7F);
2017 break;
2018 case BCM43xx_PHYTYPE_B:
2019 case BCM43xx_PHYTYPE_G:
2020 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0058, 0x7F7F);
2021 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x005a, 0x7F7F);
2022 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0070, 0x7F7F);
2023 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0072, 0x7F7F);
2024 break;
2025 }
2026}
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_radio.h b/drivers/net/wireless/bcm43xx/bcm43xx_radio.h
new file mode 100644
index 000000000000..9ed18039fa3e
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_radio.h
@@ -0,0 +1,99 @@
1/*
2
3 Broadcom BCM43xx wireless driver
4
5 Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
6 Stefano Brivio <st3@riseup.net>
7 Michael Buesch <mbuesch@freenet.de>
8 Danny van Dyk <kugelfang@gentoo.org>
9 Andreas Jaggi <andreas.jaggi@waterwave.ch>
10
11 Some parts of the code in this file are derived from the ipw2200
12 driver Copyright(c) 2003 - 2004 Intel Corporation.
13
14 This program is free software; you can redistribute it and/or modify
15 it under the terms of the GNU General Public License as published by
16 the Free Software Foundation; either version 2 of the License, or
17 (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; see the file COPYING. If not, write to
26 the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
27 Boston, MA 02110-1301, USA.
28
29*/
30
31#ifndef BCM43xx_RADIO_H_
32#define BCM43xx_RADIO_H_
33
34#include "bcm43xx.h"
35
36
37#define BCM43xx_RADIO_DEFAULT_CHANNEL_A 36
38#define BCM43xx_RADIO_DEFAULT_CHANNEL_BG 6
39
40/* Force antenna 0. */
41#define BCM43xx_RADIO_TXANTENNA_0 0
42/* Force antenna 1. */
43#define BCM43xx_RADIO_TXANTENNA_1 1
44/* Use the RX antenna, that was selected for the most recently
45 * received good PLCP header.
46 */
47#define BCM43xx_RADIO_TXANTENNA_LASTPLCP 3
48#define BCM43xx_RADIO_TXANTENNA_DEFAULT BCM43xx_RADIO_TXANTENNA_LASTPLCP
49
50#define BCM43xx_RADIO_INTERFMODE_NONE 0
51#define BCM43xx_RADIO_INTERFMODE_NONWLAN 1
52#define BCM43xx_RADIO_INTERFMODE_MANUALWLAN 2
53#define BCM43xx_RADIO_INTERFMODE_AUTOWLAN 3
54
55
56void bcm43xx_radio_lock(struct bcm43xx_private *bcm);
57void bcm43xx_radio_unlock(struct bcm43xx_private *bcm);
58
59u16 bcm43xx_radio_read16(struct bcm43xx_private *bcm, u16 offset);
60void bcm43xx_radio_write16(struct bcm43xx_private *bcm, u16 offset, u16 val);
61
62u16 bcm43xx_radio_init2050(struct bcm43xx_private *bcm);
63void bcm43xx_radio_init2060(struct bcm43xx_private *bcm);
64
65void bcm43xx_radio_turn_on(struct bcm43xx_private *bcm);
66void bcm43xx_radio_turn_off(struct bcm43xx_private *bcm);
67
68int bcm43xx_radio_selectchannel(struct bcm43xx_private *bcm, u8 channel,
69 int synthetic_pu_workaround);
70
71void bcm43xx_radio_set_txpower_a(struct bcm43xx_private *bcm, u16 txpower);
72void bcm43xx_radio_set_txpower_bg(struct bcm43xx_private *bcm,
73 u16 baseband_attenuation, u16 attenuation,
74 u16 txpower);
75
76u16 bcm43xx_default_baseband_attenuation(struct bcm43xx_private *bcm);
77u16 bcm43xx_default_radio_attenuation(struct bcm43xx_private *bcm);
78u16 bcm43xx_default_txctl1(struct bcm43xx_private *bcm);
79
80void bcm43xx_radio_set_txantenna(struct bcm43xx_private *bcm, u32 val);
81
82void bcm43xx_radio_clear_tssi(struct bcm43xx_private *bcm);
83
84u8 bcm43xx_radio_aci_detect(struct bcm43xx_private *bcm, u8 channel);
85u8 bcm43xx_radio_aci_scan(struct bcm43xx_private *bcm);
86
87int bcm43xx_radio_set_interference_mitigation(struct bcm43xx_private *bcm, int mode);
88
89void bcm43xx_calc_nrssi_slope(struct bcm43xx_private *bcm);
90void bcm43xx_calc_nrssi_threshold(struct bcm43xx_private *bcm);
91s16 bcm43xx_nrssi_hw_read(struct bcm43xx_private *bcm, u16 offset);
92void bcm43xx_nrssi_hw_write(struct bcm43xx_private *bcm, u16 offset, s16 val);
93void bcm43xx_nrssi_hw_update(struct bcm43xx_private *bcm, u16 val);
94void bcm43xx_nrssi_mem_update(struct bcm43xx_private *bcm);
95
96void bcm43xx_radio_set_tx_iq(struct bcm43xx_private *bcm);
97u16 bcm43xx_radio_calibrationvalue(struct bcm43xx_private *bcm);
98
99#endif /* BCM43xx_RADIO_H_ */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c
new file mode 100644
index 000000000000..c44d890b949b
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c
@@ -0,0 +1,322 @@
1/*
2
3 Broadcom BCM43xx wireless driver
4
5 SYSFS support routines
6
7 Copyright (c) 2006 Michael Buesch <mbuesch@freenet.de>
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; see the file COPYING. If not, write to
21 the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
22 Boston, MA 02110-1301, USA.
23
24*/
25
26#include "bcm43xx_sysfs.h"
27#include "bcm43xx.h"
28#include "bcm43xx_main.h"
29#include "bcm43xx_radio.h"
30
31#include <linux/capability.h>
32
33
34#define GENERIC_FILESIZE 64
35
36
37static int get_integer(const char *buf, size_t count)
38{
39 char tmp[10 + 1] = { 0 };
40 int ret = -EINVAL;
41
42 if (count == 0)
43 goto out;
44 count = min(count, (size_t)10);
45 memcpy(tmp, buf, count);
46 ret = simple_strtol(tmp, NULL, 10);
47out:
48 return ret;
49}
50
51static int get_boolean(const char *buf, size_t count)
52{
53 if (count != 0) {
54 if (buf[0] == '1')
55 return 1;
56 if (buf[0] == '0')
57 return 0;
58 if (count >= 4 && memcmp(buf, "true", 4) == 0)
59 return 1;
60 if (count >= 5 && memcmp(buf, "false", 5) == 0)
61 return 0;
62 if (count >= 3 && memcmp(buf, "yes", 3) == 0)
63 return 1;
64 if (count >= 2 && memcmp(buf, "no", 2) == 0)
65 return 0;
66 if (count >= 2 && memcmp(buf, "on", 2) == 0)
67 return 1;
68 if (count >= 3 && memcmp(buf, "off", 3) == 0)
69 return 0;
70 }
71 return -EINVAL;
72}
73
74static ssize_t bcm43xx_attr_sprom_show(struct device *dev,
75 struct device_attribute *attr,
76 char *buf)
77{
78 struct bcm43xx_private *bcm = devattr_to_bcm(attr, attr_sprom);
79 u16 *sprom;
80 unsigned long flags;
81 int i, err;
82
83 if (!capable(CAP_NET_ADMIN))
84 return -EPERM;
85
86 assert(BCM43xx_SPROM_SIZE * sizeof(u16) <= PAGE_SIZE);
87 sprom = kmalloc(BCM43xx_SPROM_SIZE * sizeof(*sprom),
88 GFP_KERNEL);
89 if (!sprom)
90 return -ENOMEM;
91 bcm43xx_lock_mmio(bcm, flags);
92 assert(bcm->initialized);
93 err = bcm43xx_sprom_read(bcm, sprom);
94 if (!err) {
95 for (i = 0; i < BCM43xx_SPROM_SIZE; i++) {
96 buf[i * 2] = sprom[i] & 0x00FF;
97 buf[i * 2 + 1] = (sprom[i] & 0xFF00) >> 8;
98 }
99 }
100 bcm43xx_unlock_mmio(bcm, flags);
101 kfree(sprom);
102
103 return err ? err : BCM43xx_SPROM_SIZE * sizeof(u16);
104}
105
106static ssize_t bcm43xx_attr_sprom_store(struct device *dev,
107 struct device_attribute *attr,
108 const char *buf, size_t count)
109{
110 struct bcm43xx_private *bcm = devattr_to_bcm(attr, attr_sprom);
111 u16 *sprom;
112 unsigned long flags;
113 int i, err;
114
115 if (!capable(CAP_NET_ADMIN))
116 return -EPERM;
117
118 if (count != BCM43xx_SPROM_SIZE * sizeof(u16))
119 return -EINVAL;
120 sprom = kmalloc(BCM43xx_SPROM_SIZE * sizeof(*sprom),
121 GFP_KERNEL);
122 if (!sprom)
123 return -ENOMEM;
124 for (i = 0; i < BCM43xx_SPROM_SIZE; i++) {
125 sprom[i] = buf[i * 2] & 0xFF;
126 sprom[i] |= ((u16)(buf[i * 2 + 1] & 0xFF)) << 8;
127 }
128 bcm43xx_lock_mmio(bcm, flags);
129 assert(bcm->initialized);
130 err = bcm43xx_sprom_write(bcm, sprom);
131 bcm43xx_unlock_mmio(bcm, flags);
132 kfree(sprom);
133
134 return err ? err : count;
135
136}
137
138static ssize_t bcm43xx_attr_interfmode_show(struct device *dev,
139 struct device_attribute *attr,
140 char *buf)
141{
142 struct bcm43xx_private *bcm = devattr_to_bcm(attr, attr_interfmode);
143 unsigned long flags;
144 int err;
145 ssize_t count = 0;
146
147 if (!capable(CAP_NET_ADMIN))
148 return -EPERM;
149
150 bcm43xx_lock(bcm, flags);
151 assert(bcm->initialized);
152
153 switch (bcm43xx_current_radio(bcm)->interfmode) {
154 case BCM43xx_RADIO_INTERFMODE_NONE:
155 count = snprintf(buf, PAGE_SIZE, "0 (No Interference Mitigation)\n");
156 break;
157 case BCM43xx_RADIO_INTERFMODE_NONWLAN:
158 count = snprintf(buf, PAGE_SIZE, "1 (Non-WLAN Interference Mitigation)\n");
159 break;
160 case BCM43xx_RADIO_INTERFMODE_MANUALWLAN:
161 count = snprintf(buf, PAGE_SIZE, "2 (WLAN Interference Mitigation)\n");
162 break;
163 default:
164 assert(0);
165 }
166 err = 0;
167
168 bcm43xx_unlock(bcm, flags);
169
170 return err ? err : count;
171
172}
173
174static ssize_t bcm43xx_attr_interfmode_store(struct device *dev,
175 struct device_attribute *attr,
176 const char *buf, size_t count)
177{
178 struct bcm43xx_private *bcm = devattr_to_bcm(attr, attr_interfmode);
179 unsigned long flags;
180 int err;
181 int mode;
182
183 if (!capable(CAP_NET_ADMIN))
184 return -EPERM;
185
186 mode = get_integer(buf, count);
187 switch (mode) {
188 case 0:
189 mode = BCM43xx_RADIO_INTERFMODE_NONE;
190 break;
191 case 1:
192 mode = BCM43xx_RADIO_INTERFMODE_NONWLAN;
193 break;
194 case 2:
195 mode = BCM43xx_RADIO_INTERFMODE_MANUALWLAN;
196 break;
197 case 3:
198 mode = BCM43xx_RADIO_INTERFMODE_AUTOWLAN;
199 break;
200 default:
201 return -EINVAL;
202 }
203
204 bcm43xx_lock_mmio(bcm, flags);
205 assert(bcm->initialized);
206
207 err = bcm43xx_radio_set_interference_mitigation(bcm, mode);
208 if (err) {
209 printk(KERN_ERR PFX "Interference Mitigation not "
210 "supported by device\n");
211 }
212
213 bcm43xx_unlock_mmio(bcm, flags);
214
215 return err ? err : count;
216}
217
218static ssize_t bcm43xx_attr_preamble_show(struct device *dev,
219 struct device_attribute *attr,
220 char *buf)
221{
222 struct bcm43xx_private *bcm = devattr_to_bcm(attr, attr_preamble);
223 unsigned long flags;
224 int err;
225 ssize_t count;
226
227 if (!capable(CAP_NET_ADMIN))
228 return -EPERM;
229
230 bcm43xx_lock(bcm, flags);
231 assert(bcm->initialized);
232
233 if (bcm->short_preamble)
234 count = snprintf(buf, PAGE_SIZE, "1 (Short Preamble enabled)\n");
235 else
236 count = snprintf(buf, PAGE_SIZE, "0 (Short Preamble disabled)\n");
237
238 err = 0;
239 bcm43xx_unlock(bcm, flags);
240
241 return err ? err : count;
242}
243
244static ssize_t bcm43xx_attr_preamble_store(struct device *dev,
245 struct device_attribute *attr,
246 const char *buf, size_t count)
247{
248 struct bcm43xx_private *bcm = devattr_to_bcm(attr, attr_preamble);
249 unsigned long flags;
250 int err;
251 int value;
252
253 if (!capable(CAP_NET_ADMIN))
254 return -EPERM;
255
256 value = get_boolean(buf, count);
257 if (value < 0)
258 return value;
259 bcm43xx_lock(bcm, flags);
260 assert(bcm->initialized);
261
262 bcm->short_preamble = !!value;
263
264 err = 0;
265 bcm43xx_unlock(bcm, flags);
266
267 return err ? err : count;
268}
269
270int bcm43xx_sysfs_register(struct bcm43xx_private *bcm)
271{
272 struct device *dev = &bcm->pci_dev->dev;
273 struct bcm43xx_sysfs *sysfs = &bcm->sysfs;
274 int err;
275
276 assert(bcm->initialized);
277
278 sysfs->attr_sprom.attr.name = "sprom";
279 sysfs->attr_sprom.attr.owner = THIS_MODULE;
280 sysfs->attr_sprom.attr.mode = 0600;
281 sysfs->attr_sprom.show = bcm43xx_attr_sprom_show;
282 sysfs->attr_sprom.store = bcm43xx_attr_sprom_store;
283 err = device_create_file(dev, &sysfs->attr_sprom);
284 if (err)
285 goto out;
286
287 sysfs->attr_interfmode.attr.name = "interference";
288 sysfs->attr_interfmode.attr.owner = THIS_MODULE;
289 sysfs->attr_interfmode.attr.mode = 0600;
290 sysfs->attr_interfmode.show = bcm43xx_attr_interfmode_show;
291 sysfs->attr_interfmode.store = bcm43xx_attr_interfmode_store;
292 err = device_create_file(dev, &sysfs->attr_interfmode);
293 if (err)
294 goto err_remove_sprom;
295
296 sysfs->attr_preamble.attr.name = "shortpreamble";
297 sysfs->attr_preamble.attr.owner = THIS_MODULE;
298 sysfs->attr_preamble.attr.mode = 0600;
299 sysfs->attr_preamble.show = bcm43xx_attr_preamble_show;
300 sysfs->attr_preamble.store = bcm43xx_attr_preamble_store;
301 err = device_create_file(dev, &sysfs->attr_preamble);
302 if (err)
303 goto err_remove_interfmode;
304
305out:
306 return err;
307err_remove_interfmode:
308 device_remove_file(dev, &sysfs->attr_interfmode);
309err_remove_sprom:
310 device_remove_file(dev, &sysfs->attr_sprom);
311 goto out;
312}
313
314void bcm43xx_sysfs_unregister(struct bcm43xx_private *bcm)
315{
316 struct device *dev = &bcm->pci_dev->dev;
317 struct bcm43xx_sysfs *sysfs = &bcm->sysfs;
318
319 device_remove_file(dev, &sysfs->attr_preamble);
320 device_remove_file(dev, &sysfs->attr_interfmode);
321 device_remove_file(dev, &sysfs->attr_sprom);
322}
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.h b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.h
new file mode 100644
index 000000000000..57f14514e3e0
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.h
@@ -0,0 +1,25 @@
1#ifndef BCM43xx_SYSFS_H_
2#define BCM43xx_SYSFS_H_
3
4#include <linux/device.h>
5
6
7struct bcm43xx_sysfs {
8 struct device_attribute attr_sprom;
9 struct device_attribute attr_interfmode;
10 struct device_attribute attr_preamble;
11};
12
13#define devattr_to_bcm(attr, attr_name) ({ \
14 struct bcm43xx_sysfs *__s; struct bcm43xx_private *__p; \
15 __s = container_of((attr), struct bcm43xx_sysfs, attr_name); \
16 __p = container_of(__s, struct bcm43xx_private, sysfs); \
17 __p; \
18 })
19
20struct bcm43xx_private;
21
22int bcm43xx_sysfs_register(struct bcm43xx_private *bcm);
23void bcm43xx_sysfs_unregister(struct bcm43xx_private *bcm);
24
25#endif /* BCM43xx_SYSFS_H_ */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
new file mode 100644
index 000000000000..3daee828ef4b
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
@@ -0,0 +1,1002 @@
1/*
2
3 Broadcom BCM43xx wireless driver
4
5 Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
6 Stefano Brivio <st3@riseup.net>
7 Michael Buesch <mbuesch@freenet.de>
8 Danny van Dyk <kugelfang@gentoo.org>
9 Andreas Jaggi <andreas.jaggi@waterwave.ch>
10
11 Some parts of the code in this file are derived from the ipw2200
12 driver Copyright(c) 2003 - 2004 Intel Corporation.
13
14 This program is free software; you can redistribute it and/or modify
15 it under the terms of the GNU General Public License as published by
16 the Free Software Foundation; either version 2 of the License, or
17 (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; see the file COPYING. If not, write to
26 the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
27 Boston, MA 02110-1301, USA.
28
29*/
30
31#include <linux/wireless.h>
32#include <net/iw_handler.h>
33#include <net/ieee80211softmac.h>
34#include <net/ieee80211softmac_wx.h>
35#include <linux/capability.h>
36#include <linux/sched.h> /* for capable() */
37#include <linux/delay.h>
38
39#include "bcm43xx.h"
40#include "bcm43xx_wx.h"
41#include "bcm43xx_main.h"
42#include "bcm43xx_radio.h"
43#include "bcm43xx_phy.h"
44
45
46/* The WIRELESS_EXT version, which is implemented by this driver. */
47#define BCM43xx_WX_VERSION 18
48
49#define MAX_WX_STRING 80
50
51
52static int bcm43xx_wx_get_name(struct net_device *net_dev,
53 struct iw_request_info *info,
54 union iwreq_data *data,
55 char *extra)
56{
57 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
58 unsigned long flags;
59 int i;
60 struct bcm43xx_phyinfo *phy;
61 char suffix[7] = { 0 };
62 int have_a = 0, have_b = 0, have_g = 0;
63
64 bcm43xx_lock(bcm, flags);
65 for (i = 0; i < bcm->nr_80211_available; i++) {
66 phy = &(bcm->core_80211_ext[i].phy);
67 switch (phy->type) {
68 case BCM43xx_PHYTYPE_A:
69 have_a = 1;
70 break;
71 case BCM43xx_PHYTYPE_G:
72 have_g = 1;
73 case BCM43xx_PHYTYPE_B:
74 have_b = 1;
75 break;
76 default:
77 assert(0);
78 }
79 }
80 bcm43xx_unlock(bcm, flags);
81
82 i = 0;
83 if (have_a) {
84 suffix[i++] = 'a';
85 suffix[i++] = '/';
86 }
87 if (have_b) {
88 suffix[i++] = 'b';
89 suffix[i++] = '/';
90 }
91 if (have_g) {
92 suffix[i++] = 'g';
93 suffix[i++] = '/';
94 }
95 if (i != 0)
96 suffix[i - 1] = '\0';
97
98 snprintf(data->name, IFNAMSIZ, "IEEE 802.11%s", suffix);
99
100 return 0;
101}
102
103static int bcm43xx_wx_set_channelfreq(struct net_device *net_dev,
104 struct iw_request_info *info,
105 union iwreq_data *data,
106 char *extra)
107{
108 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
109 unsigned long flags;
110 u8 channel;
111 int freq;
112 int err = -EINVAL;
113
114 bcm43xx_lock_mmio(bcm, flags);
115 if ((data->freq.m >= 0) && (data->freq.m <= 1000)) {
116 channel = data->freq.m;
117 freq = bcm43xx_channel_to_freq(bcm, channel);
118 } else {
119 channel = bcm43xx_freq_to_channel(bcm, data->freq.m);
120 freq = data->freq.m;
121 }
122 if (!bcm43xx_is_valid_channel(bcm, channel))
123 goto out_unlock;
124 if (bcm->initialized) {
125 //ieee80211softmac_disassoc(softmac, $REASON);
126 bcm43xx_mac_suspend(bcm);
127 err = bcm43xx_radio_selectchannel(bcm, channel, 0);
128 bcm43xx_mac_enable(bcm);
129 } else {
130 bcm43xx_current_radio(bcm)->initial_channel = channel;
131 err = 0;
132 }
133out_unlock:
134 bcm43xx_unlock_mmio(bcm, flags);
135
136 return err;
137}
138
139static int bcm43xx_wx_get_channelfreq(struct net_device *net_dev,
140 struct iw_request_info *info,
141 union iwreq_data *data,
142 char *extra)
143{
144 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
145 struct bcm43xx_radioinfo *radio;
146 unsigned long flags;
147 int err = -ENODEV;
148 u16 channel;
149
150 bcm43xx_lock(bcm, flags);
151 radio = bcm43xx_current_radio(bcm);
152 channel = radio->channel;
153 if (channel == 0xFF) {
154 assert(!bcm->initialized);
155 channel = radio->initial_channel;
156 if (channel == 0xFF)
157 goto out_unlock;
158 }
159 assert(channel > 0 && channel <= 1000);
160 data->freq.e = 1;
161 data->freq.m = bcm43xx_channel_to_freq(bcm, channel) * 100000;
162 data->freq.flags = 1;
163
164 err = 0;
165out_unlock:
166 bcm43xx_unlock(bcm, flags);
167
168 return err;
169}
170
171static int bcm43xx_wx_set_mode(struct net_device *net_dev,
172 struct iw_request_info *info,
173 union iwreq_data *data,
174 char *extra)
175{
176 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
177 unsigned long flags;
178 int mode;
179
180 mode = data->mode;
181 if (mode == IW_MODE_AUTO)
182 mode = BCM43xx_INITIAL_IWMODE;
183
184 bcm43xx_lock_mmio(bcm, flags);
185 if (bcm->ieee->iw_mode != mode)
186 bcm43xx_set_iwmode(bcm, mode);
187 bcm43xx_unlock_mmio(bcm, flags);
188
189 return 0;
190}
191
192static int bcm43xx_wx_get_mode(struct net_device *net_dev,
193 struct iw_request_info *info,
194 union iwreq_data *data,
195 char *extra)
196{
197 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
198 unsigned long flags;
199
200 bcm43xx_lock(bcm, flags);
201 data->mode = bcm->ieee->iw_mode;
202 bcm43xx_unlock(bcm, flags);
203
204 return 0;
205}
206
207static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev,
208 struct iw_request_info *info,
209 union iwreq_data *data,
210 char *extra)
211{
212 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
213 struct iw_range *range = (struct iw_range *)extra;
214 const struct ieee80211_geo *geo;
215 unsigned long flags;
216 int i, j;
217 struct bcm43xx_phyinfo *phy;
218
219 data->data.length = sizeof(*range);
220 memset(range, 0, sizeof(*range));
221
222 //TODO: What about 802.11b?
223 /* 54Mb/s == ~27Mb/s payload throughput (802.11g) */
224 range->throughput = 27 * 1000 * 1000;
225
226 range->max_qual.qual = 100;
227 /* TODO: Real max RSSI */
228 range->max_qual.level = 3;
229 range->max_qual.noise = 100;
230 range->max_qual.updated = 7;
231
232 range->avg_qual.qual = 70;
233 range->avg_qual.level = 2;
234 range->avg_qual.noise = 40;
235 range->avg_qual.updated = 7;
236
237 range->min_rts = BCM43xx_MIN_RTS_THRESHOLD;
238 range->max_rts = BCM43xx_MAX_RTS_THRESHOLD;
239 range->min_frag = MIN_FRAG_THRESHOLD;
240 range->max_frag = MAX_FRAG_THRESHOLD;
241
242 range->encoding_size[0] = 5;
243 range->encoding_size[1] = 13;
244 range->num_encoding_sizes = 2;
245 range->max_encoding_tokens = WEP_KEYS;
246
247 range->we_version_compiled = WIRELESS_EXT;
248 range->we_version_source = BCM43xx_WX_VERSION;
249
250 range->enc_capa = IW_ENC_CAPA_WPA |
251 IW_ENC_CAPA_WPA2 |
252 IW_ENC_CAPA_CIPHER_TKIP |
253 IW_ENC_CAPA_CIPHER_CCMP;
254
255 bcm43xx_lock(bcm, flags);
256 phy = bcm43xx_current_phy(bcm);
257
258 range->num_bitrates = 0;
259 i = 0;
260 if (phy->type == BCM43xx_PHYTYPE_A ||
261 phy->type == BCM43xx_PHYTYPE_G) {
262 range->num_bitrates = 8;
263 range->bitrate[i++] = IEEE80211_OFDM_RATE_6MB;
264 range->bitrate[i++] = IEEE80211_OFDM_RATE_9MB;
265 range->bitrate[i++] = IEEE80211_OFDM_RATE_12MB;
266 range->bitrate[i++] = IEEE80211_OFDM_RATE_18MB;
267 range->bitrate[i++] = IEEE80211_OFDM_RATE_24MB;
268 range->bitrate[i++] = IEEE80211_OFDM_RATE_36MB;
269 range->bitrate[i++] = IEEE80211_OFDM_RATE_48MB;
270 range->bitrate[i++] = IEEE80211_OFDM_RATE_54MB;
271 }
272 if (phy->type == BCM43xx_PHYTYPE_B ||
273 phy->type == BCM43xx_PHYTYPE_G) {
274 range->num_bitrates += 4;
275 range->bitrate[i++] = IEEE80211_CCK_RATE_1MB;
276 range->bitrate[i++] = IEEE80211_CCK_RATE_2MB;
277 range->bitrate[i++] = IEEE80211_CCK_RATE_5MB;
278 range->bitrate[i++] = IEEE80211_CCK_RATE_11MB;
279 }
280
281 geo = ieee80211_get_geo(bcm->ieee);
282 range->num_channels = geo->a_channels + geo->bg_channels;
283 j = 0;
284 for (i = 0; i < geo->a_channels; i++) {
285 if (j == IW_MAX_FREQUENCIES)
286 break;
287 range->freq[j].i = j + 1;
288 range->freq[j].m = geo->a[i].freq;//FIXME?
289 range->freq[j].e = 1;
290 j++;
291 }
292 for (i = 0; i < geo->bg_channels; i++) {
293 if (j == IW_MAX_FREQUENCIES)
294 break;
295 range->freq[j].i = j + 1;
296 range->freq[j].m = geo->bg[i].freq;//FIXME?
297 range->freq[j].e = 1;
298 j++;
299 }
300 range->num_frequency = j;
301
302 bcm43xx_unlock(bcm, flags);
303
304 return 0;
305}
306
307static int bcm43xx_wx_set_nick(struct net_device *net_dev,
308 struct iw_request_info *info,
309 union iwreq_data *data,
310 char *extra)
311{
312 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
313 unsigned long flags;
314 size_t len;
315
316 bcm43xx_lock(bcm, flags);
317 len = min((size_t)data->data.length, (size_t)IW_ESSID_MAX_SIZE);
318 memcpy(bcm->nick, extra, len);
319 bcm->nick[len] = '\0';
320 bcm43xx_unlock(bcm, flags);
321
322 return 0;
323}
324
325static int bcm43xx_wx_get_nick(struct net_device *net_dev,
326 struct iw_request_info *info,
327 union iwreq_data *data,
328 char *extra)
329{
330 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
331 unsigned long flags;
332 size_t len;
333
334 bcm43xx_lock(bcm, flags);
335 len = strlen(bcm->nick) + 1;
336 memcpy(extra, bcm->nick, len);
337 data->data.length = (__u16)len;
338 data->data.flags = 1;
339 bcm43xx_unlock(bcm, flags);
340
341 return 0;
342}
343
344static int bcm43xx_wx_set_rts(struct net_device *net_dev,
345 struct iw_request_info *info,
346 union iwreq_data *data,
347 char *extra)
348{
349 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
350 unsigned long flags;
351 int err = -EINVAL;
352
353 bcm43xx_lock(bcm, flags);
354 if (data->rts.disabled) {
355 bcm->rts_threshold = BCM43xx_MAX_RTS_THRESHOLD;
356 err = 0;
357 } else {
358 if (data->rts.value >= BCM43xx_MIN_RTS_THRESHOLD &&
359 data->rts.value <= BCM43xx_MAX_RTS_THRESHOLD) {
360 bcm->rts_threshold = data->rts.value;
361 err = 0;
362 }
363 }
364 bcm43xx_unlock(bcm, flags);
365
366 return err;
367}
368
369static int bcm43xx_wx_get_rts(struct net_device *net_dev,
370 struct iw_request_info *info,
371 union iwreq_data *data,
372 char *extra)
373{
374 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
375 unsigned long flags;
376
377 bcm43xx_lock(bcm, flags);
378 data->rts.value = bcm->rts_threshold;
379 data->rts.fixed = 0;
380 data->rts.disabled = (bcm->rts_threshold == BCM43xx_MAX_RTS_THRESHOLD);
381 bcm43xx_unlock(bcm, flags);
382
383 return 0;
384}
385
386static int bcm43xx_wx_set_frag(struct net_device *net_dev,
387 struct iw_request_info *info,
388 union iwreq_data *data,
389 char *extra)
390{
391 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
392 unsigned long flags;
393 int err = -EINVAL;
394
395 bcm43xx_lock(bcm, flags);
396 if (data->frag.disabled) {
397 bcm->ieee->fts = MAX_FRAG_THRESHOLD;
398 err = 0;
399 } else {
400 if (data->frag.value >= MIN_FRAG_THRESHOLD &&
401 data->frag.value <= MAX_FRAG_THRESHOLD) {
402 bcm->ieee->fts = data->frag.value & ~0x1;
403 err = 0;
404 }
405 }
406 bcm43xx_unlock(bcm, flags);
407
408 return err;
409}
410
411static int bcm43xx_wx_get_frag(struct net_device *net_dev,
412 struct iw_request_info *info,
413 union iwreq_data *data,
414 char *extra)
415{
416 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
417 unsigned long flags;
418
419 bcm43xx_lock(bcm, flags);
420 data->frag.value = bcm->ieee->fts;
421 data->frag.fixed = 0;
422 data->frag.disabled = (bcm->ieee->fts == MAX_FRAG_THRESHOLD);
423 bcm43xx_unlock(bcm, flags);
424
425 return 0;
426}
427
428static int bcm43xx_wx_set_xmitpower(struct net_device *net_dev,
429 struct iw_request_info *info,
430 union iwreq_data *data,
431 char *extra)
432{
433 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
434 struct bcm43xx_radioinfo *radio;
435 struct bcm43xx_phyinfo *phy;
436 unsigned long flags;
437 int err = -ENODEV;
438 u16 maxpower;
439
440 if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM) {
441 printk(PFX KERN_ERR "TX power not in dBm.\n");
442 return -EOPNOTSUPP;
443 }
444
445 bcm43xx_lock_mmio(bcm, flags);
446 if (!bcm->initialized)
447 goto out_unlock;
448 radio = bcm43xx_current_radio(bcm);
449 phy = bcm43xx_current_phy(bcm);
450 if (data->txpower.disabled != (!(radio->enabled))) {
451 if (data->txpower.disabled)
452 bcm43xx_radio_turn_off(bcm);
453 else
454 bcm43xx_radio_turn_on(bcm);
455 }
456 if (data->txpower.value > 0) {
457 /* desired and maxpower dBm values are in Q5.2 */
458 if (phy->type == BCM43xx_PHYTYPE_A)
459 maxpower = bcm->sprom.maxpower_aphy;
460 else
461 maxpower = bcm->sprom.maxpower_bgphy;
462 radio->txpower_desired = limit_value(data->txpower.value << 2,
463 0, maxpower);
464 bcm43xx_phy_xmitpower(bcm);
465 }
466 err = 0;
467
468out_unlock:
469 bcm43xx_unlock_mmio(bcm, flags);
470
471 return err;
472}
473
474static int bcm43xx_wx_get_xmitpower(struct net_device *net_dev,
475 struct iw_request_info *info,
476 union iwreq_data *data,
477 char *extra)
478{
479 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
480 struct bcm43xx_radioinfo *radio;
481 unsigned long flags;
482 int err = -ENODEV;
483
484 bcm43xx_lock(bcm, flags);
485 if (!bcm->initialized)
486 goto out_unlock;
487 radio = bcm43xx_current_radio(bcm);
488 /* desired dBm value is in Q5.2 */
489 data->txpower.value = radio->txpower_desired >> 2;
490 data->txpower.fixed = 1;
491 data->txpower.flags = IW_TXPOW_DBM;
492 data->txpower.disabled = !(radio->enabled);
493
494 err = 0;
495out_unlock:
496 bcm43xx_unlock(bcm, flags);
497
498 return err;
499}
500
501static int bcm43xx_wx_set_encoding(struct net_device *net_dev,
502 struct iw_request_info *info,
503 union iwreq_data *data,
504 char *extra)
505{
506 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
507 int err;
508
509 err = ieee80211_wx_set_encode(bcm->ieee, info, data, extra);
510
511 return err;
512}
513
514static int bcm43xx_wx_set_encodingext(struct net_device *net_dev,
515 struct iw_request_info *info,
516 union iwreq_data *data,
517 char *extra)
518{
519 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
520 int err;
521
522 err = ieee80211_wx_set_encodeext(bcm->ieee, info, data, extra);
523
524 return err;
525}
526
527static int bcm43xx_wx_get_encoding(struct net_device *net_dev,
528 struct iw_request_info *info,
529 union iwreq_data *data,
530 char *extra)
531{
532 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
533 int err;
534
535 err = ieee80211_wx_get_encode(bcm->ieee, info, data, extra);
536
537 return err;
538}
539
540static int bcm43xx_wx_get_encodingext(struct net_device *net_dev,
541 struct iw_request_info *info,
542 union iwreq_data *data,
543 char *extra)
544{
545 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
546 int err;
547
548 err = ieee80211_wx_get_encodeext(bcm->ieee, info, data, extra);
549
550 return err;
551}
552
553static int bcm43xx_wx_set_interfmode(struct net_device *net_dev,
554 struct iw_request_info *info,
555 union iwreq_data *data,
556 char *extra)
557{
558 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
559 unsigned long flags;
560 int mode, err = 0;
561
562 mode = *((int *)extra);
563 switch (mode) {
564 case 0:
565 mode = BCM43xx_RADIO_INTERFMODE_NONE;
566 break;
567 case 1:
568 mode = BCM43xx_RADIO_INTERFMODE_NONWLAN;
569 break;
570 case 2:
571 mode = BCM43xx_RADIO_INTERFMODE_MANUALWLAN;
572 break;
573 case 3:
574 mode = BCM43xx_RADIO_INTERFMODE_AUTOWLAN;
575 break;
576 default:
577 printk(KERN_ERR PFX "set_interfmode allowed parameters are: "
578 "0 => None, 1 => Non-WLAN, 2 => WLAN, "
579 "3 => Auto-WLAN\n");
580 return -EINVAL;
581 }
582
583 bcm43xx_lock_mmio(bcm, flags);
584 if (bcm->initialized) {
585 err = bcm43xx_radio_set_interference_mitigation(bcm, mode);
586 if (err) {
587 printk(KERN_ERR PFX "Interference Mitigation not "
588 "supported by device\n");
589 }
590 } else {
591 if (mode == BCM43xx_RADIO_INTERFMODE_AUTOWLAN) {
592 printk(KERN_ERR PFX "Interference Mitigation mode Auto-WLAN "
593 "not supported while the interface is down.\n");
594 err = -ENODEV;
595 } else
596 bcm43xx_current_radio(bcm)->interfmode = mode;
597 }
598 bcm43xx_unlock_mmio(bcm, flags);
599
600 return err;
601}
602
603static int bcm43xx_wx_get_interfmode(struct net_device *net_dev,
604 struct iw_request_info *info,
605 union iwreq_data *data,
606 char *extra)
607{
608 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
609 unsigned long flags;
610 int mode;
611
612 bcm43xx_lock(bcm, flags);
613 mode = bcm43xx_current_radio(bcm)->interfmode;
614 bcm43xx_unlock(bcm, flags);
615
616 switch (mode) {
617 case BCM43xx_RADIO_INTERFMODE_NONE:
618 strncpy(extra, "0 (No Interference Mitigation)", MAX_WX_STRING);
619 break;
620 case BCM43xx_RADIO_INTERFMODE_NONWLAN:
621 strncpy(extra, "1 (Non-WLAN Interference Mitigation)", MAX_WX_STRING);
622 break;
623 case BCM43xx_RADIO_INTERFMODE_MANUALWLAN:
624 strncpy(extra, "2 (WLAN Interference Mitigation)", MAX_WX_STRING);
625 break;
626 default:
627 assert(0);
628 }
629 data->data.length = strlen(extra) + 1;
630
631 return 0;
632}
633
634static int bcm43xx_wx_set_shortpreamble(struct net_device *net_dev,
635 struct iw_request_info *info,
636 union iwreq_data *data,
637 char *extra)
638{
639 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
640 unsigned long flags;
641 int on;
642
643 on = *((int *)extra);
644 bcm43xx_lock(bcm, flags);
645 bcm->short_preamble = !!on;
646 bcm43xx_unlock(bcm, flags);
647
648 return 0;
649}
650
651static int bcm43xx_wx_get_shortpreamble(struct net_device *net_dev,
652 struct iw_request_info *info,
653 union iwreq_data *data,
654 char *extra)
655{
656 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
657 unsigned long flags;
658 int on;
659
660 bcm43xx_lock(bcm, flags);
661 on = bcm->short_preamble;
662 bcm43xx_unlock(bcm, flags);
663
664 if (on)
665 strncpy(extra, "1 (Short Preamble enabled)", MAX_WX_STRING);
666 else
667 strncpy(extra, "0 (Short Preamble disabled)", MAX_WX_STRING);
668 data->data.length = strlen(extra) + 1;
669
670 return 0;
671}
672
673static int bcm43xx_wx_set_swencryption(struct net_device *net_dev,
674 struct iw_request_info *info,
675 union iwreq_data *data,
676 char *extra)
677{
678 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
679 unsigned long flags;
680 int on;
681
682 on = *((int *)extra);
683
684 bcm43xx_lock(bcm, flags);
685 bcm->ieee->host_encrypt = !!on;
686 bcm->ieee->host_decrypt = !!on;
687 bcm->ieee->host_build_iv = !on;
688 bcm43xx_unlock(bcm, flags);
689
690 return 0;
691}
692
693static int bcm43xx_wx_get_swencryption(struct net_device *net_dev,
694 struct iw_request_info *info,
695 union iwreq_data *data,
696 char *extra)
697{
698 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
699 unsigned long flags;
700 int on;
701
702 bcm43xx_lock(bcm, flags);
703 on = bcm->ieee->host_encrypt;
704 bcm43xx_unlock(bcm, flags);
705
706 if (on)
707 strncpy(extra, "1 (SW encryption enabled) ", MAX_WX_STRING);
708 else
709 strncpy(extra, "0 (SW encryption disabled) ", MAX_WX_STRING);
710 data->data.length = strlen(extra + 1);
711
712 return 0;
713}
714
715/* Enough buffer to hold a hexdump of the sprom data. */
716#define SPROM_BUFFERSIZE 512
717
718static int sprom2hex(const u16 *sprom, char *dump)
719{
720 int i, pos = 0;
721
722 for (i = 0; i < BCM43xx_SPROM_SIZE; i++) {
723 pos += snprintf(dump + pos, SPROM_BUFFERSIZE - pos - 1,
724 "%04X", swab16(sprom[i]) & 0xFFFF);
725 }
726
727 return pos + 1;
728}
729
730static int hex2sprom(u16 *sprom, const char *dump, unsigned int len)
731{
732 char tmp[5] = { 0 };
733 int cnt = 0;
734 unsigned long parsed;
735
736 if (len < BCM43xx_SPROM_SIZE * sizeof(u16) * 2)
737 return -EINVAL;
738 while (cnt < BCM43xx_SPROM_SIZE) {
739 memcpy(tmp, dump, 4);
740 dump += 4;
741 parsed = simple_strtoul(tmp, NULL, 16);
742 sprom[cnt++] = swab16((u16)parsed);
743 }
744
745 return 0;
746}
747
748static int bcm43xx_wx_sprom_read(struct net_device *net_dev,
749 struct iw_request_info *info,
750 union iwreq_data *data,
751 char *extra)
752{
753 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
754 int err = -EPERM;
755 u16 *sprom;
756 unsigned long flags;
757
758 if (!capable(CAP_SYS_RAWIO))
759 goto out;
760
761 err = -ENOMEM;
762 sprom = kmalloc(BCM43xx_SPROM_SIZE * sizeof(*sprom),
763 GFP_KERNEL);
764 if (!sprom)
765 goto out;
766
767 bcm43xx_lock_mmio(bcm, flags);
768 err = -ENODEV;
769 if (bcm->initialized)
770 err = bcm43xx_sprom_read(bcm, sprom);
771 bcm43xx_unlock_mmio(bcm, flags);
772 if (!err)
773 data->data.length = sprom2hex(sprom, extra);
774 kfree(sprom);
775out:
776 return err;
777}
778
779static int bcm43xx_wx_sprom_write(struct net_device *net_dev,
780 struct iw_request_info *info,
781 union iwreq_data *data,
782 char *extra)
783{
784 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
785 int err = -EPERM;
786 u16 *sprom;
787 unsigned long flags;
788 char *input;
789 unsigned int len;
790
791 if (!capable(CAP_SYS_RAWIO))
792 goto out;
793
794 err = -ENOMEM;
795 sprom = kmalloc(BCM43xx_SPROM_SIZE * sizeof(*sprom),
796 GFP_KERNEL);
797 if (!sprom)
798 goto out;
799
800 len = data->data.length;
801 extra[len - 1] = '\0';
802 input = strchr(extra, ':');
803 if (input) {
804 input++;
805 len -= input - extra;
806 } else
807 input = extra;
808 err = hex2sprom(sprom, input, len);
809 if (err)
810 goto out_kfree;
811
812 bcm43xx_lock_mmio(bcm, flags);
813 err = -ENODEV;
814 if (bcm->initialized)
815 err = bcm43xx_sprom_write(bcm, sprom);
816 bcm43xx_unlock_mmio(bcm, flags);
817out_kfree:
818 kfree(sprom);
819out:
820 return err;
821}
822
823/* Get wireless statistics. Called by /proc/net/wireless and by SIOCGIWSTATS */
824
825static struct iw_statistics *bcm43xx_get_wireless_stats(struct net_device *net_dev)
826{
827 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
828 struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
829 struct iw_statistics *wstats;
830
831 wstats = &bcm->stats.wstats;
832 if (!mac->associated) {
833 wstats->miss.beacon = 0;
834// bcm->ieee->ieee_stats.tx_retry_limit_exceeded = 0; // FIXME: should this be cleared here?
835 wstats->discard.retries = 0;
836// bcm->ieee->ieee_stats.tx_discards_wrong_sa = 0; // FIXME: same question
837 wstats->discard.nwid = 0;
838// bcm->ieee->ieee_stats.rx_discards_undecryptable = 0; // FIXME: ditto
839 wstats->discard.code = 0;
840// bcm->ieee->ieee_stats.rx_fragments = 0; // FIXME: same here
841 wstats->discard.fragment = 0;
842 wstats->discard.misc = 0;
843 wstats->qual.qual = 0;
844 wstats->qual.level = 0;
845 wstats->qual.noise = 0;
846 wstats->qual.updated = 7;
847 wstats->qual.updated |= IW_QUAL_NOISE_INVALID |
848 IW_QUAL_QUAL_INVALID | IW_QUAL_LEVEL_INVALID;
849 return wstats;
850 }
851 /* fill in the real statistics when iface associated */
852 wstats->qual.qual = 100; // TODO: get the real signal quality
853 wstats->qual.level = 3 - bcm->stats.link_quality;
854 wstats->qual.noise = bcm->stats.noise;
855 wstats->qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED |
856 IW_QUAL_NOISE_UPDATED;
857 wstats->discard.code = bcm->ieee->ieee_stats.rx_discards_undecryptable;
858 wstats->discard.retries = bcm->ieee->ieee_stats.tx_retry_limit_exceeded;
859 wstats->discard.nwid = bcm->ieee->ieee_stats.tx_discards_wrong_sa;
860 wstats->discard.fragment = bcm->ieee->ieee_stats.rx_fragments;
861 wstats->discard.misc = 0; // FIXME
862 wstats->miss.beacon = 0; // FIXME
863 return wstats;
864}
865
866
867#ifdef WX
868# undef WX
869#endif
870#define WX(ioctl) [(ioctl) - SIOCSIWCOMMIT]
871static const iw_handler bcm43xx_wx_handlers[] = {
872 /* Wireless Identification */
873 WX(SIOCGIWNAME) = bcm43xx_wx_get_name,
874 /* Basic operations */
875 WX(SIOCSIWFREQ) = bcm43xx_wx_set_channelfreq,
876 WX(SIOCGIWFREQ) = bcm43xx_wx_get_channelfreq,
877 WX(SIOCSIWMODE) = bcm43xx_wx_set_mode,
878 WX(SIOCGIWMODE) = bcm43xx_wx_get_mode,
879 /* Informative stuff */
880 WX(SIOCGIWRANGE) = bcm43xx_wx_get_rangeparams,
881 /* Access Point manipulation */
882 WX(SIOCSIWAP) = ieee80211softmac_wx_set_wap,
883 WX(SIOCGIWAP) = ieee80211softmac_wx_get_wap,
884 WX(SIOCSIWSCAN) = ieee80211softmac_wx_trigger_scan,
885 WX(SIOCGIWSCAN) = ieee80211softmac_wx_get_scan_results,
886 /* 802.11 specific support */
887 WX(SIOCSIWESSID) = ieee80211softmac_wx_set_essid,
888 WX(SIOCGIWESSID) = ieee80211softmac_wx_get_essid,
889 WX(SIOCSIWNICKN) = bcm43xx_wx_set_nick,
890 WX(SIOCGIWNICKN) = bcm43xx_wx_get_nick,
891 /* Other parameters */
892 WX(SIOCSIWRATE) = ieee80211softmac_wx_set_rate,
893 WX(SIOCGIWRATE) = ieee80211softmac_wx_get_rate,
894 WX(SIOCSIWRTS) = bcm43xx_wx_set_rts,
895 WX(SIOCGIWRTS) = bcm43xx_wx_get_rts,
896 WX(SIOCSIWFRAG) = bcm43xx_wx_set_frag,
897 WX(SIOCGIWFRAG) = bcm43xx_wx_get_frag,
898 WX(SIOCSIWTXPOW) = bcm43xx_wx_set_xmitpower,
899 WX(SIOCGIWTXPOW) = bcm43xx_wx_get_xmitpower,
900//TODO WX(SIOCSIWRETRY) = bcm43xx_wx_set_retry,
901//TODO WX(SIOCGIWRETRY) = bcm43xx_wx_get_retry,
902 /* Encoding */
903 WX(SIOCSIWENCODE) = bcm43xx_wx_set_encoding,
904 WX(SIOCGIWENCODE) = bcm43xx_wx_get_encoding,
905 WX(SIOCSIWENCODEEXT) = bcm43xx_wx_set_encodingext,
906 WX(SIOCGIWENCODEEXT) = bcm43xx_wx_get_encodingext,
907 /* Power saving */
908//TODO WX(SIOCSIWPOWER) = bcm43xx_wx_set_power,
909//TODO WX(SIOCGIWPOWER) = bcm43xx_wx_get_power,
910 WX(SIOCSIWGENIE) = ieee80211softmac_wx_set_genie,
911 WX(SIOCGIWGENIE) = ieee80211softmac_wx_get_genie,
912 WX(SIOCSIWAUTH) = ieee80211_wx_set_auth,
913 WX(SIOCGIWAUTH) = ieee80211_wx_get_auth,
914};
915#undef WX
916
917static const iw_handler bcm43xx_priv_wx_handlers[] = {
918 /* Set Interference Mitigation Mode. */
919 bcm43xx_wx_set_interfmode,
920 /* Get Interference Mitigation Mode. */
921 bcm43xx_wx_get_interfmode,
922 /* Enable/Disable Short Preamble mode. */
923 bcm43xx_wx_set_shortpreamble,
924 /* Get Short Preamble mode. */
925 bcm43xx_wx_get_shortpreamble,
926 /* Enable/Disable Software Encryption mode */
927 bcm43xx_wx_set_swencryption,
928 /* Get Software Encryption mode */
929 bcm43xx_wx_get_swencryption,
930 /* Write SRPROM data. */
931 bcm43xx_wx_sprom_write,
932 /* Read SPROM data. */
933 bcm43xx_wx_sprom_read,
934};
935
936#define PRIV_WX_SET_INTERFMODE (SIOCIWFIRSTPRIV + 0)
937#define PRIV_WX_GET_INTERFMODE (SIOCIWFIRSTPRIV + 1)
938#define PRIV_WX_SET_SHORTPREAMBLE (SIOCIWFIRSTPRIV + 2)
939#define PRIV_WX_GET_SHORTPREAMBLE (SIOCIWFIRSTPRIV + 3)
940#define PRIV_WX_SET_SWENCRYPTION (SIOCIWFIRSTPRIV + 4)
941#define PRIV_WX_GET_SWENCRYPTION (SIOCIWFIRSTPRIV + 5)
942#define PRIV_WX_SPROM_WRITE (SIOCIWFIRSTPRIV + 6)
943#define PRIV_WX_SPROM_READ (SIOCIWFIRSTPRIV + 7)
944
945#define PRIV_WX_DUMMY(ioctl) \
946 { \
947 .cmd = (ioctl), \
948 .name = "__unused" \
949 }
950
951static const struct iw_priv_args bcm43xx_priv_wx_args[] = {
952 {
953 .cmd = PRIV_WX_SET_INTERFMODE,
954 .set_args = IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
955 .name = "set_interfmode",
956 },
957 {
958 .cmd = PRIV_WX_GET_INTERFMODE,
959 .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
960 .name = "get_interfmode",
961 },
962 {
963 .cmd = PRIV_WX_SET_SHORTPREAMBLE,
964 .set_args = IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
965 .name = "set_shortpreambl",
966 },
967 {
968 .cmd = PRIV_WX_GET_SHORTPREAMBLE,
969 .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
970 .name = "get_shortpreambl",
971 },
972 {
973 .cmd = PRIV_WX_SET_SWENCRYPTION,
974 .set_args = IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
975 .name = "set_swencryption",
976 },
977 {
978 .cmd = PRIV_WX_GET_SWENCRYPTION,
979 .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
980 .name = "get_swencryption",
981 },
982 {
983 .cmd = PRIV_WX_SPROM_WRITE,
984 .set_args = IW_PRIV_TYPE_CHAR | SPROM_BUFFERSIZE,
985 .name = "write_sprom",
986 },
987 {
988 .cmd = PRIV_WX_SPROM_READ,
989 .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | SPROM_BUFFERSIZE,
990 .name = "read_sprom",
991 },
992};
993
994const struct iw_handler_def bcm43xx_wx_handlers_def = {
995 .standard = bcm43xx_wx_handlers,
996 .num_standard = ARRAY_SIZE(bcm43xx_wx_handlers),
997 .num_private = ARRAY_SIZE(bcm43xx_priv_wx_handlers),
998 .num_private_args = ARRAY_SIZE(bcm43xx_priv_wx_args),
999 .private = bcm43xx_priv_wx_handlers,
1000 .private_args = bcm43xx_priv_wx_args,
1001 .get_wireless_stats = bcm43xx_get_wireless_stats,
1002};
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.h b/drivers/net/wireless/bcm43xx/bcm43xx_wx.h
new file mode 100644
index 000000000000..1f29ff3aa4c3
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.h
@@ -0,0 +1,36 @@
1/*
2
3 Broadcom BCM43xx wireless driver
4
5 Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
6 Stefano Brivio <st3@riseup.net>
7 Michael Buesch <mbuesch@freenet.de>
8 Danny van Dyk <kugelfang@gentoo.org>
9 Andreas Jaggi <andreas.jaggi@waterwave.ch>
10
11 Some parts of the code in this file are derived from the ipw2200
12 driver Copyright(c) 2003 - 2004 Intel Corporation.
13
14 This program is free software; you can redistribute it and/or modify
15 it under the terms of the GNU General Public License as published by
16 the Free Software Foundation; either version 2 of the License, or
17 (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; see the file COPYING. If not, write to
26 the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
27 Boston, MA 02110-1301, USA.
28
29*/
30
31#ifndef BCM43xx_WX_H_
32#define BCM43xx_WX_H_
33
34extern const struct iw_handler_def bcm43xx_wx_handlers_def;
35
36#endif /* BCM43xx_WX_H_ */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c
new file mode 100644
index 000000000000..d8ece28c079f
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c
@@ -0,0 +1,582 @@
1/*
2
3 Broadcom BCM43xx wireless driver
4
5 Transmission (TX/RX) related functions.
6
7 Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
8 Stefano Brivio <st3@riseup.net>
9 Michael Buesch <mbuesch@freenet.de>
10 Danny van Dyk <kugelfang@gentoo.org>
11 Andreas Jaggi <andreas.jaggi@waterwave.ch>
12
13 This program is free software; you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation; either version 2 of the License, or
16 (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; see the file COPYING. If not, write to
25 the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
26 Boston, MA 02110-1301, USA.
27
28*/
29
30#include "bcm43xx_xmit.h"
31
32#include <linux/etherdevice.h>
33
34
35/* Extract the bitrate out of a CCK PLCP header. */
36static u8 bcm43xx_plcp_get_bitrate_cck(struct bcm43xx_plcp_hdr4 *plcp)
37{
38 switch (plcp->raw[0]) {
39 case 0x0A:
40 return IEEE80211_CCK_RATE_1MB;
41 case 0x14:
42 return IEEE80211_CCK_RATE_2MB;
43 case 0x37:
44 return IEEE80211_CCK_RATE_5MB;
45 case 0x6E:
46 return IEEE80211_CCK_RATE_11MB;
47 }
48 assert(0);
49 return 0;
50}
51
52/* Extract the bitrate out of an OFDM PLCP header. */
53static u8 bcm43xx_plcp_get_bitrate_ofdm(struct bcm43xx_plcp_hdr4 *plcp)
54{
55 switch (plcp->raw[0] & 0xF) {
56 case 0xB:
57 return IEEE80211_OFDM_RATE_6MB;
58 case 0xF:
59 return IEEE80211_OFDM_RATE_9MB;
60 case 0xA:
61 return IEEE80211_OFDM_RATE_12MB;
62 case 0xE:
63 return IEEE80211_OFDM_RATE_18MB;
64 case 0x9:
65 return IEEE80211_OFDM_RATE_24MB;
66 case 0xD:
67 return IEEE80211_OFDM_RATE_36MB;
68 case 0x8:
69 return IEEE80211_OFDM_RATE_48MB;
70 case 0xC:
71 return IEEE80211_OFDM_RATE_54MB;
72 }
73 assert(0);
74 return 0;
75}
76
77u8 bcm43xx_plcp_get_ratecode_cck(const u8 bitrate)
78{
79 switch (bitrate) {
80 case IEEE80211_CCK_RATE_1MB:
81 return 0x0A;
82 case IEEE80211_CCK_RATE_2MB:
83 return 0x14;
84 case IEEE80211_CCK_RATE_5MB:
85 return 0x37;
86 case IEEE80211_CCK_RATE_11MB:
87 return 0x6E;
88 }
89 assert(0);
90 return 0;
91}
92
93u8 bcm43xx_plcp_get_ratecode_ofdm(const u8 bitrate)
94{
95 switch (bitrate) {
96 case IEEE80211_OFDM_RATE_6MB:
97 return 0xB;
98 case IEEE80211_OFDM_RATE_9MB:
99 return 0xF;
100 case IEEE80211_OFDM_RATE_12MB:
101 return 0xA;
102 case IEEE80211_OFDM_RATE_18MB:
103 return 0xE;
104 case IEEE80211_OFDM_RATE_24MB:
105 return 0x9;
106 case IEEE80211_OFDM_RATE_36MB:
107 return 0xD;
108 case IEEE80211_OFDM_RATE_48MB:
109 return 0x8;
110 case IEEE80211_OFDM_RATE_54MB:
111 return 0xC;
112 }
113 assert(0);
114 return 0;
115}
116
117static void bcm43xx_generate_plcp_hdr(struct bcm43xx_plcp_hdr4 *plcp,
118 const u16 octets, const u8 bitrate,
119 const int ofdm_modulation)
120{
121 __le32 *data = &(plcp->data);
122 __u8 *raw = plcp->raw;
123
124 if (ofdm_modulation) {
125 *data = bcm43xx_plcp_get_ratecode_ofdm(bitrate);
126 assert(!(octets & 0xF000));
127 *data |= (octets << 5);
128 *data = cpu_to_le32(*data);
129 } else {
130 u32 plen;
131
132 plen = octets * 16 / bitrate;
133 if ((octets * 16 % bitrate) > 0) {
134 plen++;
135 if ((bitrate == IEEE80211_CCK_RATE_11MB)
136 && ((octets * 8 % 11) < 4)) {
137 raw[1] = 0x84;
138 } else
139 raw[1] = 0x04;
140 } else
141 raw[1] = 0x04;
142 *data |= cpu_to_le32(plen << 16);
143 raw[0] = bcm43xx_plcp_get_ratecode_cck(bitrate);
144 }
145}
146
147static u8 bcm43xx_calc_fallback_rate(u8 bitrate)
148{
149 switch (bitrate) {
150 case IEEE80211_CCK_RATE_1MB:
151 return IEEE80211_CCK_RATE_1MB;
152 case IEEE80211_CCK_RATE_2MB:
153 return IEEE80211_CCK_RATE_1MB;
154 case IEEE80211_CCK_RATE_5MB:
155 return IEEE80211_CCK_RATE_2MB;
156 case IEEE80211_CCK_RATE_11MB:
157 return IEEE80211_CCK_RATE_5MB;
158 case IEEE80211_OFDM_RATE_6MB:
159 return IEEE80211_CCK_RATE_5MB;
160 case IEEE80211_OFDM_RATE_9MB:
161 return IEEE80211_OFDM_RATE_6MB;
162 case IEEE80211_OFDM_RATE_12MB:
163 return IEEE80211_OFDM_RATE_9MB;
164 case IEEE80211_OFDM_RATE_18MB:
165 return IEEE80211_OFDM_RATE_12MB;
166 case IEEE80211_OFDM_RATE_24MB:
167 return IEEE80211_OFDM_RATE_18MB;
168 case IEEE80211_OFDM_RATE_36MB:
169 return IEEE80211_OFDM_RATE_24MB;
170 case IEEE80211_OFDM_RATE_48MB:
171 return IEEE80211_OFDM_RATE_36MB;
172 case IEEE80211_OFDM_RATE_54MB:
173 return IEEE80211_OFDM_RATE_48MB;
174 }
175 assert(0);
176 return 0;
177}
178
179static
180__le16 bcm43xx_calc_duration_id(const struct ieee80211_hdr *wireless_header,
181 u8 bitrate)
182{
183 const u16 frame_ctl = le16_to_cpu(wireless_header->frame_ctl);
184 __le16 duration_id = wireless_header->duration_id;
185
186 switch (WLAN_FC_GET_TYPE(frame_ctl)) {
187 case IEEE80211_FTYPE_DATA:
188 case IEEE80211_FTYPE_MGMT:
189 //TODO: Steal the code from ieee80211, once it is completed there.
190 break;
191 case IEEE80211_FTYPE_CTL:
192 /* Use the original duration/id. */
193 break;
194 default:
195 assert(0);
196 }
197
198 return duration_id;
199}
200
201static inline
202u16 ceiling_div(u16 dividend, u16 divisor)
203{
204 return ((dividend + divisor - 1) / divisor);
205}
206
207static void bcm43xx_generate_rts(const struct bcm43xx_phyinfo *phy,
208 struct bcm43xx_txhdr *txhdr,
209 u16 *flags,
210 u8 bitrate,
211 const struct ieee80211_hdr_4addr *wlhdr)
212{
213 u16 fctl;
214 u16 dur;
215 u8 fallback_bitrate;
216 int ofdm_modulation;
217 int fallback_ofdm_modulation;
218// u8 *sa, *da;
219 u16 flen;
220
221//FIXME sa = ieee80211_get_SA((struct ieee80211_hdr *)wlhdr);
222//FIXME da = ieee80211_get_DA((struct ieee80211_hdr *)wlhdr);
223 fallback_bitrate = bcm43xx_calc_fallback_rate(bitrate);
224 ofdm_modulation = !(ieee80211_is_cck_rate(bitrate));
225 fallback_ofdm_modulation = !(ieee80211_is_cck_rate(fallback_bitrate));
226
227 flen = sizeof(u16) + sizeof(u16) + ETH_ALEN + ETH_ALEN + IEEE80211_FCS_LEN,
228 bcm43xx_generate_plcp_hdr((struct bcm43xx_plcp_hdr4 *)(&txhdr->rts_cts_plcp),
229 flen, bitrate,
230 !ieee80211_is_cck_rate(bitrate));
231 bcm43xx_generate_plcp_hdr((struct bcm43xx_plcp_hdr4 *)(&txhdr->rts_cts_fallback_plcp),
232 flen, fallback_bitrate,
233 !ieee80211_is_cck_rate(fallback_bitrate));
234 fctl = IEEE80211_FTYPE_CTL;
235 fctl |= IEEE80211_STYPE_RTS;
236 dur = le16_to_cpu(wlhdr->duration_id);
237/*FIXME: should we test for dur==0 here and let it unmodified in this case?
238 * The following assert checks for this case...
239 */
240assert(dur);
241/*FIXME: The duration calculation is not really correct.
242 * I am not 100% sure which bitrate to use. We use the RTS rate here,
243 * but this is likely to be wrong.
244 */
245 if (phy->type == BCM43xx_PHYTYPE_A) {
246 /* Three times SIFS */
247 dur += 16 * 3;
248 /* Add ACK duration. */
249 dur += ceiling_div((16 + 8 * (14 /*bytes*/) + 6) * 10,
250 bitrate * 4);
251 /* Add CTS duration. */
252 dur += ceiling_div((16 + 8 * (14 /*bytes*/) + 6) * 10,
253 bitrate * 4);
254 } else {
255 /* Three times SIFS */
256 dur += 10 * 3;
257 /* Add ACK duration. */
258 dur += ceiling_div(8 * (14 /*bytes*/) * 10,
259 bitrate);
260 /* Add CTS duration. */
261 dur += ceiling_div(8 * (14 /*bytes*/) * 10,
262 bitrate);
263 }
264
265 txhdr->rts_cts_frame_control = cpu_to_le16(fctl);
266 txhdr->rts_cts_dur = cpu_to_le16(dur);
267//printk(BCM43xx_MACFMT " " BCM43xx_MACFMT " " BCM43xx_MACFMT "\n", BCM43xx_MACARG(wlhdr->addr1), BCM43xx_MACARG(wlhdr->addr2), BCM43xx_MACARG(wlhdr->addr3));
268//printk(BCM43xx_MACFMT " " BCM43xx_MACFMT "\n", BCM43xx_MACARG(sa), BCM43xx_MACARG(da));
269 memcpy(txhdr->rts_cts_mac1, wlhdr->addr1, ETH_ALEN);//FIXME!
270// memcpy(txhdr->rts_cts_mac2, sa, ETH_ALEN);
271
272 *flags |= BCM43xx_TXHDRFLAG_RTSCTS;
273 *flags |= BCM43xx_TXHDRFLAG_RTS;
274 if (ofdm_modulation)
275 *flags |= BCM43xx_TXHDRFLAG_RTSCTS_OFDM;
276 if (fallback_ofdm_modulation)
277 *flags |= BCM43xx_TXHDRFLAG_RTSCTSFALLBACK_OFDM;
278}
279
280void bcm43xx_generate_txhdr(struct bcm43xx_private *bcm,
281 struct bcm43xx_txhdr *txhdr,
282 const unsigned char *fragment_data,
283 const unsigned int fragment_len,
284 const int is_first_fragment,
285 const u16 cookie)
286{
287 const struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
288 const struct ieee80211_hdr_4addr *wireless_header = (const struct ieee80211_hdr_4addr *)fragment_data;
289 const struct ieee80211_security *secinfo = &bcm->ieee->sec;
290 u8 bitrate;
291 u8 fallback_bitrate;
292 int ofdm_modulation;
293 int fallback_ofdm_modulation;
294 u16 plcp_fragment_len = fragment_len;
295 u16 flags = 0;
296 u16 control = 0;
297 u16 wsec_rate = 0;
298 u16 encrypt_frame;
299
300 /* Now construct the TX header. */
301 memset(txhdr, 0, sizeof(*txhdr));
302
303 bitrate = bcm->softmac->txrates.default_rate;
304 ofdm_modulation = !(ieee80211_is_cck_rate(bitrate));
305 fallback_bitrate = bcm43xx_calc_fallback_rate(bitrate);
306 fallback_ofdm_modulation = !(ieee80211_is_cck_rate(fallback_bitrate));
307
308 /* Set Frame Control from 80211 header. */
309 txhdr->frame_control = wireless_header->frame_ctl;
310 /* Copy address1 from 80211 header. */
311 memcpy(txhdr->mac1, wireless_header->addr1, 6);
312 /* Set the fallback duration ID. */
313 txhdr->fallback_dur_id = bcm43xx_calc_duration_id((const struct ieee80211_hdr *)wireless_header,
314 fallback_bitrate);
315 /* Set the cookie (used as driver internal ID for the frame) */
316 txhdr->cookie = cpu_to_le16(cookie);
317
318 /* Hardware appends FCS. */
319 plcp_fragment_len += IEEE80211_FCS_LEN;
320
321 /* Hardware encryption. */
322 encrypt_frame = le16_to_cpup(&wireless_header->frame_ctl) & IEEE80211_FCTL_PROTECTED;
323 if (encrypt_frame && !bcm->ieee->host_encrypt) {
324 const struct ieee80211_hdr_3addr *hdr = (struct ieee80211_hdr_3addr *)wireless_header;
325 memcpy(txhdr->wep_iv, hdr->payload, 4);
326 /* Hardware appends ICV. */
327 plcp_fragment_len += 4;
328
329 wsec_rate |= (bcm->key[secinfo->active_key].algorithm << BCM43xx_TXHDR_WSEC_ALGO_SHIFT)
330 & BCM43xx_TXHDR_WSEC_ALGO_MASK;
331 wsec_rate |= (secinfo->active_key << BCM43xx_TXHDR_WSEC_KEYINDEX_SHIFT)
332 & BCM43xx_TXHDR_WSEC_KEYINDEX_MASK;
333 }
334
335 /* Generate the PLCP header and the fallback PLCP header. */
336 bcm43xx_generate_plcp_hdr((struct bcm43xx_plcp_hdr4 *)(&txhdr->plcp),
337 plcp_fragment_len,
338 bitrate, ofdm_modulation);
339 bcm43xx_generate_plcp_hdr(&txhdr->fallback_plcp, plcp_fragment_len,
340 fallback_bitrate, fallback_ofdm_modulation);
341
342 /* Set the CONTROL field */
343 if (ofdm_modulation)
344 control |= BCM43xx_TXHDRCTL_OFDM;
345 if (bcm->short_preamble) //FIXME: could be the other way around, please test
346 control |= BCM43xx_TXHDRCTL_SHORT_PREAMBLE;
347 control |= (phy->antenna_diversity << BCM43xx_TXHDRCTL_ANTENNADIV_SHIFT)
348 & BCM43xx_TXHDRCTL_ANTENNADIV_MASK;
349
350 /* Set the FLAGS field */
351 if (!is_multicast_ether_addr(wireless_header->addr1) &&
352 !is_broadcast_ether_addr(wireless_header->addr1))
353 flags |= BCM43xx_TXHDRFLAG_EXPECTACK;
354 if (1 /* FIXME: PS poll?? */)
355 flags |= 0x10; // FIXME: unknown meaning.
356 if (fallback_ofdm_modulation)
357 flags |= BCM43xx_TXHDRFLAG_FALLBACKOFDM;
358 if (is_first_fragment)
359 flags |= BCM43xx_TXHDRFLAG_FIRSTFRAGMENT;
360
361 /* Set WSEC/RATE field */
362 wsec_rate |= (txhdr->plcp.raw[0] << BCM43xx_TXHDR_RATE_SHIFT)
363 & BCM43xx_TXHDR_RATE_MASK;
364
365 /* Generate the RTS/CTS packet, if required. */
366 /* FIXME: We should first try with CTS-to-self,
367 * if we are on 80211g. If we get too many
368 * failures (hidden nodes), we should switch back to RTS/CTS.
369 */
370 if (0/*FIXME txctl->use_rts_cts*/) {
371 bcm43xx_generate_rts(phy, txhdr, &flags,
372 0/*FIXME txctl->rts_cts_rate*/,
373 wireless_header);
374 }
375
376 txhdr->flags = cpu_to_le16(flags);
377 txhdr->control = cpu_to_le16(control);
378 txhdr->wsec_rate = cpu_to_le16(wsec_rate);
379}
380
381static s8 bcm43xx_rssi_postprocess(struct bcm43xx_private *bcm,
382 u8 in_rssi, int ofdm,
383 int adjust_2053, int adjust_2050)
384{
385 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
386 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
387 s32 tmp;
388
389 switch (radio->version) {
390 case 0x2050:
391 if (ofdm) {
392 tmp = in_rssi;
393 if (tmp > 127)
394 tmp -= 256;
395 tmp *= 73;
396 tmp /= 64;
397 if (adjust_2050)
398 tmp += 25;
399 else
400 tmp -= 3;
401 } else {
402 if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) {
403 if (in_rssi > 63)
404 in_rssi = 63;
405 tmp = radio->nrssi_lt[in_rssi];
406 tmp = 31 - tmp;
407 tmp *= -131;
408 tmp /= 128;
409 tmp -= 57;
410 } else {
411 tmp = in_rssi;
412 tmp = 31 - tmp;
413 tmp *= -149;
414 tmp /= 128;
415 tmp -= 68;
416 }
417 if (phy->type == BCM43xx_PHYTYPE_G &&
418 adjust_2050)
419 tmp += 25;
420 }
421 break;
422 case 0x2060:
423 if (in_rssi > 127)
424 tmp = in_rssi - 256;
425 else
426 tmp = in_rssi;
427 break;
428 default:
429 tmp = in_rssi;
430 tmp -= 11;
431 tmp *= 103;
432 tmp /= 64;
433 if (adjust_2053)
434 tmp -= 109;
435 else
436 tmp -= 83;
437 }
438
439 return (s8)tmp;
440}
441
442//TODO
443#if 0
444static s8 bcm43xx_rssinoise_postprocess(struct bcm43xx_private *bcm,
445 u8 in_rssi)
446{
447 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
448 s8 ret;
449
450 if (phy->type == BCM43xx_PHYTYPE_A) {
451 //TODO: Incomplete specs.
452 ret = 0;
453 } else
454 ret = bcm43xx_rssi_postprocess(bcm, in_rssi, 0, 1, 1);
455
456 return ret;
457}
458#endif
459
460int bcm43xx_rx(struct bcm43xx_private *bcm,
461 struct sk_buff *skb,
462 struct bcm43xx_rxhdr *rxhdr)
463{
464 struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
465 struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
466 struct bcm43xx_plcp_hdr4 *plcp;
467 struct ieee80211_rx_stats stats;
468 struct ieee80211_hdr_4addr *wlhdr;
469 u16 frame_ctl;
470 int is_packet_for_us = 0;
471 int err = -EINVAL;
472 const u16 rxflags1 = le16_to_cpu(rxhdr->flags1);
473 const u16 rxflags2 = le16_to_cpu(rxhdr->flags2);
474 const u16 rxflags3 = le16_to_cpu(rxhdr->flags3);
475 const int is_ofdm = !!(rxflags1 & BCM43xx_RXHDR_FLAGS1_OFDM);
476
477 if (rxflags2 & BCM43xx_RXHDR_FLAGS2_TYPE2FRAME) {
478 plcp = (struct bcm43xx_plcp_hdr4 *)(skb->data + 2);
479 /* Skip two unknown bytes and the PLCP header. */
480 skb_pull(skb, 2 + sizeof(struct bcm43xx_plcp_hdr6));
481 } else {
482 plcp = (struct bcm43xx_plcp_hdr4 *)(skb->data);
483 /* Skip the PLCP header. */
484 skb_pull(skb, sizeof(struct bcm43xx_plcp_hdr6));
485 }
486 /* The SKB contains the PAYLOAD (wireless header + data)
487 * at this point. The FCS at the end is stripped.
488 */
489
490 memset(&stats, 0, sizeof(stats));
491 stats.mac_time = le16_to_cpu(rxhdr->mactime);
492 stats.rssi = bcm43xx_rssi_postprocess(bcm, rxhdr->rssi, is_ofdm,
493 !!(rxflags1 & BCM43xx_RXHDR_FLAGS1_2053RSSIADJ),
494 !!(rxflags3 & BCM43xx_RXHDR_FLAGS3_2050RSSIADJ));
495 stats.signal = rxhdr->signal_quality; //FIXME
496//TODO stats.noise =
497 if (is_ofdm)
498 stats.rate = bcm43xx_plcp_get_bitrate_ofdm(plcp);
499 else
500 stats.rate = bcm43xx_plcp_get_bitrate_cck(plcp);
501//printk("RX ofdm %d, rate == %u\n", is_ofdm, stats.rate);
502 stats.received_channel = radio->channel;
503//TODO stats.control =
504 stats.mask = IEEE80211_STATMASK_SIGNAL |
505//TODO IEEE80211_STATMASK_NOISE |
506 IEEE80211_STATMASK_RATE |
507 IEEE80211_STATMASK_RSSI;
508 if (phy->type == BCM43xx_PHYTYPE_A)
509 stats.freq = IEEE80211_52GHZ_BAND;
510 else
511 stats.freq = IEEE80211_24GHZ_BAND;
512 stats.len = skb->len;
513
514 bcm->stats.last_rx = jiffies;
515 if (bcm->ieee->iw_mode == IW_MODE_MONITOR) {
516 err = ieee80211_rx(bcm->ieee, skb, &stats);
517 return (err == 0) ? -EINVAL : 0;
518 }
519
520 wlhdr = (struct ieee80211_hdr_4addr *)(skb->data);
521
522 switch (bcm->ieee->iw_mode) {
523 case IW_MODE_ADHOC:
524 if (memcmp(wlhdr->addr1, bcm->net_dev->dev_addr, ETH_ALEN) == 0 ||
525 memcmp(wlhdr->addr3, bcm->ieee->bssid, ETH_ALEN) == 0 ||
526 is_broadcast_ether_addr(wlhdr->addr1) ||
527 is_multicast_ether_addr(wlhdr->addr1) ||
528 bcm->net_dev->flags & IFF_PROMISC)
529 is_packet_for_us = 1;
530 break;
531 case IW_MODE_INFRA:
532 default:
533 /* When receiving multicast or broadcast packets, filter out
534 the packets we send ourself; we shouldn't see those */
535 if (memcmp(wlhdr->addr3, bcm->ieee->bssid, ETH_ALEN) == 0 ||
536 memcmp(wlhdr->addr1, bcm->net_dev->dev_addr, ETH_ALEN) == 0 ||
537 (memcmp(wlhdr->addr3, bcm->net_dev->dev_addr, ETH_ALEN) &&
538 (is_broadcast_ether_addr(wlhdr->addr1) ||
539 is_multicast_ether_addr(wlhdr->addr1) ||
540 bcm->net_dev->flags & IFF_PROMISC)))
541 is_packet_for_us = 1;
542 break;
543 }
544
545 frame_ctl = le16_to_cpu(wlhdr->frame_ctl);
546 if ((frame_ctl & IEEE80211_FCTL_PROTECTED) && !bcm->ieee->host_decrypt) {
547 frame_ctl &= ~IEEE80211_FCTL_PROTECTED;
548 wlhdr->frame_ctl = cpu_to_le16(frame_ctl);
549 /* trim IV and ICV */
550 /* FIXME: this must be done only for WEP encrypted packets */
551 if (skb->len < 32) {
552 dprintkl(KERN_ERR PFX "RX packet dropped (PROTECTED flag "
553 "set and length < 32)\n");
554 return -EINVAL;
555 } else {
556 memmove(skb->data + 4, skb->data, 24);
557 skb_pull(skb, 4);
558 skb_trim(skb, skb->len - 4);
559 stats.len -= 8;
560 }
561 wlhdr = (struct ieee80211_hdr_4addr *)(skb->data);
562 }
563
564 switch (WLAN_FC_GET_TYPE(frame_ctl)) {
565 case IEEE80211_FTYPE_MGMT:
566 ieee80211_rx_mgt(bcm->ieee, wlhdr, &stats);
567 break;
568 case IEEE80211_FTYPE_DATA:
569 if (is_packet_for_us) {
570 err = ieee80211_rx(bcm->ieee, skb, &stats);
571 err = (err == 0) ? -EINVAL : 0;
572 }
573 break;
574 case IEEE80211_FTYPE_CTL:
575 break;
576 default:
577 assert(0);
578 return -EINVAL;
579 }
580
581 return err;
582}
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.h b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.h
new file mode 100644
index 000000000000..2aed19e35c77
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.h
@@ -0,0 +1,156 @@
1#ifndef BCM43xx_XMIT_H_
2#define BCM43xx_XMIT_H_
3
4#include "bcm43xx_main.h"
5
6
7#define _bcm43xx_declare_plcp_hdr(size) \
8 struct bcm43xx_plcp_hdr##size { \
9 union { \
10 __le32 data; \
11 __u8 raw[size]; \
12 } __attribute__((__packed__)); \
13 } __attribute__((__packed__))
14
15/* struct bcm43xx_plcp_hdr4 */
16_bcm43xx_declare_plcp_hdr(4);
17/* struct bcm43xx_plcp_hdr6 */
18_bcm43xx_declare_plcp_hdr(6);
19
20#undef _bcm43xx_declare_plcp_hdr
21
22/* Device specific TX header. To be prepended to TX frames. */
23struct bcm43xx_txhdr {
24 union {
25 struct {
26 __le16 flags;
27 __le16 wsec_rate;
28 __le16 frame_control;
29 u16 unknown_zeroed_0;
30 __le16 control;
31 u8 wep_iv[10];
32 u8 unknown_wsec_tkip_data[3]; //FIXME
33 PAD_BYTES(3);
34 u8 mac1[6];
35 u16 unknown_zeroed_1;
36 struct bcm43xx_plcp_hdr4 rts_cts_fallback_plcp;
37 __le16 rts_cts_dur_fallback;
38 struct bcm43xx_plcp_hdr4 fallback_plcp;
39 __le16 fallback_dur_id;
40 PAD_BYTES(2);
41 __le16 cookie;
42 __le16 unknown_scb_stuff; //FIXME
43 struct bcm43xx_plcp_hdr6 rts_cts_plcp;
44 __le16 rts_cts_frame_control;
45 __le16 rts_cts_dur;
46 u8 rts_cts_mac1[6];
47 u8 rts_cts_mac2[6];
48 PAD_BYTES(2);
49 struct bcm43xx_plcp_hdr6 plcp;
50 } __attribute__((__packed__));
51 u8 raw[82];
52 } __attribute__((__packed__));
53} __attribute__((__packed__));
54
55/* Values/Masks for the device TX header */
56#define BCM43xx_TXHDRFLAG_EXPECTACK 0x0001
57#define BCM43xx_TXHDRFLAG_RTSCTS 0x0002
58#define BCM43xx_TXHDRFLAG_RTS 0x0004
59#define BCM43xx_TXHDRFLAG_FIRSTFRAGMENT 0x0008
60#define BCM43xx_TXHDRFLAG_DESTPSMODE 0x0020
61#define BCM43xx_TXHDRFLAG_RTSCTS_OFDM 0x0080
62#define BCM43xx_TXHDRFLAG_FALLBACKOFDM 0x0100
63#define BCM43xx_TXHDRFLAG_RTSCTSFALLBACK_OFDM 0x0200
64#define BCM43xx_TXHDRFLAG_CTS 0x0400
65#define BCM43xx_TXHDRFLAG_FRAMEBURST 0x0800
66
67#define BCM43xx_TXHDRCTL_OFDM 0x0001
68#define BCM43xx_TXHDRCTL_SHORT_PREAMBLE 0x0010
69#define BCM43xx_TXHDRCTL_ANTENNADIV_MASK 0x0030
70#define BCM43xx_TXHDRCTL_ANTENNADIV_SHIFT 8
71
72#define BCM43xx_TXHDR_RATE_MASK 0x0F00
73#define BCM43xx_TXHDR_RATE_SHIFT 8
74#define BCM43xx_TXHDR_RTSRATE_MASK 0xF000
75#define BCM43xx_TXHDR_RTSRATE_SHIFT 12
76#define BCM43xx_TXHDR_WSEC_KEYINDEX_MASK 0x00F0
77#define BCM43xx_TXHDR_WSEC_KEYINDEX_SHIFT 4
78#define BCM43xx_TXHDR_WSEC_ALGO_MASK 0x0003
79#define BCM43xx_TXHDR_WSEC_ALGO_SHIFT 0
80
81void bcm43xx_generate_txhdr(struct bcm43xx_private *bcm,
82 struct bcm43xx_txhdr *txhdr,
83 const unsigned char *fragment_data,
84 const unsigned int fragment_len,
85 const int is_first_fragment,
86 const u16 cookie);
87
88/* RX header as received from the hardware. */
89struct bcm43xx_rxhdr {
90 /* Frame Length. Must be generated explicitely in PIO mode. */
91 __le16 frame_length;
92 PAD_BYTES(2);
93 /* Flags field 1 */
94 __le16 flags1;
95 u8 rssi;
96 u8 signal_quality;
97 PAD_BYTES(2);
98 /* Flags field 3 */
99 __le16 flags3;
100 /* Flags field 2 */
101 __le16 flags2;
102 /* Lower 16bits of the TSF at the time the frame started. */
103 __le16 mactime;
104 PAD_BYTES(14);
105} __attribute__((__packed__));
106
107#define BCM43xx_RXHDR_FLAGS1_OFDM (1 << 0)
108/*#define BCM43xx_RXHDR_FLAGS1_SIGNAL??? (1 << 3) FIXME */
109#define BCM43xx_RXHDR_FLAGS1_SHORTPREAMBLE (1 << 7)
110#define BCM43xx_RXHDR_FLAGS1_2053RSSIADJ (1 << 14)
111
112#define BCM43xx_RXHDR_FLAGS2_INVALIDFRAME (1 << 0)
113#define BCM43xx_RXHDR_FLAGS2_TYPE2FRAME (1 << 2)
114/*FIXME: WEP related flags */
115
116#define BCM43xx_RXHDR_FLAGS3_2050RSSIADJ (1 << 10)
117
118/* Transmit Status as received from the hardware. */
119struct bcm43xx_hwxmitstatus {
120 PAD_BYTES(4);
121 __le16 cookie;
122 u8 flags;
123 u8 cnt1:4,
124 cnt2:4;
125 PAD_BYTES(2);
126 __le16 seq;
127 __le16 unknown; //FIXME
128} __attribute__((__packed__));
129
130/* Transmit Status in CPU byteorder. */
131struct bcm43xx_xmitstatus {
132 u16 cookie;
133 u8 flags;
134 u8 cnt1:4,
135 cnt2:4;
136 u16 seq;
137 u16 unknown; //FIXME
138};
139
140#define BCM43xx_TXSTAT_FLAG_ACK 0x01
141//TODO #define BCM43xx_TXSTAT_FLAG_??? 0x02
142//TODO #define BCM43xx_TXSTAT_FLAG_??? 0x04
143//TODO #define BCM43xx_TXSTAT_FLAG_??? 0x08
144//TODO #define BCM43xx_TXSTAT_FLAG_??? 0x10
145#define BCM43xx_TXSTAT_FLAG_IGNORE 0x20
146//TODO #define BCM43xx_TXSTAT_FLAG_??? 0x40
147//TODO #define BCM43xx_TXSTAT_FLAG_??? 0x80
148
149u8 bcm43xx_plcp_get_ratecode_cck(const u8 bitrate);
150u8 bcm43xx_plcp_get_ratecode_ofdm(const u8 bitrate);
151
152int bcm43xx_rx(struct bcm43xx_private *bcm,
153 struct sk_buff *skb,
154 struct bcm43xx_rxhdr *rxhdr);
155
156#endif /* BCM43xx_XMIT_H_ */
diff --git a/drivers/net/wireless/hostap/hostap_80211.h b/drivers/net/wireless/hostap/hostap_80211.h
index 1fc72fe511e9..cc1ee7f4f5f8 100644
--- a/drivers/net/wireless/hostap/hostap_80211.h
+++ b/drivers/net/wireless/hostap/hostap_80211.h
@@ -92,8 +92,6 @@ void hostap_dump_rx_80211(const char *name, struct sk_buff *skb,
92void hostap_dump_tx_80211(const char *name, struct sk_buff *skb); 92void hostap_dump_tx_80211(const char *name, struct sk_buff *skb);
93int hostap_data_start_xmit(struct sk_buff *skb, struct net_device *dev); 93int hostap_data_start_xmit(struct sk_buff *skb, struct net_device *dev);
94int hostap_mgmt_start_xmit(struct sk_buff *skb, struct net_device *dev); 94int hostap_mgmt_start_xmit(struct sk_buff *skb, struct net_device *dev);
95struct sk_buff * hostap_tx_encrypt(struct sk_buff *skb,
96 struct ieee80211_crypt_data *crypt);
97int hostap_master_start_xmit(struct sk_buff *skb, struct net_device *dev); 95int hostap_master_start_xmit(struct sk_buff *skb, struct net_device *dev);
98 96
99#endif /* HOSTAP_80211_H */ 97#endif /* HOSTAP_80211_H */
diff --git a/drivers/net/wireless/hostap/hostap_80211_tx.c b/drivers/net/wireless/hostap/hostap_80211_tx.c
index 4a85e63906f1..06a5214145e3 100644
--- a/drivers/net/wireless/hostap/hostap_80211_tx.c
+++ b/drivers/net/wireless/hostap/hostap_80211_tx.c
@@ -299,8 +299,8 @@ int hostap_mgmt_start_xmit(struct sk_buff *skb, struct net_device *dev)
299 299
300 300
301/* Called only from software IRQ */ 301/* Called only from software IRQ */
302struct sk_buff * hostap_tx_encrypt(struct sk_buff *skb, 302static struct sk_buff * hostap_tx_encrypt(struct sk_buff *skb,
303 struct ieee80211_crypt_data *crypt) 303 struct ieee80211_crypt_data *crypt)
304{ 304{
305 struct hostap_interface *iface; 305 struct hostap_interface *iface;
306 local_info_t *local; 306 local_info_t *local;
@@ -317,7 +317,7 @@ struct sk_buff * hostap_tx_encrypt(struct sk_buff *skb,
317 } 317 }
318 318
319 if (local->tkip_countermeasures && 319 if (local->tkip_countermeasures &&
320 crypt && crypt->ops && strcmp(crypt->ops->name, "TKIP") == 0) { 320 strcmp(crypt->ops->name, "TKIP") == 0) {
321 hdr = (struct ieee80211_hdr_4addr *) skb->data; 321 hdr = (struct ieee80211_hdr_4addr *) skb->data;
322 if (net_ratelimit()) { 322 if (net_ratelimit()) {
323 printk(KERN_DEBUG "%s: TKIP countermeasures: dropped " 323 printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
@@ -469,7 +469,7 @@ int hostap_master_start_xmit(struct sk_buff *skb, struct net_device *dev)
469 } 469 }
470 470
471 if (local->ieee_802_1x && meta->ethertype == ETH_P_PAE && tx.crypt && 471 if (local->ieee_802_1x && meta->ethertype == ETH_P_PAE && tx.crypt &&
472 !(fc & IEEE80211_FCTL_VERS)) { 472 !(fc & IEEE80211_FCTL_PROTECTED)) {
473 no_encrypt = 1; 473 no_encrypt = 1;
474 PDEBUG(DEBUG_EXTRA2, "%s: TX: IEEE 802.1X - passing " 474 PDEBUG(DEBUG_EXTRA2, "%s: TX: IEEE 802.1X - passing "
475 "unencrypted EAPOL frame\n", dev->name); 475 "unencrypted EAPOL frame\n", dev->name);
@@ -535,5 +535,4 @@ int hostap_master_start_xmit(struct sk_buff *skb, struct net_device *dev)
535 535
536 536
537EXPORT_SYMBOL(hostap_dump_tx_80211); 537EXPORT_SYMBOL(hostap_dump_tx_80211);
538EXPORT_SYMBOL(hostap_tx_encrypt);
539EXPORT_SYMBOL(hostap_master_start_xmit); 538EXPORT_SYMBOL(hostap_master_start_xmit);
diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c
index d335b250923a..55bed923fbe9 100644
--- a/drivers/net/wireless/hostap/hostap_cs.c
+++ b/drivers/net/wireless/hostap/hostap_cs.c
@@ -42,7 +42,7 @@ MODULE_PARM_DESC(ignore_cis_vcc, "Ignore broken CIS VCC entry");
42/* struct local_info::hw_priv */ 42/* struct local_info::hw_priv */
43struct hostap_cs_priv { 43struct hostap_cs_priv {
44 dev_node_t node; 44 dev_node_t node;
45 dev_link_t *link; 45 struct pcmcia_device *link;
46 int sandisk_connectplus; 46 int sandisk_connectplus;
47}; 47};
48 48
@@ -204,15 +204,13 @@ static int hfa384x_to_bap(struct net_device *dev, u16 bap, void *buf, int len)
204 204
205static void prism2_detach(struct pcmcia_device *p_dev); 205static void prism2_detach(struct pcmcia_device *p_dev);
206static void prism2_release(u_long arg); 206static void prism2_release(u_long arg);
207static int prism2_config(dev_link_t *link); 207static int prism2_config(struct pcmcia_device *link);
208 208
209 209
210static int prism2_pccard_card_present(local_info_t *local) 210static int prism2_pccard_card_present(local_info_t *local)
211{ 211{
212 struct hostap_cs_priv *hw_priv = local->hw_priv; 212 struct hostap_cs_priv *hw_priv = local->hw_priv;
213 if (hw_priv != NULL && hw_priv->link != NULL && 213 if (hw_priv != NULL && hw_priv->link != NULL && pcmcia_dev_present(hw_priv->link))
214 ((hw_priv->link->state & (DEV_PRESENT | DEV_CONFIG)) ==
215 (DEV_PRESENT | DEV_CONFIG)))
216 return 1; 214 return 1;
217 return 0; 215 return 0;
218} 216}
@@ -237,7 +235,7 @@ static void sandisk_set_iobase(local_info_t *local)
237 reg.Action = CS_WRITE; 235 reg.Action = CS_WRITE;
238 reg.Offset = 0x10; /* 0x3f0 IO base 1 */ 236 reg.Offset = 0x10; /* 0x3f0 IO base 1 */
239 reg.Value = hw_priv->link->io.BasePort1 & 0x00ff; 237 reg.Value = hw_priv->link->io.BasePort1 & 0x00ff;
240 res = pcmcia_access_configuration_register(hw_priv->link->handle, 238 res = pcmcia_access_configuration_register(hw_priv->link,
241 &reg); 239 &reg);
242 if (res != CS_SUCCESS) { 240 if (res != CS_SUCCESS) {
243 printk(KERN_DEBUG "Prism3 SanDisk - failed to set I/O base 0 -" 241 printk(KERN_DEBUG "Prism3 SanDisk - failed to set I/O base 0 -"
@@ -249,7 +247,7 @@ static void sandisk_set_iobase(local_info_t *local)
249 reg.Action = CS_WRITE; 247 reg.Action = CS_WRITE;
250 reg.Offset = 0x12; /* 0x3f2 IO base 2 */ 248 reg.Offset = 0x12; /* 0x3f2 IO base 2 */
251 reg.Value = (hw_priv->link->io.BasePort1 & 0xff00) >> 8; 249 reg.Value = (hw_priv->link->io.BasePort1 & 0xff00) >> 8;
252 res = pcmcia_access_configuration_register(hw_priv->link->handle, 250 res = pcmcia_access_configuration_register(hw_priv->link,
253 &reg); 251 &reg);
254 if (res != CS_SUCCESS) { 252 if (res != CS_SUCCESS) {
255 printk(KERN_DEBUG "Prism3 SanDisk - failed to set I/O base 1 -" 253 printk(KERN_DEBUG "Prism3 SanDisk - failed to set I/O base 1 -"
@@ -301,9 +299,9 @@ static int sandisk_enable_wireless(struct net_device *dev)
301 tuple.TupleData = buf; 299 tuple.TupleData = buf;
302 tuple.TupleDataMax = sizeof(buf); 300 tuple.TupleDataMax = sizeof(buf);
303 tuple.TupleOffset = 0; 301 tuple.TupleOffset = 0;
304 if (pcmcia_get_first_tuple(hw_priv->link->handle, &tuple) || 302 if (pcmcia_get_first_tuple(hw_priv->link, &tuple) ||
305 pcmcia_get_tuple_data(hw_priv->link->handle, &tuple) || 303 pcmcia_get_tuple_data(hw_priv->link, &tuple) ||
306 pcmcia_parse_tuple(hw_priv->link->handle, &tuple, parse) || 304 pcmcia_parse_tuple(hw_priv->link, &tuple, parse) ||
307 parse->manfid.manf != 0xd601 || parse->manfid.card != 0x0101) { 305 parse->manfid.manf != 0xd601 || parse->manfid.card != 0x0101) {
308 /* No SanDisk manfid found */ 306 /* No SanDisk manfid found */
309 ret = -ENODEV; 307 ret = -ENODEV;
@@ -311,9 +309,9 @@ static int sandisk_enable_wireless(struct net_device *dev)
311 } 309 }
312 310
313 tuple.DesiredTuple = CISTPL_LONGLINK_MFC; 311 tuple.DesiredTuple = CISTPL_LONGLINK_MFC;
314 if (pcmcia_get_first_tuple(hw_priv->link->handle, &tuple) || 312 if (pcmcia_get_first_tuple(hw_priv->link, &tuple) ||
315 pcmcia_get_tuple_data(hw_priv->link->handle, &tuple) || 313 pcmcia_get_tuple_data(hw_priv->link, &tuple) ||
316 pcmcia_parse_tuple(hw_priv->link->handle, &tuple, parse) || 314 pcmcia_parse_tuple(hw_priv->link, &tuple, parse) ||
317 parse->longlink_mfc.nfn < 2) { 315 parse->longlink_mfc.nfn < 2) {
318 /* No multi-function links found */ 316 /* No multi-function links found */
319 ret = -ENODEV; 317 ret = -ENODEV;
@@ -328,7 +326,7 @@ static int sandisk_enable_wireless(struct net_device *dev)
328 reg.Action = CS_WRITE; 326 reg.Action = CS_WRITE;
329 reg.Offset = CISREG_COR; 327 reg.Offset = CISREG_COR;
330 reg.Value = COR_SOFT_RESET; 328 reg.Value = COR_SOFT_RESET;
331 res = pcmcia_access_configuration_register(hw_priv->link->handle, 329 res = pcmcia_access_configuration_register(hw_priv->link,
332 &reg); 330 &reg);
333 if (res != CS_SUCCESS) { 331 if (res != CS_SUCCESS) {
334 printk(KERN_DEBUG "%s: SanDisk - COR sreset failed (%d)\n", 332 printk(KERN_DEBUG "%s: SanDisk - COR sreset failed (%d)\n",
@@ -345,7 +343,7 @@ static int sandisk_enable_wireless(struct net_device *dev)
345 * will be enabled during the first cor_sreset call. 343 * will be enabled during the first cor_sreset call.
346 */ 344 */
347 reg.Value = COR_LEVEL_REQ | 0x8 | COR_ADDR_DECODE | COR_FUNC_ENA; 345 reg.Value = COR_LEVEL_REQ | 0x8 | COR_ADDR_DECODE | COR_FUNC_ENA;
348 res = pcmcia_access_configuration_register(hw_priv->link->handle, 346 res = pcmcia_access_configuration_register(hw_priv->link,
349 &reg); 347 &reg);
350 if (res != CS_SUCCESS) { 348 if (res != CS_SUCCESS) {
351 printk(KERN_DEBUG "%s: SanDisk - COR sreset failed (%d)\n", 349 printk(KERN_DEBUG "%s: SanDisk - COR sreset failed (%d)\n",
@@ -380,7 +378,7 @@ static void prism2_pccard_cor_sreset(local_info_t *local)
380 reg.Action = CS_READ; 378 reg.Action = CS_READ;
381 reg.Offset = CISREG_COR; 379 reg.Offset = CISREG_COR;
382 reg.Value = 0; 380 reg.Value = 0;
383 res = pcmcia_access_configuration_register(hw_priv->link->handle, 381 res = pcmcia_access_configuration_register(hw_priv->link,
384 &reg); 382 &reg);
385 if (res != CS_SUCCESS) { 383 if (res != CS_SUCCESS) {
386 printk(KERN_DEBUG "prism2_pccard_cor_sreset failed 1 (%d)\n", 384 printk(KERN_DEBUG "prism2_pccard_cor_sreset failed 1 (%d)\n",
@@ -392,7 +390,7 @@ static void prism2_pccard_cor_sreset(local_info_t *local)
392 390
393 reg.Action = CS_WRITE; 391 reg.Action = CS_WRITE;
394 reg.Value |= COR_SOFT_RESET; 392 reg.Value |= COR_SOFT_RESET;
395 res = pcmcia_access_configuration_register(hw_priv->link->handle, 393 res = pcmcia_access_configuration_register(hw_priv->link,
396 &reg); 394 &reg);
397 if (res != CS_SUCCESS) { 395 if (res != CS_SUCCESS) {
398 printk(KERN_DEBUG "prism2_pccard_cor_sreset failed 2 (%d)\n", 396 printk(KERN_DEBUG "prism2_pccard_cor_sreset failed 2 (%d)\n",
@@ -405,7 +403,7 @@ static void prism2_pccard_cor_sreset(local_info_t *local)
405 reg.Value &= ~COR_SOFT_RESET; 403 reg.Value &= ~COR_SOFT_RESET;
406 if (hw_priv->sandisk_connectplus) 404 if (hw_priv->sandisk_connectplus)
407 reg.Value |= COR_IREQ_ENA; 405 reg.Value |= COR_IREQ_ENA;
408 res = pcmcia_access_configuration_register(hw_priv->link->handle, 406 res = pcmcia_access_configuration_register(hw_priv->link,
409 &reg); 407 &reg);
410 if (res != CS_SUCCESS) { 408 if (res != CS_SUCCESS) {
411 printk(KERN_DEBUG "prism2_pccard_cor_sreset failed 3 (%d)\n", 409 printk(KERN_DEBUG "prism2_pccard_cor_sreset failed 3 (%d)\n",
@@ -439,7 +437,7 @@ static void prism2_pccard_genesis_reset(local_info_t *local, int hcr)
439 reg.Action = CS_READ; 437 reg.Action = CS_READ;
440 reg.Offset = CISREG_COR; 438 reg.Offset = CISREG_COR;
441 reg.Value = 0; 439 reg.Value = 0;
442 res = pcmcia_access_configuration_register(hw_priv->link->handle, 440 res = pcmcia_access_configuration_register(hw_priv->link,
443 &reg); 441 &reg);
444 if (res != CS_SUCCESS) { 442 if (res != CS_SUCCESS) {
445 printk(KERN_DEBUG "prism2_pccard_genesis_sreset failed 1 " 443 printk(KERN_DEBUG "prism2_pccard_genesis_sreset failed 1 "
@@ -452,7 +450,7 @@ static void prism2_pccard_genesis_reset(local_info_t *local, int hcr)
452 450
453 reg.Action = CS_WRITE; 451 reg.Action = CS_WRITE;
454 reg.Value |= COR_SOFT_RESET; 452 reg.Value |= COR_SOFT_RESET;
455 res = pcmcia_access_configuration_register(hw_priv->link->handle, 453 res = pcmcia_access_configuration_register(hw_priv->link,
456 &reg); 454 &reg);
457 if (res != CS_SUCCESS) { 455 if (res != CS_SUCCESS) {
458 printk(KERN_DEBUG "prism2_pccard_genesis_sreset failed 2 " 456 printk(KERN_DEBUG "prism2_pccard_genesis_sreset failed 2 "
@@ -466,7 +464,7 @@ static void prism2_pccard_genesis_reset(local_info_t *local, int hcr)
466 reg.Action = CS_WRITE; 464 reg.Action = CS_WRITE;
467 reg.Value = hcr; 465 reg.Value = hcr;
468 reg.Offset = CISREG_CCSR; 466 reg.Offset = CISREG_CCSR;
469 res = pcmcia_access_configuration_register(hw_priv->link->handle, 467 res = pcmcia_access_configuration_register(hw_priv->link,
470 &reg); 468 &reg);
471 if (res != CS_SUCCESS) { 469 if (res != CS_SUCCESS) {
472 printk(KERN_DEBUG "prism2_pccard_genesis_sreset failed 3 " 470 printk(KERN_DEBUG "prism2_pccard_genesis_sreset failed 3 "
@@ -478,7 +476,7 @@ static void prism2_pccard_genesis_reset(local_info_t *local, int hcr)
478 reg.Action = CS_WRITE; 476 reg.Action = CS_WRITE;
479 reg.Offset = CISREG_COR; 477 reg.Offset = CISREG_COR;
480 reg.Value = old_cor & ~COR_SOFT_RESET; 478 reg.Value = old_cor & ~COR_SOFT_RESET;
481 res = pcmcia_access_configuration_register(hw_priv->link->handle, 479 res = pcmcia_access_configuration_register(hw_priv->link,
482 &reg); 480 &reg);
483 if (res != CS_SUCCESS) { 481 if (res != CS_SUCCESS) {
484 printk(KERN_DEBUG "prism2_pccard_genesis_sreset failed 4 " 482 printk(KERN_DEBUG "prism2_pccard_genesis_sreset failed 4 "
@@ -501,40 +499,27 @@ static struct prism2_helper_functions prism2_pccard_funcs =
501 499
502/* allocate local data and register with CardServices 500/* allocate local data and register with CardServices
503 * initialize dev_link structure, but do not configure the card yet */ 501 * initialize dev_link structure, but do not configure the card yet */
504static int prism2_attach(struct pcmcia_device *p_dev) 502static int hostap_cs_probe(struct pcmcia_device *p_dev)
505{ 503{
506 dev_link_t *link; 504 int ret;
507
508 link = kmalloc(sizeof(dev_link_t), GFP_KERNEL);
509 if (link == NULL)
510 return -ENOMEM;
511
512 memset(link, 0, sizeof(dev_link_t));
513 505
514 PDEBUG(DEBUG_HW, "%s: setting Vcc=33 (constant)\n", dev_info); 506 PDEBUG(DEBUG_HW, "%s: setting Vcc=33 (constant)\n", dev_info);
515 link->conf.Vcc = 33; 507 p_dev->conf.IntType = INT_MEMORY_AND_IO;
516 link->conf.IntType = INT_MEMORY_AND_IO;
517
518 link->handle = p_dev;
519 p_dev->instance = link;
520 508
521 link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; 509 ret = prism2_config(p_dev);
522 if (prism2_config(link)) 510 if (ret) {
523 PDEBUG(DEBUG_EXTRA, "prism2_config() failed\n"); 511 PDEBUG(DEBUG_EXTRA, "prism2_config() failed\n");
512 }
524 513
525 return 0; 514 return ret;
526} 515}
527 516
528 517
529static void prism2_detach(struct pcmcia_device *p_dev) 518static void prism2_detach(struct pcmcia_device *link)
530{ 519{
531 dev_link_t *link = dev_to_instance(p_dev);
532
533 PDEBUG(DEBUG_FLOW, "prism2_detach\n"); 520 PDEBUG(DEBUG_FLOW, "prism2_detach\n");
534 521
535 if (link->state & DEV_CONFIG) { 522 prism2_release((u_long)link);
536 prism2_release((u_long)link);
537 }
538 523
539 /* release net devices */ 524 /* release net devices */
540 if (link->priv) { 525 if (link->priv) {
@@ -547,7 +532,6 @@ static void prism2_detach(struct pcmcia_device *p_dev)
547 prism2_free_local_data(dev); 532 prism2_free_local_data(dev);
548 kfree(hw_priv); 533 kfree(hw_priv);
549 } 534 }
550 kfree(link);
551} 535}
552 536
553 537
@@ -558,7 +542,7 @@ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
558do { int ret = (retf); \ 542do { int ret = (retf); \
559if (ret != 0) { \ 543if (ret != 0) { \
560 PDEBUG(DEBUG_EXTRA, "CardServices(" #fn ") returned %d\n", ret); \ 544 PDEBUG(DEBUG_EXTRA, "CardServices(" #fn ") returned %d\n", ret); \
561 cs_error(link->handle, fn, ret); \ 545 cs_error(link, fn, ret); \
562 goto next_entry; \ 546 goto next_entry; \
563} \ 547} \
564} while (0) 548} while (0)
@@ -566,7 +550,7 @@ if (ret != 0) { \
566 550
567/* run after a CARD_INSERTION event is received to configure the PCMCIA 551/* run after a CARD_INSERTION event is received to configure the PCMCIA
568 * socket and make the device available to the system */ 552 * socket and make the device available to the system */
569static int prism2_config(dev_link_t *link) 553static int prism2_config(struct pcmcia_device *link)
570{ 554{
571 struct net_device *dev; 555 struct net_device *dev;
572 struct hostap_interface *iface; 556 struct hostap_interface *iface;
@@ -595,27 +579,24 @@ static int prism2_config(dev_link_t *link)
595 tuple.TupleData = buf; 579 tuple.TupleData = buf;
596 tuple.TupleDataMax = sizeof(buf); 580 tuple.TupleDataMax = sizeof(buf);
597 tuple.TupleOffset = 0; 581 tuple.TupleOffset = 0;
598 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link->handle, &tuple)); 582 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
599 CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link->handle, &tuple)); 583 CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
600 CS_CHECK(ParseTuple, pcmcia_parse_tuple(link->handle, &tuple, parse)); 584 CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, parse));
601 link->conf.ConfigBase = parse->config.base; 585 link->conf.ConfigBase = parse->config.base;
602 link->conf.Present = parse->config.rmask[0]; 586 link->conf.Present = parse->config.rmask[0];
603 587
604 CS_CHECK(GetConfigurationInfo, 588 CS_CHECK(GetConfigurationInfo,
605 pcmcia_get_configuration_info(link->handle, &conf)); 589 pcmcia_get_configuration_info(link, &conf));
606 PDEBUG(DEBUG_HW, "%s: %s Vcc=%d (from config)\n", dev_info,
607 ignore_cis_vcc ? "ignoring" : "setting", conf.Vcc);
608 link->conf.Vcc = conf.Vcc;
609 590
610 /* Look for an appropriate configuration table entry in the CIS */ 591 /* Look for an appropriate configuration table entry in the CIS */
611 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; 592 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
612 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link->handle, &tuple)); 593 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
613 for (;;) { 594 for (;;) {
614 cistpl_cftable_entry_t *cfg = &(parse->cftable_entry); 595 cistpl_cftable_entry_t *cfg = &(parse->cftable_entry);
615 CFG_CHECK2(GetTupleData, 596 CFG_CHECK2(GetTupleData,
616 pcmcia_get_tuple_data(link->handle, &tuple)); 597 pcmcia_get_tuple_data(link, &tuple));
617 CFG_CHECK2(ParseTuple, 598 CFG_CHECK2(ParseTuple,
618 pcmcia_parse_tuple(link->handle, &tuple, parse)); 599 pcmcia_parse_tuple(link, &tuple, parse));
619 600
620 if (cfg->flags & CISTPL_CFTABLE_DEFAULT) 601 if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
621 dflt = *cfg; 602 dflt = *cfg;
@@ -650,10 +631,10 @@ static int prism2_config(dev_link_t *link)
650 } 631 }
651 632
652 if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) 633 if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
653 link->conf.Vpp1 = link->conf.Vpp2 = 634 link->conf.Vpp =
654 cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; 635 cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
655 else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM)) 636 else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM))
656 link->conf.Vpp1 = link->conf.Vpp2 = 637 link->conf.Vpp =
657 dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000; 638 dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
658 639
659 /* Do we need to allocate an interrupt? */ 640 /* Do we need to allocate an interrupt? */
@@ -695,19 +676,19 @@ static int prism2_config(dev_link_t *link)
695 676
696 /* This reserves IO space but doesn't actually enable it */ 677 /* This reserves IO space but doesn't actually enable it */
697 CFG_CHECK2(RequestIO, 678 CFG_CHECK2(RequestIO,
698 pcmcia_request_io(link->handle, &link->io)); 679 pcmcia_request_io(link, &link->io));
699 680
700 /* This configuration table entry is OK */ 681 /* This configuration table entry is OK */
701 break; 682 break;
702 683
703 next_entry: 684 next_entry:
704 CS_CHECK(GetNextTuple, 685 CS_CHECK(GetNextTuple,
705 pcmcia_get_next_tuple(link->handle, &tuple)); 686 pcmcia_get_next_tuple(link, &tuple));
706 } 687 }
707 688
708 /* Need to allocate net_device before requesting IRQ handler */ 689 /* Need to allocate net_device before requesting IRQ handler */
709 dev = prism2_init_local_data(&prism2_pccard_funcs, 0, 690 dev = prism2_init_local_data(&prism2_pccard_funcs, 0,
710 &handle_to_dev(link->handle)); 691 &handle_to_dev(link));
711 if (dev == NULL) 692 if (dev == NULL)
712 goto failed; 693 goto failed;
713 link->priv = dev; 694 link->priv = dev;
@@ -717,7 +698,7 @@ static int prism2_config(dev_link_t *link)
717 local->hw_priv = hw_priv; 698 local->hw_priv = hw_priv;
718 hw_priv->link = link; 699 hw_priv->link = link;
719 strcpy(hw_priv->node.dev_name, dev->name); 700 strcpy(hw_priv->node.dev_name, dev->name);
720 link->dev = &hw_priv->node; 701 link->dev_node = &hw_priv->node;
721 702
722 /* 703 /*
723 * Allocate an interrupt line. Note that this does not assign a 704 * Allocate an interrupt line. Note that this does not assign a
@@ -730,7 +711,7 @@ static int prism2_config(dev_link_t *link)
730 link->irq.Handler = prism2_interrupt; 711 link->irq.Handler = prism2_interrupt;
731 link->irq.Instance = dev; 712 link->irq.Instance = dev;
732 CS_CHECK(RequestIRQ, 713 CS_CHECK(RequestIRQ,
733 pcmcia_request_irq(link->handle, &link->irq)); 714 pcmcia_request_irq(link, &link->irq));
734 } 715 }
735 716
736 /* 717 /*
@@ -739,18 +720,17 @@ static int prism2_config(dev_link_t *link)
739 * card and host interface into "Memory and IO" mode. 720 * card and host interface into "Memory and IO" mode.
740 */ 721 */
741 CS_CHECK(RequestConfiguration, 722 CS_CHECK(RequestConfiguration,
742 pcmcia_request_configuration(link->handle, &link->conf)); 723 pcmcia_request_configuration(link, &link->conf));
743 724
744 dev->irq = link->irq.AssignedIRQ; 725 dev->irq = link->irq.AssignedIRQ;
745 dev->base_addr = link->io.BasePort1; 726 dev->base_addr = link->io.BasePort1;
746 727
747 /* Finally, report what we've done */ 728 /* Finally, report what we've done */
748 printk(KERN_INFO "%s: index 0x%02x: Vcc %d.%d", 729 printk(KERN_INFO "%s: index 0x%02x: ",
749 dev_info, link->conf.ConfigIndex, 730 dev_info, link->conf.ConfigIndex);
750 link->conf.Vcc / 10, link->conf.Vcc % 10); 731 if (link->conf.Vpp)
751 if (link->conf.Vpp1) 732 printk(", Vpp %d.%d", link->conf.Vpp / 10,
752 printk(", Vpp %d.%d", link->conf.Vpp1 / 10, 733 link->conf.Vpp % 10);
753 link->conf.Vpp1 % 10);
754 if (link->conf.Attributes & CONF_ENABLE_IRQ) 734 if (link->conf.Attributes & CONF_ENABLE_IRQ)
755 printk(", irq %d", link->irq.AssignedIRQ); 735 printk(", irq %d", link->irq.AssignedIRQ);
756 if (link->io.NumPorts1) 736 if (link->io.NumPorts1)
@@ -761,9 +741,6 @@ static int prism2_config(dev_link_t *link)
761 link->io.BasePort2+link->io.NumPorts2-1); 741 link->io.BasePort2+link->io.NumPorts2-1);
762 printk("\n"); 742 printk("\n");
763 743
764 link->state |= DEV_CONFIG;
765 link->state &= ~DEV_CONFIG_PENDING;
766
767 local->shutdown = 0; 744 local->shutdown = 0;
768 745
769 sandisk_enable_wireless(dev); 746 sandisk_enable_wireless(dev);
@@ -778,7 +755,7 @@ static int prism2_config(dev_link_t *link)
778 return ret; 755 return ret;
779 756
780 cs_failed: 757 cs_failed:
781 cs_error(link->handle, last_fn, last_ret); 758 cs_error(link, last_fn, last_ret);
782 759
783 failed: 760 failed:
784 kfree(parse); 761 kfree(parse);
@@ -790,7 +767,7 @@ static int prism2_config(dev_link_t *link)
790 767
791static void prism2_release(u_long arg) 768static void prism2_release(u_long arg)
792{ 769{
793 dev_link_t *link = (dev_link_t *)arg; 770 struct pcmcia_device *link = (struct pcmcia_device *)arg;
794 771
795 PDEBUG(DEBUG_FLOW, "prism2_release\n"); 772 PDEBUG(DEBUG_FLOW, "prism2_release\n");
796 773
@@ -799,71 +776,54 @@ static void prism2_release(u_long arg)
799 struct hostap_interface *iface; 776 struct hostap_interface *iface;
800 777
801 iface = netdev_priv(dev); 778 iface = netdev_priv(dev);
802 if (link->state & DEV_CONFIG) 779 prism2_hw_shutdown(dev, 0);
803 prism2_hw_shutdown(dev, 0);
804 iface->local->shutdown = 1; 780 iface->local->shutdown = 1;
805 } 781 }
806 782
807 if (link->win) 783 pcmcia_disable_device(link);
808 pcmcia_release_window(link->win);
809 pcmcia_release_configuration(link->handle);
810 if (link->io.NumPorts1)
811 pcmcia_release_io(link->handle, &link->io);
812 if (link->irq.AssignedIRQ)
813 pcmcia_release_irq(link->handle, &link->irq);
814
815 link->state &= ~DEV_CONFIG;
816
817 PDEBUG(DEBUG_FLOW, "release - done\n"); 784 PDEBUG(DEBUG_FLOW, "release - done\n");
818} 785}
819 786
820static int hostap_cs_suspend(struct pcmcia_device *p_dev) 787static int hostap_cs_suspend(struct pcmcia_device *link)
821{ 788{
822 dev_link_t *link = dev_to_instance(p_dev);
823 struct net_device *dev = (struct net_device *) link->priv; 789 struct net_device *dev = (struct net_device *) link->priv;
824 int dev_open = 0; 790 int dev_open = 0;
791 struct hostap_interface *iface = NULL;
825 792
826 PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_PM_SUSPEND\n", dev_info); 793 if (dev)
827 794 iface = netdev_priv(dev);
828 link->state |= DEV_SUSPEND;
829 795
830 if (link->state & DEV_CONFIG) { 796 PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_PM_SUSPEND\n", dev_info);
831 struct hostap_interface *iface = netdev_priv(dev); 797 if (iface && iface->local)
832 if (iface && iface->local) 798 dev_open = iface->local->num_dev_open > 0;
833 dev_open = iface->local->num_dev_open > 0; 799 if (dev_open) {
834 if (dev_open) { 800 netif_stop_queue(dev);
835 netif_stop_queue(dev); 801 netif_device_detach(dev);
836 netif_device_detach(dev);
837 }
838 prism2_suspend(dev);
839 pcmcia_release_configuration(link->handle);
840 } 802 }
803 prism2_suspend(dev);
841 804
842 return 0; 805 return 0;
843} 806}
844 807
845static int hostap_cs_resume(struct pcmcia_device *p_dev) 808static int hostap_cs_resume(struct pcmcia_device *link)
846{ 809{
847 dev_link_t *link = dev_to_instance(p_dev);
848 struct net_device *dev = (struct net_device *) link->priv; 810 struct net_device *dev = (struct net_device *) link->priv;
849 int dev_open = 0; 811 int dev_open = 0;
812 struct hostap_interface *iface = NULL;
850 813
851 PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_PM_RESUME\n", dev_info); 814 if (dev)
815 iface = netdev_priv(dev);
852 816
853 link->state &= ~DEV_SUSPEND; 817 PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_PM_RESUME\n", dev_info);
854 if (link->state & DEV_CONFIG) {
855 struct hostap_interface *iface = netdev_priv(dev);
856 if (iface && iface->local)
857 dev_open = iface->local->num_dev_open > 0;
858 818
859 pcmcia_request_configuration(link->handle, &link->conf); 819 if (iface && iface->local)
820 dev_open = iface->local->num_dev_open > 0;
860 821
861 prism2_hw_shutdown(dev, 1); 822 prism2_hw_shutdown(dev, 1);
862 prism2_hw_config(dev, dev_open ? 0 : 1); 823 prism2_hw_config(dev, dev_open ? 0 : 1);
863 if (dev_open) { 824 if (dev_open) {
864 netif_device_attach(dev); 825 netif_device_attach(dev);
865 netif_start_queue(dev); 826 netif_start_queue(dev);
866 }
867 } 827 }
868 828
869 return 0; 829 return 0;
@@ -930,7 +890,7 @@ static struct pcmcia_driver hostap_driver = {
930 .drv = { 890 .drv = {
931 .name = "hostap_cs", 891 .name = "hostap_cs",
932 }, 892 },
933 .probe = prism2_attach, 893 .probe = hostap_cs_probe,
934 .remove = prism2_detach, 894 .remove = prism2_detach,
935 .owner = THIS_MODULE, 895 .owner = THIS_MODULE,
936 .id_table = hostap_cs_ids, 896 .id_table = hostap_cs_ids,
diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c
index 9dce522526c5..bca89cff85a6 100644
--- a/drivers/net/wireless/ipw2200.c
+++ b/drivers/net/wireless/ipw2200.c
@@ -5573,8 +5573,7 @@ static void ipw_adhoc_create(struct ipw_priv *priv,
5573 case IEEE80211_52GHZ_BAND: 5573 case IEEE80211_52GHZ_BAND:
5574 network->mode = IEEE_A; 5574 network->mode = IEEE_A;
5575 i = ieee80211_channel_to_index(priv->ieee, priv->channel); 5575 i = ieee80211_channel_to_index(priv->ieee, priv->channel);
5576 if (i == -1) 5576 BUG_ON(i == -1);
5577 BUG();
5578 if (geo->a[i].flags & IEEE80211_CH_PASSIVE_ONLY) { 5577 if (geo->a[i].flags & IEEE80211_CH_PASSIVE_ONLY) {
5579 IPW_WARNING("Overriding invalid channel\n"); 5578 IPW_WARNING("Overriding invalid channel\n");
5580 priv->channel = geo->a[0].channel; 5579 priv->channel = geo->a[0].channel;
@@ -5587,8 +5586,7 @@ static void ipw_adhoc_create(struct ipw_priv *priv,
5587 else 5586 else
5588 network->mode = IEEE_B; 5587 network->mode = IEEE_B;
5589 i = ieee80211_channel_to_index(priv->ieee, priv->channel); 5588 i = ieee80211_channel_to_index(priv->ieee, priv->channel);
5590 if (i == -1) 5589 BUG_ON(i == -1);
5591 BUG();
5592 if (geo->bg[i].flags & IEEE80211_CH_PASSIVE_ONLY) { 5590 if (geo->bg[i].flags & IEEE80211_CH_PASSIVE_ONLY) {
5593 IPW_WARNING("Overriding invalid channel\n"); 5591 IPW_WARNING("Overriding invalid channel\n");
5594 priv->channel = geo->bg[0].channel; 5592 priv->channel = geo->bg[0].channel;
@@ -6715,8 +6713,7 @@ static int ipw_qos_association(struct ipw_priv *priv,
6715 6713
6716 switch (priv->ieee->iw_mode) { 6714 switch (priv->ieee->iw_mode) {
6717 case IW_MODE_ADHOC: 6715 case IW_MODE_ADHOC:
6718 if (!(network->capability & WLAN_CAPABILITY_IBSS)) 6716 BUG_ON(!(network->capability & WLAN_CAPABILITY_IBSS));
6719 BUG();
6720 6717
6721 qos_data = &ibss_data; 6718 qos_data = &ibss_data;
6722 break; 6719 break;
diff --git a/drivers/net/wireless/netwave_cs.c b/drivers/net/wireless/netwave_cs.c
index 75ce6ddb0cf5..9343d970537b 100644
--- a/drivers/net/wireless/netwave_cs.c
+++ b/drivers/net/wireless/netwave_cs.c
@@ -190,8 +190,8 @@ module_param(mem_speed, int, 0);
190/*====================================================================*/ 190/*====================================================================*/
191 191
192/* PCMCIA (Card Services) related functions */ 192/* PCMCIA (Card Services) related functions */
193static void netwave_release(dev_link_t *link); /* Card removal */ 193static void netwave_release(struct pcmcia_device *link); /* Card removal */
194static void netwave_pcmcia_config(dev_link_t *arg); /* Runs after card 194static int netwave_pcmcia_config(struct pcmcia_device *arg); /* Runs after card
195 insertion */ 195 insertion */
196static void netwave_detach(struct pcmcia_device *p_dev); /* Destroy instance */ 196static void netwave_detach(struct pcmcia_device *p_dev); /* Destroy instance */
197 197
@@ -221,10 +221,10 @@ static struct iw_statistics* netwave_get_wireless_stats(struct net_device *dev);
221static void set_multicast_list(struct net_device *dev); 221static void set_multicast_list(struct net_device *dev);
222 222
223/* 223/*
224 A dev_link_t structure has fields for most things that are needed 224 A struct pcmcia_device structure has fields for most things that are needed
225 to keep track of a socket, but there will usually be some device 225 to keep track of a socket, but there will usually be some device
226 specific information that also needs to be kept track of. The 226 specific information that also needs to be kept track of. The
227 'priv' pointer in a dev_link_t structure can be used to point to 227 'priv' pointer in a struct pcmcia_device structure can be used to point to
228 a device-specific private data structure, like this. 228 a device-specific private data structure, like this.
229 229
230 A driver needs to provide a dev_node_t structure for each device 230 A driver needs to provide a dev_node_t structure for each device
@@ -232,7 +232,7 @@ static void set_multicast_list(struct net_device *dev);
232 example, ethernet cards, modems). In other cases, there may be 232 example, ethernet cards, modems). In other cases, there may be
233 many actual or logical devices (SCSI adapters, memory cards with 233 many actual or logical devices (SCSI adapters, memory cards with
234 multiple partitions). The dev_node_t structures need to be kept 234 multiple partitions). The dev_node_t structures need to be kept
235 in a linked list starting at the 'dev' field of a dev_link_t 235 in a linked list starting at the 'dev' field of a struct pcmcia_device
236 structure. We allocate them in the card's private data structure, 236 structure. We allocate them in the card's private data structure,
237 because they generally can't be allocated dynamically. 237 because they generally can't be allocated dynamically.
238*/ 238*/
@@ -268,7 +268,7 @@ struct site_survey {
268}; 268};
269 269
270typedef struct netwave_private { 270typedef struct netwave_private {
271 dev_link_t link; 271 struct pcmcia_device *p_dev;
272 spinlock_t spinlock; /* Serialize access to the hardware (SMP) */ 272 spinlock_t spinlock; /* Serialize access to the hardware (SMP) */
273 dev_node_t node; 273 dev_node_t node;
274 u_char __iomem *ramBase; 274 u_char __iomem *ramBase;
@@ -376,20 +376,19 @@ static struct iw_statistics *netwave_get_wireless_stats(struct net_device *dev)
376 * configure the card at this point -- we wait until we receive a 376 * configure the card at this point -- we wait until we receive a
377 * card insertion event. 377 * card insertion event.
378 */ 378 */
379static int netwave_attach(struct pcmcia_device *p_dev) 379static int netwave_probe(struct pcmcia_device *link)
380{ 380{
381 dev_link_t *link;
382 struct net_device *dev; 381 struct net_device *dev;
383 netwave_private *priv; 382 netwave_private *priv;
384 383
385 DEBUG(0, "netwave_attach()\n"); 384 DEBUG(0, "netwave_attach()\n");
386 385
387 /* Initialize the dev_link_t structure */ 386 /* Initialize the struct pcmcia_device structure */
388 dev = alloc_etherdev(sizeof(netwave_private)); 387 dev = alloc_etherdev(sizeof(netwave_private));
389 if (!dev) 388 if (!dev)
390 return -ENOMEM; 389 return -ENOMEM;
391 priv = netdev_priv(dev); 390 priv = netdev_priv(dev);
392 link = &priv->link; 391 priv->p_dev = link;
393 link->priv = dev; 392 link->priv = dev;
394 393
395 /* The io structure describes IO port mapping */ 394 /* The io structure describes IO port mapping */
@@ -406,7 +405,6 @@ static int netwave_attach(struct pcmcia_device *p_dev)
406 405
407 /* General socket configuration */ 406 /* General socket configuration */
408 link->conf.Attributes = CONF_ENABLE_IRQ; 407 link->conf.Attributes = CONF_ENABLE_IRQ;
409 link->conf.Vcc = 50;
410 link->conf.IntType = INT_MEMORY_AND_IO; 408 link->conf.IntType = INT_MEMORY_AND_IO;
411 link->conf.ConfigIndex = 1; 409 link->conf.ConfigIndex = 1;
412 link->conf.Present = PRESENT_OPTION; 410 link->conf.Present = PRESENT_OPTION;
@@ -430,13 +428,7 @@ static int netwave_attach(struct pcmcia_device *p_dev)
430 dev->stop = &netwave_close; 428 dev->stop = &netwave_close;
431 link->irq.Instance = dev; 429 link->irq.Instance = dev;
432 430
433 link->handle = p_dev; 431 return netwave_pcmcia_config( link);
434 p_dev->instance = link;
435
436 link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
437 netwave_pcmcia_config( link);
438
439 return 0;
440} /* netwave_attach */ 432} /* netwave_attach */
441 433
442/* 434/*
@@ -447,17 +439,15 @@ static int netwave_attach(struct pcmcia_device *p_dev)
447 * structures are freed. Otherwise, the structures will be freed 439 * structures are freed. Otherwise, the structures will be freed
448 * when the device is released. 440 * when the device is released.
449 */ 441 */
450static void netwave_detach(struct pcmcia_device *p_dev) 442static void netwave_detach(struct pcmcia_device *link)
451{ 443{
452 dev_link_t *link = dev_to_instance(p_dev);
453 struct net_device *dev = link->priv; 444 struct net_device *dev = link->priv;
454 445
455 DEBUG(0, "netwave_detach(0x%p)\n", link); 446 DEBUG(0, "netwave_detach(0x%p)\n", link);
456 447
457 if (link->state & DEV_CONFIG) 448 netwave_release(link);
458 netwave_release(link);
459 449
460 if (link->dev) 450 if (link->dev_node)
461 unregister_netdev(dev); 451 unregister_netdev(dev);
462 452
463 free_netdev(dev); 453 free_netdev(dev);
@@ -743,8 +733,7 @@ static const struct iw_handler_def netwave_handler_def =
743#define CS_CHECK(fn, ret) \ 733#define CS_CHECK(fn, ret) \
744do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) 734do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
745 735
746static void netwave_pcmcia_config(dev_link_t *link) { 736static int netwave_pcmcia_config(struct pcmcia_device *link) {
747 client_handle_t handle = link->handle;
748 struct net_device *dev = link->priv; 737 struct net_device *dev = link->priv;
749 netwave_private *priv = netdev_priv(dev); 738 netwave_private *priv = netdev_priv(dev);
750 tuple_t tuple; 739 tuple_t tuple;
@@ -766,15 +755,12 @@ static void netwave_pcmcia_config(dev_link_t *link) {
766 tuple.TupleDataMax = 64; 755 tuple.TupleDataMax = 64;
767 tuple.TupleOffset = 0; 756 tuple.TupleOffset = 0;
768 tuple.DesiredTuple = CISTPL_CONFIG; 757 tuple.DesiredTuple = CISTPL_CONFIG;
769 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); 758 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
770 CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); 759 CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
771 CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); 760 CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
772 link->conf.ConfigBase = parse.config.base; 761 link->conf.ConfigBase = parse.config.base;
773 link->conf.Present = parse.config.rmask[0]; 762 link->conf.Present = parse.config.rmask[0];
774 763
775 /* Configure card */
776 link->state |= DEV_CONFIG;
777
778 /* 764 /*
779 * Try allocating IO ports. This tries a few fixed addresses. 765 * Try allocating IO ports. This tries a few fixed addresses.
780 * If you want, you can also read the card's config table to 766 * If you want, you can also read the card's config table to
@@ -782,11 +768,11 @@ static void netwave_pcmcia_config(dev_link_t *link) {
782 */ 768 */
783 for (i = j = 0x0; j < 0x400; j += 0x20) { 769 for (i = j = 0x0; j < 0x400; j += 0x20) {
784 link->io.BasePort1 = j ^ 0x300; 770 link->io.BasePort1 = j ^ 0x300;
785 i = pcmcia_request_io(link->handle, &link->io); 771 i = pcmcia_request_io(link, &link->io);
786 if (i == CS_SUCCESS) break; 772 if (i == CS_SUCCESS) break;
787 } 773 }
788 if (i != CS_SUCCESS) { 774 if (i != CS_SUCCESS) {
789 cs_error(link->handle, RequestIO, i); 775 cs_error(link, RequestIO, i);
790 goto failed; 776 goto failed;
791 } 777 }
792 778
@@ -794,16 +780,16 @@ static void netwave_pcmcia_config(dev_link_t *link) {
794 * Now allocate an interrupt line. Note that this does not 780 * Now allocate an interrupt line. Note that this does not
795 * actually assign a handler to the interrupt. 781 * actually assign a handler to the interrupt.
796 */ 782 */
797 CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq)); 783 CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
798 784
799 /* 785 /*
800 * This actually configures the PCMCIA socket -- setting up 786 * This actually configures the PCMCIA socket -- setting up
801 * the I/O windows and the interrupt mapping. 787 * the I/O windows and the interrupt mapping.
802 */ 788 */
803 CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf)); 789 CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
804 790
805 /* 791 /*
806 * Allocate a 32K memory window. Note that the dev_link_t 792 * Allocate a 32K memory window. Note that the struct pcmcia_device
807 * structure provides space for one window handle -- if your 793 * structure provides space for one window handle -- if your
808 * device needs several windows, you'll need to keep track of 794 * device needs several windows, you'll need to keep track of
809 * the handles in your private data structure, dev->priv. 795 * the handles in your private data structure, dev->priv.
@@ -813,7 +799,7 @@ static void netwave_pcmcia_config(dev_link_t *link) {
813 req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_CM|WIN_ENABLE; 799 req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_CM|WIN_ENABLE;
814 req.Base = 0; req.Size = 0x8000; 800 req.Base = 0; req.Size = 0x8000;
815 req.AccessSpeed = mem_speed; 801 req.AccessSpeed = mem_speed;
816 CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &link->win)); 802 CS_CHECK(RequestWindow, pcmcia_request_window(&link, &req, &link->win));
817 mem.CardOffset = 0x20000; mem.Page = 0; 803 mem.CardOffset = 0x20000; mem.Page = 0;
818 CS_CHECK(MapMemPage, pcmcia_map_mem_page(link->win, &mem)); 804 CS_CHECK(MapMemPage, pcmcia_map_mem_page(link->win, &mem));
819 805
@@ -823,7 +809,7 @@ static void netwave_pcmcia_config(dev_link_t *link) {
823 809
824 dev->irq = link->irq.AssignedIRQ; 810 dev->irq = link->irq.AssignedIRQ;
825 dev->base_addr = link->io.BasePort1; 811 dev->base_addr = link->io.BasePort1;
826 SET_NETDEV_DEV(dev, &handle_to_dev(handle)); 812 SET_NETDEV_DEV(dev, &handle_to_dev(link));
827 813
828 if (register_netdev(dev) != 0) { 814 if (register_netdev(dev) != 0) {
829 printk(KERN_DEBUG "netwave_cs: register_netdev() failed\n"); 815 printk(KERN_DEBUG "netwave_cs: register_netdev() failed\n");
@@ -831,8 +817,7 @@ static void netwave_pcmcia_config(dev_link_t *link) {
831 } 817 }
832 818
833 strcpy(priv->node.dev_name, dev->name); 819 strcpy(priv->node.dev_name, dev->name);
834 link->dev = &priv->node; 820 link->dev_node = &priv->node;
835 link->state &= ~DEV_CONFIG_PENDING;
836 821
837 /* Reset card before reading physical address */ 822 /* Reset card before reading physical address */
838 netwave_doreset(dev->base_addr, ramBase); 823 netwave_doreset(dev->base_addr, ramBase);
@@ -852,12 +837,13 @@ static void netwave_pcmcia_config(dev_link_t *link) {
852 printk(KERN_DEBUG "Netwave_reset: revision %04x %04x\n", 837 printk(KERN_DEBUG "Netwave_reset: revision %04x %04x\n",
853 get_uint16(ramBase + NETWAVE_EREG_ARW), 838 get_uint16(ramBase + NETWAVE_EREG_ARW),
854 get_uint16(ramBase + NETWAVE_EREG_ARW+2)); 839 get_uint16(ramBase + NETWAVE_EREG_ARW+2));
855 return; 840 return 0;
856 841
857cs_failed: 842cs_failed:
858 cs_error(link->handle, last_fn, last_ret); 843 cs_error(link, last_fn, last_ret);
859failed: 844failed:
860 netwave_release(link); 845 netwave_release(link);
846 return -ENODEV;
861} /* netwave_pcmcia_config */ 847} /* netwave_pcmcia_config */
862 848
863/* 849/*
@@ -867,52 +853,35 @@ failed:
867 * device, and release the PCMCIA configuration. If the device is 853 * device, and release the PCMCIA configuration. If the device is
868 * still open, this will be postponed until it is closed. 854 * still open, this will be postponed until it is closed.
869 */ 855 */
870static void netwave_release(dev_link_t *link) 856static void netwave_release(struct pcmcia_device *link)
871{ 857{
872 struct net_device *dev = link->priv; 858 struct net_device *dev = link->priv;
873 netwave_private *priv = netdev_priv(dev); 859 netwave_private *priv = netdev_priv(dev);
874
875 DEBUG(0, "netwave_release(0x%p)\n", link);
876 860
877 /* Don't bother checking to see if these succeed or not */ 861 DEBUG(0, "netwave_release(0x%p)\n", link);
878 if (link->win) {
879 iounmap(priv->ramBase);
880 pcmcia_release_window(link->win);
881 }
882 pcmcia_release_configuration(link->handle);
883 pcmcia_release_io(link->handle, &link->io);
884 pcmcia_release_irq(link->handle, &link->irq);
885 862
886 link->state &= ~DEV_CONFIG; 863 pcmcia_disable_device(link);
864 if (link->win)
865 iounmap(priv->ramBase);
887} 866}
888 867
889static int netwave_suspend(struct pcmcia_device *p_dev) 868static int netwave_suspend(struct pcmcia_device *link)
890{ 869{
891 dev_link_t *link = dev_to_instance(p_dev);
892 struct net_device *dev = link->priv; 870 struct net_device *dev = link->priv;
893 871
894 link->state |= DEV_SUSPEND; 872 if (link->open)
895 if (link->state & DEV_CONFIG) { 873 netif_device_detach(dev);
896 if (link->open)
897 netif_device_detach(dev);
898 pcmcia_release_configuration(link->handle);
899 }
900 874
901 return 0; 875 return 0;
902} 876}
903 877
904static int netwave_resume(struct pcmcia_device *p_dev) 878static int netwave_resume(struct pcmcia_device *link)
905{ 879{
906 dev_link_t *link = dev_to_instance(p_dev);
907 struct net_device *dev = link->priv; 880 struct net_device *dev = link->priv;
908 881
909 link->state &= ~DEV_SUSPEND; 882 if (link->open) {
910 if (link->state & DEV_CONFIG) { 883 netwave_reset(dev);
911 pcmcia_request_configuration(link->handle, &link->conf); 884 netif_device_attach(dev);
912 if (link->open) {
913 netwave_reset(dev);
914 netif_device_attach(dev);
915 }
916 } 885 }
917 886
918 return 0; 887 return 0;
@@ -1119,7 +1088,7 @@ static irqreturn_t netwave_interrupt(int irq, void* dev_id, struct pt_regs *regs
1119 u_char __iomem *ramBase; 1088 u_char __iomem *ramBase;
1120 struct net_device *dev = (struct net_device *)dev_id; 1089 struct net_device *dev = (struct net_device *)dev_id;
1121 struct netwave_private *priv = netdev_priv(dev); 1090 struct netwave_private *priv = netdev_priv(dev);
1122 dev_link_t *link = &priv->link; 1091 struct pcmcia_device *link = priv->p_dev;
1123 int i; 1092 int i;
1124 1093
1125 if (!netif_device_present(dev)) 1094 if (!netif_device_present(dev))
@@ -1138,7 +1107,7 @@ static irqreturn_t netwave_interrupt(int irq, void* dev_id, struct pt_regs *regs
1138 1107
1139 status = inb(iobase + NETWAVE_REG_ASR); 1108 status = inb(iobase + NETWAVE_REG_ASR);
1140 1109
1141 if (!DEV_OK(link)) { 1110 if (!pcmcia_dev_present(link)) {
1142 DEBUG(1, "netwave_interrupt: Interrupt with status 0x%x " 1111 DEBUG(1, "netwave_interrupt: Interrupt with status 0x%x "
1143 "from removed or suspended card!\n", status); 1112 "from removed or suspended card!\n", status);
1144 break; 1113 break;
@@ -1373,11 +1342,11 @@ static int netwave_rx(struct net_device *dev)
1373 1342
1374static int netwave_open(struct net_device *dev) { 1343static int netwave_open(struct net_device *dev) {
1375 netwave_private *priv = netdev_priv(dev); 1344 netwave_private *priv = netdev_priv(dev);
1376 dev_link_t *link = &priv->link; 1345 struct pcmcia_device *link = priv->p_dev;
1377 1346
1378 DEBUG(1, "netwave_open: starting.\n"); 1347 DEBUG(1, "netwave_open: starting.\n");
1379 1348
1380 if (!DEV_OK(link)) 1349 if (!pcmcia_dev_present(link))
1381 return -ENODEV; 1350 return -ENODEV;
1382 1351
1383 link->open++; 1352 link->open++;
@@ -1390,7 +1359,7 @@ static int netwave_open(struct net_device *dev) {
1390 1359
1391static int netwave_close(struct net_device *dev) { 1360static int netwave_close(struct net_device *dev) {
1392 netwave_private *priv = netdev_priv(dev); 1361 netwave_private *priv = netdev_priv(dev);
1393 dev_link_t *link = &priv->link; 1362 struct pcmcia_device *link = priv->p_dev;
1394 1363
1395 DEBUG(1, "netwave_close: finishing.\n"); 1364 DEBUG(1, "netwave_close: finishing.\n");
1396 1365
@@ -1411,7 +1380,7 @@ static struct pcmcia_driver netwave_driver = {
1411 .drv = { 1380 .drv = {
1412 .name = "netwave_cs", 1381 .name = "netwave_cs",
1413 }, 1382 },
1414 .probe = netwave_attach, 1383 .probe = netwave_probe,
1415 .remove = netwave_detach, 1384 .remove = netwave_detach,
1416 .id_table = netwave_ids, 1385 .id_table = netwave_ids,
1417 .suspend = netwave_suspend, 1386 .suspend = netwave_suspend,
diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c
index ec6f2a48895b..434f7d7ad841 100644
--- a/drivers/net/wireless/orinoco_cs.c
+++ b/drivers/net/wireless/orinoco_cs.c
@@ -49,7 +49,7 @@ MODULE_PARM_DESC(ignore_cis_vcc, "Allow voltage mismatch between card and socket
49/* PCMCIA specific device information (goes in the card field of 49/* PCMCIA specific device information (goes in the card field of
50 * struct orinoco_private */ 50 * struct orinoco_private */
51struct orinoco_pccard { 51struct orinoco_pccard {
52 dev_link_t link; 52 struct pcmcia_device *p_dev;
53 dev_node_t node; 53 dev_node_t node;
54 54
55 /* Used to handle hard reset */ 55 /* Used to handle hard reset */
@@ -63,8 +63,8 @@ struct orinoco_pccard {
63/* Function prototypes */ 63/* Function prototypes */
64/********************************************************************/ 64/********************************************************************/
65 65
66static void orinoco_cs_config(dev_link_t *link); 66static int orinoco_cs_config(struct pcmcia_device *link);
67static void orinoco_cs_release(dev_link_t *link); 67static void orinoco_cs_release(struct pcmcia_device *link);
68static void orinoco_cs_detach(struct pcmcia_device *p_dev); 68static void orinoco_cs_detach(struct pcmcia_device *p_dev);
69 69
70/********************************************************************/ 70/********************************************************************/
@@ -75,13 +75,13 @@ static int
75orinoco_cs_hard_reset(struct orinoco_private *priv) 75orinoco_cs_hard_reset(struct orinoco_private *priv)
76{ 76{
77 struct orinoco_pccard *card = priv->card; 77 struct orinoco_pccard *card = priv->card;
78 dev_link_t *link = &card->link; 78 struct pcmcia_device *link = card->p_dev;
79 int err; 79 int err;
80 80
81 /* We need atomic ops here, because we're not holding the lock */ 81 /* We need atomic ops here, because we're not holding the lock */
82 set_bit(0, &card->hard_reset_in_progress); 82 set_bit(0, &card->hard_reset_in_progress);
83 83
84 err = pcmcia_reset_card(link->handle, NULL); 84 err = pcmcia_reset_card(link, NULL);
85 if (err) 85 if (err)
86 return err; 86 return err;
87 87
@@ -104,12 +104,11 @@ orinoco_cs_hard_reset(struct orinoco_private *priv)
104 * configure the card at this point -- we wait until we receive a card 104 * configure the card at this point -- we wait until we receive a card
105 * insertion event. */ 105 * insertion event. */
106static int 106static int
107orinoco_cs_attach(struct pcmcia_device *p_dev) 107orinoco_cs_probe(struct pcmcia_device *link)
108{ 108{
109 struct net_device *dev; 109 struct net_device *dev;
110 struct orinoco_private *priv; 110 struct orinoco_private *priv;
111 struct orinoco_pccard *card; 111 struct orinoco_pccard *card;
112 dev_link_t *link;
113 112
114 dev = alloc_orinocodev(sizeof(*card), orinoco_cs_hard_reset); 113 dev = alloc_orinocodev(sizeof(*card), orinoco_cs_hard_reset);
115 if (! dev) 114 if (! dev)
@@ -118,7 +117,7 @@ orinoco_cs_attach(struct pcmcia_device *p_dev)
118 card = priv->card; 117 card = priv->card;
119 118
120 /* Link both structures together */ 119 /* Link both structures together */
121 link = &card->link; 120 card->p_dev = link;
122 link->priv = dev; 121 link->priv = dev;
123 122
124 /* Interrupt setup */ 123 /* Interrupt setup */
@@ -135,16 +134,7 @@ orinoco_cs_attach(struct pcmcia_device *p_dev)
135 link->conf.Attributes = 0; 134 link->conf.Attributes = 0;
136 link->conf.IntType = INT_MEMORY_AND_IO; 135 link->conf.IntType = INT_MEMORY_AND_IO;
137 136
138 /* Register with Card Services */ 137 return orinoco_cs_config(link);
139 link->next = NULL;
140
141 link->handle = p_dev;
142 p_dev->instance = link;
143
144 link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
145 orinoco_cs_config(link);
146
147 return 0;
148} /* orinoco_cs_attach */ 138} /* orinoco_cs_attach */
149 139
150/* 140/*
@@ -153,16 +143,14 @@ orinoco_cs_attach(struct pcmcia_device *p_dev)
153 * are freed. Otherwise, the structures will be freed when the device 143 * are freed. Otherwise, the structures will be freed when the device
154 * is released. 144 * is released.
155 */ 145 */
156static void orinoco_cs_detach(struct pcmcia_device *p_dev) 146static void orinoco_cs_detach(struct pcmcia_device *link)
157{ 147{
158 dev_link_t *link = dev_to_instance(p_dev);
159 struct net_device *dev = link->priv; 148 struct net_device *dev = link->priv;
160 149
161 if (link->state & DEV_CONFIG) 150 orinoco_cs_release(link);
162 orinoco_cs_release(link);
163 151
164 DEBUG(0, PFX "detach: link=%p link->dev=%p\n", link, link->dev); 152 DEBUG(0, PFX "detach: link=%p link->dev_node=%p\n", link, link->dev_node);
165 if (link->dev) { 153 if (link->dev_node) {
166 DEBUG(0, PFX "About to unregister net device %p\n", 154 DEBUG(0, PFX "About to unregister net device %p\n",
167 dev); 155 dev);
168 unregister_netdev(dev); 156 unregister_netdev(dev);
@@ -180,11 +168,10 @@ static void orinoco_cs_detach(struct pcmcia_device *p_dev)
180 last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; \ 168 last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; \
181 } while (0) 169 } while (0)
182 170
183static void 171static int
184orinoco_cs_config(dev_link_t *link) 172orinoco_cs_config(struct pcmcia_device *link)
185{ 173{
186 struct net_device *dev = link->priv; 174 struct net_device *dev = link->priv;
187 client_handle_t handle = link->handle;
188 struct orinoco_private *priv = netdev_priv(dev); 175 struct orinoco_private *priv = netdev_priv(dev);
189 struct orinoco_pccard *card = priv->card; 176 struct orinoco_pccard *card = priv->card;
190 hermes_t *hw = &priv->hw; 177 hermes_t *hw = &priv->hw;
@@ -196,7 +183,7 @@ orinoco_cs_config(dev_link_t *link)
196 cisparse_t parse; 183 cisparse_t parse;
197 void __iomem *mem; 184 void __iomem *mem;
198 185
199 CS_CHECK(ValidateCIS, pcmcia_validate_cis(handle, &info)); 186 CS_CHECK(ValidateCIS, pcmcia_validate_cis(link, &info));
200 187
201 /* 188 /*
202 * This reads the card's CONFIG tuple to find its 189 * This reads the card's CONFIG tuple to find its
@@ -207,19 +194,15 @@ orinoco_cs_config(dev_link_t *link)
207 tuple.TupleData = buf; 194 tuple.TupleData = buf;
208 tuple.TupleDataMax = sizeof(buf); 195 tuple.TupleDataMax = sizeof(buf);
209 tuple.TupleOffset = 0; 196 tuple.TupleOffset = 0;
210 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); 197 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
211 CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); 198 CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
212 CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); 199 CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
213 link->conf.ConfigBase = parse.config.base; 200 link->conf.ConfigBase = parse.config.base;
214 link->conf.Present = parse.config.rmask[0]; 201 link->conf.Present = parse.config.rmask[0];
215 202
216 /* Configure card */
217 link->state |= DEV_CONFIG;
218
219 /* Look up the current Vcc */ 203 /* Look up the current Vcc */
220 CS_CHECK(GetConfigurationInfo, 204 CS_CHECK(GetConfigurationInfo,
221 pcmcia_get_configuration_info(handle, &conf)); 205 pcmcia_get_configuration_info(link, &conf));
222 link->conf.Vcc = conf.Vcc;
223 206
224 /* 207 /*
225 * In this loop, we scan the CIS for configuration table 208 * In this loop, we scan the CIS for configuration table
@@ -236,13 +219,13 @@ orinoco_cs_config(dev_link_t *link)
236 * implementation-defined details. 219 * implementation-defined details.
237 */ 220 */
238 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; 221 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
239 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); 222 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
240 while (1) { 223 while (1) {
241 cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); 224 cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
242 cistpl_cftable_entry_t dflt = { .index = 0 }; 225 cistpl_cftable_entry_t dflt = { .index = 0 };
243 226
244 if ( (pcmcia_get_tuple_data(handle, &tuple) != 0) 227 if ( (pcmcia_get_tuple_data(link, &tuple) != 0)
245 || (pcmcia_parse_tuple(handle, &tuple, &parse) != 0)) 228 || (pcmcia_parse_tuple(link, &tuple, &parse) != 0))
246 goto next_entry; 229 goto next_entry;
247 230
248 if (cfg->flags & CISTPL_CFTABLE_DEFAULT) 231 if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
@@ -274,10 +257,10 @@ orinoco_cs_config(dev_link_t *link)
274 } 257 }
275 258
276 if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) 259 if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
277 link->conf.Vpp1 = link->conf.Vpp2 = 260 link->conf.Vpp =
278 cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; 261 cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
279 else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM)) 262 else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM))
280 link->conf.Vpp1 = link->conf.Vpp2 = 263 link->conf.Vpp =
281 dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000; 264 dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
282 265
283 /* Do we need to allocate an interrupt? */ 266 /* Do we need to allocate an interrupt? */
@@ -307,7 +290,7 @@ orinoco_cs_config(dev_link_t *link)
307 } 290 }
308 291
309 /* This reserves IO space but doesn't actually enable it */ 292 /* This reserves IO space but doesn't actually enable it */
310 if (pcmcia_request_io(link->handle, &link->io) != 0) 293 if (pcmcia_request_io(link, &link->io) != 0)
311 goto next_entry; 294 goto next_entry;
312 } 295 }
313 296
@@ -317,9 +300,8 @@ orinoco_cs_config(dev_link_t *link)
317 break; 300 break;
318 301
319 next_entry: 302 next_entry:
320 if (link->io.NumPorts1) 303 pcmcia_disable_device(link);
321 pcmcia_release_io(link->handle, &link->io); 304 last_ret = pcmcia_get_next_tuple(link, &tuple);
322 last_ret = pcmcia_get_next_tuple(handle, &tuple);
323 if (last_ret == CS_NO_MORE_ITEMS) { 305 if (last_ret == CS_NO_MORE_ITEMS) {
324 printk(KERN_ERR PFX "GetNextTuple(): No matching " 306 printk(KERN_ERR PFX "GetNextTuple(): No matching "
325 "CIS configuration. Maybe you need the " 307 "CIS configuration. Maybe you need the "
@@ -333,7 +315,7 @@ orinoco_cs_config(dev_link_t *link)
333 * a handler to the interrupt, unless the 'Handler' member of 315 * a handler to the interrupt, unless the 'Handler' member of
334 * the irq structure is initialized. 316 * the irq structure is initialized.
335 */ 317 */
336 CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq)); 318 CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
337 319
338 /* We initialize the hermes structure before completing PCMCIA 320 /* We initialize the hermes structure before completing PCMCIA
339 * configuration just in case the interrupt handler gets 321 * configuration just in case the interrupt handler gets
@@ -350,7 +332,7 @@ orinoco_cs_config(dev_link_t *link)
350 * card and host interface into "Memory and IO" mode. 332 * card and host interface into "Memory and IO" mode.
351 */ 333 */
352 CS_CHECK(RequestConfiguration, 334 CS_CHECK(RequestConfiguration,
353 pcmcia_request_configuration(link->handle, &link->conf)); 335 pcmcia_request_configuration(link, &link->conf));
354 336
355 /* Ok, we have the configuration, prepare to register the netdev */ 337 /* Ok, we have the configuration, prepare to register the netdev */
356 dev->base_addr = link->io.BasePort1; 338 dev->base_addr = link->io.BasePort1;
@@ -358,7 +340,7 @@ orinoco_cs_config(dev_link_t *link)
358 SET_MODULE_OWNER(dev); 340 SET_MODULE_OWNER(dev);
359 card->node.major = card->node.minor = 0; 341 card->node.major = card->node.minor = 0;
360 342
361 SET_NETDEV_DEV(dev, &handle_to_dev(handle)); 343 SET_NETDEV_DEV(dev, &handle_to_dev(link));
362 /* Tell the stack we exist */ 344 /* Tell the stack we exist */
363 if (register_netdev(dev) != 0) { 345 if (register_netdev(dev) != 0) {
364 printk(KERN_ERR PFX "register_netdev() failed\n"); 346 printk(KERN_ERR PFX "register_netdev() failed\n");
@@ -366,20 +348,18 @@ orinoco_cs_config(dev_link_t *link)
366 } 348 }
367 349
368 /* At this point, the dev_node_t structure(s) needs to be 350 /* At this point, the dev_node_t structure(s) needs to be
369 * initialized and arranged in a linked list at link->dev. */ 351 * initialized and arranged in a linked list at link->dev_node. */
370 strcpy(card->node.dev_name, dev->name); 352 strcpy(card->node.dev_name, dev->name);
371 link->dev = &card->node; /* link->dev being non-NULL is also 353 link->dev_node = &card->node; /* link->dev_node being non-NULL is also
372 used to indicate that the 354 used to indicate that the
373 net_device has been registered */ 355 net_device has been registered */
374 link->state &= ~DEV_CONFIG_PENDING;
375 356
376 /* Finally, report what we've done */ 357 /* Finally, report what we've done */
377 printk(KERN_DEBUG "%s: index 0x%02x: Vcc %d.%d", 358 printk(KERN_DEBUG "%s: index 0x%02x: ",
378 dev->name, link->conf.ConfigIndex, 359 dev->name, link->conf.ConfigIndex);
379 link->conf.Vcc / 10, link->conf.Vcc % 10); 360 if (link->conf.Vpp)
380 if (link->conf.Vpp1) 361 printk(", Vpp %d.%d", link->conf.Vpp / 10,
381 printk(", Vpp %d.%d", link->conf.Vpp1 / 10, 362 link->conf.Vpp % 10);
382 link->conf.Vpp1 % 10);
383 printk(", irq %d", link->irq.AssignedIRQ); 363 printk(", irq %d", link->irq.AssignedIRQ);
384 if (link->io.NumPorts1) 364 if (link->io.NumPorts1)
385 printk(", io 0x%04x-0x%04x", link->io.BasePort1, 365 printk(", io 0x%04x-0x%04x", link->io.BasePort1,
@@ -389,13 +369,14 @@ orinoco_cs_config(dev_link_t *link)
389 link->io.BasePort2 + link->io.NumPorts2 - 1); 369 link->io.BasePort2 + link->io.NumPorts2 - 1);
390 printk("\n"); 370 printk("\n");
391 371
392 return; 372 return 0;
393 373
394 cs_failed: 374 cs_failed:
395 cs_error(link->handle, last_fn, last_ret); 375 cs_error(link, last_fn, last_ret);
396 376
397 failed: 377 failed:
398 orinoco_cs_release(link); 378 orinoco_cs_release(link);
379 return -ENODEV;
399} /* orinoco_cs_config */ 380} /* orinoco_cs_config */
400 381
401/* 382/*
@@ -404,7 +385,7 @@ orinoco_cs_config(dev_link_t *link)
404 * still open, this will be postponed until it is closed. 385 * still open, this will be postponed until it is closed.
405 */ 386 */
406static void 387static void
407orinoco_cs_release(dev_link_t *link) 388orinoco_cs_release(struct pcmcia_device *link)
408{ 389{
409 struct net_device *dev = link->priv; 390 struct net_device *dev = link->priv;
410 struct orinoco_private *priv = netdev_priv(dev); 391 struct orinoco_private *priv = netdev_priv(dev);
@@ -416,88 +397,68 @@ orinoco_cs_release(dev_link_t *link)
416 priv->hw_unavailable++; 397 priv->hw_unavailable++;
417 spin_unlock_irqrestore(&priv->lock, flags); 398 spin_unlock_irqrestore(&priv->lock, flags);
418 399
419 /* Don't bother checking to see if these succeed or not */ 400 pcmcia_disable_device(link);
420 pcmcia_release_configuration(link->handle);
421 if (link->io.NumPorts1)
422 pcmcia_release_io(link->handle, &link->io);
423 if (link->irq.AssignedIRQ)
424 pcmcia_release_irq(link->handle, &link->irq);
425 link->state &= ~DEV_CONFIG;
426 if (priv->hw.iobase) 401 if (priv->hw.iobase)
427 ioport_unmap(priv->hw.iobase); 402 ioport_unmap(priv->hw.iobase);
428} /* orinoco_cs_release */ 403} /* orinoco_cs_release */
429 404
430static int orinoco_cs_suspend(struct pcmcia_device *p_dev) 405static int orinoco_cs_suspend(struct pcmcia_device *link)
431{ 406{
432 dev_link_t *link = dev_to_instance(p_dev);
433 struct net_device *dev = link->priv; 407 struct net_device *dev = link->priv;
434 struct orinoco_private *priv = netdev_priv(dev); 408 struct orinoco_private *priv = netdev_priv(dev);
435 struct orinoco_pccard *card = priv->card; 409 struct orinoco_pccard *card = priv->card;
436 int err = 0; 410 int err = 0;
437 unsigned long flags; 411 unsigned long flags;
438 412
439 link->state |= DEV_SUSPEND; 413 /* This is probably racy, but I can't think of
440 if (link->state & DEV_CONFIG) { 414 a better way, short of rewriting the PCMCIA
441 /* This is probably racy, but I can't think of 415 layer to not suck :-( */
442 a better way, short of rewriting the PCMCIA 416 if (! test_bit(0, &card->hard_reset_in_progress)) {
443 layer to not suck :-( */ 417 spin_lock_irqsave(&priv->lock, flags);
444 if (! test_bit(0, &card->hard_reset_in_progress)) {
445 spin_lock_irqsave(&priv->lock, flags);
446 418
447 err = __orinoco_down(dev); 419 err = __orinoco_down(dev);
448 if (err) 420 if (err)
449 printk(KERN_WARNING "%s: Error %d downing interface\n", 421 printk(KERN_WARNING "%s: Error %d downing interface\n",
450 dev->name, err); 422 dev->name, err);
451 423
452 netif_device_detach(dev); 424 netif_device_detach(dev);
453 priv->hw_unavailable++; 425 priv->hw_unavailable++;
454 426
455 spin_unlock_irqrestore(&priv->lock, flags); 427 spin_unlock_irqrestore(&priv->lock, flags);
456 }
457
458 pcmcia_release_configuration(link->handle);
459 } 428 }
460 429
461 return 0; 430 return 0;
462} 431}
463 432
464static int orinoco_cs_resume(struct pcmcia_device *p_dev) 433static int orinoco_cs_resume(struct pcmcia_device *link)
465{ 434{
466 dev_link_t *link = dev_to_instance(p_dev);
467 struct net_device *dev = link->priv; 435 struct net_device *dev = link->priv;
468 struct orinoco_private *priv = netdev_priv(dev); 436 struct orinoco_private *priv = netdev_priv(dev);
469 struct orinoco_pccard *card = priv->card; 437 struct orinoco_pccard *card = priv->card;
470 int err = 0; 438 int err = 0;
471 unsigned long flags; 439 unsigned long flags;
472 440
473 link->state &= ~DEV_SUSPEND; 441 if (! test_bit(0, &card->hard_reset_in_progress)) {
474 if (link->state & DEV_CONFIG) { 442 err = orinoco_reinit_firmware(dev);
475 /* FIXME: should we double check that this is 443 if (err) {
476 * the same card as we had before */ 444 printk(KERN_ERR "%s: Error %d re-initializing firmware\n",
477 pcmcia_request_configuration(link->handle, &link->conf); 445 dev->name, err);
478 446 return -EIO;
479 if (! test_bit(0, &card->hard_reset_in_progress)) { 447 }
480 err = orinoco_reinit_firmware(dev);
481 if (err) {
482 printk(KERN_ERR "%s: Error %d re-initializing firmware\n",
483 dev->name, err);
484 return -EIO;
485 }
486
487 spin_lock_irqsave(&priv->lock, flags);
488 448
489 netif_device_attach(dev); 449 spin_lock_irqsave(&priv->lock, flags);
490 priv->hw_unavailable--;
491 450
492 if (priv->open && ! priv->hw_unavailable) { 451 netif_device_attach(dev);
493 err = __orinoco_up(dev); 452 priv->hw_unavailable--;
494 if (err)
495 printk(KERN_ERR "%s: Error %d restarting card\n",
496 dev->name, err);
497 }
498 453
499 spin_unlock_irqrestore(&priv->lock, flags); 454 if (priv->open && ! priv->hw_unavailable) {
455 err = __orinoco_up(dev);
456 if (err)
457 printk(KERN_ERR "%s: Error %d restarting card\n",
458 dev->name, err);
500 } 459 }
460
461 spin_unlock_irqrestore(&priv->lock, flags);
501 } 462 }
502 463
503 return 0; 464 return 0;
@@ -604,7 +565,7 @@ static struct pcmcia_driver orinoco_driver = {
604 .drv = { 565 .drv = {
605 .name = DRIVER_NAME, 566 .name = DRIVER_NAME,
606 }, 567 },
607 .probe = orinoco_cs_attach, 568 .probe = orinoco_cs_probe,
608 .remove = orinoco_cs_detach, 569 .remove = orinoco_cs_detach,
609 .id_table = orinoco_cs_ids, 570 .id_table = orinoco_cs_ids,
610 .suspend = orinoco_cs_suspend, 571 .suspend = orinoco_cs_suspend,
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c
index 7880d8c31aad..879eb427607c 100644
--- a/drivers/net/wireless/ray_cs.c
+++ b/drivers/net/wireless/ray_cs.c
@@ -90,8 +90,8 @@ module_param(pc_debug, int, 0);
90#define DEBUG(n, args...) 90#define DEBUG(n, args...)
91#endif 91#endif
92/** Prototypes based on PCMCIA skeleton driver *******************************/ 92/** Prototypes based on PCMCIA skeleton driver *******************************/
93static void ray_config(dev_link_t *link); 93static int ray_config(struct pcmcia_device *link);
94static void ray_release(dev_link_t *link); 94static void ray_release(struct pcmcia_device *link);
95static void ray_detach(struct pcmcia_device *p_dev); 95static void ray_detach(struct pcmcia_device *p_dev);
96 96
97/***** Prototypes indicated by device structure ******************************/ 97/***** Prototypes indicated by device structure ******************************/
@@ -190,20 +190,17 @@ static int bc;
190static char *phy_addr = NULL; 190static char *phy_addr = NULL;
191 191
192 192
193/* A linked list of "instances" of the ray device. Each actual 193/* A struct pcmcia_device structure has fields for most things that are needed
194 PCMCIA card corresponds to one device instance, and is described
195 by one dev_link_t structure (defined in ds.h).
196*/
197static dev_link_t *dev_list = NULL;
198
199/* A dev_link_t structure has fields for most things that are needed
200 to keep track of a socket, but there will usually be some device 194 to keep track of a socket, but there will usually be some device
201 specific information that also needs to be kept track of. The 195 specific information that also needs to be kept track of. The
202 'priv' pointer in a dev_link_t structure can be used to point to 196 'priv' pointer in a struct pcmcia_device structure can be used to point to
203 a device-specific private data structure, like this. 197 a device-specific private data structure, like this.
204*/ 198*/
205static unsigned int ray_mem_speed = 500; 199static unsigned int ray_mem_speed = 500;
206 200
201/* WARNING: THIS DRIVER IS NOT CAPABLE OF HANDLING MULTIPLE DEVICES! */
202static struct pcmcia_device *this_device = NULL;
203
207MODULE_AUTHOR("Corey Thomas <corey@world.std.com>"); 204MODULE_AUTHOR("Corey Thomas <corey@world.std.com>");
208MODULE_DESCRIPTION("Raylink/WebGear wireless LAN driver"); 205MODULE_DESCRIPTION("Raylink/WebGear wireless LAN driver");
209MODULE_LICENSE("GPL"); 206MODULE_LICENSE("GPL");
@@ -306,56 +303,46 @@ static char rcsid[] = "Raylink/WebGear wireless LAN - Corey <Thomas corey@world.
306 configure the card at this point -- we wait until we receive a 303 configure the card at this point -- we wait until we receive a
307 card insertion event. 304 card insertion event.
308=============================================================================*/ 305=============================================================================*/
309static int ray_attach(struct pcmcia_device *p_dev) 306static int ray_probe(struct pcmcia_device *p_dev)
310{ 307{
311 dev_link_t *link;
312 ray_dev_t *local; 308 ray_dev_t *local;
313 struct net_device *dev; 309 struct net_device *dev;
314
315 DEBUG(1, "ray_attach()\n");
316 310
317 /* Initialize the dev_link_t structure */ 311 DEBUG(1, "ray_attach()\n");
318 link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
319
320 if (!link)
321 return -ENOMEM;
322 312
323 /* Allocate space for private device-specific data */ 313 /* Allocate space for private device-specific data */
324 dev = alloc_etherdev(sizeof(ray_dev_t)); 314 dev = alloc_etherdev(sizeof(ray_dev_t));
325
326 if (!dev) 315 if (!dev)
327 goto fail_alloc_dev; 316 goto fail_alloc_dev;
328 317
329 local = dev->priv; 318 local = dev->priv;
330 319 local->finder = p_dev;
331 memset(link, 0, sizeof(struct dev_link_t));
332 320
333 /* The io structure describes IO port mapping. None used here */ 321 /* The io structure describes IO port mapping. None used here */
334 link->io.NumPorts1 = 0; 322 p_dev->io.NumPorts1 = 0;
335 link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; 323 p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
336 link->io.IOAddrLines = 5; 324 p_dev->io.IOAddrLines = 5;
337 325
338 /* Interrupt setup. For PCMCIA, driver takes what's given */ 326 /* Interrupt setup. For PCMCIA, driver takes what's given */
339 link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; 327 p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
340 link->irq.IRQInfo1 = IRQ_LEVEL_ID; 328 p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID;
341 link->irq.Handler = &ray_interrupt; 329 p_dev->irq.Handler = &ray_interrupt;
342 330
343 /* General socket configuration */ 331 /* General socket configuration */
344 link->conf.Attributes = CONF_ENABLE_IRQ; 332 p_dev->conf.Attributes = CONF_ENABLE_IRQ;
345 link->conf.Vcc = 50; 333 p_dev->conf.IntType = INT_MEMORY_AND_IO;
346 link->conf.IntType = INT_MEMORY_AND_IO; 334 p_dev->conf.ConfigIndex = 1;
347 link->conf.ConfigIndex = 1; 335 p_dev->conf.Present = PRESENT_OPTION;
348 link->conf.Present = PRESENT_OPTION; 336
349 337 p_dev->priv = dev;
350 link->priv = dev; 338 p_dev->irq.Instance = dev;
351 link->irq.Instance = dev;
352 339
353 local->finder = link; 340 local->finder = p_dev;
354 local->card_status = CARD_INSERTED; 341 local->card_status = CARD_INSERTED;
355 local->authentication_state = UNAUTHENTICATED; 342 local->authentication_state = UNAUTHENTICATED;
356 local->num_multi = 0; 343 local->num_multi = 0;
357 DEBUG(2,"ray_attach link = %p, dev = %p, local = %p, intr = %p\n", 344 DEBUG(2,"ray_attach p_dev = %p, dev = %p, local = %p, intr = %p\n",
358 link,dev,local,&ray_interrupt); 345 p_dev,dev,local,&ray_interrupt);
359 346
360 /* Raylink entries in the device structure */ 347 /* Raylink entries in the device structure */
361 dev->hard_start_xmit = &ray_dev_start_xmit; 348 dev->hard_start_xmit = &ray_dev_start_xmit;
@@ -379,16 +366,10 @@ static int ray_attach(struct pcmcia_device *p_dev)
379 366
380 init_timer(&local->timer); 367 init_timer(&local->timer);
381 368
382 link->handle = p_dev; 369 this_device = p_dev;
383 p_dev->instance = link; 370 return ray_config(p_dev);
384
385 link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
386 ray_config(link);
387
388 return 0;
389 371
390fail_alloc_dev: 372fail_alloc_dev:
391 kfree(link);
392 return -ENOMEM; 373 return -ENOMEM;
393} /* ray_attach */ 374} /* ray_attach */
394/*============================================================================= 375/*=============================================================================
@@ -397,37 +378,25 @@ fail_alloc_dev:
397 structures are freed. Otherwise, the structures will be freed 378 structures are freed. Otherwise, the structures will be freed
398 when the device is released. 379 when the device is released.
399=============================================================================*/ 380=============================================================================*/
400static void ray_detach(struct pcmcia_device *p_dev) 381static void ray_detach(struct pcmcia_device *link)
401{ 382{
402 dev_link_t *link = dev_to_instance(p_dev);
403 dev_link_t **linkp;
404 struct net_device *dev; 383 struct net_device *dev;
405 ray_dev_t *local; 384 ray_dev_t *local;
406 385
407 DEBUG(1, "ray_detach(0x%p)\n", link); 386 DEBUG(1, "ray_detach(0x%p)\n", link);
408
409 /* Locate device structure */
410 for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
411 if (*linkp == link) break;
412 if (*linkp == NULL)
413 return;
414 387
388 this_device = NULL;
415 dev = link->priv; 389 dev = link->priv;
416 390
417 if (link->state & DEV_CONFIG) { 391 ray_release(link);
418 ray_release(link);
419 392
420 local = (ray_dev_t *)dev->priv; 393 local = (ray_dev_t *)dev->priv;
421 del_timer(&local->timer); 394 del_timer(&local->timer);
422 }
423 395
424 /* Unlink device structure, free pieces */
425 *linkp = link->next;
426 if (link->priv) { 396 if (link->priv) {
427 if (link->dev) unregister_netdev(dev); 397 if (link->dev_node) unregister_netdev(dev);
428 free_netdev(dev); 398 free_netdev(dev);
429 } 399 }
430 kfree(link);
431 DEBUG(2,"ray_cs ray_detach ending\n"); 400 DEBUG(2,"ray_cs ray_detach ending\n");
432} /* ray_detach */ 401} /* ray_detach */
433/*============================================================================= 402/*=============================================================================
@@ -438,9 +407,8 @@ static void ray_detach(struct pcmcia_device *p_dev)
438#define CS_CHECK(fn, ret) \ 407#define CS_CHECK(fn, ret) \
439do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) 408do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
440#define MAX_TUPLE_SIZE 128 409#define MAX_TUPLE_SIZE 128
441static void ray_config(dev_link_t *link) 410static int ray_config(struct pcmcia_device *link)
442{ 411{
443 client_handle_t handle = link->handle;
444 tuple_t tuple; 412 tuple_t tuple;
445 cisparse_t parse; 413 cisparse_t parse;
446 int last_fn = 0, last_ret = 0; 414 int last_fn = 0, last_ret = 0;
@@ -455,48 +423,45 @@ static void ray_config(dev_link_t *link)
455 423
456 /* This reads the card's CONFIG tuple to find its configuration regs */ 424 /* This reads the card's CONFIG tuple to find its configuration regs */
457 tuple.DesiredTuple = CISTPL_CONFIG; 425 tuple.DesiredTuple = CISTPL_CONFIG;
458 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); 426 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
459 tuple.TupleData = buf; 427 tuple.TupleData = buf;
460 tuple.TupleDataMax = MAX_TUPLE_SIZE; 428 tuple.TupleDataMax = MAX_TUPLE_SIZE;
461 tuple.TupleOffset = 0; 429 tuple.TupleOffset = 0;
462 CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); 430 CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
463 CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); 431 CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
464 link->conf.ConfigBase = parse.config.base; 432 link->conf.ConfigBase = parse.config.base;
465 link->conf.Present = parse.config.rmask[0]; 433 link->conf.Present = parse.config.rmask[0];
466 434
467 /* Determine card type and firmware version */ 435 /* Determine card type and firmware version */
468 buf[0] = buf[MAX_TUPLE_SIZE - 1] = 0; 436 buf[0] = buf[MAX_TUPLE_SIZE - 1] = 0;
469 tuple.DesiredTuple = CISTPL_VERS_1; 437 tuple.DesiredTuple = CISTPL_VERS_1;
470 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); 438 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
471 tuple.TupleData = buf; 439 tuple.TupleData = buf;
472 tuple.TupleDataMax = MAX_TUPLE_SIZE; 440 tuple.TupleDataMax = MAX_TUPLE_SIZE;
473 tuple.TupleOffset = 2; 441 tuple.TupleOffset = 2;
474 CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); 442 CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
475 443
476 for (i=0; i<tuple.TupleDataLen - 4; i++) 444 for (i=0; i<tuple.TupleDataLen - 4; i++)
477 if (buf[i] == 0) buf[i] = ' '; 445 if (buf[i] == 0) buf[i] = ' ';
478 printk(KERN_INFO "ray_cs Detected: %s\n",buf); 446 printk(KERN_INFO "ray_cs Detected: %s\n",buf);
479 447
480 /* Configure card */
481 link->state |= DEV_CONFIG;
482
483 /* Now allocate an interrupt line. Note that this does not 448 /* Now allocate an interrupt line. Note that this does not
484 actually assign a handler to the interrupt. 449 actually assign a handler to the interrupt.
485 */ 450 */
486 CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq)); 451 CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
487 dev->irq = link->irq.AssignedIRQ; 452 dev->irq = link->irq.AssignedIRQ;
488 453
489 /* This actually configures the PCMCIA socket -- setting up 454 /* This actually configures the PCMCIA socket -- setting up
490 the I/O windows and the interrupt mapping. 455 the I/O windows and the interrupt mapping.
491 */ 456 */
492 CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf)); 457 CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
493 458
494/*** Set up 32k window for shared memory (transmit and control) ************/ 459/*** Set up 32k window for shared memory (transmit and control) ************/
495 req.Attributes = WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_CM | WIN_ENABLE | WIN_USE_WAIT; 460 req.Attributes = WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_CM | WIN_ENABLE | WIN_USE_WAIT;
496 req.Base = 0; 461 req.Base = 0;
497 req.Size = 0x8000; 462 req.Size = 0x8000;
498 req.AccessSpeed = ray_mem_speed; 463 req.AccessSpeed = ray_mem_speed;
499 CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &link->win)); 464 CS_CHECK(RequestWindow, pcmcia_request_window(&link, &req, &link->win));
500 mem.CardOffset = 0x0000; mem.Page = 0; 465 mem.CardOffset = 0x0000; mem.Page = 0;
501 CS_CHECK(MapMemPage, pcmcia_map_mem_page(link->win, &mem)); 466 CS_CHECK(MapMemPage, pcmcia_map_mem_page(link->win, &mem));
502 local->sram = ioremap(req.Base,req.Size); 467 local->sram = ioremap(req.Base,req.Size);
@@ -506,7 +471,7 @@ static void ray_config(dev_link_t *link)
506 req.Base = 0; 471 req.Base = 0;
507 req.Size = 0x4000; 472 req.Size = 0x4000;
508 req.AccessSpeed = ray_mem_speed; 473 req.AccessSpeed = ray_mem_speed;
509 CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &local->rmem_handle)); 474 CS_CHECK(RequestWindow, pcmcia_request_window(&link, &req, &local->rmem_handle));
510 mem.CardOffset = 0x8000; mem.Page = 0; 475 mem.CardOffset = 0x8000; mem.Page = 0;
511 CS_CHECK(MapMemPage, pcmcia_map_mem_page(local->rmem_handle, &mem)); 476 CS_CHECK(MapMemPage, pcmcia_map_mem_page(local->rmem_handle, &mem));
512 local->rmem = ioremap(req.Base,req.Size); 477 local->rmem = ioremap(req.Base,req.Size);
@@ -516,7 +481,7 @@ static void ray_config(dev_link_t *link)
516 req.Base = 0; 481 req.Base = 0;
517 req.Size = 0x1000; 482 req.Size = 0x1000;
518 req.AccessSpeed = ray_mem_speed; 483 req.AccessSpeed = ray_mem_speed;
519 CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &local->amem_handle)); 484 CS_CHECK(RequestWindow, pcmcia_request_window(&link, &req, &local->amem_handle));
520 mem.CardOffset = 0x0000; mem.Page = 0; 485 mem.CardOffset = 0x0000; mem.Page = 0;
521 CS_CHECK(MapMemPage, pcmcia_map_mem_page(local->amem_handle, &mem)); 486 CS_CHECK(MapMemPage, pcmcia_map_mem_page(local->amem_handle, &mem));
522 local->amem = ioremap(req.Base,req.Size); 487 local->amem = ioremap(req.Base,req.Size);
@@ -526,32 +491,32 @@ static void ray_config(dev_link_t *link)
526 DEBUG(3,"ray_config amem=%p\n",local->amem); 491 DEBUG(3,"ray_config amem=%p\n",local->amem);
527 if (ray_init(dev) < 0) { 492 if (ray_init(dev) < 0) {
528 ray_release(link); 493 ray_release(link);
529 return; 494 return -ENODEV;
530 } 495 }
531 496
532 SET_NETDEV_DEV(dev, &handle_to_dev(handle)); 497 SET_NETDEV_DEV(dev, &handle_to_dev(link));
533 i = register_netdev(dev); 498 i = register_netdev(dev);
534 if (i != 0) { 499 if (i != 0) {
535 printk("ray_config register_netdev() failed\n"); 500 printk("ray_config register_netdev() failed\n");
536 ray_release(link); 501 ray_release(link);
537 return; 502 return i;
538 } 503 }
539 504
540 strcpy(local->node.dev_name, dev->name); 505 strcpy(local->node.dev_name, dev->name);
541 link->dev = &local->node; 506 link->dev_node = &local->node;
542 507
543 link->state &= ~DEV_CONFIG_PENDING;
544 printk(KERN_INFO "%s: RayLink, irq %d, hw_addr ", 508 printk(KERN_INFO "%s: RayLink, irq %d, hw_addr ",
545 dev->name, dev->irq); 509 dev->name, dev->irq);
546 for (i = 0; i < 6; i++) 510 for (i = 0; i < 6; i++)
547 printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n")); 511 printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n"));
548 512
549 return; 513 return 0;
550 514
551cs_failed: 515cs_failed:
552 cs_error(link->handle, last_fn, last_ret); 516 cs_error(link, last_fn, last_ret);
553 517
554 ray_release(link); 518 ray_release(link);
519 return -ENODEV;
555} /* ray_config */ 520} /* ray_config */
556 521
557static inline struct ccs __iomem *ccs_base(ray_dev_t *dev) 522static inline struct ccs __iomem *ccs_base(ray_dev_t *dev)
@@ -578,9 +543,9 @@ static int ray_init(struct net_device *dev)
578 UCHAR *p; 543 UCHAR *p;
579 struct ccs __iomem *pccs; 544 struct ccs __iomem *pccs;
580 ray_dev_t *local = (ray_dev_t *)dev->priv; 545 ray_dev_t *local = (ray_dev_t *)dev->priv;
581 dev_link_t *link = local->finder; 546 struct pcmcia_device *link = local->finder;
582 DEBUG(1, "ray_init(0x%p)\n", dev); 547 DEBUG(1, "ray_init(0x%p)\n", dev);
583 if (!(link->state & DEV_PRESENT)) { 548 if (!(pcmcia_dev_present(link))) {
584 DEBUG(0,"ray_init - device not present\n"); 549 DEBUG(0,"ray_init - device not present\n");
585 return -1; 550 return -1;
586 } 551 }
@@ -640,10 +605,10 @@ static int dl_startup_params(struct net_device *dev)
640 int ccsindex; 605 int ccsindex;
641 ray_dev_t *local = (ray_dev_t *)dev->priv; 606 ray_dev_t *local = (ray_dev_t *)dev->priv;
642 struct ccs __iomem *pccs; 607 struct ccs __iomem *pccs;
643 dev_link_t *link = local->finder; 608 struct pcmcia_device *link = local->finder;
644 609
645 DEBUG(1,"dl_startup_params entered\n"); 610 DEBUG(1,"dl_startup_params entered\n");
646 if (!(link->state & DEV_PRESENT)) { 611 if (!(pcmcia_dev_present(link))) {
647 DEBUG(2,"ray_cs dl_startup_params - device not present\n"); 612 DEBUG(2,"ray_cs dl_startup_params - device not present\n");
648 return -1; 613 return -1;
649 } 614 }
@@ -747,9 +712,9 @@ static void verify_dl_startup(u_long data)
747 ray_dev_t *local = (ray_dev_t *)data; 712 ray_dev_t *local = (ray_dev_t *)data;
748 struct ccs __iomem *pccs = ccs_base(local) + local->dl_param_ccs; 713 struct ccs __iomem *pccs = ccs_base(local) + local->dl_param_ccs;
749 UCHAR status; 714 UCHAR status;
750 dev_link_t *link = local->finder; 715 struct pcmcia_device *link = local->finder;
751 716
752 if (!(link->state & DEV_PRESENT)) { 717 if (!(pcmcia_dev_present(link))) {
753 DEBUG(2,"ray_cs verify_dl_startup - device not present\n"); 718 DEBUG(2,"ray_cs verify_dl_startup - device not present\n");
754 return; 719 return;
755 } 720 }
@@ -787,8 +752,8 @@ static void start_net(u_long data)
787 ray_dev_t *local = (ray_dev_t *)data; 752 ray_dev_t *local = (ray_dev_t *)data;
788 struct ccs __iomem *pccs; 753 struct ccs __iomem *pccs;
789 int ccsindex; 754 int ccsindex;
790 dev_link_t *link = local->finder; 755 struct pcmcia_device *link = local->finder;
791 if (!(link->state & DEV_PRESENT)) { 756 if (!(pcmcia_dev_present(link))) {
792 DEBUG(2,"ray_cs start_net - device not present\n"); 757 DEBUG(2,"ray_cs start_net - device not present\n");
793 return; 758 return;
794 } 759 }
@@ -814,9 +779,9 @@ static void join_net(u_long data)
814 779
815 struct ccs __iomem *pccs; 780 struct ccs __iomem *pccs;
816 int ccsindex; 781 int ccsindex;
817 dev_link_t *link = local->finder; 782 struct pcmcia_device *link = local->finder;
818 783
819 if (!(link->state & DEV_PRESENT)) { 784 if (!(pcmcia_dev_present(link))) {
820 DEBUG(2,"ray_cs join_net - device not present\n"); 785 DEBUG(2,"ray_cs join_net - device not present\n");
821 return; 786 return;
822 } 787 }
@@ -840,7 +805,7 @@ static void join_net(u_long data)
840 device, and release the PCMCIA configuration. If the device is 805 device, and release the PCMCIA configuration. If the device is
841 still open, this will be postponed until it is closed. 806 still open, this will be postponed until it is closed.
842=============================================================================*/ 807=============================================================================*/
843static void ray_release(dev_link_t *link) 808static void ray_release(struct pcmcia_device *link)
844{ 809{
845 struct net_device *dev = link->priv; 810 struct net_device *dev = link->priv;
846 ray_dev_t *local = dev->priv; 811 ray_dev_t *local = dev->priv;
@@ -849,56 +814,38 @@ static void ray_release(dev_link_t *link)
849 DEBUG(1, "ray_release(0x%p)\n", link); 814 DEBUG(1, "ray_release(0x%p)\n", link);
850 815
851 del_timer(&local->timer); 816 del_timer(&local->timer);
852 link->state &= ~DEV_CONFIG;
853 817
854 iounmap(local->sram); 818 iounmap(local->sram);
855 iounmap(local->rmem); 819 iounmap(local->rmem);
856 iounmap(local->amem); 820 iounmap(local->amem);
857 /* Do bother checking to see if these succeed or not */ 821 /* Do bother checking to see if these succeed or not */
858 i = pcmcia_release_window(link->win);
859 if ( i != CS_SUCCESS ) DEBUG(0,"ReleaseWindow(link->win) ret = %x\n",i);
860 i = pcmcia_release_window(local->amem_handle); 822 i = pcmcia_release_window(local->amem_handle);
861 if ( i != CS_SUCCESS ) DEBUG(0,"ReleaseWindow(local->amem) ret = %x\n",i); 823 if ( i != CS_SUCCESS ) DEBUG(0,"ReleaseWindow(local->amem) ret = %x\n",i);
862 i = pcmcia_release_window(local->rmem_handle); 824 i = pcmcia_release_window(local->rmem_handle);
863 if ( i != CS_SUCCESS ) DEBUG(0,"ReleaseWindow(local->rmem) ret = %x\n",i); 825 if ( i != CS_SUCCESS ) DEBUG(0,"ReleaseWindow(local->rmem) ret = %x\n",i);
864 i = pcmcia_release_configuration(link->handle); 826 pcmcia_disable_device(link);
865 if ( i != CS_SUCCESS ) DEBUG(0,"ReleaseConfiguration ret = %x\n",i);
866 i = pcmcia_release_irq(link->handle, &link->irq);
867 if ( i != CS_SUCCESS ) DEBUG(0,"ReleaseIRQ ret = %x\n",i);
868 827
869 DEBUG(2,"ray_release ending\n"); 828 DEBUG(2,"ray_release ending\n");
870} 829}
871 830
872static int ray_suspend(struct pcmcia_device *p_dev) 831static int ray_suspend(struct pcmcia_device *link)
873{ 832{
874 dev_link_t *link = dev_to_instance(p_dev);
875 struct net_device *dev = link->priv; 833 struct net_device *dev = link->priv;
876 834
877 link->state |= DEV_SUSPEND; 835 if (link->open)
878 if (link->state & DEV_CONFIG) { 836 netif_device_detach(dev);
879 if (link->open)
880 netif_device_detach(dev);
881
882 pcmcia_release_configuration(link->handle);
883 }
884
885 837
886 return 0; 838 return 0;
887} 839}
888 840
889static int ray_resume(struct pcmcia_device *p_dev) 841static int ray_resume(struct pcmcia_device *link)
890{ 842{
891 dev_link_t *link = dev_to_instance(p_dev);
892 struct net_device *dev = link->priv; 843 struct net_device *dev = link->priv;
893 844
894 link->state &= ~DEV_SUSPEND; 845 if (link->open) {
895 if (link->state & DEV_CONFIG) { 846 ray_reset(dev);
896 pcmcia_request_configuration(link->handle, &link->conf); 847 netif_device_attach(dev);
897 if (link->open) { 848 }
898 ray_reset(dev);
899 netif_device_attach(dev);
900 }
901 }
902 849
903 return 0; 850 return 0;
904} 851}
@@ -910,10 +857,10 @@ int ray_dev_init(struct net_device *dev)
910 int i; 857 int i;
911#endif /* RAY_IMMEDIATE_INIT */ 858#endif /* RAY_IMMEDIATE_INIT */
912 ray_dev_t *local = dev->priv; 859 ray_dev_t *local = dev->priv;
913 dev_link_t *link = local->finder; 860 struct pcmcia_device *link = local->finder;
914 861
915 DEBUG(1,"ray_dev_init(dev=%p)\n",dev); 862 DEBUG(1,"ray_dev_init(dev=%p)\n",dev);
916 if (!(link->state & DEV_PRESENT)) { 863 if (!(pcmcia_dev_present(link))) {
917 DEBUG(2,"ray_dev_init - device not present\n"); 864 DEBUG(2,"ray_dev_init - device not present\n");
918 return -1; 865 return -1;
919 } 866 }
@@ -944,10 +891,10 @@ int ray_dev_init(struct net_device *dev)
944static int ray_dev_config(struct net_device *dev, struct ifmap *map) 891static int ray_dev_config(struct net_device *dev, struct ifmap *map)
945{ 892{
946 ray_dev_t *local = dev->priv; 893 ray_dev_t *local = dev->priv;
947 dev_link_t *link = local->finder; 894 struct pcmcia_device *link = local->finder;
948 /* Dummy routine to satisfy device structure */ 895 /* Dummy routine to satisfy device structure */
949 DEBUG(1,"ray_dev_config(dev=%p,ifmap=%p)\n",dev,map); 896 DEBUG(1,"ray_dev_config(dev=%p,ifmap=%p)\n",dev,map);
950 if (!(link->state & DEV_PRESENT)) { 897 if (!(pcmcia_dev_present(link))) {
951 DEBUG(2,"ray_dev_config - device not present\n"); 898 DEBUG(2,"ray_dev_config - device not present\n");
952 return -1; 899 return -1;
953 } 900 }
@@ -958,10 +905,10 @@ static int ray_dev_config(struct net_device *dev, struct ifmap *map)
958static int ray_dev_start_xmit(struct sk_buff *skb, struct net_device *dev) 905static int ray_dev_start_xmit(struct sk_buff *skb, struct net_device *dev)
959{ 906{
960 ray_dev_t *local = dev->priv; 907 ray_dev_t *local = dev->priv;
961 dev_link_t *link = local->finder; 908 struct pcmcia_device *link = local->finder;
962 short length = skb->len; 909 short length = skb->len;
963 910
964 if (!(link->state & DEV_PRESENT)) { 911 if (!(pcmcia_dev_present(link))) {
965 DEBUG(2,"ray_dev_start_xmit - device not present\n"); 912 DEBUG(2,"ray_dev_start_xmit - device not present\n");
966 return -1; 913 return -1;
967 } 914 }
@@ -1570,7 +1517,7 @@ static int ray_commit(struct net_device *dev,
1570static iw_stats * ray_get_wireless_stats(struct net_device * dev) 1517static iw_stats * ray_get_wireless_stats(struct net_device * dev)
1571{ 1518{
1572 ray_dev_t * local = (ray_dev_t *) dev->priv; 1519 ray_dev_t * local = (ray_dev_t *) dev->priv;
1573 dev_link_t *link = local->finder; 1520 struct pcmcia_device *link = local->finder;
1574 struct status __iomem *p = local->sram + STATUS_BASE; 1521 struct status __iomem *p = local->sram + STATUS_BASE;
1575 1522
1576 if(local == (ray_dev_t *) NULL) 1523 if(local == (ray_dev_t *) NULL)
@@ -1588,7 +1535,7 @@ static iw_stats * ray_get_wireless_stats(struct net_device * dev)
1588 } 1535 }
1589#endif /* WIRELESS_SPY */ 1536#endif /* WIRELESS_SPY */
1590 1537
1591 if((link->state & DEV_PRESENT)) { 1538 if(pcmcia_dev_present(link)) {
1592 local->wstats.qual.noise = readb(&p->rxnoise); 1539 local->wstats.qual.noise = readb(&p->rxnoise);
1593 local->wstats.qual.updated |= 4; 1540 local->wstats.qual.updated |= 4;
1594 } 1541 }
@@ -1657,18 +1604,14 @@ static const struct iw_handler_def ray_handler_def =
1657/*===========================================================================*/ 1604/*===========================================================================*/
1658static int ray_open(struct net_device *dev) 1605static int ray_open(struct net_device *dev)
1659{ 1606{
1660 dev_link_t *link;
1661 ray_dev_t *local = (ray_dev_t *)dev->priv; 1607 ray_dev_t *local = (ray_dev_t *)dev->priv;
1608 struct pcmcia_device *link;
1609 link = local->finder;
1662 1610
1663 DEBUG(1, "ray_open('%s')\n", dev->name); 1611 DEBUG(1, "ray_open('%s')\n", dev->name);
1664 1612
1665 for (link = dev_list; link; link = link->next) 1613 if (link->open == 0)
1666 if (link->priv == dev) break; 1614 local->num_multi = 0;
1667 if (!DEV_OK(link)) {
1668 return -ENODEV;
1669 }
1670
1671 if (link->open == 0) local->num_multi = 0;
1672 link->open++; 1615 link->open++;
1673 1616
1674 /* If the card is not started, time to start it ! - Jean II */ 1617 /* If the card is not started, time to start it ! - Jean II */
@@ -1695,15 +1638,12 @@ static int ray_open(struct net_device *dev)
1695/*===========================================================================*/ 1638/*===========================================================================*/
1696static int ray_dev_close(struct net_device *dev) 1639static int ray_dev_close(struct net_device *dev)
1697{ 1640{
1698 dev_link_t *link; 1641 ray_dev_t *local = (ray_dev_t *)dev->priv;
1642 struct pcmcia_device *link;
1643 link = local->finder;
1699 1644
1700 DEBUG(1, "ray_dev_close('%s')\n", dev->name); 1645 DEBUG(1, "ray_dev_close('%s')\n", dev->name);
1701 1646
1702 for (link = dev_list; link; link = link->next)
1703 if (link->priv == dev) break;
1704 if (link == NULL)
1705 return -ENODEV;
1706
1707 link->open--; 1647 link->open--;
1708 netif_stop_queue(dev); 1648 netif_stop_queue(dev);
1709 1649
@@ -1725,9 +1665,9 @@ static void ray_reset(struct net_device *dev) {
1725static int interrupt_ecf(ray_dev_t *local, int ccs) 1665static int interrupt_ecf(ray_dev_t *local, int ccs)
1726{ 1666{
1727 int i = 50; 1667 int i = 50;
1728 dev_link_t *link = local->finder; 1668 struct pcmcia_device *link = local->finder;
1729 1669
1730 if (!(link->state & DEV_PRESENT)) { 1670 if (!(pcmcia_dev_present(link))) {
1731 DEBUG(2,"ray_cs interrupt_ecf - device not present\n"); 1671 DEBUG(2,"ray_cs interrupt_ecf - device not present\n");
1732 return -1; 1672 return -1;
1733 } 1673 }
@@ -1752,9 +1692,9 @@ static int get_free_tx_ccs(ray_dev_t *local)
1752{ 1692{
1753 int i; 1693 int i;
1754 struct ccs __iomem *pccs = ccs_base(local); 1694 struct ccs __iomem *pccs = ccs_base(local);
1755 dev_link_t *link = local->finder; 1695 struct pcmcia_device *link = local->finder;
1756 1696
1757 if (!(link->state & DEV_PRESENT)) { 1697 if (!(pcmcia_dev_present(link))) {
1758 DEBUG(2,"ray_cs get_free_tx_ccs - device not present\n"); 1698 DEBUG(2,"ray_cs get_free_tx_ccs - device not present\n");
1759 return ECARDGONE; 1699 return ECARDGONE;
1760 } 1700 }
@@ -1783,9 +1723,9 @@ static int get_free_ccs(ray_dev_t *local)
1783{ 1723{
1784 int i; 1724 int i;
1785 struct ccs __iomem *pccs = ccs_base(local); 1725 struct ccs __iomem *pccs = ccs_base(local);
1786 dev_link_t *link = local->finder; 1726 struct pcmcia_device *link = local->finder;
1787 1727
1788 if (!(link->state & DEV_PRESENT)) { 1728 if (!(pcmcia_dev_present(link))) {
1789 DEBUG(2,"ray_cs get_free_ccs - device not present\n"); 1729 DEBUG(2,"ray_cs get_free_ccs - device not present\n");
1790 return ECARDGONE; 1730 return ECARDGONE;
1791 } 1731 }
@@ -1858,9 +1798,9 @@ static int parse_addr(char *in_str, UCHAR *out)
1858static struct net_device_stats *ray_get_stats(struct net_device *dev) 1798static struct net_device_stats *ray_get_stats(struct net_device *dev)
1859{ 1799{
1860 ray_dev_t *local = (ray_dev_t *)dev->priv; 1800 ray_dev_t *local = (ray_dev_t *)dev->priv;
1861 dev_link_t *link = local->finder; 1801 struct pcmcia_device *link = local->finder;
1862 struct status __iomem *p = local->sram + STATUS_BASE; 1802 struct status __iomem *p = local->sram + STATUS_BASE;
1863 if (!(link->state & DEV_PRESENT)) { 1803 if (!(pcmcia_dev_present(link))) {
1864 DEBUG(2,"ray_cs net_device_stats - device not present\n"); 1804 DEBUG(2,"ray_cs net_device_stats - device not present\n");
1865 return &local->stats; 1805 return &local->stats;
1866 } 1806 }
@@ -1888,12 +1828,12 @@ static struct net_device_stats *ray_get_stats(struct net_device *dev)
1888static void ray_update_parm(struct net_device *dev, UCHAR objid, UCHAR *value, int len) 1828static void ray_update_parm(struct net_device *dev, UCHAR objid, UCHAR *value, int len)
1889{ 1829{
1890 ray_dev_t *local = (ray_dev_t *)dev->priv; 1830 ray_dev_t *local = (ray_dev_t *)dev->priv;
1891 dev_link_t *link = local->finder; 1831 struct pcmcia_device *link = local->finder;
1892 int ccsindex; 1832 int ccsindex;
1893 int i; 1833 int i;
1894 struct ccs __iomem *pccs; 1834 struct ccs __iomem *pccs;
1895 1835
1896 if (!(link->state & DEV_PRESENT)) { 1836 if (!(pcmcia_dev_present(link))) {
1897 DEBUG(2,"ray_update_parm - device not present\n"); 1837 DEBUG(2,"ray_update_parm - device not present\n");
1898 return; 1838 return;
1899 } 1839 }
@@ -1925,10 +1865,10 @@ static void ray_update_multi_list(struct net_device *dev, int all)
1925 struct ccs __iomem *pccs; 1865 struct ccs __iomem *pccs;
1926 int i = 0; 1866 int i = 0;
1927 ray_dev_t *local = (ray_dev_t *)dev->priv; 1867 ray_dev_t *local = (ray_dev_t *)dev->priv;
1928 dev_link_t *link = local->finder; 1868 struct pcmcia_device *link = local->finder;
1929 void __iomem *p = local->sram + HOST_TO_ECF_BASE; 1869 void __iomem *p = local->sram + HOST_TO_ECF_BASE;
1930 1870
1931 if (!(link->state & DEV_PRESENT)) { 1871 if (!(pcmcia_dev_present(link))) {
1932 DEBUG(2,"ray_update_multi_list - device not present\n"); 1872 DEBUG(2,"ray_update_multi_list - device not present\n");
1933 return; 1873 return;
1934 } 1874 }
@@ -2005,7 +1945,7 @@ static void set_multicast_list(struct net_device *dev)
2005static irqreturn_t ray_interrupt(int irq, void *dev_id, struct pt_regs * regs) 1945static irqreturn_t ray_interrupt(int irq, void *dev_id, struct pt_regs * regs)
2006{ 1946{
2007 struct net_device *dev = (struct net_device *)dev_id; 1947 struct net_device *dev = (struct net_device *)dev_id;
2008 dev_link_t *link; 1948 struct pcmcia_device *link;
2009 ray_dev_t *local; 1949 ray_dev_t *local;
2010 struct ccs __iomem *pccs; 1950 struct ccs __iomem *pccs;
2011 struct rcs __iomem *prcs; 1951 struct rcs __iomem *prcs;
@@ -2020,8 +1960,8 @@ static irqreturn_t ray_interrupt(int irq, void *dev_id, struct pt_regs * regs)
2020 DEBUG(4,"ray_cs: interrupt for *dev=%p\n",dev); 1960 DEBUG(4,"ray_cs: interrupt for *dev=%p\n",dev);
2021 1961
2022 local = (ray_dev_t *)dev->priv; 1962 local = (ray_dev_t *)dev->priv;
2023 link = (dev_link_t *)local->finder; 1963 link = (struct pcmcia_device *)local->finder;
2024 if ( ! (link->state & DEV_PRESENT) || link->state & DEV_SUSPEND ) { 1964 if (!pcmcia_dev_present(link)) {
2025 DEBUG(2,"ray_cs interrupt from device not present or suspended.\n"); 1965 DEBUG(2,"ray_cs interrupt from device not present or suspended.\n");
2026 return IRQ_NONE; 1966 return IRQ_NONE;
2027 } 1967 }
@@ -2540,9 +2480,9 @@ static void release_frag_chain(ray_dev_t *local, struct rcs __iomem * prcs)
2540/*===========================================================================*/ 2480/*===========================================================================*/
2541static void authenticate(ray_dev_t *local) 2481static void authenticate(ray_dev_t *local)
2542{ 2482{
2543 dev_link_t *link = local->finder; 2483 struct pcmcia_device *link = local->finder;
2544 DEBUG(0,"ray_cs Starting authentication.\n"); 2484 DEBUG(0,"ray_cs Starting authentication.\n");
2545 if (!(link->state & DEV_PRESENT)) { 2485 if (!(pcmcia_dev_present(link))) {
2546 DEBUG(2,"ray_cs authenticate - device not present\n"); 2486 DEBUG(2,"ray_cs authenticate - device not present\n");
2547 return; 2487 return;
2548 } 2488 }
@@ -2606,10 +2546,10 @@ static void rx_authenticate(ray_dev_t *local, struct rcs __iomem *prcs,
2606static void associate(ray_dev_t *local) 2546static void associate(ray_dev_t *local)
2607{ 2547{
2608 struct ccs __iomem *pccs; 2548 struct ccs __iomem *pccs;
2609 dev_link_t *link = local->finder; 2549 struct pcmcia_device *link = local->finder;
2610 struct net_device *dev = link->priv; 2550 struct net_device *dev = link->priv;
2611 int ccsindex; 2551 int ccsindex;
2612 if (!(link->state & DEV_PRESENT)) { 2552 if (!(pcmcia_dev_present(link))) {
2613 DEBUG(2,"ray_cs associate - device not present\n"); 2553 DEBUG(2,"ray_cs associate - device not present\n");
2614 return; 2554 return;
2615 } 2555 }
@@ -2689,14 +2629,14 @@ static int ray_cs_proc_read(char *buf, char **start, off_t offset, int len)
2689 * eg ifconfig 2629 * eg ifconfig
2690 */ 2630 */
2691 int i; 2631 int i;
2692 dev_link_t *link; 2632 struct pcmcia_device *link;
2693 struct net_device *dev; 2633 struct net_device *dev;
2694 ray_dev_t *local; 2634 ray_dev_t *local;
2695 UCHAR *p; 2635 UCHAR *p;
2696 struct freq_hop_element *pfh; 2636 struct freq_hop_element *pfh;
2697 UCHAR c[33]; 2637 UCHAR c[33];
2698 2638
2699 link = dev_list; 2639 link = this_device;
2700 if (!link) 2640 if (!link)
2701 return 0; 2641 return 0;
2702 dev = (struct net_device *)link->priv; 2642 dev = (struct net_device *)link->priv;
@@ -2898,7 +2838,7 @@ static struct pcmcia_driver ray_driver = {
2898 .drv = { 2838 .drv = {
2899 .name = "ray_cs", 2839 .name = "ray_cs",
2900 }, 2840 },
2901 .probe = ray_attach, 2841 .probe = ray_probe,
2902 .remove = ray_detach, 2842 .remove = ray_detach,
2903 .id_table = ray_ids, 2843 .id_table = ray_ids,
2904 .suspend = ray_suspend, 2844 .suspend = ray_suspend,
@@ -2940,7 +2880,6 @@ static void __exit exit_ray_cs(void)
2940#endif 2880#endif
2941 2881
2942 pcmcia_unregister_driver(&ray_driver); 2882 pcmcia_unregister_driver(&ray_driver);
2943 BUG_ON(dev_list != NULL);
2944} /* exit_ray_cs */ 2883} /* exit_ray_cs */
2945 2884
2946module_init(init_ray_cs); 2885module_init(init_ray_cs);
diff --git a/drivers/net/wireless/ray_cs.h b/drivers/net/wireless/ray_cs.h
index 42660fe64bfd..bd73ebf03340 100644
--- a/drivers/net/wireless/ray_cs.h
+++ b/drivers/net/wireless/ray_cs.h
@@ -31,7 +31,7 @@ typedef struct ray_dev_t {
31 void __iomem *sram; /* pointer to beginning of shared RAM */ 31 void __iomem *sram; /* pointer to beginning of shared RAM */
32 void __iomem *amem; /* pointer to attribute mem window */ 32 void __iomem *amem; /* pointer to attribute mem window */
33 void __iomem *rmem; /* pointer to receive buffer window */ 33 void __iomem *rmem; /* pointer to receive buffer window */
34 dev_link_t *finder; /* pointer back to dev_link_t for card */ 34 struct pcmcia_device *finder; /* pointer back to struct pcmcia_device for card */
35 struct timer_list timer; 35 struct timer_list timer;
36 long tx_ccs_lock; 36 long tx_ccs_lock;
37 long ccs_lock; 37 long ccs_lock;
diff --git a/drivers/net/wireless/spectrum_cs.c b/drivers/net/wireless/spectrum_cs.c
index 5fa6fbe35bb9..f7b77ce54d7b 100644
--- a/drivers/net/wireless/spectrum_cs.c
+++ b/drivers/net/wireless/spectrum_cs.c
@@ -63,7 +63,7 @@ MODULE_PARM_DESC(ignore_cis_vcc, "Allow voltage mismatch between card and socket
63/* PCMCIA specific device information (goes in the card field of 63/* PCMCIA specific device information (goes in the card field of
64 * struct orinoco_private */ 64 * struct orinoco_private */
65struct orinoco_pccard { 65struct orinoco_pccard {
66 dev_link_t link; 66 struct pcmcia_device *p_dev;
67 dev_node_t node; 67 dev_node_t node;
68}; 68};
69 69
@@ -71,8 +71,8 @@ struct orinoco_pccard {
71/* Function prototypes */ 71/* Function prototypes */
72/********************************************************************/ 72/********************************************************************/
73 73
74static void spectrum_cs_config(dev_link_t *link); 74static int spectrum_cs_config(struct pcmcia_device *link);
75static void spectrum_cs_release(dev_link_t *link); 75static void spectrum_cs_release(struct pcmcia_device *link);
76 76
77/********************************************************************/ 77/********************************************************************/
78/* Firmware downloader */ 78/* Firmware downloader */
@@ -238,14 +238,14 @@ spectrum_aux_open(hermes_t *hw)
238 * If IDLE is 1, stop the firmware, so that it can be safely rewritten. 238 * If IDLE is 1, stop the firmware, so that it can be safely rewritten.
239 */ 239 */
240static int 240static int
241spectrum_reset(dev_link_t *link, int idle) 241spectrum_reset(struct pcmcia_device *link, int idle)
242{ 242{
243 int last_ret, last_fn; 243 int last_ret, last_fn;
244 conf_reg_t reg; 244 conf_reg_t reg;
245 u_int save_cor; 245 u_int save_cor;
246 246
247 /* Doing it if hardware is gone is guaranteed crash */ 247 /* Doing it if hardware is gone is guaranteed crash */
248 if (!(link->state & DEV_CONFIG)) 248 if (pcmcia_dev_present(link))
249 return -ENODEV; 249 return -ENODEV;
250 250
251 /* Save original COR value */ 251 /* Save original COR value */
@@ -253,7 +253,7 @@ spectrum_reset(dev_link_t *link, int idle)
253 reg.Action = CS_READ; 253 reg.Action = CS_READ;
254 reg.Offset = CISREG_COR; 254 reg.Offset = CISREG_COR;
255 CS_CHECK(AccessConfigurationRegister, 255 CS_CHECK(AccessConfigurationRegister,
256 pcmcia_access_configuration_register(link->handle, &reg)); 256 pcmcia_access_configuration_register(link, &reg));
257 save_cor = reg.Value; 257 save_cor = reg.Value;
258 258
259 /* Soft-Reset card */ 259 /* Soft-Reset card */
@@ -261,14 +261,14 @@ spectrum_reset(dev_link_t *link, int idle)
261 reg.Offset = CISREG_COR; 261 reg.Offset = CISREG_COR;
262 reg.Value = (save_cor | COR_SOFT_RESET); 262 reg.Value = (save_cor | COR_SOFT_RESET);
263 CS_CHECK(AccessConfigurationRegister, 263 CS_CHECK(AccessConfigurationRegister,
264 pcmcia_access_configuration_register(link->handle, &reg)); 264 pcmcia_access_configuration_register(link, &reg));
265 udelay(1000); 265 udelay(1000);
266 266
267 /* Read CCSR */ 267 /* Read CCSR */
268 reg.Action = CS_READ; 268 reg.Action = CS_READ;
269 reg.Offset = CISREG_CCSR; 269 reg.Offset = CISREG_CCSR;
270 CS_CHECK(AccessConfigurationRegister, 270 CS_CHECK(AccessConfigurationRegister,
271 pcmcia_access_configuration_register(link->handle, &reg)); 271 pcmcia_access_configuration_register(link, &reg));
272 272
273 /* 273 /*
274 * Start or stop the firmware. Memory width bit should be 274 * Start or stop the firmware. Memory width bit should be
@@ -278,7 +278,7 @@ spectrum_reset(dev_link_t *link, int idle)
278 reg.Offset = CISREG_CCSR; 278 reg.Offset = CISREG_CCSR;
279 reg.Value = (idle ? HCR_IDLE : HCR_RUN) | (reg.Value & HCR_MEM16); 279 reg.Value = (idle ? HCR_IDLE : HCR_RUN) | (reg.Value & HCR_MEM16);
280 CS_CHECK(AccessConfigurationRegister, 280 CS_CHECK(AccessConfigurationRegister,
281 pcmcia_access_configuration_register(link->handle, &reg)); 281 pcmcia_access_configuration_register(link, &reg));
282 udelay(1000); 282 udelay(1000);
283 283
284 /* Restore original COR configuration index */ 284 /* Restore original COR configuration index */
@@ -286,12 +286,12 @@ spectrum_reset(dev_link_t *link, int idle)
286 reg.Offset = CISREG_COR; 286 reg.Offset = CISREG_COR;
287 reg.Value = (save_cor & ~COR_SOFT_RESET); 287 reg.Value = (save_cor & ~COR_SOFT_RESET);
288 CS_CHECK(AccessConfigurationRegister, 288 CS_CHECK(AccessConfigurationRegister,
289 pcmcia_access_configuration_register(link->handle, &reg)); 289 pcmcia_access_configuration_register(link, &reg));
290 udelay(1000); 290 udelay(1000);
291 return 0; 291 return 0;
292 292
293 cs_failed: 293 cs_failed:
294 cs_error(link->handle, last_fn, last_ret); 294 cs_error(link, last_fn, last_ret);
295 return -ENODEV; 295 return -ENODEV;
296} 296}
297 297
@@ -441,7 +441,7 @@ spectrum_load_blocks(hermes_t *hw, const struct dblock *first_block)
441 * care of the PDA - read it and then write it on top of the firmware. 441 * care of the PDA - read it and then write it on top of the firmware.
442 */ 442 */
443static int 443static int
444spectrum_dl_image(hermes_t *hw, dev_link_t *link, 444spectrum_dl_image(hermes_t *hw, struct pcmcia_device *link,
445 const unsigned char *image) 445 const unsigned char *image)
446{ 446{
447 int ret; 447 int ret;
@@ -505,14 +505,13 @@ spectrum_dl_image(hermes_t *hw, dev_link_t *link,
505 * reset on the card, to make sure it's in a sane state. 505 * reset on the card, to make sure it's in a sane state.
506 */ 506 */
507static int 507static int
508spectrum_dl_firmware(hermes_t *hw, dev_link_t *link) 508spectrum_dl_firmware(hermes_t *hw, struct pcmcia_device *link)
509{ 509{
510 int ret; 510 int ret;
511 client_handle_t handle = link->handle;
512 const struct firmware *fw_entry; 511 const struct firmware *fw_entry;
513 512
514 if (request_firmware(&fw_entry, primary_fw_name, 513 if (request_firmware(&fw_entry, primary_fw_name,
515 &handle_to_dev(handle)) == 0) { 514 &handle_to_dev(link)) == 0) {
516 primsym = fw_entry->data; 515 primsym = fw_entry->data;
517 } else { 516 } else {
518 printk(KERN_ERR PFX "Cannot find firmware: %s\n", 517 printk(KERN_ERR PFX "Cannot find firmware: %s\n",
@@ -521,7 +520,7 @@ spectrum_dl_firmware(hermes_t *hw, dev_link_t *link)
521 } 520 }
522 521
523 if (request_firmware(&fw_entry, secondary_fw_name, 522 if (request_firmware(&fw_entry, secondary_fw_name,
524 &handle_to_dev(handle)) == 0) { 523 &handle_to_dev(link)) == 0) {
525 secsym = fw_entry->data; 524 secsym = fw_entry->data;
526 } else { 525 } else {
527 printk(KERN_ERR PFX "Cannot find firmware: %s\n", 526 printk(KERN_ERR PFX "Cannot find firmware: %s\n",
@@ -554,12 +553,12 @@ static int
554spectrum_cs_hard_reset(struct orinoco_private *priv) 553spectrum_cs_hard_reset(struct orinoco_private *priv)
555{ 554{
556 struct orinoco_pccard *card = priv->card; 555 struct orinoco_pccard *card = priv->card;
557 dev_link_t *link = &card->link; 556 struct pcmcia_device *link = card->p_dev;
558 int err; 557 int err;
559 558
560 if (!hermes_present(&priv->hw)) { 559 if (!hermes_present(&priv->hw)) {
561 /* The firmware needs to be reloaded */ 560 /* The firmware needs to be reloaded */
562 if (spectrum_dl_firmware(&priv->hw, &card->link) != 0) { 561 if (spectrum_dl_firmware(&priv->hw, link) != 0) {
563 printk(KERN_ERR PFX "Firmware download failed\n"); 562 printk(KERN_ERR PFX "Firmware download failed\n");
564 err = -ENODEV; 563 err = -ENODEV;
565 } 564 }
@@ -584,12 +583,11 @@ spectrum_cs_hard_reset(struct orinoco_private *priv)
584 * configure the card at this point -- we wait until we receive a card 583 * configure the card at this point -- we wait until we receive a card
585 * insertion event. */ 584 * insertion event. */
586static int 585static int
587spectrum_cs_attach(struct pcmcia_device *p_dev) 586spectrum_cs_probe(struct pcmcia_device *link)
588{ 587{
589 struct net_device *dev; 588 struct net_device *dev;
590 struct orinoco_private *priv; 589 struct orinoco_private *priv;
591 struct orinoco_pccard *card; 590 struct orinoco_pccard *card;
592 dev_link_t *link;
593 591
594 dev = alloc_orinocodev(sizeof(*card), spectrum_cs_hard_reset); 592 dev = alloc_orinocodev(sizeof(*card), spectrum_cs_hard_reset);
595 if (! dev) 593 if (! dev)
@@ -598,7 +596,7 @@ spectrum_cs_attach(struct pcmcia_device *p_dev)
598 card = priv->card; 596 card = priv->card;
599 597
600 /* Link both structures together */ 598 /* Link both structures together */
601 link = &card->link; 599 card->p_dev = link;
602 link->priv = dev; 600 link->priv = dev;
603 601
604 /* Interrupt setup */ 602 /* Interrupt setup */
@@ -615,13 +613,7 @@ spectrum_cs_attach(struct pcmcia_device *p_dev)
615 link->conf.Attributes = 0; 613 link->conf.Attributes = 0;
616 link->conf.IntType = INT_MEMORY_AND_IO; 614 link->conf.IntType = INT_MEMORY_AND_IO;
617 615
618 link->handle = p_dev; 616 return spectrum_cs_config(link);
619 p_dev->instance = link;
620
621 link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
622 spectrum_cs_config(link);
623
624 return 0;
625} /* spectrum_cs_attach */ 617} /* spectrum_cs_attach */
626 618
627/* 619/*
@@ -630,16 +622,14 @@ spectrum_cs_attach(struct pcmcia_device *p_dev)
630 * are freed. Otherwise, the structures will be freed when the device 622 * are freed. Otherwise, the structures will be freed when the device
631 * is released. 623 * is released.
632 */ 624 */
633static void spectrum_cs_detach(struct pcmcia_device *p_dev) 625static void spectrum_cs_detach(struct pcmcia_device *link)
634{ 626{
635 dev_link_t *link = dev_to_instance(p_dev);
636 struct net_device *dev = link->priv; 627 struct net_device *dev = link->priv;
637 628
638 if (link->state & DEV_CONFIG) 629 spectrum_cs_release(link);
639 spectrum_cs_release(link);
640 630
641 DEBUG(0, PFX "detach: link=%p link->dev=%p\n", link, link->dev); 631 DEBUG(0, PFX "detach: link=%p link->dev_node=%p\n", link, link->dev_node);
642 if (link->dev) { 632 if (link->dev_node) {
643 DEBUG(0, PFX "About to unregister net device %p\n", 633 DEBUG(0, PFX "About to unregister net device %p\n",
644 dev); 634 dev);
645 unregister_netdev(dev); 635 unregister_netdev(dev);
@@ -653,11 +643,10 @@ static void spectrum_cs_detach(struct pcmcia_device *p_dev)
653 * device available to the system. 643 * device available to the system.
654 */ 644 */
655 645
656static void 646static int
657spectrum_cs_config(dev_link_t *link) 647spectrum_cs_config(struct pcmcia_device *link)
658{ 648{
659 struct net_device *dev = link->priv; 649 struct net_device *dev = link->priv;
660 client_handle_t handle = link->handle;
661 struct orinoco_private *priv = netdev_priv(dev); 650 struct orinoco_private *priv = netdev_priv(dev);
662 struct orinoco_pccard *card = priv->card; 651 struct orinoco_pccard *card = priv->card;
663 hermes_t *hw = &priv->hw; 652 hermes_t *hw = &priv->hw;
@@ -669,7 +658,7 @@ spectrum_cs_config(dev_link_t *link)
669 cisparse_t parse; 658 cisparse_t parse;
670 void __iomem *mem; 659 void __iomem *mem;
671 660
672 CS_CHECK(ValidateCIS, pcmcia_validate_cis(handle, &info)); 661 CS_CHECK(ValidateCIS, pcmcia_validate_cis(link, &info));
673 662
674 /* 663 /*
675 * This reads the card's CONFIG tuple to find its 664 * This reads the card's CONFIG tuple to find its
@@ -680,19 +669,15 @@ spectrum_cs_config(dev_link_t *link)
680 tuple.TupleData = buf; 669 tuple.TupleData = buf;
681 tuple.TupleDataMax = sizeof(buf); 670 tuple.TupleDataMax = sizeof(buf);
682 tuple.TupleOffset = 0; 671 tuple.TupleOffset = 0;
683 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); 672 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
684 CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); 673 CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
685 CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); 674 CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
686 link->conf.ConfigBase = parse.config.base; 675 link->conf.ConfigBase = parse.config.base;
687 link->conf.Present = parse.config.rmask[0]; 676 link->conf.Present = parse.config.rmask[0];
688 677
689 /* Configure card */
690 link->state |= DEV_CONFIG;
691
692 /* Look up the current Vcc */ 678 /* Look up the current Vcc */
693 CS_CHECK(GetConfigurationInfo, 679 CS_CHECK(GetConfigurationInfo,
694 pcmcia_get_configuration_info(handle, &conf)); 680 pcmcia_get_configuration_info(link, &conf));
695 link->conf.Vcc = conf.Vcc;
696 681
697 /* 682 /*
698 * In this loop, we scan the CIS for configuration table 683 * In this loop, we scan the CIS for configuration table
@@ -709,13 +694,13 @@ spectrum_cs_config(dev_link_t *link)
709 * implementation-defined details. 694 * implementation-defined details.
710 */ 695 */
711 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; 696 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
712 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); 697 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
713 while (1) { 698 while (1) {
714 cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); 699 cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
715 cistpl_cftable_entry_t dflt = { .index = 0 }; 700 cistpl_cftable_entry_t dflt = { .index = 0 };
716 701
717 if ( (pcmcia_get_tuple_data(handle, &tuple) != 0) 702 if ( (pcmcia_get_tuple_data(link, &tuple) != 0)
718 || (pcmcia_parse_tuple(handle, &tuple, &parse) != 0)) 703 || (pcmcia_parse_tuple(link, &tuple, &parse) != 0))
719 goto next_entry; 704 goto next_entry;
720 705
721 if (cfg->flags & CISTPL_CFTABLE_DEFAULT) 706 if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
@@ -747,10 +732,10 @@ spectrum_cs_config(dev_link_t *link)
747 } 732 }
748 733
749 if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) 734 if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
750 link->conf.Vpp1 = link->conf.Vpp2 = 735 link->conf.Vpp =
751 cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; 736 cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
752 else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM)) 737 else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM))
753 link->conf.Vpp1 = link->conf.Vpp2 = 738 link->conf.Vpp =
754 dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000; 739 dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
755 740
756 /* Do we need to allocate an interrupt? */ 741 /* Do we need to allocate an interrupt? */
@@ -780,7 +765,7 @@ spectrum_cs_config(dev_link_t *link)
780 } 765 }
781 766
782 /* This reserves IO space but doesn't actually enable it */ 767 /* This reserves IO space but doesn't actually enable it */
783 if (pcmcia_request_io(link->handle, &link->io) != 0) 768 if (pcmcia_request_io(link, &link->io) != 0)
784 goto next_entry; 769 goto next_entry;
785 } 770 }
786 771
@@ -790,9 +775,8 @@ spectrum_cs_config(dev_link_t *link)
790 break; 775 break;
791 776
792 next_entry: 777 next_entry:
793 if (link->io.NumPorts1) 778 pcmcia_disable_device(link);
794 pcmcia_release_io(link->handle, &link->io); 779 last_ret = pcmcia_get_next_tuple(link, &tuple);
795 last_ret = pcmcia_get_next_tuple(handle, &tuple);
796 if (last_ret == CS_NO_MORE_ITEMS) { 780 if (last_ret == CS_NO_MORE_ITEMS) {
797 printk(KERN_ERR PFX "GetNextTuple(): No matching " 781 printk(KERN_ERR PFX "GetNextTuple(): No matching "
798 "CIS configuration. Maybe you need the " 782 "CIS configuration. Maybe you need the "
@@ -806,7 +790,7 @@ spectrum_cs_config(dev_link_t *link)
806 * a handler to the interrupt, unless the 'Handler' member of 790 * a handler to the interrupt, unless the 'Handler' member of
807 * the irq structure is initialized. 791 * the irq structure is initialized.
808 */ 792 */
809 CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq)); 793 CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
810 794
811 /* We initialize the hermes structure before completing PCMCIA 795 /* We initialize the hermes structure before completing PCMCIA
812 * configuration just in case the interrupt handler gets 796 * configuration just in case the interrupt handler gets
@@ -823,7 +807,7 @@ spectrum_cs_config(dev_link_t *link)
823 * card and host interface into "Memory and IO" mode. 807 * card and host interface into "Memory and IO" mode.
824 */ 808 */
825 CS_CHECK(RequestConfiguration, 809 CS_CHECK(RequestConfiguration,
826 pcmcia_request_configuration(link->handle, &link->conf)); 810 pcmcia_request_configuration(link, &link->conf));
827 811
828 /* Ok, we have the configuration, prepare to register the netdev */ 812 /* Ok, we have the configuration, prepare to register the netdev */
829 dev->base_addr = link->io.BasePort1; 813 dev->base_addr = link->io.BasePort1;
@@ -836,7 +820,7 @@ spectrum_cs_config(dev_link_t *link)
836 goto failed; 820 goto failed;
837 } 821 }
838 822
839 SET_NETDEV_DEV(dev, &handle_to_dev(handle)); 823 SET_NETDEV_DEV(dev, &handle_to_dev(link));
840 /* Tell the stack we exist */ 824 /* Tell the stack we exist */
841 if (register_netdev(dev) != 0) { 825 if (register_netdev(dev) != 0) {
842 printk(KERN_ERR PFX "register_netdev() failed\n"); 826 printk(KERN_ERR PFX "register_netdev() failed\n");
@@ -844,20 +828,18 @@ spectrum_cs_config(dev_link_t *link)
844 } 828 }
845 829
846 /* At this point, the dev_node_t structure(s) needs to be 830 /* At this point, the dev_node_t structure(s) needs to be
847 * initialized and arranged in a linked list at link->dev. */ 831 * initialized and arranged in a linked list at link->dev_node. */
848 strcpy(card->node.dev_name, dev->name); 832 strcpy(card->node.dev_name, dev->name);
849 link->dev = &card->node; /* link->dev being non-NULL is also 833 link->dev_node = &card->node; /* link->dev_node being non-NULL is also
850 used to indicate that the 834 used to indicate that the
851 net_device has been registered */ 835 net_device has been registered */
852 link->state &= ~DEV_CONFIG_PENDING;
853 836
854 /* Finally, report what we've done */ 837 /* Finally, report what we've done */
855 printk(KERN_DEBUG "%s: index 0x%02x: Vcc %d.%d", 838 printk(KERN_DEBUG "%s: index 0x%02x: ",
856 dev->name, link->conf.ConfigIndex, 839 dev->name, link->conf.ConfigIndex);
857 link->conf.Vcc / 10, link->conf.Vcc % 10); 840 if (link->conf.Vpp)
858 if (link->conf.Vpp1) 841 printk(", Vpp %d.%d", link->conf.Vpp / 10,
859 printk(", Vpp %d.%d", link->conf.Vpp1 / 10, 842 link->conf.Vpp % 10);
860 link->conf.Vpp1 % 10);
861 printk(", irq %d", link->irq.AssignedIRQ); 843 printk(", irq %d", link->irq.AssignedIRQ);
862 if (link->io.NumPorts1) 844 if (link->io.NumPorts1)
863 printk(", io 0x%04x-0x%04x", link->io.BasePort1, 845 printk(", io 0x%04x-0x%04x", link->io.BasePort1,
@@ -867,13 +849,14 @@ spectrum_cs_config(dev_link_t *link)
867 link->io.BasePort2 + link->io.NumPorts2 - 1); 849 link->io.BasePort2 + link->io.NumPorts2 - 1);
868 printk("\n"); 850 printk("\n");
869 851
870 return; 852 return 0;
871 853
872 cs_failed: 854 cs_failed:
873 cs_error(link->handle, last_fn, last_ret); 855 cs_error(link, last_fn, last_ret);
874 856
875 failed: 857 failed:
876 spectrum_cs_release(link); 858 spectrum_cs_release(link);
859 return -ENODEV;
877} /* spectrum_cs_config */ 860} /* spectrum_cs_config */
878 861
879/* 862/*
@@ -882,7 +865,7 @@ spectrum_cs_config(dev_link_t *link)
882 * still open, this will be postponed until it is closed. 865 * still open, this will be postponed until it is closed.
883 */ 866 */
884static void 867static void
885spectrum_cs_release(dev_link_t *link) 868spectrum_cs_release(struct pcmcia_device *link)
886{ 869{
887 struct net_device *dev = link->priv; 870 struct net_device *dev = link->priv;
888 struct orinoco_private *priv = netdev_priv(dev); 871 struct orinoco_private *priv = netdev_priv(dev);
@@ -894,64 +877,46 @@ spectrum_cs_release(dev_link_t *link)
894 priv->hw_unavailable++; 877 priv->hw_unavailable++;
895 spin_unlock_irqrestore(&priv->lock, flags); 878 spin_unlock_irqrestore(&priv->lock, flags);
896 879
897 /* Don't bother checking to see if these succeed or not */ 880 pcmcia_disable_device(link);
898 pcmcia_release_configuration(link->handle);
899 if (link->io.NumPorts1)
900 pcmcia_release_io(link->handle, &link->io);
901 if (link->irq.AssignedIRQ)
902 pcmcia_release_irq(link->handle, &link->irq);
903 link->state &= ~DEV_CONFIG;
904 if (priv->hw.iobase) 881 if (priv->hw.iobase)
905 ioport_unmap(priv->hw.iobase); 882 ioport_unmap(priv->hw.iobase);
906} /* spectrum_cs_release */ 883} /* spectrum_cs_release */
907 884
908 885
909static int 886static int
910spectrum_cs_suspend(struct pcmcia_device *p_dev) 887spectrum_cs_suspend(struct pcmcia_device *link)
911{ 888{
912 dev_link_t *link = dev_to_instance(p_dev);
913 struct net_device *dev = link->priv; 889 struct net_device *dev = link->priv;
914 struct orinoco_private *priv = netdev_priv(dev); 890 struct orinoco_private *priv = netdev_priv(dev);
915 unsigned long flags; 891 unsigned long flags;
916 int err = 0; 892 int err = 0;
917 893
918 link->state |= DEV_SUSPEND;
919 /* Mark the device as stopped, to block IO until later */ 894 /* Mark the device as stopped, to block IO until later */
920 if (link->state & DEV_CONFIG) { 895 spin_lock_irqsave(&priv->lock, flags);
921 spin_lock_irqsave(&priv->lock, flags);
922
923 err = __orinoco_down(dev);
924 if (err)
925 printk(KERN_WARNING "%s: Error %d downing interface\n",
926 dev->name, err);
927 896
928 netif_device_detach(dev); 897 err = __orinoco_down(dev);
929 priv->hw_unavailable++; 898 if (err)
899 printk(KERN_WARNING "%s: Error %d downing interface\n",
900 dev->name, err);
930 901
931 spin_unlock_irqrestore(&priv->lock, flags); 902 netif_device_detach(dev);
903 priv->hw_unavailable++;
932 904
933 pcmcia_release_configuration(link->handle); 905 spin_unlock_irqrestore(&priv->lock, flags);
934 }
935 906
936 return 0; 907 return 0;
937} 908}
938 909
939static int 910static int
940spectrum_cs_resume(struct pcmcia_device *p_dev) 911spectrum_cs_resume(struct pcmcia_device *link)
941{ 912{
942 dev_link_t *link = dev_to_instance(p_dev);
943 struct net_device *dev = link->priv; 913 struct net_device *dev = link->priv;
944 struct orinoco_private *priv = netdev_priv(dev); 914 struct orinoco_private *priv = netdev_priv(dev);
945 915
946 link->state &= ~DEV_SUSPEND; 916 netif_device_attach(dev);
947 if (link->state & DEV_CONFIG) { 917 priv->hw_unavailable--;
948 /* FIXME: should we double check that this is 918 schedule_work(&priv->reset_work);
949 * the same card as we had before */ 919
950 pcmcia_request_configuration(link->handle, &link->conf);
951 netif_device_attach(dev);
952 priv->hw_unavailable--;
953 schedule_work(&priv->reset_work);
954 }
955 return 0; 920 return 0;
956} 921}
957 922
@@ -979,7 +944,7 @@ static struct pcmcia_driver orinoco_driver = {
979 .drv = { 944 .drv = {
980 .name = DRIVER_NAME, 945 .name = DRIVER_NAME,
981 }, 946 },
982 .probe = spectrum_cs_attach, 947 .probe = spectrum_cs_probe,
983 .remove = spectrum_cs_detach, 948 .remove = spectrum_cs_detach,
984 .suspend = spectrum_cs_suspend, 949 .suspend = spectrum_cs_suspend,
985 .resume = spectrum_cs_resume, 950 .resume = spectrum_cs_resume,
diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c
index 98122f3a4bc2..f7724eb2fa7e 100644
--- a/drivers/net/wireless/wavelan_cs.c
+++ b/drivers/net/wireless/wavelan_cs.c
@@ -1005,7 +1005,7 @@ static inline void
1005wv_82593_reconfig(struct net_device * dev) 1005wv_82593_reconfig(struct net_device * dev)
1006{ 1006{
1007 net_local * lp = netdev_priv(dev); 1007 net_local * lp = netdev_priv(dev);
1008 dev_link_t * link = lp->link; 1008 struct pcmcia_device * link = lp->link;
1009 unsigned long flags; 1009 unsigned long flags;
1010 1010
1011 /* Arm the flag, will be cleard in wv_82593_config() */ 1011 /* Arm the flag, will be cleard in wv_82593_config() */
@@ -3744,16 +3744,16 @@ wv_pcmcia_reset(struct net_device * dev)
3744{ 3744{
3745 int i; 3745 int i;
3746 conf_reg_t reg = { 0, CS_READ, CISREG_COR, 0 }; 3746 conf_reg_t reg = { 0, CS_READ, CISREG_COR, 0 };
3747 dev_link_t * link = ((net_local *)netdev_priv(dev))->link; 3747 struct pcmcia_device * link = ((net_local *)netdev_priv(dev))->link;
3748 3748
3749#ifdef DEBUG_CONFIG_TRACE 3749#ifdef DEBUG_CONFIG_TRACE
3750 printk(KERN_DEBUG "%s: ->wv_pcmcia_reset()\n", dev->name); 3750 printk(KERN_DEBUG "%s: ->wv_pcmcia_reset()\n", dev->name);
3751#endif 3751#endif
3752 3752
3753 i = pcmcia_access_configuration_register(link->handle, &reg); 3753 i = pcmcia_access_configuration_register(link, &reg);
3754 if(i != CS_SUCCESS) 3754 if(i != CS_SUCCESS)
3755 { 3755 {
3756 cs_error(link->handle, AccessConfigurationRegister, i); 3756 cs_error(link, AccessConfigurationRegister, i);
3757 return FALSE; 3757 return FALSE;
3758 } 3758 }
3759 3759
@@ -3764,19 +3764,19 @@ wv_pcmcia_reset(struct net_device * dev)
3764 3764
3765 reg.Action = CS_WRITE; 3765 reg.Action = CS_WRITE;
3766 reg.Value = reg.Value | COR_SW_RESET; 3766 reg.Value = reg.Value | COR_SW_RESET;
3767 i = pcmcia_access_configuration_register(link->handle, &reg); 3767 i = pcmcia_access_configuration_register(link, &reg);
3768 if(i != CS_SUCCESS) 3768 if(i != CS_SUCCESS)
3769 { 3769 {
3770 cs_error(link->handle, AccessConfigurationRegister, i); 3770 cs_error(link, AccessConfigurationRegister, i);
3771 return FALSE; 3771 return FALSE;
3772 } 3772 }
3773 3773
3774 reg.Action = CS_WRITE; 3774 reg.Action = CS_WRITE;
3775 reg.Value = COR_LEVEL_IRQ | COR_CONFIG; 3775 reg.Value = COR_LEVEL_IRQ | COR_CONFIG;
3776 i = pcmcia_access_configuration_register(link->handle, &reg); 3776 i = pcmcia_access_configuration_register(link, &reg);
3777 if(i != CS_SUCCESS) 3777 if(i != CS_SUCCESS)
3778 { 3778 {
3779 cs_error(link->handle, AccessConfigurationRegister, i); 3779 cs_error(link, AccessConfigurationRegister, i);
3780 return FALSE; 3780 return FALSE;
3781 } 3781 }
3782 3782
@@ -3940,9 +3940,8 @@ wv_hw_reset(struct net_device * dev)
3940 * (called by wavelan_event()) 3940 * (called by wavelan_event())
3941 */ 3941 */
3942static inline int 3942static inline int
3943wv_pcmcia_config(dev_link_t * link) 3943wv_pcmcia_config(struct pcmcia_device * link)
3944{ 3944{
3945 client_handle_t handle = link->handle;
3946 tuple_t tuple; 3945 tuple_t tuple;
3947 cisparse_t parse; 3946 cisparse_t parse;
3948 struct net_device * dev = (struct net_device *) link->priv; 3947 struct net_device * dev = (struct net_device *) link->priv;
@@ -3965,16 +3964,16 @@ wv_pcmcia_config(dev_link_t * link)
3965 { 3964 {
3966 tuple.Attributes = 0; 3965 tuple.Attributes = 0;
3967 tuple.DesiredTuple = CISTPL_CONFIG; 3966 tuple.DesiredTuple = CISTPL_CONFIG;
3968 i = pcmcia_get_first_tuple(handle, &tuple); 3967 i = pcmcia_get_first_tuple(link, &tuple);
3969 if(i != CS_SUCCESS) 3968 if(i != CS_SUCCESS)
3970 break; 3969 break;
3971 tuple.TupleData = (cisdata_t *)buf; 3970 tuple.TupleData = (cisdata_t *)buf;
3972 tuple.TupleDataMax = 64; 3971 tuple.TupleDataMax = 64;
3973 tuple.TupleOffset = 0; 3972 tuple.TupleOffset = 0;
3974 i = pcmcia_get_tuple_data(handle, &tuple); 3973 i = pcmcia_get_tuple_data(link, &tuple);
3975 if(i != CS_SUCCESS) 3974 if(i != CS_SUCCESS)
3976 break; 3975 break;
3977 i = pcmcia_parse_tuple(handle, &tuple, &parse); 3976 i = pcmcia_parse_tuple(link, &tuple, &parse);
3978 if(i != CS_SUCCESS) 3977 if(i != CS_SUCCESS)
3979 break; 3978 break;
3980 link->conf.ConfigBase = parse.config.base; 3979 link->conf.ConfigBase = parse.config.base;
@@ -3983,19 +3982,16 @@ wv_pcmcia_config(dev_link_t * link)
3983 while(0); 3982 while(0);
3984 if(i != CS_SUCCESS) 3983 if(i != CS_SUCCESS)
3985 { 3984 {
3986 cs_error(link->handle, ParseTuple, i); 3985 cs_error(link, ParseTuple, i);
3987 link->state &= ~DEV_CONFIG_PENDING;
3988 return FALSE; 3986 return FALSE;
3989 } 3987 }
3990 3988
3991 /* Configure card */
3992 link->state |= DEV_CONFIG;
3993 do 3989 do
3994 { 3990 {
3995 i = pcmcia_request_io(link->handle, &link->io); 3991 i = pcmcia_request_io(link, &link->io);
3996 if(i != CS_SUCCESS) 3992 if(i != CS_SUCCESS)
3997 { 3993 {
3998 cs_error(link->handle, RequestIO, i); 3994 cs_error(link, RequestIO, i);
3999 break; 3995 break;
4000 } 3996 }
4001 3997
@@ -4003,10 +3999,10 @@ wv_pcmcia_config(dev_link_t * link)
4003 * Now allocate an interrupt line. Note that this does not 3999 * Now allocate an interrupt line. Note that this does not
4004 * actually assign a handler to the interrupt. 4000 * actually assign a handler to the interrupt.
4005 */ 4001 */
4006 i = pcmcia_request_irq(link->handle, &link->irq); 4002 i = pcmcia_request_irq(link, &link->irq);
4007 if(i != CS_SUCCESS) 4003 if(i != CS_SUCCESS)
4008 { 4004 {
4009 cs_error(link->handle, RequestIRQ, i); 4005 cs_error(link, RequestIRQ, i);
4010 break; 4006 break;
4011 } 4007 }
4012 4008
@@ -4015,15 +4011,15 @@ wv_pcmcia_config(dev_link_t * link)
4015 * the I/O windows and the interrupt mapping. 4011 * the I/O windows and the interrupt mapping.
4016 */ 4012 */
4017 link->conf.ConfigIndex = 1; 4013 link->conf.ConfigIndex = 1;
4018 i = pcmcia_request_configuration(link->handle, &link->conf); 4014 i = pcmcia_request_configuration(link, &link->conf);
4019 if(i != CS_SUCCESS) 4015 if(i != CS_SUCCESS)
4020 { 4016 {
4021 cs_error(link->handle, RequestConfiguration, i); 4017 cs_error(link, RequestConfiguration, i);
4022 break; 4018 break;
4023 } 4019 }
4024 4020
4025 /* 4021 /*
4026 * Allocate a small memory window. Note that the dev_link_t 4022 * Allocate a small memory window. Note that the struct pcmcia_device
4027 * structure provides space for one window handle -- if your 4023 * structure provides space for one window handle -- if your
4028 * device needs several windows, you'll need to keep track of 4024 * device needs several windows, you'll need to keep track of
4029 * the handles in your private data structure, link->priv. 4025 * the handles in your private data structure, link->priv.
@@ -4031,10 +4027,10 @@ wv_pcmcia_config(dev_link_t * link)
4031 req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE; 4027 req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
4032 req.Base = req.Size = 0; 4028 req.Base = req.Size = 0;
4033 req.AccessSpeed = mem_speed; 4029 req.AccessSpeed = mem_speed;
4034 i = pcmcia_request_window(&link->handle, &req, &link->win); 4030 i = pcmcia_request_window(&link, &req, &link->win);
4035 if(i != CS_SUCCESS) 4031 if(i != CS_SUCCESS)
4036 { 4032 {
4037 cs_error(link->handle, RequestWindow, i); 4033 cs_error(link, RequestWindow, i);
4038 break; 4034 break;
4039 } 4035 }
4040 4036
@@ -4046,7 +4042,7 @@ wv_pcmcia_config(dev_link_t * link)
4046 i = pcmcia_map_mem_page(link->win, &mem); 4042 i = pcmcia_map_mem_page(link->win, &mem);
4047 if(i != CS_SUCCESS) 4043 if(i != CS_SUCCESS)
4048 { 4044 {
4049 cs_error(link->handle, MapMemPage, i); 4045 cs_error(link, MapMemPage, i);
4050 break; 4046 break;
4051 } 4047 }
4052 4048
@@ -4060,7 +4056,7 @@ wv_pcmcia_config(dev_link_t * link)
4060 lp->mem, dev->irq, (u_int) dev->base_addr); 4056 lp->mem, dev->irq, (u_int) dev->base_addr);
4061#endif 4057#endif
4062 4058
4063 SET_NETDEV_DEV(dev, &handle_to_dev(handle)); 4059 SET_NETDEV_DEV(dev, &handle_to_dev(link));
4064 i = register_netdev(dev); 4060 i = register_netdev(dev);
4065 if(i != 0) 4061 if(i != 0)
4066 { 4062 {
@@ -4072,7 +4068,6 @@ wv_pcmcia_config(dev_link_t * link)
4072 } 4068 }
4073 while(0); /* Humm... Disguised goto !!! */ 4069 while(0); /* Humm... Disguised goto !!! */
4074 4070
4075 link->state &= ~DEV_CONFIG_PENDING;
4076 /* If any step failed, release any partially configured state */ 4071 /* If any step failed, release any partially configured state */
4077 if(i != 0) 4072 if(i != 0)
4078 { 4073 {
@@ -4081,7 +4076,7 @@ wv_pcmcia_config(dev_link_t * link)
4081 } 4076 }
4082 4077
4083 strcpy(((net_local *) netdev_priv(dev))->node.dev_name, dev->name); 4078 strcpy(((net_local *) netdev_priv(dev))->node.dev_name, dev->name);
4084 link->dev = &((net_local *) netdev_priv(dev))->node; 4079 link->dev_node = &((net_local *) netdev_priv(dev))->node;
4085 4080
4086#ifdef DEBUG_CONFIG_TRACE 4081#ifdef DEBUG_CONFIG_TRACE
4087 printk(KERN_DEBUG "<-wv_pcmcia_config()\n"); 4082 printk(KERN_DEBUG "<-wv_pcmcia_config()\n");
@@ -4096,26 +4091,20 @@ wv_pcmcia_config(dev_link_t * link)
4096 * still open, this will be postponed until it is closed. 4091 * still open, this will be postponed until it is closed.
4097 */ 4092 */
4098static void 4093static void
4099wv_pcmcia_release(dev_link_t *link) 4094wv_pcmcia_release(struct pcmcia_device *link)
4100{ 4095{
4101 struct net_device * dev = (struct net_device *) link->priv; 4096 struct net_device * dev = (struct net_device *) link->priv;
4102 net_local * lp = netdev_priv(dev); 4097 net_local * lp = netdev_priv(dev);
4103 4098
4104#ifdef DEBUG_CONFIG_TRACE 4099#ifdef DEBUG_CONFIG_TRACE
4105 printk(KERN_DEBUG "%s: -> wv_pcmcia_release(0x%p)\n", dev->name, link); 4100 printk(KERN_DEBUG "%s: -> wv_pcmcia_release(0x%p)\n", dev->name, link);
4106#endif 4101#endif
4107 4102
4108 /* Don't bother checking to see if these succeed or not */ 4103 iounmap(lp->mem);
4109 iounmap(lp->mem); 4104 pcmcia_disable_device(link);
4110 pcmcia_release_window(link->win);
4111 pcmcia_release_configuration(link->handle);
4112 pcmcia_release_io(link->handle, &link->io);
4113 pcmcia_release_irq(link->handle, &link->irq);
4114
4115 link->state &= ~DEV_CONFIG;
4116 4105
4117#ifdef DEBUG_CONFIG_TRACE 4106#ifdef DEBUG_CONFIG_TRACE
4118 printk(KERN_DEBUG "%s: <- wv_pcmcia_release()\n", dev->name); 4107 printk(KERN_DEBUG "%s: <- wv_pcmcia_release()\n", dev->name);
4119#endif 4108#endif
4120} 4109}
4121 4110
@@ -4479,7 +4468,7 @@ static int
4479wavelan_open(struct net_device * dev) 4468wavelan_open(struct net_device * dev)
4480{ 4469{
4481 net_local * lp = netdev_priv(dev); 4470 net_local * lp = netdev_priv(dev);
4482 dev_link_t * link = lp->link; 4471 struct pcmcia_device * link = lp->link;
4483 kio_addr_t base = dev->base_addr; 4472 kio_addr_t base = dev->base_addr;
4484 4473
4485#ifdef DEBUG_CALLBACK_TRACE 4474#ifdef DEBUG_CALLBACK_TRACE
@@ -4533,7 +4522,7 @@ wavelan_open(struct net_device * dev)
4533static int 4522static int
4534wavelan_close(struct net_device * dev) 4523wavelan_close(struct net_device * dev)
4535{ 4524{
4536 dev_link_t * link = ((net_local *)netdev_priv(dev))->link; 4525 struct pcmcia_device * link = ((net_local *)netdev_priv(dev))->link;
4537 kio_addr_t base = dev->base_addr; 4526 kio_addr_t base = dev->base_addr;
4538 4527
4539#ifdef DEBUG_CALLBACK_TRACE 4528#ifdef DEBUG_CALLBACK_TRACE
@@ -4587,45 +4576,36 @@ wavelan_close(struct net_device * dev)
4587 * card insertion event. 4576 * card insertion event.
4588 */ 4577 */
4589static int 4578static int
4590wavelan_attach(struct pcmcia_device *p_dev) 4579wavelan_probe(struct pcmcia_device *p_dev)
4591{ 4580{
4592 dev_link_t * link; /* Info for cardmgr */
4593 struct net_device * dev; /* Interface generic data */ 4581 struct net_device * dev; /* Interface generic data */
4594 net_local * lp; /* Interface specific data */ 4582 net_local * lp; /* Interface specific data */
4583 int ret;
4595 4584
4596#ifdef DEBUG_CALLBACK_TRACE 4585#ifdef DEBUG_CALLBACK_TRACE
4597 printk(KERN_DEBUG "-> wavelan_attach()\n"); 4586 printk(KERN_DEBUG "-> wavelan_attach()\n");
4598#endif 4587#endif
4599 4588
4600 /* Initialize the dev_link_t structure */
4601 link = kzalloc(sizeof(struct dev_link_t), GFP_KERNEL);
4602 if (!link) return -ENOMEM;
4603
4604 /* The io structure describes IO port mapping */ 4589 /* The io structure describes IO port mapping */
4605 link->io.NumPorts1 = 8; 4590 p_dev->io.NumPorts1 = 8;
4606 link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; 4591 p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
4607 link->io.IOAddrLines = 3; 4592 p_dev->io.IOAddrLines = 3;
4608 4593
4609 /* Interrupt setup */ 4594 /* Interrupt setup */
4610 link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; 4595 p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
4611 link->irq.IRQInfo1 = IRQ_LEVEL_ID; 4596 p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID;
4612 link->irq.Handler = wavelan_interrupt; 4597 p_dev->irq.Handler = wavelan_interrupt;
4613 4598
4614 /* General socket configuration */ 4599 /* General socket configuration */
4615 link->conf.Attributes = CONF_ENABLE_IRQ; 4600 p_dev->conf.Attributes = CONF_ENABLE_IRQ;
4616 link->conf.Vcc = 50; 4601 p_dev->conf.IntType = INT_MEMORY_AND_IO;
4617 link->conf.IntType = INT_MEMORY_AND_IO;
4618
4619 /* Chain drivers */
4620 link->next = NULL;
4621 4602
4622 /* Allocate the generic data structure */ 4603 /* Allocate the generic data structure */
4623 dev = alloc_etherdev(sizeof(net_local)); 4604 dev = alloc_etherdev(sizeof(net_local));
4624 if (!dev) { 4605 if (!dev)
4625 kfree(link);
4626 return -ENOMEM; 4606 return -ENOMEM;
4627 } 4607
4628 link->priv = link->irq.Instance = dev; 4608 p_dev->priv = p_dev->irq.Instance = dev;
4629 4609
4630 lp = netdev_priv(dev); 4610 lp = netdev_priv(dev);
4631 4611
@@ -4642,7 +4622,6 @@ wavelan_attach(struct pcmcia_device *p_dev)
4642 spin_lock_init(&lp->spinlock); 4622 spin_lock_init(&lp->spinlock);
4643 4623
4644 /* back links */ 4624 /* back links */
4645 lp->link = link;
4646 lp->dev = dev; 4625 lp->dev = dev;
4647 4626
4648 /* wavelan NET3 callbacks */ 4627 /* wavelan NET3 callbacks */
@@ -4668,15 +4647,18 @@ wavelan_attach(struct pcmcia_device *p_dev)
4668 /* Other specific data */ 4647 /* Other specific data */
4669 dev->mtu = WAVELAN_MTU; 4648 dev->mtu = WAVELAN_MTU;
4670 4649
4671 link->handle = p_dev; 4650 ret = wv_pcmcia_config(p_dev);
4672 p_dev->instance = link; 4651 if (ret)
4652 return ret;
4673 4653
4674 link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; 4654 ret = wv_hw_config(dev);
4675 if(wv_pcmcia_config(link) && 4655 if (ret) {
4676 wv_hw_config(dev))
4677 wv_init_info(dev);
4678 else
4679 dev->irq = 0; 4656 dev->irq = 0;
4657 pcmcia_disable_device(p_dev);
4658 return ret;
4659 }
4660
4661 wv_init_info(dev);
4680 4662
4681#ifdef DEBUG_CALLBACK_TRACE 4663#ifdef DEBUG_CALLBACK_TRACE
4682 printk(KERN_DEBUG "<- wavelan_attach()\n"); 4664 printk(KERN_DEBUG "<- wavelan_attach()\n");
@@ -4693,25 +4675,14 @@ wavelan_attach(struct pcmcia_device *p_dev)
4693 * is released. 4675 * is released.
4694 */ 4676 */
4695static void 4677static void
4696wavelan_detach(struct pcmcia_device *p_dev) 4678wavelan_detach(struct pcmcia_device *link)
4697{ 4679{
4698 dev_link_t *link = dev_to_instance(p_dev);
4699
4700#ifdef DEBUG_CALLBACK_TRACE 4680#ifdef DEBUG_CALLBACK_TRACE
4701 printk(KERN_DEBUG "-> wavelan_detach(0x%p)\n", link); 4681 printk(KERN_DEBUG "-> wavelan_detach(0x%p)\n", link);
4702#endif 4682#endif
4703 4683
4704 /* 4684 /* Some others haven't done their job : give them another chance */
4705 * If the device is currently configured and active, we won't 4685 wv_pcmcia_release(link);
4706 * actually delete it yet. Instead, it is marked so that when the
4707 * release() function is called, that will trigger a proper
4708 * detach().
4709 */
4710 if(link->state & DEV_CONFIG)
4711 {
4712 /* Some others haven't done their job : give them another chance */
4713 wv_pcmcia_release(link);
4714 }
4715 4686
4716 /* Free pieces */ 4687 /* Free pieces */
4717 if(link->priv) 4688 if(link->priv)
@@ -4720,23 +4691,21 @@ wavelan_detach(struct pcmcia_device *p_dev)
4720 4691
4721 /* Remove ourselves from the kernel list of ethernet devices */ 4692 /* Remove ourselves from the kernel list of ethernet devices */
4722 /* Warning : can't be called from interrupt, timer or wavelan_close() */ 4693 /* Warning : can't be called from interrupt, timer or wavelan_close() */
4723 if (link->dev) 4694 if (link->dev_node)
4724 unregister_netdev(dev); 4695 unregister_netdev(dev);
4725 link->dev = NULL; 4696 link->dev_node = NULL;
4726 ((net_local *)netdev_priv(dev))->link = NULL; 4697 ((net_local *)netdev_priv(dev))->link = NULL;
4727 ((net_local *)netdev_priv(dev))->dev = NULL; 4698 ((net_local *)netdev_priv(dev))->dev = NULL;
4728 free_netdev(dev); 4699 free_netdev(dev);
4729 } 4700 }
4730 kfree(link);
4731 4701
4732#ifdef DEBUG_CALLBACK_TRACE 4702#ifdef DEBUG_CALLBACK_TRACE
4733 printk(KERN_DEBUG "<- wavelan_detach()\n"); 4703 printk(KERN_DEBUG "<- wavelan_detach()\n");
4734#endif 4704#endif
4735} 4705}
4736 4706
4737static int wavelan_suspend(struct pcmcia_device *p_dev) 4707static int wavelan_suspend(struct pcmcia_device *link)
4738{ 4708{
4739 dev_link_t *link = dev_to_instance(p_dev);
4740 struct net_device * dev = (struct net_device *) link->priv; 4709 struct net_device * dev = (struct net_device *) link->priv;
4741 4710
4742 /* NB: wavelan_close will be called, but too late, so we are 4711 /* NB: wavelan_close will be called, but too late, so we are
@@ -4748,36 +4717,22 @@ static int wavelan_suspend(struct pcmcia_device *p_dev)
4748 /* Stop receiving new messages and wait end of transmission */ 4717 /* Stop receiving new messages and wait end of transmission */
4749 wv_ru_stop(dev); 4718 wv_ru_stop(dev);
4750 4719
4720 if (link->open)
4721 netif_device_detach(dev);
4722
4751 /* Power down the module */ 4723 /* Power down the module */
4752 hacr_write(dev->base_addr, HACR_DEFAULT & (~HACR_PWR_STAT)); 4724 hacr_write(dev->base_addr, HACR_DEFAULT & (~HACR_PWR_STAT));
4753 4725
4754 /* The card is now suspended */
4755 link->state |= DEV_SUSPEND;
4756
4757 if(link->state & DEV_CONFIG)
4758 {
4759 if(link->open)
4760 netif_device_detach(dev);
4761 pcmcia_release_configuration(link->handle);
4762 }
4763
4764 return 0; 4726 return 0;
4765} 4727}
4766 4728
4767static int wavelan_resume(struct pcmcia_device *p_dev) 4729static int wavelan_resume(struct pcmcia_device *link)
4768{ 4730{
4769 dev_link_t *link = dev_to_instance(p_dev);
4770 struct net_device * dev = (struct net_device *) link->priv; 4731 struct net_device * dev = (struct net_device *) link->priv;
4771 4732
4772 link->state &= ~DEV_SUSPEND; 4733 if (link->open) {
4773 if(link->state & DEV_CONFIG) 4734 wv_hw_reset(dev);
4774 { 4735 netif_device_attach(dev);
4775 pcmcia_request_configuration(link->handle, &link->conf);
4776 if(link->open) /* If RESET -> True, If RESUME -> False ? */
4777 {
4778 wv_hw_reset(dev);
4779 netif_device_attach(dev);
4780 }
4781 } 4736 }
4782 4737
4783 return 0; 4738 return 0;
@@ -4798,7 +4753,7 @@ static struct pcmcia_driver wavelan_driver = {
4798 .drv = { 4753 .drv = {
4799 .name = "wavelan_cs", 4754 .name = "wavelan_cs",
4800 }, 4755 },
4801 .probe = wavelan_attach, 4756 .probe = wavelan_probe,
4802 .remove = wavelan_detach, 4757 .remove = wavelan_detach,
4803 .id_table = wavelan_ids, 4758 .id_table = wavelan_ids,
4804 .suspend = wavelan_suspend, 4759 .suspend = wavelan_suspend,
diff --git a/drivers/net/wireless/wavelan_cs.p.h b/drivers/net/wireless/wavelan_cs.p.h
index 451f6271dcbc..c65fe7a391ec 100644
--- a/drivers/net/wireless/wavelan_cs.p.h
+++ b/drivers/net/wireless/wavelan_cs.p.h
@@ -602,7 +602,7 @@ struct net_local
602 dev_node_t node; /* ???? What is this stuff ???? */ 602 dev_node_t node; /* ???? What is this stuff ???? */
603 struct net_device * dev; /* Reverse link... */ 603 struct net_device * dev; /* Reverse link... */
604 spinlock_t spinlock; /* Serialize access to the hardware (SMP) */ 604 spinlock_t spinlock; /* Serialize access to the hardware (SMP) */
605 dev_link_t * link; /* pcmcia structure */ 605 struct pcmcia_device * link; /* pcmcia structure */
606 en_stats stats; /* Ethernet interface statistics */ 606 en_stats stats; /* Ethernet interface statistics */
607 int nresets; /* Number of hw resets */ 607 int nresets; /* Number of hw resets */
608 u_char configured; /* If it is configured */ 608 u_char configured; /* If it is configured */
@@ -733,9 +733,9 @@ static int
733static inline void 733static inline void
734 wv_hw_reset(struct net_device *); /* Same, + start receiver unit */ 734 wv_hw_reset(struct net_device *); /* Same, + start receiver unit */
735static inline int 735static inline int
736 wv_pcmcia_config(dev_link_t *); /* Configure the pcmcia interface */ 736 wv_pcmcia_config(struct pcmcia_device *); /* Configure the pcmcia interface */
737static void 737static void
738 wv_pcmcia_release(dev_link_t *);/* Remove a device */ 738 wv_pcmcia_release(struct pcmcia_device *);/* Remove a device */
739/* ---------------------- INTERRUPT HANDLING ---------------------- */ 739/* ---------------------- INTERRUPT HANDLING ---------------------- */
740static irqreturn_t 740static irqreturn_t
741 wavelan_interrupt(int, /* Interrupt handler */ 741 wavelan_interrupt(int, /* Interrupt handler */
diff --git a/drivers/net/wireless/wl3501.h b/drivers/net/wireless/wl3501.h
index 4303c50c2ab6..65ceb088f700 100644
--- a/drivers/net/wireless/wl3501.h
+++ b/drivers/net/wireless/wl3501.h
@@ -611,5 +611,6 @@ struct wl3501_card {
611 struct iw_spy_data spy_data; 611 struct iw_spy_data spy_data;
612 struct iw_public_data wireless_data; 612 struct iw_public_data wireless_data;
613 struct dev_node_t node; 613 struct dev_node_t node;
614 struct pcmcia_device *p_dev;
614}; 615};
615#endif 616#endif
diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c
index 48e10b0c7e74..e52a650f6737 100644
--- a/drivers/net/wireless/wl3501_cs.c
+++ b/drivers/net/wireless/wl3501_cs.c
@@ -103,8 +103,8 @@ module_param(pc_debug, int, 0);
103 * release a socket, in response to card insertion and ejection events. They 103 * release a socket, in response to card insertion and ejection events. They
104 * are invoked from the wl24 event handler. 104 * are invoked from the wl24 event handler.
105 */ 105 */
106static void wl3501_config(dev_link_t *link); 106static int wl3501_config(struct pcmcia_device *link);
107static void wl3501_release(dev_link_t *link); 107static void wl3501_release(struct pcmcia_device *link);
108 108
109/* 109/*
110 * The dev_info variable is the "key" that is used to match up this 110 * The dev_info variable is the "key" that is used to match up this
@@ -226,17 +226,6 @@ static void iw_copy_mgmt_info_element(struct iw_mgmt_info_element *to,
226 iw_set_mgmt_info_element(from->id, to, from->data, from->len); 226 iw_set_mgmt_info_element(from->id, to, from->data, from->len);
227} 227}
228 228
229/*
230 * A linked list of "instances" of the wl24 device. Each actual PCMCIA card
231 * corresponds to one device instance, and is described by one dev_link_t
232 * structure (defined in ds.h).
233 *
234 * You may not want to use a linked list for this -- for example, the memory
235 * card driver uses an array of dev_link_t pointers, where minor device numbers
236 * are used to derive the corresponding array index.
237 */
238static dev_link_t *wl3501_dev_list;
239
240static inline void wl3501_switch_page(struct wl3501_card *this, u8 page) 229static inline void wl3501_switch_page(struct wl3501_card *this, u8 page)
241{ 230{
242 wl3501_outb(page, this->base_addr + WL3501_NIC_BSS); 231 wl3501_outb(page, this->base_addr + WL3501_NIC_BSS);
@@ -1281,15 +1270,10 @@ static int wl3501_close(struct net_device *dev)
1281 struct wl3501_card *this = dev->priv; 1270 struct wl3501_card *this = dev->priv;
1282 int rc = -ENODEV; 1271 int rc = -ENODEV;
1283 unsigned long flags; 1272 unsigned long flags;
1284 dev_link_t *link; 1273 struct pcmcia_device *link;
1274 link = this->p_dev;
1285 1275
1286 spin_lock_irqsave(&this->lock, flags); 1276 spin_lock_irqsave(&this->lock, flags);
1287 /* Check if the device is in wl3501_dev_list */
1288 for (link = wl3501_dev_list; link; link = link->next)
1289 if (link->priv == dev)
1290 break;
1291 if (!link)
1292 goto out;
1293 link->open--; 1277 link->open--;
1294 1278
1295 /* Stop wl3501_hard_start_xmit() from now on */ 1279 /* Stop wl3501_hard_start_xmit() from now on */
@@ -1301,7 +1285,6 @@ static int wl3501_close(struct net_device *dev)
1301 1285
1302 rc = 0; 1286 rc = 0;
1303 printk(KERN_INFO "%s: WL3501 closed\n", dev->name); 1287 printk(KERN_INFO "%s: WL3501 closed\n", dev->name);
1304out:
1305 spin_unlock_irqrestore(&this->lock, flags); 1288 spin_unlock_irqrestore(&this->lock, flags);
1306 return rc; 1289 return rc;
1307} 1290}
@@ -1400,14 +1383,11 @@ static int wl3501_open(struct net_device *dev)
1400 int rc = -ENODEV; 1383 int rc = -ENODEV;
1401 struct wl3501_card *this = dev->priv; 1384 struct wl3501_card *this = dev->priv;
1402 unsigned long flags; 1385 unsigned long flags;
1403 dev_link_t *link; 1386 struct pcmcia_device *link;
1387 link = this->p_dev;
1404 1388
1405 spin_lock_irqsave(&this->lock, flags); 1389 spin_lock_irqsave(&this->lock, flags);
1406 /* Check if the device is in wl3501_dev_list */ 1390 if (!pcmcia_dev_present(link))
1407 for (link = wl3501_dev_list; link; link = link->next)
1408 if (link->priv == dev)
1409 break;
1410 if (!DEV_OK(link))
1411 goto out; 1391 goto out;
1412 netif_device_attach(dev); 1392 netif_device_attach(dev);
1413 link->open++; 1393 link->open++;
@@ -1497,38 +1477,23 @@ static struct ethtool_ops ops = {
1497 * Services. If it has been released, all local data structures are freed. 1477 * Services. If it has been released, all local data structures are freed.
1498 * Otherwise, the structures will be freed when the device is released. 1478 * Otherwise, the structures will be freed when the device is released.
1499 */ 1479 */
1500static void wl3501_detach(struct pcmcia_device *p_dev) 1480static void wl3501_detach(struct pcmcia_device *link)
1501{ 1481{
1502 dev_link_t *link = dev_to_instance(p_dev);
1503 dev_link_t **linkp;
1504 struct net_device *dev = link->priv; 1482 struct net_device *dev = link->priv;
1505 1483
1506 /* Locate device structure */
1507 for (linkp = &wl3501_dev_list; *linkp; linkp = &(*linkp)->next)
1508 if (*linkp == link)
1509 break;
1510 if (!*linkp)
1511 goto out;
1512
1513 /* If the device is currently configured and active, we won't actually 1484 /* If the device is currently configured and active, we won't actually
1514 * delete it yet. Instead, it is marked so that when the release() 1485 * delete it yet. Instead, it is marked so that when the release()
1515 * function is called, that will trigger a proper detach(). */ 1486 * function is called, that will trigger a proper detach(). */
1516 1487
1517 if (link->state & DEV_CONFIG) { 1488 while (link->open > 0)
1518 while (link->open > 0) 1489 wl3501_close(dev);
1519 wl3501_close(dev);
1520
1521 netif_device_detach(dev);
1522 wl3501_release(link);
1523 }
1524 1490
1525 /* Unlink device structure, free pieces */ 1491 netif_device_detach(dev);
1526 *linkp = link->next; 1492 wl3501_release(link);
1527 1493
1528 if (link->priv) 1494 if (link->priv)
1529 free_netdev(link->priv); 1495 free_netdev(link->priv);
1530 kfree(link); 1496
1531out:
1532 return; 1497 return;
1533} 1498}
1534 1499
@@ -1953,33 +1918,26 @@ static const struct iw_handler_def wl3501_handler_def = {
1953 * The dev_link structure is initialized, but we don't actually configure the 1918 * The dev_link structure is initialized, but we don't actually configure the
1954 * card at this point -- we wait until we receive a card insertion event. 1919 * card at this point -- we wait until we receive a card insertion event.
1955 */ 1920 */
1956static int wl3501_attach(struct pcmcia_device *p_dev) 1921static int wl3501_probe(struct pcmcia_device *p_dev)
1957{ 1922{
1958 dev_link_t *link;
1959 struct net_device *dev; 1923 struct net_device *dev;
1960 struct wl3501_card *this; 1924 struct wl3501_card *this;
1961 1925
1962 /* Initialize the dev_link_t structure */
1963 link = kzalloc(sizeof(*link), GFP_KERNEL);
1964 if (!link)
1965 return -ENOMEM;
1966
1967 /* The io structure describes IO port mapping */ 1926 /* The io structure describes IO port mapping */
1968 link->io.NumPorts1 = 16; 1927 p_dev->io.NumPorts1 = 16;
1969 link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; 1928 p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
1970 link->io.IOAddrLines = 5; 1929 p_dev->io.IOAddrLines = 5;
1971 1930
1972 /* Interrupt setup */ 1931 /* Interrupt setup */
1973 link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; 1932 p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
1974 link->irq.IRQInfo1 = IRQ_LEVEL_ID; 1933 p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID;
1975 link->irq.Handler = wl3501_interrupt; 1934 p_dev->irq.Handler = wl3501_interrupt;
1976 1935
1977 /* General socket configuration */ 1936 /* General socket configuration */
1978 link->conf.Attributes = CONF_ENABLE_IRQ; 1937 p_dev->conf.Attributes = CONF_ENABLE_IRQ;
1979 link->conf.Vcc = 50; 1938 p_dev->conf.IntType = INT_MEMORY_AND_IO;
1980 link->conf.IntType = INT_MEMORY_AND_IO; 1939 p_dev->conf.ConfigIndex = 1;
1981 link->conf.ConfigIndex = 1; 1940 p_dev->conf.Present = PRESENT_OPTION;
1982 link->conf.Present = PRESENT_OPTION;
1983 1941
1984 dev = alloc_etherdev(sizeof(struct wl3501_card)); 1942 dev = alloc_etherdev(sizeof(struct wl3501_card));
1985 if (!dev) 1943 if (!dev)
@@ -1992,22 +1950,15 @@ static int wl3501_attach(struct pcmcia_device *p_dev)
1992 dev->get_stats = wl3501_get_stats; 1950 dev->get_stats = wl3501_get_stats;
1993 this = dev->priv; 1951 this = dev->priv;
1994 this->wireless_data.spy_data = &this->spy_data; 1952 this->wireless_data.spy_data = &this->spy_data;
1953 this->p_dev = p_dev;
1995 dev->wireless_data = &this->wireless_data; 1954 dev->wireless_data = &this->wireless_data;
1996 dev->wireless_handlers = (struct iw_handler_def *)&wl3501_handler_def; 1955 dev->wireless_handlers = (struct iw_handler_def *)&wl3501_handler_def;
1997 SET_ETHTOOL_OPS(dev, &ops); 1956 SET_ETHTOOL_OPS(dev, &ops);
1998 netif_stop_queue(dev); 1957 netif_stop_queue(dev);
1999 link->priv = link->irq.Instance = dev; 1958 p_dev->priv = p_dev->irq.Instance = dev;
2000
2001 link->handle = p_dev;
2002 p_dev->instance = link;
2003
2004 link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
2005 wl3501_config(link);
2006 1959
2007 return 0; 1960 return wl3501_config(p_dev);
2008out_link: 1961out_link:
2009 kfree(link);
2010 link = NULL;
2011 return -ENOMEM; 1962 return -ENOMEM;
2012} 1963}
2013 1964
@@ -2022,11 +1973,10 @@ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
2022 * received, to configure the PCMCIA socket, and to make the ethernet device 1973 * received, to configure the PCMCIA socket, and to make the ethernet device
2023 * available to the system. 1974 * available to the system.
2024 */ 1975 */
2025static void wl3501_config(dev_link_t *link) 1976static int wl3501_config(struct pcmcia_device *link)
2026{ 1977{
2027 tuple_t tuple; 1978 tuple_t tuple;
2028 cisparse_t parse; 1979 cisparse_t parse;
2029 client_handle_t handle = link->handle;
2030 struct net_device *dev = link->priv; 1980 struct net_device *dev = link->priv;
2031 int i = 0, j, last_fn, last_ret; 1981 int i = 0, j, last_fn, last_ret;
2032 unsigned char bf[64]; 1982 unsigned char bf[64];
@@ -2035,18 +1985,15 @@ static void wl3501_config(dev_link_t *link)
2035 /* This reads the card's CONFIG tuple to find its config registers. */ 1985 /* This reads the card's CONFIG tuple to find its config registers. */
2036 tuple.Attributes = 0; 1986 tuple.Attributes = 0;
2037 tuple.DesiredTuple = CISTPL_CONFIG; 1987 tuple.DesiredTuple = CISTPL_CONFIG;
2038 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); 1988 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
2039 tuple.TupleData = bf; 1989 tuple.TupleData = bf;
2040 tuple.TupleDataMax = sizeof(bf); 1990 tuple.TupleDataMax = sizeof(bf);
2041 tuple.TupleOffset = 0; 1991 tuple.TupleOffset = 0;
2042 CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); 1992 CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
2043 CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); 1993 CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
2044 link->conf.ConfigBase = parse.config.base; 1994 link->conf.ConfigBase = parse.config.base;
2045 link->conf.Present = parse.config.rmask[0]; 1995 link->conf.Present = parse.config.rmask[0];
2046 1996
2047 /* Configure card */
2048 link->state |= DEV_CONFIG;
2049
2050 /* Try allocating IO ports. This tries a few fixed addresses. If you 1997 /* Try allocating IO ports. This tries a few fixed addresses. If you
2051 * want, you can also read the card's config table to pick addresses -- 1998 * want, you can also read the card's config table to pick addresses --
2052 * see the serial driver for an example. */ 1999 * see the serial driver for an example. */
@@ -2056,28 +2003,28 @@ static void wl3501_config(dev_link_t *link)
2056 * 0x200-0x2ff, and so on, because this seems safer */ 2003 * 0x200-0x2ff, and so on, because this seems safer */
2057 link->io.BasePort1 = j; 2004 link->io.BasePort1 = j;
2058 link->io.BasePort2 = link->io.BasePort1 + 0x10; 2005 link->io.BasePort2 = link->io.BasePort1 + 0x10;
2059 i = pcmcia_request_io(link->handle, &link->io); 2006 i = pcmcia_request_io(link, &link->io);
2060 if (i == CS_SUCCESS) 2007 if (i == CS_SUCCESS)
2061 break; 2008 break;
2062 } 2009 }
2063 if (i != CS_SUCCESS) { 2010 if (i != CS_SUCCESS) {
2064 cs_error(link->handle, RequestIO, i); 2011 cs_error(link, RequestIO, i);
2065 goto failed; 2012 goto failed;
2066 } 2013 }
2067 2014
2068 /* Now allocate an interrupt line. Note that this does not actually 2015 /* Now allocate an interrupt line. Note that this does not actually
2069 * assign a handler to the interrupt. */ 2016 * assign a handler to the interrupt. */
2070 2017
2071 CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq)); 2018 CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
2072 2019
2073 /* This actually configures the PCMCIA socket -- setting up the I/O 2020 /* This actually configures the PCMCIA socket -- setting up the I/O
2074 * windows and the interrupt mapping. */ 2021 * windows and the interrupt mapping. */
2075 2022
2076 CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf)); 2023 CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
2077 2024
2078 dev->irq = link->irq.AssignedIRQ; 2025 dev->irq = link->irq.AssignedIRQ;
2079 dev->base_addr = link->io.BasePort1; 2026 dev->base_addr = link->io.BasePort1;
2080 SET_NETDEV_DEV(dev, &handle_to_dev(handle)); 2027 SET_NETDEV_DEV(dev, &handle_to_dev(link));
2081 if (register_netdev(dev)) { 2028 if (register_netdev(dev)) {
2082 printk(KERN_NOTICE "wl3501_cs: register_netdev() failed\n"); 2029 printk(KERN_NOTICE "wl3501_cs: register_netdev() failed\n");
2083 goto failed; 2030 goto failed;
@@ -2088,10 +2035,9 @@ static void wl3501_config(dev_link_t *link)
2088 this = dev->priv; 2035 this = dev->priv;
2089 /* 2036 /*
2090 * At this point, the dev_node_t structure(s) should be initialized and 2037 * At this point, the dev_node_t structure(s) should be initialized and
2091 * arranged in a linked list at link->dev. 2038 * arranged in a linked list at link->dev_node.
2092 */ 2039 */
2093 link->dev = &this->node; 2040 link->dev_node = &this->node;
2094 link->state &= ~DEV_CONFIG_PENDING;
2095 2041
2096 this->base_addr = dev->base_addr; 2042 this->base_addr = dev->base_addr;
2097 2043
@@ -2127,13 +2073,13 @@ static void wl3501_config(dev_link_t *link)
2127 spin_lock_init(&this->lock); 2073 spin_lock_init(&this->lock);
2128 init_waitqueue_head(&this->wait); 2074 init_waitqueue_head(&this->wait);
2129 netif_start_queue(dev); 2075 netif_start_queue(dev);
2130 goto out; 2076 return 0;
2077
2131cs_failed: 2078cs_failed:
2132 cs_error(link->handle, last_fn, last_ret); 2079 cs_error(link, last_fn, last_ret);
2133failed: 2080failed:
2134 wl3501_release(link); 2081 wl3501_release(link);
2135out: 2082 return -ENODEV;
2136 return;
2137} 2083}
2138 2084
2139/** 2085/**
@@ -2144,52 +2090,36 @@ out:
2144 * and release the PCMCIA configuration. If the device is still open, this 2090 * and release the PCMCIA configuration. If the device is still open, this
2145 * will be postponed until it is closed. 2091 * will be postponed until it is closed.
2146 */ 2092 */
2147static void wl3501_release(dev_link_t *link) 2093static void wl3501_release(struct pcmcia_device *link)
2148{ 2094{
2149 struct net_device *dev = link->priv; 2095 struct net_device *dev = link->priv;
2150 2096
2151 /* Unlink the device chain */ 2097 /* Unlink the device chain */
2152 if (link->dev) { 2098 if (link->dev_node)
2153 unregister_netdev(dev); 2099 unregister_netdev(dev);
2154 link->dev = NULL;
2155 }
2156 2100
2157 /* Don't bother checking to see if these succeed or not */ 2101 pcmcia_disable_device(link);
2158 pcmcia_release_configuration(link->handle);
2159 pcmcia_release_io(link->handle, &link->io);
2160 pcmcia_release_irq(link->handle, &link->irq);
2161 link->state &= ~DEV_CONFIG;
2162} 2102}
2163 2103
2164static int wl3501_suspend(struct pcmcia_device *p_dev) 2104static int wl3501_suspend(struct pcmcia_device *link)
2165{ 2105{
2166 dev_link_t *link = dev_to_instance(p_dev);
2167 struct net_device *dev = link->priv; 2106 struct net_device *dev = link->priv;
2168 2107
2169 link->state |= DEV_SUSPEND;
2170
2171 wl3501_pwr_mgmt(dev->priv, WL3501_SUSPEND); 2108 wl3501_pwr_mgmt(dev->priv, WL3501_SUSPEND);
2172 if (link->state & DEV_CONFIG) { 2109 if (link->open)
2173 if (link->open) 2110 netif_device_detach(dev);
2174 netif_device_detach(dev);
2175 pcmcia_release_configuration(link->handle);
2176 }
2177 2111
2178 return 0; 2112 return 0;
2179} 2113}
2180 2114
2181static int wl3501_resume(struct pcmcia_device *p_dev) 2115static int wl3501_resume(struct pcmcia_device *link)
2182{ 2116{
2183 dev_link_t *link = dev_to_instance(p_dev);
2184 struct net_device *dev = link->priv; 2117 struct net_device *dev = link->priv;
2185 2118
2186 wl3501_pwr_mgmt(dev->priv, WL3501_RESUME); 2119 wl3501_pwr_mgmt(dev->priv, WL3501_RESUME);
2187 if (link->state & DEV_CONFIG) { 2120 if (link->open) {
2188 pcmcia_request_configuration(link->handle, &link->conf); 2121 wl3501_reset(dev);
2189 if (link->open) { 2122 netif_device_attach(dev);
2190 wl3501_reset(dev);
2191 netif_device_attach(dev);
2192 }
2193 } 2123 }
2194 2124
2195 return 0; 2125 return 0;
@@ -2207,7 +2137,7 @@ static struct pcmcia_driver wl3501_driver = {
2207 .drv = { 2137 .drv = {
2208 .name = "wl3501_cs", 2138 .name = "wl3501_cs",
2209 }, 2139 },
2210 .probe = wl3501_attach, 2140 .probe = wl3501_probe,
2211 .remove = wl3501_detach, 2141 .remove = wl3501_detach,
2212 .id_table = wl3501_ids, 2142 .id_table = wl3501_ids,
2213 .suspend = wl3501_suspend, 2143 .suspend = wl3501_suspend,
@@ -2221,9 +2151,7 @@ static int __init wl3501_init_module(void)
2221 2151
2222static void __exit wl3501_exit_module(void) 2152static void __exit wl3501_exit_module(void)
2223{ 2153{
2224 dprintk(0, ": unloading");
2225 pcmcia_unregister_driver(&wl3501_driver); 2154 pcmcia_unregister_driver(&wl3501_driver);
2226 BUG_ON(wl3501_dev_list != NULL);
2227} 2155}
2228 2156
2229module_init(wl3501_init_module); 2157module_init(wl3501_init_module);