^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * IBM/3270 Driver - tty functions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Author(s):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Original 3270 Code for 2.4 written by Richard Hitt (UTS Global)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Rewritten for 2.5 by Martin Schwidefsky <schwidefsky@de.ibm.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * -- Copyright IBM Corp. 2003
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/kdev_t.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/tty.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/vt_kern.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/console.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/workqueue.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/memblock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/compat.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <asm/ccwdev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <asm/cio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <asm/ebcdic.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include "raw3270.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include "tty3270.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include "keyboard.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define TTY3270_CHAR_BUF_SIZE 256
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define TTY3270_OUTPUT_BUFFER_SIZE 1024
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define TTY3270_STRING_PAGES 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) struct tty_driver *tty3270_driver;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) static int tty3270_max_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) static struct raw3270_fn tty3270_fn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) struct tty3270_cell {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) unsigned char character;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) unsigned char highlight;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) unsigned char f_color;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) struct tty3270_line {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) struct tty3270_cell *cells;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define ESCAPE_NPAR 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) * The main tty view data structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) * FIXME:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) * 1) describe line orientation & lines list concept against screen
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) * 2) describe conversion of screen to lines
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) * 3) describe line format.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) struct tty3270 {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) struct raw3270_view view;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) struct tty_port port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) void **freemem_pages; /* Array of pages used for freemem. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) struct list_head freemem; /* List of free memory for strings. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) /* Output stuff. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) struct list_head lines; /* List of lines. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) struct list_head update; /* List of lines to update. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) unsigned char wcc; /* Write control character. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) int nr_lines; /* # lines in list. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) int nr_up; /* # lines up in history. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) unsigned long update_flags; /* Update indication bits. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) struct string *status; /* Lower right of display. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) struct raw3270_request *write; /* Single write request. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) struct timer_list timer; /* Output delay timer. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) /* Current tty screen. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) unsigned int cx, cy; /* Current output position. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) unsigned int highlight; /* Blink/reverse/underscore */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) unsigned int f_color; /* Foreground color */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) struct tty3270_line *screen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) unsigned int n_model, n_cols, n_rows; /* New model & size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) struct work_struct resize_work;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) /* Input stuff. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) struct string *prompt; /* Output string for input area. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) struct string *input; /* Input string for read request. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) struct raw3270_request *read; /* Single read request. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) struct raw3270_request *kreset; /* Single keyboard reset request. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) unsigned char inattr; /* Visible/invisible input. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) int throttle, attn; /* tty throttle/unthrottle. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) struct tasklet_struct readlet; /* Tasklet to issue read request. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) struct tasklet_struct hanglet; /* Tasklet to hang up the tty. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) struct kbd_data *kbd; /* key_maps stuff. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) /* Escape sequence parsing. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) int esc_state, esc_ques, esc_npar;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) int esc_par[ESCAPE_NPAR];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) unsigned int saved_cx, saved_cy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) unsigned int saved_highlight, saved_f_color;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) /* Command recalling. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) struct list_head rcl_lines; /* List of recallable lines. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) struct list_head *rcl_walk; /* Point in rcl_lines list. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) int rcl_nr, rcl_max; /* Number/max number of rcl_lines. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) /* Character array for put_char/flush_chars. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) unsigned int char_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) char char_buf[TTY3270_CHAR_BUF_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) /* tty3270->update_flags. See tty3270_update for details. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) #define TTY_UPDATE_ERASE 1 /* Use EWRITEA instead of WRITE. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) #define TTY_UPDATE_LIST 2 /* Update lines in tty3270->update. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) #define TTY_UPDATE_INPUT 4 /* Update input line. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) #define TTY_UPDATE_STATUS 8 /* Update status line. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) #define TTY_UPDATE_ALL 16 /* Recreate screen. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) static void tty3270_update(struct timer_list *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) static void tty3270_resize_work(struct work_struct *work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) * Setup timeout for a device. On timeout trigger an update.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) static void tty3270_set_timer(struct tty3270 *tp, int expires)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) mod_timer(&tp->timer, jiffies + expires);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) * The input line are the two last lines of the screen.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) tty3270_update_prompt(struct tty3270 *tp, char *input, int count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) struct string *line;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) unsigned int off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) line = tp->prompt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) if (count != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) line->string[5] = TF_INMDT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) line->string[5] = tp->inattr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) if (count > tp->view.cols * 2 - 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) count = tp->view.cols * 2 - 11;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) memcpy(line->string + 6, input, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) line->string[6 + count] = TO_IC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) /* Clear to end of input line. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) if (count < tp->view.cols * 2 - 11) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) line->string[7 + count] = TO_RA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) line->string[10 + count] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) off = tp->view.cols * tp->view.rows - 9;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) raw3270_buffer_address(tp->view.dev, line->string+count+8, off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) line->len = 11 + count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) line->len = 7 + count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) tp->update_flags |= TTY_UPDATE_INPUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) tty3270_create_prompt(struct tty3270 *tp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) static const unsigned char blueprint[] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) { TO_SBA, 0, 0, 0x6e, TO_SF, TF_INPUT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) /* empty input string */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) TO_IC, TO_RA, 0, 0, 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) struct string *line;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) unsigned int offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) line = alloc_string(&tp->freemem,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) sizeof(blueprint) + tp->view.cols * 2 - 9);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) tp->prompt = line;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) tp->inattr = TF_INPUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) /* Copy blueprint to status line */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) memcpy(line->string, blueprint, sizeof(blueprint));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) line->len = sizeof(blueprint);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) /* Set output offsets. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) offset = tp->view.cols * (tp->view.rows - 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) raw3270_buffer_address(tp->view.dev, line->string + 1, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) offset = tp->view.cols * tp->view.rows - 9;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) raw3270_buffer_address(tp->view.dev, line->string + 8, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) /* Allocate input string for reading. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) tp->input = alloc_string(&tp->freemem, tp->view.cols * 2 - 9 + 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) * The status line is the last line of the screen. It shows the string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) * "Running"/"Holding" in the lower right corner of the screen.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) tty3270_update_status(struct tty3270 * tp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) char *str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) str = (tp->nr_up != 0) ? "History" : "Running";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) memcpy(tp->status->string + 8, str, 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) codepage_convert(tp->view.ascebc, tp->status->string + 8, 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) tp->update_flags |= TTY_UPDATE_STATUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) tty3270_create_status(struct tty3270 * tp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) static const unsigned char blueprint[] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) { TO_SBA, 0, 0, TO_SF, TF_LOG, TO_SA, TAT_COLOR, TAC_GREEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 0, 0, 0, 0, 0, 0, 0, TO_SF, TF_LOG, TO_SA, TAT_COLOR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) TAC_RESET };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) struct string *line;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) unsigned int offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) line = alloc_string(&tp->freemem,sizeof(blueprint));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) tp->status = line;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) /* Copy blueprint to status line */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) memcpy(line->string, blueprint, sizeof(blueprint));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) /* Set address to start of status string (= last 9 characters). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) offset = tp->view.cols * tp->view.rows - 9;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) raw3270_buffer_address(tp->view.dev, line->string + 1, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) * Set output offsets to 3270 datastream fragment of a tty string.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) * (TO_SBA offset at the start and TO_RA offset at the end of the string)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) tty3270_update_string(struct tty3270 *tp, struct string *line, int nr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) unsigned char *cp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) raw3270_buffer_address(tp->view.dev, line->string + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) tp->view.cols * nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) cp = line->string + line->len - 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) if (*cp == TO_RA)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) raw3270_buffer_address(tp->view.dev, cp + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) tp->view.cols * (nr + 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) * Rebuild update list to print all lines.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) tty3270_rebuild_update(struct tty3270 *tp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) struct string *s, *n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) int line, nr_up;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) * Throw away update list and create a new one,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) * containing all lines that will fit on the screen.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) list_for_each_entry_safe(s, n, &tp->update, update)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) list_del_init(&s->update);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) line = tp->view.rows - 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) nr_up = tp->nr_up;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) list_for_each_entry_reverse(s, &tp->lines, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) if (nr_up > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) nr_up--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) tty3270_update_string(tp, s, line);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) list_add(&s->update, &tp->update);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) if (--line < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) tp->update_flags |= TTY_UPDATE_LIST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) * Alloc string for size bytes. If there is not enough room in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) * freemem, free strings until there is room.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) static struct string *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) tty3270_alloc_string(struct tty3270 *tp, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) struct string *s, *n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) s = alloc_string(&tp->freemem, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) if (s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) return s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) list_for_each_entry_safe(s, n, &tp->lines, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) BUG_ON(tp->nr_lines <= tp->view.rows - 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) list_del(&s->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) if (!list_empty(&s->update))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) list_del(&s->update);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) tp->nr_lines--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) if (free_string(&tp->freemem, s) >= size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) s = alloc_string(&tp->freemem, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) BUG_ON(!s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) if (tp->nr_up != 0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) tp->nr_up + tp->view.rows - 2 >= tp->nr_lines) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) tp->nr_up = tp->nr_lines - tp->view.rows + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) tty3270_rebuild_update(tp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) tty3270_update_status(tp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) return s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) * Add an empty line to the list.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) tty3270_blank_line(struct tty3270 *tp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) static const unsigned char blueprint[] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) { TO_SBA, 0, 0, TO_SA, TAT_EXTHI, TAX_RESET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) TO_SA, TAT_COLOR, TAC_RESET, TO_RA, 0, 0, 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) struct string *s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) s = tty3270_alloc_string(tp, sizeof(blueprint));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) memcpy(s->string, blueprint, sizeof(blueprint));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) s->len = sizeof(blueprint);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) list_add_tail(&s->list, &tp->lines);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) tp->nr_lines++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) if (tp->nr_up != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) tp->nr_up++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) * Create a blank screen and remove all lines from the history.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) tty3270_blank_screen(struct tty3270 *tp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) struct string *s, *n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) for (i = 0; i < tp->view.rows - 2; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) tp->screen[i].len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) tp->nr_up = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) list_for_each_entry_safe(s, n, &tp->lines, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) list_del(&s->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) if (!list_empty(&s->update))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) list_del(&s->update);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) tp->nr_lines--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) free_string(&tp->freemem, s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) * Write request completion callback.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) tty3270_write_callback(struct raw3270_request *rq, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) struct tty3270 *tp = container_of(rq->view, struct tty3270, view);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) if (rq->rc != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) /* Write wasn't successful. Refresh all. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) tp->update_flags = TTY_UPDATE_ALL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) tty3270_set_timer(tp, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) raw3270_request_reset(rq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) xchg(&tp->write, rq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) * Update 3270 display.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) tty3270_update(struct timer_list *t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) struct tty3270 *tp = from_timer(tp, t, timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) static char invalid_sba[2] = { 0xff, 0xff };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) struct raw3270_request *wrq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) unsigned long updated;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) struct string *s, *n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) char *sba, *str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) int rc, len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) wrq = xchg(&tp->write, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) if (!wrq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) tty3270_set_timer(tp, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) spin_lock(&tp->view.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) updated = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) if (tp->update_flags & TTY_UPDATE_ALL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) tty3270_rebuild_update(tp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) tty3270_update_status(tp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) tp->update_flags = TTY_UPDATE_ERASE | TTY_UPDATE_LIST |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) TTY_UPDATE_INPUT | TTY_UPDATE_STATUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) if (tp->update_flags & TTY_UPDATE_ERASE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) /* Use erase write alternate to erase display. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) raw3270_request_set_cmd(wrq, TC_EWRITEA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) updated |= TTY_UPDATE_ERASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) raw3270_request_set_cmd(wrq, TC_WRITE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) raw3270_request_add_data(wrq, &tp->wcc, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) tp->wcc = TW_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) * Update status line.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) if (tp->update_flags & TTY_UPDATE_STATUS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) if (raw3270_request_add_data(wrq, tp->status->string,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) tp->status->len) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) updated |= TTY_UPDATE_STATUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) * Write input line.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) if (tp->update_flags & TTY_UPDATE_INPUT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) if (raw3270_request_add_data(wrq, tp->prompt->string,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) tp->prompt->len) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) updated |= TTY_UPDATE_INPUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) sba = invalid_sba;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) if (tp->update_flags & TTY_UPDATE_LIST) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) /* Write strings in the update list to the screen. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) list_for_each_entry_safe(s, n, &tp->update, update) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) str = s->string;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) len = s->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) * Skip TO_SBA at the start of the string if the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) * last output position matches the start address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) * of this line.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) if (s->string[1] == sba[0] && s->string[2] == sba[1])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) str += 3, len -= 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) if (raw3270_request_add_data(wrq, str, len) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) list_del_init(&s->update);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) if (s->string[s->len - 4] == TO_RA)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) sba = s->string + s->len - 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) sba = invalid_sba;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) if (list_empty(&tp->update))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) updated |= TTY_UPDATE_LIST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) wrq->callback = tty3270_write_callback;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) rc = raw3270_start(&tp->view, wrq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) if (rc == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) tp->update_flags &= ~updated;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) if (tp->update_flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) tty3270_set_timer(tp, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) raw3270_request_reset(wrq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) xchg(&tp->write, wrq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) spin_unlock(&tp->view.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) * Command recalling.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) tty3270_rcl_add(struct tty3270 *tp, char *input, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) struct string *s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) tp->rcl_walk = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) if (len <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) if (tp->rcl_nr >= tp->rcl_max) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) s = list_entry(tp->rcl_lines.next, struct string, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) list_del(&s->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) free_string(&tp->freemem, s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) tp->rcl_nr--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) s = tty3270_alloc_string(tp, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) memcpy(s->string, input, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) list_add_tail(&s->list, &tp->rcl_lines);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) tp->rcl_nr++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) tty3270_rcl_backward(struct kbd_data *kbd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) struct tty3270 *tp = container_of(kbd->port, struct tty3270, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) struct string *s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) spin_lock_bh(&tp->view.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) if (tp->inattr == TF_INPUT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) if (tp->rcl_walk && tp->rcl_walk->prev != &tp->rcl_lines)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) tp->rcl_walk = tp->rcl_walk->prev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) else if (!list_empty(&tp->rcl_lines))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) tp->rcl_walk = tp->rcl_lines.prev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) s = tp->rcl_walk ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) list_entry(tp->rcl_walk, struct string, list) : NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) if (tp->rcl_walk) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) s = list_entry(tp->rcl_walk, struct string, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) tty3270_update_prompt(tp, s->string, s->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) tty3270_update_prompt(tp, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) tty3270_set_timer(tp, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) spin_unlock_bh(&tp->view.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) * Deactivate tty view.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) tty3270_exit_tty(struct kbd_data *kbd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) struct tty3270 *tp = container_of(kbd->port, struct tty3270, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) raw3270_deactivate_view(&tp->view);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) * Scroll forward in history.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) tty3270_scroll_forward(struct kbd_data *kbd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) struct tty3270 *tp = container_of(kbd->port, struct tty3270, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) int nr_up;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) spin_lock_bh(&tp->view.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) nr_up = tp->nr_up - tp->view.rows + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) if (nr_up < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) nr_up = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) if (nr_up != tp->nr_up) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) tp->nr_up = nr_up;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) tty3270_rebuild_update(tp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) tty3270_update_status(tp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) tty3270_set_timer(tp, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) spin_unlock_bh(&tp->view.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) * Scroll backward in history.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) tty3270_scroll_backward(struct kbd_data *kbd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) struct tty3270 *tp = container_of(kbd->port, struct tty3270, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) int nr_up;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) spin_lock_bh(&tp->view.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) nr_up = tp->nr_up + tp->view.rows - 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) if (nr_up + tp->view.rows - 2 > tp->nr_lines)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) nr_up = tp->nr_lines - tp->view.rows + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) if (nr_up != tp->nr_up) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) tp->nr_up = nr_up;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) tty3270_rebuild_update(tp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) tty3270_update_status(tp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) tty3270_set_timer(tp, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) spin_unlock_bh(&tp->view.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) * Pass input line to tty.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) tty3270_read_tasklet(unsigned long data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) struct raw3270_request *rrq = (struct raw3270_request *)data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) static char kreset_data = TW_KR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) struct tty3270 *tp = container_of(rrq->view, struct tty3270, view);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) char *input;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) spin_lock_bh(&tp->view.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) * Two AID keys are special: For 0x7d (enter) the input line
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) * has to be emitted to the tty and for 0x6d the screen
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) * needs to be redrawn.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) input = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) if (tp->input->string[0] == 0x7d) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) /* Enter: write input to tty. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) input = tp->input->string + 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) len = tp->input->len - 6 - rrq->rescnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) if (tp->inattr != TF_INPUTN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) tty3270_rcl_add(tp, input, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) if (tp->nr_up > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) tp->nr_up = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) tty3270_rebuild_update(tp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) tty3270_update_status(tp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) /* Clear input area. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) tty3270_update_prompt(tp, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) tty3270_set_timer(tp, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) } else if (tp->input->string[0] == 0x6d) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) /* Display has been cleared. Redraw. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) tp->update_flags = TTY_UPDATE_ALL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) tty3270_set_timer(tp, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) spin_unlock_bh(&tp->view.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) /* Start keyboard reset command. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) raw3270_request_reset(tp->kreset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) raw3270_request_set_cmd(tp->kreset, TC_WRITE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) raw3270_request_add_data(tp->kreset, &kreset_data, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) raw3270_start(&tp->view, tp->kreset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) while (len-- > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) kbd_keycode(tp->kbd, *input++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) /* Emit keycode for AID byte. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) kbd_keycode(tp->kbd, 256 + tp->input->string[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) raw3270_request_reset(rrq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) xchg(&tp->read, rrq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) raw3270_put_view(&tp->view);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) * Read request completion callback.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) tty3270_read_callback(struct raw3270_request *rq, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) struct tty3270 *tp = container_of(rq->view, struct tty3270, view);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) raw3270_get_view(rq->view);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) /* Schedule tasklet to pass input to tty. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) tasklet_schedule(&tp->readlet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) * Issue a read request. Call with device lock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) tty3270_issue_read(struct tty3270 *tp, int lock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) struct raw3270_request *rrq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) rrq = xchg(&tp->read, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) if (!rrq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) /* Read already scheduled. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) rrq->callback = tty3270_read_callback;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) rrq->callback_data = tp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) raw3270_request_set_cmd(rrq, TC_READMOD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) raw3270_request_set_data(rrq, tp->input->string, tp->input->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) /* Issue the read modified request. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) if (lock) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) rc = raw3270_start(&tp->view, rrq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) rc = raw3270_start_irq(&tp->view, rrq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) raw3270_request_reset(rrq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) xchg(&tp->read, rrq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) * Hang up the tty
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) tty3270_hangup_tasklet(unsigned long data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) struct tty3270 *tp = (struct tty3270 *)data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) tty_port_tty_hangup(&tp->port, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) raw3270_put_view(&tp->view);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) * Switch to the tty view.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) tty3270_activate(struct raw3270_view *view)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) struct tty3270 *tp = container_of(view, struct tty3270, view);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) tp->update_flags = TTY_UPDATE_ALL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) tty3270_set_timer(tp, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) tty3270_deactivate(struct raw3270_view *view)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) struct tty3270 *tp = container_of(view, struct tty3270, view);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) del_timer(&tp->timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) tty3270_irq(struct tty3270 *tp, struct raw3270_request *rq, struct irb *irb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) /* Handle ATTN. Schedule tasklet to read aid. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) if (irb->scsw.cmd.dstat & DEV_STAT_ATTENTION) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) if (!tp->throttle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) tty3270_issue_read(tp, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) tp->attn = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) if (rq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) if (irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) rq->rc = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) raw3270_get_view(&tp->view);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) tasklet_schedule(&tp->hanglet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) /* Normal end. Copy residual count. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) rq->rescnt = irb->scsw.cmd.count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) } else if (irb->scsw.cmd.dstat & DEV_STAT_DEV_END) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) /* Interrupt without an outstanding request -> update all */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) tp->update_flags = TTY_UPDATE_ALL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) tty3270_set_timer(tp, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) * Allocate tty3270 structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) static struct tty3270 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) tty3270_alloc_view(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) struct tty3270 *tp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) int pages;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) tp = kzalloc(sizeof(struct tty3270), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) if (!tp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) tp->freemem_pages =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) kmalloc_array(TTY3270_STRING_PAGES, sizeof(void *),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) if (!tp->freemem_pages)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) goto out_tp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) INIT_LIST_HEAD(&tp->freemem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) INIT_LIST_HEAD(&tp->lines);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) INIT_LIST_HEAD(&tp->update);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) INIT_LIST_HEAD(&tp->rcl_lines);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) tp->rcl_max = 20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) for (pages = 0; pages < TTY3270_STRING_PAGES; pages++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) tp->freemem_pages[pages] = (void *)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) __get_free_pages(GFP_KERNEL|GFP_DMA, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) if (!tp->freemem_pages[pages])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) goto out_pages;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) add_string_memory(&tp->freemem,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) tp->freemem_pages[pages], PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) tp->write = raw3270_request_alloc(TTY3270_OUTPUT_BUFFER_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) if (IS_ERR(tp->write))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) goto out_pages;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) tp->read = raw3270_request_alloc(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) if (IS_ERR(tp->read))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) goto out_write;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) tp->kreset = raw3270_request_alloc(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) if (IS_ERR(tp->kreset))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) goto out_read;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) tp->kbd = kbd_alloc();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) if (!tp->kbd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) goto out_reset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) tty_port_init(&tp->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) timer_setup(&tp->timer, tty3270_update, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) tasklet_init(&tp->readlet, tty3270_read_tasklet,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) (unsigned long) tp->read);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) tasklet_init(&tp->hanglet, tty3270_hangup_tasklet,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) (unsigned long) tp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) INIT_WORK(&tp->resize_work, tty3270_resize_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) return tp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) out_reset:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) raw3270_request_free(tp->kreset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) out_read:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) raw3270_request_free(tp->read);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) out_write:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) raw3270_request_free(tp->write);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) out_pages:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) while (pages--)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) free_pages((unsigned long) tp->freemem_pages[pages], 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) kfree(tp->freemem_pages);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) tty_port_destroy(&tp->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) out_tp:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) kfree(tp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) out_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) * Free tty3270 structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) tty3270_free_view(struct tty3270 *tp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) int pages;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) kbd_free(tp->kbd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) raw3270_request_free(tp->kreset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) raw3270_request_free(tp->read);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) raw3270_request_free(tp->write);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) for (pages = 0; pages < TTY3270_STRING_PAGES; pages++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) free_pages((unsigned long) tp->freemem_pages[pages], 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) kfree(tp->freemem_pages);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) tty_port_destroy(&tp->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) kfree(tp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) * Allocate tty3270 screen.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) static struct tty3270_line *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) tty3270_alloc_screen(unsigned int rows, unsigned int cols)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) struct tty3270_line *screen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) unsigned long size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) int lines;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) size = sizeof(struct tty3270_line) * (rows - 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) screen = kzalloc(size, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) if (!screen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) for (lines = 0; lines < rows - 2; lines++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) size = sizeof(struct tty3270_cell) * cols;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) screen[lines].cells = kzalloc(size, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) if (!screen[lines].cells)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) goto out_screen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) return screen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) out_screen:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) while (lines--)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) kfree(screen[lines].cells);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) kfree(screen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) out_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) * Free tty3270 screen.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) tty3270_free_screen(struct tty3270_line *screen, unsigned int rows)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) int lines;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) for (lines = 0; lines < rows - 2; lines++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) kfree(screen[lines].cells);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) kfree(screen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) * Resize tty3270 screen
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) static void tty3270_resize_work(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) struct tty3270 *tp = container_of(work, struct tty3270, resize_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) struct tty3270_line *screen, *oscreen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) struct tty_struct *tty;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) unsigned int orows;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) struct winsize ws;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) screen = tty3270_alloc_screen(tp->n_rows, tp->n_cols);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) if (IS_ERR(screen))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) /* Switch to new output size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) spin_lock_bh(&tp->view.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) tty3270_blank_screen(tp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) oscreen = tp->screen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) orows = tp->view.rows;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) tp->view.model = tp->n_model;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) tp->view.rows = tp->n_rows;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) tp->view.cols = tp->n_cols;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) tp->screen = screen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) free_string(&tp->freemem, tp->prompt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) free_string(&tp->freemem, tp->status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) tty3270_create_prompt(tp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) tty3270_create_status(tp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) while (tp->nr_lines < tp->view.rows - 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) tty3270_blank_line(tp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) tp->update_flags = TTY_UPDATE_ALL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) spin_unlock_bh(&tp->view.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) tty3270_free_screen(oscreen, orows);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) tty3270_set_timer(tp, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) /* Informat tty layer about new size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) tty = tty_port_tty_get(&tp->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) if (!tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) ws.ws_row = tp->view.rows - 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) ws.ws_col = tp->view.cols;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) tty_do_resize(tty, &ws);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) tty_kref_put(tty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) tty3270_resize(struct raw3270_view *view, int model, int rows, int cols)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) struct tty3270 *tp = container_of(view, struct tty3270, view);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) if (tp->n_model == model && tp->n_rows == rows && tp->n_cols == cols)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) tp->n_model = model;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) tp->n_rows = rows;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) tp->n_cols = cols;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) schedule_work(&tp->resize_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) * Unlink tty3270 data structure from tty.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) tty3270_release(struct raw3270_view *view)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) struct tty3270 *tp = container_of(view, struct tty3270, view);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) struct tty_struct *tty = tty_port_tty_get(&tp->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) if (tty) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) tty->driver_data = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) tty_port_tty_set(&tp->port, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) tty_hangup(tty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) raw3270_put_view(&tp->view);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) tty_kref_put(tty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) * Free tty3270 data structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) tty3270_free(struct raw3270_view *view)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) struct tty3270 *tp = container_of(view, struct tty3270, view);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) del_timer_sync(&tp->timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) tty3270_free_screen(tp->screen, tp->view.rows);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) tty3270_free_view(tp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) * Delayed freeing of tty3270 views.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) tty3270_del_views(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) for (i = RAW3270_FIRSTMINOR; i <= tty3270_max_index; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) struct raw3270_view *view = raw3270_find_view(&tty3270_fn, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) if (!IS_ERR(view))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) raw3270_del_view(view);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) static struct raw3270_fn tty3270_fn = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) .activate = tty3270_activate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) .deactivate = tty3270_deactivate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) .intv = (void *) tty3270_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) .release = tty3270_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) .free = tty3270_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) .resize = tty3270_resize
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) * This routine is called whenever a 3270 tty is opened first time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) static int tty3270_install(struct tty_driver *driver, struct tty_struct *tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) struct raw3270_view *view;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) struct tty3270 *tp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) int i, rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) /* Check if the tty3270 is already there. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) view = raw3270_find_view(&tty3270_fn, tty->index + RAW3270_FIRSTMINOR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) if (!IS_ERR(view)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) tp = container_of(view, struct tty3270, view);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) tty->driver_data = tp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) tty->winsize.ws_row = tp->view.rows - 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) tty->winsize.ws_col = tp->view.cols;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) tp->port.low_latency = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) tp->inattr = TF_INPUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) goto port_install;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) if (tty3270_max_index < tty->index + 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) tty3270_max_index = tty->index + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) /* Allocate tty3270 structure on first open. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) tp = tty3270_alloc_view();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) if (IS_ERR(tp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) return PTR_ERR(tp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) rc = raw3270_add_view(&tp->view, &tty3270_fn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) tty->index + RAW3270_FIRSTMINOR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) RAW3270_VIEW_LOCK_BH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) tty3270_free_view(tp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) tp->screen = tty3270_alloc_screen(tp->view.rows, tp->view.cols);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) if (IS_ERR(tp->screen)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) rc = PTR_ERR(tp->screen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) raw3270_put_view(&tp->view);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) raw3270_del_view(&tp->view);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) tty3270_free_view(tp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) tp->port.low_latency = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) tty->winsize.ws_row = tp->view.rows - 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) tty->winsize.ws_col = tp->view.cols;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) tty3270_create_prompt(tp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) tty3270_create_status(tp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) tty3270_update_status(tp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) /* Create blank line for every line in the tty output area. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) for (i = 0; i < tp->view.rows - 2; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) tty3270_blank_line(tp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) tp->kbd->port = &tp->port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) tp->kbd->fn_handler[KVAL(K_INCRCONSOLE)] = tty3270_exit_tty;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) tp->kbd->fn_handler[KVAL(K_SCROLLBACK)] = tty3270_scroll_backward;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) tp->kbd->fn_handler[KVAL(K_SCROLLFORW)] = tty3270_scroll_forward;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) tp->kbd->fn_handler[KVAL(K_CONS)] = tty3270_rcl_backward;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) kbd_ascebc(tp->kbd, tp->view.ascebc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) raw3270_activate_view(&tp->view);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) port_install:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) rc = tty_port_install(&tp->port, driver, tty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) raw3270_put_view(&tp->view);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) tty->driver_data = tp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) * This routine is called whenever a 3270 tty is opened.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) tty3270_open(struct tty_struct *tty, struct file *filp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) struct tty3270 *tp = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) struct tty_port *port = &tp->port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) port->count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) tty_port_tty_set(port, tty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) * This routine is called when the 3270 tty is closed. We wait
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) * for the remaining request to be completed. Then we clean up.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) tty3270_close(struct tty_struct *tty, struct file * filp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) struct tty3270 *tp = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) if (tty->count > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) if (tp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) tty_port_tty_set(&tp->port, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) static void tty3270_cleanup(struct tty_struct *tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) struct tty3270 *tp = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) if (tp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) tty->driver_data = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) raw3270_put_view(&tp->view);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) * We always have room.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) tty3270_write_room(struct tty_struct *tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) return INT_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) * Insert character into the screen at the current position with the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) * current color and highlight. This function does NOT do cursor movement.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) static void tty3270_put_character(struct tty3270 *tp, char ch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) struct tty3270_line *line;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) struct tty3270_cell *cell;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) line = tp->screen + tp->cy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) if (line->len <= tp->cx) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) while (line->len < tp->cx) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) cell = line->cells + line->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) cell->character = tp->view.ascebc[' '];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) cell->highlight = tp->highlight;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) cell->f_color = tp->f_color;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) line->len++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) line->len++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) cell = line->cells + tp->cx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) cell->character = tp->view.ascebc[(unsigned int) ch];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) cell->highlight = tp->highlight;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) cell->f_color = tp->f_color;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) * Convert a tty3270_line to a 3270 data fragment usable for output.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) tty3270_convert_line(struct tty3270 *tp, int line_nr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) struct tty3270_line *line;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) struct tty3270_cell *cell;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) struct string *s, *n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) unsigned char highlight;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) unsigned char f_color;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) char *cp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) int flen, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) /* Determine how long the fragment will be. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) flen = 3; /* Prefix (TO_SBA). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) line = tp->screen + line_nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) flen += line->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) highlight = TAX_RESET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) f_color = TAC_RESET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) for (i = 0, cell = line->cells; i < line->len; i++, cell++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) if (cell->highlight != highlight) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) flen += 3; /* TO_SA to switch highlight. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) highlight = cell->highlight;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) if (cell->f_color != f_color) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) flen += 3; /* TO_SA to switch color. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) f_color = cell->f_color;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) if (highlight != TAX_RESET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) flen += 3; /* TO_SA to reset hightlight. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) if (f_color != TAC_RESET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) flen += 3; /* TO_SA to reset color. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) if (line->len < tp->view.cols)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) flen += 4; /* Postfix (TO_RA). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) /* Find the line in the list. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) i = tp->view.rows - 2 - line_nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) list_for_each_entry_reverse(s, &tp->lines, list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) if (--i <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) * Check if the line needs to get reallocated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) if (s->len != flen) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) /* Reallocate string. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) n = tty3270_alloc_string(tp, flen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) list_add(&n->list, &s->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) list_del_init(&s->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) if (!list_empty(&s->update))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) list_del_init(&s->update);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) free_string(&tp->freemem, s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) s = n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) /* Write 3270 data fragment. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) cp = s->string;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) *cp++ = TO_SBA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) *cp++ = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) *cp++ = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) highlight = TAX_RESET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) f_color = TAC_RESET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) for (i = 0, cell = line->cells; i < line->len; i++, cell++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) if (cell->highlight != highlight) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) *cp++ = TO_SA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) *cp++ = TAT_EXTHI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) *cp++ = cell->highlight;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) highlight = cell->highlight;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) if (cell->f_color != f_color) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) *cp++ = TO_SA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) *cp++ = TAT_COLOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) *cp++ = cell->f_color;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) f_color = cell->f_color;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) *cp++ = cell->character;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) if (highlight != TAX_RESET) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) *cp++ = TO_SA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) *cp++ = TAT_EXTHI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) *cp++ = TAX_RESET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) if (f_color != TAC_RESET) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) *cp++ = TO_SA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) *cp++ = TAT_COLOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) *cp++ = TAC_RESET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) if (line->len < tp->view.cols) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) *cp++ = TO_RA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) *cp++ = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) *cp++ = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) *cp++ = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) if (tp->nr_up + line_nr < tp->view.rows - 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) /* Line is currently visible on screen. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) tty3270_update_string(tp, s, line_nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) /* Add line to update list. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) if (list_empty(&s->update)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) list_add_tail(&s->update, &tp->update);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) tp->update_flags |= TTY_UPDATE_LIST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) * Do carriage return.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) tty3270_cr(struct tty3270 *tp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) tp->cx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) * Do line feed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) tty3270_lf(struct tty3270 *tp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) struct tty3270_line temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) tty3270_convert_line(tp, tp->cy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) if (tp->cy < tp->view.rows - 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) tp->cy++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) /* Last line just filled up. Add new, blank line. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) tty3270_blank_line(tp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) temp = tp->screen[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) temp.len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) for (i = 0; i < tp->view.rows - 3; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) tp->screen[i] = tp->screen[i+1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) tp->screen[tp->view.rows - 3] = temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) tty3270_rebuild_update(tp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) tty3270_ri(struct tty3270 *tp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) if (tp->cy > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) tty3270_convert_line(tp, tp->cy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) tp->cy--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) * Insert characters at current position.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) tty3270_insert_characters(struct tty3270 *tp, int n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) struct tty3270_line *line;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) int k;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) line = tp->screen + tp->cy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) while (line->len < tp->cx) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) line->cells[line->len].character = tp->view.ascebc[' '];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) line->cells[line->len].highlight = TAX_RESET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) line->cells[line->len].f_color = TAC_RESET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) line->len++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) if (n > tp->view.cols - tp->cx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) n = tp->view.cols - tp->cx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) k = min_t(int, line->len - tp->cx, tp->view.cols - tp->cx - n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) while (k--)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) line->cells[tp->cx + n + k] = line->cells[tp->cx + k];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) line->len += n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) if (line->len > tp->view.cols)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) line->len = tp->view.cols;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) while (n-- > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) line->cells[tp->cx + n].character = tp->view.ascebc[' '];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) line->cells[tp->cx + n].highlight = tp->highlight;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) line->cells[tp->cx + n].f_color = tp->f_color;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) * Delete characters at current position.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) tty3270_delete_characters(struct tty3270 *tp, int n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) struct tty3270_line *line;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) line = tp->screen + tp->cy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) if (line->len <= tp->cx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) if (line->len - tp->cx <= n) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) line->len = tp->cx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) for (i = tp->cx; i + n < line->len; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) line->cells[i] = line->cells[i + n];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) line->len -= n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) * Erase characters at current position.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) tty3270_erase_characters(struct tty3270 *tp, int n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) struct tty3270_line *line;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) struct tty3270_cell *cell;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) line = tp->screen + tp->cy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) while (line->len > tp->cx && n-- > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) cell = line->cells + tp->cx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) cell->character = ' ';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) cell->highlight = TAX_RESET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) cell->f_color = TAC_RESET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) tp->cx += n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) tp->cx = min_t(int, tp->cx, tp->view.cols - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) * Erase line, 3 different cases:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) * Esc [ 0 K Erase from current position to end of line inclusive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) * Esc [ 1 K Erase from beginning of line to current position inclusive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) * Esc [ 2 K Erase entire line (without moving cursor)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) tty3270_erase_line(struct tty3270 *tp, int mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) struct tty3270_line *line;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) struct tty3270_cell *cell;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) line = tp->screen + tp->cy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) if (mode == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) line->len = tp->cx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) else if (mode == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) for (i = 0; i < tp->cx; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) cell = line->cells + i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) cell->character = ' ';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) cell->highlight = TAX_RESET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) cell->f_color = TAC_RESET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) if (line->len <= tp->cx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) line->len = tp->cx + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) } else if (mode == 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) line->len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) tty3270_convert_line(tp, tp->cy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) * Erase display, 3 different cases:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) * Esc [ 0 J Erase from current position to bottom of screen inclusive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) * Esc [ 1 J Erase from top of screen to current position inclusive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) * Esc [ 2 J Erase entire screen (without moving the cursor)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) tty3270_erase_display(struct tty3270 *tp, int mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) if (mode == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) tty3270_erase_line(tp, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) for (i = tp->cy + 1; i < tp->view.rows - 2; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) tp->screen[i].len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) tty3270_convert_line(tp, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) } else if (mode == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) for (i = 0; i < tp->cy; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) tp->screen[i].len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) tty3270_convert_line(tp, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) tty3270_erase_line(tp, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) } else if (mode == 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) for (i = 0; i < tp->view.rows - 2; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) tp->screen[i].len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) tty3270_convert_line(tp, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) tty3270_rebuild_update(tp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) * Set attributes found in an escape sequence.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) * Esc [ <attr> ; <attr> ; ... m
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) tty3270_set_attributes(struct tty3270 *tp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) static unsigned char f_colors[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) TAC_DEFAULT, TAC_RED, TAC_GREEN, TAC_YELLOW, TAC_BLUE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) TAC_PINK, TAC_TURQ, TAC_WHITE, 0, TAC_DEFAULT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) int i, attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) for (i = 0; i <= tp->esc_npar; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) attr = tp->esc_par[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) switch (attr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) case 0: /* Reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) tp->highlight = TAX_RESET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) tp->f_color = TAC_RESET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) /* Highlight. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) case 4: /* Start underlining. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) tp->highlight = TAX_UNDER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) case 5: /* Start blink. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) tp->highlight = TAX_BLINK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) case 7: /* Start reverse. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) tp->highlight = TAX_REVER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) case 24: /* End underlining */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) if (tp->highlight == TAX_UNDER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) tp->highlight = TAX_RESET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) case 25: /* End blink. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) if (tp->highlight == TAX_BLINK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) tp->highlight = TAX_RESET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) case 27: /* End reverse. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) if (tp->highlight == TAX_REVER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) tp->highlight = TAX_RESET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) /* Foreground color. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) case 30: /* Black */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) case 31: /* Red */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) case 32: /* Green */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) case 33: /* Yellow */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) case 34: /* Blue */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) case 35: /* Magenta */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) case 36: /* Cyan */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) case 37: /* White */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) case 39: /* Black */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) tp->f_color = f_colors[attr - 30];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) static inline int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) tty3270_getpar(struct tty3270 *tp, int ix)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) return (tp->esc_par[ix] > 0) ? tp->esc_par[ix] : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) tty3270_goto_xy(struct tty3270 *tp, int cx, int cy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) int max_cx = max(0, cx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) int max_cy = max(0, cy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) tp->cx = min_t(int, tp->view.cols - 1, max_cx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) cy = min_t(int, tp->view.rows - 3, max_cy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) if (cy != tp->cy) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) tty3270_convert_line(tp, tp->cy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) tp->cy = cy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) * Process escape sequences. Known sequences:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) * Esc 7 Save Cursor Position
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) * Esc 8 Restore Cursor Position
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) * Esc [ Pn ; Pn ; .. m Set attributes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) * Esc [ Pn ; Pn H Cursor Position
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) * Esc [ Pn ; Pn f Cursor Position
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) * Esc [ Pn A Cursor Up
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) * Esc [ Pn B Cursor Down
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) * Esc [ Pn C Cursor Forward
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) * Esc [ Pn D Cursor Backward
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) * Esc [ Pn G Cursor Horizontal Absolute
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) * Esc [ Pn X Erase Characters
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) * Esc [ Ps J Erase in Display
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) * Esc [ Ps K Erase in Line
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) * // FIXME: add all the new ones.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) * Pn is a numeric parameter, a string of zero or more decimal digits.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) * Ps is a selective parameter.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) tty3270_escape_sequence(struct tty3270 *tp, char ch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) enum { ESnormal, ESesc, ESsquare, ESgetpars };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) if (tp->esc_state == ESnormal) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) if (ch == 0x1b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) /* Starting new escape sequence. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) tp->esc_state = ESesc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) if (tp->esc_state == ESesc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) tp->esc_state = ESnormal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) switch (ch) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) case '[':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) tp->esc_state = ESsquare;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) case 'E':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) tty3270_cr(tp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) tty3270_lf(tp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) case 'M':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) tty3270_ri(tp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) case 'D':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) tty3270_lf(tp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) case 'Z': /* Respond ID. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) kbd_puts_queue(&tp->port, "\033[?6c");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) case '7': /* Save cursor position. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) tp->saved_cx = tp->cx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) tp->saved_cy = tp->cy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) tp->saved_highlight = tp->highlight;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) tp->saved_f_color = tp->f_color;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) case '8': /* Restore cursor position. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) tty3270_convert_line(tp, tp->cy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) tty3270_goto_xy(tp, tp->saved_cx, tp->saved_cy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) tp->highlight = tp->saved_highlight;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) tp->f_color = tp->saved_f_color;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) case 'c': /* Reset terminal. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) tp->cx = tp->saved_cx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) tp->cy = tp->saved_cy = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) tp->highlight = tp->saved_highlight = TAX_RESET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) tp->f_color = tp->saved_f_color = TAC_RESET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) tty3270_erase_display(tp, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) if (tp->esc_state == ESsquare) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) tp->esc_state = ESgetpars;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) memset(tp->esc_par, 0, sizeof(tp->esc_par));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) tp->esc_npar = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) tp->esc_ques = (ch == '?');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) if (tp->esc_ques)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) if (tp->esc_state == ESgetpars) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) if (ch == ';' && tp->esc_npar < ESCAPE_NPAR - 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) tp->esc_npar++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) if (ch >= '0' && ch <= '9') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) tp->esc_par[tp->esc_npar] *= 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) tp->esc_par[tp->esc_npar] += ch - '0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) tp->esc_state = ESnormal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) if (ch == 'n' && !tp->esc_ques) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) if (tp->esc_par[0] == 5) /* Status report. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) kbd_puts_queue(&tp->port, "\033[0n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) else if (tp->esc_par[0] == 6) { /* Cursor report. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) char buf[40];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) sprintf(buf, "\033[%d;%dR", tp->cy + 1, tp->cx + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) kbd_puts_queue(&tp->port, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) if (tp->esc_ques)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) switch (ch) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) case 'm':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) tty3270_set_attributes(tp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) case 'H': /* Set cursor position. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) case 'f':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) tty3270_goto_xy(tp, tty3270_getpar(tp, 1) - 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) tty3270_getpar(tp, 0) - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) case 'd': /* Set y position. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) tty3270_goto_xy(tp, tp->cx, tty3270_getpar(tp, 0) - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) case 'A': /* Cursor up. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) case 'F':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) tty3270_goto_xy(tp, tp->cx, tp->cy - tty3270_getpar(tp, 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) case 'B': /* Cursor down. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) case 'e':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) case 'E':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) tty3270_goto_xy(tp, tp->cx, tp->cy + tty3270_getpar(tp, 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) case 'C': /* Cursor forward. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) case 'a':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) tty3270_goto_xy(tp, tp->cx + tty3270_getpar(tp, 0), tp->cy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) case 'D': /* Cursor backward. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) tty3270_goto_xy(tp, tp->cx - tty3270_getpar(tp, 0), tp->cy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) case 'G': /* Set x position. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) case '`':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) tty3270_goto_xy(tp, tty3270_getpar(tp, 0), tp->cy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) case 'X': /* Erase Characters. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) tty3270_erase_characters(tp, tty3270_getpar(tp, 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) case 'J': /* Erase display. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) tty3270_erase_display(tp, tp->esc_par[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) case 'K': /* Erase line. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) tty3270_erase_line(tp, tp->esc_par[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) case 'P': /* Delete characters. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) tty3270_delete_characters(tp, tty3270_getpar(tp, 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) case '@': /* Insert characters. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) tty3270_insert_characters(tp, tty3270_getpar(tp, 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) case 's': /* Save cursor position. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) tp->saved_cx = tp->cx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) tp->saved_cy = tp->cy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) tp->saved_highlight = tp->highlight;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) tp->saved_f_color = tp->f_color;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) case 'u': /* Restore cursor position. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) tty3270_convert_line(tp, tp->cy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) tty3270_goto_xy(tp, tp->saved_cx, tp->saved_cy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) tp->highlight = tp->saved_highlight;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) tp->f_color = tp->saved_f_color;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) * String write routine for 3270 ttys
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) tty3270_do_write(struct tty3270 *tp, struct tty_struct *tty,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) const unsigned char *buf, int count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) int i_msg, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) spin_lock_bh(&tp->view.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) for (i_msg = 0; !tty->stopped && i_msg < count; i_msg++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) if (tp->esc_state != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) /* Continue escape sequence. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) tty3270_escape_sequence(tp, buf[i_msg]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) switch (buf[i_msg]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) case 0x07: /* '\a' -- Alarm */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) tp->wcc |= TW_PLUSALARM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) case 0x08: /* Backspace. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) if (tp->cx > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) tp->cx--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) tty3270_put_character(tp, ' ');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) case 0x09: /* '\t' -- Tabulate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) for (i = tp->cx % 8; i < 8; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) if (tp->cx >= tp->view.cols) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) tty3270_cr(tp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) tty3270_lf(tp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) tty3270_put_character(tp, ' ');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) tp->cx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) case 0x0a: /* '\n' -- New Line */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) tty3270_cr(tp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) tty3270_lf(tp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) case 0x0c: /* '\f' -- Form Feed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) tty3270_erase_display(tp, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) tp->cx = tp->cy = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) case 0x0d: /* '\r' -- Carriage Return */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) tp->cx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) case 0x0f: /* SuSE "exit alternate mode" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) case 0x1b: /* Start escape sequence. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) tty3270_escape_sequence(tp, buf[i_msg]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) default: /* Insert normal character. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) if (tp->cx >= tp->view.cols) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) tty3270_cr(tp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) tty3270_lf(tp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) tty3270_put_character(tp, buf[i_msg]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) tp->cx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) /* Convert current line to 3270 data fragment. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) tty3270_convert_line(tp, tp->cy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) /* Setup timer to update display after 1/10 second */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) if (!timer_pending(&tp->timer))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) tty3270_set_timer(tp, HZ/10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) spin_unlock_bh(&tp->view.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) * String write routine for 3270 ttys
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) tty3270_write(struct tty_struct * tty,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) const unsigned char *buf, int count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) struct tty3270 *tp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) tp = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) if (!tp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) if (tp->char_count > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) tty3270_do_write(tp, tty, tp->char_buf, tp->char_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) tp->char_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) tty3270_do_write(tp, tty, buf, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) * Put single characters to the ttys character buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) static int tty3270_put_char(struct tty_struct *tty, unsigned char ch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) struct tty3270 *tp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) tp = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) if (!tp || tp->char_count >= TTY3270_CHAR_BUF_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) tp->char_buf[tp->char_count++] = ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) * Flush all characters from the ttys characeter buffer put there
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) * by tty3270_put_char.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) tty3270_flush_chars(struct tty_struct *tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) struct tty3270 *tp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) tp = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) if (!tp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) if (tp->char_count > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) tty3270_do_write(tp, tty, tp->char_buf, tp->char_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) tp->char_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) * Returns the number of characters in the output buffer. This is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) * used in tty_wait_until_sent to wait until all characters have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) * appeared on the screen.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) tty3270_chars_in_buffer(struct tty_struct *tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) tty3270_flush_buffer(struct tty_struct *tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) * Check for visible/invisible input switches
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) tty3270_set_termios(struct tty_struct *tty, struct ktermios *old)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) struct tty3270 *tp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) int new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) tp = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) if (!tp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) spin_lock_bh(&tp->view.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) if (L_ICANON(tty)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789) new = L_ECHO(tty) ? TF_INPUT: TF_INPUTN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) if (new != tp->inattr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791) tp->inattr = new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792) tty3270_update_prompt(tp, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) tty3270_set_timer(tp, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796) spin_unlock_bh(&tp->view.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800) * Disable reading from a 3270 tty
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803) tty3270_throttle(struct tty_struct * tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) struct tty3270 *tp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) tp = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) if (!tp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810) tp->throttle = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814) * Enable reading from a 3270 tty
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817) tty3270_unthrottle(struct tty_struct * tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819) struct tty3270 *tp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821) tp = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822) if (!tp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824) tp->throttle = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825) if (tp->attn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) tty3270_issue_read(tp, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830) * Hang up the tty device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833) tty3270_hangup(struct tty_struct *tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835) struct tty3270 *tp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837) tp = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838) if (!tp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840) spin_lock_bh(&tp->view.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841) tp->cx = tp->saved_cx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842) tp->cy = tp->saved_cy = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843) tp->highlight = tp->saved_highlight = TAX_RESET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844) tp->f_color = tp->saved_f_color = TAC_RESET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845) tty3270_blank_screen(tp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846) while (tp->nr_lines < tp->view.rows - 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847) tty3270_blank_line(tp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848) tp->update_flags = TTY_UPDATE_ALL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849) spin_unlock_bh(&tp->view.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850) tty3270_set_timer(tp, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854) tty3270_wait_until_sent(struct tty_struct *tty, int timeout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858) static int tty3270_ioctl(struct tty_struct *tty, unsigned int cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859) unsigned long arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861) struct tty3270 *tp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863) tp = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864) if (!tp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866) if (tty_io_error(tty))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868) return kbd_ioctl(tp->kbd, cmd, arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871) #ifdef CONFIG_COMPAT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872) static long tty3270_compat_ioctl(struct tty_struct *tty,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873) unsigned int cmd, unsigned long arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875) struct tty3270 *tp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877) tp = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878) if (!tp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880) if (tty_io_error(tty))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882) return kbd_ioctl(tp->kbd, cmd, (unsigned long)compat_ptr(arg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886) static const struct tty_operations tty3270_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887) .install = tty3270_install,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888) .cleanup = tty3270_cleanup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889) .open = tty3270_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890) .close = tty3270_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891) .write = tty3270_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892) .put_char = tty3270_put_char,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893) .flush_chars = tty3270_flush_chars,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894) .write_room = tty3270_write_room,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895) .chars_in_buffer = tty3270_chars_in_buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896) .flush_buffer = tty3270_flush_buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897) .throttle = tty3270_throttle,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898) .unthrottle = tty3270_unthrottle,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899) .hangup = tty3270_hangup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900) .wait_until_sent = tty3270_wait_until_sent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901) .ioctl = tty3270_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902) #ifdef CONFIG_COMPAT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903) .compat_ioctl = tty3270_compat_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1905) .set_termios = tty3270_set_termios
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1906) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1907)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1908) static void tty3270_create_cb(int minor)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1909) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1910) tty_register_device(tty3270_driver, minor - RAW3270_FIRSTMINOR, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1911) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1912)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1913) static void tty3270_destroy_cb(int minor)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1914) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1915) tty_unregister_device(tty3270_driver, minor - RAW3270_FIRSTMINOR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1916) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1917)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1918) static struct raw3270_notifier tty3270_notifier =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1919) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1920) .create = tty3270_create_cb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1921) .destroy = tty3270_destroy_cb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1922) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1923)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1924) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1925) * 3270 tty registration code called from tty_init().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1926) * Most kernel services (incl. kmalloc) are available at this poimt.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1927) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1928) static int __init tty3270_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1929) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1930) struct tty_driver *driver;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1931) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1932)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1933) driver = tty_alloc_driver(RAW3270_MAXDEVS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1934) TTY_DRIVER_REAL_RAW |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1935) TTY_DRIVER_DYNAMIC_DEV |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1936) TTY_DRIVER_RESET_TERMIOS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1937) if (IS_ERR(driver))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938) return PTR_ERR(driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1939)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1940) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1941) * Initialize the tty_driver structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1942) * Entries in tty3270_driver that are NOT initialized:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1943) * proc_entry, set_termios, flush_buffer, set_ldisc, write_proc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1944) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1945) driver->driver_name = "tty3270";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1946) driver->name = "3270/tty";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1947) driver->major = IBM_TTY3270_MAJOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1948) driver->minor_start = RAW3270_FIRSTMINOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1949) driver->name_base = RAW3270_FIRSTMINOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1950) driver->type = TTY_DRIVER_TYPE_SYSTEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1951) driver->subtype = SYSTEM_TYPE_TTY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1952) driver->init_termios = tty_std_termios;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1953) tty_set_operations(driver, &tty3270_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1954) ret = tty_register_driver(driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1955) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1956) put_tty_driver(driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1957) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1958) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1959) tty3270_driver = driver;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1960) raw3270_register_notifier(&tty3270_notifier);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1961) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1962) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1963)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1964) static void __exit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1965) tty3270_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1966) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1967) struct tty_driver *driver;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1968)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1969) raw3270_unregister_notifier(&tty3270_notifier);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1970) driver = tty3270_driver;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1971) tty3270_driver = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1972) tty_unregister_driver(driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1973) put_tty_driver(driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1974) tty3270_del_views();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1975) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1976)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1977) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1978) MODULE_ALIAS_CHARDEV_MAJOR(IBM_TTY3270_MAJOR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1979)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1980) module_init(tty3270_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1981) module_exit(tty3270_exit);