blob: 6eac62b7143c5f40d6f05e996781e0d11526ef72 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*======================================================================
2
3 A PCMCIA ethernet driver for the 3com 3c589 card.
4
5 Copyright (C) 1999 David A. Hinds -- dahinds@users.sourceforge.net
6
7 3c589_cs.c 1.162 2001/10/13 00:08:50
8
9 The network driver code is based on Donald Becker's 3c589 code:
10
11 Written 1994 by Donald Becker.
12 Copyright 1993 United States Government as represented by the
13 Director, National Security Agency. This software may be used and
14 distributed according to the terms of the GNU General Public License,
15 incorporated herein by reference.
16 Donald Becker may be reached at becker@scyld.com
17
Alan Cox113aa832008-10-13 19:01:08 -070018 Updated for 2.5.x by Alan Cox <alan@lxorguk.ukuu.org.uk>
Linus Torvalds1da177e2005-04-16 15:20:36 -070019
20======================================================================*/
21
22#define DRV_NAME "3c589_cs"
23#define DRV_VERSION "1.162-ac"
24
25#include <linux/module.h>
26#include <linux/init.h>
27#include <linux/kernel.h>
28#include <linux/ptrace.h>
29#include <linux/slab.h>
30#include <linux/string.h>
31#include <linux/timer.h>
32#include <linux/interrupt.h>
33#include <linux/in.h>
34#include <linux/delay.h>
35#include <linux/ethtool.h>
36#include <linux/netdevice.h>
37#include <linux/etherdevice.h>
38#include <linux/skbuff.h>
39#include <linux/if_arp.h>
40#include <linux/ioport.h>
41#include <linux/bitops.h>
Marcelo Feitoza Parisiff5688a2006-01-09 18:37:15 -080042#include <linux/jiffies.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070043
Linus Torvalds1da177e2005-04-16 15:20:36 -070044#include <pcmcia/cs_types.h>
45#include <pcmcia/cs.h>
46#include <pcmcia/cistpl.h>
47#include <pcmcia/cisreg.h>
48#include <pcmcia/ciscode.h>
49#include <pcmcia/ds.h>
50
51#include <asm/uaccess.h>
52#include <asm/io.h>
53#include <asm/system.h>
54
55/* To minimize the size of the driver source I only define operating
56 constants if they are used several times. You'll need the manual
57 if you want to understand driver details. */
58/* Offsets from base I/O address. */
59#define EL3_DATA 0x00
60#define EL3_TIMER 0x0a
61#define EL3_CMD 0x0e
62#define EL3_STATUS 0x0e
63
64#define EEPROM_READ 0x0080
65#define EEPROM_BUSY 0x8000
66
67#define EL3WINDOW(win_num) outw(SelectWindow + (win_num), ioaddr + EL3_CMD)
68
69/* The top five bits written to EL3_CMD are a command, the lower
70 11 bits are the parameter, if applicable. */
71enum c509cmd {
72 TotalReset = 0<<11, SelectWindow = 1<<11, StartCoax = 2<<11,
73 RxDisable = 3<<11, RxEnable = 4<<11, RxReset = 5<<11, RxDiscard = 8<<11,
74 TxEnable = 9<<11, TxDisable = 10<<11, TxReset = 11<<11,
75 FakeIntr = 12<<11, AckIntr = 13<<11, SetIntrEnb = 14<<11,
76 SetStatusEnb = 15<<11, SetRxFilter = 16<<11, SetRxThreshold = 17<<11,
77 SetTxThreshold = 18<<11, SetTxStart = 19<<11, StatsEnable = 21<<11,
78 StatsDisable = 22<<11, StopCoax = 23<<11,
79};
80
81enum c509status {
82 IntLatch = 0x0001, AdapterFailure = 0x0002, TxComplete = 0x0004,
83 TxAvailable = 0x0008, RxComplete = 0x0010, RxEarly = 0x0020,
84 IntReq = 0x0040, StatsFull = 0x0080, CmdBusy = 0x1000
85};
86
87/* The SetRxFilter command accepts the following classes: */
88enum RxFilter {
89 RxStation = 1, RxMulticast = 2, RxBroadcast = 4, RxProm = 8
90};
91
92/* Register window 1 offsets, the window used in normal operation. */
93#define TX_FIFO 0x00
94#define RX_FIFO 0x00
95#define RX_STATUS 0x08
96#define TX_STATUS 0x0B
97#define TX_FREE 0x0C /* Remaining free bytes in Tx buffer. */
98
99#define WN0_IRQ 0x08 /* Window 0: Set IRQ line in bits 12-15. */
100#define WN4_MEDIA 0x0A /* Window 4: Various transcvr/media bits. */
101#define MEDIA_TP 0x00C0 /* Enable link beat and jabber for 10baseT. */
102#define MEDIA_LED 0x0001 /* Enable link light on 3C589E cards. */
103
104/* Time in jiffies before concluding Tx hung */
105#define TX_TIMEOUT ((400*HZ)/1000)
106
107struct el3_private {
Dominik Brodowskifd238232006-03-05 10:45:09 +0100108 struct pcmcia_device *p_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109 dev_node_t node;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700110 /* For transceiver monitoring */
111 struct timer_list media;
112 u16 media_status;
113 u16 fast_poll;
114 unsigned long last_irq;
115 spinlock_t lock;
116};
117
Jeff Garzik21c0f272007-09-25 00:11:34 -0400118static const char *if_names[] = { "auto", "10baseT", "10base2", "AUI" };
Linus Torvalds1da177e2005-04-16 15:20:36 -0700119
120/*====================================================================*/
121
122/* Module parameters */
123
124MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
125MODULE_DESCRIPTION("3Com 3c589 series PCMCIA ethernet driver");
126MODULE_LICENSE("GPL");
127
128#define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0)
129
130/* Special hook for setting if_port when module is loaded */
131INT_MODULE_PARM(if_port, 0);
132
Linus Torvalds1da177e2005-04-16 15:20:36 -0700133
134/*====================================================================*/
135
Dominik Brodowski15b99ac2006-03-31 17:26:06 +0200136static int tc589_config(struct pcmcia_device *link);
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200137static void tc589_release(struct pcmcia_device *link);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700138
Olof Johansson906da802008-02-04 22:27:35 -0800139static u16 read_eeprom(unsigned int ioaddr, int index);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140static void tc589_reset(struct net_device *dev);
141static void media_check(unsigned long arg);
142static int el3_config(struct net_device *dev, struct ifmap *map);
143static int el3_open(struct net_device *dev);
Stephen Hemmingerdbf02fa2009-08-31 19:50:49 +0000144static netdev_tx_t el3_start_xmit(struct sk_buff *skb,
145 struct net_device *dev);
David Howells7d12e782006-10-05 14:55:46 +0100146static irqreturn_t el3_interrupt(int irq, void *dev_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700147static void update_stats(struct net_device *dev);
148static struct net_device_stats *el3_get_stats(struct net_device *dev);
149static int el3_rx(struct net_device *dev);
150static int el3_close(struct net_device *dev);
151static void el3_tx_timeout(struct net_device *dev);
Ken Kawasakie445bb42009-07-19 13:08:12 +0000152static void set_rx_mode(struct net_device *dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700153static void set_multicast_list(struct net_device *dev);
Jeff Garzik7282d492006-09-13 14:30:00 -0400154static const struct ethtool_ops netdev_ethtool_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155
Dominik Brodowskicc3b4862005-11-14 21:23:14 +0100156static void tc589_detach(struct pcmcia_device *p_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700157
Linus Torvalds1da177e2005-04-16 15:20:36 -0700158/*======================================================================
159
160 tc589_attach() creates an "instance" of the driver, allocating
161 local data structures for one device. The device is registered
162 with Card Services.
163
164======================================================================*/
165
Stephen Hemminger97161d42009-03-20 19:36:01 +0000166static const struct net_device_ops el3_netdev_ops = {
167 .ndo_open = el3_open,
168 .ndo_stop = el3_close,
169 .ndo_start_xmit = el3_start_xmit,
170 .ndo_tx_timeout = el3_tx_timeout,
171 .ndo_set_config = el3_config,
172 .ndo_get_stats = el3_get_stats,
173 .ndo_set_multicast_list = set_multicast_list,
174 .ndo_change_mtu = eth_change_mtu,
175 .ndo_set_mac_address = eth_mac_addr,
176 .ndo_validate_addr = eth_validate_addr,
177};
178
Dominik Brodowski15b99ac2006-03-31 17:26:06 +0200179static int tc589_probe(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700180{
181 struct el3_private *lp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700182 struct net_device *dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700183
Dominik Brodowskidd0fab52009-10-24 15:51:05 +0200184 dev_dbg(&link->dev, "3c589_attach()\n");
Dominik Brodowskif8cfa612005-11-14 21:25:51 +0100185
Linus Torvalds1da177e2005-04-16 15:20:36 -0700186 /* Create new ethernet device */
187 dev = alloc_etherdev(sizeof(struct el3_private));
188 if (!dev)
Dominik Brodowskif8cfa612005-11-14 21:25:51 +0100189 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700190 lp = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700191 link->priv = dev;
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200192 lp->p_dev = link;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700193
194 spin_lock_init(&lp->lock);
195 link->io.NumPorts1 = 16;
196 link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
Komuro5e7bf8c2007-10-28 11:26:17 +0900197 link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_HANDLE_PRESENT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700198 link->irq.IRQInfo1 = IRQ_LEVEL_ID;
199 link->irq.Handler = &el3_interrupt;
200 link->irq.Instance = dev;
201 link->conf.Attributes = CONF_ENABLE_IRQ;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700202 link->conf.IntType = INT_MEMORY_AND_IO;
203 link->conf.ConfigIndex = 1;
Dominik Brodowskif8cfa612005-11-14 21:25:51 +0100204
Stephen Hemminger97161d42009-03-20 19:36:01 +0000205 dev->netdev_ops = &el3_netdev_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700206 dev->watchdog_timeo = TX_TIMEOUT;
Stephen Hemminger97161d42009-03-20 19:36:01 +0000207
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208 SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
209
Dominik Brodowski15b99ac2006-03-31 17:26:06 +0200210 return tc589_config(link);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700211} /* tc589_attach */
212
213/*======================================================================
214
215 This deletes a driver "instance". The device is de-registered
216 with Card Services. If it has been released, all local data
217 structures are freed. Otherwise, the structures will be freed
218 when the device is released.
219
220======================================================================*/
221
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200222static void tc589_detach(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700223{
224 struct net_device *dev = link->priv;
Dominik Brodowskib4635812005-11-14 21:25:35 +0100225
Dominik Brodowskidd0fab52009-10-24 15:51:05 +0200226 dev_dbg(&link->dev, "3c589_detach\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700227
Dominik Brodowskifd238232006-03-05 10:45:09 +0100228 if (link->dev_node)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700229 unregister_netdev(dev);
230
Dominik Brodowskie2d40962006-03-02 00:09:29 +0100231 tc589_release(link);
Dominik Brodowskicc3b4862005-11-14 21:23:14 +0100232
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233 free_netdev(dev);
234} /* tc589_detach */
235
236/*======================================================================
237
238 tc589_config() is scheduled to run after a CARD_INSERTION event
239 is received, to configure the PCMCIA socket, and to make the
240 ethernet device available to the system.
241
242======================================================================*/
243
Dominik Brodowski15b99ac2006-03-31 17:26:06 +0200244static int tc589_config(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700245{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700246 struct net_device *dev = link->priv;
247 struct el3_private *lp = netdev_priv(dev);
Al Virob1e247a2007-12-22 18:56:13 +0000248 __be16 *phys_addr;
Dominik Brodowskidd0fab52009-10-24 15:51:05 +0200249 int ret, i, j, multi = 0, fifo;
Olof Johansson906da802008-02-04 22:27:35 -0800250 unsigned int ioaddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700251 char *ram_split[] = {"5:3", "3:1", "1:1", "3:5"};
Dominik Brodowskidddfbd82009-10-18 23:54:24 +0200252 u8 *buf;
253 size_t len;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254
Dominik Brodowskidd0fab52009-10-24 15:51:05 +0200255 dev_dbg(&link->dev, "3c589_config\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700256
Al Virob1e247a2007-12-22 18:56:13 +0000257 phys_addr = (__be16 *)dev->dev_addr;
Dominik Brodowskiefd50582006-10-25 21:28:53 -0400258 /* Is this a 3c562? */
259 if (link->manf_id != MANFID_3COM)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700260 printk(KERN_INFO "3c589_cs: hmmm, is this really a "
261 "3Com card??\n");
Dominik Brodowskiefd50582006-10-25 21:28:53 -0400262 multi = (link->card_id == PRODID_3COM_3C562);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263
264 /* For the 3c562, the base address must be xx00-xx7f */
265 link->io.IOAddrLines = 16;
266 for (i = j = 0; j < 0x400; j += 0x10) {
267 if (multi && (j & 0x80)) continue;
268 link->io.BasePort1 = j ^ 0x300;
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200269 i = pcmcia_request_io(link, &link->io);
Dominik Brodowski4c89e882008-08-03 10:07:45 +0200270 if (i == 0)
271 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700272 }
Dominik Brodowskidd0fab52009-10-24 15:51:05 +0200273 if (i != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700274 goto failed;
Dominik Brodowskidd0fab52009-10-24 15:51:05 +0200275
276 ret = pcmcia_request_irq(link, &link->irq);
277 if (ret)
278 goto failed;
279
280 ret = pcmcia_request_configuration(link, &link->conf);
281 if (ret)
282 goto failed;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283
284 dev->irq = link->irq.AssignedIRQ;
285 dev->base_addr = link->io.BasePort1;
286 ioaddr = dev->base_addr;
287 EL3WINDOW(0);
288
289 /* The 3c589 has an extra EEPROM for configuration info, including
290 the hardware address. The 3c562 puts the address in the CIS. */
Dominik Brodowskidddfbd82009-10-18 23:54:24 +0200291 len = pcmcia_get_tuple(link, 0x88, &buf);
292 if (buf && len >= 6) {
293 for (i = 0; i < 3; i++)
294 phys_addr[i] = htons(le16_to_cpu(buf[i*2]));
295 kfree(buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700296 } else {
Dominik Brodowskidddfbd82009-10-18 23:54:24 +0200297 kfree(buf); /* 0 < len < 6 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700298 for (i = 0; i < 3; i++)
299 phys_addr[i] = htons(read_eeprom(ioaddr, i));
Al Virob1e247a2007-12-22 18:56:13 +0000300 if (phys_addr[0] == htons(0x6060)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700301 printk(KERN_ERR "3c589_cs: IO port conflict at 0x%03lx"
302 "-0x%03lx\n", dev->base_addr, dev->base_addr+15);
303 goto failed;
304 }
305 }
306
307 /* The address and resource configuration register aren't loaded from
308 the EEPROM and *must* be set to 0 and IRQ3 for the PCMCIA version. */
309 outw(0x3f00, ioaddr + 8);
310 fifo = inl(ioaddr);
311
312 /* The if_port symbol can be set when the module is loaded */
313 if ((if_port >= 0) && (if_port <= 3))
314 dev->if_port = if_port;
315 else
316 printk(KERN_ERR "3c589_cs: invalid if_port requested\n");
317
Dominik Brodowskifd238232006-03-05 10:45:09 +0100318 link->dev_node = &lp->node;
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200319 SET_NETDEV_DEV(dev, &handle_to_dev(link));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320
321 if (register_netdev(dev) != 0) {
322 printk(KERN_ERR "3c589_cs: register_netdev() failed\n");
Dominik Brodowskifd238232006-03-05 10:45:09 +0100323 link->dev_node = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324 goto failed;
325 }
326
327 strcpy(lp->node.dev_name, dev->name);
328
Joe Perches0795af52007-10-03 17:59:30 -0700329 printk(KERN_INFO "%s: 3Com 3c%s, io %#3lx, irq %d, "
Johannes Berge1749612008-10-27 15:59:26 -0700330 "hw_addr %pM\n",
Joe Perches0795af52007-10-03 17:59:30 -0700331 dev->name, (multi ? "562" : "589"), dev->base_addr, dev->irq,
Johannes Berge1749612008-10-27 15:59:26 -0700332 dev->dev_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333 printk(KERN_INFO " %dK FIFO split %s Rx:Tx, %s xcvr\n",
334 (fifo & 7) ? 32 : 8, ram_split[(fifo >> 16) & 3],
335 if_names[dev->if_port]);
Dominik Brodowski15b99ac2006-03-31 17:26:06 +0200336 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337
Linus Torvalds1da177e2005-04-16 15:20:36 -0700338failed:
339 tc589_release(link);
Dominik Brodowski15b99ac2006-03-31 17:26:06 +0200340 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700341} /* tc589_config */
342
343/*======================================================================
344
345 After a card is removed, tc589_release() will unregister the net
346 device, and release the PCMCIA configuration. If the device is
347 still open, this will be postponed until it is closed.
348
349======================================================================*/
350
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200351static void tc589_release(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700352{
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200353 pcmcia_disable_device(link);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700354}
355
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200356static int tc589_suspend(struct pcmcia_device *link)
Dominik Brodowski98e4c282005-11-14 21:21:18 +0100357{
Dominik Brodowski98e4c282005-11-14 21:21:18 +0100358 struct net_device *dev = link->priv;
359
Dominik Brodowskie2d40962006-03-02 00:09:29 +0100360 if (link->open)
Dominik Brodowski8661bb52006-03-02 00:02:33 +0100361 netif_device_detach(dev);
Dominik Brodowski98e4c282005-11-14 21:21:18 +0100362
363 return 0;
364}
365
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200366static int tc589_resume(struct pcmcia_device *link)
Dominik Brodowski98e4c282005-11-14 21:21:18 +0100367{
Dominik Brodowski98e4c282005-11-14 21:21:18 +0100368 struct net_device *dev = link->priv;
369
Dominik Brodowskie2d40962006-03-02 00:09:29 +0100370 if (link->open) {
Dominik Brodowski8661bb52006-03-02 00:02:33 +0100371 tc589_reset(dev);
372 netif_device_attach(dev);
Dominik Brodowski98e4c282005-11-14 21:21:18 +0100373 }
374
375 return 0;
376}
377
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378/*====================================================================*/
379
380/*
381 Use this for commands that may take time to finish
382*/
383static void tc589_wait_for_completion(struct net_device *dev, int cmd)
384{
385 int i = 100;
386 outw(cmd, dev->base_addr + EL3_CMD);
387 while (--i > 0)
388 if (!(inw(dev->base_addr + EL3_STATUS) & 0x1000)) break;
389 if (i == 0)
390 printk(KERN_WARNING "%s: command 0x%04x did not complete!\n",
391 dev->name, cmd);
392}
393
394/*
395 Read a word from the EEPROM using the regular EEPROM access register.
396 Assume that we are in register window zero.
397*/
Olof Johansson906da802008-02-04 22:27:35 -0800398static u16 read_eeprom(unsigned int ioaddr, int index)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399{
400 int i;
401 outw(EEPROM_READ + index, ioaddr + 10);
402 /* Reading the eeprom takes 162 us */
403 for (i = 1620; i >= 0; i--)
404 if ((inw(ioaddr + 10) & EEPROM_BUSY) == 0)
405 break;
406 return inw(ioaddr + 12);
407}
408
409/*
410 Set transceiver type, perhaps to something other than what the user
411 specified in dev->if_port.
412*/
413static void tc589_set_xcvr(struct net_device *dev, int if_port)
414{
415 struct el3_private *lp = netdev_priv(dev);
Olof Johansson906da802008-02-04 22:27:35 -0800416 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417
418 EL3WINDOW(0);
419 switch (if_port) {
420 case 0: case 1: outw(0, ioaddr + 6); break;
421 case 2: outw(3<<14, ioaddr + 6); break;
422 case 3: outw(1<<14, ioaddr + 6); break;
423 }
424 /* On PCMCIA, this just turns on the LED */
425 outw((if_port == 2) ? StartCoax : StopCoax, ioaddr + EL3_CMD);
426 /* 10baseT interface, enable link beat and jabber check. */
427 EL3WINDOW(4);
428 outw(MEDIA_LED | ((if_port < 2) ? MEDIA_TP : 0), ioaddr + WN4_MEDIA);
429 EL3WINDOW(1);
430 if (if_port == 2)
431 lp->media_status = ((dev->if_port == 0) ? 0x8000 : 0x4000);
432 else
433 lp->media_status = ((dev->if_port == 0) ? 0x4010 : 0x8800);
434}
435
436static void dump_status(struct net_device *dev)
437{
Olof Johansson906da802008-02-04 22:27:35 -0800438 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439 EL3WINDOW(1);
440 printk(KERN_INFO " irq status %04x, rx status %04x, tx status "
441 "%02x tx free %04x\n", inw(ioaddr+EL3_STATUS),
442 inw(ioaddr+RX_STATUS), inb(ioaddr+TX_STATUS),
443 inw(ioaddr+TX_FREE));
444 EL3WINDOW(4);
445 printk(KERN_INFO " diagnostics: fifo %04x net %04x ethernet %04x"
446 " media %04x\n", inw(ioaddr+0x04), inw(ioaddr+0x06),
447 inw(ioaddr+0x08), inw(ioaddr+0x0a));
448 EL3WINDOW(1);
449}
450
451/* Reset and restore all of the 3c589 registers. */
452static void tc589_reset(struct net_device *dev)
453{
Olof Johansson906da802008-02-04 22:27:35 -0800454 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700455 int i;
456
457 EL3WINDOW(0);
458 outw(0x0001, ioaddr + 4); /* Activate board. */
459 outw(0x3f00, ioaddr + 8); /* Set the IRQ line. */
460
461 /* Set the station address in window 2. */
462 EL3WINDOW(2);
463 for (i = 0; i < 6; i++)
464 outb(dev->dev_addr[i], ioaddr + i);
465
466 tc589_set_xcvr(dev, dev->if_port);
467
468 /* Switch to the stats window, and clear all stats by reading. */
469 outw(StatsDisable, ioaddr + EL3_CMD);
470 EL3WINDOW(6);
471 for (i = 0; i < 9; i++)
472 inb(ioaddr+i);
473 inw(ioaddr + 10);
474 inw(ioaddr + 12);
475
476 /* Switch to register set 1 for normal use. */
477 EL3WINDOW(1);
478
Ken Kawasakie445bb42009-07-19 13:08:12 +0000479 set_rx_mode(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700480 outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */
481 outw(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */
482 outw(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */
483 /* Allow status bits to be seen. */
484 outw(SetStatusEnb | 0xff, ioaddr + EL3_CMD);
485 /* Ack all pending events, and set active indicator mask. */
486 outw(AckIntr | IntLatch | TxAvailable | RxEarly | IntReq,
487 ioaddr + EL3_CMD);
488 outw(SetIntrEnb | IntLatch | TxAvailable | RxComplete | StatsFull
489 | AdapterFailure, ioaddr + EL3_CMD);
490}
491
492static void netdev_get_drvinfo(struct net_device *dev,
493 struct ethtool_drvinfo *info)
494{
495 strcpy(info->driver, DRV_NAME);
496 strcpy(info->version, DRV_VERSION);
497 sprintf(info->bus_info, "PCMCIA 0x%lx", dev->base_addr);
498}
499
Jeff Garzik7282d492006-09-13 14:30:00 -0400500static const struct ethtool_ops netdev_ethtool_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501 .get_drvinfo = netdev_get_drvinfo,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502};
503
504static int el3_config(struct net_device *dev, struct ifmap *map)
505{
506 if ((map->port != (u_char)(-1)) && (map->port != dev->if_port)) {
507 if (map->port <= 3) {
508 dev->if_port = map->port;
509 printk(KERN_INFO "%s: switched to %s port\n",
510 dev->name, if_names[dev->if_port]);
511 tc589_set_xcvr(dev, dev->if_port);
512 } else
513 return -EINVAL;
514 }
515 return 0;
516}
517
518static int el3_open(struct net_device *dev)
519{
520 struct el3_private *lp = netdev_priv(dev);
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200521 struct pcmcia_device *link = lp->p_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522
Dominik Brodowski9940ec32006-03-05 11:04:33 +0100523 if (!pcmcia_dev_present(link))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700524 return -ENODEV;
525
526 link->open++;
527 netif_start_queue(dev);
528
529 tc589_reset(dev);
530 init_timer(&lp->media);
531 lp->media.function = &media_check;
532 lp->media.data = (unsigned long) dev;
533 lp->media.expires = jiffies + HZ;
534 add_timer(&lp->media);
535
Dominik Brodowskidd0fab52009-10-24 15:51:05 +0200536 dev_dbg(&link->dev, "%s: opened, status %4.4x.\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700537 dev->name, inw(dev->base_addr + EL3_STATUS));
538
539 return 0;
540}
541
542static void el3_tx_timeout(struct net_device *dev)
543{
Olof Johansson906da802008-02-04 22:27:35 -0800544 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700545
546 printk(KERN_WARNING "%s: Transmit timed out!\n", dev->name);
547 dump_status(dev);
Paulius Zaleckascd652842008-04-30 01:20:20 +0300548 dev->stats.tx_errors++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700549 dev->trans_start = jiffies;
550 /* Issue TX_RESET and TX_START commands. */
551 tc589_wait_for_completion(dev, TxReset);
552 outw(TxEnable, ioaddr + EL3_CMD);
553 netif_wake_queue(dev);
554}
555
556static void pop_tx_status(struct net_device *dev)
557{
Olof Johansson906da802008-02-04 22:27:35 -0800558 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700559 int i;
560
561 /* Clear the Tx status stack. */
562 for (i = 32; i > 0; i--) {
563 u_char tx_status = inb(ioaddr + TX_STATUS);
564 if (!(tx_status & 0x84)) break;
565 /* reset transmitter on jabber error or underrun */
566 if (tx_status & 0x30)
567 tc589_wait_for_completion(dev, TxReset);
568 if (tx_status & 0x38) {
Dominik Brodowskidd0fab52009-10-24 15:51:05 +0200569 pr_debug("%s: transmit error: status 0x%02x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700570 dev->name, tx_status);
571 outw(TxEnable, ioaddr + EL3_CMD);
Paulius Zaleckascd652842008-04-30 01:20:20 +0300572 dev->stats.tx_aborted_errors++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700573 }
574 outb(0x00, ioaddr + TX_STATUS); /* Pop the status stack. */
575 }
576}
577
Stephen Hemmingerdbf02fa2009-08-31 19:50:49 +0000578static netdev_tx_t el3_start_xmit(struct sk_buff *skb,
579 struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700580{
Olof Johansson906da802008-02-04 22:27:35 -0800581 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700582 struct el3_private *priv = netdev_priv(dev);
Komurod08d2832006-12-02 11:53:27 +0900583 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700584
Dominik Brodowskidd0fab52009-10-24 15:51:05 +0200585 pr_debug("%s: el3_start_xmit(length = %ld) called, "
Linus Torvalds1da177e2005-04-16 15:20:36 -0700586 "status %4.4x.\n", dev->name, (long)skb->len,
587 inw(ioaddr + EL3_STATUS));
588
Komurod08d2832006-12-02 11:53:27 +0900589 spin_lock_irqsave(&priv->lock, flags);
590
Paulius Zaleckascd652842008-04-30 01:20:20 +0300591 dev->stats.tx_bytes += skb->len;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700592
593 /* Put out the doubleword header... */
594 outw(skb->len, ioaddr + TX_FIFO);
595 outw(0x00, ioaddr + TX_FIFO);
596 /* ... and the packet rounded to a doubleword. */
597 outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
598
599 dev->trans_start = jiffies;
600 if (inw(ioaddr + TX_FREE) <= 1536) {
601 netif_stop_queue(dev);
602 /* Interrupt us when the FIFO has room for max-sized packet. */
603 outw(SetTxThreshold + 1536, ioaddr + EL3_CMD);
604 }
605
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606 pop_tx_status(dev);
Komurod08d2832006-12-02 11:53:27 +0900607 spin_unlock_irqrestore(&priv->lock, flags);
Patrick McHardy63ac9b92007-07-02 16:08:28 +0200608 dev_kfree_skb(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609
Patrick McHardy6ed10652009-06-23 06:03:08 +0000610 return NETDEV_TX_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611}
612
613/* The EL3 interrupt handler. */
David Howells7d12e782006-10-05 14:55:46 +0100614static irqreturn_t el3_interrupt(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700615{
616 struct net_device *dev = (struct net_device *) dev_id;
617 struct el3_private *lp = netdev_priv(dev);
Olof Johansson906da802008-02-04 22:27:35 -0800618 unsigned int ioaddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619 __u16 status;
620 int i = 0, handled = 1;
621
622 if (!netif_device_present(dev))
623 return IRQ_NONE;
624
625 ioaddr = dev->base_addr;
626
Dominik Brodowskidd0fab52009-10-24 15:51:05 +0200627 pr_debug("%s: interrupt, status %4.4x.\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628 dev->name, inw(ioaddr + EL3_STATUS));
629
630 spin_lock(&lp->lock);
631 while ((status = inw(ioaddr + EL3_STATUS)) &
632 (IntLatch | RxComplete | StatsFull)) {
633 if ((status & 0xe000) != 0x2000) {
Dominik Brodowskidd0fab52009-10-24 15:51:05 +0200634 pr_debug("%s: interrupt from dead card\n", dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635 handled = 0;
636 break;
637 }
638
639 if (status & RxComplete)
640 el3_rx(dev);
641
642 if (status & TxAvailable) {
Dominik Brodowskidd0fab52009-10-24 15:51:05 +0200643 pr_debug(" TX room bit was handled.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644 /* There's room in the FIFO for a full-sized packet. */
645 outw(AckIntr | TxAvailable, ioaddr + EL3_CMD);
646 netif_wake_queue(dev);
647 }
648
649 if (status & TxComplete)
650 pop_tx_status(dev);
651
652 if (status & (AdapterFailure | RxEarly | StatsFull)) {
653 /* Handle all uncommon interrupts. */
654 if (status & StatsFull) /* Empty statistics. */
655 update_stats(dev);
656 if (status & RxEarly) { /* Rx early is unused. */
657 el3_rx(dev);
658 outw(AckIntr | RxEarly, ioaddr + EL3_CMD);
659 }
660 if (status & AdapterFailure) {
661 u16 fifo_diag;
662 EL3WINDOW(4);
663 fifo_diag = inw(ioaddr + 4);
664 EL3WINDOW(1);
665 printk(KERN_WARNING "%s: adapter failure, FIFO diagnostic"
666 " register %04x.\n", dev->name, fifo_diag);
667 if (fifo_diag & 0x0400) {
668 /* Tx overrun */
669 tc589_wait_for_completion(dev, TxReset);
670 outw(TxEnable, ioaddr + EL3_CMD);
671 }
672 if (fifo_diag & 0x2000) {
673 /* Rx underrun */
674 tc589_wait_for_completion(dev, RxReset);
Ken Kawasakie445bb42009-07-19 13:08:12 +0000675 set_rx_mode(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700676 outw(RxEnable, ioaddr + EL3_CMD);
677 }
678 outw(AckIntr | AdapterFailure, ioaddr + EL3_CMD);
679 }
680 }
681
682 if (++i > 10) {
683 printk(KERN_ERR "%s: infinite loop in interrupt, "
684 "status %4.4x.\n", dev->name, status);
685 /* Clear all interrupts */
686 outw(AckIntr | 0xFF, ioaddr + EL3_CMD);
687 break;
688 }
689 /* Acknowledge the IRQ. */
690 outw(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD);
691 }
692
693 lp->last_irq = jiffies;
694 spin_unlock(&lp->lock);
Dominik Brodowskidd0fab52009-10-24 15:51:05 +0200695 pr_debug("%s: exiting interrupt, status %4.4x.\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696 dev->name, inw(ioaddr + EL3_STATUS));
697 return IRQ_RETVAL(handled);
698}
699
700static void media_check(unsigned long arg)
701{
702 struct net_device *dev = (struct net_device *)(arg);
703 struct el3_private *lp = netdev_priv(dev);
Olof Johansson906da802008-02-04 22:27:35 -0800704 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700705 u16 media, errs;
706 unsigned long flags;
707
708 if (!netif_device_present(dev)) goto reschedule;
709
Linus Torvalds1da177e2005-04-16 15:20:36 -0700710 /* Check for pending interrupt with expired latency timer: with
711 this, we can limp along even if the interrupt is blocked */
712 if ((inw(ioaddr + EL3_STATUS) & IntLatch) &&
713 (inb(ioaddr + EL3_TIMER) == 0xff)) {
714 if (!lp->fast_poll)
715 printk(KERN_WARNING "%s: interrupt(s) dropped!\n", dev->name);
Komurod08d2832006-12-02 11:53:27 +0900716 el3_interrupt(dev->irq, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700717 lp->fast_poll = HZ;
718 }
719 if (lp->fast_poll) {
720 lp->fast_poll--;
721 lp->media.expires = jiffies + HZ/100;
722 add_timer(&lp->media);
723 return;
724 }
725
726 /* lp->lock guards the EL3 window. Window should always be 1 except
727 when the lock is held */
728 spin_lock_irqsave(&lp->lock, flags);
729 EL3WINDOW(4);
730 media = inw(ioaddr+WN4_MEDIA) & 0xc810;
731
732 /* Ignore collisions unless we've had no irq's recently */
Marcelo Feitoza Parisiff5688a2006-01-09 18:37:15 -0800733 if (time_before(jiffies, lp->last_irq + HZ)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734 media &= ~0x0010;
735 } else {
736 /* Try harder to detect carrier errors */
737 EL3WINDOW(6);
738 outw(StatsDisable, ioaddr + EL3_CMD);
739 errs = inb(ioaddr + 0);
740 outw(StatsEnable, ioaddr + EL3_CMD);
Paulius Zaleckascd652842008-04-30 01:20:20 +0300741 dev->stats.tx_carrier_errors += errs;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700742 if (errs || (lp->media_status & 0x0010)) media |= 0x0010;
743 }
744
745 if (media != lp->media_status) {
746 if ((media & lp->media_status & 0x8000) &&
747 ((lp->media_status ^ media) & 0x0800))
748 printk(KERN_INFO "%s: %s link beat\n", dev->name,
749 (lp->media_status & 0x0800 ? "lost" : "found"));
750 else if ((media & lp->media_status & 0x4000) &&
751 ((lp->media_status ^ media) & 0x0010))
752 printk(KERN_INFO "%s: coax cable %s\n", dev->name,
753 (lp->media_status & 0x0010 ? "ok" : "problem"));
754 if (dev->if_port == 0) {
755 if (media & 0x8000) {
756 if (media & 0x0800)
757 printk(KERN_INFO "%s: flipped to 10baseT\n",
758 dev->name);
759 else
760 tc589_set_xcvr(dev, 2);
761 } else if (media & 0x4000) {
762 if (media & 0x0010)
763 tc589_set_xcvr(dev, 1);
764 else
765 printk(KERN_INFO "%s: flipped to 10base2\n",
766 dev->name);
767 }
768 }
769 lp->media_status = media;
770 }
771
772 EL3WINDOW(1);
773 spin_unlock_irqrestore(&lp->lock, flags);
774
775reschedule:
776 lp->media.expires = jiffies + HZ;
777 add_timer(&lp->media);
778}
779
780static struct net_device_stats *el3_get_stats(struct net_device *dev)
781{
782 struct el3_private *lp = netdev_priv(dev);
783 unsigned long flags;
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200784 struct pcmcia_device *link = lp->p_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700785
Dominik Brodowski9940ec32006-03-05 11:04:33 +0100786 if (pcmcia_dev_present(link)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700787 spin_lock_irqsave(&lp->lock, flags);
788 update_stats(dev);
789 spin_unlock_irqrestore(&lp->lock, flags);
790 }
Paulius Zaleckascd652842008-04-30 01:20:20 +0300791 return &dev->stats;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792}
793
794/*
795 Update statistics. We change to register window 6, so this should be run
796 single-threaded if the device is active. This is expected to be a rare
797 operation, and it's simpler for the rest of the driver to assume that
798 window 1 is always valid rather than use a special window-state variable.
799
800 Caller must hold the lock for this
801*/
802static void update_stats(struct net_device *dev)
803{
Olof Johansson906da802008-02-04 22:27:35 -0800804 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700805
Dominik Brodowskidd0fab52009-10-24 15:51:05 +0200806 pr_debug("%s: updating the statistics.\n", dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700807 /* Turn off statistics updates while reading. */
808 outw(StatsDisable, ioaddr + EL3_CMD);
809 /* Switch to the stats window, and read everything. */
810 EL3WINDOW(6);
Paulius Zaleckascd652842008-04-30 01:20:20 +0300811 dev->stats.tx_carrier_errors += inb(ioaddr + 0);
812 dev->stats.tx_heartbeat_errors += inb(ioaddr + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700813 /* Multiple collisions. */ inb(ioaddr + 2);
Paulius Zaleckascd652842008-04-30 01:20:20 +0300814 dev->stats.collisions += inb(ioaddr + 3);
815 dev->stats.tx_window_errors += inb(ioaddr + 4);
816 dev->stats.rx_fifo_errors += inb(ioaddr + 5);
817 dev->stats.tx_packets += inb(ioaddr + 6);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700818 /* Rx packets */ inb(ioaddr + 7);
819 /* Tx deferrals */ inb(ioaddr + 8);
820 /* Rx octets */ inw(ioaddr + 10);
821 /* Tx octets */ inw(ioaddr + 12);
822
823 /* Back to window 1, and turn statistics back on. */
824 EL3WINDOW(1);
825 outw(StatsEnable, ioaddr + EL3_CMD);
826}
827
828static int el3_rx(struct net_device *dev)
829{
Olof Johansson906da802008-02-04 22:27:35 -0800830 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700831 int worklimit = 32;
832 short rx_status;
833
Dominik Brodowskidd0fab52009-10-24 15:51:05 +0200834 pr_debug("%s: in rx_packet(), status %4.4x, rx_status %4.4x.\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700835 dev->name, inw(ioaddr+EL3_STATUS), inw(ioaddr+RX_STATUS));
836 while (!((rx_status = inw(ioaddr + RX_STATUS)) & 0x8000) &&
Roel Kluinb9bdcd92009-03-04 00:05:56 -0800837 worklimit > 0) {
838 worklimit--;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700839 if (rx_status & 0x4000) { /* Error, update stats. */
840 short error = rx_status & 0x3800;
Paulius Zaleckascd652842008-04-30 01:20:20 +0300841 dev->stats.rx_errors++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700842 switch (error) {
Paulius Zaleckascd652842008-04-30 01:20:20 +0300843 case 0x0000: dev->stats.rx_over_errors++; break;
844 case 0x0800: dev->stats.rx_length_errors++; break;
845 case 0x1000: dev->stats.rx_frame_errors++; break;
846 case 0x1800: dev->stats.rx_length_errors++; break;
847 case 0x2000: dev->stats.rx_frame_errors++; break;
848 case 0x2800: dev->stats.rx_crc_errors++; break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700849 }
850 } else {
851 short pkt_len = rx_status & 0x7ff;
852 struct sk_buff *skb;
853
854 skb = dev_alloc_skb(pkt_len+5);
855
Dominik Brodowskidd0fab52009-10-24 15:51:05 +0200856 pr_debug(" Receiving packet size %d status %4.4x.\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700857 pkt_len, rx_status);
858 if (skb != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700859 skb_reserve(skb, 2);
860 insl(ioaddr+RX_FIFO, skb_put(skb, pkt_len),
861 (pkt_len+3)>>2);
862 skb->protocol = eth_type_trans(skb, dev);
863 netif_rx(skb);
Paulius Zaleckascd652842008-04-30 01:20:20 +0300864 dev->stats.rx_packets++;
865 dev->stats.rx_bytes += pkt_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700866 } else {
Dominik Brodowskidd0fab52009-10-24 15:51:05 +0200867 pr_debug("%s: couldn't allocate a sk_buff of"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700868 " size %d.\n", dev->name, pkt_len);
Paulius Zaleckascd652842008-04-30 01:20:20 +0300869 dev->stats.rx_dropped++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700870 }
871 }
872 /* Pop the top of the Rx FIFO */
873 tc589_wait_for_completion(dev, RxDiscard);
874 }
875 if (worklimit == 0)
876 printk(KERN_WARNING "%s: too much work in el3_rx!\n", dev->name);
877 return 0;
878}
879
Ken Kawasakie445bb42009-07-19 13:08:12 +0000880static void set_rx_mode(struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700881{
Olof Johansson906da802008-02-04 22:27:35 -0800882 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700883 u16 opts = SetRxFilter | RxStation | RxBroadcast;
884
Linus Torvalds1da177e2005-04-16 15:20:36 -0700885 if (dev->flags & IFF_PROMISC)
886 opts |= RxMulticast | RxProm;
887 else if (dev->mc_count || (dev->flags & IFF_ALLMULTI))
888 opts |= RxMulticast;
889 outw(opts, ioaddr + EL3_CMD);
890}
891
Ken Kawasakie445bb42009-07-19 13:08:12 +0000892static void set_multicast_list(struct net_device *dev)
893{
894 struct el3_private *priv = netdev_priv(dev);
895 unsigned long flags;
896
897 spin_lock_irqsave(&priv->lock, flags);
898 set_rx_mode(dev);
899 spin_unlock_irqrestore(&priv->lock, flags);
900}
901
Linus Torvalds1da177e2005-04-16 15:20:36 -0700902static int el3_close(struct net_device *dev)
903{
904 struct el3_private *lp = netdev_priv(dev);
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200905 struct pcmcia_device *link = lp->p_dev;
Olof Johansson906da802008-02-04 22:27:35 -0800906 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700907
Dominik Brodowskidd0fab52009-10-24 15:51:05 +0200908 dev_dbg(&link->dev, "%s: shutting down ethercard.\n", dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700909
Dominik Brodowski9940ec32006-03-05 11:04:33 +0100910 if (pcmcia_dev_present(link)) {
Paulius Zaleckascd652842008-04-30 01:20:20 +0300911 /* Turn off statistics ASAP. We update dev->stats below. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912 outw(StatsDisable, ioaddr + EL3_CMD);
913
914 /* Disable the receiver and transmitter. */
915 outw(RxDisable, ioaddr + EL3_CMD);
916 outw(TxDisable, ioaddr + EL3_CMD);
917
918 if (dev->if_port == 2)
919 /* Turn off thinnet power. Green! */
920 outw(StopCoax, ioaddr + EL3_CMD);
921 else if (dev->if_port == 1) {
922 /* Disable link beat and jabber */
923 EL3WINDOW(4);
924 outw(0, ioaddr + WN4_MEDIA);
925 }
926
927 /* Switching back to window 0 disables the IRQ. */
928 EL3WINDOW(0);
929 /* But we explicitly zero the IRQ line select anyway. */
930 outw(0x0f00, ioaddr + WN0_IRQ);
931
932 /* Check if the card still exists */
933 if ((inw(ioaddr+EL3_STATUS) & 0xe000) == 0x2000)
934 update_stats(dev);
935 }
936
937 link->open--;
938 netif_stop_queue(dev);
939 del_timer_sync(&lp->media);
940
941 return 0;
942}
943
Dominik Brodowski7ffec582005-06-27 16:28:19 -0700944static struct pcmcia_device_id tc589_ids[] = {
945 PCMCIA_MFC_DEVICE_MANF_CARD(0, 0x0101, 0x0562),
946 PCMCIA_MFC_DEVICE_PROD_ID1(0, "Motorola MARQUIS", 0xf03e4e77),
947 PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0589),
948 PCMCIA_DEVICE_PROD_ID12("Farallon", "ENet", 0x58d93fc4, 0x992c2202),
Ken Kawasakif0a3a152009-05-01 19:21:26 -0700949 PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0101, 0x0035, "cis/3CXEM556.cis"),
950 PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0101, 0x003d, "cis/3CXEM556.cis"),
Dominik Brodowski7ffec582005-06-27 16:28:19 -0700951 PCMCIA_DEVICE_NULL,
952};
953MODULE_DEVICE_TABLE(pcmcia, tc589_ids);
954
Linus Torvalds1da177e2005-04-16 15:20:36 -0700955static struct pcmcia_driver tc589_driver = {
956 .owner = THIS_MODULE,
957 .drv = {
958 .name = "3c589_cs",
959 },
Dominik Brodowski15b99ac2006-03-31 17:26:06 +0200960 .probe = tc589_probe,
Dominik Brodowskicc3b4862005-11-14 21:23:14 +0100961 .remove = tc589_detach,
Dominik Brodowski7ffec582005-06-27 16:28:19 -0700962 .id_table = tc589_ids,
Dominik Brodowski98e4c282005-11-14 21:21:18 +0100963 .suspend = tc589_suspend,
964 .resume = tc589_resume,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700965};
966
967static int __init init_tc589(void)
968{
969 return pcmcia_register_driver(&tc589_driver);
970}
971
972static void __exit exit_tc589(void)
973{
974 pcmcia_unregister_driver(&tc589_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975}
976
977module_init(init_tc589);
978module_exit(exit_tc589);