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-1.0+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    2) /* r3964 linediscipline for linux
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    3)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    4)  * -----------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    5)  * Copyright by 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    6)  * Philips Automation Projects
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    7)  * Kassel (Germany)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    8)  * -----------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    9)  * Author:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   10)  * L. Haag
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   11)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   12)  * $Log: n_r3964.c,v $
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   13)  * Revision 1.10  2001/03/18 13:02:24  dwmw2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   14)  * Fix timer usage, use spinlocks properly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   15)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   16)  * Revision 1.9  2001/03/18 12:52:14  dwmw2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   17)  * Merge changes in 2.4.2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   18)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   19)  * Revision 1.8  2000/03/23 14:14:54  dwmw2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   20)  * Fix race in sleeping in r3964_read()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   21)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   22)  * Revision 1.7  1999/28/08 11:41:50  dwmw2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   23)  * Port to 2.3 kernel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   24)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   25)  * Revision 1.6  1998/09/30 00:40:40  dwmw2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   26)  * Fixed compilation on 2.0.x kernels
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   27)  * Updated to newly registered tty-ldisc number 9
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   28)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   29)  * Revision 1.5  1998/09/04 21:57:36  dwmw2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   30)  * Signal handling bug fixes, port to 2.1.x.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   31)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   32)  * Revision 1.4  1998/04/02 20:26:59  lhaag
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   33)  * select, blocking, ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   34)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   35)  * Revision 1.3  1998/02/12 18:58:43  root
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   36)  * fixed some memory leaks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   37)  * calculation of checksum characters
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   38)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   39)  * Revision 1.2  1998/02/07 13:03:34  root
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   40)  * ioctl read_telegram
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   41)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   42)  * Revision 1.1  1998/02/06 19:21:03  root
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   43)  * Initial revision
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   44)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   45)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   46)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   47) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   48) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   49) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   50) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   51) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   52) #include <linux/fcntl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   53) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   54) #include <linux/ptrace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   55) #include <linux/ioport.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   56) #include <linux/in.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   57) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   58) #include <linux/tty.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   59) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   60) #include <linux/string.h>	/* used in new tty drivers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   61) #include <linux/signal.h>	/* used in new tty drivers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   62) #include <linux/ioctl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   63) #include <linux/n_r3964.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   64) #include <linux/poll.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   65) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   66) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   67) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   68) /*#define DEBUG_QUEUE*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   69) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   70) /* Log successful handshake and protocol operations  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   71) /*#define DEBUG_PROTO_S*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   72) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   73) /* Log handshake and protocol errors: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   74) /*#define DEBUG_PROTO_E*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   75) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   76) /* Log Linediscipline operations (open, close, read, write...): */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   77) /*#define DEBUG_LDISC*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   78) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   79) /* Log module and memory operations (init, cleanup; kmalloc, kfree): */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   80) /*#define DEBUG_MODUL*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   81) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   82) /* Macro helpers for debug output: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   83) #define TRACE(format, args...) printk("r3964: " format "\n" , ## args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   84) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   85) #ifdef DEBUG_MODUL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   86) #define TRACE_M(format, args...) printk("r3964: " format "\n" , ## args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   87) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   88) #define TRACE_M(fmt, arg...) do {} while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   89) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   90) #ifdef DEBUG_PROTO_S
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   91) #define TRACE_PS(format, args...) printk("r3964: " format "\n" , ## args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   92) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   93) #define TRACE_PS(fmt, arg...) do {} while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   94) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   95) #ifdef DEBUG_PROTO_E
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   96) #define TRACE_PE(format, args...) printk("r3964: " format "\n" , ## args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   97) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   98) #define TRACE_PE(fmt, arg...) do {} while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   99) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  100) #ifdef DEBUG_LDISC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  101) #define TRACE_L(format, args...) printk("r3964: " format "\n" , ## args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  102) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  103) #define TRACE_L(fmt, arg...) do {} while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  104) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  105) #ifdef DEBUG_QUEUE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  106) #define TRACE_Q(format, args...) printk("r3964: " format "\n" , ## args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  107) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  108) #define TRACE_Q(fmt, arg...) do {} while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  109) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  110) static void add_tx_queue(struct r3964_info *, struct r3964_block_header *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  111) static void remove_from_tx_queue(struct r3964_info *pInfo, int error_code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  112) static void put_char(struct r3964_info *pInfo, unsigned char ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  113) static void trigger_transmit(struct r3964_info *pInfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  114) static void retry_transmit(struct r3964_info *pInfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  115) static void transmit_block(struct r3964_info *pInfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  116) static void receive_char(struct r3964_info *pInfo, const unsigned char c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  117) static void receive_error(struct r3964_info *pInfo, const char flag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  118) static void on_timeout(struct timer_list *t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  119) static int enable_signals(struct r3964_info *pInfo, struct pid *pid, int arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  120) static int read_telegram(struct r3964_info *pInfo, struct pid *pid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  121) 		unsigned char __user * buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  122) static void add_msg(struct r3964_client_info *pClient, int msg_id, int arg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  123) 		int error_code, struct r3964_block_header *pBlock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  124) static struct r3964_message *remove_msg(struct r3964_info *pInfo,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  125) 		struct r3964_client_info *pClient);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  126) static void remove_client_block(struct r3964_info *pInfo,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  127) 		struct r3964_client_info *pClient);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  128) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  129) static int r3964_open(struct tty_struct *tty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  130) static void r3964_close(struct tty_struct *tty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  131) static ssize_t r3964_read(struct tty_struct *tty, struct file *file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  132) 		void *cookie, unsigned char *buf, size_t nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  133) static ssize_t r3964_write(struct tty_struct *tty, struct file *file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  134) 		const unsigned char *buf, size_t nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  135) static int r3964_ioctl(struct tty_struct *tty, struct file *file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  136) 		unsigned int cmd, unsigned long arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  137) #ifdef CONFIG_COMPAT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  138) static int r3964_compat_ioctl(struct tty_struct *tty, struct file *file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  139) 		unsigned int cmd, unsigned long arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  140) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  141) static void r3964_set_termios(struct tty_struct *tty, struct ktermios *old);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  142) static __poll_t r3964_poll(struct tty_struct *tty, struct file *file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  143) 		struct poll_table_struct *wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  144) static void r3964_receive_buf(struct tty_struct *tty, const unsigned char *cp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  145) 		char *fp, int count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  146) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  147) static struct tty_ldisc_ops tty_ldisc_N_R3964 = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  148) 	.owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  149) 	.magic = TTY_LDISC_MAGIC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  150) 	.name = "R3964",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  151) 	.open = r3964_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  152) 	.close = r3964_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  153) 	.read = r3964_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  154) 	.write = r3964_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  155) 	.ioctl = r3964_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  156) #ifdef CONFIG_COMPAT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  157) 	.compat_ioctl = r3964_compat_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  158) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  159) 	.set_termios = r3964_set_termios,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  160) 	.poll = r3964_poll,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  161) 	.receive_buf = r3964_receive_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  162) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  163) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  164) static void dump_block(const unsigned char *block, unsigned int length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  165) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  166) 	unsigned int i, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  167) 	char linebuf[16 * 3 + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  168) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  169) 	for (i = 0; i < length; i += 16) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  170) 		for (j = 0; (j < 16) && (j + i < length); j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  171) 			sprintf(linebuf + 3 * j, "%02x ", block[i + j]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  172) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  173) 		linebuf[3 * j] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  174) 		TRACE_PS("%s", linebuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  175) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  176) }
^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)  * Driver initialisation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  180)  *************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  181) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  182) /*************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  183)  * Module support routines
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  184)  *************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  185) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  186) static void __exit r3964_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  187) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  188) 	int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  189) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  190) 	TRACE_M("cleanup_module()");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  191) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  192) 	status = tty_unregister_ldisc(N_R3964);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  193) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  194) 	if (status != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  195) 		printk(KERN_ERR "r3964: error unregistering linediscipline: "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  196) 				"%d\n", status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  197) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  198) 		TRACE_L("linediscipline successfully unregistered");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  199) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  200) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  201) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  202) static int __init r3964_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  203) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  204) 	int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  205) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  206) 	printk("r3964: Philips r3964 Driver $Revision: 1.10 $\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  207) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  208) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  209) 	 * Register the tty line discipline
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  210) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  211) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  212) 	status = tty_register_ldisc(N_R3964, &tty_ldisc_N_R3964);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  213) 	if (status == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  214) 		TRACE_L("line discipline %d registered", N_R3964);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  215) 		TRACE_L("flags=%x num=%x", tty_ldisc_N_R3964.flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  216) 			tty_ldisc_N_R3964.num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  217) 		TRACE_L("open=%p", tty_ldisc_N_R3964.open);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  218) 		TRACE_L("tty_ldisc_N_R3964 = %p", &tty_ldisc_N_R3964);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  219) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  220) 		printk(KERN_ERR "r3964: error registering line discipline: "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  221) 				"%d\n", status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  222) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  223) 	return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  224) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  225) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  226) module_init(r3964_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  227) module_exit(r3964_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  228) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  229) /*************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  230)  * Protocol implementation routines
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  231)  *************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  232) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  233) static void add_tx_queue(struct r3964_info *pInfo,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  234) 			 struct r3964_block_header *pHeader)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  235) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  236) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  237) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  238) 	spin_lock_irqsave(&pInfo->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  239) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  240) 	pHeader->next = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  241) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  242) 	if (pInfo->tx_last == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  243) 		pInfo->tx_first = pInfo->tx_last = pHeader;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  244) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  245) 		pInfo->tx_last->next = pHeader;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  246) 		pInfo->tx_last = pHeader;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  247) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  248) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  249) 	spin_unlock_irqrestore(&pInfo->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  250) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  251) 	TRACE_Q("add_tx_queue %p, length %d, tx_first = %p",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  252) 		pHeader, pHeader->length, pInfo->tx_first);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  253) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  254) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  255) static void remove_from_tx_queue(struct r3964_info *pInfo, int error_code)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  256) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  257) 	struct r3964_block_header *pHeader;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  258) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  259) #ifdef DEBUG_QUEUE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  260) 	struct r3964_block_header *pDump;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  261) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  262) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  263) 	pHeader = pInfo->tx_first;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  264) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  265) 	if (pHeader == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  266) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  267) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  268) #ifdef DEBUG_QUEUE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  269) 	printk("r3964: remove_from_tx_queue: %p, length %u - ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  270) 		pHeader, pHeader->length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  271) 	for (pDump = pHeader; pDump; pDump = pDump->next)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  272) 		printk("%p ", pDump);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  273) 	printk("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  274) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  275) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  276) 	if (pHeader->owner) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  277) 		if (error_code) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  278) 			add_msg(pHeader->owner, R3964_MSG_ACK, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  279) 				error_code, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  280) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  281) 			add_msg(pHeader->owner, R3964_MSG_ACK, pHeader->length,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  282) 				error_code, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  283) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  284) 		wake_up_interruptible(&pInfo->tty->read_wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  285) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  286) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  287) 	spin_lock_irqsave(&pInfo->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  288) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  289) 	pInfo->tx_first = pHeader->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  290) 	if (pInfo->tx_first == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  291) 		pInfo->tx_last = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  292) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  293) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  294) 	spin_unlock_irqrestore(&pInfo->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  295) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  296) 	kfree(pHeader);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  297) 	TRACE_M("remove_from_tx_queue - kfree %p", pHeader);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  298) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  299) 	TRACE_Q("remove_from_tx_queue: tx_first = %p, tx_last = %p",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  300) 		pInfo->tx_first, pInfo->tx_last);
^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 void add_rx_queue(struct r3964_info *pInfo,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  304) 			 struct r3964_block_header *pHeader)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  305) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  306) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  307) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  308) 	spin_lock_irqsave(&pInfo->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  309) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  310) 	pHeader->next = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  311) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  312) 	if (pInfo->rx_last == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  313) 		pInfo->rx_first = pInfo->rx_last = pHeader;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  314) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  315) 		pInfo->rx_last->next = pHeader;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  316) 		pInfo->rx_last = pHeader;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  317) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  318) 	pInfo->blocks_in_rx_queue++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  319) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  320) 	spin_unlock_irqrestore(&pInfo->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  321) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  322) 	TRACE_Q("add_rx_queue: %p, length = %d, rx_first = %p, count = %d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  323) 		pHeader, pHeader->length,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  324) 		pInfo->rx_first, pInfo->blocks_in_rx_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  325) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  326) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  327) static void remove_from_rx_queue(struct r3964_info *pInfo,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  328) 				 struct r3964_block_header *pHeader)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  329) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  330) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  331) 	struct r3964_block_header *pFind;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  332) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  333) 	if (pHeader == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  334) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  335) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  336) 	TRACE_Q("remove_from_rx_queue: rx_first = %p, rx_last = %p, count = %d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  337) 		pInfo->rx_first, pInfo->rx_last, pInfo->blocks_in_rx_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  338) 	TRACE_Q("remove_from_rx_queue: %p, length %u",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  339) 		pHeader, pHeader->length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  340) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  341) 	spin_lock_irqsave(&pInfo->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  342) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  343) 	if (pInfo->rx_first == pHeader) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  344) 		/* Remove the first block in the linked list: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  345) 		pInfo->rx_first = pHeader->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  346) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  347) 		if (pInfo->rx_first == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  348) 			pInfo->rx_last = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  349) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  350) 		pInfo->blocks_in_rx_queue--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  351) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  352) 		/* Find block to remove: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  353) 		for (pFind = pInfo->rx_first; pFind; pFind = pFind->next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  354) 			if (pFind->next == pHeader) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  355) 				/* Got it. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  356) 				pFind->next = pHeader->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  357) 				pInfo->blocks_in_rx_queue--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  358) 				if (pFind->next == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  359) 					/* Oh, removed the last one! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  360) 					pInfo->rx_last = pFind;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  361) 				}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  362) 				break;
^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) 	spin_unlock_irqrestore(&pInfo->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  368) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  369) 	kfree(pHeader);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  370) 	TRACE_M("remove_from_rx_queue - kfree %p", pHeader);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  371) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  372) 	TRACE_Q("remove_from_rx_queue: rx_first = %p, rx_last = %p, count = %d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  373) 		pInfo->rx_first, pInfo->rx_last, pInfo->blocks_in_rx_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  374) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  375) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  376) static void put_char(struct r3964_info *pInfo, unsigned char ch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  377) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  378) 	struct tty_struct *tty = pInfo->tty;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  379) 	/* FIXME: put_char should not be called from an IRQ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  380) 	tty_put_char(tty, ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  381) 	pInfo->bcc ^= ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  382) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  383) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  384) static void flush(struct r3964_info *pInfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  385) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  386) 	struct tty_struct *tty = pInfo->tty;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  387) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  388) 	if (tty == NULL || tty->ops->flush_chars == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  389) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  390) 	tty->ops->flush_chars(tty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  391) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  392) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  393) static void trigger_transmit(struct r3964_info *pInfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  394) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  395) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  396) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  397) 	spin_lock_irqsave(&pInfo->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  398) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  399) 	if ((pInfo->state == R3964_IDLE) && (pInfo->tx_first != NULL)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  400) 		pInfo->state = R3964_TX_REQUEST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  401) 		pInfo->nRetry = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  402) 		pInfo->flags &= ~R3964_ERROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  403) 		mod_timer(&pInfo->tmr, jiffies + R3964_TO_QVZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  404) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  405) 		spin_unlock_irqrestore(&pInfo->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  406) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  407) 		TRACE_PS("trigger_transmit - sent STX");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  408) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  409) 		put_char(pInfo, STX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  410) 		flush(pInfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  411) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  412) 		pInfo->bcc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  413) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  414) 		spin_unlock_irqrestore(&pInfo->lock, flags);
^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) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  418) static void retry_transmit(struct r3964_info *pInfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  419) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  420) 	if (pInfo->nRetry < R3964_MAX_RETRIES) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  421) 		TRACE_PE("transmission failed. Retry #%d", pInfo->nRetry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  422) 		pInfo->bcc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  423) 		put_char(pInfo, STX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  424) 		flush(pInfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  425) 		pInfo->state = R3964_TX_REQUEST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  426) 		pInfo->nRetry++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  427) 		mod_timer(&pInfo->tmr, jiffies + R3964_TO_QVZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  428) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  429) 		TRACE_PE("transmission failed after %d retries",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  430) 			 R3964_MAX_RETRIES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  431) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  432) 		remove_from_tx_queue(pInfo, R3964_TX_FAIL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  433) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  434) 		put_char(pInfo, NAK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  435) 		flush(pInfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  436) 		pInfo->state = R3964_IDLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  437) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  438) 		trigger_transmit(pInfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  439) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  440) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  441) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  442) static void transmit_block(struct r3964_info *pInfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  443) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  444) 	struct tty_struct *tty = pInfo->tty;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  445) 	struct r3964_block_header *pBlock = pInfo->tx_first;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  446) 	int room = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  447) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  448) 	if (tty == NULL || pBlock == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  449) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  450) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  451) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  452) 	room = tty_write_room(tty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  453) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  454) 	TRACE_PS("transmit_block %p, room %d, length %d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  455) 		 pBlock, room, pBlock->length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  456) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  457) 	while (pInfo->tx_position < pBlock->length) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  458) 		if (room < 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  459) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  460) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  461) 		if (pBlock->data[pInfo->tx_position] == DLE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  462) 			/* send additional DLE char: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  463) 			put_char(pInfo, DLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  464) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  465) 		put_char(pInfo, pBlock->data[pInfo->tx_position++]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  466) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  467) 		room--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  468) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  469) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  470) 	if ((pInfo->tx_position == pBlock->length) && (room >= 3)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  471) 		put_char(pInfo, DLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  472) 		put_char(pInfo, ETX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  473) 		if (pInfo->flags & R3964_BCC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  474) 			put_char(pInfo, pInfo->bcc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  475) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  476) 		pInfo->state = R3964_WAIT_FOR_TX_ACK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  477) 		mod_timer(&pInfo->tmr, jiffies + R3964_TO_QVZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  478) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  479) 	flush(pInfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  480) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  481) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  482) static void on_receive_block(struct r3964_info *pInfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  483) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  484) 	unsigned int length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  485) 	struct r3964_client_info *pClient;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  486) 	struct r3964_block_header *pBlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  487) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  488) 	length = pInfo->rx_position;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  489) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  490) 	/* compare byte checksum characters: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  491) 	if (pInfo->flags & R3964_BCC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  492) 		if (pInfo->bcc != pInfo->last_rx) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  493) 			TRACE_PE("checksum error - got %x but expected %x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  494) 				 pInfo->last_rx, pInfo->bcc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  495) 			pInfo->flags |= R3964_CHECKSUM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  496) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  497) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  498) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  499) 	/* check for errors (parity, overrun,...): */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  500) 	if (pInfo->flags & R3964_ERROR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  501) 		TRACE_PE("on_receive_block - transmission failed error %x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  502) 			 pInfo->flags & R3964_ERROR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  503) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  504) 		put_char(pInfo, NAK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  505) 		flush(pInfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  506) 		if (pInfo->nRetry < R3964_MAX_RETRIES) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  507) 			pInfo->state = R3964_WAIT_FOR_RX_REPEAT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  508) 			pInfo->nRetry++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  509) 			mod_timer(&pInfo->tmr, jiffies + R3964_TO_RX_PANIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  510) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  511) 			TRACE_PE("on_receive_block - failed after max retries");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  512) 			pInfo->state = R3964_IDLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  513) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  514) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  515) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  516) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  517) 	/* received block; submit DLE: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  518) 	put_char(pInfo, DLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  519) 	flush(pInfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  520) 	del_timer_sync(&pInfo->tmr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  521) 	TRACE_PS(" rx success: got %d chars", length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  522) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  523) 	/* prepare struct r3964_block_header: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  524) 	pBlock = kmalloc(length + sizeof(struct r3964_block_header),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  525) 			GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  526) 	TRACE_M("on_receive_block - kmalloc %p", pBlock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  527) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  528) 	if (pBlock == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  529) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  530) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  531) 	pBlock->length = length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  532) 	pBlock->data = ((unsigned char *)pBlock) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  533) 			sizeof(struct r3964_block_header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  534) 	pBlock->locks = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  535) 	pBlock->next = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  536) 	pBlock->owner = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  537) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  538) 	memcpy(pBlock->data, pInfo->rx_buf, length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  539) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  540) 	/* queue block into rx_queue: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  541) 	add_rx_queue(pInfo, pBlock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  542) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  543) 	/* notify attached client processes: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  544) 	for (pClient = pInfo->firstClient; pClient; pClient = pClient->next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  545) 		if (pClient->sig_flags & R3964_SIG_DATA) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  546) 			add_msg(pClient, R3964_MSG_DATA, length, R3964_OK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  547) 				pBlock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  548) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  549) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  550) 	wake_up_interruptible(&pInfo->tty->read_wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  551) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  552) 	pInfo->state = R3964_IDLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  553) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  554) 	trigger_transmit(pInfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  555) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  556) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  557) static void receive_char(struct r3964_info *pInfo, const unsigned char c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  558) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  559) 	switch (pInfo->state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  560) 	case R3964_TX_REQUEST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  561) 		if (c == DLE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  562) 			TRACE_PS("TX_REQUEST - got DLE");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  563) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  564) 			pInfo->state = R3964_TRANSMITTING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  565) 			pInfo->tx_position = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  566) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  567) 			transmit_block(pInfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  568) 		} else if (c == STX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  569) 			if (pInfo->nRetry == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  570) 				TRACE_PE("TX_REQUEST - init conflict");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  571) 				if (pInfo->priority == R3964_SLAVE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  572) 					goto start_receiving;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  573) 				}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  574) 			} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  575) 				TRACE_PE("TX_REQUEST - secondary init "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  576) 					"conflict!? Switching to SLAVE mode "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  577) 					"for next rx.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  578) 				goto start_receiving;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  579) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  580) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  581) 			TRACE_PE("TX_REQUEST - char != DLE: %x", c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  582) 			retry_transmit(pInfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  583) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  584) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  585) 	case R3964_TRANSMITTING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  586) 		if (c == NAK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  587) 			TRACE_PE("TRANSMITTING - got NAK");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  588) 			retry_transmit(pInfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  589) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  590) 			TRACE_PE("TRANSMITTING - got invalid char");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  591) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  592) 			pInfo->state = R3964_WAIT_ZVZ_BEFORE_TX_RETRY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  593) 			mod_timer(&pInfo->tmr, jiffies + R3964_TO_ZVZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  594) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  595) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  596) 	case R3964_WAIT_FOR_TX_ACK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  597) 		if (c == DLE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  598) 			TRACE_PS("WAIT_FOR_TX_ACK - got DLE");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  599) 			remove_from_tx_queue(pInfo, R3964_OK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  600) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  601) 			pInfo->state = R3964_IDLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  602) 			trigger_transmit(pInfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  603) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  604) 			retry_transmit(pInfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  605) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  606) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  607) 	case R3964_WAIT_FOR_RX_REPEAT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  608) 	case R3964_IDLE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  609) 		if (c == STX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  610) 			/* Prevent rx_queue from overflow: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  611) 			if (pInfo->blocks_in_rx_queue >=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  612) 			    R3964_MAX_BLOCKS_IN_RX_QUEUE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  613) 				TRACE_PE("IDLE - got STX but no space in "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  614) 						"rx_queue!");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  615) 				pInfo->state = R3964_WAIT_FOR_RX_BUF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  616) 				mod_timer(&pInfo->tmr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  617) 					  jiffies + R3964_TO_NO_BUF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  618) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  619) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  620) start_receiving:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  621) 			/* Ok, start receiving: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  622) 			TRACE_PS("IDLE - got STX");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  623) 			pInfo->rx_position = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  624) 			pInfo->last_rx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  625) 			pInfo->flags &= ~R3964_ERROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  626) 			pInfo->state = R3964_RECEIVING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  627) 			mod_timer(&pInfo->tmr, jiffies + R3964_TO_ZVZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  628) 			pInfo->nRetry = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  629) 			put_char(pInfo, DLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  630) 			flush(pInfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  631) 			pInfo->bcc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  632) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  633) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  634) 	case R3964_RECEIVING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  635) 		if (pInfo->rx_position < RX_BUF_SIZE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  636) 			pInfo->bcc ^= c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  637) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  638) 			if (c == DLE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  639) 				if (pInfo->last_rx == DLE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  640) 					pInfo->last_rx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  641) 					goto char_to_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  642) 				}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  643) 				pInfo->last_rx = DLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  644) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  645) 			} else if ((c == ETX) && (pInfo->last_rx == DLE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  646) 				if (pInfo->flags & R3964_BCC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  647) 					pInfo->state = R3964_WAIT_FOR_BCC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  648) 					mod_timer(&pInfo->tmr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  649) 						  jiffies + R3964_TO_ZVZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  650) 				} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  651) 					on_receive_block(pInfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  652) 				}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  653) 			} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  654) 				pInfo->last_rx = c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  655) char_to_buf:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  656) 				pInfo->rx_buf[pInfo->rx_position++] = c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  657) 				mod_timer(&pInfo->tmr, jiffies + R3964_TO_ZVZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  658) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  659) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  660) 		/* else: overflow-msg? BUF_SIZE>MTU; should not happen? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  661) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  662) 	case R3964_WAIT_FOR_BCC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  663) 		pInfo->last_rx = c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  664) 		on_receive_block(pInfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  665) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  666) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  667) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  668) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  669) static void receive_error(struct r3964_info *pInfo, const char flag)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  670) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  671) 	switch (flag) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  672) 	case TTY_NORMAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  673) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  674) 	case TTY_BREAK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  675) 		TRACE_PE("received break");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  676) 		pInfo->flags |= R3964_BREAK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  677) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  678) 	case TTY_PARITY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  679) 		TRACE_PE("parity error");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  680) 		pInfo->flags |= R3964_PARITY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  681) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  682) 	case TTY_FRAME:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  683) 		TRACE_PE("frame error");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  684) 		pInfo->flags |= R3964_FRAME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  685) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  686) 	case TTY_OVERRUN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  687) 		TRACE_PE("frame overrun");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  688) 		pInfo->flags |= R3964_OVERRUN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  689) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  690) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  691) 		TRACE_PE("receive_error - unknown flag %d", flag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  692) 		pInfo->flags |= R3964_UNKNOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  693) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  694) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  695) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  696) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  697) static void on_timeout(struct timer_list *t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  698) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  699) 	struct r3964_info *pInfo = from_timer(pInfo, t, tmr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  700) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  701) 	switch (pInfo->state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  702) 	case R3964_TX_REQUEST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  703) 		TRACE_PE("TX_REQUEST - timeout");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  704) 		retry_transmit(pInfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  705) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  706) 	case R3964_WAIT_ZVZ_BEFORE_TX_RETRY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  707) 		put_char(pInfo, NAK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  708) 		flush(pInfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  709) 		retry_transmit(pInfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  710) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  711) 	case R3964_WAIT_FOR_TX_ACK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  712) 		TRACE_PE("WAIT_FOR_TX_ACK - timeout");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  713) 		retry_transmit(pInfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  714) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  715) 	case R3964_WAIT_FOR_RX_BUF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  716) 		TRACE_PE("WAIT_FOR_RX_BUF - timeout");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  717) 		put_char(pInfo, NAK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  718) 		flush(pInfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  719) 		pInfo->state = R3964_IDLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  720) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  721) 	case R3964_RECEIVING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  722) 		TRACE_PE("RECEIVING - timeout after %d chars",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  723) 			 pInfo->rx_position);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  724) 		put_char(pInfo, NAK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  725) 		flush(pInfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  726) 		pInfo->state = R3964_IDLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  727) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  728) 	case R3964_WAIT_FOR_RX_REPEAT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  729) 		TRACE_PE("WAIT_FOR_RX_REPEAT - timeout");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  730) 		pInfo->state = R3964_IDLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  731) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  732) 	case R3964_WAIT_FOR_BCC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  733) 		TRACE_PE("WAIT_FOR_BCC - timeout");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  734) 		put_char(pInfo, NAK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  735) 		flush(pInfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  736) 		pInfo->state = R3964_IDLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  737) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  738) 	}
^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) static struct r3964_client_info *findClient(struct r3964_info *pInfo,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  742) 		struct pid *pid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  743) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  744) 	struct r3964_client_info *pClient;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  745) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  746) 	for (pClient = pInfo->firstClient; pClient; pClient = pClient->next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  747) 		if (pClient->pid == pid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  748) 			return pClient;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  749) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  750) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  751) 	return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  752) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  753) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  754) static int enable_signals(struct r3964_info *pInfo, struct pid *pid, int arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  755) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  756) 	struct r3964_client_info *pClient;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  757) 	struct r3964_client_info **ppClient;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  758) 	struct r3964_message *pMsg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  759) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  760) 	if ((arg & R3964_SIG_ALL) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  761) 		/* Remove client from client list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  762) 		for (ppClient = &pInfo->firstClient; *ppClient;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  763) 		     ppClient = &(*ppClient)->next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  764) 			pClient = *ppClient;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  765) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  766) 			if (pClient->pid == pid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  767) 				TRACE_PS("removing client %d from client list",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  768) 					 pid_nr(pid));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  769) 				*ppClient = pClient->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  770) 				while (pClient->msg_count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  771) 					pMsg = remove_msg(pInfo, pClient);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  772) 					if (pMsg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  773) 						kfree(pMsg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  774) 						TRACE_M("enable_signals - msg "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  775) 							"kfree %p", pMsg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  776) 					}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  777) 				}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  778) 				put_pid(pClient->pid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  779) 				kfree(pClient);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  780) 				TRACE_M("enable_signals - kfree %p", pClient);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  781) 				return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  782) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  783) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  784) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  785) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  786) 		pClient = findClient(pInfo, pid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  787) 		if (pClient) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  788) 			/* update signal options */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  789) 			pClient->sig_flags = arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  790) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  791) 			/* add client to client list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  792) 			pClient = kmalloc(sizeof(struct r3964_client_info),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  793) 					GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  794) 			TRACE_M("enable_signals - kmalloc %p", pClient);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  795) 			if (pClient == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  796) 				return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  797) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  798) 			TRACE_PS("add client %d to client list", pid_nr(pid));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  799) 			spin_lock_init(&pClient->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  800) 			pClient->sig_flags = arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  801) 			pClient->pid = get_pid(pid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  802) 			pClient->next = pInfo->firstClient;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  803) 			pClient->first_msg = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  804) 			pClient->last_msg = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  805) 			pClient->next_block_to_read = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  806) 			pClient->msg_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  807) 			pInfo->firstClient = pClient;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  808) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  809) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  810) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  811) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  812) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  813) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  814) static int read_telegram(struct r3964_info *pInfo, struct pid *pid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  815) 			 unsigned char __user * buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  816) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  817) 	struct r3964_client_info *pClient;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  818) 	struct r3964_block_header *block;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  819) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  820) 	if (!buf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  821) 		return -EINVAL;
^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) 	pClient = findClient(pInfo, pid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  825) 	if (pClient == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  826) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  827) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  828) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  829) 	block = pClient->next_block_to_read;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  830) 	if (!block) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  831) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  832) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  833) 		if (copy_to_user(buf, block->data, block->length))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  834) 			return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  835) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  836) 		remove_client_block(pInfo, pClient);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  837) 		return block->length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  838) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  839) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  840) 	return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  841) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  842) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  843) static void add_msg(struct r3964_client_info *pClient, int msg_id, int arg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  844) 		int error_code, struct r3964_block_header *pBlock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  845) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  846) 	struct r3964_message *pMsg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  847) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  848) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  849) 	if (pClient->msg_count < R3964_MAX_MSG_COUNT - 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  850) queue_the_message:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  851) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  852) 		pMsg = kmalloc(sizeof(struct r3964_message),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  853) 				error_code ? GFP_ATOMIC : GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  854) 		TRACE_M("add_msg - kmalloc %p", pMsg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  855) 		if (pMsg == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  856) 			return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  857) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  858) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  859) 		spin_lock_irqsave(&pClient->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  860) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  861) 		pMsg->msg_id = msg_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  862) 		pMsg->arg = arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  863) 		pMsg->error_code = error_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  864) 		pMsg->block = pBlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  865) 		pMsg->next = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  866) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  867) 		if (pClient->last_msg == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  868) 			pClient->first_msg = pClient->last_msg = pMsg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  869) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  870) 			pClient->last_msg->next = pMsg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  871) 			pClient->last_msg = pMsg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  872) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  873) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  874) 		pClient->msg_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  875) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  876) 		if (pBlock != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  877) 			pBlock->locks++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  878) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  879) 		spin_unlock_irqrestore(&pClient->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  880) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  881) 		if ((pClient->last_msg->msg_id == R3964_MSG_ACK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  882) 		    && (pClient->last_msg->error_code == R3964_OVERFLOW)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  883) 			pClient->last_msg->arg++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  884) 			TRACE_PE("add_msg - inc prev OVERFLOW-msg");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  885) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  886) 			msg_id = R3964_MSG_ACK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  887) 			arg = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  888) 			error_code = R3964_OVERFLOW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  889) 			pBlock = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  890) 			TRACE_PE("add_msg - queue OVERFLOW-msg");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  891) 			goto queue_the_message;
^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) 	/* Send SIGIO signal to client process: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  895) 	if (pClient->sig_flags & R3964_USE_SIGIO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  896) 		kill_pid(pClient->pid, SIGIO, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  897) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  898) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  899) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  900) static struct r3964_message *remove_msg(struct r3964_info *pInfo,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  901) 					struct r3964_client_info *pClient)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  902) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  903) 	struct r3964_message *pMsg = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  904) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  905) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  906) 	if (pClient->first_msg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  907) 		spin_lock_irqsave(&pClient->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  908) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  909) 		pMsg = pClient->first_msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  910) 		pClient->first_msg = pMsg->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  911) 		if (pClient->first_msg == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  912) 			pClient->last_msg = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  913) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  914) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  915) 		pClient->msg_count--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  916) 		if (pMsg->block) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  917) 			remove_client_block(pInfo, pClient);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  918) 			pClient->next_block_to_read = pMsg->block;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  919) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  920) 		spin_unlock_irqrestore(&pClient->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  921) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  922) 	return pMsg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  923) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  924) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  925) static void remove_client_block(struct r3964_info *pInfo,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  926) 				struct r3964_client_info *pClient)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  927) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  928) 	struct r3964_block_header *block;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  929) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  930) 	TRACE_PS("remove_client_block PID %d", pid_nr(pClient->pid));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  931) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  932) 	block = pClient->next_block_to_read;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  933) 	if (block) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  934) 		block->locks--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  935) 		if (block->locks == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  936) 			remove_from_rx_queue(pInfo, block);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  937) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  938) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  939) 	pClient->next_block_to_read = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  940) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  941) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  942) /*************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  943)  * Line discipline routines
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  944)  *************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  945) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  946) static int r3964_open(struct tty_struct *tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  947) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  948) 	struct r3964_info *pInfo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  949) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  950) 	TRACE_L("open");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  951) 	TRACE_L("tty=%p, PID=%d, disc_data=%p",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  952) 		tty, current->pid, tty->disc_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  953) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  954) 	pInfo = kmalloc(sizeof(struct r3964_info), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  955) 	TRACE_M("r3964_open - info kmalloc %p", pInfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  956) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  957) 	if (!pInfo) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  958) 		printk(KERN_ERR "r3964: failed to alloc info structure\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  959) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  960) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  961) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  962) 	pInfo->rx_buf = kmalloc(RX_BUF_SIZE, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  963) 	TRACE_M("r3964_open - rx_buf kmalloc %p", pInfo->rx_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  964) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  965) 	if (!pInfo->rx_buf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  966) 		printk(KERN_ERR "r3964: failed to alloc receive buffer\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  967) 		kfree(pInfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  968) 		TRACE_M("r3964_open - info kfree %p", pInfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  969) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  970) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  971) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  972) 	pInfo->tx_buf = kmalloc(TX_BUF_SIZE, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  973) 	TRACE_M("r3964_open - tx_buf kmalloc %p", pInfo->tx_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  974) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  975) 	if (!pInfo->tx_buf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  976) 		printk(KERN_ERR "r3964: failed to alloc transmit buffer\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  977) 		kfree(pInfo->rx_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  978) 		TRACE_M("r3964_open - rx_buf kfree %p", pInfo->rx_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  979) 		kfree(pInfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  980) 		TRACE_M("r3964_open - info kfree %p", pInfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  981) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  982) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  983) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  984) 	spin_lock_init(&pInfo->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  985) 	mutex_init(&pInfo->read_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  986) 	pInfo->tty = tty;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  987) 	pInfo->priority = R3964_MASTER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  988) 	pInfo->rx_first = pInfo->rx_last = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  989) 	pInfo->tx_first = pInfo->tx_last = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  990) 	pInfo->rx_position = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  991) 	pInfo->tx_position = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  992) 	pInfo->last_rx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  993) 	pInfo->blocks_in_rx_queue = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  994) 	pInfo->firstClient = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  995) 	pInfo->state = R3964_IDLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  996) 	pInfo->flags = R3964_DEBUG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  997) 	pInfo->nRetry = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  998) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  999) 	tty->disc_data = pInfo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) 	tty->receive_room = 65536;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) 	timer_setup(&pInfo->tmr, on_timeout, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) static void r3964_close(struct tty_struct *tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) 	struct r3964_info *pInfo = tty->disc_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) 	struct r3964_client_info *pClient, *pNext;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) 	struct r3964_message *pMsg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) 	struct r3964_block_header *pHeader, *pNextHeader;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) 	TRACE_L("close");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) 	 * Make sure that our task queue isn't activated.  If it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) 	 * is, take it out of the linked list.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) 	del_timer_sync(&pInfo->tmr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) 	/* Remove client-structs and message queues: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) 	pClient = pInfo->firstClient;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) 	while (pClient) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) 		pNext = pClient->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) 		while (pClient->msg_count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) 			pMsg = remove_msg(pInfo, pClient);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) 			if (pMsg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) 				kfree(pMsg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) 				TRACE_M("r3964_close - msg kfree %p", pMsg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) 		put_pid(pClient->pid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) 		kfree(pClient);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) 		TRACE_M("r3964_close - client kfree %p", pClient);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) 		pClient = pNext;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) 	/* Remove jobs from tx_queue: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) 	spin_lock_irqsave(&pInfo->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) 	pHeader = pInfo->tx_first;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) 	pInfo->tx_first = pInfo->tx_last = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) 	spin_unlock_irqrestore(&pInfo->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) 	while (pHeader) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) 		pNextHeader = pHeader->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) 		kfree(pHeader);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) 		pHeader = pNextHeader;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) 	/* Free buffers: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) 	kfree(pInfo->rx_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) 	TRACE_M("r3964_close - rx_buf kfree %p", pInfo->rx_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) 	kfree(pInfo->tx_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) 	TRACE_M("r3964_close - tx_buf kfree %p", pInfo->tx_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) 	kfree(pInfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) 	TRACE_M("r3964_close - info kfree %p", pInfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) static ssize_t r3964_read(struct tty_struct *tty, struct file *file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) 			  unsigned char *kbuf, size_t nr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) 			  void **cookie, unsigned long offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) 	struct r3964_info *pInfo = tty->disc_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) 	struct r3964_client_info *pClient;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) 	struct r3964_message *pMsg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) 	struct r3964_client_message theMsg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) 	TRACE_L("read()");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) 	 *	Internal serialization of reads.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) 	if (file->f_flags & O_NONBLOCK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) 		if (!mutex_trylock(&pInfo->read_lock))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) 			return -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) 		if (mutex_lock_interruptible(&pInfo->read_lock))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) 			return -ERESTARTSYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) 	pClient = findClient(pInfo, task_pid(current));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) 	if (pClient) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) 		pMsg = remove_msg(pInfo, pClient);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) 		if (pMsg == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) 			/* no messages available. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) 			if (tty_io_nonblock(tty, file)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) 				ret = -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) 				goto unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) 			/* block until there is a message: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) 			wait_event_interruptible(tty->read_wait,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) 					(pMsg = remove_msg(pInfo, pClient)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) 		/* If we still haven't got a message, we must have been signalled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) 		if (!pMsg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) 			ret = -EINTR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) 			goto unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) 		/* deliver msg to client process: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) 		theMsg.msg_id = pMsg->msg_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) 		theMsg.arg = pMsg->arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) 		theMsg.error_code = pMsg->error_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) 		ret = sizeof(struct r3964_client_message);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) 		kfree(pMsg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) 		TRACE_M("r3964_read - msg kfree %p", pMsg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) 		memcpy(kbuf, &theMsg, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) 		TRACE_PS("read - return %d", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) 		goto unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) 	ret = -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) 	mutex_unlock(&pInfo->read_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) static ssize_t r3964_write(struct tty_struct *tty, struct file *file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) 			   const unsigned char *data, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) 	struct r3964_info *pInfo = tty->disc_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) 	struct r3964_block_header *pHeader;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) 	struct r3964_client_info *pClient;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) 	unsigned char *new_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) 	TRACE_L("write request, %d characters", count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) /* 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134)  * Verify the pointers 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) 	if (!pInfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) 		return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141)  * Ensure that the caller does not wish to send too much.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) 	if (count > R3964_MTU) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) 		if (pInfo->flags & R3964_DEBUG) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) 			TRACE_L(KERN_WARNING "r3964_write: truncating user "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) 				"packet from %u to mtu %d", count, R3964_MTU);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) 		count = R3964_MTU;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151)  * Allocate a buffer for the data and copy it from the buffer with header prepended
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) 	new_data = kmalloc(count + sizeof(struct r3964_block_header),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) 			GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) 	TRACE_M("r3964_write - kmalloc %p", new_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) 	if (new_data == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) 		if (pInfo->flags & R3964_DEBUG) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) 			printk(KERN_ERR "r3964_write: no memory\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) 		return -ENOSPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) 	pHeader = (struct r3964_block_header *)new_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) 	pHeader->data = new_data + sizeof(struct r3964_block_header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) 	pHeader->length = count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) 	pHeader->locks = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) 	pHeader->owner = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) 	pClient = findClient(pInfo, task_pid(current));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) 	if (pClient) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) 		pHeader->owner = pClient;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) 	memcpy(pHeader->data, data, count);	/* We already verified this */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) 	if (pInfo->flags & R3964_DEBUG) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) 		dump_block(pHeader->data, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181)  * Add buffer to transmit-queue:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) 	add_tx_queue(pInfo, pHeader);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) 	trigger_transmit(pInfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) static int r3964_ioctl(struct tty_struct *tty, struct file *file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) 		unsigned int cmd, unsigned long arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) 	struct r3964_info *pInfo = tty->disc_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) 	if (pInfo == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) 	switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) 	case R3964_ENABLE_SIGNALS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) 		return enable_signals(pInfo, task_pid(current), arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) 	case R3964_SETPRIORITY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) 		if (arg < R3964_MASTER || arg > R3964_SLAVE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) 			return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) 		pInfo->priority = arg & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) 	case R3964_USE_BCC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) 		if (arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) 			pInfo->flags |= R3964_BCC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) 			pInfo->flags &= ~R3964_BCC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) 	case R3964_READ_TELEGRAM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) 		return read_telegram(pInfo, task_pid(current),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) 				(unsigned char __user *)arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) 		return -ENOIOCTLCMD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) #ifdef CONFIG_COMPAT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) static int r3964_compat_ioctl(struct tty_struct *tty, struct file *file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) 		unsigned int cmd, unsigned long arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) 	switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) 	case R3964_ENABLE_SIGNALS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) 	case R3964_SETPRIORITY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) 	case R3964_USE_BCC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) 		return r3964_ioctl(tty, file, cmd, arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) 		return -ENOIOCTLCMD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) static void r3964_set_termios(struct tty_struct *tty, struct ktermios *old)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) 	TRACE_L("set_termios");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) /* Called without the kernel lock held - fine */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) static __poll_t r3964_poll(struct tty_struct *tty, struct file *file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) 			struct poll_table_struct *wait)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) 	struct r3964_info *pInfo = tty->disc_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) 	struct r3964_client_info *pClient;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) 	struct r3964_message *pMsg = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) 	__poll_t result = EPOLLOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) 	TRACE_L("POLL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) 	pClient = findClient(pInfo, task_pid(current));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) 	if (pClient) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) 		poll_wait(file, &tty->read_wait, wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) 		spin_lock_irqsave(&pInfo->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) 		pMsg = pClient->first_msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) 		spin_unlock_irqrestore(&pInfo->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) 		if (pMsg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) 			result |= EPOLLIN | EPOLLRDNORM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) 		result = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) 	return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) static void r3964_receive_buf(struct tty_struct *tty, const unsigned char *cp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) 			char *fp, int count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) 	struct r3964_info *pInfo = tty->disc_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) 	const unsigned char *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) 	char *f, flags = TTY_NORMAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) 	for (i = count, p = cp, f = fp; i; i--, p++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) 		if (f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) 			flags = *f++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) 		if (flags == TTY_NORMAL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) 			receive_char(pInfo, *p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) 			receive_error(pInfo, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) MODULE_ALIAS_LDISC(N_R3964);