diff options
Diffstat (limited to 'drivers/serial/jsm/jsm_tty.c')
-rw-r--r-- | drivers/serial/jsm/jsm_tty.c | 208 |
1 files changed, 65 insertions, 143 deletions
diff --git a/drivers/serial/jsm/jsm_tty.c b/drivers/serial/jsm/jsm_tty.c index 6fa0d62d6f68..07bf28ca3302 100644 --- a/drivers/serial/jsm/jsm_tty.c +++ b/drivers/serial/jsm/jsm_tty.c | |||
@@ -20,8 +20,10 @@ | |||
20 | * | 20 | * |
21 | * Contact Information: | 21 | * Contact Information: |
22 | * Scott H Kilau <Scott_Kilau@digi.com> | 22 | * Scott H Kilau <Scott_Kilau@digi.com> |
23 | * Wendy Xiong <wendyx@us.ltcfwd.linux.ibm.com> | 23 | * Ananda Venkatarman <mansarov@us.ibm.com> |
24 | * | 24 | * Modifications: |
25 | * 01/19/06: changed jsm_input routine to use the dynamically allocated | ||
26 | * tty_buffer changes. Contributors: Scott Kilau and Ananda V. | ||
25 | ***********************************************************************/ | 27 | ***********************************************************************/ |
26 | #include <linux/tty.h> | 28 | #include <linux/tty.h> |
27 | #include <linux/tty_flip.h> | 29 | #include <linux/tty_flip.h> |
@@ -497,16 +499,16 @@ void jsm_input(struct jsm_channel *ch) | |||
497 | { | 499 | { |
498 | struct jsm_board *bd; | 500 | struct jsm_board *bd; |
499 | struct tty_struct *tp; | 501 | struct tty_struct *tp; |
502 | struct tty_ldisc *ld; | ||
500 | u32 rmask; | 503 | u32 rmask; |
501 | u16 head; | 504 | u16 head; |
502 | u16 tail; | 505 | u16 tail; |
503 | int data_len; | 506 | int data_len; |
504 | unsigned long lock_flags; | 507 | unsigned long lock_flags; |
505 | int flip_len; | 508 | int flip_len = 0; |
506 | int len = 0; | 509 | int len = 0; |
507 | int n = 0; | 510 | int n = 0; |
508 | char *buf = NULL; | 511 | char *buf = NULL; |
509 | char *buf2 = NULL; | ||
510 | int s = 0; | 512 | int s = 0; |
511 | int i = 0; | 513 | int i = 0; |
512 | 514 | ||
@@ -574,56 +576,50 @@ void jsm_input(struct jsm_channel *ch) | |||
574 | 576 | ||
575 | /* | 577 | /* |
576 | * If the rxbuf is empty and we are not throttled, put as much | 578 | * If the rxbuf is empty and we are not throttled, put as much |
577 | * as we can directly into the linux TTY flip buffer. | 579 | * as we can directly into the linux TTY buffer. |
578 | * The jsm_rawreadok case takes advantage of carnal knowledge that | ||
579 | * the char_buf and the flag_buf are next to each other and | ||
580 | * are each of (2 * TTY_FLIPBUF_SIZE) size. | ||
581 | * | 580 | * |
582 | * NOTE: if(!tty->real_raw), the call to ldisc.receive_buf | ||
583 | *actually still uses the flag buffer, so you can't | ||
584 | *use it for input data | ||
585 | */ | 581 | */ |
586 | if (jsm_rawreadok) { | 582 | flip_len = TTY_FLIPBUF_SIZE; |
587 | if (tp->real_raw) | ||
588 | flip_len = MYFLIPLEN; | ||
589 | else | ||
590 | flip_len = 2 * TTY_FLIPBUF_SIZE; | ||
591 | } else | ||
592 | flip_len = TTY_FLIPBUF_SIZE - tp->flip.count; | ||
593 | 583 | ||
594 | len = min(data_len, flip_len); | 584 | len = min(data_len, flip_len); |
595 | len = min(len, (N_TTY_BUF_SIZE - 1) - tp->read_cnt); | 585 | len = min(len, (N_TTY_BUF_SIZE - 1) - tp->read_cnt); |
586 | ld = tty_ldisc_ref(tp); | ||
596 | 587 | ||
597 | if (len <= 0) { | 588 | /* |
598 | spin_unlock_irqrestore(&ch->ch_lock, lock_flags); | 589 | * If the DONT_FLIP flag is on, don't flush our buffer, and act |
599 | jsm_printk(READ, INFO, &ch->ch_bd->pci_dev, "jsm_input 1\n"); | 590 | * like the ld doesn't have any space to put the data right now. |
600 | return; | 591 | */ |
601 | } | 592 | if (test_bit(TTY_DONT_FLIP, &tp->flags)) |
593 | len = 0; | ||
602 | 594 | ||
603 | /* | 595 | /* |
604 | * If we're bypassing flip buffers on rx, we can blast it | 596 | * If we were unable to get a reference to the ld, |
605 | * right into the beginning of the buffer. | 597 | * don't flush our buffer, and act like the ld doesn't |
598 | * have any space to put the data right now. | ||
606 | */ | 599 | */ |
607 | if (jsm_rawreadok) { | 600 | if (!ld) { |
608 | if (tp->real_raw) { | 601 | len = 0; |
609 | if (ch->ch_flags & CH_FLIPBUF_IN_USE) { | ||
610 | jsm_printk(READ, INFO, &ch->ch_bd->pci_dev, | ||
611 | "JSM - FLIPBUF in use. delaying input\n"); | ||
612 | spin_unlock_irqrestore(&ch->ch_lock, lock_flags); | ||
613 | return; | ||
614 | } | ||
615 | ch->ch_flags |= CH_FLIPBUF_IN_USE; | ||
616 | buf = ch->ch_bd->flipbuf; | ||
617 | buf2 = NULL; | ||
618 | } else { | ||
619 | buf = tp->flip.char_buf; | ||
620 | buf2 = tp->flip.flag_buf; | ||
621 | } | ||
622 | } else { | 602 | } else { |
623 | buf = tp->flip.char_buf_ptr; | 603 | /* |
624 | buf2 = tp->flip.flag_buf_ptr; | 604 | * If ld doesn't have a pointer to a receive_buf function, |
605 | * flush the data, then act like the ld doesn't have any | ||
606 | * space to put the data right now. | ||
607 | */ | ||
608 | if (!ld->receive_buf) { | ||
609 | ch->ch_r_head = ch->ch_r_tail; | ||
610 | len = 0; | ||
611 | } | ||
625 | } | 612 | } |
626 | 613 | ||
614 | if (len <= 0) { | ||
615 | spin_unlock_irqrestore(&ch->ch_lock, lock_flags); | ||
616 | jsm_printk(READ, INFO, &ch->ch_bd->pci_dev, "jsm_input 1\n"); | ||
617 | if (ld) | ||
618 | tty_ldisc_deref(ld); | ||
619 | return; | ||
620 | } | ||
621 | |||
622 | len = tty_buffer_request_room(tp, len); | ||
627 | n = len; | 623 | n = len; |
628 | 624 | ||
629 | /* | 625 | /* |
@@ -638,121 +634,47 @@ void jsm_input(struct jsm_channel *ch) | |||
638 | if (s <= 0) | 634 | if (s <= 0) |
639 | break; | 635 | break; |
640 | 636 | ||
641 | memcpy(buf, ch->ch_rqueue + tail, s); | 637 | /* |
642 | 638 | * If conditions are such that ld needs to see all | |
643 | /* buf2 is only set when port isn't raw */ | 639 | * UART errors, we will have to walk each character |
644 | if (buf2) | 640 | * and error byte and send them to the buffer one at |
645 | memcpy(buf2, ch->ch_equeue + tail, s); | 641 | * a time. |
646 | 642 | */ | |
647 | tail += s; | ||
648 | buf += s; | ||
649 | if (buf2) | ||
650 | buf2 += s; | ||
651 | n -= s; | ||
652 | /* Flip queue if needed */ | ||
653 | tail &= rmask; | ||
654 | } | ||
655 | 643 | ||
656 | /* | ||
657 | * In high performance mode, we don't have to update | ||
658 | * flag_buf or any of the counts or pointers into flip buf. | ||
659 | */ | ||
660 | if (!jsm_rawreadok) { | ||
661 | if (I_PARMRK(tp) || I_BRKINT(tp) || I_INPCK(tp)) { | 644 | if (I_PARMRK(tp) || I_BRKINT(tp) || I_INPCK(tp)) { |
662 | for (i = 0; i < len; i++) { | 645 | for (i = 0; i < s; i++) { |
663 | /* | 646 | /* |
664 | * Give the Linux ld the flags in the | 647 | * Give the Linux ld the flags in the |
665 | * format it likes. | 648 | * format it likes. |
666 | */ | 649 | */ |
667 | if (tp->flip.flag_buf_ptr[i] & UART_LSR_BI) | 650 | if (*(ch->ch_equeue +tail +i) & UART_LSR_BI) |
668 | tp->flip.flag_buf_ptr[i] = TTY_BREAK; | 651 | tty_insert_flip_char(tp, *(ch->ch_rqueue +tail +i), TTY_BREAK); |
669 | else if (tp->flip.flag_buf_ptr[i] & UART_LSR_PE) | 652 | else if (*(ch->ch_equeue +tail +i) & UART_LSR_PE) |
670 | tp->flip.flag_buf_ptr[i] = TTY_PARITY; | 653 | tty_insert_flip_char(tp, *(ch->ch_rqueue +tail +i), TTY_PARITY); |
671 | else if (tp->flip.flag_buf_ptr[i] & UART_LSR_FE) | 654 | else if (*(ch->ch_equeue +tail +i) & UART_LSR_FE) |
672 | tp->flip.flag_buf_ptr[i] = TTY_FRAME; | 655 | tty_insert_flip_char(tp, *(ch->ch_rqueue +tail +i), TTY_FRAME); |
673 | else | 656 | else |
674 | tp->flip.flag_buf_ptr[i] = TTY_NORMAL; | 657 | tty_insert_flip_char(tp, *(ch->ch_rqueue +tail +i), TTY_NORMAL); |
675 | } | 658 | } |
676 | } else { | 659 | } else { |
677 | memset(tp->flip.flag_buf_ptr, 0, len); | 660 | tty_insert_flip_string(tp, ch->ch_rqueue + tail, s) ; |
678 | } | 661 | } |
679 | 662 | tail += s; | |
680 | tp->flip.char_buf_ptr += len; | 663 | n -= s; |
681 | tp->flip.flag_buf_ptr += len; | 664 | /* Flip queue if needed */ |
682 | tp->flip.count += len; | 665 | tail &= rmask; |
683 | } | ||
684 | else if (!tp->real_raw) { | ||
685 | if (I_PARMRK(tp) || I_BRKINT(tp) || I_INPCK(tp)) { | ||
686 | for (i = 0; i < len; i++) { | ||
687 | /* | ||
688 | * Give the Linux ld the flags in the | ||
689 | * format it likes. | ||
690 | */ | ||
691 | if (tp->flip.flag_buf_ptr[i] & UART_LSR_BI) | ||
692 | tp->flip.flag_buf_ptr[i] = TTY_BREAK; | ||
693 | else if (tp->flip.flag_buf_ptr[i] & UART_LSR_PE) | ||
694 | tp->flip.flag_buf_ptr[i] = TTY_PARITY; | ||
695 | else if (tp->flip.flag_buf_ptr[i] & UART_LSR_FE) | ||
696 | tp->flip.flag_buf_ptr[i] = TTY_FRAME; | ||
697 | else | ||
698 | tp->flip.flag_buf_ptr[i] = TTY_NORMAL; | ||
699 | } | ||
700 | } else | ||
701 | memset(tp->flip.flag_buf, 0, len); | ||
702 | } | 666 | } |
703 | 667 | ||
704 | /* | 668 | ch->ch_r_tail = tail & rmask; |
705 | * If we're doing raw reads, jam it right into the | 669 | ch->ch_e_tail = tail & rmask; |
706 | * line disc bypassing the flip buffers. | 670 | jsm_check_queue_flow_control(ch); |
707 | */ | 671 | spin_unlock_irqrestore(&ch->ch_lock, lock_flags); |
708 | if (jsm_rawreadok) { | ||
709 | if (tp->real_raw) { | ||
710 | ch->ch_r_tail = tail & rmask; | ||
711 | ch->ch_e_tail = tail & rmask; | ||
712 | |||
713 | jsm_check_queue_flow_control(ch); | ||
714 | |||
715 | /* !!! WE *MUST* LET GO OF ALL LOCKS BEFORE CALLING RECEIVE BUF !!! */ | ||
716 | 672 | ||
717 | spin_unlock_irqrestore(&ch->ch_lock, lock_flags); | 673 | /* Tell the tty layer its okay to "eat" the data now */ |
674 | tty_flip_buffer_push(tp); | ||
718 | 675 | ||
719 | jsm_printk(READ, INFO, &ch->ch_bd->pci_dev, | 676 | if (ld) |
720 | "jsm_input. %d real_raw len:%d calling receive_buf for board %d\n", | 677 | tty_ldisc_deref(ld); |
721 | __LINE__, len, ch->ch_bd->boardnum); | ||
722 | tp->ldisc.receive_buf(tp, ch->ch_bd->flipbuf, NULL, len); | ||
723 | |||
724 | /* Allow use of channel flip buffer again */ | ||
725 | spin_lock_irqsave(&ch->ch_lock, lock_flags); | ||
726 | ch->ch_flags &= ~CH_FLIPBUF_IN_USE; | ||
727 | spin_unlock_irqrestore(&ch->ch_lock, lock_flags); | ||
728 | |||
729 | } else { | ||
730 | ch->ch_r_tail = tail & rmask; | ||
731 | ch->ch_e_tail = tail & rmask; | ||
732 | |||
733 | jsm_check_queue_flow_control(ch); | ||
734 | |||
735 | /* !!! WE *MUST* LET GO OF ALL LOCKS BEFORE CALLING RECEIVE BUF !!! */ | ||
736 | spin_unlock_irqrestore(&ch->ch_lock, lock_flags); | ||
737 | |||
738 | jsm_printk(READ, INFO, &ch->ch_bd->pci_dev, | ||
739 | "jsm_input. %d not real_raw len:%d calling receive_buf for board %d\n", | ||
740 | __LINE__, len, ch->ch_bd->boardnum); | ||
741 | |||
742 | tp->ldisc.receive_buf(tp, tp->flip.char_buf, tp->flip.flag_buf, len); | ||
743 | } | ||
744 | } else { | ||
745 | ch->ch_r_tail = tail & rmask; | ||
746 | ch->ch_e_tail = tail & rmask; | ||
747 | |||
748 | jsm_check_queue_flow_control(ch); | ||
749 | |||
750 | spin_unlock_irqrestore(&ch->ch_lock, lock_flags); | ||
751 | |||
752 | jsm_printk(READ, INFO, &ch->ch_bd->pci_dev, | ||
753 | "jsm_input. %d not jsm_read raw okay scheduling flip\n", __LINE__); | ||
754 | tty_schedule_flip(tp); | ||
755 | } | ||
756 | 678 | ||
757 | jsm_printk(IOCTL, INFO, &ch->ch_bd->pci_dev, "finish\n"); | 679 | jsm_printk(IOCTL, INFO, &ch->ch_bd->pci_dev, "finish\n"); |
758 | } | 680 | } |