blob: 042f6777e6b9133865ff207c37d45a65a88dffba [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/* 3c574.c: A PCMCIA ethernet driver for the 3com 3c574 "RoadRunner".
2
3 Written 1993-1998 by
4 Donald Becker, becker@scyld.com, (driver core) and
5 David Hinds, dahinds@users.sourceforge.net (from his PC card code).
6 Locking fixes (C) Copyright 2003 Red Hat Inc
7
8 This software may be used and distributed according to the terms of
9 the GNU General Public License, incorporated herein by reference.
10
11 This driver derives from Donald Becker's 3c509 core, which has the
12 following copyright:
13 Copyright 1993 United States Government as represented by the
14 Director, National Security Agency.
15
16
17*/
18
19/*
20 Theory of Operation
21
22I. Board Compatibility
23
24This device driver is designed for the 3Com 3c574 PC card Fast Ethernet
25Adapter.
26
27II. Board-specific settings
28
29None -- PC cards are autoconfigured.
30
31III. Driver operation
32
33The 3c574 uses a Boomerang-style interface, without the bus-master capability.
34See the Boomerang driver and documentation for most details.
35
36IV. Notes and chip documentation.
37
38Two added registers are used to enhance PIO performance, RunnerRdCtrl and
39RunnerWrCtrl. These are 11 bit down-counters that are preloaded with the
40count of word (16 bits) reads or writes the driver is about to do to the Rx
41or Tx FIFO. The chip is then able to hide the internal-PCI-bus to PC-card
42translation latency by buffering the I/O operations with an 8 word FIFO.
43Note: No other chip accesses are permitted when this buffer is used.
44
45A second enhancement is that both attribute and common memory space
460x0800-0x0fff can translated to the PIO FIFO. Thus memory operations (faster
47with *some* PCcard bridges) may be used instead of I/O operations.
48This is enabled by setting the 0x10 bit in the PCMCIA LAN COR.
49
50Some slow PC card bridges work better if they never see a WAIT signal.
51This is configured by setting the 0x20 bit in the PCMCIA LAN COR.
52Only do this after testing that it is reliable and improves performance.
53
54The upper five bits of RunnerRdCtrl are used to window into PCcard
55configuration space registers. Window 0 is the regular Boomerang/Odie
56register set, 1-5 are various PC card control registers, and 16-31 are
57the (reversed!) CIS table.
58
59A final note: writing the InternalConfig register in window 3 with an
60invalid ramWidth is Very Bad.
61
62V. References
63
64http://www.scyld.com/expert/NWay.html
65http://www.national.com/pf/DP/DP83840.html
66
67Thanks to Terry Murphy of 3Com for providing development information for
68earlier 3Com products.
69
70*/
71
Joe Perches636b8112010-08-12 12:22:51 +000072#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
73
Linus Torvalds1da177e2005-04-16 15:20:36 -070074#include <linux/module.h>
75#include <linux/kernel.h>
76#include <linux/init.h>
77#include <linux/slab.h>
78#include <linux/string.h>
79#include <linux/timer.h>
80#include <linux/interrupt.h>
81#include <linux/in.h>
82#include <linux/delay.h>
83#include <linux/netdevice.h>
84#include <linux/etherdevice.h>
85#include <linux/skbuff.h>
86#include <linux/if_arp.h>
87#include <linux/ioport.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070088#include <linux/bitops.h>
Ben Hutchings0fa0ee052009-09-03 10:41:17 +000089#include <linux/mii.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070090
Linus Torvalds1da177e2005-04-16 15:20:36 -070091#include <pcmcia/cs.h>
92#include <pcmcia/cistpl.h>
93#include <pcmcia/cisreg.h>
94#include <pcmcia/ciscode.h>
95#include <pcmcia/ds.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070096
97#include <asm/uaccess.h>
98#include <asm/io.h>
99#include <asm/system.h>
100
101/*====================================================================*/
102
103/* Module parameters */
104
105MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
106MODULE_DESCRIPTION("3Com 3c574 series PCMCIA ethernet driver");
107MODULE_LICENSE("GPL");
108
109#define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0)
110
111/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
112INT_MODULE_PARM(max_interrupt_work, 32);
113
114/* Force full duplex modes? */
115INT_MODULE_PARM(full_duplex, 0);
116
117/* Autodetect link polarity reversal? */
118INT_MODULE_PARM(auto_polarity, 1);
119
Linus Torvalds1da177e2005-04-16 15:20:36 -0700120
121/*====================================================================*/
122
123/* Time in jiffies before concluding the transmitter is hung. */
124#define TX_TIMEOUT ((800*HZ)/1000)
125
126/* To minimize the size of the driver source and make the driver more
127 readable not all constants are symbolically defined.
128 You'll need the manual if you want to understand driver details anyway. */
129/* Offsets from base I/O address. */
130#define EL3_DATA 0x00
131#define EL3_CMD 0x0e
132#define EL3_STATUS 0x0e
133
134#define EL3WINDOW(win_num) outw(SelectWindow + (win_num), ioaddr + EL3_CMD)
135
136/* The top five bits written to EL3_CMD are a command, the lower
137 11 bits are the parameter, if applicable. */
138enum el3_cmds {
139 TotalReset = 0<<11, SelectWindow = 1<<11, StartCoax = 2<<11,
140 RxDisable = 3<<11, RxEnable = 4<<11, RxReset = 5<<11, RxDiscard = 8<<11,
141 TxEnable = 9<<11, TxDisable = 10<<11, TxReset = 11<<11,
142 FakeIntr = 12<<11, AckIntr = 13<<11, SetIntrEnb = 14<<11,
143 SetStatusEnb = 15<<11, SetRxFilter = 16<<11, SetRxThreshold = 17<<11,
144 SetTxThreshold = 18<<11, SetTxStart = 19<<11, StatsEnable = 21<<11,
145 StatsDisable = 22<<11, StopCoax = 23<<11,
146};
147
148enum elxl_status {
149 IntLatch = 0x0001, AdapterFailure = 0x0002, TxComplete = 0x0004,
150 TxAvailable = 0x0008, RxComplete = 0x0010, RxEarly = 0x0020,
151 IntReq = 0x0040, StatsFull = 0x0080, CmdBusy = 0x1000 };
152
153/* The SetRxFilter command accepts the following classes: */
154enum RxFilter {
155 RxStation = 1, RxMulticast = 2, RxBroadcast = 4, RxProm = 8
156};
157
158enum Window0 {
159 Wn0EepromCmd = 10, Wn0EepromData = 12, /* EEPROM command/address, data. */
160 IntrStatus=0x0E, /* Valid in all windows. */
161};
162/* These assumes the larger EEPROM. */
163enum Win0_EEPROM_cmds {
164 EEPROM_Read = 0x200, EEPROM_WRITE = 0x100, EEPROM_ERASE = 0x300,
165 EEPROM_EWENB = 0x30, /* Enable erasing/writing for 10 msec. */
166 EEPROM_EWDIS = 0x00, /* Disable EWENB before 10 msec timeout. */
167};
168
169/* Register window 1 offsets, the window used in normal operation.
170 On the "Odie" this window is always mapped at offsets 0x10-0x1f.
171 Except for TxFree, which is overlapped by RunnerWrCtrl. */
172enum Window1 {
173 TX_FIFO = 0x10, RX_FIFO = 0x10, RxErrors = 0x14,
174 RxStatus = 0x18, Timer=0x1A, TxStatus = 0x1B,
175 TxFree = 0x0C, /* Remaining free bytes in Tx buffer. */
176 RunnerRdCtrl = 0x16, RunnerWrCtrl = 0x1c,
177};
178
179enum Window3 { /* Window 3: MAC/config bits. */
180 Wn3_Config=0, Wn3_MAC_Ctrl=6, Wn3_Options=8,
181};
Al Virob6659822008-01-13 14:17:35 +0000182enum wn3_config {
183 Ram_size = 7,
184 Ram_width = 8,
185 Ram_speed = 0x30,
186 Rom_size = 0xc0,
187 Ram_split_shift = 16,
188 Ram_split = 3 << Ram_split_shift,
189 Xcvr_shift = 20,
190 Xcvr = 7 << Xcvr_shift,
191 Autoselect = 0x1000000,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700192};
193
194enum Window4 { /* Window 4: Xcvr/media bits. */
195 Wn4_FIFODiag = 4, Wn4_NetDiag = 6, Wn4_PhysicalMgmt=8, Wn4_Media = 10,
196};
197
198#define MEDIA_TP 0x00C0 /* Enable link beat and jabber for 10baseT. */
199
200struct el3_private {
Dominik Brodowskifd238232006-03-05 10:45:09 +0100201 struct pcmcia_device *p_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700202 u16 advertising, partner; /* NWay media advertisement */
203 unsigned char phys; /* MII device address */
204 unsigned int autoselect:1, default_media:3; /* Read from the EEPROM/Wn3_Config. */
205 /* for transceiver monitoring */
206 struct timer_list media;
207 unsigned short media_status;
208 unsigned short fast_poll;
209 unsigned long last_irq;
210 spinlock_t window_lock; /* Guards the Window selection */
211};
212
213/* Set iff a MII transceiver on any interface requires mdio preamble.
214 This only set with the original DP83840 on older 3c905 boards, so the extra
215 code size of a per-interface flag is not worthwhile. */
216static char mii_preamble_required = 0;
217
218/* Index of functions. */
219
Dominik Brodowski15b99ac2006-03-31 17:26:06 +0200220static int tc574_config(struct pcmcia_device *link);
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200221static void tc574_release(struct pcmcia_device *link);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700222
Olof Johansson906da802008-02-04 22:27:35 -0800223static void mdio_sync(unsigned int ioaddr, int bits);
224static int mdio_read(unsigned int ioaddr, int phy_id, int location);
225static void mdio_write(unsigned int ioaddr, int phy_id, int location,
226 int value);
227static unsigned short read_eeprom(unsigned int ioaddr, int index);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700228static void tc574_wait_for_completion(struct net_device *dev, int cmd);
229
230static void tc574_reset(struct net_device *dev);
231static void media_check(unsigned long arg);
232static int el3_open(struct net_device *dev);
Stephen Hemmingerdbf02fa2009-08-31 19:50:49 +0000233static netdev_tx_t el3_start_xmit(struct sk_buff *skb,
234 struct net_device *dev);
David Howells7d12e782006-10-05 14:55:46 +0100235static irqreturn_t el3_interrupt(int irq, void *dev_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700236static void update_stats(struct net_device *dev);
237static struct net_device_stats *el3_get_stats(struct net_device *dev);
238static int el3_rx(struct net_device *dev, int worklimit);
239static int el3_close(struct net_device *dev);
240static void el3_tx_timeout(struct net_device *dev);
241static int el3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700242static void set_rx_mode(struct net_device *dev);
Ken Kawasakie3eef532009-10-13 00:32:55 -0700243static void set_multicast_list(struct net_device *dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700244
Dominik Brodowskicc3b4862005-11-14 21:23:14 +0100245static void tc574_detach(struct pcmcia_device *p_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700246
Linus Torvalds1da177e2005-04-16 15:20:36 -0700247/*
248 tc574_attach() creates an "instance" of the driver, allocating
249 local data structures for one device. The device is registered
250 with Card Services.
251*/
Stephen Hemmingerfb72e2f2009-03-20 19:36:02 +0000252static const struct net_device_ops el3_netdev_ops = {
253 .ndo_open = el3_open,
254 .ndo_stop = el3_close,
255 .ndo_start_xmit = el3_start_xmit,
256 .ndo_tx_timeout = el3_tx_timeout,
257 .ndo_get_stats = el3_get_stats,
258 .ndo_do_ioctl = el3_ioctl,
Ken Kawasakie3eef532009-10-13 00:32:55 -0700259 .ndo_set_multicast_list = set_multicast_list,
Stephen Hemmingerfb72e2f2009-03-20 19:36:02 +0000260 .ndo_change_mtu = eth_change_mtu,
261 .ndo_set_mac_address = eth_mac_addr,
262 .ndo_validate_addr = eth_validate_addr,
263};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700264
Dominik Brodowski15b99ac2006-03-31 17:26:06 +0200265static int tc574_probe(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266{
267 struct el3_private *lp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268 struct net_device *dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269
Dominik Brodowskidd0fab52009-10-24 15:51:05 +0200270 dev_dbg(&link->dev, "3c574_attach()\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271
272 /* Create the PC card device object. */
273 dev = alloc_etherdev(sizeof(struct el3_private));
274 if (!dev)
Dominik Brodowskif8cfa612005-11-14 21:25:51 +0100275 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700276 lp = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700277 link->priv = dev;
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200278 lp->p_dev = link;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279
280 spin_lock_init(&lp->window_lock);
Dominik Brodowski90abdc32010-07-24 17:23:51 +0200281 link->resource[0]->end = 32;
282 link->resource[0]->flags |= IO_DATA_PATH_WIDTH_16;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283 link->conf.Attributes = CONF_ENABLE_IRQ;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284 link->conf.IntType = INT_MEMORY_AND_IO;
285 link->conf.ConfigIndex = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286
Stephen Hemmingerfb72e2f2009-03-20 19:36:02 +0000287 dev->netdev_ops = &el3_netdev_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288 dev->watchdog_timeo = TX_TIMEOUT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700289
Dominik Brodowski15b99ac2006-03-31 17:26:06 +0200290 return tc574_config(link);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291} /* tc574_attach */
292
293/*
294
295 This deletes a driver "instance". The device is de-registered
296 with Card Services. If it has been released, all local data
297 structures are freed. Otherwise, the structures will be freed
298 when the device is released.
299
300*/
301
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200302static void tc574_detach(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700303{
304 struct net_device *dev = link->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700305
Dominik Brodowskidd0fab52009-10-24 15:51:05 +0200306 dev_dbg(&link->dev, "3c574_detach()\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307
Dominik Brodowskic7c2fa02010-03-20 19:39:26 +0100308 unregister_netdev(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700309
Dominik Brodowskie2d40962006-03-02 00:09:29 +0100310 tc574_release(link);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700311
Linus Torvalds1da177e2005-04-16 15:20:36 -0700312 free_netdev(dev);
313} /* tc574_detach */
314
315/*
316 tc574_config() is scheduled to run after a CARD_INSERTION event
317 is received, to configure the PCMCIA socket, and to make the
318 ethernet device available to the system.
319*/
320
Arjan van de Venf71e1302006-03-03 21:33:57 -0500321static const char *ram_split[] = {"5:3", "3:1", "1:1", "3:5"};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700322
Dominik Brodowski15b99ac2006-03-31 17:26:06 +0200323static int tc574_config(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700325 struct net_device *dev = link->priv;
326 struct el3_private *lp = netdev_priv(dev);
Dominik Brodowskidd0fab52009-10-24 15:51:05 +0200327 int ret, i, j;
Olof Johansson906da802008-02-04 22:27:35 -0800328 unsigned int ioaddr;
Al Virob1e247a2007-12-22 18:56:13 +0000329 __be16 *phys_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700330 char *cardname;
Al Virob6659822008-01-13 14:17:35 +0000331 __u32 config;
Dominik Brodowskidddfbd82009-10-18 23:54:24 +0200332 u8 *buf;
333 size_t len;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334
Al Virob1e247a2007-12-22 18:56:13 +0000335 phys_addr = (__be16 *)dev->dev_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700336
Dominik Brodowskidd0fab52009-10-24 15:51:05 +0200337 dev_dbg(&link->dev, "3c574_config()\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700338
Dominik Brodowski90abdc32010-07-24 17:23:51 +0200339 link->io_lines = 16;
340
Linus Torvalds1da177e2005-04-16 15:20:36 -0700341 for (i = j = 0; j < 0x400; j += 0x20) {
Dominik Brodowski90abdc32010-07-24 17:23:51 +0200342 link->resource[0]->start = j ^ 0x300;
343 i = pcmcia_request_io(link);
Dominik Brodowski4c89e882008-08-03 10:07:45 +0200344 if (i == 0)
345 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700346 }
Dominik Brodowskidd0fab52009-10-24 15:51:05 +0200347 if (i != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700348 goto failed;
Dominik Brodowskidd0fab52009-10-24 15:51:05 +0200349
Dominik Brodowskieb141202010-03-07 12:21:16 +0100350 ret = pcmcia_request_irq(link, el3_interrupt);
Dominik Brodowskidd0fab52009-10-24 15:51:05 +0200351 if (ret)
352 goto failed;
353
354 ret = pcmcia_request_configuration(link, &link->conf);
355 if (ret)
356 goto failed;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357
Dominik Brodowskieb141202010-03-07 12:21:16 +0100358 dev->irq = link->irq;
Dominik Brodowski9a017a92010-07-24 15:58:54 +0200359 dev->base_addr = link->resource[0]->start;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700360
361 ioaddr = dev->base_addr;
362
363 /* The 3c574 normally uses an EEPROM for configuration info, including
364 the hardware address. The future products may include a modem chip
365 and put the address in the CIS. */
Dominik Brodowskidddfbd82009-10-18 23:54:24 +0200366
367 len = pcmcia_get_tuple(link, 0x88, &buf);
368 if (buf && len >= 6) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700369 for (i = 0; i < 3; i++)
Dominik Brodowskidddfbd82009-10-18 23:54:24 +0200370 phys_addr[i] = htons(le16_to_cpu(buf[i * 2]));
371 kfree(buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700372 } else {
Dominik Brodowskidddfbd82009-10-18 23:54:24 +0200373 kfree(buf); /* 0 < len < 6 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374 EL3WINDOW(0);
375 for (i = 0; i < 3; i++)
376 phys_addr[i] = htons(read_eeprom(ioaddr, i + 10));
Al Virob1e247a2007-12-22 18:56:13 +0000377 if (phys_addr[0] == htons(0x6060)) {
Joe Perches636b8112010-08-12 12:22:51 +0000378 pr_notice("IO port conflict at 0x%03lx-0x%03lx\n",
379 dev->base_addr, dev->base_addr+15);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700380 goto failed;
381 }
382 }
Dominik Brodowskia9606fd2006-06-04 18:06:13 +0200383 if (link->prod_id[1])
384 cardname = link->prod_id[1];
385 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386 cardname = "3Com 3c574";
387
388 {
389 u_char mcr;
390 outw(2<<11, ioaddr + RunnerRdCtrl);
391 mcr = inb(ioaddr + 2);
392 outw(0<<11, ioaddr + RunnerRdCtrl);
Joe Perches636b8112010-08-12 12:22:51 +0000393 pr_info(" ASIC rev %d,", mcr>>3);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700394 EL3WINDOW(3);
Al Virob6659822008-01-13 14:17:35 +0000395 config = inl(ioaddr + Wn3_Config);
396 lp->default_media = (config & Xcvr) >> Xcvr_shift;
397 lp->autoselect = config & Autoselect ? 1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700398 }
399
400 init_timer(&lp->media);
401
402 {
403 int phy;
404
405 /* Roadrunner only: Turn on the MII transceiver */
406 outw(0x8040, ioaddr + Wn3_Options);
407 mdelay(1);
408 outw(0xc040, ioaddr + Wn3_Options);
409 tc574_wait_for_completion(dev, TxReset);
410 tc574_wait_for_completion(dev, RxReset);
411 mdelay(1);
412 outw(0x8040, ioaddr + Wn3_Options);
413
414 EL3WINDOW(4);
415 for (phy = 1; phy <= 32; phy++) {
416 int mii_status;
417 mdio_sync(ioaddr, 32);
418 mii_status = mdio_read(ioaddr, phy & 0x1f, 1);
419 if (mii_status != 0xffff) {
420 lp->phys = phy & 0x1f;
Dominik Brodowskidd0fab52009-10-24 15:51:05 +0200421 dev_dbg(&link->dev, " MII transceiver at "
422 "index %d, status %x.\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423 phy, mii_status);
424 if ((mii_status & 0x0040) == 0)
425 mii_preamble_required = 1;
426 break;
427 }
428 }
429 if (phy > 32) {
Joe Perches636b8112010-08-12 12:22:51 +0000430 pr_notice(" No MII transceivers found!\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431 goto failed;
432 }
433 i = mdio_read(ioaddr, lp->phys, 16) | 0x40;
434 mdio_write(ioaddr, lp->phys, 16, i);
435 lp->advertising = mdio_read(ioaddr, lp->phys, 4);
436 if (full_duplex) {
437 /* Only advertise the FD media types. */
438 lp->advertising &= ~0x02a0;
439 mdio_write(ioaddr, lp->phys, 4, lp->advertising);
440 }
441 }
442
Dominik Brodowskidd2e5a12009-11-03 10:27:34 +0100443 SET_NETDEV_DEV(dev, &link->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444
445 if (register_netdev(dev) != 0) {
Joe Perches636b8112010-08-12 12:22:51 +0000446 pr_notice("register_netdev() failed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447 goto failed;
448 }
449
Joe Perches636b8112010-08-12 12:22:51 +0000450 netdev_info(dev, "%s at io %#3lx, irq %d, hw_addr %pM\n",
451 cardname, dev->base_addr, dev->irq, dev->dev_addr);
452 netdev_info(dev, " %dK FIFO split %s Rx:Tx, %sMII interface.\n",
453 8 << config & Ram_size,
454 ram_split[(config & Ram_split) >> Ram_split_shift],
455 config & Autoselect ? "autoselect " : "");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700456
Dominik Brodowski15b99ac2006-03-31 17:26:06 +0200457 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700458
Linus Torvalds1da177e2005-04-16 15:20:36 -0700459failed:
460 tc574_release(link);
Dominik Brodowski15b99ac2006-03-31 17:26:06 +0200461 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462
463} /* tc574_config */
464
465/*
466 After a card is removed, tc574_release() will unregister the net
467 device, and release the PCMCIA configuration. If the device is
468 still open, this will be postponed until it is closed.
469*/
470
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200471static void tc574_release(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700472{
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200473 pcmcia_disable_device(link);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474}
475
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200476static int tc574_suspend(struct pcmcia_device *link)
Dominik Brodowski98e4c282005-11-14 21:21:18 +0100477{
Dominik Brodowski98e4c282005-11-14 21:21:18 +0100478 struct net_device *dev = link->priv;
479
Dominik Brodowskie2d40962006-03-02 00:09:29 +0100480 if (link->open)
Dominik Brodowski8661bb52006-03-02 00:02:33 +0100481 netif_device_detach(dev);
Dominik Brodowski98e4c282005-11-14 21:21:18 +0100482
483 return 0;
484}
485
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200486static int tc574_resume(struct pcmcia_device *link)
Dominik Brodowski98e4c282005-11-14 21:21:18 +0100487{
Dominik Brodowski98e4c282005-11-14 21:21:18 +0100488 struct net_device *dev = link->priv;
489
Dominik Brodowskie2d40962006-03-02 00:09:29 +0100490 if (link->open) {
Dominik Brodowski8661bb52006-03-02 00:02:33 +0100491 tc574_reset(dev);
492 netif_device_attach(dev);
Dominik Brodowski98e4c282005-11-14 21:21:18 +0100493 }
494
495 return 0;
496}
497
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498static void dump_status(struct net_device *dev)
499{
Olof Johansson906da802008-02-04 22:27:35 -0800500 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501 EL3WINDOW(1);
Joe Perches636b8112010-08-12 12:22:51 +0000502 netdev_info(dev, " irq status %04x, rx status %04x, tx status %02x, tx free %04x\n",
503 inw(ioaddr+EL3_STATUS),
504 inw(ioaddr+RxStatus), inb(ioaddr+TxStatus),
505 inw(ioaddr+TxFree));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506 EL3WINDOW(4);
Joe Perches636b8112010-08-12 12:22:51 +0000507 netdev_info(dev, " diagnostics: fifo %04x net %04x ethernet %04x media %04x\n",
508 inw(ioaddr+0x04), inw(ioaddr+0x06),
509 inw(ioaddr+0x08), inw(ioaddr+0x0a));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510 EL3WINDOW(1);
511}
512
513/*
514 Use this for commands that may take time to finish
515*/
516static void tc574_wait_for_completion(struct net_device *dev, int cmd)
517{
518 int i = 1500;
519 outw(cmd, dev->base_addr + EL3_CMD);
520 while (--i > 0)
521 if (!(inw(dev->base_addr + EL3_STATUS) & 0x1000)) break;
522 if (i == 0)
Joe Perches636b8112010-08-12 12:22:51 +0000523 netdev_notice(dev, "command 0x%04x did not complete!\n", cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700524}
525
526/* Read a word from the EEPROM using the regular EEPROM access register.
527 Assume that we are in register window zero.
528 */
Olof Johansson906da802008-02-04 22:27:35 -0800529static unsigned short read_eeprom(unsigned int ioaddr, int index)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530{
531 int timer;
532 outw(EEPROM_Read + index, ioaddr + Wn0EepromCmd);
533 /* Pause for at least 162 usec for the read to take place. */
534 for (timer = 1620; timer >= 0; timer--) {
535 if ((inw(ioaddr + Wn0EepromCmd) & 0x8000) == 0)
536 break;
537 }
538 return inw(ioaddr + Wn0EepromData);
539}
540
541/* MII transceiver control section.
542 Read and write the MII registers using software-generated serial
543 MDIO protocol. See the MII specifications or DP83840A data sheet
544 for details.
545 The maxium data clock rate is 2.5 Mhz. The timing is easily met by the
546 slow PC card interface. */
547
548#define MDIO_SHIFT_CLK 0x01
549#define MDIO_DIR_WRITE 0x04
550#define MDIO_DATA_WRITE0 (0x00 | MDIO_DIR_WRITE)
551#define MDIO_DATA_WRITE1 (0x02 | MDIO_DIR_WRITE)
552#define MDIO_DATA_READ 0x02
553#define MDIO_ENB_IN 0x00
554
555/* Generate the preamble required for initial synchronization and
556 a few older transceivers. */
Olof Johansson906da802008-02-04 22:27:35 -0800557static void mdio_sync(unsigned int ioaddr, int bits)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558{
Olof Johansson906da802008-02-04 22:27:35 -0800559 unsigned int mdio_addr = ioaddr + Wn4_PhysicalMgmt;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560
561 /* Establish sync by sending at least 32 logic ones. */
562 while (-- bits >= 0) {
563 outw(MDIO_DATA_WRITE1, mdio_addr);
564 outw(MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, mdio_addr);
565 }
566}
567
Olof Johansson906da802008-02-04 22:27:35 -0800568static int mdio_read(unsigned int ioaddr, int phy_id, int location)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700569{
570 int i;
571 int read_cmd = (0xf6 << 10) | (phy_id << 5) | location;
572 unsigned int retval = 0;
Olof Johansson906da802008-02-04 22:27:35 -0800573 unsigned int mdio_addr = ioaddr + Wn4_PhysicalMgmt;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700574
575 if (mii_preamble_required)
576 mdio_sync(ioaddr, 32);
577
578 /* Shift the read command bits out. */
579 for (i = 14; i >= 0; i--) {
580 int dataval = (read_cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0;
581 outw(dataval, mdio_addr);
582 outw(dataval | MDIO_SHIFT_CLK, mdio_addr);
583 }
584 /* Read the two transition, 16 data, and wire-idle bits. */
585 for (i = 19; i > 0; i--) {
586 outw(MDIO_ENB_IN, mdio_addr);
587 retval = (retval << 1) | ((inw(mdio_addr) & MDIO_DATA_READ) ? 1 : 0);
588 outw(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr);
589 }
590 return (retval>>1) & 0xffff;
591}
592
Olof Johansson906da802008-02-04 22:27:35 -0800593static void mdio_write(unsigned int ioaddr, int phy_id, int location, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700594{
595 int write_cmd = 0x50020000 | (phy_id << 23) | (location << 18) | value;
Olof Johansson906da802008-02-04 22:27:35 -0800596 unsigned int mdio_addr = ioaddr + Wn4_PhysicalMgmt;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700597 int i;
598
599 if (mii_preamble_required)
600 mdio_sync(ioaddr, 32);
601
602 /* Shift the command bits out. */
603 for (i = 31; i >= 0; i--) {
604 int dataval = (write_cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0;
605 outw(dataval, mdio_addr);
606 outw(dataval | MDIO_SHIFT_CLK, mdio_addr);
607 }
608 /* Leave the interface idle. */
609 for (i = 1; i >= 0; i--) {
610 outw(MDIO_ENB_IN, mdio_addr);
611 outw(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr);
612 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613}
614
615/* Reset and restore all of the 3c574 registers. */
616static void tc574_reset(struct net_device *dev)
617{
618 struct el3_private *lp = netdev_priv(dev);
619 int i;
Olof Johansson906da802008-02-04 22:27:35 -0800620 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700621 unsigned long flags;
622
623 tc574_wait_for_completion(dev, TotalReset|0x10);
624
625 spin_lock_irqsave(&lp->window_lock, flags);
626 /* Clear any transactions in progress. */
627 outw(0, ioaddr + RunnerWrCtrl);
628 outw(0, ioaddr + RunnerRdCtrl);
629
630 /* Set the station address and mask. */
631 EL3WINDOW(2);
632 for (i = 0; i < 6; i++)
633 outb(dev->dev_addr[i], ioaddr + i);
634 for (; i < 12; i+=2)
635 outw(0, ioaddr + i);
636
637 /* Reset config options */
638 EL3WINDOW(3);
639 outb((dev->mtu > 1500 ? 0x40 : 0), ioaddr + Wn3_MAC_Ctrl);
640 outl((lp->autoselect ? 0x01000000 : 0) | 0x0062001b,
641 ioaddr + Wn3_Config);
642 /* Roadrunner only: Turn on the MII transceiver. */
643 outw(0x8040, ioaddr + Wn3_Options);
644 mdelay(1);
645 outw(0xc040, ioaddr + Wn3_Options);
646 EL3WINDOW(1);
647 spin_unlock_irqrestore(&lp->window_lock, flags);
648
649 tc574_wait_for_completion(dev, TxReset);
650 tc574_wait_for_completion(dev, RxReset);
651 mdelay(1);
652 spin_lock_irqsave(&lp->window_lock, flags);
653 EL3WINDOW(3);
654 outw(0x8040, ioaddr + Wn3_Options);
655
656 /* Switch to the stats window, and clear all stats by reading. */
657 outw(StatsDisable, ioaddr + EL3_CMD);
658 EL3WINDOW(6);
659 for (i = 0; i < 10; i++)
660 inb(ioaddr + i);
661 inw(ioaddr + 10);
662 inw(ioaddr + 12);
663 EL3WINDOW(4);
664 inb(ioaddr + 12);
665 inb(ioaddr + 13);
666
667 /* .. enable any extra statistics bits.. */
668 outw(0x0040, ioaddr + Wn4_NetDiag);
669
670 EL3WINDOW(1);
671 spin_unlock_irqrestore(&lp->window_lock, flags);
672
673 /* .. re-sync MII and re-fill what NWay is advertising. */
674 mdio_sync(ioaddr, 32);
675 mdio_write(ioaddr, lp->phys, 4, lp->advertising);
676 if (!auto_polarity) {
677 /* works for TDK 78Q2120 series MII's */
Richard Knutsson1569d9e2008-02-04 22:27:39 -0800678 i = mdio_read(ioaddr, lp->phys, 16) | 0x20;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700679 mdio_write(ioaddr, lp->phys, 16, i);
680 }
681
682 spin_lock_irqsave(&lp->window_lock, flags);
683 /* Switch to register set 1 for normal use, just for TxFree. */
684 set_rx_mode(dev);
685 spin_unlock_irqrestore(&lp->window_lock, flags);
686 outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */
687 outw(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */
688 outw(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */
689 /* Allow status bits to be seen. */
690 outw(SetStatusEnb | 0xff, ioaddr + EL3_CMD);
691 /* Ack all pending events, and set active indicator mask. */
692 outw(AckIntr | IntLatch | TxAvailable | RxEarly | IntReq,
693 ioaddr + EL3_CMD);
694 outw(SetIntrEnb | IntLatch | TxAvailable | RxComplete | StatsFull
695 | AdapterFailure | RxEarly, ioaddr + EL3_CMD);
696}
697
698static int el3_open(struct net_device *dev)
699{
700 struct el3_private *lp = netdev_priv(dev);
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200701 struct pcmcia_device *link = lp->p_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700702
Dominik Brodowski9940ec32006-03-05 11:04:33 +0100703 if (!pcmcia_dev_present(link))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700704 return -ENODEV;
705
706 link->open++;
707 netif_start_queue(dev);
708
709 tc574_reset(dev);
Joe Perchesc061b182010-08-23 18:20:03 +0000710 lp->media.function = media_check;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711 lp->media.data = (unsigned long) dev;
712 lp->media.expires = jiffies + HZ;
713 add_timer(&lp->media);
714
Dominik Brodowskidd0fab52009-10-24 15:51:05 +0200715 dev_dbg(&link->dev, "%s: opened, status %4.4x.\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700716 dev->name, inw(dev->base_addr + EL3_STATUS));
717
718 return 0;
719}
720
721static void el3_tx_timeout(struct net_device *dev)
722{
Olof Johansson906da802008-02-04 22:27:35 -0800723 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700724
Joe Perches636b8112010-08-12 12:22:51 +0000725 netdev_notice(dev, "Transmit timed out!\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700726 dump_status(dev);
Paulius Zaleckas2e8d31d2008-04-30 01:08:26 +0300727 dev->stats.tx_errors++;
Eric Dumazet1ae5dc32010-05-10 05:01:31 -0700728 dev->trans_start = jiffies; /* prevent tx timeout */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700729 /* Issue TX_RESET and TX_START commands. */
730 tc574_wait_for_completion(dev, TxReset);
731 outw(TxEnable, ioaddr + EL3_CMD);
732 netif_wake_queue(dev);
733}
734
735static void pop_tx_status(struct net_device *dev)
736{
Olof Johansson906da802008-02-04 22:27:35 -0800737 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700738 int i;
739
740 /* Clear the Tx status stack. */
741 for (i = 32; i > 0; i--) {
742 u_char tx_status = inb(ioaddr + TxStatus);
743 if (!(tx_status & 0x84))
744 break;
745 /* reset transmitter on jabber error or underrun */
746 if (tx_status & 0x30)
747 tc574_wait_for_completion(dev, TxReset);
748 if (tx_status & 0x38) {
Dominik Brodowskidd0fab52009-10-24 15:51:05 +0200749 pr_debug("%s: transmit error: status 0x%02x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700750 dev->name, tx_status);
751 outw(TxEnable, ioaddr + EL3_CMD);
Paulius Zaleckas2e8d31d2008-04-30 01:08:26 +0300752 dev->stats.tx_aborted_errors++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700753 }
754 outb(0x00, ioaddr + TxStatus); /* Pop the status stack. */
755 }
756}
757
Stephen Hemmingerdbf02fa2009-08-31 19:50:49 +0000758static netdev_tx_t el3_start_xmit(struct sk_buff *skb,
759 struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700760{
Olof Johansson906da802008-02-04 22:27:35 -0800761 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700762 struct el3_private *lp = netdev_priv(dev);
763 unsigned long flags;
764
Dominik Brodowskidd0fab52009-10-24 15:51:05 +0200765 pr_debug("%s: el3_start_xmit(length = %ld) called, "
Linus Torvalds1da177e2005-04-16 15:20:36 -0700766 "status %4.4x.\n", dev->name, (long)skb->len,
767 inw(ioaddr + EL3_STATUS));
768
769 spin_lock_irqsave(&lp->window_lock, flags);
Alexander Kurzdf245dc2010-04-16 03:01:01 +0000770
771 dev->stats.tx_bytes += skb->len;
772
773 /* Put out the doubleword header... */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700774 outw(skb->len, ioaddr + TX_FIFO);
775 outw(0, ioaddr + TX_FIFO);
Alexander Kurzdf245dc2010-04-16 03:01:01 +0000776 /* ... and the packet rounded to a doubleword. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700777 outsl(ioaddr + TX_FIFO, skb->data, (skb->len+3)>>2);
778
Linus Torvalds1da177e2005-04-16 15:20:36 -0700779 /* TxFree appears only in Window 1, not offset 0x1c. */
780 if (inw(ioaddr + TxFree) <= 1536) {
781 netif_stop_queue(dev);
782 /* Interrupt us when the FIFO has room for max-sized packet.
783 The threshold is in units of dwords. */
784 outw(SetTxThreshold + (1536>>2), ioaddr + EL3_CMD);
785 }
786
787 pop_tx_status(dev);
788 spin_unlock_irqrestore(&lp->window_lock, flags);
789 dev_kfree_skb(skb);
Patrick McHardy6ed10652009-06-23 06:03:08 +0000790 return NETDEV_TX_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700791}
792
793/* The EL3 interrupt handler. */
David Howells7d12e782006-10-05 14:55:46 +0100794static irqreturn_t el3_interrupt(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700795{
796 struct net_device *dev = (struct net_device *) dev_id;
797 struct el3_private *lp = netdev_priv(dev);
Olof Johansson906da802008-02-04 22:27:35 -0800798 unsigned int ioaddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799 unsigned status;
800 int work_budget = max_interrupt_work;
801 int handled = 0;
802
803 if (!netif_device_present(dev))
804 return IRQ_NONE;
805 ioaddr = dev->base_addr;
806
Dominik Brodowskidd0fab52009-10-24 15:51:05 +0200807 pr_debug("%s: interrupt, status %4.4x.\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700808 dev->name, inw(ioaddr + EL3_STATUS));
809
810 spin_lock(&lp->window_lock);
811
812 while ((status = inw(ioaddr + EL3_STATUS)) &
813 (IntLatch | RxComplete | RxEarly | StatsFull)) {
814 if (!netif_device_present(dev) ||
815 ((status & 0xe000) != 0x2000)) {
Dominik Brodowskidd0fab52009-10-24 15:51:05 +0200816 pr_debug("%s: Interrupt from dead card\n", dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700817 break;
818 }
819
820 handled = 1;
821
822 if (status & RxComplete)
823 work_budget = el3_rx(dev, work_budget);
824
825 if (status & TxAvailable) {
Dominik Brodowskidd0fab52009-10-24 15:51:05 +0200826 pr_debug(" TX room bit was handled.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827 /* There's room in the FIFO for a full-sized packet. */
828 outw(AckIntr | TxAvailable, ioaddr + EL3_CMD);
829 netif_wake_queue(dev);
830 }
831
832 if (status & TxComplete)
833 pop_tx_status(dev);
834
835 if (status & (AdapterFailure | RxEarly | StatsFull)) {
836 /* Handle all uncommon interrupts. */
837 if (status & StatsFull)
838 update_stats(dev);
839 if (status & RxEarly) {
840 work_budget = el3_rx(dev, work_budget);
841 outw(AckIntr | RxEarly, ioaddr + EL3_CMD);
842 }
843 if (status & AdapterFailure) {
844 u16 fifo_diag;
845 EL3WINDOW(4);
846 fifo_diag = inw(ioaddr + Wn4_FIFODiag);
847 EL3WINDOW(1);
Joe Perches636b8112010-08-12 12:22:51 +0000848 netdev_notice(dev, "adapter failure, FIFO diagnostic register %04x\n",
849 fifo_diag);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700850 if (fifo_diag & 0x0400) {
851 /* Tx overrun */
852 tc574_wait_for_completion(dev, TxReset);
853 outw(TxEnable, ioaddr + EL3_CMD);
854 }
855 if (fifo_diag & 0x2000) {
856 /* Rx underrun */
857 tc574_wait_for_completion(dev, RxReset);
858 set_rx_mode(dev);
859 outw(RxEnable, ioaddr + EL3_CMD);
860 }
861 outw(AckIntr | AdapterFailure, ioaddr + EL3_CMD);
862 }
863 }
864
865 if (--work_budget < 0) {
Dominik Brodowskidd0fab52009-10-24 15:51:05 +0200866 pr_debug("%s: Too much work in interrupt, "
Linus Torvalds1da177e2005-04-16 15:20:36 -0700867 "status %4.4x.\n", dev->name, status);
868 /* Clear all interrupts */
869 outw(AckIntr | 0xFF, ioaddr + EL3_CMD);
870 break;
871 }
872 /* Acknowledge the IRQ. */
873 outw(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD);
874 }
875
Dominik Brodowskidd0fab52009-10-24 15:51:05 +0200876 pr_debug("%s: exiting interrupt, status %4.4x.\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700877 dev->name, inw(ioaddr + EL3_STATUS));
878
879 spin_unlock(&lp->window_lock);
880 return IRQ_RETVAL(handled);
881}
882
883/*
884 This timer serves two purposes: to check for missed interrupts
885 (and as a last resort, poll the NIC for events), and to monitor
886 the MII, reporting changes in cable status.
887*/
888static void media_check(unsigned long arg)
889{
890 struct net_device *dev = (struct net_device *) arg;
891 struct el3_private *lp = netdev_priv(dev);
Olof Johansson906da802008-02-04 22:27:35 -0800892 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700893 unsigned long flags;
894 unsigned short /* cable, */ media, partner;
895
896 if (!netif_device_present(dev))
897 goto reschedule;
898
899 /* Check for pending interrupt with expired latency timer: with
900 this, we can limp along even if the interrupt is blocked */
901 if ((inw(ioaddr + EL3_STATUS) & IntLatch) && (inb(ioaddr + Timer) == 0xff)) {
902 if (!lp->fast_poll)
Joe Perches636b8112010-08-12 12:22:51 +0000903 netdev_info(dev, "interrupt(s) dropped!\n");
Ken Kawasaki671c8802009-12-12 14:44:11 +0000904
905 local_irq_save(flags);
Komuroe363d132007-02-10 11:57:35 +0900906 el3_interrupt(dev->irq, dev);
Ken Kawasaki671c8802009-12-12 14:44:11 +0000907 local_irq_restore(flags);
908
Linus Torvalds1da177e2005-04-16 15:20:36 -0700909 lp->fast_poll = HZ;
910 }
911 if (lp->fast_poll) {
912 lp->fast_poll--;
913 lp->media.expires = jiffies + 2*HZ/100;
914 add_timer(&lp->media);
915 return;
916 }
917
918 spin_lock_irqsave(&lp->window_lock, flags);
919 EL3WINDOW(4);
920 media = mdio_read(ioaddr, lp->phys, 1);
921 partner = mdio_read(ioaddr, lp->phys, 5);
922 EL3WINDOW(1);
923
924 if (media != lp->media_status) {
925 if ((media ^ lp->media_status) & 0x0004)
Joe Perches636b8112010-08-12 12:22:51 +0000926 netdev_info(dev, "%s link beat\n",
927 (lp->media_status & 0x0004) ? "lost" : "found");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700928 if ((media ^ lp->media_status) & 0x0020) {
929 lp->partner = 0;
930 if (lp->media_status & 0x0020) {
Joe Perches636b8112010-08-12 12:22:51 +0000931 netdev_info(dev, "autonegotiation restarted\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700932 } else if (partner) {
933 partner &= lp->advertising;
934 lp->partner = partner;
Joe Perches636b8112010-08-12 12:22:51 +0000935 netdev_info(dev, "autonegotiation complete: "
936 "%dbaseT-%cD selected\n",
937 (partner & 0x0180) ? 100 : 10,
938 (partner & 0x0140) ? 'F' : 'H');
Linus Torvalds1da177e2005-04-16 15:20:36 -0700939 } else {
Joe Perches636b8112010-08-12 12:22:51 +0000940 netdev_info(dev, "link partner did not autonegotiate\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700941 }
942
943 EL3WINDOW(3);
944 outb((partner & 0x0140 ? 0x20 : 0) |
945 (dev->mtu > 1500 ? 0x40 : 0), ioaddr + Wn3_MAC_Ctrl);
946 EL3WINDOW(1);
947
948 }
949 if (media & 0x0010)
Joe Perches636b8112010-08-12 12:22:51 +0000950 netdev_info(dev, "remote fault detected\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700951 if (media & 0x0002)
Joe Perches636b8112010-08-12 12:22:51 +0000952 netdev_info(dev, "jabber detected\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700953 lp->media_status = media;
954 }
955 spin_unlock_irqrestore(&lp->window_lock, flags);
956
957reschedule:
958 lp->media.expires = jiffies + HZ;
959 add_timer(&lp->media);
960}
961
962static struct net_device_stats *el3_get_stats(struct net_device *dev)
963{
964 struct el3_private *lp = netdev_priv(dev);
965
966 if (netif_device_present(dev)) {
967 unsigned long flags;
968 spin_lock_irqsave(&lp->window_lock, flags);
969 update_stats(dev);
970 spin_unlock_irqrestore(&lp->window_lock, flags);
971 }
Paulius Zaleckas2e8d31d2008-04-30 01:08:26 +0300972 return &dev->stats;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700973}
974
975/* Update statistics.
976 Suprisingly this need not be run single-threaded, but it effectively is.
977 The counters clear when read, so the adds must merely be atomic.
978 */
979static void update_stats(struct net_device *dev)
980{
Olof Johansson906da802008-02-04 22:27:35 -0800981 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700982 u8 rx, tx, up;
983
Dominik Brodowskidd0fab52009-10-24 15:51:05 +0200984 pr_debug("%s: updating the statistics.\n", dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700985
986 if (inw(ioaddr+EL3_STATUS) == 0xffff) /* No card. */
987 return;
988
989 /* Unlike the 3c509 we need not turn off stats updates while reading. */
990 /* Switch to the stats window, and read everything. */
991 EL3WINDOW(6);
Paulius Zaleckas2e8d31d2008-04-30 01:08:26 +0300992 dev->stats.tx_carrier_errors += inb(ioaddr + 0);
993 dev->stats.tx_heartbeat_errors += inb(ioaddr + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700994 /* Multiple collisions. */ inb(ioaddr + 2);
Paulius Zaleckas2e8d31d2008-04-30 01:08:26 +0300995 dev->stats.collisions += inb(ioaddr + 3);
996 dev->stats.tx_window_errors += inb(ioaddr + 4);
997 dev->stats.rx_fifo_errors += inb(ioaddr + 5);
998 dev->stats.tx_packets += inb(ioaddr + 6);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700999 up = inb(ioaddr + 9);
Paulius Zaleckas2e8d31d2008-04-30 01:08:26 +03001000 dev->stats.tx_packets += (up&0x30) << 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001001 /* Rx packets */ inb(ioaddr + 7);
1002 /* Tx deferrals */ inb(ioaddr + 8);
1003 rx = inw(ioaddr + 10);
1004 tx = inw(ioaddr + 12);
1005
1006 EL3WINDOW(4);
1007 /* BadSSD */ inb(ioaddr + 12);
1008 up = inb(ioaddr + 13);
1009
Linus Torvalds1da177e2005-04-16 15:20:36 -07001010 EL3WINDOW(1);
1011}
1012
1013static int el3_rx(struct net_device *dev, int worklimit)
1014{
Olof Johansson906da802008-02-04 22:27:35 -08001015 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001016 short rx_status;
1017
Dominik Brodowskidd0fab52009-10-24 15:51:05 +02001018 pr_debug("%s: in rx_packet(), status %4.4x, rx_status %4.4x.\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001019 dev->name, inw(ioaddr+EL3_STATUS), inw(ioaddr+RxStatus));
1020 while (!((rx_status = inw(ioaddr + RxStatus)) & 0x8000) &&
Roel Kluinb9bdcd92009-03-04 00:05:56 -08001021 worklimit > 0) {
1022 worklimit--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001023 if (rx_status & 0x4000) { /* Error, update stats. */
1024 short error = rx_status & 0x3800;
Paulius Zaleckas2e8d31d2008-04-30 01:08:26 +03001025 dev->stats.rx_errors++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001026 switch (error) {
Paulius Zaleckas2e8d31d2008-04-30 01:08:26 +03001027 case 0x0000: dev->stats.rx_over_errors++; break;
1028 case 0x0800: dev->stats.rx_length_errors++; break;
1029 case 0x1000: dev->stats.rx_frame_errors++; break;
1030 case 0x1800: dev->stats.rx_length_errors++; break;
1031 case 0x2000: dev->stats.rx_frame_errors++; break;
1032 case 0x2800: dev->stats.rx_crc_errors++; break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033 }
1034 } else {
1035 short pkt_len = rx_status & 0x7ff;
1036 struct sk_buff *skb;
1037
1038 skb = dev_alloc_skb(pkt_len+5);
1039
Dominik Brodowskidd0fab52009-10-24 15:51:05 +02001040 pr_debug(" Receiving packet size %d status %4.4x.\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001041 pkt_len, rx_status);
1042 if (skb != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001043 skb_reserve(skb, 2);
1044 insl(ioaddr+RX_FIFO, skb_put(skb, pkt_len),
1045 ((pkt_len+3)>>2));
1046 skb->protocol = eth_type_trans(skb, dev);
1047 netif_rx(skb);
Paulius Zaleckas2e8d31d2008-04-30 01:08:26 +03001048 dev->stats.rx_packets++;
1049 dev->stats.rx_bytes += pkt_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001050 } else {
Dominik Brodowskidd0fab52009-10-24 15:51:05 +02001051 pr_debug("%s: couldn't allocate a sk_buff of"
Linus Torvalds1da177e2005-04-16 15:20:36 -07001052 " size %d.\n", dev->name, pkt_len);
Paulius Zaleckas2e8d31d2008-04-30 01:08:26 +03001053 dev->stats.rx_dropped++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001054 }
1055 }
1056 tc574_wait_for_completion(dev, RxDiscard);
1057 }
1058
1059 return worklimit;
1060}
1061
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062/* Provide ioctl() calls to examine the MII xcvr state. */
1063static int el3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
1064{
1065 struct el3_private *lp = netdev_priv(dev);
Olof Johansson906da802008-02-04 22:27:35 -08001066 unsigned int ioaddr = dev->base_addr;
Ben Hutchings0fa0ee052009-09-03 10:41:17 +00001067 struct mii_ioctl_data *data = if_mii(rq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068 int phy = lp->phys & 0x1f;
1069
Dominik Brodowskidd0fab52009-10-24 15:51:05 +02001070 pr_debug("%s: In ioct(%-.6s, %#4.4x) %4.4x %4.4x %4.4x %4.4x.\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001071 dev->name, rq->ifr_ifrn.ifrn_name, cmd,
Ben Hutchings0fa0ee052009-09-03 10:41:17 +00001072 data->phy_id, data->reg_num, data->val_in, data->val_out);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001073
1074 switch(cmd) {
1075 case SIOCGMIIPHY: /* Get the address of the PHY in use. */
Ben Hutchings0fa0ee052009-09-03 10:41:17 +00001076 data->phy_id = phy;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001077 case SIOCGMIIREG: /* Read the specified MII register. */
1078 {
1079 int saved_window;
1080 unsigned long flags;
1081
1082 spin_lock_irqsave(&lp->window_lock, flags);
1083 saved_window = inw(ioaddr + EL3_CMD) >> 13;
1084 EL3WINDOW(4);
Ben Hutchings0fa0ee052009-09-03 10:41:17 +00001085 data->val_out = mdio_read(ioaddr, data->phy_id & 0x1f,
1086 data->reg_num & 0x1f);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001087 EL3WINDOW(saved_window);
1088 spin_unlock_irqrestore(&lp->window_lock, flags);
1089 return 0;
1090 }
1091 case SIOCSMIIREG: /* Write the specified MII register */
1092 {
1093 int saved_window;
1094 unsigned long flags;
1095
Linus Torvalds1da177e2005-04-16 15:20:36 -07001096 spin_lock_irqsave(&lp->window_lock, flags);
1097 saved_window = inw(ioaddr + EL3_CMD) >> 13;
1098 EL3WINDOW(4);
Ben Hutchings0fa0ee052009-09-03 10:41:17 +00001099 mdio_write(ioaddr, data->phy_id & 0x1f,
1100 data->reg_num & 0x1f, data->val_in);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001101 EL3WINDOW(saved_window);
1102 spin_unlock_irqrestore(&lp->window_lock, flags);
1103 return 0;
1104 }
1105 default:
1106 return -EOPNOTSUPP;
1107 }
1108}
1109
1110/* The Odie chip has a 64 bin multicast filter, but the bit layout is not
1111 documented. Until it is we revert to receiving all multicast frames when
1112 any multicast reception is desired.
1113 Note: My other drivers emit a log message whenever promiscuous mode is
1114 entered to help detect password sniffers. This is less desirable on
1115 typical PC card machines, so we omit the message.
1116 */
1117
1118static void set_rx_mode(struct net_device *dev)
1119{
Olof Johansson906da802008-02-04 22:27:35 -08001120 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001121
1122 if (dev->flags & IFF_PROMISC)
1123 outw(SetRxFilter | RxStation | RxMulticast | RxBroadcast | RxProm,
1124 ioaddr + EL3_CMD);
Jiri Pirko4cd24ea2010-02-08 04:30:35 +00001125 else if (!netdev_mc_empty(dev) || (dev->flags & IFF_ALLMULTI))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001126 outw(SetRxFilter|RxStation|RxMulticast|RxBroadcast, ioaddr + EL3_CMD);
1127 else
1128 outw(SetRxFilter | RxStation | RxBroadcast, ioaddr + EL3_CMD);
1129}
1130
Ken Kawasakie3eef532009-10-13 00:32:55 -07001131static void set_multicast_list(struct net_device *dev)
1132{
1133 struct el3_private *lp = netdev_priv(dev);
1134 unsigned long flags;
1135
1136 spin_lock_irqsave(&lp->window_lock, flags);
1137 set_rx_mode(dev);
1138 spin_unlock_irqrestore(&lp->window_lock, flags);
1139}
1140
Linus Torvalds1da177e2005-04-16 15:20:36 -07001141static int el3_close(struct net_device *dev)
1142{
Olof Johansson906da802008-02-04 22:27:35 -08001143 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001144 struct el3_private *lp = netdev_priv(dev);
Dominik Brodowskifba395e2006-03-31 17:21:06 +02001145 struct pcmcia_device *link = lp->p_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001146
Dominik Brodowskidd0fab52009-10-24 15:51:05 +02001147 dev_dbg(&link->dev, "%s: shutting down ethercard.\n", dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001148
Dominik Brodowski9940ec32006-03-05 11:04:33 +01001149 if (pcmcia_dev_present(link)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001150 unsigned long flags;
1151
1152 /* Turn off statistics ASAP. We update lp->stats below. */
1153 outw(StatsDisable, ioaddr + EL3_CMD);
1154
1155 /* Disable the receiver and transmitter. */
1156 outw(RxDisable, ioaddr + EL3_CMD);
1157 outw(TxDisable, ioaddr + EL3_CMD);
1158
1159 /* Note: Switching to window 0 may disable the IRQ. */
1160 EL3WINDOW(0);
1161 spin_lock_irqsave(&lp->window_lock, flags);
1162 update_stats(dev);
1163 spin_unlock_irqrestore(&lp->window_lock, flags);
Daniel Ritzb9a6eaf2005-04-10 20:27:45 +02001164
1165 /* force interrupts off */
1166 outw(SetIntrEnb | 0x0000, ioaddr + EL3_CMD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001167 }
1168
1169 link->open--;
1170 netif_stop_queue(dev);
1171 del_timer_sync(&lp->media);
1172
1173 return 0;
1174}
1175
Dominik Brodowski270b6e92005-06-27 16:28:18 -07001176static struct pcmcia_device_id tc574_ids[] = {
1177 PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0574),
Ken Kawasakif0a3a152009-05-01 19:21:26 -07001178 PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0101, 0x0556, "cis/3CCFEM556.cis"),
Dominik Brodowski270b6e92005-06-27 16:28:18 -07001179 PCMCIA_DEVICE_NULL,
1180};
1181MODULE_DEVICE_TABLE(pcmcia, tc574_ids);
1182
Linus Torvalds1da177e2005-04-16 15:20:36 -07001183static struct pcmcia_driver tc574_driver = {
1184 .owner = THIS_MODULE,
1185 .drv = {
1186 .name = "3c574_cs",
1187 },
Dominik Brodowski15b99ac2006-03-31 17:26:06 +02001188 .probe = tc574_probe,
Dominik Brodowskicc3b4862005-11-14 21:23:14 +01001189 .remove = tc574_detach,
Dominik Brodowski270b6e92005-06-27 16:28:18 -07001190 .id_table = tc574_ids,
Dominik Brodowski98e4c282005-11-14 21:21:18 +01001191 .suspend = tc574_suspend,
1192 .resume = tc574_resume,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001193};
1194
1195static int __init init_tc574(void)
1196{
1197 return pcmcia_register_driver(&tc574_driver);
1198}
1199
1200static void __exit exit_tc574(void)
1201{
1202 pcmcia_unregister_driver(&tc574_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001203}
1204
1205module_init(init_tc574);
1206module_exit(exit_tc574);