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