1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24#define DRV_NAME "3c515"
25#define DRV_VERSION "0.99t"
26#define DRV_RELDATE "17-Nov-2001"
27
28static char *version =
29DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " becker@scyld.com and others\n";
30
31#define CORKSCREW 1
32
33
34
35
36static const int rx_copybreak = 200;
37
38
39static const int mtu = 1500;
40
41
42static int max_interrupt_work = 20;
43
44
45#define AUTOMEDIA 1
46
47
48
49
50
51#define VORTEX_BUS_MASTER
52
53
54
55#define TX_RING_SIZE 16
56#define RX_RING_SIZE 16
57#define PKT_BUF_SZ 1536
58
59#include <linux/config.h>
60#include <linux/module.h>
61#include <linux/version.h>
62#include <linux/isapnp.h>
63
64#include <linux/kernel.h>
65#include <linux/sched.h>
66#include <linux/string.h>
67#include <linux/errno.h>
68#include <linux/in.h>
69#include <linux/ioport.h>
70#include <linux/slab.h>
71#include <linux/interrupt.h>
72#include <linux/timer.h>
73#include <linux/ethtool.h>
74
75#include <asm/uaccess.h>
76#include <asm/bitops.h>
77#include <asm/io.h>
78#include <asm/dma.h>
79
80#include <linux/netdevice.h>
81#include <linux/etherdevice.h>
82#include <linux/skbuff.h>
83
84#define NEW_MULTICAST
85#include <linux/delay.h>
86
87
88#define RUN_AT(x) (jiffies + (x))
89
90#define REQUEST_IRQ(i,h,f,n, instance) request_irq(i,h,f,n, instance)
91#define IRQ(irq, dev_id, pt_regs) (irq, dev_id, pt_regs)
92
93MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
94MODULE_DESCRIPTION("3Com 3c515 Corkscrew driver");
95MODULE_LICENSE("GPL");
96
97MODULE_PARM(debug, "i");
98MODULE_PARM(options, "1-" __MODULE_STRING(8) "i");
99MODULE_PARM(rx_copybreak, "i");
100MODULE_PARM(max_interrupt_work, "i");
101MODULE_PARM_DESC(debug, "3c515 debug level (0-6)");
102MODULE_PARM_DESC(options, "3c515: Bits 0-2: media type, bit 3: full duplex, bit 4: bus mastering");
103MODULE_PARM_DESC(rx_copybreak, "3c515 copy breakpoint for copy-only-tiny-frames");
104MODULE_PARM_DESC(max_interrupt_work, "3c515 maximum events handled per interrupt");
105
106
107
108#define DRIVER_DEBUG 1
109
110
111static int rx_nocopy, rx_copy, queued_packet;
112
113
114
115#define WAIT_TX_AVAIL 200
116
117
118#define TX_TIMEOUT 40
119
120
121
122
123#define CORKSCREW_TOTAL_SIZE 0x20
124
125#ifdef DRIVER_DEBUG
126static int corkscrew_debug = DRIVER_DEBUG;
127#else
128static int corkscrew_debug = 1;
129#endif
130
131#define CORKSCREW_ID 10
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192#define EL3WINDOW(win_num) outw(SelectWindow + (win_num), ioaddr + EL3_CMD)
193#define EL3_CMD 0x0e
194#define EL3_STATUS 0x0e
195
196
197
198
199
200
201
202enum corkscrew_cmd {
203 TotalReset = 0 << 11, SelectWindow = 1 << 11, StartCoax = 2 << 11,
204 RxDisable = 3 << 11, RxEnable = 4 << 11, RxReset = 5 << 11,
205 UpStall = 6 << 11, UpUnstall = (6 << 11) + 1,
206 DownStall = (6 << 11) + 2, DownUnstall = (6 << 11) + 3,
207 RxDiscard = 8 << 11, TxEnable = 9 << 11, TxDisable =
208 10 << 11, TxReset = 11 << 11,
209 FakeIntr = 12 << 11, AckIntr = 13 << 11, SetIntrEnb = 14 << 11,
210 SetStatusEnb = 15 << 11, SetRxFilter = 16 << 11, SetRxThreshold =
211 17 << 11,
212 SetTxThreshold = 18 << 11, SetTxStart = 19 << 11,
213 StartDMAUp = 20 << 11, StartDMADown = (20 << 11) + 1, StatsEnable =
214 21 << 11,
215 StatsDisable = 22 << 11, StopCoax = 23 << 11,
216};
217
218
219enum RxFilter {
220 RxStation = 1, RxMulticast = 2, RxBroadcast = 4, RxProm = 8
221};
222
223
224enum corkscrew_status {
225 IntLatch = 0x0001, AdapterFailure = 0x0002, TxComplete = 0x0004,
226 TxAvailable = 0x0008, RxComplete = 0x0010, RxEarly = 0x0020,
227 IntReq = 0x0040, StatsFull = 0x0080,
228 DMADone = 1 << 8, DownComplete = 1 << 9, UpComplete = 1 << 10,
229 DMAInProgress = 1 << 11,
230 CmdInProgress = 1 << 12,
231};
232
233
234
235enum Window1 {
236 TX_FIFO = 0x10, RX_FIFO = 0x10, RxErrors = 0x14,
237 RxStatus = 0x18, Timer = 0x1A, TxStatus = 0x1B,
238 TxFree = 0x1C,
239};
240enum Window0 {
241 Wn0IRQ = 0x08,
242#if defined(CORKSCREW)
243 Wn0EepromCmd = 0x200A,
244 Wn0EepromData = 0x200C,
245#else
246 Wn0EepromCmd = 10,
247 Wn0EepromData = 12,
248#endif
249};
250enum Win0_EEPROM_bits {
251 EEPROM_Read = 0x80, EEPROM_WRITE = 0x40, EEPROM_ERASE = 0xC0,
252 EEPROM_EWENB = 0x30,
253 EEPROM_EWDIS = 0x00,
254};
255
256
257enum eeprom_offset {
258 PhysAddr01 = 0, PhysAddr23 = 1, PhysAddr45 = 2, ModelID = 3,
259 EtherLink3ID = 7,
260};
261
262enum Window3 {
263 Wn3_Config = 0, Wn3_MAC_Ctrl = 6, Wn3_Options = 8,
264};
265union wn3_config {
266 int i;
267 struct w3_config_fields {
268 unsigned int ram_size:3, ram_width:1, ram_speed:2,
269 rom_size:2;
270 int pad8:8;
271 unsigned int ram_split:2, pad18:2, xcvr:3, pad21:1,
272 autoselect:1;
273 int pad24:7;
274 } u;
275};
276
277enum Window4 {
278 Wn4_NetDiag = 6, Wn4_Media = 10,
279};
280enum Win4_Media_bits {
281 Media_SQE = 0x0008,
282 Media_10TP = 0x00C0,
283 Media_Lnk = 0x0080,
284 Media_LnkBeat = 0x0800,
285};
286enum Window7 {
287 Wn7_MasterAddr = 0, Wn7_MasterLen = 6, Wn7_MasterStatus = 12,
288};
289
290
291enum MasterCtrl {
292 PktStatus = 0x400, DownListPtr = 0x404, FragAddr = 0x408, FragLen =
293 0x40c,
294 TxFreeThreshold = 0x40f, UpPktStatus = 0x410, UpListPtr = 0x418,
295};
296
297
298
299
300struct boom_rx_desc {
301 u32 next;
302 s32 status;
303 u32 addr;
304 s32 length;
305};
306
307
308enum rx_desc_status {
309 RxDComplete = 0x00008000, RxDError = 0x4000,
310
311};
312
313struct boom_tx_desc {
314 u32 next;
315 s32 status;
316 u32 addr;
317 s32 length;
318};
319
320struct corkscrew_private {
321 const char *product_name;
322 struct net_device *next_module;
323
324 struct boom_rx_desc rx_ring[RX_RING_SIZE];
325 struct boom_tx_desc tx_ring[TX_RING_SIZE];
326
327 struct sk_buff *rx_skbuff[RX_RING_SIZE];
328 struct sk_buff *tx_skbuff[TX_RING_SIZE];
329 unsigned int cur_rx, cur_tx;
330 unsigned int dirty_rx, dirty_tx;
331 struct net_device_stats stats;
332 struct sk_buff *tx_skb;
333 struct timer_list timer;
334 int capabilities ;
335 int options;
336 int last_rx_packets;
337 unsigned int available_media:8,
338 media_override:3,
339 default_media:3,
340 full_duplex:1, autoselect:1, bus_master:1,
341 full_bus_master_tx:1, full_bus_master_rx:1,
342 tx_full:1;
343};
344
345
346
347
348enum xcvr_types {
349 XCVR_10baseT =
350 0, XCVR_AUI, XCVR_10baseTOnly, XCVR_10base2, XCVR_100baseTx,
351 XCVR_100baseFx, XCVR_MII = 6, XCVR_Default = 8,
352};
353
354static struct media_table {
355 char *name;
356 unsigned int media_bits:16,
357 mask:8,
358 next:8;
359 short wait;
360} media_tbl[] = {
361 { "10baseT", Media_10TP, 0x08, XCVR_10base2, (14 * HZ) / 10 },
362 { "10Mbs AUI", Media_SQE, 0x20, XCVR_Default, (1 * HZ) / 10},
363 { "undefined", 0, 0x80, XCVR_10baseT, 10000},
364 { "10base2", 0, 0x10, XCVR_AUI, (1 * HZ) / 10},
365 { "100baseTX", Media_Lnk, 0x02, XCVR_100baseFx, (14 * HZ) / 10},
366 { "100baseFX", Media_Lnk, 0x04, XCVR_MII, (14 * HZ) / 10},
367 { "MII", 0, 0x40, XCVR_10baseT, 3 * HZ},
368 { "undefined", 0, 0x01, XCVR_10baseT, 10000},
369 { "Default", 0, 0xFF, XCVR_10baseT, 10000},
370};
371
372#ifdef __ISAPNP__
373static struct isapnp_device_id corkscrew_isapnp_adapters[] = {
374 { ISAPNP_ANY_ID, ISAPNP_ANY_ID,
375 ISAPNP_VENDOR('T', 'C', 'M'), ISAPNP_FUNCTION(0x5051),
376 (long) "3Com Fast EtherLink ISA" },
377 { }
378};
379
380MODULE_DEVICE_TABLE(isapnp, corkscrew_isapnp_adapters);
381
382static int corkscrew_isapnp_phys_addr[3];
383
384static int nopnp;
385#endif
386
387static int corkscrew_scan(struct net_device *dev);
388static struct net_device *corkscrew_found_device(struct net_device *dev,
389 int ioaddr, int irq,
390 int product_index,
391 int options);
392static int corkscrew_probe1(struct net_device *dev);
393static int corkscrew_open(struct net_device *dev);
394static void corkscrew_timer(unsigned long arg);
395static int corkscrew_start_xmit(struct sk_buff *skb,
396 struct net_device *dev);
397static int corkscrew_rx(struct net_device *dev);
398static void corkscrew_timeout(struct net_device *dev);
399static int boomerang_rx(struct net_device *dev);
400static void corkscrew_interrupt(int irq, void *dev_id,
401 struct pt_regs *regs);
402static int corkscrew_close(struct net_device *dev);
403static void update_stats(int addr, struct net_device *dev);
404static struct net_device_stats *corkscrew_get_stats(struct net_device *dev);
405static void set_rx_mode(struct net_device *dev);
406static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd);
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423static int options[8] = { -1, -1, -1, -1, -1, -1, -1, -1, };
424
425#ifdef MODULE
426static int debug = -1;
427
428static struct net_device *root_corkscrew_dev;
429
430int init_module(void)
431{
432 int cards_found;
433
434 if (debug >= 0)
435 corkscrew_debug = debug;
436 if (corkscrew_debug)
437 printk(version);
438
439 root_corkscrew_dev = NULL;
440 cards_found = corkscrew_scan(NULL);
441 return cards_found ? 0 : -ENODEV;
442}
443
444#else
445int tc515_probe(struct net_device *dev)
446{
447 int cards_found = 0;
448
449 SET_MODULE_OWNER(dev);
450
451 cards_found = corkscrew_scan(dev);
452
453 if (corkscrew_debug > 0 && cards_found)
454 printk(version);
455
456 return cards_found ? 0 : -ENODEV;
457}
458#endif
459
460static int corkscrew_scan(struct net_device *dev)
461{
462 int cards_found = 0;
463 static int ioaddr;
464#ifdef __ISAPNP__
465 short i;
466 static int pnp_cards;
467#endif
468
469#ifdef __ISAPNP__
470 if(nopnp == 1)
471 goto no_pnp;
472 for(i=0; corkscrew_isapnp_adapters[i].vendor != 0; i++) {
473 struct pci_dev *idev = NULL;
474 int irq;
475 while((idev = isapnp_find_dev(NULL,
476 corkscrew_isapnp_adapters[i].vendor,
477 corkscrew_isapnp_adapters[i].function,
478 idev))) {
479
480 if(idev->active) idev->deactivate(idev);
481
482 if(idev->prepare(idev)<0)
483 continue;
484 if (!(idev->resource[0].flags & IORESOURCE_IO))
485 continue;
486 if(idev->activate(idev)<0) {
487 printk("isapnp configure failed (out of resources?)\n");
488 return -ENOMEM;
489 }
490 if (!idev->resource[0].start || check_region(idev->resource[0].start,16))
491 continue;
492 ioaddr = idev->resource[0].start;
493 irq = idev->irq_resource[0].start;
494 if(corkscrew_debug)
495 printk ("ISAPNP reports %s at i/o 0x%x, irq %d\n",
496 (char*) corkscrew_isapnp_adapters[i].driver_data, ioaddr, irq);
497
498 if ((inw(ioaddr + 0x2002) & 0x1f0) != (ioaddr & 0x1f0))
499 continue;
500
501 {
502 int timer;
503 outw(EEPROM_Read + 7, ioaddr + Wn0EepromCmd);
504
505 for (timer = 4; timer >= 0; timer--) {
506 udelay(162);
507 if ((inw(ioaddr + Wn0EepromCmd) & 0x0200)
508 == 0)
509 break;
510 }
511 if (inw(ioaddr + Wn0EepromData) != 0x6d50)
512 continue;
513 }
514 printk(KERN_INFO "3c515 Resource configuration register %#4.4x, DCR %4.4x.\n",
515 inl(ioaddr + 0x2002), inw(ioaddr + 0x2000));
516
517 corkscrew_isapnp_phys_addr[pnp_cards] = ioaddr;
518 corkscrew_found_device(dev, ioaddr, irq, CORKSCREW_ID, dev
519 && dev->mem_start ? dev->
520 mem_start : options[cards_found]);
521 dev = 0;
522 pnp_cards++;
523 cards_found++;
524 }
525 }
526no_pnp:
527#endif
528
529
530 for (ioaddr = 0x100; ioaddr < 0x400; ioaddr += 0x20) {
531 int irq;
532#ifdef __ISAPNP__
533
534 if(ioaddr == corkscrew_isapnp_phys_addr[0]) continue;
535 if(ioaddr == corkscrew_isapnp_phys_addr[1]) continue;
536 if(ioaddr == corkscrew_isapnp_phys_addr[2]) continue;
537#endif
538 if (check_region(ioaddr, CORKSCREW_TOTAL_SIZE))
539 continue;
540
541 if ((inw(ioaddr + 0x2002) & 0x1f0) != (ioaddr & 0x1f0))
542 continue;
543
544 {
545 int timer;
546 outw(EEPROM_Read + 7, ioaddr + Wn0EepromCmd);
547
548 for (timer = 4; timer >= 0; timer--) {
549 udelay(162);
550 if ((inw(ioaddr + Wn0EepromCmd) & 0x0200)
551 == 0)
552 break;
553 }
554 if (inw(ioaddr + Wn0EepromData) != 0x6d50)
555 continue;
556 }
557 printk(KERN_INFO "3c515 Resource configuration register %#4.4x, DCR %4.4x.\n",
558 inl(ioaddr + 0x2002), inw(ioaddr + 0x2000));
559 irq = inw(ioaddr + 0x2002) & 15;
560 corkscrew_found_device(dev, ioaddr, irq, CORKSCREW_ID, dev
561 && dev->mem_start ? dev->
562 mem_start : options[cards_found]);
563 dev = 0;
564 cards_found++;
565 }
566 if (corkscrew_debug)
567 printk(KERN_INFO "%d 3c515 cards found.\n", cards_found);
568 return cards_found;
569}
570
571static struct net_device *corkscrew_found_device(struct net_device *dev,
572 int ioaddr, int irq,
573 int product_index,
574 int options)
575{
576 struct corkscrew_private *vp;
577
578#ifdef MODULE
579
580 int dev_size = sizeof(struct net_device) +
581 sizeof(struct corkscrew_private) + 15;
582
583 dev = (struct net_device *) kmalloc(dev_size, GFP_KERNEL);
584 if (!dev)
585 return NULL;
586 memset(dev, 0, dev_size);
587
588 dev->priv =
589 (void *) (((long) dev + sizeof(struct net_device) + 15) & ~15);
590 vp = (struct corkscrew_private *) dev->priv;
591 dev->base_addr = ioaddr;
592 dev->irq = irq;
593 dev->dma =
594 (product_index == CORKSCREW_ID ? inw(ioaddr + 0x2000) & 7 : 0);
595 dev->init = corkscrew_probe1;
596 vp->product_name = "3c515";
597 vp->options = options;
598 if (options >= 0) {
599 vp->media_override =
600 ((options & 7) == 2) ? 0 : options & 7;
601 vp->full_duplex = (options & 8) ? 1 : 0;
602 vp->bus_master = (options & 16) ? 1 : 0;
603 } else {
604 vp->media_override = 7;
605 vp->full_duplex = 0;
606 vp->bus_master = 0;
607 }
608 ether_setup(dev);
609 vp->next_module = root_corkscrew_dev;
610 root_corkscrew_dev = dev;
611 SET_MODULE_OWNER(dev);
612 if (register_netdev(dev) != 0) {
613 kfree(dev);
614 return NULL;
615 }
616#else
617
618 dev->priv =
619 kmalloc(sizeof(struct corkscrew_private), GFP_KERNEL);
620 if (!dev->priv)
621 return NULL;
622 memset(dev->priv, 0, sizeof(struct corkscrew_private));
623 dev = init_etherdev(dev, sizeof(struct corkscrew_private));
624 dev->base_addr = ioaddr;
625 dev->irq = irq;
626 dev->dma =
627 (product_index == CORKSCREW_ID ? inw(ioaddr + 0x2000) & 7 : 0);
628 vp = (struct corkscrew_private *) dev->priv;
629 vp->product_name = "3c515";
630 vp->options = options;
631 if (options >= 0) {
632 vp->media_override =
633 ((options & 7) == 2) ? 0 : options & 7;
634 vp->full_duplex = (options & 8) ? 1 : 0;
635 vp->bus_master = (options & 16) ? 1 : 0;
636 } else {
637 vp->media_override = 7;
638 vp->full_duplex = 0;
639 vp->bus_master = 0;
640 }
641
642 corkscrew_probe1(dev);
643#endif
644 return dev;
645}
646
647static int corkscrew_probe1(struct net_device *dev)
648{
649 int ioaddr = dev->base_addr;
650 struct corkscrew_private *vp =
651 (struct corkscrew_private *) dev->priv;
652 unsigned int eeprom[0x40], checksum = 0;
653 int i;
654
655 printk(KERN_INFO "%s: 3Com %s at %#3x,", dev->name,
656 vp->product_name, ioaddr);
657
658
659 EL3WINDOW(0);
660 for (i = 0; i < 0x18; i++) {
661 short *phys_addr = (short *) dev->dev_addr;
662 int timer;
663 outw(EEPROM_Read + i, ioaddr + Wn0EepromCmd);
664
665 for (timer = 4; timer >= 0; timer--) {
666 udelay(162);
667 if ((inw(ioaddr + Wn0EepromCmd) & 0x0200) == 0)
668 break;
669 }
670 eeprom[i] = inw(ioaddr + Wn0EepromData);
671 checksum ^= eeprom[i];
672 if (i < 3)
673 phys_addr[i] = htons(eeprom[i]);
674 }
675 checksum = (checksum ^ (checksum >> 8)) & 0xff;
676 if (checksum != 0x00)
677 printk(" ***INVALID CHECKSUM %4.4x*** ", checksum);
678 for (i = 0; i < 6; i++)
679 printk("%c%2.2x", i ? ':' : ' ', dev->dev_addr[i]);
680 if (eeprom[16] == 0x11c7) {
681 if (request_dma(dev->dma, "3c515")) {
682 printk(", DMA %d allocation failed", dev->dma);
683 dev->dma = 0;
684 } else
685 printk(", DMA %d", dev->dma);
686 }
687 printk(", IRQ %d\n", dev->irq);
688
689 if (corkscrew_debug && (dev->irq <= 0 || dev->irq > 15))
690 printk(KERN_WARNING " *** Warning: this IRQ is unlikely to work! ***\n");
691
692 {
693 char *ram_split[] = { "5:3", "3:1", "1:1", "3:5" };
694 union wn3_config config;
695 EL3WINDOW(3);
696 vp->available_media = inw(ioaddr + Wn3_Options);
697 config.i = inl(ioaddr + Wn3_Config);
698 if (corkscrew_debug > 1)
699 printk(KERN_INFO " Internal config register is %4.4x, transceivers %#x.\n",
700 config.i, inw(ioaddr + Wn3_Options));
701 printk(KERN_INFO " %dK %s-wide RAM %s Rx:Tx split, %s%s interface.\n",
702 8 << config.u.ram_size,
703 config.u.ram_width ? "word" : "byte",
704 ram_split[config.u.ram_split],
705 config.u.autoselect ? "autoselect/" : "",
706 media_tbl[config.u.xcvr].name);
707 dev->if_port = config.u.xcvr;
708 vp->default_media = config.u.xcvr;
709 vp->autoselect = config.u.autoselect;
710 }
711 if (vp->media_override != 7) {
712 printk(KERN_INFO " Media override to transceiver type %d (%s).\n",
713 vp->media_override,
714 media_tbl[vp->media_override].name);
715 dev->if_port = vp->media_override;
716 }
717
718 vp->capabilities = eeprom[16];
719 vp->full_bus_master_tx = (vp->capabilities & 0x20) ? 1 : 0;
720
721
722 vp->full_bus_master_rx = (vp->capabilities & 0x20) ? 1 : 0;
723
724
725 request_region(ioaddr, CORKSCREW_TOTAL_SIZE, vp->product_name);
726
727
728 dev->open = &corkscrew_open;
729 dev->hard_start_xmit = &corkscrew_start_xmit;
730 dev->tx_timeout = &corkscrew_timeout;
731 dev->watchdog_timeo = (400 * HZ) / 1000;
732 dev->stop = &corkscrew_close;
733 dev->get_stats = &corkscrew_get_stats;
734 dev->set_multicast_list = &set_rx_mode;
735 dev->do_ioctl = netdev_ioctl;
736
737 return 0;
738}
739
740
741static int corkscrew_open(struct net_device *dev)
742{
743 int ioaddr = dev->base_addr;
744 struct corkscrew_private *vp =
745 (struct corkscrew_private *) dev->priv;
746 union wn3_config config;
747 int i;
748
749
750 EL3WINDOW(3);
751 if (vp->full_duplex)
752 outb(0x20, ioaddr + Wn3_MAC_Ctrl);
753 config.i = inl(ioaddr + Wn3_Config);
754
755 if (vp->media_override != 7) {
756 if (corkscrew_debug > 1)
757 printk(KERN_INFO "%s: Media override to transceiver %d (%s).\n",
758 dev->name, vp->media_override,
759 media_tbl[vp->media_override].name);
760 dev->if_port = vp->media_override;
761 } else if (vp->autoselect) {
762
763 dev->if_port = 4;
764 while (!(vp->available_media & media_tbl[dev->if_port].mask))
765 dev->if_port = media_tbl[dev->if_port].next;
766
767 if (corkscrew_debug > 1)
768 printk("%s: Initial media type %s.\n",
769 dev->name, media_tbl[dev->if_port].name);
770
771 init_timer(&vp->timer);
772 vp->timer.expires = RUN_AT(media_tbl[dev->if_port].wait);
773 vp->timer.data = (unsigned long) dev;
774 vp->timer.function = &corkscrew_timer;
775 add_timer(&vp->timer);
776 } else
777 dev->if_port = vp->default_media;
778
779 config.u.xcvr = dev->if_port;
780 outl(config.i, ioaddr + Wn3_Config);
781
782 if (corkscrew_debug > 1) {
783 printk("%s: corkscrew_open() InternalConfig %8.8x.\n",
784 dev->name, config.i);
785 }
786
787 outw(TxReset, ioaddr + EL3_CMD);
788 for (i = 20; i >= 0; i--)
789 if (!(inw(ioaddr + EL3_STATUS) & CmdInProgress))
790 break;
791
792 outw(RxReset, ioaddr + EL3_CMD);
793
794 for (i = 20; i >= 0; i--)
795 if (!(inw(ioaddr + EL3_STATUS) & CmdInProgress))
796 break;
797
798 outw(SetStatusEnb | 0x00, ioaddr + EL3_CMD);
799
800
801 if (vp->capabilities == 0x11c7) {
802
803 if (dev->irq == 0
804 || dev->dma == 0
805 || request_irq(dev->irq, &corkscrew_interrupt, 0,
806 vp->product_name, dev)) return -EAGAIN;
807 enable_dma(dev->dma);
808 set_dma_mode(dev->dma, DMA_MODE_CASCADE);
809 } else if (request_irq(dev->irq, &corkscrew_interrupt, SA_SHIRQ,
810 vp->product_name, dev)) {
811 return -EAGAIN;
812 }
813
814 if (corkscrew_debug > 1) {
815 EL3WINDOW(4);
816 printk("%s: corkscrew_open() irq %d media status %4.4x.\n",
817 dev->name, dev->irq, inw(ioaddr + Wn4_Media));
818 }
819
820
821 EL3WINDOW(2);
822 for (i = 0; i < 6; i++)
823 outb(dev->dev_addr[i], ioaddr + i);
824 for (; i < 12; i += 2)
825 outw(0, ioaddr + i);
826
827 if (dev->if_port == 3)
828
829 outw(StartCoax, ioaddr + EL3_CMD);
830 EL3WINDOW(4);
831 outw((inw(ioaddr + Wn4_Media) & ~(Media_10TP | Media_SQE)) |
832 media_tbl[dev->if_port].media_bits, ioaddr + Wn4_Media);
833
834
835 outw(StatsDisable, ioaddr + EL3_CMD);
836 EL3WINDOW(6);
837 for (i = 0; i < 10; i++)
838 inb(ioaddr + i);
839 inw(ioaddr + 10);
840 inw(ioaddr + 12);
841
842 EL3WINDOW(4);
843 inb(ioaddr + 12);
844
845 outw(0x0040, ioaddr + Wn4_NetDiag);
846
847
848 EL3WINDOW(7);
849
850 if (vp->full_bus_master_rx) {
851 vp->cur_rx = vp->dirty_rx = 0;
852 if (corkscrew_debug > 2)
853 printk("%s: Filling in the Rx ring.\n",
854 dev->name);
855 for (i = 0; i < RX_RING_SIZE; i++) {
856 struct sk_buff *skb;
857 if (i < (RX_RING_SIZE - 1))
858 vp->rx_ring[i].next =
859 isa_virt_to_bus(&vp->rx_ring[i + 1]);
860 else
861 vp->rx_ring[i].next = 0;
862 vp->rx_ring[i].status = 0;
863 vp->rx_ring[i].length = PKT_BUF_SZ | 0x80000000;
864 skb = dev_alloc_skb(PKT_BUF_SZ);
865 vp->rx_skbuff[i] = skb;
866 if (skb == NULL)
867 break;
868 skb->dev = dev;
869 skb_reserve(skb, 2);
870 vp->rx_ring[i].addr = isa_virt_to_bus(skb->tail);
871 }
872 vp->rx_ring[i - 1].next = isa_virt_to_bus(&vp->rx_ring[0]);
873 outl(isa_virt_to_bus(&vp->rx_ring[0]), ioaddr + UpListPtr);
874 }
875 if (vp->full_bus_master_tx) {
876 vp->cur_tx = vp->dirty_tx = 0;
877 outb(PKT_BUF_SZ >> 8, ioaddr + TxFreeThreshold);
878
879 for (i = 0; i < TX_RING_SIZE; i++)
880 vp->tx_skbuff[i] = 0;
881 outl(0, ioaddr + DownListPtr);
882 }
883
884 set_rx_mode(dev);
885 outw(StatsEnable, ioaddr + EL3_CMD);
886
887 netif_start_queue(dev);
888
889 outw(RxEnable, ioaddr + EL3_CMD);
890 outw(TxEnable, ioaddr + EL3_CMD);
891
892 outw(SetStatusEnb | AdapterFailure | IntReq | StatsFull |
893 (vp->full_bus_master_tx ? DownComplete : TxAvailable) |
894 (vp->full_bus_master_rx ? UpComplete : RxComplete) |
895 (vp->bus_master ? DMADone : 0), ioaddr + EL3_CMD);
896
897 outw(AckIntr | IntLatch | TxAvailable | RxEarly | IntReq,
898 ioaddr + EL3_CMD);
899 outw(SetIntrEnb | IntLatch | TxAvailable | RxComplete | StatsFull
900 | (vp->bus_master ? DMADone : 0) | UpComplete | DownComplete,
901 ioaddr + EL3_CMD);
902
903 return 0;
904}
905
906static void corkscrew_timer(unsigned long data)
907{
908#ifdef AUTOMEDIA
909 struct net_device *dev = (struct net_device *) data;
910 struct corkscrew_private *vp =
911 (struct corkscrew_private *) dev->priv;
912 int ioaddr = dev->base_addr;
913 unsigned long flags;
914 int ok = 0;
915
916 if (corkscrew_debug > 1)
917 printk("%s: Media selection timer tick happened, %s.\n",
918 dev->name, media_tbl[dev->if_port].name);
919
920 save_flags(flags);
921 cli(); {
922 int old_window = inw(ioaddr + EL3_CMD) >> 13;
923 int media_status;
924 EL3WINDOW(4);
925 media_status = inw(ioaddr + Wn4_Media);
926 switch (dev->if_port) {
927 case 0:
928 case 4:
929 case 5:
930 if (media_status & Media_LnkBeat) {
931 ok = 1;
932 if (corkscrew_debug > 1)
933 printk("%s: Media %s has link beat, %x.\n",
934 dev->name,
935 media_tbl[dev->if_port].name,
936 media_status);
937 } else if (corkscrew_debug > 1)
938 printk("%s: Media %s is has no link beat, %x.\n",
939 dev->name,
940 media_tbl[dev->if_port].name,
941 media_status);
942
943 break;
944 default:
945 if (corkscrew_debug > 1)
946 printk("%s: Media %s is has no indication, %x.\n",
947 dev->name,
948 media_tbl[dev->if_port].name,
949 media_status);
950 ok = 1;
951 }
952 if (!ok) {
953 union wn3_config config;
954
955 do {
956 dev->if_port =
957 media_tbl[dev->if_port].next;
958 }
959 while (!(vp->available_media & media_tbl[dev->if_port].mask));
960
961 if (dev->if_port == 8) {
962 dev->if_port = vp->default_media;
963 if (corkscrew_debug > 1)
964 printk("%s: Media selection failing, using default %s port.\n",
965 dev->name,
966 media_tbl[dev->if_port].name);
967 } else {
968 if (corkscrew_debug > 1)
969 printk("%s: Media selection failed, now trying %s port.\n",
970 dev->name,
971 media_tbl[dev->if_port].name);
972 vp->timer.expires = RUN_AT(media_tbl[dev->if_port].wait);
973 add_timer(&vp->timer);
974 }
975 outw((media_status & ~(Media_10TP | Media_SQE)) |
976 media_tbl[dev->if_port].media_bits,
977 ioaddr + Wn4_Media);
978
979 EL3WINDOW(3);
980 config.i = inl(ioaddr + Wn3_Config);
981 config.u.xcvr = dev->if_port;
982 outl(config.i, ioaddr + Wn3_Config);
983
984 outw(dev->if_port == 3 ? StartCoax : StopCoax,
985 ioaddr + EL3_CMD);
986 }
987 EL3WINDOW(old_window);
988 }
989 restore_flags(flags);
990 if (corkscrew_debug > 1)
991 printk("%s: Media selection timer finished, %s.\n",
992 dev->name, media_tbl[dev->if_port].name);
993
994#endif
995 return;
996}
997
998static void corkscrew_timeout(struct net_device *dev)
999{
1000 int i;
1001 struct corkscrew_private *vp =
1002 (struct corkscrew_private *) dev->priv;
1003 int ioaddr = dev->base_addr;
1004
1005 printk(KERN_WARNING
1006 "%s: transmit timed out, tx_status %2.2x status %4.4x.\n",
1007 dev->name, inb(ioaddr + TxStatus),
1008 inw(ioaddr + EL3_STATUS));
1009
1010 if ((inb(ioaddr + TxStatus) & 0x88) == 0x88)
1011 printk(KERN_WARNING
1012 "%s: Transmitter encountered 16 collisions -- network"
1013 " network cable problem?\n", dev->name);
1014#ifndef final_version
1015 printk(" Flags; bus-master %d, full %d; dirty %d current %d.\n",
1016 vp->full_bus_master_tx, vp->tx_full, vp->dirty_tx,
1017 vp->cur_tx);
1018 printk(" Down list %8.8x vs. %p.\n", inl(ioaddr + DownListPtr),
1019 &vp->tx_ring[0]);
1020 for (i = 0; i < TX_RING_SIZE; i++) {
1021 printk(" %d: %p length %8.8x status %8.8x\n", i,
1022 &vp->tx_ring[i],
1023 vp->tx_ring[i].length, vp->tx_ring[i].status);
1024 }
1025#endif
1026
1027 outw(TxReset, ioaddr + EL3_CMD);
1028 for (i = 20; i >= 0; i--)
1029 if (!(inw(ioaddr + EL3_STATUS) & CmdInProgress))
1030 break;
1031 outw(TxEnable, ioaddr + EL3_CMD);
1032 dev->trans_start = jiffies;
1033 vp->stats.tx_errors++;
1034 vp->stats.tx_dropped++;
1035 netif_wake_queue(dev);
1036}
1037
1038static int corkscrew_start_xmit(struct sk_buff *skb,
1039 struct net_device *dev)
1040{
1041 struct corkscrew_private *vp =
1042 (struct corkscrew_private *) dev->priv;
1043 int ioaddr = dev->base_addr;
1044
1045
1046
1047 netif_stop_queue(dev);
1048
1049 if (vp->full_bus_master_tx) {
1050
1051 int entry = vp->cur_tx % TX_RING_SIZE;
1052 struct boom_tx_desc *prev_entry;
1053 unsigned long flags, i;
1054
1055 if (vp->tx_full)
1056 return 1;
1057 if (vp->cur_tx != 0)
1058 prev_entry =
1059 &vp->tx_ring[(vp->cur_tx - 1) % TX_RING_SIZE];
1060 else
1061 prev_entry = NULL;
1062 if (corkscrew_debug > 3)
1063 printk("%s: Trying to send a packet, Tx index %d.\n",
1064 dev->name, vp->cur_tx);
1065
1066 vp->tx_skbuff[entry] = skb;
1067 vp->tx_ring[entry].next = 0;
1068 vp->tx_ring[entry].addr = isa_virt_to_bus(skb->data);
1069 vp->tx_ring[entry].length = skb->len | 0x80000000;
1070 vp->tx_ring[entry].status = skb->len | 0x80000000;
1071
1072 save_flags(flags);
1073 cli();
1074 outw(DownStall, ioaddr + EL3_CMD);
1075
1076 for (i = 20; i >= 0; i--)
1077 if ((inw(ioaddr + EL3_STATUS) & CmdInProgress) ==
1078 0) break;
1079 if (prev_entry)
1080 prev_entry->next =
1081 isa_virt_to_bus(&vp->tx_ring[entry]);
1082 if (inl(ioaddr + DownListPtr) == 0) {
1083 outl(isa_virt_to_bus(&vp->tx_ring[entry]),
1084 ioaddr + DownListPtr);
1085 queued_packet++;
1086 }
1087 outw(DownUnstall, ioaddr + EL3_CMD);
1088 restore_flags(flags);
1089
1090 vp->cur_tx++;
1091 if (vp->cur_tx - vp->dirty_tx > TX_RING_SIZE - 1)
1092 vp->tx_full = 1;
1093 else {
1094 if (prev_entry)
1095 prev_entry->status &= ~0x80000000;
1096 netif_wake_queue(dev);
1097 }
1098 dev->trans_start = jiffies;
1099 return 0;
1100 }
1101
1102 outl(skb->len, ioaddr + TX_FIFO);
1103 vp->stats.tx_bytes += skb->len;
1104#ifdef VORTEX_BUS_MASTER
1105 if (vp->bus_master) {
1106
1107 outl((int) (skb->data), ioaddr + Wn7_MasterAddr);
1108 outw((skb->len + 3) & ~3, ioaddr + Wn7_MasterLen);
1109 vp->tx_skb = skb;
1110 outw(StartDMADown, ioaddr + EL3_CMD);
1111
1112 } else {
1113
1114 outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
1115 dev_kfree_skb(skb);
1116 if (inw(ioaddr + TxFree) > 1536) {
1117 netif_wake_queue(dev);
1118 } else
1119
1120 outw(SetTxThreshold + (1536 >> 2),
1121 ioaddr + EL3_CMD);
1122 }
1123#else
1124
1125 outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
1126 dev_kfree_skb(skb);
1127 if (inw(ioaddr + TxFree) > 1536) {
1128 netif_wake_queue(dev);
1129 } else
1130
1131 outw(SetTxThreshold + (1536 >> 2), ioaddr + EL3_CMD);
1132#endif
1133
1134 dev->trans_start = jiffies;
1135
1136
1137 {
1138 short tx_status;
1139 int i = 4;
1140
1141 while (--i > 0 && (tx_status = inb(ioaddr + TxStatus)) > 0) {
1142 if (tx_status & 0x3C) {
1143 if (corkscrew_debug > 2)
1144 printk("%s: Tx error, status %2.2x.\n",
1145 dev->name, tx_status);
1146 if (tx_status & 0x04)
1147 vp->stats.tx_fifo_errors++;
1148 if (tx_status & 0x38)
1149 vp->stats.tx_aborted_errors++;
1150 if (tx_status & 0x30) {
1151 int j;
1152 outw(TxReset, ioaddr + EL3_CMD);
1153 for (j = 20; j >= 0; j--)
1154 if (!(inw(ioaddr + EL3_STATUS) & CmdInProgress))
1155 break;
1156 }
1157 outw(TxEnable, ioaddr + EL3_CMD);
1158 }
1159 outb(0x00, ioaddr + TxStatus);
1160 }
1161 }
1162 return 0;
1163}
1164
1165
1166
1167
1168static void corkscrew_interrupt(int irq, void *dev_id,
1169 struct pt_regs *regs)
1170{
1171
1172 struct net_device *dev = dev_id;
1173 struct corkscrew_private *lp;
1174 int ioaddr, status;
1175 int latency;
1176 int i = max_interrupt_work;
1177
1178 ioaddr = dev->base_addr;
1179 latency = inb(ioaddr + Timer);
1180 lp = (struct corkscrew_private *) dev->priv;
1181
1182 status = inw(ioaddr + EL3_STATUS);
1183
1184 if (corkscrew_debug > 4)
1185 printk("%s: interrupt, status %4.4x, timer %d.\n",
1186 dev->name, status, latency);
1187 if ((status & 0xE000) != 0xE000) {
1188 static int donedidthis;
1189
1190
1191
1192 if (donedidthis++ > 100) {
1193 printk(KERN_ERR "%s: Bogus interrupt, bailing. Status %4.4x, start=%d.\n",
1194 dev->name, status, netif_running(dev));
1195 free_irq(dev->irq, dev);
1196 }
1197 }
1198
1199 do {
1200 if (corkscrew_debug > 5)
1201 printk("%s: In interrupt loop, status %4.4x.\n",
1202 dev->name, status);
1203 if (status & RxComplete)
1204 corkscrew_rx(dev);
1205
1206 if (status & TxAvailable) {
1207 if (corkscrew_debug > 5)
1208 printk
1209 (" TX room bit was handled.\n");
1210
1211 outw(AckIntr | TxAvailable, ioaddr + EL3_CMD);
1212 netif_wake_queue(dev);
1213 }
1214 if (status & DownComplete) {
1215 unsigned int dirty_tx = lp->dirty_tx;
1216
1217 while (lp->cur_tx - dirty_tx > 0) {
1218 int entry = dirty_tx % TX_RING_SIZE;
1219 if (inl(ioaddr + DownListPtr) ==
1220 isa_virt_to_bus(&lp->tx_ring[entry]))
1221 break;
1222 if (lp->tx_skbuff[entry]) {
1223 dev_kfree_skb_irq(lp->
1224 tx_skbuff
1225 [entry]);
1226 lp->tx_skbuff[entry] = 0;
1227 }
1228 dirty_tx++;
1229 }
1230 lp->dirty_tx = dirty_tx;
1231 outw(AckIntr | DownComplete, ioaddr + EL3_CMD);
1232 if (lp->tx_full
1233 && (lp->cur_tx - dirty_tx <= TX_RING_SIZE - 1)) {
1234 lp->tx_full = 0;
1235 netif_wake_queue(dev);
1236 }
1237 }
1238#ifdef VORTEX_BUS_MASTER
1239 if (status & DMADone) {
1240 outw(0x1000, ioaddr + Wn7_MasterStatus);
1241 dev_kfree_skb_irq(lp->tx_skb);
1242 netif_wake_queue(dev);
1243 }
1244#endif
1245 if (status & UpComplete) {
1246 boomerang_rx(dev);
1247 outw(AckIntr | UpComplete, ioaddr + EL3_CMD);
1248 }
1249 if (status & (AdapterFailure | RxEarly | StatsFull)) {
1250
1251 if (status & RxEarly) {
1252 corkscrew_rx(dev);
1253 outw(AckIntr | RxEarly, ioaddr + EL3_CMD);
1254 }
1255 if (status & StatsFull) {
1256 static int DoneDidThat;
1257 if (corkscrew_debug > 4)
1258 printk("%s: Updating stats.\n",
1259 dev->name);
1260 update_stats(ioaddr, dev);
1261
1262
1263 if (DoneDidThat == 0 &&
1264 inw(ioaddr + EL3_STATUS) & StatsFull) {
1265 int win, reg;
1266 printk("%s: Updating stats failed, disabling stats as an"
1267 " interrupt source.\n",
1268 dev->name);
1269 for (win = 0; win < 8; win++) {
1270 EL3WINDOW(win);
1271 printk("\n Vortex window %d:", win);
1272 for (reg = 0; reg < 16; reg++)
1273 printk(" %2.2x",
1274 inb(ioaddr + reg));
1275 }
1276 EL3WINDOW(7);
1277 outw(SetIntrEnb | TxAvailable |
1278 RxComplete | AdapterFailure |
1279 UpComplete | DownComplete |
1280 TxComplete, ioaddr + EL3_CMD);
1281 DoneDidThat++;
1282 }
1283 }
1284 if (status & AdapterFailure) {
1285
1286 outw(RxReset, ioaddr + EL3_CMD);
1287
1288 set_rx_mode(dev);
1289 outw(RxEnable, ioaddr + EL3_CMD);
1290 outw(AckIntr | AdapterFailure,
1291 ioaddr + EL3_CMD);
1292 }
1293 }
1294
1295 if (--i < 0) {
1296 printk(KERN_ERR "%s: Too much work in interrupt, status %4.4x. "
1297 "Disabling functions (%4.4x).\n", dev->name,
1298 status, SetStatusEnb | ((~status) & 0x7FE));
1299
1300 outw(SetStatusEnb | ((~status) & 0x7FE),
1301 ioaddr + EL3_CMD);
1302 outw(AckIntr | 0x7FF, ioaddr + EL3_CMD);
1303 break;
1304 }
1305
1306 outw(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD);
1307
1308 } while ((status = inw(ioaddr + EL3_STATUS)) &
1309 (IntLatch | RxComplete));
1310
1311 if (corkscrew_debug > 4)
1312 printk("%s: exiting interrupt, status %4.4x.\n", dev->name,
1313 status);
1314}
1315
1316static int corkscrew_rx(struct net_device *dev)
1317{
1318 struct corkscrew_private *vp = (struct corkscrew_private *) dev->priv;
1319 int ioaddr = dev->base_addr;
1320 int i;
1321 short rx_status;
1322
1323 if (corkscrew_debug > 5)
1324 printk(" In rx_packet(), status %4.4x, rx_status %4.4x.\n",
1325 inw(ioaddr + EL3_STATUS), inw(ioaddr + RxStatus));
1326 while ((rx_status = inw(ioaddr + RxStatus)) > 0) {
1327 if (rx_status & 0x4000) {
1328 unsigned char rx_error = inb(ioaddr + RxErrors);
1329 if (corkscrew_debug > 2)
1330 printk(" Rx error: status %2.2x.\n",
1331 rx_error);
1332 vp->stats.rx_errors++;
1333 if (rx_error & 0x01)
1334 vp->stats.rx_over_errors++;
1335 if (rx_error & 0x02)
1336 vp->stats.rx_length_errors++;
1337 if (rx_error & 0x04)
1338 vp->stats.rx_frame_errors++;
1339 if (rx_error & 0x08)
1340 vp->stats.rx_crc_errors++;
1341 if (rx_error & 0x10)
1342 vp->stats.rx_length_errors++;
1343 } else {
1344
1345 short pkt_len = rx_status & 0x1fff;
1346 struct sk_buff *skb;
1347
1348 skb = dev_alloc_skb(pkt_len + 5 + 2);
1349 if (corkscrew_debug > 4)
1350 printk("Receiving packet size %d status %4.4x.\n",
1351 pkt_len, rx_status);
1352 if (skb != NULL) {
1353 skb->dev = dev;
1354 skb_reserve(skb, 2);
1355
1356 insl(ioaddr + RX_FIFO,
1357 skb_put(skb, pkt_len),
1358 (pkt_len + 3) >> 2);
1359 outw(RxDiscard, ioaddr + EL3_CMD);
1360 skb->protocol = eth_type_trans(skb, dev);
1361 netif_rx(skb);
1362 dev->last_rx = jiffies;
1363 vp->stats.rx_packets++;
1364 vp->stats.rx_bytes += pkt_len;
1365
1366 for (i = 200; i >= 0; i--)
1367 if (! (inw(ioaddr + EL3_STATUS) & CmdInProgress))
1368 break;
1369 continue;
1370 } else if (corkscrew_debug)
1371 printk("%s: Couldn't allocate a sk_buff of size %d.\n", dev->name, pkt_len);
1372 }
1373 outw(RxDiscard, ioaddr + EL3_CMD);
1374 vp->stats.rx_dropped++;
1375
1376 for (i = 200; i >= 0; i--)
1377 if (!(inw(ioaddr + EL3_STATUS) & CmdInProgress))
1378 break;
1379 }
1380 return 0;
1381}
1382
1383static int boomerang_rx(struct net_device *dev)
1384{
1385 struct corkscrew_private *vp =
1386 (struct corkscrew_private *) dev->priv;
1387 int entry = vp->cur_rx % RX_RING_SIZE;
1388 int ioaddr = dev->base_addr;
1389 int rx_status;
1390
1391 if (corkscrew_debug > 5)
1392 printk(" In boomerang_rx(), status %4.4x, rx_status %4.4x.\n",
1393 inw(ioaddr + EL3_STATUS), inw(ioaddr + RxStatus));
1394 while ((rx_status = vp->rx_ring[entry].status) & RxDComplete) {
1395 if (rx_status & RxDError) {
1396 unsigned char rx_error = rx_status >> 16;
1397 if (corkscrew_debug > 2)
1398 printk(" Rx error: status %2.2x.\n",
1399 rx_error);
1400 vp->stats.rx_errors++;
1401 if (rx_error & 0x01)
1402 vp->stats.rx_over_errors++;
1403 if (rx_error & 0x02)
1404 vp->stats.rx_length_errors++;
1405 if (rx_error & 0x04)
1406 vp->stats.rx_frame_errors++;
1407 if (rx_error & 0x08)
1408 vp->stats.rx_crc_errors++;
1409 if (rx_error & 0x10)
1410 vp->stats.rx_length_errors++;
1411 } else {
1412
1413 short pkt_len = rx_status & 0x1fff;
1414 struct sk_buff *skb;
1415
1416 vp->stats.rx_bytes += pkt_len;
1417 if (corkscrew_debug > 4)
1418 printk("Receiving packet size %d status %4.4x.\n",
1419 pkt_len, rx_status);
1420
1421
1422
1423 if (pkt_len < rx_copybreak
1424 && (skb = dev_alloc_skb(pkt_len + 4)) != 0) {
1425 skb->dev = dev;
1426 skb_reserve(skb, 2);
1427
1428 memcpy(skb_put(skb, pkt_len),
1429 isa_bus_to_virt(vp->rx_ring[entry].
1430 addr), pkt_len);
1431 rx_copy++;
1432 } else {
1433 void *temp;
1434
1435 skb = vp->rx_skbuff[entry];
1436 vp->rx_skbuff[entry] = NULL;
1437 temp = skb_put(skb, pkt_len);
1438
1439 if (isa_bus_to_virt(vp->rx_ring[entry].addr) != temp)
1440 printk("%s: Warning -- the skbuff addresses do not match"
1441 " in boomerang_rx: %p vs. %p / %p.\n",
1442 dev->name,
1443 isa_bus_to_virt(vp->
1444 rx_ring[entry].
1445 addr), skb->head,
1446 temp);
1447 rx_nocopy++;
1448 }
1449 skb->protocol = eth_type_trans(skb, dev);
1450 netif_rx(skb);
1451 dev->last_rx = jiffies;
1452 vp->stats.rx_packets++;
1453 }
1454 entry = (++vp->cur_rx) % RX_RING_SIZE;
1455 }
1456
1457 for (; vp->cur_rx - vp->dirty_rx > 0; vp->dirty_rx++) {
1458 struct sk_buff *skb;
1459 entry = vp->dirty_rx % RX_RING_SIZE;
1460 if (vp->rx_skbuff[entry] == NULL) {
1461 skb = dev_alloc_skb(PKT_BUF_SZ);
1462 if (skb == NULL)
1463 break;
1464 skb->dev = dev;
1465 skb_reserve(skb, 2);
1466 vp->rx_ring[entry].addr = isa_virt_to_bus(skb->tail);
1467 vp->rx_skbuff[entry] = skb;
1468 }
1469 vp->rx_ring[entry].status = 0;
1470 }
1471 return 0;
1472}
1473
1474static int corkscrew_close(struct net_device *dev)
1475{
1476 struct corkscrew_private *vp =
1477 (struct corkscrew_private *) dev->priv;
1478 int ioaddr = dev->base_addr;
1479 int i;
1480
1481 netif_stop_queue(dev);
1482
1483 if (corkscrew_debug > 1) {
1484 printk("%s: corkscrew_close() status %4.4x, Tx status %2.2x.\n",
1485 dev->name, inw(ioaddr + EL3_STATUS),
1486 inb(ioaddr + TxStatus));
1487 printk("%s: corkscrew close stats: rx_nocopy %d rx_copy %d"
1488 " tx_queued %d.\n", dev->name, rx_nocopy, rx_copy,
1489 queued_packet);
1490 }
1491
1492 del_timer(&vp->timer);
1493
1494
1495 outw(StatsDisable, ioaddr + EL3_CMD);
1496
1497
1498 outw(RxDisable, ioaddr + EL3_CMD);
1499 outw(TxDisable, ioaddr + EL3_CMD);
1500
1501 if (dev->if_port == XCVR_10base2)
1502
1503 outw(StopCoax, ioaddr + EL3_CMD);
1504
1505 free_irq(dev->irq, dev);
1506
1507 outw(SetIntrEnb | 0x0000, ioaddr + EL3_CMD);
1508
1509 update_stats(ioaddr, dev);
1510 if (vp->full_bus_master_rx) {
1511 outl(0, ioaddr + UpListPtr);
1512 for (i = 0; i < RX_RING_SIZE; i++)
1513 if (vp->rx_skbuff[i]) {
1514 dev_kfree_skb(vp->rx_skbuff[i]);
1515 vp->rx_skbuff[i] = 0;
1516 }
1517 }
1518 if (vp->full_bus_master_tx) {
1519 outl(0, ioaddr + DownListPtr);
1520 for (i = 0; i < TX_RING_SIZE; i++)
1521 if (vp->tx_skbuff[i]) {
1522 dev_kfree_skb(vp->tx_skbuff[i]);
1523 vp->tx_skbuff[i] = 0;
1524 }
1525 }
1526
1527 return 0;
1528}
1529
1530static struct net_device_stats *corkscrew_get_stats(struct net_device *dev)
1531{
1532 struct corkscrew_private *vp =
1533 (struct corkscrew_private *) dev->priv;
1534 unsigned long flags;
1535
1536 if (netif_running(dev)) {
1537 save_flags(flags);
1538 cli();
1539 update_stats(dev->base_addr, dev);
1540 restore_flags(flags);
1541 }
1542 return &vp->stats;
1543}
1544
1545
1546
1547
1548
1549
1550
1551
1552static void update_stats(int ioaddr, struct net_device *dev)
1553{
1554 struct corkscrew_private *vp =
1555 (struct corkscrew_private *) dev->priv;
1556
1557
1558
1559 EL3WINDOW(6);
1560 vp->stats.tx_carrier_errors += inb(ioaddr + 0);
1561 vp->stats.tx_heartbeat_errors += inb(ioaddr + 1);
1562 inb(ioaddr + 2);
1563 vp->stats.collisions += inb(ioaddr + 3);
1564 vp->stats.tx_window_errors += inb(ioaddr + 4);
1565 vp->stats.rx_fifo_errors += inb(ioaddr + 5);
1566 vp->stats.tx_packets += inb(ioaddr + 6);
1567 vp->stats.tx_packets += (inb(ioaddr + 9) & 0x30) << 4;
1568 inb(ioaddr + 7);
1569
1570 inb(ioaddr + 8);
1571
1572
1573
1574 inw(ioaddr + 10);
1575 inw(ioaddr + 12);
1576
1577 EL3WINDOW(4);
1578 inb(ioaddr + 12);
1579
1580
1581 EL3WINDOW(7);
1582 return;
1583}
1584
1585
1586
1587
1588
1589static void set_rx_mode(struct net_device *dev)
1590{
1591 int ioaddr = dev->base_addr;
1592 short new_mode;
1593
1594 if (dev->flags & IFF_PROMISC) {
1595 if (corkscrew_debug > 3)
1596 printk("%s: Setting promiscuous mode.\n",
1597 dev->name);
1598 new_mode = SetRxFilter | RxStation | RxMulticast | RxBroadcast | RxProm;
1599 } else if ((dev->mc_list) || (dev->flags & IFF_ALLMULTI)) {
1600 new_mode = SetRxFilter | RxStation | RxMulticast | RxBroadcast;
1601 } else
1602 new_mode = SetRxFilter | RxStation | RxBroadcast;
1603
1604 outw(new_mode, ioaddr + EL3_CMD);
1605}
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr)
1616{
1617 u32 ethcmd;
1618
1619
1620
1621
1622 if (get_user(ethcmd, (u32 *)useraddr))
1623 return -EFAULT;
1624
1625 switch (ethcmd) {
1626
1627 case ETHTOOL_GDRVINFO: {
1628 struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
1629 strcpy (info.driver, DRV_NAME);
1630 strcpy (info.version, DRV_VERSION);
1631 sprintf(info.bus_info, "ISA 0x%lx", dev->base_addr);
1632 if (copy_to_user (useraddr, &info, sizeof (info)))
1633 return -EFAULT;
1634 return 0;
1635 }
1636
1637
1638 case ETHTOOL_GMSGLVL: {
1639 struct ethtool_value edata = {ETHTOOL_GMSGLVL};
1640 edata.data = corkscrew_debug;
1641 if (copy_to_user(useraddr, &edata, sizeof(edata)))
1642 return -EFAULT;
1643 return 0;
1644 }
1645
1646 case ETHTOOL_SMSGLVL: {
1647 struct ethtool_value edata;
1648 if (copy_from_user(&edata, useraddr, sizeof(edata)))
1649 return -EFAULT;
1650 corkscrew_debug = edata.data;
1651 return 0;
1652 }
1653
1654 default:
1655 break;
1656 }
1657
1658 return -EOPNOTSUPP;
1659}
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
1671{
1672 int rc = 0;
1673
1674 switch (cmd) {
1675 case SIOCETHTOOL:
1676 rc = netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
1677 break;
1678
1679 default:
1680 rc = -EOPNOTSUPP;
1681 break;
1682 }
1683
1684 return rc;
1685}
1686
1687
1688#ifdef MODULE
1689void cleanup_module(void)
1690{
1691 struct net_device *next_dev;
1692
1693
1694 while (root_corkscrew_dev) {
1695 next_dev =
1696 ((struct corkscrew_private *) root_corkscrew_dev->
1697 priv)->next_module;
1698 if (root_corkscrew_dev->dma)
1699 free_dma(root_corkscrew_dev->dma);
1700 unregister_netdev(root_corkscrew_dev);
1701 outw(TotalReset, root_corkscrew_dev->base_addr + EL3_CMD);
1702 release_region(root_corkscrew_dev->base_addr,
1703 CORKSCREW_TOTAL_SIZE);
1704 kfree(root_corkscrew_dev);
1705 root_corkscrew_dev = next_dev;
1706 }
1707}
1708#endif
1709
1710
1711
1712
1713
1714
1715
1716
1717