sun3lance.c revision afc8eb46c0ea2cab8bc28713b2e0614f015a7516
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* sun3lance.c: Ethernet driver for SUN3 Lance chip */ 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 46aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik Sun3 Lance ethernet driver, by Sam Creasey (sammy@users.qual.net). 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds This driver is a part of the linux kernel, and is thus distributed 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds under the GNU General Public License. 76aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds The values used in LANCE_OBIO and LANCE_IRQ seem to be empirically 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds true for the correct IRQ and address of the lance registers. They 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds have not been widely tested, however. What we probably need is a 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "proper" way to search for a device in the sun3's prom, but, alas, 126aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik linux has no such thing. 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds This driver is largely based on atarilance.c, by Roman Hodek. Other 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sources of inspiration were the NetBSD sun3 am7990 driver, and the 166aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik linux sparc lance driver (sunlance.c). 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds There are more assumptions made throughout this driver, it almost 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds certainly still needs work, but it does work at least for RARP/BOOTP and 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mounting the root NFS filesystem. 216aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/ 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic char *version = "sun3lance.c: v1.2 1/12/2001 Sam Creasey (sammy@sammy.net)\n"; 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/stddef.h> 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/string.h> 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h> 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/slab.h> 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/interrupt.h> 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ioport.h> 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/delay.h> 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/netdevice.h> 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/etherdevice.h> 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/skbuff.h> 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/bitops.h> 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 41a1f8e7f7fb9d7e2cbcb53170edca7c0ac4680697Al Viro#include <asm/cacheflush.h> 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/setup.h> 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/irq.h> 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/io.h> 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/pgtable.h> 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/dvma.h> 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/idprom.h> 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/machines.h> 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_SUN3 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/sun3mmu.h> 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/sun3xprom.h> 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* sun3/60 addr/irq for the lance chip. If your sun is different, 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds change this. */ 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LANCE_OBIO 0x120000 594facfde9f1d7b8a61fb0017460da45e23e60115cRoman Zippel#define LANCE_IRQ IRQ_AUTO_3 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Debug level: 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 0 = silent, print only serious errors 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1 = normal, print error messages 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2 = debug, print debug infos 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 3 = debug, print even more debug infos (packet data) 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LANCE_DEBUG 0 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef LANCE_DEBUG 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int lance_debug = LANCE_DEBUG; 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int lance_debug = 1; 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 758d3b33f67fdc0fb364a1ef6d8fbbea7c2e4e6c98Rusty Russellmodule_param(lance_debug, int, 0); 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(lance_debug, "SUN3 Lance debug level (0-3)"); 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DPRINTK(n,a) \ 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do { \ 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (lance_debug >= n) \ 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk a; \ 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } while( 0 ) 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* we're only using 32k of memory, so we use 4 TX 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buffers and 16 RX buffers. These values are expressed as log2. */ 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TX_LOG_RING_SIZE 3 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RX_LOG_RING_SIZE 5 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* These are the derived values */ 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TX_RING_SIZE (1 << TX_LOG_RING_SIZE) 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TX_RING_LEN_BITS (TX_LOG_RING_SIZE << 5) 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TX_RING_MOD_MASK (TX_RING_SIZE - 1) 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RX_RING_SIZE (1 << RX_LOG_RING_SIZE) 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RX_RING_LEN_BITS (RX_LOG_RING_SIZE << 5) 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RX_RING_MOD_MASK (RX_RING_SIZE - 1) 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Definitions for packet buffer access: */ 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PKT_BUF_SZ 1544 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Get the address of a packet buffer corresponding to a given buffer head */ 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PKTBUF_ADDR(head) (void *)((unsigned long)(MEM) | (head)->base) 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* The LANCE Rx and Tx ring descriptors. */ 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct lance_rx_head { 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned short base; /* Low word of base addr */ 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds volatile unsigned char flag; 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char base_hi; /* High word of base addr (unused) */ 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds short buf_length; /* This length is 2s complement! */ 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds volatile short msg_length; /* This length is "normal". */ 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct lance_tx_head { 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned short base; /* Low word of base addr */ 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds volatile unsigned char flag; 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char base_hi; /* High word of base addr (unused) */ 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds short length; /* Length is 2s complement! */ 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds volatile short misc; 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* The LANCE initialization block, described in databook. */ 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct lance_init_block { 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned short mode; /* Pre-set mode */ 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char hwaddr[6]; /* Physical ethernet address */ 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int filter[2]; /* Multicast filter (unused). */ 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Receive and transmit ring base, along with length bits. */ 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned short rdra; 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned short rlen; 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned short tdra; 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned short tlen; 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned short pad[4]; /* is thie needed? */ 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* The whole layout of the Lance shared memory */ 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct lance_memory { 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct lance_init_block init; 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct lance_tx_head tx_head[TX_RING_SIZE]; 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct lance_rx_head rx_head[RX_RING_SIZE]; 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char rx_data[RX_RING_SIZE][PKT_BUF_SZ]; 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char tx_data[TX_RING_SIZE][PKT_BUF_SZ]; 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* The driver's private device structure */ 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct lance_private { 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds volatile unsigned short *iobase; 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct lance_memory *mem; 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int new_rx, new_tx; /* The next free ring entry */ 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int old_tx, old_rx; /* ring entry to be processed */ 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct net_device_stats stats; 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* These two must be longs for set_bit() */ 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds long tx_full; 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds long lock; 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* I/O register access macros */ 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MEM lp->mem 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DREG lp->iobase[0] 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define AREG lp->iobase[1] 166e345d5ef6d476cc236f64d90d9528143a70745c8Al Viro#define REGA(a) (*( AREG = (a), &DREG )) 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Definitions for the Lance */ 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* tx_head flags */ 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TMD1_ENP 0x01 /* end of packet */ 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TMD1_STP 0x02 /* start of packet */ 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TMD1_DEF 0x04 /* deferred */ 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TMD1_ONE 0x08 /* one retry needed */ 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TMD1_MORE 0x10 /* more than one retry needed */ 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TMD1_ERR 0x40 /* error summary */ 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TMD1_OWN 0x80 /* ownership (set: chip owns) */ 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TMD1_OWN_CHIP TMD1_OWN 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TMD1_OWN_HOST 0 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* tx_head misc field */ 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TMD3_TDR 0x03FF /* Time Domain Reflectometry counter */ 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TMD3_RTRY 0x0400 /* failed after 16 retries */ 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TMD3_LCAR 0x0800 /* carrier lost */ 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TMD3_LCOL 0x1000 /* late collision */ 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TMD3_UFLO 0x4000 /* underflow (late memory) */ 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TMD3_BUFF 0x8000 /* buffering error (no ENP) */ 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* rx_head flags */ 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RMD1_ENP 0x01 /* end of packet */ 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RMD1_STP 0x02 /* start of packet */ 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RMD1_BUFF 0x04 /* buffer error */ 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RMD1_CRC 0x08 /* CRC error */ 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RMD1_OFLO 0x10 /* overflow */ 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RMD1_FRAM 0x20 /* framing error */ 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RMD1_ERR 0x40 /* error summary */ 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RMD1_OWN 0x80 /* ownership (set: ship owns) */ 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RMD1_OWN_CHIP RMD1_OWN 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RMD1_OWN_HOST 0 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* register names */ 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR0 0 /* mode/status */ 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR1 1 /* init block addr (low) */ 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR2 2 /* init block addr (high) */ 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR3 3 /* misc */ 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR8 8 /* address filter */ 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR15 15 /* promiscuous mode */ 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* CSR0 */ 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* (R=readable, W=writeable, S=set on write, C=clear on write) */ 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR0_INIT 0x0001 /* initialize (RS) */ 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR0_STRT 0x0002 /* start (RS) */ 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR0_STOP 0x0004 /* stop (RS) */ 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR0_TDMD 0x0008 /* transmit demand (RS) */ 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR0_TXON 0x0010 /* transmitter on (R) */ 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR0_RXON 0x0020 /* receiver on (R) */ 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR0_INEA 0x0040 /* interrupt enable (RW) */ 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR0_INTR 0x0080 /* interrupt active (R) */ 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR0_IDON 0x0100 /* initialization done (RC) */ 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR0_TINT 0x0200 /* transmitter interrupt (RC) */ 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR0_RINT 0x0400 /* receiver interrupt (RC) */ 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR0_MERR 0x0800 /* memory error (RC) */ 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR0_MISS 0x1000 /* missed frame (RC) */ 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR0_CERR 0x2000 /* carrier error (no heartbeat :-) (RC) */ 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR0_BABL 0x4000 /* babble: tx-ed too many bits (RC) */ 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR0_ERR 0x8000 /* error (RC) */ 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* CSR3 */ 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR3_BCON 0x0001 /* byte control */ 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR3_ACON 0x0002 /* ALE control */ 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR3_BSWP 0x0004 /* byte swap (1=big endian) */ 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/***************************** Prototypes *****************************/ 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int lance_probe( struct net_device *dev); 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int lance_open( struct net_device *dev ); 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void lance_init_ring( struct net_device *dev ); 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int lance_start_xmit( struct sk_buff *skb, struct net_device *dev ); 2417d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic irqreturn_t lance_interrupt( int irq, void *dev_id); 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int lance_rx( struct net_device *dev ); 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int lance_close( struct net_device *dev ); 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct net_device_stats *lance_get_stats( struct net_device *dev ); 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void set_multicast_list( struct net_device *dev ); 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/************************* End of Prototypes **************************/ 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct net_device * __init sun3lance_probe(int unit) 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct net_device *dev; 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds static int found; 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err = -ENODEV; 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* check that this machine has an onboard lance */ 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch(idprom->id_machtype) { 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case SM_SUN3|SM_3_50: 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case SM_SUN3|SM_3_60: 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case SM_SUN3X|SM_3_80: 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* these machines have lance */ 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ERR_PTR(-ENODEV); 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (found) 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ERR_PTR(-ENODEV); 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev = alloc_etherdev(sizeof(struct lance_private)); 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!dev) 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ERR_PTR(-ENOMEM); 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unit >= 0) { 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sprintf(dev->name, "eth%d", unit); 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netdev_boot_setup_check(dev); 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET_MODULE_OWNER(dev); 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!lance_probe(dev)) 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = register_netdev(dev); 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (err) 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out1; 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds found = 1; 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return dev; 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout1: 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_SUN3 290437111ca381263520d23c877e55e0a83558e79daAl Viro iounmap((void __iomem *)dev->base_addr); 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout: 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds free_netdev(dev); 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ERR_PTR(err); 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init lance_probe( struct net_device *dev) 2986aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik{ 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long ioaddr; 3006aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct lance_private *lp; 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds static int did_version; 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds volatile unsigned short *ioaddr_probe; 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned short tmp1, tmp2; 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_SUN3 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ioaddr = (unsigned long)ioremap(LANCE_OBIO, PAGE_SIZE); 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!ioaddr) 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ioaddr = SUN3X_LANCE; 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* test to see if there's really a lance here */ 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* (CSRO_INIT shouldn't be readable) */ 3176aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ioaddr_probe = (volatile unsigned short *)ioaddr; 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp1 = ioaddr_probe[0]; 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp2 = ioaddr_probe[1]; 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ioaddr_probe[1] = CSR0; 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ioaddr_probe[0] = CSR0_INIT | CSR0_STOP; 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(ioaddr_probe[0] != CSR0_STOP) { 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ioaddr_probe[0] = tmp1; 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ioaddr_probe[1] = tmp2; 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_SUN3 330437111ca381263520d23c877e55e0a83558e79daAl Viro iounmap((void __iomem *)ioaddr); 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp = netdev_priv(dev); 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* XXX - leak? */ 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM = dvma_malloc_align(sizeof(struct lance_memory), 0x10000); 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->iobase = (volatile unsigned short *)ioaddr; 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->base_addr = (unsigned long)ioaddr; /* informational only */ 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3436aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik REGA(CSR0) = CSR0_STOP; 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3451fb9df5d3069064c037c81c0ab8bf783ffa5e373Thomas Gleixner request_irq(LANCE_IRQ, lance_interrupt, IRQF_DISABLED, "SUN3 Lance", dev); 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->irq = (unsigned short)LANCE_IRQ; 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("%s: SUN3 Lance at io %#lx, mem %#lx, irq %d, hwaddr ", 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->name, 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (unsigned long)ioaddr, 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (unsigned long)MEM, 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->irq); 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* copy in the ethernet address from the prom */ 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for(i = 0; i < 6 ; i++) 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->dev_addr[i] = idprom->id_ethaddr[i]; 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* tell the card it's ether address, bytes swapped */ 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->init.hwaddr[0] = dev->dev_addr[1]; 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->init.hwaddr[1] = dev->dev_addr[0]; 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->init.hwaddr[2] = dev->dev_addr[3]; 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->init.hwaddr[3] = dev->dev_addr[2]; 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->init.hwaddr[4] = dev->dev_addr[5]; 3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->init.hwaddr[5] = dev->dev_addr[4]; 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for( i = 0; i < 6; ++i ) 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk( "%02x%s", dev->dev_addr[i], (i < 5) ? ":" : "\n" ); 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->init.mode = 0x0000; 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->init.filter[0] = 0x00000000; 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->init.filter[1] = 0x00000000; 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->init.rdra = dvma_vtob(MEM->rx_head); 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->init.rlen = (RX_LOG_RING_SIZE << 13) | 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (dvma_vtob(MEM->rx_head) >> 16); 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->init.tdra = dvma_vtob(MEM->tx_head); 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->init.tlen = (TX_LOG_RING_SIZE << 13) | 3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (dvma_vtob(MEM->tx_head) >> 16); 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK(2, ("initaddr: %08lx rx_ring: %08lx tx_ring: %08lx\n", 3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dvma_vtob(&(MEM->init)), dvma_vtob(MEM->rx_head), 3826aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik (dvma_vtob(MEM->tx_head)))); 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (did_version++ == 0) 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk( version ); 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* The LANCE-specific entries in the device structure. */ 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->open = &lance_open; 3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->hard_start_xmit = &lance_start_xmit; 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->stop = &lance_close; 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->get_stats = &lance_get_stats; 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->set_multicast_list = &set_multicast_list; 393a5d361fc24b75ea51e219367ee32c64422a2134fAl Viro dev->set_mac_address = NULL; 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds// KLUDGE -- REMOVE ME 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_bit(__LINK_STATE_PRESENT, &dev->state); 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset( &lp->stats, 0, sizeof(lp->stats) ); 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int lance_open( struct net_device *dev ) 4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct lance_private *lp = netdev_priv(dev); 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK( 2, ( "%s: lance_open()\n", dev->name )); 4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds REGA(CSR0) = CSR0_STOP; 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lance_init_ring(dev); 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* From now on, AREG is kept to point to CSR0 */ 4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds REGA(CSR0) = CSR0_INIT; 4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = 1000000; 4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (--i > 0) 4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (DREG & CSR0_IDON) 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (i < 0 || (DREG & CSR0_ERR)) { 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK( 2, ( "lance_open(): opening %s failed, i=%d, csr0=%04x\n", 4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->name, i, DREG )); 4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DREG = CSR0_STOP; 4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return( -EIO ); 4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DREG = CSR0_IDON | CSR0_STRT | CSR0_INEA; 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netif_start_queue(dev); 4316aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik 4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK( 2, ( "%s: LANCE is open, csr0 %04x\n", dev->name, DREG )); 4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return( 0 ); 4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Initialize the LANCE Rx and Tx rings. */ 4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void lance_init_ring( struct net_device *dev ) 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct lance_private *lp = netdev_priv(dev); 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->lock = 0; 4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->tx_full = 0; 4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->new_rx = lp->new_tx = 0; 4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->old_rx = lp->old_tx = 0; 4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for( i = 0; i < TX_RING_SIZE; i++ ) { 4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->tx_head[i].base = dvma_vtob(MEM->tx_data[i]); 4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->tx_head[i].flag = 0; 4536aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik MEM->tx_head[i].base_hi = 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (dvma_vtob(MEM->tx_data[i])) >>16; 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->tx_head[i].length = 0; 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->tx_head[i].misc = 0; 4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for( i = 0; i < RX_RING_SIZE; i++ ) { 4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->rx_head[i].base = dvma_vtob(MEM->rx_data[i]); 4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->rx_head[i].flag = RMD1_OWN_CHIP; 4626aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik MEM->rx_head[i].base_hi = 4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (dvma_vtob(MEM->rx_data[i])) >> 16; 4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->rx_head[i].buf_length = -PKT_BUF_SZ | 0xf000; 4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->rx_head[i].msg_length = 0; 4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* tell the card it's ether address, bytes swapped */ 4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->init.hwaddr[0] = dev->dev_addr[1]; 4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->init.hwaddr[1] = dev->dev_addr[0]; 4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->init.hwaddr[2] = dev->dev_addr[3]; 4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->init.hwaddr[3] = dev->dev_addr[2]; 4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->init.hwaddr[4] = dev->dev_addr[5]; 4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->init.hwaddr[5] = dev->dev_addr[4]; 4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->init.mode = 0x0000; 4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->init.filter[0] = 0x00000000; 4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->init.filter[1] = 0x00000000; 4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->init.rdra = dvma_vtob(MEM->rx_head); 4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->init.rlen = (RX_LOG_RING_SIZE << 13) | 4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (dvma_vtob(MEM->rx_head) >> 16); 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->init.tdra = dvma_vtob(MEM->tx_head); 4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->init.tlen = (TX_LOG_RING_SIZE << 13) | 4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (dvma_vtob(MEM->tx_head) >> 16); 4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* tell the lance the address of its init block */ 4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds REGA(CSR1) = dvma_vtob(&(MEM->init)); 4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds REGA(CSR2) = dvma_vtob(&(MEM->init)) >> 16; 4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_SUN3X 4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds REGA(CSR3) = CSR3_BSWP | CSR3_ACON | CSR3_BCON; 4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds REGA(CSR3) = CSR3_BSWP; 4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int lance_start_xmit( struct sk_buff *skb, struct net_device *dev ) 5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct lance_private *lp = netdev_priv(dev); 5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int entry, len; 5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct lance_tx_head *head; 5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK( 1, ( "%s: transmit start.\n", 5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->name)); 5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Transmitter timeout, serious problems. */ 5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (netif_queue_stopped(dev)) { 5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int tickssofar = jiffies - dev->trans_start; 5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (tickssofar < 20) 5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return( 1 ); 5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK( 1, ( "%s: transmit timed out, status %04x, resetting.\n", 5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->name, DREG )); 5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DREG = CSR0_STOP; 5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Always set BSWP after a STOP as STOP puts it back into 5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * little endian mode. 5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds REGA(CSR3) = CSR3_BSWP; 5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->stats.tx_errors++; 5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(lance_debug >= 2) { 5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("Ring data: old_tx %d new_tx %d%s new_rx %d\n", 5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->old_tx, lp->new_tx, 5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->tx_full ? " (full)" : "", 5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->new_rx ); 5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for( i = 0 ; i < RX_RING_SIZE; i++ ) 5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk( "rx #%d: base=%04x blen=%04x mlen=%04x\n", 5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i, MEM->rx_head[i].base, 5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds -MEM->rx_head[i].buf_length, 5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->rx_head[i].msg_length); 5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for( i = 0 ; i < TX_RING_SIZE; i++ ) 5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("tx #%d: base=%04x len=%04x misc=%04x\n", 5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i, MEM->tx_head[i].base, 5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds -MEM->tx_head[i].length, 5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->tx_head[i].misc ); 5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lance_init_ring(dev); 5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds REGA( CSR0 ) = CSR0_INEA | CSR0_INIT | CSR0_STRT; 5466aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik 5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netif_start_queue(dev); 5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->trans_start = jiffies; 5496aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik 5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5536aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik 5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Block a timer-based transmit from overlapping. This could better be 5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */ 5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Block a timer-based transmit from overlapping with us by 5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stopping the queue for a bit... */ 5596aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik 5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netif_stop_queue(dev); 5616aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik 5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (test_and_set_bit( 0, (void*)&lp->lock ) != 0) { 5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk( "%s: tx queue lock!.\n", dev->name); 5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* don't clear dev->tbusy flag. */ 5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds AREG = CSR0; 5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK( 2, ( "%s: lance_start_xmit() called, csr0 %4.4x.\n", 5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->name, DREG )); 5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_SUN3X 5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* this weirdness doesn't appear on sun3... */ 5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(!(DREG & CSR0_INIT)) { 5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK( 1, ("INIT not set, reinitializing...\n")); 5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds REGA( CSR0 ) = CSR0_STOP; 5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lance_init_ring(dev); 5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds REGA( CSR0 ) = CSR0_INIT | CSR0_STRT; 5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Fill in a Tx ring entry */ 5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if 0 5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (lance_debug >= 2) { 5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_char *p; 5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk( "%s: TX pkt %d type 0x%04x from ", dev->name, 5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->new_tx, ((u_short *)skb->data)[6]); 5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for( p = &((u_char *)skb->data)[6], i = 0; i < 6; i++ ) 5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("%02x%s", *p++, i != 5 ? ":" : "" ); 5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(" to "); 5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for( p = (u_char *)skb->data, i = 0; i < 6; i++ ) 5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("%02x%s", *p++, i != 5 ? ":" : "" ); 5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(" data at 0x%08x len %d\n", (int)skb->data, 5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (int)skb->len ); 5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5976aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik#endif 5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* We're not prepared for the int until the last flags are set/reset. 5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * And the int may happen already after setting the OWN_CHIP... */ 6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds local_irq_save(flags); 6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Mask to ring buffer boundary. */ 6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds entry = lp->new_tx; 6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds head = &(MEM->tx_head[entry]); 6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Caution: the write order is important here, set the "ownership" bits 6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * last. 6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* the sun3's lance needs it's buffer padded to the minimum 6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds size */ 6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN; 6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds// head->length = -len; 6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds head->length = (-len) | 0xf000; 6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds head->misc = 0; 6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memcpy( PKTBUF_ADDR(head), (void *)skb->data, skb->len ); 6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (len != skb->len) 6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset(PKTBUF_ADDR(head) + skb->len, 0, len-skb->len); 6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds head->flag = TMD1_OWN_CHIP | TMD1_ENP | TMD1_STP; 6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->new_tx = (lp->new_tx + 1) & TX_RING_MOD_MASK; 6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->stats.tx_bytes += skb->len; 6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Trigger an immediate send poll. */ 6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds REGA(CSR0) = CSR0_INEA | CSR0_TDMD | CSR0_STRT; 6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds AREG = CSR0; 6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK( 2, ( "%s: lance_start_xmit() exiting, csr0 %4.4x.\n", 6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->name, DREG )); 6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->trans_start = jiffies; 6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_kfree_skb( skb ); 6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->lock = 0; 6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((MEM->tx_head[(entry+1) & TX_RING_MOD_MASK].flag & TMD1_OWN) == 6366aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik TMD1_OWN_HOST) 6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netif_start_queue(dev); 6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds local_irq_restore(flags); 6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* The LANCE interrupt handler. */ 6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6467d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic irqreturn_t lance_interrupt( int irq, void *dev_id) 6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct net_device *dev = dev_id; 6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct lance_private *lp = netdev_priv(dev); 6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int csr0; 6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds static int in_interrupt; 6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev == NULL) { 6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK( 1, ( "lance_interrupt(): invalid dev_id\n" )); 6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return IRQ_NONE; 6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (in_interrupt) 6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK( 2, ( "%s: Re-entering the interrupt handler.\n", dev->name )); 6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds in_interrupt = 1; 6616aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik 6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds still_more: 6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds flush_cache_all(); 6646aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik 6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds AREG = CSR0; 6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds csr0 = DREG; 6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* ack interrupts */ 6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DREG = csr0 & (CSR0_TINT | CSR0_RINT | CSR0_IDON); 6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* clear errors */ 6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(csr0 & CSR0_ERR) 6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DREG = CSR0_BABL | CSR0_MERR | CSR0_CERR | CSR0_MISS; 6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK( 2, ( "%s: interrupt csr0=%04x new csr=%04x.\n", 6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->name, csr0, DREG )); 6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (csr0 & CSR0_TINT) { /* Tx-done interrupt */ 6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int old_tx = lp->old_tx; 6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds// if(lance_debug >= 3) { 6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds// int i; 6846aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik// 6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds// printk("%s: tx int\n", dev->name); 6866aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik// 6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds// for(i = 0; i < TX_RING_SIZE; i++) 6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds// printk("ring %d flag=%04x\n", i, 6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds// MEM->tx_head[i].flag); 6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds// } 6916aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik 6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while( old_tx != lp->new_tx) { 6936aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik struct lance_tx_head *head = &(MEM->tx_head[old_tx]); 6946aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik 6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK(3, ("on tx_ring %d\n", old_tx)); 6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (head->flag & TMD1_OWN_CHIP) 6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; /* It still hasn't been Txed */ 6996aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik 7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (head->flag & TMD1_ERR) { 7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int status = head->misc; 7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->stats.tx_errors++; 7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status & TMD3_RTRY) lp->stats.tx_aborted_errors++; 7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status & TMD3_LCAR) lp->stats.tx_carrier_errors++; 7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status & TMD3_LCOL) lp->stats.tx_window_errors++; 7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status & (TMD3_UFLO | TMD3_BUFF)) { 7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->stats.tx_fifo_errors++; 7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("%s: Tx FIFO error\n", 7096aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik dev->name); 7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds REGA(CSR0) = CSR0_STOP; 7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds REGA(CSR3) = CSR3_BSWP; 7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lance_init_ring(dev); 7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds REGA(CSR0) = CSR0_STRT | CSR0_INEA; 7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return IRQ_HANDLED; 7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if(head->flag & (TMD1_ENP | TMD1_STP)) { 7176aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik 7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds head->flag &= ~(TMD1_ENP | TMD1_STP); 7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(head->flag & (TMD1_ONE | TMD1_MORE)) 7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->stats.collisions++; 7216aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik 7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->stats.tx_packets++; 7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK(3, ("cleared tx ring %d\n", old_tx)); 7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds old_tx = (old_tx +1) & TX_RING_MOD_MASK; 7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->old_tx = old_tx; 7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (netif_queue_stopped(dev)) { 7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* The ring is no longer full, clear tbusy. */ 7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netif_start_queue(dev); 7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netif_wake_queue(dev); 7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (csr0 & CSR0_RINT) /* Rx interrupt */ 7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lance_rx( dev ); 7406aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik 7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Log misc errors. */ 7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (csr0 & CSR0_BABL) lp->stats.tx_errors++; /* Tx babble. */ 7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (csr0 & CSR0_MISS) lp->stats.rx_errors++; /* Missed a Rx frame. */ 7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (csr0 & CSR0_MERR) { 7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK( 1, ( "%s: Bus master arbitration failure (?!?), " 7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "status %04x.\n", dev->name, csr0 )); 7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Restart the chip. */ 7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds REGA(CSR0) = CSR0_STOP; 7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds REGA(CSR3) = CSR3_BSWP; 7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lance_init_ring(dev); 7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds REGA(CSR0) = CSR0_STRT | CSR0_INEA; 7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Clear any other interrupt, and set interrupt enable. */ 7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds// DREG = CSR0_BABL | CSR0_CERR | CSR0_MISS | CSR0_MERR | 7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds// CSR0_IDON | CSR0_INEA; 7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds REGA(CSR0) = CSR0_INEA; 7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(DREG & (CSR0_RINT | CSR0_TINT)) { 7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK(2, ("restarting interrupt, csr0=%#04x\n", DREG)); 7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto still_more; 7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK( 2, ( "%s: exiting interrupt, csr0=%#04x.\n", 7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->name, DREG )); 7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds in_interrupt = 0; 7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return IRQ_HANDLED; 7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* get packet, toss into skbuff */ 7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int lance_rx( struct net_device *dev ) 7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct lance_private *lp = netdev_priv(dev); 7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int entry = lp->new_rx; 7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* If we own the next entry, it's a new packet. Send it up. */ 7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while( (MEM->rx_head[entry].flag & RMD1_OWN) == RMD1_OWN_HOST ) { 7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct lance_rx_head *head = &(MEM->rx_head[entry]); 7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int status = head->flag; 7826aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik 7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status != (RMD1_ENP|RMD1_STP)) { /* There was an error. */ 7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* There is a tricky error noted by John Murphy, 7856aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik <murf@perftech.com> to Russ Nelson: Even with 7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds full-sized buffers it's possible for a jabber packet to use two 7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buffers, with only the last correctly noting the error. */ 7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status & RMD1_ENP) /* Only count a general error at the */ 7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->stats.rx_errors++; /* end of a packet.*/ 7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status & RMD1_FRAM) lp->stats.rx_frame_errors++; 7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status & RMD1_OFLO) lp->stats.rx_over_errors++; 7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status & RMD1_CRC) lp->stats.rx_crc_errors++; 7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status & RMD1_BUFF) lp->stats.rx_fifo_errors++; 7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds head->flag &= (RMD1_ENP|RMD1_STP); 7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Malloc up new buffer, compatible with net-3. */ 7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds// short pkt_len = head->msg_length;// & 0xfff; 7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds short pkt_len = (head->msg_length & 0xfff) - 4; 7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sk_buff *skb; 8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (pkt_len < 60) { 8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk( "%s: Runt packet!\n", dev->name ); 8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->stats.rx_errors++; 8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else { 8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb = dev_alloc_skb( pkt_len+2 ); 8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (skb == NULL) { 8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK( 1, ( "%s: Memory squeeze, deferring packet.\n", 8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->name )); 8106aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik 8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->stats.rx_dropped++; 8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds head->msg_length = 0; 8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds head->flag |= RMD1_OWN_CHIP; 8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->new_rx = (lp->new_rx+1) & 8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds RX_RING_MOD_MASK; 8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if 0 8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (lance_debug >= 3) { 8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_char *data = PKTBUF_ADDR(head), *p; 8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk( "%s: RX pkt %d type 0x%04x from ", dev->name, entry, ((u_short *)data)[6]); 8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for( p = &data[6], i = 0; i < 6; i++ ) 8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("%02x%s", *p++, i != 5 ? ":" : "" ); 8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(" to "); 8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for( p = data, i = 0; i < 6; i++ ) 8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("%02x%s", *p++, i != 5 ? ":" : "" ); 8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(" data %02x %02x %02x %02x %02x %02x %02x %02x " 8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "len %d at %08x\n", 8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data[15], data[16], data[17], data[18], 8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data[19], data[20], data[21], data[22], 8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pkt_len, data); 8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (lance_debug >= 3) { 8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_char *data = PKTBUF_ADDR(head); 8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk( "%s: RX pkt %d type 0x%04x len %d\n ", dev->name, entry, ((u_short *)data)[6], pkt_len); 8376aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik } 8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb->dev = dev; 8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb_reserve( skb, 2 ); /* 16 byte align */ 8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb_put( skb, pkt_len ); /* Make room */ 8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds// memcpy( skb->data, PKTBUF_ADDR(head), pkt_len ); 8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds eth_copy_and_sum(skb, 8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds PKTBUF_ADDR(head), 8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pkt_len, 0); 8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb->protocol = eth_type_trans( skb, dev ); 8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netif_rx( skb ); 8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->last_rx = jiffies; 8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->stats.rx_packets++; 8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->stats.rx_bytes += pkt_len; 8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds// head->buf_length = -PKT_BUF_SZ | 0xf000; 8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds head->msg_length = 0; 8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds head->flag = RMD1_OWN_CHIP; 8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds entry = lp->new_rx = (lp->new_rx +1) & RX_RING_MOD_MASK; 8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* From lance.c (Donald Becker): */ 8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* We should check that at least two ring entries are free. 8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds If not, we should free one and mark stats->rx_dropped++. */ 8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int lance_close( struct net_device *dev ) 8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct lance_private *lp = netdev_priv(dev); 8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netif_stop_queue(dev); 8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds AREG = CSR0; 8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK( 2, ( "%s: Shutting down ethercard, status was %2.2x.\n", 8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->name, DREG )); 8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* We stop the LANCE here -- it occasionally polls 8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memory if we don't. */ 8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DREG = CSR0_STOP; 8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct net_device_stats *lance_get_stats( struct net_device *dev ) 8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct lance_private *lp = netdev_priv(dev); 8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return &lp->stats; 8941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Set or clear the multicast filter for this adaptor. 8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds num_addrs == -1 Promiscuous mode, receive all packets 8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds num_addrs == 0 Normal mode, clear multicast list 9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds num_addrs > 0 Multicast mode, receive normal and MC packets, and do 9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds best-effort filtering. 9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 9031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* completely untested on a sun3 */ 9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void set_multicast_list( struct net_device *dev ) 9061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 9071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct lance_private *lp = netdev_priv(dev); 9081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(netif_queue_stopped(dev)) 9101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Only possible if board is already started */ 9111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 9121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* We take the simple way out and always enable promiscuous mode. */ 9141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DREG = CSR0_STOP; /* Temporarily stop the lance. */ 9151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev->flags & IFF_PROMISC) { 9171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Log any net taps. */ 918d5b20697ca37d80cc4ec2ba3c5ddf1339dc1d49aAndy Gospodarek DPRINTK( 3, ( "%s: Promiscuous mode enabled.\n", dev->name )); 9191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds REGA( CSR15 ) = 0x8000; /* Set promiscuous mode */ 9201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 9211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds short multicast_table[4]; 9221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int num_addrs = dev->mc_count; 9231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* We don't use the multicast table, but rely on upper-layer 9251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * filtering. */ 9261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset( multicast_table, (num_addrs == 0) ? 0 : -1, 9271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof(multicast_table) ); 9281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for( i = 0; i < 4; i++ ) 9291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds REGA( CSR8+i ) = multicast_table[i]; 9301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds REGA( CSR15 ) = 0; /* Unset promiscuous mode */ 9311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 9341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Always set BSWP after a STOP as STOP puts it back into 9351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * little endian mode. 9361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 9371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds REGA( CSR3 ) = CSR3_BSWP; 9381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Resume normal operation and reset AREG to CSR0 */ 9401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds REGA( CSR0 ) = CSR0_IDON | CSR0_INEA | CSR0_STRT; 9411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef MODULE 9451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct net_device *sun3lance_dev; 9471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 948afc8eb46c0ea2cab8bc28713b2e0614f015a7516Al Viroint __init init_module(void) 9491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 9501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sun3lance_dev = sun3lance_probe(-1); 9511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (IS_ERR(sun3lance_dev)) 9521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return PTR_ERR(sun3lance_dev); 9531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 9541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 956afc8eb46c0ea2cab8bc28713b2e0614f015a7516Al Virovoid __exit cleanup_module(void) 9571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 9581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unregister_netdev(sun3lance_dev); 9591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_SUN3 960437111ca381263520d23c877e55e0a83558e79daAl Viro iounmap((void __iomem *)sun3lance_dev->base_addr); 9611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 9621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds free_netdev(sun3lance_dev); 9631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif /* MODULE */ 9661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 967