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