Commit 3f8e1a1d authored by Ralf Bächle's avatar Ralf Bächle

[netdrvr] update declance

parent 022dc70e
...@@ -1850,7 +1850,7 @@ config SGISEEQ ...@@ -1850,7 +1850,7 @@ config SGISEEQ
used in many Silicon Graphics machines. used in many Silicon Graphics machines.
config DECLANCE config DECLANCE
bool "DEC LANCE ethernet controller support" tristate "DEC LANCE ethernet controller support"
depends on NET_ETHERNET && DECSTATION depends on NET_ETHERNET && DECSTATION
help help
This driver is for the series of Ethernet controllers produced by This driver is for the series of Ethernet controllers produced by
......
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
* *
* adopted from sunlance.c by Richard van den Berg * adopted from sunlance.c by Richard van den Berg
* *
* Copyright (C) 2002, 2003 Maciej W. Rozycki
*
* additional sources: * additional sources:
* - PMAD-AA TURBOchannel Ethernet Module Functional Specification, * - PMAD-AA TURBOchannel Ethernet Module Functional Specification,
* Revision 1.2 * Revision 1.2
...@@ -16,76 +18,71 @@ ...@@ -16,76 +18,71 @@
* v0.002: Removed most sparc stuff, left only some module and dma stuff. * v0.002: Removed most sparc stuff, left only some module and dma stuff.
* *
* v0.003: Enhanced base address calculation from proposals by * v0.003: Enhanced base address calculation from proposals by
* Harald Koerfgen and Thomas Riemer. * Harald Koerfgen and Thomas Riemer.
* *
* v0.004: lance-regs is pointing at the right addresses, added prom * v0.004: lance-regs is pointing at the right addresses, added prom
* check. First start of address mapping and DMA. * check. First start of address mapping and DMA.
* *
* v0.005: started to play around with LANCE-DMA. This driver will not work * v0.005: started to play around with LANCE-DMA. This driver will not
* for non IOASIC lances. HK * work for non IOASIC lances. HK
* *
* v0.006: added pointer arrays to lance_private and setup routine for them * v0.006: added pointer arrays to lance_private and setup routine for
* in dec_lance_init. HK * them in dec_lance_init. HK
* *
* v0.007: Big shit. The LANCE seems to use a different DMA mechanism to access * v0.007: Big shit. The LANCE seems to use a different DMA mechanism to
* the init block. This looks like one (short) word at a time, but the smallest * access the init block. This looks like one (short) word at a
* amount the IOASIC can transfer is a (long) word. So we have a 2-2 padding here. * time, but the smallest amount the IOASIC can transfer is a
* Changed lance_init_block accordingly. The 16-16 padding for the buffers * (long) word. So we have a 2-2 padding here. Changed
* seems to be correct. HK * lance_init_block accordingly. The 16-16 padding for the buffers
* seems to be correct. HK
* *
* v0.008 - mods to make PMAX_LANCE work. 01/09/1999 triemer * v0.008: mods to make PMAX_LANCE work. 01/09/1999 triemer
*/ *
* v0.009: Module support fixes, multiple interfaces support, various
#undef DEBUG_DRIVER * bits. macro
static char *version =
"declance.c: v0.008 by Linux Mips DECstation task force\n";
static char *lancestr = "LANCE";
/*
* card types
*/ */
#define ASIC_LANCE 1
#define PMAD_LANCE 2
#define PMAX_LANCE 3
#include <linux/config.h>
#include <linux/crc32.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/if_ether.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h>
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/spinlock.h>
#include <linux/stddef.h>
#include <linux/string.h>
#include <asm/addrspace.h>
#include <asm/dec/interrupts.h> #include <asm/dec/interrupts.h>
#include <asm/dec/ioasic_ints.h> #include <asm/dec/ioasic.h>
#include <asm/dec/ioasic_addrs.h> #include <asm/dec/ioasic_addrs.h>
#include <asm/dec/kn01.h>
#include <asm/dec/machtype.h> #include <asm/dec/machtype.h>
#include <asm/dec/tc.h> #include <asm/dec/tc.h>
#include <asm/dec/kn01.h> #include <asm/system.h>
#include <asm/wbflush.h>
#include <asm/addrspace.h>
#include <linux/config.h> static char version[] __devinitdata =
#include <linux/errno.h> "declance.c: v0.009 by Linux MIPS DECstation task force\n";
#include <linux/hdreg.h>
#include <linux/ioport.h> MODULE_AUTHOR("Linux MIPS DECstation task force");
#include <linux/mm.h> MODULE_DESCRIPTION("DEC LANCE (DECstation onboard, PMAD-xx) driver");
#include <linux/stddef.h> MODULE_LICENSE("GPL");
#include <linux/string.h>
#include <linux/unistd.h> /*
#include <linux/slab.h> * card types
#include <linux/user.h> */
#include <linux/utsname.h> #define ASIC_LANCE 1
#include <linux/a.out.h> #define PMAD_LANCE 2
#include <linux/tty.h> #define PMAX_LANCE 3
#include <linux/delay.h>
#include <linux/crc32.h>
#include <asm/io.h>
#include <linux/etherdevice.h>
#ifndef CONFIG_TC #ifndef CONFIG_TC
unsigned long system_base; unsigned long system_base;
unsigned long dmaptr; unsigned long dmaptr;
#endif #endif
static int type;
#define LE_CSR0 0 #define LE_CSR0 0
#define LE_CSR1 1 #define LE_CSR1 1
...@@ -160,8 +157,6 @@ static int type; ...@@ -160,8 +157,6 @@ static int type;
#define TX_BUFF_SIZE PKT_BUF_SZ #define TX_BUFF_SIZE PKT_BUF_SZ
#undef TEST_HITS #undef TEST_HITS
#define DEBUG_DRIVER 1
#define ZERO 0 #define ZERO 0
/* The DS2000/3000 have a linear 64 KB buffer. /* The DS2000/3000 have a linear 64 KB buffer.
...@@ -179,26 +174,26 @@ static int type; ...@@ -179,26 +174,26 @@ static int type;
*/ */
struct lance_rx_desc { struct lance_rx_desc {
unsigned short rmd0; /* low address of packet */ unsigned short rmd0; /* low address of packet */
short gap0; short gap0;
unsigned char rmd1_hadr; /* high address of packet */ unsigned char rmd1_hadr; /* high address of packet */
unsigned char rmd1_bits; /* descriptor bits */ unsigned char rmd1_bits; /* descriptor bits */
short gap1; short gap1;
short length; /* This length is 2s complement (negative)! short length; /* 2s complement (negative!)
* Buffer length of buffer length */
*/
short gap2; short gap2;
unsigned short mblength; /* This is the actual number of bytes received */ unsigned short mblength; /* actual number of bytes received */
short gap3; short gap3;
}; };
struct lance_tx_desc { struct lance_tx_desc {
unsigned short tmd0; /* low address of packet */ unsigned short tmd0; /* low address of packet */
short gap0; short gap0;
unsigned char tmd1_hadr; /* high address of packet */ unsigned char tmd1_hadr; /* high address of packet */
unsigned char tmd1_bits; /* descriptor bits */ unsigned char tmd1_bits; /* descriptor bits */
short gap1; short gap1;
short length; /* Length is 2s complement (negative)! */ short length; /* 2s complement (negative!)
of buffer length */
short gap2; short gap2;
unsigned short misc; unsigned short misc;
short gap3; short gap3;
...@@ -207,28 +202,26 @@ struct lance_tx_desc { ...@@ -207,28 +202,26 @@ struct lance_tx_desc {
/* First part of the LANCE initialization block, described in databook. */ /* First part of the LANCE initialization block, described in databook. */
struct lance_init_block { struct lance_init_block {
unsigned short mode; /* Pre-set mode (reg. 15) */ unsigned short mode; /* pre-set mode (reg. 15) */
short gap0; short gap0;
unsigned char phys_addr[12]; /* Physical ethernet address unsigned char phys_addr[12]; /* physical ethernet address
* only 0, 1, 4, 5, 8, 9 are valid only 0, 1, 4, 5, 8, 9 are valid
* 2, 3, 6, 7, 10, 11 are gaps 2, 3, 6, 7, 10, 11 are gaps */
*/ unsigned short filter[8]; /* multicast filter
unsigned short filter[8]; /* Multicast filter. only 0, 2, 4, 6 are valid
* only 0, 2, 4, 6 are valid 1, 3, 5, 7 are gaps */
* 1, 3, 5, 7 are gaps
*/
/* Receive and transmit ring base, along with extra bits. */ /* Receive and transmit ring base, along with extra bits. */
unsigned short rx_ptr; /* receive descriptor addr */ unsigned short rx_ptr; /* receive descriptor addr */
short gap1; short gap1;
unsigned short rx_len; /* receive len and high addr */ unsigned short rx_len; /* receive len and high addr */
short gap2; short gap2;
unsigned short tx_ptr; /* transmit descriptor addr */ unsigned short tx_ptr; /* transmit descriptor addr */
short gap3; short gap3;
unsigned short tx_len; /* transmit len and high addr */ unsigned short tx_len; /* transmit len and high addr */
short gap4; short gap4;
char gap5[16]; short gap5[8];
/* The buffer descriptors */ /* The buffer descriptors */
struct lance_rx_desc brx_ring[RX_RING_SIZE]; struct lance_rx_desc brx_ring[RX_RING_SIZE];
...@@ -247,10 +240,12 @@ struct lance_init_block { ...@@ -247,10 +240,12 @@ struct lance_init_block {
#define LANCE_ADDR(x) (PHYSADDR(x) >> 1) #define LANCE_ADDR(x) (PHYSADDR(x) >> 1)
struct lance_private { struct lance_private {
char *name; struct net_device *next;
int type;
int slot;
int dma_irq;
volatile struct lance_regs *ll; volatile struct lance_regs *ll;
volatile struct lance_init_block *init_block; volatile struct lance_init_block *init_block;
volatile unsigned long *dma_ptr_reg;
spinlock_t lock; spinlock_t lock;
...@@ -261,8 +256,6 @@ struct lance_private { ...@@ -261,8 +256,6 @@ struct lance_private {
unsigned short busmaster_regval; unsigned short busmaster_regval;
struct net_device *dev; /* Backpointer */
struct lance_private *next_module;
struct timer_list multicast_timer; struct timer_list multicast_timer;
/* Pointers to the ring buffers as seen from the CPU */ /* Pointers to the ring buffers as seen from the CPU */
...@@ -292,16 +285,12 @@ struct lance_regs { ...@@ -292,16 +285,12 @@ struct lance_regs {
int dec_lance_debug = 2; int dec_lance_debug = 2;
/* static struct net_device *root_lance_dev;
#ifdef MODULE
static struct lance_private *root_lance_dev = NULL;
#endif
*/
static inline void writereg(volatile unsigned short *regptr, short value) static inline void writereg(volatile unsigned short *regptr, short value)
{ {
*regptr = value; *regptr = value;
wbflush(); iob();
} }
/* Load the CSR registers */ /* Load the CSR registers */
...@@ -330,7 +319,7 @@ static void load_csrs(struct lance_private *lp) ...@@ -330,7 +319,7 @@ static void load_csrs(struct lance_private *lp)
* Our specialized copy routines * Our specialized copy routines
* *
*/ */
void cp_to_buf(void *to, const void *from, __kernel_size_t len) void cp_to_buf(const int type, void *to, const void *from, int len)
{ {
unsigned short *tp, *fp, clen; unsigned short *tp, *fp, clen;
unsigned char *rtp, *rfp; unsigned char *rtp, *rfp;
...@@ -381,10 +370,10 @@ void cp_to_buf(void *to, const void *from, __kernel_size_t len) ...@@ -381,10 +370,10 @@ void cp_to_buf(void *to, const void *from, __kernel_size_t len)
} }
} }
wbflush(); iob();
} }
void cp_from_buf(void *to, unsigned char *from, int len) void cp_from_buf(const int type, void *to, const void *from, int len)
{ {
unsigned short *tp, *fp, clen; unsigned short *tp, *fp, clen;
unsigned char *rtp, *rfp; unsigned char *rtp, *rfp;
...@@ -509,7 +498,7 @@ static void lance_init_ring(struct net_device *dev) ...@@ -509,7 +498,7 @@ static void lance_init_ring(struct net_device *dev)
if (i < 3 && ZERO) if (i < 3 && ZERO)
printk("%d: 0x%8.8x(0x%8.8x)\n", i, leptr, (int) lp->rx_buf_ptr_cpu[i]); printk("%d: 0x%8.8x(0x%8.8x)\n", i, leptr, (int) lp->rx_buf_ptr_cpu[i]);
} }
wbflush(); iob();
} }
static int init_restart_lance(struct lance_private *lp) static int init_restart_lance(struct lance_private *lp)
...@@ -551,22 +540,21 @@ static int lance_rx(struct net_device *dev) ...@@ -551,22 +540,21 @@ static int lance_rx(struct net_device *dev)
#ifdef TEST_HITS #ifdef TEST_HITS
{ {
int i; int i;
printk("["); printk("[");
for (i = 0; i < RX_RING_SIZE; i++) { for (i = 0; i < RX_RING_SIZE; i++) {
if (i == lp->rx_new) if (i == lp->rx_new)
printk("%s", printk("%s", ib->brx_ring[i].rmd1_bits &
ib->brx_ring[i].rmd1_bits & LE_R1_OWN ? "_" : "X"); LE_R1_OWN ? "_" : "X");
else else
printk("%s", printk("%s", ib->brx_ring[i].rmd1_bits &
ib->brx_ring[i].rmd1_bits & LE_R1_OWN ? "." : "1"); LE_R1_OWN ? "." : "1");
} }
printk("]"); printk("]");
} }
#endif #endif
for (rd = &ib->brx_ring[lp->rx_new]; for (rd = &ib->brx_ring[lp->rx_new];
!((bits = rd->rmd1_bits) & LE_R1_OWN); !((bits = rd->rmd1_bits) & LE_R1_OWN);
rd = &ib->brx_ring[lp->rx_new]) { rd = &ib->brx_ring[lp->rx_new]) {
...@@ -608,8 +596,8 @@ static int lance_rx(struct net_device *dev) ...@@ -608,8 +596,8 @@ static int lance_rx(struct net_device *dev)
skb_reserve(skb, 2); /* 16 byte align */ skb_reserve(skb, 2); /* 16 byte align */
skb_put(skb, len); /* make room */ skb_put(skb, len); /* make room */
cp_from_buf(skb->data, cp_from_buf(lp->type, skb->data,
(char *) lp->rx_buf_ptr_cpu[lp->rx_new], (char *)lp->rx_buf_ptr_cpu[lp->rx_new],
len); len);
skb->protocol = eth_type_trans(skb, dev); skb->protocol = eth_type_trans(skb, dev);
...@@ -709,6 +697,14 @@ static void lance_tx(struct net_device *dev) ...@@ -709,6 +697,14 @@ static void lance_tx(struct net_device *dev)
spin_unlock(&lp->lock); spin_unlock(&lp->lock);
} }
static void lance_dma_merr_int(const int irq, void *dev_id,
struct pt_regs *regs)
{
struct net_device *dev = (struct net_device *) dev_id;
printk("%s: DMA error\n", dev->name);
}
static irqreturn_t static irqreturn_t
lance_interrupt(const int irq, void *dev_id, struct pt_regs *regs) lance_interrupt(const int irq, void *dev_id, struct pt_regs *regs)
{ {
...@@ -741,19 +737,8 @@ lance_interrupt(const int irq, void *dev_id, struct pt_regs *regs) ...@@ -741,19 +737,8 @@ lance_interrupt(const int irq, void *dev_id, struct pt_regs *regs)
lp->stats.rx_errors++; lp->stats.rx_errors++;
if (csr0 & LE_C0_MERR) { if (csr0 & LE_C0_MERR) {
volatile unsigned long int_stat = *(unsigned long *) (system_base + IOCTL + SIR);
printk("%s: Memory error, status %04x\n", dev->name, csr0); printk("%s: Memory error, status %04x\n", dev->name, csr0);
if (int_stat & LANCE_DMA_MEMRDERR) {
printk("%s: DMA error\n", dev->name);
int_stat |= LANCE_DMA_MEMRDERR;
/*
* re-enable LANCE DMA
*/
*(unsigned long *) (system_base + IOCTL + SSR) |= (1 << 16);
wbflush();
}
writereg(&ll->rdp, LE_C0_STOP); writereg(&ll->rdp, LE_C0_STOP);
lance_init_ring(dev); lance_init_ring(dev);
...@@ -800,10 +785,30 @@ static int lance_open(struct net_device *dev) ...@@ -800,10 +785,30 @@ static int lance_open(struct net_device *dev)
netif_start_queue(dev); netif_start_queue(dev);
/* Associate IRQ with lance_interrupt */ /* Associate IRQ with lance_interrupt */
if (request_irq(dev->irq, &lance_interrupt, 0, lp->name, dev)) { if (request_irq(dev->irq, &lance_interrupt, 0, "lance", dev)) {
printk("Lance: Can't get irq %d\n", dev->irq); printk("lance: Can't get IRQ %d\n", dev->irq);
return -EAGAIN; return -EAGAIN;
} }
if (lp->dma_irq >= 0) {
unsigned long flags;
if (request_irq(lp->dma_irq, &lance_dma_merr_int, 0,
"lance error", dev)) {
free_irq(dev->irq, dev);
printk("lance: Can't get DMA IRQ %d\n", lp->dma_irq);
return -EAGAIN;
}
spin_lock_irqsave(&ioasic_ssr_lock, flags);
fast_mb();
/* Enable I/O ASIC LANCE DMA. */
ioasic_write(IO_REG_SSR,
ioasic_read(IO_REG_SSR) | IO_SSR_LANCE_DMA_EN);
fast_mb();
spin_unlock_irqrestore(&ioasic_ssr_lock, flags);
}
status = init_restart_lance(lp); status = init_restart_lance(lp);
...@@ -827,7 +832,22 @@ static int lance_close(struct net_device *dev) ...@@ -827,7 +832,22 @@ static int lance_close(struct net_device *dev)
writereg(&ll->rap, LE_CSR0); writereg(&ll->rap, LE_CSR0);
writereg(&ll->rdp, LE_C0_STOP); writereg(&ll->rdp, LE_C0_STOP);
free_irq(dev->irq, (void *) dev); if (lp->dma_irq >= 0) {
unsigned long flags;
spin_lock_irqsave(&ioasic_ssr_lock, flags);
fast_mb();
/* Disable I/O ASIC LANCE DMA. */
ioasic_write(IO_REG_SSR,
ioasic_read(IO_REG_SSR) & ~IO_SSR_LANCE_DMA_EN);
fast_iob();
spin_unlock_irqrestore(&ioasic_ssr_lock, flags);
free_irq(lp->dma_irq, dev);
}
free_irq(dev->irq, dev);
/* /*
MOD_DEC_USE_COUNT; MOD_DEC_USE_COUNT;
*/ */
...@@ -886,7 +906,8 @@ static int lance_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -886,7 +906,8 @@ static int lance_start_xmit(struct sk_buff *skb, struct net_device *dev)
ib->btx_ring[entry].length = (-len); ib->btx_ring[entry].length = (-len);
ib->btx_ring[entry].misc = 0; ib->btx_ring[entry].misc = 0;
cp_to_buf((char *) lp->tx_buf_ptr_cpu[entry], skb->data, skblen); cp_to_buf(lp->type, (char *)lp->tx_buf_ptr_cpu[entry], skb->data,
skblen);
/* Clear the slack of the packet, do I need this? */ /* Clear the slack of the packet, do I need this? */
/* For a firewall it's a good idea - AC */ /* For a firewall it's a good idea - AC */
...@@ -926,7 +947,7 @@ static void lance_load_multicast(struct net_device *dev) ...@@ -926,7 +947,7 @@ static void lance_load_multicast(struct net_device *dev)
volatile u16 *mcast_table = (u16 *) & ib->filter; volatile u16 *mcast_table = (u16 *) & ib->filter;
struct dev_mc_list *dmi = dev->mc_list; struct dev_mc_list *dmi = dev->mc_list;
char *addrs; char *addrs;
int i, j, bit, byte; int i;
u32 crc; u32 crc;
/* set all multicast bits */ /* set all multicast bits */
...@@ -952,7 +973,7 @@ static void lance_load_multicast(struct net_device *dev) ...@@ -952,7 +973,7 @@ static void lance_load_multicast(struct net_device *dev)
if (!(*addrs & 1)) if (!(*addrs & 1))
continue; continue;
crc = ether_crc_le(6, addrs); crc = ether_crc_le(ETH_ALEN, addrs);
crc = crc >> 26; crc = crc >> 26;
mcast_table[2 * (crc >> 4)] |= 1 << (crc & 0xf); mcast_table[2 * (crc >> 4)] |= 1 << (crc & 0xf);
} }
...@@ -1001,7 +1022,7 @@ static void lance_set_multicast_retry(unsigned long _opaque) ...@@ -1001,7 +1022,7 @@ static void lance_set_multicast_retry(unsigned long _opaque)
lance_set_multicast(dev); lance_set_multicast(dev);
} }
static int __init dec_lance_init(struct net_device *dev, const int type) static int __init dec_lance_init(const int type, const int slot)
{ {
static unsigned version_printed; static unsigned version_printed;
struct net_device *dev; struct net_device *dev;
...@@ -1013,25 +1034,29 @@ static int __init dec_lance_init(struct net_device *dev, const int type) ...@@ -1013,25 +1034,29 @@ static int __init dec_lance_init(struct net_device *dev, const int type)
#ifndef CONFIG_TC #ifndef CONFIG_TC
system_base = KN01_LANCE_BASE; system_base = KN01_LANCE_BASE;
#else
int slot;
#endif #endif
if (dec_lance_debug && version_printed++ == 0) if (dec_lance_debug && version_printed++ == 0)
printk(version); printk(version);
dev = init_etherdev(0, sizeof(struct lance_private)); dev = init_etherdev(NULL, sizeof(struct lance_private));
if (!dev) if (!dev)
return -ENOMEM; return -ENOMEM;
SET_MODULE_OWNER(dev);
/* init_etherdev ensures the data structures used by the LANCE are aligned. */ /*
* init_etherdev ensures the data structures used by the LANCE
* are aligned.
*/
lp = (struct lance_private *) dev->priv; lp = (struct lance_private *) dev->priv;
spin_lock_init(&lp->lock); spin_lock_init(&lp->lock);
lp->type = type;
lp->slot = slot;
switch (type) { switch (type) {
#ifdef CONFIG_TC #ifdef CONFIG_TC
case ASIC_LANCE: case ASIC_LANCE:
dev->base_addr = system_base + LANCE; dev->base_addr = system_base + IOASIC_LANCE;
/* buffer space for the on-board LANCE shared memory */ /* buffer space for the on-board LANCE shared memory */
/* /*
...@@ -1039,78 +1064,101 @@ static int __init dec_lance_init(struct net_device *dev, const int type) ...@@ -1039,78 +1064,101 @@ static int __init dec_lance_init(struct net_device *dev, const int type)
*/ */
dev->mem_start = KSEG1ADDR(0x00020000); dev->mem_start = KSEG1ADDR(0x00020000);
dev->mem_end = dev->mem_start + 0x00020000; dev->mem_end = dev->mem_start + 0x00020000;
dev->irq = ETHER; dev->irq = dec_interrupt[DEC_IRQ_LANCE];
esar_base = system_base + ESAR; esar_base = system_base + IOASIC_ESAR;
/* Workaround crash with booting KN04 2.1k from Disk */ /* Workaround crash with booting KN04 2.1k from Disk */
memset(dev->mem_start, 0, dev->mem_end - dev->mem_start); memset((void *)dev->mem_start, 0,
dev->mem_end - dev->mem_start);
/* /*
* setup the pointer arrays, this sucks [tm] :-( * setup the pointer arrays, this sucks [tm] :-(
*/ */
for (i = 0; i < RX_RING_SIZE; i++) { for (i = 0; i < RX_RING_SIZE; i++) {
lp->rx_buf_ptr_cpu[i] = (char *) (dev->mem_start + BUF_OFFSET_CPU lp->rx_buf_ptr_cpu[i] =
+ 2 * i * RX_BUFF_SIZE); (char *)(dev->mem_start + BUF_OFFSET_CPU +
lp->rx_buf_ptr_lnc[i] = (char *) (BUF_OFFSET_LNC 2 * i * RX_BUFF_SIZE);
+ i * RX_BUFF_SIZE); lp->rx_buf_ptr_lnc[i] =
(char *)(BUF_OFFSET_LNC + i * RX_BUFF_SIZE);
} }
for (i = 0; i < TX_RING_SIZE; i++) { for (i = 0; i < TX_RING_SIZE; i++) {
lp->tx_buf_ptr_cpu[i] = (char *) (dev->mem_start + BUF_OFFSET_CPU lp->tx_buf_ptr_cpu[i] =
+ 2 * RX_RING_SIZE * RX_BUFF_SIZE (char *)(dev->mem_start + BUF_OFFSET_CPU +
+ 2 * i * TX_BUFF_SIZE); 2 * RX_RING_SIZE * RX_BUFF_SIZE +
lp->tx_buf_ptr_lnc[i] = (char *) (BUF_OFFSET_LNC 2 * i * TX_BUFF_SIZE);
+ RX_RING_SIZE * RX_BUFF_SIZE lp->tx_buf_ptr_lnc[i] =
+ i * TX_BUFF_SIZE); (char *)(BUF_OFFSET_LNC +
RX_RING_SIZE * RX_BUFF_SIZE +
i * TX_BUFF_SIZE);
} }
/* /* Setup I/O ASIC LANCE DMA. */
* setup and enable IOASIC LANCE DMA lp->dma_irq = dec_interrupt[DEC_IRQ_LANCE_MERR];
*/ ioasic_write(IO_REG_LANCE_DMA_P,
lp->dma_ptr_reg = (unsigned long *) (system_base + IOCTL + LANCE_DMA_P); PHYSADDR(dev->mem_start) << 3);
*(lp->dma_ptr_reg) = PHYSADDR(dev->mem_start) << 3;
*(unsigned long *) (system_base + IOCTL + SSR) |= (1 << 16);
wbflush();
break; break;
case PMAD_LANCE: case PMAD_LANCE:
slot = search_tc_card("PMAD-AA");
claim_tc_card(slot); claim_tc_card(slot);
dev->mem_start = get_tc_base_addr(slot); dev->mem_start = get_tc_base_addr(slot);
dev->base_addr = dev->mem_start + 0x100000; dev->base_addr = dev->mem_start + 0x100000;
dev->irq = get_tc_irq_nr(slot); dev->irq = get_tc_irq_nr(slot);
esar_base = dev->mem_start + 0x1c0002; esar_base = dev->mem_start + 0x1c0002;
lp->dma_irq = -1;
for (i = 0; i < RX_RING_SIZE; i++) {
lp->rx_buf_ptr_cpu[i] =
(char *)(dev->mem_start + BUF_OFFSET_CPU +
i * RX_BUFF_SIZE);
lp->rx_buf_ptr_lnc[i] =
(char *)(BUF_OFFSET_LNC + i * RX_BUFF_SIZE);
}
for (i = 0; i < TX_RING_SIZE; i++) {
lp->tx_buf_ptr_cpu[i] =
(char *)(dev->mem_start + BUF_OFFSET_CPU +
RX_RING_SIZE * RX_BUFF_SIZE +
i * TX_BUFF_SIZE);
lp->tx_buf_ptr_lnc[i] =
(char *)(BUF_OFFSET_LNC +
RX_RING_SIZE * RX_BUFF_SIZE +
i * TX_BUFF_SIZE);
}
break; break;
#endif #endif
case PMAX_LANCE: case PMAX_LANCE:
dev->irq = ETHER; dev->irq = dec_interrupt[DEC_IRQ_LANCE];
dev->base_addr = KN01_LANCE_BASE; dev->base_addr = KN01_LANCE_BASE;
dev->mem_start = KN01_LANCE_BASE + 0x01000000; dev->mem_start = KN01_LANCE_BASE + 0x01000000;
esar_base = KN01_RTC_BASE + 1; esar_base = KN01_RTC_BASE + 1;
lp->dma_irq = -1;
/* /*
* setup the pointer arrays, this sucks [tm] :-( * setup the pointer arrays, this sucks [tm] :-(
*/ */
for (i = 0; i < RX_RING_SIZE; i++) { for (i = 0; i < RX_RING_SIZE; i++) {
lp->rx_buf_ptr_cpu[i] = lp->rx_buf_ptr_cpu[i] =
(char *) (dev->mem_start + BUF_OFFSET_CPU (char *)(dev->mem_start + BUF_OFFSET_CPU +
+ 2 * i * RX_BUFF_SIZE); 2 * i * RX_BUFF_SIZE);
lp->rx_buf_ptr_lnc[i] = lp->rx_buf_ptr_lnc[i] =
(char *) (BUF_OFFSET_LNC (char *)(BUF_OFFSET_LNC + i * RX_BUFF_SIZE);
+ i * RX_BUFF_SIZE);
} }
for (i = 0; i < TX_RING_SIZE; i++) { for (i = 0; i < TX_RING_SIZE; i++) {
lp->tx_buf_ptr_cpu[i] = lp->tx_buf_ptr_cpu[i] =
(char *) (dev->mem_start + BUF_OFFSET_CPU (char *)(dev->mem_start + BUF_OFFSET_CPU +
+ 2 * RX_RING_SIZE * RX_BUFF_SIZE 2 * RX_RING_SIZE * RX_BUFF_SIZE +
+ 2 * i * TX_BUFF_SIZE); 2 * i * TX_BUFF_SIZE);
lp->tx_buf_ptr_lnc[i] = (char *) (BUF_OFFSET_LNC lp->tx_buf_ptr_lnc[i] =
+ RX_RING_SIZE * RX_BUFF_SIZE (char *)(BUF_OFFSET_LNC +
+ i * TX_BUFF_SIZE); RX_RING_SIZE * RX_BUFF_SIZE +
i * TX_BUFF_SIZE);
} }
break; break;
default: default:
printk("declance_init called with unknown type\n"); printk("declance_init called with unknown type\n");
ret = -ENODEV; ret = -ENODEV;
...@@ -1140,6 +1188,9 @@ static int __init dec_lance_init(struct net_device *dev, const int type) ...@@ -1140,6 +1188,9 @@ static int __init dec_lance_init(struct net_device *dev, const int type)
} }
} }
lp->next = root_lance_dev;
root_lance_dev = dev;
/* Copy the ethernet address to the device structure, later to the /* Copy the ethernet address to the device structure, later to the
* lance initialization block so the lance gets it every time it's * lance initialization block so the lance gets it every time it's
* (re)initialized. * (re)initialized.
...@@ -1162,7 +1213,6 @@ static int __init dec_lance_init(struct net_device *dev, const int type) ...@@ -1162,7 +1213,6 @@ static int __init dec_lance_init(struct net_device *dev, const int type)
printk(" irq = %d\n", dev->irq); printk(" irq = %d\n", dev->irq);
lp->dev = dev;
dev->open = &lance_open; dev->open = &lance_open;
dev->stop = &lance_close; dev->stop = &lance_close;
dev->hard_start_xmit = &lance_start_xmit; dev->hard_start_xmit = &lance_start_xmit;
...@@ -1174,8 +1224,6 @@ static int __init dec_lance_init(struct net_device *dev, const int type) ...@@ -1174,8 +1224,6 @@ static int __init dec_lance_init(struct net_device *dev, const int type)
/* lp->ll is the location of the registers for lance card */ /* lp->ll is the location of the registers for lance card */
lp->ll = ll; lp->ll = ll;
lp->name = lancestr;
/* busmaster_regval (CSR3) should be zero according to the PMAD-AA /* busmaster_regval (CSR3) should be zero according to the PMAD-AA
* specification. * specification.
*/ */
...@@ -1183,8 +1231,6 @@ static int __init dec_lance_init(struct net_device *dev, const int type) ...@@ -1183,8 +1231,6 @@ static int __init dec_lance_init(struct net_device *dev, const int type)
dev->dma = 0; dev->dma = 0;
ether_setup(dev);
/* We cannot sleep if the chip is busy during a /* We cannot sleep if the chip is busy during a
* multicast list update event, because such events * multicast list update event, because such events
* can occur from interrupts (ex. IPv6). So we * can occur from interrupts (ex. IPv6). So we
...@@ -1194,11 +1240,6 @@ static int __init dec_lance_init(struct net_device *dev, const int type) ...@@ -1194,11 +1240,6 @@ static int __init dec_lance_init(struct net_device *dev, const int type)
lp->multicast_timer.data = (unsigned long) dev; lp->multicast_timer.data = (unsigned long) dev;
lp->multicast_timer.function = &lance_set_multicast_retry; lp->multicast_timer.function = &lance_set_multicast_retry;
#ifdef MODULE
dev->ifindex = dev_new_index();
lp->next_module = root_lance_dev;
root_lance_dev = lp;
#endif
return 0; return 0;
err_out: err_out:
...@@ -1211,61 +1252,51 @@ static int __init dec_lance_init(struct net_device *dev, const int type) ...@@ -1211,61 +1252,51 @@ static int __init dec_lance_init(struct net_device *dev, const int type)
/* Find all the lance cards on the system and initialize them */ /* Find all the lance cards on the system and initialize them */
static int __init dec_lance_probe(void) static int __init dec_lance_probe(void)
{ {
struct net_device *dev = NULL; int count = 0;
static int called;
#ifdef MODULE
root_lance_dev = NULL;
#endif
/* Scan slots for PMAD-AA cards first. */
#ifdef CONFIG_TC #ifdef CONFIG_TC
int slot = -1;
if (TURBOCHANNEL) { if (TURBOCHANNEL) {
if (IOASIC && !called) { int slot;
called = 1;
type = ASIC_LANCE; while ((slot = search_tc_card("PMAD-AA")) >= 0) {
} else { if (dec_lance_init(PMAD_LANCE, slot) < 0)
if ((slot = search_tc_card("PMAD-AA")) >= 0) { break;
type = PMAD_LANCE; count++;
} else {
return -ENODEV;
}
}
} else {
if (!called) {
called = 1;
type = PMAX_LANCE;
} else {
return -ENODEV;
} }
} }
#else
if (!called && !TURBOCHANNEL) {
called = 1;
type = PMAX_LANCE;
} else {
return -ENODEV;
}
#endif #endif
return dec_lance_init(dev, type); /* Then handle onboard devices. */
if (dec_interrupt[DEC_IRQ_LANCE] >= 0) {
if (dec_interrupt[DEC_IRQ_LANCE_MERR] >= 0) {
#ifdef CONFIG_TC
if (dec_lance_init(ASIC_LANCE, -1) >= 0)
count++;
#endif
} else if (!TURBOCHANNEL) {
if (dec_lance_init(PMAX_LANCE, -1) >= 0)
count++;
}
}
return (count > 0) ? 0 : -ENODEV;
} }
static void __exit dec_lance_cleanup(void) static void __exit dec_lance_cleanup(void)
{ {
#ifdef MODULE while (root_lance_dev) {
struct lance_private *lp; struct net_device *dev = root_lance_dev;
struct lance_private *lp = (struct lance_private *)dev->priv;
while (root_lance_dev) {
lp = root_lance_dev->next_module;
unregister_netdev(root_lance_dev->dev); #ifdef CONFIG_TC
kfree(root_lance_dev->dev); if (lp->slot >= 0)
root_lance_dev = lp; release_tc_card(lp->slot);
} #endif
#endif /* MODULE */ root_lance_dev = lp->next;
unregister_netdev(dev);
kfree(dev);
}
} }
module_init(dec_lance_probe); module_init(dec_lance_probe);
......
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