mkiss.c revision ddbe9a686805c36a0e68451ebb8cb51b21d0c718
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/module.h>
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/system.h>
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/bitops.h>
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/uaccess.h>
235793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle#include <linux/crc16.h>
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/string.h>
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mm.h>
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/interrupt.h>
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/in.h>
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/inet.h>
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/tty.h>
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h>
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/netdevice.h>
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/major.h>
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h>
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/rtnetlink.h>
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/etherdevice.h>
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/skbuff.h>
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/if_arp.h>
38cd8749b4aa6b7502e234d72cb53c00a3bc27ed1bMarcelo Feitoza Parisi#include <linux/jiffies.h>
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <net/ax25.h>
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
42815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle#define AX_MTU		236
43815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
44815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle/* SLIP/KISS protocol characters. */
45815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle#define END             0300		/* indicates end of frame	*/
46815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle#define ESC             0333		/* indicates byte stuffing	*/
47815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle#define ESC_END         0334		/* ESC ESC_END means END 'data'	*/
48815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle#define ESC_ESC         0335		/* ESC ESC_ESC means ESC 'data'	*/
49815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
50815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechlestruct mkiss {
51815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	struct tty_struct	*tty;	/* ptr to TTY structure		*/
52815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	struct net_device	*dev;	/* easy for intr handling	*/
53815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
54815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	/* These are pointers to the malloc()ed frame buffers. */
55815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	spinlock_t		buflock;/* lock for rbuf and xbuf */
56815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	unsigned char		*rbuff;	/* receiver buffer		*/
57815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	int			rcount;	/* received chars counter       */
58815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	unsigned char		*xbuff;	/* transmitter buffer		*/
59815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	unsigned char		*xhead;	/* pointer to next byte to XMIT */
60815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	int			xleft;	/* bytes left in XMIT queue     */
61815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
62815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	/* Detailed SLIP statistics. */
63815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	int		mtu;		/* Our mtu (to spot changes!)   */
64815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	int		buffsize;	/* Max buffers sizes            */
65815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
66815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	unsigned long	flags;		/* Flag values/ mode etc	*/
67815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle					/* long req'd: used by set_bit --RR */
68815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle#define AXF_INUSE	0		/* Channel in use               */
69815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle#define AXF_ESCAPE	1               /* ESC received                 */
70815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle#define AXF_ERROR	2               /* Parity, etc. error           */
71815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle#define AXF_KEEPTEST	3		/* Keepalive test flag		*/
72815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle#define AXF_OUTWAIT	4		/* is outpacket was flag	*/
73815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
74815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	int		mode;
75815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle        int		crcmode;	/* MW: for FlexNet, SMACK etc.  */
765793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle	int		crcauto;	/* CRC auto mode */
775793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle
785793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle#define CRC_MODE_NONE		0
795793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle#define CRC_MODE_FLEX		1
805793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle#define CRC_MODE_SMACK		2
815793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle#define CRC_MODE_FLEX_TEST	3
825793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle#define CRC_MODE_SMACK_TEST	4
83815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
84815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	atomic_t		refcnt;
85815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	struct semaphore	dead_sem;
86815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle};
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*---------------------------------------------------------------------------*/
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
90815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechlestatic const unsigned short crc_flex_table[] = {
91815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0x0f87, 0x1e0e, 0x2c95, 0x3d1c, 0x49a3, 0x582a, 0x6ab1, 0x7b38,
92815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0x83cf, 0x9246, 0xa0dd, 0xb154, 0xc5eb, 0xd462, 0xe6f9, 0xf770,
93815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0x1f06, 0x0e8f, 0x3c14, 0x2d9d, 0x5922, 0x48ab, 0x7a30, 0x6bb9,
94815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0x934e, 0x82c7, 0xb05c, 0xa1d5, 0xd56a, 0xc4e3, 0xf678, 0xe7f1,
95815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0x2e85, 0x3f0c, 0x0d97, 0x1c1e, 0x68a1, 0x7928, 0x4bb3, 0x5a3a,
96815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0xa2cd, 0xb344, 0x81df, 0x9056, 0xe4e9, 0xf560, 0xc7fb, 0xd672,
97815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0x3e04, 0x2f8d, 0x1d16, 0x0c9f, 0x7820, 0x69a9, 0x5b32, 0x4abb,
98815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0xb24c, 0xa3c5, 0x915e, 0x80d7, 0xf468, 0xe5e1, 0xd77a, 0xc6f3,
99815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0x4d83, 0x5c0a, 0x6e91, 0x7f18, 0x0ba7, 0x1a2e, 0x28b5, 0x393c,
100815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0xc1cb, 0xd042, 0xe2d9, 0xf350, 0x87ef, 0x9666, 0xa4fd, 0xb574,
101815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0x5d02, 0x4c8b, 0x7e10, 0x6f99, 0x1b26, 0x0aaf, 0x3834, 0x29bd,
102815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0xd14a, 0xc0c3, 0xf258, 0xe3d1, 0x976e, 0x86e7, 0xb47c, 0xa5f5,
103815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0x6c81, 0x7d08, 0x4f93, 0x5e1a, 0x2aa5, 0x3b2c, 0x09b7, 0x183e,
104815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0xe0c9, 0xf140, 0xc3db, 0xd252, 0xa6ed, 0xb764, 0x85ff, 0x9476,
105815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0x7c00, 0x6d89, 0x5f12, 0x4e9b, 0x3a24, 0x2bad, 0x1936, 0x08bf,
106815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0xf048, 0xe1c1, 0xd35a, 0xc2d3, 0xb66c, 0xa7e5, 0x957e, 0x84f7,
107815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0x8b8f, 0x9a06, 0xa89d, 0xb914, 0xcdab, 0xdc22, 0xeeb9, 0xff30,
108815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0x07c7, 0x164e, 0x24d5, 0x355c, 0x41e3, 0x506a, 0x62f1, 0x7378,
109815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0x9b0e, 0x8a87, 0xb81c, 0xa995, 0xdd2a, 0xcca3, 0xfe38, 0xefb1,
110815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0x1746, 0x06cf, 0x3454, 0x25dd, 0x5162, 0x40eb, 0x7270, 0x63f9,
111815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0xaa8d, 0xbb04, 0x899f, 0x9816, 0xeca9, 0xfd20, 0xcfbb, 0xde32,
112815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0x26c5, 0x374c, 0x05d7, 0x145e, 0x60e1, 0x7168, 0x43f3, 0x527a,
113815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0xba0c, 0xab85, 0x991e, 0x8897, 0xfc28, 0xeda1, 0xdf3a, 0xceb3,
114815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0x3644, 0x27cd, 0x1556, 0x04df, 0x7060, 0x61e9, 0x5372, 0x42fb,
115815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0xc98b, 0xd802, 0xea99, 0xfb10, 0x8faf, 0x9e26, 0xacbd, 0xbd34,
116815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0x45c3, 0x544a, 0x66d1, 0x7758, 0x03e7, 0x126e, 0x20f5, 0x317c,
117815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0xd90a, 0xc883, 0xfa18, 0xeb91, 0x9f2e, 0x8ea7, 0xbc3c, 0xadb5,
118815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0x5542, 0x44cb, 0x7650, 0x67d9, 0x1366, 0x02ef, 0x3074, 0x21fd,
119815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0xe889, 0xf900, 0xcb9b, 0xda12, 0xaead, 0xbf24, 0x8dbf, 0x9c36,
120815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0x64c1, 0x7548, 0x47d3, 0x565a, 0x22e5, 0x336c, 0x01f7, 0x107e,
121815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0xf808, 0xe981, 0xdb1a, 0xca93, 0xbe2c, 0xafa5, 0x9d3e, 0x8cb7,
122815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0x7440, 0x65c9, 0x5752, 0x46db, 0x3264, 0x23ed, 0x1176, 0x00ff
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned short calc_crc_flex(unsigned char *cp, int size)
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
127815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	unsigned short crc = 0xffff;
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
129815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	while (size--)
130815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		crc = (crc << 8) ^ crc_flex_table[((crc >> 8) ^ *cp++) & 0xff];
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
132815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	return crc;
133815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle}
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int check_crc_flex(unsigned char *cp, int size)
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
137815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	unsigned short crc = 0xffff;
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
139815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	if (size < 3)
140815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		return -1;
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
142815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	while (size--)
143815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		crc = (crc << 8) ^ crc_flex_table[((crc >> 8) ^ *cp++) & 0xff];
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
145815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	if ((crc & 0xffff) != 0x7070)
146815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		return -1;
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
148815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	return 0;
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1515793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechlestatic int check_crc_16(unsigned char *cp, int size)
1525793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle{
1535793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle	unsigned short crc = 0x0000;
1545793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle
1555793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle	if (size < 3)
1565793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		return -1;
1575793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle
1585793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle	crc = crc16(0, cp, size);
1595793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle
1605793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle	if (crc != 0x0000)
1615793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		return -1;
1625793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle
1635793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle	return 0;
1645793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle}
1655793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle
166815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle/*
167815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle * Standard encapsulation
168815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle */
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
170815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechlestatic int kiss_esc(unsigned char *s, unsigned char *d, int len)
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
172815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	unsigned char *ptr = d;
173815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	unsigned char c;
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
175815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	/*
176815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	 * Send an initial END character to flush out any data that may have
177815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	 * accumulated in the receiver due to line noise.
178815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	 */
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
180815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	*ptr++ = END;
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
182815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	while (len-- > 0) {
183815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		switch (c = *s++) {
184815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		case END:
185815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			*ptr++ = ESC;
186815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			*ptr++ = ESC_END;
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
188815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		case ESC:
189815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			*ptr++ = ESC;
190815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			*ptr++ = ESC_ESC;
191815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			break;
192815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		default:
193815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			*ptr++ = c;
194815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			break;
195815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		}
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
198815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	*ptr++ = END;
199815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
200815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	return ptr - d;
201815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle}
202815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
203815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle/*
204815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle * MW:
205815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle * OK its ugly, but tell me a better solution without copying the
206815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle * packet to a temporary buffer :-)
207815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle */
208815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechlestatic int kiss_esc_crc(unsigned char *s, unsigned char *d, unsigned short crc,
209815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	int len)
210815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle{
211815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	unsigned char *ptr = d;
212815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	unsigned char c=0;
213815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
214815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	*ptr++ = END;
215815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	while (len > 0) {
216815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		if (len > 2)
217815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			c = *s++;
218815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		else if (len > 1)
219815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			c = crc >> 8;
220815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		else if (len > 0)
221815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			c = crc & 0xff;
222815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
223815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		len--;
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
225815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		switch (c) {
226815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		case END:
227815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			*ptr++ = ESC;
228815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			*ptr++ = ESC_END;
229815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			break;
230815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		case ESC:
231815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			*ptr++ = ESC;
232815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			*ptr++ = ESC_ESC;
233815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			break;
234815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		default:
235815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			*ptr++ = c;
236815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			break;
237815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		}
2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
239815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	*ptr++ = END;
240815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
241815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	return ptr - d;
242815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle}
243815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
244815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle/* Send one completely decapsulated AX.25 packet to the AX.25 layer. */
245815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechlestatic void ax_bump(struct mkiss *ax)
246815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle{
247815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	struct sk_buff *skb;
248815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	int count;
249815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
250815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	spin_lock_bh(&ax->buflock);
251815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	if (ax->rbuff[0] > 0x0f) {
2525793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		if (ax->rbuff[0] & 0x80) {
2535793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			if (check_crc_16(ax->rbuff, ax->rcount) < 0) {
254ddbe9a686805c36a0e68451ebb8cb51b21d0c718Stephen Hemminger				ax->dev->stats.rx_errors++;
2555793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				spin_unlock_bh(&ax->buflock);
2565793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle
2575793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				return;
2585793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			}
2595793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			if (ax->crcmode != CRC_MODE_SMACK && ax->crcauto) {
2605793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				printk(KERN_INFO
2615793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				       "mkiss: %s: Switchting to crc-smack\n",
2625793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				       ax->dev->name);
2635793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				ax->crcmode = CRC_MODE_SMACK;
2645793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			}
2655793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			ax->rcount -= 2;
2665793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			*ax->rbuff &= ~0x80;
2675793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		} else if (ax->rbuff[0] & 0x20)  {
268815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			if (check_crc_flex(ax->rbuff, ax->rcount) < 0) {
269ddbe9a686805c36a0e68451ebb8cb51b21d0c718Stephen Hemminger				ax->dev->stats.rx_errors++;
2705793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				spin_unlock_bh(&ax->buflock);
271815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle				return;
272815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			}
2735793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			if (ax->crcmode != CRC_MODE_FLEX && ax->crcauto) {
2745793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				printk(KERN_INFO
2755793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				       "mkiss: %s: Switchting to crc-flexnet\n",
2765793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				       ax->dev->name);
2775793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				ax->crcmode = CRC_MODE_FLEX;
2785793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			}
279815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			ax->rcount -= 2;
2805793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle
2815793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			/*
2825793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			 * dl9sau bugfix: the trailling two bytes flexnet crc
2835793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			 * will not be passed to the kernel. thus we have to
2845793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			 * correct the kissparm signature, because it indicates
2855793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			 * a crc but there's none
286815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			 */
2875793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			*ax->rbuff &= ~0x20;
2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
289815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle 	}
290815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
291815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	count = ax->rcount;
292815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
293815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	if ((skb = dev_alloc_skb(count)) == NULL) {
294815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		printk(KERN_ERR "mkiss: %s: memory squeeze, dropping packet.\n",
295815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		       ax->dev->name);
296ddbe9a686805c36a0e68451ebb8cb51b21d0c718Stephen Hemminger		ax->dev->stats.rx_dropped++;
2979f30c768c00fd0f0a2ab37ef29d8c8c5a7abdf2eJarek Poplawski		spin_unlock_bh(&ax->buflock);
298815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		return;
2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
301815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	memcpy(skb_put(skb,count), ax->rbuff, count);
302815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	skb->protocol = ax25_type_trans(skb, ax->dev);
303815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	netif_rx(skb);
304ddbe9a686805c36a0e68451ebb8cb51b21d0c718Stephen Hemminger	ax->dev->stats.rx_packets++;
305ddbe9a686805c36a0e68451ebb8cb51b21d0c718Stephen Hemminger	ax->dev->stats.rx_bytes += count;
3069f30c768c00fd0f0a2ab37ef29d8c8c5a7abdf2eJarek Poplawski	spin_unlock_bh(&ax->buflock);
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
309815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechlestatic void kiss_unesc(struct mkiss *ax, unsigned char s)
3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
311815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	switch (s) {
312815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	case END:
313815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		/* drop keeptest bit = VSV */
314815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		if (test_bit(AXF_KEEPTEST, &ax->flags))
315815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			clear_bit(AXF_KEEPTEST, &ax->flags);
316815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
317815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		if (!test_and_clear_bit(AXF_ERROR, &ax->flags) && (ax->rcount > 2))
318815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			ax_bump(ax);
319815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
320815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		clear_bit(AXF_ESCAPE, &ax->flags);
321815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		ax->rcount = 0;
322815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		return;
323815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
324815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	case ESC:
325815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		set_bit(AXF_ESCAPE, &ax->flags);
326815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		return;
327815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	case ESC_ESC:
328815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		if (test_and_clear_bit(AXF_ESCAPE, &ax->flags))
329815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			s = ESC;
330815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		break;
331815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	case ESC_END:
332815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		if (test_and_clear_bit(AXF_ESCAPE, &ax->flags))
333815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			s = END;
334815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		break;
335815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	}
336815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
337815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	spin_lock_bh(&ax->buflock);
338815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	if (!test_bit(AXF_ERROR, &ax->flags)) {
339815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		if (ax->rcount < ax->buffsize) {
340815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			ax->rbuff[ax->rcount++] = s;
341815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			spin_unlock_bh(&ax->buflock);
342815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			return;
343815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		}
344815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
345ddbe9a686805c36a0e68451ebb8cb51b21d0c718Stephen Hemminger		ax->dev->stats.rx_over_errors++;
346815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		set_bit(AXF_ERROR, &ax->flags);
347815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	}
348815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	spin_unlock_bh(&ax->buflock);
349815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle}
350815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
351815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechlestatic int ax_set_mac_address(struct net_device *dev, void *addr)
352815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle{
353815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	struct sockaddr_ax25 *sa = addr;
354815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
355932ff279a43ab7257942cddff2595acd541cc49bHerbert Xu	netif_tx_lock_bh(dev);
356e308a5d806c852f56590ffdd3834d0df0cbed8d7David S. Miller	netif_addr_lock(dev);
357815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	memcpy(dev->dev_addr, &sa->sax25_call, AX25_ADDR_LEN);
358e308a5d806c852f56590ffdd3834d0df0cbed8d7David S. Miller	netif_addr_unlock(dev);
359932ff279a43ab7257942cddff2595acd541cc49bHerbert Xu	netif_tx_unlock_bh(dev);
360815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
361815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	return 0;
3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
364815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle/*---------------------------------------------------------------------------*/
365815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
366815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechlestatic void ax_changedmtu(struct mkiss *ax)
3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct net_device *dev = ax->dev;
3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned char *xbuff, *rbuff, *oxbuff, *orbuff;
3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int len;
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	len = dev->mtu * 2;
3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * allow for arrival of larger UDP packets, even if we say not to
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * also fixes a bug in which SunOS sends 512-byte packets even with
3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * an MSS of 128
3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (len < 576 * 2)
3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		len = 576 * 2;
3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	xbuff = kmalloc(len + 4, GFP_ATOMIC);
3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rbuff = kmalloc(len + 4, GFP_ATOMIC);
3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (xbuff == NULL || rbuff == NULL)  {
386815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		printk(KERN_ERR "mkiss: %s: unable to grow ax25 buffers, "
387815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		       "MTU change cancelled.\n",
3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       ax->dev->name);
3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev->mtu = ax->mtu;
390b4558ea93d66a43f7990d26f145fd4c54a01c9bfJesper Juhl		kfree(xbuff);
391b4558ea93d66a43f7990d26f145fd4c54a01c9bfJesper Juhl		kfree(rbuff);
3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_bh(&ax->buflock);
3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	oxbuff    = ax->xbuff;
3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ax->xbuff = xbuff;
3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	orbuff    = ax->rbuff;
4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ax->rbuff = rbuff;
4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ax->xleft) {
4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (ax->xleft <= len) {
4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			memcpy(ax->xbuff, ax->xhead, ax->xleft);
4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else  {
4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ax->xleft = 0;
407ddbe9a686805c36a0e68451ebb8cb51b21d0c718Stephen Hemminger			dev->stats.tx_dropped++;
4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ax->xhead = ax->xbuff;
4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ax->rcount) {
4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (ax->rcount <= len) {
4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			memcpy(ax->rbuff, orbuff, ax->rcount);
4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else  {
4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ax->rcount = 0;
418ddbe9a686805c36a0e68451ebb8cb51b21d0c718Stephen Hemminger			dev->stats.rx_over_errors++;
4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			set_bit(AXF_ERROR, &ax->flags);
4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ax->mtu      = dev->mtu + 73;
4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ax->buffsize = len;
4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_bh(&ax->buflock);
4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
428815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	kfree(oxbuff);
429815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	kfree(orbuff);
4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Encapsulate one AX.25 packet and stuff into a TTY queue. */
433815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechlestatic void ax_encaps(struct net_device *dev, unsigned char *icp, int len)
4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
435815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	struct mkiss *ax = netdev_priv(dev);
4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned char *p;
4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int actual, count;
4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ax->mtu != ax->dev->mtu + 73)	/* Someone has been ifconfigging */
4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ax_changedmtu(ax);
4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (len > ax->mtu) {		/* Sigh, shouldn't occur BUT ... */
4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		len = ax->mtu;
4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_ERR "mkiss: %s: truncating oversized transmit packet!\n", ax->dev->name);
445ddbe9a686805c36a0e68451ebb8cb51b21d0c718Stephen Hemminger		dev->stats.tx_dropped++;
446815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		netif_start_queue(dev);
4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	p = icp;
4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_bh(&ax->buflock);
4535793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle	if ((*p & 0x0f) != 0) {
4545793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		/* Configuration Command (kissparms(1).
4555793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		 * Protocol spec says: never append CRC.
4565793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		 * This fixes a very old bug in the linux
4575793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		 * kiss driver. -- dl9sau */
4585793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		switch (*p & 0xff) {
4595793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		case 0x85:
4605793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			/* command from userspace especially for us,
4615793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			 * not for delivery to the tnc */
4625793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			if (len > 1) {
4635793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				int cmd = (p[1] & 0xff);
4645793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				switch(cmd) {
4655793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				case 3:
4665793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				  ax->crcmode = CRC_MODE_SMACK;
4675793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				  break;
4685793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				case 2:
4695793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				  ax->crcmode = CRC_MODE_FLEX;
4705793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				  break;
4715793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				case 1:
4725793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				  ax->crcmode = CRC_MODE_NONE;
4735793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				  break;
4745793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				case 0:
4755793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				default:
4765793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				  ax->crcmode = CRC_MODE_SMACK_TEST;
4775793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				  cmd = 0;
4785793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				}
4795793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				ax->crcauto = (cmd ? 0 : 1);
4805793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				printk(KERN_INFO "mkiss: %s: crc mode %s %d\n", ax->dev->name, (len) ? "set to" : "is", cmd);
4815793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			}
4825793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			spin_unlock_bh(&ax->buflock);
4835793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			netif_start_queue(dev);
4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4855793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			return;
4865793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		default:
4875793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			count = kiss_esc(p, (unsigned char *)ax->xbuff, len);
4885793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		}
4895793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle	} else {
4905793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		unsigned short crc;
4915793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		switch (ax->crcmode) {
4925793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		case CRC_MODE_SMACK_TEST:
4935793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			ax->crcmode  = CRC_MODE_FLEX_TEST;
4945793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			printk(KERN_INFO "mkiss: %s: Trying crc-smack\n", ax->dev->name);
4955793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			// fall through
4965793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		case CRC_MODE_SMACK:
4975793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			*p |= 0x80;
4985793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			crc = swab16(crc16(0, p, len));
4995793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			count = kiss_esc_crc(p, (unsigned char *)ax->xbuff, crc, len+2);
5005793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			break;
5015793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		case CRC_MODE_FLEX_TEST:
5025793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			ax->crcmode = CRC_MODE_NONE;
5035793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			printk(KERN_INFO "mkiss: %s: Trying crc-flexnet\n", ax->dev->name);
5045793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			// fall through
5055793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		case CRC_MODE_FLEX:
5065793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			*p |= 0x20;
5075793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			crc = calc_crc_flex(p, len);
5085793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			count = kiss_esc_crc(p, (unsigned char *)ax->xbuff, crc, len+2);
5095793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			break;
5105793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle
5115793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		default:
5125793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			count = kiss_esc(p, (unsigned char *)ax->xbuff, len);
5135793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		}
5145793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle  	}
515c1854ebc7f13b23c3d6a6e641a1a1db1116ca998Ralf Baechle	spin_unlock_bh(&ax->buflock);
5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
517815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	set_bit(TTY_DO_WRITE_WAKEUP, &ax->tty->flags);
518f34d7a5b7010b82fe97da95496b9971435530062Alan Cox	actual = ax->tty->ops->write(ax->tty, ax->xbuff, count);
519ddbe9a686805c36a0e68451ebb8cb51b21d0c718Stephen Hemminger	dev->stats.tx_packets++;
520ddbe9a686805c36a0e68451ebb8cb51b21d0c718Stephen Hemminger	dev->stats.tx_bytes += actual;
521815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ax->dev->trans_start = jiffies;
5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ax->xleft = count - actual;
5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ax->xhead = ax->xbuff + actual;
5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Encapsulate an AX.25 packet and kick it into a TTY queue. */
5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ax_xmit(struct sk_buff *skb, struct net_device *dev)
5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
530815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	struct mkiss *ax = netdev_priv(dev);
5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!netif_running(dev))  {
5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_ERR "mkiss: %s: xmit call when iface is down\n", dev->name);
5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 1;
5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (netif_queue_stopped(dev)) {
5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * May be we must check transmitter timeout here ?
5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 *      14 Oct 1994 Dmitry Gorodchanin.
5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
542cd8749b4aa6b7502e234d72cb53c00a3bc27ed1bMarcelo Feitoza Parisi		if (time_before(jiffies, dev->trans_start + 20 * HZ)) {
5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* 20 sec timeout not reached */
5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return 1;
5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_ERR "mkiss: %s: transmit timed out, %s?\n", dev->name,
5485608784fdf417467cbb2ccfb1129500464416f79Eugene Teo		       (tty_chars_in_buffer(ax->tty) || ax->xleft) ?
5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       "bad line quality" : "driver error");
5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ax->xleft = 0;
552815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		clear_bit(TTY_DO_WRITE_WAKEUP, &ax->tty->flags);
553815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		netif_start_queue(dev);
5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* We were not busy, so we are now... :-) */
5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (skb != NULL) {
558815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		netif_stop_queue(dev);
559815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		ax_encaps(dev, skb->data, skb->len);
5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		kfree_skb(skb);
5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
566815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechlestatic int ax_open_dev(struct net_device *dev)
567815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle{
568815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	struct mkiss *ax = netdev_priv(dev);
569815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
570815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	if (ax->tty == NULL)
571815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		return -ENODEV;
572815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
573815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	return 0;
574815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle}
575815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Return the frame type ID */
5793b04ddde02cf1b6f14f2697da5c20eca5715017fStephen Hemmingerstatic int ax_header(struct sk_buff *skb, struct net_device *dev,
5803b04ddde02cf1b6f14f2697da5c20eca5715017fStephen Hemminger		     unsigned short type, const void *daddr,
5813b04ddde02cf1b6f14f2697da5c20eca5715017fStephen Hemminger		     const void *saddr, unsigned len)
5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_INET
584d9a19d200f00533b56fb109b6c538b6ea2961ab2Al Viro	if (type != ETH_P_AX25)
5856f74998e5c3b4610e6eba06babf16547369c512aRalf Baechle		return ax25_hard_header(skb, dev, type, daddr, saddr, len);
5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ax_rebuild_header(struct sk_buff *skb)
5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_INET
5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ax25_rebuild_header(skb);
5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else
5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif	/* CONFIG_{AX25,AX25_MODULE} */
6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Open the low-level part of the AX25 channel. Easy! */
6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ax_open(struct net_device *dev)
6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
605815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	struct mkiss *ax = netdev_priv(dev);
6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long len;
6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ax->tty == NULL)
6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ENODEV;
6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Allocate the frame buffers:
6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *
6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * rbuff	Receive buffer.
6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * xbuff	Transmit buffer.
6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	len = dev->mtu * 2;
6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * allow for arrival of larger UDP packets, even if we say not to
6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * also fixes a bug in which SunOS sends 512-byte packets even with
6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * an MSS of 128
6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (len < 576 * 2)
6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		len = 576 * 2;
6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((ax->rbuff = kmalloc(len + 4, GFP_KERNEL)) == NULL)
6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto norbuff;
6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((ax->xbuff = kmalloc(len + 4, GFP_KERNEL)) == NULL)
6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto noxbuff;
6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ax->mtu	     = dev->mtu + 73;
6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ax->buffsize = len;
6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ax->rcount   = 0;
6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ax->xleft    = 0;
6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ax->flags   &= (1 << AXF_INUSE);      /* Clear ESCAPE & ERROR flags */
6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_init(&ax->buflock);
6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsnoxbuff:
6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	kfree(ax->rbuff);
6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsnorbuff:
6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return -ENOMEM;
6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Close the low-level part of the AX25 channel. Easy! */
6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ax_close(struct net_device *dev)
6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
655815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	struct mkiss *ax = netdev_priv(dev);
6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
657815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	if (ax->tty)
658815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		clear_bit(TTY_DO_WRITE_WAKEUP, &ax->tty->flags);
6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	netif_stop_queue(dev);
6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6653b04ddde02cf1b6f14f2697da5c20eca5715017fStephen Hemmingerstatic const struct header_ops ax_header_ops = {
6663b04ddde02cf1b6f14f2697da5c20eca5715017fStephen Hemminger	.create    = ax_header,
6673b04ddde02cf1b6f14f2697da5c20eca5715017fStephen Hemminger	.rebuild   = ax_rebuild_header,
6683b04ddde02cf1b6f14f2697da5c20eca5715017fStephen Hemminger};
6693b04ddde02cf1b6f14f2697da5c20eca5715017fStephen Hemminger
670815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechlestatic void ax_setup(struct net_device *dev)
671815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle{
672815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	/* Finish setting up the DEVICE info. */
673815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	dev->mtu             = AX_MTU;
674815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	dev->hard_start_xmit = ax_xmit;
675815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	dev->open            = ax_open_dev;
676815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	dev->stop            = ax_close;
677815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	dev->set_mac_address = ax_set_mac_address;
678815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	dev->hard_header_len = 0;
679815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	dev->addr_len        = 0;
680815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	dev->type            = ARPHRD_AX25;
681815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	dev->tx_queue_len    = 10;
6823b04ddde02cf1b6f14f2697da5c20eca5715017fStephen Hemminger	dev->header_ops      = &ax_header_ops;
6833b04ddde02cf1b6f14f2697da5c20eca5715017fStephen Hemminger
684815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
68515b1c0e822f578306332d4f4c449250db5c5dcebRalf Baechle	memcpy(dev->broadcast, &ax25_bcast, AX25_ADDR_LEN);
68615b1c0e822f578306332d4f4c449250db5c5dcebRalf Baechle	memcpy(dev->dev_addr,  &ax25_defaddr,  AX25_ADDR_LEN);
687815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
688815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	dev->flags      = IFF_BROADCAST | IFF_MULTICAST;
6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
692815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle * We have a potential race on dereferencing tty->disc_data, because the tty
693815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle * layer provides no locking at all - thus one cpu could be running
694815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle * sixpack_receive_buf while another calls sixpack_close, which zeroes
695815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle * tty->disc_data and frees the memory that sixpack_receive_buf is using.  The
696815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle * best way to fix this is to use a rwlock in the tty struct, but for now we
697815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle * use a single global rwlock for all ttys in ppp line discipline.
6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
699d5919586265d36c6694a5d10ba589c02806873b6Ralf Baechlestatic DEFINE_RWLOCK(disc_data_lock);
700815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
701815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechlestatic struct mkiss *mkiss_get(struct tty_struct *tty)
7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
703815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	struct mkiss *ax;
7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
705815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	read_lock(&disc_data_lock);
706815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	ax = tty->disc_data;
707815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	if (ax)
708815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		atomic_inc(&ax->refcnt);
709815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	read_unlock(&disc_data_lock);
7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
711815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	return ax;
712815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle}
7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
714815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechlestatic void mkiss_put(struct mkiss *ax)
715815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle{
716815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	if (atomic_dec_and_test(&ax->refcnt))
717815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		up(&ax->dead_sem);
7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7205793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechlestatic int crc_force = 0;	/* Can be overridden with insmod */
7215793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle
722815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechlestatic int mkiss_open(struct tty_struct *tty)
7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
724815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	struct net_device *dev;
725815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	struct mkiss *ax;
7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int err;
7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
728815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	if (!capable(CAP_NET_ADMIN))
729815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		return -EPERM;
730f34d7a5b7010b82fe97da95496b9971435530062Alan Cox	if (tty->ops->write == NULL)
731f34d7a5b7010b82fe97da95496b9971435530062Alan Cox		return -EOPNOTSUPP;
7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
733815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	dev = alloc_netdev(sizeof(struct mkiss), "ax%d", ax_setup);
734815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	if (!dev) {
735815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		err = -ENOMEM;
736815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		goto out;
737815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	}
738815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
739815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	ax = netdev_priv(dev);
740815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	ax->dev = dev;
741815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
742815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	spin_lock_init(&ax->buflock);
743815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	atomic_set(&ax->refcnt, 1);
744815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	init_MUTEX_LOCKED(&ax->dead_sem);
7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ax->tty = tty;
7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tty->disc_data = ax;
74833f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox	tty->receive_room = 65535;
7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
750f34d7a5b7010b82fe97da95496b9971435530062Alan Cox	tty_driver_flush_buffer(tty);
7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Restore default settings */
753815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	dev->type = ARPHRD_AX25;
7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Perform the low-level AX25 initialization. */
756815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	if ((err = ax_open(ax->dev))) {
757815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		goto out_free_netdev;
758815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	}
7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
760815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	if (register_netdev(dev))
761815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		goto out_free_buffers;
7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7635793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle	/* after register_netdev() - because else printk smashes the kernel */
7645793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle	switch (crc_force) {
7655793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle	case 3:
7665793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		ax->crcmode  = CRC_MODE_SMACK;
7675793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		printk(KERN_INFO "mkiss: %s: crc mode smack forced.\n",
7685793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		       ax->dev->name);
7695793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		break;
7705793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle	case 2:
7715793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		ax->crcmode  = CRC_MODE_FLEX;
7725793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		printk(KERN_INFO "mkiss: %s: crc mode flexnet forced.\n",
7735793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		       ax->dev->name);
7745793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		break;
7755793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle	case 1:
7765793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		ax->crcmode  = CRC_MODE_NONE;
7775793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		printk(KERN_INFO "mkiss: %s: crc mode disabled.\n",
7785793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		       ax->dev->name);
7795793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		break;
7805793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle	case 0:
7815793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		/* fall through */
7825793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle	default:
7835793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		crc_force = 0;
7845793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		printk(KERN_INFO "mkiss: %s: crc mode is auto.\n",
7855793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		       ax->dev->name);
7865793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		ax->crcmode  = CRC_MODE_SMACK_TEST;
7875793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle	}
7885793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle	ax->crcauto = (crc_force ? 0 : 1);
7895793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle
790815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	netif_start_queue(dev);
7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
792815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	/* Done.  We have linked the TTY line to a channel. */
793815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	return 0;
7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
795815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechleout_free_buffers:
796815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	kfree(ax->rbuff);
797815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	kfree(ax->xbuff);
7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
799815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechleout_free_netdev:
800815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	free_netdev(dev);
8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
802815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechleout:
803815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	return err;
8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
806815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechlestatic void mkiss_close(struct tty_struct *tty)
8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
808815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	struct mkiss *ax;
8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
810815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	write_lock(&disc_data_lock);
811815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	ax = tty->disc_data;
812815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	tty->disc_data = NULL;
813815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	write_unlock(&disc_data_lock);
8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
81579ea13ce07c951bb4d95471e7300baa0f1be9e78Al Viro	if (!ax)
816815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		return;
8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
819815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	 * We have now ensured that nobody can start using ap from now on, but
820815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	 * we have to wait for all existing users to finish.
8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
822815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	if (!atomic_dec_and_test(&ax->refcnt))
823815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		down(&ax->dead_sem);
8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
825815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	unregister_netdev(ax->dev);
8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
827815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	/* Free all AX25 frame buffers. */
828815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	kfree(ax->rbuff);
829815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	kfree(ax->xbuff);
8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
831815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	ax->tty = NULL;
8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
834815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle/* Perform I/O control on an active ax25 channel. */
835815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechlestatic int mkiss_ioctl(struct tty_struct *tty, struct file *file,
836815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	unsigned int cmd, unsigned long arg)
8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
838815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	struct mkiss *ax = mkiss_get(tty);
839f40e0638237a2d3e2ce8bedf3af4b3c02cf6fff7Julia Lawall	struct net_device *dev;
840815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	unsigned int tmp, err;
8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
842815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	/* First make sure we're connected. */
843815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	if (ax == NULL)
844815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		return -ENXIO;
845f40e0638237a2d3e2ce8bedf3af4b3c02cf6fff7Julia Lawall	dev = ax->dev;
8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
847815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	switch (cmd) {
848815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle 	case SIOCGIFNAME:
849815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		err = copy_to_user((void __user *) arg, ax->dev->name,
850815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		                   strlen(ax->dev->name) + 1) ? -EFAULT : 0;
851815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		break;
852815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
853815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	case SIOCGIFENCAP:
854815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		err = put_user(4, (int __user *) arg);
855815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		break;
856815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
857815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	case SIOCSIFENCAP:
858815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		if (get_user(tmp, (int __user *) arg)) {
859815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			err = -EFAULT;
860815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			break;
8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
863815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		ax->mode = tmp;
864815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		dev->addr_len        = AX25_ADDR_LEN;
865815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		dev->hard_header_len = AX25_KISS_HEADER_LEN +
866815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		                       AX25_MAX_HEADER_LEN + 3;
867815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		dev->type            = ARPHRD_AX25;
8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
869815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		err = 0;
870815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		break;
8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
872815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	case SIOCSIFHWADDR: {
873815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		char addr[AX25_ADDR_LEN];
8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
875815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		if (copy_from_user(&addr,
876815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		                   (void __user *) arg, AX25_ADDR_LEN)) {
877815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			err = -EFAULT;
8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
881932ff279a43ab7257942cddff2595acd541cc49bHerbert Xu		netif_tx_lock_bh(dev);
882815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		memcpy(dev->dev_addr, addr, AX25_ADDR_LEN);
883932ff279a43ab7257942cddff2595acd541cc49bHerbert Xu		netif_tx_unlock_bh(dev);
884815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
885815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		err = 0;
886815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		break;
887815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	}
888815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	default:
889815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		err = -ENOIOCTLCMD;
8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
892815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	mkiss_put(ax);
8931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
894815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	return err;
8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
897815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle/*
898815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle * Handle the 'receiver data ready' interrupt.
899815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle * This function is called by the 'tty_io' module in the kernel when
900815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle * a block of data has been received, which can now be decapsulated
901815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle * and sent on to the AX.25 layer for further processing.
902815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle */
903815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechlestatic void mkiss_receive_buf(struct tty_struct *tty, const unsigned char *cp,
904815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	char *fp, int count)
9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
906815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	struct mkiss *ax = mkiss_get(tty);
9071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
908815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	if (!ax)
909815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		return;
9101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
911815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	/*
912815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	 * Argh! mtu change time! - costs us the packet part received
913815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	 * at the change
914815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	 */
915815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	if (ax->mtu != ax->dev->mtu + 73)
916815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		ax_changedmtu(ax);
9171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
918815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	/* Read the characters out of the buffer */
919815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	while (count--) {
920815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		if (fp != NULL && *fp++) {
921815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			if (!test_and_set_bit(AXF_ERROR, &ax->flags))
922ddbe9a686805c36a0e68451ebb8cb51b21d0c718Stephen Hemminger				ax->dev->stats.rx_errors++;
923815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			cp++;
924815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			continue;
925815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		}
9261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
927815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		kiss_unesc(ax, *cp++);
9281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
929815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
930815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	mkiss_put(ax);
93139c2e60f8c584c1b29b5c4375dd49df7995386bbAlan Cox	tty_unthrottle(tty);
9321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
934815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle/*
935815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle * Called by the driver when there's room for more data.  If we have
936815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle * more packets to send, we send them here.
937815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle */
938815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechlestatic void mkiss_write_wakeup(struct tty_struct *tty)
9391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
940815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	struct mkiss *ax = mkiss_get(tty);
941815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	int actual;
9421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
943815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	if (!ax)
944815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		return;
9451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
946815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	if (ax->xleft <= 0)  {
947815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		/* Now serial buffer is almost free & we can start
948815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		 * transmission of another packet
949815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		 */
950815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
9511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
952815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		netif_wake_queue(ax->dev);
953815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		goto out;
954815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	}
9551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
956f34d7a5b7010b82fe97da95496b9971435530062Alan Cox	actual = tty->ops->write(tty, ax->xhead, ax->xleft);
957815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	ax->xleft -= actual;
958815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	ax->xhead += actual;
9591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
960815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechleout:
961815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	mkiss_put(ax);
9621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
964a352def21a642133758b868c71bee12ab34ad5c5Alan Coxstatic struct tty_ldisc_ops ax_ldisc = {
96574cfe03f80adc320bde4dd37616354aefe2271aaRalf Baechle	.owner		= THIS_MODULE,
966815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	.magic		= TTY_LDISC_MAGIC,
967815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	.name		= "mkiss",
968815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	.open		= mkiss_open,
969815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	.close		= mkiss_close,
970815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	.ioctl		= mkiss_ioctl,
971815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	.receive_buf	= mkiss_receive_buf,
972815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	.write_wakeup	= mkiss_write_wakeup
973815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle};
9741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
975815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechlestatic char banner[] __initdata = KERN_INFO \
976815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	"mkiss: AX.25 Multikiss, Hans Albas PE1AYX\n";
977815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechlestatic char msg_regfail[] __initdata = KERN_ERR \
978815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	"mkiss: can't register line discipline (err = %d)\n";
9791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init mkiss_init_driver(void)
9811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int status;
9831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk(banner);
9851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
986815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	if ((status = tty_register_ldisc(N_AX25, &ax_ldisc)) != 0)
987815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		printk(msg_regfail);
9881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return status;
9901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
992815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechlestatic const char msg_unregfail[] __exitdata = KERN_ERR \
993815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	"mkiss: can't unregister line discipline (err = %d)\n";
994815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
9951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit mkiss_exit_driver(void)
9961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
997815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	int ret;
9981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
999815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	if ((ret = tty_unregister_ldisc(N_AX25)))
1000815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		printk(msg_unregfail, ret);
10011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1003815f62bf742718458ba822a7e1f51f285eb997f2Ralf BaechleMODULE_AUTHOR("Ralf Baechle DL5RB <ralf@linux-mips.org>");
10041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("KISS driver for AX.25 over TTYs");
10058d3b33f67fdc0fb364a1ef6d8fbbea7c2e4e6c98Rusty Russellmodule_param(crc_force, int, 0);
10065793f4be23f0171b4999ca68a39a9157b44139f3Ralf BaechleMODULE_PARM_DESC(crc_force, "crc [0 = auto | 1 = none | 2 = flexnet | 3 = smack]");
10071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL");
10081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_ALIAS_LDISC(N_AX25);
1009815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
10101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(mkiss_init_driver);
10111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(mkiss_exit_driver);
1012