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