patch-2.4.4 linux/drivers/s390/char/tubttybld.c

Next file: linux/drivers/s390/char/tubttyrcl.c
Previous file: linux/drivers/s390/char/tubttyaid.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.3/linux/drivers/s390/char/tubttybld.c linux/drivers/s390/char/tubttybld.c
@@ -0,0 +1,448 @@
+/*
+ *  IBM/3270 Driver -- Copyright (C) 2000 UTS Global LLC
+ *
+ *  tubttybld.c -- Linemode tty driver screen-building functions
+ *
+ *
+ *
+ *
+ *
+ *  Author:  Richard Hitt
+ */
+
+#include "tubio.h"
+
+extern int tty3270_io(tub_t *);
+static void tty3270_set_status_area(tub_t *, char **);
+static int tty3270_next_char(tub_t *);
+static void tty3270_update_log_area(tub_t *, char **);
+static void tty3270_update_log_area_esc(tub_t *, char **);
+static void tty3270_clear_log_area(tub_t *, char **);
+static void tty3270_tub_bufadr(tub_t *, int, char **);
+
+/*
+ * tty3270_clear_log_area(tub_t *tubp, char **cpp)
+ */
+static void
+tty3270_clear_log_area(tub_t *tubp, char **cpp)
+{
+	*(*cpp)++ = TO_SBA;
+	TUB_BUFADR(GEOM_LOG, cpp);
+	*(*cpp)++ = TO_SF;
+	*(*cpp)++ = TF_LOG;
+	*(*cpp)++ = TO_RA;
+	TUB_BUFADR(GEOM_INPUT, cpp);
+	*(*cpp)++ = '\0';
+	tubp->tty_oucol = tubp->tty_nextlogx = 0;
+}
+
+static void
+tty3270_update_log_area(tub_t *tubp, char **cpp)
+{
+	int lastx = GEOM_INPUT;
+	int c;
+	int next, fill, i;
+	int sba_needed = 1;
+	char *overrun = &(*tubp->ttyscreen)[tubp->ttyscreenl - TS_LENGTH];
+
+	/* Place characters */
+	while (tubp->tty_bcb.bc_cnt != 0) {
+		if (tubp->tty_nextlogx >= lastx) {
+			if (sba_needed == 0 || tubp->stat == TBS_RUNNING) {
+				tubp->stat = TBS_MORE;
+				tty3270_set_status_area(tubp, cpp);
+				tty3270_scl_settimer(tubp);
+			}
+			break;
+		}
+
+		/* Check for room for another char + possible ESCs */
+		if (&(*cpp)[tubp->tty_escx + 1] >= overrun)
+			break;
+
+		/* Fetch a character */
+		if ((c = tty3270_next_char(tubp)) == -1)
+			break;
+
+		/* Add a Set-Buffer-Address Order if we haven't */
+		if (sba_needed) {
+			sba_needed = 0;
+			*(*cpp)++ = TO_SBA;
+			TUB_BUFADR(tubp->tty_nextlogx, cpp);
+		}
+
+		switch(c) {
+		default:
+			if (c < ' ')    /* Blank it if we don't know it */
+				c = ' ';
+			for (i = 0; i < tubp->tty_escx; i++)
+				*(*cpp)++ = tubp->tty_esca[i];
+			tubp->tty_escx = 0;
+			*(*cpp)++ = tub_ascebc[(int)c];
+			tubp->tty_nextlogx++;
+			tubp->tty_oucol++;
+			break;
+		case 0x1b:              /* ESC */
+			tty3270_update_log_area_esc(tubp, cpp);
+			break;
+		case '\r':
+			break;          /* completely ignore 0x0d = CR. */
+		case '\n':
+			if (tubp->tty_oucol == GEOM_COLS) {
+				tubp->tty_oucol = 0;
+				break;
+			}
+			next = (tubp->tty_nextlogx + GEOM_COLS) /
+				GEOM_COLS * GEOM_COLS;
+			next = MIN(next, lastx);
+			fill = next - tubp->tty_nextlogx;
+			if (fill < 5) {
+				for (i = 0; i < fill; i++)
+					*(*cpp)++ = tub_ascebc[' '];
+			} else {
+				*(*cpp)++ = TO_RA;
+				TUB_BUFADR(next, cpp);
+				*(*cpp)++ = tub_ascebc[' '];
+			}
+			tubp->tty_nextlogx = next;
+			tubp->tty_oucol = 0;
+			break;
+		case '\t':
+			fill = (tubp->tty_nextlogx % GEOM_COLS) % 8;
+			for (; fill < 8; fill++) {
+				if (tubp->tty_nextlogx >= lastx)
+					break;
+				*(*cpp)++ = tub_ascebc[' '];
+				tubp->tty_nextlogx++;
+				tubp->tty_oucol++;
+			}
+			break;
+		case '\a':
+			tubp->flags |= TUB_ALARM;
+			break;
+		case '\f':
+			tty3270_clear_log_area(tubp, cpp);
+			break;
+		}
+	}
+}
+
+#define NUMQUANT 8
+static void
+tty3270_update_log_area_esc(tub_t *tubp, char **cpp)
+{
+	int lastx = GEOM_INPUT;
+	int c;
+	int i;
+	int start, next, fill;
+	int quant[NUMQUANT];
+
+	if ((c = tty3270_next_char(tubp)) != '[') {
+		return;
+	}
+
+	/*
+	 * Parse potentially empty string "nn;nn;nn..."
+	 */
+	i = -1;
+	c = ';';
+	do {
+		if (c == ';') {
+			if (++i == NUMQUANT)
+				break;
+			quant[i] = 0;
+		} else if (c < '0' || c > '9') {
+			break;
+		} else {
+			quant[i] = quant[i] * 10 + c - '0';
+		}
+	} while ((c = tty3270_next_char(tubp)) != -1);
+	if (c == -1) {
+		return;
+	}
+	if (i >= NUMQUANT) {
+		return;
+	}
+	switch(c) {
+	case -1:
+		return;
+	case 'm':		/* Set Attribute */
+		for (next = 0; next <= i; next++) {
+			int type = -1, value = 0;
+
+			if (tubp->tty_escx + 3 > MAX_TTY_ESCA)
+				break;
+			switch(quant[next]) {
+			case 0:		/* Reset */
+				tubp->tty_esca[tubp->tty_escx++] = TO_SA;
+				tubp->tty_esca[tubp->tty_escx++] = TAT_RESET;
+				tubp->tty_esca[tubp->tty_escx++] = TAR_RESET;
+				break;
+			case 1:		/* Bright */
+			case 2:		/* Dim */
+			case 4:		/* Underscore */
+			case 5:		/* Blink */
+			case 7:		/* Reverse */
+			case 8:		/* Hidden */
+				break;		/* For now ... */
+			/* Foreground Colors */
+			case 30:	/* Black */
+				type = TAT_COLOR; value = TAC_DEFAULT;
+				break;
+			case 31:	/* Red */
+				type = TAT_COLOR; value = TAC_RED;
+				break;
+			case 32:	/* Green */
+				type = TAT_COLOR; value = TAC_GREEN;
+				break;
+			case 33:	/* Yellow */
+				type = TAT_COLOR; value = TAC_YELLOW;
+				break;
+			case 34:	/* Blue */
+				type = TAT_COLOR; value = TAC_BLUE;
+				break;
+			case 35:	/* Magenta */
+				type = TAT_COLOR; value = TAC_PINK;
+				break;
+			case 36:	/* Cyan */
+				type = TAT_COLOR; value = TAC_TURQ;
+				break;
+			case 37:	/* White */
+				type = TAT_COLOR; value = TAC_WHITE;
+				break;
+			case 39:	/* Black */
+				type = TAT_COLOR; value = TAC_DEFAULT;
+				break;
+			/* Background Colors */
+			case 40:	/* Black */
+			case 41:	/* Red */
+			case 42:	/* Green */
+			case 43:	/* Yellow */
+			case 44:	/* Blue */
+			case 45:	/* Magenta */
+			case 46:	/* Cyan */
+			case 47:	/* White */
+				break;		/* For now ... */
+			/* Oops */
+			default:
+				break;
+			}
+			if (type != -1) {
+				tubp->tty_esca[tubp->tty_escx++] = TO_SA;
+				tubp->tty_esca[tubp->tty_escx++] = type;
+				tubp->tty_esca[tubp->tty_escx++] = value;
+			}
+		}
+		break;
+	case 'H':		/* Cursor Home */
+	case 'f':		/* Force Cursor Position */
+		return;
+	case 'A':		/* Cursor Up */
+		return;
+	case 'B':		/* Cursor Down */
+		return;
+	case 'C':		/* Cursor Forward */
+		next = tubp->tty_nextlogx % GEOM_COLS;
+		start = tubp->tty_nextlogx - next;
+		next = start + MIN(next + quant[i], GEOM_COLS - 1);
+		next = MIN(next, lastx);
+do_fill:
+		fill = next - tubp->tty_nextlogx;
+		if (fill < 5) {
+			for (i = 0; i < fill; i++)
+				*(*cpp)++ = tub_ascebc[' '];
+		} else {
+			*(*cpp)++ = TO_RA;
+			TUB_BUFADR(next, cpp);
+			*(*cpp)++ = tub_ascebc[' '];
+		}
+		tubp->tty_nextlogx = next;
+		tubp->tty_oucol = tubp->tty_nextlogx % GEOM_COLS;
+		break;
+	case 'D':		/* Cursor Backward */
+		next = MIN(quant[i], tubp->tty_nextlogx % GEOM_COLS);
+		tubp->tty_nextlogx -= next;
+		tubp->tty_oucol = tubp->tty_nextlogx % GEOM_COLS;
+		*(*cpp)++ = TO_SBA;
+		TUB_BUFADR(tubp->tty_nextlogx, cpp);
+		break;
+	case 'G':
+		start = tubp->tty_nextlogx / GEOM_COLS * GEOM_COLS;
+		next = MIN(quant[i], GEOM_COLS - 1) + start;
+		next = MIN(next, lastx);
+		goto do_fill;
+	}
+}
+
+
+static int
+tty3270_next_char(tub_t *tubp)
+{
+	int c;
+	bcb_t *ib;
+
+	ib = &tubp->tty_bcb;
+	if (ib->bc_cnt == 0)
+		return -1;
+	c = ib->bc_buf[ib->bc_rd++];
+	if (ib->bc_rd == ib->bc_len)
+		ib->bc_rd = 0;
+	ib->bc_cnt--;
+	return c;
+}
+
+
+static void
+tty3270_clear_input_area(tub_t *tubp, char **cpp)
+{
+	*(*cpp)++ = TO_SBA;
+	TUB_BUFADR(GEOM_INPUT, cpp);
+	*(*cpp)++ = TO_SF;
+	*(*cpp)++ = tubp->tty_inattr;
+	*(*cpp)++ = TO_IC;
+	*(*cpp)++ = TO_RA;
+	TUB_BUFADR(GEOM_STAT, cpp);
+	*(*cpp)++ = '\0';
+}
+
+static void
+tty3270_update_input_area(tub_t *tubp, char **cpp)
+{
+	int len;
+
+	*(*cpp)++ = TO_SBA;
+	TUB_BUFADR(GEOM_INPUT, cpp);
+	*(*cpp)++ = TO_SF;
+	*(*cpp)++ = TF_INMDT;
+	len = strlen(tubp->tty_input);
+	memcpy(*cpp, tubp->tty_input, len);
+	*cpp += len;
+	*(*cpp)++ = TO_IC;
+	len = GEOM_INPLEN - len;
+	if (len > 4) {
+		*(*cpp)++ = TO_RA;
+		TUB_BUFADR(GEOM_STAT, cpp);
+		*(*cpp)++ = '\0';
+	} else {
+		for (; len > 0; len--)
+			*(*cpp)++ = '\0';
+	}
+}
+
+/*
+ * tty3270_set_status_area(tub_t *tubp, char **cpp)
+ */
+static void
+tty3270_set_status_area(tub_t *tubp, char **cpp)
+{
+	char *sp;
+
+	if (tubp->stat == TBS_RUNNING)
+		sp = TS_RUNNING;
+	else if (tubp->stat == TBS_MORE)
+		sp = TS_MORE;
+	else if (tubp->stat == TBS_HOLD)
+		sp = TS_HOLD;
+	else
+		sp = "Linux Whatstat";
+
+	*(*cpp)++ = TO_SBA;
+	TUB_BUFADR(GEOM_STAT, cpp);
+	*(*cpp)++ = TO_SF;
+	*(*cpp)++ = TF_STAT;
+	memcpy(*cpp, sp, sizeof TS_RUNNING);
+	TUB_ASCEBC(*cpp, sizeof TS_RUNNING);
+	*cpp += sizeof TS_RUNNING;
+}
+
+/*
+ * tty3270_build() -- build an output stream
+ */
+int
+tty3270_build(tub_t *tubp)
+{
+	char *cp, *startcp;
+	int chancmd;
+	int writecc = TW_KR;
+	int force = 0;
+
+	if (tubp->mode == TBM_FS)
+		return 0;
+
+	cp = startcp = *tubp->ttyscreen + 1;
+
+	switch(tubp->cmd) {
+	default:
+		printk(KERN_WARNING "tty3270_build unknown command %d\n", tubp->cmd);
+		return 0;
+	case TBC_OPEN:
+		chancmd = TC_EWRITEA;
+		tty3270_clear_input_area(tubp, &cp);
+		tty3270_set_status_area(tubp, &cp);
+		tty3270_clear_log_area(tubp, &cp);
+		break;
+	case TBC_UPDLOG:
+		chancmd = TC_WRITE;
+		writecc = TW_NONE;
+		tty3270_update_log_area(tubp, &cp);
+		break;
+	case TBC_KRUPDLOG:
+		chancmd = TC_WRITE;
+		force = 1;
+		tty3270_update_log_area(tubp, &cp);
+		break;
+	case TBC_CLRUPDLOG:
+		chancmd = TC_WRITE;
+		tty3270_set_status_area(tubp, &cp);
+		tty3270_clear_log_area(tubp, &cp);
+		tty3270_update_log_area(tubp, &cp);
+		break;
+	case TBC_UPDATE:
+		chancmd = TC_EWRITEA;
+		tubp->tty_oucol = tubp->tty_nextlogx = 0;
+		tty3270_clear_input_area(tubp, &cp);
+		tty3270_set_status_area(tubp, &cp);
+		tty3270_update_log_area(tubp, &cp);
+		break;
+	case TBC_UPDSTAT:
+		chancmd = TC_WRITE;
+		tty3270_set_status_area(tubp, &cp);
+		break;
+	case TBC_CLRINPUT:
+		chancmd = TC_WRITE;
+		tty3270_clear_input_area(tubp, &cp);
+		break;
+	case TBC_UPDINPUT:
+		chancmd = TC_WRITE;
+		tty3270_update_input_area(tubp, &cp);
+		break;
+	}
+
+	/* Set Write Control Character and start I/O */
+	if (force == 0 && cp == startcp &&
+	    (tubp->flags & TUB_ALARM) == 0)
+		return 0;
+	if (tubp->flags & TUB_ALARM) {
+		tubp->flags &= ~TUB_ALARM;
+		writecc |= TW_PLUSALARM;
+	}
+	**tubp->ttyscreen = writecc;
+	tubp->ttyccw.cmd_code = chancmd;
+	tubp->ttyccw.flags = CCW_FLAG_SLI;
+	tubp->ttyccw.cda = virt_to_phys(*tubp->ttyscreen);
+	tubp->ttyccw.count = cp - *tubp->ttyscreen;
+	tty3270_io(tubp);
+	return 1;
+}
+
+static void
+tty3270_tub_bufadr(tub_t *tubp, int adr, char **cpp)
+{
+	if (tubp->tty_14bitadr) {
+		*(*cpp)++ = (adr >> 8) & 0x3f;
+		*(*cpp)++ = adr & 0xff;
+	} else {
+		*(*cpp)++ = tub_ebcgraf[(adr >> 6) & 0x3f];
+		*(*cpp)++ = tub_ebcgraf[adr & 0x3f];
+	}
+}

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)