1
2
3
4
5
6
7
8
9
10
11
12
13
14
15#include <linux/module.h>
16#include <asm/system.h>
17#include <asm/uaccess.h>
18#include <linux/bitops.h>
19#include <linux/string.h>
20#include <linux/mm.h>
21#include <linux/interrupt.h>
22#include <linux/in.h>
23#include <linux/tty.h>
24#include <linux/errno.h>
25#include <linux/netdevice.h>
26#include <linux/timer.h>
27#include <net/ax25.h>
28#include <linux/etherdevice.h>
29#include <linux/skbuff.h>
30#include <linux/rtnetlink.h>
31#include <linux/spinlock.h>
32#include <linux/if_arp.h>
33#include <linux/init.h>
34#include <linux/ip.h>
35#include <linux/tcp.h>
36#include <linux/semaphore.h>
37#include <asm/atomic.h>
38
39#define SIXPACK_VERSION "Revision: 0.3.0"
40
41
42#define SIXP_SEOF 0x40
43#define SIXP_TX_URUN 0x48
44#define SIXP_RX_ORUN 0x50
45#define SIXP_RX_BUF_OVL 0x58
46
47#define SIXP_CHKSUM 0xFF
48
49
50
51#define SIXP_CMD_MASK 0xC0
52#define SIXP_CHN_MASK 0x07
53#define SIXP_PRIO_CMD_MASK 0x80
54#define SIXP_STD_CMD_MASK 0x40
55#define SIXP_PRIO_DATA_MASK 0x38
56#define SIXP_TX_MASK 0x20
57#define SIXP_RX_MASK 0x10
58#define SIXP_RX_DCD_MASK 0x18
59#define SIXP_LEDS_ON 0x78
60#define SIXP_LEDS_OFF 0x60
61#define SIXP_CON 0x08
62#define SIXP_STA 0x10
63
64#define SIXP_FOUND_TNC 0xe9
65#define SIXP_CON_ON 0x68
66#define SIXP_DCD_MASK 0x08
67#define SIXP_DAMA_OFF 0
68
69
70#define SIXP_TXDELAY (HZ/4)
71#define SIXP_PERSIST 50
72#define SIXP_SLOTTIME (HZ/10)
73#define SIXP_INIT_RESYNC_TIMEOUT (3*HZ/2)
74#define SIXP_RESYNC_TIMEOUT 5*HZ
75
76
77#define SIXP_NRUNIT 31
78#define SIXP_MTU 256
79
80enum sixpack_flags {
81 SIXPF_ERROR,
82};
83
84struct sixpack {
85
86 struct tty_struct *tty;
87 struct net_device *dev;
88
89
90 unsigned char *rbuff;
91 int rcount;
92 unsigned char *xbuff;
93 unsigned char *xhead;
94 int xleft;
95
96 unsigned char raw_buf[4];
97 unsigned char cooked_buf[400];
98
99 unsigned int rx_count;
100 unsigned int rx_count_cooked;
101
102 int mtu;
103 int buffsize;
104
105 unsigned long flags;
106 unsigned char mode;
107
108
109 unsigned char tx_delay;
110 unsigned char persistence;
111 unsigned char slottime;
112 unsigned char duplex;
113 unsigned char led_state;
114 unsigned char status;
115 unsigned char status1;
116 unsigned char status2;
117 unsigned char tx_enable;
118 unsigned char tnc_state;
119
120 struct timer_list tx_t;
121 struct timer_list resync_t;
122 atomic_t refcnt;
123 struct semaphore dead_sem;
124 spinlock_t lock;
125};
126
127#define AX25_6PACK_HEADER_LEN 0
128
129static void sixpack_decode(struct sixpack *, unsigned char[], int);
130static int encode_sixpack(unsigned char *, unsigned char *, int, unsigned char);
131
132
133
134
135
136
137
138static void sp_xmit_on_air(unsigned long channel)
139{
140 struct sixpack *sp = (struct sixpack *) channel;
141 int actual, when = sp->slottime;
142 static unsigned char random;
143
144 random = random * 17 + 41;
145
146 if (((sp->status1 & SIXP_DCD_MASK) == 0) && (random < sp->persistence)) {
147 sp->led_state = 0x70;
148 sp->tty->ops->write(sp->tty, &sp->led_state, 1);
149 sp->tx_enable = 1;
150 actual = sp->tty->ops->write(sp->tty, sp->xbuff, sp->status2);
151 sp->xleft -= actual;
152 sp->xhead += actual;
153 sp->led_state = 0x60;
154 sp->tty->ops->write(sp->tty, &sp->led_state, 1);
155 sp->status2 = 0;
156 } else
157 mod_timer(&sp->tx_t, jiffies + ((when + 1) * HZ) / 100);
158}
159
160
161
162
163static void sp_encaps(struct sixpack *sp, unsigned char *icp, int len)
164{
165 unsigned char *msg, *p = icp;
166 int actual, count;
167
168 if (len > sp->mtu) {
169 msg = "oversized transmit packet!";
170 goto out_drop;
171 }
172
173 if (len > sp->mtu) {
174 msg = "oversized transmit packet!";
175 goto out_drop;
176 }
177
178 if (p[0] > 5) {
179 msg = "invalid KISS command";
180 goto out_drop;
181 }
182
183 if ((p[0] != 0) && (len > 2)) {
184 msg = "KISS control packet too long";
185 goto out_drop;
186 }
187
188 if ((p[0] == 0) && (len < 15)) {
189 msg = "bad AX.25 packet to transmit";
190 goto out_drop;
191 }
192
193 count = encode_sixpack(p, sp->xbuff, len, sp->tx_delay);
194 set_bit(TTY_DO_WRITE_WAKEUP, &sp->tty->flags);
195
196 switch (p[0]) {
197 case 1: sp->tx_delay = p[1];
198 return;
199 case 2: sp->persistence = p[1];
200 return;
201 case 3: sp->slottime = p[1];
202 return;
203 case 4:
204 return;
205 case 5: sp->duplex = p[1];
206 return;
207 }
208
209 if (p[0] != 0)
210 return;
211
212
213
214
215
216
217
218 if (sp->duplex == 1) {
219 sp->led_state = 0x70;
220 sp->tty->ops->write(sp->tty, &sp->led_state, 1);
221 sp->tx_enable = 1;
222 actual = sp->tty->ops->write(sp->tty, sp->xbuff, count);
223 sp->xleft = count - actual;
224 sp->xhead = sp->xbuff + actual;
225 sp->led_state = 0x60;
226 sp->tty->ops->write(sp->tty, &sp->led_state, 1);
227 } else {
228 sp->xleft = count;
229 sp->xhead = sp->xbuff;
230 sp->status2 = count;
231 sp_xmit_on_air((unsigned long)sp);
232 }
233
234 return;
235
236out_drop:
237 sp->dev->stats.tx_dropped++;
238 netif_start_queue(sp->dev);
239 if (net_ratelimit())
240 printk(KERN_DEBUG "%s: %s - dropped.\n", sp->dev->name, msg);
241}
242
243
244
245static netdev_tx_t sp_xmit(struct sk_buff *skb, struct net_device *dev)
246{
247 struct sixpack *sp = netdev_priv(dev);
248
249 spin_lock_bh(&sp->lock);
250
251 netif_stop_queue(dev);
252 dev->stats.tx_bytes += skb->len;
253 sp_encaps(sp, skb->data, skb->len);
254 spin_unlock_bh(&sp->lock);
255
256 dev_kfree_skb(skb);
257
258 return NETDEV_TX_OK;
259}
260
261static int sp_open_dev(struct net_device *dev)
262{
263 struct sixpack *sp = netdev_priv(dev);
264
265 if (sp->tty == NULL)
266 return -ENODEV;
267 return 0;
268}
269
270
271static int sp_close(struct net_device *dev)
272{
273 struct sixpack *sp = netdev_priv(dev);
274
275 spin_lock_bh(&sp->lock);
276 if (sp->tty) {
277
278 clear_bit(TTY_DO_WRITE_WAKEUP, &sp->tty->flags);
279 }
280 netif_stop_queue(dev);
281 spin_unlock_bh(&sp->lock);
282
283 return 0;
284}
285
286
287static int sp_header(struct sk_buff *skb, struct net_device *dev,
288 unsigned short type, const void *daddr,
289 const void *saddr, unsigned len)
290{
291#ifdef CONFIG_INET
292 if (type != ETH_P_AX25)
293 return ax25_hard_header(skb, dev, type, daddr, saddr, len);
294#endif
295 return 0;
296}
297
298static int sp_set_mac_address(struct net_device *dev, void *addr)
299{
300 struct sockaddr_ax25 *sa = addr;
301
302 netif_tx_lock_bh(dev);
303 netif_addr_lock(dev);
304 memcpy(dev->dev_addr, &sa->sax25_call, AX25_ADDR_LEN);
305 netif_addr_unlock(dev);
306 netif_tx_unlock_bh(dev);
307
308 return 0;
309}
310
311static int sp_rebuild_header(struct sk_buff *skb)
312{
313#ifdef CONFIG_INET
314 return ax25_rebuild_header(skb);
315#else
316 return 0;
317#endif
318}
319
320static const struct header_ops sp_header_ops = {
321 .create = sp_header,
322 .rebuild = sp_rebuild_header,
323};
324
325static const struct net_device_ops sp_netdev_ops = {
326 .ndo_open = sp_open_dev,
327 .ndo_stop = sp_close,
328 .ndo_start_xmit = sp_xmit,
329 .ndo_set_mac_address = sp_set_mac_address,
330};
331
332static void sp_setup(struct net_device *dev)
333{
334
335 dev->netdev_ops = &sp_netdev_ops;
336 dev->destructor = free_netdev;
337 dev->mtu = SIXP_MTU;
338 dev->hard_header_len = AX25_MAX_HEADER_LEN;
339 dev->header_ops = &sp_header_ops;
340
341 dev->addr_len = AX25_ADDR_LEN;
342 dev->type = ARPHRD_AX25;
343 dev->tx_queue_len = 10;
344
345
346 memcpy(dev->broadcast, &ax25_bcast, AX25_ADDR_LEN);
347 memcpy(dev->dev_addr, &ax25_defaddr, AX25_ADDR_LEN);
348
349 dev->flags = 0;
350}
351
352
353
354
355
356
357
358
359static void sp_bump(struct sixpack *sp, char cmd)
360{
361 struct sk_buff *skb;
362 int count;
363 unsigned char *ptr;
364
365 count = sp->rcount + 1;
366
367 sp->dev->stats.rx_bytes += count;
368
369 if ((skb = dev_alloc_skb(count)) == NULL)
370 goto out_mem;
371
372 ptr = skb_put(skb, count);
373 *ptr++ = cmd;
374
375 memcpy(ptr, sp->cooked_buf + 1, count);
376 skb->protocol = ax25_type_trans(skb, sp->dev);
377 netif_rx(skb);
378 sp->dev->stats.rx_packets++;
379
380 return;
381
382out_mem:
383 sp->dev->stats.rx_dropped++;
384}
385
386
387
388
389
390
391
392
393
394
395
396
397static DEFINE_RWLOCK(disc_data_lock);
398
399static struct sixpack *sp_get(struct tty_struct *tty)
400{
401 struct sixpack *sp;
402
403 read_lock(&disc_data_lock);
404 sp = tty->disc_data;
405 if (sp)
406 atomic_inc(&sp->refcnt);
407 read_unlock(&disc_data_lock);
408
409 return sp;
410}
411
412static void sp_put(struct sixpack *sp)
413{
414 if (atomic_dec_and_test(&sp->refcnt))
415 up(&sp->dead_sem);
416}
417
418
419
420
421
422static void sixpack_write_wakeup(struct tty_struct *tty)
423{
424 struct sixpack *sp = sp_get(tty);
425 int actual;
426
427 if (!sp)
428 return;
429 if (sp->xleft <= 0) {
430
431
432 sp->dev->stats.tx_packets++;
433 clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
434 sp->tx_enable = 0;
435 netif_wake_queue(sp->dev);
436 goto out;
437 }
438
439 if (sp->tx_enable) {
440 actual = tty->ops->write(tty, sp->xhead, sp->xleft);
441 sp->xleft -= actual;
442 sp->xhead += actual;
443 }
444
445out:
446 sp_put(sp);
447}
448
449
450
451
452
453
454
455
456
457static void sixpack_receive_buf(struct tty_struct *tty,
458 const unsigned char *cp, char *fp, int count)
459{
460 struct sixpack *sp;
461 unsigned char buf[512];
462 int count1;
463
464 if (!count)
465 return;
466
467 sp = sp_get(tty);
468 if (!sp)
469 return;
470
471 memcpy(buf, cp, count < sizeof(buf) ? count : sizeof(buf));
472
473
474
475 count1 = count;
476 while (count) {
477 count--;
478 if (fp && *fp++) {
479 if (!test_and_set_bit(SIXPF_ERROR, &sp->flags))
480 sp->dev->stats.rx_errors++;
481 continue;
482 }
483 }
484 sixpack_decode(sp, buf, count1);
485
486 sp_put(sp);
487 tty_unthrottle(tty);
488}
489
490
491
492
493
494
495#define TNC_UNINITIALIZED 0
496#define TNC_UNSYNC_STARTUP 1
497#define TNC_UNSYNCED 2
498#define TNC_IN_SYNC 3
499
500static void __tnc_set_sync_state(struct sixpack *sp, int new_tnc_state)
501{
502 char *msg;
503
504 switch (new_tnc_state) {
505 default:
506 case TNC_UNSYNC_STARTUP:
507 msg = "Synchronizing with TNC";
508 break;
509 case TNC_UNSYNCED:
510 msg = "Lost synchronization with TNC\n";
511 break;
512 case TNC_IN_SYNC:
513 msg = "Found TNC";
514 break;
515 }
516
517 sp->tnc_state = new_tnc_state;
518 printk(KERN_INFO "%s: %s\n", sp->dev->name, msg);
519}
520
521static inline void tnc_set_sync_state(struct sixpack *sp, int new_tnc_state)
522{
523 int old_tnc_state = sp->tnc_state;
524
525 if (old_tnc_state != new_tnc_state)
526 __tnc_set_sync_state(sp, new_tnc_state);
527}
528
529static void resync_tnc(unsigned long channel)
530{
531 struct sixpack *sp = (struct sixpack *) channel;
532 static char resync_cmd = 0xe8;
533
534
535
536 sp->rx_count = 0;
537 sp->rx_count_cooked = 0;
538
539
540
541 sp->status = 1;
542 sp->status1 = 1;
543 sp->status2 = 0;
544
545
546
547 sp->led_state = 0x60;
548 sp->tty->ops->write(sp->tty, &sp->led_state, 1);
549 sp->tty->ops->write(sp->tty, &resync_cmd, 1);
550
551
552
553
554 del_timer(&sp->resync_t);
555 sp->resync_t.data = (unsigned long) sp;
556 sp->resync_t.function = resync_tnc;
557 sp->resync_t.expires = jiffies + SIXP_RESYNC_TIMEOUT;
558 add_timer(&sp->resync_t);
559}
560
561static inline int tnc_init(struct sixpack *sp)
562{
563 unsigned char inbyte = 0xe8;
564
565 tnc_set_sync_state(sp, TNC_UNSYNC_STARTUP);
566
567 sp->tty->ops->write(sp->tty, &inbyte, 1);
568
569 del_timer(&sp->resync_t);
570 sp->resync_t.data = (unsigned long) sp;
571 sp->resync_t.function = resync_tnc;
572 sp->resync_t.expires = jiffies + SIXP_RESYNC_TIMEOUT;
573 add_timer(&sp->resync_t);
574
575 return 0;
576}
577
578
579
580
581
582
583
584
585static int sixpack_open(struct tty_struct *tty)
586{
587 char *rbuff = NULL, *xbuff = NULL;
588 struct net_device *dev;
589 struct sixpack *sp;
590 unsigned long len;
591 int err = 0;
592
593 if (!capable(CAP_NET_ADMIN))
594 return -EPERM;
595 if (tty->ops->write == NULL)
596 return -EOPNOTSUPP;
597
598 dev = alloc_netdev(sizeof(struct sixpack), "sp%d", sp_setup);
599 if (!dev) {
600 err = -ENOMEM;
601 goto out;
602 }
603
604 sp = netdev_priv(dev);
605 sp->dev = dev;
606
607 spin_lock_init(&sp->lock);
608 atomic_set(&sp->refcnt, 1);
609 init_MUTEX_LOCKED(&sp->dead_sem);
610
611
612
613 len = dev->mtu * 2;
614
615 rbuff = kmalloc(len + 4, GFP_KERNEL);
616 xbuff = kmalloc(len + 4, GFP_KERNEL);
617
618 if (rbuff == NULL || xbuff == NULL) {
619 err = -ENOBUFS;
620 goto out_free;
621 }
622
623 spin_lock_bh(&sp->lock);
624
625 sp->tty = tty;
626
627 sp->rbuff = rbuff;
628 sp->xbuff = xbuff;
629
630 sp->mtu = AX25_MTU + 73;
631 sp->buffsize = len;
632 sp->rcount = 0;
633 sp->rx_count = 0;
634 sp->rx_count_cooked = 0;
635 sp->xleft = 0;
636
637 sp->flags = 0;
638
639 sp->duplex = 0;
640 sp->tx_delay = SIXP_TXDELAY;
641 sp->persistence = SIXP_PERSIST;
642 sp->slottime = SIXP_SLOTTIME;
643 sp->led_state = 0x60;
644 sp->status = 1;
645 sp->status1 = 1;
646 sp->status2 = 0;
647 sp->tx_enable = 0;
648
649 netif_start_queue(dev);
650
651 init_timer(&sp->tx_t);
652 sp->tx_t.function = sp_xmit_on_air;
653 sp->tx_t.data = (unsigned long) sp;
654
655 init_timer(&sp->resync_t);
656
657 spin_unlock_bh(&sp->lock);
658
659
660 tty->disc_data = sp;
661 tty->receive_room = 65536;
662
663
664 if (register_netdev(dev))
665 goto out_free;
666
667 tnc_init(sp);
668
669 return 0;
670
671out_free:
672 kfree(xbuff);
673 kfree(rbuff);
674
675 if (dev)
676 free_netdev(dev);
677
678out:
679 return err;
680}
681
682
683
684
685
686
687
688
689static void sixpack_close(struct tty_struct *tty)
690{
691 struct sixpack *sp;
692
693 write_lock(&disc_data_lock);
694 sp = tty->disc_data;
695 tty->disc_data = NULL;
696 write_unlock(&disc_data_lock);
697 if (!sp)
698 return;
699
700
701
702
703
704 if (!atomic_dec_and_test(&sp->refcnt))
705 down(&sp->dead_sem);
706
707 unregister_netdev(sp->dev);
708
709 del_timer(&sp->tx_t);
710 del_timer(&sp->resync_t);
711
712
713 kfree(sp->rbuff);
714 kfree(sp->xbuff);
715}
716
717
718static int sixpack_ioctl(struct tty_struct *tty, struct file *file,
719 unsigned int cmd, unsigned long arg)
720{
721 struct sixpack *sp = sp_get(tty);
722 struct net_device *dev;
723 unsigned int tmp, err;
724
725 if (!sp)
726 return -ENXIO;
727 dev = sp->dev;
728
729 switch(cmd) {
730 case SIOCGIFNAME:
731 err = copy_to_user((void __user *) arg, dev->name,
732 strlen(dev->name) + 1) ? -EFAULT : 0;
733 break;
734
735 case SIOCGIFENCAP:
736 err = put_user(0, (int __user *) arg);
737 break;
738
739 case SIOCSIFENCAP:
740 if (get_user(tmp, (int __user *) arg)) {
741 err = -EFAULT;
742 break;
743 }
744
745 sp->mode = tmp;
746 dev->addr_len = AX25_ADDR_LEN;
747 dev->hard_header_len = AX25_KISS_HEADER_LEN +
748 AX25_MAX_HEADER_LEN + 3;
749 dev->type = ARPHRD_AX25;
750
751 err = 0;
752 break;
753
754 case SIOCSIFHWADDR: {
755 char addr[AX25_ADDR_LEN];
756
757 if (copy_from_user(&addr,
758 (void __user *) arg, AX25_ADDR_LEN)) {
759 err = -EFAULT;
760 break;
761 }
762
763 netif_tx_lock_bh(dev);
764 memcpy(dev->dev_addr, &addr, AX25_ADDR_LEN);
765 netif_tx_unlock_bh(dev);
766
767 err = 0;
768 break;
769 }
770
771 default:
772 err = tty_mode_ioctl(tty, file, cmd, arg);
773 }
774
775 sp_put(sp);
776
777 return err;
778}
779
780static struct tty_ldisc_ops sp_ldisc = {
781 .owner = THIS_MODULE,
782 .magic = TTY_LDISC_MAGIC,
783 .name = "6pack",
784 .open = sixpack_open,
785 .close = sixpack_close,
786 .ioctl = sixpack_ioctl,
787 .receive_buf = sixpack_receive_buf,
788 .write_wakeup = sixpack_write_wakeup,
789};
790
791
792
793static const char msg_banner[] __initdata = KERN_INFO \
794 "AX.25: 6pack driver, " SIXPACK_VERSION "\n";
795static const char msg_regfail[] __initdata = KERN_ERR \
796 "6pack: can't register line discipline (err = %d)\n";
797
798static int __init sixpack_init_driver(void)
799{
800 int status;
801
802 printk(msg_banner);
803
804
805 if ((status = tty_register_ldisc(N_6PACK, &sp_ldisc)) != 0)
806 printk(msg_regfail, status);
807
808 return status;
809}
810
811static const char msg_unregfail[] __exitdata = KERN_ERR \
812 "6pack: can't unregister line discipline (err = %d)\n";
813
814static void __exit sixpack_exit_driver(void)
815{
816 int ret;
817
818 if ((ret = tty_unregister_ldisc(N_6PACK)))
819 printk(msg_unregfail, ret);
820}
821
822
823
824static int encode_sixpack(unsigned char *tx_buf, unsigned char *tx_buf_raw,
825 int length, unsigned char tx_delay)
826{
827 int count = 0;
828 unsigned char checksum = 0, buf[400];
829 int raw_count = 0;
830
831 tx_buf_raw[raw_count++] = SIXP_PRIO_CMD_MASK | SIXP_TX_MASK;
832 tx_buf_raw[raw_count++] = SIXP_SEOF;
833
834 buf[0] = tx_delay;
835 for (count = 1; count < length; count++)
836 buf[count] = tx_buf[count];
837
838 for (count = 0; count < length; count++)
839 checksum += buf[count];
840 buf[length] = (unsigned char) 0xff - checksum;
841
842 for (count = 0; count <= length; count++) {
843 if ((count % 3) == 0) {
844 tx_buf_raw[raw_count++] = (buf[count] & 0x3f);
845 tx_buf_raw[raw_count] = ((buf[count] >> 2) & 0x30);
846 } else if ((count % 3) == 1) {
847 tx_buf_raw[raw_count++] |= (buf[count] & 0x0f);
848 tx_buf_raw[raw_count] = ((buf[count] >> 2) & 0x3c);
849 } else {
850 tx_buf_raw[raw_count++] |= (buf[count] & 0x03);
851 tx_buf_raw[raw_count++] = (buf[count] >> 2);
852 }
853 }
854 if ((length % 3) != 2)
855 raw_count++;
856 tx_buf_raw[raw_count++] = SIXP_SEOF;
857 return raw_count;
858}
859
860
861
862static void decode_data(struct sixpack *sp, unsigned char inbyte)
863{
864 unsigned char *buf;
865
866 if (sp->rx_count != 3) {
867 sp->raw_buf[sp->rx_count++] = inbyte;
868
869 return;
870 }
871
872 buf = sp->raw_buf;
873 sp->cooked_buf[sp->rx_count_cooked++] =
874 buf[0] | ((buf[1] << 2) & 0xc0);
875 sp->cooked_buf[sp->rx_count_cooked++] =
876 (buf[1] & 0x0f) | ((buf[2] << 2) & 0xf0);
877 sp->cooked_buf[sp->rx_count_cooked++] =
878 (buf[2] & 0x03) | (inbyte << 2);
879 sp->rx_count = 0;
880}
881
882
883
884static void decode_prio_command(struct sixpack *sp, unsigned char cmd)
885{
886 unsigned char channel;
887 int actual;
888
889 channel = cmd & SIXP_CHN_MASK;
890 if ((cmd & SIXP_PRIO_DATA_MASK) != 0) {
891
892
893
894
895
896
897
898
899 if (((sp->status & SIXP_DCD_MASK) == 0) &&
900 ((cmd & SIXP_RX_DCD_MASK) == SIXP_RX_DCD_MASK)) {
901 if (sp->status != 1)
902 printk(KERN_DEBUG "6pack: protocol violation\n");
903 else
904 sp->status = 0;
905 cmd &= ~SIXP_RX_DCD_MASK;
906 }
907 sp->status = cmd & SIXP_PRIO_DATA_MASK;
908 } else {
909 if ((sp->status2 != 0) && (sp->duplex == 1)) {
910 sp->led_state = 0x70;
911 sp->tty->ops->write(sp->tty, &sp->led_state, 1);
912 sp->tx_enable = 1;
913 actual = sp->tty->ops->write(sp->tty, sp->xbuff, sp->status2);
914 sp->xleft -= actual;
915 sp->xhead += actual;
916 sp->led_state = 0x60;
917 sp->status2 = 0;
918
919 }
920 }
921
922
923 sp->tty->ops->write(sp->tty, &sp->led_state, 1);
924
925
926
927
928 if (sp->tnc_state == TNC_IN_SYNC) {
929 del_timer(&sp->resync_t);
930 sp->resync_t.data = (unsigned long) sp;
931 sp->resync_t.function = resync_tnc;
932 sp->resync_t.expires = jiffies + SIXP_INIT_RESYNC_TIMEOUT;
933 add_timer(&sp->resync_t);
934 }
935
936 sp->status1 = cmd & SIXP_PRIO_DATA_MASK;
937}
938
939
940
941static void decode_std_command(struct sixpack *sp, unsigned char cmd)
942{
943 unsigned char checksum = 0, rest = 0, channel;
944 short i;
945
946 channel = cmd & SIXP_CHN_MASK;
947 switch (cmd & SIXP_CMD_MASK) {
948 case SIXP_SEOF:
949 if ((sp->rx_count == 0) && (sp->rx_count_cooked == 0)) {
950 if ((sp->status & SIXP_RX_DCD_MASK) ==
951 SIXP_RX_DCD_MASK) {
952 sp->led_state = 0x68;
953 sp->tty->ops->write(sp->tty, &sp->led_state, 1);
954 }
955 } else {
956 sp->led_state = 0x60;
957
958 sp->tty->ops->write(sp->tty, &sp->led_state, 1);
959 rest = sp->rx_count;
960 if (rest != 0)
961 for (i = rest; i <= 3; i++)
962 decode_data(sp, 0);
963 if (rest == 2)
964 sp->rx_count_cooked -= 2;
965 else if (rest == 3)
966 sp->rx_count_cooked -= 1;
967 for (i = 0; i < sp->rx_count_cooked; i++)
968 checksum += sp->cooked_buf[i];
969 if (checksum != SIXP_CHKSUM) {
970 printk(KERN_DEBUG "6pack: bad checksum %2.2x\n", checksum);
971 } else {
972 sp->rcount = sp->rx_count_cooked-2;
973 sp_bump(sp, 0);
974 }
975 sp->rx_count_cooked = 0;
976 }
977 break;
978 case SIXP_TX_URUN: printk(KERN_DEBUG "6pack: TX underrun\n");
979 break;
980 case SIXP_RX_ORUN: printk(KERN_DEBUG "6pack: RX overrun\n");
981 break;
982 case SIXP_RX_BUF_OVL:
983 printk(KERN_DEBUG "6pack: RX buffer overflow\n");
984 }
985}
986
987
988
989static void
990sixpack_decode(struct sixpack *sp, unsigned char *pre_rbuff, int count)
991{
992 unsigned char inbyte;
993 int count1;
994
995 for (count1 = 0; count1 < count; count1++) {
996 inbyte = pre_rbuff[count1];
997 if (inbyte == SIXP_FOUND_TNC) {
998 tnc_set_sync_state(sp, TNC_IN_SYNC);
999 del_timer(&sp->resync_t);
1000 }
1001 if ((inbyte & SIXP_PRIO_CMD_MASK) != 0)
1002 decode_prio_command(sp, inbyte);
1003 else if ((inbyte & SIXP_STD_CMD_MASK) != 0)
1004 decode_std_command(sp, inbyte);
1005 else if ((sp->status & SIXP_RX_DCD_MASK) == SIXP_RX_DCD_MASK)
1006 decode_data(sp, inbyte);
1007 }
1008}
1009
1010MODULE_AUTHOR("Ralf Baechle DO1GRB <ralf@linux-mips.org>");
1011MODULE_DESCRIPTION("6pack driver for AX.25");
1012MODULE_LICENSE("GPL");
1013MODULE_ALIAS_LDISC(N_6PACK);
1014
1015module_init(sixpack_init_driver);
1016module_exit(sixpack_exit_driver);
1017