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