atarilance.c revision 6ed106549d17474ca17a16057f4c0ed4eba5a7ca
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* atarilance.c: Ethernet driver for VME Lance cards on the Atari */ 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Written 1995/96 by Roman Hodek (Roman.Hodek@informatik.uni-erlangen.de) 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds This software may be used and distributed according to the terms 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds of the GNU General Public License, incorporated herein by reference. 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds This drivers was written with the following sources of reference: 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds - The driver for the Riebl Lance card by the TU Vienna. 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds - The modified TUW driver for PAM's VME cards 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds - The PC-Linux driver for Lance cards (but this is for bus master 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cards, not the shared memory ones) 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds - The Amiga Ariadne driver 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds v1.0: (in 1.2.13pl4/0.9.13) 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Initial version 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds v1.1: (in 1.2.13pl5) 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds more comments 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds deleted some debugging stuff 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds optimized register access (keep AREG pointing to CSR0) 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds following AMD, CSR0_STRT should be set only after IDON is detected 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds use memcpy() for data transfers, that also employs long word moves 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds better probe procedure for 24-bit systems 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds non-VME-RieblCards need extra delays in memcpy 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds must also do write test, since 0xfxe00000 may hit ROM 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds use 8/32 tx/rx buffers, which should give better NFS performance; 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds this is made possible by shifting the last packet buffer after the 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds RieblCard reserved area 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds v1.2: (in 1.2.13pl8) 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds again fixed probing for the Falcon; 0xfe01000 hits phys. 0x00010000 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds and thus RAM, in case of no Lance found all memory contents have to 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds be restored! 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Now possible to compile as module. 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds v1.3: 03/30/96 Jes Sorensen, Roman (in 1.3) 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Several little 1.3 adaptions 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds When the lance is stopped it jumps back into little-endian 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mode. It is therefore necessary to put it back where it 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds belongs, in big endian mode, in order to make things work. 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds This might be the reason why multicast-mode didn't work 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds before, but I'm not able to test it as I only got an Amiga 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (we had similar problems with the A2065 driver). 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/ 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic char version[] = "atarilance.c: v1.3 04/04/96 " 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Roman.Hodek@informatik.uni-erlangen.de\n"; 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/netdevice.h> 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/etherdevice.h> 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/stddef.h> 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/string.h> 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h> 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/skbuff.h> 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/slab.h> 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/interrupt.h> 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/bitops.h> 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/setup.h> 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/irq.h> 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/atarihw.h> 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/atariints.h> 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/io.h> 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Debug level: 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 0 = silent, print only serious errors 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1 = normal, print error messages 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2 = debug, print debug infos 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 3 = debug, print even more debug infos (packet data) 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LANCE_DEBUG 1 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef LANCE_DEBUG 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int lance_debug = LANCE_DEBUG; 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int lance_debug = 1; 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 818d3b33f67fdc0fb364a1ef6d8fbbea7c2e4e6c98Rusty Russellmodule_param(lance_debug, int, 0); 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(lance_debug, "atarilance debug level (0-3)"); 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Print debug messages on probing? */ 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef LANCE_DEBUG_PROBE 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DPRINTK(n,a) \ 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do { \ 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (lance_debug >= n) \ 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk a; \ 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } while( 0 ) 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef LANCE_DEBUG_PROBE 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds# define PROBE_PRINT(a) printk a 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds# define PROBE_PRINT(a) 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* These define the number of Rx and Tx buffers as log2. (Only powers 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * of two are valid) 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Much more rx buffers (32) are reserved than tx buffers (8), since receiving 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * is more time critical then sending and packets may have to remain in the 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * board's memory when main memory is low. 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TX_LOG_RING_SIZE 3 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RX_LOG_RING_SIZE 5 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* These are the derived values */ 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TX_RING_SIZE (1 << TX_LOG_RING_SIZE) 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TX_RING_LEN_BITS (TX_LOG_RING_SIZE << 5) 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TX_RING_MOD_MASK (TX_RING_SIZE - 1) 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RX_RING_SIZE (1 << RX_LOG_RING_SIZE) 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RX_RING_LEN_BITS (RX_LOG_RING_SIZE << 5) 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RX_RING_MOD_MASK (RX_RING_SIZE - 1) 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TX_TIMEOUT 20 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* The LANCE Rx and Tx ring descriptors. */ 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct lance_rx_head { 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned short base; /* Low word of base addr */ 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds volatile unsigned char flag; 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char base_hi; /* High word of base addr (unused) */ 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds short buf_length; /* This length is 2s complement! */ 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds volatile short msg_length; /* This length is "normal". */ 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct lance_tx_head { 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned short base; /* Low word of base addr */ 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds volatile unsigned char flag; 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char base_hi; /* High word of base addr (unused) */ 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds short length; /* Length is 2s complement! */ 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds volatile short misc; 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct ringdesc { 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned short adr_lo; /* Low 16 bits of address */ 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char len; /* Length bits */ 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char adr_hi; /* High 8 bits of address (unused) */ 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* The LANCE initialization block, described in databook. */ 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct lance_init_block { 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned short mode; /* Pre-set mode */ 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char hwaddr[6]; /* Physical ethernet address */ 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned filter[2]; /* Multicast filter (unused). */ 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Receive and transmit ring base, along with length bits. */ 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ringdesc rx_ring; 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ringdesc tx_ring; 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* The whole layout of the Lance shared memory */ 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct lance_memory { 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct lance_init_block init; 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct lance_tx_head tx_head[TX_RING_SIZE]; 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct lance_rx_head rx_head[RX_RING_SIZE]; 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char packet_area[0]; /* packet data follow after the 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * init block and the ring 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * descriptors and are located 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * at runtime */ 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* RieblCard specifics: 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The original TOS driver for these cards reserves the area from offset 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 0xee70 to 0xeebb for storing configuration data. Of interest to us is the 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Ethernet address there, and the magic for verifying the data's validity. 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The reserved area isn't touch by packet buffers. Furthermore, offset 0xfffe 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * is reserved for the interrupt vector number. 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RIEBL_RSVD_START 0xee70 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RIEBL_RSVD_END 0xeec0 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RIEBL_MAGIC 0x09051990 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RIEBL_MAGIC_ADDR ((unsigned long *)(((char *)MEM) + 0xee8a)) 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RIEBL_HWADDR_ADDR ((unsigned char *)(((char *)MEM) + 0xee8e)) 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RIEBL_IVEC_ADDR ((unsigned short *)(((char *)MEM) + 0xfffe)) 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* This is a default address for the old RieblCards without a battery 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * that have no ethernet address at boot time. 00:00:36:04 is the 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * prefix for Riebl cards, the 00:00 at the end is arbitrary. 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned char OldRieblDefHwaddr[6] = { 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0x00, 0x00, 0x36, 0x04, 0x00, 0x00 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* I/O registers of the Lance chip */ 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct lance_ioreg { 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* base+0x0 */ volatile unsigned short data; 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* base+0x2 */ volatile unsigned short addr; 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char _dummy1[3]; 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* base+0x7 */ volatile unsigned char ivec; 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char _dummy2[5]; 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* base+0xd */ volatile unsigned char eeprom; 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char _dummy3; 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* base+0xf */ volatile unsigned char mem; 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Types of boards this driver supports */ 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsenum lance_type { 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OLD_RIEBL, /* old Riebl card without battery */ 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds NEW_RIEBL, /* new Riebl card with battery */ 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds PAM_CARD /* PAM card with EEPROM */ 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic char *lance_names[] = { 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Riebl-Card (without battery)", 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Riebl-Card (with battery)", 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "PAM intern card" 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* The driver's private device structure */ 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct lance_private { 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds enum lance_type cardtype; 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct lance_ioreg *iobase; 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct lance_memory *mem; 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int cur_rx, cur_tx; /* The next free ring entry */ 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int dirty_tx; /* Ring entries to be freed. */ 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* copy function */ 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void *(*memcpy_f)( void *, const void *, size_t ); 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* This must be long for set_bit() */ 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds long tx_full; 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spinlock_t devlock; 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* I/O register access macros */ 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MEM lp->mem 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DREG IO->data 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define AREG IO->addr 237e345d5ef6d476cc236f64d90d9528143a70745c8Al Viro#define REGA(a) (*( AREG = (a), &DREG )) 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Definitions for packet buffer access: */ 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PKT_BUF_SZ 1544 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Get the address of a packet buffer corresponding to a given buffer head */ 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PKTBUF_ADDR(head) (((unsigned char *)(MEM)) + (head)->base) 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Possible memory/IO addresses for probing */ 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2463cacd2a1ce5464b9874508927d561c0dfce74637Adrian Bunkstatic struct lance_addr { 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long memaddr; 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long ioaddr; 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int slow_flag; 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} lance_addr_list[] = { 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 0xfe010000, 0xfe00fff0, 0 }, /* RieblCard VME in TT */ 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 0xffc10000, 0xffc0fff0, 0 }, /* RieblCard VME in MegaSTE 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (highest byte stripped) */ 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 0xffe00000, 0xffff7000, 1 }, /* RieblCard in ST 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (highest byte stripped) */ 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 0xffd00000, 0xffff7000, 1 }, /* RieblCard in ST with hw modif. to 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds avoid conflict with ROM 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (highest byte stripped) */ 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 0xffcf0000, 0xffcffff0, 0 }, /* PAMCard VME in TT and MSTE 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (highest byte stripped) */ 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 0xfecf0000, 0xfecffff0, 0 }, /* Rhotron's PAMCard VME in TT and MSTE 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (highest byte stripped) */ 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 265ff8ac60948ba819b89e9c87083e8050fc2f89999Denis Cheng#define N_LANCE_ADDR ARRAY_SIZE(lance_addr_list) 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Definitions for the Lance */ 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* tx_head flags */ 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TMD1_ENP 0x01 /* end of packet */ 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TMD1_STP 0x02 /* start of packet */ 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TMD1_DEF 0x04 /* deferred */ 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TMD1_ONE 0x08 /* one retry needed */ 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TMD1_MORE 0x10 /* more than one retry needed */ 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TMD1_ERR 0x40 /* error summary */ 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TMD1_OWN 0x80 /* ownership (set: chip owns) */ 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TMD1_OWN_CHIP TMD1_OWN 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TMD1_OWN_HOST 0 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* tx_head misc field */ 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TMD3_TDR 0x03FF /* Time Domain Reflectometry counter */ 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TMD3_RTRY 0x0400 /* failed after 16 retries */ 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TMD3_LCAR 0x0800 /* carrier lost */ 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TMD3_LCOL 0x1000 /* late collision */ 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TMD3_UFLO 0x4000 /* underflow (late memory) */ 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TMD3_BUFF 0x8000 /* buffering error (no ENP) */ 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* rx_head flags */ 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RMD1_ENP 0x01 /* end of packet */ 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RMD1_STP 0x02 /* start of packet */ 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RMD1_BUFF 0x04 /* buffer error */ 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RMD1_CRC 0x08 /* CRC error */ 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RMD1_OFLO 0x10 /* overflow */ 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RMD1_FRAM 0x20 /* framing error */ 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RMD1_ERR 0x40 /* error summary */ 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RMD1_OWN 0x80 /* ownership (set: ship owns) */ 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RMD1_OWN_CHIP RMD1_OWN 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RMD1_OWN_HOST 0 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* register names */ 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR0 0 /* mode/status */ 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR1 1 /* init block addr (low) */ 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR2 2 /* init block addr (high) */ 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR3 3 /* misc */ 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR8 8 /* address filter */ 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR15 15 /* promiscuous mode */ 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* CSR0 */ 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* (R=readable, W=writeable, S=set on write, C=clear on write) */ 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR0_INIT 0x0001 /* initialize (RS) */ 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR0_STRT 0x0002 /* start (RS) */ 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR0_STOP 0x0004 /* stop (RS) */ 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR0_TDMD 0x0008 /* transmit demand (RS) */ 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR0_TXON 0x0010 /* transmitter on (R) */ 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR0_RXON 0x0020 /* receiver on (R) */ 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR0_INEA 0x0040 /* interrupt enable (RW) */ 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR0_INTR 0x0080 /* interrupt active (R) */ 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR0_IDON 0x0100 /* initialization done (RC) */ 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR0_TINT 0x0200 /* transmitter interrupt (RC) */ 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR0_RINT 0x0400 /* receiver interrupt (RC) */ 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR0_MERR 0x0800 /* memory error (RC) */ 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR0_MISS 0x1000 /* missed frame (RC) */ 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR0_CERR 0x2000 /* carrier error (no heartbeat :-) (RC) */ 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR0_BABL 0x4000 /* babble: tx-ed too many bits (RC) */ 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR0_ERR 0x8000 /* error (RC) */ 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* CSR3 */ 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR3_BCON 0x0001 /* byte control */ 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR3_ACON 0x0002 /* ALE control */ 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR3_BSWP 0x0004 /* byte swap (1=big endian) */ 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/***************************** Prototypes *****************************/ 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned long lance_probe1( struct net_device *dev, struct lance_addr 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *init_rec ); 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int lance_open( struct net_device *dev ); 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void lance_init_ring( struct net_device *dev ); 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int lance_start_xmit( struct sk_buff *skb, struct net_device *dev ); 3447d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic irqreturn_t lance_interrupt( int irq, void *dev_id ); 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int lance_rx( struct net_device *dev ); 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int lance_close( struct net_device *dev ); 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void set_multicast_list( struct net_device *dev ); 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int lance_set_mac_address( struct net_device *dev, void *addr ); 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void lance_tx_timeout (struct net_device *dev); 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/************************* End of Prototypes **************************/ 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3556aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void *slow_memcpy( void *dst, const void *src, size_t len ) 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ char *cto = dst; 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds const char *cfrom = src; 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while( len-- ) { 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *cto++ = *cfrom++; 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MFPDELAY(); 3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return( dst ); 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct net_device * __init atarilance_probe(int unit) 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds static int found; 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct net_device *dev; 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err = -ENODEV; 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!MACH_IS_ATARI || found) 3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Assume there's only one board possible... That seems true, since 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the Riebl/PAM board's address cannot be changed. */ 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ERR_PTR(-ENODEV); 3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev = alloc_etherdev(sizeof(struct lance_private)); 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!dev) 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ERR_PTR(-ENOMEM); 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unit >= 0) { 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sprintf(dev->name, "eth%d", unit); 3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netdev_boot_setup_check(dev); 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for( i = 0; i < N_LANCE_ADDR; ++i ) { 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (lance_probe1( dev, &lance_addr_list[i] )) { 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds found = 1; 3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = register_netdev(dev); 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!err) 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return dev; 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds free_irq(dev->irq, dev); 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds free_netdev(dev); 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ERR_PTR(err); 4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Derived from hwreg_present() in atari/config.c: */ 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 407f37c768c39e3aeb8a508e1a45e461a506771445eAdrian Bunkstatic noinline int __init addr_accessible(volatile void *regp, int wordflag, 408f37c768c39e3aeb8a508e1a45e461a506771445eAdrian Bunk int writeflag) 4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret; 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds long flags; 4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds long *vbr, save_berr; 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds local_irq_save(flags); 4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __asm__ __volatile__ ( "movec %/vbr,%0" : "=r" (vbr) : ); 4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds save_berr = vbr[2]; 4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __asm__ __volatile__ 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ( "movel %/sp,%/d1\n\t" 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "movel #Lberr,%2@\n\t" 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "moveq #0,%0\n\t" 4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "tstl %3\n\t" 4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "bne 1f\n\t" 4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "moveb %1@,%/d0\n\t" 4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "nop \n\t" 4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "bra 2f\n" 4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds"1: movew %1@,%/d0\n\t" 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "nop \n" 4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds"2: tstl %4\n\t" 4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "beq 2f\n\t" 4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "tstl %3\n\t" 4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "bne 1f\n\t" 4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "clrb %1@\n\t" 4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "nop \n\t" 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "moveb %/d0,%1@\n\t" 4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "nop \n\t" 4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "bra 2f\n" 4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds"1: clrw %1@\n\t" 4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "nop \n\t" 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "movew %/d0,%1@\n\t" 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "nop \n" 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds"2: moveq #1,%0\n" 4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds"Lberr: movel %/d1,%/sp" 4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds : "=&d" (ret) 4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds : "a" (regp), "a" (&vbr[2]), "rm" (wordflag), "rm" (writeflag) 4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds : "d0", "d1", "memory" 4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ); 4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vbr[2] = save_berr; 4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds local_irq_restore(flags); 4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return( ret ); 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4568e7678fe0992a6107041b839b08ac4af55d41592Alexander Beregalovstatic const struct net_device_ops lance_netdev_ops = { 4578e7678fe0992a6107041b839b08ac4af55d41592Alexander Beregalov .ndo_open = lance_open, 4588e7678fe0992a6107041b839b08ac4af55d41592Alexander Beregalov .ndo_stop = lance_close, 4598e7678fe0992a6107041b839b08ac4af55d41592Alexander Beregalov .ndo_start_xmit = lance_start_xmit, 4608e7678fe0992a6107041b839b08ac4af55d41592Alexander Beregalov .ndo_set_multicast_list = set_multicast_list, 4618e7678fe0992a6107041b839b08ac4af55d41592Alexander Beregalov .ndo_set_mac_address = lance_set_mac_address, 4628e7678fe0992a6107041b839b08ac4af55d41592Alexander Beregalov .ndo_tx_timeout = lance_tx_timeout, 4638e7678fe0992a6107041b839b08ac4af55d41592Alexander Beregalov .ndo_validate_addr = eth_validate_addr, 4648e7678fe0992a6107041b839b08ac4af55d41592Alexander Beregalov .ndo_change_mtu = eth_change_mtu, 4658e7678fe0992a6107041b839b08ac4af55d41592Alexander Beregalov}; 4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned long __init lance_probe1( struct net_device *dev, 4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct lance_addr *init_rec ) 4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds volatile unsigned short *memaddr = 4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (volatile unsigned short *)init_rec->memaddr; 4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds volatile unsigned short *ioaddr = 4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (volatile unsigned short *)init_rec->ioaddr; 4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct lance_private *lp; 4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct lance_ioreg *IO; 4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds static int did_version; 4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned short save1, save2; 4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds PROBE_PRINT(( "Probing for Lance card at mem %#lx io %#lx\n", 4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (long)memaddr, (long)ioaddr )); 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Test whether memory readable and writable */ 4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds PROBE_PRINT(( "lance_probe1: testing memory to be accessible\n" )); 4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!addr_accessible( memaddr, 1, 1 )) goto probe_fail; 4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Written values should come back... */ 4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds PROBE_PRINT(( "lance_probe1: testing memory to be writable (1)\n" )); 4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds save1 = *memaddr; 4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *memaddr = 0x0001; 4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (*memaddr != 0x0001) goto probe_fail; 4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds PROBE_PRINT(( "lance_probe1: testing memory to be writable (2)\n" )); 4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *memaddr = 0x0000; 4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (*memaddr != 0x0000) goto probe_fail; 4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *memaddr = save1; 4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* First port should be readable and writable */ 4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds PROBE_PRINT(( "lance_probe1: testing ioport to be accessible\n" )); 4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!addr_accessible( ioaddr, 1, 1 )) goto probe_fail; 5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* and written values should be readable */ 5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds PROBE_PRINT(( "lance_probe1: testing ioport to be writeable\n" )); 5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds save2 = ioaddr[1]; 5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ioaddr[1] = 0x0001; 5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ioaddr[1] != 0x0001) goto probe_fail; 5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* The CSR0_INIT bit should not be readable */ 5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds PROBE_PRINT(( "lance_probe1: testing CSR0 register function (1)\n" )); 5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds save1 = ioaddr[0]; 5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ioaddr[1] = CSR0; 5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ioaddr[0] = CSR0_INIT | CSR0_STOP; 5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ioaddr[0] != CSR0_STOP) { 5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ioaddr[0] = save1; 5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ioaddr[1] = save2; 5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto probe_fail; 5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds PROBE_PRINT(( "lance_probe1: testing CSR0 register function (2)\n" )); 5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ioaddr[0] = CSR0_STOP; 5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ioaddr[0] != CSR0_STOP) { 5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ioaddr[0] = save1; 5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ioaddr[1] = save2; 5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto probe_fail; 5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Now ok... */ 5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds PROBE_PRINT(( "lance_probe1: Lance card detected\n" )); 5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto probe_ok; 5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds probe_fail: 5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return( 0 ); 5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds probe_ok: 533454d7c9b14e20fd1949e2686e9de4a2926e01476Wang Chen lp = netdev_priv(dev); 5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM = (struct lance_memory *)memaddr; 5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds IO = lp->iobase = (struct lance_ioreg *)ioaddr; 5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->base_addr = (unsigned long)ioaddr; /* informational only */ 5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->memcpy_f = init_rec->slow_flag ? slow_memcpy : memcpy; 5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds REGA( CSR0 ) = CSR0_STOP; 5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Now test for type: If the eeprom I/O port is readable, it is a 5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * PAM card */ 5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (addr_accessible( &(IO->eeprom), 0, 0 )) { 5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Switch back to Ram */ 5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = IO->mem; 5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->cardtype = PAM_CARD; 5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (*RIEBL_MAGIC_ADDR == RIEBL_MAGIC) { 5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->cardtype = NEW_RIEBL; 5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->cardtype = OLD_RIEBL; 5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (lp->cardtype == PAM_CARD || 5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memaddr == (unsigned short *)0xffe00000) { 5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* PAMs card and Riebl on ST use level 5 autovector */ 5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (request_irq(IRQ_AUTO_5, lance_interrupt, IRQ_TYPE_PRIO, 5586aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik "PAM/Riebl-ST Ethernet", dev)) { 5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk( "Lance: request for irq %d failed\n", IRQ_AUTO_5 ); 5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return( 0 ); 5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->irq = (unsigned short)IRQ_AUTO_5; 5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else { 5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* For VME-RieblCards, request a free VME int; 5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (This must be unsigned long, since dev->irq is short and the 5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * IRQ_MACHSPEC bit would be cut off...) 5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long irq = atari_register_vme_int(); 5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!irq) { 5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk( "Lance: request for VME interrupt failed\n" ); 5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return( 0 ); 5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (request_irq(irq, lance_interrupt, IRQ_TYPE_PRIO, 5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Riebl-VME Ethernet", dev)) { 5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk( "Lance: request for irq %ld failed\n", irq ); 5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return( 0 ); 5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->irq = irq; 5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("%s: %s at io %#lx, mem %#lx, irq %d%s, hwaddr ", 5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->name, lance_names[lp->cardtype], 5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (unsigned long)ioaddr, 5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (unsigned long)memaddr, 5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->irq, 5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds init_rec->slow_flag ? " (slow memcpy)" : "" ); 5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Get the ethernet address */ 5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch( lp->cardtype ) { 5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case OLD_RIEBL: 5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* No ethernet address! (Set some default address) */ 5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memcpy( dev->dev_addr, OldRieblDefHwaddr, 6 ); 5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case NEW_RIEBL: 5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->memcpy_f( dev->dev_addr, RIEBL_HWADDR_ADDR, 6 ); 5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PAM_CARD: 5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = IO->eeprom; 6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for( i = 0; i < 6; ++i ) 6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->dev_addr[i] = 6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ((((unsigned short *)MEM)[i*2] & 0x0f) << 4) | 6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ((((unsigned short *)MEM)[i*2+1] & 0x0f)); 6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = IO->mem; 6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 607e174961ca1a0b28f7abf0be47973ad57cb74e5f0Johannes Berg printk("%pM\n", dev->dev_addr); 6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (lp->cardtype == OLD_RIEBL) { 6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk( "%s: Warning: This is a default ethernet address!\n", 6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->name ); 6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk( " Use \"ifconfig hw ether ...\" to set the address.\n" ); 6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_init(&lp->devlock); 6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->init.mode = 0x0000; /* Disable Rx and Tx. */ 6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for( i = 0; i < 6; i++ ) 6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->init.hwaddr[i] = dev->dev_addr[i^1]; /* <- 16 bit swap! */ 6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->init.filter[0] = 0x00000000; 6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->init.filter[1] = 0x00000000; 6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->init.rx_ring.adr_lo = offsetof( struct lance_memory, rx_head ); 6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->init.rx_ring.adr_hi = 0; 6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->init.rx_ring.len = RX_RING_LEN_BITS; 6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->init.tx_ring.adr_lo = offsetof( struct lance_memory, tx_head ); 6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->init.tx_ring.adr_hi = 0; 6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->init.tx_ring.len = TX_RING_LEN_BITS; 6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (lp->cardtype == PAM_CARD) 6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds IO->ivec = IRQ_SOURCE_TO_VECTOR(dev->irq); 6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *RIEBL_IVEC_ADDR = IRQ_SOURCE_TO_VECTOR(dev->irq); 6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (did_version++ == 0) 6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK( 1, ( version )); 6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6368e7678fe0992a6107041b839b08ac4af55d41592Alexander Beregalov dev->netdev_ops = &lance_netdev_ops; 6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* XXX MSch */ 6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->watchdog_timeo = TX_TIMEOUT; 6406aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik 6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return( 1 ); 6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6446aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik 6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int lance_open( struct net_device *dev ) 646454d7c9b14e20fd1949e2686e9de4a2926e01476Wang Chen{ 647454d7c9b14e20fd1949e2686e9de4a2926e01476Wang Chen struct lance_private *lp = netdev_priv(dev); 6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct lance_ioreg *IO = lp->iobase; 6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK( 2, ( "%s: lance_open()\n", dev->name )); 6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lance_init_ring(dev); 6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Re-initialize the LANCE, and start it when done. */ 6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds REGA( CSR3 ) = CSR3_BSWP | (lp->cardtype == PAM_CARD ? CSR3_ACON : 0); 6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds REGA( CSR2 ) = 0; 6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds REGA( CSR1 ) = 0; 6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds REGA( CSR0 ) = CSR0_INIT; 6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* From now on, AREG is kept to point to CSR0 */ 6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = 1000000; 6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (--i > 0) 6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (DREG & CSR0_IDON) 6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (i < 0 || (DREG & CSR0_ERR)) { 6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK( 2, ( "lance_open(): opening %s failed, i=%d, csr0=%04x\n", 6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->name, i, DREG )); 6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DREG = CSR0_STOP; 6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return( -EIO ); 6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DREG = CSR0_IDON; 6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DREG = CSR0_STRT; 6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DREG = CSR0_INEA; 6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netif_start_queue (dev); 6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK( 2, ( "%s: LANCE is open, csr0 %04x\n", dev->name, DREG )); 6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return( 0 ); 6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Initialize the LANCE Rx and Tx rings. */ 6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void lance_init_ring( struct net_device *dev ) 687454d7c9b14e20fd1949e2686e9de4a2926e01476Wang Chen{ 688454d7c9b14e20fd1949e2686e9de4a2926e01476Wang Chen struct lance_private *lp = netdev_priv(dev); 6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned offset; 6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->tx_full = 0; 6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->cur_rx = lp->cur_tx = 0; 6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->dirty_tx = 0; 6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds offset = offsetof( struct lance_memory, packet_area ); 6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* If the packet buffer at offset 'o' would conflict with the reserved area 6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * of RieblCards, advance it */ 7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CHECK_OFFSET(o) \ 7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do { \ 7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (lp->cardtype == OLD_RIEBL || lp->cardtype == NEW_RIEBL) { \ 7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (((o) < RIEBL_RSVD_START) ? (o)+PKT_BUF_SZ > RIEBL_RSVD_START \ 7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds : (o) < RIEBL_RSVD_END) \ 7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (o) = RIEBL_RSVD_END; \ 7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } \ 7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } while(0) 7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for( i = 0; i < TX_RING_SIZE; i++ ) { 7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds CHECK_OFFSET(offset); 7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->tx_head[i].base = offset; 7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->tx_head[i].flag = TMD1_OWN_HOST; 7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->tx_head[i].base_hi = 0; 7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->tx_head[i].length = 0; 7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->tx_head[i].misc = 0; 7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds offset += PKT_BUF_SZ; 7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for( i = 0; i < RX_RING_SIZE; i++ ) { 7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds CHECK_OFFSET(offset); 7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->rx_head[i].base = offset; 7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->rx_head[i].flag = TMD1_OWN_CHIP; 7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->rx_head[i].base_hi = 0; 7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->rx_head[i].buf_length = -PKT_BUF_SZ; 7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->rx_head[i].msg_length = 0; 7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds offset += PKT_BUF_SZ; 7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */ 7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void lance_tx_timeout (struct net_device *dev) 7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 736454d7c9b14e20fd1949e2686e9de4a2926e01476Wang Chen struct lance_private *lp = netdev_priv(dev); 7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct lance_ioreg *IO = lp->iobase; 7386aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik 7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds AREG = CSR0; 7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK( 1, ( "%s: transmit timed out, status %04x, resetting.\n", 7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->name, DREG )); 7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DREG = CSR0_STOP; 7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Always set BSWP after a STOP as STOP puts it back into 7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * little endian mode. 7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds REGA( CSR3 ) = CSR3_BSWP | (lp->cardtype == PAM_CARD ? CSR3_ACON : 0); 74809f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik dev->stats.tx_errors++; 7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifndef final_version 7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { int i; 7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK( 2, ( "Ring data: dirty_tx %d cur_tx %d%s cur_rx %d\n", 7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->dirty_tx, lp->cur_tx, 7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->tx_full ? " (full)" : "", 7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->cur_rx )); 7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for( i = 0 ; i < RX_RING_SIZE; i++ ) 7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK( 2, ( "rx #%d: base=%04x blen=%04x mlen=%04x\n", 7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i, MEM->rx_head[i].base, 7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds -MEM->rx_head[i].buf_length, 7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->rx_head[i].msg_length )); 7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for( i = 0 ; i < TX_RING_SIZE; i++ ) 7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK( 2, ( "tx #%d: base=%04x len=%04x misc=%04x\n", 7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i, MEM->tx_head[i].base, 7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds -MEM->tx_head[i].length, 7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->tx_head[i].misc )); 7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7666aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik#endif 7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* XXX MSch: maybe purge/reinit ring here */ 7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* lance_restart, essentially */ 7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lance_init_ring(dev); 7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds REGA( CSR0 ) = CSR0_INEA | CSR0_INIT | CSR0_STRT; 7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->trans_start = jiffies; 7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netif_wake_queue (dev); 7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */ 7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int lance_start_xmit( struct sk_buff *skb, struct net_device *dev ) 778454d7c9b14e20fd1949e2686e9de4a2926e01476Wang Chen{ 779454d7c9b14e20fd1949e2686e9de4a2926e01476Wang Chen struct lance_private *lp = netdev_priv(dev); 7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct lance_ioreg *IO = lp->iobase; 7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int entry, len; 7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct lance_tx_head *head; 7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK( 2, ( "%s: lance_start_xmit() called, csr0 %4.4x.\n", 7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->name, DREG )); 7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* The old LANCE chips doesn't automatically pad buffers to min. size. */ 7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len = skb->len; 7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (len < ETH_ZLEN) 7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len = ETH_ZLEN; 7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* PAM-Card has a bug: Can only send packets with even number of bytes! */ 7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (lp->cardtype == PAM_CARD && (len & 1)) 7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ++len; 7966aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik 7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (len > skb->len) { 7985b057c6b1a25d57edf2b4d1e956e50936480a9ffHerbert Xu if (skb_padto(skb, len)) 7996ed106549d17474ca17a16057f4c0ed4eba5a7caPatrick McHardy return NETDEV_TX_OK; 8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8016aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik 8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netif_stop_queue (dev); 8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Fill in a Tx ring entry */ 8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (lance_debug >= 3) { 806e174961ca1a0b28f7abf0be47973ad57cb74e5f0Johannes Berg printk( "%s: TX pkt type 0x%04x from %pM to %pM" 8070795af5729b18218767fab27c44b1384f72dc9adJoe Perches " data at 0x%08x len %d\n", 8080795af5729b18218767fab27c44b1384f72dc9adJoe Perches dev->name, ((u_short *)skb->data)[6], 809e174961ca1a0b28f7abf0be47973ad57cb74e5f0Johannes Berg &skb->data[6], skb->data, 8100795af5729b18218767fab27c44b1384f72dc9adJoe Perches (int)skb->data, (int)skb->len ); 8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* We're not prepared for the int until the last flags are set/reset. And 8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the int may happen already after setting the OWN_CHIP... */ 8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave (&lp->devlock, flags); 8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Mask to ring buffer boundary. */ 8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds entry = lp->cur_tx & TX_RING_MOD_MASK; 8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds head = &(MEM->tx_head[entry]); 8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Caution: the write order is important here, set the "ownership" bits 8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * last. 8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds head->length = -len; 8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds head->misc = 0; 8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->memcpy_f( PKTBUF_ADDR(head), (void *)skb->data, skb->len ); 8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds head->flag = TMD1_OWN_CHIP | TMD1_ENP | TMD1_STP; 83009f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik dev->stats.tx_bytes += skb->len; 8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_kfree_skb( skb ); 8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->cur_tx++; 8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while( lp->cur_tx >= TX_RING_SIZE && lp->dirty_tx >= TX_RING_SIZE ) { 8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->cur_tx -= TX_RING_SIZE; 8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->dirty_tx -= TX_RING_SIZE; 8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Trigger an immediate send poll. */ 8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DREG = CSR0_INEA | CSR0_TDMD; 8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->trans_start = jiffies; 8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((MEM->tx_head[(entry+1) & TX_RING_MOD_MASK].flag & TMD1_OWN) == 8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds TMD1_OWN_HOST) 8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netif_start_queue (dev); 8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->tx_full = 1; 8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore (&lp->devlock, flags); 8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8496ed106549d17474ca17a16057f4c0ed4eba5a7caPatrick McHardy return NETDEV_TX_OK; 8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* The LANCE interrupt handler. */ 8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8547d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic irqreturn_t lance_interrupt( int irq, void *dev_id ) 8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct net_device *dev = dev_id; 8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct lance_private *lp; 8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct lance_ioreg *IO; 8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int csr0, boguscnt = 10; 8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int handled = 0; 8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev == NULL) { 8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK( 1, ( "lance_interrupt(): interrupt for unknown device.\n" )); 8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return IRQ_NONE; 8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 867454d7c9b14e20fd1949e2686e9de4a2926e01476Wang Chen lp = netdev_priv(dev); 8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds IO = lp->iobase; 8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock (&lp->devlock); 8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds AREG = CSR0; 8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while( ((csr0 = DREG) & (CSR0_ERR | CSR0_TINT | CSR0_RINT)) && 8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds --boguscnt >= 0) { 8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds handled = 1; 8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Acknowledge all of the current interrupt sources ASAP. */ 8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DREG = csr0 & ~(CSR0_INIT | CSR0_STRT | CSR0_STOP | 8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds CSR0_TDMD | CSR0_INEA); 8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK( 2, ( "%s: interrupt csr0=%04x new csr=%04x.\n", 8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->name, csr0, DREG )); 8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (csr0 & CSR0_RINT) /* Rx interrupt */ 8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lance_rx( dev ); 8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (csr0 & CSR0_TINT) { /* Tx-done interrupt */ 8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int dirty_tx = lp->dirty_tx; 8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while( dirty_tx < lp->cur_tx) { 8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int entry = dirty_tx & TX_RING_MOD_MASK; 8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int status = MEM->tx_head[entry].flag; 8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status & TMD1_OWN_CHIP) 8941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; /* It still hasn't been Txed */ 8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->tx_head[entry].flag = 0; 8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status & TMD1_ERR) { 8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* There was an major error, log it. */ 9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err_status = MEM->tx_head[entry].misc; 90109f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik dev->stats.tx_errors++; 90209f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik if (err_status & TMD3_RTRY) dev->stats.tx_aborted_errors++; 90309f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik if (err_status & TMD3_LCAR) dev->stats.tx_carrier_errors++; 90409f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik if (err_status & TMD3_LCOL) dev->stats.tx_window_errors++; 9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (err_status & TMD3_UFLO) { 9061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Ackk! On FIFO errors the Tx unit is turned off! */ 90709f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik dev->stats.tx_fifo_errors++; 9081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Remove this verbosity later! */ 9091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK( 1, ( "%s: Tx FIFO error! Status %04x\n", 9101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->name, csr0 )); 9111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Restart the chip. */ 9121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DREG = CSR0_STRT; 9131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 9151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status & (TMD1_MORE | TMD1_ONE | TMD1_DEF)) 91609f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik dev->stats.collisions++; 91709f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik dev->stats.tx_packets++; 9181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* XXX MSch: free skb?? */ 9211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dirty_tx++; 9221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifndef final_version 9251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (lp->cur_tx - dirty_tx >= TX_RING_SIZE) { 9261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK( 0, ( "out-of-sync dirty pointer," 9271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds " %d vs. %d, full=%ld.\n", 9281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dirty_tx, lp->cur_tx, lp->tx_full )); 9291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dirty_tx += TX_RING_SIZE; 9301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 9321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (lp->tx_full && (netif_queue_stopped(dev)) 9341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds && dirty_tx > lp->cur_tx - TX_RING_SIZE + 2) { 9351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* The ring is no longer full, clear tbusy. */ 9361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->tx_full = 0; 9371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netif_wake_queue (dev); 9381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->dirty_tx = dirty_tx; 9411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Log misc errors. */ 94409f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik if (csr0 & CSR0_BABL) dev->stats.tx_errors++; /* Tx babble. */ 94509f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik if (csr0 & CSR0_MISS) dev->stats.rx_errors++; /* Missed a Rx frame. */ 9461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (csr0 & CSR0_MERR) { 9471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK( 1, ( "%s: Bus master arbitration failure (?!?), " 9481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "status %04x.\n", dev->name, csr0 )); 9491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Restart the chip. */ 9501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DREG = CSR0_STRT; 9511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Clear any other interrupt, and set interrupt enable. */ 9551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DREG = CSR0_BABL | CSR0_CERR | CSR0_MISS | CSR0_MERR | 9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds CSR0_IDON | CSR0_INEA; 9571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK( 2, ( "%s: exiting interrupt, csr0=%#04x.\n", 9591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->name, DREG )); 9601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock (&lp->devlock); 9621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return IRQ_RETVAL(handled); 9631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int lance_rx( struct net_device *dev ) 967454d7c9b14e20fd1949e2686e9de4a2926e01476Wang Chen{ 968454d7c9b14e20fd1949e2686e9de4a2926e01476Wang Chen struct lance_private *lp = netdev_priv(dev); 9691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int entry = lp->cur_rx & RX_RING_MOD_MASK; 9701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 9711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK( 2, ( "%s: rx int, flag=%04x\n", dev->name, 9731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->rx_head[entry].flag )); 9741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* If we own the next entry, it's a new packet. Send it up. */ 9761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while( (MEM->rx_head[entry].flag & RMD1_OWN) == RMD1_OWN_HOST ) { 9771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct lance_rx_head *head = &(MEM->rx_head[entry]); 9781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int status = head->flag; 9791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status != (RMD1_ENP|RMD1_STP)) { /* There was an error. */ 9811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* There is a tricky error noted by John Murphy, 9821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds <murf@perftech.com> to Russ Nelson: Even with full-sized 9831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buffers it's possible for a jabber packet to use two 9841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buffers, with only the last correctly noting the error. */ 9851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status & RMD1_ENP) /* Only count a general error at the */ 98609f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik dev->stats.rx_errors++; /* end of a packet.*/ 98709f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik if (status & RMD1_FRAM) dev->stats.rx_frame_errors++; 98809f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik if (status & RMD1_OFLO) dev->stats.rx_over_errors++; 98909f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik if (status & RMD1_CRC) dev->stats.rx_crc_errors++; 99009f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik if (status & RMD1_BUFF) dev->stats.rx_fifo_errors++; 9911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds head->flag &= (RMD1_ENP|RMD1_STP); 9921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 9931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Malloc up new buffer, compatible with net-3. */ 9941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds short pkt_len = head->msg_length & 0xfff; 9951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sk_buff *skb; 9961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (pkt_len < 60) { 9981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk( "%s: Runt packet!\n", dev->name ); 99909f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik dev->stats.rx_errors++; 10001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else { 10021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb = dev_alloc_skb( pkt_len+2 ); 10031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (skb == NULL) { 10041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK( 1, ( "%s: Memory squeeze, deferring packet.\n", 10051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->name )); 10061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for( i = 0; i < RX_RING_SIZE; i++ ) 10071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (MEM->rx_head[(entry+i) & RX_RING_MOD_MASK].flag & 10081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds RMD1_OWN_CHIP) 10091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 10101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (i > RX_RING_SIZE - 2) { 101209f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik dev->stats.rx_dropped++; 10131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds head->flag |= RMD1_OWN_CHIP; 10141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->cur_rx++; 10151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 10171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (lance_debug >= 3) { 10200795af5729b18218767fab27c44b1384f72dc9adJoe Perches u_char *data = PKTBUF_ADDR(head); 10210795af5729b18218767fab27c44b1384f72dc9adJoe Perches 1022e174961ca1a0b28f7abf0be47973ad57cb74e5f0Johannes Berg printk(KERN_DEBUG "%s: RX pkt type 0x%04x from %pM to %pM " 10230795af5729b18218767fab27c44b1384f72dc9adJoe Perches "data %02x %02x %02x %02x %02x %02x %02x %02x " 10241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "len %d\n", 10250795af5729b18218767fab27c44b1384f72dc9adJoe Perches dev->name, ((u_short *)data)[6], 1026e174961ca1a0b28f7abf0be47973ad57cb74e5f0Johannes Berg &data[6], data, 10271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data[15], data[16], data[17], data[18], 10281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data[19], data[20], data[21], data[22], 10290795af5729b18218767fab27c44b1384f72dc9adJoe Perches pkt_len); 10301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb_reserve( skb, 2 ); /* 16 byte align */ 10331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb_put( skb, pkt_len ); /* Make room */ 10341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->memcpy_f( skb->data, PKTBUF_ADDR(head), pkt_len ); 10351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb->protocol = eth_type_trans( skb, dev ); 10361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netif_rx( skb ); 103709f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik dev->stats.rx_packets++; 103809f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik dev->stats.rx_bytes += pkt_len; 10391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds head->flag |= RMD1_OWN_CHIP; 10431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds entry = (++lp->cur_rx) & RX_RING_MOD_MASK; 10441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->cur_rx &= RX_RING_MOD_MASK; 10461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* From lance.c (Donald Becker): */ 10481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* We should check that at least two ring entries are free. If not, 10491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds we should free one and mark stats->rx_dropped++. */ 10501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 10521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int lance_close( struct net_device *dev ) 1056454d7c9b14e20fd1949e2686e9de4a2926e01476Wang Chen{ 1057454d7c9b14e20fd1949e2686e9de4a2926e01476Wang Chen struct lance_private *lp = netdev_priv(dev); 10581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct lance_ioreg *IO = lp->iobase; 10591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netif_stop_queue (dev); 10611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds AREG = CSR0; 10631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK( 2, ( "%s: Shutting down ethercard, status was %2.2x.\n", 10651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->name, DREG )); 10661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* We stop the LANCE here -- it occasionally polls 10681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memory if we don't. */ 10691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DREG = CSR0_STOP; 10701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 10721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Set or clear the multicast filter for this adaptor. 10761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds num_addrs == -1 Promiscuous mode, receive all packets 10771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds num_addrs == 0 Normal mode, clear multicast list 10781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds num_addrs > 0 Multicast mode, receive normal and MC packets, and do 10791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds best-effort filtering. 10801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 10811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void set_multicast_list( struct net_device *dev ) 1083454d7c9b14e20fd1949e2686e9de4a2926e01476Wang Chen{ 1084454d7c9b14e20fd1949e2686e9de4a2926e01476Wang Chen struct lance_private *lp = netdev_priv(dev); 10851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct lance_ioreg *IO = lp->iobase; 10861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (netif_running(dev)) 10881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Only possible if board is already started */ 10891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 10901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* We take the simple way out and always enable promiscuous mode. */ 10921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DREG = CSR0_STOP; /* Temporarily stop the lance. */ 10931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev->flags & IFF_PROMISC) { 10951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Log any net taps. */ 1096d5b20697ca37d80cc4ec2ba3c5ddf1339dc1d49aAndy Gospodarek DPRINTK( 2, ( "%s: Promiscuous mode enabled.\n", dev->name )); 10971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds REGA( CSR15 ) = 0x8000; /* Set promiscuous mode */ 10981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 10991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds short multicast_table[4]; 11001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int num_addrs = dev->mc_count; 11011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 11021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* We don't use the multicast table, but rely on upper-layer 11031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * filtering. */ 11041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset( multicast_table, (num_addrs == 0) ? 0 : -1, 11051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof(multicast_table) ); 11061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for( i = 0; i < 4; i++ ) 11071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds REGA( CSR8+i ) = multicast_table[i]; 11081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds REGA( CSR15 ) = 0; /* Unset promiscuous mode */ 11091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 11121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Always set BSWP after a STOP as STOP puts it back into 11131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * little endian mode. 11141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 11151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds REGA( CSR3 ) = CSR3_BSWP | (lp->cardtype == PAM_CARD ? CSR3_ACON : 0); 11161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Resume normal operation and reset AREG to CSR0 */ 11181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds REGA( CSR0 ) = CSR0_IDON | CSR0_INEA | CSR0_STRT; 11191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 11201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* This is needed for old RieblCards and possible for new RieblCards */ 11231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int lance_set_mac_address( struct net_device *dev, void *addr ) 1125454d7c9b14e20fd1949e2686e9de4a2926e01476Wang Chen{ 1126454d7c9b14e20fd1949e2686e9de4a2926e01476Wang Chen struct lance_private *lp = netdev_priv(dev); 11271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sockaddr *saddr = addr; 11281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 11291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (lp->cardtype != OLD_RIEBL && lp->cardtype != NEW_RIEBL) 11311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return( -EOPNOTSUPP ); 11321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (netif_running(dev)) { 11341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Only possible while card isn't started */ 11351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK( 1, ( "%s: hwaddr can be set only while card isn't open.\n", 11361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->name )); 11371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return( -EIO ); 11381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memcpy( dev->dev_addr, saddr->sa_data, dev->addr_len ); 11411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for( i = 0; i < 6; i++ ) 11421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->init.hwaddr[i] = dev->dev_addr[i^1]; /* <- 16 bit swap! */ 11431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->memcpy_f( RIEBL_HWADDR_ADDR, dev->dev_addr, 6 ); 11441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* set also the magic for future sessions */ 11451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *RIEBL_MAGIC_ADDR = RIEBL_MAGIC; 11461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return( 0 ); 11481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 11491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11506aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik 11511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef MODULE 11521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct net_device *atarilance_dev; 11531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 115453e7c46b0680ccc3ac67a2b8cd7f050569836e44Jon Schindlerstatic int __init atarilance_module_init(void) 11551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 11561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atarilance_dev = atarilance_probe(-1); 11571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (IS_ERR(atarilance_dev)) 11581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return PTR_ERR(atarilance_dev); 11591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 11601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 11611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 116253e7c46b0680ccc3ac67a2b8cd7f050569836e44Jon Schindlerstatic void __exit atarilance_module_exit(void) 11631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 11641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unregister_netdev(atarilance_dev); 11651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds free_irq(atarilance_dev->irq, atarilance_dev); 11661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds free_netdev(atarilance_dev); 11671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 116853e7c46b0680ccc3ac67a2b8cd7f050569836e44Jon Schindlermodule_init(atarilance_module_init); 116953e7c46b0680ccc3ac67a2b8cd7f050569836e44Jon Schindlermodule_exit(atarilance_module_exit); 11701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif /* MODULE */ 11716aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik 11721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 11741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Local variables: 11751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * c-indent-level: 4 11761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * tab-width: 4 11771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * End: 11781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1179