s390/tty3270: resize terminal when the clear key is pressed
authorSven Schnelle <svens@linux.ibm.com>
Mon, 28 Nov 2022 18:53:04 +0000 (19:53 +0100)
committerHeiko Carstens <hca@linux.ibm.com>
Mon, 9 Jan 2023 13:33:59 +0000 (14:33 +0100)
There's no easy way to figure out whether the user has re-connected
to the z/VM session. When the user re-connected with a different geometry
to z/VM, the screen layout is broken. Allow the user to force a resizing
by pressing the Clear Key.

Signed-off-by: Sven Schnelle <svens@linux.ibm.com>
Acked-by: Heiko Carstens <hca@linux.ibm.com>
Tested-by: Niklas Schnelle <schnelle@linux.ibm.com>
Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
drivers/s390/char/con3270.c
drivers/s390/char/raw3270.c
drivers/s390/char/raw3270.h

index caccf5d..61c73eb 100644 (file)
@@ -58,6 +58,10 @@ struct tty3270_line {
        int len;
 };
 
+static const unsigned char sfq_read_partition[] = {
+       0x00, 0x07, 0x01, 0xff, 0x03, 0x00, 0x81
+};
+
 #define ESCAPE_NPAR 8
 
 /*
@@ -95,6 +99,7 @@ struct tty3270 {
        struct string *input;           /* Input string for read request. */
        struct raw3270_request *read;   /* Single read request. */
        struct raw3270_request *kreset; /* Single keyboard reset request. */
+       struct raw3270_request *readpartreq;
        unsigned char inattr;           /* Visible/invisible input. */
        int throttle, attn;             /* tty throttle/unthrottle. */
        struct tasklet_struct readlet;  /* Tasklet to issue read request. */
@@ -581,6 +586,14 @@ static void tty3270_read_tasklet(unsigned long data)
                /* Display has been cleared. Redraw. */
                tp->update_flags = TTY_UPDATE_ALL;
                tty3270_set_timer(tp, 1);
+               if (!list_empty(&tp->readpartreq->list))
+                       break;
+               raw3270_start_request(&tp->view, tp->readpartreq, TC_WRITESF,
+                                     (char *)sfq_read_partition, sizeof(sfq_read_partition));
+               break;
+       case AID_READ_PARTITION:
+               raw3270_read_modified_cb(tp->readpartreq, tp->input->string);
+               break;
        default:
                break;
        }
@@ -731,9 +744,12 @@ static struct tty3270 *tty3270_alloc_view(void)
        tp->kreset = raw3270_request_alloc(1);
        if (IS_ERR(tp->kreset))
                goto out_read;
+       tp->readpartreq = raw3270_request_alloc(sizeof(sfq_read_partition));
+       if (IS_ERR(tp->readpartreq))
+               goto out_reset;
        tp->kbd = kbd_alloc();
        if (!tp->kbd)
-               goto out_reset;
+               goto out_readpartreq;
 
        tty_port_init(&tp->port);
        timer_setup(&tp->timer, tty3270_update, 0);
@@ -743,6 +759,8 @@ static struct tty3270 *tty3270_alloc_view(void)
                     (unsigned long) tp);
        return tp;
 
+out_readpartreq:
+       raw3270_request_free(tp->readpartreq);
 out_reset:
        raw3270_request_free(tp->kreset);
 out_read:
index 032244c..e2d703e 100644 (file)
@@ -465,15 +465,14 @@ static void raw3270_size_device_vm(struct raw3270 *rp)
        }
 }
 
-static void raw3270_size_device(struct raw3270 *rp)
+static void raw3270_size_device(struct raw3270 *rp, char *init_data)
 {
        struct raw3270_ua *uap;
 
        /* Got a Query Reply */
-       uap = (struct raw3270_ua *) (rp->init_data + 1);
+       uap = (struct raw3270_ua *)(init_data + 1);
        /* Paranoia check. */
-       if (rp->init_readmod.rc || rp->init_data[0] != 0x88 ||
-           uap->uab.qcode != 0x81) {
+       if (init_data[0] != 0x88 || uap->uab.qcode != 0x81) {
                /* Couldn't detect size. Use default model 2. */
                rp->model = 2;
                rp->rows = 24;
@@ -534,11 +533,10 @@ static void raw3270_size_device_done(struct raw3270 *rp)
        schedule_work(&rp->resize_work);
 }
 
-static void raw3270_read_modified_cb(struct raw3270_request *rq, void *data)
+void raw3270_read_modified_cb(struct raw3270_request *rq, void *data)
 {
        struct raw3270 *rp = rq->view->dev;
-
-       raw3270_size_device(rp);
+       raw3270_size_device(rp, data);
        raw3270_size_device_done(rp);
 }
 
@@ -554,6 +552,7 @@ static void raw3270_read_modified(struct raw3270 *rp)
        rp->init_readmod.ccw.count = sizeof(rp->init_data);
        rp->init_readmod.ccw.cda = (__u32) __pa(rp->init_data);
        rp->init_readmod.callback = raw3270_read_modified_cb;
+       rp->init_readmod.callback_data = rp->init_data;
        rp->state = RAW3270_STATE_READMOD;
        raw3270_start_irq(&rp->init_view, &rp->init_readmod);
 }
@@ -1287,6 +1286,7 @@ module_init(raw3270_init);
 module_exit(raw3270_exit);
 
 EXPORT_SYMBOL(class3270);
+EXPORT_SYMBOL(raw3270_read_modified_cb);
 EXPORT_SYMBOL(raw3270_request_alloc);
 EXPORT_SYMBOL(raw3270_request_free);
 EXPORT_SYMBOL(raw3270_request_reset);
index 66f9f8d..05cd501 100644 (file)
@@ -182,6 +182,7 @@ struct raw3270_view *raw3270_view(struct raw3270_view *);
 int raw3270_view_active(struct raw3270_view *);
 int raw3270_start_request(struct raw3270_view *view, struct raw3270_request *rq,
                          int cmd, void *data, size_t len);
+void raw3270_read_modified_cb(struct raw3270_request *rq, void *data);
 
 /* Reference count inliner for view structures. */
 static inline void