Commit c5ad8565 authored by Dave Jones's avatar Dave Jones Committed by Linus Torvalds

Merge bug fixes and cleanups for sun3lance net driver

from 2.4.x kernel series.
parent 0af1d03e
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
*/ */
static char *version = "sun3lance.c: v1.1 11/17/1999 Sam Creasey (sammy@oh.verio.com)\n"; static char *version = "sun3lance.c: v1.2 1/12/2001 Sam Creasey (sammy@sammy.net)\n";
#include <linux/module.h> #include <linux/module.h>
...@@ -35,16 +35,24 @@ static char *version = "sun3lance.c: v1.1 11/17/1999 Sam Creasey (sammy@oh.veri ...@@ -35,16 +35,24 @@ static char *version = "sun3lance.c: v1.1 11/17/1999 Sam Creasey (sammy@oh.veri
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/delay.h>
#include <asm/setup.h> #include <asm/setup.h>
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/bitops.h> #include <asm/bitops.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/idprom.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <asm/sun3mmu.h> #include <asm/pgalloc.h>
#include <asm/dvma.h> #include <asm/dvma.h>
#include <asm/idprom.h>
#include <asm/machines.h>
#ifdef CONFIG_SUN3
#include <asm/sun3mmu.h>
#else
#include <asm/sun3xprom.h>
#endif
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/etherdevice.h> #include <linux/etherdevice.h>
...@@ -62,7 +70,7 @@ static char *version = "sun3lance.c: v1.1 11/17/1999 Sam Creasey (sammy@oh.veri ...@@ -62,7 +70,7 @@ static char *version = "sun3lance.c: v1.1 11/17/1999 Sam Creasey (sammy@oh.veri
* 3 = debug, print even more debug infos (packet data) * 3 = debug, print even more debug infos (packet data)
*/ */
#define LANCE_DEBUG 1 #define LANCE_DEBUG 0
#ifdef LANCE_DEBUG #ifdef LANCE_DEBUG
static int lance_debug = LANCE_DEBUG; static int lance_debug = LANCE_DEBUG;
...@@ -139,7 +147,7 @@ struct lance_memory { ...@@ -139,7 +147,7 @@ struct lance_memory {
struct lance_tx_head tx_head[TX_RING_SIZE]; struct lance_tx_head tx_head[TX_RING_SIZE];
struct lance_rx_head rx_head[RX_RING_SIZE]; struct lance_rx_head rx_head[RX_RING_SIZE];
char rx_data[RX_RING_SIZE][PKT_BUF_SZ]; char rx_data[RX_RING_SIZE][PKT_BUF_SZ];
char tx_data[RX_RING_SIZE][PKT_BUF_SZ]; char tx_data[TX_RING_SIZE][PKT_BUF_SZ];
}; };
/* The driver's private device structure */ /* The driver's private device structure */
...@@ -151,8 +159,8 @@ struct lance_private { ...@@ -151,8 +159,8 @@ struct lance_private {
int old_tx, old_rx; /* ring entry to be processed */ int old_tx, old_rx; /* ring entry to be processed */
struct net_device_stats stats; struct net_device_stats stats;
/* These two must be longs for set_bit() */ /* These two must be longs for set_bit() */
long tx_full; long tx_full;
long lock; long lock;
}; };
/* I/O register access macros */ /* I/O register access macros */
...@@ -247,15 +255,27 @@ int __init sun3lance_probe( struct net_device *dev ) ...@@ -247,15 +255,27 @@ int __init sun3lance_probe( struct net_device *dev )
{ {
static int found; static int found;
/* check that this machine has an onboard lance */
switch(idprom->id_machtype) {
case SM_SUN3|SM_3_50:
case SM_SUN3|SM_3_60:
case SM_SUN3X|SM_3_80:
/* these machines have lance */
break;
default:
return(-ENODEV);
}
if(found) if(found)
return(ENODEV); return(-ENODEV);
if (lance_probe(dev)) { if (lance_probe(dev)) {
found = 1; found = 1;
return( 0 ); return( 0 );
} }
return( ENODEV ); return( -ENODEV );
} }
static int __init lance_probe( struct net_device *dev) static int __init lance_probe( struct net_device *dev)
...@@ -269,6 +289,7 @@ static int __init lance_probe( struct net_device *dev) ...@@ -269,6 +289,7 @@ static int __init lance_probe( struct net_device *dev)
volatile unsigned short *ioaddr_probe; volatile unsigned short *ioaddr_probe;
unsigned short tmp1, tmp2; unsigned short tmp1, tmp2;
#ifdef CONFIG_SUN3
/* LANCE_OBIO can be found within the IO pmeg with some effort */ /* LANCE_OBIO can be found within the IO pmeg with some effort */
for(ioaddr = 0xfe00000; ioaddr < (0xfe00000 + for(ioaddr = 0xfe00000; ioaddr < (0xfe00000 +
SUN3_PMEG_SIZE); ioaddr += SUN3_PTE_SIZE) { SUN3_PMEG_SIZE); ioaddr += SUN3_PTE_SIZE) {
...@@ -286,6 +307,9 @@ static int __init lance_probe( struct net_device *dev) ...@@ -286,6 +307,9 @@ static int __init lance_probe( struct net_device *dev)
if(!found) if(!found)
return 0; return 0;
#else
ioaddr = SUN3X_LANCE;
#endif
/* test to see if there's really a lance here */ /* test to see if there's really a lance here */
/* (CSRO_INIT shouldn't be readable) */ /* (CSRO_INIT shouldn't be readable) */
...@@ -311,8 +335,9 @@ static int __init lance_probe( struct net_device *dev) ...@@ -311,8 +335,9 @@ static int __init lance_probe( struct net_device *dev)
return 0; return 0;
} }
lp = (struct lance_private *)dev->priv; lp = (struct lance_private *)dev->priv;
MEM = (struct lance_memory *)sun3_dvma_malloc(sizeof(struct
lance_memory)); MEM = dvma_malloc_align(sizeof(struct lance_memory), 0x10000);
lp->iobase = (volatile unsigned short *)ioaddr; lp->iobase = (volatile unsigned short *)ioaddr;
dev->base_addr = (unsigned long)ioaddr; /* informational only */ dev->base_addr = (unsigned long)ioaddr; /* informational only */
...@@ -331,7 +356,7 @@ static int __init lance_probe( struct net_device *dev) ...@@ -331,7 +356,7 @@ static int __init lance_probe( struct net_device *dev)
/* copy in the ethernet address from the prom */ /* copy in the ethernet address from the prom */
for(i = 0; i < 6 ; i++) for(i = 0; i < 6 ; i++)
dev->dev_addr[i] = idprom->id_ethaddr[i]; dev->dev_addr[i] = idprom->id_ethaddr[i];
/* tell the card it's ether address, bytes swapped */ /* tell the card it's ether address, bytes swapped */
MEM->init.hwaddr[0] = dev->dev_addr[1]; MEM->init.hwaddr[0] = dev->dev_addr[1];
MEM->init.hwaddr[1] = dev->dev_addr[0]; MEM->init.hwaddr[1] = dev->dev_addr[0];
...@@ -346,20 +371,19 @@ static int __init lance_probe( struct net_device *dev) ...@@ -346,20 +371,19 @@ static int __init lance_probe( struct net_device *dev)
MEM->init.mode = 0x0000; MEM->init.mode = 0x0000;
MEM->init.filter[0] = 0x00000000; MEM->init.filter[0] = 0x00000000;
MEM->init.filter[1] = 0x00000000; MEM->init.filter[1] = 0x00000000;
MEM->init.rdra = sun3_dvma_vtop(MEM->rx_head); MEM->init.rdra = dvma_vtob(MEM->rx_head);
MEM->init.rlen = (RX_LOG_RING_SIZE << 13) | MEM->init.rlen = (RX_LOG_RING_SIZE << 13) |
(sun3_dvma_vtop(MEM->rx_head) >> 16); (dvma_vtob(MEM->rx_head) >> 16);
MEM->init.tdra = sun3_dvma_vtop(MEM->tx_head); MEM->init.tdra = dvma_vtob(MEM->tx_head);
MEM->init.tlen = (TX_LOG_RING_SIZE << 13) | MEM->init.tlen = (TX_LOG_RING_SIZE << 13) |
(sun3_dvma_vtop(MEM->tx_head) >> 16); (dvma_vtob(MEM->tx_head) >> 16);
DPRINTK(2, ("initaddr: %08lx rx_ring: %08lx tx_ring: %08lx\n", DPRINTK(2, ("initaddr: %08lx rx_ring: %08lx tx_ring: %08lx\n",
sun3_dvma_vtop(&(MEM->init)), sun3_dvma_vtop(MEM->rx_head), dvma_vtob(&(MEM->init)), dvma_vtob(MEM->rx_head),
(sun3_dvma_vtop(MEM->tx_head)))); (dvma_vtob(MEM->tx_head))));
if (did_version++ == 0) if (did_version++ == 0)
DPRINTK( 1, ( version )); printk( version );
/* The LANCE-specific entries in the device structure. */ /* The LANCE-specific entries in the device structure. */
dev->open = &lance_open; dev->open = &lance_open;
...@@ -386,16 +410,8 @@ static int lance_open( struct net_device *dev ) ...@@ -386,16 +410,8 @@ static int lance_open( struct net_device *dev )
REGA(CSR0) = CSR0_STOP; REGA(CSR0) = CSR0_STOP;
/* tell the lance the address of its init block */
REGA(CSR1) = sun3_dvma_vtop(&(MEM->init));
REGA(CSR2) = sun3_dvma_vtop(&(MEM->init)) >> 16;
lance_init_ring(dev); lance_init_ring(dev);
/* Re-initialize the LANCE, and start it when done. */
REGA(CSR3) = CSR3_BSWP;
/* From now on, AREG is kept to point to CSR0 */ /* From now on, AREG is kept to point to CSR0 */
REGA(CSR0) = CSR0_INIT; REGA(CSR0) = CSR0_INIT;
...@@ -434,23 +450,52 @@ static void lance_init_ring( struct net_device *dev ) ...@@ -434,23 +450,52 @@ static void lance_init_ring( struct net_device *dev )
lp->old_rx = lp->old_tx = 0; lp->old_rx = lp->old_tx = 0;
for( i = 0; i < TX_RING_SIZE; i++ ) { for( i = 0; i < TX_RING_SIZE; i++ ) {
MEM->tx_head[i].base = sun3_dvma_vtop(MEM->tx_data[i]); MEM->tx_head[i].base = dvma_vtob(MEM->tx_data[i]);
MEM->tx_head[i].flag = 0; MEM->tx_head[i].flag = 0;
MEM->tx_head[i].base_hi = MEM->tx_head[i].base_hi =
(sun3_dvma_vtop(MEM->tx_data[i])) >>16; (dvma_vtob(MEM->tx_data[i])) >>16;
MEM->tx_head[i].length = 0; MEM->tx_head[i].length = 0;
MEM->tx_head[i].misc = 0; MEM->tx_head[i].misc = 0;
} }
for( i = 0; i < RX_RING_SIZE; i++ ) { for( i = 0; i < RX_RING_SIZE; i++ ) {
MEM->rx_head[i].base = sun3_dvma_vtop(MEM->rx_data[i]); MEM->rx_head[i].base = dvma_vtob(MEM->rx_data[i]);
MEM->rx_head[i].flag = TMD1_OWN_CHIP; MEM->rx_head[i].flag = RMD1_OWN_CHIP;
MEM->rx_head[i].base_hi = MEM->rx_head[i].base_hi =
(sun3_dvma_vtop(MEM->rx_data[i])) >> 16; (dvma_vtob(MEM->rx_data[i])) >> 16;
MEM->rx_head[i].buf_length = -PKT_BUF_SZ | 0xf000; MEM->rx_head[i].buf_length = -PKT_BUF_SZ | 0xf000;
MEM->rx_head[i].msg_length = 0; MEM->rx_head[i].msg_length = 0;
} }
/* tell the card it's ether address, bytes swapped */
MEM->init.hwaddr[0] = dev->dev_addr[1];
MEM->init.hwaddr[1] = dev->dev_addr[0];
MEM->init.hwaddr[2] = dev->dev_addr[3];
MEM->init.hwaddr[3] = dev->dev_addr[2];
MEM->init.hwaddr[4] = dev->dev_addr[5];
MEM->init.hwaddr[5] = dev->dev_addr[4];
MEM->init.mode = 0x0000;
MEM->init.filter[0] = 0x00000000;
MEM->init.filter[1] = 0x00000000;
MEM->init.rdra = dvma_vtob(MEM->rx_head);
MEM->init.rlen = (RX_LOG_RING_SIZE << 13) |
(dvma_vtob(MEM->rx_head) >> 16);
MEM->init.tdra = dvma_vtob(MEM->tx_head);
MEM->init.tlen = (TX_LOG_RING_SIZE << 13) |
(dvma_vtob(MEM->tx_head) >> 16);
/* tell the lance the address of its init block */
REGA(CSR1) = dvma_vtob(&(MEM->init));
REGA(CSR2) = dvma_vtob(&(MEM->init)) >> 16;
#ifdef CONFIG_SUN3X
REGA(CSR3) = CSR3_BSWP | CSR3_ACON | CSR3_BCON;
#else
REGA(CSR3) = CSR3_BSWP;
#endif
} }
...@@ -512,7 +557,7 @@ static int lance_start_xmit( struct sk_buff *skb, struct net_device *dev ) ...@@ -512,7 +557,7 @@ static int lance_start_xmit( struct sk_buff *skb, struct net_device *dev )
stopping the queue for a bit... */ stopping the queue for a bit... */
netif_stop_queue(dev); netif_stop_queue(dev);
if (test_and_set_bit( 0, (void*)&lp->lock ) != 0) { if (test_and_set_bit( 0, (void*)&lp->lock ) != 0) {
printk( "%s: tx queue lock!.\n", dev->name); printk( "%s: tx queue lock!.\n", dev->name);
/* don't clear dev->tbusy flag. */ /* don't clear dev->tbusy flag. */
...@@ -520,13 +565,22 @@ static int lance_start_xmit( struct sk_buff *skb, struct net_device *dev ) ...@@ -520,13 +565,22 @@ static int lance_start_xmit( struct sk_buff *skb, struct net_device *dev )
} }
AREG = CSR0; AREG = CSR0;
// DPRINTK( 2, ( "%s: lance_start_xmit() called, csr0 %4.4x.\n", DPRINTK( 2, ( "%s: lance_start_xmit() called, csr0 %4.4x.\n",
// dev->name, DREG )); dev->name, DREG ));
#ifdef CONFIG_SUN3X
/* this weirdness doesn't appear on sun3... */
if(!(DREG & CSR0_INIT)) {
DPRINTK( 1, ("INIT not set, reinitializing...\n"));
REGA( CSR0 ) = CSR0_STOP;
lance_init_ring(dev);
REGA( CSR0 ) = CSR0_INIT | CSR0_STRT;
}
#endif
/* Fill in a Tx ring entry */ /* Fill in a Tx ring entry */
#if 0 #if 0
if (lance_debug >= 3) { if (lance_debug >= 2) {
u_char *p; u_char *p;
int i; int i;
printk( "%s: TX pkt %d type 0x%04x from ", dev->name, printk( "%s: TX pkt %d type 0x%04x from ", dev->name,
...@@ -566,7 +620,10 @@ static int lance_start_xmit( struct sk_buff *skb, struct net_device *dev ) ...@@ -566,7 +620,10 @@ static int lance_start_xmit( struct sk_buff *skb, struct net_device *dev )
lp->stats.tx_bytes += skb->len; lp->stats.tx_bytes += skb->len;
/* Trigger an immediate send poll. */ /* Trigger an immediate send poll. */
REGA(CSR0) = CSR0_INEA | CSR0_TDMD; REGA(CSR0) = CSR0_INEA | CSR0_TDMD | CSR0_STRT;
AREG = CSR0;
DPRINTK( 2, ( "%s: lance_start_xmit() exiting, csr0 %4.4x.\n",
dev->name, DREG ));
dev->trans_start = jiffies; dev->trans_start = jiffies;
dev_kfree_skb( skb ); dev_kfree_skb( skb );
...@@ -597,14 +654,15 @@ static void lance_interrupt( int irq, void *dev_id, struct pt_regs *fp) ...@@ -597,14 +654,15 @@ static void lance_interrupt( int irq, void *dev_id, struct pt_regs *fp)
if (in_interrupt) if (in_interrupt)
DPRINTK( 2, ( "%s: Re-entering the interrupt handler.\n", dev->name )); DPRINTK( 2, ( "%s: Re-entering the interrupt handler.\n", dev->name ));
in_interrupt = 1; in_interrupt = 1;
still_more: still_more:
flush_cache_all();
AREG = CSR0; AREG = CSR0;
csr0 = DREG; csr0 = DREG;
/* ack interrupts */ /* ack interrupts */
DREG = csr0 & (CSR0_TINT | CSR0_RINT); DREG = csr0 & (CSR0_TINT | CSR0_RINT | CSR0_IDON);
/* clear errors */ /* clear errors */
if(csr0 & CSR0_ERR) if(csr0 & CSR0_ERR)
......
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