summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRalf Bächle <ralf@linux-mips.org>2003-06-25 09:00:35 -0400
committerRalf Bächle <ralf@linux-mips.org>2003-06-25 09:00:35 -0400
commitf0e373dc194bba55389b428b6a778304ea050cac (patch)
tree8dc52e7afa245e1d70a294771bebfca61df4a21d
parente3e33952885ee80865b86f1f63d43713b5bfb5ba (diff)
[netdrvr] sgiseeq update
-rw-r--r--drivers/net/Kconfig2
-rw-r--r--drivers/net/Space.c11
-rw-r--r--drivers/net/sgiseeq.c209
-rw-r--r--drivers/net/sgiseeq.h2
4 files changed, 102 insertions, 122 deletions
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 6e9ed10ae2da..7101ffda6ad8 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -1843,7 +1843,7 @@ config DE620
The module will be called de620.
config SGISEEQ
- bool "SGI Seeq ethernet controller support"
+ tristate "SGI Seeq ethernet controller support"
depends on NET_ETHERNET && SGI_IP22
help
Say Y here if you have an Seeq based Ethernet network card. This is
diff --git a/drivers/net/Space.c b/drivers/net/Space.c
index f745ac102265..838c59729c71 100644
--- a/drivers/net/Space.c
+++ b/drivers/net/Space.c
@@ -82,7 +82,6 @@ extern int sonic_probe(struct net_device *);
extern int SK_init(struct net_device *);
extern int seeq8005_probe(struct net_device *);
extern int smc_init( struct net_device * );
-extern int sgiseeq_probe(struct net_device *);
extern int atarilance_probe(struct net_device *);
extern int sun3lance_probe(struct net_device *);
extern int sun3_82586_probe(struct net_device *);
@@ -343,14 +342,6 @@ static struct devprobe m68k_probes[] __initdata = {
{NULL, 0},
};
-
-static struct devprobe sgi_probes[] __initdata = {
-#ifdef CONFIG_SGISEEQ
- {sgiseeq_probe, 0},
-#endif
- {NULL, 0},
-};
-
static struct devprobe mips_probes[] __initdata = {
#ifdef CONFIG_MIPS_JAZZ_SONIC
{sonic_probe, 0},
@@ -385,8 +376,6 @@ static int __init ethif_probe(struct net_device *dev)
return 0;
if (probe_list(dev, mips_probes) == 0)
return 0;
- if (probe_list(dev, sgi_probes) == 0)
- return 0;
if (probe_list(dev, eisa_probes) == 0)
return 0;
if (probe_list(dev, mca_probes) == 0)
diff --git a/drivers/net/sgiseeq.c b/drivers/net/sgiseeq.c
index b3a9cab9845c..c0b240416526 100644
--- a/drivers/net/sgiseeq.c
+++ b/drivers/net/sgiseeq.c
@@ -5,6 +5,7 @@
*/
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/init.h>
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
@@ -25,8 +26,8 @@
#include <asm/bitops.h>
#include <asm/page.h>
#include <asm/pgtable.h>
-#include <asm/sgi/sgihpc.h>
-#include <asm/sgi/sgint23.h>
+#include <asm/sgi/hpc3.h>
+#include <asm/sgi/ip22.h>
#include <asm/sgialib.h>
#include "sgiseeq.h"
@@ -90,8 +91,8 @@ struct sgiseeq_init_block { /* Note the name ;-) */
struct sgiseeq_private {
volatile struct sgiseeq_init_block srings;
char *name;
- volatile struct hpc3_ethregs *hregs;
- volatile struct sgiseeq_regs *sregs;
+ struct hpc3_ethregs *hregs;
+ struct sgiseeq_regs *sregs;
/* Ring entry counters. */
unsigned int rx_new, tx_new;
@@ -102,17 +103,22 @@ struct sgiseeq_private {
unsigned char mode;
struct net_device_stats stats;
+
+ struct net_device *next_module;
};
-static inline void hpc3_eth_reset(volatile struct hpc3_ethregs *hregs)
+/* A list of all installed seeq devices, for removing the driver module. */
+static struct net_device *root_sgiseeq_dev;
+
+static inline void hpc3_eth_reset(struct hpc3_ethregs *hregs)
{
hregs->rx_reset = (HPC3_ERXRST_CRESET | HPC3_ERXRST_CLRIRQ);
udelay(20);
hregs->rx_reset = 0;
}
-static inline void reset_hpc3_and_seeq(volatile struct hpc3_ethregs *hregs,
- volatile struct sgiseeq_regs *sregs)
+static inline void reset_hpc3_and_seeq(struct hpc3_ethregs *hregs,
+ struct sgiseeq_regs *sregs)
{
hregs->rx_ctrl = hregs->tx_ctrl = 0;
hpc3_eth_reset(hregs);
@@ -122,15 +128,15 @@ static inline void reset_hpc3_and_seeq(volatile struct hpc3_ethregs *hregs,
SEEQ_RCMD_IDRIB | SEEQ_RCMD_ICRC)
static inline void seeq_go(struct sgiseeq_private *sp,
- volatile struct hpc3_ethregs *hregs,
- volatile struct sgiseeq_regs *sregs)
+ struct hpc3_ethregs *hregs,
+ struct sgiseeq_regs *sregs)
{
sregs->rstat = sp->mode | RSTAT_GO_BITS;
hregs->rx_ctrl = HPC3_ERXCTRL_ACTIVE;
}
static inline void seeq_load_eaddr(struct net_device *dev,
- volatile struct sgiseeq_regs *sregs)
+ struct sgiseeq_regs *sregs)
{
int i;
@@ -171,7 +177,6 @@ static int seeq_init_ring(struct net_device *dev)
return -ENOMEM;
ib->tx_desc[i].buf_vaddr = KSEG1ADDR(buffer);
ib->tx_desc[i].tdma.pbuf = PHYSADDR(buffer);
-// flush_cache_all();
}
ib->tx_desc[i].tdma.cntinfo = (TCNTINFO_INIT);
}
@@ -186,7 +191,6 @@ static int seeq_init_ring(struct net_device *dev)
return -ENOMEM;
ib->rx_desc[i].buf_vaddr = KSEG1ADDR(buffer);
ib->rx_desc[i].rdma.pbuf = PHYSADDR(buffer);
-// flush_cache_all();
}
ib->rx_desc[i].rdma.cntinfo = (RCNTINFO_INIT);
}
@@ -203,7 +207,7 @@ void sgiseeq_dump_rings(void)
static int once;
struct sgiseeq_rx_desc *r = gpriv->srings.rx_desc;
struct sgiseeq_tx_desc *t = gpriv->srings.tx_desc;
- volatile struct hpc3_ethregs *hregs = gpriv->hregs;
+ struct hpc3_ethregs *hregs = gpriv->hregs;
int i;
if(once)
@@ -242,9 +246,9 @@ void sgiseeq_dump_rings(void)
#define RDMACFG_INIT (HPC3_ERXDCFG_FRXDC | HPC3_ERXDCFG_FEOP | HPC3_ERXDCFG_FIRQ)
static int init_seeq(struct net_device *dev, struct sgiseeq_private *sp,
- volatile struct sgiseeq_regs *sregs)
+ struct sgiseeq_regs *sregs)
{
- volatile struct hpc3_ethregs *hregs = sp->hregs;
+ struct hpc3_ethregs *hregs = sp->hregs;
int err;
reset_hpc3_and_seeq(hregs, sregs);
@@ -285,8 +289,8 @@ static inline void record_rx_errors(struct sgiseeq_private *sp,
}
static inline void rx_maybe_restart(struct sgiseeq_private *sp,
- volatile struct hpc3_ethregs *hregs,
- volatile struct sgiseeq_regs *sregs)
+ struct hpc3_ethregs *hregs,
+ struct sgiseeq_regs *sregs)
{
if (!(hregs->rx_ctrl & HPC3_ERXCTRL_ACTIVE)) {
hregs->rx_ndptr = PHYSADDR(&sp->srings.rx_desc[sp->rx_new]);
@@ -299,8 +303,8 @@ static inline void rx_maybe_restart(struct sgiseeq_private *sp,
(rd) = &(sp)->srings.rx_desc[(sp)->rx_new])
static inline void sgiseeq_rx(struct net_device *dev, struct sgiseeq_private *sp,
- volatile struct hpc3_ethregs *hregs,
- volatile struct sgiseeq_regs *sregs)
+ struct hpc3_ethregs *hregs,
+ struct sgiseeq_regs *sregs)
{
struct sgiseeq_rx_desc *rd;
struct sk_buff *skb = 0;
@@ -332,7 +336,7 @@ static inline void sgiseeq_rx(struct net_device *dev, struct sgiseeq_private *sp
sp->stats.rx_packets++;
sp->stats.rx_bytes += len;
} else {
- printk ("%s: Memory squeeze, deferring packet.\n",
+ printk (KERN_NOTICE "%s: Memory squeeze, deferring packet.\n",
dev->name);
sp->stats.rx_dropped++;
}
@@ -350,7 +354,7 @@ static inline void sgiseeq_rx(struct net_device *dev, struct sgiseeq_private *sp
}
static inline void tx_maybe_reset_collisions(struct sgiseeq_private *sp,
- volatile struct sgiseeq_regs *sregs)
+ struct sgiseeq_regs *sregs)
{
if (sp->is_edlc) {
sregs->rw.wregs.control = sp->control & ~(SEEQ_CTRL_XCNT);
@@ -359,7 +363,7 @@ static inline void tx_maybe_reset_collisions(struct sgiseeq_private *sp,
}
static inline void kick_tx(struct sgiseeq_tx_desc *td,
- volatile struct hpc3_ethregs *hregs)
+ struct hpc3_ethregs *hregs)
{
/* If the HPC aint doin nothin, and there are more packets
* with ETXD cleared and XIU set we must make very certain
@@ -377,8 +381,8 @@ static inline void kick_tx(struct sgiseeq_tx_desc *td,
}
static inline void sgiseeq_tx(struct net_device *dev, struct sgiseeq_private *sp,
- volatile struct hpc3_ethregs *hregs,
- volatile struct sgiseeq_regs *sregs)
+ struct hpc3_ethregs *hregs,
+ struct sgiseeq_regs *sregs)
{
struct sgiseeq_tx_desc *td;
unsigned long status = hregs->tx_ctrl;
@@ -420,8 +424,8 @@ static irqreturn_t sgiseeq_interrupt(int irq, void *dev_id, struct pt_regs *regs
{
struct net_device *dev = (struct net_device *) dev_id;
struct sgiseeq_private *sp = (struct sgiseeq_private *) dev->priv;
- volatile struct hpc3_ethregs *hregs = sp->hregs;
- volatile struct sgiseeq_regs *sregs = sp->sregs;
+ struct hpc3_ethregs *hregs = sp->hregs;
+ struct sgiseeq_regs *sregs = sp->sregs;
/* Ack the IRQ and set software state. */
hregs->rx_reset = HPC3_ERXRST_CLRIRQ;
@@ -429,7 +433,7 @@ static irqreturn_t sgiseeq_interrupt(int irq, void *dev_id, struct pt_regs *regs
/* Always check for received packets. */
sgiseeq_rx(dev, sp, hregs, sregs);
- /* Only check for tx acks iff we have something queued. */
+ /* Only check for tx acks if we have something queued. */
if (sp->tx_old != sp->tx_new)
sgiseeq_tx(dev, sp, hregs, sregs);
@@ -442,47 +446,34 @@ static irqreturn_t sgiseeq_interrupt(int irq, void *dev_id, struct pt_regs *regs
static int sgiseeq_open(struct net_device *dev)
{
struct sgiseeq_private *sp = (struct sgiseeq_private *)dev->priv;
- volatile struct sgiseeq_regs *sregs = sp->sregs;
- unsigned long flags;
- int err;
+ struct sgiseeq_regs *sregs = sp->sregs;
- local_irq_save(flags);
-
- err = -EAGAIN;
- if (request_irq(dev->irq, sgiseeq_interrupt, 0, sgiseeqstr, dev)) {
- printk("Seeq8003: Can't get irq %d\n", dev->irq);
- goto out;
- }
- err = init_seeq(dev, sp, sregs);
+ int err = init_seeq(dev, sp, sregs);
if (err)
- goto out;
+ return err;
netif_start_queue(dev);
-out:
- local_irq_restore(flags);
- return err;
+ return 0;
}
static int sgiseeq_close(struct net_device *dev)
{
struct sgiseeq_private *sp = (struct sgiseeq_private *) dev->priv;
- volatile struct sgiseeq_regs *sregs = sp->sregs;
+ struct sgiseeq_regs *sregs = sp->sregs;
netif_stop_queue(dev);
/* Shutdown the Seeq. */
reset_hpc3_and_seeq(sp->hregs, sregs);
- free_irq(dev->irq, dev);
-
return 0;
}
static inline int sgiseeq_reset(struct net_device *dev)
{
struct sgiseeq_private *sp = (struct sgiseeq_private *) dev->priv;
- volatile struct sgiseeq_regs *sregs = sp->sregs;
+ struct sgiseeq_regs *sregs = sp->sregs;
int err;
err = init_seeq(dev, sp, sregs);
@@ -504,12 +495,12 @@ void sgiseeq_my_reset(void)
static int sgiseeq_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct sgiseeq_private *sp = (struct sgiseeq_private *) dev->priv;
- volatile struct hpc3_ethregs *hregs = sp->hregs;
+ struct hpc3_ethregs *hregs = sp->hregs;
unsigned long flags;
struct sgiseeq_tx_desc *td;
int skblen, len, entry;
- save_and_cli(flags);
+ local_irq_save(flags);
/* Setup... */
skblen = skb->len;
@@ -553,14 +544,14 @@ static int sgiseeq_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (!TX_BUFFS_AVAIL(sp))
netif_stop_queue(dev);
- restore_flags(flags);
+ local_irq_restore(flags);
return 0;
}
static void timeout(struct net_device *dev)
{
- printk("%s: transmit timed out, resetting\n", dev->name);
+ printk(KERN_NOTICE "%s: transmit timed out, resetting\n", dev->name);
sgiseeq_reset(dev);
dev->trans_start = jiffies;
@@ -603,41 +594,56 @@ static inline void setup_rx_ring(struct sgiseeq_rx_desc *buf, int nbufs)
buf[i].rdma.pnext = PHYSADDR(&buf[0]);
}
-static char onboard_eth_addr[6];
-
#define ALIGNED(x) ((((unsigned long)(x)) + 0xf) & ~(0xf))
-int sgiseeq_init(struct net_device *dev, struct sgiseeq_regs *sregs,
- struct hpc3_ethregs *hregs, int irq)
+int sgiseeq_init(struct hpc3_regs* regs, int irq)
{
- static unsigned version_printed;
- int i;
+ struct net_device *dev;
struct sgiseeq_private *sp;
+ int i;
+
+ sp = (struct sgiseeq_private *) get_zeroed_page(GFP_KERNEL);
+ if (!sp) {
+ printk (KERN_ERR
+ "Seeq8003: Could not allocate private data.\n");
+ return -ENOMEM;
+ }
- dev->priv = (struct sgiseeq_private *) get_zeroed_page(GFP_KERNEL);
- if (dev->priv == NULL)
+ dev = init_etherdev(NULL, 0);
+ if (!dev) {
+ printk (KERN_ERR
+ "Seeq8003: Could not allocate memory for device.\n");
+ free_page((unsigned long) sp);
return -ENOMEM;
+ }
- if (!version_printed++)
- printk(version);
+ if (request_irq(irq, sgiseeq_interrupt, 0, sgiseeqstr, dev)) {
+ printk(KERN_ERR "Seeq8003: Can't get irq %d\n", dev->irq);
+ free_page((unsigned long) sp);
+ unregister_netdev(dev);
+ return -EAGAIN;
+ }
- printk("%s: SGI Seeq8003 ", dev->name);
+ printk(KERN_INFO "%s: SGI Seeq8003 ", dev->name);
- for (i = 0; i < 6; i++)
- printk("%2.2x%c",
- dev->dev_addr[i] = onboard_eth_addr[i],
- i == 5 ? ' ': ':');
+#define EADDR_NVOFS 250
+ for (i = 0; i < 3; i++) {
+ unsigned short tmp = ip22_nvram_read(EADDR_NVOFS / 2 + i);
+ printk("%2.2x:%2.2x%c",
+ dev->dev_addr[2 * i] = tmp >> 8,
+ dev->dev_addr[2 * i + 1] = tmp & 0xff,
+ i == 2 ? ' ' : ':');
+ }
printk("\n");
- sp = (struct sgiseeq_private *) dev->priv;
+ dev->priv = sp;
#ifdef DEBUG
gpriv = sp;
gdev = dev;
#endif
- memset((char *)dev->priv, 0, sizeof(struct sgiseeq_private));
- sp->sregs = sregs;
- sp->hregs = hregs;
+ sp->sregs = (struct sgiseeq_regs *) &hpc3c0->eth_ext[0];
+ sp->hregs = &hpc3c0->ethregs;
sp->name = sgiseeqstr;
sp->srings.rx_desc = (struct sgiseeq_rx_desc *)
@@ -654,14 +660,13 @@ int sgiseeq_init(struct net_device *dev, struct sgiseeq_regs *sregs,
setup_tx_ring(sp->srings.tx_desc, SEEQ_TX_BUFFERS);
/* Reset the chip. */
- hpc3_eth_reset((volatile struct hpc3_ethregs *) hregs);
+ hpc3_eth_reset(sp->hregs);
- sp->is_edlc = !(sregs->rw.rregs.collision_tx[0] & 0xff);
- if (sp->is_edlc) {
+ sp->is_edlc = !(sp->sregs->rw.rregs.collision_tx[0] & 0xff);
+ if (sp->is_edlc)
sp->control = (SEEQ_CTRL_XCNT | SEEQ_CTRL_ACCNT |
SEEQ_CTRL_SFLAG | SEEQ_CTRL_ESHORT |
SEEQ_CTRL_ENCARR);
- }
dev->open = sgiseeq_open;
dev->stop = sgiseeq_close;
@@ -674,51 +679,37 @@ int sgiseeq_init(struct net_device *dev, struct sgiseeq_regs *sregs,
dev->dma = 0;
ether_setup(dev);
+ sp->next_module = root_sgiseeq_dev;
+ root_sgiseeq_dev = dev;
+
return 0;
}
-static inline unsigned char str2hexnum(unsigned char c)
+static int __init sgiseeq_probe(void)
{
- if (c >= '0' && c <= '9')
- return c - '0';
- if (c >= 'a' && c <= 'f')
- return c - 'a' + 10;
- return 0; /* foo */
+ printk(version);
+
+ /* On board adapter on 1st HPC is always present */
+ return sgiseeq_init(hpc3c0, SGI_ENET_IRQ);
}
-static inline void str2eaddr(unsigned char *ea, unsigned char *str)
+static void __exit sgiseeq_exit(void)
{
- int i;
-
- for (i = 0; i < 6; i++) {
- unsigned char num;
-
- if(*str == ':')
- str++;
- num = str2hexnum(*str++) << 4;
- num |= (str2hexnum(*str++));
- ea[i] = num;
+ struct sgiseeq_private *sp;
+ struct net_device *next, *dev = root_sgiseeq_dev;
+
+ while (dev) {
+ sp = (struct sgiseeq_private *) dev->priv;
+ next = sp->next_module;
+ free_irq(dev->irq, dev);
+ free_page((unsigned long) sp);
+ unregister_netdev(dev);
+ kfree(dev);
+ dev = next;
}
}
-int sgiseeq_probe(struct net_device *dev)
-{
- static int initialized;
- char *ep;
-
- if (initialized) /* Already initialized? */
- return 1;
- initialized++;
-
- /* First get the ethernet address of the onboard interface from ARCS.
- * This is fragile; PROM doesn't like running from cache.
- * On MIPS64 it crashes for some other, yet unknown reason ...
- */
- ep = ArcGetEnvironmentVariable("eaddr");
- str2eaddr(onboard_eth_addr, ep);
- return sgiseeq_init(dev,
- (struct sgiseeq_regs *) (KSEG1ADDR(0x1fbd4000)),
- &hpc3c0->ethregs, SGI_ENET_IRQ);
-}
+module_init(sgiseeq_probe);
+module_exit(sgiseeq_exit);
MODULE_LICENSE("GPL");
diff --git a/drivers/net/sgiseeq.h b/drivers/net/sgiseeq.h
index 0b5d39c688a7..ebcca688dac4 100644
--- a/drivers/net/sgiseeq.h
+++ b/drivers/net/sgiseeq.h
@@ -1,4 +1,4 @@
-/* $Id: sgiseeq.h,v 1.4 1999/10/09 00:01:24 ralf Exp $
+/*
* sgiseeq.h: Defines for the Seeq8003 ethernet controller.
*
* Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)