This source file includes following definitions.
- el16_probe
- el16_probe1
- el16_open
- el16_send_packet
- el16_interrupt
- el16_close
- el16_get_stats
- init_rx_bufs
- init_82586_mem
- hardware_send_packet
- el16_rx
- init_module
- cleanup_module
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 static const char *version =
27 "3c507.c:v1.10 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
28
29
30 #include <linux/module.h>
31
32
33
34
35
36
37
38
39
40
41
42
43 #include <linux/kernel.h>
44 #include <linux/sched.h>
45 #include <linux/types.h>
46 #include <linux/fcntl.h>
47 #include <linux/interrupt.h>
48 #include <linux/ptrace.h>
49 #include <linux/ioport.h>
50 #include <linux/in.h>
51 #include <linux/string.h>
52 #include <asm/system.h>
53 #include <asm/bitops.h>
54 #include <asm/io.h>
55 #include <asm/dma.h>
56 #include <linux/errno.h>
57
58 #include <linux/netdevice.h>
59 #include <linux/etherdevice.h>
60 #include <linux/skbuff.h>
61 #include <linux/malloc.h>
62
63
64
65 #ifndef NET_DEBUG
66 #define NET_DEBUG 1
67 #endif
68 static unsigned int net_debug = NET_DEBUG;
69
70
71 static unsigned int netcard_portlist[] =
72 { 0x300, 0x320, 0x340, 0x280, 0};
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89 #define CUC_START 0x0100
90 #define CUC_RESUME 0x0200
91 #define CUC_SUSPEND 0x0300
92 #define RX_START 0x0010
93 #define RX_RESUME 0x0020
94 #define RX_SUSPEND 0x0030
95
96
97
98
99
100
101
102
103
104
105
106
107
108 #define CMD_EOL 0x8000
109 #define CMD_SUSP 0x4000
110 #define CMD_INTR 0x2000
111
112 enum commands {
113 CmdNOp = 0, CmdSASetup = 1, CmdConfigure = 2, CmdMulticastList = 3,
114 CmdTx = 4, CmdTDR = 5, CmdDump = 6, CmdDiagnose = 7};
115
116
117 struct net_local {
118 struct enet_statistics stats;
119 int last_restart;
120 ushort rx_head;
121 ushort rx_tail;
122 ushort tx_head;
123 ushort tx_cmd_link;
124 ushort tx_reap;
125 };
126
127
128
129
130
131
132
133
134
135 #define SA_DATA 0
136 #define MISC_CTRL 6
137 #define RESET_IRQ 10
138 #define SIGNAL_CA 11
139 #define ROM_CONFIG 13
140 #define MEM_CONFIG 14
141 #define IRQ_CONFIG 15
142 #define EL16_IO_EXTENT 16
143
144
145 #define ID_PORT 0x100
146
147
148 #define iSCB_STATUS 0x8
149 #define iSCB_CMD 0xA
150 #define iSCB_CBL 0xC
151 #define iSCB_RFA 0xE
152
153
154
155
156
157
158
159
160
161
162 #define SCB_BASE ((unsigned)64*1024 - (dev->mem_end - dev->mem_start))
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180 #define CONFIG_CMD 0x0018
181 #define SET_SA_CMD 0x0024
182 #define SA_OFFSET 0x002A
183 #define IDLELOOP 0x30
184 #define TDR_CMD 0x38
185 #define TDR_TIME 0x3C
186 #define DUMP_CMD 0x40
187 #define DIAG_CMD 0x48
188 #define SET_MC_CMD 0x4E
189 #define DUMP_DATA 0x56
190
191 #define TX_BUF_START 0x0100
192 #define NUM_TX_BUFS 4
193 #define TX_BUF_SIZE (1518+14+20+16)
194
195 #define RX_BUF_START 0x2000
196 #define RX_BUF_SIZE (1518+14+18)
197 #define RX_BUF_END (dev->mem_end - dev->mem_start)
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232 unsigned short init_words[] = {
233
234 0x0000,
235 0,0,
236 0x0000,0x0000,
237
238
239 0x0001,
240 0x0008,0,0,
241
242
243 0,0xf000|RX_START|CUC_START,
244 CONFIG_CMD,
245 RX_BUF_START,
246 0,0,0,0,
247
248
249 0, CmdConfigure,
250 SET_SA_CMD,
251 0x0804,
252 0x2e40,
253 0,
254
255
256 0, CmdSASetup,
257 SET_MC_CMD,
258 0xaa00,0xb000,0x0bad,
259
260
261 0, CmdNOp, IDLELOOP, 0 ,
262
263
264 0, CmdTDR, IDLELOOP, 0,
265
266
267 0, CmdDump, IDLELOOP, DUMP_DATA,
268
269
270 0, CmdDiagnose, IDLELOOP,
271
272
273 0, CmdMulticastList, IDLELOOP, 0,
274 };
275
276
277
278 extern int el16_probe(struct device *dev);
279
280 static int el16_probe1(struct device *dev, int ioaddr);
281 static int el16_open(struct device *dev);
282 static int el16_send_packet(struct sk_buff *skb, struct device *dev);
283 static void el16_interrupt(int irq, struct pt_regs *regs);
284 static void el16_rx(struct device *dev);
285 static int el16_close(struct device *dev);
286 static struct enet_statistics *el16_get_stats(struct device *dev);
287
288 static void hardware_send_packet(struct device *dev, void *buf, short length);
289 void init_82586_mem(struct device *dev);
290
291
292 #ifdef HAVE_DEVLIST
293 struct netdev_entry netcard_drv =
294 {"3c507", el16_probe1, EL16_IO_EXTENT, netcard_portlist};
295 #endif
296
297
298
299
300
301
302
303 int
304 el16_probe(struct device *dev)
305 {
306 int base_addr = dev ? dev->base_addr : 0;
307 int i;
308
309 if (base_addr > 0x1ff)
310 return el16_probe1(dev, base_addr);
311 else if (base_addr != 0)
312 return ENXIO;
313
314 for (i = 0; netcard_portlist[i]; i++) {
315 int ioaddr = netcard_portlist[i];
316 if (check_region(ioaddr, EL16_IO_EXTENT))
317 continue;
318 if (el16_probe1(dev, ioaddr) == 0)
319 return 0;
320 }
321
322 return ENODEV;
323 }
324
325 int el16_probe1(struct device *dev, int ioaddr)
326 {
327 static unsigned char init_ID_done = 0, version_printed = 0;
328 int i, irq, irqval;
329
330 if (init_ID_done == 0) {
331 ushort lrs_state = 0xff;
332
333 outb(0x00, ID_PORT);
334 for(i = 0; i < 255; i++) {
335 outb(lrs_state, ID_PORT);
336 lrs_state <<= 1;
337 if (lrs_state & 0x100)
338 lrs_state ^= 0xe7;
339 }
340 outb(0x00, ID_PORT);
341 init_ID_done = 1;
342 }
343
344 if (inb(ioaddr) == '*' && inb(ioaddr+1) == '3'
345 && inb(ioaddr+2) == 'C' && inb(ioaddr+3) == 'O')
346 ;
347 else
348 return ENODEV;
349
350
351 if (dev == NULL)
352 dev = init_etherdev(0, sizeof(struct net_local));
353
354 if (net_debug && version_printed++ == 0)
355 printk(version);
356
357 printk("%s: 3c507 at %#x,", dev->name, ioaddr);
358
359
360
361
362 irq = inb(ioaddr + IRQ_CONFIG) & 0x0f;
363
364 irqval = request_irq(irq, &el16_interrupt, 0, "3c507");
365 if (irqval) {
366 printk ("unable to get IRQ %d (irqval=%d).\n", irq, irqval);
367 return EAGAIN;
368 }
369
370
371 request_region(ioaddr, EL16_IO_EXTENT, "3c507");
372 dev->base_addr = ioaddr;
373
374 outb(0x01, ioaddr + MISC_CTRL);
375 for (i = 0; i < 6; i++) {
376 dev->dev_addr[i] = inb(ioaddr + i);
377 printk(" %02x", dev->dev_addr[i]);
378 }
379
380 if ((dev->mem_start & 0xf) > 0)
381 net_debug = dev->mem_start & 7;
382
383 #ifdef MEM_BASE
384 dev->mem_start = MEM_BASE;
385 dev->mem_end = dev->mem_start + 0x10000;
386 #else
387 {
388 int base;
389 int size;
390 char mem_config = inb(ioaddr + MEM_CONFIG);
391 if (mem_config & 0x20) {
392 size = 64*1024;
393 base = 0xf00000 + (mem_config & 0x08 ? 0x080000
394 : ((mem_config & 3) << 17));
395 } else {
396 size = ((mem_config & 3) + 1) << 14;
397 base = 0x0c0000 + ( (mem_config & 0x18) << 12);
398 }
399 dev->mem_start = base;
400 dev->mem_end = base + size;
401 }
402 #endif
403
404 dev->if_port = (inb(ioaddr + ROM_CONFIG) & 0x80) ? 1 : 0;
405 dev->irq = inb(ioaddr + IRQ_CONFIG) & 0x0f;
406
407 printk(", IRQ %d, %sternal xcvr, memory %#lx-%#lx.\n", dev->irq,
408 dev->if_port ? "ex" : "in", dev->mem_start, dev->mem_end-1);
409
410 if (net_debug)
411 printk(version);
412
413
414 dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);
415 if (dev->priv == NULL)
416 return -ENOMEM;
417 memset(dev->priv, 0, sizeof(struct net_local));
418
419 dev->open = el16_open;
420 dev->stop = el16_close;
421 dev->hard_start_xmit = el16_send_packet;
422 dev->get_stats = el16_get_stats;
423
424 ether_setup(dev);
425
426 dev->flags&=~IFF_MULTICAST;
427
428 return 0;
429 }
430
431
432
433 static int
434 el16_open(struct device *dev)
435 {
436 irq2dev_map[dev->irq] = dev;
437
438
439 init_82586_mem(dev);
440
441 dev->tbusy = 0;
442 dev->interrupt = 0;
443 dev->start = 1;
444
445 MOD_INC_USE_COUNT;
446
447 return 0;
448 }
449
450 static int
451 el16_send_packet(struct sk_buff *skb, struct device *dev)
452 {
453 struct net_local *lp = (struct net_local *)dev->priv;
454 int ioaddr = dev->base_addr;
455 short *shmem = (short*)dev->mem_start;
456
457 if (dev->tbusy) {
458
459
460 int tickssofar = jiffies - dev->trans_start;
461 if (tickssofar < 5)
462 return 1;
463 if (net_debug > 1)
464 printk("%s: transmit timed out, %s? ", dev->name,
465 shmem[iSCB_STATUS>>1] & 0x8000 ? "IRQ conflict" :
466 "network cable problem");
467
468 if (lp->last_restart == lp->stats.tx_packets) {
469 if (net_debug > 1) printk("Resetting board.\n");
470
471 init_82586_mem(dev);
472 } else {
473
474 if (net_debug > 1) printk("Kicking board.\n");
475 shmem[iSCB_CMD>>1] = 0xf000|CUC_START|RX_START;
476 outb(0, ioaddr + SIGNAL_CA);
477 lp->last_restart = lp->stats.tx_packets;
478 }
479 dev->tbusy=0;
480 dev->trans_start = jiffies;
481 }
482
483
484
485
486 if (skb == NULL) {
487 dev_tint(dev);
488 return 0;
489 }
490
491
492 if (set_bit(0, (void*)&dev->tbusy) != 0)
493 printk("%s: Transmitter access conflict.\n", dev->name);
494 else {
495 short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
496 unsigned char *buf = skb->data;
497
498
499 outb(0x80, ioaddr + MISC_CTRL);
500 hardware_send_packet(dev, buf, length);
501 dev->trans_start = jiffies;
502
503 outb(0x84, ioaddr + MISC_CTRL);
504 }
505
506 dev_kfree_skb (skb, FREE_WRITE);
507
508
509
510 return 0;
511 }
512
513
514
515 static void
516 el16_interrupt(int irq, struct pt_regs *regs)
517 {
518 struct device *dev = (struct device *)(irq2dev_map[irq]);
519 struct net_local *lp;
520 int ioaddr, status, boguscount = 0;
521 ushort ack_cmd = 0;
522 ushort *shmem;
523
524 if (dev == NULL) {
525 printk ("net_interrupt(): irq %d for unknown device.\n", irq);
526 return;
527 }
528 dev->interrupt = 1;
529
530 ioaddr = dev->base_addr;
531 lp = (struct net_local *)dev->priv;
532 shmem = ((ushort*)dev->mem_start);
533
534 status = shmem[iSCB_STATUS>>1];
535
536 if (net_debug > 4) {
537 printk("%s: 3c507 interrupt, status %4.4x.\n", dev->name, status);
538 }
539
540
541 outb(0x80, ioaddr + MISC_CTRL);
542
543
544 while (lp->tx_reap != lp->tx_head) {
545 unsigned short tx_status = shmem[lp->tx_reap>>1];
546
547 if (tx_status == 0) {
548 if (net_debug > 5) printk("Couldn't reap %#x.\n", lp->tx_reap);
549 break;
550 }
551 if (tx_status & 0x2000) {
552 lp->stats.tx_packets++;
553 lp->stats.collisions += tx_status & 0xf;
554 dev->tbusy = 0;
555 mark_bh(NET_BH);
556 } else {
557 lp->stats.tx_errors++;
558 if (tx_status & 0x0600) lp->stats.tx_carrier_errors++;
559 if (tx_status & 0x0100) lp->stats.tx_fifo_errors++;
560 if (!(tx_status & 0x0040)) lp->stats.tx_heartbeat_errors++;
561 if (tx_status & 0x0020) lp->stats.tx_aborted_errors++;
562 }
563 if (net_debug > 5)
564 printk("Reaped %x, Tx status %04x.\n" , lp->tx_reap, tx_status);
565 lp->tx_reap += TX_BUF_SIZE;
566 if (lp->tx_reap > RX_BUF_START - TX_BUF_SIZE)
567 lp->tx_reap = TX_BUF_START;
568 if (++boguscount > 4)
569 break;
570 }
571
572 if (status & 0x4000) {
573 if (net_debug > 5)
574 printk("Received packet, rx_head %04x.\n", lp->rx_head);
575 el16_rx(dev);
576 }
577
578
579 ack_cmd = status & 0xf000;
580
581 if ((status & 0x0700) != 0x0200 && dev->start) {
582 if (net_debug)
583 printk("%s: Command unit stopped, status %04x, restarting.\n",
584 dev->name, status);
585
586
587
588 ack_cmd |= CUC_RESUME;
589 }
590
591 if ((status & 0x0070) != 0x0040 && dev->start) {
592 static void init_rx_bufs(struct device *);
593
594
595 if (net_debug)
596 printk("%s: Rx unit stopped, status %04x, restarting.\n",
597 dev->name, status);
598 init_rx_bufs(dev);
599 shmem[iSCB_RFA >> 1] = RX_BUF_START;
600 ack_cmd |= RX_START;
601 }
602
603 shmem[iSCB_CMD>>1] = ack_cmd;
604 outb(0, ioaddr + SIGNAL_CA);
605
606
607 outb(0, ioaddr + RESET_IRQ);
608
609
610 outb(0x84, ioaddr + MISC_CTRL);
611
612 return;
613 }
614
615 static int
616 el16_close(struct device *dev)
617 {
618 int ioaddr = dev->base_addr;
619 ushort *shmem = (short*)dev->mem_start;
620
621 dev->tbusy = 1;
622 dev->start = 0;
623
624
625 shmem[iSCB_CMD >> 1] = RX_SUSPEND | CUC_SUSPEND;
626 outb(0, ioaddr + SIGNAL_CA);
627
628
629 outb(0x80, ioaddr + MISC_CTRL);
630
631
632
633
634 irq2dev_map[dev->irq] = 0;
635
636
637
638 MOD_DEC_USE_COUNT;
639
640 return 0;
641 }
642
643
644
645 static struct enet_statistics *
646 el16_get_stats(struct device *dev)
647 {
648 struct net_local *lp = (struct net_local *)dev->priv;
649
650
651
652 return &lp->stats;
653 }
654
655
656 static void
657 init_rx_bufs(struct device *dev)
658 {
659 struct net_local *lp = (struct net_local *)dev->priv;
660 unsigned short *write_ptr;
661 unsigned short SCB_base = SCB_BASE;
662
663 int cur_rxbuf = lp->rx_head = RX_BUF_START;
664
665
666 do {
667
668 write_ptr = (unsigned short *)(dev->mem_start + cur_rxbuf);
669
670 *write_ptr++ = 0x0000;
671 *write_ptr++ = 0x0000;
672 *write_ptr++ = cur_rxbuf + RX_BUF_SIZE;
673 *write_ptr++ = cur_rxbuf + 22;
674 *write_ptr++ = 0x0000;
675 *write_ptr++ = 0x0000;
676 *write_ptr++ = 0x0000;
677 *write_ptr++ = 0x0000;
678 *write_ptr++ = 0x0000;
679 *write_ptr++ = 0x0000;
680 *write_ptr++ = 0x0000;
681
682 *write_ptr++ = 0x0000;
683 *write_ptr++ = -1;
684 *write_ptr++ = cur_rxbuf + 0x20 + SCB_base;
685 *write_ptr++ = 0x0000;
686
687 *write_ptr++ = 0x8000 + RX_BUF_SIZE-0x20;
688
689 lp->rx_tail = cur_rxbuf;
690 cur_rxbuf += RX_BUF_SIZE;
691 } while (cur_rxbuf <= RX_BUF_END - RX_BUF_SIZE);
692
693
694
695 write_ptr = (unsigned short *)
696 (dev->mem_start + lp->rx_tail + 2);
697 *write_ptr++ = 0xC000;
698 *write_ptr++ = lp->rx_head;
699
700 }
701
702 void
703 init_82586_mem(struct device *dev)
704 {
705 struct net_local *lp = (struct net_local *)dev->priv;
706 short ioaddr = dev->base_addr;
707 ushort *shmem = (short*)dev->mem_start;
708
709
710
711 outb(0x20, ioaddr + MISC_CTRL);
712
713
714 init_words[3] = SCB_BASE;
715 init_words[7] = SCB_BASE;
716
717
718 memcpy((void*)dev->mem_end-10, init_words, 10);
719
720
721 memcpy((char*)dev->mem_start, init_words + 5, sizeof(init_words) - 10);
722
723
724 memcpy((char*)dev->mem_start+SA_OFFSET, dev->dev_addr,
725 sizeof(dev->dev_addr));
726
727
728 lp->tx_cmd_link = IDLELOOP + 4;
729 lp->tx_head = lp->tx_reap = TX_BUF_START;
730
731 init_rx_bufs(dev);
732
733
734 outb(0xA0, ioaddr + MISC_CTRL);
735
736
737
738 outb(0, ioaddr + SIGNAL_CA);
739
740 {
741 int boguscnt = 50;
742 while (shmem[iSCB_STATUS>>1] == 0)
743 if (--boguscnt == 0) {
744 printk("%s: i82586 initialization timed out with status %04x,"
745 "cmd %04x.\n", dev->name,
746 shmem[iSCB_STATUS>>1], shmem[iSCB_CMD>>1]);
747 break;
748 }
749
750 outb(0, ioaddr + SIGNAL_CA);
751 }
752
753
754 outb(0x84, ioaddr + MISC_CTRL);
755 if (net_debug > 4)
756 printk("%s: Initialized 82586, status %04x.\n", dev->name,
757 shmem[iSCB_STATUS>>1]);
758 return;
759 }
760
761 static void
762 hardware_send_packet(struct device *dev, void *buf, short length)
763 {
764 struct net_local *lp = (struct net_local *)dev->priv;
765 short ioaddr = dev->base_addr;
766 ushort tx_block = lp->tx_head;
767 ushort *write_ptr = (ushort *)(dev->mem_start + tx_block);
768
769
770 *write_ptr++ = 0x0000;
771 *write_ptr++ = CMD_INTR|CmdTx;
772 *write_ptr++ = tx_block+16;
773 *write_ptr++ = tx_block+8;
774
775
776 *write_ptr++ = length | 0x8000;
777 *write_ptr++ = -1;
778 *write_ptr++ = tx_block+22+SCB_BASE;
779 *write_ptr++ = 0x0000;
780
781
782 *write_ptr++ = 0x0000;
783 *write_ptr++ = CmdNOp;
784 *write_ptr++ = tx_block+16;
785
786
787 memcpy(write_ptr, buf, length);
788
789
790 *(ushort*)(dev->mem_start + lp->tx_cmd_link) = tx_block;
791 lp->tx_cmd_link = tx_block + 20;
792
793
794 lp->tx_head = tx_block + TX_BUF_SIZE;
795 if (lp->tx_head > RX_BUF_START - TX_BUF_SIZE)
796 lp->tx_head = TX_BUF_START;
797
798 if (net_debug > 4) {
799 printk("%s: 3c507 @%x send length = %d, tx_block %3x, next %3x.\n",
800 dev->name, ioaddr, length, tx_block, lp->tx_head);
801 }
802
803 if (lp->tx_head != lp->tx_reap)
804 dev->tbusy = 0;
805 }
806
807 static void
808 el16_rx(struct device *dev)
809 {
810 struct net_local *lp = (struct net_local *)dev->priv;
811 short *shmem = (short*)dev->mem_start;
812 ushort rx_head = lp->rx_head;
813 ushort rx_tail = lp->rx_tail;
814 ushort boguscount = 10;
815 short frame_status;
816
817 while ((frame_status = shmem[rx_head>>1]) < 0) {
818 ushort *read_frame = (short *)(dev->mem_start + rx_head);
819 ushort rfd_cmd = read_frame[1];
820 ushort next_rx_frame = read_frame[2];
821 ushort data_buffer_addr = read_frame[3];
822 ushort *data_frame = (short *)(dev->mem_start + data_buffer_addr);
823 ushort pkt_len = data_frame[0];
824
825 if (rfd_cmd != 0 || data_buffer_addr != rx_head + 22
826 || (pkt_len & 0xC000) != 0xC000) {
827 printk("%s: Rx frame at %#x corrupted, status %04x cmd %04x"
828 "next %04x data-buf @%04x %04x.\n", dev->name, rx_head,
829 frame_status, rfd_cmd, next_rx_frame, data_buffer_addr,
830 pkt_len);
831 } else if ((frame_status & 0x2000) == 0) {
832
833 lp->stats.rx_errors++;
834 if (frame_status & 0x0800) lp->stats.rx_crc_errors++;
835 if (frame_status & 0x0400) lp->stats.rx_frame_errors++;
836 if (frame_status & 0x0200) lp->stats.rx_fifo_errors++;
837 if (frame_status & 0x0100) lp->stats.rx_over_errors++;
838 if (frame_status & 0x0080) lp->stats.rx_length_errors++;
839 } else {
840
841 struct sk_buff *skb;
842
843 pkt_len &= 0x3fff;
844 skb = dev_alloc_skb(pkt_len+2);
845 if (skb == NULL) {
846 printk("%s: Memory squeeze, dropping packet.\n", dev->name);
847 lp->stats.rx_dropped++;
848 break;
849 }
850
851 skb_reserve(skb,2);
852 skb->dev = dev;
853
854
855 memcpy(skb_put(skb,pkt_len), data_frame + 5, pkt_len);
856
857 skb->protocol=eth_type_trans(skb,dev);
858 netif_rx(skb);
859 lp->stats.rx_packets++;
860 }
861
862
863 read_frame[0] = 0;
864 read_frame[1] = 0xC000;
865
866 *(short*)(dev->mem_start + rx_tail + 2) = 0x0000;
867
868 rx_tail = rx_head;
869 rx_head = next_rx_frame;
870 if (--boguscount == 0)
871 break;
872 }
873
874 lp->rx_head = rx_head;
875 lp->rx_tail = rx_tail;
876 }
877 #ifdef MODULE
878 static char devicename[9] = { 0, };
879 static struct device dev_3c507 = {
880 devicename,
881 0, 0, 0, 0,
882 0, 0,
883 0, 0, 0, NULL, el16_probe
884 };
885
886 static int io = 0x300;
887 static int irq = 0;
888
889 int init_module(void)
890 {
891 if (io == 0)
892 printk("3c507: You should not use auto-probing with insmod!\n");
893 dev_3c507.base_addr = io;
894 dev_3c507.irq = irq;
895 if (register_netdev(&dev_3c507) != 0) {
896 printk("3c507: register_netdev() returned non-zero.\n");
897 return -EIO;
898 }
899 return 0;
900 }
901
902 void
903 cleanup_module(void)
904 {
905 unregister_netdev(&dev_3c507);
906 kfree(dev_3c507.priv);
907 dev_3c507.priv = NULL;
908
909
910 free_irq(dev_3c507.irq);
911 release_region(dev_3c507.base_addr, EL16_IO_EXTENT);
912 }
913 #endif
914
915
916
917
918
919
920
921
922
923