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/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/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 int board;
174 int nodeid;
175 unsigned char node_acquire;
176 struct atalk_addr node_addr;
177 spinlock_t lock;
178};
179
180
181static int cops_probe1 (struct net_device *dev, int ioaddr);
182static int cops_irq (int ioaddr, int board);
183
184static int cops_open (struct net_device *dev);
185static int cops_jumpstart (struct net_device *dev);
186static void cops_reset (struct net_device *dev, int sleep);
187static void cops_load (struct net_device *dev);
188static int cops_nodeid (struct net_device *dev, int nodeid);
189
190static irqreturn_t cops_interrupt (int irq, void *dev_id);
191static void cops_poll (unsigned long ltdev);
192static void cops_timeout(struct net_device *dev);
193static void cops_rx (struct net_device *dev);
194static netdev_tx_t cops_send_packet (struct sk_buff *skb,
195 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);
199
200static 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
213struct 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;
254out1:
255 cleanup_card(dev);
256out:
257 free_netdev(dev);
258 return ERR_PTR(err);
259}
260
261static 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
275static 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
362err_out:
363 release_region(ioaddr, COPS_IO_EXTENT);
364 return retval;
365}
366
367static 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
416static 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 init_timer(&cops_timer);
429 cops_timer.function = cops_poll;
430 cops_timer.data = (unsigned long)dev;
431 cops_timer.expires = jiffies + HZ/20;
432 add_timer(&cops_timer);
433 }
434 else
435 {
436 printk(KERN_WARNING "%s: No irq line set\n", dev->name);
437 return -EAGAIN;
438 }
439 }
440
441 cops_jumpstart(dev);
442
443 netif_start_queue(dev);
444 return 0;
445}
446
447
448
449
450static int cops_jumpstart(struct net_device *dev)
451{
452 struct cops_local *lp = netdev_priv(dev);
453
454
455
456
457
458 cops_reset(dev,1);
459 cops_load(dev);
460
461
462
463
464
465
466
467 if(lp->nodeid == 1)
468 cops_nodeid(dev,lp->node_acquire);
469
470 return 0;
471}
472
473static void tangent_wait_reset(int ioaddr)
474{
475 int timeout=0;
476
477 while(timeout++ < 5 && (inb(ioaddr+TANG_CARD_STATUS)&TANG_TX_READY)==0)
478 mdelay(1);
479}
480
481
482
483
484static void cops_reset(struct net_device *dev, int sleep)
485{
486 struct cops_local *lp = netdev_priv(dev);
487 int ioaddr=dev->base_addr;
488
489 if(lp->board==TANGENT)
490 {
491 inb(ioaddr);
492 outb(0,ioaddr);
493 outb(0, ioaddr+TANG_RESET);
494
495 tangent_wait_reset(ioaddr);
496 outb(0, ioaddr+TANG_CLEAR_INT);
497 }
498 if(lp->board==DAYNA)
499 {
500 outb(0, ioaddr+DAYNA_RESET);
501 inb(ioaddr+DAYNA_RESET);
502 if (sleep)
503 msleep(333);
504 else
505 mdelay(333);
506 }
507
508 netif_wake_queue(dev);
509}
510
511static void cops_load (struct net_device *dev)
512{
513 struct ifreq ifr;
514 struct ltfirmware *ltf= (struct ltfirmware *)&ifr.ifr_ifru;
515 struct cops_local *lp = netdev_priv(dev);
516 int ioaddr=dev->base_addr;
517 int length, i = 0;
518
519 strcpy(ifr.ifr_name,"lt0");
520
521
522#ifdef CONFIG_COPS_DAYNA
523 if(lp->board==DAYNA)
524 {
525 ltf->length=sizeof(ffdrv_code);
526 ltf->data=ffdrv_code;
527 }
528 else
529#endif
530#ifdef CONFIG_COPS_TANGENT
531 if(lp->board==TANGENT)
532 {
533 ltf->length=sizeof(ltdrv_code);
534 ltf->data=ltdrv_code;
535 }
536 else
537#endif
538 {
539 printk(KERN_INFO "%s; unsupported board type.\n", dev->name);
540 return;
541 }
542
543
544 if(lp->board==DAYNA && ltf->length!=5983)
545 {
546 printk(KERN_WARNING "%s: Firmware is not length of FFDRV.BIN.\n", dev->name);
547 return;
548 }
549 if(lp->board==TANGENT && ltf->length!=2501)
550 {
551 printk(KERN_WARNING "%s: Firmware is not length of DRVCODE.BIN.\n", dev->name);
552 return;
553 }
554
555 if(lp->board==DAYNA)
556 {
557
558
559
560
561 while(++i<65536)
562 {
563 if((inb(ioaddr+DAYNA_CARD_STATUS)&3)==1)
564 break;
565 }
566
567 if(i==65536)
568 return;
569 }
570
571
572
573
574 i=0;
575 length = ltf->length;
576 while(length--)
577 {
578 outb(ltf->data[i], ioaddr);
579 i++;
580 }
581
582 if(cops_debug > 1)
583 printk("%s: Uploaded firmware - %d bytes of %d bytes.\n",
584 dev->name, i, ltf->length);
585
586 if(lp->board==DAYNA)
587 outb(1, ioaddr+DAYNA_INT_CARD);
588 else
589 inb(ioaddr);
590
591 if(lp->board==TANGENT)
592 {
593 tangent_wait_reset(ioaddr);
594 inb(ioaddr);
595 }
596}
597
598
599
600
601
602
603
604static int cops_nodeid (struct net_device *dev, int nodeid)
605{
606 struct cops_local *lp = netdev_priv(dev);
607 int ioaddr = dev->base_addr;
608
609 if(lp->board == DAYNA)
610 {
611
612 while((inb(ioaddr+DAYNA_CARD_STATUS)&DAYNA_TX_READY)==0)
613 {
614 outb(0, ioaddr+COPS_CLEAR_INT);
615 if((inb(ioaddr+DAYNA_CARD_STATUS)&0x03)==DAYNA_RX_REQUEST)
616 cops_rx(dev);
617 schedule();
618 }
619
620 outb(2, ioaddr);
621 outb(0, ioaddr);
622 outb(LAP_INIT, ioaddr);
623 outb(nodeid, ioaddr);
624 }
625
626 if(lp->board == TANGENT)
627 {
628
629 while(inb(ioaddr+TANG_CARD_STATUS)&TANG_RX_READY)
630 {
631 outb(0, ioaddr+COPS_CLEAR_INT);
632 cops_rx(dev);
633 schedule();
634 }
635
636
637 if(nodeid == 0)
638 nodeid = jiffies&0xFF;
639 outb(2, ioaddr);
640 outb(0, ioaddr);
641 outb(LAP_INIT, ioaddr);
642 outb(nodeid, ioaddr);
643 outb(0xFF, ioaddr);
644 }
645
646 lp->node_acquire=0;
647 while(lp->node_acquire==0)
648 {
649 outb(0, ioaddr+COPS_CLEAR_INT);
650
651 if(lp->board == DAYNA)
652 {
653 if((inb(ioaddr+DAYNA_CARD_STATUS)&0x03)==DAYNA_RX_REQUEST)
654 cops_rx(dev);
655 }
656 if(lp->board == TANGENT)
657 {
658 if(inb(ioaddr+TANG_CARD_STATUS)&TANG_RX_READY)
659 cops_rx(dev);
660 }
661 schedule();
662 }
663
664 if(cops_debug > 1)
665 printk(KERN_DEBUG "%s: Node ID %d has been acquired.\n",
666 dev->name, lp->node_acquire);
667
668 lp->nodeid=1;
669
670 return 0;
671}
672
673
674
675
676
677static void cops_poll(unsigned long ltdev)
678{
679 int ioaddr, status;
680 int boguscount = 0;
681
682 struct net_device *dev = (struct net_device *)ltdev;
683
684 del_timer(&cops_timer);
685
686 if(dev == NULL)
687 return;
688
689 ioaddr = dev->base_addr;
690 do {
691 status=inb(ioaddr+TANG_CARD_STATUS);
692 if(status & TANG_RX_READY)
693 cops_rx(dev);
694 if(status & TANG_TX_READY)
695 netif_wake_queue(dev);
696 status = inb(ioaddr+TANG_CARD_STATUS);
697 } while((++boguscount < 20) && (status&(TANG_RX_READY|TANG_TX_READY)));
698
699
700 cops_timer.expires = jiffies + HZ/20;
701 add_timer(&cops_timer);
702}
703
704
705
706
707
708static irqreturn_t cops_interrupt(int irq, void *dev_id)
709{
710 struct net_device *dev = dev_id;
711 struct cops_local *lp;
712 int ioaddr, status;
713 int boguscount = 0;
714
715 ioaddr = dev->base_addr;
716 lp = netdev_priv(dev);
717
718 if(lp->board==DAYNA)
719 {
720 do {
721 outb(0, ioaddr + COPS_CLEAR_INT);
722 status=inb(ioaddr+DAYNA_CARD_STATUS);
723 if((status&0x03)==DAYNA_RX_REQUEST)
724 cops_rx(dev);
725 netif_wake_queue(dev);
726 } while(++boguscount < 20);
727 }
728 else
729 {
730 do {
731 status=inb(ioaddr+TANG_CARD_STATUS);
732 if(status & TANG_RX_READY)
733 cops_rx(dev);
734 if(status & TANG_TX_READY)
735 netif_wake_queue(dev);
736 status=inb(ioaddr+TANG_CARD_STATUS);
737 } while((++boguscount < 20) && (status&(TANG_RX_READY|TANG_TX_READY)));
738 }
739
740 return IRQ_HANDLED;
741}
742
743
744
745
746static void cops_rx(struct net_device *dev)
747{
748 int pkt_len = 0;
749 int rsp_type = 0;
750 struct sk_buff *skb = NULL;
751 struct cops_local *lp = netdev_priv(dev);
752 int ioaddr = dev->base_addr;
753 int boguscount = 0;
754 unsigned long flags;
755
756
757 spin_lock_irqsave(&lp->lock, flags);
758
759 if(lp->board==DAYNA)
760 {
761 outb(0, ioaddr);
762 outb(0, ioaddr);
763 outb(DATA_READ, ioaddr);
764
765
766 while(++boguscount<1000000)
767 {
768 barrier();
769 if((inb(ioaddr+DAYNA_CARD_STATUS)&0x03)==DAYNA_RX_READY)
770 break;
771 }
772
773 if(boguscount==1000000)
774 {
775 printk(KERN_WARNING "%s: DMA timed out.\n",dev->name);
776 spin_unlock_irqrestore(&lp->lock, flags);
777 return;
778 }
779 }
780
781
782 if(lp->board==DAYNA)
783 pkt_len = inb(ioaddr) & 0xFF;
784 else
785 pkt_len = inb(ioaddr) & 0x00FF;
786 pkt_len |= (inb(ioaddr) << 8);
787
788 rsp_type=inb(ioaddr);
789
790
791 skb = dev_alloc_skb(pkt_len);
792 if(skb == NULL)
793 {
794 printk(KERN_WARNING "%s: Memory squeeze, dropping packet.\n",
795 dev->name);
796 dev->stats.rx_dropped++;
797 while(pkt_len--)
798 inb(ioaddr);
799 spin_unlock_irqrestore(&lp->lock, flags);
800 return;
801 }
802 skb->dev = dev;
803 skb_put(skb, pkt_len);
804 skb->protocol = htons(ETH_P_LOCALTALK);
805
806 insb(ioaddr, skb->data, pkt_len);
807
808 if(lp->board==DAYNA)
809 outb(1, ioaddr+DAYNA_INT_CARD);
810
811 spin_unlock_irqrestore(&lp->lock, flags);
812
813
814 if(pkt_len < 0 || pkt_len > MAX_LLAP_SIZE)
815 {
816 printk(KERN_WARNING "%s: Bad packet length of %d bytes.\n",
817 dev->name, pkt_len);
818 dev->stats.tx_errors++;
819 dev_kfree_skb_any(skb);
820 return;
821 }
822
823
824 if(rsp_type == LAP_INIT_RSP)
825 {
826 lp->node_acquire = skb->data[0];
827 dev_kfree_skb_any(skb);
828 return;
829 }
830
831
832 if(rsp_type != LAP_RESPONSE)
833 {
834 printk(KERN_WARNING "%s: Bad packet type %d.\n", dev->name, rsp_type);
835 dev->stats.tx_errors++;
836 dev_kfree_skb_any(skb);
837 return;
838 }
839
840 skb_reset_mac_header(skb);
841 skb_pull(skb,3);
842 skb_reset_transport_header(skb);
843
844
845 dev->stats.rx_packets++;
846 dev->stats.rx_bytes += skb->len;
847
848
849 netif_rx(skb);
850}
851
852static void cops_timeout(struct net_device *dev)
853{
854 struct cops_local *lp = netdev_priv(dev);
855 int ioaddr = dev->base_addr;
856
857 dev->stats.tx_errors++;
858 if(lp->board==TANGENT)
859 {
860 if((inb(ioaddr+TANG_CARD_STATUS)&TANG_TX_READY)==0)
861 printk(KERN_WARNING "%s: No TX complete interrupt.\n", dev->name);
862 }
863 printk(KERN_WARNING "%s: Transmit timed out.\n", dev->name);
864 cops_jumpstart(dev);
865 dev->trans_start = jiffies;
866 netif_wake_queue(dev);
867}
868
869
870
871
872
873
874static netdev_tx_t cops_send_packet(struct sk_buff *skb,
875 struct net_device *dev)
876{
877 struct cops_local *lp = netdev_priv(dev);
878 int ioaddr = dev->base_addr;
879 unsigned long flags;
880
881
882
883
884
885 netif_stop_queue(dev);
886
887 spin_lock_irqsave(&lp->lock, flags);
888 if(lp->board == DAYNA)
889 while((inb(ioaddr+DAYNA_CARD_STATUS)&DAYNA_TX_READY)==0)
890 cpu_relax();
891 if(lp->board == TANGENT)
892 while((inb(ioaddr+TANG_CARD_STATUS)&TANG_TX_READY)==0)
893 cpu_relax();
894
895
896 outb(skb->len, ioaddr);
897 if(lp->board == DAYNA)
898 outb(skb->len >> 8, ioaddr);
899 else
900 outb((skb->len >> 8)&0x0FF, ioaddr);
901
902
903 outb(LAP_WRITE, ioaddr);
904
905 if(lp->board == DAYNA)
906 while((inb(ioaddr+DAYNA_CARD_STATUS)&DAYNA_TX_READY)==0);
907
908 outsb(ioaddr, skb->data, skb->len);
909
910 if(lp->board==DAYNA)
911 outb(1, ioaddr+DAYNA_INT_CARD);
912
913 spin_unlock_irqrestore(&lp->lock, flags);
914
915
916 dev->stats.tx_packets++;
917 dev->stats.tx_bytes += skb->len;
918 dev_kfree_skb (skb);
919 return NETDEV_TX_OK;
920}
921
922
923
924
925
926static void set_multicast_list(struct net_device *dev)
927{
928 if(cops_debug >= 3)
929 printk("%s: set_multicast_list executed\n", dev->name);
930}
931
932
933
934
935
936static int cops_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
937{
938 struct cops_local *lp = netdev_priv(dev);
939 struct sockaddr_at *sa = (struct sockaddr_at *)&ifr->ifr_addr;
940 struct atalk_addr *aa = (struct atalk_addr *)&lp->node_addr;
941
942 switch(cmd)
943 {
944 case SIOCSIFADDR:
945
946 cops_nodeid(dev, sa->sat_addr.s_node);
947 aa->s_net = sa->sat_addr.s_net;
948 aa->s_node = lp->node_acquire;
949
950
951 dev->broadcast[0] = 0xFF;
952
953
954 dev->dev_addr[0] = aa->s_node;
955 dev->addr_len = 1;
956 return 0;
957
958 case SIOCGIFADDR:
959 sa->sat_addr.s_net = aa->s_net;
960 sa->sat_addr.s_node = aa->s_node;
961 return 0;
962
963 default:
964 return -EOPNOTSUPP;
965 }
966}
967
968
969
970
971
972static int cops_close(struct net_device *dev)
973{
974 struct cops_local *lp = netdev_priv(dev);
975
976
977
978 if(lp->board==TANGENT && dev->irq==0)
979 del_timer(&cops_timer);
980
981 netif_stop_queue(dev);
982 return 0;
983}
984
985
986#ifdef MODULE
987static struct net_device *cops_dev;
988
989MODULE_LICENSE("GPL");
990module_param(io, int, 0);
991module_param(irq, int, 0);
992module_param(board_type, int, 0);
993
994static int __init cops_module_init(void)
995{
996 if (io == 0)
997 printk(KERN_WARNING "%s: You shouldn't autoprobe with insmod\n",
998 cardname);
999 cops_dev = cops_probe(-1);
1000 if (IS_ERR(cops_dev))
1001 return PTR_ERR(cops_dev);
1002 return 0;
1003}
1004
1005static void __exit cops_module_exit(void)
1006{
1007 unregister_netdev(cops_dev);
1008 cleanup_card(cops_dev);
1009 free_netdev(cops_dev);
1010}
1011module_init(cops_module_init);
1012module_exit(cops_module_exit);
1013#endif
1014