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