blob: adb4bf5eb4b4166dcdaa6c7883ef01fd3deb2afe [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/* 3c509.c: A 3c509 EtherLink3 ethernet driver for linux. */
2/*
3 Written 1993-2000 by Donald Becker.
4
5 Copyright 1994-2000 by Donald Becker.
6 Copyright 1993 United States Government as represented by the
7 Director, National Security Agency. This software may be used and
8 distributed according to the terms of the GNU General Public License,
9 incorporated herein by reference.
10
11 This driver is for the 3Com EtherLinkIII series.
12
13 The author may be reached as becker@scyld.com, or C/O
14 Scyld Computing Corporation
15 410 Severn Ave., Suite 210
16 Annapolis MD 21403
17
18 Known limitations:
19 Because of the way 3c509 ISA detection works it's difficult to predict
20 a priori which of several ISA-mode cards will be detected first.
21
22 This driver does not use predictive interrupt mode, resulting in higher
23 packet latency but lower overhead. If interrupts are disabled for an
24 unusually long time it could also result in missed packets, but in
25 practice this rarely happens.
26
27
28 FIXES:
29 Alan Cox: Removed the 'Unexpected interrupt' bug.
30 Michael Meskes: Upgraded to Donald Becker's version 1.07.
Jeff Garzik6aa20a22006-09-13 13:24:59 -040031 Alan Cox: Increased the eeprom delay. Regardless of
Linus Torvalds1da177e2005-04-16 15:20:36 -070032 what the docs say some people definitely
33 get problems with lower (but in card spec)
34 delays
35 v1.10 4/21/97 Fixed module code so that multiple cards may be detected,
36 other cleanups. -djb
37 Andrea Arcangeli: Upgraded to Donald Becker's version 1.12.
38 Rick Payne: Fixed SMP race condition
39 v1.13 9/8/97 Made 'max_interrupt_work' an insmod-settable variable -djb
40 v1.14 10/15/97 Avoided waiting..discard message for fast machines -djb
41 v1.15 1/31/98 Faster recovery for Tx errors. -djb
42 v1.16 2/3/98 Different ID port handling to avoid sound cards. -djb
Francois Camie1f8e872008-10-15 22:01:59 -070043 v1.18 12Mar2001 Andrew Morton
Linus Torvalds1da177e2005-04-16 15:20:36 -070044 - Avoid bogus detect of 3c590's (Andrzej Krzysztofowicz)
45 - Reviewed against 1.18 from scyld.com
46 v1.18a 17Nov2001 Jeff Garzik <jgarzik@pobox.com>
47 - ethtool support
48 v1.18b 1Mar2002 Zwane Mwaikambo <zwane@commfireservices.com>
49 - Power Management support
50 v1.18c 1Mar2002 David Ruggiero <jdr@farfalle.com>
51 - Full duplex support
52 v1.19 16Oct2002 Zwane Mwaikambo <zwane@linuxpower.ca>
53 - Additional ethtool features
54 v1.19a 28Oct2002 Davud Ruggiero <jdr@farfalle.com>
55 - Increase *read_eeprom udelay to workaround oops with 2 cards.
56 v1.19b 08Nov2002 Marc Zyngier <maz@wild-wind.fr.eu.org>
Ondrej Zaryac4bed12008-03-28 14:41:23 -070057 - Introduce driver model for EISA cards.
58 v1.20 04Feb2008 Ondrej Zary <linux@rainbow-software.org>
59 - convert to isa_driver and pnp_driver and some cleanups
Linus Torvalds1da177e2005-04-16 15:20:36 -070060*/
61
62#define DRV_NAME "3c509"
Ondrej Zaryac4bed12008-03-28 14:41:23 -070063#define DRV_VERSION "1.20"
64#define DRV_RELDATE "04Feb2008"
Linus Torvalds1da177e2005-04-16 15:20:36 -070065
66/* A few values that may be tweaked. */
67
68/* Time in jiffies before concluding the transmitter is hung. */
69#define TX_TIMEOUT (400*HZ/1000)
Linus Torvalds1da177e2005-04-16 15:20:36 -070070
Linus Torvalds1da177e2005-04-16 15:20:36 -070071#include <linux/module.h>
Ondrej Zaryac4bed12008-03-28 14:41:23 -070072#include <linux/isa.h>
73#include <linux/pnp.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070074#include <linux/string.h>
75#include <linux/interrupt.h>
76#include <linux/errno.h>
77#include <linux/in.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070078#include <linux/ioport.h>
79#include <linux/init.h>
80#include <linux/netdevice.h>
81#include <linux/etherdevice.h>
82#include <linux/pm.h>
83#include <linux/skbuff.h>
84#include <linux/delay.h> /* for udelay() */
85#include <linux/spinlock.h>
86#include <linux/ethtool.h>
87#include <linux/device.h>
88#include <linux/eisa.h>
89#include <linux/bitops.h>
90
91#include <asm/uaccess.h>
92#include <asm/io.h>
93#include <asm/irq.h>
94
Bill Pemberton2791cf72012-12-03 09:22:50 -050095static char version[] = DRV_NAME ".c:" DRV_VERSION " " DRV_RELDATE " becker@scyld.com\n";
Linus Torvalds1da177e2005-04-16 15:20:36 -070096
97#ifdef EL3_DEBUG
98static int el3_debug = EL3_DEBUG;
99#else
100static int el3_debug = 2;
101#endif
102
103/* Used to do a global count of all the cards in the system. Must be
Paul Gortmakera5e371f2012-05-16 19:48:42 -0400104 * a global variable so that the eisa probe routines can increment
Linus Torvalds1da177e2005-04-16 15:20:36 -0700105 * it */
106static int el3_cards = 0;
Ondrej Zaryac4bed12008-03-28 14:41:23 -0700107#define EL3_MAX_CARDS 8
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108
109/* To minimize the size of the driver source I only define operating
110 constants if they are used several times. You'll need the manual
111 anyway if you want to understand driver details. */
112/* Offsets from base I/O address. */
113#define EL3_DATA 0x00
114#define EL3_CMD 0x0e
115#define EL3_STATUS 0x0e
Ondrej Zaryac4bed12008-03-28 14:41:23 -0700116#define EEPROM_READ 0x80
Linus Torvalds1da177e2005-04-16 15:20:36 -0700117
118#define EL3_IO_EXTENT 16
119
120#define EL3WINDOW(win_num) outw(SelectWindow + (win_num), ioaddr + EL3_CMD)
121
122
123/* The top five bits written to EL3_CMD are a command, the lower
124 11 bits are the parameter, if applicable. */
125enum c509cmd {
126 TotalReset = 0<<11, SelectWindow = 1<<11, StartCoax = 2<<11,
127 RxDisable = 3<<11, RxEnable = 4<<11, RxReset = 5<<11, RxDiscard = 8<<11,
128 TxEnable = 9<<11, TxDisable = 10<<11, TxReset = 11<<11,
129 FakeIntr = 12<<11, AckIntr = 13<<11, SetIntrEnb = 14<<11,
130 SetStatusEnb = 15<<11, SetRxFilter = 16<<11, SetRxThreshold = 17<<11,
131 SetTxThreshold = 18<<11, SetTxStart = 19<<11, StatsEnable = 21<<11,
132 StatsDisable = 22<<11, StopCoax = 23<<11, PowerUp = 27<<11,
133 PowerDown = 28<<11, PowerAuto = 29<<11};
134
135enum c509status {
136 IntLatch = 0x0001, AdapterFailure = 0x0002, TxComplete = 0x0004,
137 TxAvailable = 0x0008, RxComplete = 0x0010, RxEarly = 0x0020,
138 IntReq = 0x0040, StatsFull = 0x0080, CmdBusy = 0x1000, };
139
140/* The SetRxFilter command accepts the following classes: */
141enum RxFilter {
142 RxStation = 1, RxMulticast = 2, RxBroadcast = 4, RxProm = 8 };
143
144/* Register window 1 offsets, the window used in normal operation. */
145#define TX_FIFO 0x00
146#define RX_FIFO 0x00
147#define RX_STATUS 0x08
148#define TX_STATUS 0x0B
149#define TX_FREE 0x0C /* Remaining free bytes in Tx buffer. */
150
151#define WN0_CONF_CTRL 0x04 /* Window 0: Configuration control register */
152#define WN0_ADDR_CONF 0x06 /* Window 0: Address configuration register */
153#define WN0_IRQ 0x08 /* Window 0: Set IRQ line in bits 12-15. */
154#define WN4_MEDIA 0x0A /* Window 4: Various transcvr/media bits. */
155#define MEDIA_TP 0x00C0 /* Enable link beat and jabber for 10baseT. */
156#define WN4_NETDIAG 0x06 /* Window 4: Net diagnostic */
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400157#define FD_ENABLE 0x8000 /* Enable full-duplex ("external loopback") */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700158
159/*
160 * Must be a power of two (we use a binary and in the
161 * circular queue)
162 */
163#define SKB_QUEUE_SIZE 64
164
Paul Gortmakera5e371f2012-05-16 19:48:42 -0400165enum el3_cardtype { EL3_ISA, EL3_PNP, EL3_EISA };
Ondrej Zaryac4bed12008-03-28 14:41:23 -0700166
Linus Torvalds1da177e2005-04-16 15:20:36 -0700167struct el3_private {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700168 spinlock_t lock;
169 /* skb send-queue */
170 int head, size;
171 struct sk_buff *queue[SKB_QUEUE_SIZE];
Ondrej Zaryac4bed12008-03-28 14:41:23 -0700172 enum el3_cardtype type;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700173};
Ondrej Zaryac4bed12008-03-28 14:41:23 -0700174static int id_port;
175static int current_tag;
176static struct net_device *el3_devs[EL3_MAX_CARDS];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700177
Ondrej Zaryac4bed12008-03-28 14:41:23 -0700178/* Parameters that may be passed into the module. */
179static int debug = -1;
180static int irq[] = {-1, -1, -1, -1, -1, -1, -1, -1};
181/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
182static int max_interrupt_work = 10;
183#ifdef CONFIG_PNP
184static int nopnp;
185#endif
186
Bill Pemberton2791cf72012-12-03 09:22:50 -0500187static int el3_common_init(struct net_device *dev);
Ondrej Zaryac4bed12008-03-28 14:41:23 -0700188static void el3_common_remove(struct net_device *dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189static ushort id_read_eeprom(int index);
190static ushort read_eeprom(int ioaddr, int index);
191static int el3_open(struct net_device *dev);
Stephen Hemminger27a1de92009-08-31 19:50:54 +0000192static netdev_tx_t el3_start_xmit(struct sk_buff *skb, struct net_device *dev);
David Howells7d12e782006-10-05 14:55:46 +0100193static irqreturn_t el3_interrupt(int irq, void *dev_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700194static void update_stats(struct net_device *dev);
195static struct net_device_stats *el3_get_stats(struct net_device *dev);
196static int el3_rx(struct net_device *dev);
197static int el3_close(struct net_device *dev);
198static void set_multicast_list(struct net_device *dev);
199static void el3_tx_timeout (struct net_device *dev);
200static void el3_down(struct net_device *dev);
201static void el3_up(struct net_device *dev);
Jeff Garzik7282d492006-09-13 14:30:00 -0400202static const struct ethtool_ops ethtool_ops;
Ondrej Zaryac4bed12008-03-28 14:41:23 -0700203#ifdef CONFIG_PM
Pekka Enberg60a89ff2006-03-08 00:06:28 -0800204static int el3_suspend(struct device *, pm_message_t);
205static int el3_resume(struct device *);
206#else
207#define el3_suspend NULL
208#define el3_resume NULL
Linus Torvalds1da177e2005-04-16 15:20:36 -0700209#endif
Pekka Enberg60a89ff2006-03-08 00:06:28 -0800210
211
Linus Torvalds1da177e2005-04-16 15:20:36 -0700212/* generic device remove for all device types */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700213static int el3_device_remove (struct device *device);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700214#ifdef CONFIG_NET_POLL_CONTROLLER
215static void el3_poll_controller(struct net_device *dev);
216#endif
217
Ondrej Zaryac4bed12008-03-28 14:41:23 -0700218/* Return 0 on success, 1 on error, 2 when found already detected PnP card */
219static int el3_isa_id_sequence(__be16 *phys_addr)
220{
221 short lrs_state = 0xff;
222 int i;
223
224 /* ISA boards are detected by sending the ID sequence to the
225 ID_PORT. We find cards past the first by setting the 'current_tag'
226 on cards as they are found. Cards with their tag set will not
227 respond to subsequent ID sequences. */
228
229 outb(0x00, id_port);
230 outb(0x00, id_port);
231 for (i = 0; i < 255; i++) {
232 outb(lrs_state, id_port);
233 lrs_state <<= 1;
234 lrs_state = lrs_state & 0x100 ? lrs_state ^ 0xcf : lrs_state;
235 }
236 /* For the first probe, clear all board's tag registers. */
237 if (current_tag == 0)
238 outb(0xd0, id_port);
239 else /* Otherwise kill off already-found boards. */
240 outb(0xd8, id_port);
241 if (id_read_eeprom(7) != 0x6d50)
242 return 1;
243 /* Read in EEPROM data, which does contention-select.
244 Only the lowest address board will stay "on-line".
245 3Com got the byte order backwards. */
246 for (i = 0; i < 3; i++)
247 phys_addr[i] = htons(id_read_eeprom(i));
248#ifdef CONFIG_PNP
249 if (!nopnp) {
250 /* The ISA PnP 3c509 cards respond to the ID sequence too.
251 This check is needed in order not to register them twice. */
252 for (i = 0; i < el3_cards; i++) {
253 struct el3_private *lp = netdev_priv(el3_devs[i]);
Joe Perches8e95a202009-12-03 07:58:21 +0000254 if (lp->type == EL3_PNP &&
255 !memcmp(phys_addr, el3_devs[i]->dev_addr,
256 ETH_ALEN)) {
Ondrej Zaryac4bed12008-03-28 14:41:23 -0700257 if (el3_debug > 3)
Alexander Beregalov646cdb32009-05-26 12:35:25 +0000258 pr_debug("3c509 with address %02x %02x %02x %02x %02x %02x was found by ISAPnP\n",
Ondrej Zaryac4bed12008-03-28 14:41:23 -0700259 phys_addr[0] & 0xff, phys_addr[0] >> 8,
260 phys_addr[1] & 0xff, phys_addr[1] >> 8,
261 phys_addr[2] & 0xff, phys_addr[2] >> 8);
262 /* Set the adaptor tag so that the next card can be found. */
263 outb(0xd0 + ++current_tag, id_port);
264 return 2;
265 }
266 }
267 }
268#endif /* CONFIG_PNP */
269 return 0;
270
271}
272
Greg Kroah-Hartman1dd06ae2012-12-06 14:30:56 +0000273static void el3_dev_fill(struct net_device *dev, __be16 *phys_addr, int ioaddr,
274 int irq, int if_port, enum el3_cardtype type)
Ondrej Zaryac4bed12008-03-28 14:41:23 -0700275{
276 struct el3_private *lp = netdev_priv(dev);
277
278 memcpy(dev->dev_addr, phys_addr, ETH_ALEN);
279 dev->base_addr = ioaddr;
280 dev->irq = irq;
281 dev->if_port = if_port;
282 lp->type = type;
283}
284
Greg Kroah-Hartman1dd06ae2012-12-06 14:30:56 +0000285static int el3_isa_match(struct device *pdev, unsigned int ndev)
Ondrej Zaryac4bed12008-03-28 14:41:23 -0700286{
287 struct net_device *dev;
288 int ioaddr, isa_irq, if_port, err;
289 unsigned int iobase;
290 __be16 phys_addr[3];
291
292 while ((err = el3_isa_id_sequence(phys_addr)) == 2)
293 ; /* Skip to next card when PnP card found */
294 if (err == 1)
295 return 0;
296
297 iobase = id_read_eeprom(8);
298 if_port = iobase >> 14;
299 ioaddr = 0x200 + ((iobase & 0x1f) << 4);
300 if (irq[el3_cards] > 1 && irq[el3_cards] < 16)
301 isa_irq = irq[el3_cards];
302 else
303 isa_irq = id_read_eeprom(9) >> 12;
304
305 dev = alloc_etherdev(sizeof(struct el3_private));
306 if (!dev)
307 return -ENOMEM;
308
Matthew Whitehead3b549122013-04-29 17:46:53 -0400309 SET_NETDEV_DEV(dev, pdev);
Ondrej Zaryac4bed12008-03-28 14:41:23 -0700310 netdev_boot_setup_check(dev);
311
312 if (!request_region(ioaddr, EL3_IO_EXTENT, "3c509-isa")) {
313 free_netdev(dev);
314 return 0;
315 }
316
317 /* Set the adaptor tag so that the next card can be found. */
318 outb(0xd0 + ++current_tag, id_port);
319
320 /* Activate the adaptor at the EEPROM location. */
321 outb((ioaddr >> 4) | 0xe0, id_port);
322
323 EL3WINDOW(0);
324 if (inw(ioaddr) != 0x6d50) {
325 free_netdev(dev);
326 return 0;
327 }
328
329 /* Free the interrupt so that some other card can use it. */
330 outw(0x0f00, ioaddr + WN0_IRQ);
331
332 el3_dev_fill(dev, phys_addr, ioaddr, isa_irq, if_port, EL3_ISA);
333 dev_set_drvdata(pdev, dev);
334 if (el3_common_init(dev)) {
335 free_netdev(dev);
336 return 0;
337 }
338
339 el3_devs[el3_cards++] = dev;
340 return 1;
341}
342
Bill Pemberton2791cf72012-12-03 09:22:50 -0500343static int el3_isa_remove(struct device *pdev,
Ondrej Zaryac4bed12008-03-28 14:41:23 -0700344 unsigned int ndev)
345{
346 el3_device_remove(pdev);
347 dev_set_drvdata(pdev, NULL);
348 return 0;
349}
350
351#ifdef CONFIG_PM
352static int el3_isa_suspend(struct device *dev, unsigned int n,
353 pm_message_t state)
354{
355 current_tag = 0;
356 return el3_suspend(dev, state);
357}
358
359static int el3_isa_resume(struct device *dev, unsigned int n)
360{
361 struct net_device *ndev = dev_get_drvdata(dev);
362 int ioaddr = ndev->base_addr, err;
363 __be16 phys_addr[3];
364
365 while ((err = el3_isa_id_sequence(phys_addr)) == 2)
366 ; /* Skip to next card when PnP card found */
367 if (err == 1)
368 return 0;
369 /* Set the adaptor tag so that the next card can be found. */
370 outb(0xd0 + ++current_tag, id_port);
371 /* Enable the card */
372 outb((ioaddr >> 4) | 0xe0, id_port);
373 EL3WINDOW(0);
374 if (inw(ioaddr) != 0x6d50)
375 return 1;
376 /* Free the interrupt so that some other card can use it. */
377 outw(0x0f00, ioaddr + WN0_IRQ);
378 return el3_resume(dev);
379}
380#endif
381
382static struct isa_driver el3_isa_driver = {
383 .match = el3_isa_match,
Bill Pemberton2791cf72012-12-03 09:22:50 -0500384 .remove = el3_isa_remove,
Ondrej Zaryac4bed12008-03-28 14:41:23 -0700385#ifdef CONFIG_PM
386 .suspend = el3_isa_suspend,
387 .resume = el3_isa_resume,
388#endif
389 .driver = {
390 .name = "3c509"
391 },
392};
393static int isa_registered;
394
395#ifdef CONFIG_PNP
David S. Miller948252c2011-05-31 19:27:48 -0700396static struct pnp_device_id el3_pnp_ids[] = {
Ondrej Zaryac4bed12008-03-28 14:41:23 -0700397 { .id = "TCM5090" }, /* 3Com Etherlink III (TP) */
398 { .id = "TCM5091" }, /* 3Com Etherlink III */
399 { .id = "TCM5094" }, /* 3Com Etherlink III (combo) */
400 { .id = "TCM5095" }, /* 3Com Etherlink III (TPO) */
401 { .id = "TCM5098" }, /* 3Com Etherlink III (TPC) */
402 { .id = "PNP80f7" }, /* 3Com Etherlink III compatible */
403 { .id = "PNP80f8" }, /* 3Com Etherlink III compatible */
404 { .id = "" }
405};
406MODULE_DEVICE_TABLE(pnp, el3_pnp_ids);
407
Greg Kroah-Hartman1dd06ae2012-12-06 14:30:56 +0000408static int el3_pnp_probe(struct pnp_dev *pdev, const struct pnp_device_id *id)
Ondrej Zaryac4bed12008-03-28 14:41:23 -0700409{
410 short i;
411 int ioaddr, irq, if_port;
Al Viro4ec7ffa2008-05-21 06:32:11 +0100412 __be16 phys_addr[3];
Ondrej Zaryac4bed12008-03-28 14:41:23 -0700413 struct net_device *dev = NULL;
414 int err;
415
416 ioaddr = pnp_port_start(pdev, 0);
417 if (!request_region(ioaddr, EL3_IO_EXTENT, "3c509-pnp"))
418 return -EBUSY;
419 irq = pnp_irq(pdev, 0);
420 EL3WINDOW(0);
421 for (i = 0; i < 3; i++)
422 phys_addr[i] = htons(read_eeprom(ioaddr, i));
423 if_port = read_eeprom(ioaddr, 8) >> 14;
424 dev = alloc_etherdev(sizeof(struct el3_private));
425 if (!dev) {
426 release_region(ioaddr, EL3_IO_EXTENT);
427 return -ENOMEM;
428 }
429 SET_NETDEV_DEV(dev, &pdev->dev);
430 netdev_boot_setup_check(dev);
431
432 el3_dev_fill(dev, phys_addr, ioaddr, irq, if_port, EL3_PNP);
433 pnp_set_drvdata(pdev, dev);
434 err = el3_common_init(dev);
435
436 if (err) {
437 pnp_set_drvdata(pdev, NULL);
438 free_netdev(dev);
439 return err;
440 }
441
442 el3_devs[el3_cards++] = dev;
443 return 0;
444}
445
Bill Pemberton2791cf72012-12-03 09:22:50 -0500446static void el3_pnp_remove(struct pnp_dev *pdev)
Ondrej Zaryac4bed12008-03-28 14:41:23 -0700447{
448 el3_common_remove(pnp_get_drvdata(pdev));
449 pnp_set_drvdata(pdev, NULL);
450}
451
452#ifdef CONFIG_PM
453static int el3_pnp_suspend(struct pnp_dev *pdev, pm_message_t state)
454{
455 return el3_suspend(&pdev->dev, state);
456}
457
458static int el3_pnp_resume(struct pnp_dev *pdev)
459{
460 return el3_resume(&pdev->dev);
461}
462#endif
463
464static struct pnp_driver el3_pnp_driver = {
465 .name = "3c509",
466 .id_table = el3_pnp_ids,
467 .probe = el3_pnp_probe,
Bill Pemberton2791cf72012-12-03 09:22:50 -0500468 .remove = el3_pnp_remove,
Ondrej Zaryac4bed12008-03-28 14:41:23 -0700469#ifdef CONFIG_PM
470 .suspend = el3_pnp_suspend,
471 .resume = el3_pnp_resume,
472#endif
473};
474static int pnp_registered;
475#endif /* CONFIG_PNP */
476
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477#ifdef CONFIG_EISA
David S. Miller948252c2011-05-31 19:27:48 -0700478static struct eisa_device_id el3_eisa_ids[] = {
Maciej W. Rozyckicf9f6e22009-06-01 03:12:04 -0700479 { "TCM5090" },
480 { "TCM5091" },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481 { "TCM5092" },
482 { "TCM5093" },
Maciej W. Rozyckicf9f6e22009-06-01 03:12:04 -0700483 { "TCM5094" },
Adrian Bunkf04e3f02005-05-16 21:13:03 +0200484 { "TCM5095" },
Maciej W. Rozyckicf9f6e22009-06-01 03:12:04 -0700485 { "TCM5098" },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700486 { "" }
487};
Michael Tokarev07563c72006-09-27 01:50:56 -0700488MODULE_DEVICE_TABLE(eisa, el3_eisa_ids);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700489
490static int el3_eisa_probe (struct device *device);
491
492static struct eisa_driver el3_eisa_driver = {
493 .id_table = el3_eisa_ids,
494 .driver = {
Ondrej Zaryac4bed12008-03-28 14:41:23 -0700495 .name = "3c579",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496 .probe = el3_eisa_probe,
Bill Pemberton2791cf72012-12-03 09:22:50 -0500497 .remove = el3_device_remove,
Pekka Enberg60a89ff2006-03-08 00:06:28 -0800498 .suspend = el3_suspend,
499 .resume = el3_resume,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500 }
501};
Ondrej Zaryac4bed12008-03-28 14:41:23 -0700502static int eisa_registered;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503#endif
504
Stephen Hemminger3186ae82009-01-09 13:01:14 +0000505static const struct net_device_ops netdev_ops = {
506 .ndo_open = el3_open,
507 .ndo_stop = el3_close,
508 .ndo_start_xmit = el3_start_xmit,
509 .ndo_get_stats = el3_get_stats,
Jiri Pirkoafc4b132011-08-16 06:29:01 +0000510 .ndo_set_rx_mode = set_multicast_list,
Stephen Hemminger3186ae82009-01-09 13:01:14 +0000511 .ndo_tx_timeout = el3_tx_timeout,
512 .ndo_change_mtu = eth_change_mtu,
513 .ndo_set_mac_address = eth_mac_addr,
514 .ndo_validate_addr = eth_validate_addr,
515#ifdef CONFIG_NET_POLL_CONTROLLER
516 .ndo_poll_controller = el3_poll_controller,
517#endif
518};
519
Bill Pemberton2791cf72012-12-03 09:22:50 -0500520static int el3_common_init(struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700521{
522 struct el3_private *lp = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700523 int err;
Joe Perches0795af52007-10-03 17:59:30 -0700524 const char *if_names[] = {"10baseT", "AUI", "undefined", "BNC"};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525
526 spin_lock_init(&lp->lock);
527
528 if (dev->mem_start & 0x05) { /* xcvr codes 1/3/4/12 */
529 dev->if_port = (dev->mem_start & 0x0f);
530 } else { /* xcvr codes 0/8 */
531 /* use eeprom value, but save user's full-duplex selection */
532 dev->if_port |= (dev->mem_start & 0x08);
533 }
534
535 /* The EL3-specific entries in the device structure. */
Stephen Hemminger3186ae82009-01-09 13:01:14 +0000536 dev->netdev_ops = &netdev_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700537 dev->watchdog_timeo = TX_TIMEOUT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538 SET_ETHTOOL_OPS(dev, &ethtool_ops);
539
540 err = register_netdev(dev);
541 if (err) {
Alexander Beregalov646cdb32009-05-26 12:35:25 +0000542 pr_err("Failed to register 3c5x9 at %#3.3lx, IRQ %d.\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543 dev->base_addr, dev->irq);
544 release_region(dev->base_addr, EL3_IO_EXTENT);
545 return err;
546 }
547
Alexander Beregalov646cdb32009-05-26 12:35:25 +0000548 pr_info("%s: 3c5x9 found at %#3.3lx, %s port, address %pM, IRQ %d.\n",
Joe Perches0795af52007-10-03 17:59:30 -0700549 dev->name, dev->base_addr, if_names[(dev->if_port & 0x03)],
Johannes Berge1749612008-10-27 15:59:26 -0700550 dev->dev_addr, dev->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700551
552 if (el3_debug > 0)
Alexander Beregalov646cdb32009-05-26 12:35:25 +0000553 pr_info("%s", version);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700554 return 0;
555
556}
557
558static void el3_common_remove (struct net_device *dev)
559{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560 unregister_netdev (dev);
561 release_region(dev->base_addr, EL3_IO_EXTENT);
562 free_netdev (dev);
563}
564
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565#ifdef CONFIG_EISA
David S. Miller948252c2011-05-31 19:27:48 -0700566static int __init el3_eisa_probe (struct device *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700567{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700568 short i;
569 int ioaddr, irq, if_port;
Al Viro4ec7ffa2008-05-21 06:32:11 +0100570 __be16 phys_addr[3];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700571 struct net_device *dev = NULL;
572 struct eisa_device *edev;
573 int err;
574
575 /* Yeepee, The driver framework is calling us ! */
576 edev = to_eisa_device (device);
577 ioaddr = edev->base_addr;
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400578
Ondrej Zaryac4bed12008-03-28 14:41:23 -0700579 if (!request_region(ioaddr, EL3_IO_EXTENT, "3c579-eisa"))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700580 return -EBUSY;
581
582 /* Change the register set to the configuration window 0. */
583 outw(SelectWindow | 0, ioaddr + 0xC80 + EL3_CMD);
584
585 irq = inw(ioaddr + WN0_IRQ) >> 12;
586 if_port = inw(ioaddr + 6)>>14;
587 for (i = 0; i < 3; i++)
588 phys_addr[i] = htons(read_eeprom(ioaddr, i));
589
590 /* Restore the "Product ID" to the EEPROM read register. */
591 read_eeprom(ioaddr, 3);
592
593 dev = alloc_etherdev(sizeof (struct el3_private));
594 if (dev == NULL) {
595 release_region(ioaddr, EL3_IO_EXTENT);
596 return -ENOMEM;
597 }
598
Matthew Whitehead3b549122013-04-29 17:46:53 -0400599 SET_NETDEV_DEV(dev, device);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600 netdev_boot_setup_check(dev);
601
Ondrej Zaryac4bed12008-03-28 14:41:23 -0700602 el3_dev_fill(dev, phys_addr, ioaddr, irq, if_port, EL3_EISA);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700603 eisa_set_drvdata (edev, dev);
604 err = el3_common_init(dev);
605
606 if (err) {
607 eisa_set_drvdata (edev, NULL);
608 free_netdev(dev);
609 return err;
610 }
611
Ondrej Zaryac4bed12008-03-28 14:41:23 -0700612 el3_devs[el3_cards++] = dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613 return 0;
614}
615#endif
616
Linus Torvalds1da177e2005-04-16 15:20:36 -0700617/* This remove works for all device types.
618 *
Greg Kroah-Hartman1aec5bd2009-04-30 12:19:31 +0000619 * The net dev must be stored in the driver data field */
Bill Pemberton2791cf72012-12-03 09:22:50 -0500620static int el3_device_remove(struct device *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700621{
622 struct net_device *dev;
623
Greg Kroah-Hartman1aec5bd2009-04-30 12:19:31 +0000624 dev = dev_get_drvdata(device);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700625
626 el3_common_remove (dev);
627 return 0;
628}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700629
630/* Read a word from the EEPROM using the regular EEPROM access register.
631 Assume that we are in register window zero.
632 */
633static ushort read_eeprom(int ioaddr, int index)
634{
635 outw(EEPROM_READ + index, ioaddr + 10);
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400636 /* Pause for at least 162 us. for the read to take place.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700637 Some chips seem to require much longer */
638 mdelay(2);
639 return inw(ioaddr + 12);
640}
641
642/* Read a word from the EEPROM when in the ISA ID probe state. */
Ondrej Zaryac4bed12008-03-28 14:41:23 -0700643static ushort id_read_eeprom(int index)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644{
645 int bit, word = 0;
646
647 /* Issue read command, and pause for at least 162 us. for it to complete.
648 Assume extra-fast 16Mhz bus. */
649 outb(EEPROM_READ + index, id_port);
650
651 /* Pause for at least 162 us. for the read to take place. */
652 /* Some chips seem to require much longer */
653 mdelay(4);
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400654
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655 for (bit = 15; bit >= 0; bit--)
656 word = (word << 1) + (inb(id_port) & 0x01);
657
658 if (el3_debug > 3)
Alexander Beregalov646cdb32009-05-26 12:35:25 +0000659 pr_debug(" 3c509 EEPROM word %d %#4.4x.\n", index, word);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700660
661 return word;
662}
663
664
665static int
666el3_open(struct net_device *dev)
667{
668 int ioaddr = dev->base_addr;
669 int i;
670
671 outw(TxReset, ioaddr + EL3_CMD);
672 outw(RxReset, ioaddr + EL3_CMD);
673 outw(SetStatusEnb | 0x00, ioaddr + EL3_CMD);
674
Joe Perchesa0607fd2009-11-18 23:29:17 -0800675 i = request_irq(dev->irq, el3_interrupt, 0, dev->name, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700676 if (i)
677 return i;
678
679 EL3WINDOW(0);
680 if (el3_debug > 3)
Alexander Beregalov646cdb32009-05-26 12:35:25 +0000681 pr_debug("%s: Opening, IRQ %d status@%x %4.4x.\n", dev->name,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700682 dev->irq, ioaddr + EL3_STATUS, inw(ioaddr + EL3_STATUS));
683
684 el3_up(dev);
685
686 if (el3_debug > 3)
Alexander Beregalov646cdb32009-05-26 12:35:25 +0000687 pr_debug("%s: Opened 3c509 IRQ %d status %4.4x.\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700688 dev->name, dev->irq, inw(ioaddr + EL3_STATUS));
689
690 return 0;
691}
692
693static void
694el3_tx_timeout (struct net_device *dev)
695{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696 int ioaddr = dev->base_addr;
697
698 /* Transmitter timeout, serious problems. */
Alexander Beregalov646cdb32009-05-26 12:35:25 +0000699 pr_warning("%s: transmit timed out, Tx_status %2.2x status %4.4x Tx FIFO room %d.\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700700 dev->name, inb(ioaddr + TX_STATUS), inw(ioaddr + EL3_STATUS),
701 inw(ioaddr + TX_FREE));
Paulius Zaleckas815f8802008-04-29 02:45:43 +0300702 dev->stats.tx_errors++;
Eric Dumazet1ae5dc32010-05-10 05:01:31 -0700703 dev->trans_start = jiffies; /* prevent tx timeout */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700704 /* Issue TX_RESET and TX_START commands. */
705 outw(TxReset, ioaddr + EL3_CMD);
706 outw(TxEnable, ioaddr + EL3_CMD);
707 netif_wake_queue(dev);
708}
709
710
Stephen Hemminger27a1de92009-08-31 19:50:54 +0000711static netdev_tx_t
Linus Torvalds1da177e2005-04-16 15:20:36 -0700712el3_start_xmit(struct sk_buff *skb, struct net_device *dev)
713{
714 struct el3_private *lp = netdev_priv(dev);
715 int ioaddr = dev->base_addr;
716 unsigned long flags;
717
718 netif_stop_queue (dev);
719
Paulius Zaleckas815f8802008-04-29 02:45:43 +0300720 dev->stats.tx_bytes += skb->len;
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400721
Linus Torvalds1da177e2005-04-16 15:20:36 -0700722 if (el3_debug > 4) {
Alexander Beregalov646cdb32009-05-26 12:35:25 +0000723 pr_debug("%s: el3_start_xmit(length = %u) called, status %4.4x.\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700724 dev->name, skb->len, inw(ioaddr + EL3_STATUS));
725 }
726#if 0
727#ifndef final_version
728 { /* Error-checking code, delete someday. */
729 ushort status = inw(ioaddr + EL3_STATUS);
Joe Perches8e95a202009-12-03 07:58:21 +0000730 if (status & 0x0001 && /* IRQ line active, missed one. */
731 inw(ioaddr + EL3_STATUS) & 1) { /* Make sure. */
Alexander Beregalov646cdb32009-05-26 12:35:25 +0000732 pr_debug("%s: Missed interrupt, status then %04x now %04x"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700733 " Tx %2.2x Rx %4.4x.\n", dev->name, status,
734 inw(ioaddr + EL3_STATUS), inb(ioaddr + TX_STATUS),
735 inw(ioaddr + RX_STATUS));
736 /* Fake interrupt trigger by masking, acknowledge interrupts. */
737 outw(SetStatusEnb | 0x00, ioaddr + EL3_CMD);
738 outw(AckIntr | IntLatch | TxAvailable | RxEarly | IntReq,
739 ioaddr + EL3_CMD);
740 outw(SetStatusEnb | 0xff, ioaddr + EL3_CMD);
741 }
742 }
743#endif
744#endif
745 /*
746 * We lock the driver against other processors. Note
747 * we don't need to lock versus the IRQ as we suspended
748 * that. This means that we lose the ability to take
749 * an RX during a TX upload. That sucks a bit with SMP
750 * on an original 3c509 (2K buffer)
751 *
752 * Using disable_irq stops us crapping on other
753 * time sensitive devices.
754 */
755
756 spin_lock_irqsave(&lp->lock, flags);
757
758 /* Put out the doubleword header... */
759 outw(skb->len, ioaddr + TX_FIFO);
760 outw(0x00, ioaddr + TX_FIFO);
761 /* ... and the packet rounded to a doubleword. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700762 outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700763
Linus Torvalds1da177e2005-04-16 15:20:36 -0700764 if (inw(ioaddr + TX_FREE) > 1536)
765 netif_start_queue(dev);
766 else
767 /* Interrupt us when the FIFO has room for max-sized packet. */
768 outw(SetTxThreshold + 1536, ioaddr + EL3_CMD);
769
770 spin_unlock_irqrestore(&lp->lock, flags);
771
772 dev_kfree_skb (skb);
773
774 /* Clear the Tx status stack. */
775 {
776 short tx_status;
777 int i = 4;
778
779 while (--i > 0 && (tx_status = inb(ioaddr + TX_STATUS)) > 0) {
Paulius Zaleckas815f8802008-04-29 02:45:43 +0300780 if (tx_status & 0x38) dev->stats.tx_aborted_errors++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700781 if (tx_status & 0x30) outw(TxReset, ioaddr + EL3_CMD);
782 if (tx_status & 0x3C) outw(TxEnable, ioaddr + EL3_CMD);
783 outb(0x00, ioaddr + TX_STATUS); /* Pop the status stack. */
784 }
785 }
Patrick McHardy6ed10652009-06-23 06:03:08 +0000786 return NETDEV_TX_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700787}
788
789/* The EL3 interrupt handler. */
790static irqreturn_t
David Howells7d12e782006-10-05 14:55:46 +0100791el3_interrupt(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792{
Jeff Garzikc31f28e2006-10-06 14:56:04 -0400793 struct net_device *dev = dev_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700794 struct el3_private *lp;
795 int ioaddr, status;
796 int i = max_interrupt_work;
797
Linus Torvalds1da177e2005-04-16 15:20:36 -0700798 lp = netdev_priv(dev);
799 spin_lock(&lp->lock);
800
801 ioaddr = dev->base_addr;
802
803 if (el3_debug > 4) {
804 status = inw(ioaddr + EL3_STATUS);
Alexander Beregalov646cdb32009-05-26 12:35:25 +0000805 pr_debug("%s: interrupt, status %4.4x.\n", dev->name, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700806 }
807
808 while ((status = inw(ioaddr + EL3_STATUS)) &
809 (IntLatch | RxComplete | StatsFull)) {
810
811 if (status & RxComplete)
812 el3_rx(dev);
813
814 if (status & TxAvailable) {
815 if (el3_debug > 5)
Alexander Beregalov646cdb32009-05-26 12:35:25 +0000816 pr_debug(" TX room bit was handled.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700817 /* There's room in the FIFO for a full-sized packet. */
818 outw(AckIntr | TxAvailable, ioaddr + EL3_CMD);
819 netif_wake_queue (dev);
820 }
821 if (status & (AdapterFailure | RxEarly | StatsFull | TxComplete)) {
822 /* Handle all uncommon interrupts. */
823 if (status & StatsFull) /* Empty statistics. */
824 update_stats(dev);
825 if (status & RxEarly) { /* Rx early is unused. */
826 el3_rx(dev);
827 outw(AckIntr | RxEarly, ioaddr + EL3_CMD);
828 }
829 if (status & TxComplete) { /* Really Tx error. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700830 short tx_status;
831 int i = 4;
832
833 while (--i>0 && (tx_status = inb(ioaddr + TX_STATUS)) > 0) {
Paulius Zaleckas815f8802008-04-29 02:45:43 +0300834 if (tx_status & 0x38) dev->stats.tx_aborted_errors++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700835 if (tx_status & 0x30) outw(TxReset, ioaddr + EL3_CMD);
836 if (tx_status & 0x3C) outw(TxEnable, ioaddr + EL3_CMD);
837 outb(0x00, ioaddr + TX_STATUS); /* Pop the status stack. */
838 }
839 }
840 if (status & AdapterFailure) {
841 /* Adapter failure requires Rx reset and reinit. */
842 outw(RxReset, ioaddr + EL3_CMD);
843 /* Set the Rx filter to the current state. */
844 outw(SetRxFilter | RxStation | RxBroadcast
845 | (dev->flags & IFF_ALLMULTI ? RxMulticast : 0)
846 | (dev->flags & IFF_PROMISC ? RxProm : 0),
847 ioaddr + EL3_CMD);
848 outw(RxEnable, ioaddr + EL3_CMD); /* Re-enable the receiver. */
849 outw(AckIntr | AdapterFailure, ioaddr + EL3_CMD);
850 }
851 }
852
853 if (--i < 0) {
Alexander Beregalov646cdb32009-05-26 12:35:25 +0000854 pr_err("%s: Infinite loop in interrupt, status %4.4x.\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700855 dev->name, status);
856 /* Clear all interrupts. */
857 outw(AckIntr | 0xFF, ioaddr + EL3_CMD);
858 break;
859 }
860 /* Acknowledge the IRQ. */
861 outw(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD); /* Ack IRQ */
862 }
863
864 if (el3_debug > 4) {
Alexander Beregalov646cdb32009-05-26 12:35:25 +0000865 pr_debug("%s: exiting interrupt, status %4.4x.\n", dev->name,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700866 inw(ioaddr + EL3_STATUS));
867 }
868 spin_unlock(&lp->lock);
869 return IRQ_HANDLED;
870}
871
872
873#ifdef CONFIG_NET_POLL_CONTROLLER
874/*
875 * Polling receive - used by netconsole and other diagnostic tools
876 * to allow network i/o with interrupts disabled.
877 */
878static void el3_poll_controller(struct net_device *dev)
879{
880 disable_irq(dev->irq);
David Howells7d12e782006-10-05 14:55:46 +0100881 el3_interrupt(dev->irq, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882 enable_irq(dev->irq);
883}
884#endif
885
886static struct net_device_stats *
887el3_get_stats(struct net_device *dev)
888{
889 struct el3_private *lp = netdev_priv(dev);
890 unsigned long flags;
891
892 /*
893 * This is fast enough not to bother with disable IRQ
894 * stuff.
895 */
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400896
Linus Torvalds1da177e2005-04-16 15:20:36 -0700897 spin_lock_irqsave(&lp->lock, flags);
898 update_stats(dev);
899 spin_unlock_irqrestore(&lp->lock, flags);
Paulius Zaleckas815f8802008-04-29 02:45:43 +0300900 return &dev->stats;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901}
902
903/* Update statistics. We change to register window 6, so this should be run
904 single-threaded if the device is active. This is expected to be a rare
905 operation, and it's simpler for the rest of the driver to assume that
906 window 1 is always valid rather than use a special window-state variable.
907 */
908static void update_stats(struct net_device *dev)
909{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700910 int ioaddr = dev->base_addr;
911
912 if (el3_debug > 5)
Alexander Beregalov646cdb32009-05-26 12:35:25 +0000913 pr_debug(" Updating the statistics.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700914 /* Turn off statistics updates while reading. */
915 outw(StatsDisable, ioaddr + EL3_CMD);
916 /* Switch to the stats window, and read everything. */
917 EL3WINDOW(6);
Paulius Zaleckas815f8802008-04-29 02:45:43 +0300918 dev->stats.tx_carrier_errors += inb(ioaddr + 0);
919 dev->stats.tx_heartbeat_errors += inb(ioaddr + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700920 /* Multiple collisions. */ inb(ioaddr + 2);
Paulius Zaleckas815f8802008-04-29 02:45:43 +0300921 dev->stats.collisions += inb(ioaddr + 3);
922 dev->stats.tx_window_errors += inb(ioaddr + 4);
923 dev->stats.rx_fifo_errors += inb(ioaddr + 5);
924 dev->stats.tx_packets += inb(ioaddr + 6);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700925 /* Rx packets */ inb(ioaddr + 7);
926 /* Tx deferrals */ inb(ioaddr + 8);
927 inw(ioaddr + 10); /* Total Rx and Tx octets. */
928 inw(ioaddr + 12);
929
930 /* Back to window 1, and turn statistics back on. */
931 EL3WINDOW(1);
932 outw(StatsEnable, ioaddr + EL3_CMD);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700933}
934
935static int
936el3_rx(struct net_device *dev)
937{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700938 int ioaddr = dev->base_addr;
939 short rx_status;
940
941 if (el3_debug > 5)
Alexander Beregalov646cdb32009-05-26 12:35:25 +0000942 pr_debug(" In rx_packet(), status %4.4x, rx_status %4.4x.\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700943 inw(ioaddr+EL3_STATUS), inw(ioaddr+RX_STATUS));
944 while ((rx_status = inw(ioaddr + RX_STATUS)) > 0) {
945 if (rx_status & 0x4000) { /* Error, update stats. */
946 short error = rx_status & 0x3800;
947
948 outw(RxDiscard, ioaddr + EL3_CMD);
Paulius Zaleckas815f8802008-04-29 02:45:43 +0300949 dev->stats.rx_errors++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700950 switch (error) {
Paulius Zaleckas815f8802008-04-29 02:45:43 +0300951 case 0x0000: dev->stats.rx_over_errors++; break;
952 case 0x0800: dev->stats.rx_length_errors++; break;
953 case 0x1000: dev->stats.rx_frame_errors++; break;
954 case 0x1800: dev->stats.rx_length_errors++; break;
955 case 0x2000: dev->stats.rx_frame_errors++; break;
956 case 0x2800: dev->stats.rx_crc_errors++; break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700957 }
958 } else {
959 short pkt_len = rx_status & 0x7ff;
960 struct sk_buff *skb;
961
Pradeep A Dalvi1d266432012-02-05 02:49:09 +0000962 skb = netdev_alloc_skb(dev, pkt_len + 5);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700963 if (el3_debug > 4)
Alexander Beregalov646cdb32009-05-26 12:35:25 +0000964 pr_debug("Receiving packet size %d status %4.4x.\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700965 pkt_len, rx_status);
966 if (skb != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700967 skb_reserve(skb, 2); /* Align IP on 16 byte */
968
969 /* 'skb->data' points to the start of sk_buff data area. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700970 insl(ioaddr + RX_FIFO, skb_put(skb,pkt_len),
971 (pkt_len + 3) >> 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700972
973 outw(RxDiscard, ioaddr + EL3_CMD); /* Pop top Rx packet. */
974 skb->protocol = eth_type_trans(skb,dev);
975 netif_rx(skb);
Wang Chenf7f312a2008-05-20 17:13:52 +0800976 dev->stats.rx_bytes += pkt_len;
Paulius Zaleckas815f8802008-04-29 02:45:43 +0300977 dev->stats.rx_packets++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700978 continue;
979 }
980 outw(RxDiscard, ioaddr + EL3_CMD);
Paulius Zaleckas815f8802008-04-29 02:45:43 +0300981 dev->stats.rx_dropped++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700982 if (el3_debug)
Alexander Beregalov646cdb32009-05-26 12:35:25 +0000983 pr_debug("%s: Couldn't allocate a sk_buff of size %d.\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700984 dev->name, pkt_len);
985 }
986 inw(ioaddr + EL3_STATUS); /* Delay. */
987 while (inw(ioaddr + EL3_STATUS) & 0x1000)
Alexander Beregalov646cdb32009-05-26 12:35:25 +0000988 pr_debug(" Waiting for 3c509 to discard packet, status %x.\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989 inw(ioaddr + EL3_STATUS) );
990 }
991
992 return 0;
993}
994
995/*
996 * Set or clear the multicast filter for this adaptor.
997 */
998static void
999set_multicast_list(struct net_device *dev)
1000{
1001 unsigned long flags;
1002 struct el3_private *lp = netdev_priv(dev);
1003 int ioaddr = dev->base_addr;
Jiri Pirko4cd24ea2010-02-08 04:30:35 +00001004 int mc_count = netdev_mc_count(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001005
1006 if (el3_debug > 1) {
1007 static int old;
Jiri Pirko4cd24ea2010-02-08 04:30:35 +00001008 if (old != mc_count) {
1009 old = mc_count;
1010 pr_debug("%s: Setting Rx mode to %d addresses.\n",
1011 dev->name, mc_count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001012 }
1013 }
1014 spin_lock_irqsave(&lp->lock, flags);
1015 if (dev->flags&IFF_PROMISC) {
1016 outw(SetRxFilter | RxStation | RxMulticast | RxBroadcast | RxProm,
1017 ioaddr + EL3_CMD);
1018 }
Jiri Pirko4cd24ea2010-02-08 04:30:35 +00001019 else if (mc_count || (dev->flags&IFF_ALLMULTI)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001020 outw(SetRxFilter | RxStation | RxMulticast | RxBroadcast, ioaddr + EL3_CMD);
1021 }
1022 else
1023 outw(SetRxFilter | RxStation | RxBroadcast, ioaddr + EL3_CMD);
1024 spin_unlock_irqrestore(&lp->lock, flags);
1025}
1026
1027static int
1028el3_close(struct net_device *dev)
1029{
1030 int ioaddr = dev->base_addr;
1031 struct el3_private *lp = netdev_priv(dev);
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001032
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033 if (el3_debug > 2)
Alexander Beregalov646cdb32009-05-26 12:35:25 +00001034 pr_debug("%s: Shutting down ethercard.\n", dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035
1036 el3_down(dev);
1037
1038 free_irq(dev->irq, dev);
1039 /* Switching back to window 0 disables the IRQ. */
1040 EL3WINDOW(0);
1041 if (lp->type != EL3_EISA) {
1042 /* But we explicitly zero the IRQ line select anyway. Don't do
1043 * it on EISA cards, it prevents the module from getting an
1044 * IRQ after unload+reload... */
1045 outw(0x0f00, ioaddr + WN0_IRQ);
1046 }
1047
1048 return 0;
1049}
1050
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001051static int
Linus Torvalds1da177e2005-04-16 15:20:36 -07001052el3_link_ok(struct net_device *dev)
1053{
1054 int ioaddr = dev->base_addr;
1055 u16 tmp;
1056
1057 EL3WINDOW(4);
1058 tmp = inw(ioaddr + WN4_MEDIA);
1059 EL3WINDOW(1);
1060 return tmp & (1<<11);
1061}
1062
1063static int
1064el3_netdev_get_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd)
1065{
1066 u16 tmp;
1067 int ioaddr = dev->base_addr;
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001068
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069 EL3WINDOW(0);
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001070 /* obtain current transceiver via WN4_MEDIA? */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001071 tmp = inw(ioaddr + WN0_ADDR_CONF);
1072 ecmd->transceiver = XCVR_INTERNAL;
1073 switch (tmp >> 14) {
1074 case 0:
1075 ecmd->port = PORT_TP;
1076 break;
1077 case 1:
1078 ecmd->port = PORT_AUI;
1079 ecmd->transceiver = XCVR_EXTERNAL;
1080 break;
1081 case 3:
1082 ecmd->port = PORT_BNC;
1083 default:
1084 break;
1085 }
1086
1087 ecmd->duplex = DUPLEX_HALF;
1088 ecmd->supported = 0;
1089 tmp = inw(ioaddr + WN0_CONF_CTRL);
1090 if (tmp & (1<<13))
1091 ecmd->supported |= SUPPORTED_AUI;
1092 if (tmp & (1<<12))
1093 ecmd->supported |= SUPPORTED_BNC;
1094 if (tmp & (1<<9)) {
1095 ecmd->supported |= SUPPORTED_TP | SUPPORTED_10baseT_Half |
1096 SUPPORTED_10baseT_Full; /* hmm... */
1097 EL3WINDOW(4);
1098 tmp = inw(ioaddr + WN4_NETDIAG);
1099 if (tmp & FD_ENABLE)
1100 ecmd->duplex = DUPLEX_FULL;
1101 }
1102
David Decotigny70739492011-04-27 18:32:40 +00001103 ethtool_cmd_speed_set(ecmd, SPEED_10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001104 EL3WINDOW(1);
1105 return 0;
1106}
1107
1108static int
1109el3_netdev_set_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd)
1110{
1111 u16 tmp;
1112 int ioaddr = dev->base_addr;
1113
1114 if (ecmd->speed != SPEED_10)
1115 return -EINVAL;
1116 if ((ecmd->duplex != DUPLEX_HALF) && (ecmd->duplex != DUPLEX_FULL))
1117 return -EINVAL;
1118 if ((ecmd->transceiver != XCVR_INTERNAL) && (ecmd->transceiver != XCVR_EXTERNAL))
1119 return -EINVAL;
1120
1121 /* change XCVR type */
1122 EL3WINDOW(0);
1123 tmp = inw(ioaddr + WN0_ADDR_CONF);
1124 switch (ecmd->port) {
1125 case PORT_TP:
1126 tmp &= ~(3<<14);
1127 dev->if_port = 0;
1128 break;
1129 case PORT_AUI:
1130 tmp |= (1<<14);
1131 dev->if_port = 1;
1132 break;
1133 case PORT_BNC:
1134 tmp |= (3<<14);
1135 dev->if_port = 3;
1136 break;
1137 default:
1138 return -EINVAL;
1139 }
1140
1141 outw(tmp, ioaddr + WN0_ADDR_CONF);
1142 if (dev->if_port == 3) {
1143 /* fire up the DC-DC convertor if BNC gets enabled */
1144 tmp = inw(ioaddr + WN0_ADDR_CONF);
1145 if (tmp & (3 << 14)) {
1146 outw(StartCoax, ioaddr + EL3_CMD);
1147 udelay(800);
1148 } else
1149 return -EIO;
1150 }
1151
1152 EL3WINDOW(4);
1153 tmp = inw(ioaddr + WN4_NETDIAG);
1154 if (ecmd->duplex == DUPLEX_FULL)
1155 tmp |= FD_ENABLE;
1156 else
1157 tmp &= ~FD_ENABLE;
1158 outw(tmp, ioaddr + WN4_NETDIAG);
1159 EL3WINDOW(1);
1160
1161 return 0;
1162}
1163
1164static void el3_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
1165{
Jiri Pirko7826d432013-01-06 00:44:26 +00001166 strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
1167 strlcpy(info->version, DRV_VERSION, sizeof(info->version));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001168}
1169
1170static int el3_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
1171{
1172 struct el3_private *lp = netdev_priv(dev);
1173 int ret;
1174
1175 spin_lock_irq(&lp->lock);
1176 ret = el3_netdev_get_ecmd(dev, ecmd);
1177 spin_unlock_irq(&lp->lock);
1178 return ret;
1179}
1180
1181static int el3_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
1182{
1183 struct el3_private *lp = netdev_priv(dev);
1184 int ret;
1185
1186 spin_lock_irq(&lp->lock);
1187 ret = el3_netdev_set_ecmd(dev, ecmd);
1188 spin_unlock_irq(&lp->lock);
1189 return ret;
1190}
1191
1192static u32 el3_get_link(struct net_device *dev)
1193{
1194 struct el3_private *lp = netdev_priv(dev);
1195 u32 ret;
1196
1197 spin_lock_irq(&lp->lock);
1198 ret = el3_link_ok(dev);
1199 spin_unlock_irq(&lp->lock);
1200 return ret;
1201}
1202
1203static u32 el3_get_msglevel(struct net_device *dev)
1204{
1205 return el3_debug;
1206}
1207
1208static void el3_set_msglevel(struct net_device *dev, u32 v)
1209{
1210 el3_debug = v;
1211}
1212
Jeff Garzik7282d492006-09-13 14:30:00 -04001213static const struct ethtool_ops ethtool_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001214 .get_drvinfo = el3_get_drvinfo,
1215 .get_settings = el3_get_settings,
1216 .set_settings = el3_set_settings,
1217 .get_link = el3_get_link,
1218 .get_msglevel = el3_get_msglevel,
1219 .set_msglevel = el3_set_msglevel,
1220};
1221
1222static void
1223el3_down(struct net_device *dev)
1224{
1225 int ioaddr = dev->base_addr;
1226
1227 netif_stop_queue(dev);
1228
1229 /* Turn off statistics ASAP. We update lp->stats below. */
1230 outw(StatsDisable, ioaddr + EL3_CMD);
1231
1232 /* Disable the receiver and transmitter. */
1233 outw(RxDisable, ioaddr + EL3_CMD);
1234 outw(TxDisable, ioaddr + EL3_CMD);
1235
1236 if (dev->if_port == 3)
1237 /* Turn off thinnet power. Green! */
1238 outw(StopCoax, ioaddr + EL3_CMD);
1239 else if (dev->if_port == 0) {
1240 /* Disable link beat and jabber, if_port may change here next open(). */
1241 EL3WINDOW(4);
1242 outw(inw(ioaddr + WN4_MEDIA) & ~MEDIA_TP, ioaddr + WN4_MEDIA);
1243 }
1244
1245 outw(SetIntrEnb | 0x0000, ioaddr + EL3_CMD);
1246
1247 update_stats(dev);
1248}
1249
1250static void
1251el3_up(struct net_device *dev)
1252{
1253 int i, sw_info, net_diag;
1254 int ioaddr = dev->base_addr;
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001255
Linus Torvalds1da177e2005-04-16 15:20:36 -07001256 /* Activating the board required and does no harm otherwise */
1257 outw(0x0001, ioaddr + 4);
1258
1259 /* Set the IRQ line. */
1260 outw((dev->irq << 12) | 0x0f00, ioaddr + WN0_IRQ);
1261
1262 /* Set the station address in window 2 each time opened. */
1263 EL3WINDOW(2);
1264
1265 for (i = 0; i < 6; i++)
1266 outb(dev->dev_addr[i], ioaddr + i);
1267
1268 if ((dev->if_port & 0x03) == 3) /* BNC interface */
1269 /* Start the thinnet transceiver. We should really wait 50ms...*/
1270 outw(StartCoax, ioaddr + EL3_CMD);
1271 else if ((dev->if_port & 0x03) == 0) { /* 10baseT interface */
1272 /* Combine secondary sw_info word (the adapter level) and primary
1273 sw_info word (duplex setting plus other useless bits) */
1274 EL3WINDOW(0);
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001275 sw_info = (read_eeprom(ioaddr, 0x14) & 0x400f) |
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276 (read_eeprom(ioaddr, 0x0d) & 0xBff0);
1277
1278 EL3WINDOW(4);
1279 net_diag = inw(ioaddr + WN4_NETDIAG);
1280 net_diag = (net_diag | FD_ENABLE); /* temporarily assume full-duplex will be set */
Alexander Beregalov646cdb32009-05-26 12:35:25 +00001281 pr_info("%s: ", dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001282 switch (dev->if_port & 0x0c) {
1283 case 12:
1284 /* force full-duplex mode if 3c5x9b */
1285 if (sw_info & 0x000f) {
Alexander Beregalov646cdb32009-05-26 12:35:25 +00001286 pr_cont("Forcing 3c5x9b full-duplex mode");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001287 break;
1288 }
1289 case 8:
1290 /* set full-duplex mode based on eeprom config setting */
1291 if ((sw_info & 0x000f) && (sw_info & 0x8000)) {
Alexander Beregalov646cdb32009-05-26 12:35:25 +00001292 pr_cont("Setting 3c5x9b full-duplex mode (from EEPROM configuration bit)");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001293 break;
1294 }
1295 default:
1296 /* xcvr=(0 || 4) OR user has an old 3c5x9 non "B" model */
Alexander Beregalov646cdb32009-05-26 12:35:25 +00001297 pr_cont("Setting 3c5x9/3c5x9B half-duplex mode");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001298 net_diag = (net_diag & ~FD_ENABLE); /* disable full duplex */
1299 }
1300
1301 outw(net_diag, ioaddr + WN4_NETDIAG);
Alexander Beregalov646cdb32009-05-26 12:35:25 +00001302 pr_cont(" if_port: %d, sw_info: %4.4x\n", dev->if_port, sw_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001303 if (el3_debug > 3)
Alexander Beregalov646cdb32009-05-26 12:35:25 +00001304 pr_debug("%s: 3c5x9 net diag word is now: %4.4x.\n", dev->name, net_diag);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001305 /* Enable link beat and jabber check. */
1306 outw(inw(ioaddr + WN4_MEDIA) | MEDIA_TP, ioaddr + WN4_MEDIA);
1307 }
1308
1309 /* Switch to the stats window, and clear all stats by reading. */
1310 outw(StatsDisable, ioaddr + EL3_CMD);
1311 EL3WINDOW(6);
1312 for (i = 0; i < 9; i++)
1313 inb(ioaddr + i);
1314 inw(ioaddr + 10);
1315 inw(ioaddr + 12);
1316
1317 /* Switch to register set 1 for normal use. */
1318 EL3WINDOW(1);
1319
1320 /* Accept b-case and phys addr only. */
1321 outw(SetRxFilter | RxStation | RxBroadcast, ioaddr + EL3_CMD);
1322 outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */
1323
1324 outw(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */
1325 outw(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */
1326 /* Allow status bits to be seen. */
1327 outw(SetStatusEnb | 0xff, ioaddr + EL3_CMD);
1328 /* Ack all pending events, and set active indicator mask. */
1329 outw(AckIntr | IntLatch | TxAvailable | RxEarly | IntReq,
1330 ioaddr + EL3_CMD);
1331 outw(SetIntrEnb | IntLatch|TxAvailable|TxComplete|RxComplete|StatsFull,
1332 ioaddr + EL3_CMD);
1333
1334 netif_start_queue(dev);
1335}
1336
1337/* Power Management support functions */
Ondrej Zaryac4bed12008-03-28 14:41:23 -07001338#ifdef CONFIG_PM
Linus Torvalds1da177e2005-04-16 15:20:36 -07001339
1340static int
Pekka Enberg60a89ff2006-03-08 00:06:28 -08001341el3_suspend(struct device *pdev, pm_message_t state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001342{
1343 unsigned long flags;
1344 struct net_device *dev;
1345 struct el3_private *lp;
1346 int ioaddr;
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001347
Greg Kroah-Hartman1aec5bd2009-04-30 12:19:31 +00001348 dev = dev_get_drvdata(pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001349 lp = netdev_priv(dev);
1350 ioaddr = dev->base_addr;
1351
1352 spin_lock_irqsave(&lp->lock, flags);
1353
1354 if (netif_running(dev))
1355 netif_device_detach(dev);
1356
1357 el3_down(dev);
1358 outw(PowerDown, ioaddr + EL3_CMD);
1359
1360 spin_unlock_irqrestore(&lp->lock, flags);
1361 return 0;
1362}
1363
1364static int
Pekka Enberg60a89ff2006-03-08 00:06:28 -08001365el3_resume(struct device *pdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001366{
1367 unsigned long flags;
1368 struct net_device *dev;
1369 struct el3_private *lp;
1370 int ioaddr;
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001371
Greg Kroah-Hartman1aec5bd2009-04-30 12:19:31 +00001372 dev = dev_get_drvdata(pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001373 lp = netdev_priv(dev);
1374 ioaddr = dev->base_addr;
1375
1376 spin_lock_irqsave(&lp->lock, flags);
1377
1378 outw(PowerUp, ioaddr + EL3_CMD);
Ondrej Zary152abd12009-02-06 22:04:08 -08001379 EL3WINDOW(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001380 el3_up(dev);
1381
1382 if (netif_running(dev))
1383 netif_device_attach(dev);
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001384
Linus Torvalds1da177e2005-04-16 15:20:36 -07001385 spin_unlock_irqrestore(&lp->lock, flags);
1386 return 0;
1387}
1388
Ondrej Zaryac4bed12008-03-28 14:41:23 -07001389#endif /* CONFIG_PM */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001390
1391module_param(debug,int, 0);
1392module_param_array(irq, int, NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001393module_param(max_interrupt_work, int, 0);
1394MODULE_PARM_DESC(debug, "debug level (0-6)");
1395MODULE_PARM_DESC(irq, "IRQ number(s) (assigned)");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001396MODULE_PARM_DESC(max_interrupt_work, "maximum events handled per interrupt");
Ondrej Zaryac4bed12008-03-28 14:41:23 -07001397#ifdef CONFIG_PNP
Linus Torvalds1da177e2005-04-16 15:20:36 -07001398module_param(nopnp, int, 0);
1399MODULE_PARM_DESC(nopnp, "disable ISA PnP support (0-1)");
Ondrej Zaryac4bed12008-03-28 14:41:23 -07001400#endif /* CONFIG_PNP */
1401MODULE_DESCRIPTION("3Com Etherlink III (3c509, 3c509B, 3c529, 3c579) ethernet driver");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001402MODULE_LICENSE("GPL");
1403
1404static int __init el3_init_module(void)
1405{
Andrew Morton0992a5d2006-03-08 00:06:27 -08001406 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001407
1408 if (debug >= 0)
1409 el3_debug = debug;
1410
Ondrej Zaryac4bed12008-03-28 14:41:23 -07001411#ifdef CONFIG_PNP
1412 if (!nopnp) {
1413 ret = pnp_register_driver(&el3_pnp_driver);
1414 if (!ret)
1415 pnp_registered = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001416 }
Ondrej Zaryac4bed12008-03-28 14:41:23 -07001417#endif
1418 /* Select an open I/O location at 0x1*0 to do ISA contention select. */
1419 /* Start with 0x110 to avoid some sound cards.*/
1420 for (id_port = 0x110 ; id_port < 0x200; id_port += 0x10) {
1421 if (!request_region(id_port, 1, "3c509-control"))
1422 continue;
1423 outb(0x00, id_port);
1424 outb(0xff, id_port);
1425 if (inb(id_port) & 0x01)
1426 break;
1427 else
1428 release_region(id_port, 1);
1429 }
1430 if (id_port >= 0x200) {
1431 id_port = 0;
Alexander Beregalov646cdb32009-05-26 12:35:25 +00001432 pr_err("No I/O port available for 3c509 activation.\n");
Ondrej Zaryac4bed12008-03-28 14:41:23 -07001433 } else {
1434 ret = isa_register_driver(&el3_isa_driver, EL3_MAX_CARDS);
1435 if (!ret)
1436 isa_registered = 1;
1437 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001438#ifdef CONFIG_EISA
Andrew Morton0992a5d2006-03-08 00:06:27 -08001439 ret = eisa_driver_register(&el3_eisa_driver);
Ondrej Zaryac4bed12008-03-28 14:41:23 -07001440 if (!ret)
1441 eisa_registered = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001442#endif
Ondrej Zaryac4bed12008-03-28 14:41:23 -07001443
1444#ifdef CONFIG_PNP
1445 if (pnp_registered)
1446 ret = 0;
1447#endif
1448 if (isa_registered)
1449 ret = 0;
1450#ifdef CONFIG_EISA
1451 if (eisa_registered)
1452 ret = 0;
1453#endif
Andrew Morton0992a5d2006-03-08 00:06:27 -08001454 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001455}
1456
1457static void __exit el3_cleanup_module(void)
1458{
Ondrej Zaryac4bed12008-03-28 14:41:23 -07001459#ifdef CONFIG_PNP
1460 if (pnp_registered)
1461 pnp_unregister_driver(&el3_pnp_driver);
1462#endif
1463 if (isa_registered)
1464 isa_unregister_driver(&el3_isa_driver);
1465 if (id_port)
1466 release_region(id_port, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001467#ifdef CONFIG_EISA
Ondrej Zaryac4bed12008-03-28 14:41:23 -07001468 if (eisa_registered)
1469 eisa_driver_unregister(&el3_eisa_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001470#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001471}
1472
1473module_init (el3_init_module);
1474module_exit (el3_cleanup_module);