Commit 3994d502 authored by David Kilroy's avatar David Kilroy Committed by John W. Linville

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: default avatarDavid Kilroy <kilroyd@gmail.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 8f5ae73c
...@@ -335,6 +335,7 @@ config HERMES ...@@ -335,6 +335,7 @@ config HERMES
tristate "Hermes chipset 802.11b support (Orinoco/Prism2/Symbol)" tristate "Hermes chipset 802.11b support (Orinoco/Prism2/Symbol)"
depends on (PPC_PMAC || PCI || PCMCIA) && WLAN_80211 depends on (PPC_PMAC || PCI || PCMCIA) && WLAN_80211
select WIRELESS_EXT select WIRELESS_EXT
select FW_LOADER
---help--- ---help---
A driver for 802.11b wireless cards based on the "Hermes" or A driver for 802.11b wireless cards based on the "Hermes" or
Intersil HFA384x (Prism 2) MAC controller. This includes the vast Intersil HFA384x (Prism 2) MAC controller. This includes the vast
...@@ -424,7 +425,6 @@ config PCMCIA_HERMES ...@@ -424,7 +425,6 @@ config PCMCIA_HERMES
config PCMCIA_SPECTRUM config PCMCIA_SPECTRUM
tristate "Symbol Spectrum24 Trilogy PCMCIA card support" tristate "Symbol Spectrum24 Trilogy PCMCIA card support"
depends on PCMCIA && HERMES depends on PCMCIA && HERMES
select FW_LOADER
---help--- ---help---
This is a driver for 802.11b cards using RAM-loadable Symbol This is a driver for 802.11b cards using RAM-loadable Symbol
......
...@@ -180,7 +180,8 @@ airport_attach(struct macio_dev *mdev, const struct of_device_id *match) ...@@ -180,7 +180,8 @@ airport_attach(struct macio_dev *mdev, const struct of_device_id *match)
} }
/* Allocate space for private device-specific data */ /* Allocate space for private device-specific data */
dev = alloc_orinocodev(sizeof(*card), airport_hard_reset); dev = alloc_orinocodev(sizeof(*card), &mdev->ofdev.dev,
airport_hard_reset, NULL);
if (! dev) { if (! dev) {
printk(KERN_ERR PFX "Cannot allocate network device\n"); printk(KERN_ERR PFX "Cannot allocate network device\n");
return -ENODEV; return -ENODEV;
......
This diff is collapsed.
...@@ -44,7 +44,9 @@ typedef struct { ...@@ -44,7 +44,9 @@ typedef struct {
struct orinoco_private { struct orinoco_private {
void *card; /* Pointer to card dependent structure */ void *card; /* Pointer to card dependent structure */
struct device *dev;
int (*hard_reset)(struct orinoco_private *); int (*hard_reset)(struct orinoco_private *);
int (*stop_fw)(struct orinoco_private *, int);
/* Synchronisation stuff */ /* Synchronisation stuff */
spinlock_t lock; spinlock_t lock;
...@@ -83,6 +85,7 @@ struct orinoco_private { ...@@ -83,6 +85,7 @@ struct orinoco_private {
unsigned int has_preamble:1; unsigned int has_preamble:1;
unsigned int has_sensitivity:1; unsigned int has_sensitivity:1;
unsigned int has_hostscan:1; unsigned int has_hostscan:1;
unsigned int do_fw_download:1;
unsigned int broken_disableport:1; unsigned int broken_disableport:1;
unsigned int broken_monitor:1; unsigned int broken_monitor:1;
...@@ -130,8 +133,10 @@ extern int orinoco_debug; ...@@ -130,8 +133,10 @@ extern int orinoco_debug;
/* Exported prototypes */ /* Exported prototypes */
/********************************************************************/ /********************************************************************/
extern struct net_device *alloc_orinocodev(int sizeof_card, extern struct net_device *alloc_orinocodev(
int (*hard_reset)(struct orinoco_private *)); int sizeof_card, struct device *device,
int (*hard_reset)(struct orinoco_private *),
int (*stop_fw)(struct orinoco_private *, int));
extern void free_orinocodev(struct net_device *dev); extern void free_orinocodev(struct net_device *dev);
extern int __orinoco_up(struct net_device *dev); extern int __orinoco_up(struct net_device *dev);
extern int __orinoco_down(struct net_device *dev); extern int __orinoco_down(struct net_device *dev);
......
...@@ -109,7 +109,8 @@ orinoco_cs_probe(struct pcmcia_device *link) ...@@ -109,7 +109,8 @@ orinoco_cs_probe(struct pcmcia_device *link)
struct orinoco_private *priv; struct orinoco_private *priv;
struct orinoco_pccard *card; struct orinoco_pccard *card;
dev = alloc_orinocodev(sizeof(*card), orinoco_cs_hard_reset); dev = alloc_orinocodev(sizeof(*card), &handle_to_dev(link),
orinoco_cs_hard_reset, NULL);
if (! dev) if (! dev)
return -ENOMEM; return -ENOMEM;
priv = netdev_priv(dev); priv = netdev_priv(dev);
......
...@@ -182,7 +182,8 @@ static int orinoco_nortel_init_one(struct pci_dev *pdev, ...@@ -182,7 +182,8 @@ static int orinoco_nortel_init_one(struct pci_dev *pdev,
} }
/* Allocate network device */ /* Allocate network device */
dev = alloc_orinocodev(sizeof(*card), orinoco_nortel_cor_reset); dev = alloc_orinocodev(sizeof(*card), &pdev->dev,
orinoco_nortel_cor_reset, NULL);
if (!dev) { if (!dev) {
printk(KERN_ERR PFX "Cannot allocate network device\n"); printk(KERN_ERR PFX "Cannot allocate network device\n");
err = -ENOMEM; err = -ENOMEM;
......
...@@ -139,7 +139,8 @@ static int orinoco_pci_init_one(struct pci_dev *pdev, ...@@ -139,7 +139,8 @@ static int orinoco_pci_init_one(struct pci_dev *pdev,
} }
/* Allocate network device */ /* Allocate network device */
dev = alloc_orinocodev(sizeof(*card), orinoco_pci_cor_reset); dev = alloc_orinocodev(sizeof(*card), &pdev->dev,
orinoco_pci_cor_reset, NULL);
if (!dev) { if (!dev) {
printk(KERN_ERR PFX "Cannot allocate network device\n"); printk(KERN_ERR PFX "Cannot allocate network device\n");
err = -ENOMEM; err = -ENOMEM;
......
...@@ -221,7 +221,8 @@ static int orinoco_plx_init_one(struct pci_dev *pdev, ...@@ -221,7 +221,8 @@ static int orinoco_plx_init_one(struct pci_dev *pdev,
} }
/* Allocate network device */ /* Allocate network device */
dev = alloc_orinocodev(sizeof(*card), orinoco_plx_cor_reset); dev = alloc_orinocodev(sizeof(*card), &pdev->dev,
orinoco_plx_cor_reset, NULL);
if (!dev) { if (!dev) {
printk(KERN_ERR PFX "Cannot allocate network device\n"); printk(KERN_ERR PFX "Cannot allocate network device\n");
err = -ENOMEM; err = -ENOMEM;
......
...@@ -124,7 +124,8 @@ static int orinoco_tmd_init_one(struct pci_dev *pdev, ...@@ -124,7 +124,8 @@ static int orinoco_tmd_init_one(struct pci_dev *pdev,
} }
/* Allocate network device */ /* Allocate network device */
dev = alloc_orinocodev(sizeof(*card), orinoco_tmd_cor_reset); dev = alloc_orinocodev(sizeof(*card), &pdev->dev,
orinoco_tmd_cor_reset, NULL);
if (!dev) { if (!dev) {
printk(KERN_ERR PFX "Cannot allocate network device\n"); printk(KERN_ERR PFX "Cannot allocate network device\n");
err = -ENOMEM; err = -ENOMEM;
......
...@@ -25,7 +25,6 @@ ...@@ -25,7 +25,6 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/firmware.h>
#include <pcmcia/cs_types.h> #include <pcmcia/cs_types.h>
#include <pcmcia/cs.h> #include <pcmcia/cs.h>
#include <pcmcia/cistpl.h> #include <pcmcia/cistpl.h>
...@@ -33,10 +32,6 @@ ...@@ -33,10 +32,6 @@
#include <pcmcia/ds.h> #include <pcmcia/ds.h>
#include "orinoco.h" #include "orinoco.h"
#include "hermes_dld.h"
static const char primary_fw_name[] = "symbol_sp24t_prim_fw";
static const char secondary_fw_name[] = "symbol_sp24t_sec_fw";
/********************************************************************/ /********************************************************************/
/* Module stuff */ /* Module stuff */
...@@ -72,26 +67,11 @@ struct orinoco_pccard { ...@@ -72,26 +67,11 @@ struct orinoco_pccard {
static int spectrum_cs_config(struct pcmcia_device *link); static int spectrum_cs_config(struct pcmcia_device *link);
static void spectrum_cs_release(struct pcmcia_device *link); static void spectrum_cs_release(struct pcmcia_device *link);
/********************************************************************/
/* Firmware downloader */
/********************************************************************/
/* Position of PDA in the adapter memory */
#define EEPROM_ADDR 0x3000
#define EEPROM_LEN 0x200
#define PDA_OFFSET 0x100
#define PDA_ADDR (EEPROM_ADDR + PDA_OFFSET)
#define PDA_WORDS ((EEPROM_LEN - PDA_OFFSET) / 2)
/* Constants for the CISREG_CCSR register */ /* Constants for the CISREG_CCSR register */
#define HCR_RUN 0x07 /* run firmware after reset */ #define HCR_RUN 0x07 /* run firmware after reset */
#define HCR_IDLE 0x0E /* don't run firmware after reset */ #define HCR_IDLE 0x0E /* don't run firmware after reset */
#define HCR_MEM16 0x10 /* memory width bit, should be preserved */ #define HCR_MEM16 0x10 /* memory width bit, should be preserved */
/* End markers */
#define TEXT_END 0x1A /* End of text header */
#define CS_CHECK(fn, ret) \ #define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) 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,142 +138,29 @@ spectrum_reset(struct pcmcia_device *link, int idle)
return -ENODEV; return -ENODEV;
} }
/********************************************************************/
/* Device methods */
/********************************************************************/
/*
* Process a firmware image - stop the card, load the firmware, reset
* the card and make sure it responds. For the secondary firmware take
* care of the PDA - read it and then write it on top of the firmware.
*/
static int static int
spectrum_dl_image(hermes_t *hw, struct pcmcia_device *link, spectrum_cs_hard_reset(struct orinoco_private *priv)
const unsigned char *image, const unsigned char *end,
int secondary)
{ {
int ret; struct orinoco_pccard *card = priv->card;
const unsigned char *ptr; struct pcmcia_device *link = card->p_dev;
const unsigned char *first_block;
/* Plug Data Area (PDA) */
__le16 pda[PDA_WORDS];
/* Binary block begins after the 0x1A marker */
ptr = image;
while (*ptr++ != TEXT_END);
first_block = ptr;
/* Read the PDA from EEPROM */
if (secondary) {
ret = hermes_read_pda(hw, pda, PDA_ADDR, sizeof(pda), 1);
if (ret)
return ret;
}
/* Stop the firmware, so that it can be safely rewritten */
ret = spectrum_reset(link, 1);
if (ret)
return ret;
/* Program the adapter with new firmware */
ret = hermes_program(hw, first_block, end);
if (ret)
return ret;
/* Write the PDA to the adapter */
if (secondary) {
size_t len = hermes_blocks_length(first_block);
ptr = first_block + len;
ret = hermes_apply_pda(hw, ptr, pda);
if (ret)
return ret;
}
/* Run the firmware */
ret = spectrum_reset(link, 0);
if (ret)
return ret;
/* Reset hermes chip and make sure it responds */
ret = hermes_init(hw);
/* hermes_reset() should return 0 with the secondary firmware */
if (secondary && ret != 0)
return -ENODEV;
/* And this should work with any firmware */ /* Soft reset using COR and HCR */
if (!hermes_present(hw)) spectrum_reset(link, 0);
return -ENODEV;
return 0; return 0;
} }
/*
* Download the firmware into the card, this also does a PCMCIA soft
* reset on the card, to make sure it's in a sane state.
*/
static int static int
spectrum_dl_firmware(hermes_t *hw, struct pcmcia_device *link) spectrum_cs_stop_firmware(struct orinoco_private *priv, int idle)
{
int ret;
const struct firmware *fw_entry;
if (request_firmware(&fw_entry, primary_fw_name,
&handle_to_dev(link)) != 0) {
printk(KERN_ERR PFX "Cannot find firmware: %s\n",
primary_fw_name);
return -ENOENT;
}
/* Load primary firmware */
ret = spectrum_dl_image(hw, link, fw_entry->data,
fw_entry->data + fw_entry->size, 0);
release_firmware(fw_entry);
if (ret) {
printk(KERN_ERR PFX "Primary firmware download failed\n");
return ret;
}
if (request_firmware(&fw_entry, secondary_fw_name,
&handle_to_dev(link)) != 0) {
printk(KERN_ERR PFX "Cannot find firmware: %s\n",
secondary_fw_name);
return -ENOENT;
}
/* Load secondary firmware */
ret = spectrum_dl_image(hw, link, fw_entry->data,
fw_entry->data + fw_entry->size, 1);
release_firmware(fw_entry);
if (ret) {
printk(KERN_ERR PFX "Secondary firmware download failed\n");
}
return ret;
}
/********************************************************************/
/* Device methods */
/********************************************************************/
static int
spectrum_cs_hard_reset(struct orinoco_private *priv)
{ {
struct orinoco_pccard *card = priv->card; struct orinoco_pccard *card = priv->card;
struct pcmcia_device *link = card->p_dev; struct pcmcia_device *link = card->p_dev;
int err;
if (!hermes_present(&priv->hw)) { return spectrum_reset(link, idle);
/* The firmware needs to be reloaded */
if (spectrum_dl_firmware(&priv->hw, link) != 0) {
printk(KERN_ERR PFX "Firmware download failed\n");
err = -ENODEV;
}
} else {
/* Soft reset using COR and HCR */
spectrum_reset(link, 0);
}
return 0;
} }
/********************************************************************/ /********************************************************************/
...@@ -315,7 +182,9 @@ spectrum_cs_probe(struct pcmcia_device *link) ...@@ -315,7 +182,9 @@ spectrum_cs_probe(struct pcmcia_device *link)
struct orinoco_private *priv; struct orinoco_private *priv;
struct orinoco_pccard *card; struct orinoco_pccard *card;
dev = alloc_orinocodev(sizeof(*card), spectrum_cs_hard_reset); dev = alloc_orinocodev(sizeof(*card), &handle_to_dev(link),
spectrum_cs_hard_reset,
spectrum_cs_stop_firmware);
if (! dev) if (! dev)
return -ENOMEM; return -ENOMEM;
priv = netdev_priv(dev); priv = netdev_priv(dev);
...@@ -517,7 +386,7 @@ spectrum_cs_config(struct pcmcia_device *link) ...@@ -517,7 +386,7 @@ spectrum_cs_config(struct pcmcia_device *link)
dev->irq = link->irq.AssignedIRQ; dev->irq = link->irq.AssignedIRQ;
card->node.major = card->node.minor = 0; card->node.major = card->node.minor = 0;
/* Reset card and download firmware */ /* Reset card */
if (spectrum_cs_hard_reset(priv) != 0) { if (spectrum_cs_hard_reset(priv) != 0) {
goto failed; goto failed;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment