Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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);