xref: /linux/drivers/net/ethernet/amd/nmclan_cs.c (revision 96a30175f927facfb421655ef08b7a0fe546fbed)
1b955f6caSJeff Kirsher /* ----------------------------------------------------------------------------
2b955f6caSJeff Kirsher Linux PCMCIA ethernet adapter driver for the New Media Ethernet LAN.
3b955f6caSJeff Kirsher   nmclan_cs.c,v 0.16 1995/07/01 06:42:17 rpao Exp rpao
4b955f6caSJeff Kirsher 
5b955f6caSJeff Kirsher   The Ethernet LAN uses the Advanced Micro Devices (AMD) Am79C940 Media
6b955f6caSJeff Kirsher   Access Controller for Ethernet (MACE).  It is essentially the Am2150
7b955f6caSJeff Kirsher   PCMCIA Ethernet card contained in the Am2150 Demo Kit.
8b955f6caSJeff Kirsher 
9b955f6caSJeff Kirsher Written by Roger C. Pao <rpao@paonet.org>
10b955f6caSJeff Kirsher   Copyright 1995 Roger C. Pao
11b955f6caSJeff Kirsher   Linux 2.5 cleanups Copyright Red Hat 2003
12b955f6caSJeff Kirsher 
13b955f6caSJeff Kirsher   This software may be used and distributed according to the terms of
14b955f6caSJeff Kirsher   the GNU General Public License.
15b955f6caSJeff Kirsher 
16b955f6caSJeff Kirsher Ported to Linux 1.3.* network driver environment by
17b955f6caSJeff Kirsher   Matti Aarnio <mea@utu.fi>
18b955f6caSJeff Kirsher 
19b955f6caSJeff Kirsher References
20b955f6caSJeff Kirsher 
21b955f6caSJeff Kirsher   Am2150 Technical Reference Manual, Revision 1.0, August 17, 1993
22b955f6caSJeff Kirsher   Am79C940 (MACE) Data Sheet, 1994
23b955f6caSJeff Kirsher   Am79C90 (C-LANCE) Data Sheet, 1994
24b955f6caSJeff Kirsher   Linux PCMCIA Programmer's Guide v1.17
25b955f6caSJeff Kirsher   /usr/src/linux/net/inet/dev.c, Linux kernel 1.2.8
26b955f6caSJeff Kirsher 
27b955f6caSJeff Kirsher   Eric Mears, New Media Corporation
28b955f6caSJeff Kirsher   Tom Pollard, New Media Corporation
29b955f6caSJeff Kirsher   Dean Siasoyco, New Media Corporation
30b955f6caSJeff Kirsher   Ken Lesniak, Silicon Graphics, Inc. <lesniak@boston.sgi.com>
31b955f6caSJeff Kirsher   Donald Becker <becker@scyld.com>
32b955f6caSJeff Kirsher   David Hinds <dahinds@users.sourceforge.net>
33b955f6caSJeff Kirsher 
34b955f6caSJeff Kirsher   The Linux client driver is based on the 3c589_cs.c client driver by
35b955f6caSJeff Kirsher   David Hinds.
36b955f6caSJeff Kirsher 
37b955f6caSJeff Kirsher   The Linux network driver outline is based on the 3c589_cs.c driver,
38b955f6caSJeff Kirsher   the 8390.c driver, and the example skeleton.c kernel code, which are
39b955f6caSJeff Kirsher   by Donald Becker.
40b955f6caSJeff Kirsher 
41b955f6caSJeff Kirsher   The Am2150 network driver hardware interface code is based on the
42b955f6caSJeff Kirsher   OS/9000 driver for the New Media Ethernet LAN by Eric Mears.
43b955f6caSJeff Kirsher 
44b955f6caSJeff Kirsher   Special thanks for testing and help in debugging this driver goes
45b955f6caSJeff Kirsher   to Ken Lesniak.
46b955f6caSJeff Kirsher 
47b955f6caSJeff Kirsher -------------------------------------------------------------------------------
48b955f6caSJeff Kirsher Driver Notes and Issues
49b955f6caSJeff Kirsher -------------------------------------------------------------------------------
50b955f6caSJeff Kirsher 
51b955f6caSJeff Kirsher 1. Developed on a Dell 320SLi
52b955f6caSJeff Kirsher    PCMCIA Card Services 2.6.2
53b955f6caSJeff Kirsher    Linux dell 1.2.10 #1 Thu Jun 29 20:23:41 PDT 1995 i386
54b955f6caSJeff Kirsher 
55b955f6caSJeff Kirsher 2. rc.pcmcia may require loading pcmcia_core with io_speed=300:
56b955f6caSJeff Kirsher    'insmod pcmcia_core.o io_speed=300'.
57b955f6caSJeff Kirsher    This will avoid problems with fast systems which causes rx_framecnt
58b955f6caSJeff Kirsher    to return random values.
59b955f6caSJeff Kirsher 
60b955f6caSJeff Kirsher 3. If hot extraction does not work for you, use 'ifconfig eth0 down'
61b955f6caSJeff Kirsher    before extraction.
62b955f6caSJeff Kirsher 
63b955f6caSJeff Kirsher 4. There is a bad slow-down problem in this driver.
64b955f6caSJeff Kirsher 
65b955f6caSJeff Kirsher 5. Future: Multicast processing.  In the meantime, do _not_ compile your
66b955f6caSJeff Kirsher    kernel with multicast ip enabled.
67b955f6caSJeff Kirsher 
68b955f6caSJeff Kirsher -------------------------------------------------------------------------------
69b955f6caSJeff Kirsher History
70b955f6caSJeff Kirsher -------------------------------------------------------------------------------
71b955f6caSJeff Kirsher Log: nmclan_cs.c,v
72b955f6caSJeff Kirsher  * 2.5.75-ac1 2003/07/11 Alan Cox <alan@lxorguk.ukuu.org.uk>
73b955f6caSJeff Kirsher  * Fixed hang on card eject as we probe it
74b955f6caSJeff Kirsher  * Cleaned up to use new style locking.
75b955f6caSJeff Kirsher  *
76b955f6caSJeff Kirsher  * Revision 0.16  1995/07/01  06:42:17  rpao
77b955f6caSJeff Kirsher  * Bug fix: nmclan_reset() called CardServices incorrectly.
78b955f6caSJeff Kirsher  *
79b955f6caSJeff Kirsher  * Revision 0.15  1995/05/24  08:09:47  rpao
80b955f6caSJeff Kirsher  * Re-implement MULTI_TX dev->tbusy handling.
81b955f6caSJeff Kirsher  *
82b955f6caSJeff Kirsher  * Revision 0.14  1995/05/23  03:19:30  rpao
83b955f6caSJeff Kirsher  * Added, in nmclan_config(), "tuple.Attributes = 0;".
84b955f6caSJeff Kirsher  * Modified MACE ID check to ignore chip revision level.
85b955f6caSJeff Kirsher  * Avoid tx_free_frames race condition between _start_xmit and _interrupt.
86b955f6caSJeff Kirsher  *
87b955f6caSJeff Kirsher  * Revision 0.13  1995/05/18  05:56:34  rpao
88b955f6caSJeff Kirsher  * Statistics changes.
89b955f6caSJeff Kirsher  * Bug fix: nmclan_reset did not enable TX and RX: call restore_multicast_list.
90b955f6caSJeff Kirsher  * Bug fix: mace_interrupt checks ~MACE_IMR_DEFAULT.  Fixes driver lockup.
91b955f6caSJeff Kirsher  *
92b955f6caSJeff Kirsher  * Revision 0.12  1995/05/14  00:12:23  rpao
93b955f6caSJeff Kirsher  * Statistics overhaul.
94b955f6caSJeff Kirsher  *
95b955f6caSJeff Kirsher 
96b955f6caSJeff Kirsher 95/05/13 rpao	V0.10a
97b955f6caSJeff Kirsher 		Bug fix: MACE statistics counters used wrong I/O ports.
98b955f6caSJeff Kirsher 		Bug fix: mace_interrupt() needed to allow statistics to be
99b955f6caSJeff Kirsher 		processed without RX or TX interrupts pending.
100b955f6caSJeff Kirsher 95/05/11 rpao	V0.10
101b955f6caSJeff Kirsher 		Multiple transmit request processing.
102b955f6caSJeff Kirsher 		Modified statistics to use MACE counters where possible.
103b955f6caSJeff Kirsher 95/05/10 rpao	V0.09 Bug fix: Must use IO_DATA_PATH_WIDTH_AUTO.
104b955f6caSJeff Kirsher 		*Released
105b955f6caSJeff Kirsher 95/05/10 rpao	V0.08
106b955f6caSJeff Kirsher 		Bug fix: Make all non-exported functions private by using
107b955f6caSJeff Kirsher 		static keyword.
108b955f6caSJeff Kirsher 		Bug fix: Test IntrCnt _before_ reading MACE_IR.
109b955f6caSJeff Kirsher 95/05/10 rpao	V0.07 Statistics.
110b955f6caSJeff Kirsher 95/05/09 rpao	V0.06 Fix rx_framecnt problem by addition of PCIC wait states.
111b955f6caSJeff Kirsher 
112b955f6caSJeff Kirsher ---------------------------------------------------------------------------- */
113b955f6caSJeff Kirsher 
114b955f6caSJeff Kirsher #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
115b955f6caSJeff Kirsher 
116b955f6caSJeff Kirsher #define DRV_NAME	"nmclan_cs"
117b955f6caSJeff Kirsher #define DRV_VERSION	"0.16"
118b955f6caSJeff Kirsher 
119b955f6caSJeff Kirsher 
120b955f6caSJeff Kirsher /* ----------------------------------------------------------------------------
121b955f6caSJeff Kirsher Conditional Compilation Options
122b955f6caSJeff Kirsher ---------------------------------------------------------------------------- */
123b955f6caSJeff Kirsher 
124b955f6caSJeff Kirsher #define MULTI_TX			0
125b955f6caSJeff Kirsher #define RESET_ON_TIMEOUT		1
126b955f6caSJeff Kirsher #define TX_INTERRUPTABLE		1
127b955f6caSJeff Kirsher #define RESET_XILINX			0
128b955f6caSJeff Kirsher 
129b955f6caSJeff Kirsher /* ----------------------------------------------------------------------------
130b955f6caSJeff Kirsher Include Files
131b955f6caSJeff Kirsher ---------------------------------------------------------------------------- */
132b955f6caSJeff Kirsher 
133b955f6caSJeff Kirsher #include <linux/module.h>
134b955f6caSJeff Kirsher #include <linux/kernel.h>
135b955f6caSJeff Kirsher #include <linux/ptrace.h>
136b955f6caSJeff Kirsher #include <linux/slab.h>
137b955f6caSJeff Kirsher #include <linux/string.h>
138b955f6caSJeff Kirsher #include <linux/timer.h>
139b955f6caSJeff Kirsher #include <linux/interrupt.h>
140b955f6caSJeff Kirsher #include <linux/in.h>
141b955f6caSJeff Kirsher #include <linux/delay.h>
142b955f6caSJeff Kirsher #include <linux/ethtool.h>
143b955f6caSJeff Kirsher #include <linux/netdevice.h>
144b955f6caSJeff Kirsher #include <linux/etherdevice.h>
145b955f6caSJeff Kirsher #include <linux/skbuff.h>
146b955f6caSJeff Kirsher #include <linux/if_arp.h>
147b955f6caSJeff Kirsher #include <linux/ioport.h>
148b955f6caSJeff Kirsher #include <linux/bitops.h>
149b955f6caSJeff Kirsher 
150b955f6caSJeff Kirsher #include <pcmcia/cisreg.h>
151b955f6caSJeff Kirsher #include <pcmcia/cistpl.h>
152b955f6caSJeff Kirsher #include <pcmcia/ds.h>
153b955f6caSJeff Kirsher 
154b955f6caSJeff Kirsher #include <asm/uaccess.h>
155b955f6caSJeff Kirsher #include <asm/io.h>
156b955f6caSJeff Kirsher 
157b955f6caSJeff Kirsher /* ----------------------------------------------------------------------------
158b955f6caSJeff Kirsher Defines
159b955f6caSJeff Kirsher ---------------------------------------------------------------------------- */
160b955f6caSJeff Kirsher 
161b955f6caSJeff Kirsher #define MACE_LADRF_LEN			8
162b955f6caSJeff Kirsher 					/* 8 bytes in Logical Address Filter */
163b955f6caSJeff Kirsher 
164b955f6caSJeff Kirsher /* Loop Control Defines */
165b955f6caSJeff Kirsher #define MACE_MAX_IR_ITERATIONS		10
166b955f6caSJeff Kirsher #define MACE_MAX_RX_ITERATIONS		12
167b955f6caSJeff Kirsher 	/*
168b955f6caSJeff Kirsher 	TBD: Dean brought this up, and I assumed the hardware would
169b955f6caSJeff Kirsher 	handle it:
170b955f6caSJeff Kirsher 
171b955f6caSJeff Kirsher 	If MACE_MAX_RX_ITERATIONS is > 1, rx_framecnt may still be
172b955f6caSJeff Kirsher 	non-zero when the isr exits.  We may not get another interrupt
173b955f6caSJeff Kirsher 	to process the remaining packets for some time.
174b955f6caSJeff Kirsher 	*/
175b955f6caSJeff Kirsher 
176b955f6caSJeff Kirsher /*
177b955f6caSJeff Kirsher The Am2150 has a Xilinx XC3042 field programmable gate array (FPGA)
178b955f6caSJeff Kirsher which manages the interface between the MACE and the PCMCIA bus.  It
179b955f6caSJeff Kirsher also includes buffer management for the 32K x 8 SRAM to control up to
180b955f6caSJeff Kirsher four transmit and 12 receive frames at a time.
181b955f6caSJeff Kirsher */
182b955f6caSJeff Kirsher #define AM2150_MAX_TX_FRAMES		4
183b955f6caSJeff Kirsher #define AM2150_MAX_RX_FRAMES		12
184b955f6caSJeff Kirsher 
185b955f6caSJeff Kirsher /* Am2150 Ethernet Card I/O Mapping */
186b955f6caSJeff Kirsher #define AM2150_RCV			0x00
187b955f6caSJeff Kirsher #define AM2150_XMT			0x04
188b955f6caSJeff Kirsher #define AM2150_XMT_SKIP			0x09
189b955f6caSJeff Kirsher #define AM2150_RCV_NEXT			0x0A
190b955f6caSJeff Kirsher #define AM2150_RCV_FRAME_COUNT		0x0B
191b955f6caSJeff Kirsher #define AM2150_MACE_BANK		0x0C
192b955f6caSJeff Kirsher #define AM2150_MACE_BASE		0x10
193b955f6caSJeff Kirsher 
194b955f6caSJeff Kirsher /* MACE Registers */
195b955f6caSJeff Kirsher #define MACE_RCVFIFO			0
196b955f6caSJeff Kirsher #define MACE_XMTFIFO			1
197b955f6caSJeff Kirsher #define MACE_XMTFC			2
198b955f6caSJeff Kirsher #define MACE_XMTFS			3
199b955f6caSJeff Kirsher #define MACE_XMTRC			4
200b955f6caSJeff Kirsher #define MACE_RCVFC			5
201b955f6caSJeff Kirsher #define MACE_RCVFS			6
202b955f6caSJeff Kirsher #define MACE_FIFOFC			7
203b955f6caSJeff Kirsher #define MACE_IR				8
204b955f6caSJeff Kirsher #define MACE_IMR			9
205b955f6caSJeff Kirsher #define MACE_PR				10
206b955f6caSJeff Kirsher #define MACE_BIUCC			11
207b955f6caSJeff Kirsher #define MACE_FIFOCC			12
208b955f6caSJeff Kirsher #define MACE_MACCC			13
209b955f6caSJeff Kirsher #define MACE_PLSCC			14
210b955f6caSJeff Kirsher #define MACE_PHYCC			15
211b955f6caSJeff Kirsher #define MACE_CHIPIDL			16
212b955f6caSJeff Kirsher #define MACE_CHIPIDH			17
213b955f6caSJeff Kirsher #define MACE_IAC			18
214b955f6caSJeff Kirsher /* Reserved */
215b955f6caSJeff Kirsher #define MACE_LADRF			20
216b955f6caSJeff Kirsher #define MACE_PADR			21
217b955f6caSJeff Kirsher /* Reserved */
218b955f6caSJeff Kirsher /* Reserved */
219b955f6caSJeff Kirsher #define MACE_MPC			24
220b955f6caSJeff Kirsher /* Reserved */
221b955f6caSJeff Kirsher #define MACE_RNTPC			26
222b955f6caSJeff Kirsher #define MACE_RCVCC			27
223b955f6caSJeff Kirsher /* Reserved */
224b955f6caSJeff Kirsher #define MACE_UTR			29
225b955f6caSJeff Kirsher #define MACE_RTR1			30
226b955f6caSJeff Kirsher #define MACE_RTR2			31
227b955f6caSJeff Kirsher 
228b955f6caSJeff Kirsher /* MACE Bit Masks */
229b955f6caSJeff Kirsher #define MACE_XMTRC_EXDEF		0x80
230b955f6caSJeff Kirsher #define MACE_XMTRC_XMTRC		0x0F
231b955f6caSJeff Kirsher 
232b955f6caSJeff Kirsher #define MACE_XMTFS_XMTSV		0x80
233b955f6caSJeff Kirsher #define MACE_XMTFS_UFLO			0x40
234b955f6caSJeff Kirsher #define MACE_XMTFS_LCOL			0x20
235b955f6caSJeff Kirsher #define MACE_XMTFS_MORE			0x10
236b955f6caSJeff Kirsher #define MACE_XMTFS_ONE			0x08
237b955f6caSJeff Kirsher #define MACE_XMTFS_DEFER		0x04
238b955f6caSJeff Kirsher #define MACE_XMTFS_LCAR			0x02
239b955f6caSJeff Kirsher #define MACE_XMTFS_RTRY			0x01
240b955f6caSJeff Kirsher 
241b955f6caSJeff Kirsher #define MACE_RCVFS_RCVSTS		0xF000
242b955f6caSJeff Kirsher #define MACE_RCVFS_OFLO			0x8000
243b955f6caSJeff Kirsher #define MACE_RCVFS_CLSN			0x4000
244b955f6caSJeff Kirsher #define MACE_RCVFS_FRAM			0x2000
245b955f6caSJeff Kirsher #define MACE_RCVFS_FCS			0x1000
246b955f6caSJeff Kirsher 
247b955f6caSJeff Kirsher #define MACE_FIFOFC_RCVFC		0xF0
248b955f6caSJeff Kirsher #define MACE_FIFOFC_XMTFC		0x0F
249b955f6caSJeff Kirsher 
250b955f6caSJeff Kirsher #define MACE_IR_JAB			0x80
251b955f6caSJeff Kirsher #define MACE_IR_BABL			0x40
252b955f6caSJeff Kirsher #define MACE_IR_CERR			0x20
253b955f6caSJeff Kirsher #define MACE_IR_RCVCCO			0x10
254b955f6caSJeff Kirsher #define MACE_IR_RNTPCO			0x08
255b955f6caSJeff Kirsher #define MACE_IR_MPCO			0x04
256b955f6caSJeff Kirsher #define MACE_IR_RCVINT			0x02
257b955f6caSJeff Kirsher #define MACE_IR_XMTINT			0x01
258b955f6caSJeff Kirsher 
259b955f6caSJeff Kirsher #define MACE_MACCC_PROM			0x80
260b955f6caSJeff Kirsher #define MACE_MACCC_DXMT2PD		0x40
261b955f6caSJeff Kirsher #define MACE_MACCC_EMBA			0x20
262b955f6caSJeff Kirsher #define MACE_MACCC_RESERVED		0x10
263b955f6caSJeff Kirsher #define MACE_MACCC_DRCVPA		0x08
264b955f6caSJeff Kirsher #define MACE_MACCC_DRCVBC		0x04
265b955f6caSJeff Kirsher #define MACE_MACCC_ENXMT		0x02
266b955f6caSJeff Kirsher #define MACE_MACCC_ENRCV		0x01
267b955f6caSJeff Kirsher 
268b955f6caSJeff Kirsher #define MACE_PHYCC_LNKFL		0x80
269b955f6caSJeff Kirsher #define MACE_PHYCC_DLNKTST		0x40
270b955f6caSJeff Kirsher #define MACE_PHYCC_REVPOL		0x20
271b955f6caSJeff Kirsher #define MACE_PHYCC_DAPC			0x10
272b955f6caSJeff Kirsher #define MACE_PHYCC_LRT			0x08
273b955f6caSJeff Kirsher #define MACE_PHYCC_ASEL			0x04
274b955f6caSJeff Kirsher #define MACE_PHYCC_RWAKE		0x02
275b955f6caSJeff Kirsher #define MACE_PHYCC_AWAKE		0x01
276b955f6caSJeff Kirsher 
277b955f6caSJeff Kirsher #define MACE_IAC_ADDRCHG		0x80
278b955f6caSJeff Kirsher #define MACE_IAC_PHYADDR		0x04
279b955f6caSJeff Kirsher #define MACE_IAC_LOGADDR		0x02
280b955f6caSJeff Kirsher 
281b955f6caSJeff Kirsher #define MACE_UTR_RTRE			0x80
282b955f6caSJeff Kirsher #define MACE_UTR_RTRD			0x40
283b955f6caSJeff Kirsher #define MACE_UTR_RPA			0x20
284b955f6caSJeff Kirsher #define MACE_UTR_FCOLL			0x10
285b955f6caSJeff Kirsher #define MACE_UTR_RCVFCSE		0x08
286b955f6caSJeff Kirsher #define MACE_UTR_LOOP_INCL_MENDEC	0x06
287b955f6caSJeff Kirsher #define MACE_UTR_LOOP_NO_MENDEC		0x04
288b955f6caSJeff Kirsher #define MACE_UTR_LOOP_EXTERNAL		0x02
289b955f6caSJeff Kirsher #define MACE_UTR_LOOP_NONE		0x00
290b955f6caSJeff Kirsher #define MACE_UTR_RESERVED		0x01
291b955f6caSJeff Kirsher 
292b955f6caSJeff Kirsher /* Switch MACE register bank (only 0 and 1 are valid) */
293b955f6caSJeff Kirsher #define MACEBANK(win_num) outb((win_num), ioaddr + AM2150_MACE_BANK)
294b955f6caSJeff Kirsher 
295b955f6caSJeff Kirsher #define MACE_IMR_DEFAULT \
296b955f6caSJeff Kirsher   (0xFF - \
297b955f6caSJeff Kirsher     ( \
298b955f6caSJeff Kirsher       MACE_IR_CERR | \
299b955f6caSJeff Kirsher       MACE_IR_RCVCCO | \
300b955f6caSJeff Kirsher       MACE_IR_RNTPCO | \
301b955f6caSJeff Kirsher       MACE_IR_MPCO | \
302b955f6caSJeff Kirsher       MACE_IR_RCVINT | \
303b955f6caSJeff Kirsher       MACE_IR_XMTINT \
304b955f6caSJeff Kirsher     ) \
305b955f6caSJeff Kirsher   )
306b955f6caSJeff Kirsher #undef MACE_IMR_DEFAULT
307b955f6caSJeff Kirsher #define MACE_IMR_DEFAULT 0x00 /* New statistics handling: grab everything */
308b955f6caSJeff Kirsher 
309b955f6caSJeff Kirsher #define TX_TIMEOUT		((400*HZ)/1000)
310b955f6caSJeff Kirsher 
311b955f6caSJeff Kirsher /* ----------------------------------------------------------------------------
312b955f6caSJeff Kirsher Type Definitions
313b955f6caSJeff Kirsher ---------------------------------------------------------------------------- */
314b955f6caSJeff Kirsher 
315b955f6caSJeff Kirsher typedef struct _mace_statistics {
316b955f6caSJeff Kirsher     /* MACE_XMTFS */
317b955f6caSJeff Kirsher     int xmtsv;
318b955f6caSJeff Kirsher     int uflo;
319b955f6caSJeff Kirsher     int lcol;
320b955f6caSJeff Kirsher     int more;
321b955f6caSJeff Kirsher     int one;
322b955f6caSJeff Kirsher     int defer;
323b955f6caSJeff Kirsher     int lcar;
324b955f6caSJeff Kirsher     int rtry;
325b955f6caSJeff Kirsher 
326b955f6caSJeff Kirsher     /* MACE_XMTRC */
327b955f6caSJeff Kirsher     int exdef;
328b955f6caSJeff Kirsher     int xmtrc;
329b955f6caSJeff Kirsher 
330b955f6caSJeff Kirsher     /* RFS1--Receive Status (RCVSTS) */
331b955f6caSJeff Kirsher     int oflo;
332b955f6caSJeff Kirsher     int clsn;
333b955f6caSJeff Kirsher     int fram;
334b955f6caSJeff Kirsher     int fcs;
335b955f6caSJeff Kirsher 
336b955f6caSJeff Kirsher     /* RFS2--Runt Packet Count (RNTPC) */
337b955f6caSJeff Kirsher     int rfs_rntpc;
338b955f6caSJeff Kirsher 
339b955f6caSJeff Kirsher     /* RFS3--Receive Collision Count (RCVCC) */
340b955f6caSJeff Kirsher     int rfs_rcvcc;
341b955f6caSJeff Kirsher 
342b955f6caSJeff Kirsher     /* MACE_IR */
343b955f6caSJeff Kirsher     int jab;
344b955f6caSJeff Kirsher     int babl;
345b955f6caSJeff Kirsher     int cerr;
346b955f6caSJeff Kirsher     int rcvcco;
347b955f6caSJeff Kirsher     int rntpco;
348b955f6caSJeff Kirsher     int mpco;
349b955f6caSJeff Kirsher 
350b955f6caSJeff Kirsher     /* MACE_MPC */
351b955f6caSJeff Kirsher     int mpc;
352b955f6caSJeff Kirsher 
353b955f6caSJeff Kirsher     /* MACE_RNTPC */
354b955f6caSJeff Kirsher     int rntpc;
355b955f6caSJeff Kirsher 
356b955f6caSJeff Kirsher     /* MACE_RCVCC */
357b955f6caSJeff Kirsher     int rcvcc;
358b955f6caSJeff Kirsher } mace_statistics;
359b955f6caSJeff Kirsher 
360b955f6caSJeff Kirsher typedef struct _mace_private {
361b955f6caSJeff Kirsher 	struct pcmcia_device	*p_dev;
362b955f6caSJeff Kirsher     struct net_device_stats linux_stats; /* Linux statistics counters */
363b955f6caSJeff Kirsher     mace_statistics mace_stats; /* MACE chip statistics counters */
364b955f6caSJeff Kirsher 
365b955f6caSJeff Kirsher     /* restore_multicast_list() state variables */
366b955f6caSJeff Kirsher     int multicast_ladrf[MACE_LADRF_LEN]; /* Logical address filter */
367b955f6caSJeff Kirsher     int multicast_num_addrs;
368b955f6caSJeff Kirsher 
369b955f6caSJeff Kirsher     char tx_free_frames; /* Number of free transmit frame buffers */
370b955f6caSJeff Kirsher     char tx_irq_disabled; /* MACE TX interrupt disabled */
371b955f6caSJeff Kirsher 
372b955f6caSJeff Kirsher     spinlock_t bank_lock; /* Must be held if you step off bank 0 */
373b955f6caSJeff Kirsher } mace_private;
374b955f6caSJeff Kirsher 
375b955f6caSJeff Kirsher /* ----------------------------------------------------------------------------
376b955f6caSJeff Kirsher Private Global Variables
377b955f6caSJeff Kirsher ---------------------------------------------------------------------------- */
378b955f6caSJeff Kirsher 
379b955f6caSJeff Kirsher static const char *if_names[]={
380b955f6caSJeff Kirsher     "Auto", "10baseT", "BNC",
381b955f6caSJeff Kirsher };
382b955f6caSJeff Kirsher 
383b955f6caSJeff Kirsher /* ----------------------------------------------------------------------------
384b955f6caSJeff Kirsher Parameters
385b955f6caSJeff Kirsher 	These are the parameters that can be set during loading with
386b955f6caSJeff Kirsher 	'insmod'.
387b955f6caSJeff Kirsher ---------------------------------------------------------------------------- */
388b955f6caSJeff Kirsher 
389b955f6caSJeff Kirsher MODULE_DESCRIPTION("New Media PCMCIA ethernet driver");
390b955f6caSJeff Kirsher MODULE_LICENSE("GPL");
391b955f6caSJeff Kirsher 
392b955f6caSJeff Kirsher #define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0)
393b955f6caSJeff Kirsher 
394b955f6caSJeff Kirsher /* 0=auto, 1=10baseT, 2 = 10base2, default=auto */
395b955f6caSJeff Kirsher INT_MODULE_PARM(if_port, 0);
396b955f6caSJeff Kirsher 
397b955f6caSJeff Kirsher 
398b955f6caSJeff Kirsher /* ----------------------------------------------------------------------------
399b955f6caSJeff Kirsher Function Prototypes
400b955f6caSJeff Kirsher ---------------------------------------------------------------------------- */
401b955f6caSJeff Kirsher 
402b955f6caSJeff Kirsher static int nmclan_config(struct pcmcia_device *link);
403b955f6caSJeff Kirsher static void nmclan_release(struct pcmcia_device *link);
404b955f6caSJeff Kirsher 
405b955f6caSJeff Kirsher static void nmclan_reset(struct net_device *dev);
406b955f6caSJeff Kirsher static int mace_config(struct net_device *dev, struct ifmap *map);
407b955f6caSJeff Kirsher static int mace_open(struct net_device *dev);
408b955f6caSJeff Kirsher static int mace_close(struct net_device *dev);
409b955f6caSJeff Kirsher static netdev_tx_t mace_start_xmit(struct sk_buff *skb,
410b955f6caSJeff Kirsher 					 struct net_device *dev);
411b955f6caSJeff Kirsher static void mace_tx_timeout(struct net_device *dev);
412b955f6caSJeff Kirsher static irqreturn_t mace_interrupt(int irq, void *dev_id);
413b955f6caSJeff Kirsher static struct net_device_stats *mace_get_stats(struct net_device *dev);
414b955f6caSJeff Kirsher static int mace_rx(struct net_device *dev, unsigned char RxCnt);
415b955f6caSJeff Kirsher static void restore_multicast_list(struct net_device *dev);
416b955f6caSJeff Kirsher static void set_multicast_list(struct net_device *dev);
417b955f6caSJeff Kirsher static const struct ethtool_ops netdev_ethtool_ops;
418b955f6caSJeff Kirsher 
419b955f6caSJeff Kirsher 
420b955f6caSJeff Kirsher static void nmclan_detach(struct pcmcia_device *p_dev);
421b955f6caSJeff Kirsher 
422b955f6caSJeff Kirsher static const struct net_device_ops mace_netdev_ops = {
423b955f6caSJeff Kirsher 	.ndo_open		= mace_open,
424b955f6caSJeff Kirsher 	.ndo_stop		= mace_close,
425b955f6caSJeff Kirsher 	.ndo_start_xmit		= mace_start_xmit,
426b955f6caSJeff Kirsher 	.ndo_tx_timeout		= mace_tx_timeout,
427b955f6caSJeff Kirsher 	.ndo_set_config		= mace_config,
428b955f6caSJeff Kirsher 	.ndo_get_stats		= mace_get_stats,
429afc4b13dSJiri Pirko 	.ndo_set_rx_mode	= set_multicast_list,
430b955f6caSJeff Kirsher 	.ndo_change_mtu		= eth_change_mtu,
431b955f6caSJeff Kirsher 	.ndo_set_mac_address 	= eth_mac_addr,
432b955f6caSJeff Kirsher 	.ndo_validate_addr	= eth_validate_addr,
433b955f6caSJeff Kirsher };
434b955f6caSJeff Kirsher 
435b955f6caSJeff Kirsher static int nmclan_probe(struct pcmcia_device *link)
436b955f6caSJeff Kirsher {
437b955f6caSJeff Kirsher     mace_private *lp;
438b955f6caSJeff Kirsher     struct net_device *dev;
439b955f6caSJeff Kirsher 
440b955f6caSJeff Kirsher     dev_dbg(&link->dev, "nmclan_attach()\n");
441b955f6caSJeff Kirsher 
442b955f6caSJeff Kirsher     /* Create new ethernet device */
443b955f6caSJeff Kirsher     dev = alloc_etherdev(sizeof(mace_private));
444b955f6caSJeff Kirsher     if (!dev)
445b955f6caSJeff Kirsher 	    return -ENOMEM;
446b955f6caSJeff Kirsher     lp = netdev_priv(dev);
447b955f6caSJeff Kirsher     lp->p_dev = link;
448b955f6caSJeff Kirsher     link->priv = dev;
449b955f6caSJeff Kirsher 
450b955f6caSJeff Kirsher     spin_lock_init(&lp->bank_lock);
451b955f6caSJeff Kirsher     link->resource[0]->end = 32;
452b955f6caSJeff Kirsher     link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
453b955f6caSJeff Kirsher     link->config_flags |= CONF_ENABLE_IRQ;
454b955f6caSJeff Kirsher     link->config_index = 1;
455b955f6caSJeff Kirsher     link->config_regs = PRESENT_OPTION;
456b955f6caSJeff Kirsher 
457b955f6caSJeff Kirsher     lp->tx_free_frames=AM2150_MAX_TX_FRAMES;
458b955f6caSJeff Kirsher 
459b955f6caSJeff Kirsher     dev->netdev_ops = &mace_netdev_ops;
4607ad24ea4SWilfried Klaebe     dev->ethtool_ops = &netdev_ethtool_ops;
461b955f6caSJeff Kirsher     dev->watchdog_timeo = TX_TIMEOUT;
462b955f6caSJeff Kirsher 
463b955f6caSJeff Kirsher     return nmclan_config(link);
464b955f6caSJeff Kirsher } /* nmclan_attach */
465b955f6caSJeff Kirsher 
466b955f6caSJeff Kirsher static void nmclan_detach(struct pcmcia_device *link)
467b955f6caSJeff Kirsher {
468b955f6caSJeff Kirsher     struct net_device *dev = link->priv;
469b955f6caSJeff Kirsher 
470b955f6caSJeff Kirsher     dev_dbg(&link->dev, "nmclan_detach\n");
471b955f6caSJeff Kirsher 
472b955f6caSJeff Kirsher     unregister_netdev(dev);
473b955f6caSJeff Kirsher 
474b955f6caSJeff Kirsher     nmclan_release(link);
475b955f6caSJeff Kirsher 
476b955f6caSJeff Kirsher     free_netdev(dev);
477b955f6caSJeff Kirsher } /* nmclan_detach */
478b955f6caSJeff Kirsher 
479b955f6caSJeff Kirsher /* ----------------------------------------------------------------------------
480b955f6caSJeff Kirsher mace_read
481b955f6caSJeff Kirsher 	Reads a MACE register.  This is bank independent; however, the
482b955f6caSJeff Kirsher 	caller must ensure that this call is not interruptable.  We are
483b955f6caSJeff Kirsher 	assuming that during normal operation, the MACE is always in
484b955f6caSJeff Kirsher 	bank 0.
485b955f6caSJeff Kirsher ---------------------------------------------------------------------------- */
486b955f6caSJeff Kirsher static int mace_read(mace_private *lp, unsigned int ioaddr, int reg)
487b955f6caSJeff Kirsher {
488b955f6caSJeff Kirsher   int data = 0xFF;
489b955f6caSJeff Kirsher   unsigned long flags;
490b955f6caSJeff Kirsher 
491b955f6caSJeff Kirsher   switch (reg >> 4) {
492b955f6caSJeff Kirsher     case 0: /* register 0-15 */
493b955f6caSJeff Kirsher       data = inb(ioaddr + AM2150_MACE_BASE + reg);
494b955f6caSJeff Kirsher       break;
495b955f6caSJeff Kirsher     case 1: /* register 16-31 */
496b955f6caSJeff Kirsher       spin_lock_irqsave(&lp->bank_lock, flags);
497b955f6caSJeff Kirsher       MACEBANK(1);
498b955f6caSJeff Kirsher       data = inb(ioaddr + AM2150_MACE_BASE + (reg & 0x0F));
499b955f6caSJeff Kirsher       MACEBANK(0);
500b955f6caSJeff Kirsher       spin_unlock_irqrestore(&lp->bank_lock, flags);
501b955f6caSJeff Kirsher       break;
502b955f6caSJeff Kirsher   }
503b955f6caSJeff Kirsher   return data & 0xFF;
504b955f6caSJeff Kirsher } /* mace_read */
505b955f6caSJeff Kirsher 
506b955f6caSJeff Kirsher /* ----------------------------------------------------------------------------
507b955f6caSJeff Kirsher mace_write
508b955f6caSJeff Kirsher 	Writes to a MACE register.  This is bank independent; however,
509b955f6caSJeff Kirsher 	the caller must ensure that this call is not interruptable.  We
510b955f6caSJeff Kirsher 	are assuming that during normal operation, the MACE is always in
511b955f6caSJeff Kirsher 	bank 0.
512b955f6caSJeff Kirsher ---------------------------------------------------------------------------- */
513b955f6caSJeff Kirsher static void mace_write(mace_private *lp, unsigned int ioaddr, int reg,
514b955f6caSJeff Kirsher 		       int data)
515b955f6caSJeff Kirsher {
516b955f6caSJeff Kirsher   unsigned long flags;
517b955f6caSJeff Kirsher 
518b955f6caSJeff Kirsher   switch (reg >> 4) {
519b955f6caSJeff Kirsher     case 0: /* register 0-15 */
520b955f6caSJeff Kirsher       outb(data & 0xFF, ioaddr + AM2150_MACE_BASE + reg);
521b955f6caSJeff Kirsher       break;
522b955f6caSJeff Kirsher     case 1: /* register 16-31 */
523b955f6caSJeff Kirsher       spin_lock_irqsave(&lp->bank_lock, flags);
524b955f6caSJeff Kirsher       MACEBANK(1);
525b955f6caSJeff Kirsher       outb(data & 0xFF, ioaddr + AM2150_MACE_BASE + (reg & 0x0F));
526b955f6caSJeff Kirsher       MACEBANK(0);
527b955f6caSJeff Kirsher       spin_unlock_irqrestore(&lp->bank_lock, flags);
528b955f6caSJeff Kirsher       break;
529b955f6caSJeff Kirsher   }
530b955f6caSJeff Kirsher } /* mace_write */
531b955f6caSJeff Kirsher 
532b955f6caSJeff Kirsher /* ----------------------------------------------------------------------------
533b955f6caSJeff Kirsher mace_init
534b955f6caSJeff Kirsher 	Resets the MACE chip.
535b955f6caSJeff Kirsher ---------------------------------------------------------------------------- */
536b955f6caSJeff Kirsher static int mace_init(mace_private *lp, unsigned int ioaddr, char *enet_addr)
537b955f6caSJeff Kirsher {
538b955f6caSJeff Kirsher   int i;
539b955f6caSJeff Kirsher   int ct = 0;
540b955f6caSJeff Kirsher 
541b955f6caSJeff Kirsher   /* MACE Software reset */
542b955f6caSJeff Kirsher   mace_write(lp, ioaddr, MACE_BIUCC, 1);
543b955f6caSJeff Kirsher   while (mace_read(lp, ioaddr, MACE_BIUCC) & 0x01) {
544b955f6caSJeff Kirsher     /* Wait for reset bit to be cleared automatically after <= 200ns */;
545b955f6caSJeff Kirsher     if(++ct > 500)
546b955f6caSJeff Kirsher     {
547b955f6caSJeff Kirsher 	pr_err("reset failed, card removed?\n");
548b955f6caSJeff Kirsher     	return -1;
549b955f6caSJeff Kirsher     }
550b955f6caSJeff Kirsher     udelay(1);
551b955f6caSJeff Kirsher   }
552b955f6caSJeff Kirsher   mace_write(lp, ioaddr, MACE_BIUCC, 0);
553b955f6caSJeff Kirsher 
554b955f6caSJeff Kirsher   /* The Am2150 requires that the MACE FIFOs operate in burst mode. */
555b955f6caSJeff Kirsher   mace_write(lp, ioaddr, MACE_FIFOCC, 0x0F);
556b955f6caSJeff Kirsher 
557b955f6caSJeff Kirsher   mace_write(lp,ioaddr, MACE_RCVFC, 0); /* Disable Auto Strip Receive */
558b955f6caSJeff Kirsher   mace_write(lp, ioaddr, MACE_IMR, 0xFF); /* Disable all interrupts until _open */
559b955f6caSJeff Kirsher 
560b955f6caSJeff Kirsher   /*
561b955f6caSJeff Kirsher    * Bit 2-1 PORTSEL[1-0] Port Select.
562b955f6caSJeff Kirsher    * 00 AUI/10Base-2
563b955f6caSJeff Kirsher    * 01 10Base-T
564b955f6caSJeff Kirsher    * 10 DAI Port (reserved in Am2150)
565b955f6caSJeff Kirsher    * 11 GPSI
566b955f6caSJeff Kirsher    * For this card, only the first two are valid.
567b955f6caSJeff Kirsher    * So, PLSCC should be set to
568b955f6caSJeff Kirsher    * 0x00 for 10Base-2
569b955f6caSJeff Kirsher    * 0x02 for 10Base-T
570b955f6caSJeff Kirsher    * Or just set ASEL in PHYCC below!
571b955f6caSJeff Kirsher    */
572b955f6caSJeff Kirsher   switch (if_port) {
573b955f6caSJeff Kirsher     case 1:
574b955f6caSJeff Kirsher       mace_write(lp, ioaddr, MACE_PLSCC, 0x02);
575b955f6caSJeff Kirsher       break;
576b955f6caSJeff Kirsher     case 2:
577b955f6caSJeff Kirsher       mace_write(lp, ioaddr, MACE_PLSCC, 0x00);
578b955f6caSJeff Kirsher       break;
579b955f6caSJeff Kirsher     default:
580b955f6caSJeff Kirsher       mace_write(lp, ioaddr, MACE_PHYCC, /* ASEL */ 4);
581b955f6caSJeff Kirsher       /* ASEL Auto Select.  When set, the PORTSEL[1-0] bits are overridden,
582b955f6caSJeff Kirsher 	 and the MACE device will automatically select the operating media
583b955f6caSJeff Kirsher 	 interface port. */
584b955f6caSJeff Kirsher       break;
585b955f6caSJeff Kirsher   }
586b955f6caSJeff Kirsher 
587b955f6caSJeff Kirsher   mace_write(lp, ioaddr, MACE_IAC, MACE_IAC_ADDRCHG | MACE_IAC_PHYADDR);
588b955f6caSJeff Kirsher   /* Poll ADDRCHG bit */
589b955f6caSJeff Kirsher   ct = 0;
590b955f6caSJeff Kirsher   while (mace_read(lp, ioaddr, MACE_IAC) & MACE_IAC_ADDRCHG)
591b955f6caSJeff Kirsher   {
592b955f6caSJeff Kirsher   	if(++ ct > 500)
593b955f6caSJeff Kirsher   	{
594b955f6caSJeff Kirsher 		pr_err("ADDRCHG timeout, card removed?\n");
595b955f6caSJeff Kirsher   		return -1;
596b955f6caSJeff Kirsher   	}
597b955f6caSJeff Kirsher   }
598b955f6caSJeff Kirsher   /* Set PADR register */
599104bf3fbSJoe Perches   for (i = 0; i < ETH_ALEN; i++)
600b955f6caSJeff Kirsher     mace_write(lp, ioaddr, MACE_PADR, enet_addr[i]);
601b955f6caSJeff Kirsher 
602b955f6caSJeff Kirsher   /* MAC Configuration Control Register should be written last */
603b955f6caSJeff Kirsher   /* Let set_multicast_list set this. */
604b955f6caSJeff Kirsher   /* mace_write(lp, ioaddr, MACE_MACCC, MACE_MACCC_ENXMT | MACE_MACCC_ENRCV); */
605b955f6caSJeff Kirsher   mace_write(lp, ioaddr, MACE_MACCC, 0x00);
606b955f6caSJeff Kirsher   return 0;
607b955f6caSJeff Kirsher } /* mace_init */
608b955f6caSJeff Kirsher 
609b955f6caSJeff Kirsher static int nmclan_config(struct pcmcia_device *link)
610b955f6caSJeff Kirsher {
611b955f6caSJeff Kirsher   struct net_device *dev = link->priv;
612b955f6caSJeff Kirsher   mace_private *lp = netdev_priv(dev);
613b955f6caSJeff Kirsher   u8 *buf;
614b955f6caSJeff Kirsher   size_t len;
615b955f6caSJeff Kirsher   int i, ret;
616b955f6caSJeff Kirsher   unsigned int ioaddr;
617b955f6caSJeff Kirsher 
618b955f6caSJeff Kirsher   dev_dbg(&link->dev, "nmclan_config\n");
619b955f6caSJeff Kirsher 
620b955f6caSJeff Kirsher   link->io_lines = 5;
621b955f6caSJeff Kirsher   ret = pcmcia_request_io(link);
622b955f6caSJeff Kirsher   if (ret)
623b955f6caSJeff Kirsher 	  goto failed;
6245f5316fcSJeff Kirsher   ret = pcmcia_request_irq(link, mace_interrupt);
625b955f6caSJeff Kirsher   if (ret)
626b955f6caSJeff Kirsher 	  goto failed;
627b955f6caSJeff Kirsher   ret = pcmcia_enable_device(link);
628b955f6caSJeff Kirsher   if (ret)
629b955f6caSJeff Kirsher 	  goto failed;
630b955f6caSJeff Kirsher 
631b955f6caSJeff Kirsher   dev->irq = link->irq;
632b955f6caSJeff Kirsher   dev->base_addr = link->resource[0]->start;
633b955f6caSJeff Kirsher 
634b955f6caSJeff Kirsher   ioaddr = dev->base_addr;
635b955f6caSJeff Kirsher 
636b955f6caSJeff Kirsher   /* Read the ethernet address from the CIS. */
637b955f6caSJeff Kirsher   len = pcmcia_get_tuple(link, 0x80, &buf);
638104bf3fbSJoe Perches   if (!buf || len < ETH_ALEN) {
639b955f6caSJeff Kirsher 	  kfree(buf);
640b955f6caSJeff Kirsher 	  goto failed;
641b955f6caSJeff Kirsher   }
642104bf3fbSJoe Perches   memcpy(dev->dev_addr, buf, ETH_ALEN);
643b955f6caSJeff Kirsher   kfree(buf);
644b955f6caSJeff Kirsher 
645b955f6caSJeff Kirsher   /* Verify configuration by reading the MACE ID. */
646b955f6caSJeff Kirsher   {
647b955f6caSJeff Kirsher     char sig[2];
648b955f6caSJeff Kirsher 
649b955f6caSJeff Kirsher     sig[0] = mace_read(lp, ioaddr, MACE_CHIPIDL);
650b955f6caSJeff Kirsher     sig[1] = mace_read(lp, ioaddr, MACE_CHIPIDH);
651b955f6caSJeff Kirsher     if ((sig[0] == 0x40) && ((sig[1] & 0x0F) == 0x09)) {
652b955f6caSJeff Kirsher       dev_dbg(&link->dev, "nmclan_cs configured: mace id=%x %x\n",
653b955f6caSJeff Kirsher 	    sig[0], sig[1]);
654b955f6caSJeff Kirsher     } else {
655b955f6caSJeff Kirsher       pr_notice("mace id not found: %x %x should be 0x40 0x?9\n",
656b955f6caSJeff Kirsher 		sig[0], sig[1]);
657b955f6caSJeff Kirsher       return -ENODEV;
658b955f6caSJeff Kirsher     }
659b955f6caSJeff Kirsher   }
660b955f6caSJeff Kirsher 
661b955f6caSJeff Kirsher   if(mace_init(lp, ioaddr, dev->dev_addr) == -1)
662b955f6caSJeff Kirsher   	goto failed;
663b955f6caSJeff Kirsher 
664b955f6caSJeff Kirsher   /* The if_port symbol can be set when the module is loaded */
665b955f6caSJeff Kirsher   if (if_port <= 2)
666b955f6caSJeff Kirsher     dev->if_port = if_port;
667b955f6caSJeff Kirsher   else
668b955f6caSJeff Kirsher     pr_notice("invalid if_port requested\n");
669b955f6caSJeff Kirsher 
670b955f6caSJeff Kirsher   SET_NETDEV_DEV(dev, &link->dev);
671b955f6caSJeff Kirsher 
672b955f6caSJeff Kirsher   i = register_netdev(dev);
673b955f6caSJeff Kirsher   if (i != 0) {
674b955f6caSJeff Kirsher     pr_notice("register_netdev() failed\n");
675b955f6caSJeff Kirsher     goto failed;
676b955f6caSJeff Kirsher   }
677b955f6caSJeff Kirsher 
678b955f6caSJeff Kirsher   netdev_info(dev, "nmclan: port %#3lx, irq %d, %s port, hw_addr %pM\n",
679b955f6caSJeff Kirsher 	      dev->base_addr, dev->irq, if_names[dev->if_port], dev->dev_addr);
680b955f6caSJeff Kirsher   return 0;
681b955f6caSJeff Kirsher 
682b955f6caSJeff Kirsher failed:
683b955f6caSJeff Kirsher 	nmclan_release(link);
684b955f6caSJeff Kirsher 	return -ENODEV;
685b955f6caSJeff Kirsher } /* nmclan_config */
686b955f6caSJeff Kirsher 
687b955f6caSJeff Kirsher static void nmclan_release(struct pcmcia_device *link)
688b955f6caSJeff Kirsher {
689b955f6caSJeff Kirsher 	dev_dbg(&link->dev, "nmclan_release\n");
690b955f6caSJeff Kirsher 	pcmcia_disable_device(link);
691b955f6caSJeff Kirsher }
692b955f6caSJeff Kirsher 
693b955f6caSJeff Kirsher static int nmclan_suspend(struct pcmcia_device *link)
694b955f6caSJeff Kirsher {
695b955f6caSJeff Kirsher 	struct net_device *dev = link->priv;
696b955f6caSJeff Kirsher 
697b955f6caSJeff Kirsher 	if (link->open)
698b955f6caSJeff Kirsher 		netif_device_detach(dev);
699b955f6caSJeff Kirsher 
700b955f6caSJeff Kirsher 	return 0;
701b955f6caSJeff Kirsher }
702b955f6caSJeff Kirsher 
703b955f6caSJeff Kirsher static int nmclan_resume(struct pcmcia_device *link)
704b955f6caSJeff Kirsher {
705b955f6caSJeff Kirsher 	struct net_device *dev = link->priv;
706b955f6caSJeff Kirsher 
707b955f6caSJeff Kirsher 	if (link->open) {
708b955f6caSJeff Kirsher 		nmclan_reset(dev);
709b955f6caSJeff Kirsher 		netif_device_attach(dev);
710b955f6caSJeff Kirsher 	}
711b955f6caSJeff Kirsher 
712b955f6caSJeff Kirsher 	return 0;
713b955f6caSJeff Kirsher }
714b955f6caSJeff Kirsher 
715b955f6caSJeff Kirsher 
716b955f6caSJeff Kirsher /* ----------------------------------------------------------------------------
717b955f6caSJeff Kirsher nmclan_reset
718b955f6caSJeff Kirsher 	Reset and restore all of the Xilinx and MACE registers.
719b955f6caSJeff Kirsher ---------------------------------------------------------------------------- */
720b955f6caSJeff Kirsher static void nmclan_reset(struct net_device *dev)
721b955f6caSJeff Kirsher {
722b955f6caSJeff Kirsher   mace_private *lp = netdev_priv(dev);
723b955f6caSJeff Kirsher 
724b955f6caSJeff Kirsher #if RESET_XILINX
725b955f6caSJeff Kirsher   struct pcmcia_device *link = &lp->link;
726b955f6caSJeff Kirsher   u8 OrigCorValue;
727b955f6caSJeff Kirsher 
728b955f6caSJeff Kirsher   /* Save original COR value */
729b955f6caSJeff Kirsher   pcmcia_read_config_byte(link, CISREG_COR, &OrigCorValue);
730b955f6caSJeff Kirsher 
731b955f6caSJeff Kirsher   /* Reset Xilinx */
732b955f6caSJeff Kirsher   dev_dbg(&link->dev, "nmclan_reset: OrigCorValue=0x%x, resetting...\n",
733b955f6caSJeff Kirsher 	OrigCorValue);
734b955f6caSJeff Kirsher   pcmcia_write_config_byte(link, CISREG_COR, COR_SOFT_RESET);
735b955f6caSJeff Kirsher   /* Need to wait for 20 ms for PCMCIA to finish reset. */
736b955f6caSJeff Kirsher 
737b955f6caSJeff Kirsher   /* Restore original COR configuration index */
738b955f6caSJeff Kirsher   pcmcia_write_config_byte(link, CISREG_COR,
739b955f6caSJeff Kirsher 			  (COR_LEVEL_REQ | (OrigCorValue & COR_CONFIG_MASK)));
740b955f6caSJeff Kirsher   /* Xilinx is now completely reset along with the MACE chip. */
741b955f6caSJeff Kirsher   lp->tx_free_frames=AM2150_MAX_TX_FRAMES;
742b955f6caSJeff Kirsher 
743b955f6caSJeff Kirsher #endif /* #if RESET_XILINX */
744b955f6caSJeff Kirsher 
745b955f6caSJeff Kirsher   /* Xilinx is now completely reset along with the MACE chip. */
746b955f6caSJeff Kirsher   lp->tx_free_frames=AM2150_MAX_TX_FRAMES;
747b955f6caSJeff Kirsher 
748b955f6caSJeff Kirsher   /* Reinitialize the MACE chip for operation. */
749b955f6caSJeff Kirsher   mace_init(lp, dev->base_addr, dev->dev_addr);
750b955f6caSJeff Kirsher   mace_write(lp, dev->base_addr, MACE_IMR, MACE_IMR_DEFAULT);
751b955f6caSJeff Kirsher 
752b955f6caSJeff Kirsher   /* Restore the multicast list and enable TX and RX. */
753b955f6caSJeff Kirsher   restore_multicast_list(dev);
754b955f6caSJeff Kirsher } /* nmclan_reset */
755b955f6caSJeff Kirsher 
756b955f6caSJeff Kirsher /* ----------------------------------------------------------------------------
757b955f6caSJeff Kirsher mace_config
758b955f6caSJeff Kirsher 	[Someone tell me what this is supposed to do?  Is if_port a defined
759b955f6caSJeff Kirsher 	standard?  If so, there should be defines to indicate 1=10Base-T,
760b955f6caSJeff Kirsher 	2=10Base-2, etc. including limited automatic detection.]
761b955f6caSJeff Kirsher ---------------------------------------------------------------------------- */
762b955f6caSJeff Kirsher static int mace_config(struct net_device *dev, struct ifmap *map)
763b955f6caSJeff Kirsher {
764b955f6caSJeff Kirsher   if ((map->port != (u_char)(-1)) && (map->port != dev->if_port)) {
765b955f6caSJeff Kirsher     if (map->port <= 2) {
766b955f6caSJeff Kirsher       dev->if_port = map->port;
767b955f6caSJeff Kirsher       netdev_info(dev, "switched to %s port\n", if_names[dev->if_port]);
768b955f6caSJeff Kirsher     } else
769b955f6caSJeff Kirsher       return -EINVAL;
770b955f6caSJeff Kirsher   }
771b955f6caSJeff Kirsher   return 0;
772b955f6caSJeff Kirsher } /* mace_config */
773b955f6caSJeff Kirsher 
774b955f6caSJeff Kirsher /* ----------------------------------------------------------------------------
775b955f6caSJeff Kirsher mace_open
776b955f6caSJeff Kirsher 	Open device driver.
777b955f6caSJeff Kirsher ---------------------------------------------------------------------------- */
778b955f6caSJeff Kirsher static int mace_open(struct net_device *dev)
779b955f6caSJeff Kirsher {
780b955f6caSJeff Kirsher   unsigned int ioaddr = dev->base_addr;
781b955f6caSJeff Kirsher   mace_private *lp = netdev_priv(dev);
782b955f6caSJeff Kirsher   struct pcmcia_device *link = lp->p_dev;
783b955f6caSJeff Kirsher 
784b955f6caSJeff Kirsher   if (!pcmcia_dev_present(link))
785b955f6caSJeff Kirsher     return -ENODEV;
786b955f6caSJeff Kirsher 
787b955f6caSJeff Kirsher   link->open++;
788b955f6caSJeff Kirsher 
789b955f6caSJeff Kirsher   MACEBANK(0);
790b955f6caSJeff Kirsher 
791b955f6caSJeff Kirsher   netif_start_queue(dev);
792b955f6caSJeff Kirsher   nmclan_reset(dev);
793b955f6caSJeff Kirsher 
794b955f6caSJeff Kirsher   return 0; /* Always succeed */
795b955f6caSJeff Kirsher } /* mace_open */
796b955f6caSJeff Kirsher 
797b955f6caSJeff Kirsher /* ----------------------------------------------------------------------------
798b955f6caSJeff Kirsher mace_close
799b955f6caSJeff Kirsher 	Closes device driver.
800b955f6caSJeff Kirsher ---------------------------------------------------------------------------- */
801b955f6caSJeff Kirsher static int mace_close(struct net_device *dev)
802b955f6caSJeff Kirsher {
803b955f6caSJeff Kirsher   unsigned int ioaddr = dev->base_addr;
804b955f6caSJeff Kirsher   mace_private *lp = netdev_priv(dev);
805b955f6caSJeff Kirsher   struct pcmcia_device *link = lp->p_dev;
806b955f6caSJeff Kirsher 
807b955f6caSJeff Kirsher   dev_dbg(&link->dev, "%s: shutting down ethercard.\n", dev->name);
808b955f6caSJeff Kirsher 
809b955f6caSJeff Kirsher   /* Mask off all interrupts from the MACE chip. */
810b955f6caSJeff Kirsher   outb(0xFF, ioaddr + AM2150_MACE_BASE + MACE_IMR);
811b955f6caSJeff Kirsher 
812b955f6caSJeff Kirsher   link->open--;
813b955f6caSJeff Kirsher   netif_stop_queue(dev);
814b955f6caSJeff Kirsher 
815b955f6caSJeff Kirsher   return 0;
816b955f6caSJeff Kirsher } /* mace_close */
817b955f6caSJeff Kirsher 
818b955f6caSJeff Kirsher static void netdev_get_drvinfo(struct net_device *dev,
819b955f6caSJeff Kirsher 			       struct ethtool_drvinfo *info)
820b955f6caSJeff Kirsher {
82133a5ba14SRick Jones 	strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
82233a5ba14SRick Jones 	strlcpy(info->version, DRV_VERSION, sizeof(info->version));
82333a5ba14SRick Jones 	snprintf(info->bus_info, sizeof(info->bus_info),
82433a5ba14SRick Jones 		"PCMCIA 0x%lx", dev->base_addr);
825b955f6caSJeff Kirsher }
826b955f6caSJeff Kirsher 
827b955f6caSJeff Kirsher static const struct ethtool_ops netdev_ethtool_ops = {
828b955f6caSJeff Kirsher 	.get_drvinfo		= netdev_get_drvinfo,
829b955f6caSJeff Kirsher };
830b955f6caSJeff Kirsher 
831b955f6caSJeff Kirsher /* ----------------------------------------------------------------------------
832b955f6caSJeff Kirsher mace_start_xmit
833b955f6caSJeff Kirsher 	This routine begins the packet transmit function.  When completed,
834b955f6caSJeff Kirsher 	it will generate a transmit interrupt.
835b955f6caSJeff Kirsher 
836b955f6caSJeff Kirsher 	According to /usr/src/linux/net/inet/dev.c, if _start_xmit
837b955f6caSJeff Kirsher 	returns 0, the "packet is now solely the responsibility of the
838b955f6caSJeff Kirsher 	driver."  If _start_xmit returns non-zero, the "transmission
839b955f6caSJeff Kirsher 	failed, put skb back into a list."
840b955f6caSJeff Kirsher ---------------------------------------------------------------------------- */
841b955f6caSJeff Kirsher 
842b955f6caSJeff Kirsher static void mace_tx_timeout(struct net_device *dev)
843b955f6caSJeff Kirsher {
844b955f6caSJeff Kirsher   mace_private *lp = netdev_priv(dev);
845b955f6caSJeff Kirsher   struct pcmcia_device *link = lp->p_dev;
846b955f6caSJeff Kirsher 
847b955f6caSJeff Kirsher   netdev_notice(dev, "transmit timed out -- ");
848b955f6caSJeff Kirsher #if RESET_ON_TIMEOUT
849b955f6caSJeff Kirsher   pr_cont("resetting card\n");
850b955f6caSJeff Kirsher   pcmcia_reset_card(link->socket);
851b955f6caSJeff Kirsher #else /* #if RESET_ON_TIMEOUT */
852b955f6caSJeff Kirsher   pr_cont("NOT resetting card\n");
853b955f6caSJeff Kirsher #endif /* #if RESET_ON_TIMEOUT */
854b955f6caSJeff Kirsher   dev->trans_start = jiffies; /* prevent tx timeout */
855b955f6caSJeff Kirsher   netif_wake_queue(dev);
856b955f6caSJeff Kirsher }
857b955f6caSJeff Kirsher 
858b955f6caSJeff Kirsher static netdev_tx_t mace_start_xmit(struct sk_buff *skb,
859b955f6caSJeff Kirsher 					 struct net_device *dev)
860b955f6caSJeff Kirsher {
861b955f6caSJeff Kirsher   mace_private *lp = netdev_priv(dev);
862b955f6caSJeff Kirsher   unsigned int ioaddr = dev->base_addr;
863b955f6caSJeff Kirsher 
864b955f6caSJeff Kirsher   netif_stop_queue(dev);
865b955f6caSJeff Kirsher 
866b955f6caSJeff Kirsher   pr_debug("%s: mace_start_xmit(length = %ld) called.\n",
867b955f6caSJeff Kirsher 	dev->name, (long)skb->len);
868b955f6caSJeff Kirsher 
869b955f6caSJeff Kirsher #if (!TX_INTERRUPTABLE)
870b955f6caSJeff Kirsher   /* Disable MACE TX interrupts. */
871b955f6caSJeff Kirsher   outb(MACE_IMR_DEFAULT | MACE_IR_XMTINT,
872b955f6caSJeff Kirsher     ioaddr + AM2150_MACE_BASE + MACE_IMR);
873b955f6caSJeff Kirsher   lp->tx_irq_disabled=1;
874b955f6caSJeff Kirsher #endif /* #if (!TX_INTERRUPTABLE) */
875b955f6caSJeff Kirsher 
876b955f6caSJeff Kirsher   {
877b955f6caSJeff Kirsher     /* This block must not be interrupted by another transmit request!
878b955f6caSJeff Kirsher        mace_tx_timeout will take care of timer-based retransmissions from
879b955f6caSJeff Kirsher        the upper layers.  The interrupt handler is guaranteed never to
880b955f6caSJeff Kirsher        service a transmit interrupt while we are in here.
881b955f6caSJeff Kirsher     */
882b955f6caSJeff Kirsher 
883b955f6caSJeff Kirsher     lp->linux_stats.tx_bytes += skb->len;
884b955f6caSJeff Kirsher     lp->tx_free_frames--;
885b955f6caSJeff Kirsher 
886b955f6caSJeff Kirsher     /* WARNING: Write the _exact_ number of bytes written in the header! */
887b955f6caSJeff Kirsher     /* Put out the word header [must be an outw()] . . . */
888b955f6caSJeff Kirsher     outw(skb->len, ioaddr + AM2150_XMT);
889b955f6caSJeff Kirsher     /* . . . and the packet [may be any combination of outw() and outb()] */
890b955f6caSJeff Kirsher     outsw(ioaddr + AM2150_XMT, skb->data, skb->len >> 1);
891b955f6caSJeff Kirsher     if (skb->len & 1) {
892b955f6caSJeff Kirsher       /* Odd byte transfer */
893b955f6caSJeff Kirsher       outb(skb->data[skb->len-1], ioaddr + AM2150_XMT);
894b955f6caSJeff Kirsher     }
895b955f6caSJeff Kirsher 
896b955f6caSJeff Kirsher #if MULTI_TX
897b955f6caSJeff Kirsher     if (lp->tx_free_frames > 0)
898b955f6caSJeff Kirsher       netif_start_queue(dev);
899b955f6caSJeff Kirsher #endif /* #if MULTI_TX */
900b955f6caSJeff Kirsher   }
901b955f6caSJeff Kirsher 
902b955f6caSJeff Kirsher #if (!TX_INTERRUPTABLE)
903b955f6caSJeff Kirsher   /* Re-enable MACE TX interrupts. */
904b955f6caSJeff Kirsher   lp->tx_irq_disabled=0;
905b955f6caSJeff Kirsher   outb(MACE_IMR_DEFAULT, ioaddr + AM2150_MACE_BASE + MACE_IMR);
906b955f6caSJeff Kirsher #endif /* #if (!TX_INTERRUPTABLE) */
907b955f6caSJeff Kirsher 
908b955f6caSJeff Kirsher   dev_kfree_skb(skb);
909b955f6caSJeff Kirsher 
910b955f6caSJeff Kirsher   return NETDEV_TX_OK;
911b955f6caSJeff Kirsher } /* mace_start_xmit */
912b955f6caSJeff Kirsher 
913b955f6caSJeff Kirsher /* ----------------------------------------------------------------------------
914b955f6caSJeff Kirsher mace_interrupt
915b955f6caSJeff Kirsher 	The interrupt handler.
916b955f6caSJeff Kirsher ---------------------------------------------------------------------------- */
917b955f6caSJeff Kirsher static irqreturn_t mace_interrupt(int irq, void *dev_id)
918b955f6caSJeff Kirsher {
919b955f6caSJeff Kirsher   struct net_device *dev = (struct net_device *) dev_id;
920b955f6caSJeff Kirsher   mace_private *lp = netdev_priv(dev);
921b955f6caSJeff Kirsher   unsigned int ioaddr;
922b955f6caSJeff Kirsher   int status;
923b955f6caSJeff Kirsher   int IntrCnt = MACE_MAX_IR_ITERATIONS;
924b955f6caSJeff Kirsher 
925b955f6caSJeff Kirsher   if (dev == NULL) {
926b955f6caSJeff Kirsher     pr_debug("mace_interrupt(): irq 0x%X for unknown device.\n",
927b955f6caSJeff Kirsher 	  irq);
928b955f6caSJeff Kirsher     return IRQ_NONE;
929b955f6caSJeff Kirsher   }
930b955f6caSJeff Kirsher 
931b955f6caSJeff Kirsher   ioaddr = dev->base_addr;
932b955f6caSJeff Kirsher 
933b955f6caSJeff Kirsher   if (lp->tx_irq_disabled) {
934b955f6caSJeff Kirsher     const char *msg;
935b955f6caSJeff Kirsher     if (lp->tx_irq_disabled)
936b955f6caSJeff Kirsher       msg = "Interrupt with tx_irq_disabled";
937b955f6caSJeff Kirsher     else
938b955f6caSJeff Kirsher       msg = "Re-entering the interrupt handler";
939b955f6caSJeff Kirsher     netdev_notice(dev, "%s [isr=%02X, imr=%02X]\n",
940b955f6caSJeff Kirsher 		  msg,
941b955f6caSJeff Kirsher 		  inb(ioaddr + AM2150_MACE_BASE + MACE_IR),
942b955f6caSJeff Kirsher 		  inb(ioaddr + AM2150_MACE_BASE + MACE_IMR));
943b955f6caSJeff Kirsher     /* WARNING: MACE_IR has been read! */
944b955f6caSJeff Kirsher     return IRQ_NONE;
945b955f6caSJeff Kirsher   }
946b955f6caSJeff Kirsher 
947b955f6caSJeff Kirsher   if (!netif_device_present(dev)) {
948b955f6caSJeff Kirsher     netdev_dbg(dev, "interrupt from dead card\n");
949b955f6caSJeff Kirsher     return IRQ_NONE;
950b955f6caSJeff Kirsher   }
951b955f6caSJeff Kirsher 
952b955f6caSJeff Kirsher   do {
953b955f6caSJeff Kirsher     /* WARNING: MACE_IR is a READ/CLEAR port! */
954b955f6caSJeff Kirsher     status = inb(ioaddr + AM2150_MACE_BASE + MACE_IR);
955*96a30175SArnd Bergmann     if (!(status & ~MACE_IMR_DEFAULT) && IntrCnt == MACE_MAX_IR_ITERATIONS)
956*96a30175SArnd Bergmann       return IRQ_NONE;
957b955f6caSJeff Kirsher 
958b955f6caSJeff Kirsher     pr_debug("mace_interrupt: irq 0x%X status 0x%X.\n", irq, status);
959b955f6caSJeff Kirsher 
960b955f6caSJeff Kirsher     if (status & MACE_IR_RCVINT) {
961b955f6caSJeff Kirsher       mace_rx(dev, MACE_MAX_RX_ITERATIONS);
962b955f6caSJeff Kirsher     }
963b955f6caSJeff Kirsher 
964b955f6caSJeff Kirsher     if (status & MACE_IR_XMTINT) {
965b955f6caSJeff Kirsher       unsigned char fifofc;
966b955f6caSJeff Kirsher       unsigned char xmtrc;
967b955f6caSJeff Kirsher       unsigned char xmtfs;
968b955f6caSJeff Kirsher 
969b955f6caSJeff Kirsher       fifofc = inb(ioaddr + AM2150_MACE_BASE + MACE_FIFOFC);
970b955f6caSJeff Kirsher       if ((fifofc & MACE_FIFOFC_XMTFC)==0) {
971b955f6caSJeff Kirsher 	lp->linux_stats.tx_errors++;
972b955f6caSJeff Kirsher 	outb(0xFF, ioaddr + AM2150_XMT_SKIP);
973b955f6caSJeff Kirsher       }
974b955f6caSJeff Kirsher 
975b955f6caSJeff Kirsher       /* Transmit Retry Count (XMTRC, reg 4) */
976b955f6caSJeff Kirsher       xmtrc = inb(ioaddr + AM2150_MACE_BASE + MACE_XMTRC);
977b955f6caSJeff Kirsher       if (xmtrc & MACE_XMTRC_EXDEF) lp->mace_stats.exdef++;
978b955f6caSJeff Kirsher       lp->mace_stats.xmtrc += (xmtrc & MACE_XMTRC_XMTRC);
979b955f6caSJeff Kirsher 
980b955f6caSJeff Kirsher       if (
981b955f6caSJeff Kirsher         (xmtfs = inb(ioaddr + AM2150_MACE_BASE + MACE_XMTFS)) &
982b955f6caSJeff Kirsher         MACE_XMTFS_XMTSV /* Transmit Status Valid */
983b955f6caSJeff Kirsher       ) {
984b955f6caSJeff Kirsher 	lp->mace_stats.xmtsv++;
985b955f6caSJeff Kirsher 
986b955f6caSJeff Kirsher 	if (xmtfs & ~MACE_XMTFS_XMTSV) {
987b955f6caSJeff Kirsher 	  if (xmtfs & MACE_XMTFS_UFLO) {
988b955f6caSJeff Kirsher 	    /* Underflow.  Indicates that the Transmit FIFO emptied before
989b955f6caSJeff Kirsher 	       the end of frame was reached. */
990b955f6caSJeff Kirsher 	    lp->mace_stats.uflo++;
991b955f6caSJeff Kirsher 	  }
992b955f6caSJeff Kirsher 	  if (xmtfs & MACE_XMTFS_LCOL) {
993b955f6caSJeff Kirsher 	    /* Late Collision */
994b955f6caSJeff Kirsher 	    lp->mace_stats.lcol++;
995b955f6caSJeff Kirsher 	  }
996b955f6caSJeff Kirsher 	  if (xmtfs & MACE_XMTFS_MORE) {
997b955f6caSJeff Kirsher 	    /* MORE than one retry was needed */
998b955f6caSJeff Kirsher 	    lp->mace_stats.more++;
999b955f6caSJeff Kirsher 	  }
1000b955f6caSJeff Kirsher 	  if (xmtfs & MACE_XMTFS_ONE) {
1001b955f6caSJeff Kirsher 	    /* Exactly ONE retry occurred */
1002b955f6caSJeff Kirsher 	    lp->mace_stats.one++;
1003b955f6caSJeff Kirsher 	  }
1004b955f6caSJeff Kirsher 	  if (xmtfs & MACE_XMTFS_DEFER) {
1005b955f6caSJeff Kirsher 	    /* Transmission was defered */
1006b955f6caSJeff Kirsher 	    lp->mace_stats.defer++;
1007b955f6caSJeff Kirsher 	  }
1008b955f6caSJeff Kirsher 	  if (xmtfs & MACE_XMTFS_LCAR) {
1009b955f6caSJeff Kirsher 	    /* Loss of carrier */
1010b955f6caSJeff Kirsher 	    lp->mace_stats.lcar++;
1011b955f6caSJeff Kirsher 	  }
1012b955f6caSJeff Kirsher 	  if (xmtfs & MACE_XMTFS_RTRY) {
1013b955f6caSJeff Kirsher 	    /* Retry error: transmit aborted after 16 attempts */
1014b955f6caSJeff Kirsher 	    lp->mace_stats.rtry++;
1015b955f6caSJeff Kirsher 	  }
1016b955f6caSJeff Kirsher         } /* if (xmtfs & ~MACE_XMTFS_XMTSV) */
1017b955f6caSJeff Kirsher 
1018b955f6caSJeff Kirsher       } /* if (xmtfs & MACE_XMTFS_XMTSV) */
1019b955f6caSJeff Kirsher 
1020b955f6caSJeff Kirsher       lp->linux_stats.tx_packets++;
1021b955f6caSJeff Kirsher       lp->tx_free_frames++;
1022b955f6caSJeff Kirsher       netif_wake_queue(dev);
1023b955f6caSJeff Kirsher     } /* if (status & MACE_IR_XMTINT) */
1024b955f6caSJeff Kirsher 
1025b955f6caSJeff Kirsher     if (status & ~MACE_IMR_DEFAULT & ~MACE_IR_RCVINT & ~MACE_IR_XMTINT) {
1026b955f6caSJeff Kirsher       if (status & MACE_IR_JAB) {
1027b955f6caSJeff Kirsher         /* Jabber Error.  Excessive transmit duration (20-150ms). */
1028b955f6caSJeff Kirsher         lp->mace_stats.jab++;
1029b955f6caSJeff Kirsher       }
1030b955f6caSJeff Kirsher       if (status & MACE_IR_BABL) {
1031b955f6caSJeff Kirsher         /* Babble Error.  >1518 bytes transmitted. */
1032b955f6caSJeff Kirsher         lp->mace_stats.babl++;
1033b955f6caSJeff Kirsher       }
1034b955f6caSJeff Kirsher       if (status & MACE_IR_CERR) {
1035b955f6caSJeff Kirsher 	/* Collision Error.  CERR indicates the absence of the
1036b955f6caSJeff Kirsher 	   Signal Quality Error Test message after a packet
1037b955f6caSJeff Kirsher 	   transmission. */
1038b955f6caSJeff Kirsher         lp->mace_stats.cerr++;
1039b955f6caSJeff Kirsher       }
1040b955f6caSJeff Kirsher       if (status & MACE_IR_RCVCCO) {
1041b955f6caSJeff Kirsher         /* Receive Collision Count Overflow; */
1042b955f6caSJeff Kirsher         lp->mace_stats.rcvcco++;
1043b955f6caSJeff Kirsher       }
1044b955f6caSJeff Kirsher       if (status & MACE_IR_RNTPCO) {
1045b955f6caSJeff Kirsher         /* Runt Packet Count Overflow */
1046b955f6caSJeff Kirsher         lp->mace_stats.rntpco++;
1047b955f6caSJeff Kirsher       }
1048b955f6caSJeff Kirsher       if (status & MACE_IR_MPCO) {
1049b955f6caSJeff Kirsher         /* Missed Packet Count Overflow */
1050b955f6caSJeff Kirsher         lp->mace_stats.mpco++;
1051b955f6caSJeff Kirsher       }
1052b955f6caSJeff Kirsher     } /* if (status & ~MACE_IMR_DEFAULT & ~MACE_IR_RCVINT & ~MACE_IR_XMTINT) */
1053b955f6caSJeff Kirsher 
1054b955f6caSJeff Kirsher   } while ((status & ~MACE_IMR_DEFAULT) && (--IntrCnt));
1055b955f6caSJeff Kirsher 
1056b955f6caSJeff Kirsher   return IRQ_HANDLED;
1057b955f6caSJeff Kirsher } /* mace_interrupt */
1058b955f6caSJeff Kirsher 
1059b955f6caSJeff Kirsher /* ----------------------------------------------------------------------------
1060b955f6caSJeff Kirsher mace_rx
1061b955f6caSJeff Kirsher 	Receives packets.
1062b955f6caSJeff Kirsher ---------------------------------------------------------------------------- */
1063b955f6caSJeff Kirsher static int mace_rx(struct net_device *dev, unsigned char RxCnt)
1064b955f6caSJeff Kirsher {
1065b955f6caSJeff Kirsher   mace_private *lp = netdev_priv(dev);
1066b955f6caSJeff Kirsher   unsigned int ioaddr = dev->base_addr;
1067b955f6caSJeff Kirsher   unsigned char rx_framecnt;
1068b955f6caSJeff Kirsher   unsigned short rx_status;
1069b955f6caSJeff Kirsher 
1070b955f6caSJeff Kirsher   while (
1071b955f6caSJeff Kirsher     ((rx_framecnt = inb(ioaddr + AM2150_RCV_FRAME_COUNT)) > 0) &&
1072b955f6caSJeff Kirsher     (rx_framecnt <= 12) && /* rx_framecnt==0xFF if card is extracted. */
1073b955f6caSJeff Kirsher     (RxCnt--)
1074b955f6caSJeff Kirsher   ) {
1075b955f6caSJeff Kirsher     rx_status = inw(ioaddr + AM2150_RCV);
1076b955f6caSJeff Kirsher 
1077b955f6caSJeff Kirsher     pr_debug("%s: in mace_rx(), framecnt 0x%X, rx_status"
1078b955f6caSJeff Kirsher 	  " 0x%X.\n", dev->name, rx_framecnt, rx_status);
1079b955f6caSJeff Kirsher 
1080b955f6caSJeff Kirsher     if (rx_status & MACE_RCVFS_RCVSTS) { /* Error, update stats. */
1081b955f6caSJeff Kirsher       lp->linux_stats.rx_errors++;
1082b955f6caSJeff Kirsher       if (rx_status & MACE_RCVFS_OFLO) {
1083b955f6caSJeff Kirsher         lp->mace_stats.oflo++;
1084b955f6caSJeff Kirsher       }
1085b955f6caSJeff Kirsher       if (rx_status & MACE_RCVFS_CLSN) {
1086b955f6caSJeff Kirsher         lp->mace_stats.clsn++;
1087b955f6caSJeff Kirsher       }
1088b955f6caSJeff Kirsher       if (rx_status & MACE_RCVFS_FRAM) {
1089b955f6caSJeff Kirsher 	lp->mace_stats.fram++;
1090b955f6caSJeff Kirsher       }
1091b955f6caSJeff Kirsher       if (rx_status & MACE_RCVFS_FCS) {
1092b955f6caSJeff Kirsher         lp->mace_stats.fcs++;
1093b955f6caSJeff Kirsher       }
1094b955f6caSJeff Kirsher     } else {
1095b955f6caSJeff Kirsher       short pkt_len = (rx_status & ~MACE_RCVFS_RCVSTS) - 4;
1096b955f6caSJeff Kirsher         /* Auto Strip is off, always subtract 4 */
1097b955f6caSJeff Kirsher       struct sk_buff *skb;
1098b955f6caSJeff Kirsher 
1099b955f6caSJeff Kirsher       lp->mace_stats.rfs_rntpc += inb(ioaddr + AM2150_RCV);
1100b955f6caSJeff Kirsher         /* runt packet count */
1101b955f6caSJeff Kirsher       lp->mace_stats.rfs_rcvcc += inb(ioaddr + AM2150_RCV);
1102b955f6caSJeff Kirsher         /* rcv collision count */
1103b955f6caSJeff Kirsher 
1104b955f6caSJeff Kirsher       pr_debug("    receiving packet size 0x%X rx_status"
1105b955f6caSJeff Kirsher 	    " 0x%X.\n", pkt_len, rx_status);
1106b955f6caSJeff Kirsher 
11071d266430SPradeep A Dalvi       skb = netdev_alloc_skb(dev, pkt_len + 2);
1108b955f6caSJeff Kirsher 
1109b955f6caSJeff Kirsher       if (skb != NULL) {
1110b955f6caSJeff Kirsher 	skb_reserve(skb, 2);
1111b955f6caSJeff Kirsher 	insw(ioaddr + AM2150_RCV, skb_put(skb, pkt_len), pkt_len>>1);
1112b955f6caSJeff Kirsher 	if (pkt_len & 1)
1113b955f6caSJeff Kirsher 	    *(skb_tail_pointer(skb) - 1) = inb(ioaddr + AM2150_RCV);
1114b955f6caSJeff Kirsher 	skb->protocol = eth_type_trans(skb, dev);
1115b955f6caSJeff Kirsher 
1116b955f6caSJeff Kirsher 	netif_rx(skb); /* Send the packet to the upper (protocol) layers. */
1117b955f6caSJeff Kirsher 
1118b955f6caSJeff Kirsher 	lp->linux_stats.rx_packets++;
1119b955f6caSJeff Kirsher 	lp->linux_stats.rx_bytes += pkt_len;
1120b955f6caSJeff Kirsher 	outb(0xFF, ioaddr + AM2150_RCV_NEXT); /* skip to next frame */
1121b955f6caSJeff Kirsher 	continue;
1122b955f6caSJeff Kirsher       } else {
1123b955f6caSJeff Kirsher 	pr_debug("%s: couldn't allocate a sk_buff of size"
1124b955f6caSJeff Kirsher 	      " %d.\n", dev->name, pkt_len);
1125b955f6caSJeff Kirsher 	lp->linux_stats.rx_dropped++;
1126b955f6caSJeff Kirsher       }
1127b955f6caSJeff Kirsher     }
1128b955f6caSJeff Kirsher     outb(0xFF, ioaddr + AM2150_RCV_NEXT); /* skip to next frame */
1129b955f6caSJeff Kirsher   } /* while */
1130b955f6caSJeff Kirsher 
1131b955f6caSJeff Kirsher   return 0;
1132b955f6caSJeff Kirsher } /* mace_rx */
1133b955f6caSJeff Kirsher 
1134b955f6caSJeff Kirsher /* ----------------------------------------------------------------------------
1135b955f6caSJeff Kirsher pr_linux_stats
1136b955f6caSJeff Kirsher ---------------------------------------------------------------------------- */
1137b955f6caSJeff Kirsher static void pr_linux_stats(struct net_device_stats *pstats)
1138b955f6caSJeff Kirsher {
1139b955f6caSJeff Kirsher   pr_debug("pr_linux_stats\n");
1140b955f6caSJeff Kirsher   pr_debug(" rx_packets=%-7ld        tx_packets=%ld\n",
1141b955f6caSJeff Kirsher 	(long)pstats->rx_packets, (long)pstats->tx_packets);
1142b955f6caSJeff Kirsher   pr_debug(" rx_errors=%-7ld         tx_errors=%ld\n",
1143b955f6caSJeff Kirsher 	(long)pstats->rx_errors, (long)pstats->tx_errors);
1144b955f6caSJeff Kirsher   pr_debug(" rx_dropped=%-7ld        tx_dropped=%ld\n",
1145b955f6caSJeff Kirsher 	(long)pstats->rx_dropped, (long)pstats->tx_dropped);
1146b955f6caSJeff Kirsher   pr_debug(" multicast=%-7ld         collisions=%ld\n",
1147b955f6caSJeff Kirsher 	(long)pstats->multicast, (long)pstats->collisions);
1148b955f6caSJeff Kirsher 
1149b955f6caSJeff Kirsher   pr_debug(" rx_length_errors=%-7ld  rx_over_errors=%ld\n",
1150b955f6caSJeff Kirsher 	(long)pstats->rx_length_errors, (long)pstats->rx_over_errors);
1151b955f6caSJeff Kirsher   pr_debug(" rx_crc_errors=%-7ld     rx_frame_errors=%ld\n",
1152b955f6caSJeff Kirsher 	(long)pstats->rx_crc_errors, (long)pstats->rx_frame_errors);
1153b955f6caSJeff Kirsher   pr_debug(" rx_fifo_errors=%-7ld    rx_missed_errors=%ld\n",
1154b955f6caSJeff Kirsher 	(long)pstats->rx_fifo_errors, (long)pstats->rx_missed_errors);
1155b955f6caSJeff Kirsher 
1156b955f6caSJeff Kirsher   pr_debug(" tx_aborted_errors=%-7ld tx_carrier_errors=%ld\n",
1157b955f6caSJeff Kirsher 	(long)pstats->tx_aborted_errors, (long)pstats->tx_carrier_errors);
1158b955f6caSJeff Kirsher   pr_debug(" tx_fifo_errors=%-7ld    tx_heartbeat_errors=%ld\n",
1159b955f6caSJeff Kirsher 	(long)pstats->tx_fifo_errors, (long)pstats->tx_heartbeat_errors);
1160b955f6caSJeff Kirsher   pr_debug(" tx_window_errors=%ld\n",
1161b955f6caSJeff Kirsher 	(long)pstats->tx_window_errors);
1162b955f6caSJeff Kirsher } /* pr_linux_stats */
1163b955f6caSJeff Kirsher 
1164b955f6caSJeff Kirsher /* ----------------------------------------------------------------------------
1165b955f6caSJeff Kirsher pr_mace_stats
1166b955f6caSJeff Kirsher ---------------------------------------------------------------------------- */
1167b955f6caSJeff Kirsher static void pr_mace_stats(mace_statistics *pstats)
1168b955f6caSJeff Kirsher {
1169b955f6caSJeff Kirsher   pr_debug("pr_mace_stats\n");
1170b955f6caSJeff Kirsher 
1171b955f6caSJeff Kirsher   pr_debug(" xmtsv=%-7d             uflo=%d\n",
1172b955f6caSJeff Kirsher 	pstats->xmtsv, pstats->uflo);
1173b955f6caSJeff Kirsher   pr_debug(" lcol=%-7d              more=%d\n",
1174b955f6caSJeff Kirsher 	pstats->lcol, pstats->more);
1175b955f6caSJeff Kirsher   pr_debug(" one=%-7d               defer=%d\n",
1176b955f6caSJeff Kirsher 	pstats->one, pstats->defer);
1177b955f6caSJeff Kirsher   pr_debug(" lcar=%-7d              rtry=%d\n",
1178b955f6caSJeff Kirsher 	pstats->lcar, pstats->rtry);
1179b955f6caSJeff Kirsher 
1180b955f6caSJeff Kirsher   /* MACE_XMTRC */
1181b955f6caSJeff Kirsher   pr_debug(" exdef=%-7d             xmtrc=%d\n",
1182b955f6caSJeff Kirsher 	pstats->exdef, pstats->xmtrc);
1183b955f6caSJeff Kirsher 
1184b955f6caSJeff Kirsher   /* RFS1--Receive Status (RCVSTS) */
1185b955f6caSJeff Kirsher   pr_debug(" oflo=%-7d              clsn=%d\n",
1186b955f6caSJeff Kirsher 	pstats->oflo, pstats->clsn);
1187b955f6caSJeff Kirsher   pr_debug(" fram=%-7d              fcs=%d\n",
1188b955f6caSJeff Kirsher 	pstats->fram, pstats->fcs);
1189b955f6caSJeff Kirsher 
1190b955f6caSJeff Kirsher   /* RFS2--Runt Packet Count (RNTPC) */
1191b955f6caSJeff Kirsher   /* RFS3--Receive Collision Count (RCVCC) */
1192b955f6caSJeff Kirsher   pr_debug(" rfs_rntpc=%-7d         rfs_rcvcc=%d\n",
1193b955f6caSJeff Kirsher 	pstats->rfs_rntpc, pstats->rfs_rcvcc);
1194b955f6caSJeff Kirsher 
1195b955f6caSJeff Kirsher   /* MACE_IR */
1196b955f6caSJeff Kirsher   pr_debug(" jab=%-7d               babl=%d\n",
1197b955f6caSJeff Kirsher 	pstats->jab, pstats->babl);
1198b955f6caSJeff Kirsher   pr_debug(" cerr=%-7d              rcvcco=%d\n",
1199b955f6caSJeff Kirsher 	pstats->cerr, pstats->rcvcco);
1200b955f6caSJeff Kirsher   pr_debug(" rntpco=%-7d            mpco=%d\n",
1201b955f6caSJeff Kirsher 	pstats->rntpco, pstats->mpco);
1202b955f6caSJeff Kirsher 
1203b955f6caSJeff Kirsher   /* MACE_MPC */
1204b955f6caSJeff Kirsher   pr_debug(" mpc=%d\n", pstats->mpc);
1205b955f6caSJeff Kirsher 
1206b955f6caSJeff Kirsher   /* MACE_RNTPC */
1207b955f6caSJeff Kirsher   pr_debug(" rntpc=%d\n", pstats->rntpc);
1208b955f6caSJeff Kirsher 
1209b955f6caSJeff Kirsher   /* MACE_RCVCC */
1210b955f6caSJeff Kirsher   pr_debug(" rcvcc=%d\n", pstats->rcvcc);
1211b955f6caSJeff Kirsher 
1212b955f6caSJeff Kirsher } /* pr_mace_stats */
1213b955f6caSJeff Kirsher 
1214b955f6caSJeff Kirsher /* ----------------------------------------------------------------------------
1215b955f6caSJeff Kirsher update_stats
1216b955f6caSJeff Kirsher 	Update statistics.  We change to register window 1, so this
1217b955f6caSJeff Kirsher 	should be run single-threaded if the device is active. This is
1218b955f6caSJeff Kirsher 	expected to be a rare operation, and it's simpler for the rest
1219b955f6caSJeff Kirsher 	of the driver to assume that window 0 is always valid rather
1220b955f6caSJeff Kirsher 	than use a special window-state variable.
1221b955f6caSJeff Kirsher 
1222b955f6caSJeff Kirsher 	oflo & uflo should _never_ occur since it would mean the Xilinx
1223b955f6caSJeff Kirsher 	was not able to transfer data between the MACE FIFO and the
1224b955f6caSJeff Kirsher 	card's SRAM fast enough.  If this happens, something is
1225b955f6caSJeff Kirsher 	seriously wrong with the hardware.
1226b955f6caSJeff Kirsher ---------------------------------------------------------------------------- */
1227b955f6caSJeff Kirsher static void update_stats(unsigned int ioaddr, struct net_device *dev)
1228b955f6caSJeff Kirsher {
1229b955f6caSJeff Kirsher   mace_private *lp = netdev_priv(dev);
1230b955f6caSJeff Kirsher 
1231b955f6caSJeff Kirsher   lp->mace_stats.rcvcc += mace_read(lp, ioaddr, MACE_RCVCC);
1232b955f6caSJeff Kirsher   lp->mace_stats.rntpc += mace_read(lp, ioaddr, MACE_RNTPC);
1233b955f6caSJeff Kirsher   lp->mace_stats.mpc += mace_read(lp, ioaddr, MACE_MPC);
1234b955f6caSJeff Kirsher   /* At this point, mace_stats is fully updated for this call.
1235b955f6caSJeff Kirsher      We may now update the linux_stats. */
1236b955f6caSJeff Kirsher 
1237b955f6caSJeff Kirsher   /* The MACE has no equivalent for linux_stats field which are commented
1238b955f6caSJeff Kirsher      out. */
1239b955f6caSJeff Kirsher 
1240b955f6caSJeff Kirsher   /* lp->linux_stats.multicast; */
1241b955f6caSJeff Kirsher   lp->linux_stats.collisions =
1242b955f6caSJeff Kirsher     lp->mace_stats.rcvcco * 256 + lp->mace_stats.rcvcc;
1243b955f6caSJeff Kirsher     /* Collision: The MACE may retry sending a packet 15 times
1244b955f6caSJeff Kirsher        before giving up.  The retry count is in XMTRC.
1245b955f6caSJeff Kirsher        Does each retry constitute a collision?
1246b955f6caSJeff Kirsher        If so, why doesn't the RCVCC record these collisions? */
1247b955f6caSJeff Kirsher 
1248b955f6caSJeff Kirsher   /* detailed rx_errors: */
1249b955f6caSJeff Kirsher   lp->linux_stats.rx_length_errors =
1250b955f6caSJeff Kirsher     lp->mace_stats.rntpco * 256 + lp->mace_stats.rntpc;
1251b955f6caSJeff Kirsher   /* lp->linux_stats.rx_over_errors */
1252b955f6caSJeff Kirsher   lp->linux_stats.rx_crc_errors = lp->mace_stats.fcs;
1253b955f6caSJeff Kirsher   lp->linux_stats.rx_frame_errors = lp->mace_stats.fram;
1254b955f6caSJeff Kirsher   lp->linux_stats.rx_fifo_errors = lp->mace_stats.oflo;
1255b955f6caSJeff Kirsher   lp->linux_stats.rx_missed_errors =
1256b955f6caSJeff Kirsher     lp->mace_stats.mpco * 256 + lp->mace_stats.mpc;
1257b955f6caSJeff Kirsher 
1258b955f6caSJeff Kirsher   /* detailed tx_errors */
1259b955f6caSJeff Kirsher   lp->linux_stats.tx_aborted_errors = lp->mace_stats.rtry;
1260b955f6caSJeff Kirsher   lp->linux_stats.tx_carrier_errors = lp->mace_stats.lcar;
1261b955f6caSJeff Kirsher     /* LCAR usually results from bad cabling. */
1262b955f6caSJeff Kirsher   lp->linux_stats.tx_fifo_errors = lp->mace_stats.uflo;
1263b955f6caSJeff Kirsher   lp->linux_stats.tx_heartbeat_errors = lp->mace_stats.cerr;
1264b955f6caSJeff Kirsher   /* lp->linux_stats.tx_window_errors; */
1265b955f6caSJeff Kirsher } /* update_stats */
1266b955f6caSJeff Kirsher 
1267b955f6caSJeff Kirsher /* ----------------------------------------------------------------------------
1268b955f6caSJeff Kirsher mace_get_stats
1269b955f6caSJeff Kirsher 	Gathers ethernet statistics from the MACE chip.
1270b955f6caSJeff Kirsher ---------------------------------------------------------------------------- */
1271b955f6caSJeff Kirsher static struct net_device_stats *mace_get_stats(struct net_device *dev)
1272b955f6caSJeff Kirsher {
1273b955f6caSJeff Kirsher   mace_private *lp = netdev_priv(dev);
1274b955f6caSJeff Kirsher 
1275b955f6caSJeff Kirsher   update_stats(dev->base_addr, dev);
1276b955f6caSJeff Kirsher 
1277b955f6caSJeff Kirsher   pr_debug("%s: updating the statistics.\n", dev->name);
1278b955f6caSJeff Kirsher   pr_linux_stats(&lp->linux_stats);
1279b955f6caSJeff Kirsher   pr_mace_stats(&lp->mace_stats);
1280b955f6caSJeff Kirsher 
1281b955f6caSJeff Kirsher   return &lp->linux_stats;
1282b955f6caSJeff Kirsher } /* net_device_stats */
1283b955f6caSJeff Kirsher 
1284b955f6caSJeff Kirsher /* ----------------------------------------------------------------------------
1285b955f6caSJeff Kirsher updateCRC
1286b955f6caSJeff Kirsher 	Modified from Am79C90 data sheet.
1287b955f6caSJeff Kirsher ---------------------------------------------------------------------------- */
1288b955f6caSJeff Kirsher 
1289b955f6caSJeff Kirsher #ifdef BROKEN_MULTICAST
1290b955f6caSJeff Kirsher 
1291b955f6caSJeff Kirsher static void updateCRC(int *CRC, int bit)
1292b955f6caSJeff Kirsher {
1293b955f6caSJeff Kirsher   static const int poly[]={
1294b955f6caSJeff Kirsher     1,1,1,0, 1,1,0,1,
1295b955f6caSJeff Kirsher     1,0,1,1, 1,0,0,0,
1296b955f6caSJeff Kirsher     1,0,0,0, 0,0,1,1,
1297b955f6caSJeff Kirsher     0,0,1,0, 0,0,0,0
1298b955f6caSJeff Kirsher   }; /* CRC polynomial.  poly[n] = coefficient of the x**n term of the
1299b955f6caSJeff Kirsher 	CRC generator polynomial. */
1300b955f6caSJeff Kirsher 
1301b955f6caSJeff Kirsher   int j;
1302b955f6caSJeff Kirsher 
1303b955f6caSJeff Kirsher   /* shift CRC and control bit (CRC[32]) */
1304b955f6caSJeff Kirsher   for (j = 32; j > 0; j--)
1305b955f6caSJeff Kirsher     CRC[j] = CRC[j-1];
1306b955f6caSJeff Kirsher   CRC[0] = 0;
1307b955f6caSJeff Kirsher 
1308b955f6caSJeff Kirsher   /* If bit XOR(control bit) = 1, set CRC = CRC XOR polynomial. */
1309b955f6caSJeff Kirsher   if (bit ^ CRC[32])
1310b955f6caSJeff Kirsher     for (j = 0; j < 32; j++)
1311b955f6caSJeff Kirsher       CRC[j] ^= poly[j];
1312b955f6caSJeff Kirsher } /* updateCRC */
1313b955f6caSJeff Kirsher 
1314b955f6caSJeff Kirsher /* ----------------------------------------------------------------------------
1315b955f6caSJeff Kirsher BuildLAF
1316b955f6caSJeff Kirsher 	Build logical address filter.
1317b955f6caSJeff Kirsher 	Modified from Am79C90 data sheet.
1318b955f6caSJeff Kirsher 
1319b955f6caSJeff Kirsher Input
1320b955f6caSJeff Kirsher 	ladrf: logical address filter (contents initialized to 0)
1321b955f6caSJeff Kirsher 	adr: ethernet address
1322b955f6caSJeff Kirsher ---------------------------------------------------------------------------- */
1323b955f6caSJeff Kirsher static void BuildLAF(int *ladrf, int *adr)
1324b955f6caSJeff Kirsher {
1325b955f6caSJeff Kirsher   int CRC[33]={1}; /* CRC register, 1 word/bit + extra control bit */
1326b955f6caSJeff Kirsher 
1327b955f6caSJeff Kirsher   int i, byte; /* temporary array indices */
1328b955f6caSJeff Kirsher   int hashcode; /* the output object */
1329b955f6caSJeff Kirsher 
1330b955f6caSJeff Kirsher   CRC[32]=0;
1331b955f6caSJeff Kirsher 
1332b955f6caSJeff Kirsher   for (byte = 0; byte < 6; byte++)
1333b955f6caSJeff Kirsher     for (i = 0; i < 8; i++)
1334b955f6caSJeff Kirsher       updateCRC(CRC, (adr[byte] >> i) & 1);
1335b955f6caSJeff Kirsher 
1336b955f6caSJeff Kirsher   hashcode = 0;
1337b955f6caSJeff Kirsher   for (i = 0; i < 6; i++)
1338b955f6caSJeff Kirsher     hashcode = (hashcode << 1) + CRC[i];
1339b955f6caSJeff Kirsher 
1340b955f6caSJeff Kirsher   byte = hashcode >> 3;
1341b955f6caSJeff Kirsher   ladrf[byte] |= (1 << (hashcode & 7));
1342b955f6caSJeff Kirsher 
1343b955f6caSJeff Kirsher #ifdef PCMCIA_DEBUG
1344b955f6caSJeff Kirsher   if (0)
1345b955f6caSJeff Kirsher     printk(KERN_DEBUG "    adr =%pM\n", adr);
1346b955f6caSJeff Kirsher   printk(KERN_DEBUG "    hashcode = %d(decimal), ladrf[0:63] =", hashcode);
1347b955f6caSJeff Kirsher   for (i = 0; i < 8; i++)
1348b955f6caSJeff Kirsher     pr_cont(" %02X", ladrf[i]);
1349b955f6caSJeff Kirsher   pr_cont("\n");
1350b955f6caSJeff Kirsher #endif
1351b955f6caSJeff Kirsher } /* BuildLAF */
1352b955f6caSJeff Kirsher 
1353b955f6caSJeff Kirsher /* ----------------------------------------------------------------------------
1354b955f6caSJeff Kirsher restore_multicast_list
1355b955f6caSJeff Kirsher 	Restores the multicast filter for MACE chip to the last
1356b955f6caSJeff Kirsher 	set_multicast_list() call.
1357b955f6caSJeff Kirsher 
1358b955f6caSJeff Kirsher Input
1359b955f6caSJeff Kirsher 	multicast_num_addrs
1360b955f6caSJeff Kirsher 	multicast_ladrf[]
1361b955f6caSJeff Kirsher ---------------------------------------------------------------------------- */
1362b955f6caSJeff Kirsher static void restore_multicast_list(struct net_device *dev)
1363b955f6caSJeff Kirsher {
1364b955f6caSJeff Kirsher   mace_private *lp = netdev_priv(dev);
1365b955f6caSJeff Kirsher   int num_addrs = lp->multicast_num_addrs;
1366b955f6caSJeff Kirsher   int *ladrf = lp->multicast_ladrf;
1367b955f6caSJeff Kirsher   unsigned int ioaddr = dev->base_addr;
1368b955f6caSJeff Kirsher   int i;
1369b955f6caSJeff Kirsher 
1370b955f6caSJeff Kirsher   pr_debug("%s: restoring Rx mode to %d addresses.\n",
1371b955f6caSJeff Kirsher 	dev->name, num_addrs);
1372b955f6caSJeff Kirsher 
1373b955f6caSJeff Kirsher   if (num_addrs > 0) {
1374b955f6caSJeff Kirsher 
1375b955f6caSJeff Kirsher     pr_debug("Attempt to restore multicast list detected.\n");
1376b955f6caSJeff Kirsher 
1377b955f6caSJeff Kirsher     mace_write(lp, ioaddr, MACE_IAC, MACE_IAC_ADDRCHG | MACE_IAC_LOGADDR);
1378b955f6caSJeff Kirsher     /* Poll ADDRCHG bit */
1379b955f6caSJeff Kirsher     while (mace_read(lp, ioaddr, MACE_IAC) & MACE_IAC_ADDRCHG)
1380b955f6caSJeff Kirsher       ;
1381b955f6caSJeff Kirsher     /* Set LADRF register */
1382b955f6caSJeff Kirsher     for (i = 0; i < MACE_LADRF_LEN; i++)
1383b955f6caSJeff Kirsher       mace_write(lp, ioaddr, MACE_LADRF, ladrf[i]);
1384b955f6caSJeff Kirsher 
1385b955f6caSJeff Kirsher     mace_write(lp, ioaddr, MACE_UTR, MACE_UTR_RCVFCSE | MACE_UTR_LOOP_EXTERNAL);
1386b955f6caSJeff Kirsher     mace_write(lp, ioaddr, MACE_MACCC, MACE_MACCC_ENXMT | MACE_MACCC_ENRCV);
1387b955f6caSJeff Kirsher 
1388b955f6caSJeff Kirsher   } else if (num_addrs < 0) {
1389b955f6caSJeff Kirsher 
1390b955f6caSJeff Kirsher     /* Promiscuous mode: receive all packets */
1391b955f6caSJeff Kirsher     mace_write(lp, ioaddr, MACE_UTR, MACE_UTR_LOOP_EXTERNAL);
1392b955f6caSJeff Kirsher     mace_write(lp, ioaddr, MACE_MACCC,
1393b955f6caSJeff Kirsher       MACE_MACCC_PROM | MACE_MACCC_ENXMT | MACE_MACCC_ENRCV
1394b955f6caSJeff Kirsher     );
1395b955f6caSJeff Kirsher 
1396b955f6caSJeff Kirsher   } else {
1397b955f6caSJeff Kirsher 
1398b955f6caSJeff Kirsher     /* Normal mode */
1399b955f6caSJeff Kirsher     mace_write(lp, ioaddr, MACE_UTR, MACE_UTR_LOOP_EXTERNAL);
1400b955f6caSJeff Kirsher     mace_write(lp, ioaddr, MACE_MACCC, MACE_MACCC_ENXMT | MACE_MACCC_ENRCV);
1401b955f6caSJeff Kirsher 
1402b955f6caSJeff Kirsher   }
1403b955f6caSJeff Kirsher } /* restore_multicast_list */
1404b955f6caSJeff Kirsher 
1405b955f6caSJeff Kirsher /* ----------------------------------------------------------------------------
1406b955f6caSJeff Kirsher set_multicast_list
1407b955f6caSJeff Kirsher 	Set or clear the multicast filter for this adaptor.
1408b955f6caSJeff Kirsher 
1409b955f6caSJeff Kirsher Input
1410b955f6caSJeff Kirsher 	num_addrs == -1	Promiscuous mode, receive all packets
1411b955f6caSJeff Kirsher 	num_addrs == 0	Normal mode, clear multicast list
1412b955f6caSJeff Kirsher 	num_addrs > 0	Multicast mode, receive normal and MC packets, and do
1413b955f6caSJeff Kirsher 			best-effort filtering.
1414b955f6caSJeff Kirsher Output
1415b955f6caSJeff Kirsher 	multicast_num_addrs
1416b955f6caSJeff Kirsher 	multicast_ladrf[]
1417b955f6caSJeff Kirsher ---------------------------------------------------------------------------- */
1418b955f6caSJeff Kirsher 
1419b955f6caSJeff Kirsher static void set_multicast_list(struct net_device *dev)
1420b955f6caSJeff Kirsher {
1421b955f6caSJeff Kirsher   mace_private *lp = netdev_priv(dev);
1422104bf3fbSJoe Perches   int adr[ETH_ALEN] = {0}; /* Ethernet address */
1423b955f6caSJeff Kirsher   struct netdev_hw_addr *ha;
1424b955f6caSJeff Kirsher 
1425b955f6caSJeff Kirsher #ifdef PCMCIA_DEBUG
1426b955f6caSJeff Kirsher   {
1427b955f6caSJeff Kirsher     static int old;
1428b955f6caSJeff Kirsher     if (netdev_mc_count(dev) != old) {
1429b955f6caSJeff Kirsher       old = netdev_mc_count(dev);
1430b955f6caSJeff Kirsher       pr_debug("%s: setting Rx mode to %d addresses.\n",
1431b955f6caSJeff Kirsher 	    dev->name, old);
1432b955f6caSJeff Kirsher     }
1433b955f6caSJeff Kirsher   }
1434b955f6caSJeff Kirsher #endif
1435b955f6caSJeff Kirsher 
1436b955f6caSJeff Kirsher   /* Set multicast_num_addrs. */
1437b955f6caSJeff Kirsher   lp->multicast_num_addrs = netdev_mc_count(dev);
1438b955f6caSJeff Kirsher 
1439b955f6caSJeff Kirsher   /* Set multicast_ladrf. */
1440b955f6caSJeff Kirsher   if (num_addrs > 0) {
1441b955f6caSJeff Kirsher     /* Calculate multicast logical address filter */
1442b955f6caSJeff Kirsher     memset(lp->multicast_ladrf, 0, MACE_LADRF_LEN);
1443b955f6caSJeff Kirsher     netdev_for_each_mc_addr(ha, dev) {
1444104bf3fbSJoe Perches       memcpy(adr, ha->addr, ETH_ALEN);
1445b955f6caSJeff Kirsher       BuildLAF(lp->multicast_ladrf, adr);
1446b955f6caSJeff Kirsher     }
1447b955f6caSJeff Kirsher   }
1448b955f6caSJeff Kirsher 
1449b955f6caSJeff Kirsher   restore_multicast_list(dev);
1450b955f6caSJeff Kirsher 
1451b955f6caSJeff Kirsher } /* set_multicast_list */
1452b955f6caSJeff Kirsher 
1453b955f6caSJeff Kirsher #endif /* BROKEN_MULTICAST */
1454b955f6caSJeff Kirsher 
1455b955f6caSJeff Kirsher static void restore_multicast_list(struct net_device *dev)
1456b955f6caSJeff Kirsher {
1457b955f6caSJeff Kirsher   unsigned int ioaddr = dev->base_addr;
1458b955f6caSJeff Kirsher   mace_private *lp = netdev_priv(dev);
1459b955f6caSJeff Kirsher 
1460b955f6caSJeff Kirsher   pr_debug("%s: restoring Rx mode to %d addresses.\n", dev->name,
1461b955f6caSJeff Kirsher 	lp->multicast_num_addrs);
1462b955f6caSJeff Kirsher 
1463b955f6caSJeff Kirsher   if (dev->flags & IFF_PROMISC) {
1464b955f6caSJeff Kirsher     /* Promiscuous mode: receive all packets */
1465b955f6caSJeff Kirsher     mace_write(lp,ioaddr, MACE_UTR, MACE_UTR_LOOP_EXTERNAL);
1466b955f6caSJeff Kirsher     mace_write(lp, ioaddr, MACE_MACCC,
1467b955f6caSJeff Kirsher       MACE_MACCC_PROM | MACE_MACCC_ENXMT | MACE_MACCC_ENRCV
1468b955f6caSJeff Kirsher     );
1469b955f6caSJeff Kirsher   } else {
1470b955f6caSJeff Kirsher     /* Normal mode */
1471b955f6caSJeff Kirsher     mace_write(lp, ioaddr, MACE_UTR, MACE_UTR_LOOP_EXTERNAL);
1472b955f6caSJeff Kirsher     mace_write(lp, ioaddr, MACE_MACCC, MACE_MACCC_ENXMT | MACE_MACCC_ENRCV);
1473b955f6caSJeff Kirsher   }
1474b955f6caSJeff Kirsher } /* restore_multicast_list */
1475b955f6caSJeff Kirsher 
1476b955f6caSJeff Kirsher static void set_multicast_list(struct net_device *dev)
1477b955f6caSJeff Kirsher {
1478b955f6caSJeff Kirsher   mace_private *lp = netdev_priv(dev);
1479b955f6caSJeff Kirsher 
1480b955f6caSJeff Kirsher #ifdef PCMCIA_DEBUG
1481b955f6caSJeff Kirsher   {
1482b955f6caSJeff Kirsher     static int old;
1483b955f6caSJeff Kirsher     if (netdev_mc_count(dev) != old) {
1484b955f6caSJeff Kirsher       old = netdev_mc_count(dev);
1485b955f6caSJeff Kirsher       pr_debug("%s: setting Rx mode to %d addresses.\n",
1486b955f6caSJeff Kirsher 	    dev->name, old);
1487b955f6caSJeff Kirsher     }
1488b955f6caSJeff Kirsher   }
1489b955f6caSJeff Kirsher #endif
1490b955f6caSJeff Kirsher 
1491b955f6caSJeff Kirsher   lp->multicast_num_addrs = netdev_mc_count(dev);
1492b955f6caSJeff Kirsher   restore_multicast_list(dev);
1493b955f6caSJeff Kirsher 
1494b955f6caSJeff Kirsher } /* set_multicast_list */
1495b955f6caSJeff Kirsher 
1496b955f6caSJeff Kirsher static const struct pcmcia_device_id nmclan_ids[] = {
1497b955f6caSJeff Kirsher 	PCMCIA_DEVICE_PROD_ID12("New Media Corporation", "Ethernet", 0x085a850b, 0x00b2e941),
1498b955f6caSJeff Kirsher 	PCMCIA_DEVICE_PROD_ID12("Portable Add-ons", "Ethernet+", 0xebf1d60, 0xad673aaf),
1499b955f6caSJeff Kirsher 	PCMCIA_DEVICE_NULL,
1500b955f6caSJeff Kirsher };
1501b955f6caSJeff Kirsher MODULE_DEVICE_TABLE(pcmcia, nmclan_ids);
1502b955f6caSJeff Kirsher 
1503b955f6caSJeff Kirsher static struct pcmcia_driver nmclan_cs_driver = {
1504b955f6caSJeff Kirsher 	.owner		= THIS_MODULE,
1505b955f6caSJeff Kirsher 	.name		= "nmclan_cs",
1506b955f6caSJeff Kirsher 	.probe		= nmclan_probe,
1507b955f6caSJeff Kirsher 	.remove		= nmclan_detach,
1508b955f6caSJeff Kirsher 	.id_table       = nmclan_ids,
1509b955f6caSJeff Kirsher 	.suspend	= nmclan_suspend,
1510b955f6caSJeff Kirsher 	.resume		= nmclan_resume,
1511b955f6caSJeff Kirsher };
1512fdd3f29eSH Hartley Sweeten module_pcmcia_driver(nmclan_cs_driver);
1513