1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * 6pack.c This module implements the 6pack protocol for kernel-based
4 * devices like TTY. It interfaces between a raw TTY and the
5 * kernel's AX.25 protocol layers.
6 *
7 * Authors: Andreas Könsgen <ajk@comnets.uni-bremen.de>
8 * Ralf Baechle DL5RB <ralf@linux-mips.org>
9 *
10 * Quite a lot of stuff "stolen" by Joerg Reuter from slip.c, written by
11 *
12 * Laurence Culhane, <loz@holmes.demon.co.uk>
13 * Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
14 */
15
16 #include <linux/module.h>
17 #include <linux/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 <linux/slab.h>
28 #include <net/ax25.h>
29 #include <linux/etherdevice.h>
30 #include <linux/skbuff.h>
31 #include <linux/rtnetlink.h>
32 #include <linux/spinlock.h>
33 #include <linux/if_arp.h>
34 #include <linux/init.h>
35 #include <linux/ip.h>
36 #include <linux/tcp.h>
37 #include <linux/semaphore.h>
38 #include <linux/refcount.h>
39
40 /* sixpack priority commands */
41 #define SIXP_SEOF 0x40 /* start and end of a 6pack frame */
42 #define SIXP_TX_URUN 0x48 /* transmit overrun */
43 #define SIXP_RX_ORUN 0x50 /* receive overrun */
44 #define SIXP_RX_BUF_OVL 0x58 /* receive buffer overflow */
45
46 #define SIXP_CHKSUM 0xFF /* valid checksum of a 6pack frame */
47
48 /* masks to get certain bits out of the status bytes sent by the TNC */
49
50 #define SIXP_CMD_MASK 0xC0
51 #define SIXP_CHN_MASK 0x07
52 #define SIXP_PRIO_CMD_MASK 0x80
53 #define SIXP_STD_CMD_MASK 0x40
54 #define SIXP_PRIO_DATA_MASK 0x38
55 #define SIXP_TX_MASK 0x20
56 #define SIXP_RX_MASK 0x10
57 #define SIXP_RX_DCD_MASK 0x18
58 #define SIXP_LEDS_ON 0x78
59 #define SIXP_LEDS_OFF 0x60
60 #define SIXP_CON 0x08
61 #define SIXP_STA 0x10
62
63 #define SIXP_FOUND_TNC 0xe9
64 #define SIXP_CON_ON 0x68
65 #define SIXP_DCD_MASK 0x08
66 #define SIXP_DAMA_OFF 0
67
68 /* default level 2 parameters */
69 #define SIXP_TXDELAY 25 /* 250 ms */
70 #define SIXP_PERSIST 50 /* in 256ths */
71 #define SIXP_SLOTTIME 10 /* 100 ms */
72 #define SIXP_INIT_RESYNC_TIMEOUT (3*HZ/2) /* in 1 s */
73 #define SIXP_RESYNC_TIMEOUT 5*HZ /* in 1 s */
74
75 /* 6pack configuration. */
76 #define SIXP_NRUNIT 31 /* MAX number of 6pack channels */
77 #define SIXP_MTU 256 /* Default MTU */
78
79 enum sixpack_flags {
80 SIXPF_ERROR, /* Parity, etc. error */
81 };
82
83 struct sixpack {
84 /* Various fields. */
85 struct tty_struct *tty; /* ptr to TTY structure */
86 struct net_device *dev; /* easy for intr handling */
87
88 /* These are pointers to the malloc()ed frame buffers. */
89 int rcount; /* received chars counter */
90 unsigned char *xbuff; /* transmitter buffer */
91 unsigned char *xhead; /* next byte to XMIT */
92 int xleft; /* bytes left in XMIT queue */
93
94 u8 raw_buf[4];
95 u8 cooked_buf[400];
96
97 unsigned int rx_count;
98 unsigned int rx_count_cooked;
99 spinlock_t rxlock;
100
101 unsigned long flags; /* Flag values/ mode etc */
102 unsigned char mode; /* 6pack mode */
103
104 /* 6pack stuff */
105 unsigned char tx_delay;
106 unsigned char persistence;
107 unsigned char slottime;
108 unsigned char duplex;
109 unsigned char led_state;
110 u8 status;
111 u8 status1;
112 unsigned char status2;
113 unsigned char tx_enable;
114 unsigned char tnc_state;
115
116 struct timer_list tx_t;
117 struct timer_list resync_t;
118 spinlock_t lock;
119 };
120
121 #define AX25_6PACK_HEADER_LEN 0
122
123 static void sixpack_decode(struct sixpack *, const u8 *, size_t);
124 static int encode_sixpack(unsigned char *, unsigned char *, int, unsigned char);
125
126 /*
127 * Perform the persistence/slottime algorithm for CSMA access. If the
128 * persistence check was successful, write the data to the serial driver.
129 * Note that in case of DAMA operation, the data is not sent here.
130 */
131
sp_xmit_on_air(struct timer_list * t)132 static void sp_xmit_on_air(struct timer_list *t)
133 {
134 struct sixpack *sp = timer_container_of(sp, t, tx_t);
135 int actual, when = sp->slottime;
136 static unsigned char random;
137
138 random = random * 17 + 41;
139
140 if (((sp->status1 & SIXP_DCD_MASK) == 0) && (random < sp->persistence)) {
141 sp->led_state = 0x70;
142 sp->tty->ops->write(sp->tty, &sp->led_state, 1);
143 sp->tx_enable = 1;
144 actual = sp->tty->ops->write(sp->tty, sp->xbuff, sp->status2);
145 sp->xleft -= actual;
146 sp->xhead += actual;
147 sp->led_state = 0x60;
148 sp->tty->ops->write(sp->tty, &sp->led_state, 1);
149 sp->status2 = 0;
150 } else
151 mod_timer(&sp->tx_t, jiffies + ((when + 1) * HZ) / 100);
152 }
153
154 /* ----> 6pack timer interrupt handler and friends. <---- */
155
156 /* Encapsulate one AX.25 frame and stuff into a TTY queue. */
sp_encaps(struct sixpack * sp,unsigned char * icp,int len)157 static void sp_encaps(struct sixpack *sp, unsigned char *icp, int len)
158 {
159 unsigned char *msg, *p = icp;
160 int actual, count;
161
162 if (len > AX25_MTU + 73) {
163 msg = "oversized transmit packet!";
164 goto out_drop;
165 }
166
167 if (p[0] > 5) {
168 msg = "invalid KISS command";
169 goto out_drop;
170 }
171
172 if ((p[0] != 0) && (len > 2)) {
173 msg = "KISS control packet too long";
174 goto out_drop;
175 }
176
177 if ((p[0] == 0) && (len < 15)) {
178 msg = "bad AX.25 packet to transmit";
179 goto out_drop;
180 }
181
182 count = encode_sixpack(p, sp->xbuff, len, sp->tx_delay);
183 set_bit(TTY_DO_WRITE_WAKEUP, &sp->tty->flags);
184
185 switch (p[0]) {
186 case 1: sp->tx_delay = p[1];
187 return;
188 case 2: sp->persistence = p[1];
189 return;
190 case 3: sp->slottime = p[1];
191 return;
192 case 4: /* ignored */
193 return;
194 case 5: sp->duplex = p[1];
195 return;
196 }
197
198 if (p[0] != 0)
199 return;
200
201 /*
202 * In case of fullduplex or DAMA operation, we don't take care about the
203 * state of the DCD or of any timers, as the determination of the
204 * correct time to send is the job of the AX.25 layer. We send
205 * immediately after data has arrived.
206 */
207 if (sp->duplex == 1) {
208 sp->led_state = 0x70;
209 sp->tty->ops->write(sp->tty, &sp->led_state, 1);
210 sp->tx_enable = 1;
211 actual = sp->tty->ops->write(sp->tty, sp->xbuff, count);
212 sp->xleft = count - actual;
213 sp->xhead = sp->xbuff + actual;
214 sp->led_state = 0x60;
215 sp->tty->ops->write(sp->tty, &sp->led_state, 1);
216 } else {
217 sp->xleft = count;
218 sp->xhead = sp->xbuff;
219 sp->status2 = count;
220 sp_xmit_on_air(&sp->tx_t);
221 }
222
223 return;
224
225 out_drop:
226 sp->dev->stats.tx_dropped++;
227 netif_start_queue(sp->dev);
228 if (net_ratelimit())
229 printk(KERN_DEBUG "%s: %s - dropped.\n", sp->dev->name, msg);
230 }
231
232 /* Encapsulate an IP datagram and kick it into a TTY queue. */
233
sp_xmit(struct sk_buff * skb,struct net_device * dev)234 static netdev_tx_t sp_xmit(struct sk_buff *skb, struct net_device *dev)
235 {
236 struct sixpack *sp = netdev_priv(dev);
237
238 if (skb->protocol == htons(ETH_P_IP))
239 return ax25_ip_xmit(skb);
240
241 spin_lock_bh(&sp->lock);
242 /* We were not busy, so we are now... :-) */
243 netif_stop_queue(dev);
244 dev->stats.tx_bytes += skb->len;
245 sp_encaps(sp, skb->data, skb->len);
246 spin_unlock_bh(&sp->lock);
247
248 dev_kfree_skb(skb);
249
250 return NETDEV_TX_OK;
251 }
252
sp_open_dev(struct net_device * dev)253 static int sp_open_dev(struct net_device *dev)
254 {
255 struct sixpack *sp = netdev_priv(dev);
256
257 if (sp->tty == NULL)
258 return -ENODEV;
259 return 0;
260 }
261
262 /* Close the low-level part of the 6pack channel. */
sp_close(struct net_device * dev)263 static int sp_close(struct net_device *dev)
264 {
265 struct sixpack *sp = netdev_priv(dev);
266
267 spin_lock_bh(&sp->lock);
268 if (sp->tty) {
269 /* TTY discipline is running. */
270 clear_bit(TTY_DO_WRITE_WAKEUP, &sp->tty->flags);
271 }
272 netif_stop_queue(dev);
273 spin_unlock_bh(&sp->lock);
274
275 return 0;
276 }
277
sp_set_mac_address(struct net_device * dev,void * addr)278 static int sp_set_mac_address(struct net_device *dev, void *addr)
279 {
280 struct sockaddr_ax25 *sa = addr;
281
282 netif_tx_lock_bh(dev);
283 netif_addr_lock(dev);
284 __dev_addr_set(dev, &sa->sax25_call, AX25_ADDR_LEN);
285 netif_addr_unlock(dev);
286 netif_tx_unlock_bh(dev);
287
288 return 0;
289 }
290
291 static const struct net_device_ops sp_netdev_ops = {
292 .ndo_open = sp_open_dev,
293 .ndo_stop = sp_close,
294 .ndo_start_xmit = sp_xmit,
295 .ndo_set_mac_address = sp_set_mac_address,
296 };
297
sp_setup(struct net_device * dev)298 static void sp_setup(struct net_device *dev)
299 {
300 /* Finish setting up the DEVICE info. */
301 dev->netdev_ops = &sp_netdev_ops;
302 dev->mtu = SIXP_MTU;
303 dev->hard_header_len = AX25_MAX_HEADER_LEN;
304 dev->header_ops = &ax25_header_ops;
305
306 dev->addr_len = AX25_ADDR_LEN;
307 dev->type = ARPHRD_AX25;
308 dev->tx_queue_len = 10;
309
310 /* Only activated in AX.25 mode */
311 memcpy(dev->broadcast, &ax25_bcast, AX25_ADDR_LEN);
312 dev_addr_set(dev, (u8 *)&ax25_defaddr);
313
314 dev->flags = 0;
315 }
316
317 /* Send one completely decapsulated IP datagram to the IP layer. */
318
319 /*
320 * This is the routine that sends the received data to the kernel AX.25.
321 * 'cmd' is the KISS command. For AX.25 data, it is zero.
322 */
323
sp_bump(struct sixpack * sp,char cmd)324 static void sp_bump(struct sixpack *sp, char cmd)
325 {
326 struct sk_buff *skb;
327 int count;
328 u8 *ptr;
329
330 count = sp->rcount + 1;
331
332 sp->dev->stats.rx_bytes += count;
333
334 if ((skb = dev_alloc_skb(count + 1)) == NULL)
335 goto out_mem;
336
337 ptr = skb_put(skb, count + 1);
338 *ptr++ = cmd; /* KISS command */
339
340 memcpy(ptr, sp->cooked_buf + 1, count);
341 skb->protocol = ax25_type_trans(skb, sp->dev);
342 netif_rx(skb);
343 sp->dev->stats.rx_packets++;
344
345 return;
346
347 out_mem:
348 sp->dev->stats.rx_dropped++;
349 }
350
351
352 /* ----------------------------------------------------------------------- */
353
354 /*
355 * Called by the TTY driver when there's room for more data. If we have
356 * more packets to send, we send them here.
357 */
sixpack_write_wakeup(struct tty_struct * tty)358 static void sixpack_write_wakeup(struct tty_struct *tty)
359 {
360 struct sixpack *sp = tty->disc_data;
361 int actual;
362
363 if (!sp)
364 return;
365 if (sp->xleft <= 0) {
366 /* Now serial buffer is almost free & we can start
367 * transmission of another packet */
368 sp->dev->stats.tx_packets++;
369 clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
370 sp->tx_enable = 0;
371 netif_wake_queue(sp->dev);
372 return;
373 }
374
375 if (sp->tx_enable) {
376 actual = tty->ops->write(tty, sp->xhead, sp->xleft);
377 sp->xleft -= actual;
378 sp->xhead += actual;
379 }
380 }
381
382 /* ----------------------------------------------------------------------- */
383
384 /*
385 * Handle the 'receiver data ready' interrupt.
386 * This function is called by the tty module in the kernel when
387 * a block of 6pack data has been received, which can now be decapsulated
388 * and sent on to some IP layer for further processing.
389 */
sixpack_receive_buf(struct tty_struct * tty,const u8 * cp,const u8 * fp,size_t count)390 static void sixpack_receive_buf(struct tty_struct *tty, const u8 *cp,
391 const u8 *fp, size_t count)
392 {
393 struct sixpack *sp;
394 size_t count1;
395
396 if (!count)
397 return;
398
399 sp = tty->disc_data;
400 if (!sp)
401 return;
402
403 /* Read the characters out of the buffer */
404 count1 = count;
405 while (count) {
406 count--;
407 if (fp && *fp++) {
408 if (!test_and_set_bit(SIXPF_ERROR, &sp->flags))
409 sp->dev->stats.rx_errors++;
410 continue;
411 }
412 }
413 sixpack_decode(sp, cp, count1);
414
415 tty_unthrottle(tty);
416 }
417
418 /*
419 * Try to resync the TNC. Called by the resync timer defined in
420 * decode_prio_command
421 */
422
423 #define TNC_UNINITIALIZED 0
424 #define TNC_UNSYNC_STARTUP 1
425 #define TNC_UNSYNCED 2
426 #define TNC_IN_SYNC 3
427
__tnc_set_sync_state(struct sixpack * sp,int new_tnc_state)428 static void __tnc_set_sync_state(struct sixpack *sp, int new_tnc_state)
429 {
430 char *msg;
431
432 switch (new_tnc_state) {
433 default: /* gcc oh piece-o-crap ... */
434 case TNC_UNSYNC_STARTUP:
435 msg = "Synchronizing with TNC";
436 break;
437 case TNC_UNSYNCED:
438 msg = "Lost synchronization with TNC\n";
439 break;
440 case TNC_IN_SYNC:
441 msg = "Found TNC";
442 break;
443 }
444
445 sp->tnc_state = new_tnc_state;
446 printk(KERN_INFO "%s: %s\n", sp->dev->name, msg);
447 }
448
tnc_set_sync_state(struct sixpack * sp,int new_tnc_state)449 static inline void tnc_set_sync_state(struct sixpack *sp, int new_tnc_state)
450 {
451 int old_tnc_state = sp->tnc_state;
452
453 if (old_tnc_state != new_tnc_state)
454 __tnc_set_sync_state(sp, new_tnc_state);
455 }
456
resync_tnc(struct timer_list * t)457 static void resync_tnc(struct timer_list *t)
458 {
459 struct sixpack *sp = timer_container_of(sp, t, resync_t);
460 static char resync_cmd = 0xe8;
461
462 /* clear any data that might have been received */
463
464 sp->rx_count = 0;
465 sp->rx_count_cooked = 0;
466
467 /* reset state machine */
468
469 sp->status = 1;
470 sp->status1 = 1;
471 sp->status2 = 0;
472
473 /* resync the TNC */
474
475 sp->led_state = 0x60;
476 sp->tty->ops->write(sp->tty, &sp->led_state, 1);
477 sp->tty->ops->write(sp->tty, &resync_cmd, 1);
478
479
480 /* Start resync timer again -- the TNC might be still absent */
481 mod_timer(&sp->resync_t, jiffies + SIXP_RESYNC_TIMEOUT);
482 }
483
tnc_init(struct sixpack * sp)484 static inline int tnc_init(struct sixpack *sp)
485 {
486 unsigned char inbyte = 0xe8;
487
488 tnc_set_sync_state(sp, TNC_UNSYNC_STARTUP);
489
490 sp->tty->ops->write(sp->tty, &inbyte, 1);
491
492 mod_timer(&sp->resync_t, jiffies + SIXP_RESYNC_TIMEOUT);
493
494 return 0;
495 }
496
497 /*
498 * Open the high-level part of the 6pack channel.
499 * This function is called by the TTY module when the
500 * 6pack line discipline is called for. Because we are
501 * sure the tty line exists, we only have to link it to
502 * a free 6pcack channel...
503 */
sixpack_open(struct tty_struct * tty)504 static int sixpack_open(struct tty_struct *tty)
505 {
506 char *xbuff = NULL;
507 struct net_device *dev;
508 struct sixpack *sp;
509 unsigned long len;
510 int err = 0;
511
512 if (!capable(CAP_NET_ADMIN))
513 return -EPERM;
514 if (tty->ops->write == NULL)
515 return -EOPNOTSUPP;
516
517 dev = alloc_netdev(sizeof(struct sixpack), "sp%d", NET_NAME_UNKNOWN,
518 sp_setup);
519 if (!dev) {
520 err = -ENOMEM;
521 goto out;
522 }
523
524 sp = netdev_priv(dev);
525 sp->dev = dev;
526
527 spin_lock_init(&sp->lock);
528 spin_lock_init(&sp->rxlock);
529
530 /* !!! length of the buffers. MTU is IP MTU, not PACLEN! */
531
532 len = dev->mtu * 2;
533
534 xbuff = kmalloc(len + 4, GFP_KERNEL);
535 if (xbuff == NULL) {
536 err = -ENOBUFS;
537 goto out_free;
538 }
539
540 spin_lock_bh(&sp->lock);
541
542 sp->tty = tty;
543
544 sp->xbuff = xbuff;
545
546 sp->rcount = 0;
547 sp->rx_count = 0;
548 sp->rx_count_cooked = 0;
549 sp->xleft = 0;
550
551 sp->flags = 0; /* Clear ESCAPE & ERROR flags */
552
553 sp->duplex = 0;
554 sp->tx_delay = SIXP_TXDELAY;
555 sp->persistence = SIXP_PERSIST;
556 sp->slottime = SIXP_SLOTTIME;
557 sp->led_state = 0x60;
558 sp->status = 1;
559 sp->status1 = 1;
560 sp->status2 = 0;
561 sp->tx_enable = 0;
562
563 netif_start_queue(dev);
564
565 timer_setup(&sp->tx_t, sp_xmit_on_air, 0);
566
567 timer_setup(&sp->resync_t, resync_tnc, 0);
568
569 spin_unlock_bh(&sp->lock);
570
571 /* Done. We have linked the TTY line to a channel. */
572 tty->disc_data = sp;
573 tty->receive_room = 65536;
574
575 /* Now we're ready to register. */
576 err = register_netdev(dev);
577 if (err)
578 goto out_free;
579
580 tnc_init(sp);
581
582 return 0;
583
584 out_free:
585 kfree(xbuff);
586
587 free_netdev(dev);
588
589 out:
590 return err;
591 }
592
593
594 /*
595 * Close down a 6pack channel.
596 * This means flushing out any pending queues, and then restoring the
597 * TTY line discipline to what it was before it got hooked to 6pack
598 * (which usually is TTY again).
599 */
sixpack_close(struct tty_struct * tty)600 static void sixpack_close(struct tty_struct *tty)
601 {
602 struct sixpack *sp;
603
604 sp = tty->disc_data;
605 if (!sp)
606 return;
607
608 tty->disc_data = NULL;
609
610 /* We must stop the queue to avoid potentially scribbling
611 * on the free buffers. The sp->dead completion is not sufficient
612 * to protect us from sp->xbuff access.
613 */
614 netif_stop_queue(sp->dev);
615
616 unregister_netdev(sp->dev);
617
618 timer_delete_sync(&sp->tx_t);
619 timer_delete_sync(&sp->resync_t);
620
621 /* Free all 6pack frame buffers after unreg. */
622 kfree(sp->xbuff);
623
624 free_netdev(sp->dev);
625 }
626
627 /* Perform I/O control on an active 6pack channel. */
sixpack_ioctl(struct tty_struct * tty,unsigned int cmd,unsigned long arg)628 static int sixpack_ioctl(struct tty_struct *tty, unsigned int cmd,
629 unsigned long arg)
630 {
631 struct sixpack *sp = tty->disc_data;
632 struct net_device *dev;
633 unsigned int tmp, err;
634
635 if (!sp)
636 return -ENXIO;
637 dev = sp->dev;
638
639 switch(cmd) {
640 case SIOCGIFNAME:
641 err = copy_to_user((void __user *) arg, dev->name,
642 strlen(dev->name) + 1) ? -EFAULT : 0;
643 break;
644
645 case SIOCGIFENCAP:
646 err = put_user(0, (int __user *) arg);
647 break;
648
649 case SIOCSIFENCAP:
650 if (get_user(tmp, (int __user *) arg)) {
651 err = -EFAULT;
652 break;
653 }
654
655 sp->mode = tmp;
656 dev->addr_len = AX25_ADDR_LEN;
657 dev->hard_header_len = AX25_KISS_HEADER_LEN +
658 AX25_MAX_HEADER_LEN + 3;
659 dev->type = ARPHRD_AX25;
660
661 err = 0;
662 break;
663
664 case SIOCSIFHWADDR: {
665 char addr[AX25_ADDR_LEN];
666
667 if (copy_from_user(&addr,
668 (void __user *)arg, AX25_ADDR_LEN)) {
669 err = -EFAULT;
670 break;
671 }
672
673 netif_tx_lock_bh(dev);
674 __dev_addr_set(dev, &addr, AX25_ADDR_LEN);
675 netif_tx_unlock_bh(dev);
676 err = 0;
677 break;
678 }
679 default:
680 err = tty_mode_ioctl(tty, cmd, arg);
681 }
682
683 return err;
684 }
685
686 static struct tty_ldisc_ops sp_ldisc = {
687 .owner = THIS_MODULE,
688 .num = N_6PACK,
689 .name = "6pack",
690 .open = sixpack_open,
691 .close = sixpack_close,
692 .ioctl = sixpack_ioctl,
693 .receive_buf = sixpack_receive_buf,
694 .write_wakeup = sixpack_write_wakeup,
695 };
696
697 /* Initialize 6pack control device -- register 6pack line discipline */
698
sixpack_init_driver(void)699 static int __init sixpack_init_driver(void)
700 {
701 int status;
702
703 /* Register the provided line protocol discipline */
704 status = tty_register_ldisc(&sp_ldisc);
705 if (status)
706 pr_err("6pack: can't register line discipline (err = %d)\n", status);
707
708 return status;
709 }
710
sixpack_exit_driver(void)711 static void __exit sixpack_exit_driver(void)
712 {
713 tty_unregister_ldisc(&sp_ldisc);
714 }
715
716 /* encode an AX.25 packet into 6pack */
717
encode_sixpack(unsigned char * tx_buf,unsigned char * tx_buf_raw,int length,unsigned char tx_delay)718 static int encode_sixpack(unsigned char *tx_buf, unsigned char *tx_buf_raw,
719 int length, unsigned char tx_delay)
720 {
721 int count = 0;
722 unsigned char checksum = 0, buf[400];
723 int raw_count = 0;
724
725 tx_buf_raw[raw_count++] = SIXP_PRIO_CMD_MASK | SIXP_TX_MASK;
726 tx_buf_raw[raw_count++] = SIXP_SEOF;
727
728 buf[0] = tx_delay;
729 for (count = 1; count < length; count++)
730 buf[count] = tx_buf[count];
731
732 for (count = 0; count < length; count++)
733 checksum += buf[count];
734 buf[length] = (unsigned char) 0xff - checksum;
735
736 for (count = 0; count <= length; count++) {
737 if ((count % 3) == 0) {
738 tx_buf_raw[raw_count++] = (buf[count] & 0x3f);
739 tx_buf_raw[raw_count] = ((buf[count] >> 2) & 0x30);
740 } else if ((count % 3) == 1) {
741 tx_buf_raw[raw_count++] |= (buf[count] & 0x0f);
742 tx_buf_raw[raw_count] = ((buf[count] >> 2) & 0x3c);
743 } else {
744 tx_buf_raw[raw_count++] |= (buf[count] & 0x03);
745 tx_buf_raw[raw_count++] = (buf[count] >> 2);
746 }
747 }
748 if ((length % 3) != 2)
749 raw_count++;
750 tx_buf_raw[raw_count++] = SIXP_SEOF;
751 return raw_count;
752 }
753
754 /* decode 4 sixpack-encoded bytes into 3 data bytes */
755
decode_data(struct sixpack * sp,u8 inbyte)756 static void decode_data(struct sixpack *sp, u8 inbyte)
757 {
758 u8 *buf;
759
760 if (sp->rx_count != 3) {
761 sp->raw_buf[sp->rx_count++] = inbyte;
762
763 return;
764 }
765
766 if (sp->rx_count_cooked + 2 >= sizeof(sp->cooked_buf)) {
767 pr_err("6pack: cooked buffer overrun, data loss\n");
768 sp->rx_count = 0;
769 return;
770 }
771
772 buf = sp->raw_buf;
773 sp->cooked_buf[sp->rx_count_cooked++] =
774 buf[0] | ((buf[1] << 2) & 0xc0);
775 sp->cooked_buf[sp->rx_count_cooked++] =
776 (buf[1] & 0x0f) | ((buf[2] << 2) & 0xf0);
777 sp->cooked_buf[sp->rx_count_cooked++] =
778 (buf[2] & 0x03) | (inbyte << 2);
779 sp->rx_count = 0;
780 }
781
782 /* identify and execute a 6pack priority command byte */
783
decode_prio_command(struct sixpack * sp,u8 cmd)784 static void decode_prio_command(struct sixpack *sp, u8 cmd)
785 {
786 ssize_t actual;
787
788 if ((cmd & SIXP_PRIO_DATA_MASK) != 0) { /* idle ? */
789
790 /* RX and DCD flags can only be set in the same prio command,
791 if the DCD flag has been set without the RX flag in the previous
792 prio command. If DCD has not been set before, something in the
793 transmission has gone wrong. In this case, RX and DCD are
794 cleared in order to prevent the decode_data routine from
795 reading further data that might be corrupt. */
796
797 if (((sp->status & SIXP_DCD_MASK) == 0) &&
798 ((cmd & SIXP_RX_DCD_MASK) == SIXP_RX_DCD_MASK)) {
799 if (sp->status != 1)
800 printk(KERN_DEBUG "6pack: protocol violation\n");
801 else
802 sp->status = 0;
803 cmd &= ~SIXP_RX_DCD_MASK;
804 }
805 sp->status = cmd & SIXP_PRIO_DATA_MASK;
806 } else { /* output watchdog char if idle */
807 if ((sp->status2 != 0) && (sp->duplex == 1)) {
808 sp->led_state = 0x70;
809 sp->tty->ops->write(sp->tty, &sp->led_state, 1);
810 sp->tx_enable = 1;
811 actual = sp->tty->ops->write(sp->tty, sp->xbuff, sp->status2);
812 sp->xleft -= actual;
813 sp->xhead += actual;
814 sp->led_state = 0x60;
815 sp->status2 = 0;
816
817 }
818 }
819
820 /* needed to trigger the TNC watchdog */
821 sp->tty->ops->write(sp->tty, &sp->led_state, 1);
822
823 /* if the state byte has been received, the TNC is present,
824 so the resync timer can be reset. */
825
826 if (sp->tnc_state == TNC_IN_SYNC)
827 mod_timer(&sp->resync_t, jiffies + SIXP_INIT_RESYNC_TIMEOUT);
828
829 sp->status1 = cmd & SIXP_PRIO_DATA_MASK;
830 }
831
832 /* identify and execute a standard 6pack command byte */
833
decode_std_command(struct sixpack * sp,u8 cmd)834 static void decode_std_command(struct sixpack *sp, u8 cmd)
835 {
836 u8 checksum = 0, rest = 0;
837 short i;
838
839 switch (cmd & SIXP_CMD_MASK) { /* normal command */
840 case SIXP_SEOF:
841 if ((sp->rx_count == 0) && (sp->rx_count_cooked == 0)) {
842 if ((sp->status & SIXP_RX_DCD_MASK) ==
843 SIXP_RX_DCD_MASK) {
844 sp->led_state = 0x68;
845 sp->tty->ops->write(sp->tty, &sp->led_state, 1);
846 }
847 } else {
848 sp->led_state = 0x60;
849 /* fill trailing bytes with zeroes */
850 sp->tty->ops->write(sp->tty, &sp->led_state, 1);
851 spin_lock_bh(&sp->rxlock);
852 rest = sp->rx_count;
853 if (rest != 0)
854 for (i = rest; i <= 3; i++)
855 decode_data(sp, 0);
856 if (rest == 2)
857 sp->rx_count_cooked -= 2;
858 else if (rest == 3)
859 sp->rx_count_cooked -= 1;
860 for (i = 0; i < sp->rx_count_cooked; i++)
861 checksum += sp->cooked_buf[i];
862 if (checksum != SIXP_CHKSUM) {
863 printk(KERN_DEBUG "6pack: bad checksum %2.2x\n", checksum);
864 } else {
865 sp->rcount = sp->rx_count_cooked-2;
866 sp_bump(sp, 0);
867 }
868 sp->rx_count_cooked = 0;
869 spin_unlock_bh(&sp->rxlock);
870 }
871 break;
872 case SIXP_TX_URUN: printk(KERN_DEBUG "6pack: TX underrun\n");
873 break;
874 case SIXP_RX_ORUN: printk(KERN_DEBUG "6pack: RX overrun\n");
875 break;
876 case SIXP_RX_BUF_OVL:
877 printk(KERN_DEBUG "6pack: RX buffer overflow\n");
878 }
879 }
880
881 /* decode a 6pack packet */
882
883 static void
sixpack_decode(struct sixpack * sp,const u8 * pre_rbuff,size_t count)884 sixpack_decode(struct sixpack *sp, const u8 *pre_rbuff, size_t count)
885 {
886 size_t count1;
887 u8 inbyte;
888
889 for (count1 = 0; count1 < count; count1++) {
890 inbyte = pre_rbuff[count1];
891 if (inbyte == SIXP_FOUND_TNC) {
892 tnc_set_sync_state(sp, TNC_IN_SYNC);
893 timer_delete(&sp->resync_t);
894 }
895 if ((inbyte & SIXP_PRIO_CMD_MASK) != 0)
896 decode_prio_command(sp, inbyte);
897 else if ((inbyte & SIXP_STD_CMD_MASK) != 0)
898 decode_std_command(sp, inbyte);
899 else if ((sp->status & SIXP_RX_DCD_MASK) == SIXP_RX_DCD_MASK) {
900 spin_lock_bh(&sp->rxlock);
901 decode_data(sp, inbyte);
902 spin_unlock_bh(&sp->rxlock);
903 }
904 }
905 }
906
907 MODULE_AUTHOR("Ralf Baechle DO1GRB <ralf@linux-mips.org>");
908 MODULE_DESCRIPTION("6pack driver for AX.25");
909 MODULE_LICENSE("GPL");
910 MODULE_ALIAS_LDISC(N_6PACK);
911
912 module_init(sixpack_init_driver);
913 module_exit(sixpack_exit_driver);
914