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