aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/orinoco.c
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/wireless/orinoco.c
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/wireless/orinoco.c')
-rw-r--r--drivers/net/wireless/orinoco.c314
1 files changed, 312 insertions, 2 deletions
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;