Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

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