Commit 5bb7978a authored by David Gibson's avatar David Gibson Committed by Jeff Garzik

[PATCH] Orinoco driver update

This updates the orinoco wireless driver to version 0.13.
parent aa3f2b33
/* airport.c 0.11b /* airport.c 0.13
* *
* A driver for "Hermes" chipset based Apple Airport wireless * A driver for "Hermes" chipset based Apple Airport wireless
* card. * card.
...@@ -30,7 +30,6 @@ ...@@ -30,7 +30,6 @@
#include <linux/if_arp.h> #include <linux/if_arp.h>
#include <linux/etherdevice.h> #include <linux/etherdevice.h>
#include <linux/wireless.h> #include <linux/wireless.h>
#include <linux/list.h>
#include <linux/adb.h> #include <linux/adb.h>
#include <linux/pmu.h> #include <linux/pmu.h>
...@@ -39,22 +38,15 @@ ...@@ -39,22 +38,15 @@
#include <asm/pmac_feature.h> #include <asm/pmac_feature.h>
#include <asm/irq.h> #include <asm/irq.h>
#include "hermes.h"
#include "orinoco.h" #include "orinoco.h"
static char version[] __initdata = "airport.c 0.11b (Benjamin Herrenschmidt <benh@kernel.crashing.org>)";
MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
MODULE_DESCRIPTION("Driver for the Apple Airport wireless card.");
MODULE_LICENSE("Dual MPL/GPL");
#define AIRPORT_IO_LEN (0x1000) /* one page */ #define AIRPORT_IO_LEN (0x1000) /* one page */
struct airport { struct airport {
struct device_node* node; struct device_node *node;
void *vaddr; void *vaddr;
int irq_requested; int irq_requested;
int ndev_registered; int ndev_registered;
int open;
}; };
#ifdef CONFIG_PMAC_PBOOK #ifdef CONFIG_PMAC_PBOOK
...@@ -70,101 +62,77 @@ static struct pmu_sleep_notifier airport_sleep_notifier = { ...@@ -70,101 +62,77 @@ static struct pmu_sleep_notifier airport_sleep_notifier = {
static struct net_device *airport_attach(struct device_node *of_node); static struct net_device *airport_attach(struct device_node *of_node);
static void airport_detach(struct net_device *dev); static void airport_detach(struct net_device *dev);
static int airport_open(struct net_device *dev);
static int airport_stop(struct net_device *dev);
/*
A linked list of "instances" of the dummy device. Each actual
PCMCIA card corresponds to one device instance, and is described
by one dev_link_t structure (defined in ds.h).
You may not want to use a linked list for this -- for example, the
memory card driver uses an array of dev_link_t pointers, where minor
device numbers are used to derive the corresponding array index.
*/
static struct net_device *airport_dev; static struct net_device *airport_dev;
static int
airport_open(struct net_device *dev)
{
struct orinoco_private *priv = dev->priv;
struct airport* card = (struct airport *)priv->card;
int rc;
TRACE_ENTER(dev->name);
netif_device_attach(dev);
rc = orinoco_reset(priv);
if (rc)
airport_stop(dev);
else {
card->open = 1;
netif_start_queue(dev);
}
TRACE_EXIT(dev->name);
return rc;
}
static int
airport_stop(struct net_device *dev)
{
struct orinoco_private *priv = dev->priv;
struct airport* card = (struct airport *)priv->card;
TRACE_ENTER(dev->name);
netif_stop_queue(dev);
orinoco_shutdown(priv);
card->open = 0;
TRACE_EXIT(dev->name);
return 0;
}
#ifdef CONFIG_PMAC_PBOOK #ifdef CONFIG_PMAC_PBOOK
static int static int
airport_sleep_notify(struct pmu_sleep_notifier *self, int when) airport_sleep_notify(struct pmu_sleep_notifier *self, int when)
{ {
struct net_device *dev = airport_dev; struct net_device *dev = airport_dev;
struct orinoco_private *priv = (struct orinoco_private *)dev->priv; struct orinoco_private *priv = dev->priv;
struct hermes *hw = &priv->hw; struct airport *card = priv->card;
struct airport* card = (struct airport *)priv->card; unsigned long flags;
int rc; int err;
if (! airport_dev) if (! airport_dev)
return PBOOK_SLEEP_OK; return PBOOK_SLEEP_OK;
switch (when) { switch (when) {
case PBOOK_SLEEP_REQUEST:
break;
case PBOOK_SLEEP_REJECT:
break;
case PBOOK_SLEEP_NOW: case PBOOK_SLEEP_NOW:
printk(KERN_INFO "%s: Airport entering sleep mode\n", dev->name); printk(KERN_DEBUG "%s: Airport entering sleep mode\n", dev->name);
if (card->open) {
netif_stop_queue(dev); err = orinoco_lock(priv, &flags);
orinoco_shutdown(priv); if (err) {
netif_device_detach(dev); printk(KERN_ERR "%s: hw_unavailable on PBOOK_SLEEP_NOW\n",
dev->name);
break;
} }
err = __orinoco_down(dev);
if (err)
printk(KERN_WARNING "%s: PBOOK_SLEEP_NOW: Error %d downing interface\n",
dev->name, err);
netif_device_detach(dev);
priv->hw_unavailable = 1;
orinoco_unlock(priv, &flags);
disable_irq(dev->irq); disable_irq(dev->irq);
pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, card->node, 0, 0); pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, card->node, 0, 0);
break; break;
case PBOOK_WAKE: case PBOOK_WAKE:
printk(KERN_INFO "%s: Airport waking up\n", dev->name); printk(KERN_DEBUG "%s: Airport waking up\n", dev->name);
pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, card->node, 0, 1); pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, card->node, 0, 1);
mdelay(200); mdelay(200);
hermes_reset(hw);
rc = orinoco_reset(priv);
if (rc)
printk(KERN_ERR "airport: Error %d re-initing card !\n", rc);
else if (card->open)
netif_device_attach(dev);
enable_irq(dev->irq); enable_irq(dev->irq);
err = orinoco_reinit_firmware(dev);
if (err) {
printk(KERN_ERR "%s: Error %d re-initializing firmware on PBOOK_WAKE\n",
dev->name, err);
break;
}
spin_lock_irqsave(&priv->lock, flags);
netif_device_attach(dev);
if (priv->open) {
err = __orinoco_up(dev);
if (err)
printk(KERN_ERR "%s: Error %d restarting card on PBOOK_WAKE\n",
dev->name, err);
}
priv->hw_unavailable = 0;
spin_unlock_irqrestore(&priv->lock, flags);
break; break;
} }
return PBOOK_SLEEP_OK; return PBOOK_SLEEP_OK;
...@@ -172,7 +140,7 @@ airport_sleep_notify(struct pmu_sleep_notifier *self, int when) ...@@ -172,7 +140,7 @@ airport_sleep_notify(struct pmu_sleep_notifier *self, int when)
#endif /* CONFIG_PMAC_PBOOK */ #endif /* CONFIG_PMAC_PBOOK */
static struct net_device * static struct net_device *
airport_attach(struct device_node* of_node) airport_attach(struct device_node *of_node)
{ {
struct orinoco_private *priv; struct orinoco_private *priv;
struct net_device *dev; struct net_device *dev;
...@@ -180,15 +148,13 @@ airport_attach(struct device_node* of_node) ...@@ -180,15 +148,13 @@ airport_attach(struct device_node* of_node)
unsigned long phys_addr; unsigned long phys_addr;
hermes_t *hw; hermes_t *hw;
TRACE_ENTER("orinoco");
if (of_node->n_addrs < 1 || of_node->n_intrs < 1) { if (of_node->n_addrs < 1 || of_node->n_intrs < 1) {
printk(KERN_ERR "airport: wrong interrupt/addresses in OF tree\n"); printk(KERN_ERR "airport: wrong interrupt/addresses in OF tree\n");
return NULL; return NULL;
} }
/* Allocate space for private device-specific data */ /* Allocate space for private device-specific data */
dev = alloc_orinocodev(sizeof(*card)); dev = alloc_orinocodev(sizeof(*card), NULL);
if (! dev) { if (! dev) {
printk(KERN_ERR "airport: can't allocate device datas\n"); printk(KERN_ERR "airport: can't allocate device datas\n");
return NULL; return NULL;
...@@ -204,17 +170,14 @@ airport_attach(struct device_node* of_node) ...@@ -204,17 +170,14 @@ airport_attach(struct device_node* of_node)
kfree(dev); kfree(dev);
return NULL; return NULL;
} }
dev->name[0] = '\0'; /* register_netdev will give us an ethX name */ dev->name[0] = '\0'; /* register_netdev will give us an ethX name */
SET_MODULE_OWNER(dev); SET_MODULE_OWNER(dev);
/* Overrides */
dev->open = airport_open;
dev->stop = airport_stop;
/* Setup interrupts & base address */ /* Setup interrupts & base address */
dev->irq = of_node->intrs[0].line; dev->irq = of_node->intrs[0].line;
phys_addr = of_node->addrs[0].address; /* Physical address */ phys_addr = of_node->addrs[0].address; /* Physical address */
printk(KERN_DEBUG "Airport at physical address %lx\n", phys_addr);
dev->base_addr = phys_addr; dev->base_addr = phys_addr;
card->vaddr = ioremap(phys_addr, AIRPORT_IO_LEN); card->vaddr = ioremap(phys_addr, AIRPORT_IO_LEN);
if (! card->vaddr) { if (! card->vaddr) {
...@@ -231,14 +194,14 @@ airport_attach(struct device_node* of_node) ...@@ -231,14 +194,14 @@ airport_attach(struct device_node* of_node)
schedule_timeout(HZ); schedule_timeout(HZ);
/* Reset it before we get the interrupt */ /* Reset it before we get the interrupt */
hermes_reset(hw); hermes_init(hw);
if (request_irq(dev->irq, orinoco_interrupt, 0, "Airport", (void *)priv)) { if (request_irq(dev->irq, orinoco_interrupt, 0, "Airport", (void *)priv)) {
printk(KERN_ERR "airport: Couldn't get IRQ %d\n", dev->irq); printk(KERN_ERR "airport: Couldn't get IRQ %d\n", dev->irq);
goto failed; goto failed;
} }
card->irq_requested = 1; card->irq_requested = 1;
/* Tell the stack we exist */ /* Tell the stack we exist */
if (register_netdev(dev) != 0) { if (register_netdev(dev) != 0) {
printk(KERN_ERR "airport: register_netdev() failed\n"); printk(KERN_ERR "airport: register_netdev() failed\n");
...@@ -248,7 +211,7 @@ airport_attach(struct device_node* of_node) ...@@ -248,7 +211,7 @@ airport_attach(struct device_node* of_node)
card->ndev_registered = 1; card->ndev_registered = 1;
/* And give us the proc nodes for debugging */ /* And give us the proc nodes for debugging */
if (orinoco_proc_dev_init(priv) != 0) if (orinoco_proc_dev_init(dev) != 0)
printk(KERN_ERR "airport: Failed to create /proc node for %s\n", printk(KERN_ERR "airport: Failed to create /proc node for %s\n",
dev->name); dev->name);
...@@ -257,7 +220,7 @@ airport_attach(struct device_node* of_node) ...@@ -257,7 +220,7 @@ airport_attach(struct device_node* of_node)
#endif #endif
return dev; return dev;
failed: failed:
airport_detach(dev); airport_detach(dev);
return NULL; return NULL;
} /* airport_attach */ } /* airport_attach */
...@@ -273,7 +236,7 @@ airport_detach(struct net_device *dev) ...@@ -273,7 +236,7 @@ airport_detach(struct net_device *dev)
struct airport *card = priv->card; struct airport *card = priv->card;
/* Unregister proc entry */ /* Unregister proc entry */
orinoco_proc_dev_cleanup(priv); orinoco_proc_dev_cleanup(dev);
#ifdef CONFIG_PMAC_PBOOK #ifdef CONFIG_PMAC_PBOOK
pmu_unregister_sleep_notifier(&airport_sleep_notifier); pmu_unregister_sleep_notifier(&airport_sleep_notifier);
...@@ -281,7 +244,7 @@ airport_detach(struct net_device *dev) ...@@ -281,7 +244,7 @@ airport_detach(struct net_device *dev)
if (card->ndev_registered) if (card->ndev_registered)
unregister_netdev(dev); unregister_netdev(dev);
card->ndev_registered = 0; card->ndev_registered = 0;
if (card->irq_requested) if (card->irq_requested)
free_irq(dev->irq, priv); free_irq(dev->irq, priv);
card->irq_requested = 0; card->irq_requested = 0;
...@@ -289,22 +252,28 @@ airport_detach(struct net_device *dev) ...@@ -289,22 +252,28 @@ airport_detach(struct net_device *dev)
if (card->vaddr) if (card->vaddr)
iounmap(card->vaddr); iounmap(card->vaddr);
card->vaddr = 0; card->vaddr = 0;
dev->base_addr = 0; dev->base_addr = 0;
release_OF_resource(card->node, 0); release_OF_resource(card->node, 0);
pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, card->node, 0, 0); pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, card->node, 0, 0);
current->state = TASK_UNINTERRUPTIBLE; current->state = TASK_UNINTERRUPTIBLE;
schedule_timeout(HZ); schedule_timeout(HZ);
kfree(dev); kfree(dev);
} /* airport_detach */ } /* airport_detach */
static char version[] __initdata = "airport.c 0.13 (Benjamin Herrenschmidt <benh@kernel.crashing.org>)";
MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
MODULE_DESCRIPTION("Driver for the Apple Airport wireless card.");
MODULE_LICENSE("Dual MPL/GPL");
EXPORT_NO_SYMBOLS;
static int __init static int __init
init_airport(void) init_airport(void)
{ {
struct device_node* airport_node; struct device_node *airport_node;
printk(KERN_DEBUG "%s\n", version); printk(KERN_DEBUG "%s\n", version);
......
...@@ -45,7 +45,6 @@ ...@@ -45,7 +45,6 @@
#include <linux/threads.h> #include <linux/threads.h>
#include <linux/smp.h> #include <linux/smp.h>
#include <asm/io.h> #include <asm/io.h>
#include <linux/ptrace.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/kernel.h> #include <linux/kernel.h>
...@@ -53,7 +52,7 @@ ...@@ -53,7 +52,7 @@
#include "hermes.h" #include "hermes.h"
static char version[] __initdata = "hermes.c: 5 Apr 2002 David Gibson <hermes@gibson.dropbear.id.au>"; static char version[] __initdata = "hermes.c: 4 Jul 2002 David Gibson <hermes@gibson.dropbear.id.au>";
MODULE_DESCRIPTION("Low-level driver helper for Lucent Hermes chipset and Prism II HFA384x wireless MAC controller"); MODULE_DESCRIPTION("Low-level driver helper for Lucent Hermes chipset and Prism II HFA384x wireless MAC controller");
MODULE_AUTHOR("David Gibson <hermes@gibson.dropbear.id.au>"); MODULE_AUTHOR("David Gibson <hermes@gibson.dropbear.id.au>");
#ifdef MODULE_LICENSE #ifdef MODULE_LICENSE
...@@ -70,14 +69,14 @@ MODULE_LICENSE("Dual MPL/GPL"); ...@@ -70,14 +69,14 @@ MODULE_LICENSE("Dual MPL/GPL");
* Debugging helpers * Debugging helpers
*/ */
#define IO_TYPE(hw) ((hw)->io_space ? "IO " : "MEM ")
#define DMSG(stuff...) do {printk(KERN_DEBUG "hermes @ %s0x%x: " , IO_TYPE(hw), hw->iobase); \
printk(stuff);} while (0)
#undef HERMES_DEBUG #undef HERMES_DEBUG
#ifdef HERMES_DEBUG #ifdef HERMES_DEBUG
#include <stdarg.h> #include <stdarg.h>
#define DMSG(stuff...) do {printk(KERN_DEBUG "hermes @ 0x%x: " , hw->iobase); \
printk(stuff);} while (0)
#define DEBUG(lvl, stuff...) if ( (lvl) <= HERMES_DEBUG) DMSG(stuff) #define DEBUG(lvl, stuff...) if ( (lvl) <= HERMES_DEBUG) DMSG(stuff)
#else /* ! HERMES_DEBUG */ #else /* ! HERMES_DEBUG */
...@@ -86,7 +85,6 @@ MODULE_LICENSE("Dual MPL/GPL"); ...@@ -86,7 +85,6 @@ MODULE_LICENSE("Dual MPL/GPL");
#endif /* ! HERMES_DEBUG */ #endif /* ! HERMES_DEBUG */
#define IO_TYPE(hw) ((hw)->io_space ? "IO " : "MEM ")
/* /*
* Internal functions * Internal functions
...@@ -111,7 +109,6 @@ static int hermes_issue_cmd(hermes_t *hw, u16 cmd, u16 param0) ...@@ -111,7 +109,6 @@ static int hermes_issue_cmd(hermes_t *hw, u16 cmd, u16 param0)
udelay(1); udelay(1);
reg = hermes_read_regn(hw, CMD); reg = hermes_read_regn(hw, CMD);
} }
DEBUG(3, "hermes_issue_cmd: did %d retries.\n", CMD_BUSY_TIMEOUT-k);
if (reg & HERMES_CMD_BUSY) { if (reg & HERMES_CMD_BUSY) {
return -EBUSY; return -EBUSY;
} }
...@@ -143,7 +140,7 @@ void hermes_struct_init(hermes_t *hw, ulong address, ...@@ -143,7 +140,7 @@ void hermes_struct_init(hermes_t *hw, ulong address,
#endif #endif
} }
int hermes_reset(hermes_t *hw) int hermes_init(hermes_t *hw)
{ {
u16 status, reg; u16 status, reg;
int err = 0; int err = 0;
...@@ -195,8 +192,6 @@ int hermes_reset(hermes_t *hw) ...@@ -195,8 +192,6 @@ int hermes_reset(hermes_t *hw)
reg = hermes_read_regn(hw, EVSTAT); reg = hermes_read_regn(hw, EVSTAT);
} }
DEBUG(0, "Reset completed in %d iterations\n", CMD_INIT_TIMEOUT - k);
hermes_write_regn(hw, SWSUPPORT0, HERMES_MAGIC); hermes_write_regn(hw, SWSUPPORT0, HERMES_MAGIC);
if (! hermes_present(hw)) { if (! hermes_present(hw)) {
...@@ -303,9 +298,6 @@ int hermes_allocate(hermes_t *hw, u16 size, u16 *fid) ...@@ -303,9 +298,6 @@ int hermes_allocate(hermes_t *hw, u16 size, u16 *fid)
err = hermes_docmd_wait(hw, HERMES_CMD_ALLOC, size, NULL); err = hermes_docmd_wait(hw, HERMES_CMD_ALLOC, size, NULL);
if (err) { if (err) {
printk(KERN_WARNING "hermes @ %s0x%lx: "
"Frame allocation command failed (0x%X).\n",
IO_TYPE(hw), hw->iobase, err);
return err; return err;
} }
...@@ -393,12 +385,10 @@ static int hermes_bap_seek(hermes_t *hw, int bap, u16 id, u16 offset) ...@@ -393,12 +385,10 @@ static int hermes_bap_seek(hermes_t *hw, int bap, u16 id, u16 offset)
} }
if (reg & HERMES_OFFSET_BUSY) { if (reg & HERMES_OFFSET_BUSY) {
DEBUG(1,"hermes_bap_seek: timeout\n");
return -ETIMEDOUT; return -ETIMEDOUT;
} }
if (reg & HERMES_OFFSET_ERR) { if (reg & HERMES_OFFSET_ERR) {
DEBUG(1,"hermes_bap_seek: BAP error\n");
return -EIO; return -EIO;
} }
...@@ -472,6 +462,7 @@ int hermes_read_ltv(hermes_t *hw, int bap, u16 rid, int bufsize, ...@@ -472,6 +462,7 @@ int hermes_read_ltv(hermes_t *hw, int bap, u16 rid, int bufsize,
int err = 0; int err = 0;
int dreg = bap ? HERMES_DATA1 : HERMES_DATA0; int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
u16 rlength, rtype; u16 rlength, rtype;
int nwords;
if ( (bufsize < 0) || (bufsize % 2) ) if ( (bufsize < 0) || (bufsize % 2) )
return -EINVAL; return -EINVAL;
...@@ -500,10 +491,9 @@ int hermes_read_ltv(hermes_t *hw, int bap, u16 rid, int bufsize, ...@@ -500,10 +491,9 @@ int hermes_read_ltv(hermes_t *hw, int bap, u16 rid, int bufsize,
"(rid=0x%04x, len=0x%04x)\n", "(rid=0x%04x, len=0x%04x)\n",
IO_TYPE(hw), hw->iobase, IO_TYPE(hw), hw->iobase,
HERMES_RECLEN_TO_BYTES(rlength), bufsize, rid, rlength); HERMES_RECLEN_TO_BYTES(rlength), bufsize, rid, rlength);
/* FIXME: we should read the min of the requested length and nwords = min_t(int, rlength - 1, bufsize / 2);
the actual record length */ hermes_read_words(hw, dreg, buf, nwords);
hermes_read_words(hw, dreg, buf, bufsize / 2);
out: out:
return err; return err;
...@@ -516,9 +506,6 @@ int hermes_write_ltv(hermes_t *hw, int bap, u16 rid, ...@@ -516,9 +506,6 @@ int hermes_write_ltv(hermes_t *hw, int bap, u16 rid,
int err = 0; int err = 0;
int count; int count;
DEBUG(3, "write_ltv(): bap=%d rid=0x%04x length=%d (value=0x%04x)\n",
bap, rid, length, * ((u16 *)value));
err = hermes_bap_seek(hw, bap, rid, 0); err = hermes_bap_seek(hw, bap, rid, 0);
if (err) if (err)
goto out; goto out;
...@@ -538,7 +525,7 @@ int hermes_write_ltv(hermes_t *hw, int bap, u16 rid, ...@@ -538,7 +525,7 @@ int hermes_write_ltv(hermes_t *hw, int bap, u16 rid,
} }
EXPORT_SYMBOL(hermes_struct_init); EXPORT_SYMBOL(hermes_struct_init);
EXPORT_SYMBOL(hermes_reset); EXPORT_SYMBOL(hermes_init);
EXPORT_SYMBOL(hermes_docmd_wait); EXPORT_SYMBOL(hermes_docmd_wait);
EXPORT_SYMBOL(hermes_allocate); EXPORT_SYMBOL(hermes_allocate);
......
...@@ -171,6 +171,7 @@ struct hermes_rx_descriptor { ...@@ -171,6 +171,7 @@ struct hermes_rx_descriptor {
#define HERMES_RXSTAT_BADCRC (0x0001) #define HERMES_RXSTAT_BADCRC (0x0001)
#define HERMES_RXSTAT_UNDECRYPTABLE (0x0002) #define HERMES_RXSTAT_UNDECRYPTABLE (0x0002)
#define HERMES_RXSTAT_MACPORT (0x0700) #define HERMES_RXSTAT_MACPORT (0x0700)
#define HERMES_RXSTAT_PCF (0x1000) /* Frame was received in CF period */
#define HERMES_RXSTAT_MSGTYPE (0xE000) #define HERMES_RXSTAT_MSGTYPE (0xE000)
#define HERMES_RXSTAT_1042 (0x2000) /* RFC-1042 frame */ #define HERMES_RXSTAT_1042 (0x2000) /* RFC-1042 frame */
#define HERMES_RXSTAT_TUNNEL (0x4000) /* bridge-tunnel encoded frame */ #define HERMES_RXSTAT_TUNNEL (0x4000) /* bridge-tunnel encoded frame */
...@@ -299,7 +300,7 @@ typedef struct hermes_response { ...@@ -299,7 +300,7 @@ typedef struct hermes_response {
/* Function prototypes */ /* Function prototypes */
void hermes_struct_init(hermes_t *hw, ulong address, int io_space, int reg_spacing); void hermes_struct_init(hermes_t *hw, ulong address, int io_space, int reg_spacing);
int hermes_reset(hermes_t *hw); int hermes_init(hermes_t *hw);
int hermes_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0, hermes_response_t *resp); int hermes_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0, hermes_response_t *resp);
int hermes_allocate(hermes_t *hw, u16 size, u16 *fid); int hermes_allocate(hermes_t *hw, u16 size, u16 *fid);
...@@ -319,12 +320,6 @@ static inline int hermes_present(hermes_t *hw) ...@@ -319,12 +320,6 @@ static inline int hermes_present(hermes_t *hw)
return hermes_read_regn(hw, SWSUPPORT0) == HERMES_MAGIC; return hermes_read_regn(hw, SWSUPPORT0) == HERMES_MAGIC;
} }
static inline void hermes_enable_interrupt(hermes_t *hw, u16 events)
{
hw->inten |= events;
hermes_write_regn(hw, INTEN, hw->inten);
}
static inline void hermes_set_irqmask(hermes_t *hw, u16 events) static inline void hermes_set_irqmask(hermes_t *hw, u16 events)
{ {
hw->inten = events; hw->inten = events;
...@@ -350,7 +345,7 @@ static inline int hermes_inquire(hermes_t *hw, u16 rid) ...@@ -350,7 +345,7 @@ static inline int hermes_inquire(hermes_t *hw, u16 rid)
return hermes_docmd_wait(hw, HERMES_CMD_INQUIRE, rid, NULL); return hermes_docmd_wait(hw, HERMES_CMD_INQUIRE, rid, NULL);
} }
#define HERMES_BYTES_TO_RECLEN(n) ( ((n) % 2) ? (((n)+1)/2)+1 : ((n)/2)+1 ) #define HERMES_BYTES_TO_RECLEN(n) ( (((n)+1)/2) + 1 )
#define HERMES_RECLEN_TO_BYTES(n) ( ((n)-1) * 2 ) #define HERMES_RECLEN_TO_BYTES(n) ( ((n)-1) * 2 )
/* Note that for the next two, the count is in 16-bit words, not bytes */ /* Note that for the next two, the count is in 16-bit words, not bytes */
......
...@@ -3,8 +3,8 @@ ...@@ -3,8 +3,8 @@
#define IEEE802_11_DATA_LEN 2304 #define IEEE802_11_DATA_LEN 2304
/* Actually, the standard seems to be inconsistent about what the /* Actually, the standard seems to be inconsistent about what the
maximum frame size really is. S6.2.1.1.2 says 2304 octets, but the maximum frame size really is. Section 6.2.1.1.2 says 2304 octets,
figure in section 7.1.2 says 2312 octects. */ but the figure in Section 7.1.2 says 2312 octects. */
#define IEEE802_11_HLEN 30 #define IEEE802_11_HLEN 30
#define IEEE802_11_FRAME_LEN (IEEE802_11_DATA_LEN + IEEE802_11_HLEN) #define IEEE802_11_FRAME_LEN (IEEE802_11_DATA_LEN + IEEE802_11_HLEN)
......
This diff is collapsed.
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
#ifndef _ORINOCO_H #ifndef _ORINOCO_H
#define _ORINOCO_H #define _ORINOCO_H
#include "hermes.h"
/* To enable debug messages */ /* To enable debug messages */
//#define ORINOCO_DEBUG 3 //#define ORINOCO_DEBUG 3
...@@ -18,24 +20,26 @@ ...@@ -18,24 +20,26 @@
#define ORINOCO_MAX_KEY_SIZE 14 #define ORINOCO_MAX_KEY_SIZE 14
#define ORINOCO_MAX_KEYS 4 #define ORINOCO_MAX_KEYS 4
typedef struct orinoco_key { struct orinoco_key {
u16 len; /* always store little-endian */ u16 len; /* always stored as little-endian */
char data[ORINOCO_MAX_KEY_SIZE]; char data[ORINOCO_MAX_KEY_SIZE];
} __attribute__ ((packed)) orinoco_key_t; } __attribute__ ((packed));
typedef orinoco_key_t orinoco_keys_t[ORINOCO_MAX_KEYS]; #define ORINOCO_INTEN ( HERMES_EV_RX | HERMES_EV_ALLOC | HERMES_EV_TX | \
HERMES_EV_TXEXC | HERMES_EV_WTERR | HERMES_EV_INFO | \
HERMES_EV_INFDROP )
/*====================================================================*/
struct orinoco_private { struct orinoco_private {
void *card; /* Pointer to card dependant structure */ void *card; /* Pointer to card dependant structure */
/* card dependant extra reset code (i.e. bus/interface specific */
int (*hard_reset)(struct orinoco_private *); int (*hard_reset)(struct orinoco_private *);
/* Synchronisation stuff */
spinlock_t lock; spinlock_t lock;
long state; int hw_unavailable;
#define ORINOCO_STATE_INIRQ 0 struct tq_struct timeout_task;
#define ORINOCO_STATE_DOIRQ 1
int open;
/* Net device stuff */ /* Net device stuff */
struct net_device *ndev; struct net_device *ndev;
...@@ -58,14 +62,13 @@ struct orinoco_private { ...@@ -58,14 +62,13 @@ struct orinoco_private {
int has_preamble; int has_preamble;
int has_sensitivity; int has_sensitivity;
int nicbuf_size; int nicbuf_size;
int broken_cor_reset;
u16 channel_mask; u16 channel_mask;
/* Configuration paramaters */ /* Configuration paramaters */
u32 iw_mode; u32 iw_mode;
int prefer_port3; int prefer_port3;
u16 wep_on, wep_restrict, tx_key; u16 wep_on, wep_restrict, tx_key;
orinoco_keys_t keys; struct orinoco_key keys[ORINOCO_MAX_KEYS];
int bitratemode; int bitratemode;
char nick[IW_ESSID_MAX_SIZE+1]; char nick[IW_ESSID_MAX_SIZE+1];
char desired_essid[IW_ESSID_MAX_SIZE+1]; char desired_essid[IW_ESSID_MAX_SIZE+1];
...@@ -81,38 +84,58 @@ struct orinoco_private { ...@@ -81,38 +84,58 @@ struct orinoco_private {
#endif #endif
/* Configuration dependent variables */ /* Configuration dependent variables */
int port_type, allow_ibss; int port_type, createibss;
int promiscuous, mc_count; int promiscuous, mc_count;
/* /proc based debugging stuff */ /* /proc based debugging stuff */
struct proc_dir_entry *dir_dev; struct proc_dir_entry *dir_dev;
}; };
/*====================================================================*/
extern struct list_head orinoco_instances;
#ifdef ORINOCO_DEBUG #ifdef ORINOCO_DEBUG
extern int orinoco_debug; extern int orinoco_debug;
#define DEBUG(n, args...) do { if (orinoco_debug>(n)) printk(KERN_DEBUG args); } while(0) #define DEBUG(n, args...) do { if (orinoco_debug>(n)) printk(KERN_DEBUG args); } while(0)
#define DEBUGMORE(n, args...) do { if (orinoco_debug>(n)) printk(args); } while (0)
#else #else
#define DEBUG(n, args...) do { } while (0) #define DEBUG(n, args...) do { } while (0)
#define DEBUGMORE(n, args...) do { } while (0)
#endif /* ORINOCO_DEBUG */ #endif /* ORINOCO_DEBUG */
#define TRACE_ENTER(devname) DEBUG(2, "%s: -> " __FUNCTION__ "()\n", devname); #define TRACE_ENTER(devname) DEBUG(2, "%s: -> " __FUNCTION__ "()\n", devname);
#define TRACE_EXIT(devname) DEBUG(2, "%s: <- " __FUNCTION__ "()\n", devname); #define TRACE_EXIT(devname) DEBUG(2, "%s: <- " __FUNCTION__ "()\n", devname);
#define RUP_EVEN(a) ( (a) % 2 ? (a) + 1 : (a) ) extern struct net_device *alloc_orinocodev(int sizeof_card,
int (*hard_reset)(struct orinoco_private *));
extern int __orinoco_up(struct net_device *dev);
extern int __orinoco_down(struct net_device *dev);
int orinoco_reinit_firmware(struct net_device *dev);
/* utility routines */ extern int orinoco_proc_dev_init(struct net_device *dev);
struct net_device *alloc_orinocodev(int sizeof_card); extern void orinoco_proc_dev_cleanup(struct net_device *dev);
extern void orinoco_shutdown(struct orinoco_private *dev);
extern int orinoco_reset(struct orinoco_private *dev);
extern int orinoco_proc_dev_init(struct orinoco_private *dev);
extern void orinoco_proc_dev_cleanup(struct orinoco_private *priv);
extern void orinoco_interrupt(int irq, void * dev_id, struct pt_regs *regs); extern void orinoco_interrupt(int irq, void * dev_id, struct pt_regs *regs);
/********************************************************************/
/* Locking and synchronization functions */
/********************************************************************/
/* These functions *must* be inline or they will break horribly on
* SPARC, due to its weird semantics for save/restore flags. extern
* inline should prevent the kernel from linking or module from
* loading if they are not inlined. */
extern inline int orinoco_lock(struct orinoco_private *priv,
unsigned long *flags)
{
spin_lock_irqsave(&priv->lock, *flags);
if (priv->hw_unavailable) {
printk(KERN_DEBUG "orinoco_lock() called with hw_unavailable (dev=%p)\n",
priv->ndev);
spin_unlock_irqrestore(&priv->lock, *flags);
return -EBUSY;
}
return 0;
}
extern inline void orinoco_unlock(struct orinoco_private *priv,
unsigned long *flags)
{
spin_unlock_irqrestore(&priv->lock, *flags);
}
#endif /* _ORINOCO_H */ #endif /* _ORINOCO_H */
This diff is collapsed.
/* orinoco_plx.c 0.11b /* orinoco_plx.c 0.13
* *
* Driver for Prism II devices which would usually be driven by orinoco_cs, * Driver for Prism II devices which would usually be driven by orinoco_cs,
* but are connected to the PCI bus by a PLX9052. * but are connected to the PCI bus by a PLX9052.
...@@ -134,13 +134,6 @@ not have time for a while.. ...@@ -134,13 +134,6 @@ not have time for a while..
#include "hermes.h" #include "hermes.h"
#include "orinoco.h" #include "orinoco.h"
static char version[] __initdata = "orinoco_plx.c 0.11b (Daniel Barlow <dan@telent.net>)";
MODULE_AUTHOR("Daniel Barlow <dan@telent.net>");
MODULE_DESCRIPTION("Driver for wireless LAN cards using the PLX9052 PCI bridge");
#ifdef MODULE_LICENSE
MODULE_LICENSE("Dual MPL/GPL");
#endif
static char dev_info[] = "orinoco_plx"; static char dev_info[] = "orinoco_plx";
#define COR_OFFSET (0x3e0 / 2) /* COR attribute offset of Prism2 PC card */ #define COR_OFFSET (0x3e0 / 2) /* COR attribute offset of Prism2 PC card */
...@@ -149,37 +142,6 @@ static char dev_info[] = "orinoco_plx"; ...@@ -149,37 +142,6 @@ static char dev_info[] = "orinoco_plx";
#define PLX_INTCSR 0x4c /* Interrupt Control and Status Register */ #define PLX_INTCSR 0x4c /* Interrupt Control and Status Register */
#define PLX_INTCSR_INTEN (1<<6) /* Interrupt Enable bit */ #define PLX_INTCSR_INTEN (1<<6) /* Interrupt Enable bit */
static int orinoco_plx_open(struct net_device *dev)
{
struct orinoco_private *priv = (struct orinoco_private *) dev->priv;
int err;
netif_device_attach(dev);
err = orinoco_reset(priv);
if (err)
printk(KERN_ERR "%s: orinoco_reset failed in orinoco_plx_open()",
dev->name);
else
netif_start_queue(dev);
return err;
}
static int orinoco_plx_stop(struct net_device *dev)
{
struct orinoco_private *priv = (struct orinoco_private *) dev->priv;
netif_stop_queue(dev);
orinoco_shutdown(priv);
return 0;
}
static void
orinoco_plx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
orinoco_interrupt(irq, (struct orinoco_private *)dev_id, regs);
}
static const u16 cis_magic[] = { static const u16 cis_magic[] = {
0x0001, 0x0003, 0x0000, 0x0000, 0x00ff, 0x0017, 0x0004, 0x0067 0x0001, 0x0003, 0x0000, 0x0000, 0x00ff, 0x0017, 0x0004, 0x0067
}; };
...@@ -197,8 +159,6 @@ static int orinoco_plx_init_one(struct pci_dev *pdev, ...@@ -197,8 +159,6 @@ static int orinoco_plx_init_one(struct pci_dev *pdev,
int netdev_registered = 0; int netdev_registered = 0;
int i; int i;
TRACE_ENTER("orinoco_plx");
err = pci_enable_device(pdev); err = pci_enable_device(pdev);
if (err) if (err)
return -EIO; return -EIO;
...@@ -266,7 +226,7 @@ static int orinoco_plx_init_one(struct pci_dev *pdev, ...@@ -266,7 +226,7 @@ static int orinoco_plx_init_one(struct pci_dev *pdev,
goto fail; goto fail;
} }
dev = alloc_orinocodev(0); dev = alloc_orinocodev(0, NULL);
if (! dev) { if (! dev) {
err = -ENOMEM; err = -ENOMEM;
goto fail; goto fail;
...@@ -274,8 +234,6 @@ static int orinoco_plx_init_one(struct pci_dev *pdev, ...@@ -274,8 +234,6 @@ static int orinoco_plx_init_one(struct pci_dev *pdev,
priv = dev->priv; priv = dev->priv;
dev->base_addr = pccard_ioaddr; dev->base_addr = pccard_ioaddr;
dev->open = orinoco_plx_open;
dev->stop = orinoco_plx_stop;
SET_MODULE_OWNER(dev); SET_MODULE_OWNER(dev);
printk(KERN_DEBUG printk(KERN_DEBUG
...@@ -286,7 +244,7 @@ static int orinoco_plx_init_one(struct pci_dev *pdev, ...@@ -286,7 +244,7 @@ static int orinoco_plx_init_one(struct pci_dev *pdev,
HERMES_IO, HERMES_16BIT_REGSPACING); HERMES_IO, HERMES_16BIT_REGSPACING);
pci_set_drvdata(pdev, dev); pci_set_drvdata(pdev, dev);
err = request_irq(pdev->irq, orinoco_plx_interrupt, SA_SHIRQ, dev->name, priv); err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ, dev->name, priv);
if (err) { if (err) {
printk(KERN_ERR "orinoco_plx: Error allocating IRQ %d.\n", pdev->irq); printk(KERN_ERR "orinoco_plx: Error allocating IRQ %d.\n", pdev->irq);
err = -EBUSY; err = -EBUSY;
...@@ -299,19 +257,17 @@ static int orinoco_plx_init_one(struct pci_dev *pdev, ...@@ -299,19 +257,17 @@ static int orinoco_plx_init_one(struct pci_dev *pdev,
goto fail; goto fail;
netdev_registered = 1; netdev_registered = 1;
err = orinoco_proc_dev_init(priv); err = orinoco_proc_dev_init(dev);
if (err) if (err)
goto fail; goto fail;
TRACE_EXIT("orinoco_plx");
return 0; /* succeeded */ return 0; /* succeeded */
fail: fail:
printk(KERN_DEBUG "orinoco_plx: init_one(), FAIL!\n"); printk(KERN_DEBUG "orinoco_plx: init_one(), FAIL!\n");
if (priv) { if (priv) {
orinoco_proc_dev_cleanup(priv); orinoco_proc_dev_cleanup(dev);
if (netdev_registered) if (netdev_registered)
unregister_netdev(dev); unregister_netdev(dev);
...@@ -330,8 +286,6 @@ static int orinoco_plx_init_one(struct pci_dev *pdev, ...@@ -330,8 +286,6 @@ static int orinoco_plx_init_one(struct pci_dev *pdev,
pci_disable_device(pdev); pci_disable_device(pdev);
TRACE_EXIT("orinoco_plx");
return err; return err;
} }
...@@ -340,12 +294,10 @@ static void __devexit orinoco_plx_remove_one(struct pci_dev *pdev) ...@@ -340,12 +294,10 @@ static void __devexit orinoco_plx_remove_one(struct pci_dev *pdev)
struct net_device *dev = pci_get_drvdata(pdev); struct net_device *dev = pci_get_drvdata(pdev);
struct orinoco_private *priv = dev->priv; struct orinoco_private *priv = dev->priv;
TRACE_ENTER("orinoco_plx");
if (! dev) if (! dev)
BUG(); BUG();
orinoco_proc_dev_cleanup(priv); orinoco_proc_dev_cleanup(dev);
unregister_netdev(dev); unregister_netdev(dev);
...@@ -357,13 +309,10 @@ static void __devexit orinoco_plx_remove_one(struct pci_dev *pdev) ...@@ -357,13 +309,10 @@ static void __devexit orinoco_plx_remove_one(struct pci_dev *pdev)
release_region(pci_resource_start(pdev, 3), pci_resource_len(pdev, 3)); release_region(pci_resource_start(pdev, 3), pci_resource_len(pdev, 3));
pci_disable_device(pdev); pci_disable_device(pdev);
TRACE_EXIT("orinoco_plx");
} }
static struct pci_device_id orinoco_plx_pci_id_table[] __devinitdata = { static struct pci_device_id orinoco_plx_pci_id_table[] __devinitdata = {
{0x10b7, 0x7770, PCI_ANY_ID, PCI_ANY_ID,}, /* 3ComAirConnect */
{0x111a, 0x1023, PCI_ANY_ID, PCI_ANY_ID,}, /* Siemens SpeedStream SS1023 */ {0x111a, 0x1023, PCI_ANY_ID, PCI_ANY_ID,}, /* Siemens SpeedStream SS1023 */
{0x1385, 0x4100, PCI_ANY_ID, PCI_ANY_ID,}, /* Netgear MA301 */ {0x1385, 0x4100, PCI_ANY_ID, PCI_ANY_ID,}, /* Netgear MA301 */
{0x15e8, 0x0130, PCI_ANY_ID, PCI_ANY_ID,}, /* Correga - does this work? */ {0x15e8, 0x0130, PCI_ANY_ID, PCI_ANY_ID,}, /* Correga - does this work? */
...@@ -376,7 +325,8 @@ static struct pci_device_id orinoco_plx_pci_id_table[] __devinitdata = { ...@@ -376,7 +325,8 @@ static struct pci_device_id orinoco_plx_pci_id_table[] __devinitdata = {
{0x16ec, 0x3685, PCI_ANY_ID, PCI_ANY_ID,}, /* USR 2415 */ {0x16ec, 0x3685, PCI_ANY_ID, PCI_ANY_ID,}, /* USR 2415 */
{0xec80, 0xec00, PCI_ANY_ID, PCI_ANY_ID,}, /* Belkin F5D6000 tested by {0xec80, 0xec00, PCI_ANY_ID, PCI_ANY_ID,}, /* Belkin F5D6000 tested by
Brendan W. McAdams <rit@jacked-in.org> */ Brendan W. McAdams <rit@jacked-in.org> */
{0x126c, 0x8030, PCI_ANY_ID, PCI_ANY_ID,}, /* Nortel emobility */ {0x10b7, 0x7770, PCI_ANY_ID, PCI_ANY_ID,}, /* 3Com AirConnect PCI tested by
Damien Persohn <damien@persohn.net> */
{0,}, {0,},
}; };
...@@ -387,8 +337,17 @@ static struct pci_driver orinoco_plx_driver = { ...@@ -387,8 +337,17 @@ static struct pci_driver orinoco_plx_driver = {
.id_table = orinoco_plx_pci_id_table, .id_table = orinoco_plx_pci_id_table,
.probe = orinoco_plx_init_one, .probe = orinoco_plx_init_one,
.remove = __devexit_p(orinoco_plx_remove_one), .remove = __devexit_p(orinoco_plx_remove_one),
.suspend = 0,
.resume = 0,
}; };
static char version[] __initdata = "orinoco_plx.c 0.13 (Daniel Barlow <dan@telent.net>, David Gibson <hermes@gibson.dropbear.id.au>)";
MODULE_AUTHOR("Daniel Barlow <dan@telent.net>");
MODULE_DESCRIPTION("Driver for wireless LAN cards using the PLX9052 PCI bridge");
#ifdef MODULE_LICENSE
MODULE_LICENSE("Dual MPL/GPL");
#endif
static int __init orinoco_plx_init(void) static int __init orinoco_plx_init(void)
{ {
printk(KERN_DEBUG "%s\n", version); printk(KERN_DEBUG "%s\n", version);
......
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