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
- Lines: 449
- Date:
Wed Apr 11 19:02:28 2001
- Orig file:
v2.4.3/linux/drivers/s390/char/tubttybld.c
- Orig date:
Wed Dec 31 16:00:00 1969
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)