#define PFX DRIVER_NAME ": "
#include <linux/config.h>
-#ifdef __IN_PCMCIA_PACKAGE__
-#include <pcmcia/k_compat.h>
-#endif /* __IN_PCMCIA_PACKAGE__ */
-
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/ptrace.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/ioport.h>
-#include <linux/netdevice.h>
-#include <linux/if_arp.h>
-#include <linux/etherdevice.h>
-#include <linux/wireless.h>
-
+#include <linux/delay.h>
+#include <linux/firmware.h>
#include <pcmcia/cs_types.h>
#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/cisreg.h>
#include <pcmcia/ds.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/system.h>
-
#include "orinoco.h"
-/*
- * If SPECTRUM_FW_INCLUDED is defined, the firmware is hardcoded into
- * the driver. Use get_symbol_fw script to generate spectrum_fw.h and
- * copy it to the same directory as spectrum_cs.c.
- *
- * If SPECTRUM_FW_INCLUDED is not defined, the firmware is loaded at the
- * runtime using hotplug. Use the same get_symbol_fw script to generate
- * files symbol_sp24t_prim_fw symbol_sp24t_sec_fw, copy them to the
- * hotplug firmware directory (typically /usr/lib/hotplug/firmware) and
- * make sure that you have hotplug installed and enabled in the kernel.
- */
-/* #define SPECTRUM_FW_INCLUDED 1 */
-
-#ifdef SPECTRUM_FW_INCLUDED
-/* Header with the firmware */
-#include "spectrum_fw.h"
-#else /* !SPECTRUM_FW_INCLUDED */
-#include <linux/firmware.h>
static unsigned char *primsym;
static unsigned char *secsym;
static const char primary_fw_name[] = "symbol_sp24t_prim_fw";
static const char secondary_fw_name[] = "symbol_sp24t_sec_fw";
-#endif /* !SPECTRUM_FW_INCLUDED */
/********************************************************************/
/* Module stuff */
module_param(ignore_cis_vcc, int, 0);
MODULE_PARM_DESC(ignore_cis_vcc, "Allow voltage mismatch between card and socket");
-/********************************************************************/
-/* Magic constants */
-/********************************************************************/
-
-/*
- * The dev_info variable is the "key" that is used to match up this
- * device driver with appropriate cards, through the card
- * configuration database.
- */
-static dev_info_t dev_info = DRIVER_NAME;
-
/********************************************************************/
/* Data structures */
/********************************************************************/
dev_node_t node;
};
-/*
- * A linked list of "instances" of the device. Each actual PCMCIA
- * card corresponds to one device instance, and is described by one
- * dev_link_t structure (defined in ds.h).
- */
-static dev_link_t *dev_list; /* = NULL */
-
/********************************************************************/
/* Function prototypes */
/********************************************************************/
-/* device methods */
-static int spectrum_cs_hard_reset(struct orinoco_private *priv);
-
-/* PCMCIA gumpf */
-static void spectrum_cs_config(dev_link_t * link);
-static void spectrum_cs_release(dev_link_t * link);
-static int spectrum_cs_event(event_t event, int priority,
- event_callback_args_t * args);
-
-static dev_link_t *spectrum_cs_attach(void);
-static void spectrum_cs_detach(dev_link_t *);
+static void spectrum_cs_config(dev_link_t *link);
+static void spectrum_cs_release(dev_link_t *link);
/********************************************************************/
/* Firmware downloader */
* Each block has the following structure.
*/
struct dblock {
- u32 _addr; /* adapter address where to write the block */
- u16 _len; /* length of the data only, in bytes */
+ __le32 _addr; /* adapter address where to write the block */
+ __le16 _len; /* length of the data only, in bytes */
char data[0]; /* data to be written */
} __attribute__ ((packed));
* items with matching ID should be written.
*/
struct pdr {
- u32 _id; /* record ID */
- u32 _addr; /* adapter address where to write the data */
- u32 _len; /* expected length of the data, in bytes */
+ __le32 _id; /* record ID */
+ __le32 _addr; /* adapter address where to write the data */
+ __le32 _len; /* expected length of the data, in bytes */
char next[0]; /* next PDR starts here */
} __attribute__ ((packed));
* be plugged into the secondary firmware.
*/
struct pdi {
- u16 _len; /* length of ID and data, in words */
- u16 _id; /* record ID */
+ __le16 _len; /* length of ID and data, in words */
+ __le16 _id; /* record ID */
char data[0]; /* plug data */
} __attribute__ ((packed));;
/* Read PDA from the adapter */
static int
-spectrum_read_pda(hermes_t *hw, u16 *pda, int pda_len)
+spectrum_read_pda(hermes_t *hw, __le16 *pda, int pda_len)
{
int ret;
int pda_size;
/* Parse PDA and write the records into the adapter */
static int
spectrum_apply_pda(hermes_t *hw, const struct dblock *first_block,
- u16 *pda)
+ __le16 *pda)
{
int ret;
struct pdi *pdi;
const struct dblock *first_block;
/* Plug Data Area (PDA) */
- u16 pda[PDA_WORDS];
+ __le16 pda[PDA_WORDS];
/* Binary block begins after the 0x1A marker */
ptr = image;
{
int ret;
client_handle_t handle = link->handle;
-
-#ifndef SPECTRUM_FW_INCLUDED
const struct firmware *fw_entry;
if (request_firmware(&fw_entry, primary_fw_name,
secondary_fw_name);
return -ENOENT;
}
-#endif
/* Load primary firmware */
ret = spectrum_dl_image(hw, link, primsym);
* The dev_link structure is initialized, but we don't actually
* configure the card at this point -- we wait until we receive a card
* insertion event. */
-static dev_link_t *
-spectrum_cs_attach(void)
+static int
+spectrum_cs_attach(struct pcmcia_device *p_dev)
{
struct net_device *dev;
struct orinoco_private *priv;
struct orinoco_pccard *card;
dev_link_t *link;
- client_reg_t client_reg;
- int ret;
dev = alloc_orinocodev(sizeof(*card), spectrum_cs_hard_reset);
if (! dev)
- return NULL;
+ return -ENOMEM;
priv = netdev_priv(dev);
card = priv->card;
link->conf.Attributes = 0;
link->conf.IntType = INT_MEMORY_AND_IO;
- /* Register with Card Services */
- /* FIXME: need a lock? */
- link->next = dev_list;
- dev_list = link;
-
- client_reg.dev_info = &dev_info;
- client_reg.Version = 0x0210; /* FIXME: what does this mean? */
- client_reg.event_callback_args.client_data = link;
+ link->handle = p_dev;
+ p_dev->instance = link;
- ret = pcmcia_register_client(&link->handle, &client_reg);
- if (ret != CS_SUCCESS) {
- cs_error(link->handle, RegisterClient, ret);
- spectrum_cs_detach(link);
- return NULL;
- }
+ link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+ spectrum_cs_config(link);
- return link;
+ return 0;
} /* spectrum_cs_attach */
/*
* are freed. Otherwise, the structures will be freed when the device
* is released.
*/
-static void spectrum_cs_detach(dev_link_t *link)
+static void spectrum_cs_detach(struct pcmcia_device *p_dev)
{
- dev_link_t **linkp;
+ dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
- /* Locate device structure */
- for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
- if (*linkp == link)
- break;
-
- BUG_ON(*linkp == NULL);
-
if (link->state & DEV_CONFIG)
spectrum_cs_release(link);
- /* Break the link with Card Services */
- if (link->handle)
- pcmcia_deregister_client(link->handle);
-
- /* Unlink device structure, and free it */
- *linkp = link->next;
DEBUG(0, PFX "detach: link=%p link->dev=%p\n", link, link->dev);
if (link->dev) {
DEBUG(0, PFX "About to unregister net device %p\n",
ioport_unmap(priv->hw.iobase);
} /* spectrum_cs_release */
-/*
- * The card status event handler. Mostly, this schedules other stuff
- * to run after an event is received.
- */
+
static int
-spectrum_cs_event(event_t event, int priority,
- event_callback_args_t * args)
+spectrum_cs_suspend(struct pcmcia_device *p_dev)
{
- dev_link_t *link = args->client_data;
+ dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
struct orinoco_private *priv = netdev_priv(dev);
- int err = 0;
unsigned long flags;
+ int err = 0;
- switch (event) {
- case CS_EVENT_CARD_REMOVAL:
- link->state &= ~DEV_PRESENT;
- if (link->state & DEV_CONFIG) {
- unsigned long flags;
+ link->state |= DEV_SUSPEND;
+ /* Mark the device as stopped, to block IO until later */
+ if (link->state & DEV_CONFIG) {
+ spin_lock_irqsave(&priv->lock, flags);
- spin_lock_irqsave(&priv->lock, flags);
- netif_device_detach(dev);
- priv->hw_unavailable++;
- spin_unlock_irqrestore(&priv->lock, flags);
- }
- break;
+ err = __orinoco_down(dev);
+ if (err)
+ printk(KERN_WARNING "%s: Error %d downing interface\n",
+ dev->name, err);
- case CS_EVENT_CARD_INSERTION:
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- spectrum_cs_config(link);
- break;
+ netif_device_detach(dev);
+ priv->hw_unavailable++;
- case CS_EVENT_PM_SUSPEND:
- link->state |= DEV_SUSPEND;
- /* Fall through... */
- case CS_EVENT_RESET_PHYSICAL:
- /* Mark the device as stopped, to block IO until later */
- if (link->state & DEV_CONFIG) {
- /* This is probably racy, but I can't think of
- a better way, short of rewriting the PCMCIA
- layer to not suck :-( */
- spin_lock_irqsave(&priv->lock, flags);
-
- err = __orinoco_down(dev);
- if (err)
- printk(KERN_WARNING "%s: %s: Error %d downing interface\n",
- dev->name,
- event == CS_EVENT_PM_SUSPEND ? "SUSPEND" : "RESET_PHYSICAL",
- err);
-
- netif_device_detach(dev);
- priv->hw_unavailable++;
-
- spin_unlock_irqrestore(&priv->lock, flags);
-
- pcmcia_release_configuration(link->handle);
- }
- break;
+ spin_unlock_irqrestore(&priv->lock, flags);
- case CS_EVENT_PM_RESUME:
- link->state &= ~DEV_SUSPEND;
- /* Fall through... */
- case CS_EVENT_CARD_RESET:
- if (link->state & DEV_CONFIG) {
- /* FIXME: should we double check that this is
- * the same card as we had before */
- pcmcia_request_configuration(link->handle, &link->conf);
- netif_device_attach(dev);
- priv->hw_unavailable--;
- schedule_work(&priv->reset_work);
- }
- break;
+ pcmcia_release_configuration(link->handle);
}
- return err;
-} /* spectrum_cs_event */
+ return 0;
+}
+
+static int
+spectrum_cs_resume(struct pcmcia_device *p_dev)
+{
+ dev_link_t *link = dev_to_instance(p_dev);
+ struct net_device *dev = link->priv;
+ struct orinoco_private *priv = netdev_priv(dev);
+
+ link->state &= ~DEV_SUSPEND;
+ if (link->state & DEV_CONFIG) {
+ /* FIXME: should we double check that this is
+ * the same card as we had before */
+ pcmcia_request_configuration(link->handle, &link->conf);
+ netif_device_attach(dev);
+ priv->hw_unavailable--;
+ schedule_work(&priv->reset_work);
+ }
+ return 0;
+}
+
/********************************************************************/
/* Module initialization */
static struct pcmcia_device_id spectrum_cs_ids[] = {
PCMCIA_DEVICE_MANF_CARD(0x026c, 0x0001), /* Symbol Spectrum24 LA4100 */
PCMCIA_DEVICE_MANF_CARD(0x0104, 0x0001), /* Socket Communications CF */
- PCMCIA_DEVICE_MANF_CARD(0x0089, 0x0001), /* Intel PRO/Wireless 2011B */
+ PCMCIA_DEVICE_PROD_ID12("Intel", "PRO/Wireless LAN PC Card", 0x816cc815, 0x6fbf459a), /* 2011B, not 2011 */
PCMCIA_DEVICE_NULL,
};
MODULE_DEVICE_TABLE(pcmcia, spectrum_cs_ids);
.drv = {
.name = DRIVER_NAME,
},
- .attach = spectrum_cs_attach,
- .event = spectrum_cs_event,
- .detach = spectrum_cs_detach,
+ .probe = spectrum_cs_attach,
+ .remove = spectrum_cs_detach,
+ .suspend = spectrum_cs_suspend,
+ .resume = spectrum_cs_resume,
.id_table = spectrum_cs_ids,
};
exit_spectrum_cs(void)
{
pcmcia_unregister_driver(&orinoco_driver);
- BUG_ON(dev_list != NULL);
}
module_init(init_spectrum_cs);