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/interrupt.h> 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/bitops.h> 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/setup.h> 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/irq.h> 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/atarihw.h> 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/atariints.h> 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/io.h> 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Debug level: 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 0 = silent, print only serious errors 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1 = normal, print error messages 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2 = debug, print debug infos 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 3 = debug, print even more debug infos (packet data) 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LANCE_DEBUG 1 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef LANCE_DEBUG 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int lance_debug = LANCE_DEBUG; 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int lance_debug = 1; 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 808d3b33f67fdc0fb364a1ef6d8fbbea7c2e4e6c98Rusty Russellmodule_param(lance_debug, int, 0); 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(lance_debug, "atarilance debug level (0-3)"); 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Print debug messages on probing? */ 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef LANCE_DEBUG_PROBE 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DPRINTK(n,a) \ 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do { \ 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (lance_debug >= n) \ 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk a; \ 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } while( 0 ) 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef LANCE_DEBUG_PROBE 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds# define PROBE_PRINT(a) printk a 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds# define PROBE_PRINT(a) 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* These define the number of Rx and Tx buffers as log2. (Only powers 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * of two are valid) 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Much more rx buffers (32) are reserved than tx buffers (8), since receiving 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * is more time critical then sending and packets may have to remain in the 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * board's memory when main memory is low. 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TX_LOG_RING_SIZE 3 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RX_LOG_RING_SIZE 5 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* These are the derived values */ 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TX_RING_SIZE (1 << TX_LOG_RING_SIZE) 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TX_RING_LEN_BITS (TX_LOG_RING_SIZE << 5) 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TX_RING_MOD_MASK (TX_RING_SIZE - 1) 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RX_RING_SIZE (1 << RX_LOG_RING_SIZE) 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RX_RING_LEN_BITS (RX_LOG_RING_SIZE << 5) 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RX_RING_MOD_MASK (RX_RING_SIZE - 1) 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 119c63fdf46ad0a7f8fe3c0252a0e763515617e0ea7Eric Dumazet#define TX_TIMEOUT (HZ/5) 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* The LANCE Rx and Tx ring descriptors. */ 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct lance_rx_head { 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned short base; /* Low word of base addr */ 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds volatile unsigned char flag; 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char base_hi; /* High word of base addr (unused) */ 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds short buf_length; /* This length is 2s complement! */ 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds volatile short msg_length; /* This length is "normal". */ 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct lance_tx_head { 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned short base; /* Low word of base addr */ 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds volatile unsigned char flag; 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char base_hi; /* High word of base addr (unused) */ 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds short length; /* Length is 2s complement! */ 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds volatile short misc; 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct ringdesc { 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned short adr_lo; /* Low 16 bits of address */ 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char len; /* Length bits */ 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char adr_hi; /* High 8 bits of address (unused) */ 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* The LANCE initialization block, described in databook. */ 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct lance_init_block { 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned short mode; /* Pre-set mode */ 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char hwaddr[6]; /* Physical ethernet address */ 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned filter[2]; /* Multicast filter (unused). */ 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Receive and transmit ring base, along with length bits. */ 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ringdesc rx_ring; 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ringdesc tx_ring; 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* The whole layout of the Lance shared memory */ 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct lance_memory { 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct lance_init_block init; 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct lance_tx_head tx_head[TX_RING_SIZE]; 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct lance_rx_head rx_head[RX_RING_SIZE]; 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char packet_area[0]; /* packet data follow after the 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * init block and the ring 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * descriptors and are located 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * at runtime */ 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* RieblCard specifics: 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The original TOS driver for these cards reserves the area from offset 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 0xee70 to 0xeebb for storing configuration data. Of interest to us is the 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Ethernet address there, and the magic for verifying the data's validity. 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The reserved area isn't touch by packet buffers. Furthermore, offset 0xfffe 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * is reserved for the interrupt vector number. 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RIEBL_RSVD_START 0xee70 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RIEBL_RSVD_END 0xeec0 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RIEBL_MAGIC 0x09051990 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RIEBL_MAGIC_ADDR ((unsigned long *)(((char *)MEM) + 0xee8a)) 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RIEBL_HWADDR_ADDR ((unsigned char *)(((char *)MEM) + 0xee8e)) 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RIEBL_IVEC_ADDR ((unsigned short *)(((char *)MEM) + 0xfffe)) 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* This is a default address for the old RieblCards without a battery 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * that have no ethernet address at boot time. 00:00:36:04 is the 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * prefix for Riebl cards, the 00:00 at the end is arbitrary. 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned char OldRieblDefHwaddr[6] = { 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0x00, 0x00, 0x36, 0x04, 0x00, 0x00 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* I/O registers of the Lance chip */ 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct lance_ioreg { 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* base+0x0 */ volatile unsigned short data; 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* base+0x2 */ volatile unsigned short addr; 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char _dummy1[3]; 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* base+0x7 */ volatile unsigned char ivec; 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char _dummy2[5]; 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* base+0xd */ volatile unsigned char eeprom; 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char _dummy3; 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* base+0xf */ volatile unsigned char mem; 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Types of boards this driver supports */ 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsenum lance_type { 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OLD_RIEBL, /* old Riebl card without battery */ 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds NEW_RIEBL, /* new Riebl card with battery */ 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds PAM_CARD /* PAM card with EEPROM */ 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic char *lance_names[] = { 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Riebl-Card (without battery)", 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Riebl-Card (with battery)", 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "PAM intern card" 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* The driver's private device structure */ 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct lance_private { 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds enum lance_type cardtype; 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct lance_ioreg *iobase; 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct lance_memory *mem; 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int cur_rx, cur_tx; /* The next free ring entry */ 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int dirty_tx; /* Ring entries to be freed. */ 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* copy function */ 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void *(*memcpy_f)( void *, const void *, size_t ); 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* This must be long for set_bit() */ 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds long tx_full; 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spinlock_t devlock; 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* I/O register access macros */ 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MEM lp->mem 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DREG IO->data 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define AREG IO->addr 236e345d5ef6d476cc236f64d90d9528143a70745c8Al Viro#define REGA(a) (*( AREG = (a), &DREG )) 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Definitions for packet buffer access: */ 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PKT_BUF_SZ 1544 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Get the address of a packet buffer corresponding to a given buffer head */ 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PKTBUF_ADDR(head) (((unsigned char *)(MEM)) + (head)->base) 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Possible memory/IO addresses for probing */ 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2453cacd2a1ce5464b9874508927d561c0dfce74637Adrian Bunkstatic struct lance_addr { 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long memaddr; 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long ioaddr; 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int slow_flag; 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} lance_addr_list[] = { 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 0xfe010000, 0xfe00fff0, 0 }, /* RieblCard VME in TT */ 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 0xffc10000, 0xffc0fff0, 0 }, /* RieblCard VME in MegaSTE 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (highest byte stripped) */ 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 0xffe00000, 0xffff7000, 1 }, /* RieblCard in ST 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (highest byte stripped) */ 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 0xffd00000, 0xffff7000, 1 }, /* RieblCard in ST with hw modif. to 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds avoid conflict with ROM 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (highest byte stripped) */ 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 0xffcf0000, 0xffcffff0, 0 }, /* PAMCard VME in TT and MSTE 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (highest byte stripped) */ 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 0xfecf0000, 0xfecffff0, 0 }, /* Rhotron's PAMCard VME in TT and MSTE 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (highest byte stripped) */ 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 264ff8ac60948ba819b89e9c87083e8050fc2f89999Denis Cheng#define N_LANCE_ADDR ARRAY_SIZE(lance_addr_list) 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Definitions for the Lance */ 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* tx_head flags */ 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TMD1_ENP 0x01 /* end of packet */ 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TMD1_STP 0x02 /* start of packet */ 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TMD1_DEF 0x04 /* deferred */ 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TMD1_ONE 0x08 /* one retry needed */ 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TMD1_MORE 0x10 /* more than one retry needed */ 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TMD1_ERR 0x40 /* error summary */ 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TMD1_OWN 0x80 /* ownership (set: chip owns) */ 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TMD1_OWN_CHIP TMD1_OWN 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TMD1_OWN_HOST 0 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* tx_head misc field */ 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TMD3_TDR 0x03FF /* Time Domain Reflectometry counter */ 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TMD3_RTRY 0x0400 /* failed after 16 retries */ 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TMD3_LCAR 0x0800 /* carrier lost */ 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TMD3_LCOL 0x1000 /* late collision */ 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TMD3_UFLO 0x4000 /* underflow (late memory) */ 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TMD3_BUFF 0x8000 /* buffering error (no ENP) */ 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* rx_head flags */ 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RMD1_ENP 0x01 /* end of packet */ 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RMD1_STP 0x02 /* start of packet */ 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RMD1_BUFF 0x04 /* buffer error */ 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RMD1_CRC 0x08 /* CRC error */ 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RMD1_OFLO 0x10 /* overflow */ 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RMD1_FRAM 0x20 /* framing error */ 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RMD1_ERR 0x40 /* error summary */ 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RMD1_OWN 0x80 /* ownership (set: ship owns) */ 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RMD1_OWN_CHIP RMD1_OWN 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RMD1_OWN_HOST 0 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* register names */ 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR0 0 /* mode/status */ 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR1 1 /* init block addr (low) */ 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR2 2 /* init block addr (high) */ 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR3 3 /* misc */ 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR8 8 /* address filter */ 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR15 15 /* promiscuous mode */ 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* CSR0 */ 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* (R=readable, W=writeable, S=set on write, C=clear on write) */ 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR0_INIT 0x0001 /* initialize (RS) */ 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR0_STRT 0x0002 /* start (RS) */ 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR0_STOP 0x0004 /* stop (RS) */ 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR0_TDMD 0x0008 /* transmit demand (RS) */ 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR0_TXON 0x0010 /* transmitter on (R) */ 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR0_RXON 0x0020 /* receiver on (R) */ 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR0_INEA 0x0040 /* interrupt enable (RW) */ 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR0_INTR 0x0080 /* interrupt active (R) */ 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR0_IDON 0x0100 /* initialization done (RC) */ 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR0_TINT 0x0200 /* transmitter interrupt (RC) */ 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR0_RINT 0x0400 /* receiver interrupt (RC) */ 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR0_MERR 0x0800 /* memory error (RC) */ 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR0_MISS 0x1000 /* missed frame (RC) */ 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR0_CERR 0x2000 /* carrier error (no heartbeat :-) (RC) */ 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR0_BABL 0x4000 /* babble: tx-ed too many bits (RC) */ 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR0_ERR 0x8000 /* error (RC) */ 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* CSR3 */ 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR3_BCON 0x0001 /* byte control */ 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR3_ACON 0x0002 /* ALE control */ 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CSR3_BSWP 0x0004 /* byte swap (1=big endian) */ 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/***************************** Prototypes *****************************/ 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned long lance_probe1( struct net_device *dev, struct lance_addr 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *init_rec ); 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int lance_open( struct net_device *dev ); 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void lance_init_ring( struct net_device *dev ); 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int lance_start_xmit( struct sk_buff *skb, struct net_device *dev ); 3437d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic irqreturn_t lance_interrupt( int irq, void *dev_id ); 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int lance_rx( struct net_device *dev ); 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int lance_close( struct net_device *dev ); 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void set_multicast_list( struct net_device *dev ); 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int lance_set_mac_address( struct net_device *dev, void *addr ); 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void lance_tx_timeout (struct net_device *dev); 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/************************* End of Prototypes **************************/ 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3546aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void *slow_memcpy( void *dst, const void *src, size_t len ) 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ char *cto = dst; 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds const char *cfrom = src; 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while( len-- ) { 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *cto++ = *cfrom++; 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MFPDELAY(); 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 365807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet return dst; 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct net_device * __init atarilance_probe(int unit) 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds static int found; 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct net_device *dev; 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err = -ENODEV; 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!MACH_IS_ATARI || found) 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Assume there's only one board possible... That seems true, since 3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the Riebl/PAM board's address cannot be changed. */ 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ERR_PTR(-ENODEV); 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev = alloc_etherdev(sizeof(struct lance_private)); 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!dev) 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ERR_PTR(-ENOMEM); 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unit >= 0) { 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sprintf(dev->name, "eth%d", unit); 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netdev_boot_setup_check(dev); 3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for( i = 0; i < N_LANCE_ADDR; ++i ) { 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (lance_probe1( dev, &lance_addr_list[i] )) { 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds found = 1; 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = register_netdev(dev); 3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!err) 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return dev; 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds free_irq(dev->irq, dev); 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds free_netdev(dev); 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ERR_PTR(err); 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Derived from hwreg_present() in atari/config.c: */ 4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 406f37c768c39e3aeb8a508e1a45e461a506771445eAdrian Bunkstatic noinline int __init addr_accessible(volatile void *regp, int wordflag, 407f37c768c39e3aeb8a508e1a45e461a506771445eAdrian Bunk int writeflag) 4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret; 410d1abc9a9aca06ceb795eb5405264eaafe016ec5cGeert Uytterhoeven unsigned long flags; 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds long *vbr, save_berr; 4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds local_irq_save(flags); 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __asm__ __volatile__ ( "movec %/vbr,%0" : "=r" (vbr) : ); 4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds save_berr = vbr[2]; 4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __asm__ __volatile__ 4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ( "movel %/sp,%/d1\n\t" 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "movel #Lberr,%2@\n\t" 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "moveq #0,%0\n\t" 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "tstl %3\n\t" 4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "bne 1f\n\t" 4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "moveb %1@,%/d0\n\t" 4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "nop \n\t" 4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "bra 2f\n" 4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds"1: movew %1@,%/d0\n\t" 4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "nop \n" 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds"2: tstl %4\n\t" 4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "beq 2f\n\t" 4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "tstl %3\n\t" 4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "bne 1f\n\t" 4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "clrb %1@\n\t" 4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "nop \n\t" 4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "moveb %/d0,%1@\n\t" 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "nop \n\t" 4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "bra 2f\n" 4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds"1: clrw %1@\n\t" 4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "nop \n\t" 4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "movew %/d0,%1@\n\t" 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "nop \n" 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds"2: moveq #1,%0\n" 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds"Lberr: movel %/d1,%/sp" 4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds : "=&d" (ret) 4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds : "a" (regp), "a" (&vbr[2]), "rm" (wordflag), "rm" (writeflag) 4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds : "d0", "d1", "memory" 4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ); 4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vbr[2] = save_berr; 4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds local_irq_restore(flags); 4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 452807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet return ret; 4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4558e7678fe0992a6107041b839b08ac4af55d41592Alexander Beregalovstatic const struct net_device_ops lance_netdev_ops = { 4568e7678fe0992a6107041b839b08ac4af55d41592Alexander Beregalov .ndo_open = lance_open, 4578e7678fe0992a6107041b839b08ac4af55d41592Alexander Beregalov .ndo_stop = lance_close, 4588e7678fe0992a6107041b839b08ac4af55d41592Alexander Beregalov .ndo_start_xmit = lance_start_xmit, 459afc4b13df143122f99a0eb10bfefb216c2806de0Jiri Pirko .ndo_set_rx_mode = set_multicast_list, 4608e7678fe0992a6107041b839b08ac4af55d41592Alexander Beregalov .ndo_set_mac_address = lance_set_mac_address, 4618e7678fe0992a6107041b839b08ac4af55d41592Alexander Beregalov .ndo_tx_timeout = lance_tx_timeout, 4628e7678fe0992a6107041b839b08ac4af55d41592Alexander Beregalov .ndo_validate_addr = eth_validate_addr, 4638e7678fe0992a6107041b839b08ac4af55d41592Alexander Beregalov .ndo_change_mtu = eth_change_mtu, 4648e7678fe0992a6107041b839b08ac4af55d41592Alexander Beregalov}; 4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned long __init lance_probe1( struct net_device *dev, 4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct lance_addr *init_rec ) 4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds volatile unsigned short *memaddr = 4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (volatile unsigned short *)init_rec->memaddr; 4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds volatile unsigned short *ioaddr = 4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (volatile unsigned short *)init_rec->ioaddr; 4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct lance_private *lp; 4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct lance_ioreg *IO; 4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds static int did_version; 4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned short save1, save2; 4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds PROBE_PRINT(( "Probing for Lance card at mem %#lx io %#lx\n", 4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (long)memaddr, (long)ioaddr )); 4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Test whether memory readable and writable */ 4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds PROBE_PRINT(( "lance_probe1: testing memory to be accessible\n" )); 4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!addr_accessible( memaddr, 1, 1 )) goto probe_fail; 4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Written values should come back... */ 4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds PROBE_PRINT(( "lance_probe1: testing memory to be writable (1)\n" )); 4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds save1 = *memaddr; 4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *memaddr = 0x0001; 4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (*memaddr != 0x0001) goto probe_fail; 4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds PROBE_PRINT(( "lance_probe1: testing memory to be writable (2)\n" )); 4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *memaddr = 0x0000; 4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (*memaddr != 0x0000) goto probe_fail; 4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *memaddr = save1; 4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* First port should be readable and writable */ 4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds PROBE_PRINT(( "lance_probe1: testing ioport to be accessible\n" )); 4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!addr_accessible( ioaddr, 1, 1 )) goto probe_fail; 4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* and written values should be readable */ 5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds PROBE_PRINT(( "lance_probe1: testing ioport to be writeable\n" )); 5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds save2 = ioaddr[1]; 5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ioaddr[1] = 0x0001; 5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ioaddr[1] != 0x0001) goto probe_fail; 5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* The CSR0_INIT bit should not be readable */ 5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds PROBE_PRINT(( "lance_probe1: testing CSR0 register function (1)\n" )); 5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds save1 = ioaddr[0]; 5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ioaddr[1] = CSR0; 5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ioaddr[0] = CSR0_INIT | CSR0_STOP; 5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ioaddr[0] != CSR0_STOP) { 5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ioaddr[0] = save1; 5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ioaddr[1] = save2; 5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto probe_fail; 5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds PROBE_PRINT(( "lance_probe1: testing CSR0 register function (2)\n" )); 5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ioaddr[0] = CSR0_STOP; 5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ioaddr[0] != CSR0_STOP) { 5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ioaddr[0] = save1; 5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ioaddr[1] = save2; 5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto probe_fail; 5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Now ok... */ 5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds PROBE_PRINT(( "lance_probe1: Lance card detected\n" )); 5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto probe_ok; 5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds probe_fail: 529807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet return 0; 5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds probe_ok: 532454d7c9b14e20fd1949e2686e9de4a2926e01476Wang Chen lp = netdev_priv(dev); 5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM = (struct lance_memory *)memaddr; 5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds IO = lp->iobase = (struct lance_ioreg *)ioaddr; 5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->base_addr = (unsigned long)ioaddr; /* informational only */ 5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->memcpy_f = init_rec->slow_flag ? slow_memcpy : memcpy; 5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds REGA( CSR0 ) = CSR0_STOP; 5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Now test for type: If the eeprom I/O port is readable, it is a 5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * PAM card */ 5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (addr_accessible( &(IO->eeprom), 0, 0 )) { 5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Switch back to Ram */ 5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = IO->mem; 5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->cardtype = PAM_CARD; 5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (*RIEBL_MAGIC_ADDR == RIEBL_MAGIC) { 5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->cardtype = NEW_RIEBL; 5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->cardtype = OLD_RIEBL; 5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (lp->cardtype == PAM_CARD || 5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memaddr == (unsigned short *)0xffe00000) { 5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* PAMs card and Riebl on ST use level 5 autovector */ 5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (request_irq(IRQ_AUTO_5, lance_interrupt, IRQ_TYPE_PRIO, 55779abeed6ee93231d494c191a9251c0845bd71fddGeert Uytterhoeven "PAM,Riebl-ST Ethernet", dev)) { 5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk( "Lance: request for irq %d failed\n", IRQ_AUTO_5 ); 559807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet return 0; 5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->irq = (unsigned short)IRQ_AUTO_5; 5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else { 5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* For VME-RieblCards, request a free VME int; 5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (This must be unsigned long, since dev->irq is short and the 5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * IRQ_MACHSPEC bit would be cut off...) 5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long irq = atari_register_vme_int(); 5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!irq) { 5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk( "Lance: request for VME interrupt failed\n" ); 571807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet return 0; 5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (request_irq(irq, lance_interrupt, IRQ_TYPE_PRIO, 5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Riebl-VME Ethernet", dev)) { 5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk( "Lance: request for irq %ld failed\n", irq ); 576807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet return 0; 5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->irq = irq; 5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("%s: %s at io %#lx, mem %#lx, irq %d%s, hwaddr ", 5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->name, lance_names[lp->cardtype], 5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (unsigned long)ioaddr, 5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (unsigned long)memaddr, 5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->irq, 5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds init_rec->slow_flag ? " (slow memcpy)" : "" ); 5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Get the ethernet address */ 5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch( lp->cardtype ) { 5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case OLD_RIEBL: 5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* No ethernet address! (Set some default address) */ 5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memcpy( dev->dev_addr, OldRieblDefHwaddr, 6 ); 5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case NEW_RIEBL: 5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->memcpy_f( dev->dev_addr, RIEBL_HWADDR_ADDR, 6 ); 5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PAM_CARD: 5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = IO->eeprom; 5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for( i = 0; i < 6; ++i ) 6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->dev_addr[i] = 6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ((((unsigned short *)MEM)[i*2] & 0x0f) << 4) | 6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ((((unsigned short *)MEM)[i*2+1] & 0x0f)); 6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = IO->mem; 6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 606e174961ca1a0b28f7abf0be47973ad57cb74e5f0Johannes Berg printk("%pM\n", dev->dev_addr); 6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (lp->cardtype == OLD_RIEBL) { 6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk( "%s: Warning: This is a default ethernet address!\n", 6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->name ); 6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk( " Use \"ifconfig hw ether ...\" to set the address.\n" ); 6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_init(&lp->devlock); 6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->init.mode = 0x0000; /* Disable Rx and Tx. */ 6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for( i = 0; i < 6; i++ ) 6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->init.hwaddr[i] = dev->dev_addr[i^1]; /* <- 16 bit swap! */ 6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->init.filter[0] = 0x00000000; 6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->init.filter[1] = 0x00000000; 6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->init.rx_ring.adr_lo = offsetof( struct lance_memory, rx_head ); 6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->init.rx_ring.adr_hi = 0; 6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->init.rx_ring.len = RX_RING_LEN_BITS; 6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->init.tx_ring.adr_lo = offsetof( struct lance_memory, tx_head ); 6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->init.tx_ring.adr_hi = 0; 6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->init.tx_ring.len = TX_RING_LEN_BITS; 6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (lp->cardtype == PAM_CARD) 6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds IO->ivec = IRQ_SOURCE_TO_VECTOR(dev->irq); 6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *RIEBL_IVEC_ADDR = IRQ_SOURCE_TO_VECTOR(dev->irq); 6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (did_version++ == 0) 6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK( 1, ( version )); 6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6358e7678fe0992a6107041b839b08ac4af55d41592Alexander Beregalov dev->netdev_ops = &lance_netdev_ops; 6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* XXX MSch */ 6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->watchdog_timeo = TX_TIMEOUT; 6396aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik 640807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet return 1; 6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6436aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik 6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int lance_open( struct net_device *dev ) 645454d7c9b14e20fd1949e2686e9de4a2926e01476Wang Chen{ 646454d7c9b14e20fd1949e2686e9de4a2926e01476Wang Chen struct lance_private *lp = netdev_priv(dev); 6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct lance_ioreg *IO = lp->iobase; 6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK( 2, ( "%s: lance_open()\n", dev->name )); 6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lance_init_ring(dev); 6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Re-initialize the LANCE, and start it when done. */ 6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds REGA( CSR3 ) = CSR3_BSWP | (lp->cardtype == PAM_CARD ? CSR3_ACON : 0); 6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds REGA( CSR2 ) = 0; 6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds REGA( CSR1 ) = 0; 6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds REGA( CSR0 ) = CSR0_INIT; 6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* From now on, AREG is kept to point to CSR0 */ 6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = 1000000; 6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (--i > 0) 6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (DREG & CSR0_IDON) 6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 665e145b98484f5c7444151e90cc0853f14e6d396a4roel kluin if (i <= 0 || (DREG & CSR0_ERR)) { 6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK( 2, ( "lance_open(): opening %s failed, i=%d, csr0=%04x\n", 6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->name, i, DREG )); 6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DREG = CSR0_STOP; 669807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet return -EIO; 6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DREG = CSR0_IDON; 6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DREG = CSR0_STRT; 6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DREG = CSR0_INEA; 6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netif_start_queue (dev); 6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK( 2, ( "%s: LANCE is open, csr0 %04x\n", dev->name, DREG )); 6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 679807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet return 0; 6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Initialize the LANCE Rx and Tx rings. */ 6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void lance_init_ring( struct net_device *dev ) 686454d7c9b14e20fd1949e2686e9de4a2926e01476Wang Chen{ 687454d7c9b14e20fd1949e2686e9de4a2926e01476Wang Chen struct lance_private *lp = netdev_priv(dev); 6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned offset; 6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->tx_full = 0; 6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->cur_rx = lp->cur_tx = 0; 6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->dirty_tx = 0; 6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds offset = offsetof( struct lance_memory, packet_area ); 6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* If the packet buffer at offset 'o' would conflict with the reserved area 6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * of RieblCards, advance it */ 6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CHECK_OFFSET(o) \ 7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do { \ 7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (lp->cardtype == OLD_RIEBL || lp->cardtype == NEW_RIEBL) { \ 7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (((o) < RIEBL_RSVD_START) ? (o)+PKT_BUF_SZ > RIEBL_RSVD_START \ 7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds : (o) < RIEBL_RSVD_END) \ 7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (o) = RIEBL_RSVD_END; \ 7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } \ 7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } while(0) 7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for( i = 0; i < TX_RING_SIZE; i++ ) { 7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds CHECK_OFFSET(offset); 7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->tx_head[i].base = offset; 7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->tx_head[i].flag = TMD1_OWN_HOST; 7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->tx_head[i].base_hi = 0; 7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->tx_head[i].length = 0; 7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->tx_head[i].misc = 0; 7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds offset += PKT_BUF_SZ; 7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for( i = 0; i < RX_RING_SIZE; i++ ) { 7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds CHECK_OFFSET(offset); 7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->rx_head[i].base = offset; 7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->rx_head[i].flag = TMD1_OWN_CHIP; 7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->rx_head[i].base_hi = 0; 7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->rx_head[i].buf_length = -PKT_BUF_SZ; 7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->rx_head[i].msg_length = 0; 7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds offset += PKT_BUF_SZ; 7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */ 7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void lance_tx_timeout (struct net_device *dev) 7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 735454d7c9b14e20fd1949e2686e9de4a2926e01476Wang Chen struct lance_private *lp = netdev_priv(dev); 7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct lance_ioreg *IO = lp->iobase; 7376aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik 7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds AREG = CSR0; 7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK( 1, ( "%s: transmit timed out, status %04x, resetting.\n", 7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->name, DREG )); 7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DREG = CSR0_STOP; 7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Always set BSWP after a STOP as STOP puts it back into 7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * little endian mode. 7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds REGA( CSR3 ) = CSR3_BSWP | (lp->cardtype == PAM_CARD ? CSR3_ACON : 0); 74709f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik dev->stats.tx_errors++; 7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifndef final_version 7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { int i; 7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK( 2, ( "Ring data: dirty_tx %d cur_tx %d%s cur_rx %d\n", 7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->dirty_tx, lp->cur_tx, 7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->tx_full ? " (full)" : "", 7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->cur_rx )); 7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for( i = 0 ; i < RX_RING_SIZE; i++ ) 7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK( 2, ( "rx #%d: base=%04x blen=%04x mlen=%04x\n", 7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i, MEM->rx_head[i].base, 7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds -MEM->rx_head[i].buf_length, 7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->rx_head[i].msg_length )); 7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for( i = 0 ; i < TX_RING_SIZE; i++ ) 7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK( 2, ( "tx #%d: base=%04x len=%04x misc=%04x\n", 7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i, MEM->tx_head[i].base, 7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds -MEM->tx_head[i].length, 7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->tx_head[i].misc )); 7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7656aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik#endif 7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* XXX MSch: maybe purge/reinit ring here */ 7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* lance_restart, essentially */ 7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lance_init_ring(dev); 7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds REGA( CSR0 ) = CSR0_INEA | CSR0_INIT | CSR0_STRT; 7701ae5dc342ac78d7a42965fd1f323815f6f5ef2c1Eric Dumazet dev->trans_start = jiffies; /* prevent tx timeout */ 7711ae5dc342ac78d7a42965fd1f323815f6f5ef2c1Eric Dumazet netif_wake_queue(dev); 7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */ 7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int lance_start_xmit( struct sk_buff *skb, struct net_device *dev ) 777454d7c9b14e20fd1949e2686e9de4a2926e01476Wang Chen{ 778454d7c9b14e20fd1949e2686e9de4a2926e01476Wang Chen struct lance_private *lp = netdev_priv(dev); 7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct lance_ioreg *IO = lp->iobase; 7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int entry, len; 7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct lance_tx_head *head; 7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK( 2, ( "%s: lance_start_xmit() called, csr0 %4.4x.\n", 7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->name, DREG )); 7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* The old LANCE chips doesn't automatically pad buffers to min. size. */ 7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len = skb->len; 7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (len < ETH_ZLEN) 7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len = ETH_ZLEN; 7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* PAM-Card has a bug: Can only send packets with even number of bytes! */ 7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (lp->cardtype == PAM_CARD && (len & 1)) 7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ++len; 7956aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik 7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (len > skb->len) { 7975b057c6b1a25d57edf2b4d1e956e50936480a9ffHerbert Xu if (skb_padto(skb, len)) 7986ed106549d17474ca17a16057f4c0ed4eba5a7caPatrick McHardy return NETDEV_TX_OK; 7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8006aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik 8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netif_stop_queue (dev); 8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Fill in a Tx ring entry */ 8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (lance_debug >= 3) { 805e174961ca1a0b28f7abf0be47973ad57cb74e5f0Johannes Berg printk( "%s: TX pkt type 0x%04x from %pM to %pM" 8060795af5729b18218767fab27c44b1384f72dc9adJoe Perches " data at 0x%08x len %d\n", 8070795af5729b18218767fab27c44b1384f72dc9adJoe Perches dev->name, ((u_short *)skb->data)[6], 808e174961ca1a0b28f7abf0be47973ad57cb74e5f0Johannes Berg &skb->data[6], skb->data, 8090795af5729b18218767fab27c44b1384f72dc9adJoe Perches (int)skb->data, (int)skb->len ); 8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* We're not prepared for the int until the last flags are set/reset. And 8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the int may happen already after setting the OWN_CHIP... */ 8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave (&lp->devlock, flags); 8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Mask to ring buffer boundary. */ 8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds entry = lp->cur_tx & TX_RING_MOD_MASK; 8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds head = &(MEM->tx_head[entry]); 8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Caution: the write order is important here, set the "ownership" bits 8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * last. 8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds head->length = -len; 8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds head->misc = 0; 8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->memcpy_f( PKTBUF_ADDR(head), (void *)skb->data, skb->len ); 8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds head->flag = TMD1_OWN_CHIP | TMD1_ENP | TMD1_STP; 82909f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik dev->stats.tx_bytes += skb->len; 8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_kfree_skb( skb ); 8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->cur_tx++; 8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while( lp->cur_tx >= TX_RING_SIZE && lp->dirty_tx >= TX_RING_SIZE ) { 8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->cur_tx -= TX_RING_SIZE; 8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->dirty_tx -= TX_RING_SIZE; 8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Trigger an immediate send poll. */ 8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DREG = CSR0_INEA | CSR0_TDMD; 8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((MEM->tx_head[(entry+1) & TX_RING_MOD_MASK].flag & TMD1_OWN) == 8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds TMD1_OWN_HOST) 8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netif_start_queue (dev); 8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->tx_full = 1; 8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore (&lp->devlock, flags); 8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8476ed106549d17474ca17a16057f4c0ed4eba5a7caPatrick McHardy return NETDEV_TX_OK; 8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* The LANCE interrupt handler. */ 8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8527d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic irqreturn_t lance_interrupt( int irq, void *dev_id ) 8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct net_device *dev = dev_id; 8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct lance_private *lp; 8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct lance_ioreg *IO; 8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int csr0, boguscnt = 10; 8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int handled = 0; 8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev == NULL) { 8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK( 1, ( "lance_interrupt(): interrupt for unknown device.\n" )); 8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return IRQ_NONE; 8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 865454d7c9b14e20fd1949e2686e9de4a2926e01476Wang Chen lp = netdev_priv(dev); 8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds IO = lp->iobase; 8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock (&lp->devlock); 8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds AREG = CSR0; 8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while( ((csr0 = DREG) & (CSR0_ERR | CSR0_TINT | CSR0_RINT)) && 8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds --boguscnt >= 0) { 8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds handled = 1; 8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Acknowledge all of the current interrupt sources ASAP. */ 8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DREG = csr0 & ~(CSR0_INIT | CSR0_STRT | CSR0_STOP | 8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds CSR0_TDMD | CSR0_INEA); 8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK( 2, ( "%s: interrupt csr0=%04x new csr=%04x.\n", 8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->name, csr0, DREG )); 8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (csr0 & CSR0_RINT) /* Rx interrupt */ 8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lance_rx( dev ); 8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (csr0 & CSR0_TINT) { /* Tx-done interrupt */ 8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int dirty_tx = lp->dirty_tx; 8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while( dirty_tx < lp->cur_tx) { 8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int entry = dirty_tx & TX_RING_MOD_MASK; 8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int status = MEM->tx_head[entry].flag; 8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status & TMD1_OWN_CHIP) 8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; /* It still hasn't been Txed */ 8931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->tx_head[entry].flag = 0; 8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status & TMD1_ERR) { 8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* There was an major error, log it. */ 8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err_status = MEM->tx_head[entry].misc; 89909f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik dev->stats.tx_errors++; 90009f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik if (err_status & TMD3_RTRY) dev->stats.tx_aborted_errors++; 90109f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik if (err_status & TMD3_LCAR) dev->stats.tx_carrier_errors++; 90209f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik if (err_status & TMD3_LCOL) dev->stats.tx_window_errors++; 9031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (err_status & TMD3_UFLO) { 9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Ackk! On FIFO errors the Tx unit is turned off! */ 90509f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik dev->stats.tx_fifo_errors++; 9061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Remove this verbosity later! */ 9071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK( 1, ( "%s: Tx FIFO error! Status %04x\n", 9081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->name, csr0 )); 9091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Restart the chip. */ 9101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DREG = CSR0_STRT; 9111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 9131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status & (TMD1_MORE | TMD1_ONE | TMD1_DEF)) 91409f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik dev->stats.collisions++; 91509f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik dev->stats.tx_packets++; 9161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* XXX MSch: free skb?? */ 9191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dirty_tx++; 9201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifndef final_version 9231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (lp->cur_tx - dirty_tx >= TX_RING_SIZE) { 9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK( 0, ( "out-of-sync dirty pointer," 9251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds " %d vs. %d, full=%ld.\n", 9261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dirty_tx, lp->cur_tx, lp->tx_full )); 9271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dirty_tx += TX_RING_SIZE; 9281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 9301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9318e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches if (lp->tx_full && (netif_queue_stopped(dev)) && 9328e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches dirty_tx > lp->cur_tx - TX_RING_SIZE + 2) { 9331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* The ring is no longer full, clear tbusy. */ 9341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->tx_full = 0; 9351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netif_wake_queue (dev); 9361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->dirty_tx = dirty_tx; 9391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Log misc errors. */ 94209f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik if (csr0 & CSR0_BABL) dev->stats.tx_errors++; /* Tx babble. */ 94309f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik if (csr0 & CSR0_MISS) dev->stats.rx_errors++; /* Missed a Rx frame. */ 9441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (csr0 & CSR0_MERR) { 9451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK( 1, ( "%s: Bus master arbitration failure (?!?), " 9461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "status %04x.\n", dev->name, csr0 )); 9471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Restart the chip. */ 9481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DREG = CSR0_STRT; 9491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Clear any other interrupt, and set interrupt enable. */ 9531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DREG = CSR0_BABL | CSR0_CERR | CSR0_MISS | CSR0_MERR | 9541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds CSR0_IDON | CSR0_INEA; 9551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK( 2, ( "%s: exiting interrupt, csr0=%#04x.\n", 9571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->name, DREG )); 9581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock (&lp->devlock); 9601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return IRQ_RETVAL(handled); 9611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int lance_rx( struct net_device *dev ) 965454d7c9b14e20fd1949e2686e9de4a2926e01476Wang Chen{ 966454d7c9b14e20fd1949e2686e9de4a2926e01476Wang Chen struct lance_private *lp = netdev_priv(dev); 9671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int entry = lp->cur_rx & RX_RING_MOD_MASK; 9681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 9691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK( 2, ( "%s: rx int, flag=%04x\n", dev->name, 9711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->rx_head[entry].flag )); 9721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* If we own the next entry, it's a new packet. Send it up. */ 9741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while( (MEM->rx_head[entry].flag & RMD1_OWN) == RMD1_OWN_HOST ) { 9751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct lance_rx_head *head = &(MEM->rx_head[entry]); 9761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int status = head->flag; 9771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status != (RMD1_ENP|RMD1_STP)) { /* There was an error. */ 9791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* There is a tricky error noted by John Murphy, 9801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds <murf@perftech.com> to Russ Nelson: Even with full-sized 9811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buffers it's possible for a jabber packet to use two 9821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buffers, with only the last correctly noting the error. */ 9831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status & RMD1_ENP) /* Only count a general error at the */ 98409f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik dev->stats.rx_errors++; /* end of a packet.*/ 98509f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik if (status & RMD1_FRAM) dev->stats.rx_frame_errors++; 98609f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik if (status & RMD1_OFLO) dev->stats.rx_over_errors++; 98709f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik if (status & RMD1_CRC) dev->stats.rx_crc_errors++; 98809f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik if (status & RMD1_BUFF) dev->stats.rx_fifo_errors++; 9891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds head->flag &= (RMD1_ENP|RMD1_STP); 9901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 9911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Malloc up new buffer, compatible with net-3. */ 9921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds short pkt_len = head->msg_length & 0xfff; 9931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sk_buff *skb; 9941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (pkt_len < 60) { 9961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk( "%s: Runt packet!\n", dev->name ); 99709f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik dev->stats.rx_errors++; 9981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else { 10001d266430546acf01438ae42d0a7370db4817e2adPradeep A Dalvi skb = netdev_alloc_skb(dev, pkt_len + 2); 10011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (skb == NULL) { 10021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK( 1, ( "%s: Memory squeeze, deferring packet.\n", 10031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->name )); 10041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for( i = 0; i < RX_RING_SIZE; i++ ) 10051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (MEM->rx_head[(entry+i) & RX_RING_MOD_MASK].flag & 10061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds RMD1_OWN_CHIP) 10071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 10081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (i > RX_RING_SIZE - 2) { 101009f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik dev->stats.rx_dropped++; 10111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds head->flag |= RMD1_OWN_CHIP; 10121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->cur_rx++; 10131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 10151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (lance_debug >= 3) { 10180795af5729b18218767fab27c44b1384f72dc9adJoe Perches u_char *data = PKTBUF_ADDR(head); 10190795af5729b18218767fab27c44b1384f72dc9adJoe Perches 1020e174961ca1a0b28f7abf0be47973ad57cb74e5f0Johannes Berg printk(KERN_DEBUG "%s: RX pkt type 0x%04x from %pM to %pM " 10210795af5729b18218767fab27c44b1384f72dc9adJoe Perches "data %02x %02x %02x %02x %02x %02x %02x %02x " 10221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "len %d\n", 10230795af5729b18218767fab27c44b1384f72dc9adJoe Perches dev->name, ((u_short *)data)[6], 1024e174961ca1a0b28f7abf0be47973ad57cb74e5f0Johannes Berg &data[6], data, 10251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data[15], data[16], data[17], data[18], 10261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data[19], data[20], data[21], data[22], 10270795af5729b18218767fab27c44b1384f72dc9adJoe Perches pkt_len); 10281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb_reserve( skb, 2 ); /* 16 byte align */ 10311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb_put( skb, pkt_len ); /* Make room */ 10321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->memcpy_f( skb->data, PKTBUF_ADDR(head), pkt_len ); 10331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb->protocol = eth_type_trans( skb, dev ); 10341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netif_rx( skb ); 103509f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik dev->stats.rx_packets++; 103609f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik dev->stats.rx_bytes += pkt_len; 10371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds head->flag |= RMD1_OWN_CHIP; 10411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds entry = (++lp->cur_rx) & RX_RING_MOD_MASK; 10421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->cur_rx &= RX_RING_MOD_MASK; 10441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* From lance.c (Donald Becker): */ 10461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* We should check that at least two ring entries are free. If not, 10471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds we should free one and mark stats->rx_dropped++. */ 10481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 10501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int lance_close( struct net_device *dev ) 1054454d7c9b14e20fd1949e2686e9de4a2926e01476Wang Chen{ 1055454d7c9b14e20fd1949e2686e9de4a2926e01476Wang Chen struct lance_private *lp = netdev_priv(dev); 10561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct lance_ioreg *IO = lp->iobase; 10571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netif_stop_queue (dev); 10591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds AREG = CSR0; 10611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK( 2, ( "%s: Shutting down ethercard, status was %2.2x.\n", 10631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->name, DREG )); 10641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* We stop the LANCE here -- it occasionally polls 10661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memory if we don't. */ 10671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DREG = CSR0_STOP; 10681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 10701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Set or clear the multicast filter for this adaptor. 10741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds num_addrs == -1 Promiscuous mode, receive all packets 10751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds num_addrs == 0 Normal mode, clear multicast list 10761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds num_addrs > 0 Multicast mode, receive normal and MC packets, and do 10771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds best-effort filtering. 10781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 10791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void set_multicast_list( struct net_device *dev ) 1081454d7c9b14e20fd1949e2686e9de4a2926e01476Wang Chen{ 1082454d7c9b14e20fd1949e2686e9de4a2926e01476Wang Chen struct lance_private *lp = netdev_priv(dev); 10831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct lance_ioreg *IO = lp->iobase; 10841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (netif_running(dev)) 10861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Only possible if board is already started */ 10871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 10881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* We take the simple way out and always enable promiscuous mode. */ 10901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DREG = CSR0_STOP; /* Temporarily stop the lance. */ 10911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev->flags & IFF_PROMISC) { 10931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Log any net taps. */ 1094d5b20697ca37d80cc4ec2ba3c5ddf1339dc1d49aAndy Gospodarek DPRINTK( 2, ( "%s: Promiscuous mode enabled.\n", dev->name )); 10951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds REGA( CSR15 ) = 0x8000; /* Set promiscuous mode */ 10961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 10971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds short multicast_table[4]; 10984cd24eaf0c6ee7f0242e34ee77ec899f255e66b5Jiri Pirko int num_addrs = netdev_mc_count(dev); 10991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 11001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* We don't use the multicast table, but rely on upper-layer 11011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * filtering. */ 11021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset( multicast_table, (num_addrs == 0) ? 0 : -1, 11031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof(multicast_table) ); 11041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for( i = 0; i < 4; i++ ) 11051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds REGA( CSR8+i ) = multicast_table[i]; 11061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds REGA( CSR15 ) = 0; /* Unset promiscuous mode */ 11071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 11101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Always set BSWP after a STOP as STOP puts it back into 11111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * little endian mode. 11121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 11131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds REGA( CSR3 ) = CSR3_BSWP | (lp->cardtype == PAM_CARD ? CSR3_ACON : 0); 11141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Resume normal operation and reset AREG to CSR0 */ 11161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds REGA( CSR0 ) = CSR0_IDON | CSR0_INEA | CSR0_STRT; 11171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 11181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* This is needed for old RieblCards and possible for new RieblCards */ 11211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int lance_set_mac_address( struct net_device *dev, void *addr ) 1123454d7c9b14e20fd1949e2686e9de4a2926e01476Wang Chen{ 1124454d7c9b14e20fd1949e2686e9de4a2926e01476Wang Chen struct lance_private *lp = netdev_priv(dev); 11251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sockaddr *saddr = addr; 11261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 11271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (lp->cardtype != OLD_RIEBL && lp->cardtype != NEW_RIEBL) 1129807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet return -EOPNOTSUPP; 11301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (netif_running(dev)) { 11321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Only possible while card isn't started */ 11331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK( 1, ( "%s: hwaddr can be set only while card isn't open.\n", 11341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->name )); 1135807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet return -EIO; 11361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memcpy( dev->dev_addr, saddr->sa_data, dev->addr_len ); 11391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for( i = 0; i < 6; i++ ) 11401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEM->init.hwaddr[i] = dev->dev_addr[i^1]; /* <- 16 bit swap! */ 11411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->memcpy_f( RIEBL_HWADDR_ADDR, dev->dev_addr, 6 ); 11421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* set also the magic for future sessions */ 11431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *RIEBL_MAGIC_ADDR = RIEBL_MAGIC; 11441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1145807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet return 0; 11461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 11471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11486aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik 11491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef MODULE 11501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct net_device *atarilance_dev; 11511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 115253e7c46b0680ccc3ac67a2b8cd7f050569836e44Jon Schindlerstatic int __init atarilance_module_init(void) 11531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 11541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atarilance_dev = atarilance_probe(-1); 11551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (IS_ERR(atarilance_dev)) 11561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return PTR_ERR(atarilance_dev); 11571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 11581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 11591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 116053e7c46b0680ccc3ac67a2b8cd7f050569836e44Jon Schindlerstatic void __exit atarilance_module_exit(void) 11611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 11621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unregister_netdev(atarilance_dev); 11631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds free_irq(atarilance_dev->irq, atarilance_dev); 11641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds free_netdev(atarilance_dev); 11651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 116653e7c46b0680ccc3ac67a2b8cd7f050569836e44Jon Schindlermodule_init(atarilance_module_init); 116753e7c46b0680ccc3ac67a2b8cd7f050569836e44Jon Schindlermodule_exit(atarilance_module_exit); 11681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif /* MODULE */ 11696aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik 11701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 11721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Local variables: 11731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * c-indent-level: 4 11741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * tab-width: 4 11751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * End: 11761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1177