mkiss.c revision b4558ea93d66a43f7990d26f145fd4c54a01c9bf
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
2815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle *  This program is free software; you can distribute it and/or modify it
3815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle *  under the terms of the GNU General Public License (Version 2) as
4815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle *  published by the Free Software Foundation.
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
6815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle *  This program is distributed in the hope it will be useful, but WITHOUT
7815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
8815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
9815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle *  for more details.
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
11815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle *  You should have received a copy of the GNU General Public License along
12815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle *  with this program; if not, write to the Free Software Foundation, Inc.,
13815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
15815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle * Copyright (C) Hans Alblas PE1AYX <hans@esrac.ele.tue.nl>
16815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle * Copyright (C) 2004, 05 Ralf Baechle DL5RB <ralf@linux-mips.org>
175793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle * Copyright (C) 2004, 05 Thomas Osterried DL9SAU <thomas@x-berg.in-berlin.de>
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/config.h>
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h>
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/system.h>
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/bitops.h>
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/uaccess.h>
245793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle#include <linux/crc16.h>
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/string.h>
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mm.h>
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/interrupt.h>
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/in.h>
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/inet.h>
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/tty.h>
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h>
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/netdevice.h>
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/major.h>
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h>
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/rtnetlink.h>
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/etherdevice.h>
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/skbuff.h>
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/if_arp.h>
39cd8749b4aa6b7502e234d72cb53c00a3bc27ed1bMarcelo Feitoza Parisi#include <linux/jiffies.h>
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <net/ax25.h>
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
43815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle#define AX_MTU		236
44815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
45815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle/* SLIP/KISS protocol characters. */
46815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle#define END             0300		/* indicates end of frame	*/
47815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle#define ESC             0333		/* indicates byte stuffing	*/
48815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle#define ESC_END         0334		/* ESC ESC_END means END 'data'	*/
49815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle#define ESC_ESC         0335		/* ESC ESC_ESC means ESC 'data'	*/
50815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
51815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechlestruct mkiss {
52815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	struct tty_struct	*tty;	/* ptr to TTY structure		*/
53815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	struct net_device	*dev;	/* easy for intr handling	*/
54815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
55815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	/* These are pointers to the malloc()ed frame buffers. */
56815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	spinlock_t		buflock;/* lock for rbuf and xbuf */
57815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	unsigned char		*rbuff;	/* receiver buffer		*/
58815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	int			rcount;	/* received chars counter       */
59815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	unsigned char		*xbuff;	/* transmitter buffer		*/
60815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	unsigned char		*xhead;	/* pointer to next byte to XMIT */
61815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	int			xleft;	/* bytes left in XMIT queue     */
62815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
63815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	struct net_device_stats	stats;
64815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
65815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	/* Detailed SLIP statistics. */
66815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	int		mtu;		/* Our mtu (to spot changes!)   */
67815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	int		buffsize;	/* Max buffers sizes            */
68815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
69815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	unsigned long	flags;		/* Flag values/ mode etc	*/
70815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle					/* long req'd: used by set_bit --RR */
71815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle#define AXF_INUSE	0		/* Channel in use               */
72815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle#define AXF_ESCAPE	1               /* ESC received                 */
73815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle#define AXF_ERROR	2               /* Parity, etc. error           */
74815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle#define AXF_KEEPTEST	3		/* Keepalive test flag		*/
75815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle#define AXF_OUTWAIT	4		/* is outpacket was flag	*/
76815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
77815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	int		mode;
78815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle        int		crcmode;	/* MW: for FlexNet, SMACK etc.  */
795793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle	int		crcauto;	/* CRC auto mode */
805793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle
815793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle#define CRC_MODE_NONE		0
825793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle#define CRC_MODE_FLEX		1
835793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle#define CRC_MODE_SMACK		2
845793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle#define CRC_MODE_FLEX_TEST	3
855793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle#define CRC_MODE_SMACK_TEST	4
86815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
87815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	atomic_t		refcnt;
88815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	struct semaphore	dead_sem;
89815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle};
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*---------------------------------------------------------------------------*/
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
93815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechlestatic const unsigned short crc_flex_table[] = {
94815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0x0f87, 0x1e0e, 0x2c95, 0x3d1c, 0x49a3, 0x582a, 0x6ab1, 0x7b38,
95815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0x83cf, 0x9246, 0xa0dd, 0xb154, 0xc5eb, 0xd462, 0xe6f9, 0xf770,
96815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0x1f06, 0x0e8f, 0x3c14, 0x2d9d, 0x5922, 0x48ab, 0x7a30, 0x6bb9,
97815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0x934e, 0x82c7, 0xb05c, 0xa1d5, 0xd56a, 0xc4e3, 0xf678, 0xe7f1,
98815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0x2e85, 0x3f0c, 0x0d97, 0x1c1e, 0x68a1, 0x7928, 0x4bb3, 0x5a3a,
99815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0xa2cd, 0xb344, 0x81df, 0x9056, 0xe4e9, 0xf560, 0xc7fb, 0xd672,
100815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0x3e04, 0x2f8d, 0x1d16, 0x0c9f, 0x7820, 0x69a9, 0x5b32, 0x4abb,
101815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0xb24c, 0xa3c5, 0x915e, 0x80d7, 0xf468, 0xe5e1, 0xd77a, 0xc6f3,
102815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0x4d83, 0x5c0a, 0x6e91, 0x7f18, 0x0ba7, 0x1a2e, 0x28b5, 0x393c,
103815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0xc1cb, 0xd042, 0xe2d9, 0xf350, 0x87ef, 0x9666, 0xa4fd, 0xb574,
104815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0x5d02, 0x4c8b, 0x7e10, 0x6f99, 0x1b26, 0x0aaf, 0x3834, 0x29bd,
105815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0xd14a, 0xc0c3, 0xf258, 0xe3d1, 0x976e, 0x86e7, 0xb47c, 0xa5f5,
106815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0x6c81, 0x7d08, 0x4f93, 0x5e1a, 0x2aa5, 0x3b2c, 0x09b7, 0x183e,
107815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0xe0c9, 0xf140, 0xc3db, 0xd252, 0xa6ed, 0xb764, 0x85ff, 0x9476,
108815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0x7c00, 0x6d89, 0x5f12, 0x4e9b, 0x3a24, 0x2bad, 0x1936, 0x08bf,
109815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0xf048, 0xe1c1, 0xd35a, 0xc2d3, 0xb66c, 0xa7e5, 0x957e, 0x84f7,
110815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0x8b8f, 0x9a06, 0xa89d, 0xb914, 0xcdab, 0xdc22, 0xeeb9, 0xff30,
111815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0x07c7, 0x164e, 0x24d5, 0x355c, 0x41e3, 0x506a, 0x62f1, 0x7378,
112815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0x9b0e, 0x8a87, 0xb81c, 0xa995, 0xdd2a, 0xcca3, 0xfe38, 0xefb1,
113815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0x1746, 0x06cf, 0x3454, 0x25dd, 0x5162, 0x40eb, 0x7270, 0x63f9,
114815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0xaa8d, 0xbb04, 0x899f, 0x9816, 0xeca9, 0xfd20, 0xcfbb, 0xde32,
115815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0x26c5, 0x374c, 0x05d7, 0x145e, 0x60e1, 0x7168, 0x43f3, 0x527a,
116815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0xba0c, 0xab85, 0x991e, 0x8897, 0xfc28, 0xeda1, 0xdf3a, 0xceb3,
117815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0x3644, 0x27cd, 0x1556, 0x04df, 0x7060, 0x61e9, 0x5372, 0x42fb,
118815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0xc98b, 0xd802, 0xea99, 0xfb10, 0x8faf, 0x9e26, 0xacbd, 0xbd34,
119815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0x45c3, 0x544a, 0x66d1, 0x7758, 0x03e7, 0x126e, 0x20f5, 0x317c,
120815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0xd90a, 0xc883, 0xfa18, 0xeb91, 0x9f2e, 0x8ea7, 0xbc3c, 0xadb5,
121815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0x5542, 0x44cb, 0x7650, 0x67d9, 0x1366, 0x02ef, 0x3074, 0x21fd,
122815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0xe889, 0xf900, 0xcb9b, 0xda12, 0xaead, 0xbf24, 0x8dbf, 0x9c36,
123815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0x64c1, 0x7548, 0x47d3, 0x565a, 0x22e5, 0x336c, 0x01f7, 0x107e,
124815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0xf808, 0xe981, 0xdb1a, 0xca93, 0xbe2c, 0xafa5, 0x9d3e, 0x8cb7,
125815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0x7440, 0x65c9, 0x5752, 0x46db, 0x3264, 0x23ed, 0x1176, 0x00ff
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned short calc_crc_flex(unsigned char *cp, int size)
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
130815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	unsigned short crc = 0xffff;
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
132815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	while (size--)
133815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		crc = (crc << 8) ^ crc_flex_table[((crc >> 8) ^ *cp++) & 0xff];
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
135815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	return crc;
136815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle}
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int check_crc_flex(unsigned char *cp, int size)
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
140815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	unsigned short crc = 0xffff;
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
142815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	if (size < 3)
143815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		return -1;
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
145815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	while (size--)
146815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		crc = (crc << 8) ^ crc_flex_table[((crc >> 8) ^ *cp++) & 0xff];
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
148815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	if ((crc & 0xffff) != 0x7070)
149815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		return -1;
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
151815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	return 0;
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1545793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechlestatic int check_crc_16(unsigned char *cp, int size)
1555793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle{
1565793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle	unsigned short crc = 0x0000;
1575793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle
1585793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle	if (size < 3)
1595793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		return -1;
1605793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle
1615793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle	crc = crc16(0, cp, size);
1625793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle
1635793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle	if (crc != 0x0000)
1645793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		return -1;
1655793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle
1665793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle	return 0;
1675793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle}
1685793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle
169815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle/*
170815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle * Standard encapsulation
171815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle */
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
173815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechlestatic int kiss_esc(unsigned char *s, unsigned char *d, int len)
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
175815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	unsigned char *ptr = d;
176815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	unsigned char c;
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
178815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	/*
179815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	 * Send an initial END character to flush out any data that may have
180815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	 * accumulated in the receiver due to line noise.
181815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	 */
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
183815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	*ptr++ = END;
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
185815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	while (len-- > 0) {
186815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		switch (c = *s++) {
187815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		case END:
188815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			*ptr++ = ESC;
189815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			*ptr++ = ESC_END;
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
191815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		case ESC:
192815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			*ptr++ = ESC;
193815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			*ptr++ = ESC_ESC;
194815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			break;
195815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		default:
196815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			*ptr++ = c;
197815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			break;
198815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		}
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
201815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	*ptr++ = END;
202815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
203815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	return ptr - d;
204815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle}
205815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
206815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle/*
207815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle * MW:
208815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle * OK its ugly, but tell me a better solution without copying the
209815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle * packet to a temporary buffer :-)
210815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle */
211815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechlestatic int kiss_esc_crc(unsigned char *s, unsigned char *d, unsigned short crc,
212815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	int len)
213815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle{
214815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	unsigned char *ptr = d;
215815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	unsigned char c=0;
216815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
217815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	*ptr++ = END;
218815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	while (len > 0) {
219815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		if (len > 2)
220815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			c = *s++;
221815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		else if (len > 1)
222815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			c = crc >> 8;
223815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		else if (len > 0)
224815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			c = crc & 0xff;
225815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
226815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		len--;
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
228815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		switch (c) {
229815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		case END:
230815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			*ptr++ = ESC;
231815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			*ptr++ = ESC_END;
232815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			break;
233815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		case ESC:
234815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			*ptr++ = ESC;
235815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			*ptr++ = ESC_ESC;
236815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			break;
237815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		default:
238815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			*ptr++ = c;
239815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			break;
240815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		}
2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
242815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	*ptr++ = END;
243815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
244815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	return ptr - d;
245815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle}
246815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
247815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle/* Send one completely decapsulated AX.25 packet to the AX.25 layer. */
248815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechlestatic void ax_bump(struct mkiss *ax)
249815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle{
250815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	struct sk_buff *skb;
251815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	int count;
252815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
253815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	spin_lock_bh(&ax->buflock);
254815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	if (ax->rbuff[0] > 0x0f) {
2555793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		if (ax->rbuff[0] & 0x80) {
2565793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			if (check_crc_16(ax->rbuff, ax->rcount) < 0) {
2575793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				ax->stats.rx_errors++;
2585793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				spin_unlock_bh(&ax->buflock);
2595793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle
2605793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				return;
2615793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			}
2625793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			if (ax->crcmode != CRC_MODE_SMACK && ax->crcauto) {
2635793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				printk(KERN_INFO
2645793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				       "mkiss: %s: Switchting to crc-smack\n",
2655793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				       ax->dev->name);
2665793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				ax->crcmode = CRC_MODE_SMACK;
2675793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			}
2685793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			ax->rcount -= 2;
2695793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			*ax->rbuff &= ~0x80;
2705793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		} else if (ax->rbuff[0] & 0x20)  {
271815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			if (check_crc_flex(ax->rbuff, ax->rcount) < 0) {
2725793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				ax->stats.rx_errors++;
2735793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				spin_unlock_bh(&ax->buflock);
274815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle				return;
275815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			}
2765793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			if (ax->crcmode != CRC_MODE_FLEX && ax->crcauto) {
2775793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				printk(KERN_INFO
2785793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				       "mkiss: %s: Switchting to crc-flexnet\n",
2795793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				       ax->dev->name);
2805793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				ax->crcmode = CRC_MODE_FLEX;
2815793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			}
282815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			ax->rcount -= 2;
2835793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle
2845793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			/*
2855793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			 * dl9sau bugfix: the trailling two bytes flexnet crc
2865793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			 * will not be passed to the kernel. thus we have to
2875793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			 * correct the kissparm signature, because it indicates
2885793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			 * a crc but there's none
289815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			 */
2905793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			*ax->rbuff &= ~0x20;
2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
292815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle 	}
293815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	spin_unlock_bh(&ax->buflock);
294815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
295815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	count = ax->rcount;
296815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
297815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	if ((skb = dev_alloc_skb(count)) == NULL) {
298815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		printk(KERN_ERR "mkiss: %s: memory squeeze, dropping packet.\n",
299815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		       ax->dev->name);
300815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		ax->stats.rx_dropped++;
301815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		return;
3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
304815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	spin_lock_bh(&ax->buflock);
305815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	memcpy(skb_put(skb,count), ax->rbuff, count);
306815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	spin_unlock_bh(&ax->buflock);
307815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	skb->protocol = ax25_type_trans(skb, ax->dev);
308815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	netif_rx(skb);
309815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	ax->dev->last_rx = jiffies;
310815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	ax->stats.rx_packets++;
311815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	ax->stats.rx_bytes += count;
3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
314815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechlestatic void kiss_unesc(struct mkiss *ax, unsigned char s)
3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
316815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	switch (s) {
317815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	case END:
318815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		/* drop keeptest bit = VSV */
319815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		if (test_bit(AXF_KEEPTEST, &ax->flags))
320815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			clear_bit(AXF_KEEPTEST, &ax->flags);
321815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
322815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		if (!test_and_clear_bit(AXF_ERROR, &ax->flags) && (ax->rcount > 2))
323815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			ax_bump(ax);
324815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
325815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		clear_bit(AXF_ESCAPE, &ax->flags);
326815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		ax->rcount = 0;
327815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		return;
328815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
329815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	case ESC:
330815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		set_bit(AXF_ESCAPE, &ax->flags);
331815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		return;
332815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	case ESC_ESC:
333815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		if (test_and_clear_bit(AXF_ESCAPE, &ax->flags))
334815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			s = ESC;
335815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		break;
336815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	case ESC_END:
337815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		if (test_and_clear_bit(AXF_ESCAPE, &ax->flags))
338815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			s = END;
339815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		break;
340815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	}
341815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
342815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	spin_lock_bh(&ax->buflock);
343815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	if (!test_bit(AXF_ERROR, &ax->flags)) {
344815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		if (ax->rcount < ax->buffsize) {
345815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			ax->rbuff[ax->rcount++] = s;
346815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			spin_unlock_bh(&ax->buflock);
347815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			return;
348815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		}
349815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
350815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		ax->stats.rx_over_errors++;
351815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		set_bit(AXF_ERROR, &ax->flags);
352815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	}
353815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	spin_unlock_bh(&ax->buflock);
354815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle}
355815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
356815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechlestatic int ax_set_mac_address(struct net_device *dev, void *addr)
357815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle{
358815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	struct sockaddr_ax25 *sa = addr;
359815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
360815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	spin_lock_irq(&dev->xmit_lock);
361815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	memcpy(dev->dev_addr, &sa->sax25_call, AX25_ADDR_LEN);
362815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	spin_unlock_irq(&dev->xmit_lock);
363815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
364815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	return 0;
3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
367815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle/*---------------------------------------------------------------------------*/
368815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
369815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechlestatic void ax_changedmtu(struct mkiss *ax)
3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct net_device *dev = ax->dev;
3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned char *xbuff, *rbuff, *oxbuff, *orbuff;
3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int len;
3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	len = dev->mtu * 2;
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * allow for arrival of larger UDP packets, even if we say not to
3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * also fixes a bug in which SunOS sends 512-byte packets even with
3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * an MSS of 128
3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (len < 576 * 2)
3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		len = 576 * 2;
3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	xbuff = kmalloc(len + 4, GFP_ATOMIC);
3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rbuff = kmalloc(len + 4, GFP_ATOMIC);
3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (xbuff == NULL || rbuff == NULL)  {
389815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		printk(KERN_ERR "mkiss: %s: unable to grow ax25 buffers, "
390815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		       "MTU change cancelled.\n",
3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       ax->dev->name);
3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev->mtu = ax->mtu;
393b4558ea93d66a43f7990d26f145fd4c54a01c9bfJesper Juhl		kfree(xbuff);
394b4558ea93d66a43f7990d26f145fd4c54a01c9bfJesper Juhl		kfree(rbuff);
3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_bh(&ax->buflock);
3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	oxbuff    = ax->xbuff;
4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ax->xbuff = xbuff;
4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	orbuff    = ax->rbuff;
4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ax->rbuff = rbuff;
4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ax->xleft) {
4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (ax->xleft <= len) {
4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			memcpy(ax->xbuff, ax->xhead, ax->xleft);
4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else  {
4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ax->xleft = 0;
410815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			ax->stats.tx_dropped++;
4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ax->xhead = ax->xbuff;
4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ax->rcount) {
4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (ax->rcount <= len) {
4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			memcpy(ax->rbuff, orbuff, ax->rcount);
4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else  {
4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ax->rcount = 0;
421815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			ax->stats.rx_over_errors++;
4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			set_bit(AXF_ERROR, &ax->flags);
4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ax->mtu      = dev->mtu + 73;
4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ax->buffsize = len;
4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_bh(&ax->buflock);
4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
431815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	kfree(oxbuff);
432815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	kfree(orbuff);
4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Encapsulate one AX.25 packet and stuff into a TTY queue. */
436815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechlestatic void ax_encaps(struct net_device *dev, unsigned char *icp, int len)
4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
438815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	struct mkiss *ax = netdev_priv(dev);
4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned char *p;
4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int actual, count;
4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ax->mtu != ax->dev->mtu + 73)	/* Someone has been ifconfigging */
4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ax_changedmtu(ax);
4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (len > ax->mtu) {		/* Sigh, shouldn't occur BUT ... */
4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		len = ax->mtu;
4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_ERR "mkiss: %s: truncating oversized transmit packet!\n", ax->dev->name);
448815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		ax->stats.tx_dropped++;
449815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		netif_start_queue(dev);
4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	p = icp;
4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_bh(&ax->buflock);
4565793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle	if ((*p & 0x0f) != 0) {
4575793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		/* Configuration Command (kissparms(1).
4585793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		 * Protocol spec says: never append CRC.
4595793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		 * This fixes a very old bug in the linux
4605793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		 * kiss driver. -- dl9sau */
4615793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		switch (*p & 0xff) {
4625793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		case 0x85:
4635793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			/* command from userspace especially for us,
4645793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			 * not for delivery to the tnc */
4655793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			if (len > 1) {
4665793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				int cmd = (p[1] & 0xff);
4675793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				switch(cmd) {
4685793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				case 3:
4695793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				  ax->crcmode = CRC_MODE_SMACK;
4705793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				  break;
4715793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				case 2:
4725793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				  ax->crcmode = CRC_MODE_FLEX;
4735793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				  break;
4745793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				case 1:
4755793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				  ax->crcmode = CRC_MODE_NONE;
4765793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				  break;
4775793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				case 0:
4785793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				default:
4795793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				  ax->crcmode = CRC_MODE_SMACK_TEST;
4805793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				  cmd = 0;
4815793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				}
4825793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				ax->crcauto = (cmd ? 0 : 1);
4835793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				printk(KERN_INFO "mkiss: %s: crc mode %s %d\n", ax->dev->name, (len) ? "set to" : "is", cmd);
4845793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			}
4855793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			spin_unlock_bh(&ax->buflock);
4865793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			netif_start_queue(dev);
4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4885793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			return;
4895793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		default:
4905793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			count = kiss_esc(p, (unsigned char *)ax->xbuff, len);
4915793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		}
4925793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle	} else {
4935793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		unsigned short crc;
4945793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		switch (ax->crcmode) {
4955793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		case CRC_MODE_SMACK_TEST:
4965793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			ax->crcmode  = CRC_MODE_FLEX_TEST;
4975793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			printk(KERN_INFO "mkiss: %s: Trying crc-smack\n", ax->dev->name);
4985793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			// fall through
4995793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		case CRC_MODE_SMACK:
5005793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			*p |= 0x80;
5015793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			crc = swab16(crc16(0, p, len));
5025793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			count = kiss_esc_crc(p, (unsigned char *)ax->xbuff, crc, len+2);
5035793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			break;
5045793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		case CRC_MODE_FLEX_TEST:
5055793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			ax->crcmode = CRC_MODE_NONE;
5065793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			printk(KERN_INFO "mkiss: %s: Trying crc-flexnet\n", ax->dev->name);
5075793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			// fall through
5085793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		case CRC_MODE_FLEX:
5095793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			*p |= 0x20;
5105793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			crc = calc_crc_flex(p, len);
5115793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			count = kiss_esc_crc(p, (unsigned char *)ax->xbuff, crc, len+2);
5125793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			break;
5135793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle
5145793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		default:
5155793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			count = kiss_esc(p, (unsigned char *)ax->xbuff, len);
5165793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		}
5175793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle  	}
5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
519815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	set_bit(TTY_DO_WRITE_WAKEUP, &ax->tty->flags);
5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	actual = ax->tty->driver->write(ax->tty, ax->xbuff, count);
521815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	ax->stats.tx_packets++;
522815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	ax->stats.tx_bytes += actual;
523815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ax->dev->trans_start = jiffies;
5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ax->xleft = count - actual;
5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ax->xhead = ax->xbuff + actual;
5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Encapsulate an AX.25 packet and kick it into a TTY queue. */
5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ax_xmit(struct sk_buff *skb, struct net_device *dev)
5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
532815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	struct mkiss *ax = netdev_priv(dev);
5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!netif_running(dev))  {
5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_ERR "mkiss: %s: xmit call when iface is down\n", dev->name);
5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 1;
5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (netif_queue_stopped(dev)) {
5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * May be we must check transmitter timeout here ?
5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 *      14 Oct 1994 Dmitry Gorodchanin.
5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
544cd8749b4aa6b7502e234d72cb53c00a3bc27ed1bMarcelo Feitoza Parisi		if (time_before(jiffies, dev->trans_start + 20 * HZ)) {
5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* 20 sec timeout not reached */
5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return 1;
5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_ERR "mkiss: %s: transmit timed out, %s?\n", dev->name,
5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       (ax->tty->driver->chars_in_buffer(ax->tty) || ax->xleft) ?
5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       "bad line quality" : "driver error");
5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ax->xleft = 0;
554815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		clear_bit(TTY_DO_WRITE_WAKEUP, &ax->tty->flags);
555815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		netif_start_queue(dev);
5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* We were not busy, so we are now... :-) */
5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (skb != NULL) {
560815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		netif_stop_queue(dev);
561815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		ax_encaps(dev, skb->data, skb->len);
5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		kfree_skb(skb);
5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
568815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechlestatic int ax_open_dev(struct net_device *dev)
569815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle{
570815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	struct mkiss *ax = netdev_priv(dev);
571815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
572815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	if (ax->tty == NULL)
573815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		return -ENODEV;
574815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
575815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	return 0;
576815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle}
577815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Return the frame type ID */
5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ax_header(struct sk_buff *skb, struct net_device *dev, unsigned short type,
5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	  void *daddr, void *saddr, unsigned len)
5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_INET
5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (type != htons(ETH_P_AX25))
5866f74998e5c3b4610e6eba06babf16547369c512aRalf Baechle		return ax25_hard_header(skb, dev, type, daddr, saddr, len);
5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ax_rebuild_header(struct sk_buff *skb)
5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_INET
5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ax25_rebuild_header(skb);
5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else
5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif	/* CONFIG_{AX25,AX25_MODULE} */
6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Open the low-level part of the AX25 channel. Easy! */
6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ax_open(struct net_device *dev)
6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
606815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	struct mkiss *ax = netdev_priv(dev);
6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long len;
6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ax->tty == NULL)
6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ENODEV;
6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Allocate the frame buffers:
6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *
6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * rbuff	Receive buffer.
6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * xbuff	Transmit buffer.
6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	len = dev->mtu * 2;
6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * allow for arrival of larger UDP packets, even if we say not to
6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * also fixes a bug in which SunOS sends 512-byte packets even with
6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * an MSS of 128
6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (len < 576 * 2)
6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		len = 576 * 2;
6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((ax->rbuff = kmalloc(len + 4, GFP_KERNEL)) == NULL)
6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto norbuff;
6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((ax->xbuff = kmalloc(len + 4, GFP_KERNEL)) == NULL)
6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto noxbuff;
6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ax->mtu	     = dev->mtu + 73;
6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ax->buffsize = len;
6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ax->rcount   = 0;
6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ax->xleft    = 0;
6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ax->flags   &= (1 << AXF_INUSE);      /* Clear ESCAPE & ERROR flags */
6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_init(&ax->buflock);
6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsnoxbuff:
6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	kfree(ax->rbuff);
6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsnorbuff:
6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return -ENOMEM;
6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Close the low-level part of the AX25 channel. Easy! */
6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ax_close(struct net_device *dev)
6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
656815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	struct mkiss *ax = netdev_priv(dev);
6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
658815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	if (ax->tty)
659815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		clear_bit(TTY_DO_WRITE_WAKEUP, &ax->tty->flags);
6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	netif_stop_queue(dev);
6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
666815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechlestatic struct net_device_stats *ax_get_stats(struct net_device *dev)
6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
668815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	struct mkiss *ax = netdev_priv(dev);
669815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
670815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	return &ax->stats;
671815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle}
672815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
673815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechlestatic void ax_setup(struct net_device *dev)
674815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle{
675815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	static char ax25_bcast[AX25_ADDR_LEN] =
676815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		{'Q'<<1,'S'<<1,'T'<<1,' '<<1,' '<<1,' '<<1,'0'<<1};
677815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	static char ax25_test[AX25_ADDR_LEN] =
678815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		{'L'<<1,'I'<<1,'N'<<1,'U'<<1,'X'<<1,' '<<1,'1'<<1};
679815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
680815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	/* Finish setting up the DEVICE info. */
681815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	dev->mtu             = AX_MTU;
682815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	dev->hard_start_xmit = ax_xmit;
683815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	dev->open            = ax_open_dev;
684815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	dev->stop            = ax_close;
685815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	dev->get_stats	     = ax_get_stats;
686815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	dev->set_mac_address = ax_set_mac_address;
687815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	dev->hard_header_len = 0;
688815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	dev->addr_len        = 0;
689815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	dev->type            = ARPHRD_AX25;
690815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	dev->tx_queue_len    = 10;
691815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	dev->hard_header     = ax_header;
692815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	dev->rebuild_header  = ax_rebuild_header;
693815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
694815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	memcpy(dev->broadcast, ax25_bcast, AX25_ADDR_LEN);
695815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	memcpy(dev->dev_addr,  ax25_test,  AX25_ADDR_LEN);
696815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
697815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	dev->flags      = IFF_BROADCAST | IFF_MULTICAST;
6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
701815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle * We have a potential race on dereferencing tty->disc_data, because the tty
702815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle * layer provides no locking at all - thus one cpu could be running
703815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle * sixpack_receive_buf while another calls sixpack_close, which zeroes
704815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle * tty->disc_data and frees the memory that sixpack_receive_buf is using.  The
705815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle * best way to fix this is to use a rwlock in the tty struct, but for now we
706815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle * use a single global rwlock for all ttys in ppp line discipline.
7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
708d5919586265d36c6694a5d10ba589c02806873b6Ralf Baechlestatic DEFINE_RWLOCK(disc_data_lock);
709815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
710815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechlestatic struct mkiss *mkiss_get(struct tty_struct *tty)
7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
712815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	struct mkiss *ax;
7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
714815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	read_lock(&disc_data_lock);
715815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	ax = tty->disc_data;
716815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	if (ax)
717815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		atomic_inc(&ax->refcnt);
718815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	read_unlock(&disc_data_lock);
7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
720815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	return ax;
721815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle}
7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
723815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechlestatic void mkiss_put(struct mkiss *ax)
724815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle{
725815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	if (atomic_dec_and_test(&ax->refcnt))
726815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		up(&ax->dead_sem);
7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7295793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechlestatic int crc_force = 0;	/* Can be overridden with insmod */
7305793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle
731815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechlestatic int mkiss_open(struct tty_struct *tty)
7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
733815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	struct net_device *dev;
734815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	struct mkiss *ax;
7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int err;
7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
737815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	if (!capable(CAP_NET_ADMIN))
738815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		return -EPERM;
7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
740815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	dev = alloc_netdev(sizeof(struct mkiss), "ax%d", ax_setup);
741815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	if (!dev) {
742815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		err = -ENOMEM;
743815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		goto out;
744815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	}
745815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
746815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	ax = netdev_priv(dev);
747815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	ax->dev = dev;
748815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
749815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	spin_lock_init(&ax->buflock);
750815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	atomic_set(&ax->refcnt, 1);
751815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	init_MUTEX_LOCKED(&ax->dead_sem);
7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ax->tty = tty;
7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tty->disc_data = ax;
7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (tty->driver->flush_buffer)
7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		tty->driver->flush_buffer(tty);
7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Restore default settings */
760815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	dev->type = ARPHRD_AX25;
7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Perform the low-level AX25 initialization. */
763815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	if ((err = ax_open(ax->dev))) {
764815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		goto out_free_netdev;
765815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	}
7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
767815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	if (register_netdev(dev))
768815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		goto out_free_buffers;
7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7705793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle	/* after register_netdev() - because else printk smashes the kernel */
7715793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle	switch (crc_force) {
7725793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle	case 3:
7735793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		ax->crcmode  = CRC_MODE_SMACK;
7745793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		printk(KERN_INFO "mkiss: %s: crc mode smack forced.\n",
7755793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		       ax->dev->name);
7765793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		break;
7775793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle	case 2:
7785793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		ax->crcmode  = CRC_MODE_FLEX;
7795793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		printk(KERN_INFO "mkiss: %s: crc mode flexnet forced.\n",
7805793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		       ax->dev->name);
7815793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		break;
7825793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle	case 1:
7835793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		ax->crcmode  = CRC_MODE_NONE;
7845793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		printk(KERN_INFO "mkiss: %s: crc mode disabled.\n",
7855793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		       ax->dev->name);
7865793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		break;
7875793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle	case 0:
7885793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		/* fall through */
7895793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle	default:
7905793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		crc_force = 0;
7915793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		printk(KERN_INFO "mkiss: %s: crc mode is auto.\n",
7925793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		       ax->dev->name);
7935793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		ax->crcmode  = CRC_MODE_SMACK_TEST;
7945793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle	}
7955793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle	ax->crcauto = (crc_force ? 0 : 1);
7965793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle
797815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	netif_start_queue(dev);
7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
799815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	/* Done.  We have linked the TTY line to a channel. */
800815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	return 0;
8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
802815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechleout_free_buffers:
803815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	kfree(ax->rbuff);
804815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	kfree(ax->xbuff);
8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
806815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechleout_free_netdev:
807815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	free_netdev(dev);
8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
809815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechleout:
810815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	return err;
8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
813815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechlestatic void mkiss_close(struct tty_struct *tty)
8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
815815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	struct mkiss *ax;
8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
817815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	write_lock(&disc_data_lock);
818815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	ax = tty->disc_data;
819815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	tty->disc_data = NULL;
820815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	write_unlock(&disc_data_lock);
8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
822815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	if (ax == 0)
823815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		return;
8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
826815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	 * We have now ensured that nobody can start using ap from now on, but
827815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	 * we have to wait for all existing users to finish.
8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
829815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	if (!atomic_dec_and_test(&ax->refcnt))
830815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		down(&ax->dead_sem);
8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
832815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	unregister_netdev(ax->dev);
8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
834815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	/* Free all AX25 frame buffers. */
835815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	kfree(ax->rbuff);
836815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	kfree(ax->xbuff);
8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
838815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	ax->tty = NULL;
8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
841815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle/* Perform I/O control on an active ax25 channel. */
842815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechlestatic int mkiss_ioctl(struct tty_struct *tty, struct file *file,
843815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	unsigned int cmd, unsigned long arg)
8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
845815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	struct mkiss *ax = mkiss_get(tty);
846815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	struct net_device *dev = ax->dev;
847815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	unsigned int tmp, err;
8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
849815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	/* First make sure we're connected. */
850815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	if (ax == NULL)
851815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		return -ENXIO;
8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
853815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	switch (cmd) {
854815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle 	case SIOCGIFNAME:
855815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		err = copy_to_user((void __user *) arg, ax->dev->name,
856815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		                   strlen(ax->dev->name) + 1) ? -EFAULT : 0;
857815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		break;
858815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
859815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	case SIOCGIFENCAP:
860815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		err = put_user(4, (int __user *) arg);
861815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		break;
862815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
863815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	case SIOCSIFENCAP:
864815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		if (get_user(tmp, (int __user *) arg)) {
865815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			err = -EFAULT;
866815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			break;
8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
869815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		ax->mode = tmp;
870815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		dev->addr_len        = AX25_ADDR_LEN;
871815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		dev->hard_header_len = AX25_KISS_HEADER_LEN +
872815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		                       AX25_MAX_HEADER_LEN + 3;
873815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		dev->type            = ARPHRD_AX25;
8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
875815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		err = 0;
876815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		break;
8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
878815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	case SIOCSIFHWADDR: {
879815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		char addr[AX25_ADDR_LEN];
8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
881815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		if (copy_from_user(&addr,
882815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		                   (void __user *) arg, AX25_ADDR_LEN)) {
883815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			err = -EFAULT;
8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
887815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		spin_lock_irq(&dev->xmit_lock);
888815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		memcpy(dev->dev_addr, addr, AX25_ADDR_LEN);
889815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		spin_unlock_irq(&dev->xmit_lock);
890815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
891815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		err = 0;
892815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		break;
893815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	}
894815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	default:
895815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		err = -ENOIOCTLCMD;
8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
898815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	mkiss_put(ax);
8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
900815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	return err;
9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
903815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle/*
904815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle * Handle the 'receiver data ready' interrupt.
905815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle * This function is called by the 'tty_io' module in the kernel when
906815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle * a block of data has been received, which can now be decapsulated
907815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle * and sent on to the AX.25 layer for further processing.
908815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle */
909815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechlestatic void mkiss_receive_buf(struct tty_struct *tty, const unsigned char *cp,
910815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	char *fp, int count)
9111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
912815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	struct mkiss *ax = mkiss_get(tty);
9131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
914815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	if (!ax)
915815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		return;
9161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
917815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	/*
918815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	 * Argh! mtu change time! - costs us the packet part received
919815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	 * at the change
920815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	 */
921815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	if (ax->mtu != ax->dev->mtu + 73)
922815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		ax_changedmtu(ax);
9231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
924815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	/* Read the characters out of the buffer */
925815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	while (count--) {
926815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		if (fp != NULL && *fp++) {
927815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			if (!test_and_set_bit(AXF_ERROR, &ax->flags))
928815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle				ax->stats.rx_errors++;
929815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			cp++;
930815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			continue;
931815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		}
9321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
933815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		kiss_unesc(ax, *cp++);
9341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
935815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
936815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	mkiss_put(ax);
937815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	if (test_and_clear_bit(TTY_THROTTLED, &tty->flags)
938815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	    && tty->driver->unthrottle)
939815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		tty->driver->unthrottle(tty);
9401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
942815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechlestatic int mkiss_receive_room(struct tty_struct *tty)
9431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
944815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	return 65536;  /* We can handle an infinite amount of data. :-) */
9451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
947815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle/*
948815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle * Called by the driver when there's room for more data.  If we have
949815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle * more packets to send, we send them here.
950815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle */
951815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechlestatic void mkiss_write_wakeup(struct tty_struct *tty)
9521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
953815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	struct mkiss *ax = mkiss_get(tty);
954815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	int actual;
9551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
956815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	if (!ax)
957815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		return;
9581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
959815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	if (ax->xleft <= 0)  {
960815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		/* Now serial buffer is almost free & we can start
961815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		 * transmission of another packet
962815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		 */
963815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
9641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
965815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		netif_wake_queue(ax->dev);
966815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		goto out;
967815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	}
9681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
969815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	actual = tty->driver->write(tty, ax->xhead, ax->xleft);
970815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	ax->xleft -= actual;
971815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	ax->xhead += actual;
9721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
973815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechleout:
974815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	mkiss_put(ax);
9751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
977815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechlestatic struct tty_ldisc ax_ldisc = {
97874cfe03f80adc320bde4dd37616354aefe2271aaRalf Baechle	.owner		= THIS_MODULE,
979815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	.magic		= TTY_LDISC_MAGIC,
980815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	.name		= "mkiss",
981815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	.open		= mkiss_open,
982815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	.close		= mkiss_close,
983815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	.ioctl		= mkiss_ioctl,
984815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	.receive_buf	= mkiss_receive_buf,
985815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	.receive_room	= mkiss_receive_room,
986815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	.write_wakeup	= mkiss_write_wakeup
987815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle};
9881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
989815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechlestatic char banner[] __initdata = KERN_INFO \
990815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	"mkiss: AX.25 Multikiss, Hans Albas PE1AYX\n";
991815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechlestatic char msg_regfail[] __initdata = KERN_ERR \
992815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	"mkiss: can't register line discipline (err = %d)\n";
9931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init mkiss_init_driver(void)
9951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int status;
9971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk(banner);
9991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1000815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	if ((status = tty_register_ldisc(N_AX25, &ax_ldisc)) != 0)
1001815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		printk(msg_regfail);
10021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return status;
10041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1006815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechlestatic const char msg_unregfail[] __exitdata = KERN_ERR \
1007815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	"mkiss: can't unregister line discipline (err = %d)\n";
1008815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
10091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit mkiss_exit_driver(void)
10101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1011815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	int ret;
10121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1013815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	if ((ret = tty_unregister_ldisc(N_AX25)))
1014815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		printk(msg_unregfail, ret);
10151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1017815f62bf742718458ba822a7e1f51f285eb997f2Ralf BaechleMODULE_AUTHOR("Ralf Baechle DL5RB <ralf@linux-mips.org>");
10181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("KISS driver for AX.25 over TTYs");
10195793f4be23f0171b4999ca68a39a9157b44139f3Ralf BaechleMODULE_PARM(crc_force, "i");
10205793f4be23f0171b4999ca68a39a9157b44139f3Ralf BaechleMODULE_PARM_DESC(crc_force, "crc [0 = auto | 1 = none | 2 = flexnet | 3 = smack]");
10211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL");
10221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_ALIAS_LDISC(N_AX25);
1023815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
10241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(mkiss_init_driver);
10251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(mkiss_exit_driver);
1026