History

tty: remove broken r3964 line discipline

Noone stepped up in the past two years since it was marked as BROKEN by commit c7084edc3f6d (tty: mark Siemens R3964 line discipline as BROKEN). Remove the line discipline for good. Three remarks: * we remove also the uapi header (as noone is able to use that interface anyway) * we do *not* remove the N_R3964 constant definition from tty.h, so it remains reserved. * in_interrupt() check is now removed from vt's con_put_char. Noone else calls tty_operations::put_char from interrupt context.

Jiri Slaby committed 5 years ago

Commit ed5aecd1 parent d7e325a7 files · +0 −1574Browse files

Unified · Split

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