This source file includes following definitions.
- cleanup_card
- cops_probe
- cops_probe1
- cops_irq
- cops_open
- cops_jumpstart
- tangent_wait_reset
- cops_reset
- cops_load
- cops_nodeid
- cops_poll
- cops_interrupt
- cops_rx
- cops_timeout
- cops_send_packet
- set_multicast_list
- cops_ioctl
- cops_close
- cops_module_init
- cops_module_exit
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
27
28
29
30
31
32
33
34
35
36 static const char *version =
37 "cops.c:v0.04 6/7/98 Jay Schulist <jschlst@samba.org>\n";
38
39
40
41
42
43
44
45
46
47
48
49
50
51 #include <linux/module.h>
52 #include <linux/kernel.h>
53 #include <linux/types.h>
54 #include <linux/fcntl.h>
55 #include <linux/interrupt.h>
56 #include <linux/ptrace.h>
57 #include <linux/ioport.h>
58 #include <linux/in.h>
59 #include <linux/string.h>
60 #include <linux/errno.h>
61 #include <linux/init.h>
62 #include <linux/netdevice.h>
63 #include <linux/etherdevice.h>
64 #include <linux/skbuff.h>
65 #include <linux/if_arp.h>
66 #include <linux/if_ltalk.h>
67 #include <linux/delay.h>
68 #include <linux/atalk.h>
69 #include <linux/spinlock.h>
70 #include <linux/bitops.h>
71 #include <linux/jiffies.h>
72
73 #include <asm/io.h>
74 #include <asm/dma.h>
75
76 #include "cops.h"
77 #include "cops_ltdrv.h"
78 #include "cops_ffdrv.h"
79
80
81
82
83
84
85 static const char *cardname = "cops";
86
87 #ifdef CONFIG_COPS_DAYNA
88 static int board_type = DAYNA;
89 #else
90 static int board_type = TANGENT;
91 #endif
92
93 static int io = 0x240;
94 static int irq = 5;
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143 static unsigned int ports[] = {
144 0x240, 0x340, 0x200, 0x210, 0x220, 0x230, 0x260,
145 0x2A0, 0x300, 0x310, 0x320, 0x330, 0x350, 0x360,
146 0
147 };
148
149
150
151
152
153 static int cops_irqlist[] = {
154 5, 4, 3, 0
155 };
156
157 static struct timer_list cops_timer;
158 static struct net_device *cops_timer_dev;
159
160
161 #ifndef COPS_DEBUG
162 #define COPS_DEBUG 1
163 #endif
164 static unsigned int cops_debug = COPS_DEBUG;
165
166
167 #define COPS_IO_EXTENT 8
168
169
170
171 struct cops_local
172 {
173 int board;
174 int nodeid;
175 unsigned char node_acquire;
176 struct atalk_addr node_addr;
177 spinlock_t lock;
178 };
179
180
181 static int cops_probe1 (struct net_device *dev, int ioaddr);
182 static int cops_irq (int ioaddr, int board);
183
184 static int cops_open (struct net_device *dev);
185 static int cops_jumpstart (struct net_device *dev);
186 static void cops_reset (struct net_device *dev, int sleep);
187 static void cops_load (struct net_device *dev);
188 static int cops_nodeid (struct net_device *dev, int nodeid);
189
190 static irqreturn_t cops_interrupt (int irq, void *dev_id);
191 static void cops_poll(struct timer_list *t);
192 static void cops_timeout(struct net_device *dev);
193 static void cops_rx (struct net_device *dev);
194 static netdev_tx_t cops_send_packet (struct sk_buff *skb,
195 struct net_device *dev);
196 static void set_multicast_list (struct net_device *dev);
197 static int cops_ioctl (struct net_device *dev, struct ifreq *rq, int cmd);
198 static int cops_close (struct net_device *dev);
199
200 static void cleanup_card(struct net_device *dev)
201 {
202 if (dev->irq)
203 free_irq(dev->irq, dev);
204 release_region(dev->base_addr, COPS_IO_EXTENT);
205 }
206
207
208
209
210
211
212
213 struct net_device * __init cops_probe(int unit)
214 {
215 struct net_device *dev;
216 unsigned *port;
217 int base_addr;
218 int err = 0;
219
220 dev = alloc_ltalkdev(sizeof(struct cops_local));
221 if (!dev)
222 return ERR_PTR(-ENOMEM);
223
224 if (unit >= 0) {
225 sprintf(dev->name, "lt%d", unit);
226 netdev_boot_setup_check(dev);
227 irq = dev->irq;
228 base_addr = dev->base_addr;
229 } else {
230 base_addr = dev->base_addr = io;
231 }
232
233 if (base_addr > 0x1ff) {
234 err = cops_probe1(dev, base_addr);
235 } else if (base_addr != 0) {
236 err = -ENXIO;
237 } else {
238
239
240
241
242
243 for (port = ports; *port && cops_probe1(dev, *port) < 0; port++)
244 ;
245 if (!*port)
246 err = -ENODEV;
247 }
248 if (err)
249 goto out;
250 err = register_netdev(dev);
251 if (err)
252 goto out1;
253 return dev;
254 out1:
255 cleanup_card(dev);
256 out:
257 free_netdev(dev);
258 return ERR_PTR(err);
259 }
260
261 static const struct net_device_ops cops_netdev_ops = {
262 .ndo_open = cops_open,
263 .ndo_stop = cops_close,
264 .ndo_start_xmit = cops_send_packet,
265 .ndo_tx_timeout = cops_timeout,
266 .ndo_do_ioctl = cops_ioctl,
267 .ndo_set_rx_mode = set_multicast_list,
268 };
269
270
271
272
273
274
275 static int __init cops_probe1(struct net_device *dev, int ioaddr)
276 {
277 struct cops_local *lp;
278 static unsigned version_printed;
279 int board = board_type;
280 int retval;
281
282 if(cops_debug && version_printed++ == 0)
283 printk("%s", version);
284
285
286 if (!request_region(ioaddr, COPS_IO_EXTENT, dev->name))
287 return -EBUSY;
288
289
290
291
292
293
294
295
296 dev->irq = irq;
297 switch (dev->irq)
298 {
299 case 0:
300
301 dev->irq = cops_irq(ioaddr, board);
302 if (dev->irq)
303 break;
304
305 case 1:
306 retval = -EINVAL;
307 goto err_out;
308
309
310
311
312 case 2:
313 dev->irq = 9;
314 break;
315
316
317
318
319
320 case 0xff:
321 dev->irq = 0;
322 break;
323
324 default:
325 break;
326 }
327
328
329 if (dev->irq) {
330 retval = request_irq(dev->irq, cops_interrupt, 0, dev->name, dev);
331 if (retval)
332 goto err_out;
333 }
334
335 dev->base_addr = ioaddr;
336
337 lp = netdev_priv(dev);
338 spin_lock_init(&lp->lock);
339
340
341 lp->board = board;
342
343 dev->netdev_ops = &cops_netdev_ops;
344 dev->watchdog_timeo = HZ * 2;
345
346
347
348 if(board==DAYNA)
349 printk("%s: %s at %#3x, using IRQ %d, in Dayna mode.\n",
350 dev->name, cardname, ioaddr, dev->irq);
351 if(board==TANGENT) {
352 if(dev->irq)
353 printk("%s: %s at %#3x, IRQ %d, in Tangent mode\n",
354 dev->name, cardname, ioaddr, dev->irq);
355 else
356 printk("%s: %s at %#3x, using polled IO, in Tangent mode.\n",
357 dev->name, cardname, ioaddr);
358
359 }
360 return 0;
361
362 err_out:
363 release_region(ioaddr, COPS_IO_EXTENT);
364 return retval;
365 }
366
367 static int __init cops_irq (int ioaddr, int board)
368 {
369
370
371
372
373
374
375 int irqaddr=0;
376 int i, x, status;
377
378 if(board==DAYNA)
379 {
380 outb(0, ioaddr+DAYNA_RESET);
381 inb(ioaddr+DAYNA_RESET);
382 mdelay(333);
383 }
384 if(board==TANGENT)
385 {
386 inb(ioaddr);
387 outb(0, ioaddr);
388 outb(0, ioaddr+TANG_RESET);
389 }
390
391 for(i=0; cops_irqlist[i] !=0; i++)
392 {
393 irqaddr = cops_irqlist[i];
394 for(x = 0xFFFF; x>0; x --)
395 {
396 if(board==DAYNA)
397 {
398 status = (inb(ioaddr+DAYNA_CARD_STATUS)&3);
399 if(status == 1)
400 return irqaddr;
401 }
402 if(board==TANGENT)
403 {
404 if((inb(ioaddr+TANG_CARD_STATUS)& TANG_TX_READY) !=0)
405 return irqaddr;
406 }
407 }
408 }
409 return 0;
410 }
411
412
413
414
415
416 static int cops_open(struct net_device *dev)
417 {
418 struct cops_local *lp = netdev_priv(dev);
419
420 if(dev->irq==0)
421 {
422
423
424
425
426 if(lp->board==TANGENT)
427 {
428 cops_timer_dev = dev;
429 timer_setup(&cops_timer, cops_poll, 0);
430 cops_timer.expires = jiffies + HZ/20;
431 add_timer(&cops_timer);
432 }
433 else
434 {
435 printk(KERN_WARNING "%s: No irq line set\n", dev->name);
436 return -EAGAIN;
437 }
438 }
439
440 cops_jumpstart(dev);
441
442 netif_start_queue(dev);
443 return 0;
444 }
445
446
447
448
449 static int cops_jumpstart(struct net_device *dev)
450 {
451 struct cops_local *lp = netdev_priv(dev);
452
453
454
455
456
457 cops_reset(dev,1);
458 cops_load(dev);
459
460
461
462
463
464
465
466 if(lp->nodeid == 1)
467 cops_nodeid(dev,lp->node_acquire);
468
469 return 0;
470 }
471
472 static void tangent_wait_reset(int ioaddr)
473 {
474 int timeout=0;
475
476 while(timeout++ < 5 && (inb(ioaddr+TANG_CARD_STATUS)&TANG_TX_READY)==0)
477 mdelay(1);
478 }
479
480
481
482
483 static void cops_reset(struct net_device *dev, int sleep)
484 {
485 struct cops_local *lp = netdev_priv(dev);
486 int ioaddr=dev->base_addr;
487
488 if(lp->board==TANGENT)
489 {
490 inb(ioaddr);
491 outb(0,ioaddr);
492 outb(0, ioaddr+TANG_RESET);
493
494 tangent_wait_reset(ioaddr);
495 outb(0, ioaddr+TANG_CLEAR_INT);
496 }
497 if(lp->board==DAYNA)
498 {
499 outb(0, ioaddr+DAYNA_RESET);
500 inb(ioaddr+DAYNA_RESET);
501 if (sleep)
502 msleep(333);
503 else
504 mdelay(333);
505 }
506
507 netif_wake_queue(dev);
508 }
509
510 static void cops_load (struct net_device *dev)
511 {
512 struct ifreq ifr;
513 struct ltfirmware *ltf= (struct ltfirmware *)&ifr.ifr_ifru;
514 struct cops_local *lp = netdev_priv(dev);
515 int ioaddr=dev->base_addr;
516 int length, i = 0;
517
518 strcpy(ifr.ifr_name,"lt0");
519
520
521 #ifdef CONFIG_COPS_DAYNA
522 if(lp->board==DAYNA)
523 {
524 ltf->length=sizeof(ffdrv_code);
525 ltf->data=ffdrv_code;
526 }
527 else
528 #endif
529 #ifdef CONFIG_COPS_TANGENT
530 if(lp->board==TANGENT)
531 {
532 ltf->length=sizeof(ltdrv_code);
533 ltf->data=ltdrv_code;
534 }
535 else
536 #endif
537 {
538 printk(KERN_INFO "%s; unsupported board type.\n", dev->name);
539 return;
540 }
541
542
543 if(lp->board==DAYNA && ltf->length!=5983)
544 {
545 printk(KERN_WARNING "%s: Firmware is not length of FFDRV.BIN.\n", dev->name);
546 return;
547 }
548 if(lp->board==TANGENT && ltf->length!=2501)
549 {
550 printk(KERN_WARNING "%s: Firmware is not length of DRVCODE.BIN.\n", dev->name);
551 return;
552 }
553
554 if(lp->board==DAYNA)
555 {
556
557
558
559
560 while(++i<65536)
561 {
562 if((inb(ioaddr+DAYNA_CARD_STATUS)&3)==1)
563 break;
564 }
565
566 if(i==65536)
567 return;
568 }
569
570
571
572
573 i=0;
574 length = ltf->length;
575 while(length--)
576 {
577 outb(ltf->data[i], ioaddr);
578 i++;
579 }
580
581 if(cops_debug > 1)
582 printk("%s: Uploaded firmware - %d bytes of %d bytes.\n",
583 dev->name, i, ltf->length);
584
585 if(lp->board==DAYNA)
586 outb(1, ioaddr+DAYNA_INT_CARD);
587 else
588 inb(ioaddr);
589
590 if(lp->board==TANGENT)
591 {
592 tangent_wait_reset(ioaddr);
593 inb(ioaddr);
594 }
595 }
596
597
598
599
600
601
602
603 static int cops_nodeid (struct net_device *dev, int nodeid)
604 {
605 struct cops_local *lp = netdev_priv(dev);
606 int ioaddr = dev->base_addr;
607
608 if(lp->board == DAYNA)
609 {
610
611 while((inb(ioaddr+DAYNA_CARD_STATUS)&DAYNA_TX_READY)==0)
612 {
613 outb(0, ioaddr+COPS_CLEAR_INT);
614 if((inb(ioaddr+DAYNA_CARD_STATUS)&0x03)==DAYNA_RX_REQUEST)
615 cops_rx(dev);
616 schedule();
617 }
618
619 outb(2, ioaddr);
620 outb(0, ioaddr);
621 outb(LAP_INIT, ioaddr);
622 outb(nodeid, ioaddr);
623 }
624
625 if(lp->board == TANGENT)
626 {
627
628 while(inb(ioaddr+TANG_CARD_STATUS)&TANG_RX_READY)
629 {
630 outb(0, ioaddr+COPS_CLEAR_INT);
631 cops_rx(dev);
632 schedule();
633 }
634
635
636 if(nodeid == 0)
637 nodeid = jiffies&0xFF;
638 outb(2, ioaddr);
639 outb(0, ioaddr);
640 outb(LAP_INIT, ioaddr);
641 outb(nodeid, ioaddr);
642 outb(0xFF, ioaddr);
643 }
644
645 lp->node_acquire=0;
646 while(lp->node_acquire==0)
647 {
648 outb(0, ioaddr+COPS_CLEAR_INT);
649
650 if(lp->board == DAYNA)
651 {
652 if((inb(ioaddr+DAYNA_CARD_STATUS)&0x03)==DAYNA_RX_REQUEST)
653 cops_rx(dev);
654 }
655 if(lp->board == TANGENT)
656 {
657 if(inb(ioaddr+TANG_CARD_STATUS)&TANG_RX_READY)
658 cops_rx(dev);
659 }
660 schedule();
661 }
662
663 if(cops_debug > 1)
664 printk(KERN_DEBUG "%s: Node ID %d has been acquired.\n",
665 dev->name, lp->node_acquire);
666
667 lp->nodeid=1;
668
669 return 0;
670 }
671
672
673
674
675
676 static void cops_poll(struct timer_list *unused)
677 {
678 int ioaddr, status;
679 int boguscount = 0;
680 struct net_device *dev = cops_timer_dev;
681
682 del_timer(&cops_timer);
683
684 if(dev == NULL)
685 return;
686
687 ioaddr = dev->base_addr;
688 do {
689 status=inb(ioaddr+TANG_CARD_STATUS);
690 if(status & TANG_RX_READY)
691 cops_rx(dev);
692 if(status & TANG_TX_READY)
693 netif_wake_queue(dev);
694 status = inb(ioaddr+TANG_CARD_STATUS);
695 } while((++boguscount < 20) && (status&(TANG_RX_READY|TANG_TX_READY)));
696
697
698 cops_timer.expires = jiffies + HZ/20;
699 add_timer(&cops_timer);
700 }
701
702
703
704
705
706 static irqreturn_t cops_interrupt(int irq, void *dev_id)
707 {
708 struct net_device *dev = dev_id;
709 struct cops_local *lp;
710 int ioaddr, status;
711 int boguscount = 0;
712
713 ioaddr = dev->base_addr;
714 lp = netdev_priv(dev);
715
716 if(lp->board==DAYNA)
717 {
718 do {
719 outb(0, ioaddr + COPS_CLEAR_INT);
720 status=inb(ioaddr+DAYNA_CARD_STATUS);
721 if((status&0x03)==DAYNA_RX_REQUEST)
722 cops_rx(dev);
723 netif_wake_queue(dev);
724 } while(++boguscount < 20);
725 }
726 else
727 {
728 do {
729 status=inb(ioaddr+TANG_CARD_STATUS);
730 if(status & TANG_RX_READY)
731 cops_rx(dev);
732 if(status & TANG_TX_READY)
733 netif_wake_queue(dev);
734 status=inb(ioaddr+TANG_CARD_STATUS);
735 } while((++boguscount < 20) && (status&(TANG_RX_READY|TANG_TX_READY)));
736 }
737
738 return IRQ_HANDLED;
739 }
740
741
742
743
744 static void cops_rx(struct net_device *dev)
745 {
746 int pkt_len = 0;
747 int rsp_type = 0;
748 struct sk_buff *skb = NULL;
749 struct cops_local *lp = netdev_priv(dev);
750 int ioaddr = dev->base_addr;
751 int boguscount = 0;
752 unsigned long flags;
753
754
755 spin_lock_irqsave(&lp->lock, flags);
756
757 if(lp->board==DAYNA)
758 {
759 outb(0, ioaddr);
760 outb(0, ioaddr);
761 outb(DATA_READ, ioaddr);
762
763
764 while(++boguscount<1000000)
765 {
766 barrier();
767 if((inb(ioaddr+DAYNA_CARD_STATUS)&0x03)==DAYNA_RX_READY)
768 break;
769 }
770
771 if(boguscount==1000000)
772 {
773 printk(KERN_WARNING "%s: DMA timed out.\n",dev->name);
774 spin_unlock_irqrestore(&lp->lock, flags);
775 return;
776 }
777 }
778
779
780 pkt_len = inb(ioaddr);
781 pkt_len |= (inb(ioaddr) << 8);
782
783 rsp_type=inb(ioaddr);
784
785
786 skb = dev_alloc_skb(pkt_len);
787 if(skb == NULL)
788 {
789 printk(KERN_WARNING "%s: Memory squeeze, dropping packet.\n",
790 dev->name);
791 dev->stats.rx_dropped++;
792 while(pkt_len--)
793 inb(ioaddr);
794 spin_unlock_irqrestore(&lp->lock, flags);
795 return;
796 }
797 skb->dev = dev;
798 skb_put(skb, pkt_len);
799 skb->protocol = htons(ETH_P_LOCALTALK);
800
801 insb(ioaddr, skb->data, pkt_len);
802
803 if(lp->board==DAYNA)
804 outb(1, ioaddr+DAYNA_INT_CARD);
805
806 spin_unlock_irqrestore(&lp->lock, flags);
807
808
809 if(pkt_len < 0 || pkt_len > MAX_LLAP_SIZE)
810 {
811 printk(KERN_WARNING "%s: Bad packet length of %d bytes.\n",
812 dev->name, pkt_len);
813 dev->stats.tx_errors++;
814 dev_kfree_skb_any(skb);
815 return;
816 }
817
818
819 if(rsp_type == LAP_INIT_RSP)
820 {
821 lp->node_acquire = skb->data[0];
822 dev_kfree_skb_any(skb);
823 return;
824 }
825
826
827 if(rsp_type != LAP_RESPONSE)
828 {
829 printk(KERN_WARNING "%s: Bad packet type %d.\n", dev->name, rsp_type);
830 dev->stats.tx_errors++;
831 dev_kfree_skb_any(skb);
832 return;
833 }
834
835 skb_reset_mac_header(skb);
836 skb_pull(skb,3);
837 skb_reset_transport_header(skb);
838
839
840 dev->stats.rx_packets++;
841 dev->stats.rx_bytes += skb->len;
842
843
844 netif_rx(skb);
845 }
846
847 static void cops_timeout(struct net_device *dev)
848 {
849 struct cops_local *lp = netdev_priv(dev);
850 int ioaddr = dev->base_addr;
851
852 dev->stats.tx_errors++;
853 if(lp->board==TANGENT)
854 {
855 if((inb(ioaddr+TANG_CARD_STATUS)&TANG_TX_READY)==0)
856 printk(KERN_WARNING "%s: No TX complete interrupt.\n", dev->name);
857 }
858 printk(KERN_WARNING "%s: Transmit timed out.\n", dev->name);
859 cops_jumpstart(dev);
860 netif_trans_update(dev);
861 netif_wake_queue(dev);
862 }
863
864
865
866
867
868
869 static netdev_tx_t cops_send_packet(struct sk_buff *skb,
870 struct net_device *dev)
871 {
872 struct cops_local *lp = netdev_priv(dev);
873 int ioaddr = dev->base_addr;
874 unsigned long flags;
875
876
877
878
879
880 netif_stop_queue(dev);
881
882 spin_lock_irqsave(&lp->lock, flags);
883 if(lp->board == DAYNA)
884 while((inb(ioaddr+DAYNA_CARD_STATUS)&DAYNA_TX_READY)==0)
885 cpu_relax();
886 if(lp->board == TANGENT)
887 while((inb(ioaddr+TANG_CARD_STATUS)&TANG_TX_READY)==0)
888 cpu_relax();
889
890
891 outb(skb->len, ioaddr);
892 outb(skb->len >> 8, ioaddr);
893
894
895 outb(LAP_WRITE, ioaddr);
896
897 if(lp->board == DAYNA)
898 while((inb(ioaddr+DAYNA_CARD_STATUS)&DAYNA_TX_READY)==0);
899
900 outsb(ioaddr, skb->data, skb->len);
901
902 if(lp->board==DAYNA)
903 outb(1, ioaddr+DAYNA_INT_CARD);
904
905 spin_unlock_irqrestore(&lp->lock, flags);
906
907
908 dev->stats.tx_packets++;
909 dev->stats.tx_bytes += skb->len;
910 dev_kfree_skb (skb);
911 return NETDEV_TX_OK;
912 }
913
914
915
916
917
918 static void set_multicast_list(struct net_device *dev)
919 {
920 if(cops_debug >= 3)
921 printk("%s: set_multicast_list executed\n", dev->name);
922 }
923
924
925
926
927
928 static int cops_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
929 {
930 struct cops_local *lp = netdev_priv(dev);
931 struct sockaddr_at *sa = (struct sockaddr_at *)&ifr->ifr_addr;
932 struct atalk_addr *aa = &lp->node_addr;
933
934 switch(cmd)
935 {
936 case SIOCSIFADDR:
937
938 cops_nodeid(dev, sa->sat_addr.s_node);
939 aa->s_net = sa->sat_addr.s_net;
940 aa->s_node = lp->node_acquire;
941
942
943 dev->broadcast[0] = 0xFF;
944
945
946 dev->dev_addr[0] = aa->s_node;
947 dev->addr_len = 1;
948 return 0;
949
950 case SIOCGIFADDR:
951 sa->sat_addr.s_net = aa->s_net;
952 sa->sat_addr.s_node = aa->s_node;
953 return 0;
954
955 default:
956 return -EOPNOTSUPP;
957 }
958 }
959
960
961
962
963
964 static int cops_close(struct net_device *dev)
965 {
966 struct cops_local *lp = netdev_priv(dev);
967
968
969
970 if(lp->board==TANGENT && dev->irq==0)
971 del_timer(&cops_timer);
972
973 netif_stop_queue(dev);
974 return 0;
975 }
976
977
978 #ifdef MODULE
979 static struct net_device *cops_dev;
980
981 MODULE_LICENSE("GPL");
982 module_param_hw(io, int, ioport, 0);
983 module_param_hw(irq, int, irq, 0);
984 module_param_hw(board_type, int, other, 0);
985
986 static int __init cops_module_init(void)
987 {
988 if (io == 0)
989 printk(KERN_WARNING "%s: You shouldn't autoprobe with insmod\n",
990 cardname);
991 cops_dev = cops_probe(-1);
992 return PTR_ERR_OR_ZERO(cops_dev);
993 }
994
995 static void __exit cops_module_exit(void)
996 {
997 unregister_netdev(cops_dev);
998 cleanup_card(cops_dev);
999 free_netdev(cops_dev);
1000 }
1001 module_init(cops_module_init);
1002 module_exit(cops_module_exit);
1003 #endif