1 | /* ====================================================================== |
2 | * |
3 | * A PCMCIA ethernet driver for the 3com 3c589 card. |
4 | * |
5 | * Copyright (C) 1999 David A. Hinds -- dahinds@users.sourceforge.net |
6 | * |
7 | * 3c589_cs.c 1.162 2001/10/13 00:08:50 |
8 | * |
9 | * The network driver code is based on Donald Becker's 3c589 code: |
10 | * |
11 | * Written 1994 by Donald Becker. |
12 | * Copyright 1993 United States Government as represented by the |
13 | * Director, National Security Agency. This software may be used and |
14 | * distributed according to the terms of the GNU General Public License, |
15 | * incorporated herein by reference. |
16 | * Donald Becker may be reached at becker@scyld.com |
17 | * |
18 | * Updated for 2.5.x by Alan Cox <alan@lxorguk.ukuu.org.uk> |
19 | * |
20 | * ====================================================================== |
21 | */ |
22 | |
23 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
24 | |
25 | #define DRV_NAME "3c589_cs" |
26 | |
27 | #include <linux/module.h> |
28 | #include <linux/kernel.h> |
29 | #include <linux/ptrace.h> |
30 | #include <linux/slab.h> |
31 | #include <linux/string.h> |
32 | #include <linux/timer.h> |
33 | #include <linux/interrupt.h> |
34 | #include <linux/in.h> |
35 | #include <linux/delay.h> |
36 | #include <linux/ethtool.h> |
37 | #include <linux/netdevice.h> |
38 | #include <linux/etherdevice.h> |
39 | #include <linux/skbuff.h> |
40 | #include <linux/if_arp.h> |
41 | #include <linux/ioport.h> |
42 | #include <linux/bitops.h> |
43 | #include <linux/jiffies.h> |
44 | #include <linux/uaccess.h> |
45 | #include <linux/io.h> |
46 | |
47 | #include <pcmcia/cistpl.h> |
48 | #include <pcmcia/cisreg.h> |
49 | #include <pcmcia/ciscode.h> |
50 | #include <pcmcia/ds.h> |
51 | |
52 | |
53 | /* To minimize the size of the driver source I only define operating |
54 | * constants if they are used several times. You'll need the manual |
55 | * if you want to understand driver details. |
56 | */ |
57 | |
58 | /* Offsets from base I/O address. */ |
59 | #define EL3_DATA 0x00 |
60 | #define EL3_TIMER 0x0a |
61 | #define EL3_CMD 0x0e |
62 | #define EL3_STATUS 0x0e |
63 | |
64 | #define EEPROM_READ 0x0080 |
65 | #define EEPROM_BUSY 0x8000 |
66 | |
67 | #define EL3WINDOW(win_num) outw(SelectWindow + (win_num), ioaddr + EL3_CMD) |
68 | |
69 | /* The top five bits written to EL3_CMD are a command, the lower |
70 | * 11 bits are the parameter, if applicable. |
71 | */ |
72 | |
73 | enum c509cmd { |
74 | TotalReset = 0<<11, |
75 | SelectWindow = 1<<11, |
76 | StartCoax = 2<<11, |
77 | RxDisable = 3<<11, |
78 | RxEnable = 4<<11, |
79 | RxReset = 5<<11, |
80 | RxDiscard = 8<<11, |
81 | TxEnable = 9<<11, |
82 | TxDisable = 10<<11, |
83 | TxReset = 11<<11, |
84 | FakeIntr = 12<<11, |
85 | AckIntr = 13<<11, |
86 | SetIntrEnb = 14<<11, |
87 | SetStatusEnb = 15<<11, |
88 | SetRxFilter = 16<<11, |
89 | SetRxThreshold = 17<<11, |
90 | SetTxThreshold = 18<<11, |
91 | SetTxStart = 19<<11, |
92 | StatsEnable = 21<<11, |
93 | StatsDisable = 22<<11, |
94 | StopCoax = 23<<11 |
95 | }; |
96 | |
97 | enum c509status { |
98 | IntLatch = 0x0001, |
99 | AdapterFailure = 0x0002, |
100 | TxComplete = 0x0004, |
101 | TxAvailable = 0x0008, |
102 | RxComplete = 0x0010, |
103 | RxEarly = 0x0020, |
104 | IntReq = 0x0040, |
105 | StatsFull = 0x0080, |
106 | CmdBusy = 0x1000 |
107 | }; |
108 | |
109 | /* The SetRxFilter command accepts the following classes: */ |
110 | enum RxFilter { |
111 | RxStation = 1, |
112 | RxMulticast = 2, |
113 | RxBroadcast = 4, |
114 | RxProm = 8 |
115 | }; |
116 | |
117 | /* Register window 1 offsets, the window used in normal operation. */ |
118 | #define TX_FIFO 0x00 |
119 | #define RX_FIFO 0x00 |
120 | #define RX_STATUS 0x08 |
121 | #define TX_STATUS 0x0B |
122 | #define TX_FREE 0x0C /* Remaining free bytes in Tx buffer. */ |
123 | |
124 | #define WN0_IRQ 0x08 /* Window 0: Set IRQ line in bits 12-15. */ |
125 | #define WN4_MEDIA 0x0A /* Window 4: Various transcvr/media bits. */ |
126 | #define MEDIA_TP 0x00C0 /* Enable link beat and jabber for 10baseT. */ |
127 | #define MEDIA_LED 0x0001 /* Enable link light on 3C589E cards. */ |
128 | |
129 | /* Time in jiffies before concluding Tx hung */ |
130 | #define TX_TIMEOUT ((400*HZ)/1000) |
131 | |
132 | struct el3_private { |
133 | struct pcmcia_device *p_dev; |
134 | /* For transceiver monitoring */ |
135 | struct timer_list media; |
136 | u16 media_status; |
137 | u16 fast_poll; |
138 | unsigned long last_irq; |
139 | spinlock_t lock; |
140 | }; |
141 | |
142 | static const char *if_names[] = { "auto" , "10baseT" , "10base2" , "AUI" }; |
143 | |
144 | /*====================================================================*/ |
145 | |
146 | /* Module parameters */ |
147 | |
148 | MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>" ); |
149 | MODULE_DESCRIPTION("3Com 3c589 series PCMCIA ethernet driver" ); |
150 | MODULE_LICENSE("GPL" ); |
151 | |
152 | #define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0) |
153 | |
154 | /* Special hook for setting if_port when module is loaded */ |
155 | INT_MODULE_PARM(if_port, 0); |
156 | |
157 | |
158 | /*====================================================================*/ |
159 | |
160 | static int tc589_config(struct pcmcia_device *link); |
161 | static void tc589_release(struct pcmcia_device *link); |
162 | |
163 | static u16 read_eeprom(unsigned int ioaddr, int index); |
164 | static void tc589_reset(struct net_device *dev); |
165 | static void media_check(struct timer_list *t); |
166 | static int el3_config(struct net_device *dev, struct ifmap *map); |
167 | static int el3_open(struct net_device *dev); |
168 | static netdev_tx_t el3_start_xmit(struct sk_buff *skb, |
169 | struct net_device *dev); |
170 | static irqreturn_t el3_interrupt(int irq, void *dev_id); |
171 | static void update_stats(struct net_device *dev); |
172 | static struct net_device_stats *el3_get_stats(struct net_device *dev); |
173 | static int el3_rx(struct net_device *dev); |
174 | static int el3_close(struct net_device *dev); |
175 | static void el3_tx_timeout(struct net_device *dev, unsigned int txqueue); |
176 | static void set_rx_mode(struct net_device *dev); |
177 | static void set_multicast_list(struct net_device *dev); |
178 | static const struct ethtool_ops netdev_ethtool_ops; |
179 | |
180 | static void tc589_detach(struct pcmcia_device *p_dev); |
181 | |
182 | static const struct net_device_ops el3_netdev_ops = { |
183 | .ndo_open = el3_open, |
184 | .ndo_stop = el3_close, |
185 | .ndo_start_xmit = el3_start_xmit, |
186 | .ndo_tx_timeout = el3_tx_timeout, |
187 | .ndo_set_config = el3_config, |
188 | .ndo_get_stats = el3_get_stats, |
189 | .ndo_set_rx_mode = set_multicast_list, |
190 | .ndo_set_mac_address = eth_mac_addr, |
191 | .ndo_validate_addr = eth_validate_addr, |
192 | }; |
193 | |
194 | static int tc589_probe(struct pcmcia_device *link) |
195 | { |
196 | struct el3_private *lp; |
197 | struct net_device *dev; |
198 | int ret; |
199 | |
200 | dev_dbg(&link->dev, "3c589_attach()\n" ); |
201 | |
202 | /* Create new ethernet device */ |
203 | dev = alloc_etherdev(sizeof(struct el3_private)); |
204 | if (!dev) |
205 | return -ENOMEM; |
206 | lp = netdev_priv(dev); |
207 | link->priv = dev; |
208 | lp->p_dev = link; |
209 | |
210 | spin_lock_init(&lp->lock); |
211 | link->resource[0]->end = 16; |
212 | link->resource[0]->flags |= IO_DATA_PATH_WIDTH_16; |
213 | |
214 | link->config_flags |= CONF_ENABLE_IRQ; |
215 | link->config_index = 1; |
216 | |
217 | dev->netdev_ops = &el3_netdev_ops; |
218 | dev->watchdog_timeo = TX_TIMEOUT; |
219 | |
220 | dev->ethtool_ops = &netdev_ethtool_ops; |
221 | |
222 | ret = tc589_config(link); |
223 | if (ret) |
224 | goto err_free_netdev; |
225 | |
226 | return 0; |
227 | |
228 | err_free_netdev: |
229 | free_netdev(dev); |
230 | return ret; |
231 | } |
232 | |
233 | static void tc589_detach(struct pcmcia_device *link) |
234 | { |
235 | struct net_device *dev = link->priv; |
236 | |
237 | dev_dbg(&link->dev, "3c589_detach\n" ); |
238 | |
239 | unregister_netdev(dev); |
240 | |
241 | tc589_release(link); |
242 | |
243 | free_netdev(dev); |
244 | } /* tc589_detach */ |
245 | |
246 | static int tc589_config(struct pcmcia_device *link) |
247 | { |
248 | struct net_device *dev = link->priv; |
249 | int ret, i, j, multi = 0, fifo; |
250 | __be16 addr[ETH_ALEN / 2]; |
251 | unsigned int ioaddr; |
252 | static const char * const ram_split[] = {"5:3" , "3:1" , "1:1" , "3:5" }; |
253 | u8 *buf; |
254 | size_t len; |
255 | |
256 | dev_dbg(&link->dev, "3c589_config\n" ); |
257 | |
258 | /* Is this a 3c562? */ |
259 | if (link->manf_id != MANFID_3COM) |
260 | dev_info(&link->dev, "hmmm, is this really a 3Com card??\n" ); |
261 | multi = (link->card_id == PRODID_3COM_3C562); |
262 | |
263 | link->io_lines = 16; |
264 | |
265 | /* For the 3c562, the base address must be xx00-xx7f */ |
266 | for (i = j = 0; j < 0x400; j += 0x10) { |
267 | if (multi && (j & 0x80)) |
268 | continue; |
269 | link->resource[0]->start = j ^ 0x300; |
270 | i = pcmcia_request_io(p_dev: link); |
271 | if (i == 0) |
272 | break; |
273 | } |
274 | if (i != 0) |
275 | goto failed; |
276 | |
277 | ret = pcmcia_request_irq(p_dev: link, handler: el3_interrupt); |
278 | if (ret) |
279 | goto failed; |
280 | |
281 | ret = pcmcia_enable_device(p_dev: link); |
282 | if (ret) |
283 | goto failed; |
284 | |
285 | dev->irq = link->irq; |
286 | dev->base_addr = link->resource[0]->start; |
287 | ioaddr = dev->base_addr; |
288 | EL3WINDOW(0); |
289 | |
290 | /* The 3c589 has an extra EEPROM for configuration info, including |
291 | * the hardware address. The 3c562 puts the address in the CIS. |
292 | */ |
293 | len = pcmcia_get_tuple(p_dev: link, code: 0x88, buf: &buf); |
294 | if (buf && len >= 6) { |
295 | for (i = 0; i < 3; i++) |
296 | addr[i] = htons(le16_to_cpu(buf[i*2])); |
297 | kfree(objp: buf); |
298 | } else { |
299 | kfree(objp: buf); /* 0 < len < 6 */ |
300 | for (i = 0; i < 3; i++) |
301 | addr[i] = htons(read_eeprom(ioaddr, i)); |
302 | if (addr[0] == htons(0x6060)) { |
303 | dev_err(&link->dev, "IO port conflict at 0x%03lx-0x%03lx\n" , |
304 | dev->base_addr, dev->base_addr+15); |
305 | goto failed; |
306 | } |
307 | } |
308 | eth_hw_addr_set(dev, addr: (u8 *)addr); |
309 | |
310 | /* The address and resource configuration register aren't loaded from |
311 | * the EEPROM and *must* be set to 0 and IRQ3 for the PCMCIA version. |
312 | */ |
313 | |
314 | outw(value: 0x3f00, port: ioaddr + 8); |
315 | fifo = inl(port: ioaddr); |
316 | |
317 | /* The if_port symbol can be set when the module is loaded */ |
318 | if ((if_port >= 0) && (if_port <= 3)) |
319 | dev->if_port = if_port; |
320 | else |
321 | dev_err(&link->dev, "invalid if_port requested\n" ); |
322 | |
323 | SET_NETDEV_DEV(dev, &link->dev); |
324 | |
325 | if (register_netdev(dev) != 0) { |
326 | dev_err(&link->dev, "register_netdev() failed\n" ); |
327 | goto failed; |
328 | } |
329 | |
330 | netdev_info(dev, format: "3Com 3c%s, io %#3lx, irq %d, hw_addr %pM\n" , |
331 | (multi ? "562" : "589" ), dev->base_addr, dev->irq, |
332 | dev->dev_addr); |
333 | netdev_info(dev, format: " %dK FIFO split %s Rx:Tx, %s xcvr\n" , |
334 | (fifo & 7) ? 32 : 8, ram_split[(fifo >> 16) & 3], |
335 | if_names[dev->if_port]); |
336 | return 0; |
337 | |
338 | failed: |
339 | tc589_release(link); |
340 | return -ENODEV; |
341 | } /* tc589_config */ |
342 | |
343 | static void tc589_release(struct pcmcia_device *link) |
344 | { |
345 | pcmcia_disable_device(p_dev: link); |
346 | } |
347 | |
348 | static int tc589_suspend(struct pcmcia_device *link) |
349 | { |
350 | struct net_device *dev = link->priv; |
351 | |
352 | if (link->open) |
353 | netif_device_detach(dev); |
354 | |
355 | return 0; |
356 | } |
357 | |
358 | static int tc589_resume(struct pcmcia_device *link) |
359 | { |
360 | struct net_device *dev = link->priv; |
361 | |
362 | if (link->open) { |
363 | tc589_reset(dev); |
364 | netif_device_attach(dev); |
365 | } |
366 | |
367 | return 0; |
368 | } |
369 | |
370 | /*====================================================================*/ |
371 | |
372 | /* Use this for commands that may take time to finish */ |
373 | |
374 | static void tc589_wait_for_completion(struct net_device *dev, int cmd) |
375 | { |
376 | int i = 100; |
377 | outw(value: cmd, port: dev->base_addr + EL3_CMD); |
378 | while (--i > 0) |
379 | if (!(inw(port: dev->base_addr + EL3_STATUS) & 0x1000)) |
380 | break; |
381 | if (i == 0) |
382 | netdev_warn(dev, format: "command 0x%04x did not complete!\n" , cmd); |
383 | } |
384 | |
385 | /* Read a word from the EEPROM using the regular EEPROM access register. |
386 | * Assume that we are in register window zero. |
387 | */ |
388 | |
389 | static u16 read_eeprom(unsigned int ioaddr, int index) |
390 | { |
391 | int i; |
392 | outw(EEPROM_READ + index, port: ioaddr + 10); |
393 | /* Reading the eeprom takes 162 us */ |
394 | for (i = 1620; i >= 0; i--) |
395 | if ((inw(port: ioaddr + 10) & EEPROM_BUSY) == 0) |
396 | break; |
397 | return inw(port: ioaddr + 12); |
398 | } |
399 | |
400 | /* Set transceiver type, perhaps to something other than what the user |
401 | * specified in dev->if_port. |
402 | */ |
403 | |
404 | static void tc589_set_xcvr(struct net_device *dev, int if_port) |
405 | { |
406 | struct el3_private *lp = netdev_priv(dev); |
407 | unsigned int ioaddr = dev->base_addr; |
408 | |
409 | EL3WINDOW(0); |
410 | switch (if_port) { |
411 | case 0: |
412 | case 1: |
413 | outw(value: 0, port: ioaddr + 6); |
414 | break; |
415 | case 2: |
416 | outw(value: 3<<14, port: ioaddr + 6); |
417 | break; |
418 | case 3: |
419 | outw(value: 1<<14, port: ioaddr + 6); |
420 | break; |
421 | } |
422 | /* On PCMCIA, this just turns on the LED */ |
423 | outw(value: (if_port == 2) ? StartCoax : StopCoax, port: ioaddr + EL3_CMD); |
424 | /* 10baseT interface, enable link beat and jabber check. */ |
425 | EL3WINDOW(4); |
426 | outw(MEDIA_LED | ((if_port < 2) ? MEDIA_TP : 0), port: ioaddr + WN4_MEDIA); |
427 | EL3WINDOW(1); |
428 | if (if_port == 2) |
429 | lp->media_status = ((dev->if_port == 0) ? 0x8000 : 0x4000); |
430 | else |
431 | lp->media_status = ((dev->if_port == 0) ? 0x4010 : 0x8800); |
432 | } |
433 | |
434 | static void dump_status(struct net_device *dev) |
435 | { |
436 | unsigned int ioaddr = dev->base_addr; |
437 | EL3WINDOW(1); |
438 | netdev_info(dev, format: " irq status %04x, rx status %04x, tx status %02x tx free %04x\n" , |
439 | inw(port: ioaddr+EL3_STATUS), inw(port: ioaddr+RX_STATUS), |
440 | inb(port: ioaddr+TX_STATUS), inw(port: ioaddr+TX_FREE)); |
441 | EL3WINDOW(4); |
442 | netdev_info(dev, format: " diagnostics: fifo %04x net %04x ethernet %04x media %04x\n" , |
443 | inw(port: ioaddr+0x04), inw(port: ioaddr+0x06), inw(port: ioaddr+0x08), |
444 | inw(port: ioaddr+0x0a)); |
445 | EL3WINDOW(1); |
446 | } |
447 | |
448 | /* Reset and restore all of the 3c589 registers. */ |
449 | static void tc589_reset(struct net_device *dev) |
450 | { |
451 | unsigned int ioaddr = dev->base_addr; |
452 | int i; |
453 | |
454 | EL3WINDOW(0); |
455 | outw(value: 0x0001, port: ioaddr + 4); /* Activate board. */ |
456 | outw(value: 0x3f00, port: ioaddr + 8); /* Set the IRQ line. */ |
457 | |
458 | /* Set the station address in window 2. */ |
459 | EL3WINDOW(2); |
460 | for (i = 0; i < 6; i++) |
461 | outb(value: dev->dev_addr[i], port: ioaddr + i); |
462 | |
463 | tc589_set_xcvr(dev, if_port: dev->if_port); |
464 | |
465 | /* Switch to the stats window, and clear all stats by reading. */ |
466 | outw(value: StatsDisable, port: ioaddr + EL3_CMD); |
467 | EL3WINDOW(6); |
468 | for (i = 0; i < 9; i++) |
469 | inb(port: ioaddr+i); |
470 | inw(port: ioaddr + 10); |
471 | inw(port: ioaddr + 12); |
472 | |
473 | /* Switch to register set 1 for normal use. */ |
474 | EL3WINDOW(1); |
475 | |
476 | set_rx_mode(dev); |
477 | outw(value: StatsEnable, port: ioaddr + EL3_CMD); /* Turn on statistics. */ |
478 | outw(value: RxEnable, port: ioaddr + EL3_CMD); /* Enable the receiver. */ |
479 | outw(value: TxEnable, port: ioaddr + EL3_CMD); /* Enable transmitter. */ |
480 | /* Allow status bits to be seen. */ |
481 | outw(value: SetStatusEnb | 0xff, port: ioaddr + EL3_CMD); |
482 | /* Ack all pending events, and set active indicator mask. */ |
483 | outw(value: AckIntr | IntLatch | TxAvailable | RxEarly | IntReq, |
484 | port: ioaddr + EL3_CMD); |
485 | outw(value: SetIntrEnb | IntLatch | TxAvailable | RxComplete | StatsFull |
486 | | AdapterFailure, port: ioaddr + EL3_CMD); |
487 | } |
488 | |
489 | static void netdev_get_drvinfo(struct net_device *dev, |
490 | struct ethtool_drvinfo *info) |
491 | { |
492 | strscpy(p: info->driver, DRV_NAME, size: sizeof(info->driver)); |
493 | snprintf(buf: info->bus_info, size: sizeof(info->bus_info), |
494 | fmt: "PCMCIA 0x%lx" , dev->base_addr); |
495 | } |
496 | |
497 | static const struct ethtool_ops netdev_ethtool_ops = { |
498 | .get_drvinfo = netdev_get_drvinfo, |
499 | }; |
500 | |
501 | static int el3_config(struct net_device *dev, struct ifmap *map) |
502 | { |
503 | if ((map->port != (u_char)(-1)) && (map->port != dev->if_port)) { |
504 | if (map->port <= 3) { |
505 | dev->if_port = map->port; |
506 | netdev_info(dev, format: "switched to %s port\n" , if_names[dev->if_port]); |
507 | tc589_set_xcvr(dev, if_port: dev->if_port); |
508 | } else { |
509 | return -EINVAL; |
510 | } |
511 | } |
512 | return 0; |
513 | } |
514 | |
515 | static int el3_open(struct net_device *dev) |
516 | { |
517 | struct el3_private *lp = netdev_priv(dev); |
518 | struct pcmcia_device *link = lp->p_dev; |
519 | |
520 | if (!pcmcia_dev_present(p_dev: link)) |
521 | return -ENODEV; |
522 | |
523 | link->open++; |
524 | netif_start_queue(dev); |
525 | |
526 | tc589_reset(dev); |
527 | timer_setup(&lp->media, media_check, 0); |
528 | mod_timer(timer: &lp->media, expires: jiffies + HZ); |
529 | |
530 | dev_dbg(&link->dev, "%s: opened, status %4.4x.\n" , |
531 | dev->name, inw(dev->base_addr + EL3_STATUS)); |
532 | |
533 | return 0; |
534 | } |
535 | |
536 | static void el3_tx_timeout(struct net_device *dev, unsigned int txqueue) |
537 | { |
538 | unsigned int ioaddr = dev->base_addr; |
539 | |
540 | netdev_warn(dev, format: "Transmit timed out!\n" ); |
541 | dump_status(dev); |
542 | dev->stats.tx_errors++; |
543 | netif_trans_update(dev); /* prevent tx timeout */ |
544 | /* Issue TX_RESET and TX_START commands. */ |
545 | tc589_wait_for_completion(dev, cmd: TxReset); |
546 | outw(value: TxEnable, port: ioaddr + EL3_CMD); |
547 | netif_wake_queue(dev); |
548 | } |
549 | |
550 | static void pop_tx_status(struct net_device *dev) |
551 | { |
552 | unsigned int ioaddr = dev->base_addr; |
553 | int i; |
554 | |
555 | /* Clear the Tx status stack. */ |
556 | for (i = 32; i > 0; i--) { |
557 | u_char tx_status = inb(port: ioaddr + TX_STATUS); |
558 | if (!(tx_status & 0x84)) |
559 | break; |
560 | /* reset transmitter on jabber error or underrun */ |
561 | if (tx_status & 0x30) |
562 | tc589_wait_for_completion(dev, cmd: TxReset); |
563 | if (tx_status & 0x38) { |
564 | netdev_dbg(dev, "transmit error: status 0x%02x\n" , tx_status); |
565 | outw(value: TxEnable, port: ioaddr + EL3_CMD); |
566 | dev->stats.tx_aborted_errors++; |
567 | } |
568 | outb(value: 0x00, port: ioaddr + TX_STATUS); /* Pop the status stack. */ |
569 | } |
570 | } |
571 | |
572 | static netdev_tx_t el3_start_xmit(struct sk_buff *skb, |
573 | struct net_device *dev) |
574 | { |
575 | unsigned int ioaddr = dev->base_addr; |
576 | struct el3_private *priv = netdev_priv(dev); |
577 | unsigned long flags; |
578 | |
579 | netdev_dbg(dev, "el3_start_xmit(length = %ld) called, status %4.4x.\n" , |
580 | (long)skb->len, inw(ioaddr + EL3_STATUS)); |
581 | |
582 | spin_lock_irqsave(&priv->lock, flags); |
583 | |
584 | dev->stats.tx_bytes += skb->len; |
585 | |
586 | /* Put out the doubleword header... */ |
587 | outw(value: skb->len, port: ioaddr + TX_FIFO); |
588 | outw(value: 0x00, port: ioaddr + TX_FIFO); |
589 | /* ... and the packet rounded to a doubleword. */ |
590 | outsl(port: ioaddr + TX_FIFO, addr: skb->data, count: (skb->len + 3) >> 2); |
591 | |
592 | if (inw(port: ioaddr + TX_FREE) <= 1536) { |
593 | netif_stop_queue(dev); |
594 | /* Interrupt us when the FIFO has room for max-sized packet. */ |
595 | outw(value: SetTxThreshold + 1536, port: ioaddr + EL3_CMD); |
596 | } |
597 | |
598 | pop_tx_status(dev); |
599 | spin_unlock_irqrestore(lock: &priv->lock, flags); |
600 | dev_kfree_skb(skb); |
601 | |
602 | return NETDEV_TX_OK; |
603 | } |
604 | |
605 | /* The EL3 interrupt handler. */ |
606 | static irqreturn_t el3_interrupt(int irq, void *dev_id) |
607 | { |
608 | struct net_device *dev = (struct net_device *) dev_id; |
609 | struct el3_private *lp = netdev_priv(dev); |
610 | unsigned int ioaddr; |
611 | __u16 status; |
612 | int i = 0, handled = 1; |
613 | |
614 | if (!netif_device_present(dev)) |
615 | return IRQ_NONE; |
616 | |
617 | ioaddr = dev->base_addr; |
618 | |
619 | netdev_dbg(dev, "interrupt, status %4.4x.\n" , inw(ioaddr + EL3_STATUS)); |
620 | |
621 | spin_lock(lock: &lp->lock); |
622 | while ((status = inw(port: ioaddr + EL3_STATUS)) & |
623 | (IntLatch | RxComplete | StatsFull)) { |
624 | if ((status & 0xe000) != 0x2000) { |
625 | netdev_dbg(dev, "interrupt from dead card\n" ); |
626 | handled = 0; |
627 | break; |
628 | } |
629 | if (status & RxComplete) |
630 | el3_rx(dev); |
631 | if (status & TxAvailable) { |
632 | netdev_dbg(dev, " TX room bit was handled.\n" ); |
633 | /* There's room in the FIFO for a full-sized packet. */ |
634 | outw(value: AckIntr | TxAvailable, port: ioaddr + EL3_CMD); |
635 | netif_wake_queue(dev); |
636 | } |
637 | if (status & TxComplete) |
638 | pop_tx_status(dev); |
639 | if (status & (AdapterFailure | RxEarly | StatsFull)) { |
640 | /* Handle all uncommon interrupts. */ |
641 | if (status & StatsFull) /* Empty statistics. */ |
642 | update_stats(dev); |
643 | if (status & RxEarly) { |
644 | /* Rx early is unused. */ |
645 | el3_rx(dev); |
646 | outw(value: AckIntr | RxEarly, port: ioaddr + EL3_CMD); |
647 | } |
648 | if (status & AdapterFailure) { |
649 | u16 fifo_diag; |
650 | EL3WINDOW(4); |
651 | fifo_diag = inw(port: ioaddr + 4); |
652 | EL3WINDOW(1); |
653 | netdev_warn(dev, format: "adapter failure, FIFO diagnostic register %04x.\n" , |
654 | fifo_diag); |
655 | if (fifo_diag & 0x0400) { |
656 | /* Tx overrun */ |
657 | tc589_wait_for_completion(dev, cmd: TxReset); |
658 | outw(value: TxEnable, port: ioaddr + EL3_CMD); |
659 | } |
660 | if (fifo_diag & 0x2000) { |
661 | /* Rx underrun */ |
662 | tc589_wait_for_completion(dev, cmd: RxReset); |
663 | set_rx_mode(dev); |
664 | outw(value: RxEnable, port: ioaddr + EL3_CMD); |
665 | } |
666 | outw(value: AckIntr | AdapterFailure, port: ioaddr + EL3_CMD); |
667 | } |
668 | } |
669 | if (++i > 10) { |
670 | netdev_err(dev, format: "infinite loop in interrupt, status %4.4x.\n" , |
671 | status); |
672 | /* Clear all interrupts */ |
673 | outw(value: AckIntr | 0xFF, port: ioaddr + EL3_CMD); |
674 | break; |
675 | } |
676 | /* Acknowledge the IRQ. */ |
677 | outw(value: AckIntr | IntReq | IntLatch, port: ioaddr + EL3_CMD); |
678 | } |
679 | lp->last_irq = jiffies; |
680 | spin_unlock(lock: &lp->lock); |
681 | netdev_dbg(dev, "exiting interrupt, status %4.4x.\n" , |
682 | inw(ioaddr + EL3_STATUS)); |
683 | return IRQ_RETVAL(handled); |
684 | } |
685 | |
686 | static void media_check(struct timer_list *t) |
687 | { |
688 | struct el3_private *lp = from_timer(lp, t, media); |
689 | struct net_device *dev = lp->p_dev->priv; |
690 | unsigned int ioaddr = dev->base_addr; |
691 | u16 media, errs; |
692 | unsigned long flags; |
693 | |
694 | if (!netif_device_present(dev)) |
695 | goto reschedule; |
696 | |
697 | /* Check for pending interrupt with expired latency timer: with |
698 | * this, we can limp along even if the interrupt is blocked |
699 | */ |
700 | if ((inw(port: ioaddr + EL3_STATUS) & IntLatch) && |
701 | (inb(port: ioaddr + EL3_TIMER) == 0xff)) { |
702 | if (!lp->fast_poll) |
703 | netdev_warn(dev, format: "interrupt(s) dropped!\n" ); |
704 | |
705 | local_irq_save(flags); |
706 | el3_interrupt(irq: dev->irq, dev_id: dev); |
707 | local_irq_restore(flags); |
708 | |
709 | lp->fast_poll = HZ; |
710 | } |
711 | if (lp->fast_poll) { |
712 | lp->fast_poll--; |
713 | lp->media.expires = jiffies + HZ/100; |
714 | add_timer(timer: &lp->media); |
715 | return; |
716 | } |
717 | |
718 | /* lp->lock guards the EL3 window. Window should always be 1 except |
719 | * when the lock is held |
720 | */ |
721 | |
722 | spin_lock_irqsave(&lp->lock, flags); |
723 | EL3WINDOW(4); |
724 | media = inw(port: ioaddr+WN4_MEDIA) & 0xc810; |
725 | |
726 | /* Ignore collisions unless we've had no irq's recently */ |
727 | if (time_before(jiffies, lp->last_irq + HZ)) { |
728 | media &= ~0x0010; |
729 | } else { |
730 | /* Try harder to detect carrier errors */ |
731 | EL3WINDOW(6); |
732 | outw(value: StatsDisable, port: ioaddr + EL3_CMD); |
733 | errs = inb(port: ioaddr + 0); |
734 | outw(value: StatsEnable, port: ioaddr + EL3_CMD); |
735 | dev->stats.tx_carrier_errors += errs; |
736 | if (errs || (lp->media_status & 0x0010)) |
737 | media |= 0x0010; |
738 | } |
739 | |
740 | if (media != lp->media_status) { |
741 | if ((media & lp->media_status & 0x8000) && |
742 | ((lp->media_status ^ media) & 0x0800)) |
743 | netdev_info(dev, format: "%s link beat\n" , |
744 | (lp->media_status & 0x0800 ? "lost" : "found" )); |
745 | else if ((media & lp->media_status & 0x4000) && |
746 | ((lp->media_status ^ media) & 0x0010)) |
747 | netdev_info(dev, format: "coax cable %s\n" , |
748 | (lp->media_status & 0x0010 ? "ok" : "problem" )); |
749 | if (dev->if_port == 0) { |
750 | if (media & 0x8000) { |
751 | if (media & 0x0800) |
752 | netdev_info(dev, format: "flipped to 10baseT\n" ); |
753 | else |
754 | tc589_set_xcvr(dev, if_port: 2); |
755 | } else if (media & 0x4000) { |
756 | if (media & 0x0010) |
757 | tc589_set_xcvr(dev, if_port: 1); |
758 | else |
759 | netdev_info(dev, format: "flipped to 10base2\n" ); |
760 | } |
761 | } |
762 | lp->media_status = media; |
763 | } |
764 | |
765 | EL3WINDOW(1); |
766 | spin_unlock_irqrestore(lock: &lp->lock, flags); |
767 | |
768 | reschedule: |
769 | lp->media.expires = jiffies + HZ; |
770 | add_timer(timer: &lp->media); |
771 | } |
772 | |
773 | static struct net_device_stats *el3_get_stats(struct net_device *dev) |
774 | { |
775 | struct el3_private *lp = netdev_priv(dev); |
776 | unsigned long flags; |
777 | struct pcmcia_device *link = lp->p_dev; |
778 | |
779 | if (pcmcia_dev_present(p_dev: link)) { |
780 | spin_lock_irqsave(&lp->lock, flags); |
781 | update_stats(dev); |
782 | spin_unlock_irqrestore(lock: &lp->lock, flags); |
783 | } |
784 | return &dev->stats; |
785 | } |
786 | |
787 | /* Update statistics. We change to register window 6, so this should be run |
788 | * single-threaded if the device is active. This is expected to be a rare |
789 | * operation, and it's simpler for the rest of the driver to assume that |
790 | * window 1 is always valid rather than use a special window-state variable. |
791 | * |
792 | * Caller must hold the lock for this |
793 | */ |
794 | |
795 | static void update_stats(struct net_device *dev) |
796 | { |
797 | unsigned int ioaddr = dev->base_addr; |
798 | |
799 | netdev_dbg(dev, "updating the statistics.\n" ); |
800 | /* Turn off statistics updates while reading. */ |
801 | outw(value: StatsDisable, port: ioaddr + EL3_CMD); |
802 | /* Switch to the stats window, and read everything. */ |
803 | EL3WINDOW(6); |
804 | dev->stats.tx_carrier_errors += inb(port: ioaddr + 0); |
805 | dev->stats.tx_heartbeat_errors += inb(port: ioaddr + 1); |
806 | /* Multiple collisions. */ |
807 | inb(port: ioaddr + 2); |
808 | dev->stats.collisions += inb(port: ioaddr + 3); |
809 | dev->stats.tx_window_errors += inb(port: ioaddr + 4); |
810 | dev->stats.rx_fifo_errors += inb(port: ioaddr + 5); |
811 | dev->stats.tx_packets += inb(port: ioaddr + 6); |
812 | /* Rx packets */ |
813 | inb(port: ioaddr + 7); |
814 | /* Tx deferrals */ |
815 | inb(port: ioaddr + 8); |
816 | /* Rx octets */ |
817 | inw(port: ioaddr + 10); |
818 | /* Tx octets */ |
819 | inw(port: ioaddr + 12); |
820 | |
821 | /* Back to window 1, and turn statistics back on. */ |
822 | EL3WINDOW(1); |
823 | outw(value: StatsEnable, port: ioaddr + EL3_CMD); |
824 | } |
825 | |
826 | static int el3_rx(struct net_device *dev) |
827 | { |
828 | unsigned int ioaddr = dev->base_addr; |
829 | int worklimit = 32; |
830 | short rx_status; |
831 | |
832 | netdev_dbg(dev, "in rx_packet(), status %4.4x, rx_status %4.4x.\n" , |
833 | inw(ioaddr+EL3_STATUS), inw(ioaddr+RX_STATUS)); |
834 | while (!((rx_status = inw(port: ioaddr + RX_STATUS)) & 0x8000) && |
835 | worklimit > 0) { |
836 | worklimit--; |
837 | if (rx_status & 0x4000) { /* Error, update stats. */ |
838 | short error = rx_status & 0x3800; |
839 | dev->stats.rx_errors++; |
840 | switch (error) { |
841 | case 0x0000: |
842 | dev->stats.rx_over_errors++; |
843 | break; |
844 | case 0x0800: |
845 | dev->stats.rx_length_errors++; |
846 | break; |
847 | case 0x1000: |
848 | dev->stats.rx_frame_errors++; |
849 | break; |
850 | case 0x1800: |
851 | dev->stats.rx_length_errors++; |
852 | break; |
853 | case 0x2000: |
854 | dev->stats.rx_frame_errors++; |
855 | break; |
856 | case 0x2800: |
857 | dev->stats.rx_crc_errors++; |
858 | break; |
859 | } |
860 | } else { |
861 | short pkt_len = rx_status & 0x7ff; |
862 | struct sk_buff *skb; |
863 | |
864 | skb = netdev_alloc_skb(dev, length: pkt_len + 5); |
865 | |
866 | netdev_dbg(dev, " Receiving packet size %d status %4.4x.\n" , |
867 | pkt_len, rx_status); |
868 | if (skb != NULL) { |
869 | skb_reserve(skb, len: 2); |
870 | insl(port: ioaddr+RX_FIFO, addr: skb_put(skb, len: pkt_len), |
871 | count: (pkt_len+3)>>2); |
872 | skb->protocol = eth_type_trans(skb, dev); |
873 | netif_rx(skb); |
874 | dev->stats.rx_packets++; |
875 | dev->stats.rx_bytes += pkt_len; |
876 | } else { |
877 | netdev_dbg(dev, "couldn't allocate a sk_buff of size %d.\n" , |
878 | pkt_len); |
879 | dev->stats.rx_dropped++; |
880 | } |
881 | } |
882 | /* Pop the top of the Rx FIFO */ |
883 | tc589_wait_for_completion(dev, cmd: RxDiscard); |
884 | } |
885 | if (worklimit == 0) |
886 | netdev_warn(dev, format: "too much work in el3_rx!\n" ); |
887 | return 0; |
888 | } |
889 | |
890 | static void set_rx_mode(struct net_device *dev) |
891 | { |
892 | unsigned int ioaddr = dev->base_addr; |
893 | u16 opts = SetRxFilter | RxStation | RxBroadcast; |
894 | |
895 | if (dev->flags & IFF_PROMISC) |
896 | opts |= RxMulticast | RxProm; |
897 | else if (!netdev_mc_empty(dev) || (dev->flags & IFF_ALLMULTI)) |
898 | opts |= RxMulticast; |
899 | outw(value: opts, port: ioaddr + EL3_CMD); |
900 | } |
901 | |
902 | static void set_multicast_list(struct net_device *dev) |
903 | { |
904 | struct el3_private *priv = netdev_priv(dev); |
905 | unsigned long flags; |
906 | |
907 | spin_lock_irqsave(&priv->lock, flags); |
908 | set_rx_mode(dev); |
909 | spin_unlock_irqrestore(lock: &priv->lock, flags); |
910 | } |
911 | |
912 | static int el3_close(struct net_device *dev) |
913 | { |
914 | struct el3_private *lp = netdev_priv(dev); |
915 | struct pcmcia_device *link = lp->p_dev; |
916 | unsigned int ioaddr = dev->base_addr; |
917 | |
918 | dev_dbg(&link->dev, "%s: shutting down ethercard.\n" , dev->name); |
919 | |
920 | if (pcmcia_dev_present(p_dev: link)) { |
921 | /* Turn off statistics ASAP. We update dev->stats below. */ |
922 | outw(value: StatsDisable, port: ioaddr + EL3_CMD); |
923 | |
924 | /* Disable the receiver and transmitter. */ |
925 | outw(value: RxDisable, port: ioaddr + EL3_CMD); |
926 | outw(value: TxDisable, port: ioaddr + EL3_CMD); |
927 | |
928 | if (dev->if_port == 2) |
929 | /* Turn off thinnet power. Green! */ |
930 | outw(value: StopCoax, port: ioaddr + EL3_CMD); |
931 | else if (dev->if_port == 1) { |
932 | /* Disable link beat and jabber */ |
933 | EL3WINDOW(4); |
934 | outw(value: 0, port: ioaddr + WN4_MEDIA); |
935 | } |
936 | |
937 | /* Switching back to window 0 disables the IRQ. */ |
938 | EL3WINDOW(0); |
939 | /* But we explicitly zero the IRQ line select anyway. */ |
940 | outw(value: 0x0f00, port: ioaddr + WN0_IRQ); |
941 | |
942 | /* Check if the card still exists */ |
943 | if ((inw(port: ioaddr+EL3_STATUS) & 0xe000) == 0x2000) |
944 | update_stats(dev); |
945 | } |
946 | |
947 | link->open--; |
948 | netif_stop_queue(dev); |
949 | del_timer_sync(timer: &lp->media); |
950 | |
951 | return 0; |
952 | } |
953 | |
954 | static const struct pcmcia_device_id tc589_ids[] = { |
955 | PCMCIA_MFC_DEVICE_MANF_CARD(0, 0x0101, 0x0562), |
956 | PCMCIA_MFC_DEVICE_PROD_ID1(0, "Motorola MARQUIS" , 0xf03e4e77), |
957 | PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0589), |
958 | PCMCIA_DEVICE_PROD_ID12("Farallon" , "ENet" , 0x58d93fc4, 0x992c2202), |
959 | PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0101, 0x0035, "cis/3CXEM556.cis" ), |
960 | PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0101, 0x003d, "cis/3CXEM556.cis" ), |
961 | PCMCIA_DEVICE_NULL, |
962 | }; |
963 | MODULE_DEVICE_TABLE(pcmcia, tc589_ids); |
964 | |
965 | static struct pcmcia_driver tc589_driver = { |
966 | .owner = THIS_MODULE, |
967 | .name = "3c589_cs" , |
968 | .probe = tc589_probe, |
969 | .remove = tc589_detach, |
970 | .id_table = tc589_ids, |
971 | .suspend = tc589_suspend, |
972 | .resume = tc589_resume, |
973 | }; |
974 | module_pcmcia_driver(tc589_driver); |
975 | |