blob: 9a1840b67e78826d2def1371c8c103f0e8f4333e [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
72#include <linux/module.h>
73#include <linux/kernel.h>
74#include <linux/init.h>
75#include <linux/slab.h>
76#include <linux/string.h>
77#include <linux/timer.h>
78#include <linux/interrupt.h>
79#include <linux/in.h>
80#include <linux/delay.h>
81#include <linux/netdevice.h>
82#include <linux/etherdevice.h>
83#include <linux/skbuff.h>
84#include <linux/if_arp.h>
85#include <linux/ioport.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070086#include <linux/bitops.h>
Ben Hutchings0fa0ee052009-09-03 10:41:17 +000087#include <linux/mii.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070088
Linus Torvalds1da177e2005-04-16 15:20:36 -070089#include <pcmcia/cs.h>
90#include <pcmcia/cistpl.h>
91#include <pcmcia/cisreg.h>
92#include <pcmcia/ciscode.h>
93#include <pcmcia/ds.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070094
95#include <asm/uaccess.h>
96#include <asm/io.h>
97#include <asm/system.h>
98
99/*====================================================================*/
100
101/* Module parameters */
102
103MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
104MODULE_DESCRIPTION("3Com 3c574 series PCMCIA ethernet driver");
105MODULE_LICENSE("GPL");
106
107#define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0)
108
109/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
110INT_MODULE_PARM(max_interrupt_work, 32);
111
112/* Force full duplex modes? */
113INT_MODULE_PARM(full_duplex, 0);
114
115/* Autodetect link polarity reversal? */
116INT_MODULE_PARM(auto_polarity, 1);
117
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118
119/*====================================================================*/
120
121/* Time in jiffies before concluding the transmitter is hung. */
122#define TX_TIMEOUT ((800*HZ)/1000)
123
124/* To minimize the size of the driver source and make the driver more
125 readable not all constants are symbolically defined.
126 You'll need the manual if you want to understand driver details anyway. */
127/* Offsets from base I/O address. */
128#define EL3_DATA 0x00
129#define EL3_CMD 0x0e
130#define EL3_STATUS 0x0e
131
132#define EL3WINDOW(win_num) outw(SelectWindow + (win_num), ioaddr + EL3_CMD)
133
134/* The top five bits written to EL3_CMD are a command, the lower
135 11 bits are the parameter, if applicable. */
136enum el3_cmds {
137 TotalReset = 0<<11, SelectWindow = 1<<11, StartCoax = 2<<11,
138 RxDisable = 3<<11, RxEnable = 4<<11, RxReset = 5<<11, RxDiscard = 8<<11,
139 TxEnable = 9<<11, TxDisable = 10<<11, TxReset = 11<<11,
140 FakeIntr = 12<<11, AckIntr = 13<<11, SetIntrEnb = 14<<11,
141 SetStatusEnb = 15<<11, SetRxFilter = 16<<11, SetRxThreshold = 17<<11,
142 SetTxThreshold = 18<<11, SetTxStart = 19<<11, StatsEnable = 21<<11,
143 StatsDisable = 22<<11, StopCoax = 23<<11,
144};
145
146enum elxl_status {
147 IntLatch = 0x0001, AdapterFailure = 0x0002, TxComplete = 0x0004,
148 TxAvailable = 0x0008, RxComplete = 0x0010, RxEarly = 0x0020,
149 IntReq = 0x0040, StatsFull = 0x0080, CmdBusy = 0x1000 };
150
151/* The SetRxFilter command accepts the following classes: */
152enum RxFilter {
153 RxStation = 1, RxMulticast = 2, RxBroadcast = 4, RxProm = 8
154};
155
156enum Window0 {
157 Wn0EepromCmd = 10, Wn0EepromData = 12, /* EEPROM command/address, data. */
158 IntrStatus=0x0E, /* Valid in all windows. */
159};
160/* These assumes the larger EEPROM. */
161enum Win0_EEPROM_cmds {
162 EEPROM_Read = 0x200, EEPROM_WRITE = 0x100, EEPROM_ERASE = 0x300,
163 EEPROM_EWENB = 0x30, /* Enable erasing/writing for 10 msec. */
164 EEPROM_EWDIS = 0x00, /* Disable EWENB before 10 msec timeout. */
165};
166
167/* Register window 1 offsets, the window used in normal operation.
168 On the "Odie" this window is always mapped at offsets 0x10-0x1f.
169 Except for TxFree, which is overlapped by RunnerWrCtrl. */
170enum Window1 {
171 TX_FIFO = 0x10, RX_FIFO = 0x10, RxErrors = 0x14,
172 RxStatus = 0x18, Timer=0x1A, TxStatus = 0x1B,
173 TxFree = 0x0C, /* Remaining free bytes in Tx buffer. */
174 RunnerRdCtrl = 0x16, RunnerWrCtrl = 0x1c,
175};
176
177enum Window3 { /* Window 3: MAC/config bits. */
178 Wn3_Config=0, Wn3_MAC_Ctrl=6, Wn3_Options=8,
179};
Al Virob6659822008-01-13 14:17:35 +0000180enum wn3_config {
181 Ram_size = 7,
182 Ram_width = 8,
183 Ram_speed = 0x30,
184 Rom_size = 0xc0,
185 Ram_split_shift = 16,
186 Ram_split = 3 << Ram_split_shift,
187 Xcvr_shift = 20,
188 Xcvr = 7 << Xcvr_shift,
189 Autoselect = 0x1000000,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700190};
191
192enum Window4 { /* Window 4: Xcvr/media bits. */
193 Wn4_FIFODiag = 4, Wn4_NetDiag = 6, Wn4_PhysicalMgmt=8, Wn4_Media = 10,
194};
195
196#define MEDIA_TP 0x00C0 /* Enable link beat and jabber for 10baseT. */
197
198struct el3_private {
Dominik Brodowskifd238232006-03-05 10:45:09 +0100199 struct pcmcia_device *p_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200 u16 advertising, partner; /* NWay media advertisement */
201 unsigned char phys; /* MII device address */
202 unsigned int autoselect:1, default_media:3; /* Read from the EEPROM/Wn3_Config. */
203 /* for transceiver monitoring */
204 struct timer_list media;
205 unsigned short media_status;
206 unsigned short fast_poll;
207 unsigned long last_irq;
208 spinlock_t window_lock; /* Guards the Window selection */
209};
210
211/* Set iff a MII transceiver on any interface requires mdio preamble.
212 This only set with the original DP83840 on older 3c905 boards, so the extra
213 code size of a per-interface flag is not worthwhile. */
214static char mii_preamble_required = 0;
215
216/* Index of functions. */
217
Dominik Brodowski15b99ac2006-03-31 17:26:06 +0200218static int tc574_config(struct pcmcia_device *link);
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200219static void tc574_release(struct pcmcia_device *link);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700220
Olof Johansson906da802008-02-04 22:27:35 -0800221static void mdio_sync(unsigned int ioaddr, int bits);
222static int mdio_read(unsigned int ioaddr, int phy_id, int location);
223static void mdio_write(unsigned int ioaddr, int phy_id, int location,
224 int value);
225static unsigned short read_eeprom(unsigned int ioaddr, int index);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700226static void tc574_wait_for_completion(struct net_device *dev, int cmd);
227
228static void tc574_reset(struct net_device *dev);
229static void media_check(unsigned long arg);
230static int el3_open(struct net_device *dev);
Stephen Hemmingerdbf02fa2009-08-31 19:50:49 +0000231static netdev_tx_t el3_start_xmit(struct sk_buff *skb,
232 struct net_device *dev);
David Howells7d12e782006-10-05 14:55:46 +0100233static irqreturn_t el3_interrupt(int irq, void *dev_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234static void update_stats(struct net_device *dev);
235static struct net_device_stats *el3_get_stats(struct net_device *dev);
236static int el3_rx(struct net_device *dev, int worklimit);
237static int el3_close(struct net_device *dev);
238static void el3_tx_timeout(struct net_device *dev);
239static int el3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700240static void set_rx_mode(struct net_device *dev);
Ken Kawasakie3eef532009-10-13 00:32:55 -0700241static void set_multicast_list(struct net_device *dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700242
Dominik Brodowskicc3b4862005-11-14 21:23:14 +0100243static void tc574_detach(struct pcmcia_device *p_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700244
Linus Torvalds1da177e2005-04-16 15:20:36 -0700245/*
246 tc574_attach() creates an "instance" of the driver, allocating
247 local data structures for one device. The device is registered
248 with Card Services.
249*/
Stephen Hemmingerfb72e2f2009-03-20 19:36:02 +0000250static const struct net_device_ops el3_netdev_ops = {
251 .ndo_open = el3_open,
252 .ndo_stop = el3_close,
253 .ndo_start_xmit = el3_start_xmit,
254 .ndo_tx_timeout = el3_tx_timeout,
255 .ndo_get_stats = el3_get_stats,
256 .ndo_do_ioctl = el3_ioctl,
Ken Kawasakie3eef532009-10-13 00:32:55 -0700257 .ndo_set_multicast_list = set_multicast_list,
Stephen Hemmingerfb72e2f2009-03-20 19:36:02 +0000258 .ndo_change_mtu = eth_change_mtu,
259 .ndo_set_mac_address = eth_mac_addr,
260 .ndo_validate_addr = eth_validate_addr,
261};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700262
Dominik Brodowski15b99ac2006-03-31 17:26:06 +0200263static int tc574_probe(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700264{
265 struct el3_private *lp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266 struct net_device *dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700267
Dominik Brodowskidd0fab52009-10-24 15:51:05 +0200268 dev_dbg(&link->dev, "3c574_attach()\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269
270 /* Create the PC card device object. */
271 dev = alloc_etherdev(sizeof(struct el3_private));
272 if (!dev)
Dominik Brodowskif8cfa612005-11-14 21:25:51 +0100273 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700274 lp = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275 link->priv = dev;
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200276 lp->p_dev = link;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700277
278 spin_lock_init(&lp->window_lock);
Dominik Brodowski90abdc32010-07-24 17:23:51 +0200279 link->resource[0]->end = 32;
280 link->resource[0]->flags |= IO_DATA_PATH_WIDTH_16;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700281 link->conf.Attributes = CONF_ENABLE_IRQ;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700282 link->conf.IntType = INT_MEMORY_AND_IO;
283 link->conf.ConfigIndex = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284
Stephen Hemmingerfb72e2f2009-03-20 19:36:02 +0000285 dev->netdev_ops = &el3_netdev_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286 dev->watchdog_timeo = TX_TIMEOUT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287
Dominik Brodowski15b99ac2006-03-31 17:26:06 +0200288 return tc574_config(link);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700289} /* tc574_attach */
290
291/*
292
293 This deletes a driver "instance". The device is de-registered
294 with Card Services. If it has been released, all local data
295 structures are freed. Otherwise, the structures will be freed
296 when the device is released.
297
298*/
299
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200300static void tc574_detach(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700301{
302 struct net_device *dev = link->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700303
Dominik Brodowskidd0fab52009-10-24 15:51:05 +0200304 dev_dbg(&link->dev, "3c574_detach()\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700305
Dominik Brodowskic7c2fa02010-03-20 19:39:26 +0100306 unregister_netdev(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307
Dominik Brodowskie2d40962006-03-02 00:09:29 +0100308 tc574_release(link);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700309
Linus Torvalds1da177e2005-04-16 15:20:36 -0700310 free_netdev(dev);
311} /* tc574_detach */
312
313/*
314 tc574_config() is scheduled to run after a CARD_INSERTION event
315 is received, to configure the PCMCIA socket, and to make the
316 ethernet device available to the system.
317*/
318
Arjan van de Venf71e1302006-03-03 21:33:57 -0500319static const char *ram_split[] = {"5:3", "3:1", "1:1", "3:5"};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320
Dominik Brodowski15b99ac2006-03-31 17:26:06 +0200321static int tc574_config(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700322{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700323 struct net_device *dev = link->priv;
324 struct el3_private *lp = netdev_priv(dev);
Dominik Brodowskidd0fab52009-10-24 15:51:05 +0200325 int ret, i, j;
Olof Johansson906da802008-02-04 22:27:35 -0800326 unsigned int ioaddr;
Al Virob1e247a2007-12-22 18:56:13 +0000327 __be16 *phys_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700328 char *cardname;
Al Virob6659822008-01-13 14:17:35 +0000329 __u32 config;
Dominik Brodowskidddfbd82009-10-18 23:54:24 +0200330 u8 *buf;
331 size_t len;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700332
Al Virob1e247a2007-12-22 18:56:13 +0000333 phys_addr = (__be16 *)dev->dev_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334
Dominik Brodowskidd0fab52009-10-24 15:51:05 +0200335 dev_dbg(&link->dev, "3c574_config()\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700336
Dominik Brodowski90abdc32010-07-24 17:23:51 +0200337 link->io_lines = 16;
338
Linus Torvalds1da177e2005-04-16 15:20:36 -0700339 for (i = j = 0; j < 0x400; j += 0x20) {
Dominik Brodowski90abdc32010-07-24 17:23:51 +0200340 link->resource[0]->start = j ^ 0x300;
341 i = pcmcia_request_io(link);
Dominik Brodowski4c89e882008-08-03 10:07:45 +0200342 if (i == 0)
343 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700344 }
Dominik Brodowskidd0fab52009-10-24 15:51:05 +0200345 if (i != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700346 goto failed;
Dominik Brodowskidd0fab52009-10-24 15:51:05 +0200347
Dominik Brodowskieb141202010-03-07 12:21:16 +0100348 ret = pcmcia_request_irq(link, el3_interrupt);
Dominik Brodowskidd0fab52009-10-24 15:51:05 +0200349 if (ret)
350 goto failed;
351
352 ret = pcmcia_request_configuration(link, &link->conf);
353 if (ret)
354 goto failed;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700355
Dominik Brodowskieb141202010-03-07 12:21:16 +0100356 dev->irq = link->irq;
Dominik Brodowski9a017a92010-07-24 15:58:54 +0200357 dev->base_addr = link->resource[0]->start;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700358
359 ioaddr = dev->base_addr;
360
361 /* The 3c574 normally uses an EEPROM for configuration info, including
362 the hardware address. The future products may include a modem chip
363 and put the address in the CIS. */
Dominik Brodowskidddfbd82009-10-18 23:54:24 +0200364
365 len = pcmcia_get_tuple(link, 0x88, &buf);
366 if (buf && len >= 6) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700367 for (i = 0; i < 3; i++)
Dominik Brodowskidddfbd82009-10-18 23:54:24 +0200368 phys_addr[i] = htons(le16_to_cpu(buf[i * 2]));
369 kfree(buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700370 } else {
Dominik Brodowskidddfbd82009-10-18 23:54:24 +0200371 kfree(buf); /* 0 < len < 6 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700372 EL3WINDOW(0);
373 for (i = 0; i < 3; i++)
374 phys_addr[i] = htons(read_eeprom(ioaddr, i + 10));
Al Virob1e247a2007-12-22 18:56:13 +0000375 if (phys_addr[0] == htons(0x6060)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700376 printk(KERN_NOTICE "3c574_cs: IO port conflict at 0x%03lx"
377 "-0x%03lx\n", dev->base_addr, dev->base_addr+15);
378 goto failed;
379 }
380 }
Dominik Brodowskia9606fd2006-06-04 18:06:13 +0200381 if (link->prod_id[1])
382 cardname = link->prod_id[1];
383 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384 cardname = "3Com 3c574";
385
386 {
387 u_char mcr;
388 outw(2<<11, ioaddr + RunnerRdCtrl);
389 mcr = inb(ioaddr + 2);
390 outw(0<<11, ioaddr + RunnerRdCtrl);
391 printk(KERN_INFO " ASIC rev %d,", mcr>>3);
392 EL3WINDOW(3);
Al Virob6659822008-01-13 14:17:35 +0000393 config = inl(ioaddr + Wn3_Config);
394 lp->default_media = (config & Xcvr) >> Xcvr_shift;
395 lp->autoselect = config & Autoselect ? 1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396 }
397
398 init_timer(&lp->media);
399
400 {
401 int phy;
402
403 /* Roadrunner only: Turn on the MII transceiver */
404 outw(0x8040, ioaddr + Wn3_Options);
405 mdelay(1);
406 outw(0xc040, ioaddr + Wn3_Options);
407 tc574_wait_for_completion(dev, TxReset);
408 tc574_wait_for_completion(dev, RxReset);
409 mdelay(1);
410 outw(0x8040, ioaddr + Wn3_Options);
411
412 EL3WINDOW(4);
413 for (phy = 1; phy <= 32; phy++) {
414 int mii_status;
415 mdio_sync(ioaddr, 32);
416 mii_status = mdio_read(ioaddr, phy & 0x1f, 1);
417 if (mii_status != 0xffff) {
418 lp->phys = phy & 0x1f;
Dominik Brodowskidd0fab52009-10-24 15:51:05 +0200419 dev_dbg(&link->dev, " MII transceiver at "
420 "index %d, status %x.\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421 phy, mii_status);
422 if ((mii_status & 0x0040) == 0)
423 mii_preamble_required = 1;
424 break;
425 }
426 }
427 if (phy > 32) {
428 printk(KERN_NOTICE " No MII transceivers found!\n");
429 goto failed;
430 }
431 i = mdio_read(ioaddr, lp->phys, 16) | 0x40;
432 mdio_write(ioaddr, lp->phys, 16, i);
433 lp->advertising = mdio_read(ioaddr, lp->phys, 4);
434 if (full_duplex) {
435 /* Only advertise the FD media types. */
436 lp->advertising &= ~0x02a0;
437 mdio_write(ioaddr, lp->phys, 4, lp->advertising);
438 }
439 }
440
Dominik Brodowskidd2e5a12009-11-03 10:27:34 +0100441 SET_NETDEV_DEV(dev, &link->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442
443 if (register_netdev(dev) != 0) {
444 printk(KERN_NOTICE "3c574_cs: register_netdev() failed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445 goto failed;
446 }
447
Joe Perches0795af52007-10-03 17:59:30 -0700448 printk(KERN_INFO "%s: %s at io %#3lx, irq %d, "
Johannes Berge1749612008-10-27 15:59:26 -0700449 "hw_addr %pM.\n",
Joe Perches0795af52007-10-03 17:59:30 -0700450 dev->name, cardname, dev->base_addr, dev->irq,
Johannes Berge1749612008-10-27 15:59:26 -0700451 dev->dev_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452 printk(" %dK FIFO split %s Rx:Tx, %sMII interface.\n",
Al Virob6659822008-01-13 14:17:35 +0000453 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);
502 printk(KERN_INFO " irq status %04x, rx status %04x, tx status "
503 "%02x, tx free %04x\n", inw(ioaddr+EL3_STATUS),
504 inw(ioaddr+RxStatus), inb(ioaddr+TxStatus),
505 inw(ioaddr+TxFree));
506 EL3WINDOW(4);
507 printk(KERN_INFO " diagnostics: fifo %04x net %04x ethernet %04x"
508 " media %04x\n", inw(ioaddr+0x04), inw(ioaddr+0x06),
509 inw(ioaddr+0x08), inw(ioaddr+0x0a));
510 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)
523 printk(KERN_NOTICE "%s: command 0x%04x did not complete!\n", dev->name, cmd);
524}
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);
710 lp->media.function = &media_check;
711 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
725 printk(KERN_NOTICE "%s: Transmit timed out!\n", dev->name);
726 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);
848 printk(KERN_NOTICE "%s: adapter failure, FIFO diagnostic"
849 " register %04x.\n", dev->name, fifo_diag);
850 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)
903 printk(KERN_INFO "%s: interrupt(s) dropped!\n", dev->name);
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)
926 printk(KERN_INFO "%s: %s link beat\n", dev->name,
927 (lp->media_status & 0x0004) ? "lost" : "found");
928 if ((media ^ lp->media_status) & 0x0020) {
929 lp->partner = 0;
930 if (lp->media_status & 0x0020) {
931 printk(KERN_INFO "%s: autonegotiation restarted\n",
932 dev->name);
933 } else if (partner) {
934 partner &= lp->advertising;
935 lp->partner = partner;
936 printk(KERN_INFO "%s: autonegotiation complete: "
937 "%sbaseT-%cD selected\n", dev->name,
938 ((partner & 0x0180) ? "100" : "10"),
939 ((partner & 0x0140) ? 'F' : 'H'));
940 } else {
941 printk(KERN_INFO "%s: link partner did not autonegotiate\n",
942 dev->name);
943 }
944
945 EL3WINDOW(3);
946 outb((partner & 0x0140 ? 0x20 : 0) |
947 (dev->mtu > 1500 ? 0x40 : 0), ioaddr + Wn3_MAC_Ctrl);
948 EL3WINDOW(1);
949
950 }
951 if (media & 0x0010)
952 printk(KERN_INFO "%s: remote fault detected\n",
953 dev->name);
954 if (media & 0x0002)
955 printk(KERN_INFO "%s: jabber detected\n", dev->name);
956 lp->media_status = media;
957 }
958 spin_unlock_irqrestore(&lp->window_lock, flags);
959
960reschedule:
961 lp->media.expires = jiffies + HZ;
962 add_timer(&lp->media);
963}
964
965static struct net_device_stats *el3_get_stats(struct net_device *dev)
966{
967 struct el3_private *lp = netdev_priv(dev);
968
969 if (netif_device_present(dev)) {
970 unsigned long flags;
971 spin_lock_irqsave(&lp->window_lock, flags);
972 update_stats(dev);
973 spin_unlock_irqrestore(&lp->window_lock, flags);
974 }
Paulius Zaleckas2e8d31d2008-04-30 01:08:26 +0300975 return &dev->stats;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700976}
977
978/* Update statistics.
979 Suprisingly this need not be run single-threaded, but it effectively is.
980 The counters clear when read, so the adds must merely be atomic.
981 */
982static void update_stats(struct net_device *dev)
983{
Olof Johansson906da802008-02-04 22:27:35 -0800984 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700985 u8 rx, tx, up;
986
Dominik Brodowskidd0fab52009-10-24 15:51:05 +0200987 pr_debug("%s: updating the statistics.\n", dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700988
989 if (inw(ioaddr+EL3_STATUS) == 0xffff) /* No card. */
990 return;
991
992 /* Unlike the 3c509 we need not turn off stats updates while reading. */
993 /* Switch to the stats window, and read everything. */
994 EL3WINDOW(6);
Paulius Zaleckas2e8d31d2008-04-30 01:08:26 +0300995 dev->stats.tx_carrier_errors += inb(ioaddr + 0);
996 dev->stats.tx_heartbeat_errors += inb(ioaddr + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700997 /* Multiple collisions. */ inb(ioaddr + 2);
Paulius Zaleckas2e8d31d2008-04-30 01:08:26 +0300998 dev->stats.collisions += inb(ioaddr + 3);
999 dev->stats.tx_window_errors += inb(ioaddr + 4);
1000 dev->stats.rx_fifo_errors += inb(ioaddr + 5);
1001 dev->stats.tx_packets += inb(ioaddr + 6);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001002 up = inb(ioaddr + 9);
Paulius Zaleckas2e8d31d2008-04-30 01:08:26 +03001003 dev->stats.tx_packets += (up&0x30) << 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001004 /* Rx packets */ inb(ioaddr + 7);
1005 /* Tx deferrals */ inb(ioaddr + 8);
1006 rx = inw(ioaddr + 10);
1007 tx = inw(ioaddr + 12);
1008
1009 EL3WINDOW(4);
1010 /* BadSSD */ inb(ioaddr + 12);
1011 up = inb(ioaddr + 13);
1012
Linus Torvalds1da177e2005-04-16 15:20:36 -07001013 EL3WINDOW(1);
1014}
1015
1016static int el3_rx(struct net_device *dev, int worklimit)
1017{
Olof Johansson906da802008-02-04 22:27:35 -08001018 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001019 short rx_status;
1020
Dominik Brodowskidd0fab52009-10-24 15:51:05 +02001021 pr_debug("%s: in rx_packet(), status %4.4x, rx_status %4.4x.\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022 dev->name, inw(ioaddr+EL3_STATUS), inw(ioaddr+RxStatus));
1023 while (!((rx_status = inw(ioaddr + RxStatus)) & 0x8000) &&
Roel Kluinb9bdcd92009-03-04 00:05:56 -08001024 worklimit > 0) {
1025 worklimit--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001026 if (rx_status & 0x4000) { /* Error, update stats. */
1027 short error = rx_status & 0x3800;
Paulius Zaleckas2e8d31d2008-04-30 01:08:26 +03001028 dev->stats.rx_errors++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029 switch (error) {
Paulius Zaleckas2e8d31d2008-04-30 01:08:26 +03001030 case 0x0000: dev->stats.rx_over_errors++; break;
1031 case 0x0800: dev->stats.rx_length_errors++; break;
1032 case 0x1000: dev->stats.rx_frame_errors++; break;
1033 case 0x1800: dev->stats.rx_length_errors++; break;
1034 case 0x2000: dev->stats.rx_frame_errors++; break;
1035 case 0x2800: dev->stats.rx_crc_errors++; break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001036 }
1037 } else {
1038 short pkt_len = rx_status & 0x7ff;
1039 struct sk_buff *skb;
1040
1041 skb = dev_alloc_skb(pkt_len+5);
1042
Dominik Brodowskidd0fab52009-10-24 15:51:05 +02001043 pr_debug(" Receiving packet size %d status %4.4x.\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001044 pkt_len, rx_status);
1045 if (skb != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001046 skb_reserve(skb, 2);
1047 insl(ioaddr+RX_FIFO, skb_put(skb, pkt_len),
1048 ((pkt_len+3)>>2));
1049 skb->protocol = eth_type_trans(skb, dev);
1050 netif_rx(skb);
Paulius Zaleckas2e8d31d2008-04-30 01:08:26 +03001051 dev->stats.rx_packets++;
1052 dev->stats.rx_bytes += pkt_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053 } else {
Dominik Brodowskidd0fab52009-10-24 15:51:05 +02001054 pr_debug("%s: couldn't allocate a sk_buff of"
Linus Torvalds1da177e2005-04-16 15:20:36 -07001055 " size %d.\n", dev->name, pkt_len);
Paulius Zaleckas2e8d31d2008-04-30 01:08:26 +03001056 dev->stats.rx_dropped++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057 }
1058 }
1059 tc574_wait_for_completion(dev, RxDiscard);
1060 }
1061
1062 return worklimit;
1063}
1064
Linus Torvalds1da177e2005-04-16 15:20:36 -07001065/* Provide ioctl() calls to examine the MII xcvr state. */
1066static int el3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
1067{
1068 struct el3_private *lp = netdev_priv(dev);
Olof Johansson906da802008-02-04 22:27:35 -08001069 unsigned int ioaddr = dev->base_addr;
Ben Hutchings0fa0ee052009-09-03 10:41:17 +00001070 struct mii_ioctl_data *data = if_mii(rq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001071 int phy = lp->phys & 0x1f;
1072
Dominik Brodowskidd0fab52009-10-24 15:51:05 +02001073 pr_debug("%s: In ioct(%-.6s, %#4.4x) %4.4x %4.4x %4.4x %4.4x.\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001074 dev->name, rq->ifr_ifrn.ifrn_name, cmd,
Ben Hutchings0fa0ee052009-09-03 10:41:17 +00001075 data->phy_id, data->reg_num, data->val_in, data->val_out);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076
1077 switch(cmd) {
1078 case SIOCGMIIPHY: /* Get the address of the PHY in use. */
Ben Hutchings0fa0ee052009-09-03 10:41:17 +00001079 data->phy_id = phy;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001080 case SIOCGMIIREG: /* Read the specified MII register. */
1081 {
1082 int saved_window;
1083 unsigned long flags;
1084
1085 spin_lock_irqsave(&lp->window_lock, flags);
1086 saved_window = inw(ioaddr + EL3_CMD) >> 13;
1087 EL3WINDOW(4);
Ben Hutchings0fa0ee052009-09-03 10:41:17 +00001088 data->val_out = mdio_read(ioaddr, data->phy_id & 0x1f,
1089 data->reg_num & 0x1f);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001090 EL3WINDOW(saved_window);
1091 spin_unlock_irqrestore(&lp->window_lock, flags);
1092 return 0;
1093 }
1094 case SIOCSMIIREG: /* Write the specified MII register */
1095 {
1096 int saved_window;
1097 unsigned long flags;
1098
Linus Torvalds1da177e2005-04-16 15:20:36 -07001099 spin_lock_irqsave(&lp->window_lock, flags);
1100 saved_window = inw(ioaddr + EL3_CMD) >> 13;
1101 EL3WINDOW(4);
Ben Hutchings0fa0ee052009-09-03 10:41:17 +00001102 mdio_write(ioaddr, data->phy_id & 0x1f,
1103 data->reg_num & 0x1f, data->val_in);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001104 EL3WINDOW(saved_window);
1105 spin_unlock_irqrestore(&lp->window_lock, flags);
1106 return 0;
1107 }
1108 default:
1109 return -EOPNOTSUPP;
1110 }
1111}
1112
1113/* The Odie chip has a 64 bin multicast filter, but the bit layout is not
1114 documented. Until it is we revert to receiving all multicast frames when
1115 any multicast reception is desired.
1116 Note: My other drivers emit a log message whenever promiscuous mode is
1117 entered to help detect password sniffers. This is less desirable on
1118 typical PC card machines, so we omit the message.
1119 */
1120
1121static void set_rx_mode(struct net_device *dev)
1122{
Olof Johansson906da802008-02-04 22:27:35 -08001123 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001124
1125 if (dev->flags & IFF_PROMISC)
1126 outw(SetRxFilter | RxStation | RxMulticast | RxBroadcast | RxProm,
1127 ioaddr + EL3_CMD);
Jiri Pirko4cd24ea2010-02-08 04:30:35 +00001128 else if (!netdev_mc_empty(dev) || (dev->flags & IFF_ALLMULTI))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001129 outw(SetRxFilter|RxStation|RxMulticast|RxBroadcast, ioaddr + EL3_CMD);
1130 else
1131 outw(SetRxFilter | RxStation | RxBroadcast, ioaddr + EL3_CMD);
1132}
1133
Ken Kawasakie3eef532009-10-13 00:32:55 -07001134static void set_multicast_list(struct net_device *dev)
1135{
1136 struct el3_private *lp = netdev_priv(dev);
1137 unsigned long flags;
1138
1139 spin_lock_irqsave(&lp->window_lock, flags);
1140 set_rx_mode(dev);
1141 spin_unlock_irqrestore(&lp->window_lock, flags);
1142}
1143
Linus Torvalds1da177e2005-04-16 15:20:36 -07001144static int el3_close(struct net_device *dev)
1145{
Olof Johansson906da802008-02-04 22:27:35 -08001146 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001147 struct el3_private *lp = netdev_priv(dev);
Dominik Brodowskifba395e2006-03-31 17:21:06 +02001148 struct pcmcia_device *link = lp->p_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001149
Dominik Brodowskidd0fab52009-10-24 15:51:05 +02001150 dev_dbg(&link->dev, "%s: shutting down ethercard.\n", dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001151
Dominik Brodowski9940ec32006-03-05 11:04:33 +01001152 if (pcmcia_dev_present(link)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001153 unsigned long flags;
1154
1155 /* Turn off statistics ASAP. We update lp->stats below. */
1156 outw(StatsDisable, ioaddr + EL3_CMD);
1157
1158 /* Disable the receiver and transmitter. */
1159 outw(RxDisable, ioaddr + EL3_CMD);
1160 outw(TxDisable, ioaddr + EL3_CMD);
1161
1162 /* Note: Switching to window 0 may disable the IRQ. */
1163 EL3WINDOW(0);
1164 spin_lock_irqsave(&lp->window_lock, flags);
1165 update_stats(dev);
1166 spin_unlock_irqrestore(&lp->window_lock, flags);
Daniel Ritzb9a6eaf2005-04-10 20:27:45 +02001167
1168 /* force interrupts off */
1169 outw(SetIntrEnb | 0x0000, ioaddr + EL3_CMD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001170 }
1171
1172 link->open--;
1173 netif_stop_queue(dev);
1174 del_timer_sync(&lp->media);
1175
1176 return 0;
1177}
1178
Dominik Brodowski270b6e92005-06-27 16:28:18 -07001179static struct pcmcia_device_id tc574_ids[] = {
1180 PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0574),
Ken Kawasakif0a3a152009-05-01 19:21:26 -07001181 PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0101, 0x0556, "cis/3CCFEM556.cis"),
Dominik Brodowski270b6e92005-06-27 16:28:18 -07001182 PCMCIA_DEVICE_NULL,
1183};
1184MODULE_DEVICE_TABLE(pcmcia, tc574_ids);
1185
Linus Torvalds1da177e2005-04-16 15:20:36 -07001186static struct pcmcia_driver tc574_driver = {
1187 .owner = THIS_MODULE,
1188 .drv = {
1189 .name = "3c574_cs",
1190 },
Dominik Brodowski15b99ac2006-03-31 17:26:06 +02001191 .probe = tc574_probe,
Dominik Brodowskicc3b4862005-11-14 21:23:14 +01001192 .remove = tc574_detach,
Dominik Brodowski270b6e92005-06-27 16:28:18 -07001193 .id_table = tc574_ids,
Dominik Brodowski98e4c282005-11-14 21:21:18 +01001194 .suspend = tc574_suspend,
1195 .resume = tc574_resume,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001196};
1197
1198static int __init init_tc574(void)
1199{
1200 return pcmcia_register_driver(&tc574_driver);
1201}
1202
1203static void __exit exit_tc574(void)
1204{
1205 pcmcia_unregister_driver(&tc574_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206}
1207
1208module_init(init_tc574);
1209module_exit(exit_tc574);