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 - console view.
^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, 2009
^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/console.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <linux/list.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include <linux/reboot.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) #include <asm/ccwdev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) #include <asm/cio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) #include <asm/cpcmd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) #include <asm/ebcdic.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) #include "raw3270.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) #include "tty3270.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) #include "ctrlchar.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) #define CON3270_OUTPUT_BUFFER_SIZE 1024
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) #define CON3270_STRING_PAGES 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) static struct raw3270_fn con3270_fn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) static bool auto_update = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) module_param(auto_update, bool, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39)  * Main 3270 console view data structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) struct con3270 {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 	struct raw3270_view view;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 	struct list_head freemem;	/* list of free memory for strings. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 	/* Output stuff. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 	struct list_head lines;		/* list of lines. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	struct list_head update;	/* list of lines to update. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 	int line_nr;			/* line number for next update. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 	int nr_lines;			/* # lines in list. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 	int nr_up;			/* # lines up in history. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 	unsigned long update_flags;	/* Update indication bits. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 	struct string *cline;		/* current output line. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 	struct string *status;		/* last line of display. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 	struct raw3270_request *write;	/* single write request. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 	struct timer_list timer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 	/* Input stuff. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 	struct string *input;		/* input string for read request. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 	struct raw3270_request *read;	/* single read request. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 	struct raw3270_request *kreset;	/* single keyboard reset request. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 	struct tasklet_struct readlet;	/* tasklet to issue read request. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) static struct con3270 *condev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) /* con3270->update_flags. See con3270_update for details. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) #define CON_UPDATE_ERASE	1	/* Use EWRITEA instead of WRITE. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) #define CON_UPDATE_LIST		2	/* Update lines in tty3270->update. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) #define CON_UPDATE_STATUS	4	/* Update status line. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) #define CON_UPDATE_ALL		8	/* Recreate screen. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) static void con3270_update(struct timer_list *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75)  * Setup timeout for a device. On timeout trigger an update.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) static void con3270_set_timer(struct con3270 *cp, int expires)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 	if (expires == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 		del_timer(&cp->timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 		mod_timer(&cp->timer, jiffies + expires);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86)  * The status line is the last line of the screen. It shows the string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87)  * "console view" in the lower left corner and "Running"/"More..."/"Holding"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88)  * in the lower right corner of the screen.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) con3270_update_status(struct con3270 *cp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	char *str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 	str = (cp->nr_up != 0) ? "History" : "Running";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 	memcpy(cp->status->string + 24, str, 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	codepage_convert(cp->view.ascebc, cp->status->string + 24, 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	cp->update_flags |= CON_UPDATE_STATUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) con3270_create_status(struct con3270 *cp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 	static const unsigned char blueprint[] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 		{ TO_SBA, 0, 0, TO_SF,TF_LOG,TO_SA,TAT_COLOR, TAC_GREEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 		  'c','o','n','s','o','l','e',' ','v','i','e','w',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 		  TO_RA,0,0,0,'R','u','n','n','i','n','g',TO_SF,TF_LOG };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 	cp->status = alloc_string(&cp->freemem, sizeof(blueprint));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 	/* Copy blueprint to status line */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 	memcpy(cp->status->string, blueprint, sizeof(blueprint));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 	/* Set TO_RA addresses. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 	raw3270_buffer_address(cp->view.dev, cp->status->string + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 			       cp->view.cols * (cp->view.rows - 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 	raw3270_buffer_address(cp->view.dev, cp->status->string + 21,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 			       cp->view.cols * cp->view.rows - 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	/* Convert strings to ebcdic. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 	codepage_convert(cp->view.ascebc, cp->status->string + 8, 12);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	codepage_convert(cp->view.ascebc, cp->status->string + 24, 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)  * Set output offsets to 3270 datastream fragment of a console string.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) con3270_update_string(struct con3270 *cp, struct string *s, int nr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 	if (s->len < 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 		/* This indicates a bug, but printing a warning would
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 		 * cause a deadlock. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	if (s->string[s->len - 4] != TO_RA)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 	raw3270_buffer_address(cp->view.dev, s->string + s->len - 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 			       cp->view.cols * (nr + 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)  * Rebuild update list to print all lines.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) con3270_rebuild_update(struct con3270 *cp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 	struct string *s, *n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 	int nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 	/* 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 	 * Throw away update list and create a new one,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 	 * containing all lines that will fit on the screen.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 	list_for_each_entry_safe(s, n, &cp->update, update)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 		list_del_init(&s->update);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 	nr = cp->view.rows - 2 + cp->nr_up;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 	list_for_each_entry_reverse(s, &cp->lines, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 		if (nr < cp->view.rows - 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 			list_add(&s->update, &cp->update);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 		if (--nr < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 	cp->line_nr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 	cp->update_flags |= CON_UPDATE_LIST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)  * Alloc string for size bytes. Free strings from history if necessary.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) static struct string *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) con3270_alloc_string(struct con3270 *cp, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 	struct string *s, *n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 	s = alloc_string(&cp->freemem, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 	if (s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 		return s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 	list_for_each_entry_safe(s, n, &cp->lines, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 		list_del(&s->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 		if (!list_empty(&s->update))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 			list_del(&s->update);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 		cp->nr_lines--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 		if (free_string(&cp->freemem, s) >= size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 	s = alloc_string(&cp->freemem, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 	BUG_ON(!s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 	if (cp->nr_up != 0 && cp->nr_up + cp->view.rows > cp->nr_lines) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 		cp->nr_up = cp->nr_lines - cp->view.rows + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 		con3270_rebuild_update(cp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 		con3270_update_status(cp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 	return s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)  * Write completion callback.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) con3270_write_callback(struct raw3270_request *rq, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 	raw3270_request_reset(rq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 	xchg(&((struct con3270 *) rq->view)->write, rq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) }
^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)  * Update console display.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) con3270_update(struct timer_list *t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 	struct con3270 *cp = from_timer(cp, t, timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 	struct raw3270_request *wrq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 	char wcc, prolog[6];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 	unsigned long updated;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 	struct string *s, *n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 	if (!auto_update && !raw3270_view_active(&cp->view))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 	if (cp->view.dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 		raw3270_activate_view(&cp->view);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 	wrq = xchg(&cp->write, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 	if (!wrq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 		con3270_set_timer(cp, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 	spin_lock_irqsave(&cp->view.lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 	updated = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 	if (cp->update_flags & CON_UPDATE_ALL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 		con3270_rebuild_update(cp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 		con3270_update_status(cp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 		cp->update_flags = CON_UPDATE_ERASE | CON_UPDATE_LIST |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 			CON_UPDATE_STATUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 	if (cp->update_flags & CON_UPDATE_ERASE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 		/* Use erase write alternate to initialize display. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 		raw3270_request_set_cmd(wrq, TC_EWRITEA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 		updated |= CON_UPDATE_ERASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 	} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 		raw3270_request_set_cmd(wrq, TC_WRITE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 	wcc = TW_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 	raw3270_request_add_data(wrq, &wcc, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 	 * Update status line.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 	if (cp->update_flags & CON_UPDATE_STATUS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 		if (raw3270_request_add_data(wrq, cp->status->string,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 					     cp->status->len) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 			updated |= CON_UPDATE_STATUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 	if (cp->update_flags & CON_UPDATE_LIST) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 		prolog[0] = TO_SBA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 		prolog[3] = TO_SA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 		prolog[4] = TAT_COLOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 		prolog[5] = TAC_TURQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 		raw3270_buffer_address(cp->view.dev, prolog + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 				       cp->view.cols * cp->line_nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 		raw3270_request_add_data(wrq, prolog, 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 		/* Write strings in the update list to the screen. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 		list_for_each_entry_safe(s, n, &cp->update, update) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 			if (s != cp->cline)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 				con3270_update_string(cp, s, cp->line_nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 			if (raw3270_request_add_data(wrq, s->string,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 						     s->len) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 			list_del_init(&s->update);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 			if (s != cp->cline)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 				cp->line_nr++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 		if (list_empty(&cp->update))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 			updated |= CON_UPDATE_LIST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 	wrq->callback = con3270_write_callback;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 	rc = raw3270_start(&cp->view, wrq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 	if (rc == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 		cp->update_flags &= ~updated;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 		if (cp->update_flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 			con3270_set_timer(cp, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 		raw3270_request_reset(wrq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 		xchg(&cp->write, wrq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 	spin_unlock_irqrestore(&cp->view.lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)  * Read tasklet.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) con3270_read_tasklet(struct raw3270_request *rrq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 	static char kreset_data = TW_KR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 	struct con3270 *cp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 	int nr_up, deactivate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 	cp = (struct con3270 *) rrq->view;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 	spin_lock_irqsave(&cp->view.lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 	nr_up = cp->nr_up;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 	deactivate = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 	/* Check aid byte. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 	switch (cp->input->string[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 	case 0x7d:	/* enter: jump to bottom. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 		nr_up = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 	case 0xf3:	/* PF3: deactivate the console view. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 		deactivate = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 	case 0x6d:	/* clear: start from scratch. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 		cp->update_flags = CON_UPDATE_ALL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 		con3270_set_timer(cp, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 	case 0xf7:	/* PF7: do a page up in the console log. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 		nr_up += cp->view.rows - 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 		if (nr_up + cp->view.rows - 1 > cp->nr_lines) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 			nr_up = cp->nr_lines - cp->view.rows + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 			if (nr_up < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 				nr_up = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 	case 0xf8:	/* PF8: do a page down in the console log. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 		nr_up -= cp->view.rows - 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 		if (nr_up < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 			nr_up = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 	if (nr_up != cp->nr_up) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 		cp->nr_up = nr_up;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 		con3270_rebuild_update(cp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 		con3270_update_status(cp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 		con3270_set_timer(cp, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 	spin_unlock_irqrestore(&cp->view.lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 	/* Start keyboard reset command. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 	raw3270_request_reset(cp->kreset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 	raw3270_request_set_cmd(cp->kreset, TC_WRITE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 	raw3270_request_add_data(cp->kreset, &kreset_data, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 	raw3270_start(&cp->view, cp->kreset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 	if (deactivate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 		raw3270_deactivate_view(&cp->view);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 	raw3270_request_reset(rrq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 	xchg(&cp->read, rrq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 	raw3270_put_view(&cp->view);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)  * Read request completion callback.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) con3270_read_callback(struct raw3270_request *rq, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 	raw3270_get_view(rq->view);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 	/* Schedule tasklet to pass input to tty. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 	tasklet_schedule(&((struct con3270 *) rq->view)->readlet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)  * Issue a read request. Called only from interrupt function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) con3270_issue_read(struct con3270 *cp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 	struct raw3270_request *rrq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 	rrq = xchg(&cp->read, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 	if (!rrq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 		/* Read already scheduled. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 	rrq->callback = con3270_read_callback;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 	rrq->callback_data = cp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 	raw3270_request_set_cmd(rrq, TC_READMOD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 	raw3270_request_set_data(rrq, cp->input->string, cp->input->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 	/* Issue the read modified request. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 	rc = raw3270_start_irq(&cp->view, rrq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 		raw3270_request_reset(rrq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)  * Switch to the console view.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) con3270_activate(struct raw3270_view *view)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 	struct con3270 *cp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 	cp = (struct con3270 *) view;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 	cp->update_flags = CON_UPDATE_ALL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 	con3270_set_timer(cp, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) con3270_deactivate(struct raw3270_view *view)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 	struct con3270 *cp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 	cp = (struct con3270 *) view;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 	del_timer(&cp->timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) con3270_irq(struct con3270 *cp, struct raw3270_request *rq, struct irb *irb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 	/* Handle ATTN. Schedule tasklet to read aid. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 	if (irb->scsw.cmd.dstat & DEV_STAT_ATTENTION)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 		con3270_issue_read(cp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 	if (rq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 		if (irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 			rq->rc = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 			/* Normal end. Copy residual count. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 			rq->rescnt = irb->scsw.cmd.count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) 	} else if (irb->scsw.cmd.dstat & DEV_STAT_DEV_END) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 		/* Interrupt without an outstanding request -> update all */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) 		cp->update_flags = CON_UPDATE_ALL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) 		con3270_set_timer(cp, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) /* Console view to a 3270 device. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) static struct raw3270_fn con3270_fn = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) 	.activate = con3270_activate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) 	.deactivate = con3270_deactivate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) 	.intv = (void *) con3270_irq
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) con3270_cline_add(struct con3270 *cp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) 	if (!list_empty(&cp->cline->list))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 		/* Already added. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) 	list_add_tail(&cp->cline->list, &cp->lines);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) 	cp->nr_lines++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) 	con3270_rebuild_update(cp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) con3270_cline_insert(struct con3270 *cp, unsigned char c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) 	cp->cline->string[cp->cline->len++] = 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) 		cp->view.ascebc[(c < ' ') ? ' ' : c];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) 	if (list_empty(&cp->cline->update)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) 		list_add_tail(&cp->cline->update, &cp->update);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 		cp->update_flags |= CON_UPDATE_LIST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) con3270_cline_end(struct con3270 *cp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) 	struct string *s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) 	unsigned int size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) 	/* Copy cline. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) 	size = (cp->cline->len < cp->view.cols - 5) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 		cp->cline->len + 4 : cp->view.cols;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 	s = con3270_alloc_string(cp, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 	memcpy(s->string, cp->cline->string, cp->cline->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) 	if (cp->cline->len < cp->view.cols - 5) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) 		s->string[s->len - 4] = TO_RA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) 		s->string[s->len - 1] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) 		while (--size >= cp->cline->len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) 			s->string[size] = cp->view.ascebc[' '];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) 	/* Replace cline with allocated line s and reset cline. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) 	list_add(&s->list, &cp->cline->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) 	list_del_init(&cp->cline->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) 	if (!list_empty(&cp->cline->update)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) 		list_add(&s->update, &cp->cline->update);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) 		list_del_init(&cp->cline->update);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) 	cp->cline->len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)  * Write a string to the 3270 console
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) con3270_write(struct console *co, const char *str, unsigned int count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) 	struct con3270 *cp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) 	unsigned char c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) 	cp = condev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) 	spin_lock_irqsave(&cp->view.lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) 	while (count-- > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) 		c = *str++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) 		if (cp->cline->len == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) 			con3270_cline_add(cp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) 		if (c != '\n')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) 			con3270_cline_insert(cp, c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) 		if (c == '\n' || cp->cline->len >= cp->view.cols)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) 			con3270_cline_end(cp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) 	/* Setup timer to output current console buffer after 1/10 second */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) 	cp->nr_up = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) 	if (cp->view.dev && !timer_pending(&cp->timer))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) 		con3270_set_timer(cp, HZ/10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) 	spin_unlock_irqrestore(&cp->view.lock,flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) static struct tty_driver *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) con3270_device(struct console *c, int *index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) 	*index = c->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) 	return tty3270_driver;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523)  * Wait for end of write request.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) con3270_wait_write(struct con3270 *cp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) 	while (!cp->write) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) 		raw3270_wait_cons_dev(cp->view.dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) 		barrier();
^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) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535)  * panic() calls con3270_flush through a panic_notifier
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)  * before the system enters a disabled, endless loop.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) con3270_flush(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) 	struct con3270 *cp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) 	cp = condev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) 	if (!cp->view.dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) 	raw3270_pm_unfreeze(&cp->view);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) 	raw3270_activate_view(&cp->view);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) 	spin_lock_irqsave(&cp->view.lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) 	con3270_wait_write(cp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) 	cp->nr_up = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) 	con3270_rebuild_update(cp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) 	con3270_update_status(cp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) 	while (cp->update_flags != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) 		spin_unlock_irqrestore(&cp->view.lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) 		con3270_update(&cp->timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) 		spin_lock_irqsave(&cp->view.lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) 		con3270_wait_write(cp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) 	spin_unlock_irqrestore(&cp->view.lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) static int con3270_notify(struct notifier_block *self,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) 			  unsigned long event, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) 	con3270_flush();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) 	return NOTIFY_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) static struct notifier_block on_panic_nb = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) 	.notifier_call = con3270_notify,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) 	.priority = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) static struct notifier_block on_reboot_nb = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) 	.notifier_call = con3270_notify,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) 	.priority = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581)  *  The console structure for the 3270 console
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) static struct console con3270 = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) 	.name	 = "tty3270",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) 	.write	 = con3270_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) 	.device	 = con3270_device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) 	.flags	 = CON_PRINTBUFFER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591)  * 3270 console initialization code called from console_init().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) static int __init
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) con3270_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) 	struct raw3270 *rp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) 	void *cbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) 	/* Check if 3270 is to be the console */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) 	if (!CONSOLE_IS_3270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) 	/* Set the console mode for VM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) 	if (MACHINE_IS_VM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) 		cpcmd("TERM CONMODE 3270", NULL, 0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) 		cpcmd("TERM AUTOCR OFF", NULL, 0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) 	rp = raw3270_setup_console();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) 	if (IS_ERR(rp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) 		return PTR_ERR(rp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) 	condev = kzalloc(sizeof(struct con3270), GFP_KERNEL | GFP_DMA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) 	if (!condev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) 	condev->view.dev = rp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) 	condev->read = raw3270_request_alloc(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) 	condev->read->callback = con3270_read_callback;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) 	condev->read->callback_data = condev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) 	condev->write = raw3270_request_alloc(CON3270_OUTPUT_BUFFER_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) 	condev->kreset = raw3270_request_alloc(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) 	INIT_LIST_HEAD(&condev->lines);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) 	INIT_LIST_HEAD(&condev->update);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) 	timer_setup(&condev->timer, con3270_update, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) 	tasklet_init(&condev->readlet, 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) 		     (void (*)(unsigned long)) con3270_read_tasklet,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) 		     (unsigned long) condev->read);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) 	raw3270_add_view(&condev->view, &con3270_fn, 1, RAW3270_VIEW_LOCK_IRQ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) 	INIT_LIST_HEAD(&condev->freemem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) 	for (i = 0; i < CON3270_STRING_PAGES; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) 		cbuf = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) 		add_string_memory(&condev->freemem, cbuf, PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) 	condev->cline = alloc_string(&condev->freemem, condev->view.cols);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) 	condev->cline->len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) 	con3270_create_status(condev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) 	condev->input = alloc_string(&condev->freemem, 80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) 	atomic_notifier_chain_register(&panic_notifier_list, &on_panic_nb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) 	register_reboot_notifier(&on_reboot_nb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) 	register_console(&con3270);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) console_initcall(con3270_init);