aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorDavid Kilroy <kilroyd@gmail.com>2008-08-21 18:27:54 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-08-22 19:28:05 -0400
commit3994d502017a2239e30152d1231843ad05d04a7b (patch)
treec4f15d1b95783d035d954173167ff08e65665461 /drivers/net
parent8f5ae73c5366128d3800cf9765507422bcf1ef96 (diff)
orinoco: Invoke firmware download in main driver
Firmware download is enabled for Agere in orinoco_cs. Symbol firmware download has been moved out of spectrum_cs into orinoco_cs. Firmware download is not enabled for Intersil. Symbol based firmware is restricted to only download on spectrum_cs based cards. The firmware names are hardcoded for each firmware type. Signed-off-by: David Kilroy <kilroyd@gmail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/Kconfig2
-rw-r--r--drivers/net/wireless/airport.c3
-rw-r--r--drivers/net/wireless/orinoco.c314
-rw-r--r--drivers/net/wireless/orinoco.h9
-rw-r--r--drivers/net/wireless/orinoco_cs.c3
-rw-r--r--drivers/net/wireless/orinoco_nortel.c3
-rw-r--r--drivers/net/wireless/orinoco_pci.c3
-rw-r--r--drivers/net/wireless/orinoco_plx.c3
-rw-r--r--drivers/net/wireless/orinoco_tmd.c3
-rw-r--r--drivers/net/wireless/spectrum_cs.c159
10 files changed, 346 insertions, 156 deletions
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index 1ac46ad48c3e..ea7da7117f4d 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -335,6 +335,7 @@ config HERMES
335 tristate "Hermes chipset 802.11b support (Orinoco/Prism2/Symbol)" 335 tristate "Hermes chipset 802.11b support (Orinoco/Prism2/Symbol)"
336 depends on (PPC_PMAC || PCI || PCMCIA) && WLAN_80211 336 depends on (PPC_PMAC || PCI || PCMCIA) && WLAN_80211
337 select WIRELESS_EXT 337 select WIRELESS_EXT
338 select FW_LOADER
338 ---help--- 339 ---help---
339 A driver for 802.11b wireless cards based on the "Hermes" or 340 A driver for 802.11b wireless cards based on the "Hermes" or
340 Intersil HFA384x (Prism 2) MAC controller. This includes the vast 341 Intersil HFA384x (Prism 2) MAC controller. This includes the vast
@@ -424,7 +425,6 @@ config PCMCIA_HERMES
424config PCMCIA_SPECTRUM 425config PCMCIA_SPECTRUM
425 tristate "Symbol Spectrum24 Trilogy PCMCIA card support" 426 tristate "Symbol Spectrum24 Trilogy PCMCIA card support"
426 depends on PCMCIA && HERMES 427 depends on PCMCIA && HERMES
427 select FW_LOADER
428 ---help--- 428 ---help---
429 429
430 This is a driver for 802.11b cards using RAM-loadable Symbol 430 This is a driver for 802.11b cards using RAM-loadable Symbol
diff --git a/drivers/net/wireless/airport.c b/drivers/net/wireless/airport.c
index 6f7eb9f59223..ce03a2e865fa 100644
--- a/drivers/net/wireless/airport.c
+++ b/drivers/net/wireless/airport.c
@@ -180,7 +180,8 @@ airport_attach(struct macio_dev *mdev, const struct of_device_id *match)
180 } 180 }
181 181
182 /* Allocate space for private device-specific data */ 182 /* Allocate space for private device-specific data */
183 dev = alloc_orinocodev(sizeof(*card), airport_hard_reset); 183 dev = alloc_orinocodev(sizeof(*card), &mdev->ofdev.dev,
184 airport_hard_reset, NULL);
184 if (! dev) { 185 if (! dev) {
185 printk(KERN_ERR PFX "Cannot allocate network device\n"); 186 printk(KERN_ERR PFX "Cannot allocate network device\n");
186 return -ENODEV; 187 return -ENODEV;
diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c
index 00b1d595fa3c..306697aa3330 100644
--- a/drivers/net/wireless/orinoco.c
+++ b/drivers/net/wireless/orinoco.c
@@ -82,12 +82,14 @@
82#include <linux/netdevice.h> 82#include <linux/netdevice.h>
83#include <linux/etherdevice.h> 83#include <linux/etherdevice.h>
84#include <linux/ethtool.h> 84#include <linux/ethtool.h>
85#include <linux/firmware.h>
85#include <linux/if_arp.h> 86#include <linux/if_arp.h>
86#include <linux/wireless.h> 87#include <linux/wireless.h>
87#include <net/iw_handler.h> 88#include <net/iw_handler.h>
88#include <net/ieee80211.h> 89#include <net/ieee80211.h>
89 90
90#include "hermes_rid.h" 91#include "hermes_rid.h"
92#include "hermes_dld.h"
91#include "orinoco.h" 93#include "orinoco.h"
92 94
93/********************************************************************/ 95/********************************************************************/
@@ -301,6 +303,272 @@ static void orinoco_bss_data_init(struct orinoco_private *priv)
301 list_add_tail(&priv->bss_data[i].list, &priv->bss_free_list); 303 list_add_tail(&priv->bss_data[i].list, &priv->bss_free_list);
302} 304}
303 305
306
307/********************************************************************/
308/* Download functionality */
309/********************************************************************/
310
311struct fw_info {
312 char *pri_fw;
313 char *sta_fw;
314 char *ap_fw;
315 u32 pda_addr;
316 u16 pda_size;
317};
318
319const static struct fw_info orinoco_fw[] = {
320 { "", "agere_sta_fw.bin", "agere_ap_fw.bin", 0x00390000, 1000 },
321 { "", "prism_sta_fw.bin", "prism_ap_fw.bin", 0, 1024 },
322 { "symbol_sp24t_prim_fw", "symbol_sp24t_sec_fw", "", 0x00003100, 0x100 }
323};
324
325/* Structure used to access fields in FW
326 * Make sure LE decoding macros are used
327 */
328struct orinoco_fw_header {
329 char hdr_vers[6]; /* ASCII string for header version */
330 __le16 headersize; /* Total length of header */
331 __le32 entry_point; /* NIC entry point */
332 __le32 blocks; /* Number of blocks to program */
333 __le32 block_offset; /* Offset of block data from eof header */
334 __le32 pdr_offset; /* Offset to PDR data from eof header */
335 __le32 pri_offset; /* Offset to primary plug data */
336 __le32 compat_offset; /* Offset to compatibility data*/
337 char signature[0]; /* FW signature length headersize-20 */
338} __attribute__ ((packed));
339
340/* Download either STA or AP firmware into the card. */
341static int
342orinoco_dl_firmware(struct orinoco_private *priv,
343 const struct fw_info *fw,
344 int ap)
345{
346 /* Plug Data Area (PDA) */
347 __le16 pda[512] = { 0 };
348
349 hermes_t *hw = &priv->hw;
350 const struct firmware *fw_entry;
351 const struct orinoco_fw_header *hdr;
352 const unsigned char *first_block;
353 const unsigned char *end;
354 const char *firmware;
355 struct net_device *dev = priv->ndev;
356 int err;
357
358 if (ap)
359 firmware = fw->ap_fw;
360 else
361 firmware = fw->sta_fw;
362
363 printk(KERN_DEBUG "%s: Attempting to download firmware %s\n",
364 dev->name, firmware);
365
366 /* Read current plug data */
367 err = hermes_read_pda(hw, pda, fw->pda_addr,
368 min_t(u16, fw->pda_size, sizeof(pda)), 0);
369 printk(KERN_DEBUG "%s: Read PDA returned %d\n", dev->name, err);
370 if (err)
371 return err;
372
373 err = request_firmware(&fw_entry, firmware, priv->dev);
374 if (err) {
375 printk(KERN_ERR "%s: Cannot find firmware %s\n",
376 dev->name, firmware);
377 return -ENOENT;
378 }
379
380 hdr = (const struct orinoco_fw_header *) fw_entry->data;
381
382 /* Enable aux port to allow programming */
383 err = hermesi_program_init(hw, le32_to_cpu(hdr->entry_point));
384 printk(KERN_DEBUG "%s: Program init returned %d\n", dev->name, err);
385 if (err != 0)
386 goto abort;
387
388 /* Program data */
389 first_block = (fw_entry->data +
390 le16_to_cpu(hdr->headersize) +
391 le32_to_cpu(hdr->block_offset));
392 end = fw_entry->data + fw_entry->size;
393
394 err = hermes_program(hw, first_block, end);
395 printk(KERN_DEBUG "%s: Program returned %d\n", dev->name, err);
396 if (err != 0)
397 goto abort;
398
399 /* Update production data */
400 first_block = (fw_entry->data +
401 le16_to_cpu(hdr->headersize) +
402 le32_to_cpu(hdr->pdr_offset));
403
404 err = hermes_apply_pda_with_defaults(hw, first_block, pda);
405 printk(KERN_DEBUG "%s: Apply PDA returned %d\n", dev->name, err);
406 if (err)
407 goto abort;
408
409 /* Tell card we've finished */
410 err = hermesi_program_end(hw);
411 printk(KERN_DEBUG "%s: Program end returned %d\n", dev->name, err);
412 if (err != 0)
413 goto abort;
414
415 /* Check if we're running */
416 printk(KERN_DEBUG "%s: hermes_present returned %d\n",
417 dev->name, hermes_present(hw));
418
419abort:
420 release_firmware(fw_entry);
421 return err;
422}
423
424/* End markers */
425#define TEXT_END 0x1A /* End of text header */
426
427/*
428 * Process a firmware image - stop the card, load the firmware, reset
429 * the card and make sure it responds. For the secondary firmware take
430 * care of the PDA - read it and then write it on top of the firmware.
431 */
432static int
433symbol_dl_image(struct orinoco_private *priv, const struct fw_info *fw,
434 const unsigned char *image, const unsigned char *end,
435 int secondary)
436{
437 hermes_t *hw = &priv->hw;
438 int ret;
439 const unsigned char *ptr;
440 const unsigned char *first_block;
441
442 /* Plug Data Area (PDA) */
443 __le16 pda[256];
444
445 /* Binary block begins after the 0x1A marker */
446 ptr = image;
447 while (*ptr++ != TEXT_END);
448 first_block = ptr;
449
450 /* Read the PDA from EEPROM */
451 if (secondary) {
452 ret = hermes_read_pda(hw, pda, fw->pda_addr, sizeof(pda), 1);
453 if (ret)
454 return ret;
455 }
456
457 /* Stop the firmware, so that it can be safely rewritten */
458 if (priv->stop_fw) {
459 ret = priv->stop_fw(priv, 1);
460 if (ret)
461 return ret;
462 }
463
464 /* Program the adapter with new firmware */
465 ret = hermes_program(hw, first_block, end);
466 if (ret)
467 return ret;
468
469 /* Write the PDA to the adapter */
470 if (secondary) {
471 size_t len = hermes_blocks_length(first_block);
472 ptr = first_block + len;
473 ret = hermes_apply_pda(hw, ptr, pda);
474 if (ret)
475 return ret;
476 }
477
478 /* Run the firmware */
479 if (priv->stop_fw) {
480 ret = priv->stop_fw(priv, 0);
481 if (ret)
482 return ret;
483 }
484
485 /* Reset hermes chip and make sure it responds */
486 ret = hermes_init(hw);
487
488 /* hermes_reset() should return 0 with the secondary firmware */
489 if (secondary && ret != 0)
490 return -ENODEV;
491
492 /* And this should work with any firmware */
493 if (!hermes_present(hw))
494 return -ENODEV;
495
496 return 0;
497}
498
499
500/*
501 * Download the firmware into the card, this also does a PCMCIA soft
502 * reset on the card, to make sure it's in a sane state.
503 */
504static int
505symbol_dl_firmware(struct orinoco_private *priv,
506 const struct fw_info *fw)
507{
508 struct net_device *dev = priv->ndev;
509 int ret;
510 const struct firmware *fw_entry;
511
512 if (request_firmware(&fw_entry, fw->pri_fw,
513 priv->dev) != 0) {
514 printk(KERN_ERR "%s: Cannot find firmware: %s\n",
515 dev->name, fw->pri_fw);
516 return -ENOENT;
517 }
518
519 /* Load primary firmware */
520 ret = symbol_dl_image(priv, fw, fw_entry->data,
521 fw_entry->data + fw_entry->size, 0);
522 release_firmware(fw_entry);
523 if (ret) {
524 printk(KERN_ERR "%s: Primary firmware download failed\n",
525 dev->name);
526 return ret;
527 }
528
529 if (request_firmware(&fw_entry, fw->sta_fw,
530 priv->dev) != 0) {
531 printk(KERN_ERR "%s: Cannot find firmware: %s\n",
532 dev->name, fw->sta_fw);
533 return -ENOENT;
534 }
535
536 /* Load secondary firmware */
537 ret = symbol_dl_image(priv, fw, fw_entry->data,
538 fw_entry->data + fw_entry->size, 1);
539 release_firmware(fw_entry);
540 if (ret) {
541 printk(KERN_ERR "%s: Secondary firmware download failed\n",
542 dev->name);
543 }
544
545 return ret;
546}
547
548static int orinoco_download(struct orinoco_private *priv)
549{
550 int err = 0;
551 /* Reload firmware */
552 switch (priv->firmware_type) {
553 case FIRMWARE_TYPE_AGERE:
554 /* case FIRMWARE_TYPE_INTERSIL: */
555 err = orinoco_dl_firmware(priv,
556 &orinoco_fw[priv->firmware_type], 0);
557 break;
558
559 case FIRMWARE_TYPE_SYMBOL:
560 err = symbol_dl_firmware(priv,
561 &orinoco_fw[priv->firmware_type]);
562 break;
563 case FIRMWARE_TYPE_INTERSIL:
564 break;
565 }
566 /* TODO: if we fail we probably need to reinitialise
567 * the driver */
568
569 return err;
570}
571
304/********************************************************************/ 572/********************************************************************/
305/* Device methods */ 573/* Device methods */
306/********************************************************************/ 574/********************************************************************/
@@ -2043,6 +2311,12 @@ static void orinoco_reset(struct work_struct *work)
2043 } 2311 }
2044 } 2312 }
2045 2313
2314 if (priv->do_fw_download) {
2315 err = orinoco_download(priv);
2316 if (err)
2317 priv->do_fw_download = 0;
2318 }
2319
2046 err = orinoco_reinit_firmware(dev); 2320 err = orinoco_reinit_firmware(dev);
2047 if (err) { 2321 if (err) {
2048 printk(KERN_ERR "%s: orinoco_reset: Error %d re-initializing firmware\n", 2322 printk(KERN_ERR "%s: orinoco_reset: Error %d re-initializing firmware\n",
@@ -2254,6 +2528,7 @@ static int determine_firmware(struct net_device *dev)
2254 priv->has_ibss = 1; 2528 priv->has_ibss = 1;
2255 priv->has_wep = 0; 2529 priv->has_wep = 0;
2256 priv->has_big_wep = 0; 2530 priv->has_big_wep = 0;
2531 priv->do_fw_download = 0;
2257 2532
2258 /* Determine capabilities from the firmware version */ 2533 /* Determine capabilities from the firmware version */
2259 switch (priv->firmware_type) { 2534 switch (priv->firmware_type) {
@@ -2273,6 +2548,7 @@ static int determine_firmware(struct net_device *dev)
2273 priv->has_pm = (firmver >= 0x40020); /* Don't work in 7.52 ? */ 2548 priv->has_pm = (firmver >= 0x40020); /* Don't work in 7.52 ? */
2274 priv->ibss_port = 1; 2549 priv->ibss_port = 1;
2275 priv->has_hostscan = (firmver >= 0x8000a); 2550 priv->has_hostscan = (firmver >= 0x8000a);
2551 priv->do_fw_download = 1;
2276 priv->broken_monitor = (firmver >= 0x80000); 2552 priv->broken_monitor = (firmver >= 0x80000);
2277 2553
2278 /* Tested with Agere firmware : 2554 /* Tested with Agere firmware :
@@ -2317,6 +2593,21 @@ static int determine_firmware(struct net_device *dev)
2317 firmver >= 0x31000; 2593 firmver >= 0x31000;
2318 priv->has_preamble = (firmver >= 0x20000); 2594 priv->has_preamble = (firmver >= 0x20000);
2319 priv->ibss_port = 4; 2595 priv->ibss_port = 4;
2596
2597 /* Symbol firmware is found on various cards, but
2598 * there has been no attempt to check firmware
2599 * download on non-spectrum_cs based cards.
2600 *
2601 * Given that the Agere firmware download works
2602 * differently, we should avoid doing a firmware
2603 * download with the Symbol algorithm on non-spectrum
2604 * cards.
2605 *
2606 * For now we can identify a spectrum_cs based card
2607 * because it has a firmware reset function.
2608 */
2609 priv->do_fw_download = (priv->stop_fw != NULL);
2610
2320 priv->broken_disableport = (firmver == 0x25013) || 2611 priv->broken_disableport = (firmver == 0x25013) ||
2321 (firmver >= 0x30000 && firmver <= 0x31000); 2612 (firmver >= 0x30000 && firmver <= 0x31000);
2322 priv->has_hostscan = (firmver >= 0x31001) || 2613 priv->has_hostscan = (firmver >= 0x31001) ||
@@ -2387,6 +2678,20 @@ static int orinoco_init(struct net_device *dev)
2387 goto out; 2678 goto out;
2388 } 2679 }
2389 2680
2681 if (priv->do_fw_download) {
2682 err = orinoco_download(priv);
2683 if (err)
2684 priv->do_fw_download = 0;
2685
2686 /* Check firmware version again */
2687 err = determine_firmware(dev);
2688 if (err != 0) {
2689 printk(KERN_ERR "%s: Incompatible firmware, aborting\n",
2690 dev->name);
2691 goto out;
2692 }
2693 }
2694
2390 if (priv->has_port3) 2695 if (priv->has_port3)
2391 printk(KERN_DEBUG "%s: Ad-hoc demo mode supported\n", dev->name); 2696 printk(KERN_DEBUG "%s: Ad-hoc demo mode supported\n", dev->name);
2392 if (priv->has_ibss) 2697 if (priv->has_ibss)
@@ -2529,8 +2834,11 @@ static int orinoco_init(struct net_device *dev)
2529 return err; 2834 return err;
2530} 2835}
2531 2836
2532struct net_device *alloc_orinocodev(int sizeof_card, 2837struct net_device
2533 int (*hard_reset)(struct orinoco_private *)) 2838*alloc_orinocodev(int sizeof_card,
2839 struct device *device,
2840 int (*hard_reset)(struct orinoco_private *),
2841 int (*stop_fw)(struct orinoco_private *, int))
2534{ 2842{
2535 struct net_device *dev; 2843 struct net_device *dev;
2536 struct orinoco_private *priv; 2844 struct orinoco_private *priv;
@@ -2545,6 +2853,7 @@ struct net_device *alloc_orinocodev(int sizeof_card,
2545 + sizeof(struct orinoco_private)); 2853 + sizeof(struct orinoco_private));
2546 else 2854 else
2547 priv->card = NULL; 2855 priv->card = NULL;
2856 priv->dev = device;
2548 2857
2549 if (orinoco_bss_data_allocate(priv)) 2858 if (orinoco_bss_data_allocate(priv))
2550 goto err_out_free; 2859 goto err_out_free;
@@ -2570,6 +2879,7 @@ struct net_device *alloc_orinocodev(int sizeof_card,
2570 dev->open = orinoco_open; 2879 dev->open = orinoco_open;
2571 dev->stop = orinoco_stop; 2880 dev->stop = orinoco_stop;
2572 priv->hard_reset = hard_reset; 2881 priv->hard_reset = hard_reset;
2882 priv->stop_fw = stop_fw;
2573 2883
2574 spin_lock_init(&priv->lock); 2884 spin_lock_init(&priv->lock);
2575 priv->open = 0; 2885 priv->open = 0;
diff --git a/drivers/net/wireless/orinoco.h b/drivers/net/wireless/orinoco.h
index c6b1858abde8..e0acb633e9d5 100644
--- a/drivers/net/wireless/orinoco.h
+++ b/drivers/net/wireless/orinoco.h
@@ -44,7 +44,9 @@ typedef struct {
44 44
45struct orinoco_private { 45struct orinoco_private {
46 void *card; /* Pointer to card dependent structure */ 46 void *card; /* Pointer to card dependent structure */
47 struct device *dev;
47 int (*hard_reset)(struct orinoco_private *); 48 int (*hard_reset)(struct orinoco_private *);
49 int (*stop_fw)(struct orinoco_private *, int);
48 50
49 /* Synchronisation stuff */ 51 /* Synchronisation stuff */
50 spinlock_t lock; 52 spinlock_t lock;
@@ -83,6 +85,7 @@ struct orinoco_private {
83 unsigned int has_preamble:1; 85 unsigned int has_preamble:1;
84 unsigned int has_sensitivity:1; 86 unsigned int has_sensitivity:1;
85 unsigned int has_hostscan:1; 87 unsigned int has_hostscan:1;
88 unsigned int do_fw_download:1;
86 unsigned int broken_disableport:1; 89 unsigned int broken_disableport:1;
87 unsigned int broken_monitor:1; 90 unsigned int broken_monitor:1;
88 91
@@ -130,8 +133,10 @@ extern int orinoco_debug;
130/* Exported prototypes */ 133/* Exported prototypes */
131/********************************************************************/ 134/********************************************************************/
132 135
133extern struct net_device *alloc_orinocodev(int sizeof_card, 136extern struct net_device *alloc_orinocodev(
134 int (*hard_reset)(struct orinoco_private *)); 137 int sizeof_card, struct device *device,
138 int (*hard_reset)(struct orinoco_private *),
139 int (*stop_fw)(struct orinoco_private *, int));
135extern void free_orinocodev(struct net_device *dev); 140extern void free_orinocodev(struct net_device *dev);
136extern int __orinoco_up(struct net_device *dev); 141extern int __orinoco_up(struct net_device *dev);
137extern int __orinoco_down(struct net_device *dev); 142extern int __orinoco_down(struct net_device *dev);
diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c
index 1c216e015f64..1ccf5a40cf06 100644
--- a/drivers/net/wireless/orinoco_cs.c
+++ b/drivers/net/wireless/orinoco_cs.c
@@ -109,7 +109,8 @@ orinoco_cs_probe(struct pcmcia_device *link)
109 struct orinoco_private *priv; 109 struct orinoco_private *priv;
110 struct orinoco_pccard *card; 110 struct orinoco_pccard *card;
111 111
112 dev = alloc_orinocodev(sizeof(*card), orinoco_cs_hard_reset); 112 dev = alloc_orinocodev(sizeof(*card), &handle_to_dev(link),
113 orinoco_cs_hard_reset, NULL);
113 if (! dev) 114 if (! dev)
114 return -ENOMEM; 115 return -ENOMEM;
115 priv = netdev_priv(dev); 116 priv = netdev_priv(dev);
diff --git a/drivers/net/wireless/orinoco_nortel.c b/drivers/net/wireless/orinoco_nortel.c
index 35ec5fcf81a6..2fc86596302e 100644
--- a/drivers/net/wireless/orinoco_nortel.c
+++ b/drivers/net/wireless/orinoco_nortel.c
@@ -182,7 +182,8 @@ static int orinoco_nortel_init_one(struct pci_dev *pdev,
182 } 182 }
183 183
184 /* Allocate network device */ 184 /* Allocate network device */
185 dev = alloc_orinocodev(sizeof(*card), orinoco_nortel_cor_reset); 185 dev = alloc_orinocodev(sizeof(*card), &pdev->dev,
186 orinoco_nortel_cor_reset, NULL);
186 if (!dev) { 187 if (!dev) {
187 printk(KERN_ERR PFX "Cannot allocate network device\n"); 188 printk(KERN_ERR PFX "Cannot allocate network device\n");
188 err = -ENOMEM; 189 err = -ENOMEM;
diff --git a/drivers/net/wireless/orinoco_pci.c b/drivers/net/wireless/orinoco_pci.c
index 2547d5dac0d3..4ebd638a073e 100644
--- a/drivers/net/wireless/orinoco_pci.c
+++ b/drivers/net/wireless/orinoco_pci.c
@@ -139,7 +139,8 @@ static int orinoco_pci_init_one(struct pci_dev *pdev,
139 } 139 }
140 140
141 /* Allocate network device */ 141 /* Allocate network device */
142 dev = alloc_orinocodev(sizeof(*card), orinoco_pci_cor_reset); 142 dev = alloc_orinocodev(sizeof(*card), &pdev->dev,
143 orinoco_pci_cor_reset, NULL);
143 if (!dev) { 144 if (!dev) {
144 printk(KERN_ERR PFX "Cannot allocate network device\n"); 145 printk(KERN_ERR PFX "Cannot allocate network device\n");
145 err = -ENOMEM; 146 err = -ENOMEM;
diff --git a/drivers/net/wireless/orinoco_plx.c b/drivers/net/wireless/orinoco_plx.c
index 98fe165337d1..ef761857bb38 100644
--- a/drivers/net/wireless/orinoco_plx.c
+++ b/drivers/net/wireless/orinoco_plx.c
@@ -221,7 +221,8 @@ static int orinoco_plx_init_one(struct pci_dev *pdev,
221 } 221 }
222 222
223 /* Allocate network device */ 223 /* Allocate network device */
224 dev = alloc_orinocodev(sizeof(*card), orinoco_plx_cor_reset); 224 dev = alloc_orinocodev(sizeof(*card), &pdev->dev,
225 orinoco_plx_cor_reset, NULL);
225 if (!dev) { 226 if (!dev) {
226 printk(KERN_ERR PFX "Cannot allocate network device\n"); 227 printk(KERN_ERR PFX "Cannot allocate network device\n");
227 err = -ENOMEM; 228 err = -ENOMEM;
diff --git a/drivers/net/wireless/orinoco_tmd.c b/drivers/net/wireless/orinoco_tmd.c
index df493185a4af..ede24ec309c0 100644
--- a/drivers/net/wireless/orinoco_tmd.c
+++ b/drivers/net/wireless/orinoco_tmd.c
@@ -124,7 +124,8 @@ static int orinoco_tmd_init_one(struct pci_dev *pdev,
124 } 124 }
125 125
126 /* Allocate network device */ 126 /* Allocate network device */
127 dev = alloc_orinocodev(sizeof(*card), orinoco_tmd_cor_reset); 127 dev = alloc_orinocodev(sizeof(*card), &pdev->dev,
128 orinoco_tmd_cor_reset, NULL);
128 if (!dev) { 129 if (!dev) {
129 printk(KERN_ERR PFX "Cannot allocate network device\n"); 130 printk(KERN_ERR PFX "Cannot allocate network device\n");
130 err = -ENOMEM; 131 err = -ENOMEM;
diff --git a/drivers/net/wireless/spectrum_cs.c b/drivers/net/wireless/spectrum_cs.c
index 2fb00183cd71..e368759d1d89 100644
--- a/drivers/net/wireless/spectrum_cs.c
+++ b/drivers/net/wireless/spectrum_cs.c
@@ -25,7 +25,6 @@
25#include <linux/kernel.h> 25#include <linux/kernel.h>
26#include <linux/init.h> 26#include <linux/init.h>
27#include <linux/delay.h> 27#include <linux/delay.h>
28#include <linux/firmware.h>
29#include <pcmcia/cs_types.h> 28#include <pcmcia/cs_types.h>
30#include <pcmcia/cs.h> 29#include <pcmcia/cs.h>
31#include <pcmcia/cistpl.h> 30#include <pcmcia/cistpl.h>
@@ -33,10 +32,6 @@
33#include <pcmcia/ds.h> 32#include <pcmcia/ds.h>
34 33
35#include "orinoco.h" 34#include "orinoco.h"
36#include "hermes_dld.h"
37
38static const char primary_fw_name[] = "symbol_sp24t_prim_fw";
39static const char secondary_fw_name[] = "symbol_sp24t_sec_fw";
40 35
41/********************************************************************/ 36/********************************************************************/
42/* Module stuff */ 37/* Module stuff */
@@ -72,26 +67,11 @@ struct orinoco_pccard {
72static int spectrum_cs_config(struct pcmcia_device *link); 67static int spectrum_cs_config(struct pcmcia_device *link);
73static void spectrum_cs_release(struct pcmcia_device *link); 68static void spectrum_cs_release(struct pcmcia_device *link);
74 69
75/********************************************************************/
76/* Firmware downloader */
77/********************************************************************/
78
79/* Position of PDA in the adapter memory */
80#define EEPROM_ADDR 0x3000
81#define EEPROM_LEN 0x200
82#define PDA_OFFSET 0x100
83
84#define PDA_ADDR (EEPROM_ADDR + PDA_OFFSET)
85#define PDA_WORDS ((EEPROM_LEN - PDA_OFFSET) / 2)
86
87/* Constants for the CISREG_CCSR register */ 70/* Constants for the CISREG_CCSR register */
88#define HCR_RUN 0x07 /* run firmware after reset */ 71#define HCR_RUN 0x07 /* run firmware after reset */
89#define HCR_IDLE 0x0E /* don't run firmware after reset */ 72#define HCR_IDLE 0x0E /* don't run firmware after reset */
90#define HCR_MEM16 0x10 /* memory width bit, should be preserved */ 73#define HCR_MEM16 0x10 /* memory width bit, should be preserved */
91 74
92/* End markers */
93#define TEXT_END 0x1A /* End of text header */
94
95 75
96#define CS_CHECK(fn, ret) \ 76#define CS_CHECK(fn, ret) \
97 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) 77 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
@@ -158,142 +138,29 @@ spectrum_reset(struct pcmcia_device *link, int idle)
158 return -ENODEV; 138 return -ENODEV;
159} 139}
160 140
141/********************************************************************/
142/* Device methods */
143/********************************************************************/
161 144
162/*
163 * Process a firmware image - stop the card, load the firmware, reset
164 * the card and make sure it responds. For the secondary firmware take
165 * care of the PDA - read it and then write it on top of the firmware.
166 */
167static int 145static int
168spectrum_dl_image(hermes_t *hw, struct pcmcia_device *link, 146spectrum_cs_hard_reset(struct orinoco_private *priv)
169 const unsigned char *image, const unsigned char *end,
170 int secondary)
171{ 147{
172 int ret; 148 struct orinoco_pccard *card = priv->card;
173 const unsigned char *ptr; 149 struct pcmcia_device *link = card->p_dev;
174 const unsigned char *first_block;
175
176 /* Plug Data Area (PDA) */
177 __le16 pda[PDA_WORDS];
178
179 /* Binary block begins after the 0x1A marker */
180 ptr = image;
181 while (*ptr++ != TEXT_END);
182 first_block = ptr;
183
184 /* Read the PDA from EEPROM */
185 if (secondary) {
186 ret = hermes_read_pda(hw, pda, PDA_ADDR, sizeof(pda), 1);
187 if (ret)
188 return ret;
189 }
190
191 /* Stop the firmware, so that it can be safely rewritten */
192 ret = spectrum_reset(link, 1);
193 if (ret)
194 return ret;
195
196 /* Program the adapter with new firmware */
197 ret = hermes_program(hw, first_block, end);
198 if (ret)
199 return ret;
200
201 /* Write the PDA to the adapter */
202 if (secondary) {
203 size_t len = hermes_blocks_length(first_block);
204 ptr = first_block + len;
205 ret = hermes_apply_pda(hw, ptr, pda);
206 if (ret)
207 return ret;
208 }
209
210 /* Run the firmware */
211 ret = spectrum_reset(link, 0);
212 if (ret)
213 return ret;
214
215 /* Reset hermes chip and make sure it responds */
216 ret = hermes_init(hw);
217
218 /* hermes_reset() should return 0 with the secondary firmware */
219 if (secondary && ret != 0)
220 return -ENODEV;
221 150
222 /* And this should work with any firmware */ 151 /* Soft reset using COR and HCR */
223 if (!hermes_present(hw)) 152 spectrum_reset(link, 0);
224 return -ENODEV;
225 153
226 return 0; 154 return 0;
227} 155}
228 156
229
230/*
231 * Download the firmware into the card, this also does a PCMCIA soft
232 * reset on the card, to make sure it's in a sane state.
233 */
234static int 157static int
235spectrum_dl_firmware(hermes_t *hw, struct pcmcia_device *link) 158spectrum_cs_stop_firmware(struct orinoco_private *priv, int idle)
236{
237 int ret;
238 const struct firmware *fw_entry;
239
240 if (request_firmware(&fw_entry, primary_fw_name,
241 &handle_to_dev(link)) != 0) {
242 printk(KERN_ERR PFX "Cannot find firmware: %s\n",
243 primary_fw_name);
244 return -ENOENT;
245 }
246
247 /* Load primary firmware */
248 ret = spectrum_dl_image(hw, link, fw_entry->data,
249 fw_entry->data + fw_entry->size, 0);
250 release_firmware(fw_entry);
251 if (ret) {
252 printk(KERN_ERR PFX "Primary firmware download failed\n");
253 return ret;
254 }
255
256 if (request_firmware(&fw_entry, secondary_fw_name,
257 &handle_to_dev(link)) != 0) {
258 printk(KERN_ERR PFX "Cannot find firmware: %s\n",
259 secondary_fw_name);
260 return -ENOENT;
261 }
262
263 /* Load secondary firmware */
264 ret = spectrum_dl_image(hw, link, fw_entry->data,
265 fw_entry->data + fw_entry->size, 1);
266 release_firmware(fw_entry);
267 if (ret) {
268 printk(KERN_ERR PFX "Secondary firmware download failed\n");
269 }
270
271 return ret;
272}
273
274/********************************************************************/
275/* Device methods */
276/********************************************************************/
277
278static int
279spectrum_cs_hard_reset(struct orinoco_private *priv)
280{ 159{
281 struct orinoco_pccard *card = priv->card; 160 struct orinoco_pccard *card = priv->card;
282 struct pcmcia_device *link = card->p_dev; 161 struct pcmcia_device *link = card->p_dev;
283 int err;
284 162
285 if (!hermes_present(&priv->hw)) { 163 return spectrum_reset(link, idle);
286 /* The firmware needs to be reloaded */
287 if (spectrum_dl_firmware(&priv->hw, link) != 0) {
288 printk(KERN_ERR PFX "Firmware download failed\n");
289 err = -ENODEV;
290 }
291 } else {
292 /* Soft reset using COR and HCR */
293 spectrum_reset(link, 0);
294 }
295
296 return 0;
297} 164}
298 165
299/********************************************************************/ 166/********************************************************************/
@@ -315,7 +182,9 @@ spectrum_cs_probe(struct pcmcia_device *link)
315 struct orinoco_private *priv; 182 struct orinoco_private *priv;
316 struct orinoco_pccard *card; 183 struct orinoco_pccard *card;
317 184
318 dev = alloc_orinocodev(sizeof(*card), spectrum_cs_hard_reset); 185 dev = alloc_orinocodev(sizeof(*card), &handle_to_dev(link),
186 spectrum_cs_hard_reset,
187 spectrum_cs_stop_firmware);
319 if (! dev) 188 if (! dev)
320 return -ENOMEM; 189 return -ENOMEM;
321 priv = netdev_priv(dev); 190 priv = netdev_priv(dev);
@@ -517,7 +386,7 @@ spectrum_cs_config(struct pcmcia_device *link)
517 dev->irq = link->irq.AssignedIRQ; 386 dev->irq = link->irq.AssignedIRQ;
518 card->node.major = card->node.minor = 0; 387 card->node.major = card->node.minor = 0;
519 388
520 /* Reset card and download firmware */ 389 /* Reset card */
521 if (spectrum_cs_hard_reset(priv) != 0) { 390 if (spectrum_cs_hard_reset(priv) != 0) {
522 goto failed; 391 goto failed;
523 } 392 }