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