aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/char/tty3270.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/char/tty3270.c')
-rw-r--r--drivers/s390/char/tty3270.c121
1 files changed, 56 insertions, 65 deletions
diff --git a/drivers/s390/char/tty3270.c b/drivers/s390/char/tty3270.c
index b43445a55cb6..10ec690197cb 100644
--- a/drivers/s390/char/tty3270.c
+++ b/drivers/s390/char/tty3270.c
@@ -61,7 +61,7 @@ struct tty3270_line {
61 */ 61 */
62struct tty3270 { 62struct tty3270 {
63 struct raw3270_view view; 63 struct raw3270_view view;
64 struct tty_struct *tty; /* Pointer to tty structure */ 64 struct tty_port port;
65 void **freemem_pages; /* Array of pages used for freemem. */ 65 void **freemem_pages; /* Array of pages used for freemem. */
66 struct list_head freemem; /* List of free memory for strings. */ 66 struct list_head freemem; /* List of free memory for strings. */
67 67
@@ -324,9 +324,8 @@ tty3270_blank_line(struct tty3270 *tp)
324static void 324static void
325tty3270_write_callback(struct raw3270_request *rq, void *data) 325tty3270_write_callback(struct raw3270_request *rq, void *data)
326{ 326{
327 struct tty3270 *tp; 327 struct tty3270 *tp = container_of(rq->view, struct tty3270, view);
328 328
329 tp = (struct tty3270 *) rq->view;
330 if (rq->rc != 0) { 329 if (rq->rc != 0) {
331 /* Write wasn't successful. Refresh all. */ 330 /* Write wasn't successful. Refresh all. */
332 tp->update_flags = TTY_UPDATE_ALL; 331 tp->update_flags = TTY_UPDATE_ALL;
@@ -450,10 +449,9 @@ tty3270_rcl_add(struct tty3270 *tp, char *input, int len)
450static void 449static void
451tty3270_rcl_backward(struct kbd_data *kbd) 450tty3270_rcl_backward(struct kbd_data *kbd)
452{ 451{
453 struct tty3270 *tp; 452 struct tty3270 *tp = container_of(kbd->port, struct tty3270, port);
454 struct string *s; 453 struct string *s;
455 454
456 tp = kbd->tty->driver_data;
457 spin_lock_bh(&tp->view.lock); 455 spin_lock_bh(&tp->view.lock);
458 if (tp->inattr == TF_INPUT) { 456 if (tp->inattr == TF_INPUT) {
459 if (tp->rcl_walk && tp->rcl_walk->prev != &tp->rcl_lines) 457 if (tp->rcl_walk && tp->rcl_walk->prev != &tp->rcl_lines)
@@ -478,9 +476,8 @@ tty3270_rcl_backward(struct kbd_data *kbd)
478static void 476static void
479tty3270_exit_tty(struct kbd_data *kbd) 477tty3270_exit_tty(struct kbd_data *kbd)
480{ 478{
481 struct tty3270 *tp; 479 struct tty3270 *tp = container_of(kbd->port, struct tty3270, port);
482 480
483 tp = kbd->tty->driver_data;
484 raw3270_deactivate_view(&tp->view); 481 raw3270_deactivate_view(&tp->view);
485} 482}
486 483
@@ -490,10 +487,9 @@ tty3270_exit_tty(struct kbd_data *kbd)
490static void 487static void
491tty3270_scroll_forward(struct kbd_data *kbd) 488tty3270_scroll_forward(struct kbd_data *kbd)
492{ 489{
493 struct tty3270 *tp; 490 struct tty3270 *tp = container_of(kbd->port, struct tty3270, port);
494 int nr_up; 491 int nr_up;
495 492
496 tp = kbd->tty->driver_data;
497 spin_lock_bh(&tp->view.lock); 493 spin_lock_bh(&tp->view.lock);
498 nr_up = tp->nr_up - tp->view.rows + 2; 494 nr_up = tp->nr_up - tp->view.rows + 2;
499 if (nr_up < 0) 495 if (nr_up < 0)
@@ -513,10 +509,9 @@ tty3270_scroll_forward(struct kbd_data *kbd)
513static void 509static void
514tty3270_scroll_backward(struct kbd_data *kbd) 510tty3270_scroll_backward(struct kbd_data *kbd)
515{ 511{
516 struct tty3270 *tp; 512 struct tty3270 *tp = container_of(kbd->port, struct tty3270, port);
517 int nr_up; 513 int nr_up;
518 514
519 tp = kbd->tty->driver_data;
520 spin_lock_bh(&tp->view.lock); 515 spin_lock_bh(&tp->view.lock);
521 nr_up = tp->nr_up + tp->view.rows - 2; 516 nr_up = tp->nr_up + tp->view.rows - 2;
522 if (nr_up + tp->view.rows - 2 > tp->nr_lines) 517 if (nr_up + tp->view.rows - 2 > tp->nr_lines)
@@ -537,11 +532,10 @@ static void
537tty3270_read_tasklet(struct raw3270_request *rrq) 532tty3270_read_tasklet(struct raw3270_request *rrq)
538{ 533{
539 static char kreset_data = TW_KR; 534 static char kreset_data = TW_KR;
540 struct tty3270 *tp; 535 struct tty3270 *tp = container_of(rrq->view, struct tty3270, view);
541 char *input; 536 char *input;
542 int len; 537 int len;
543 538
544 tp = (struct tty3270 *) rrq->view;
545 spin_lock_bh(&tp->view.lock); 539 spin_lock_bh(&tp->view.lock);
546 /* 540 /*
547 * Two AID keys are special: For 0x7d (enter) the input line 541 * Two AID keys are special: For 0x7d (enter) the input line
@@ -577,13 +571,10 @@ tty3270_read_tasklet(struct raw3270_request *rrq)
577 raw3270_request_add_data(tp->kreset, &kreset_data, 1); 571 raw3270_request_add_data(tp->kreset, &kreset_data, 1);
578 raw3270_start(&tp->view, tp->kreset); 572 raw3270_start(&tp->view, tp->kreset);
579 573
580 /* Emit input string. */ 574 while (len-- > 0)
581 if (tp->tty) { 575 kbd_keycode(tp->kbd, *input++);
582 while (len-- > 0) 576 /* Emit keycode for AID byte. */
583 kbd_keycode(tp->kbd, *input++); 577 kbd_keycode(tp->kbd, 256 + tp->input->string[0]);
584 /* Emit keycode for AID byte. */
585 kbd_keycode(tp->kbd, 256 + tp->input->string[0]);
586 }
587 578
588 raw3270_request_reset(rrq); 579 raw3270_request_reset(rrq);
589 xchg(&tp->read, rrq); 580 xchg(&tp->read, rrq);
@@ -596,9 +587,10 @@ tty3270_read_tasklet(struct raw3270_request *rrq)
596static void 587static void
597tty3270_read_callback(struct raw3270_request *rq, void *data) 588tty3270_read_callback(struct raw3270_request *rq, void *data)
598{ 589{
590 struct tty3270 *tp = container_of(rq->view, struct tty3270, view);
599 raw3270_get_view(rq->view); 591 raw3270_get_view(rq->view);
600 /* Schedule tasklet to pass input to tty. */ 592 /* Schedule tasklet to pass input to tty. */
601 tasklet_schedule(&((struct tty3270 *) rq->view)->readlet); 593 tasklet_schedule(&tp->readlet);
602} 594}
603 595
604/* 596/*
@@ -635,9 +627,8 @@ tty3270_issue_read(struct tty3270 *tp, int lock)
635static int 627static int
636tty3270_activate(struct raw3270_view *view) 628tty3270_activate(struct raw3270_view *view)
637{ 629{
638 struct tty3270 *tp; 630 struct tty3270 *tp = container_of(view, struct tty3270, view);
639 631
640 tp = (struct tty3270 *) view;
641 tp->update_flags = TTY_UPDATE_ALL; 632 tp->update_flags = TTY_UPDATE_ALL;
642 tty3270_set_timer(tp, 1); 633 tty3270_set_timer(tp, 1);
643 return 0; 634 return 0;
@@ -646,9 +637,8 @@ tty3270_activate(struct raw3270_view *view)
646static void 637static void
647tty3270_deactivate(struct raw3270_view *view) 638tty3270_deactivate(struct raw3270_view *view)
648{ 639{
649 struct tty3270 *tp; 640 struct tty3270 *tp = container_of(view, struct tty3270, view);
650 641
651 tp = (struct tty3270 *) view;
652 del_timer(&tp->timer); 642 del_timer(&tp->timer);
653} 643}
654 644
@@ -690,6 +680,17 @@ tty3270_alloc_view(void)
690 if (!tp->freemem_pages) 680 if (!tp->freemem_pages)
691 goto out_tp; 681 goto out_tp;
692 INIT_LIST_HEAD(&tp->freemem); 682 INIT_LIST_HEAD(&tp->freemem);
683 INIT_LIST_HEAD(&tp->lines);
684 INIT_LIST_HEAD(&tp->update);
685 INIT_LIST_HEAD(&tp->rcl_lines);
686 tp->rcl_max = 20;
687 tty_port_init(&tp->port);
688 setup_timer(&tp->timer, (void (*)(unsigned long)) tty3270_update,
689 (unsigned long) tp);
690 tasklet_init(&tp->readlet,
691 (void (*)(unsigned long)) tty3270_read_tasklet,
692 (unsigned long) tp->read);
693
693 for (pages = 0; pages < TTY3270_STRING_PAGES; pages++) { 694 for (pages = 0; pages < TTY3270_STRING_PAGES; pages++) {
694 tp->freemem_pages[pages] = (void *) 695 tp->freemem_pages[pages] = (void *)
695 __get_free_pages(GFP_KERNEL|GFP_DMA, 0); 696 __get_free_pages(GFP_KERNEL|GFP_DMA, 0);
@@ -794,16 +795,15 @@ tty3270_free_screen(struct tty3270 *tp)
794static void 795static void
795tty3270_release(struct raw3270_view *view) 796tty3270_release(struct raw3270_view *view)
796{ 797{
797 struct tty3270 *tp; 798 struct tty3270 *tp = container_of(view, struct tty3270, view);
798 struct tty_struct *tty; 799 struct tty_struct *tty = tty_port_tty_get(&tp->port);
799 800
800 tp = (struct tty3270 *) view;
801 tty = tp->tty;
802 if (tty) { 801 if (tty) {
803 tty->driver_data = NULL; 802 tty->driver_data = NULL;
804 tp->tty = tp->kbd->tty = NULL; 803 tty_port_tty_set(&tp->port, NULL);
805 tty_hangup(tty); 804 tty_hangup(tty);
806 raw3270_put_view(&tp->view); 805 raw3270_put_view(&tp->view);
806 tty_kref_put(tty);
807 } 807 }
808} 808}
809 809
@@ -813,8 +813,9 @@ tty3270_release(struct raw3270_view *view)
813static void 813static void
814tty3270_free(struct raw3270_view *view) 814tty3270_free(struct raw3270_view *view)
815{ 815{
816 tty3270_free_screen((struct tty3270 *) view); 816 struct tty3270 *tp = container_of(view, struct tty3270, view);
817 tty3270_free_view((struct tty3270 *) view); 817 tty3270_free_screen(tp);
818 tty3270_free_view(tp);
818} 819}
819 820
820/* 821/*
@@ -823,14 +824,13 @@ tty3270_free(struct raw3270_view *view)
823static void 824static void
824tty3270_del_views(void) 825tty3270_del_views(void)
825{ 826{
826 struct tty3270 *tp;
827 int i; 827 int i;
828 828
829 for (i = 0; i < tty3270_max_index; i++) { 829 for (i = 0; i < tty3270_max_index; i++) {
830 tp = (struct tty3270 *) 830 struct raw3270_view *view =
831 raw3270_find_view(&tty3270_fn, i + RAW3270_FIRSTMINOR); 831 raw3270_find_view(&tty3270_fn, i + RAW3270_FIRSTMINOR);
832 if (!IS_ERR(tp)) 832 if (!IS_ERR(view))
833 raw3270_del_view(&tp->view); 833 raw3270_del_view(view);
834 } 834 }
835} 835}
836 836
@@ -848,22 +848,23 @@ static struct raw3270_fn tty3270_fn = {
848static int 848static int
849tty3270_open(struct tty_struct *tty, struct file * filp) 849tty3270_open(struct tty_struct *tty, struct file * filp)
850{ 850{
851 struct raw3270_view *view;
851 struct tty3270 *tp; 852 struct tty3270 *tp;
852 int i, rc; 853 int i, rc;
853 854
854 if (tty->count > 1) 855 if (tty->count > 1)
855 return 0; 856 return 0;
856 /* Check if the tty3270 is already there. */ 857 /* Check if the tty3270 is already there. */
857 tp = (struct tty3270 *) 858 view = raw3270_find_view(&tty3270_fn,
858 raw3270_find_view(&tty3270_fn,
859 tty->index + RAW3270_FIRSTMINOR); 859 tty->index + RAW3270_FIRSTMINOR);
860 if (!IS_ERR(tp)) { 860 if (!IS_ERR(view)) {
861 tp = container_of(view, struct tty3270, view);
861 tty->driver_data = tp; 862 tty->driver_data = tp;
862 tty->winsize.ws_row = tp->view.rows - 2; 863 tty->winsize.ws_row = tp->view.rows - 2;
863 tty->winsize.ws_col = tp->view.cols; 864 tty->winsize.ws_col = tp->view.cols;
864 tty->low_latency = 0; 865 tty->low_latency = 0;
865 tp->tty = tty; 866 /* why to reassign? */
866 tp->kbd->tty = tty; 867 tty_port_tty_set(&tp->port, tty);
867 tp->inattr = TF_INPUT; 868 tp->inattr = TF_INPUT;
868 return 0; 869 return 0;
869 } 870 }
@@ -871,7 +872,7 @@ tty3270_open(struct tty_struct *tty, struct file * filp)
871 tty3270_max_index = tty->index + 1; 872 tty3270_max_index = tty->index + 1;
872 873
873 /* Quick exit if there is no device for tty->index. */ 874 /* Quick exit if there is no device for tty->index. */
874 if (PTR_ERR(tp) == -ENODEV) 875 if (PTR_ERR(view) == -ENODEV)
875 return -ENODEV; 876 return -ENODEV;
876 877
877 /* Allocate tty3270 structure on first open. */ 878 /* Allocate tty3270 structure on first open. */
@@ -879,16 +880,6 @@ tty3270_open(struct tty_struct *tty, struct file * filp)
879 if (IS_ERR(tp)) 880 if (IS_ERR(tp))
880 return PTR_ERR(tp); 881 return PTR_ERR(tp);
881 882
882 INIT_LIST_HEAD(&tp->lines);
883 INIT_LIST_HEAD(&tp->update);
884 INIT_LIST_HEAD(&tp->rcl_lines);
885 tp->rcl_max = 20;
886 setup_timer(&tp->timer, (void (*)(unsigned long)) tty3270_update,
887 (unsigned long) tp);
888 tasklet_init(&tp->readlet,
889 (void (*)(unsigned long)) tty3270_read_tasklet,
890 (unsigned long) tp->read);
891
892 rc = raw3270_add_view(&tp->view, &tty3270_fn, 883 rc = raw3270_add_view(&tp->view, &tty3270_fn,
893 tty->index + RAW3270_FIRSTMINOR); 884 tty->index + RAW3270_FIRSTMINOR);
894 if (rc) { 885 if (rc) {
@@ -903,7 +894,7 @@ tty3270_open(struct tty_struct *tty, struct file * filp)
903 return rc; 894 return rc;
904 } 895 }
905 896
906 tp->tty = tty; 897 tty_port_tty_set(&tp->port, tty);
907 tty->low_latency = 0; 898 tty->low_latency = 0;
908 tty->driver_data = tp; 899 tty->driver_data = tp;
909 tty->winsize.ws_row = tp->view.rows - 2; 900 tty->winsize.ws_row = tp->view.rows - 2;
@@ -917,7 +908,7 @@ tty3270_open(struct tty_struct *tty, struct file * filp)
917 for (i = 0; i < tp->view.rows - 2; i++) 908 for (i = 0; i < tp->view.rows - 2; i++)
918 tty3270_blank_line(tp); 909 tty3270_blank_line(tp);
919 910
920 tp->kbd->tty = tty; 911 tp->kbd->port = &tp->port;
921 tp->kbd->fn_handler[KVAL(K_INCRCONSOLE)] = tty3270_exit_tty; 912 tp->kbd->fn_handler[KVAL(K_INCRCONSOLE)] = tty3270_exit_tty;
922 tp->kbd->fn_handler[KVAL(K_SCROLLBACK)] = tty3270_scroll_backward; 913 tp->kbd->fn_handler[KVAL(K_SCROLLBACK)] = tty3270_scroll_backward;
923 tp->kbd->fn_handler[KVAL(K_SCROLLFORW)] = tty3270_scroll_forward; 914 tp->kbd->fn_handler[KVAL(K_SCROLLFORW)] = tty3270_scroll_forward;
@@ -935,14 +926,13 @@ tty3270_open(struct tty_struct *tty, struct file * filp)
935static void 926static void
936tty3270_close(struct tty_struct *tty, struct file * filp) 927tty3270_close(struct tty_struct *tty, struct file * filp)
937{ 928{
938 struct tty3270 *tp; 929 struct tty3270 *tp = tty->driver_data;
939 930
940 if (tty->count > 1) 931 if (tty->count > 1)
941 return; 932 return;
942 tp = (struct tty3270 *) tty->driver_data;
943 if (tp) { 933 if (tp) {
944 tty->driver_data = NULL; 934 tty->driver_data = NULL;
945 tp->tty = tp->kbd->tty = NULL; 935 tty_port_tty_set(&tp->port, NULL);
946 raw3270_put_view(&tp->view); 936 raw3270_put_view(&tp->view);
947 } 937 }
948} 938}
@@ -1391,7 +1381,7 @@ tty3270_escape_sequence(struct tty3270 *tp, char ch)
1391 tty3270_lf(tp); 1381 tty3270_lf(tp);
1392 break; 1382 break;
1393 case 'Z': /* Respond ID. */ 1383 case 'Z': /* Respond ID. */
1394 kbd_puts_queue(tp->tty, "\033[?6c"); 1384 kbd_puts_queue(&tp->port, "\033[?6c");
1395 break; 1385 break;
1396 case '7': /* Save cursor position. */ 1386 case '7': /* Save cursor position. */
1397 tp->saved_cx = tp->cx; 1387 tp->saved_cx = tp->cx;
@@ -1437,11 +1427,11 @@ tty3270_escape_sequence(struct tty3270 *tp, char ch)
1437 tp->esc_state = ESnormal; 1427 tp->esc_state = ESnormal;
1438 if (ch == 'n' && !tp->esc_ques) { 1428 if (ch == 'n' && !tp->esc_ques) {
1439 if (tp->esc_par[0] == 5) /* Status report. */ 1429 if (tp->esc_par[0] == 5) /* Status report. */
1440 kbd_puts_queue(tp->tty, "\033[0n"); 1430 kbd_puts_queue(&tp->port, "\033[0n");
1441 else if (tp->esc_par[0] == 6) { /* Cursor report. */ 1431 else if (tp->esc_par[0] == 6) { /* Cursor report. */
1442 char buf[40]; 1432 char buf[40];
1443 sprintf(buf, "\033[%d;%dR", tp->cy + 1, tp->cx + 1); 1433 sprintf(buf, "\033[%d;%dR", tp->cy + 1, tp->cx + 1);
1444 kbd_puts_queue(tp->tty, buf); 1434 kbd_puts_queue(&tp->port, buf);
1445 } 1435 }
1446 return; 1436 return;
1447 } 1437 }
@@ -1513,12 +1503,13 @@ tty3270_escape_sequence(struct tty3270 *tp, char ch)
1513 * String write routine for 3270 ttys 1503 * String write routine for 3270 ttys
1514 */ 1504 */
1515static void 1505static void
1516tty3270_do_write(struct tty3270 *tp, const unsigned char *buf, int count) 1506tty3270_do_write(struct tty3270 *tp, struct tty_struct *tty,
1507 const unsigned char *buf, int count)
1517{ 1508{
1518 int i_msg, i; 1509 int i_msg, i;
1519 1510
1520 spin_lock_bh(&tp->view.lock); 1511 spin_lock_bh(&tp->view.lock);
1521 for (i_msg = 0; !tp->tty->stopped && i_msg < count; i_msg++) { 1512 for (i_msg = 0; !tty->stopped && i_msg < count; i_msg++) {
1522 if (tp->esc_state != 0) { 1513 if (tp->esc_state != 0) {
1523 /* Continue escape sequence. */ 1514 /* Continue escape sequence. */
1524 tty3270_escape_sequence(tp, buf[i_msg]); 1515 tty3270_escape_sequence(tp, buf[i_msg]);
@@ -1595,10 +1586,10 @@ tty3270_write(struct tty_struct * tty,
1595 if (!tp) 1586 if (!tp)
1596 return 0; 1587 return 0;
1597 if (tp->char_count > 0) { 1588 if (tp->char_count > 0) {
1598 tty3270_do_write(tp, tp->char_buf, tp->char_count); 1589 tty3270_do_write(tp, tty, tp->char_buf, tp->char_count);
1599 tp->char_count = 0; 1590 tp->char_count = 0;
1600 } 1591 }
1601 tty3270_do_write(tp, buf, count); 1592 tty3270_do_write(tp, tty, buf, count);
1602 return count; 1593 return count;
1603} 1594}
1604 1595
@@ -1629,7 +1620,7 @@ tty3270_flush_chars(struct tty_struct *tty)
1629 if (!tp) 1620 if (!tp)
1630 return; 1621 return;
1631 if (tp->char_count > 0) { 1622 if (tp->char_count > 0) {
1632 tty3270_do_write(tp, tp->char_buf, tp->char_count); 1623 tty3270_do_write(tp, tty, tp->char_buf, tp->char_count);
1633 tp->char_count = 0; 1624 tp->char_count = 0;
1634 } 1625 }
1635} 1626}