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