xref: /openbmc/linux/drivers/net/ethernet/3com/3c509.c (revision ca7a8e85)
1ca7a8e85SJeff Kirsher /* 3c509.c: A 3c509 EtherLink3 ethernet driver for linux. */
2ca7a8e85SJeff Kirsher /*
3ca7a8e85SJeff Kirsher 	Written 1993-2000 by Donald Becker.
4ca7a8e85SJeff Kirsher 
5ca7a8e85SJeff Kirsher 	Copyright 1994-2000 by Donald Becker.
6ca7a8e85SJeff Kirsher 	Copyright 1993 United States Government as represented by the
7ca7a8e85SJeff Kirsher 	Director, National Security Agency.	 This software may be used and
8ca7a8e85SJeff Kirsher 	distributed according to the terms of the GNU General Public License,
9ca7a8e85SJeff Kirsher 	incorporated herein by reference.
10ca7a8e85SJeff Kirsher 
11ca7a8e85SJeff Kirsher 	This driver is for the 3Com EtherLinkIII series.
12ca7a8e85SJeff Kirsher 
13ca7a8e85SJeff Kirsher 	The author may be reached as becker@scyld.com, or C/O
14ca7a8e85SJeff Kirsher 	Scyld Computing Corporation
15ca7a8e85SJeff Kirsher 	410 Severn Ave., Suite 210
16ca7a8e85SJeff Kirsher 	Annapolis MD 21403
17ca7a8e85SJeff Kirsher 
18ca7a8e85SJeff Kirsher 	Known limitations:
19ca7a8e85SJeff Kirsher 	Because of the way 3c509 ISA detection works it's difficult to predict
20ca7a8e85SJeff Kirsher 	a priori which of several ISA-mode cards will be detected first.
21ca7a8e85SJeff Kirsher 
22ca7a8e85SJeff Kirsher 	This driver does not use predictive interrupt mode, resulting in higher
23ca7a8e85SJeff Kirsher 	packet latency but lower overhead.  If interrupts are disabled for an
24ca7a8e85SJeff Kirsher 	unusually long time it could also result in missed packets, but in
25ca7a8e85SJeff Kirsher 	practice this rarely happens.
26ca7a8e85SJeff Kirsher 
27ca7a8e85SJeff Kirsher 
28ca7a8e85SJeff Kirsher 	FIXES:
29ca7a8e85SJeff Kirsher 		Alan Cox:       Removed the 'Unexpected interrupt' bug.
30ca7a8e85SJeff Kirsher 		Michael Meskes:	Upgraded to Donald Becker's version 1.07.
31ca7a8e85SJeff Kirsher 		Alan Cox:	Increased the eeprom delay. Regardless of
32ca7a8e85SJeff Kirsher 				what the docs say some people definitely
33ca7a8e85SJeff Kirsher 				get problems with lower (but in card spec)
34ca7a8e85SJeff Kirsher 				delays
35ca7a8e85SJeff Kirsher 		v1.10 4/21/97 Fixed module code so that multiple cards may be detected,
36ca7a8e85SJeff Kirsher 				other cleanups.  -djb
37ca7a8e85SJeff Kirsher 		Andrea Arcangeli:	Upgraded to Donald Becker's version 1.12.
38ca7a8e85SJeff Kirsher 		Rick Payne:	Fixed SMP race condition
39ca7a8e85SJeff Kirsher 		v1.13 9/8/97 Made 'max_interrupt_work' an insmod-settable variable -djb
40ca7a8e85SJeff Kirsher 		v1.14 10/15/97 Avoided waiting..discard message for fast machines -djb
41ca7a8e85SJeff Kirsher 		v1.15 1/31/98 Faster recovery for Tx errors. -djb
42ca7a8e85SJeff Kirsher 		v1.16 2/3/98 Different ID port handling to avoid sound cards. -djb
43ca7a8e85SJeff Kirsher 		v1.18 12Mar2001 Andrew Morton
44ca7a8e85SJeff Kirsher 			- Avoid bogus detect of 3c590's (Andrzej Krzysztofowicz)
45ca7a8e85SJeff Kirsher 			- Reviewed against 1.18 from scyld.com
46ca7a8e85SJeff Kirsher 		v1.18a 17Nov2001 Jeff Garzik <jgarzik@pobox.com>
47ca7a8e85SJeff Kirsher 			- ethtool support
48ca7a8e85SJeff Kirsher 		v1.18b 1Mar2002 Zwane Mwaikambo <zwane@commfireservices.com>
49ca7a8e85SJeff Kirsher 			- Power Management support
50ca7a8e85SJeff Kirsher 		v1.18c 1Mar2002 David Ruggiero <jdr@farfalle.com>
51ca7a8e85SJeff Kirsher 			- Full duplex support
52ca7a8e85SJeff Kirsher 		v1.19  16Oct2002 Zwane Mwaikambo <zwane@linuxpower.ca>
53ca7a8e85SJeff Kirsher 			- Additional ethtool features
54ca7a8e85SJeff Kirsher 		v1.19a 28Oct2002 Davud Ruggiero <jdr@farfalle.com>
55ca7a8e85SJeff Kirsher 			- Increase *read_eeprom udelay to workaround oops with 2 cards.
56ca7a8e85SJeff Kirsher 		v1.19b 08Nov2002 Marc Zyngier <maz@wild-wind.fr.eu.org>
57ca7a8e85SJeff Kirsher 			- Introduce driver model for EISA cards.
58ca7a8e85SJeff Kirsher 		v1.20  04Feb2008 Ondrej Zary <linux@rainbow-software.org>
59ca7a8e85SJeff Kirsher 			- convert to isa_driver and pnp_driver and some cleanups
60ca7a8e85SJeff Kirsher */
61ca7a8e85SJeff Kirsher 
62ca7a8e85SJeff Kirsher #define DRV_NAME	"3c509"
63ca7a8e85SJeff Kirsher #define DRV_VERSION	"1.20"
64ca7a8e85SJeff Kirsher #define DRV_RELDATE	"04Feb2008"
65ca7a8e85SJeff Kirsher 
66ca7a8e85SJeff Kirsher /* A few values that may be tweaked. */
67ca7a8e85SJeff Kirsher 
68ca7a8e85SJeff Kirsher /* Time in jiffies before concluding the transmitter is hung. */
69ca7a8e85SJeff Kirsher #define TX_TIMEOUT  (400*HZ/1000)
70ca7a8e85SJeff Kirsher 
71ca7a8e85SJeff Kirsher #include <linux/module.h>
72ca7a8e85SJeff Kirsher #include <linux/mca.h>
73ca7a8e85SJeff Kirsher #include <linux/isa.h>
74ca7a8e85SJeff Kirsher #include <linux/pnp.h>
75ca7a8e85SJeff Kirsher #include <linux/string.h>
76ca7a8e85SJeff Kirsher #include <linux/interrupt.h>
77ca7a8e85SJeff Kirsher #include <linux/errno.h>
78ca7a8e85SJeff Kirsher #include <linux/in.h>
79ca7a8e85SJeff Kirsher #include <linux/ioport.h>
80ca7a8e85SJeff Kirsher #include <linux/init.h>
81ca7a8e85SJeff Kirsher #include <linux/netdevice.h>
82ca7a8e85SJeff Kirsher #include <linux/etherdevice.h>
83ca7a8e85SJeff Kirsher #include <linux/pm.h>
84ca7a8e85SJeff Kirsher #include <linux/skbuff.h>
85ca7a8e85SJeff Kirsher #include <linux/delay.h>	/* for udelay() */
86ca7a8e85SJeff Kirsher #include <linux/spinlock.h>
87ca7a8e85SJeff Kirsher #include <linux/ethtool.h>
88ca7a8e85SJeff Kirsher #include <linux/device.h>
89ca7a8e85SJeff Kirsher #include <linux/eisa.h>
90ca7a8e85SJeff Kirsher #include <linux/bitops.h>
91ca7a8e85SJeff Kirsher 
92ca7a8e85SJeff Kirsher #include <asm/uaccess.h>
93ca7a8e85SJeff Kirsher #include <asm/io.h>
94ca7a8e85SJeff Kirsher #include <asm/irq.h>
95ca7a8e85SJeff Kirsher 
96ca7a8e85SJeff Kirsher static char version[] __devinitdata = DRV_NAME ".c:" DRV_VERSION " " DRV_RELDATE " becker@scyld.com\n";
97ca7a8e85SJeff Kirsher 
98ca7a8e85SJeff Kirsher #ifdef EL3_DEBUG
99ca7a8e85SJeff Kirsher static int el3_debug = EL3_DEBUG;
100ca7a8e85SJeff Kirsher #else
101ca7a8e85SJeff Kirsher static int el3_debug = 2;
102ca7a8e85SJeff Kirsher #endif
103ca7a8e85SJeff Kirsher 
104ca7a8e85SJeff Kirsher /* Used to do a global count of all the cards in the system.  Must be
105ca7a8e85SJeff Kirsher  * a global variable so that the mca/eisa probe routines can increment
106ca7a8e85SJeff Kirsher  * it */
107ca7a8e85SJeff Kirsher static int el3_cards = 0;
108ca7a8e85SJeff Kirsher #define EL3_MAX_CARDS 8
109ca7a8e85SJeff Kirsher 
110ca7a8e85SJeff Kirsher /* To minimize the size of the driver source I only define operating
111ca7a8e85SJeff Kirsher    constants if they are used several times.  You'll need the manual
112ca7a8e85SJeff Kirsher    anyway if you want to understand driver details. */
113ca7a8e85SJeff Kirsher /* Offsets from base I/O address. */
114ca7a8e85SJeff Kirsher #define EL3_DATA 0x00
115ca7a8e85SJeff Kirsher #define EL3_CMD 0x0e
116ca7a8e85SJeff Kirsher #define EL3_STATUS 0x0e
117ca7a8e85SJeff Kirsher #define	EEPROM_READ 0x80
118ca7a8e85SJeff Kirsher 
119ca7a8e85SJeff Kirsher #define EL3_IO_EXTENT	16
120ca7a8e85SJeff Kirsher 
121ca7a8e85SJeff Kirsher #define EL3WINDOW(win_num) outw(SelectWindow + (win_num), ioaddr + EL3_CMD)
122ca7a8e85SJeff Kirsher 
123ca7a8e85SJeff Kirsher 
124ca7a8e85SJeff Kirsher /* The top five bits written to EL3_CMD are a command, the lower
125ca7a8e85SJeff Kirsher    11 bits are the parameter, if applicable. */
126ca7a8e85SJeff Kirsher enum c509cmd {
127ca7a8e85SJeff Kirsher 	TotalReset = 0<<11, SelectWindow = 1<<11, StartCoax = 2<<11,
128ca7a8e85SJeff Kirsher 	RxDisable = 3<<11, RxEnable = 4<<11, RxReset = 5<<11, RxDiscard = 8<<11,
129ca7a8e85SJeff Kirsher 	TxEnable = 9<<11, TxDisable = 10<<11, TxReset = 11<<11,
130ca7a8e85SJeff Kirsher 	FakeIntr = 12<<11, AckIntr = 13<<11, SetIntrEnb = 14<<11,
131ca7a8e85SJeff Kirsher 	SetStatusEnb = 15<<11, SetRxFilter = 16<<11, SetRxThreshold = 17<<11,
132ca7a8e85SJeff Kirsher 	SetTxThreshold = 18<<11, SetTxStart = 19<<11, StatsEnable = 21<<11,
133ca7a8e85SJeff Kirsher 	StatsDisable = 22<<11, StopCoax = 23<<11, PowerUp = 27<<11,
134ca7a8e85SJeff Kirsher 	PowerDown = 28<<11, PowerAuto = 29<<11};
135ca7a8e85SJeff Kirsher 
136ca7a8e85SJeff Kirsher enum c509status {
137ca7a8e85SJeff Kirsher 	IntLatch = 0x0001, AdapterFailure = 0x0002, TxComplete = 0x0004,
138ca7a8e85SJeff Kirsher 	TxAvailable = 0x0008, RxComplete = 0x0010, RxEarly = 0x0020,
139ca7a8e85SJeff Kirsher 	IntReq = 0x0040, StatsFull = 0x0080, CmdBusy = 0x1000, };
140ca7a8e85SJeff Kirsher 
141ca7a8e85SJeff Kirsher /* The SetRxFilter command accepts the following classes: */
142ca7a8e85SJeff Kirsher enum RxFilter {
143ca7a8e85SJeff Kirsher 	RxStation = 1, RxMulticast = 2, RxBroadcast = 4, RxProm = 8 };
144ca7a8e85SJeff Kirsher 
145ca7a8e85SJeff Kirsher /* Register window 1 offsets, the window used in normal operation. */
146ca7a8e85SJeff Kirsher #define TX_FIFO		0x00
147ca7a8e85SJeff Kirsher #define RX_FIFO		0x00
148ca7a8e85SJeff Kirsher #define RX_STATUS 	0x08
149ca7a8e85SJeff Kirsher #define TX_STATUS 	0x0B
150ca7a8e85SJeff Kirsher #define TX_FREE		0x0C		/* Remaining free bytes in Tx buffer. */
151ca7a8e85SJeff Kirsher 
152ca7a8e85SJeff Kirsher #define WN0_CONF_CTRL	0x04		/* Window 0: Configuration control register */
153ca7a8e85SJeff Kirsher #define WN0_ADDR_CONF	0x06		/* Window 0: Address configuration register */
154ca7a8e85SJeff Kirsher #define WN0_IRQ		0x08		/* Window 0: Set IRQ line in bits 12-15. */
155ca7a8e85SJeff Kirsher #define WN4_MEDIA	0x0A		/* Window 4: Various transcvr/media bits. */
156ca7a8e85SJeff Kirsher #define	MEDIA_TP	0x00C0		/* Enable link beat and jabber for 10baseT. */
157ca7a8e85SJeff Kirsher #define WN4_NETDIAG	0x06		/* Window 4: Net diagnostic */
158ca7a8e85SJeff Kirsher #define FD_ENABLE	0x8000		/* Enable full-duplex ("external loopback") */
159ca7a8e85SJeff Kirsher 
160ca7a8e85SJeff Kirsher /*
161ca7a8e85SJeff Kirsher  * Must be a power of two (we use a binary and in the
162ca7a8e85SJeff Kirsher  * circular queue)
163ca7a8e85SJeff Kirsher  */
164ca7a8e85SJeff Kirsher #define SKB_QUEUE_SIZE	64
165ca7a8e85SJeff Kirsher 
166ca7a8e85SJeff Kirsher enum el3_cardtype { EL3_ISA, EL3_PNP, EL3_MCA, EL3_EISA };
167ca7a8e85SJeff Kirsher 
168ca7a8e85SJeff Kirsher struct el3_private {
169ca7a8e85SJeff Kirsher 	spinlock_t lock;
170ca7a8e85SJeff Kirsher 	/* skb send-queue */
171ca7a8e85SJeff Kirsher 	int head, size;
172ca7a8e85SJeff Kirsher 	struct sk_buff *queue[SKB_QUEUE_SIZE];
173ca7a8e85SJeff Kirsher 	enum el3_cardtype type;
174ca7a8e85SJeff Kirsher };
175ca7a8e85SJeff Kirsher static int id_port;
176ca7a8e85SJeff Kirsher static int current_tag;
177ca7a8e85SJeff Kirsher static struct net_device *el3_devs[EL3_MAX_CARDS];
178ca7a8e85SJeff Kirsher 
179ca7a8e85SJeff Kirsher /* Parameters that may be passed into the module. */
180ca7a8e85SJeff Kirsher static int debug = -1;
181ca7a8e85SJeff Kirsher static int irq[] = {-1, -1, -1, -1, -1, -1, -1, -1};
182ca7a8e85SJeff Kirsher /* Maximum events (Rx packets, etc.) to handle at each interrupt. */
183ca7a8e85SJeff Kirsher static int max_interrupt_work = 10;
184ca7a8e85SJeff Kirsher #ifdef CONFIG_PNP
185ca7a8e85SJeff Kirsher static int nopnp;
186ca7a8e85SJeff Kirsher #endif
187ca7a8e85SJeff Kirsher 
188ca7a8e85SJeff Kirsher static int __devinit el3_common_init(struct net_device *dev);
189ca7a8e85SJeff Kirsher static void el3_common_remove(struct net_device *dev);
190ca7a8e85SJeff Kirsher static ushort id_read_eeprom(int index);
191ca7a8e85SJeff Kirsher static ushort read_eeprom(int ioaddr, int index);
192ca7a8e85SJeff Kirsher static int el3_open(struct net_device *dev);
193ca7a8e85SJeff Kirsher static netdev_tx_t el3_start_xmit(struct sk_buff *skb, struct net_device *dev);
194ca7a8e85SJeff Kirsher static irqreturn_t el3_interrupt(int irq, void *dev_id);
195ca7a8e85SJeff Kirsher static void update_stats(struct net_device *dev);
196ca7a8e85SJeff Kirsher static struct net_device_stats *el3_get_stats(struct net_device *dev);
197ca7a8e85SJeff Kirsher static int el3_rx(struct net_device *dev);
198ca7a8e85SJeff Kirsher static int el3_close(struct net_device *dev);
199ca7a8e85SJeff Kirsher static void set_multicast_list(struct net_device *dev);
200ca7a8e85SJeff Kirsher static void el3_tx_timeout (struct net_device *dev);
201ca7a8e85SJeff Kirsher static void el3_down(struct net_device *dev);
202ca7a8e85SJeff Kirsher static void el3_up(struct net_device *dev);
203ca7a8e85SJeff Kirsher static const struct ethtool_ops ethtool_ops;
204ca7a8e85SJeff Kirsher #ifdef CONFIG_PM
205ca7a8e85SJeff Kirsher static int el3_suspend(struct device *, pm_message_t);
206ca7a8e85SJeff Kirsher static int el3_resume(struct device *);
207ca7a8e85SJeff Kirsher #else
208ca7a8e85SJeff Kirsher #define el3_suspend NULL
209ca7a8e85SJeff Kirsher #define el3_resume NULL
210ca7a8e85SJeff Kirsher #endif
211ca7a8e85SJeff Kirsher 
212ca7a8e85SJeff Kirsher 
213ca7a8e85SJeff Kirsher /* generic device remove for all device types */
214ca7a8e85SJeff Kirsher static int el3_device_remove (struct device *device);
215ca7a8e85SJeff Kirsher #ifdef CONFIG_NET_POLL_CONTROLLER
216ca7a8e85SJeff Kirsher static void el3_poll_controller(struct net_device *dev);
217ca7a8e85SJeff Kirsher #endif
218ca7a8e85SJeff Kirsher 
219ca7a8e85SJeff Kirsher /* Return 0 on success, 1 on error, 2 when found already detected PnP card */
220ca7a8e85SJeff Kirsher static int el3_isa_id_sequence(__be16 *phys_addr)
221ca7a8e85SJeff Kirsher {
222ca7a8e85SJeff Kirsher 	short lrs_state = 0xff;
223ca7a8e85SJeff Kirsher 	int i;
224ca7a8e85SJeff Kirsher 
225ca7a8e85SJeff Kirsher 	/* ISA boards are detected by sending the ID sequence to the
226ca7a8e85SJeff Kirsher 	   ID_PORT.  We find cards past the first by setting the 'current_tag'
227ca7a8e85SJeff Kirsher 	   on cards as they are found.  Cards with their tag set will not
228ca7a8e85SJeff Kirsher 	   respond to subsequent ID sequences. */
229ca7a8e85SJeff Kirsher 
230ca7a8e85SJeff Kirsher 	outb(0x00, id_port);
231ca7a8e85SJeff Kirsher 	outb(0x00, id_port);
232ca7a8e85SJeff Kirsher 	for (i = 0; i < 255; i++) {
233ca7a8e85SJeff Kirsher 		outb(lrs_state, id_port);
234ca7a8e85SJeff Kirsher 		lrs_state <<= 1;
235ca7a8e85SJeff Kirsher 		lrs_state = lrs_state & 0x100 ? lrs_state ^ 0xcf : lrs_state;
236ca7a8e85SJeff Kirsher 	}
237ca7a8e85SJeff Kirsher 	/* For the first probe, clear all board's tag registers. */
238ca7a8e85SJeff Kirsher 	if (current_tag == 0)
239ca7a8e85SJeff Kirsher 		outb(0xd0, id_port);
240ca7a8e85SJeff Kirsher 	else			/* Otherwise kill off already-found boards. */
241ca7a8e85SJeff Kirsher 		outb(0xd8, id_port);
242ca7a8e85SJeff Kirsher 	if (id_read_eeprom(7) != 0x6d50)
243ca7a8e85SJeff Kirsher 		return 1;
244ca7a8e85SJeff Kirsher 	/* Read in EEPROM data, which does contention-select.
245ca7a8e85SJeff Kirsher 	   Only the lowest address board will stay "on-line".
246ca7a8e85SJeff Kirsher 	   3Com got the byte order backwards. */
247ca7a8e85SJeff Kirsher 	for (i = 0; i < 3; i++)
248ca7a8e85SJeff Kirsher 		phys_addr[i] = htons(id_read_eeprom(i));
249ca7a8e85SJeff Kirsher #ifdef CONFIG_PNP
250ca7a8e85SJeff Kirsher 	if (!nopnp) {
251ca7a8e85SJeff Kirsher 		/* The ISA PnP 3c509 cards respond to the ID sequence too.
252ca7a8e85SJeff Kirsher 		   This check is needed in order not to register them twice. */
253ca7a8e85SJeff Kirsher 		for (i = 0; i < el3_cards; i++) {
254ca7a8e85SJeff Kirsher 			struct el3_private *lp = netdev_priv(el3_devs[i]);
255ca7a8e85SJeff Kirsher 			if (lp->type == EL3_PNP &&
256ca7a8e85SJeff Kirsher 			    !memcmp(phys_addr, el3_devs[i]->dev_addr,
257ca7a8e85SJeff Kirsher 				    ETH_ALEN)) {
258ca7a8e85SJeff Kirsher 				if (el3_debug > 3)
259ca7a8e85SJeff Kirsher 					pr_debug("3c509 with address %02x %02x %02x %02x %02x %02x was found by ISAPnP\n",
260ca7a8e85SJeff Kirsher 						phys_addr[0] & 0xff, phys_addr[0] >> 8,
261ca7a8e85SJeff Kirsher 						phys_addr[1] & 0xff, phys_addr[1] >> 8,
262ca7a8e85SJeff Kirsher 						phys_addr[2] & 0xff, phys_addr[2] >> 8);
263ca7a8e85SJeff Kirsher 				/* Set the adaptor tag so that the next card can be found. */
264ca7a8e85SJeff Kirsher 				outb(0xd0 + ++current_tag, id_port);
265ca7a8e85SJeff Kirsher 				return 2;
266ca7a8e85SJeff Kirsher 			}
267ca7a8e85SJeff Kirsher 		}
268ca7a8e85SJeff Kirsher 	}
269ca7a8e85SJeff Kirsher #endif /* CONFIG_PNP */
270ca7a8e85SJeff Kirsher 	return 0;
271ca7a8e85SJeff Kirsher 
272ca7a8e85SJeff Kirsher }
273ca7a8e85SJeff Kirsher 
274ca7a8e85SJeff Kirsher static void __devinit el3_dev_fill(struct net_device *dev, __be16 *phys_addr,
275ca7a8e85SJeff Kirsher 				   int ioaddr, int irq, int if_port,
276ca7a8e85SJeff Kirsher 				   enum el3_cardtype type)
277ca7a8e85SJeff Kirsher {
278ca7a8e85SJeff Kirsher 	struct el3_private *lp = netdev_priv(dev);
279ca7a8e85SJeff Kirsher 
280ca7a8e85SJeff Kirsher 	memcpy(dev->dev_addr, phys_addr, ETH_ALEN);
281ca7a8e85SJeff Kirsher 	dev->base_addr = ioaddr;
282ca7a8e85SJeff Kirsher 	dev->irq = irq;
283ca7a8e85SJeff Kirsher 	dev->if_port = if_port;
284ca7a8e85SJeff Kirsher 	lp->type = type;
285ca7a8e85SJeff Kirsher }
286ca7a8e85SJeff Kirsher 
287ca7a8e85SJeff Kirsher static int __devinit el3_isa_match(struct device *pdev,
288ca7a8e85SJeff Kirsher 				   unsigned int ndev)
289ca7a8e85SJeff Kirsher {
290ca7a8e85SJeff Kirsher 	struct net_device *dev;
291ca7a8e85SJeff Kirsher 	int ioaddr, isa_irq, if_port, err;
292ca7a8e85SJeff Kirsher 	unsigned int iobase;
293ca7a8e85SJeff Kirsher 	__be16 phys_addr[3];
294ca7a8e85SJeff Kirsher 
295ca7a8e85SJeff Kirsher 	while ((err = el3_isa_id_sequence(phys_addr)) == 2)
296ca7a8e85SJeff Kirsher 		;	/* Skip to next card when PnP card found */
297ca7a8e85SJeff Kirsher 	if (err == 1)
298ca7a8e85SJeff Kirsher 		return 0;
299ca7a8e85SJeff Kirsher 
300ca7a8e85SJeff Kirsher 	iobase = id_read_eeprom(8);
301ca7a8e85SJeff Kirsher 	if_port = iobase >> 14;
302ca7a8e85SJeff Kirsher 	ioaddr = 0x200 + ((iobase & 0x1f) << 4);
303ca7a8e85SJeff Kirsher 	if (irq[el3_cards] > 1 && irq[el3_cards] < 16)
304ca7a8e85SJeff Kirsher 		isa_irq = irq[el3_cards];
305ca7a8e85SJeff Kirsher 	else
306ca7a8e85SJeff Kirsher 		isa_irq = id_read_eeprom(9) >> 12;
307ca7a8e85SJeff Kirsher 
308ca7a8e85SJeff Kirsher 	dev = alloc_etherdev(sizeof(struct el3_private));
309ca7a8e85SJeff Kirsher 	if (!dev)
310ca7a8e85SJeff Kirsher 		return -ENOMEM;
311ca7a8e85SJeff Kirsher 
312ca7a8e85SJeff Kirsher 	netdev_boot_setup_check(dev);
313ca7a8e85SJeff Kirsher 
314ca7a8e85SJeff Kirsher 	if (!request_region(ioaddr, EL3_IO_EXTENT, "3c509-isa")) {
315ca7a8e85SJeff Kirsher 		free_netdev(dev);
316ca7a8e85SJeff Kirsher 		return 0;
317ca7a8e85SJeff Kirsher 	}
318ca7a8e85SJeff Kirsher 
319ca7a8e85SJeff Kirsher 	/* Set the adaptor tag so that the next card can be found. */
320ca7a8e85SJeff Kirsher 	outb(0xd0 + ++current_tag, id_port);
321ca7a8e85SJeff Kirsher 
322ca7a8e85SJeff Kirsher 	/* Activate the adaptor at the EEPROM location. */
323ca7a8e85SJeff Kirsher 	outb((ioaddr >> 4) | 0xe0, id_port);
324ca7a8e85SJeff Kirsher 
325ca7a8e85SJeff Kirsher 	EL3WINDOW(0);
326ca7a8e85SJeff Kirsher 	if (inw(ioaddr) != 0x6d50) {
327ca7a8e85SJeff Kirsher 		free_netdev(dev);
328ca7a8e85SJeff Kirsher 		return 0;
329ca7a8e85SJeff Kirsher 	}
330ca7a8e85SJeff Kirsher 
331ca7a8e85SJeff Kirsher 	/* Free the interrupt so that some other card can use it. */
332ca7a8e85SJeff Kirsher 	outw(0x0f00, ioaddr + WN0_IRQ);
333ca7a8e85SJeff Kirsher 
334ca7a8e85SJeff Kirsher 	el3_dev_fill(dev, phys_addr, ioaddr, isa_irq, if_port, EL3_ISA);
335ca7a8e85SJeff Kirsher 	dev_set_drvdata(pdev, dev);
336ca7a8e85SJeff Kirsher 	if (el3_common_init(dev)) {
337ca7a8e85SJeff Kirsher 		free_netdev(dev);
338ca7a8e85SJeff Kirsher 		return 0;
339ca7a8e85SJeff Kirsher 	}
340ca7a8e85SJeff Kirsher 
341ca7a8e85SJeff Kirsher 	el3_devs[el3_cards++] = dev;
342ca7a8e85SJeff Kirsher 	return 1;
343ca7a8e85SJeff Kirsher }
344ca7a8e85SJeff Kirsher 
345ca7a8e85SJeff Kirsher static int __devexit el3_isa_remove(struct device *pdev,
346ca7a8e85SJeff Kirsher 				    unsigned int ndev)
347ca7a8e85SJeff Kirsher {
348ca7a8e85SJeff Kirsher 	el3_device_remove(pdev);
349ca7a8e85SJeff Kirsher 	dev_set_drvdata(pdev, NULL);
350ca7a8e85SJeff Kirsher 	return 0;
351ca7a8e85SJeff Kirsher }
352ca7a8e85SJeff Kirsher 
353ca7a8e85SJeff Kirsher #ifdef CONFIG_PM
354ca7a8e85SJeff Kirsher static int el3_isa_suspend(struct device *dev, unsigned int n,
355ca7a8e85SJeff Kirsher 			   pm_message_t state)
356ca7a8e85SJeff Kirsher {
357ca7a8e85SJeff Kirsher 	current_tag = 0;
358ca7a8e85SJeff Kirsher 	return el3_suspend(dev, state);
359ca7a8e85SJeff Kirsher }
360ca7a8e85SJeff Kirsher 
361ca7a8e85SJeff Kirsher static int el3_isa_resume(struct device *dev, unsigned int n)
362ca7a8e85SJeff Kirsher {
363ca7a8e85SJeff Kirsher 	struct net_device *ndev = dev_get_drvdata(dev);
364ca7a8e85SJeff Kirsher 	int ioaddr = ndev->base_addr, err;
365ca7a8e85SJeff Kirsher 	__be16 phys_addr[3];
366ca7a8e85SJeff Kirsher 
367ca7a8e85SJeff Kirsher 	while ((err = el3_isa_id_sequence(phys_addr)) == 2)
368ca7a8e85SJeff Kirsher 		;	/* Skip to next card when PnP card found */
369ca7a8e85SJeff Kirsher 	if (err == 1)
370ca7a8e85SJeff Kirsher 		return 0;
371ca7a8e85SJeff Kirsher 	/* Set the adaptor tag so that the next card can be found. */
372ca7a8e85SJeff Kirsher 	outb(0xd0 + ++current_tag, id_port);
373ca7a8e85SJeff Kirsher 	/* Enable the card */
374ca7a8e85SJeff Kirsher 	outb((ioaddr >> 4) | 0xe0, id_port);
375ca7a8e85SJeff Kirsher 	EL3WINDOW(0);
376ca7a8e85SJeff Kirsher 	if (inw(ioaddr) != 0x6d50)
377ca7a8e85SJeff Kirsher 		return 1;
378ca7a8e85SJeff Kirsher 	/* Free the interrupt so that some other card can use it. */
379ca7a8e85SJeff Kirsher 	outw(0x0f00, ioaddr + WN0_IRQ);
380ca7a8e85SJeff Kirsher 	return el3_resume(dev);
381ca7a8e85SJeff Kirsher }
382ca7a8e85SJeff Kirsher #endif
383ca7a8e85SJeff Kirsher 
384ca7a8e85SJeff Kirsher static struct isa_driver el3_isa_driver = {
385ca7a8e85SJeff Kirsher 	.match		= el3_isa_match,
386ca7a8e85SJeff Kirsher 	.remove		= __devexit_p(el3_isa_remove),
387ca7a8e85SJeff Kirsher #ifdef CONFIG_PM
388ca7a8e85SJeff Kirsher 	.suspend	= el3_isa_suspend,
389ca7a8e85SJeff Kirsher 	.resume		= el3_isa_resume,
390ca7a8e85SJeff Kirsher #endif
391ca7a8e85SJeff Kirsher 	.driver		= {
392ca7a8e85SJeff Kirsher 		.name	= "3c509"
393ca7a8e85SJeff Kirsher 	},
394ca7a8e85SJeff Kirsher };
395ca7a8e85SJeff Kirsher static int isa_registered;
396ca7a8e85SJeff Kirsher 
397ca7a8e85SJeff Kirsher #ifdef CONFIG_PNP
398ca7a8e85SJeff Kirsher static struct pnp_device_id el3_pnp_ids[] = {
399ca7a8e85SJeff Kirsher 	{ .id = "TCM5090" }, /* 3Com Etherlink III (TP) */
400ca7a8e85SJeff Kirsher 	{ .id = "TCM5091" }, /* 3Com Etherlink III */
401ca7a8e85SJeff Kirsher 	{ .id = "TCM5094" }, /* 3Com Etherlink III (combo) */
402ca7a8e85SJeff Kirsher 	{ .id = "TCM5095" }, /* 3Com Etherlink III (TPO) */
403ca7a8e85SJeff Kirsher 	{ .id = "TCM5098" }, /* 3Com Etherlink III (TPC) */
404ca7a8e85SJeff Kirsher 	{ .id = "PNP80f7" }, /* 3Com Etherlink III compatible */
405ca7a8e85SJeff Kirsher 	{ .id = "PNP80f8" }, /* 3Com Etherlink III compatible */
406ca7a8e85SJeff Kirsher 	{ .id = "" }
407ca7a8e85SJeff Kirsher };
408ca7a8e85SJeff Kirsher MODULE_DEVICE_TABLE(pnp, el3_pnp_ids);
409ca7a8e85SJeff Kirsher 
410ca7a8e85SJeff Kirsher static int __devinit el3_pnp_probe(struct pnp_dev *pdev,
411ca7a8e85SJeff Kirsher 				    const struct pnp_device_id *id)
412ca7a8e85SJeff Kirsher {
413ca7a8e85SJeff Kirsher 	short i;
414ca7a8e85SJeff Kirsher 	int ioaddr, irq, if_port;
415ca7a8e85SJeff Kirsher 	__be16 phys_addr[3];
416ca7a8e85SJeff Kirsher 	struct net_device *dev = NULL;
417ca7a8e85SJeff Kirsher 	int err;
418ca7a8e85SJeff Kirsher 
419ca7a8e85SJeff Kirsher 	ioaddr = pnp_port_start(pdev, 0);
420ca7a8e85SJeff Kirsher 	if (!request_region(ioaddr, EL3_IO_EXTENT, "3c509-pnp"))
421ca7a8e85SJeff Kirsher 		return -EBUSY;
422ca7a8e85SJeff Kirsher 	irq = pnp_irq(pdev, 0);
423ca7a8e85SJeff Kirsher 	EL3WINDOW(0);
424ca7a8e85SJeff Kirsher 	for (i = 0; i < 3; i++)
425ca7a8e85SJeff Kirsher 		phys_addr[i] = htons(read_eeprom(ioaddr, i));
426ca7a8e85SJeff Kirsher 	if_port = read_eeprom(ioaddr, 8) >> 14;
427ca7a8e85SJeff Kirsher 	dev = alloc_etherdev(sizeof(struct el3_private));
428ca7a8e85SJeff Kirsher 	if (!dev) {
429ca7a8e85SJeff Kirsher 		release_region(ioaddr, EL3_IO_EXTENT);
430ca7a8e85SJeff Kirsher 		return -ENOMEM;
431ca7a8e85SJeff Kirsher 	}
432ca7a8e85SJeff Kirsher 	SET_NETDEV_DEV(dev, &pdev->dev);
433ca7a8e85SJeff Kirsher 	netdev_boot_setup_check(dev);
434ca7a8e85SJeff Kirsher 
435ca7a8e85SJeff Kirsher 	el3_dev_fill(dev, phys_addr, ioaddr, irq, if_port, EL3_PNP);
436ca7a8e85SJeff Kirsher 	pnp_set_drvdata(pdev, dev);
437ca7a8e85SJeff Kirsher 	err = el3_common_init(dev);
438ca7a8e85SJeff Kirsher 
439ca7a8e85SJeff Kirsher 	if (err) {
440ca7a8e85SJeff Kirsher 		pnp_set_drvdata(pdev, NULL);
441ca7a8e85SJeff Kirsher 		free_netdev(dev);
442ca7a8e85SJeff Kirsher 		return err;
443ca7a8e85SJeff Kirsher 	}
444ca7a8e85SJeff Kirsher 
445ca7a8e85SJeff Kirsher 	el3_devs[el3_cards++] = dev;
446ca7a8e85SJeff Kirsher 	return 0;
447ca7a8e85SJeff Kirsher }
448ca7a8e85SJeff Kirsher 
449ca7a8e85SJeff Kirsher static void __devexit el3_pnp_remove(struct pnp_dev *pdev)
450ca7a8e85SJeff Kirsher {
451ca7a8e85SJeff Kirsher 	el3_common_remove(pnp_get_drvdata(pdev));
452ca7a8e85SJeff Kirsher 	pnp_set_drvdata(pdev, NULL);
453ca7a8e85SJeff Kirsher }
454ca7a8e85SJeff Kirsher 
455ca7a8e85SJeff Kirsher #ifdef CONFIG_PM
456ca7a8e85SJeff Kirsher static int el3_pnp_suspend(struct pnp_dev *pdev, pm_message_t state)
457ca7a8e85SJeff Kirsher {
458ca7a8e85SJeff Kirsher 	return el3_suspend(&pdev->dev, state);
459ca7a8e85SJeff Kirsher }
460ca7a8e85SJeff Kirsher 
461ca7a8e85SJeff Kirsher static int el3_pnp_resume(struct pnp_dev *pdev)
462ca7a8e85SJeff Kirsher {
463ca7a8e85SJeff Kirsher 	return el3_resume(&pdev->dev);
464ca7a8e85SJeff Kirsher }
465ca7a8e85SJeff Kirsher #endif
466ca7a8e85SJeff Kirsher 
467ca7a8e85SJeff Kirsher static struct pnp_driver el3_pnp_driver = {
468ca7a8e85SJeff Kirsher 	.name		= "3c509",
469ca7a8e85SJeff Kirsher 	.id_table	= el3_pnp_ids,
470ca7a8e85SJeff Kirsher 	.probe		= el3_pnp_probe,
471ca7a8e85SJeff Kirsher 	.remove		= __devexit_p(el3_pnp_remove),
472ca7a8e85SJeff Kirsher #ifdef CONFIG_PM
473ca7a8e85SJeff Kirsher 	.suspend	= el3_pnp_suspend,
474ca7a8e85SJeff Kirsher 	.resume		= el3_pnp_resume,
475ca7a8e85SJeff Kirsher #endif
476ca7a8e85SJeff Kirsher };
477ca7a8e85SJeff Kirsher static int pnp_registered;
478ca7a8e85SJeff Kirsher #endif /* CONFIG_PNP */
479ca7a8e85SJeff Kirsher 
480ca7a8e85SJeff Kirsher #ifdef CONFIG_EISA
481ca7a8e85SJeff Kirsher static struct eisa_device_id el3_eisa_ids[] = {
482ca7a8e85SJeff Kirsher 		{ "TCM5090" },
483ca7a8e85SJeff Kirsher 		{ "TCM5091" },
484ca7a8e85SJeff Kirsher 		{ "TCM5092" },
485ca7a8e85SJeff Kirsher 		{ "TCM5093" },
486ca7a8e85SJeff Kirsher 		{ "TCM5094" },
487ca7a8e85SJeff Kirsher 		{ "TCM5095" },
488ca7a8e85SJeff Kirsher 		{ "TCM5098" },
489ca7a8e85SJeff Kirsher 		{ "" }
490ca7a8e85SJeff Kirsher };
491ca7a8e85SJeff Kirsher MODULE_DEVICE_TABLE(eisa, el3_eisa_ids);
492ca7a8e85SJeff Kirsher 
493ca7a8e85SJeff Kirsher static int el3_eisa_probe (struct device *device);
494ca7a8e85SJeff Kirsher 
495ca7a8e85SJeff Kirsher static struct eisa_driver el3_eisa_driver = {
496ca7a8e85SJeff Kirsher 		.id_table = el3_eisa_ids,
497ca7a8e85SJeff Kirsher 		.driver   = {
498ca7a8e85SJeff Kirsher 				.name    = "3c579",
499ca7a8e85SJeff Kirsher 				.probe   = el3_eisa_probe,
500ca7a8e85SJeff Kirsher 				.remove  = __devexit_p (el3_device_remove),
501ca7a8e85SJeff Kirsher 				.suspend = el3_suspend,
502ca7a8e85SJeff Kirsher 				.resume  = el3_resume,
503ca7a8e85SJeff Kirsher 		}
504ca7a8e85SJeff Kirsher };
505ca7a8e85SJeff Kirsher static int eisa_registered;
506ca7a8e85SJeff Kirsher #endif
507ca7a8e85SJeff Kirsher 
508ca7a8e85SJeff Kirsher #ifdef CONFIG_MCA
509ca7a8e85SJeff Kirsher static int el3_mca_probe(struct device *dev);
510ca7a8e85SJeff Kirsher 
511ca7a8e85SJeff Kirsher static short el3_mca_adapter_ids[] __initdata = {
512ca7a8e85SJeff Kirsher 		0x627c,
513ca7a8e85SJeff Kirsher 		0x627d,
514ca7a8e85SJeff Kirsher 		0x62db,
515ca7a8e85SJeff Kirsher 		0x62f6,
516ca7a8e85SJeff Kirsher 		0x62f7,
517ca7a8e85SJeff Kirsher 		0x0000
518ca7a8e85SJeff Kirsher };
519ca7a8e85SJeff Kirsher 
520ca7a8e85SJeff Kirsher static char *el3_mca_adapter_names[] __initdata = {
521ca7a8e85SJeff Kirsher 		"3Com 3c529 EtherLink III (10base2)",
522ca7a8e85SJeff Kirsher 		"3Com 3c529 EtherLink III (10baseT)",
523ca7a8e85SJeff Kirsher 		"3Com 3c529 EtherLink III (test mode)",
524ca7a8e85SJeff Kirsher 		"3Com 3c529 EtherLink III (TP or coax)",
525ca7a8e85SJeff Kirsher 		"3Com 3c529 EtherLink III (TP)",
526ca7a8e85SJeff Kirsher 		NULL
527ca7a8e85SJeff Kirsher };
528ca7a8e85SJeff Kirsher 
529ca7a8e85SJeff Kirsher static struct mca_driver el3_mca_driver = {
530ca7a8e85SJeff Kirsher 		.id_table = el3_mca_adapter_ids,
531ca7a8e85SJeff Kirsher 		.driver = {
532ca7a8e85SJeff Kirsher 				.name = "3c529",
533ca7a8e85SJeff Kirsher 				.bus = &mca_bus_type,
534ca7a8e85SJeff Kirsher 				.probe = el3_mca_probe,
535ca7a8e85SJeff Kirsher 				.remove = __devexit_p(el3_device_remove),
536ca7a8e85SJeff Kirsher 				.suspend = el3_suspend,
537ca7a8e85SJeff Kirsher 				.resume  = el3_resume,
538ca7a8e85SJeff Kirsher 		},
539ca7a8e85SJeff Kirsher };
540ca7a8e85SJeff Kirsher static int mca_registered;
541ca7a8e85SJeff Kirsher #endif /* CONFIG_MCA */
542ca7a8e85SJeff Kirsher 
543ca7a8e85SJeff Kirsher static const struct net_device_ops netdev_ops = {
544ca7a8e85SJeff Kirsher 	.ndo_open 		= el3_open,
545ca7a8e85SJeff Kirsher 	.ndo_stop	 	= el3_close,
546ca7a8e85SJeff Kirsher 	.ndo_start_xmit 	= el3_start_xmit,
547ca7a8e85SJeff Kirsher 	.ndo_get_stats 		= el3_get_stats,
548ca7a8e85SJeff Kirsher 	.ndo_set_multicast_list = set_multicast_list,
549ca7a8e85SJeff Kirsher 	.ndo_tx_timeout 	= el3_tx_timeout,
550ca7a8e85SJeff Kirsher 	.ndo_change_mtu		= eth_change_mtu,
551ca7a8e85SJeff Kirsher 	.ndo_set_mac_address 	= eth_mac_addr,
552ca7a8e85SJeff Kirsher 	.ndo_validate_addr	= eth_validate_addr,
553ca7a8e85SJeff Kirsher #ifdef CONFIG_NET_POLL_CONTROLLER
554ca7a8e85SJeff Kirsher 	.ndo_poll_controller	= el3_poll_controller,
555ca7a8e85SJeff Kirsher #endif
556ca7a8e85SJeff Kirsher };
557ca7a8e85SJeff Kirsher 
558ca7a8e85SJeff Kirsher static int __devinit el3_common_init(struct net_device *dev)
559ca7a8e85SJeff Kirsher {
560ca7a8e85SJeff Kirsher 	struct el3_private *lp = netdev_priv(dev);
561ca7a8e85SJeff Kirsher 	int err;
562ca7a8e85SJeff Kirsher 	const char *if_names[] = {"10baseT", "AUI", "undefined", "BNC"};
563ca7a8e85SJeff Kirsher 
564ca7a8e85SJeff Kirsher 	spin_lock_init(&lp->lock);
565ca7a8e85SJeff Kirsher 
566ca7a8e85SJeff Kirsher 	if (dev->mem_start & 0x05) { /* xcvr codes 1/3/4/12 */
567ca7a8e85SJeff Kirsher 		dev->if_port = (dev->mem_start & 0x0f);
568ca7a8e85SJeff Kirsher 	} else { /* xcvr codes 0/8 */
569ca7a8e85SJeff Kirsher 		/* use eeprom value, but save user's full-duplex selection */
570ca7a8e85SJeff Kirsher 		dev->if_port |= (dev->mem_start & 0x08);
571ca7a8e85SJeff Kirsher 	}
572ca7a8e85SJeff Kirsher 
573ca7a8e85SJeff Kirsher 	/* The EL3-specific entries in the device structure. */
574ca7a8e85SJeff Kirsher 	dev->netdev_ops = &netdev_ops;
575ca7a8e85SJeff Kirsher 	dev->watchdog_timeo = TX_TIMEOUT;
576ca7a8e85SJeff Kirsher 	SET_ETHTOOL_OPS(dev, &ethtool_ops);
577ca7a8e85SJeff Kirsher 
578ca7a8e85SJeff Kirsher 	err = register_netdev(dev);
579ca7a8e85SJeff Kirsher 	if (err) {
580ca7a8e85SJeff Kirsher 		pr_err("Failed to register 3c5x9 at %#3.3lx, IRQ %d.\n",
581ca7a8e85SJeff Kirsher 			dev->base_addr, dev->irq);
582ca7a8e85SJeff Kirsher 		release_region(dev->base_addr, EL3_IO_EXTENT);
583ca7a8e85SJeff Kirsher 		return err;
584ca7a8e85SJeff Kirsher 	}
585ca7a8e85SJeff Kirsher 
586ca7a8e85SJeff Kirsher 	pr_info("%s: 3c5x9 found at %#3.3lx, %s port, address %pM, IRQ %d.\n",
587ca7a8e85SJeff Kirsher 	       dev->name, dev->base_addr, if_names[(dev->if_port & 0x03)],
588ca7a8e85SJeff Kirsher 	       dev->dev_addr, dev->irq);
589ca7a8e85SJeff Kirsher 
590ca7a8e85SJeff Kirsher 	if (el3_debug > 0)
591ca7a8e85SJeff Kirsher 		pr_info("%s", version);
592ca7a8e85SJeff Kirsher 	return 0;
593ca7a8e85SJeff Kirsher 
594ca7a8e85SJeff Kirsher }
595ca7a8e85SJeff Kirsher 
596ca7a8e85SJeff Kirsher static void el3_common_remove (struct net_device *dev)
597ca7a8e85SJeff Kirsher {
598ca7a8e85SJeff Kirsher 	unregister_netdev (dev);
599ca7a8e85SJeff Kirsher 	release_region(dev->base_addr, EL3_IO_EXTENT);
600ca7a8e85SJeff Kirsher 	free_netdev (dev);
601ca7a8e85SJeff Kirsher }
602ca7a8e85SJeff Kirsher 
603ca7a8e85SJeff Kirsher #ifdef CONFIG_MCA
604ca7a8e85SJeff Kirsher static int __init el3_mca_probe(struct device *device)
605ca7a8e85SJeff Kirsher {
606ca7a8e85SJeff Kirsher 	/* Based on Erik Nygren's (nygren@mit.edu) 3c529 patch,
607ca7a8e85SJeff Kirsher 	 * heavily modified by Chris Beauregard
608ca7a8e85SJeff Kirsher 	 * (cpbeaure@csclub.uwaterloo.ca) to support standard MCA
609ca7a8e85SJeff Kirsher 	 * probing.
610ca7a8e85SJeff Kirsher 	 *
611ca7a8e85SJeff Kirsher 	 * redone for multi-card detection by ZP Gu (zpg@castle.net)
612ca7a8e85SJeff Kirsher 	 * now works as a module */
613ca7a8e85SJeff Kirsher 
614ca7a8e85SJeff Kirsher 	short i;
615ca7a8e85SJeff Kirsher 	int ioaddr, irq, if_port;
616ca7a8e85SJeff Kirsher 	__be16 phys_addr[3];
617ca7a8e85SJeff Kirsher 	struct net_device *dev = NULL;
618ca7a8e85SJeff Kirsher 	u_char pos4, pos5;
619ca7a8e85SJeff Kirsher 	struct mca_device *mdev = to_mca_device(device);
620ca7a8e85SJeff Kirsher 	int slot = mdev->slot;
621ca7a8e85SJeff Kirsher 	int err;
622ca7a8e85SJeff Kirsher 
623ca7a8e85SJeff Kirsher 	pos4 = mca_device_read_stored_pos(mdev, 4);
624ca7a8e85SJeff Kirsher 	pos5 = mca_device_read_stored_pos(mdev, 5);
625ca7a8e85SJeff Kirsher 
626ca7a8e85SJeff Kirsher 	ioaddr = ((short)((pos4&0xfc)|0x02)) << 8;
627ca7a8e85SJeff Kirsher 	irq = pos5 & 0x0f;
628ca7a8e85SJeff Kirsher 
629ca7a8e85SJeff Kirsher 
630ca7a8e85SJeff Kirsher 	pr_info("3c529: found %s at slot %d\n",
631ca7a8e85SJeff Kirsher 		el3_mca_adapter_names[mdev->index], slot + 1);
632ca7a8e85SJeff Kirsher 
633ca7a8e85SJeff Kirsher 	/* claim the slot */
634ca7a8e85SJeff Kirsher 	strncpy(mdev->name, el3_mca_adapter_names[mdev->index],
635ca7a8e85SJeff Kirsher 			sizeof(mdev->name));
636ca7a8e85SJeff Kirsher 	mca_device_set_claim(mdev, 1);
637ca7a8e85SJeff Kirsher 
638ca7a8e85SJeff Kirsher 	if_port = pos4 & 0x03;
639ca7a8e85SJeff Kirsher 
640ca7a8e85SJeff Kirsher 	irq = mca_device_transform_irq(mdev, irq);
641ca7a8e85SJeff Kirsher 	ioaddr = mca_device_transform_ioport(mdev, ioaddr);
642ca7a8e85SJeff Kirsher 	if (el3_debug > 2) {
643ca7a8e85SJeff Kirsher 		pr_debug("3c529: irq %d  ioaddr 0x%x  ifport %d\n", irq, ioaddr, if_port);
644ca7a8e85SJeff Kirsher 	}
645ca7a8e85SJeff Kirsher 	EL3WINDOW(0);
646ca7a8e85SJeff Kirsher 	for (i = 0; i < 3; i++)
647ca7a8e85SJeff Kirsher 		phys_addr[i] = htons(read_eeprom(ioaddr, i));
648ca7a8e85SJeff Kirsher 
649ca7a8e85SJeff Kirsher 	dev = alloc_etherdev(sizeof (struct el3_private));
650ca7a8e85SJeff Kirsher 	if (dev == NULL) {
651ca7a8e85SJeff Kirsher 		release_region(ioaddr, EL3_IO_EXTENT);
652ca7a8e85SJeff Kirsher 		return -ENOMEM;
653ca7a8e85SJeff Kirsher 	}
654ca7a8e85SJeff Kirsher 
655ca7a8e85SJeff Kirsher 	netdev_boot_setup_check(dev);
656ca7a8e85SJeff Kirsher 
657ca7a8e85SJeff Kirsher 	el3_dev_fill(dev, phys_addr, ioaddr, irq, if_port, EL3_MCA);
658ca7a8e85SJeff Kirsher 	dev_set_drvdata(device, dev);
659ca7a8e85SJeff Kirsher 	err = el3_common_init(dev);
660ca7a8e85SJeff Kirsher 
661ca7a8e85SJeff Kirsher 	if (err) {
662ca7a8e85SJeff Kirsher 		dev_set_drvdata(device, NULL);
663ca7a8e85SJeff Kirsher 		free_netdev(dev);
664ca7a8e85SJeff Kirsher 		return -ENOMEM;
665ca7a8e85SJeff Kirsher 	}
666ca7a8e85SJeff Kirsher 
667ca7a8e85SJeff Kirsher 	el3_devs[el3_cards++] = dev;
668ca7a8e85SJeff Kirsher 	return 0;
669ca7a8e85SJeff Kirsher }
670ca7a8e85SJeff Kirsher 
671ca7a8e85SJeff Kirsher #endif /* CONFIG_MCA */
672ca7a8e85SJeff Kirsher 
673ca7a8e85SJeff Kirsher #ifdef CONFIG_EISA
674ca7a8e85SJeff Kirsher static int __init el3_eisa_probe (struct device *device)
675ca7a8e85SJeff Kirsher {
676ca7a8e85SJeff Kirsher 	short i;
677ca7a8e85SJeff Kirsher 	int ioaddr, irq, if_port;
678ca7a8e85SJeff Kirsher 	__be16 phys_addr[3];
679ca7a8e85SJeff Kirsher 	struct net_device *dev = NULL;
680ca7a8e85SJeff Kirsher 	struct eisa_device *edev;
681ca7a8e85SJeff Kirsher 	int err;
682ca7a8e85SJeff Kirsher 
683ca7a8e85SJeff Kirsher 	/* Yeepee, The driver framework is calling us ! */
684ca7a8e85SJeff Kirsher 	edev = to_eisa_device (device);
685ca7a8e85SJeff Kirsher 	ioaddr = edev->base_addr;
686ca7a8e85SJeff Kirsher 
687ca7a8e85SJeff Kirsher 	if (!request_region(ioaddr, EL3_IO_EXTENT, "3c579-eisa"))
688ca7a8e85SJeff Kirsher 		return -EBUSY;
689ca7a8e85SJeff Kirsher 
690ca7a8e85SJeff Kirsher 	/* Change the register set to the configuration window 0. */
691ca7a8e85SJeff Kirsher 	outw(SelectWindow | 0, ioaddr + 0xC80 + EL3_CMD);
692ca7a8e85SJeff Kirsher 
693ca7a8e85SJeff Kirsher 	irq = inw(ioaddr + WN0_IRQ) >> 12;
694ca7a8e85SJeff Kirsher 	if_port = inw(ioaddr + 6)>>14;
695ca7a8e85SJeff Kirsher 	for (i = 0; i < 3; i++)
696ca7a8e85SJeff Kirsher 		phys_addr[i] = htons(read_eeprom(ioaddr, i));
697ca7a8e85SJeff Kirsher 
698ca7a8e85SJeff Kirsher 	/* Restore the "Product ID" to the EEPROM read register. */
699ca7a8e85SJeff Kirsher 	read_eeprom(ioaddr, 3);
700ca7a8e85SJeff Kirsher 
701ca7a8e85SJeff Kirsher 	dev = alloc_etherdev(sizeof (struct el3_private));
702ca7a8e85SJeff Kirsher 	if (dev == NULL) {
703ca7a8e85SJeff Kirsher 		release_region(ioaddr, EL3_IO_EXTENT);
704ca7a8e85SJeff Kirsher 		return -ENOMEM;
705ca7a8e85SJeff Kirsher 	}
706ca7a8e85SJeff Kirsher 
707ca7a8e85SJeff Kirsher 	netdev_boot_setup_check(dev);
708ca7a8e85SJeff Kirsher 
709ca7a8e85SJeff Kirsher 	el3_dev_fill(dev, phys_addr, ioaddr, irq, if_port, EL3_EISA);
710ca7a8e85SJeff Kirsher 	eisa_set_drvdata (edev, dev);
711ca7a8e85SJeff Kirsher 	err = el3_common_init(dev);
712ca7a8e85SJeff Kirsher 
713ca7a8e85SJeff Kirsher 	if (err) {
714ca7a8e85SJeff Kirsher 		eisa_set_drvdata (edev, NULL);
715ca7a8e85SJeff Kirsher 		free_netdev(dev);
716ca7a8e85SJeff Kirsher 		return err;
717ca7a8e85SJeff Kirsher 	}
718ca7a8e85SJeff Kirsher 
719ca7a8e85SJeff Kirsher 	el3_devs[el3_cards++] = dev;
720ca7a8e85SJeff Kirsher 	return 0;
721ca7a8e85SJeff Kirsher }
722ca7a8e85SJeff Kirsher #endif
723ca7a8e85SJeff Kirsher 
724ca7a8e85SJeff Kirsher /* This remove works for all device types.
725ca7a8e85SJeff Kirsher  *
726ca7a8e85SJeff Kirsher  * The net dev must be stored in the driver data field */
727ca7a8e85SJeff Kirsher static int __devexit el3_device_remove (struct device *device)
728ca7a8e85SJeff Kirsher {
729ca7a8e85SJeff Kirsher 	struct net_device *dev;
730ca7a8e85SJeff Kirsher 
731ca7a8e85SJeff Kirsher 	dev = dev_get_drvdata(device);
732ca7a8e85SJeff Kirsher 
733ca7a8e85SJeff Kirsher 	el3_common_remove (dev);
734ca7a8e85SJeff Kirsher 	return 0;
735ca7a8e85SJeff Kirsher }
736ca7a8e85SJeff Kirsher 
737ca7a8e85SJeff Kirsher /* Read a word from the EEPROM using the regular EEPROM access register.
738ca7a8e85SJeff Kirsher    Assume that we are in register window zero.
739ca7a8e85SJeff Kirsher  */
740ca7a8e85SJeff Kirsher static ushort read_eeprom(int ioaddr, int index)
741ca7a8e85SJeff Kirsher {
742ca7a8e85SJeff Kirsher 	outw(EEPROM_READ + index, ioaddr + 10);
743ca7a8e85SJeff Kirsher 	/* Pause for at least 162 us. for the read to take place.
744ca7a8e85SJeff Kirsher 	   Some chips seem to require much longer */
745ca7a8e85SJeff Kirsher 	mdelay(2);
746ca7a8e85SJeff Kirsher 	return inw(ioaddr + 12);
747ca7a8e85SJeff Kirsher }
748ca7a8e85SJeff Kirsher 
749ca7a8e85SJeff Kirsher /* Read a word from the EEPROM when in the ISA ID probe state. */
750ca7a8e85SJeff Kirsher static ushort id_read_eeprom(int index)
751ca7a8e85SJeff Kirsher {
752ca7a8e85SJeff Kirsher 	int bit, word = 0;
753ca7a8e85SJeff Kirsher 
754ca7a8e85SJeff Kirsher 	/* Issue read command, and pause for at least 162 us. for it to complete.
755ca7a8e85SJeff Kirsher 	   Assume extra-fast 16Mhz bus. */
756ca7a8e85SJeff Kirsher 	outb(EEPROM_READ + index, id_port);
757ca7a8e85SJeff Kirsher 
758ca7a8e85SJeff Kirsher 	/* Pause for at least 162 us. for the read to take place. */
759ca7a8e85SJeff Kirsher 	/* Some chips seem to require much longer */
760ca7a8e85SJeff Kirsher 	mdelay(4);
761ca7a8e85SJeff Kirsher 
762ca7a8e85SJeff Kirsher 	for (bit = 15; bit >= 0; bit--)
763ca7a8e85SJeff Kirsher 		word = (word << 1) + (inb(id_port) & 0x01);
764ca7a8e85SJeff Kirsher 
765ca7a8e85SJeff Kirsher 	if (el3_debug > 3)
766ca7a8e85SJeff Kirsher 		pr_debug("  3c509 EEPROM word %d %#4.4x.\n", index, word);
767ca7a8e85SJeff Kirsher 
768ca7a8e85SJeff Kirsher 	return word;
769ca7a8e85SJeff Kirsher }
770ca7a8e85SJeff Kirsher 
771ca7a8e85SJeff Kirsher 
772ca7a8e85SJeff Kirsher static int
773ca7a8e85SJeff Kirsher el3_open(struct net_device *dev)
774ca7a8e85SJeff Kirsher {
775ca7a8e85SJeff Kirsher 	int ioaddr = dev->base_addr;
776ca7a8e85SJeff Kirsher 	int i;
777ca7a8e85SJeff Kirsher 
778ca7a8e85SJeff Kirsher 	outw(TxReset, ioaddr + EL3_CMD);
779ca7a8e85SJeff Kirsher 	outw(RxReset, ioaddr + EL3_CMD);
780ca7a8e85SJeff Kirsher 	outw(SetStatusEnb | 0x00, ioaddr + EL3_CMD);
781ca7a8e85SJeff Kirsher 
782ca7a8e85SJeff Kirsher 	i = request_irq(dev->irq, el3_interrupt, 0, dev->name, dev);
783ca7a8e85SJeff Kirsher 	if (i)
784ca7a8e85SJeff Kirsher 		return i;
785ca7a8e85SJeff Kirsher 
786ca7a8e85SJeff Kirsher 	EL3WINDOW(0);
787ca7a8e85SJeff Kirsher 	if (el3_debug > 3)
788ca7a8e85SJeff Kirsher 		pr_debug("%s: Opening, IRQ %d	 status@%x %4.4x.\n", dev->name,
789ca7a8e85SJeff Kirsher 			   dev->irq, ioaddr + EL3_STATUS, inw(ioaddr + EL3_STATUS));
790ca7a8e85SJeff Kirsher 
791ca7a8e85SJeff Kirsher 	el3_up(dev);
792ca7a8e85SJeff Kirsher 
793ca7a8e85SJeff Kirsher 	if (el3_debug > 3)
794ca7a8e85SJeff Kirsher 		pr_debug("%s: Opened 3c509  IRQ %d  status %4.4x.\n",
795ca7a8e85SJeff Kirsher 			   dev->name, dev->irq, inw(ioaddr + EL3_STATUS));
796ca7a8e85SJeff Kirsher 
797ca7a8e85SJeff Kirsher 	return 0;
798ca7a8e85SJeff Kirsher }
799ca7a8e85SJeff Kirsher 
800ca7a8e85SJeff Kirsher static void
801ca7a8e85SJeff Kirsher el3_tx_timeout (struct net_device *dev)
802ca7a8e85SJeff Kirsher {
803ca7a8e85SJeff Kirsher 	int ioaddr = dev->base_addr;
804ca7a8e85SJeff Kirsher 
805ca7a8e85SJeff Kirsher 	/* Transmitter timeout, serious problems. */
806ca7a8e85SJeff Kirsher 	pr_warning("%s: transmit timed out, Tx_status %2.2x status %4.4x Tx FIFO room %d.\n",
807ca7a8e85SJeff Kirsher 		   dev->name, inb(ioaddr + TX_STATUS), inw(ioaddr + EL3_STATUS),
808ca7a8e85SJeff Kirsher 		   inw(ioaddr + TX_FREE));
809ca7a8e85SJeff Kirsher 	dev->stats.tx_errors++;
810ca7a8e85SJeff Kirsher 	dev->trans_start = jiffies; /* prevent tx timeout */
811ca7a8e85SJeff Kirsher 	/* Issue TX_RESET and TX_START commands. */
812ca7a8e85SJeff Kirsher 	outw(TxReset, ioaddr + EL3_CMD);
813ca7a8e85SJeff Kirsher 	outw(TxEnable, ioaddr + EL3_CMD);
814ca7a8e85SJeff Kirsher 	netif_wake_queue(dev);
815ca7a8e85SJeff Kirsher }
816ca7a8e85SJeff Kirsher 
817ca7a8e85SJeff Kirsher 
818ca7a8e85SJeff Kirsher static netdev_tx_t
819ca7a8e85SJeff Kirsher el3_start_xmit(struct sk_buff *skb, struct net_device *dev)
820ca7a8e85SJeff Kirsher {
821ca7a8e85SJeff Kirsher 	struct el3_private *lp = netdev_priv(dev);
822ca7a8e85SJeff Kirsher 	int ioaddr = dev->base_addr;
823ca7a8e85SJeff Kirsher 	unsigned long flags;
824ca7a8e85SJeff Kirsher 
825ca7a8e85SJeff Kirsher 	netif_stop_queue (dev);
826ca7a8e85SJeff Kirsher 
827ca7a8e85SJeff Kirsher 	dev->stats.tx_bytes += skb->len;
828ca7a8e85SJeff Kirsher 
829ca7a8e85SJeff Kirsher 	if (el3_debug > 4) {
830ca7a8e85SJeff Kirsher 		pr_debug("%s: el3_start_xmit(length = %u) called, status %4.4x.\n",
831ca7a8e85SJeff Kirsher 			   dev->name, skb->len, inw(ioaddr + EL3_STATUS));
832ca7a8e85SJeff Kirsher 	}
833ca7a8e85SJeff Kirsher #if 0
834ca7a8e85SJeff Kirsher #ifndef final_version
835ca7a8e85SJeff Kirsher 	{	/* Error-checking code, delete someday. */
836ca7a8e85SJeff Kirsher 		ushort status = inw(ioaddr + EL3_STATUS);
837ca7a8e85SJeff Kirsher 		if (status & 0x0001 && 		/* IRQ line active, missed one. */
838ca7a8e85SJeff Kirsher 		    inw(ioaddr + EL3_STATUS) & 1) { 			/* Make sure. */
839ca7a8e85SJeff Kirsher 			pr_debug("%s: Missed interrupt, status then %04x now %04x"
840ca7a8e85SJeff Kirsher 				   "  Tx %2.2x Rx %4.4x.\n", dev->name, status,
841ca7a8e85SJeff Kirsher 				   inw(ioaddr + EL3_STATUS), inb(ioaddr + TX_STATUS),
842ca7a8e85SJeff Kirsher 				   inw(ioaddr + RX_STATUS));
843ca7a8e85SJeff Kirsher 			/* Fake interrupt trigger by masking, acknowledge interrupts. */
844ca7a8e85SJeff Kirsher 			outw(SetStatusEnb | 0x00, ioaddr + EL3_CMD);
845ca7a8e85SJeff Kirsher 			outw(AckIntr | IntLatch | TxAvailable | RxEarly | IntReq,
846ca7a8e85SJeff Kirsher 				 ioaddr + EL3_CMD);
847ca7a8e85SJeff Kirsher 			outw(SetStatusEnb | 0xff, ioaddr + EL3_CMD);
848ca7a8e85SJeff Kirsher 		}
849ca7a8e85SJeff Kirsher 	}
850ca7a8e85SJeff Kirsher #endif
851ca7a8e85SJeff Kirsher #endif
852ca7a8e85SJeff Kirsher 	/*
853ca7a8e85SJeff Kirsher 	 *	We lock the driver against other processors. Note
854ca7a8e85SJeff Kirsher 	 *	we don't need to lock versus the IRQ as we suspended
855ca7a8e85SJeff Kirsher 	 *	that. This means that we lose the ability to take
856ca7a8e85SJeff Kirsher 	 *	an RX during a TX upload. That sucks a bit with SMP
857ca7a8e85SJeff Kirsher 	 *	on an original 3c509 (2K buffer)
858ca7a8e85SJeff Kirsher 	 *
859ca7a8e85SJeff Kirsher 	 *	Using disable_irq stops us crapping on other
860ca7a8e85SJeff Kirsher 	 *	time sensitive devices.
861ca7a8e85SJeff Kirsher 	 */
862ca7a8e85SJeff Kirsher 
863ca7a8e85SJeff Kirsher 	spin_lock_irqsave(&lp->lock, flags);
864ca7a8e85SJeff Kirsher 
865ca7a8e85SJeff Kirsher 	/* Put out the doubleword header... */
866ca7a8e85SJeff Kirsher 	outw(skb->len, ioaddr + TX_FIFO);
867ca7a8e85SJeff Kirsher 	outw(0x00, ioaddr + TX_FIFO);
868ca7a8e85SJeff Kirsher 	/* ... and the packet rounded to a doubleword. */
869ca7a8e85SJeff Kirsher 	outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
870ca7a8e85SJeff Kirsher 
871ca7a8e85SJeff Kirsher 	if (inw(ioaddr + TX_FREE) > 1536)
872ca7a8e85SJeff Kirsher 		netif_start_queue(dev);
873ca7a8e85SJeff Kirsher 	else
874ca7a8e85SJeff Kirsher 		/* Interrupt us when the FIFO has room for max-sized packet. */
875ca7a8e85SJeff Kirsher 		outw(SetTxThreshold + 1536, ioaddr + EL3_CMD);
876ca7a8e85SJeff Kirsher 
877ca7a8e85SJeff Kirsher 	spin_unlock_irqrestore(&lp->lock, flags);
878ca7a8e85SJeff Kirsher 
879ca7a8e85SJeff Kirsher 	dev_kfree_skb (skb);
880ca7a8e85SJeff Kirsher 
881ca7a8e85SJeff Kirsher 	/* Clear the Tx status stack. */
882ca7a8e85SJeff Kirsher 	{
883ca7a8e85SJeff Kirsher 		short tx_status;
884ca7a8e85SJeff Kirsher 		int i = 4;
885ca7a8e85SJeff Kirsher 
886ca7a8e85SJeff Kirsher 		while (--i > 0	&&	(tx_status = inb(ioaddr + TX_STATUS)) > 0) {
887ca7a8e85SJeff Kirsher 			if (tx_status & 0x38) dev->stats.tx_aborted_errors++;
888ca7a8e85SJeff Kirsher 			if (tx_status & 0x30) outw(TxReset, ioaddr + EL3_CMD);
889ca7a8e85SJeff Kirsher 			if (tx_status & 0x3C) outw(TxEnable, ioaddr + EL3_CMD);
890ca7a8e85SJeff Kirsher 			outb(0x00, ioaddr + TX_STATUS); /* Pop the status stack. */
891ca7a8e85SJeff Kirsher 		}
892ca7a8e85SJeff Kirsher 	}
893ca7a8e85SJeff Kirsher 	return NETDEV_TX_OK;
894ca7a8e85SJeff Kirsher }
895ca7a8e85SJeff Kirsher 
896ca7a8e85SJeff Kirsher /* The EL3 interrupt handler. */
897ca7a8e85SJeff Kirsher static irqreturn_t
898ca7a8e85SJeff Kirsher el3_interrupt(int irq, void *dev_id)
899ca7a8e85SJeff Kirsher {
900ca7a8e85SJeff Kirsher 	struct net_device *dev = dev_id;
901ca7a8e85SJeff Kirsher 	struct el3_private *lp;
902ca7a8e85SJeff Kirsher 	int ioaddr, status;
903ca7a8e85SJeff Kirsher 	int i = max_interrupt_work;
904ca7a8e85SJeff Kirsher 
905ca7a8e85SJeff Kirsher 	lp = netdev_priv(dev);
906ca7a8e85SJeff Kirsher 	spin_lock(&lp->lock);
907ca7a8e85SJeff Kirsher 
908ca7a8e85SJeff Kirsher 	ioaddr = dev->base_addr;
909ca7a8e85SJeff Kirsher 
910ca7a8e85SJeff Kirsher 	if (el3_debug > 4) {
911ca7a8e85SJeff Kirsher 		status = inw(ioaddr + EL3_STATUS);
912ca7a8e85SJeff Kirsher 		pr_debug("%s: interrupt, status %4.4x.\n", dev->name, status);
913ca7a8e85SJeff Kirsher 	}
914ca7a8e85SJeff Kirsher 
915ca7a8e85SJeff Kirsher 	while ((status = inw(ioaddr + EL3_STATUS)) &
916ca7a8e85SJeff Kirsher 		   (IntLatch | RxComplete | StatsFull)) {
917ca7a8e85SJeff Kirsher 
918ca7a8e85SJeff Kirsher 		if (status & RxComplete)
919ca7a8e85SJeff Kirsher 			el3_rx(dev);
920ca7a8e85SJeff Kirsher 
921ca7a8e85SJeff Kirsher 		if (status & TxAvailable) {
922ca7a8e85SJeff Kirsher 			if (el3_debug > 5)
923ca7a8e85SJeff Kirsher 				pr_debug("	TX room bit was handled.\n");
924ca7a8e85SJeff Kirsher 			/* There's room in the FIFO for a full-sized packet. */
925ca7a8e85SJeff Kirsher 			outw(AckIntr | TxAvailable, ioaddr + EL3_CMD);
926ca7a8e85SJeff Kirsher 			netif_wake_queue (dev);
927ca7a8e85SJeff Kirsher 		}
928ca7a8e85SJeff Kirsher 		if (status & (AdapterFailure | RxEarly | StatsFull | TxComplete)) {
929ca7a8e85SJeff Kirsher 			/* Handle all uncommon interrupts. */
930ca7a8e85SJeff Kirsher 			if (status & StatsFull)				/* Empty statistics. */
931ca7a8e85SJeff Kirsher 				update_stats(dev);
932ca7a8e85SJeff Kirsher 			if (status & RxEarly) {				/* Rx early is unused. */
933ca7a8e85SJeff Kirsher 				el3_rx(dev);
934ca7a8e85SJeff Kirsher 				outw(AckIntr | RxEarly, ioaddr + EL3_CMD);
935ca7a8e85SJeff Kirsher 			}
936ca7a8e85SJeff Kirsher 			if (status & TxComplete) {			/* Really Tx error. */
937ca7a8e85SJeff Kirsher 				short tx_status;
938ca7a8e85SJeff Kirsher 				int i = 4;
939ca7a8e85SJeff Kirsher 
940ca7a8e85SJeff Kirsher 				while (--i>0 && (tx_status = inb(ioaddr + TX_STATUS)) > 0) {
941ca7a8e85SJeff Kirsher 					if (tx_status & 0x38) dev->stats.tx_aborted_errors++;
942ca7a8e85SJeff Kirsher 					if (tx_status & 0x30) outw(TxReset, ioaddr + EL3_CMD);
943ca7a8e85SJeff Kirsher 					if (tx_status & 0x3C) outw(TxEnable, ioaddr + EL3_CMD);
944ca7a8e85SJeff Kirsher 					outb(0x00, ioaddr + TX_STATUS); /* Pop the status stack. */
945ca7a8e85SJeff Kirsher 				}
946ca7a8e85SJeff Kirsher 			}
947ca7a8e85SJeff Kirsher 			if (status & AdapterFailure) {
948ca7a8e85SJeff Kirsher 				/* Adapter failure requires Rx reset and reinit. */
949ca7a8e85SJeff Kirsher 				outw(RxReset, ioaddr + EL3_CMD);
950ca7a8e85SJeff Kirsher 				/* Set the Rx filter to the current state. */
951ca7a8e85SJeff Kirsher 				outw(SetRxFilter | RxStation | RxBroadcast
952ca7a8e85SJeff Kirsher 					 | (dev->flags & IFF_ALLMULTI ? RxMulticast : 0)
953ca7a8e85SJeff Kirsher 					 | (dev->flags & IFF_PROMISC ? RxProm : 0),
954ca7a8e85SJeff Kirsher 					 ioaddr + EL3_CMD);
955ca7a8e85SJeff Kirsher 				outw(RxEnable, ioaddr + EL3_CMD); /* Re-enable the receiver. */
956ca7a8e85SJeff Kirsher 				outw(AckIntr | AdapterFailure, ioaddr + EL3_CMD);
957ca7a8e85SJeff Kirsher 			}
958ca7a8e85SJeff Kirsher 		}
959ca7a8e85SJeff Kirsher 
960ca7a8e85SJeff Kirsher 		if (--i < 0) {
961ca7a8e85SJeff Kirsher 			pr_err("%s: Infinite loop in interrupt, status %4.4x.\n",
962ca7a8e85SJeff Kirsher 				   dev->name, status);
963ca7a8e85SJeff Kirsher 			/* Clear all interrupts. */
964ca7a8e85SJeff Kirsher 			outw(AckIntr | 0xFF, ioaddr + EL3_CMD);
965ca7a8e85SJeff Kirsher 			break;
966ca7a8e85SJeff Kirsher 		}
967ca7a8e85SJeff Kirsher 		/* Acknowledge the IRQ. */
968ca7a8e85SJeff Kirsher 		outw(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD); /* Ack IRQ */
969ca7a8e85SJeff Kirsher 	}
970ca7a8e85SJeff Kirsher 
971ca7a8e85SJeff Kirsher 	if (el3_debug > 4) {
972ca7a8e85SJeff Kirsher 		pr_debug("%s: exiting interrupt, status %4.4x.\n", dev->name,
973ca7a8e85SJeff Kirsher 			   inw(ioaddr + EL3_STATUS));
974ca7a8e85SJeff Kirsher 	}
975ca7a8e85SJeff Kirsher 	spin_unlock(&lp->lock);
976ca7a8e85SJeff Kirsher 	return IRQ_HANDLED;
977ca7a8e85SJeff Kirsher }
978ca7a8e85SJeff Kirsher 
979ca7a8e85SJeff Kirsher 
980ca7a8e85SJeff Kirsher #ifdef CONFIG_NET_POLL_CONTROLLER
981ca7a8e85SJeff Kirsher /*
982ca7a8e85SJeff Kirsher  * Polling receive - used by netconsole and other diagnostic tools
983ca7a8e85SJeff Kirsher  * to allow network i/o with interrupts disabled.
984ca7a8e85SJeff Kirsher  */
985ca7a8e85SJeff Kirsher static void el3_poll_controller(struct net_device *dev)
986ca7a8e85SJeff Kirsher {
987ca7a8e85SJeff Kirsher 	disable_irq(dev->irq);
988ca7a8e85SJeff Kirsher 	el3_interrupt(dev->irq, dev);
989ca7a8e85SJeff Kirsher 	enable_irq(dev->irq);
990ca7a8e85SJeff Kirsher }
991ca7a8e85SJeff Kirsher #endif
992ca7a8e85SJeff Kirsher 
993ca7a8e85SJeff Kirsher static struct net_device_stats *
994ca7a8e85SJeff Kirsher el3_get_stats(struct net_device *dev)
995ca7a8e85SJeff Kirsher {
996ca7a8e85SJeff Kirsher 	struct el3_private *lp = netdev_priv(dev);
997ca7a8e85SJeff Kirsher 	unsigned long flags;
998ca7a8e85SJeff Kirsher 
999ca7a8e85SJeff Kirsher 	/*
1000ca7a8e85SJeff Kirsher 	 *	This is fast enough not to bother with disable IRQ
1001ca7a8e85SJeff Kirsher 	 *	stuff.
1002ca7a8e85SJeff Kirsher 	 */
1003ca7a8e85SJeff Kirsher 
1004ca7a8e85SJeff Kirsher 	spin_lock_irqsave(&lp->lock, flags);
1005ca7a8e85SJeff Kirsher 	update_stats(dev);
1006ca7a8e85SJeff Kirsher 	spin_unlock_irqrestore(&lp->lock, flags);
1007ca7a8e85SJeff Kirsher 	return &dev->stats;
1008ca7a8e85SJeff Kirsher }
1009ca7a8e85SJeff Kirsher 
1010ca7a8e85SJeff Kirsher /*  Update statistics.  We change to register window 6, so this should be run
1011ca7a8e85SJeff Kirsher 	single-threaded if the device is active. This is expected to be a rare
1012ca7a8e85SJeff Kirsher 	operation, and it's simpler for the rest of the driver to assume that
1013ca7a8e85SJeff Kirsher 	window 1 is always valid rather than use a special window-state variable.
1014ca7a8e85SJeff Kirsher 	*/
1015ca7a8e85SJeff Kirsher static void update_stats(struct net_device *dev)
1016ca7a8e85SJeff Kirsher {
1017ca7a8e85SJeff Kirsher 	int ioaddr = dev->base_addr;
1018ca7a8e85SJeff Kirsher 
1019ca7a8e85SJeff Kirsher 	if (el3_debug > 5)
1020ca7a8e85SJeff Kirsher 		pr_debug("   Updating the statistics.\n");
1021ca7a8e85SJeff Kirsher 	/* Turn off statistics updates while reading. */
1022ca7a8e85SJeff Kirsher 	outw(StatsDisable, ioaddr + EL3_CMD);
1023ca7a8e85SJeff Kirsher 	/* Switch to the stats window, and read everything. */
1024ca7a8e85SJeff Kirsher 	EL3WINDOW(6);
1025ca7a8e85SJeff Kirsher 	dev->stats.tx_carrier_errors 	+= inb(ioaddr + 0);
1026ca7a8e85SJeff Kirsher 	dev->stats.tx_heartbeat_errors	+= inb(ioaddr + 1);
1027ca7a8e85SJeff Kirsher 	/* Multiple collisions. */	   inb(ioaddr + 2);
1028ca7a8e85SJeff Kirsher 	dev->stats.collisions		+= inb(ioaddr + 3);
1029ca7a8e85SJeff Kirsher 	dev->stats.tx_window_errors	+= inb(ioaddr + 4);
1030ca7a8e85SJeff Kirsher 	dev->stats.rx_fifo_errors	+= inb(ioaddr + 5);
1031ca7a8e85SJeff Kirsher 	dev->stats.tx_packets		+= inb(ioaddr + 6);
1032ca7a8e85SJeff Kirsher 	/* Rx packets	*/		   inb(ioaddr + 7);
1033ca7a8e85SJeff Kirsher 	/* Tx deferrals */		   inb(ioaddr + 8);
1034ca7a8e85SJeff Kirsher 	inw(ioaddr + 10);	/* Total Rx and Tx octets. */
1035ca7a8e85SJeff Kirsher 	inw(ioaddr + 12);
1036ca7a8e85SJeff Kirsher 
1037ca7a8e85SJeff Kirsher 	/* Back to window 1, and turn statistics back on. */
1038ca7a8e85SJeff Kirsher 	EL3WINDOW(1);
1039ca7a8e85SJeff Kirsher 	outw(StatsEnable, ioaddr + EL3_CMD);
1040ca7a8e85SJeff Kirsher }
1041ca7a8e85SJeff Kirsher 
1042ca7a8e85SJeff Kirsher static int
1043ca7a8e85SJeff Kirsher el3_rx(struct net_device *dev)
1044ca7a8e85SJeff Kirsher {
1045ca7a8e85SJeff Kirsher 	int ioaddr = dev->base_addr;
1046ca7a8e85SJeff Kirsher 	short rx_status;
1047ca7a8e85SJeff Kirsher 
1048ca7a8e85SJeff Kirsher 	if (el3_debug > 5)
1049ca7a8e85SJeff Kirsher 		pr_debug("   In rx_packet(), status %4.4x, rx_status %4.4x.\n",
1050ca7a8e85SJeff Kirsher 			   inw(ioaddr+EL3_STATUS), inw(ioaddr+RX_STATUS));
1051ca7a8e85SJeff Kirsher 	while ((rx_status = inw(ioaddr + RX_STATUS)) > 0) {
1052ca7a8e85SJeff Kirsher 		if (rx_status & 0x4000) { /* Error, update stats. */
1053ca7a8e85SJeff Kirsher 			short error = rx_status & 0x3800;
1054ca7a8e85SJeff Kirsher 
1055ca7a8e85SJeff Kirsher 			outw(RxDiscard, ioaddr + EL3_CMD);
1056ca7a8e85SJeff Kirsher 			dev->stats.rx_errors++;
1057ca7a8e85SJeff Kirsher 			switch (error) {
1058ca7a8e85SJeff Kirsher 			case 0x0000:		dev->stats.rx_over_errors++; break;
1059ca7a8e85SJeff Kirsher 			case 0x0800:		dev->stats.rx_length_errors++; break;
1060ca7a8e85SJeff Kirsher 			case 0x1000:		dev->stats.rx_frame_errors++; break;
1061ca7a8e85SJeff Kirsher 			case 0x1800:		dev->stats.rx_length_errors++; break;
1062ca7a8e85SJeff Kirsher 			case 0x2000:		dev->stats.rx_frame_errors++; break;
1063ca7a8e85SJeff Kirsher 			case 0x2800:		dev->stats.rx_crc_errors++; break;
1064ca7a8e85SJeff Kirsher 			}
1065ca7a8e85SJeff Kirsher 		} else {
1066ca7a8e85SJeff Kirsher 			short pkt_len = rx_status & 0x7ff;
1067ca7a8e85SJeff Kirsher 			struct sk_buff *skb;
1068ca7a8e85SJeff Kirsher 
1069ca7a8e85SJeff Kirsher 			skb = dev_alloc_skb(pkt_len+5);
1070ca7a8e85SJeff Kirsher 			if (el3_debug > 4)
1071ca7a8e85SJeff Kirsher 				pr_debug("Receiving packet size %d status %4.4x.\n",
1072ca7a8e85SJeff Kirsher 					   pkt_len, rx_status);
1073ca7a8e85SJeff Kirsher 			if (skb != NULL) {
1074ca7a8e85SJeff Kirsher 				skb_reserve(skb, 2);     /* Align IP on 16 byte */
1075ca7a8e85SJeff Kirsher 
1076ca7a8e85SJeff Kirsher 				/* 'skb->data' points to the start of sk_buff data area. */
1077ca7a8e85SJeff Kirsher 				insl(ioaddr + RX_FIFO, skb_put(skb,pkt_len),
1078ca7a8e85SJeff Kirsher 					 (pkt_len + 3) >> 2);
1079ca7a8e85SJeff Kirsher 
1080ca7a8e85SJeff Kirsher 				outw(RxDiscard, ioaddr + EL3_CMD); /* Pop top Rx packet. */
1081ca7a8e85SJeff Kirsher 				skb->protocol = eth_type_trans(skb,dev);
1082ca7a8e85SJeff Kirsher 				netif_rx(skb);
1083ca7a8e85SJeff Kirsher 				dev->stats.rx_bytes += pkt_len;
1084ca7a8e85SJeff Kirsher 				dev->stats.rx_packets++;
1085ca7a8e85SJeff Kirsher 				continue;
1086ca7a8e85SJeff Kirsher 			}
1087ca7a8e85SJeff Kirsher 			outw(RxDiscard, ioaddr + EL3_CMD);
1088ca7a8e85SJeff Kirsher 			dev->stats.rx_dropped++;
1089ca7a8e85SJeff Kirsher 			if (el3_debug)
1090ca7a8e85SJeff Kirsher 				pr_debug("%s: Couldn't allocate a sk_buff of size %d.\n",
1091ca7a8e85SJeff Kirsher 					   dev->name, pkt_len);
1092ca7a8e85SJeff Kirsher 		}
1093ca7a8e85SJeff Kirsher 		inw(ioaddr + EL3_STATUS); 				/* Delay. */
1094ca7a8e85SJeff Kirsher 		while (inw(ioaddr + EL3_STATUS) & 0x1000)
1095ca7a8e85SJeff Kirsher 			pr_debug("	Waiting for 3c509 to discard packet, status %x.\n",
1096ca7a8e85SJeff Kirsher 				   inw(ioaddr + EL3_STATUS) );
1097ca7a8e85SJeff Kirsher 	}
1098ca7a8e85SJeff Kirsher 
1099ca7a8e85SJeff Kirsher 	return 0;
1100ca7a8e85SJeff Kirsher }
1101ca7a8e85SJeff Kirsher 
1102ca7a8e85SJeff Kirsher /*
1103ca7a8e85SJeff Kirsher  *     Set or clear the multicast filter for this adaptor.
1104ca7a8e85SJeff Kirsher  */
1105ca7a8e85SJeff Kirsher static void
1106ca7a8e85SJeff Kirsher set_multicast_list(struct net_device *dev)
1107ca7a8e85SJeff Kirsher {
1108ca7a8e85SJeff Kirsher 	unsigned long flags;
1109ca7a8e85SJeff Kirsher 	struct el3_private *lp = netdev_priv(dev);
1110ca7a8e85SJeff Kirsher 	int ioaddr = dev->base_addr;
1111ca7a8e85SJeff Kirsher 	int mc_count = netdev_mc_count(dev);
1112ca7a8e85SJeff Kirsher 
1113ca7a8e85SJeff Kirsher 	if (el3_debug > 1) {
1114ca7a8e85SJeff Kirsher 		static int old;
1115ca7a8e85SJeff Kirsher 		if (old != mc_count) {
1116ca7a8e85SJeff Kirsher 			old = mc_count;
1117ca7a8e85SJeff Kirsher 			pr_debug("%s: Setting Rx mode to %d addresses.\n",
1118ca7a8e85SJeff Kirsher 				 dev->name, mc_count);
1119ca7a8e85SJeff Kirsher 		}
1120ca7a8e85SJeff Kirsher 	}
1121ca7a8e85SJeff Kirsher 	spin_lock_irqsave(&lp->lock, flags);
1122ca7a8e85SJeff Kirsher 	if (dev->flags&IFF_PROMISC) {
1123ca7a8e85SJeff Kirsher 		outw(SetRxFilter | RxStation | RxMulticast | RxBroadcast | RxProm,
1124ca7a8e85SJeff Kirsher 			 ioaddr + EL3_CMD);
1125ca7a8e85SJeff Kirsher 	}
1126ca7a8e85SJeff Kirsher 	else if (mc_count || (dev->flags&IFF_ALLMULTI)) {
1127ca7a8e85SJeff Kirsher 		outw(SetRxFilter | RxStation | RxMulticast | RxBroadcast, ioaddr + EL3_CMD);
1128ca7a8e85SJeff Kirsher 	}
1129ca7a8e85SJeff Kirsher 	else
1130ca7a8e85SJeff Kirsher 		outw(SetRxFilter | RxStation | RxBroadcast, ioaddr + EL3_CMD);
1131ca7a8e85SJeff Kirsher 	spin_unlock_irqrestore(&lp->lock, flags);
1132ca7a8e85SJeff Kirsher }
1133ca7a8e85SJeff Kirsher 
1134ca7a8e85SJeff Kirsher static int
1135ca7a8e85SJeff Kirsher el3_close(struct net_device *dev)
1136ca7a8e85SJeff Kirsher {
1137ca7a8e85SJeff Kirsher 	int ioaddr = dev->base_addr;
1138ca7a8e85SJeff Kirsher 	struct el3_private *lp = netdev_priv(dev);
1139ca7a8e85SJeff Kirsher 
1140ca7a8e85SJeff Kirsher 	if (el3_debug > 2)
1141ca7a8e85SJeff Kirsher 		pr_debug("%s: Shutting down ethercard.\n", dev->name);
1142ca7a8e85SJeff Kirsher 
1143ca7a8e85SJeff Kirsher 	el3_down(dev);
1144ca7a8e85SJeff Kirsher 
1145ca7a8e85SJeff Kirsher 	free_irq(dev->irq, dev);
1146ca7a8e85SJeff Kirsher 	/* Switching back to window 0 disables the IRQ. */
1147ca7a8e85SJeff Kirsher 	EL3WINDOW(0);
1148ca7a8e85SJeff Kirsher 	if (lp->type != EL3_EISA) {
1149ca7a8e85SJeff Kirsher 		/* But we explicitly zero the IRQ line select anyway. Don't do
1150ca7a8e85SJeff Kirsher 		 * it on EISA cards, it prevents the module from getting an
1151ca7a8e85SJeff Kirsher 		 * IRQ after unload+reload... */
1152ca7a8e85SJeff Kirsher 		outw(0x0f00, ioaddr + WN0_IRQ);
1153ca7a8e85SJeff Kirsher 	}
1154ca7a8e85SJeff Kirsher 
1155ca7a8e85SJeff Kirsher 	return 0;
1156ca7a8e85SJeff Kirsher }
1157ca7a8e85SJeff Kirsher 
1158ca7a8e85SJeff Kirsher static int
1159ca7a8e85SJeff Kirsher el3_link_ok(struct net_device *dev)
1160ca7a8e85SJeff Kirsher {
1161ca7a8e85SJeff Kirsher 	int ioaddr = dev->base_addr;
1162ca7a8e85SJeff Kirsher 	u16 tmp;
1163ca7a8e85SJeff Kirsher 
1164ca7a8e85SJeff Kirsher 	EL3WINDOW(4);
1165ca7a8e85SJeff Kirsher 	tmp = inw(ioaddr + WN4_MEDIA);
1166ca7a8e85SJeff Kirsher 	EL3WINDOW(1);
1167ca7a8e85SJeff Kirsher 	return tmp & (1<<11);
1168ca7a8e85SJeff Kirsher }
1169ca7a8e85SJeff Kirsher 
1170ca7a8e85SJeff Kirsher static int
1171ca7a8e85SJeff Kirsher el3_netdev_get_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd)
1172ca7a8e85SJeff Kirsher {
1173ca7a8e85SJeff Kirsher 	u16 tmp;
1174ca7a8e85SJeff Kirsher 	int ioaddr = dev->base_addr;
1175ca7a8e85SJeff Kirsher 
1176ca7a8e85SJeff Kirsher 	EL3WINDOW(0);
1177ca7a8e85SJeff Kirsher 	/* obtain current transceiver via WN4_MEDIA? */
1178ca7a8e85SJeff Kirsher 	tmp = inw(ioaddr + WN0_ADDR_CONF);
1179ca7a8e85SJeff Kirsher 	ecmd->transceiver = XCVR_INTERNAL;
1180ca7a8e85SJeff Kirsher 	switch (tmp >> 14) {
1181ca7a8e85SJeff Kirsher 	case 0:
1182ca7a8e85SJeff Kirsher 		ecmd->port = PORT_TP;
1183ca7a8e85SJeff Kirsher 		break;
1184ca7a8e85SJeff Kirsher 	case 1:
1185ca7a8e85SJeff Kirsher 		ecmd->port = PORT_AUI;
1186ca7a8e85SJeff Kirsher 		ecmd->transceiver = XCVR_EXTERNAL;
1187ca7a8e85SJeff Kirsher 		break;
1188ca7a8e85SJeff Kirsher 	case 3:
1189ca7a8e85SJeff Kirsher 		ecmd->port = PORT_BNC;
1190ca7a8e85SJeff Kirsher 	default:
1191ca7a8e85SJeff Kirsher 		break;
1192ca7a8e85SJeff Kirsher 	}
1193ca7a8e85SJeff Kirsher 
1194ca7a8e85SJeff Kirsher 	ecmd->duplex = DUPLEX_HALF;
1195ca7a8e85SJeff Kirsher 	ecmd->supported = 0;
1196ca7a8e85SJeff Kirsher 	tmp = inw(ioaddr + WN0_CONF_CTRL);
1197ca7a8e85SJeff Kirsher 	if (tmp & (1<<13))
1198ca7a8e85SJeff Kirsher 		ecmd->supported |= SUPPORTED_AUI;
1199ca7a8e85SJeff Kirsher 	if (tmp & (1<<12))
1200ca7a8e85SJeff Kirsher 		ecmd->supported |= SUPPORTED_BNC;
1201ca7a8e85SJeff Kirsher 	if (tmp & (1<<9)) {
1202ca7a8e85SJeff Kirsher 		ecmd->supported |= SUPPORTED_TP | SUPPORTED_10baseT_Half |
1203ca7a8e85SJeff Kirsher 				SUPPORTED_10baseT_Full;	/* hmm... */
1204ca7a8e85SJeff Kirsher 		EL3WINDOW(4);
1205ca7a8e85SJeff Kirsher 		tmp = inw(ioaddr + WN4_NETDIAG);
1206ca7a8e85SJeff Kirsher 		if (tmp & FD_ENABLE)
1207ca7a8e85SJeff Kirsher 			ecmd->duplex = DUPLEX_FULL;
1208ca7a8e85SJeff Kirsher 	}
1209ca7a8e85SJeff Kirsher 
1210ca7a8e85SJeff Kirsher 	ethtool_cmd_speed_set(ecmd, SPEED_10);
1211ca7a8e85SJeff Kirsher 	EL3WINDOW(1);
1212ca7a8e85SJeff Kirsher 	return 0;
1213ca7a8e85SJeff Kirsher }
1214ca7a8e85SJeff Kirsher 
1215ca7a8e85SJeff Kirsher static int
1216ca7a8e85SJeff Kirsher el3_netdev_set_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd)
1217ca7a8e85SJeff Kirsher {
1218ca7a8e85SJeff Kirsher 	u16 tmp;
1219ca7a8e85SJeff Kirsher 	int ioaddr = dev->base_addr;
1220ca7a8e85SJeff Kirsher 
1221ca7a8e85SJeff Kirsher 	if (ecmd->speed != SPEED_10)
1222ca7a8e85SJeff Kirsher 		return -EINVAL;
1223ca7a8e85SJeff Kirsher 	if ((ecmd->duplex != DUPLEX_HALF) && (ecmd->duplex != DUPLEX_FULL))
1224ca7a8e85SJeff Kirsher 		return -EINVAL;
1225ca7a8e85SJeff Kirsher 	if ((ecmd->transceiver != XCVR_INTERNAL) && (ecmd->transceiver != XCVR_EXTERNAL))
1226ca7a8e85SJeff Kirsher 		return -EINVAL;
1227ca7a8e85SJeff Kirsher 
1228ca7a8e85SJeff Kirsher 	/* change XCVR type */
1229ca7a8e85SJeff Kirsher 	EL3WINDOW(0);
1230ca7a8e85SJeff Kirsher 	tmp = inw(ioaddr + WN0_ADDR_CONF);
1231ca7a8e85SJeff Kirsher 	switch (ecmd->port) {
1232ca7a8e85SJeff Kirsher 	case PORT_TP:
1233ca7a8e85SJeff Kirsher 		tmp &= ~(3<<14);
1234ca7a8e85SJeff Kirsher 		dev->if_port = 0;
1235ca7a8e85SJeff Kirsher 		break;
1236ca7a8e85SJeff Kirsher 	case PORT_AUI:
1237ca7a8e85SJeff Kirsher 		tmp |= (1<<14);
1238ca7a8e85SJeff Kirsher 		dev->if_port = 1;
1239ca7a8e85SJeff Kirsher 		break;
1240ca7a8e85SJeff Kirsher 	case PORT_BNC:
1241ca7a8e85SJeff Kirsher 		tmp |= (3<<14);
1242ca7a8e85SJeff Kirsher 		dev->if_port = 3;
1243ca7a8e85SJeff Kirsher 		break;
1244ca7a8e85SJeff Kirsher 	default:
1245ca7a8e85SJeff Kirsher 		return -EINVAL;
1246ca7a8e85SJeff Kirsher 	}
1247ca7a8e85SJeff Kirsher 
1248ca7a8e85SJeff Kirsher 	outw(tmp, ioaddr + WN0_ADDR_CONF);
1249ca7a8e85SJeff Kirsher 	if (dev->if_port == 3) {
1250ca7a8e85SJeff Kirsher 		/* fire up the DC-DC convertor if BNC gets enabled */
1251ca7a8e85SJeff Kirsher 		tmp = inw(ioaddr + WN0_ADDR_CONF);
1252ca7a8e85SJeff Kirsher 		if (tmp & (3 << 14)) {
1253ca7a8e85SJeff Kirsher 			outw(StartCoax, ioaddr + EL3_CMD);
1254ca7a8e85SJeff Kirsher 			udelay(800);
1255ca7a8e85SJeff Kirsher 		} else
1256ca7a8e85SJeff Kirsher 			return -EIO;
1257ca7a8e85SJeff Kirsher 	}
1258ca7a8e85SJeff Kirsher 
1259ca7a8e85SJeff Kirsher 	EL3WINDOW(4);
1260ca7a8e85SJeff Kirsher 	tmp = inw(ioaddr + WN4_NETDIAG);
1261ca7a8e85SJeff Kirsher 	if (ecmd->duplex == DUPLEX_FULL)
1262ca7a8e85SJeff Kirsher 		tmp |= FD_ENABLE;
1263ca7a8e85SJeff Kirsher 	else
1264ca7a8e85SJeff Kirsher 		tmp &= ~FD_ENABLE;
1265ca7a8e85SJeff Kirsher 	outw(tmp, ioaddr + WN4_NETDIAG);
1266ca7a8e85SJeff Kirsher 	EL3WINDOW(1);
1267ca7a8e85SJeff Kirsher 
1268ca7a8e85SJeff Kirsher 	return 0;
1269ca7a8e85SJeff Kirsher }
1270ca7a8e85SJeff Kirsher 
1271ca7a8e85SJeff Kirsher static void el3_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
1272ca7a8e85SJeff Kirsher {
1273ca7a8e85SJeff Kirsher 	strcpy(info->driver, DRV_NAME);
1274ca7a8e85SJeff Kirsher 	strcpy(info->version, DRV_VERSION);
1275ca7a8e85SJeff Kirsher }
1276ca7a8e85SJeff Kirsher 
1277ca7a8e85SJeff Kirsher static int el3_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
1278ca7a8e85SJeff Kirsher {
1279ca7a8e85SJeff Kirsher 	struct el3_private *lp = netdev_priv(dev);
1280ca7a8e85SJeff Kirsher 	int ret;
1281ca7a8e85SJeff Kirsher 
1282ca7a8e85SJeff Kirsher 	spin_lock_irq(&lp->lock);
1283ca7a8e85SJeff Kirsher 	ret = el3_netdev_get_ecmd(dev, ecmd);
1284ca7a8e85SJeff Kirsher 	spin_unlock_irq(&lp->lock);
1285ca7a8e85SJeff Kirsher 	return ret;
1286ca7a8e85SJeff Kirsher }
1287ca7a8e85SJeff Kirsher 
1288ca7a8e85SJeff Kirsher static int el3_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
1289ca7a8e85SJeff Kirsher {
1290ca7a8e85SJeff Kirsher 	struct el3_private *lp = netdev_priv(dev);
1291ca7a8e85SJeff Kirsher 	int ret;
1292ca7a8e85SJeff Kirsher 
1293ca7a8e85SJeff Kirsher 	spin_lock_irq(&lp->lock);
1294ca7a8e85SJeff Kirsher 	ret = el3_netdev_set_ecmd(dev, ecmd);
1295ca7a8e85SJeff Kirsher 	spin_unlock_irq(&lp->lock);
1296ca7a8e85SJeff Kirsher 	return ret;
1297ca7a8e85SJeff Kirsher }
1298ca7a8e85SJeff Kirsher 
1299ca7a8e85SJeff Kirsher static u32 el3_get_link(struct net_device *dev)
1300ca7a8e85SJeff Kirsher {
1301ca7a8e85SJeff Kirsher 	struct el3_private *lp = netdev_priv(dev);
1302ca7a8e85SJeff Kirsher 	u32 ret;
1303ca7a8e85SJeff Kirsher 
1304ca7a8e85SJeff Kirsher 	spin_lock_irq(&lp->lock);
1305ca7a8e85SJeff Kirsher 	ret = el3_link_ok(dev);
1306ca7a8e85SJeff Kirsher 	spin_unlock_irq(&lp->lock);
1307ca7a8e85SJeff Kirsher 	return ret;
1308ca7a8e85SJeff Kirsher }
1309ca7a8e85SJeff Kirsher 
1310ca7a8e85SJeff Kirsher static u32 el3_get_msglevel(struct net_device *dev)
1311ca7a8e85SJeff Kirsher {
1312ca7a8e85SJeff Kirsher 	return el3_debug;
1313ca7a8e85SJeff Kirsher }
1314ca7a8e85SJeff Kirsher 
1315ca7a8e85SJeff Kirsher static void el3_set_msglevel(struct net_device *dev, u32 v)
1316ca7a8e85SJeff Kirsher {
1317ca7a8e85SJeff Kirsher 	el3_debug = v;
1318ca7a8e85SJeff Kirsher }
1319ca7a8e85SJeff Kirsher 
1320ca7a8e85SJeff Kirsher static const struct ethtool_ops ethtool_ops = {
1321ca7a8e85SJeff Kirsher 	.get_drvinfo = el3_get_drvinfo,
1322ca7a8e85SJeff Kirsher 	.get_settings = el3_get_settings,
1323ca7a8e85SJeff Kirsher 	.set_settings = el3_set_settings,
1324ca7a8e85SJeff Kirsher 	.get_link = el3_get_link,
1325ca7a8e85SJeff Kirsher 	.get_msglevel = el3_get_msglevel,
1326ca7a8e85SJeff Kirsher 	.set_msglevel = el3_set_msglevel,
1327ca7a8e85SJeff Kirsher };
1328ca7a8e85SJeff Kirsher 
1329ca7a8e85SJeff Kirsher static void
1330ca7a8e85SJeff Kirsher el3_down(struct net_device *dev)
1331ca7a8e85SJeff Kirsher {
1332ca7a8e85SJeff Kirsher 	int ioaddr = dev->base_addr;
1333ca7a8e85SJeff Kirsher 
1334ca7a8e85SJeff Kirsher 	netif_stop_queue(dev);
1335ca7a8e85SJeff Kirsher 
1336ca7a8e85SJeff Kirsher 	/* Turn off statistics ASAP.  We update lp->stats below. */
1337ca7a8e85SJeff Kirsher 	outw(StatsDisable, ioaddr + EL3_CMD);
1338ca7a8e85SJeff Kirsher 
1339ca7a8e85SJeff Kirsher 	/* Disable the receiver and transmitter. */
1340ca7a8e85SJeff Kirsher 	outw(RxDisable, ioaddr + EL3_CMD);
1341ca7a8e85SJeff Kirsher 	outw(TxDisable, ioaddr + EL3_CMD);
1342ca7a8e85SJeff Kirsher 
1343ca7a8e85SJeff Kirsher 	if (dev->if_port == 3)
1344ca7a8e85SJeff Kirsher 		/* Turn off thinnet power.  Green! */
1345ca7a8e85SJeff Kirsher 		outw(StopCoax, ioaddr + EL3_CMD);
1346ca7a8e85SJeff Kirsher 	else if (dev->if_port == 0) {
1347ca7a8e85SJeff Kirsher 		/* Disable link beat and jabber, if_port may change here next open(). */
1348ca7a8e85SJeff Kirsher 		EL3WINDOW(4);
1349ca7a8e85SJeff Kirsher 		outw(inw(ioaddr + WN4_MEDIA) & ~MEDIA_TP, ioaddr + WN4_MEDIA);
1350ca7a8e85SJeff Kirsher 	}
1351ca7a8e85SJeff Kirsher 
1352ca7a8e85SJeff Kirsher 	outw(SetIntrEnb | 0x0000, ioaddr + EL3_CMD);
1353ca7a8e85SJeff Kirsher 
1354ca7a8e85SJeff Kirsher 	update_stats(dev);
1355ca7a8e85SJeff Kirsher }
1356ca7a8e85SJeff Kirsher 
1357ca7a8e85SJeff Kirsher static void
1358ca7a8e85SJeff Kirsher el3_up(struct net_device *dev)
1359ca7a8e85SJeff Kirsher {
1360ca7a8e85SJeff Kirsher 	int i, sw_info, net_diag;
1361ca7a8e85SJeff Kirsher 	int ioaddr = dev->base_addr;
1362ca7a8e85SJeff Kirsher 
1363ca7a8e85SJeff Kirsher 	/* Activating the board required and does no harm otherwise */
1364ca7a8e85SJeff Kirsher 	outw(0x0001, ioaddr + 4);
1365ca7a8e85SJeff Kirsher 
1366ca7a8e85SJeff Kirsher 	/* Set the IRQ line. */
1367ca7a8e85SJeff Kirsher 	outw((dev->irq << 12) | 0x0f00, ioaddr + WN0_IRQ);
1368ca7a8e85SJeff Kirsher 
1369ca7a8e85SJeff Kirsher 	/* Set the station address in window 2 each time opened. */
1370ca7a8e85SJeff Kirsher 	EL3WINDOW(2);
1371ca7a8e85SJeff Kirsher 
1372ca7a8e85SJeff Kirsher 	for (i = 0; i < 6; i++)
1373ca7a8e85SJeff Kirsher 		outb(dev->dev_addr[i], ioaddr + i);
1374ca7a8e85SJeff Kirsher 
1375ca7a8e85SJeff Kirsher 	if ((dev->if_port & 0x03) == 3) /* BNC interface */
1376ca7a8e85SJeff Kirsher 		/* Start the thinnet transceiver. We should really wait 50ms...*/
1377ca7a8e85SJeff Kirsher 		outw(StartCoax, ioaddr + EL3_CMD);
1378ca7a8e85SJeff Kirsher 	else if ((dev->if_port & 0x03) == 0) { /* 10baseT interface */
1379ca7a8e85SJeff Kirsher 		/* Combine secondary sw_info word (the adapter level) and primary
1380ca7a8e85SJeff Kirsher 			sw_info word (duplex setting plus other useless bits) */
1381ca7a8e85SJeff Kirsher 		EL3WINDOW(0);
1382ca7a8e85SJeff Kirsher 		sw_info = (read_eeprom(ioaddr, 0x14) & 0x400f) |
1383ca7a8e85SJeff Kirsher 			(read_eeprom(ioaddr, 0x0d) & 0xBff0);
1384ca7a8e85SJeff Kirsher 
1385ca7a8e85SJeff Kirsher 		EL3WINDOW(4);
1386ca7a8e85SJeff Kirsher 		net_diag = inw(ioaddr + WN4_NETDIAG);
1387ca7a8e85SJeff Kirsher 		net_diag = (net_diag | FD_ENABLE); /* temporarily assume full-duplex will be set */
1388ca7a8e85SJeff Kirsher 		pr_info("%s: ", dev->name);
1389ca7a8e85SJeff Kirsher 		switch (dev->if_port & 0x0c) {
1390ca7a8e85SJeff Kirsher 			case 12:
1391ca7a8e85SJeff Kirsher 				/* force full-duplex mode if 3c5x9b */
1392ca7a8e85SJeff Kirsher 				if (sw_info & 0x000f) {
1393ca7a8e85SJeff Kirsher 					pr_cont("Forcing 3c5x9b full-duplex mode");
1394ca7a8e85SJeff Kirsher 					break;
1395ca7a8e85SJeff Kirsher 				}
1396ca7a8e85SJeff Kirsher 			case 8:
1397ca7a8e85SJeff Kirsher 				/* set full-duplex mode based on eeprom config setting */
1398ca7a8e85SJeff Kirsher 				if ((sw_info & 0x000f) && (sw_info & 0x8000)) {
1399ca7a8e85SJeff Kirsher 					pr_cont("Setting 3c5x9b full-duplex mode (from EEPROM configuration bit)");
1400ca7a8e85SJeff Kirsher 					break;
1401ca7a8e85SJeff Kirsher 				}
1402ca7a8e85SJeff Kirsher 			default:
1403ca7a8e85SJeff Kirsher 				/* xcvr=(0 || 4) OR user has an old 3c5x9 non "B" model */
1404ca7a8e85SJeff Kirsher 				pr_cont("Setting 3c5x9/3c5x9B half-duplex mode");
1405ca7a8e85SJeff Kirsher 				net_diag = (net_diag & ~FD_ENABLE); /* disable full duplex */
1406ca7a8e85SJeff Kirsher 		}
1407ca7a8e85SJeff Kirsher 
1408ca7a8e85SJeff Kirsher 		outw(net_diag, ioaddr + WN4_NETDIAG);
1409ca7a8e85SJeff Kirsher 		pr_cont(" if_port: %d, sw_info: %4.4x\n", dev->if_port, sw_info);
1410ca7a8e85SJeff Kirsher 		if (el3_debug > 3)
1411ca7a8e85SJeff Kirsher 			pr_debug("%s: 3c5x9 net diag word is now: %4.4x.\n", dev->name, net_diag);
1412ca7a8e85SJeff Kirsher 		/* Enable link beat and jabber check. */
1413ca7a8e85SJeff Kirsher 		outw(inw(ioaddr + WN4_MEDIA) | MEDIA_TP, ioaddr + WN4_MEDIA);
1414ca7a8e85SJeff Kirsher 	}
1415ca7a8e85SJeff Kirsher 
1416ca7a8e85SJeff Kirsher 	/* Switch to the stats window, and clear all stats by reading. */
1417ca7a8e85SJeff Kirsher 	outw(StatsDisable, ioaddr + EL3_CMD);
1418ca7a8e85SJeff Kirsher 	EL3WINDOW(6);
1419ca7a8e85SJeff Kirsher 	for (i = 0; i < 9; i++)
1420ca7a8e85SJeff Kirsher 		inb(ioaddr + i);
1421ca7a8e85SJeff Kirsher 	inw(ioaddr + 10);
1422ca7a8e85SJeff Kirsher 	inw(ioaddr + 12);
1423ca7a8e85SJeff Kirsher 
1424ca7a8e85SJeff Kirsher 	/* Switch to register set 1 for normal use. */
1425ca7a8e85SJeff Kirsher 	EL3WINDOW(1);
1426ca7a8e85SJeff Kirsher 
1427ca7a8e85SJeff Kirsher 	/* Accept b-case and phys addr only. */
1428ca7a8e85SJeff Kirsher 	outw(SetRxFilter | RxStation | RxBroadcast, ioaddr + EL3_CMD);
1429ca7a8e85SJeff Kirsher 	outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */
1430ca7a8e85SJeff Kirsher 
1431ca7a8e85SJeff Kirsher 	outw(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */
1432ca7a8e85SJeff Kirsher 	outw(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */
1433ca7a8e85SJeff Kirsher 	/* Allow status bits to be seen. */
1434ca7a8e85SJeff Kirsher 	outw(SetStatusEnb | 0xff, ioaddr + EL3_CMD);
1435ca7a8e85SJeff Kirsher 	/* Ack all pending events, and set active indicator mask. */
1436ca7a8e85SJeff Kirsher 	outw(AckIntr | IntLatch | TxAvailable | RxEarly | IntReq,
1437ca7a8e85SJeff Kirsher 		 ioaddr + EL3_CMD);
1438ca7a8e85SJeff Kirsher 	outw(SetIntrEnb | IntLatch|TxAvailable|TxComplete|RxComplete|StatsFull,
1439ca7a8e85SJeff Kirsher 		 ioaddr + EL3_CMD);
1440ca7a8e85SJeff Kirsher 
1441ca7a8e85SJeff Kirsher 	netif_start_queue(dev);
1442ca7a8e85SJeff Kirsher }
1443ca7a8e85SJeff Kirsher 
1444ca7a8e85SJeff Kirsher /* Power Management support functions */
1445ca7a8e85SJeff Kirsher #ifdef CONFIG_PM
1446ca7a8e85SJeff Kirsher 
1447ca7a8e85SJeff Kirsher static int
1448ca7a8e85SJeff Kirsher el3_suspend(struct device *pdev, pm_message_t state)
1449ca7a8e85SJeff Kirsher {
1450ca7a8e85SJeff Kirsher 	unsigned long flags;
1451ca7a8e85SJeff Kirsher 	struct net_device *dev;
1452ca7a8e85SJeff Kirsher 	struct el3_private *lp;
1453ca7a8e85SJeff Kirsher 	int ioaddr;
1454ca7a8e85SJeff Kirsher 
1455ca7a8e85SJeff Kirsher 	dev = dev_get_drvdata(pdev);
1456ca7a8e85SJeff Kirsher 	lp = netdev_priv(dev);
1457ca7a8e85SJeff Kirsher 	ioaddr = dev->base_addr;
1458ca7a8e85SJeff Kirsher 
1459ca7a8e85SJeff Kirsher 	spin_lock_irqsave(&lp->lock, flags);
1460ca7a8e85SJeff Kirsher 
1461ca7a8e85SJeff Kirsher 	if (netif_running(dev))
1462ca7a8e85SJeff Kirsher 		netif_device_detach(dev);
1463ca7a8e85SJeff Kirsher 
1464ca7a8e85SJeff Kirsher 	el3_down(dev);
1465ca7a8e85SJeff Kirsher 	outw(PowerDown, ioaddr + EL3_CMD);
1466ca7a8e85SJeff Kirsher 
1467ca7a8e85SJeff Kirsher 	spin_unlock_irqrestore(&lp->lock, flags);
1468ca7a8e85SJeff Kirsher 	return 0;
1469ca7a8e85SJeff Kirsher }
1470ca7a8e85SJeff Kirsher 
1471ca7a8e85SJeff Kirsher static int
1472ca7a8e85SJeff Kirsher el3_resume(struct device *pdev)
1473ca7a8e85SJeff Kirsher {
1474ca7a8e85SJeff Kirsher 	unsigned long flags;
1475ca7a8e85SJeff Kirsher 	struct net_device *dev;
1476ca7a8e85SJeff Kirsher 	struct el3_private *lp;
1477ca7a8e85SJeff Kirsher 	int ioaddr;
1478ca7a8e85SJeff Kirsher 
1479ca7a8e85SJeff Kirsher 	dev = dev_get_drvdata(pdev);
1480ca7a8e85SJeff Kirsher 	lp = netdev_priv(dev);
1481ca7a8e85SJeff Kirsher 	ioaddr = dev->base_addr;
1482ca7a8e85SJeff Kirsher 
1483ca7a8e85SJeff Kirsher 	spin_lock_irqsave(&lp->lock, flags);
1484ca7a8e85SJeff Kirsher 
1485ca7a8e85SJeff Kirsher 	outw(PowerUp, ioaddr + EL3_CMD);
1486ca7a8e85SJeff Kirsher 	EL3WINDOW(0);
1487ca7a8e85SJeff Kirsher 	el3_up(dev);
1488ca7a8e85SJeff Kirsher 
1489ca7a8e85SJeff Kirsher 	if (netif_running(dev))
1490ca7a8e85SJeff Kirsher 		netif_device_attach(dev);
1491ca7a8e85SJeff Kirsher 
1492ca7a8e85SJeff Kirsher 	spin_unlock_irqrestore(&lp->lock, flags);
1493ca7a8e85SJeff Kirsher 	return 0;
1494ca7a8e85SJeff Kirsher }
1495ca7a8e85SJeff Kirsher 
1496ca7a8e85SJeff Kirsher #endif /* CONFIG_PM */
1497ca7a8e85SJeff Kirsher 
1498ca7a8e85SJeff Kirsher module_param(debug,int, 0);
1499ca7a8e85SJeff Kirsher module_param_array(irq, int, NULL, 0);
1500ca7a8e85SJeff Kirsher module_param(max_interrupt_work, int, 0);
1501ca7a8e85SJeff Kirsher MODULE_PARM_DESC(debug, "debug level (0-6)");
1502ca7a8e85SJeff Kirsher MODULE_PARM_DESC(irq, "IRQ number(s) (assigned)");
1503ca7a8e85SJeff Kirsher MODULE_PARM_DESC(max_interrupt_work, "maximum events handled per interrupt");
1504ca7a8e85SJeff Kirsher #ifdef CONFIG_PNP
1505ca7a8e85SJeff Kirsher module_param(nopnp, int, 0);
1506ca7a8e85SJeff Kirsher MODULE_PARM_DESC(nopnp, "disable ISA PnP support (0-1)");
1507ca7a8e85SJeff Kirsher #endif	/* CONFIG_PNP */
1508ca7a8e85SJeff Kirsher MODULE_DESCRIPTION("3Com Etherlink III (3c509, 3c509B, 3c529, 3c579) ethernet driver");
1509ca7a8e85SJeff Kirsher MODULE_LICENSE("GPL");
1510ca7a8e85SJeff Kirsher 
1511ca7a8e85SJeff Kirsher static int __init el3_init_module(void)
1512ca7a8e85SJeff Kirsher {
1513ca7a8e85SJeff Kirsher 	int ret = 0;
1514ca7a8e85SJeff Kirsher 
1515ca7a8e85SJeff Kirsher 	if (debug >= 0)
1516ca7a8e85SJeff Kirsher 		el3_debug = debug;
1517ca7a8e85SJeff Kirsher 
1518ca7a8e85SJeff Kirsher #ifdef CONFIG_PNP
1519ca7a8e85SJeff Kirsher 	if (!nopnp) {
1520ca7a8e85SJeff Kirsher 		ret = pnp_register_driver(&el3_pnp_driver);
1521ca7a8e85SJeff Kirsher 		if (!ret)
1522ca7a8e85SJeff Kirsher 			pnp_registered = 1;
1523ca7a8e85SJeff Kirsher 	}
1524ca7a8e85SJeff Kirsher #endif
1525ca7a8e85SJeff Kirsher 	/* Select an open I/O location at 0x1*0 to do ISA contention select. */
1526ca7a8e85SJeff Kirsher 	/* Start with 0x110 to avoid some sound cards.*/
1527ca7a8e85SJeff Kirsher 	for (id_port = 0x110 ; id_port < 0x200; id_port += 0x10) {
1528ca7a8e85SJeff Kirsher 		if (!request_region(id_port, 1, "3c509-control"))
1529ca7a8e85SJeff Kirsher 			continue;
1530ca7a8e85SJeff Kirsher 		outb(0x00, id_port);
1531ca7a8e85SJeff Kirsher 		outb(0xff, id_port);
1532ca7a8e85SJeff Kirsher 		if (inb(id_port) & 0x01)
1533ca7a8e85SJeff Kirsher 			break;
1534ca7a8e85SJeff Kirsher 		else
1535ca7a8e85SJeff Kirsher 			release_region(id_port, 1);
1536ca7a8e85SJeff Kirsher 	}
1537ca7a8e85SJeff Kirsher 	if (id_port >= 0x200) {
1538ca7a8e85SJeff Kirsher 		id_port = 0;
1539ca7a8e85SJeff Kirsher 		pr_err("No I/O port available for 3c509 activation.\n");
1540ca7a8e85SJeff Kirsher 	} else {
1541ca7a8e85SJeff Kirsher 		ret = isa_register_driver(&el3_isa_driver, EL3_MAX_CARDS);
1542ca7a8e85SJeff Kirsher 		if (!ret)
1543ca7a8e85SJeff Kirsher 			isa_registered = 1;
1544ca7a8e85SJeff Kirsher 	}
1545ca7a8e85SJeff Kirsher #ifdef CONFIG_EISA
1546ca7a8e85SJeff Kirsher 	ret = eisa_driver_register(&el3_eisa_driver);
1547ca7a8e85SJeff Kirsher 	if (!ret)
1548ca7a8e85SJeff Kirsher 		eisa_registered = 1;
1549ca7a8e85SJeff Kirsher #endif
1550ca7a8e85SJeff Kirsher #ifdef CONFIG_MCA
1551ca7a8e85SJeff Kirsher 	ret = mca_register_driver(&el3_mca_driver);
1552ca7a8e85SJeff Kirsher 	if (!ret)
1553ca7a8e85SJeff Kirsher 		mca_registered = 1;
1554ca7a8e85SJeff Kirsher #endif
1555ca7a8e85SJeff Kirsher 
1556ca7a8e85SJeff Kirsher #ifdef CONFIG_PNP
1557ca7a8e85SJeff Kirsher 	if (pnp_registered)
1558ca7a8e85SJeff Kirsher 		ret = 0;
1559ca7a8e85SJeff Kirsher #endif
1560ca7a8e85SJeff Kirsher 	if (isa_registered)
1561ca7a8e85SJeff Kirsher 		ret = 0;
1562ca7a8e85SJeff Kirsher #ifdef CONFIG_EISA
1563ca7a8e85SJeff Kirsher 	if (eisa_registered)
1564ca7a8e85SJeff Kirsher 		ret = 0;
1565ca7a8e85SJeff Kirsher #endif
1566ca7a8e85SJeff Kirsher #ifdef CONFIG_MCA
1567ca7a8e85SJeff Kirsher 	if (mca_registered)
1568ca7a8e85SJeff Kirsher 		ret = 0;
1569ca7a8e85SJeff Kirsher #endif
1570ca7a8e85SJeff Kirsher 	return ret;
1571ca7a8e85SJeff Kirsher }
1572ca7a8e85SJeff Kirsher 
1573ca7a8e85SJeff Kirsher static void __exit el3_cleanup_module(void)
1574ca7a8e85SJeff Kirsher {
1575ca7a8e85SJeff Kirsher #ifdef CONFIG_PNP
1576ca7a8e85SJeff Kirsher 	if (pnp_registered)
1577ca7a8e85SJeff Kirsher 		pnp_unregister_driver(&el3_pnp_driver);
1578ca7a8e85SJeff Kirsher #endif
1579ca7a8e85SJeff Kirsher 	if (isa_registered)
1580ca7a8e85SJeff Kirsher 		isa_unregister_driver(&el3_isa_driver);
1581ca7a8e85SJeff Kirsher 	if (id_port)
1582ca7a8e85SJeff Kirsher 		release_region(id_port, 1);
1583ca7a8e85SJeff Kirsher #ifdef CONFIG_EISA
1584ca7a8e85SJeff Kirsher 	if (eisa_registered)
1585ca7a8e85SJeff Kirsher 		eisa_driver_unregister(&el3_eisa_driver);
1586ca7a8e85SJeff Kirsher #endif
1587ca7a8e85SJeff Kirsher #ifdef CONFIG_MCA
1588ca7a8e85SJeff Kirsher 	if (mca_registered)
1589ca7a8e85SJeff Kirsher 		mca_unregister_driver(&el3_mca_driver);
1590ca7a8e85SJeff Kirsher #endif
1591ca7a8e85SJeff Kirsher }
1592ca7a8e85SJeff Kirsher 
1593ca7a8e85SJeff Kirsher module_init (el3_init_module);
1594ca7a8e85SJeff Kirsher module_exit (el3_cleanup_module);
1595