Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v5.4 1287 lines 32 kB view raw
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 unsigned char __user * 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 /* FALLTHROUGH */ 609 case R3964_IDLE: 610 if (c == STX) { 611 /* Prevent rx_queue from overflow: */ 612 if (pInfo->blocks_in_rx_queue >= 613 R3964_MAX_BLOCKS_IN_RX_QUEUE) { 614 TRACE_PE("IDLE - got STX but no space in " 615 "rx_queue!"); 616 pInfo->state = R3964_WAIT_FOR_RX_BUF; 617 mod_timer(&pInfo->tmr, 618 jiffies + R3964_TO_NO_BUF); 619 break; 620 } 621start_receiving: 622 /* Ok, start receiving: */ 623 TRACE_PS("IDLE - got STX"); 624 pInfo->rx_position = 0; 625 pInfo->last_rx = 0; 626 pInfo->flags &= ~R3964_ERROR; 627 pInfo->state = R3964_RECEIVING; 628 mod_timer(&pInfo->tmr, jiffies + R3964_TO_ZVZ); 629 pInfo->nRetry = 0; 630 put_char(pInfo, DLE); 631 flush(pInfo); 632 pInfo->bcc = 0; 633 } 634 break; 635 case R3964_RECEIVING: 636 if (pInfo->rx_position < RX_BUF_SIZE) { 637 pInfo->bcc ^= c; 638 639 if (c == DLE) { 640 if (pInfo->last_rx == DLE) { 641 pInfo->last_rx = 0; 642 goto char_to_buf; 643 } 644 pInfo->last_rx = DLE; 645 break; 646 } else if ((c == ETX) && (pInfo->last_rx == DLE)) { 647 if (pInfo->flags & R3964_BCC) { 648 pInfo->state = R3964_WAIT_FOR_BCC; 649 mod_timer(&pInfo->tmr, 650 jiffies + R3964_TO_ZVZ); 651 } else { 652 on_receive_block(pInfo); 653 } 654 } else { 655 pInfo->last_rx = c; 656char_to_buf: 657 pInfo->rx_buf[pInfo->rx_position++] = c; 658 mod_timer(&pInfo->tmr, jiffies + R3964_TO_ZVZ); 659 } 660 } 661 /* else: overflow-msg? BUF_SIZE>MTU; should not happen? */ 662 break; 663 case R3964_WAIT_FOR_BCC: 664 pInfo->last_rx = c; 665 on_receive_block(pInfo); 666 break; 667 } 668} 669 670static void receive_error(struct r3964_info *pInfo, const char flag) 671{ 672 switch (flag) { 673 case TTY_NORMAL: 674 break; 675 case TTY_BREAK: 676 TRACE_PE("received break"); 677 pInfo->flags |= R3964_BREAK; 678 break; 679 case TTY_PARITY: 680 TRACE_PE("parity error"); 681 pInfo->flags |= R3964_PARITY; 682 break; 683 case TTY_FRAME: 684 TRACE_PE("frame error"); 685 pInfo->flags |= R3964_FRAME; 686 break; 687 case TTY_OVERRUN: 688 TRACE_PE("frame overrun"); 689 pInfo->flags |= R3964_OVERRUN; 690 break; 691 default: 692 TRACE_PE("receive_error - unknown flag %d", flag); 693 pInfo->flags |= R3964_UNKNOWN; 694 break; 695 } 696} 697 698static void on_timeout(struct timer_list *t) 699{ 700 struct r3964_info *pInfo = from_timer(pInfo, t, tmr); 701 702 switch (pInfo->state) { 703 case R3964_TX_REQUEST: 704 TRACE_PE("TX_REQUEST - timeout"); 705 retry_transmit(pInfo); 706 break; 707 case R3964_WAIT_ZVZ_BEFORE_TX_RETRY: 708 put_char(pInfo, NAK); 709 flush(pInfo); 710 retry_transmit(pInfo); 711 break; 712 case R3964_WAIT_FOR_TX_ACK: 713 TRACE_PE("WAIT_FOR_TX_ACK - timeout"); 714 retry_transmit(pInfo); 715 break; 716 case R3964_WAIT_FOR_RX_BUF: 717 TRACE_PE("WAIT_FOR_RX_BUF - timeout"); 718 put_char(pInfo, NAK); 719 flush(pInfo); 720 pInfo->state = R3964_IDLE; 721 break; 722 case R3964_RECEIVING: 723 TRACE_PE("RECEIVING - timeout after %d chars", 724 pInfo->rx_position); 725 put_char(pInfo, NAK); 726 flush(pInfo); 727 pInfo->state = R3964_IDLE; 728 break; 729 case R3964_WAIT_FOR_RX_REPEAT: 730 TRACE_PE("WAIT_FOR_RX_REPEAT - timeout"); 731 pInfo->state = R3964_IDLE; 732 break; 733 case R3964_WAIT_FOR_BCC: 734 TRACE_PE("WAIT_FOR_BCC - timeout"); 735 put_char(pInfo, NAK); 736 flush(pInfo); 737 pInfo->state = R3964_IDLE; 738 break; 739 } 740} 741 742static struct r3964_client_info *findClient(struct r3964_info *pInfo, 743 struct pid *pid) 744{ 745 struct r3964_client_info *pClient; 746 747 for (pClient = pInfo->firstClient; pClient; pClient = pClient->next) { 748 if (pClient->pid == pid) { 749 return pClient; 750 } 751 } 752 return NULL; 753} 754 755static int enable_signals(struct r3964_info *pInfo, struct pid *pid, int arg) 756{ 757 struct r3964_client_info *pClient; 758 struct r3964_client_info **ppClient; 759 struct r3964_message *pMsg; 760 761 if ((arg & R3964_SIG_ALL) == 0) { 762 /* Remove client from client list */ 763 for (ppClient = &pInfo->firstClient; *ppClient; 764 ppClient = &(*ppClient)->next) { 765 pClient = *ppClient; 766 767 if (pClient->pid == pid) { 768 TRACE_PS("removing client %d from client list", 769 pid_nr(pid)); 770 *ppClient = pClient->next; 771 while (pClient->msg_count) { 772 pMsg = remove_msg(pInfo, pClient); 773 if (pMsg) { 774 kfree(pMsg); 775 TRACE_M("enable_signals - msg " 776 "kfree %p", pMsg); 777 } 778 } 779 put_pid(pClient->pid); 780 kfree(pClient); 781 TRACE_M("enable_signals - kfree %p", pClient); 782 return 0; 783 } 784 } 785 return -EINVAL; 786 } else { 787 pClient = findClient(pInfo, pid); 788 if (pClient) { 789 /* update signal options */ 790 pClient->sig_flags = arg; 791 } else { 792 /* add client to client list */ 793 pClient = kmalloc(sizeof(struct r3964_client_info), 794 GFP_KERNEL); 795 TRACE_M("enable_signals - kmalloc %p", pClient); 796 if (pClient == NULL) 797 return -ENOMEM; 798 799 TRACE_PS("add client %d to client list", pid_nr(pid)); 800 spin_lock_init(&pClient->lock); 801 pClient->sig_flags = arg; 802 pClient->pid = get_pid(pid); 803 pClient->next = pInfo->firstClient; 804 pClient->first_msg = NULL; 805 pClient->last_msg = NULL; 806 pClient->next_block_to_read = NULL; 807 pClient->msg_count = 0; 808 pInfo->firstClient = pClient; 809 } 810 } 811 812 return 0; 813} 814 815static int read_telegram(struct r3964_info *pInfo, struct pid *pid, 816 unsigned char __user * buf) 817{ 818 struct r3964_client_info *pClient; 819 struct r3964_block_header *block; 820 821 if (!buf) { 822 return -EINVAL; 823 } 824 825 pClient = findClient(pInfo, pid); 826 if (pClient == NULL) { 827 return -EINVAL; 828 } 829 830 block = pClient->next_block_to_read; 831 if (!block) { 832 return 0; 833 } else { 834 if (copy_to_user(buf, block->data, block->length)) 835 return -EFAULT; 836 837 remove_client_block(pInfo, pClient); 838 return block->length; 839 } 840 841 return -EINVAL; 842} 843 844static void add_msg(struct r3964_client_info *pClient, int msg_id, int arg, 845 int error_code, struct r3964_block_header *pBlock) 846{ 847 struct r3964_message *pMsg; 848 unsigned long flags; 849 850 if (pClient->msg_count < R3964_MAX_MSG_COUNT - 1) { 851queue_the_message: 852 853 pMsg = kmalloc(sizeof(struct r3964_message), 854 error_code ? GFP_ATOMIC : GFP_KERNEL); 855 TRACE_M("add_msg - kmalloc %p", pMsg); 856 if (pMsg == NULL) { 857 return; 858 } 859 860 spin_lock_irqsave(&pClient->lock, flags); 861 862 pMsg->msg_id = msg_id; 863 pMsg->arg = arg; 864 pMsg->error_code = error_code; 865 pMsg->block = pBlock; 866 pMsg->next = NULL; 867 868 if (pClient->last_msg == NULL) { 869 pClient->first_msg = pClient->last_msg = pMsg; 870 } else { 871 pClient->last_msg->next = pMsg; 872 pClient->last_msg = pMsg; 873 } 874 875 pClient->msg_count++; 876 877 if (pBlock != NULL) { 878 pBlock->locks++; 879 } 880 spin_unlock_irqrestore(&pClient->lock, flags); 881 } else { 882 if ((pClient->last_msg->msg_id == R3964_MSG_ACK) 883 && (pClient->last_msg->error_code == R3964_OVERFLOW)) { 884 pClient->last_msg->arg++; 885 TRACE_PE("add_msg - inc prev OVERFLOW-msg"); 886 } else { 887 msg_id = R3964_MSG_ACK; 888 arg = 0; 889 error_code = R3964_OVERFLOW; 890 pBlock = NULL; 891 TRACE_PE("add_msg - queue OVERFLOW-msg"); 892 goto queue_the_message; 893 } 894 } 895 /* Send SIGIO signal to client process: */ 896 if (pClient->sig_flags & R3964_USE_SIGIO) { 897 kill_pid(pClient->pid, SIGIO, 1); 898 } 899} 900 901static struct r3964_message *remove_msg(struct r3964_info *pInfo, 902 struct r3964_client_info *pClient) 903{ 904 struct r3964_message *pMsg = NULL; 905 unsigned long flags; 906 907 if (pClient->first_msg) { 908 spin_lock_irqsave(&pClient->lock, flags); 909 910 pMsg = pClient->first_msg; 911 pClient->first_msg = pMsg->next; 912 if (pClient->first_msg == NULL) { 913 pClient->last_msg = NULL; 914 } 915 916 pClient->msg_count--; 917 if (pMsg->block) { 918 remove_client_block(pInfo, pClient); 919 pClient->next_block_to_read = pMsg->block; 920 } 921 spin_unlock_irqrestore(&pClient->lock, flags); 922 } 923 return pMsg; 924} 925 926static void remove_client_block(struct r3964_info *pInfo, 927 struct r3964_client_info *pClient) 928{ 929 struct r3964_block_header *block; 930 931 TRACE_PS("remove_client_block PID %d", pid_nr(pClient->pid)); 932 933 block = pClient->next_block_to_read; 934 if (block) { 935 block->locks--; 936 if (block->locks == 0) { 937 remove_from_rx_queue(pInfo, block); 938 } 939 } 940 pClient->next_block_to_read = NULL; 941} 942 943/************************************************************* 944 * Line discipline routines 945 *************************************************************/ 946 947static int r3964_open(struct tty_struct *tty) 948{ 949 struct r3964_info *pInfo; 950 951 TRACE_L("open"); 952 TRACE_L("tty=%p, PID=%d, disc_data=%p", 953 tty, current->pid, tty->disc_data); 954 955 pInfo = kmalloc(sizeof(struct r3964_info), GFP_KERNEL); 956 TRACE_M("r3964_open - info kmalloc %p", pInfo); 957 958 if (!pInfo) { 959 printk(KERN_ERR "r3964: failed to alloc info structure\n"); 960 return -ENOMEM; 961 } 962 963 pInfo->rx_buf = kmalloc(RX_BUF_SIZE, GFP_KERNEL); 964 TRACE_M("r3964_open - rx_buf kmalloc %p", pInfo->rx_buf); 965 966 if (!pInfo->rx_buf) { 967 printk(KERN_ERR "r3964: failed to alloc receive buffer\n"); 968 kfree(pInfo); 969 TRACE_M("r3964_open - info kfree %p", pInfo); 970 return -ENOMEM; 971 } 972 973 pInfo->tx_buf = kmalloc(TX_BUF_SIZE, GFP_KERNEL); 974 TRACE_M("r3964_open - tx_buf kmalloc %p", pInfo->tx_buf); 975 976 if (!pInfo->tx_buf) { 977 printk(KERN_ERR "r3964: failed to alloc transmit buffer\n"); 978 kfree(pInfo->rx_buf); 979 TRACE_M("r3964_open - rx_buf kfree %p", pInfo->rx_buf); 980 kfree(pInfo); 981 TRACE_M("r3964_open - info kfree %p", pInfo); 982 return -ENOMEM; 983 } 984 985 spin_lock_init(&pInfo->lock); 986 mutex_init(&pInfo->read_lock); 987 pInfo->tty = tty; 988 pInfo->priority = R3964_MASTER; 989 pInfo->rx_first = pInfo->rx_last = NULL; 990 pInfo->tx_first = pInfo->tx_last = NULL; 991 pInfo->rx_position = 0; 992 pInfo->tx_position = 0; 993 pInfo->last_rx = 0; 994 pInfo->blocks_in_rx_queue = 0; 995 pInfo->firstClient = NULL; 996 pInfo->state = R3964_IDLE; 997 pInfo->flags = R3964_DEBUG; 998 pInfo->nRetry = 0; 999 1000 tty->disc_data = pInfo; 1001 tty->receive_room = 65536; 1002 1003 timer_setup(&pInfo->tmr, on_timeout, 0); 1004 1005 return 0; 1006} 1007 1008static void r3964_close(struct tty_struct *tty) 1009{ 1010 struct r3964_info *pInfo = tty->disc_data; 1011 struct r3964_client_info *pClient, *pNext; 1012 struct r3964_message *pMsg; 1013 struct r3964_block_header *pHeader, *pNextHeader; 1014 unsigned long flags; 1015 1016 TRACE_L("close"); 1017 1018 /* 1019 * Make sure that our task queue isn't activated. If it 1020 * is, take it out of the linked list. 1021 */ 1022 del_timer_sync(&pInfo->tmr); 1023 1024 /* Remove client-structs and message queues: */ 1025 pClient = pInfo->firstClient; 1026 while (pClient) { 1027 pNext = pClient->next; 1028 while (pClient->msg_count) { 1029 pMsg = remove_msg(pInfo, pClient); 1030 if (pMsg) { 1031 kfree(pMsg); 1032 TRACE_M("r3964_close - msg kfree %p", pMsg); 1033 } 1034 } 1035 put_pid(pClient->pid); 1036 kfree(pClient); 1037 TRACE_M("r3964_close - client kfree %p", pClient); 1038 pClient = pNext; 1039 } 1040 /* Remove jobs from tx_queue: */ 1041 spin_lock_irqsave(&pInfo->lock, flags); 1042 pHeader = pInfo->tx_first; 1043 pInfo->tx_first = pInfo->tx_last = NULL; 1044 spin_unlock_irqrestore(&pInfo->lock, flags); 1045 1046 while (pHeader) { 1047 pNextHeader = pHeader->next; 1048 kfree(pHeader); 1049 pHeader = pNextHeader; 1050 } 1051 1052 /* Free buffers: */ 1053 kfree(pInfo->rx_buf); 1054 TRACE_M("r3964_close - rx_buf kfree %p", pInfo->rx_buf); 1055 kfree(pInfo->tx_buf); 1056 TRACE_M("r3964_close - tx_buf kfree %p", pInfo->tx_buf); 1057 kfree(pInfo); 1058 TRACE_M("r3964_close - info kfree %p", pInfo); 1059} 1060 1061static ssize_t r3964_read(struct tty_struct *tty, struct file *file, 1062 unsigned char __user * buf, size_t nr) 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 if (copy_to_user(buf, &theMsg, ret)) { 1114 ret = -EFAULT; 1115 goto unlock; 1116 } 1117 1118 TRACE_PS("read - return %d", ret); 1119 goto unlock; 1120 } 1121 ret = -EPERM; 1122unlock: 1123 mutex_unlock(&pInfo->read_lock); 1124 return ret; 1125} 1126 1127static ssize_t r3964_write(struct tty_struct *tty, struct file *file, 1128 const unsigned char *data, size_t count) 1129{ 1130 struct r3964_info *pInfo = tty->disc_data; 1131 struct r3964_block_header *pHeader; 1132 struct r3964_client_info *pClient; 1133 unsigned char *new_data; 1134 1135 TRACE_L("write request, %d characters", count); 1136/* 1137 * Verify the pointers 1138 */ 1139 1140 if (!pInfo) 1141 return -EIO; 1142 1143/* 1144 * Ensure that the caller does not wish to send too much. 1145 */ 1146 if (count > R3964_MTU) { 1147 if (pInfo->flags & R3964_DEBUG) { 1148 TRACE_L(KERN_WARNING "r3964_write: truncating user " 1149 "packet from %u to mtu %d", count, R3964_MTU); 1150 } 1151 count = R3964_MTU; 1152 } 1153/* 1154 * Allocate a buffer for the data and copy it from the buffer with header prepended 1155 */ 1156 new_data = kmalloc(count + sizeof(struct r3964_block_header), 1157 GFP_KERNEL); 1158 TRACE_M("r3964_write - kmalloc %p", new_data); 1159 if (new_data == NULL) { 1160 if (pInfo->flags & R3964_DEBUG) { 1161 printk(KERN_ERR "r3964_write: no memory\n"); 1162 } 1163 return -ENOSPC; 1164 } 1165 1166 pHeader = (struct r3964_block_header *)new_data; 1167 pHeader->data = new_data + sizeof(struct r3964_block_header); 1168 pHeader->length = count; 1169 pHeader->locks = 0; 1170 pHeader->owner = NULL; 1171 1172 pClient = findClient(pInfo, task_pid(current)); 1173 if (pClient) { 1174 pHeader->owner = pClient; 1175 } 1176 1177 memcpy(pHeader->data, data, count); /* We already verified this */ 1178 1179 if (pInfo->flags & R3964_DEBUG) { 1180 dump_block(pHeader->data, count); 1181 } 1182 1183/* 1184 * Add buffer to transmit-queue: 1185 */ 1186 add_tx_queue(pInfo, pHeader); 1187 trigger_transmit(pInfo); 1188 1189 return 0; 1190} 1191 1192static int r3964_ioctl(struct tty_struct *tty, struct file *file, 1193 unsigned int cmd, unsigned long arg) 1194{ 1195 struct r3964_info *pInfo = tty->disc_data; 1196 if (pInfo == NULL) 1197 return -EINVAL; 1198 switch (cmd) { 1199 case R3964_ENABLE_SIGNALS: 1200 return enable_signals(pInfo, task_pid(current), arg); 1201 case R3964_SETPRIORITY: 1202 if (arg < R3964_MASTER || arg > R3964_SLAVE) 1203 return -EINVAL; 1204 pInfo->priority = arg & 0xff; 1205 return 0; 1206 case R3964_USE_BCC: 1207 if (arg) 1208 pInfo->flags |= R3964_BCC; 1209 else 1210 pInfo->flags &= ~R3964_BCC; 1211 return 0; 1212 case R3964_READ_TELEGRAM: 1213 return read_telegram(pInfo, task_pid(current), 1214 (unsigned char __user *)arg); 1215 default: 1216 return -ENOIOCTLCMD; 1217 } 1218} 1219 1220#ifdef CONFIG_COMPAT 1221static int r3964_compat_ioctl(struct tty_struct *tty, struct file *file, 1222 unsigned int cmd, unsigned long arg) 1223{ 1224 switch (cmd) { 1225 case R3964_ENABLE_SIGNALS: 1226 case R3964_SETPRIORITY: 1227 case R3964_USE_BCC: 1228 return r3964_ioctl(tty, file, cmd, arg); 1229 default: 1230 return -ENOIOCTLCMD; 1231 } 1232} 1233#endif 1234 1235static void r3964_set_termios(struct tty_struct *tty, struct ktermios *old) 1236{ 1237 TRACE_L("set_termios"); 1238} 1239 1240/* Called without the kernel lock held - fine */ 1241static __poll_t r3964_poll(struct tty_struct *tty, struct file *file, 1242 struct poll_table_struct *wait) 1243{ 1244 struct r3964_info *pInfo = tty->disc_data; 1245 struct r3964_client_info *pClient; 1246 struct r3964_message *pMsg = NULL; 1247 unsigned long flags; 1248 __poll_t result = EPOLLOUT; 1249 1250 TRACE_L("POLL"); 1251 1252 pClient = findClient(pInfo, task_pid(current)); 1253 if (pClient) { 1254 poll_wait(file, &tty->read_wait, wait); 1255 spin_lock_irqsave(&pInfo->lock, flags); 1256 pMsg = pClient->first_msg; 1257 spin_unlock_irqrestore(&pInfo->lock, flags); 1258 if (pMsg) 1259 result |= EPOLLIN | EPOLLRDNORM; 1260 } else { 1261 result = -EINVAL; 1262 } 1263 return result; 1264} 1265 1266static void r3964_receive_buf(struct tty_struct *tty, const unsigned char *cp, 1267 char *fp, int count) 1268{ 1269 struct r3964_info *pInfo = tty->disc_data; 1270 const unsigned char *p; 1271 char *f, flags = TTY_NORMAL; 1272 int i; 1273 1274 for (i = count, p = cp, f = fp; i; i--, p++) { 1275 if (f) 1276 flags = *f++; 1277 if (flags == TTY_NORMAL) { 1278 receive_char(pInfo, *p); 1279 } else { 1280 receive_error(pInfo, flags); 1281 } 1282 1283 } 1284} 1285 1286MODULE_LICENSE("GPL"); 1287MODULE_ALIAS_LDISC(N_R3964);