xref: /openbmc/linux/drivers/net/ethernet/amd/atarilance.c (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
1b955f6caSJeff Kirsher /* atarilance.c: Ethernet driver for VME Lance cards on the Atari */
2b955f6caSJeff Kirsher /*
3b955f6caSJeff Kirsher 	Written 1995/96 by Roman Hodek (Roman.Hodek@informatik.uni-erlangen.de)
4b955f6caSJeff Kirsher 
5b955f6caSJeff Kirsher 	This software may be used and distributed according to the terms
6b955f6caSJeff Kirsher 	of the GNU General Public License, incorporated herein by reference.
7b955f6caSJeff Kirsher 
8b955f6caSJeff Kirsher 	This drivers was written with the following sources of reference:
9b955f6caSJeff Kirsher 	 - The driver for the Riebl Lance card by the TU Vienna.
10b955f6caSJeff Kirsher 	 - The modified TUW driver for PAM's VME cards
11b955f6caSJeff Kirsher 	 - The PC-Linux driver for Lance cards (but this is for bus master
12b955f6caSJeff Kirsher        cards, not the shared memory ones)
13b955f6caSJeff Kirsher 	 - The Amiga Ariadne driver
14b955f6caSJeff Kirsher 
15b955f6caSJeff Kirsher 	v1.0: (in 1.2.13pl4/0.9.13)
16b955f6caSJeff Kirsher 	      Initial version
17b955f6caSJeff Kirsher 	v1.1: (in 1.2.13pl5)
18b955f6caSJeff Kirsher 	      more comments
19b955f6caSJeff Kirsher 		  deleted some debugging stuff
20b955f6caSJeff Kirsher 		  optimized register access (keep AREG pointing to CSR0)
21b955f6caSJeff Kirsher 		  following AMD, CSR0_STRT should be set only after IDON is detected
22b955f6caSJeff Kirsher 		  use memcpy() for data transfers, that also employs long word moves
23b955f6caSJeff Kirsher 		  better probe procedure for 24-bit systems
24b955f6caSJeff Kirsher           non-VME-RieblCards need extra delays in memcpy
25b955f6caSJeff Kirsher 		  must also do write test, since 0xfxe00000 may hit ROM
26b955f6caSJeff Kirsher 		  use 8/32 tx/rx buffers, which should give better NFS performance;
27b955f6caSJeff Kirsher 		    this is made possible by shifting the last packet buffer after the
28b955f6caSJeff Kirsher 		    RieblCard reserved area
29b955f6caSJeff Kirsher     v1.2: (in 1.2.13pl8)
30b955f6caSJeff Kirsher 	      again fixed probing for the Falcon; 0xfe01000 hits phys. 0x00010000
31b955f6caSJeff Kirsher 		  and thus RAM, in case of no Lance found all memory contents have to
32b955f6caSJeff Kirsher 		  be restored!
33b955f6caSJeff Kirsher 		  Now possible to compile as module.
34b955f6caSJeff Kirsher 	v1.3: 03/30/96 Jes Sorensen, Roman (in 1.3)
35b955f6caSJeff Kirsher 	      Several little 1.3 adaptions
36b955f6caSJeff Kirsher 		  When the lance is stopped it jumps back into little-endian
37b955f6caSJeff Kirsher 		  mode. It is therefore necessary to put it back where it
38b955f6caSJeff Kirsher 		  belongs, in big endian mode, in order to make things work.
39b955f6caSJeff Kirsher 		  This might be the reason why multicast-mode didn't work
40b955f6caSJeff Kirsher 		  before, but I'm not able to test it as I only got an Amiga
41b955f6caSJeff Kirsher 		  (we had similar problems with the A2065 driver).
42b955f6caSJeff Kirsher 
43b955f6caSJeff Kirsher */
44b955f6caSJeff Kirsher 
4506324664SKees Cook static const char version[] = "atarilance.c: v1.3 04/04/96 "
46b955f6caSJeff Kirsher 			      "Roman.Hodek@informatik.uni-erlangen.de\n";
47b955f6caSJeff Kirsher 
48b955f6caSJeff Kirsher #include <linux/netdevice.h>
49b955f6caSJeff Kirsher #include <linux/etherdevice.h>
50b955f6caSJeff Kirsher #include <linux/module.h>
51b955f6caSJeff Kirsher #include <linux/stddef.h>
52b955f6caSJeff Kirsher #include <linux/kernel.h>
53b955f6caSJeff Kirsher #include <linux/string.h>
54b955f6caSJeff Kirsher #include <linux/errno.h>
55b955f6caSJeff Kirsher #include <linux/skbuff.h>
56b955f6caSJeff Kirsher #include <linux/interrupt.h>
57b955f6caSJeff Kirsher #include <linux/init.h>
58b955f6caSJeff Kirsher #include <linux/bitops.h>
59b955f6caSJeff Kirsher 
60b955f6caSJeff Kirsher #include <asm/setup.h>
61b955f6caSJeff Kirsher #include <asm/irq.h>
62b955f6caSJeff Kirsher #include <asm/atarihw.h>
63b955f6caSJeff Kirsher #include <asm/atariints.h>
64b955f6caSJeff Kirsher #include <asm/io.h>
65b955f6caSJeff Kirsher 
66b955f6caSJeff Kirsher /* Debug level:
67b955f6caSJeff Kirsher  *  0 = silent, print only serious errors
68b955f6caSJeff Kirsher  *  1 = normal, print error messages
69b955f6caSJeff Kirsher  *  2 = debug, print debug infos
70b955f6caSJeff Kirsher  *  3 = debug, print even more debug infos (packet data)
71b955f6caSJeff Kirsher  */
72b955f6caSJeff Kirsher 
73b955f6caSJeff Kirsher #define	LANCE_DEBUG	1
74b955f6caSJeff Kirsher 
75b955f6caSJeff Kirsher #ifdef LANCE_DEBUG
76b955f6caSJeff Kirsher static int lance_debug = LANCE_DEBUG;
77b955f6caSJeff Kirsher #else
78b955f6caSJeff Kirsher static int lance_debug = 1;
79b955f6caSJeff Kirsher #endif
80b955f6caSJeff Kirsher module_param(lance_debug, int, 0);
81b955f6caSJeff Kirsher MODULE_PARM_DESC(lance_debug, "atarilance debug level (0-3)");
82b955f6caSJeff Kirsher MODULE_LICENSE("GPL");
83b955f6caSJeff Kirsher 
84b955f6caSJeff Kirsher /* Print debug messages on probing? */
85b955f6caSJeff Kirsher #undef LANCE_DEBUG_PROBE
86b955f6caSJeff Kirsher 
87b955f6caSJeff Kirsher #define	DPRINTK(n,a)							\
88b955f6caSJeff Kirsher 	do {										\
89b955f6caSJeff Kirsher 		if (lance_debug >= n)					\
90b955f6caSJeff Kirsher 			printk a;							\
91b955f6caSJeff Kirsher 	} while( 0 )
92b955f6caSJeff Kirsher 
93b955f6caSJeff Kirsher #ifdef LANCE_DEBUG_PROBE
94b955f6caSJeff Kirsher # define PROBE_PRINT(a)	printk a
95b955f6caSJeff Kirsher #else
96b955f6caSJeff Kirsher # define PROBE_PRINT(a)
97b955f6caSJeff Kirsher #endif
98b955f6caSJeff Kirsher 
99b955f6caSJeff Kirsher /* These define the number of Rx and Tx buffers as log2. (Only powers
100b955f6caSJeff Kirsher  * of two are valid)
101b955f6caSJeff Kirsher  * Much more rx buffers (32) are reserved than tx buffers (8), since receiving
102b955f6caSJeff Kirsher  * is more time critical then sending and packets may have to remain in the
103b955f6caSJeff Kirsher  * board's memory when main memory is low.
104b955f6caSJeff Kirsher  */
105b955f6caSJeff Kirsher 
106b955f6caSJeff Kirsher #define TX_LOG_RING_SIZE			3
107b955f6caSJeff Kirsher #define RX_LOG_RING_SIZE			5
108b955f6caSJeff Kirsher 
109b955f6caSJeff Kirsher /* These are the derived values */
110b955f6caSJeff Kirsher 
111b955f6caSJeff Kirsher #define TX_RING_SIZE			(1 << TX_LOG_RING_SIZE)
112b955f6caSJeff Kirsher #define TX_RING_LEN_BITS		(TX_LOG_RING_SIZE << 5)
113b955f6caSJeff Kirsher #define	TX_RING_MOD_MASK		(TX_RING_SIZE - 1)
114b955f6caSJeff Kirsher 
115b955f6caSJeff Kirsher #define RX_RING_SIZE			(1 << RX_LOG_RING_SIZE)
116b955f6caSJeff Kirsher #define RX_RING_LEN_BITS		(RX_LOG_RING_SIZE << 5)
117b955f6caSJeff Kirsher #define	RX_RING_MOD_MASK		(RX_RING_SIZE - 1)
118b955f6caSJeff Kirsher 
119b955f6caSJeff Kirsher #define TX_TIMEOUT	(HZ/5)
120b955f6caSJeff Kirsher 
121b955f6caSJeff Kirsher /* The LANCE Rx and Tx ring descriptors. */
122b955f6caSJeff Kirsher struct lance_rx_head {
123b955f6caSJeff Kirsher 	unsigned short			base;		/* Low word of base addr */
124b955f6caSJeff Kirsher 	volatile unsigned char	flag;
125b955f6caSJeff Kirsher 	unsigned char			base_hi;	/* High word of base addr (unused) */
126b955f6caSJeff Kirsher 	short					buf_length;	/* This length is 2s complement! */
127b955f6caSJeff Kirsher 	volatile short			msg_length;	/* This length is "normal". */
128b955f6caSJeff Kirsher };
129b955f6caSJeff Kirsher 
130b955f6caSJeff Kirsher struct lance_tx_head {
131b955f6caSJeff Kirsher 	unsigned short			base;		/* Low word of base addr */
132b955f6caSJeff Kirsher 	volatile unsigned char	flag;
133b955f6caSJeff Kirsher 	unsigned char			base_hi;	/* High word of base addr (unused) */
134b955f6caSJeff Kirsher 	short					length;		/* Length is 2s complement! */
135b955f6caSJeff Kirsher 	volatile short			misc;
136b955f6caSJeff Kirsher };
137b955f6caSJeff Kirsher 
138b955f6caSJeff Kirsher struct ringdesc {
139b955f6caSJeff Kirsher 	unsigned short	adr_lo;		/* Low 16 bits of address */
140b955f6caSJeff Kirsher 	unsigned char	len;		/* Length bits */
141b955f6caSJeff Kirsher 	unsigned char	adr_hi;		/* High 8 bits of address (unused) */
142b955f6caSJeff Kirsher };
143b955f6caSJeff Kirsher 
144b955f6caSJeff Kirsher /* The LANCE initialization block, described in databook. */
145b955f6caSJeff Kirsher struct lance_init_block {
146b955f6caSJeff Kirsher 	unsigned short	mode;		/* Pre-set mode */
147b955f6caSJeff Kirsher 	unsigned char	hwaddr[6];	/* Physical ethernet address */
148b955f6caSJeff Kirsher 	unsigned		filter[2];	/* Multicast filter (unused). */
149b955f6caSJeff Kirsher 	/* Receive and transmit ring base, along with length bits. */
150b955f6caSJeff Kirsher 	struct ringdesc	rx_ring;
151b955f6caSJeff Kirsher 	struct ringdesc	tx_ring;
152b955f6caSJeff Kirsher };
153b955f6caSJeff Kirsher 
154b955f6caSJeff Kirsher /* The whole layout of the Lance shared memory */
155b955f6caSJeff Kirsher struct lance_memory {
156b955f6caSJeff Kirsher 	struct lance_init_block	init;
157b955f6caSJeff Kirsher 	struct lance_tx_head	tx_head[TX_RING_SIZE];
158b955f6caSJeff Kirsher 	struct lance_rx_head	rx_head[RX_RING_SIZE];
159c2dfc7d2SGustavo A. R. Silva 	char					packet_area[];	/* packet data follow after the
160b955f6caSJeff Kirsher 											 * init block and the ring
161b955f6caSJeff Kirsher 											 * descriptors and are located
162b955f6caSJeff Kirsher 											 * at runtime */
163b955f6caSJeff Kirsher };
164b955f6caSJeff Kirsher 
165b955f6caSJeff Kirsher /* RieblCard specifics:
166b955f6caSJeff Kirsher  * The original TOS driver for these cards reserves the area from offset
167b955f6caSJeff Kirsher  * 0xee70 to 0xeebb for storing configuration data. Of interest to us is the
168b955f6caSJeff Kirsher  * Ethernet address there, and the magic for verifying the data's validity.
169b955f6caSJeff Kirsher  * The reserved area isn't touch by packet buffers. Furthermore, offset 0xfffe
170b955f6caSJeff Kirsher  * is reserved for the interrupt vector number.
171b955f6caSJeff Kirsher  */
172b955f6caSJeff Kirsher #define	RIEBL_RSVD_START	0xee70
173b955f6caSJeff Kirsher #define	RIEBL_RSVD_END		0xeec0
174b955f6caSJeff Kirsher #define RIEBL_MAGIC			0x09051990
175b955f6caSJeff Kirsher #define RIEBL_MAGIC_ADDR	((unsigned long *)(((char *)MEM) + 0xee8a))
176b955f6caSJeff Kirsher #define RIEBL_HWADDR_ADDR	((unsigned char *)(((char *)MEM) + 0xee8e))
177b955f6caSJeff Kirsher #define RIEBL_IVEC_ADDR		((unsigned short *)(((char *)MEM) + 0xfffe))
178b955f6caSJeff Kirsher 
179b955f6caSJeff Kirsher /* This is a default address for the old RieblCards without a battery
180b955f6caSJeff Kirsher  * that have no ethernet address at boot time. 00:00:36:04 is the
181b955f6caSJeff Kirsher  * prefix for Riebl cards, the 00:00 at the end is arbitrary.
182b955f6caSJeff Kirsher  */
183b955f6caSJeff Kirsher 
184b955f6caSJeff Kirsher static unsigned char OldRieblDefHwaddr[6] = {
185b955f6caSJeff Kirsher 	0x00, 0x00, 0x36, 0x04, 0x00, 0x00
186b955f6caSJeff Kirsher };
187b955f6caSJeff Kirsher 
188b955f6caSJeff Kirsher 
189b955f6caSJeff Kirsher /* I/O registers of the Lance chip */
190b955f6caSJeff Kirsher 
191b955f6caSJeff Kirsher struct lance_ioreg {
192b955f6caSJeff Kirsher /* base+0x0 */	volatile unsigned short	data;
193b955f6caSJeff Kirsher /* base+0x2 */	volatile unsigned short	addr;
194b955f6caSJeff Kirsher 				unsigned char			_dummy1[3];
195b955f6caSJeff Kirsher /* base+0x7 */	volatile unsigned char	ivec;
196b955f6caSJeff Kirsher 				unsigned char			_dummy2[5];
197b955f6caSJeff Kirsher /* base+0xd */	volatile unsigned char	eeprom;
198b955f6caSJeff Kirsher 				unsigned char			_dummy3;
199b955f6caSJeff Kirsher /* base+0xf */	volatile unsigned char	mem;
200b955f6caSJeff Kirsher };
201b955f6caSJeff Kirsher 
202b955f6caSJeff Kirsher /* Types of boards this driver supports */
203b955f6caSJeff Kirsher 
204b955f6caSJeff Kirsher enum lance_type {
205b955f6caSJeff Kirsher 	OLD_RIEBL,		/* old Riebl card without battery */
206b955f6caSJeff Kirsher 	NEW_RIEBL,		/* new Riebl card with battery */
207b955f6caSJeff Kirsher 	PAM_CARD		/* PAM card with EEPROM */
208b955f6caSJeff Kirsher };
209b955f6caSJeff Kirsher 
210b955f6caSJeff Kirsher static char *lance_names[] = {
211b955f6caSJeff Kirsher 	"Riebl-Card (without battery)",
212b955f6caSJeff Kirsher 	"Riebl-Card (with battery)",
213b955f6caSJeff Kirsher 	"PAM intern card"
214b955f6caSJeff Kirsher };
215b955f6caSJeff Kirsher 
216b955f6caSJeff Kirsher /* The driver's private device structure */
217b955f6caSJeff Kirsher 
218b955f6caSJeff Kirsher struct lance_private {
219b955f6caSJeff Kirsher 	enum lance_type		cardtype;
220b955f6caSJeff Kirsher 	struct lance_ioreg	*iobase;
221b955f6caSJeff Kirsher 	struct lance_memory	*mem;
222b955f6caSJeff Kirsher 	int		 	cur_rx, cur_tx;	/* The next free ring entry */
223b955f6caSJeff Kirsher 	int			dirty_tx;		/* Ring entries to be freed. */
224b955f6caSJeff Kirsher 				/* copy function */
225b955f6caSJeff Kirsher 	void			*(*memcpy_f)( void *, const void *, size_t );
226b955f6caSJeff Kirsher /* This must be long for set_bit() */
227b955f6caSJeff Kirsher 	long			tx_full;
228b955f6caSJeff Kirsher 	spinlock_t		devlock;
229b955f6caSJeff Kirsher };
230b955f6caSJeff Kirsher 
231b955f6caSJeff Kirsher /* I/O register access macros */
232b955f6caSJeff Kirsher 
233b955f6caSJeff Kirsher #define	MEM		lp->mem
234b955f6caSJeff Kirsher #define	DREG	IO->data
235b955f6caSJeff Kirsher #define	AREG	IO->addr
236b955f6caSJeff Kirsher #define	REGA(a)	(*( AREG = (a), &DREG ))
237b955f6caSJeff Kirsher 
238b955f6caSJeff Kirsher /* Definitions for packet buffer access: */
239b955f6caSJeff Kirsher #define PKT_BUF_SZ		1544
240b955f6caSJeff Kirsher /* Get the address of a packet buffer corresponding to a given buffer head */
241b955f6caSJeff Kirsher #define	PKTBUF_ADDR(head)	(((unsigned char *)(MEM)) + (head)->base)
242b955f6caSJeff Kirsher 
243b955f6caSJeff Kirsher /* Possible memory/IO addresses for probing */
244b955f6caSJeff Kirsher 
245b955f6caSJeff Kirsher static struct lance_addr {
246b955f6caSJeff Kirsher 	unsigned long	memaddr;
247b955f6caSJeff Kirsher 	unsigned long	ioaddr;
248b955f6caSJeff Kirsher 	int				slow_flag;
249b955f6caSJeff Kirsher } lance_addr_list[] = {
250b955f6caSJeff Kirsher 	{ 0xfe010000, 0xfe00fff0, 0 },	/* RieblCard VME in TT */
251b955f6caSJeff Kirsher 	{ 0xffc10000, 0xffc0fff0, 0 },	/* RieblCard VME in MegaSTE
252b955f6caSJeff Kirsher 									   (highest byte stripped) */
253b955f6caSJeff Kirsher 	{ 0xffe00000, 0xffff7000, 1 },	/* RieblCard in ST
254b955f6caSJeff Kirsher 									   (highest byte stripped) */
255b955f6caSJeff Kirsher 	{ 0xffd00000, 0xffff7000, 1 },	/* RieblCard in ST with hw modif. to
256b955f6caSJeff Kirsher 									   avoid conflict with ROM
257b955f6caSJeff Kirsher 									   (highest byte stripped) */
258b955f6caSJeff Kirsher 	{ 0xffcf0000, 0xffcffff0, 0 },	/* PAMCard VME in TT and MSTE
259b955f6caSJeff Kirsher 									   (highest byte stripped) */
260b955f6caSJeff Kirsher 	{ 0xfecf0000, 0xfecffff0, 0 },	/* Rhotron's PAMCard VME in TT and MSTE
261b955f6caSJeff Kirsher 									   (highest byte stripped) */
262b955f6caSJeff Kirsher };
263b955f6caSJeff Kirsher 
264b955f6caSJeff Kirsher #define	N_LANCE_ADDR	ARRAY_SIZE(lance_addr_list)
265b955f6caSJeff Kirsher 
266b955f6caSJeff Kirsher 
267b955f6caSJeff Kirsher /* Definitions for the Lance */
268b955f6caSJeff Kirsher 
269b955f6caSJeff Kirsher /* tx_head flags */
270b955f6caSJeff Kirsher #define TMD1_ENP		0x01	/* end of packet */
271b955f6caSJeff Kirsher #define TMD1_STP		0x02	/* start of packet */
272b955f6caSJeff Kirsher #define TMD1_DEF		0x04	/* deferred */
273b955f6caSJeff Kirsher #define TMD1_ONE		0x08	/* one retry needed */
274b955f6caSJeff Kirsher #define TMD1_MORE		0x10	/* more than one retry needed */
275b955f6caSJeff Kirsher #define TMD1_ERR		0x40	/* error summary */
276b955f6caSJeff Kirsher #define TMD1_OWN 		0x80	/* ownership (set: chip owns) */
277b955f6caSJeff Kirsher 
278b955f6caSJeff Kirsher #define TMD1_OWN_CHIP	TMD1_OWN
279b955f6caSJeff Kirsher #define TMD1_OWN_HOST	0
280b955f6caSJeff Kirsher 
281b955f6caSJeff Kirsher /* tx_head misc field */
282b955f6caSJeff Kirsher #define TMD3_TDR		0x03FF	/* Time Domain Reflectometry counter */
283b955f6caSJeff Kirsher #define TMD3_RTRY		0x0400	/* failed after 16 retries */
284b955f6caSJeff Kirsher #define TMD3_LCAR		0x0800	/* carrier lost */
285b955f6caSJeff Kirsher #define TMD3_LCOL		0x1000	/* late collision */
286b955f6caSJeff Kirsher #define TMD3_UFLO		0x4000	/* underflow (late memory) */
287b955f6caSJeff Kirsher #define TMD3_BUFF		0x8000	/* buffering error (no ENP) */
288b955f6caSJeff Kirsher 
289b955f6caSJeff Kirsher /* rx_head flags */
290b955f6caSJeff Kirsher #define RMD1_ENP		0x01	/* end of packet */
291b955f6caSJeff Kirsher #define RMD1_STP		0x02	/* start of packet */
292b955f6caSJeff Kirsher #define RMD1_BUFF		0x04	/* buffer error */
293b955f6caSJeff Kirsher #define RMD1_CRC		0x08	/* CRC error */
294b955f6caSJeff Kirsher #define RMD1_OFLO		0x10	/* overflow */
295b955f6caSJeff Kirsher #define RMD1_FRAM		0x20	/* framing error */
296b955f6caSJeff Kirsher #define RMD1_ERR		0x40	/* error summary */
297b955f6caSJeff Kirsher #define RMD1_OWN 		0x80	/* ownership (set: ship owns) */
298b955f6caSJeff Kirsher 
299b955f6caSJeff Kirsher #define RMD1_OWN_CHIP	RMD1_OWN
300b955f6caSJeff Kirsher #define RMD1_OWN_HOST	0
301b955f6caSJeff Kirsher 
302b955f6caSJeff Kirsher /* register names */
303b955f6caSJeff Kirsher #define CSR0	0		/* mode/status */
304b955f6caSJeff Kirsher #define CSR1	1		/* init block addr (low) */
305b955f6caSJeff Kirsher #define CSR2	2		/* init block addr (high) */
306b955f6caSJeff Kirsher #define CSR3	3		/* misc */
307b955f6caSJeff Kirsher #define CSR8	8	  	/* address filter */
308b955f6caSJeff Kirsher #define CSR15	15		/* promiscuous mode */
309b955f6caSJeff Kirsher 
310b955f6caSJeff Kirsher /* CSR0 */
311b955f6caSJeff Kirsher /* (R=readable, W=writeable, S=set on write, C=clear on write) */
312b955f6caSJeff Kirsher #define CSR0_INIT	0x0001		/* initialize (RS) */
313b955f6caSJeff Kirsher #define CSR0_STRT	0x0002		/* start (RS) */
314b955f6caSJeff Kirsher #define CSR0_STOP	0x0004		/* stop (RS) */
315b955f6caSJeff Kirsher #define CSR0_TDMD	0x0008		/* transmit demand (RS) */
316b955f6caSJeff Kirsher #define CSR0_TXON	0x0010		/* transmitter on (R) */
317b955f6caSJeff Kirsher #define CSR0_RXON	0x0020		/* receiver on (R) */
318b955f6caSJeff Kirsher #define CSR0_INEA	0x0040		/* interrupt enable (RW) */
319b955f6caSJeff Kirsher #define CSR0_INTR	0x0080		/* interrupt active (R) */
320b955f6caSJeff Kirsher #define CSR0_IDON	0x0100		/* initialization done (RC) */
321b955f6caSJeff Kirsher #define CSR0_TINT	0x0200		/* transmitter interrupt (RC) */
322b955f6caSJeff Kirsher #define CSR0_RINT	0x0400		/* receiver interrupt (RC) */
323b955f6caSJeff Kirsher #define CSR0_MERR	0x0800		/* memory error (RC) */
324b955f6caSJeff Kirsher #define CSR0_MISS	0x1000		/* missed frame (RC) */
325b955f6caSJeff Kirsher #define CSR0_CERR	0x2000		/* carrier error (no heartbeat :-) (RC) */
326b955f6caSJeff Kirsher #define CSR0_BABL	0x4000		/* babble: tx-ed too many bits (RC) */
327b955f6caSJeff Kirsher #define CSR0_ERR	0x8000		/* error (RC) */
328b955f6caSJeff Kirsher 
329b955f6caSJeff Kirsher /* CSR3 */
330b955f6caSJeff Kirsher #define CSR3_BCON	0x0001		/* byte control */
331b955f6caSJeff Kirsher #define CSR3_ACON	0x0002		/* ALE control */
332b955f6caSJeff Kirsher #define CSR3_BSWP	0x0004		/* byte swap (1=big endian) */
333b955f6caSJeff Kirsher 
334b955f6caSJeff Kirsher 
335b955f6caSJeff Kirsher 
336b955f6caSJeff Kirsher /***************************** Prototypes *****************************/
337b955f6caSJeff Kirsher 
338b955f6caSJeff Kirsher static unsigned long lance_probe1( struct net_device *dev, struct lance_addr
339b955f6caSJeff Kirsher                                    *init_rec );
340b955f6caSJeff Kirsher static int lance_open( struct net_device *dev );
341b955f6caSJeff Kirsher static void lance_init_ring( struct net_device *dev );
342fe72352eSYueHaibing static netdev_tx_t lance_start_xmit(struct sk_buff *skb,
343fe72352eSYueHaibing 				    struct net_device *dev);
344b955f6caSJeff Kirsher static irqreturn_t lance_interrupt( int irq, void *dev_id );
345b955f6caSJeff Kirsher static int lance_rx( struct net_device *dev );
346b955f6caSJeff Kirsher static int lance_close( struct net_device *dev );
347b955f6caSJeff Kirsher static void set_multicast_list( struct net_device *dev );
348b955f6caSJeff Kirsher static int lance_set_mac_address( struct net_device *dev, void *addr );
3490290bd29SMichael S. Tsirkin static void lance_tx_timeout (struct net_device *dev, unsigned int txqueue);
350b955f6caSJeff Kirsher 
351b955f6caSJeff Kirsher /************************* End of Prototypes **************************/
352b955f6caSJeff Kirsher 
353b955f6caSJeff Kirsher 
354b955f6caSJeff Kirsher 
355b955f6caSJeff Kirsher 
356b955f6caSJeff Kirsher 
slow_memcpy(void * dst,const void * src,size_t len)357b955f6caSJeff Kirsher static void *slow_memcpy( void *dst, const void *src, size_t len )
358b955f6caSJeff Kirsher 
359b955f6caSJeff Kirsher {	char *cto = dst;
360b955f6caSJeff Kirsher 	const char *cfrom = src;
361b955f6caSJeff Kirsher 
362b955f6caSJeff Kirsher 	while( len-- ) {
363b955f6caSJeff Kirsher 		*cto++ = *cfrom++;
364b955f6caSJeff Kirsher 		MFPDELAY();
365b955f6caSJeff Kirsher 	}
366b955f6caSJeff Kirsher 	return dst;
367b955f6caSJeff Kirsher }
368b955f6caSJeff Kirsher 
369b955f6caSJeff Kirsher 
atarilance_probe(void)370*7191c140SArnd Bergmann static struct net_device * __init atarilance_probe(void)
371b955f6caSJeff Kirsher {
372b955f6caSJeff Kirsher 	int i;
373b955f6caSJeff Kirsher 	static int found;
374b955f6caSJeff Kirsher 	struct net_device *dev;
375b955f6caSJeff Kirsher 	int err = -ENODEV;
376b955f6caSJeff Kirsher 
377b955f6caSJeff Kirsher 	if (!MACH_IS_ATARI || found)
378b955f6caSJeff Kirsher 		/* Assume there's only one board possible... That seems true, since
379b955f6caSJeff Kirsher 		 * the Riebl/PAM board's address cannot be changed. */
380b955f6caSJeff Kirsher 		return ERR_PTR(-ENODEV);
381b955f6caSJeff Kirsher 
382b955f6caSJeff Kirsher 	dev = alloc_etherdev(sizeof(struct lance_private));
383b955f6caSJeff Kirsher 	if (!dev)
384b955f6caSJeff Kirsher 		return ERR_PTR(-ENOMEM);
385b955f6caSJeff Kirsher 
386b955f6caSJeff Kirsher 	for( i = 0; i < N_LANCE_ADDR; ++i ) {
387b955f6caSJeff Kirsher 		if (lance_probe1( dev, &lance_addr_list[i] )) {
388b955f6caSJeff Kirsher 			found = 1;
389b955f6caSJeff Kirsher 			err = register_netdev(dev);
390b955f6caSJeff Kirsher 			if (!err)
391b955f6caSJeff Kirsher 				return dev;
392b955f6caSJeff Kirsher 			free_irq(dev->irq, dev);
393b955f6caSJeff Kirsher 			break;
394b955f6caSJeff Kirsher 		}
395b955f6caSJeff Kirsher 	}
396b955f6caSJeff Kirsher 	free_netdev(dev);
397b955f6caSJeff Kirsher 	return ERR_PTR(err);
398b955f6caSJeff Kirsher }
399b955f6caSJeff Kirsher 
400b955f6caSJeff Kirsher 
401b955f6caSJeff Kirsher /* Derived from hwreg_present() in atari/config.c: */
402b955f6caSJeff Kirsher 
addr_accessible(volatile void * regp,int wordflag,int writeflag)403b955f6caSJeff Kirsher static noinline int __init addr_accessible(volatile void *regp, int wordflag,
404b955f6caSJeff Kirsher 					   int writeflag)
405b955f6caSJeff Kirsher {
406b955f6caSJeff Kirsher 	int		ret;
407b955f6caSJeff Kirsher 	unsigned long	flags;
408b955f6caSJeff Kirsher 	long	*vbr, save_berr;
409b955f6caSJeff Kirsher 
410b955f6caSJeff Kirsher 	local_irq_save(flags);
411b955f6caSJeff Kirsher 
412b955f6caSJeff Kirsher 	__asm__ __volatile__ ( "movec	%/vbr,%0" : "=r" (vbr) : );
413b955f6caSJeff Kirsher 	save_berr = vbr[2];
414b955f6caSJeff Kirsher 
415b955f6caSJeff Kirsher 	__asm__ __volatile__
416b955f6caSJeff Kirsher 	(	"movel	%/sp,%/d1\n\t"
417b955f6caSJeff Kirsher 		"movel	#Lberr,%2@\n\t"
418b955f6caSJeff Kirsher 		"moveq	#0,%0\n\t"
419b955f6caSJeff Kirsher 		"tstl   %3\n\t"
420b955f6caSJeff Kirsher 		"bne	1f\n\t"
421b955f6caSJeff Kirsher 		"moveb	%1@,%/d0\n\t"
422b955f6caSJeff Kirsher 		"nop	\n\t"
423b955f6caSJeff Kirsher 		"bra	2f\n"
424b955f6caSJeff Kirsher "1:		 movew	%1@,%/d0\n\t"
425b955f6caSJeff Kirsher 		"nop	\n"
426b955f6caSJeff Kirsher "2:		 tstl   %4\n\t"
427b955f6caSJeff Kirsher 		"beq	2f\n\t"
428b955f6caSJeff Kirsher 		"tstl	%3\n\t"
429b955f6caSJeff Kirsher 		"bne	1f\n\t"
430b955f6caSJeff Kirsher 		"clrb	%1@\n\t"
431b955f6caSJeff Kirsher 		"nop	\n\t"
432b955f6caSJeff Kirsher 		"moveb	%/d0,%1@\n\t"
433b955f6caSJeff Kirsher 		"nop	\n\t"
434b955f6caSJeff Kirsher 		"bra	2f\n"
435b955f6caSJeff Kirsher "1:		 clrw	%1@\n\t"
436b955f6caSJeff Kirsher 		"nop	\n\t"
437b955f6caSJeff Kirsher 		"movew	%/d0,%1@\n\t"
438b955f6caSJeff Kirsher 		"nop	\n"
439b955f6caSJeff Kirsher "2:		 moveq	#1,%0\n"
440b955f6caSJeff Kirsher "Lberr:	 movel	%/d1,%/sp"
441b955f6caSJeff Kirsher 		: "=&d" (ret)
442b955f6caSJeff Kirsher 		: "a" (regp), "a" (&vbr[2]), "rm" (wordflag), "rm" (writeflag)
443b955f6caSJeff Kirsher 		: "d0", "d1", "memory"
444b955f6caSJeff Kirsher 	);
445b955f6caSJeff Kirsher 
446b955f6caSJeff Kirsher 	vbr[2] = save_berr;
447b955f6caSJeff Kirsher 	local_irq_restore(flags);
448b955f6caSJeff Kirsher 
449b955f6caSJeff Kirsher 	return ret;
450b955f6caSJeff Kirsher }
451b955f6caSJeff Kirsher 
452b955f6caSJeff Kirsher static const struct net_device_ops lance_netdev_ops = {
453b955f6caSJeff Kirsher 	.ndo_open		= lance_open,
454b955f6caSJeff Kirsher 	.ndo_stop		= lance_close,
455b955f6caSJeff Kirsher 	.ndo_start_xmit		= lance_start_xmit,
456afc4b13dSJiri Pirko 	.ndo_set_rx_mode	= set_multicast_list,
457b955f6caSJeff Kirsher 	.ndo_set_mac_address	= lance_set_mac_address,
458b955f6caSJeff Kirsher 	.ndo_tx_timeout		= lance_tx_timeout,
459b955f6caSJeff Kirsher 	.ndo_validate_addr	= eth_validate_addr,
460b955f6caSJeff Kirsher };
461b955f6caSJeff Kirsher 
lance_probe1(struct net_device * dev,struct lance_addr * init_rec)462b955f6caSJeff Kirsher static unsigned long __init lance_probe1( struct net_device *dev,
463b955f6caSJeff Kirsher 					   struct lance_addr *init_rec )
464b955f6caSJeff Kirsher {
465b955f6caSJeff Kirsher 	volatile unsigned short *memaddr =
466b955f6caSJeff Kirsher 		(volatile unsigned short *)init_rec->memaddr;
467b955f6caSJeff Kirsher 	volatile unsigned short *ioaddr =
468b955f6caSJeff Kirsher 		(volatile unsigned short *)init_rec->ioaddr;
469b955f6caSJeff Kirsher 	struct lance_private	*lp;
470b955f6caSJeff Kirsher 	struct lance_ioreg		*IO;
471b955f6caSJeff Kirsher 	int 					i;
472b955f6caSJeff Kirsher 	static int 				did_version;
473b955f6caSJeff Kirsher 	unsigned short			save1, save2;
474c3dc2f71SJakub Kicinski 	u8 addr[ETH_ALEN];
475b955f6caSJeff Kirsher 
476b955f6caSJeff Kirsher 	PROBE_PRINT(( "Probing for Lance card at mem %#lx io %#lx\n",
477b955f6caSJeff Kirsher 				  (long)memaddr, (long)ioaddr ));
478b955f6caSJeff Kirsher 
479b955f6caSJeff Kirsher 	/* Test whether memory readable and writable */
480b955f6caSJeff Kirsher 	PROBE_PRINT(( "lance_probe1: testing memory to be accessible\n" ));
481b955f6caSJeff Kirsher 	if (!addr_accessible( memaddr, 1, 1 )) goto probe_fail;
482b955f6caSJeff Kirsher 
483b955f6caSJeff Kirsher 	/* Written values should come back... */
484b955f6caSJeff Kirsher 	PROBE_PRINT(( "lance_probe1: testing memory to be writable (1)\n" ));
485b955f6caSJeff Kirsher 	save1 = *memaddr;
486b955f6caSJeff Kirsher 	*memaddr = 0x0001;
487b955f6caSJeff Kirsher 	if (*memaddr != 0x0001) goto probe_fail;
488b955f6caSJeff Kirsher 	PROBE_PRINT(( "lance_probe1: testing memory to be writable (2)\n" ));
489b955f6caSJeff Kirsher 	*memaddr = 0x0000;
490b955f6caSJeff Kirsher 	if (*memaddr != 0x0000) goto probe_fail;
491b955f6caSJeff Kirsher 	*memaddr = save1;
492b955f6caSJeff Kirsher 
493b955f6caSJeff Kirsher 	/* First port should be readable and writable */
494b955f6caSJeff Kirsher 	PROBE_PRINT(( "lance_probe1: testing ioport to be accessible\n" ));
495b955f6caSJeff Kirsher 	if (!addr_accessible( ioaddr, 1, 1 )) goto probe_fail;
496b955f6caSJeff Kirsher 
497b955f6caSJeff Kirsher 	/* and written values should be readable */
498b955f6caSJeff Kirsher 	PROBE_PRINT(( "lance_probe1: testing ioport to be writeable\n" ));
499b955f6caSJeff Kirsher 	save2 = ioaddr[1];
500b955f6caSJeff Kirsher 	ioaddr[1] = 0x0001;
501b955f6caSJeff Kirsher 	if (ioaddr[1] != 0x0001) goto probe_fail;
502b955f6caSJeff Kirsher 
503b955f6caSJeff Kirsher 	/* The CSR0_INIT bit should not be readable */
504b955f6caSJeff Kirsher 	PROBE_PRINT(( "lance_probe1: testing CSR0 register function (1)\n" ));
505b955f6caSJeff Kirsher 	save1 = ioaddr[0];
506b955f6caSJeff Kirsher 	ioaddr[1] = CSR0;
507b955f6caSJeff Kirsher 	ioaddr[0] = CSR0_INIT | CSR0_STOP;
508b955f6caSJeff Kirsher 	if (ioaddr[0] != CSR0_STOP) {
509b955f6caSJeff Kirsher 		ioaddr[0] = save1;
510b955f6caSJeff Kirsher 		ioaddr[1] = save2;
511b955f6caSJeff Kirsher 		goto probe_fail;
512b955f6caSJeff Kirsher 	}
513b955f6caSJeff Kirsher 	PROBE_PRINT(( "lance_probe1: testing CSR0 register function (2)\n" ));
514b955f6caSJeff Kirsher 	ioaddr[0] = CSR0_STOP;
515b955f6caSJeff Kirsher 	if (ioaddr[0] != CSR0_STOP) {
516b955f6caSJeff Kirsher 		ioaddr[0] = save1;
517b955f6caSJeff Kirsher 		ioaddr[1] = save2;
518b955f6caSJeff Kirsher 		goto probe_fail;
519b955f6caSJeff Kirsher 	}
520b955f6caSJeff Kirsher 
521b955f6caSJeff Kirsher 	/* Now ok... */
522b955f6caSJeff Kirsher 	PROBE_PRINT(( "lance_probe1: Lance card detected\n" ));
523b955f6caSJeff Kirsher 	goto probe_ok;
524b955f6caSJeff Kirsher 
525b955f6caSJeff Kirsher   probe_fail:
526b955f6caSJeff Kirsher 	return 0;
527b955f6caSJeff Kirsher 
528b955f6caSJeff Kirsher   probe_ok:
529b955f6caSJeff Kirsher 	lp = netdev_priv(dev);
530b955f6caSJeff Kirsher 	MEM = (struct lance_memory *)memaddr;
531b955f6caSJeff Kirsher 	IO = lp->iobase = (struct lance_ioreg *)ioaddr;
532b955f6caSJeff Kirsher 	dev->base_addr = (unsigned long)ioaddr; /* informational only */
533b955f6caSJeff Kirsher 	lp->memcpy_f = init_rec->slow_flag ? slow_memcpy : memcpy;
534b955f6caSJeff Kirsher 
535b955f6caSJeff Kirsher 	REGA( CSR0 ) = CSR0_STOP;
536b955f6caSJeff Kirsher 
537b955f6caSJeff Kirsher 	/* Now test for type: If the eeprom I/O port is readable, it is a
538b955f6caSJeff Kirsher 	 * PAM card */
539b955f6caSJeff Kirsher 	if (addr_accessible( &(IO->eeprom), 0, 0 )) {
540b955f6caSJeff Kirsher 		/* Switch back to Ram */
541b955f6caSJeff Kirsher 		i = IO->mem;
542b955f6caSJeff Kirsher 		lp->cardtype = PAM_CARD;
543b955f6caSJeff Kirsher 	}
544b955f6caSJeff Kirsher 	else if (*RIEBL_MAGIC_ADDR == RIEBL_MAGIC) {
545b955f6caSJeff Kirsher 		lp->cardtype = NEW_RIEBL;
546b955f6caSJeff Kirsher 	}
547b955f6caSJeff Kirsher 	else
548b955f6caSJeff Kirsher 		lp->cardtype = OLD_RIEBL;
549b955f6caSJeff Kirsher 
550b955f6caSJeff Kirsher 	if (lp->cardtype == PAM_CARD ||
551b955f6caSJeff Kirsher 		memaddr == (unsigned short *)0xffe00000) {
552b955f6caSJeff Kirsher 		/* PAMs card and Riebl on ST use level 5 autovector */
5538f2bfe5fSGeert Uytterhoeven 		if (request_irq(IRQ_AUTO_5, lance_interrupt, 0,
554b955f6caSJeff Kirsher 				"PAM,Riebl-ST Ethernet", dev)) {
555b955f6caSJeff Kirsher 			printk( "Lance: request for irq %d failed\n", IRQ_AUTO_5 );
556b955f6caSJeff Kirsher 			return 0;
557b955f6caSJeff Kirsher 		}
55844883eb0SGeert Uytterhoeven 		dev->irq = IRQ_AUTO_5;
559b955f6caSJeff Kirsher 	}
560b955f6caSJeff Kirsher 	else {
56144883eb0SGeert Uytterhoeven 		/* For VME-RieblCards, request a free VME int */
56244883eb0SGeert Uytterhoeven 		unsigned int irq = atari_register_vme_int();
563b955f6caSJeff Kirsher 		if (!irq) {
564b955f6caSJeff Kirsher 			printk( "Lance: request for VME interrupt failed\n" );
565b955f6caSJeff Kirsher 			return 0;
566b955f6caSJeff Kirsher 		}
5678f2bfe5fSGeert Uytterhoeven 		if (request_irq(irq, lance_interrupt, 0, "Riebl-VME Ethernet",
5688f2bfe5fSGeert Uytterhoeven 				dev)) {
56944883eb0SGeert Uytterhoeven 			printk( "Lance: request for irq %u failed\n", irq );
570b955f6caSJeff Kirsher 			return 0;
571b955f6caSJeff Kirsher 		}
572b955f6caSJeff Kirsher 		dev->irq = irq;
573b955f6caSJeff Kirsher 	}
574b955f6caSJeff Kirsher 
575b955f6caSJeff Kirsher 	printk("%s: %s at io %#lx, mem %#lx, irq %d%s, hwaddr ",
576b955f6caSJeff Kirsher 		   dev->name, lance_names[lp->cardtype],
577b955f6caSJeff Kirsher 		   (unsigned long)ioaddr,
578b955f6caSJeff Kirsher 		   (unsigned long)memaddr,
579b955f6caSJeff Kirsher 		   dev->irq,
580b955f6caSJeff Kirsher 		   init_rec->slow_flag ? " (slow memcpy)" : "" );
581b955f6caSJeff Kirsher 
582b955f6caSJeff Kirsher 	/* Get the ethernet address */
583b955f6caSJeff Kirsher 	switch( lp->cardtype ) {
584b955f6caSJeff Kirsher 	case OLD_RIEBL:
585b955f6caSJeff Kirsher 		/* No ethernet address! (Set some default address) */
586a96d317fSJakub Kicinski 		eth_hw_addr_set(dev, OldRieblDefHwaddr);
587b955f6caSJeff Kirsher 		break;
588b955f6caSJeff Kirsher 	case NEW_RIEBL:
589c3dc2f71SJakub Kicinski 		lp->memcpy_f(addr, RIEBL_HWADDR_ADDR, ETH_ALEN);
590c3dc2f71SJakub Kicinski 		eth_hw_addr_set(dev, addr);
591b955f6caSJeff Kirsher 		break;
592b955f6caSJeff Kirsher 	case PAM_CARD:
593b955f6caSJeff Kirsher 		i = IO->eeprom;
594b955f6caSJeff Kirsher 		for( i = 0; i < 6; ++i )
595c3dc2f71SJakub Kicinski 			addr[i] =
596b955f6caSJeff Kirsher 				((((unsigned short *)MEM)[i*2] & 0x0f) << 4) |
597b955f6caSJeff Kirsher 				((((unsigned short *)MEM)[i*2+1] & 0x0f));
598c3dc2f71SJakub Kicinski 		eth_hw_addr_set(dev, addr);
599b955f6caSJeff Kirsher 		i = IO->mem;
600b955f6caSJeff Kirsher 		break;
601b955f6caSJeff Kirsher 	}
602b955f6caSJeff Kirsher 	printk("%pM\n", dev->dev_addr);
603b955f6caSJeff Kirsher 	if (lp->cardtype == OLD_RIEBL) {
604b955f6caSJeff Kirsher 		printk( "%s: Warning: This is a default ethernet address!\n",
605b955f6caSJeff Kirsher 				dev->name );
606b955f6caSJeff Kirsher 		printk( "      Use \"ifconfig hw ether ...\" to set the address.\n" );
607b955f6caSJeff Kirsher 	}
608b955f6caSJeff Kirsher 
609b955f6caSJeff Kirsher 	spin_lock_init(&lp->devlock);
610b955f6caSJeff Kirsher 
611b955f6caSJeff Kirsher 	MEM->init.mode = 0x0000;		/* Disable Rx and Tx. */
612b955f6caSJeff Kirsher 	for( i = 0; i < 6; i++ )
613b955f6caSJeff Kirsher 		MEM->init.hwaddr[i] = dev->dev_addr[i^1]; /* <- 16 bit swap! */
614b955f6caSJeff Kirsher 	MEM->init.filter[0] = 0x00000000;
615b955f6caSJeff Kirsher 	MEM->init.filter[1] = 0x00000000;
616b955f6caSJeff Kirsher 	MEM->init.rx_ring.adr_lo = offsetof( struct lance_memory, rx_head );
617b955f6caSJeff Kirsher 	MEM->init.rx_ring.adr_hi = 0;
618b955f6caSJeff Kirsher 	MEM->init.rx_ring.len    = RX_RING_LEN_BITS;
619b955f6caSJeff Kirsher 	MEM->init.tx_ring.adr_lo = offsetof( struct lance_memory, tx_head );
620b955f6caSJeff Kirsher 	MEM->init.tx_ring.adr_hi = 0;
621b955f6caSJeff Kirsher 	MEM->init.tx_ring.len    = TX_RING_LEN_BITS;
622b955f6caSJeff Kirsher 
623b955f6caSJeff Kirsher 	if (lp->cardtype == PAM_CARD)
624b955f6caSJeff Kirsher 		IO->ivec = IRQ_SOURCE_TO_VECTOR(dev->irq);
625b955f6caSJeff Kirsher 	else
626b955f6caSJeff Kirsher 		*RIEBL_IVEC_ADDR = IRQ_SOURCE_TO_VECTOR(dev->irq);
627b955f6caSJeff Kirsher 
628b955f6caSJeff Kirsher 	if (did_version++ == 0)
629b955f6caSJeff Kirsher 		DPRINTK( 1, ( version ));
630b955f6caSJeff Kirsher 
631b955f6caSJeff Kirsher 	dev->netdev_ops = &lance_netdev_ops;
632b955f6caSJeff Kirsher 
633b955f6caSJeff Kirsher 	/* XXX MSch */
634b955f6caSJeff Kirsher 	dev->watchdog_timeo = TX_TIMEOUT;
635b955f6caSJeff Kirsher 
636b955f6caSJeff Kirsher 	return 1;
637b955f6caSJeff Kirsher }
638b955f6caSJeff Kirsher 
639b955f6caSJeff Kirsher 
lance_open(struct net_device * dev)640b955f6caSJeff Kirsher static int lance_open( struct net_device *dev )
641b955f6caSJeff Kirsher {
642b955f6caSJeff Kirsher 	struct lance_private *lp = netdev_priv(dev);
643b955f6caSJeff Kirsher 	struct lance_ioreg	 *IO = lp->iobase;
644b955f6caSJeff Kirsher 	int i;
645b955f6caSJeff Kirsher 
646b955f6caSJeff Kirsher 	DPRINTK( 2, ( "%s: lance_open()\n", dev->name ));
647b955f6caSJeff Kirsher 
648b955f6caSJeff Kirsher 	lance_init_ring(dev);
649b955f6caSJeff Kirsher 	/* Re-initialize the LANCE, and start it when done. */
650b955f6caSJeff Kirsher 
651b955f6caSJeff Kirsher 	REGA( CSR3 ) = CSR3_BSWP | (lp->cardtype == PAM_CARD ? CSR3_ACON : 0);
652b955f6caSJeff Kirsher 	REGA( CSR2 ) = 0;
653b955f6caSJeff Kirsher 	REGA( CSR1 ) = 0;
654b955f6caSJeff Kirsher 	REGA( CSR0 ) = CSR0_INIT;
655b955f6caSJeff Kirsher 	/* From now on, AREG is kept to point to CSR0 */
656b955f6caSJeff Kirsher 
657b955f6caSJeff Kirsher 	i = 1000000;
658b955f6caSJeff Kirsher 	while (--i > 0)
659b955f6caSJeff Kirsher 		if (DREG & CSR0_IDON)
660b955f6caSJeff Kirsher 			break;
661b955f6caSJeff Kirsher 	if (i <= 0 || (DREG & CSR0_ERR)) {
662b955f6caSJeff Kirsher 		DPRINTK( 2, ( "lance_open(): opening %s failed, i=%d, csr0=%04x\n",
663b955f6caSJeff Kirsher 					  dev->name, i, DREG ));
664b955f6caSJeff Kirsher 		DREG = CSR0_STOP;
665b955f6caSJeff Kirsher 		return -EIO;
666b955f6caSJeff Kirsher 	}
667b955f6caSJeff Kirsher 	DREG = CSR0_IDON;
668b955f6caSJeff Kirsher 	DREG = CSR0_STRT;
669b955f6caSJeff Kirsher 	DREG = CSR0_INEA;
670b955f6caSJeff Kirsher 
671b955f6caSJeff Kirsher 	netif_start_queue (dev);
672b955f6caSJeff Kirsher 
673b955f6caSJeff Kirsher 	DPRINTK( 2, ( "%s: LANCE is open, csr0 %04x\n", dev->name, DREG ));
674b955f6caSJeff Kirsher 
675b955f6caSJeff Kirsher 	return 0;
676b955f6caSJeff Kirsher }
677b955f6caSJeff Kirsher 
678b955f6caSJeff Kirsher 
679b955f6caSJeff Kirsher /* Initialize the LANCE Rx and Tx rings. */
680b955f6caSJeff Kirsher 
lance_init_ring(struct net_device * dev)681b955f6caSJeff Kirsher static void lance_init_ring( struct net_device *dev )
682b955f6caSJeff Kirsher {
683b955f6caSJeff Kirsher 	struct lance_private *lp = netdev_priv(dev);
684b955f6caSJeff Kirsher 	int i;
685b955f6caSJeff Kirsher 	unsigned offset;
686b955f6caSJeff Kirsher 
687b955f6caSJeff Kirsher 	lp->tx_full = 0;
688b955f6caSJeff Kirsher 	lp->cur_rx = lp->cur_tx = 0;
689b955f6caSJeff Kirsher 	lp->dirty_tx = 0;
690b955f6caSJeff Kirsher 
691b955f6caSJeff Kirsher 	offset = offsetof( struct lance_memory, packet_area );
692b955f6caSJeff Kirsher 
693b955f6caSJeff Kirsher /* If the packet buffer at offset 'o' would conflict with the reserved area
694b955f6caSJeff Kirsher  * of RieblCards, advance it */
695b955f6caSJeff Kirsher #define	CHECK_OFFSET(o)														 \
696b955f6caSJeff Kirsher 	do {																	 \
697b955f6caSJeff Kirsher 		if (lp->cardtype == OLD_RIEBL || lp->cardtype == NEW_RIEBL) {		 \
698b955f6caSJeff Kirsher 			if (((o) < RIEBL_RSVD_START) ? (o)+PKT_BUF_SZ > RIEBL_RSVD_START \
699b955f6caSJeff Kirsher 										 : (o) < RIEBL_RSVD_END)			 \
700b955f6caSJeff Kirsher 				(o) = RIEBL_RSVD_END;										 \
701b955f6caSJeff Kirsher 		}																	 \
702b955f6caSJeff Kirsher 	} while(0)
703b955f6caSJeff Kirsher 
704b955f6caSJeff Kirsher 	for( i = 0; i < TX_RING_SIZE; i++ ) {
705b955f6caSJeff Kirsher 		CHECK_OFFSET(offset);
706b955f6caSJeff Kirsher 		MEM->tx_head[i].base = offset;
707b955f6caSJeff Kirsher 		MEM->tx_head[i].flag = TMD1_OWN_HOST;
708b955f6caSJeff Kirsher 		MEM->tx_head[i].base_hi = 0;
709b955f6caSJeff Kirsher 		MEM->tx_head[i].length = 0;
710b955f6caSJeff Kirsher 		MEM->tx_head[i].misc = 0;
711b955f6caSJeff Kirsher 		offset += PKT_BUF_SZ;
712b955f6caSJeff Kirsher 	}
713b955f6caSJeff Kirsher 
714b955f6caSJeff Kirsher 	for( i = 0; i < RX_RING_SIZE; i++ ) {
715b955f6caSJeff Kirsher 		CHECK_OFFSET(offset);
716b955f6caSJeff Kirsher 		MEM->rx_head[i].base = offset;
717b955f6caSJeff Kirsher 		MEM->rx_head[i].flag = TMD1_OWN_CHIP;
718b955f6caSJeff Kirsher 		MEM->rx_head[i].base_hi = 0;
719b955f6caSJeff Kirsher 		MEM->rx_head[i].buf_length = -PKT_BUF_SZ;
720b955f6caSJeff Kirsher 		MEM->rx_head[i].msg_length = 0;
721b955f6caSJeff Kirsher 		offset += PKT_BUF_SZ;
722b955f6caSJeff Kirsher 	}
723b955f6caSJeff Kirsher }
724b955f6caSJeff Kirsher 
725b955f6caSJeff Kirsher 
726b955f6caSJeff Kirsher /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
727b955f6caSJeff Kirsher 
728b955f6caSJeff Kirsher 
lance_tx_timeout(struct net_device * dev,unsigned int txqueue)7290290bd29SMichael S. Tsirkin static void lance_tx_timeout (struct net_device *dev, unsigned int txqueue)
730b955f6caSJeff Kirsher {
731b955f6caSJeff Kirsher 	struct lance_private *lp = netdev_priv(dev);
732b955f6caSJeff Kirsher 	struct lance_ioreg	 *IO = lp->iobase;
733b955f6caSJeff Kirsher 
734b955f6caSJeff Kirsher 	AREG = CSR0;
735b955f6caSJeff Kirsher 	DPRINTK( 1, ( "%s: transmit timed out, status %04x, resetting.\n",
736b955f6caSJeff Kirsher 			  dev->name, DREG ));
737b955f6caSJeff Kirsher 	DREG = CSR0_STOP;
738b955f6caSJeff Kirsher 	/*
739b955f6caSJeff Kirsher 	 * Always set BSWP after a STOP as STOP puts it back into
740b955f6caSJeff Kirsher 	 * little endian mode.
741b955f6caSJeff Kirsher 	 */
742b955f6caSJeff Kirsher 	REGA( CSR3 ) = CSR3_BSWP | (lp->cardtype == PAM_CARD ? CSR3_ACON : 0);
743b955f6caSJeff Kirsher 	dev->stats.tx_errors++;
744b955f6caSJeff Kirsher #ifndef final_version
745b955f6caSJeff Kirsher 		{	int i;
746b955f6caSJeff Kirsher 			DPRINTK( 2, ( "Ring data: dirty_tx %d cur_tx %d%s cur_rx %d\n",
747b955f6caSJeff Kirsher 						  lp->dirty_tx, lp->cur_tx,
748b955f6caSJeff Kirsher 						  lp->tx_full ? " (full)" : "",
749b955f6caSJeff Kirsher 						  lp->cur_rx ));
750b955f6caSJeff Kirsher 			for( i = 0 ; i < RX_RING_SIZE; i++ )
751b955f6caSJeff Kirsher 				DPRINTK( 2, ( "rx #%d: base=%04x blen=%04x mlen=%04x\n",
752b955f6caSJeff Kirsher 							  i, MEM->rx_head[i].base,
753b955f6caSJeff Kirsher 							  -MEM->rx_head[i].buf_length,
754b955f6caSJeff Kirsher 							  MEM->rx_head[i].msg_length ));
755b955f6caSJeff Kirsher 			for( i = 0 ; i < TX_RING_SIZE; i++ )
756b955f6caSJeff Kirsher 				DPRINTK( 2, ( "tx #%d: base=%04x len=%04x misc=%04x\n",
757b955f6caSJeff Kirsher 							  i, MEM->tx_head[i].base,
758b955f6caSJeff Kirsher 							  -MEM->tx_head[i].length,
759b955f6caSJeff Kirsher 							  MEM->tx_head[i].misc ));
760b955f6caSJeff Kirsher 		}
761b955f6caSJeff Kirsher #endif
762b955f6caSJeff Kirsher 	/* XXX MSch: maybe purge/reinit ring here */
763b955f6caSJeff Kirsher 	/* lance_restart, essentially */
764b955f6caSJeff Kirsher 	lance_init_ring(dev);
765b955f6caSJeff Kirsher 	REGA( CSR0 ) = CSR0_INEA | CSR0_INIT | CSR0_STRT;
766860e9538SFlorian Westphal 	netif_trans_update(dev); /* prevent tx timeout */
767b955f6caSJeff Kirsher 	netif_wake_queue(dev);
768b955f6caSJeff Kirsher }
769b955f6caSJeff Kirsher 
770b955f6caSJeff Kirsher /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
771b955f6caSJeff Kirsher 
772fe72352eSYueHaibing static netdev_tx_t
lance_start_xmit(struct sk_buff * skb,struct net_device * dev)773fe72352eSYueHaibing lance_start_xmit(struct sk_buff *skb, struct net_device *dev)
774b955f6caSJeff Kirsher {
775b955f6caSJeff Kirsher 	struct lance_private *lp = netdev_priv(dev);
776b955f6caSJeff Kirsher 	struct lance_ioreg	 *IO = lp->iobase;
777b955f6caSJeff Kirsher 	int entry, len;
778b955f6caSJeff Kirsher 	struct lance_tx_head *head;
779b955f6caSJeff Kirsher 	unsigned long flags;
780b955f6caSJeff Kirsher 
781b955f6caSJeff Kirsher 	DPRINTK( 2, ( "%s: lance_start_xmit() called, csr0 %4.4x.\n",
782b955f6caSJeff Kirsher 				  dev->name, DREG ));
783b955f6caSJeff Kirsher 
784b955f6caSJeff Kirsher 
785b955f6caSJeff Kirsher 	/* The old LANCE chips doesn't automatically pad buffers to min. size. */
786b955f6caSJeff Kirsher 	len = skb->len;
787b955f6caSJeff Kirsher 	if (len < ETH_ZLEN)
788b955f6caSJeff Kirsher 		len = ETH_ZLEN;
789b955f6caSJeff Kirsher 	/* PAM-Card has a bug: Can only send packets with even number of bytes! */
790b955f6caSJeff Kirsher 	else if (lp->cardtype == PAM_CARD && (len & 1))
791b955f6caSJeff Kirsher 		++len;
792b955f6caSJeff Kirsher 
793b955f6caSJeff Kirsher 	if (len > skb->len) {
794b955f6caSJeff Kirsher 		if (skb_padto(skb, len))
795b955f6caSJeff Kirsher 			return NETDEV_TX_OK;
796b955f6caSJeff Kirsher 	}
797b955f6caSJeff Kirsher 
798b955f6caSJeff Kirsher 	netif_stop_queue (dev);
799b955f6caSJeff Kirsher 
800b955f6caSJeff Kirsher 	/* Fill in a Tx ring entry */
801b955f6caSJeff Kirsher 	if (lance_debug >= 3) {
802b955f6caSJeff Kirsher 		printk( "%s: TX pkt type 0x%04x from %pM to %pM"
803b955f6caSJeff Kirsher 				" data at 0x%08x len %d\n",
804b955f6caSJeff Kirsher 				dev->name, ((u_short *)skb->data)[6],
805b955f6caSJeff Kirsher 				&skb->data[6], skb->data,
806b955f6caSJeff Kirsher 				(int)skb->data, (int)skb->len );
807b955f6caSJeff Kirsher 	}
808b955f6caSJeff Kirsher 
809b955f6caSJeff Kirsher 	/* We're not prepared for the int until the last flags are set/reset. And
810b955f6caSJeff Kirsher 	 * the int may happen already after setting the OWN_CHIP... */
811b955f6caSJeff Kirsher 	spin_lock_irqsave (&lp->devlock, flags);
812b955f6caSJeff Kirsher 
813b955f6caSJeff Kirsher 	/* Mask to ring buffer boundary. */
814b955f6caSJeff Kirsher 	entry = lp->cur_tx & TX_RING_MOD_MASK;
815b955f6caSJeff Kirsher 	head  = &(MEM->tx_head[entry]);
816b955f6caSJeff Kirsher 
817b955f6caSJeff Kirsher 	/* Caution: the write order is important here, set the "ownership" bits
818b955f6caSJeff Kirsher 	 * last.
819b955f6caSJeff Kirsher 	 */
820b955f6caSJeff Kirsher 
821b955f6caSJeff Kirsher 
822b955f6caSJeff Kirsher 	head->length = -len;
823b955f6caSJeff Kirsher 	head->misc = 0;
824b955f6caSJeff Kirsher 	lp->memcpy_f( PKTBUF_ADDR(head), (void *)skb->data, skb->len );
825b955f6caSJeff Kirsher 	head->flag = TMD1_OWN_CHIP | TMD1_ENP | TMD1_STP;
826b955f6caSJeff Kirsher 	dev->stats.tx_bytes += skb->len;
8276151d105SYang Yingliang 	dev_consume_skb_irq(skb);
828b955f6caSJeff Kirsher 	lp->cur_tx++;
829b955f6caSJeff Kirsher 	while( lp->cur_tx >= TX_RING_SIZE && lp->dirty_tx >= TX_RING_SIZE ) {
830b955f6caSJeff Kirsher 		lp->cur_tx -= TX_RING_SIZE;
831b955f6caSJeff Kirsher 		lp->dirty_tx -= TX_RING_SIZE;
832b955f6caSJeff Kirsher 	}
833b955f6caSJeff Kirsher 
834b955f6caSJeff Kirsher 	/* Trigger an immediate send poll. */
835b955f6caSJeff Kirsher 	DREG = CSR0_INEA | CSR0_TDMD;
836b955f6caSJeff Kirsher 
837b955f6caSJeff Kirsher 	if ((MEM->tx_head[(entry+1) & TX_RING_MOD_MASK].flag & TMD1_OWN) ==
838b955f6caSJeff Kirsher 		TMD1_OWN_HOST)
839b955f6caSJeff Kirsher 		netif_start_queue (dev);
840b955f6caSJeff Kirsher 	else
841b955f6caSJeff Kirsher 		lp->tx_full = 1;
842b955f6caSJeff Kirsher 	spin_unlock_irqrestore (&lp->devlock, flags);
843b955f6caSJeff Kirsher 
844b955f6caSJeff Kirsher 	return NETDEV_TX_OK;
845b955f6caSJeff Kirsher }
846b955f6caSJeff Kirsher 
847b955f6caSJeff Kirsher /* The LANCE interrupt handler. */
848b955f6caSJeff Kirsher 
lance_interrupt(int irq,void * dev_id)849b955f6caSJeff Kirsher static irqreturn_t lance_interrupt( int irq, void *dev_id )
850b955f6caSJeff Kirsher {
851b955f6caSJeff Kirsher 	struct net_device *dev = dev_id;
852b955f6caSJeff Kirsher 	struct lance_private *lp;
853b955f6caSJeff Kirsher 	struct lance_ioreg	 *IO;
854b955f6caSJeff Kirsher 	int csr0, boguscnt = 10;
855b955f6caSJeff Kirsher 	int handled = 0;
856b955f6caSJeff Kirsher 
857b0b815a3SGuofeng Yue 	if (!dev) {
858b955f6caSJeff Kirsher 		DPRINTK( 1, ( "lance_interrupt(): interrupt for unknown device.\n" ));
859b955f6caSJeff Kirsher 		return IRQ_NONE;
860b955f6caSJeff Kirsher 	}
861b955f6caSJeff Kirsher 
862b955f6caSJeff Kirsher 	lp = netdev_priv(dev);
863b955f6caSJeff Kirsher 	IO = lp->iobase;
864b955f6caSJeff Kirsher 	spin_lock (&lp->devlock);
865b955f6caSJeff Kirsher 
866b955f6caSJeff Kirsher 	AREG = CSR0;
867b955f6caSJeff Kirsher 
868b955f6caSJeff Kirsher 	while( ((csr0 = DREG) & (CSR0_ERR | CSR0_TINT | CSR0_RINT)) &&
869b955f6caSJeff Kirsher 		   --boguscnt >= 0) {
870b955f6caSJeff Kirsher 		handled = 1;
871b955f6caSJeff Kirsher 		/* Acknowledge all of the current interrupt sources ASAP. */
872b955f6caSJeff Kirsher 		DREG = csr0 & ~(CSR0_INIT | CSR0_STRT | CSR0_STOP |
873b955f6caSJeff Kirsher 									CSR0_TDMD | CSR0_INEA);
874b955f6caSJeff Kirsher 
875b955f6caSJeff Kirsher 		DPRINTK( 2, ( "%s: interrupt  csr0=%04x new csr=%04x.\n",
876b955f6caSJeff Kirsher 					  dev->name, csr0, DREG ));
877b955f6caSJeff Kirsher 
878b955f6caSJeff Kirsher 		if (csr0 & CSR0_RINT)			/* Rx interrupt */
879b955f6caSJeff Kirsher 			lance_rx( dev );
880b955f6caSJeff Kirsher 
881b955f6caSJeff Kirsher 		if (csr0 & CSR0_TINT) {			/* Tx-done interrupt */
882b955f6caSJeff Kirsher 			int dirty_tx = lp->dirty_tx;
883b955f6caSJeff Kirsher 
884b955f6caSJeff Kirsher 			while( dirty_tx < lp->cur_tx) {
885b955f6caSJeff Kirsher 				int entry = dirty_tx & TX_RING_MOD_MASK;
886b955f6caSJeff Kirsher 				int status = MEM->tx_head[entry].flag;
887b955f6caSJeff Kirsher 
888b955f6caSJeff Kirsher 				if (status & TMD1_OWN_CHIP)
889b955f6caSJeff Kirsher 					break;			/* It still hasn't been Txed */
890b955f6caSJeff Kirsher 
891b955f6caSJeff Kirsher 				MEM->tx_head[entry].flag = 0;
892b955f6caSJeff Kirsher 
893b955f6caSJeff Kirsher 				if (status & TMD1_ERR) {
894b955f6caSJeff Kirsher 					/* There was an major error, log it. */
895b955f6caSJeff Kirsher 					int err_status = MEM->tx_head[entry].misc;
896b955f6caSJeff Kirsher 					dev->stats.tx_errors++;
897b955f6caSJeff Kirsher 					if (err_status & TMD3_RTRY) dev->stats.tx_aborted_errors++;
898b955f6caSJeff Kirsher 					if (err_status & TMD3_LCAR) dev->stats.tx_carrier_errors++;
899b955f6caSJeff Kirsher 					if (err_status & TMD3_LCOL) dev->stats.tx_window_errors++;
900b955f6caSJeff Kirsher 					if (err_status & TMD3_UFLO) {
901b955f6caSJeff Kirsher 						/* Ackk!  On FIFO errors the Tx unit is turned off! */
902b955f6caSJeff Kirsher 						dev->stats.tx_fifo_errors++;
903b955f6caSJeff Kirsher 						/* Remove this verbosity later! */
904b955f6caSJeff Kirsher 						DPRINTK( 1, ( "%s: Tx FIFO error! Status %04x\n",
905b955f6caSJeff Kirsher 									  dev->name, csr0 ));
906b955f6caSJeff Kirsher 						/* Restart the chip. */
907b955f6caSJeff Kirsher 						DREG = CSR0_STRT;
908b955f6caSJeff Kirsher 					}
909b955f6caSJeff Kirsher 				} else {
910b955f6caSJeff Kirsher 					if (status & (TMD1_MORE | TMD1_ONE | TMD1_DEF))
911b955f6caSJeff Kirsher 						dev->stats.collisions++;
912b955f6caSJeff Kirsher 					dev->stats.tx_packets++;
913b955f6caSJeff Kirsher 				}
914b955f6caSJeff Kirsher 
915b955f6caSJeff Kirsher 				/* XXX MSch: free skb?? */
916b955f6caSJeff Kirsher 				dirty_tx++;
917b955f6caSJeff Kirsher 			}
918b955f6caSJeff Kirsher 
919b955f6caSJeff Kirsher #ifndef final_version
920b955f6caSJeff Kirsher 			if (lp->cur_tx - dirty_tx >= TX_RING_SIZE) {
921b955f6caSJeff Kirsher 				DPRINTK( 0, ( "out-of-sync dirty pointer,"
922b955f6caSJeff Kirsher 							  " %d vs. %d, full=%ld.\n",
923b955f6caSJeff Kirsher 							  dirty_tx, lp->cur_tx, lp->tx_full ));
924b955f6caSJeff Kirsher 				dirty_tx += TX_RING_SIZE;
925b955f6caSJeff Kirsher 			}
926b955f6caSJeff Kirsher #endif
927b955f6caSJeff Kirsher 
928b955f6caSJeff Kirsher 			if (lp->tx_full && (netif_queue_stopped(dev)) &&
929b955f6caSJeff Kirsher 				dirty_tx > lp->cur_tx - TX_RING_SIZE + 2) {
930b955f6caSJeff Kirsher 				/* The ring is no longer full, clear tbusy. */
931b955f6caSJeff Kirsher 				lp->tx_full = 0;
932b955f6caSJeff Kirsher 				netif_wake_queue (dev);
933b955f6caSJeff Kirsher 			}
934b955f6caSJeff Kirsher 
935b955f6caSJeff Kirsher 			lp->dirty_tx = dirty_tx;
936b955f6caSJeff Kirsher 		}
937b955f6caSJeff Kirsher 
938b955f6caSJeff Kirsher 		/* Log misc errors. */
939b955f6caSJeff Kirsher 		if (csr0 & CSR0_BABL) dev->stats.tx_errors++; /* Tx babble. */
940b955f6caSJeff Kirsher 		if (csr0 & CSR0_MISS) dev->stats.rx_errors++; /* Missed a Rx frame. */
941b955f6caSJeff Kirsher 		if (csr0 & CSR0_MERR) {
942b955f6caSJeff Kirsher 			DPRINTK( 1, ( "%s: Bus master arbitration failure (?!?), "
943b955f6caSJeff Kirsher 						  "status %04x.\n", dev->name, csr0 ));
944b955f6caSJeff Kirsher 			/* Restart the chip. */
945b955f6caSJeff Kirsher 			DREG = CSR0_STRT;
946b955f6caSJeff Kirsher 		}
947b955f6caSJeff Kirsher 	}
948b955f6caSJeff Kirsher 
949b955f6caSJeff Kirsher     /* Clear any other interrupt, and set interrupt enable. */
950b955f6caSJeff Kirsher 	DREG = CSR0_BABL | CSR0_CERR | CSR0_MISS | CSR0_MERR |
951b955f6caSJeff Kirsher 		   CSR0_IDON | CSR0_INEA;
952b955f6caSJeff Kirsher 
953b955f6caSJeff Kirsher 	DPRINTK( 2, ( "%s: exiting interrupt, csr0=%#04x.\n",
954b955f6caSJeff Kirsher 				  dev->name, DREG ));
955b955f6caSJeff Kirsher 
956b955f6caSJeff Kirsher 	spin_unlock (&lp->devlock);
957b955f6caSJeff Kirsher 	return IRQ_RETVAL(handled);
958b955f6caSJeff Kirsher }
959b955f6caSJeff Kirsher 
960b955f6caSJeff Kirsher 
lance_rx(struct net_device * dev)961b955f6caSJeff Kirsher static int lance_rx( struct net_device *dev )
962b955f6caSJeff Kirsher {
963b955f6caSJeff Kirsher 	struct lance_private *lp = netdev_priv(dev);
964b955f6caSJeff Kirsher 	int entry = lp->cur_rx & RX_RING_MOD_MASK;
965b955f6caSJeff Kirsher 	int i;
966b955f6caSJeff Kirsher 
967b955f6caSJeff Kirsher 	DPRINTK( 2, ( "%s: rx int, flag=%04x\n", dev->name,
968b955f6caSJeff Kirsher 				  MEM->rx_head[entry].flag ));
969b955f6caSJeff Kirsher 
970b955f6caSJeff Kirsher 	/* If we own the next entry, it's a new packet. Send it up. */
971b955f6caSJeff Kirsher 	while( (MEM->rx_head[entry].flag & RMD1_OWN) == RMD1_OWN_HOST ) {
972b955f6caSJeff Kirsher 		struct lance_rx_head *head = &(MEM->rx_head[entry]);
973b955f6caSJeff Kirsher 		int status = head->flag;
974b955f6caSJeff Kirsher 
975b955f6caSJeff Kirsher 		if (status != (RMD1_ENP|RMD1_STP)) {		/* There was an error. */
976b955f6caSJeff Kirsher 			/* There is a tricky error noted by John Murphy,
977b955f6caSJeff Kirsher 			   <murf@perftech.com> to Russ Nelson: Even with full-sized
978b955f6caSJeff Kirsher 			   buffers it's possible for a jabber packet to use two
979b955f6caSJeff Kirsher 			   buffers, with only the last correctly noting the error. */
980b955f6caSJeff Kirsher 			if (status & RMD1_ENP)	/* Only count a general error at the */
981b955f6caSJeff Kirsher 				dev->stats.rx_errors++; /* end of a packet.*/
982b955f6caSJeff Kirsher 			if (status & RMD1_FRAM) dev->stats.rx_frame_errors++;
983b955f6caSJeff Kirsher 			if (status & RMD1_OFLO) dev->stats.rx_over_errors++;
984b955f6caSJeff Kirsher 			if (status & RMD1_CRC) dev->stats.rx_crc_errors++;
985b955f6caSJeff Kirsher 			if (status & RMD1_BUFF) dev->stats.rx_fifo_errors++;
986b955f6caSJeff Kirsher 			head->flag &= (RMD1_ENP|RMD1_STP);
987b955f6caSJeff Kirsher 		} else {
988b955f6caSJeff Kirsher 			/* Malloc up new buffer, compatible with net-3. */
989b955f6caSJeff Kirsher 			short pkt_len = head->msg_length & 0xfff;
990b955f6caSJeff Kirsher 			struct sk_buff *skb;
991b955f6caSJeff Kirsher 
992b955f6caSJeff Kirsher 			if (pkt_len < 60) {
993b955f6caSJeff Kirsher 				printk( "%s: Runt packet!\n", dev->name );
994b955f6caSJeff Kirsher 				dev->stats.rx_errors++;
995b955f6caSJeff Kirsher 			}
996b955f6caSJeff Kirsher 			else {
9971d266430SPradeep A Dalvi 				skb = netdev_alloc_skb(dev, pkt_len + 2);
998b0b815a3SGuofeng Yue 				if (!skb) {
999b955f6caSJeff Kirsher 					for( i = 0; i < RX_RING_SIZE; i++ )
1000b955f6caSJeff Kirsher 						if (MEM->rx_head[(entry+i) & RX_RING_MOD_MASK].flag &
1001b955f6caSJeff Kirsher 							RMD1_OWN_CHIP)
1002b955f6caSJeff Kirsher 							break;
1003b955f6caSJeff Kirsher 
1004b955f6caSJeff Kirsher 					if (i > RX_RING_SIZE - 2) {
1005b955f6caSJeff Kirsher 						dev->stats.rx_dropped++;
1006b955f6caSJeff Kirsher 						head->flag |= RMD1_OWN_CHIP;
1007b955f6caSJeff Kirsher 						lp->cur_rx++;
1008b955f6caSJeff Kirsher 					}
1009b955f6caSJeff Kirsher 					break;
1010b955f6caSJeff Kirsher 				}
1011b955f6caSJeff Kirsher 
1012b955f6caSJeff Kirsher 				if (lance_debug >= 3) {
1013b955f6caSJeff Kirsher 					u_char *data = PKTBUF_ADDR(head);
1014b955f6caSJeff Kirsher 
1015b955f6caSJeff Kirsher 					printk(KERN_DEBUG "%s: RX pkt type 0x%04x from %pM to %pM "
1016b14945acSRasmus Villemoes 						   "data %8ph len %d\n",
1017b955f6caSJeff Kirsher 						   dev->name, ((u_short *)data)[6],
1018b14945acSRasmus Villemoes 						   &data[6], data, &data[15], pkt_len);
1019b955f6caSJeff Kirsher 				}
1020b955f6caSJeff Kirsher 
1021b955f6caSJeff Kirsher 				skb_reserve( skb, 2 );	/* 16 byte align */
1022b955f6caSJeff Kirsher 				skb_put( skb, pkt_len );	/* Make room */
1023b955f6caSJeff Kirsher 				lp->memcpy_f( skb->data, PKTBUF_ADDR(head), pkt_len );
1024b955f6caSJeff Kirsher 				skb->protocol = eth_type_trans( skb, dev );
1025b955f6caSJeff Kirsher 				netif_rx( skb );
1026b955f6caSJeff Kirsher 				dev->stats.rx_packets++;
1027b955f6caSJeff Kirsher 				dev->stats.rx_bytes += pkt_len;
1028b955f6caSJeff Kirsher 			}
1029b955f6caSJeff Kirsher 		}
1030b955f6caSJeff Kirsher 
1031b955f6caSJeff Kirsher 		head->flag |= RMD1_OWN_CHIP;
1032b955f6caSJeff Kirsher 		entry = (++lp->cur_rx) & RX_RING_MOD_MASK;
1033b955f6caSJeff Kirsher 	}
1034b955f6caSJeff Kirsher 	lp->cur_rx &= RX_RING_MOD_MASK;
1035b955f6caSJeff Kirsher 
1036b955f6caSJeff Kirsher 	/* From lance.c (Donald Becker): */
1037b955f6caSJeff Kirsher 	/* We should check that at least two ring entries are free.	 If not,
1038b955f6caSJeff Kirsher 	   we should free one and mark stats->rx_dropped++. */
1039b955f6caSJeff Kirsher 
1040b955f6caSJeff Kirsher 	return 0;
1041b955f6caSJeff Kirsher }
1042b955f6caSJeff Kirsher 
1043b955f6caSJeff Kirsher 
lance_close(struct net_device * dev)1044b955f6caSJeff Kirsher static int lance_close( struct net_device *dev )
1045b955f6caSJeff Kirsher {
1046b955f6caSJeff Kirsher 	struct lance_private *lp = netdev_priv(dev);
1047b955f6caSJeff Kirsher 	struct lance_ioreg	 *IO = lp->iobase;
1048b955f6caSJeff Kirsher 
1049b955f6caSJeff Kirsher 	netif_stop_queue (dev);
1050b955f6caSJeff Kirsher 
1051b955f6caSJeff Kirsher 	AREG = CSR0;
1052b955f6caSJeff Kirsher 
1053b955f6caSJeff Kirsher 	DPRINTK( 2, ( "%s: Shutting down ethercard, status was %2.2x.\n",
1054b955f6caSJeff Kirsher 				  dev->name, DREG ));
1055b955f6caSJeff Kirsher 
1056b955f6caSJeff Kirsher 	/* We stop the LANCE here -- it occasionally polls
1057b955f6caSJeff Kirsher 	   memory if we don't. */
1058b955f6caSJeff Kirsher 	DREG = CSR0_STOP;
1059b955f6caSJeff Kirsher 
1060b955f6caSJeff Kirsher 	return 0;
1061b955f6caSJeff Kirsher }
1062b955f6caSJeff Kirsher 
1063b955f6caSJeff Kirsher 
1064b955f6caSJeff Kirsher /* Set or clear the multicast filter for this adaptor.
1065b955f6caSJeff Kirsher    num_addrs == -1		Promiscuous mode, receive all packets
1066b955f6caSJeff Kirsher    num_addrs == 0		Normal mode, clear multicast list
1067b955f6caSJeff Kirsher    num_addrs > 0		Multicast mode, receive normal and MC packets, and do
1068b955f6caSJeff Kirsher 						best-effort filtering.
1069b955f6caSJeff Kirsher  */
1070b955f6caSJeff Kirsher 
set_multicast_list(struct net_device * dev)1071b955f6caSJeff Kirsher static void set_multicast_list( struct net_device *dev )
1072b955f6caSJeff Kirsher {
1073b955f6caSJeff Kirsher 	struct lance_private *lp = netdev_priv(dev);
1074b955f6caSJeff Kirsher 	struct lance_ioreg	 *IO = lp->iobase;
1075b955f6caSJeff Kirsher 
1076b955f6caSJeff Kirsher 	if (netif_running(dev))
1077b955f6caSJeff Kirsher 		/* Only possible if board is already started */
1078b955f6caSJeff Kirsher 		return;
1079b955f6caSJeff Kirsher 
1080b955f6caSJeff Kirsher 	/* We take the simple way out and always enable promiscuous mode. */
1081b955f6caSJeff Kirsher 	DREG = CSR0_STOP; /* Temporarily stop the lance. */
1082b955f6caSJeff Kirsher 
1083b955f6caSJeff Kirsher 	if (dev->flags & IFF_PROMISC) {
1084b955f6caSJeff Kirsher 		/* Log any net taps. */
1085b955f6caSJeff Kirsher 		DPRINTK( 2, ( "%s: Promiscuous mode enabled.\n", dev->name ));
1086b955f6caSJeff Kirsher 		REGA( CSR15 ) = 0x8000; /* Set promiscuous mode */
1087b955f6caSJeff Kirsher 	} else {
1088b955f6caSJeff Kirsher 		short multicast_table[4];
1089b955f6caSJeff Kirsher 		int num_addrs = netdev_mc_count(dev);
1090b955f6caSJeff Kirsher 		int i;
1091b955f6caSJeff Kirsher 		/* We don't use the multicast table, but rely on upper-layer
1092b955f6caSJeff Kirsher 		 * filtering. */
1093b955f6caSJeff Kirsher 		memset( multicast_table, (num_addrs == 0) ? 0 : -1,
1094b955f6caSJeff Kirsher 				sizeof(multicast_table) );
1095b955f6caSJeff Kirsher 		for( i = 0; i < 4; i++ )
1096b955f6caSJeff Kirsher 			REGA( CSR8+i ) = multicast_table[i];
1097b955f6caSJeff Kirsher 		REGA( CSR15 ) = 0; /* Unset promiscuous mode */
1098b955f6caSJeff Kirsher 	}
1099b955f6caSJeff Kirsher 
1100b955f6caSJeff Kirsher 	/*
1101b955f6caSJeff Kirsher 	 * Always set BSWP after a STOP as STOP puts it back into
1102b955f6caSJeff Kirsher 	 * little endian mode.
1103b955f6caSJeff Kirsher 	 */
1104b955f6caSJeff Kirsher 	REGA( CSR3 ) = CSR3_BSWP | (lp->cardtype == PAM_CARD ? CSR3_ACON : 0);
1105b955f6caSJeff Kirsher 
1106b955f6caSJeff Kirsher 	/* Resume normal operation and reset AREG to CSR0 */
1107b955f6caSJeff Kirsher 	REGA( CSR0 ) = CSR0_IDON | CSR0_INEA | CSR0_STRT;
1108b955f6caSJeff Kirsher }
1109b955f6caSJeff Kirsher 
1110b955f6caSJeff Kirsher 
1111b955f6caSJeff Kirsher /* This is needed for old RieblCards and possible for new RieblCards */
1112b955f6caSJeff Kirsher 
lance_set_mac_address(struct net_device * dev,void * addr)1113b955f6caSJeff Kirsher static int lance_set_mac_address( struct net_device *dev, void *addr )
1114b955f6caSJeff Kirsher {
1115b955f6caSJeff Kirsher 	struct lance_private *lp = netdev_priv(dev);
1116b955f6caSJeff Kirsher 	struct sockaddr *saddr = addr;
1117b955f6caSJeff Kirsher 	int i;
1118b955f6caSJeff Kirsher 
1119b955f6caSJeff Kirsher 	if (lp->cardtype != OLD_RIEBL && lp->cardtype != NEW_RIEBL)
1120b955f6caSJeff Kirsher 		return -EOPNOTSUPP;
1121b955f6caSJeff Kirsher 
1122b955f6caSJeff Kirsher 	if (netif_running(dev)) {
1123b955f6caSJeff Kirsher 		/* Only possible while card isn't started */
1124b955f6caSJeff Kirsher 		DPRINTK( 1, ( "%s: hwaddr can be set only while card isn't open.\n",
1125b955f6caSJeff Kirsher 					  dev->name ));
1126b955f6caSJeff Kirsher 		return -EIO;
1127b955f6caSJeff Kirsher 	}
1128b955f6caSJeff Kirsher 
1129a05e4c0aSJakub Kicinski 	eth_hw_addr_set(dev, saddr->sa_data);
1130b955f6caSJeff Kirsher 	for( i = 0; i < 6; i++ )
1131b955f6caSJeff Kirsher 		MEM->init.hwaddr[i] = dev->dev_addr[i^1]; /* <- 16 bit swap! */
1132b955f6caSJeff Kirsher 	lp->memcpy_f( RIEBL_HWADDR_ADDR, dev->dev_addr, 6 );
1133b955f6caSJeff Kirsher 	/* set also the magic for future sessions */
1134b955f6caSJeff Kirsher 	*RIEBL_MAGIC_ADDR = RIEBL_MAGIC;
1135b955f6caSJeff Kirsher 
1136b955f6caSJeff Kirsher 	return 0;
1137b955f6caSJeff Kirsher }
1138b955f6caSJeff Kirsher 
1139b955f6caSJeff Kirsher static struct net_device *atarilance_dev;
1140b955f6caSJeff Kirsher 
atarilance_module_init(void)1141b955f6caSJeff Kirsher static int __init atarilance_module_init(void)
1142b955f6caSJeff Kirsher {
1143e179d78eSArnd Bergmann 	atarilance_dev = atarilance_probe();
11448c6ffba0SRusty Russell 	return PTR_ERR_OR_ZERO(atarilance_dev);
1145b955f6caSJeff Kirsher }
1146b955f6caSJeff Kirsher 
atarilance_module_exit(void)1147b955f6caSJeff Kirsher static void __exit atarilance_module_exit(void)
1148b955f6caSJeff Kirsher {
1149b955f6caSJeff Kirsher 	unregister_netdev(atarilance_dev);
1150b955f6caSJeff Kirsher 	free_irq(atarilance_dev->irq, atarilance_dev);
1151b955f6caSJeff Kirsher 	free_netdev(atarilance_dev);
1152b955f6caSJeff Kirsher }
1153b955f6caSJeff Kirsher module_init(atarilance_module_init);
1154b955f6caSJeff Kirsher module_exit(atarilance_module_exit);
1155