mkiss.c revision 55db4c64eddf37e31279ec15fe90314713bc9cfa
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>
295a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.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>
409646e7ce3d1955478aa0573b36c151ab4b649486Arnd Bergmann#include <linux/compat.h>
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <net/ax25.h>
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
44815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle#define AX_MTU		236
45815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
46815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle/* SLIP/KISS protocol characters. */
47815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle#define END             0300		/* indicates end of frame	*/
48815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle#define ESC             0333		/* indicates byte stuffing	*/
49815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle#define ESC_END         0334		/* ESC ESC_END means END 'data'	*/
50815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle#define ESC_ESC         0335		/* ESC ESC_ESC means ESC 'data'	*/
51815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
52815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechlestruct mkiss {
53815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	struct tty_struct	*tty;	/* ptr to TTY structure		*/
54815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	struct net_device	*dev;	/* easy for intr handling	*/
55815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
56815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	/* These are pointers to the malloc()ed frame buffers. */
57815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	spinlock_t		buflock;/* lock for rbuf and xbuf */
58815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	unsigned char		*rbuff;	/* receiver buffer		*/
59815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	int			rcount;	/* received chars counter       */
60815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	unsigned char		*xbuff;	/* transmitter buffer		*/
61815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	unsigned char		*xhead;	/* pointer to next byte to XMIT */
62815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	int			xleft;	/* bytes left in XMIT queue     */
63815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
64815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	/* Detailed SLIP statistics. */
65815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	int		mtu;		/* Our mtu (to spot changes!)   */
66815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	int		buffsize;	/* Max buffers sizes            */
67815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
68815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	unsigned long	flags;		/* Flag values/ mode etc	*/
69815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle					/* long req'd: used by set_bit --RR */
70815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle#define AXF_INUSE	0		/* Channel in use               */
71815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle#define AXF_ESCAPE	1               /* ESC received                 */
72815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle#define AXF_ERROR	2               /* Parity, etc. error           */
73815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle#define AXF_KEEPTEST	3		/* Keepalive test flag		*/
74815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle#define AXF_OUTWAIT	4		/* is outpacket was flag	*/
75815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
76815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	int		mode;
77815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle        int		crcmode;	/* MW: for FlexNet, SMACK etc.  */
785793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle	int		crcauto;	/* CRC auto mode */
795793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle
805793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle#define CRC_MODE_NONE		0
815793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle#define CRC_MODE_FLEX		1
825793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle#define CRC_MODE_SMACK		2
835793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle#define CRC_MODE_FLEX_TEST	3
845793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle#define CRC_MODE_SMACK_TEST	4
85815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
86815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	atomic_t		refcnt;
87815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	struct semaphore	dead_sem;
88815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle};
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*---------------------------------------------------------------------------*/
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
92815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechlestatic const unsigned short crc_flex_table[] = {
93815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0x0f87, 0x1e0e, 0x2c95, 0x3d1c, 0x49a3, 0x582a, 0x6ab1, 0x7b38,
94815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0x83cf, 0x9246, 0xa0dd, 0xb154, 0xc5eb, 0xd462, 0xe6f9, 0xf770,
95815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0x1f06, 0x0e8f, 0x3c14, 0x2d9d, 0x5922, 0x48ab, 0x7a30, 0x6bb9,
96815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0x934e, 0x82c7, 0xb05c, 0xa1d5, 0xd56a, 0xc4e3, 0xf678, 0xe7f1,
97815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0x2e85, 0x3f0c, 0x0d97, 0x1c1e, 0x68a1, 0x7928, 0x4bb3, 0x5a3a,
98815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0xa2cd, 0xb344, 0x81df, 0x9056, 0xe4e9, 0xf560, 0xc7fb, 0xd672,
99815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0x3e04, 0x2f8d, 0x1d16, 0x0c9f, 0x7820, 0x69a9, 0x5b32, 0x4abb,
100815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0xb24c, 0xa3c5, 0x915e, 0x80d7, 0xf468, 0xe5e1, 0xd77a, 0xc6f3,
101815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0x4d83, 0x5c0a, 0x6e91, 0x7f18, 0x0ba7, 0x1a2e, 0x28b5, 0x393c,
102815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0xc1cb, 0xd042, 0xe2d9, 0xf350, 0x87ef, 0x9666, 0xa4fd, 0xb574,
103815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0x5d02, 0x4c8b, 0x7e10, 0x6f99, 0x1b26, 0x0aaf, 0x3834, 0x29bd,
104815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0xd14a, 0xc0c3, 0xf258, 0xe3d1, 0x976e, 0x86e7, 0xb47c, 0xa5f5,
105815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0x6c81, 0x7d08, 0x4f93, 0x5e1a, 0x2aa5, 0x3b2c, 0x09b7, 0x183e,
106815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0xe0c9, 0xf140, 0xc3db, 0xd252, 0xa6ed, 0xb764, 0x85ff, 0x9476,
107815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0x7c00, 0x6d89, 0x5f12, 0x4e9b, 0x3a24, 0x2bad, 0x1936, 0x08bf,
108815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0xf048, 0xe1c1, 0xd35a, 0xc2d3, 0xb66c, 0xa7e5, 0x957e, 0x84f7,
109815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0x8b8f, 0x9a06, 0xa89d, 0xb914, 0xcdab, 0xdc22, 0xeeb9, 0xff30,
110815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0x07c7, 0x164e, 0x24d5, 0x355c, 0x41e3, 0x506a, 0x62f1, 0x7378,
111815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0x9b0e, 0x8a87, 0xb81c, 0xa995, 0xdd2a, 0xcca3, 0xfe38, 0xefb1,
112815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0x1746, 0x06cf, 0x3454, 0x25dd, 0x5162, 0x40eb, 0x7270, 0x63f9,
113815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0xaa8d, 0xbb04, 0x899f, 0x9816, 0xeca9, 0xfd20, 0xcfbb, 0xde32,
114815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0x26c5, 0x374c, 0x05d7, 0x145e, 0x60e1, 0x7168, 0x43f3, 0x527a,
115815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0xba0c, 0xab85, 0x991e, 0x8897, 0xfc28, 0xeda1, 0xdf3a, 0xceb3,
116815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0x3644, 0x27cd, 0x1556, 0x04df, 0x7060, 0x61e9, 0x5372, 0x42fb,
117815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0xc98b, 0xd802, 0xea99, 0xfb10, 0x8faf, 0x9e26, 0xacbd, 0xbd34,
118815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0x45c3, 0x544a, 0x66d1, 0x7758, 0x03e7, 0x126e, 0x20f5, 0x317c,
119815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0xd90a, 0xc883, 0xfa18, 0xeb91, 0x9f2e, 0x8ea7, 0xbc3c, 0xadb5,
120815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0x5542, 0x44cb, 0x7650, 0x67d9, 0x1366, 0x02ef, 0x3074, 0x21fd,
121815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0xe889, 0xf900, 0xcb9b, 0xda12, 0xaead, 0xbf24, 0x8dbf, 0x9c36,
122815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0x64c1, 0x7548, 0x47d3, 0x565a, 0x22e5, 0x336c, 0x01f7, 0x107e,
123815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0xf808, 0xe981, 0xdb1a, 0xca93, 0xbe2c, 0xafa5, 0x9d3e, 0x8cb7,
124815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	0x7440, 0x65c9, 0x5752, 0x46db, 0x3264, 0x23ed, 0x1176, 0x00ff
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned short calc_crc_flex(unsigned char *cp, int size)
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
129815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	unsigned short crc = 0xffff;
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
131815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	while (size--)
132815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		crc = (crc << 8) ^ crc_flex_table[((crc >> 8) ^ *cp++) & 0xff];
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
134815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	return crc;
135815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle}
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int check_crc_flex(unsigned char *cp, int size)
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
139815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	unsigned short crc = 0xffff;
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
141815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	if (size < 3)
142815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		return -1;
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
144815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	while (size--)
145815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		crc = (crc << 8) ^ crc_flex_table[((crc >> 8) ^ *cp++) & 0xff];
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
147815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	if ((crc & 0xffff) != 0x7070)
148815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		return -1;
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
150815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	return 0;
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1535793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechlestatic int check_crc_16(unsigned char *cp, int size)
1545793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle{
1555793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle	unsigned short crc = 0x0000;
1565793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle
1575793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle	if (size < 3)
1585793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		return -1;
1595793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle
1605793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle	crc = crc16(0, cp, size);
1615793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle
1625793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle	if (crc != 0x0000)
1635793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		return -1;
1645793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle
1655793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle	return 0;
1665793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle}
1675793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle
168815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle/*
169815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle * Standard encapsulation
170815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle */
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
172815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechlestatic int kiss_esc(unsigned char *s, unsigned char *d, int len)
1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
174815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	unsigned char *ptr = d;
175815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	unsigned char c;
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
177815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	/*
178815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	 * Send an initial END character to flush out any data that may have
179815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	 * accumulated in the receiver due to line noise.
180815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	 */
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
182815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	*ptr++ = END;
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
184815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	while (len-- > 0) {
185815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		switch (c = *s++) {
186815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		case END:
187815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			*ptr++ = ESC;
188815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			*ptr++ = ESC_END;
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
190815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		case ESC:
191815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			*ptr++ = ESC;
192815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			*ptr++ = ESC_ESC;
193815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			break;
194815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		default:
195815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			*ptr++ = c;
196815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			break;
197815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		}
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
200815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	*ptr++ = END;
201815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
202815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	return ptr - d;
203815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle}
204815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
205815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle/*
206815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle * MW:
207815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle * OK its ugly, but tell me a better solution without copying the
208815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle * packet to a temporary buffer :-)
209815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle */
210815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechlestatic int kiss_esc_crc(unsigned char *s, unsigned char *d, unsigned short crc,
211815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	int len)
212815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle{
213815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	unsigned char *ptr = d;
214815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	unsigned char c=0;
215815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
216815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	*ptr++ = END;
217815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	while (len > 0) {
218815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		if (len > 2)
219815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			c = *s++;
220815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		else if (len > 1)
221815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			c = crc >> 8;
222815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		else if (len > 0)
223815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			c = crc & 0xff;
224815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
225815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		len--;
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
227815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		switch (c) {
228815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		case END:
229815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			*ptr++ = ESC;
230815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			*ptr++ = ESC_END;
231815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			break;
232815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		case ESC:
233815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			*ptr++ = ESC;
234815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			*ptr++ = ESC_ESC;
235815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			break;
236815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		default:
237815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			*ptr++ = c;
238815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			break;
239815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		}
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
241815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	*ptr++ = END;
242815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
243815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	return ptr - d;
244815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle}
245815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
246815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle/* Send one completely decapsulated AX.25 packet to the AX.25 layer. */
247815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechlestatic void ax_bump(struct mkiss *ax)
248815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle{
249815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	struct sk_buff *skb;
250815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	int count;
251815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
252815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	spin_lock_bh(&ax->buflock);
253815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	if (ax->rbuff[0] > 0x0f) {
2545793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		if (ax->rbuff[0] & 0x80) {
2555793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			if (check_crc_16(ax->rbuff, ax->rcount) < 0) {
256ddbe9a686805c36a0e68451ebb8cb51b21d0c718Stephen Hemminger				ax->dev->stats.rx_errors++;
2575793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				spin_unlock_bh(&ax->buflock);
2585793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle
2595793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				return;
2605793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			}
2615793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			if (ax->crcmode != CRC_MODE_SMACK && ax->crcauto) {
2625793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				printk(KERN_INFO
2637b1401cf5cc4b72e1273a5d7e7566a58e7fba001Ralf Baechle				       "mkiss: %s: Switching to crc-smack\n",
2645793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				       ax->dev->name);
2655793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				ax->crcmode = CRC_MODE_SMACK;
2665793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			}
2675793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			ax->rcount -= 2;
2685793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			*ax->rbuff &= ~0x80;
2695793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		} else if (ax->rbuff[0] & 0x20)  {
270815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			if (check_crc_flex(ax->rbuff, ax->rcount) < 0) {
271ddbe9a686805c36a0e68451ebb8cb51b21d0c718Stephen Hemminger				ax->dev->stats.rx_errors++;
2725793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				spin_unlock_bh(&ax->buflock);
273815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle				return;
274815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			}
2755793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			if (ax->crcmode != CRC_MODE_FLEX && ax->crcauto) {
2765793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				printk(KERN_INFO
2777b1401cf5cc4b72e1273a5d7e7566a58e7fba001Ralf Baechle				       "mkiss: %s: Switching to crc-flexnet\n",
2785793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				       ax->dev->name);
2795793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				ax->crcmode = CRC_MODE_FLEX;
2805793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			}
281815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			ax->rcount -= 2;
2825793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle
2835793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			/*
2845793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			 * dl9sau bugfix: the trailling two bytes flexnet crc
2855793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			 * will not be passed to the kernel. thus we have to
2865793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			 * correct the kissparm signature, because it indicates
2875793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			 * a crc but there's none
288815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			 */
2895793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			*ax->rbuff &= ~0x20;
2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
291815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle 	}
292815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
293815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	count = ax->rcount;
294815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
295815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	if ((skb = dev_alloc_skb(count)) == NULL) {
296815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		printk(KERN_ERR "mkiss: %s: memory squeeze, dropping packet.\n",
297815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		       ax->dev->name);
298ddbe9a686805c36a0e68451ebb8cb51b21d0c718Stephen Hemminger		ax->dev->stats.rx_dropped++;
2999f30c768c00fd0f0a2ab37ef29d8c8c5a7abdf2eJarek Poplawski		spin_unlock_bh(&ax->buflock);
300815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		return;
3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
303815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	memcpy(skb_put(skb,count), ax->rbuff, count);
304815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	skb->protocol = ax25_type_trans(skb, ax->dev);
305815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	netif_rx(skb);
306ddbe9a686805c36a0e68451ebb8cb51b21d0c718Stephen Hemminger	ax->dev->stats.rx_packets++;
307ddbe9a686805c36a0e68451ebb8cb51b21d0c718Stephen Hemminger	ax->dev->stats.rx_bytes += count;
3089f30c768c00fd0f0a2ab37ef29d8c8c5a7abdf2eJarek Poplawski	spin_unlock_bh(&ax->buflock);
3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
311815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechlestatic void kiss_unesc(struct mkiss *ax, unsigned char s)
3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
313815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	switch (s) {
314815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	case END:
315815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		/* drop keeptest bit = VSV */
316815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		if (test_bit(AXF_KEEPTEST, &ax->flags))
317815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			clear_bit(AXF_KEEPTEST, &ax->flags);
318815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
319815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		if (!test_and_clear_bit(AXF_ERROR, &ax->flags) && (ax->rcount > 2))
320815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			ax_bump(ax);
321815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
322815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		clear_bit(AXF_ESCAPE, &ax->flags);
323815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		ax->rcount = 0;
324815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		return;
325815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
326815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	case ESC:
327815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		set_bit(AXF_ESCAPE, &ax->flags);
328815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		return;
329815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	case ESC_ESC:
330815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		if (test_and_clear_bit(AXF_ESCAPE, &ax->flags))
331815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			s = ESC;
332815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		break;
333815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	case ESC_END:
334815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		if (test_and_clear_bit(AXF_ESCAPE, &ax->flags))
335815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			s = END;
336815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		break;
337815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	}
338815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
339815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	spin_lock_bh(&ax->buflock);
340815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	if (!test_bit(AXF_ERROR, &ax->flags)) {
341815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		if (ax->rcount < ax->buffsize) {
342815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			ax->rbuff[ax->rcount++] = s;
343815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			spin_unlock_bh(&ax->buflock);
344815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			return;
345815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		}
346815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
347ddbe9a686805c36a0e68451ebb8cb51b21d0c718Stephen Hemminger		ax->dev->stats.rx_over_errors++;
348815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		set_bit(AXF_ERROR, &ax->flags);
349815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	}
350815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	spin_unlock_bh(&ax->buflock);
351815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle}
352815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
353815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechlestatic int ax_set_mac_address(struct net_device *dev, void *addr)
354815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle{
355815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	struct sockaddr_ax25 *sa = addr;
356815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
357932ff279a43ab7257942cddff2595acd541cc49bHerbert Xu	netif_tx_lock_bh(dev);
358e308a5d806c852f56590ffdd3834d0df0cbed8d7David S. Miller	netif_addr_lock(dev);
359815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	memcpy(dev->dev_addr, &sa->sax25_call, AX25_ADDR_LEN);
360e308a5d806c852f56590ffdd3834d0df0cbed8d7David S. Miller	netif_addr_unlock(dev);
361932ff279a43ab7257942cddff2595acd541cc49bHerbert Xu	netif_tx_unlock_bh(dev);
362815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
363815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	return 0;
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
366815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle/*---------------------------------------------------------------------------*/
367815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
368815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechlestatic void ax_changedmtu(struct mkiss *ax)
3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct net_device *dev = ax->dev;
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned char *xbuff, *rbuff, *oxbuff, *orbuff;
3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int len;
3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	len = dev->mtu * 2;
3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * allow for arrival of larger UDP packets, even if we say not to
3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * also fixes a bug in which SunOS sends 512-byte packets even with
3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * an MSS of 128
3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (len < 576 * 2)
3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		len = 576 * 2;
3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	xbuff = kmalloc(len + 4, GFP_ATOMIC);
3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rbuff = kmalloc(len + 4, GFP_ATOMIC);
3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (xbuff == NULL || rbuff == NULL)  {
388815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		printk(KERN_ERR "mkiss: %s: unable to grow ax25 buffers, "
389815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		       "MTU change cancelled.\n",
3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       ax->dev->name);
3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev->mtu = ax->mtu;
392b4558ea93d66a43f7990d26f145fd4c54a01c9bfJesper Juhl		kfree(xbuff);
393b4558ea93d66a43f7990d26f145fd4c54a01c9bfJesper Juhl		kfree(rbuff);
3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_bh(&ax->buflock);
3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	oxbuff    = ax->xbuff;
4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ax->xbuff = xbuff;
4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	orbuff    = ax->rbuff;
4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ax->rbuff = rbuff;
4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ax->xleft) {
4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (ax->xleft <= len) {
4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			memcpy(ax->xbuff, ax->xhead, ax->xleft);
4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else  {
4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ax->xleft = 0;
409ddbe9a686805c36a0e68451ebb8cb51b21d0c718Stephen Hemminger			dev->stats.tx_dropped++;
4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ax->xhead = ax->xbuff;
4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ax->rcount) {
4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (ax->rcount <= len) {
4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			memcpy(ax->rbuff, orbuff, ax->rcount);
4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else  {
4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ax->rcount = 0;
420ddbe9a686805c36a0e68451ebb8cb51b21d0c718Stephen Hemminger			dev->stats.rx_over_errors++;
4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			set_bit(AXF_ERROR, &ax->flags);
4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ax->mtu      = dev->mtu + 73;
4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ax->buffsize = len;
4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_bh(&ax->buflock);
4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
430815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	kfree(oxbuff);
431815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	kfree(orbuff);
4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Encapsulate one AX.25 packet and stuff into a TTY queue. */
435815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechlestatic void ax_encaps(struct net_device *dev, unsigned char *icp, int len)
4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
437815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	struct mkiss *ax = netdev_priv(dev);
4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned char *p;
4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int actual, count;
4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ax->mtu != ax->dev->mtu + 73)	/* Someone has been ifconfigging */
4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ax_changedmtu(ax);
4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (len > ax->mtu) {		/* Sigh, shouldn't occur BUT ... */
4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		len = ax->mtu;
4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_ERR "mkiss: %s: truncating oversized transmit packet!\n", ax->dev->name);
447ddbe9a686805c36a0e68451ebb8cb51b21d0c718Stephen Hemminger		dev->stats.tx_dropped++;
448815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		netif_start_queue(dev);
4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	p = icp;
4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_bh(&ax->buflock);
4555793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle	if ((*p & 0x0f) != 0) {
4565793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		/* Configuration Command (kissparms(1).
4575793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		 * Protocol spec says: never append CRC.
4585793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		 * This fixes a very old bug in the linux
4595793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		 * kiss driver. -- dl9sau */
4605793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		switch (*p & 0xff) {
4615793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		case 0x85:
4625793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			/* command from userspace especially for us,
4635793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			 * not for delivery to the tnc */
4645793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			if (len > 1) {
4655793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				int cmd = (p[1] & 0xff);
4665793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				switch(cmd) {
4675793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				case 3:
4685793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				  ax->crcmode = CRC_MODE_SMACK;
4695793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				  break;
4705793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				case 2:
4715793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				  ax->crcmode = CRC_MODE_FLEX;
4725793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				  break;
4735793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				case 1:
4745793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				  ax->crcmode = CRC_MODE_NONE;
4755793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				  break;
4765793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				case 0:
4775793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				default:
4785793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				  ax->crcmode = CRC_MODE_SMACK_TEST;
4795793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				  cmd = 0;
4805793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				}
4815793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				ax->crcauto = (cmd ? 0 : 1);
4825793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle				printk(KERN_INFO "mkiss: %s: crc mode %s %d\n", ax->dev->name, (len) ? "set to" : "is", cmd);
4835793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			}
4845793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			spin_unlock_bh(&ax->buflock);
4855793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			netif_start_queue(dev);
4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4875793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			return;
4885793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		default:
4895793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			count = kiss_esc(p, (unsigned char *)ax->xbuff, len);
4905793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		}
4915793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle	} else {
4925793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		unsigned short crc;
4935793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		switch (ax->crcmode) {
4945793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		case CRC_MODE_SMACK_TEST:
4955793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			ax->crcmode  = CRC_MODE_FLEX_TEST;
4965793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			printk(KERN_INFO "mkiss: %s: Trying crc-smack\n", ax->dev->name);
4975793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			// fall through
4985793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		case CRC_MODE_SMACK:
4995793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			*p |= 0x80;
5005793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			crc = swab16(crc16(0, p, len));
5015793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			count = kiss_esc_crc(p, (unsigned char *)ax->xbuff, crc, len+2);
5025793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			break;
5035793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		case CRC_MODE_FLEX_TEST:
5045793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			ax->crcmode = CRC_MODE_NONE;
5055793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			printk(KERN_INFO "mkiss: %s: Trying crc-flexnet\n", ax->dev->name);
5065793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			// fall through
5075793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		case CRC_MODE_FLEX:
5085793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			*p |= 0x20;
5095793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			crc = calc_crc_flex(p, len);
5105793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			count = kiss_esc_crc(p, (unsigned char *)ax->xbuff, crc, len+2);
5115793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			break;
5125793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle
5135793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		default:
5145793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle			count = kiss_esc(p, (unsigned char *)ax->xbuff, len);
5155793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		}
5165793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle  	}
517c1854ebc7f13b23c3d6a6e641a1a1db1116ca998Ralf Baechle	spin_unlock_bh(&ax->buflock);
5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
519815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	set_bit(TTY_DO_WRITE_WAKEUP, &ax->tty->flags);
520f34d7a5b7010b82fe97da95496b9971435530062Alan Cox	actual = ax->tty->ops->write(ax->tty, ax->xbuff, count);
521ddbe9a686805c36a0e68451ebb8cb51b21d0c718Stephen Hemminger	dev->stats.tx_packets++;
522ddbe9a686805c36a0e68451ebb8cb51b21d0c718Stephen Hemminger	dev->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. */
53036e4d64a82d9a91a73a2b9b32117aedfe2211fb3Stephen Hemmingerstatic netdev_tx_t 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);
5365b548140225c6bbbbd560551dd1048b2c0ce58bePatrick McHardy		return NETDEV_TX_BUSY;
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 */
5465b548140225c6bbbbd560551dd1048b2c0ce58bePatrick McHardy			return NETDEV_TX_BUSY;
5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_ERR "mkiss: %s: transmit timed out, %s?\n", dev->name,
5505608784fdf417467cbb2ccfb1129500464416f79Eugene Teo		       (tty_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
5656ed106549d17474ca17a16057f4c0ed4eba5a7caPatrick McHardy	return NETDEV_TX_OK;
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 */
5813b04ddde02cf1b6f14f2697da5c20eca5715017fStephen Hemmingerstatic int ax_header(struct sk_buff *skb, struct net_device *dev,
5823b04ddde02cf1b6f14f2697da5c20eca5715017fStephen Hemminger		     unsigned short type, const void *daddr,
5833b04ddde02cf1b6f14f2697da5c20eca5715017fStephen Hemminger		     const void *saddr, unsigned len)
5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_INET
586d9a19d200f00533b56fb109b6c538b6ea2961ab2Al Viro	if (type != ETH_P_AX25)
5876f74998e5c3b4610e6eba06babf16547369c512aRalf Baechle		return ax25_hard_header(skb, dev, type, daddr, saddr, len);
5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ax_rebuild_header(struct sk_buff *skb)
5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_INET
5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ax25_rebuild_header(skb);
5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else
5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif	/* CONFIG_{AX25,AX25_MODULE} */
6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Open the low-level part of the AX25 channel. Easy! */
6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ax_open(struct net_device *dev)
6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
607815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	struct mkiss *ax = netdev_priv(dev);
6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long len;
6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ax->tty == NULL)
6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ENODEV;
6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Allocate the frame buffers:
6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *
6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * rbuff	Receive buffer.
6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * xbuff	Transmit buffer.
6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	len = dev->mtu * 2;
6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * allow for arrival of larger UDP packets, even if we say not to
6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * also fixes a bug in which SunOS sends 512-byte packets even with
6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * an MSS of 128
6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (len < 576 * 2)
6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		len = 576 * 2;
6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((ax->rbuff = kmalloc(len + 4, GFP_KERNEL)) == NULL)
6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto norbuff;
6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((ax->xbuff = kmalloc(len + 4, GFP_KERNEL)) == NULL)
6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto noxbuff;
6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ax->mtu	     = dev->mtu + 73;
6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ax->buffsize = len;
6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ax->rcount   = 0;
6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ax->xleft    = 0;
6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ax->flags   &= (1 << AXF_INUSE);      /* Clear ESCAPE & ERROR flags */
6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_init(&ax->buflock);
6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsnoxbuff:
6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	kfree(ax->rbuff);
6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsnorbuff:
6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return -ENOMEM;
6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Close the low-level part of the AX25 channel. Easy! */
6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ax_close(struct net_device *dev)
6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
657815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	struct mkiss *ax = netdev_priv(dev);
6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
659815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	if (ax->tty)
660815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		clear_bit(TTY_DO_WRITE_WAKEUP, &ax->tty->flags);
6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	netif_stop_queue(dev);
6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6673b04ddde02cf1b6f14f2697da5c20eca5715017fStephen Hemmingerstatic const struct header_ops ax_header_ops = {
6683b04ddde02cf1b6f14f2697da5c20eca5715017fStephen Hemminger	.create    = ax_header,
6693b04ddde02cf1b6f14f2697da5c20eca5715017fStephen Hemminger	.rebuild   = ax_rebuild_header,
6703b04ddde02cf1b6f14f2697da5c20eca5715017fStephen Hemminger};
6713b04ddde02cf1b6f14f2697da5c20eca5715017fStephen Hemminger
6726095e08126790592699d8aeef4d31b263a4176a4Stephen Hemmingerstatic const struct net_device_ops ax_netdev_ops = {
6736095e08126790592699d8aeef4d31b263a4176a4Stephen Hemminger	.ndo_open            = ax_open_dev,
6746095e08126790592699d8aeef4d31b263a4176a4Stephen Hemminger	.ndo_stop            = ax_close,
6756095e08126790592699d8aeef4d31b263a4176a4Stephen Hemminger	.ndo_start_xmit	     = ax_xmit,
6766095e08126790592699d8aeef4d31b263a4176a4Stephen Hemminger	.ndo_set_mac_address = ax_set_mac_address,
6776095e08126790592699d8aeef4d31b263a4176a4Stephen Hemminger};
6786095e08126790592699d8aeef4d31b263a4176a4Stephen Hemminger
679815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechlestatic void ax_setup(struct net_device *dev)
680815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle{
681815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	/* Finish setting up the DEVICE info. */
682815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	dev->mtu             = AX_MTU;
683815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	dev->hard_header_len = 0;
684815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	dev->addr_len        = 0;
685815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	dev->type            = ARPHRD_AX25;
686815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	dev->tx_queue_len    = 10;
6873b04ddde02cf1b6f14f2697da5c20eca5715017fStephen Hemminger	dev->header_ops      = &ax_header_ops;
6886095e08126790592699d8aeef4d31b263a4176a4Stephen Hemminger	dev->netdev_ops	     = &ax_netdev_ops;
6893b04ddde02cf1b6f14f2697da5c20eca5715017fStephen Hemminger
690815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
69115b1c0e822f578306332d4f4c449250db5c5dcebRalf Baechle	memcpy(dev->broadcast, &ax25_bcast, AX25_ADDR_LEN);
69215b1c0e822f578306332d4f4c449250db5c5dcebRalf Baechle	memcpy(dev->dev_addr,  &ax25_defaddr,  AX25_ADDR_LEN);
693815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
694815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	dev->flags      = IFF_BROADCAST | IFF_MULTICAST;
6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
698815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle * We have a potential race on dereferencing tty->disc_data, because the tty
699815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle * layer provides no locking at all - thus one cpu could be running
700815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle * sixpack_receive_buf while another calls sixpack_close, which zeroes
701815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle * tty->disc_data and frees the memory that sixpack_receive_buf is using.  The
702815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle * best way to fix this is to use a rwlock in the tty struct, but for now we
703815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle * use a single global rwlock for all ttys in ppp line discipline.
7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
705d5919586265d36c6694a5d10ba589c02806873b6Ralf Baechlestatic DEFINE_RWLOCK(disc_data_lock);
706815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
707815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechlestatic struct mkiss *mkiss_get(struct tty_struct *tty)
7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
709815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	struct mkiss *ax;
7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
711815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	read_lock(&disc_data_lock);
712815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	ax = tty->disc_data;
713815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	if (ax)
714815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		atomic_inc(&ax->refcnt);
715815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	read_unlock(&disc_data_lock);
7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
717815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	return ax;
718815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle}
7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
720815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechlestatic void mkiss_put(struct mkiss *ax)
721815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle{
722815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	if (atomic_dec_and_test(&ax->refcnt))
723815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		up(&ax->dead_sem);
7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7265793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechlestatic int crc_force = 0;	/* Can be overridden with insmod */
7275793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle
728815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechlestatic int mkiss_open(struct tty_struct *tty)
7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
730815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	struct net_device *dev;
731815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	struct mkiss *ax;
7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int err;
7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
734815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	if (!capable(CAP_NET_ADMIN))
735815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		return -EPERM;
736f34d7a5b7010b82fe97da95496b9971435530062Alan Cox	if (tty->ops->write == NULL)
737f34d7a5b7010b82fe97da95496b9971435530062Alan Cox		return -EOPNOTSUPP;
7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
739815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	dev = alloc_netdev(sizeof(struct mkiss), "ax%d", ax_setup);
740815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	if (!dev) {
741815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		err = -ENOMEM;
742815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		goto out;
743815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	}
744815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
745815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	ax = netdev_priv(dev);
746815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	ax->dev = dev;
747815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
748815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	spin_lock_init(&ax->buflock);
749815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	atomic_set(&ax->refcnt, 1);
750495e64bddeb9349395ed346177057fff7d52857eThomas Gleixner	sema_init(&ax->dead_sem, 0);
7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ax->tty = tty;
7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tty->disc_data = ax;
75433f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox	tty->receive_room = 65535;
7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
756f34d7a5b7010b82fe97da95496b9971435530062Alan Cox	tty_driver_flush_buffer(tty);
7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Restore default settings */
759815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	dev->type = ARPHRD_AX25;
7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Perform the low-level AX25 initialization. */
762815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	if ((err = ax_open(ax->dev))) {
763815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		goto out_free_netdev;
764815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	}
7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
766815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	if (register_netdev(dev))
767815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		goto out_free_buffers;
7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7695793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle	/* after register_netdev() - because else printk smashes the kernel */
7705793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle	switch (crc_force) {
7715793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle	case 3:
7725793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		ax->crcmode  = CRC_MODE_SMACK;
7735793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		printk(KERN_INFO "mkiss: %s: crc mode smack forced.\n",
7745793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		       ax->dev->name);
7755793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		break;
7765793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle	case 2:
7775793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		ax->crcmode  = CRC_MODE_FLEX;
7785793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		printk(KERN_INFO "mkiss: %s: crc mode flexnet forced.\n",
7795793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		       ax->dev->name);
7805793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		break;
7815793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle	case 1:
7825793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		ax->crcmode  = CRC_MODE_NONE;
7835793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		printk(KERN_INFO "mkiss: %s: crc mode disabled.\n",
7845793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		       ax->dev->name);
7855793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		break;
7865793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle	case 0:
7875793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		/* fall through */
7885793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle	default:
7895793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		crc_force = 0;
7905793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		printk(KERN_INFO "mkiss: %s: crc mode is auto.\n",
7915793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		       ax->dev->name);
7925793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle		ax->crcmode  = CRC_MODE_SMACK_TEST;
7935793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle	}
7945793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle	ax->crcauto = (crc_force ? 0 : 1);
7955793f4be23f0171b4999ca68a39a9157b44139f3Ralf Baechle
796815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	netif_start_queue(dev);
7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
798815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	/* Done.  We have linked the TTY line to a channel. */
799815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	return 0;
8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
801815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechleout_free_buffers:
802815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	kfree(ax->rbuff);
803815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	kfree(ax->xbuff);
8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
805815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechleout_free_netdev:
806815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	free_netdev(dev);
8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
808815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechleout:
809815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	return err;
8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
812815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechlestatic void mkiss_close(struct tty_struct *tty)
8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
814815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	struct mkiss *ax;
8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
816815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	write_lock(&disc_data_lock);
817815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	ax = tty->disc_data;
818815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	tty->disc_data = NULL;
819815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	write_unlock(&disc_data_lock);
8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
82179ea13ce07c951bb4d95471e7300baa0f1be9e78Al Viro	if (!ax)
822815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		return;
8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
825815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	 * We have now ensured that nobody can start using ap from now on, but
826815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	 * we have to wait for all existing users to finish.
8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
828815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	if (!atomic_dec_and_test(&ax->refcnt))
829815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		down(&ax->dead_sem);
8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
831815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	unregister_netdev(ax->dev);
8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
833815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	/* Free all AX25 frame buffers. */
834815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	kfree(ax->rbuff);
835815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	kfree(ax->xbuff);
8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
837815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	ax->tty = NULL;
8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
840815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle/* Perform I/O control on an active ax25 channel. */
841815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechlestatic int mkiss_ioctl(struct tty_struct *tty, struct file *file,
842815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	unsigned int cmd, unsigned long arg)
8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
844815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	struct mkiss *ax = mkiss_get(tty);
845f40e0638237a2d3e2ce8bedf3af4b3c02cf6fff7Julia Lawall	struct net_device *dev;
846815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	unsigned int tmp, err;
8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
848815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	/* First make sure we're connected. */
849815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	if (ax == NULL)
850815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		return -ENXIO;
851f40e0638237a2d3e2ce8bedf3af4b3c02cf6fff7Julia Lawall	dev = ax->dev;
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
887932ff279a43ab7257942cddff2595acd541cc49bHerbert Xu		netif_tx_lock_bh(dev);
888815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		memcpy(dev->dev_addr, addr, AX25_ADDR_LEN);
889932ff279a43ab7257942cddff2595acd541cc49bHerbert Xu		netif_tx_unlock_bh(dev);
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
9039646e7ce3d1955478aa0573b36c151ab4b649486Arnd Bergmann#ifdef CONFIG_COMPAT
9049646e7ce3d1955478aa0573b36c151ab4b649486Arnd Bergmannstatic long mkiss_compat_ioctl(struct tty_struct *tty, struct file *file,
9059646e7ce3d1955478aa0573b36c151ab4b649486Arnd Bergmann	unsigned int cmd, unsigned long arg)
9069646e7ce3d1955478aa0573b36c151ab4b649486Arnd Bergmann{
90707c3c4ee3a4143d0c8bb2e260c089bf012cf2c6eArnd Bergmann	switch (cmd) {
9089646e7ce3d1955478aa0573b36c151ab4b649486Arnd Bergmann	case SIOCGIFNAME:
9099646e7ce3d1955478aa0573b36c151ab4b649486Arnd Bergmann	case SIOCGIFENCAP:
9109646e7ce3d1955478aa0573b36c151ab4b649486Arnd Bergmann	case SIOCSIFENCAP:
9119646e7ce3d1955478aa0573b36c151ab4b649486Arnd Bergmann	case SIOCSIFHWADDR:
9129646e7ce3d1955478aa0573b36c151ab4b649486Arnd Bergmann		return mkiss_ioctl(tty, file, cmd,
9139646e7ce3d1955478aa0573b36c151ab4b649486Arnd Bergmann				   (unsigned long)compat_ptr(arg));
9149646e7ce3d1955478aa0573b36c151ab4b649486Arnd Bergmann	}
9159646e7ce3d1955478aa0573b36c151ab4b649486Arnd Bergmann
9169646e7ce3d1955478aa0573b36c151ab4b649486Arnd Bergmann	return -ENOIOCTLCMD;
9179646e7ce3d1955478aa0573b36c151ab4b649486Arnd Bergmann}
9189646e7ce3d1955478aa0573b36c151ab4b649486Arnd Bergmann#endif
9199646e7ce3d1955478aa0573b36c151ab4b649486Arnd Bergmann
920815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle/*
921815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle * Handle the 'receiver data ready' interrupt.
922815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle * This function is called by the 'tty_io' module in the kernel when
923815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle * a block of data has been received, which can now be decapsulated
924815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle * and sent on to the AX.25 layer for further processing.
925815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle */
92655db4c64eddf37e31279ec15fe90314713bc9cfaLinus Torvaldsstatic void mkiss_receive_buf(struct tty_struct *tty, const unsigned char *cp,
92755db4c64eddf37e31279ec15fe90314713bc9cfaLinus Torvalds	char *fp, int count)
9281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
929815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	struct mkiss *ax = mkiss_get(tty);
9301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
931815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	if (!ax)
93255db4c64eddf37e31279ec15fe90314713bc9cfaLinus Torvalds		return;
9331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
934815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	/*
935815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	 * Argh! mtu change time! - costs us the packet part received
936815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	 * at the change
937815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	 */
938815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	if (ax->mtu != ax->dev->mtu + 73)
939815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		ax_changedmtu(ax);
9401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
941815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	/* Read the characters out of the buffer */
94255db4c64eddf37e31279ec15fe90314713bc9cfaLinus Torvalds	while (count--) {
943815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		if (fp != NULL && *fp++) {
944815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			if (!test_and_set_bit(AXF_ERROR, &ax->flags))
945ddbe9a686805c36a0e68451ebb8cb51b21d0c718Stephen Hemminger				ax->dev->stats.rx_errors++;
946815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			cp++;
947815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle			continue;
948815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		}
9491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
950815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		kiss_unesc(ax, *cp++);
9511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
952815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
953815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	mkiss_put(ax);
95439c2e60f8c584c1b29b5c4375dd49df7995386bbAlan Cox	tty_unthrottle(tty);
9551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
957815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle/*
958815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle * Called by the driver when there's room for more data.  If we have
959815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle * more packets to send, we send them here.
960815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle */
961815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechlestatic void mkiss_write_wakeup(struct tty_struct *tty)
9621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
963815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	struct mkiss *ax = mkiss_get(tty);
964815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	int actual;
9651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
966815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	if (!ax)
967815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		return;
9681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
969815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	if (ax->xleft <= 0)  {
970815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		/* Now serial buffer is almost free & we can start
971815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		 * transmission of another packet
972815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		 */
973815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
9741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
975815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		netif_wake_queue(ax->dev);
976815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		goto out;
977815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	}
9781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
979f34d7a5b7010b82fe97da95496b9971435530062Alan Cox	actual = tty->ops->write(tty, ax->xhead, ax->xleft);
980815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	ax->xleft -= actual;
981815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	ax->xhead += actual;
9821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
983815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechleout:
984815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	mkiss_put(ax);
9851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
987a352def21a642133758b868c71bee12ab34ad5c5Alan Coxstatic struct tty_ldisc_ops ax_ldisc = {
98874cfe03f80adc320bde4dd37616354aefe2271aaRalf Baechle	.owner		= THIS_MODULE,
989815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	.magic		= TTY_LDISC_MAGIC,
990815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	.name		= "mkiss",
991815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	.open		= mkiss_open,
992815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	.close		= mkiss_close,
993815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	.ioctl		= mkiss_ioctl,
9949646e7ce3d1955478aa0573b36c151ab4b649486Arnd Bergmann#ifdef CONFIG_COMPAT
9959646e7ce3d1955478aa0573b36c151ab4b649486Arnd Bergmann	.compat_ioctl	= mkiss_compat_ioctl,
9969646e7ce3d1955478aa0573b36c151ab4b649486Arnd Bergmann#endif
997815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	.receive_buf	= mkiss_receive_buf,
998815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	.write_wakeup	= mkiss_write_wakeup
999815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle};
10001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1001eb33ae248682ecfdf44d693c72bc4f523f2fb6e3Hannes Ederstatic const char banner[] __initdata = KERN_INFO \
1002815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	"mkiss: AX.25 Multikiss, Hans Albas PE1AYX\n";
1003eb33ae248682ecfdf44d693c72bc4f523f2fb6e3Hannes Ederstatic const char msg_regfail[] __initdata = KERN_ERR \
1004815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	"mkiss: can't register line discipline (err = %d)\n";
10051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init mkiss_init_driver(void)
10071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
10081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int status;
10091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk(banner);
10111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1012eb33ae248682ecfdf44d693c72bc4f523f2fb6e3Hannes Eder	status = tty_register_ldisc(N_AX25, &ax_ldisc);
1013eb33ae248682ecfdf44d693c72bc4f523f2fb6e3Hannes Eder	if (status != 0)
1014eb33ae248682ecfdf44d693c72bc4f523f2fb6e3Hannes Eder		printk(msg_regfail, status);
10151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return status;
10171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1019815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechlestatic const char msg_unregfail[] __exitdata = KERN_ERR \
1020815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	"mkiss: can't unregister line discipline (err = %d)\n";
1021815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
10221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit mkiss_exit_driver(void)
10231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1024815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	int ret;
10251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1026815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle	if ((ret = tty_unregister_ldisc(N_AX25)))
1027815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle		printk(msg_unregfail, ret);
10281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1030815f62bf742718458ba822a7e1f51f285eb997f2Ralf BaechleMODULE_AUTHOR("Ralf Baechle DL5RB <ralf@linux-mips.org>");
10311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("KISS driver for AX.25 over TTYs");
10328d3b33f67fdc0fb364a1ef6d8fbbea7c2e4e6c98Rusty Russellmodule_param(crc_force, int, 0);
10335793f4be23f0171b4999ca68a39a9157b44139f3Ralf BaechleMODULE_PARM_DESC(crc_force, "crc [0 = auto | 1 = none | 2 = flexnet | 3 = smack]");
10341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL");
10351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_ALIAS_LDISC(N_AX25);
1036815f62bf742718458ba822a7e1f51f285eb997f2Ralf Baechle
10371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(mkiss_init_driver);
10381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(mkiss_exit_driver);
1039