^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);