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