Commit f0e373dc authored by Ralf Bächle's avatar Ralf Bächle

[netdrvr] sgiseeq update

parent e3e33952
......@@ -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
......
......@@ -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)
......
......@@ -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;
local_irq_save(flags);
struct sgiseeq_regs *sregs = sp->sregs;
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;
dev->priv = (struct sgiseeq_private *) get_zeroed_page(GFP_KERNEL);
if (dev->priv == NULL)
sp = (struct sgiseeq_private *) get_zeroed_page(GFP_KERNEL);
if (!sp) {
printk (KERN_ERR
"Seeq8003: Could not allocate private data.\n");
return -ENOMEM;
}
if (!version_printed++)
printk(version);
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;
}
printk("%s: SGI Seeq8003 ", dev->name);
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;
}
for (i = 0; i < 6; i++)
printk("%2.2x%c",
dev->dev_addr[i] = onboard_eth_addr[i],
i == 5 ? ' ': ':');
printk(KERN_INFO "%s: SGI Seeq8003 ", dev->name);
#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;
struct sgiseeq_private *sp;
struct net_device *next, *dev = root_sgiseeq_dev;
if(*str == ':')
str++;
num = str2hexnum(*str++) << 4;
num |= (str2hexnum(*str++));
ea[i] = num;
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");
/* $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)
......
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