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