Linux 6.10-rc3
[linux-block.git] / drivers / s390 / char / con3270.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  *    IBM/3270 Driver - tty functions.
4  *
5  *  Author(s):
6  *    Original 3270 Code for 2.4 written by Richard Hitt (UTS Global)
7  *    Rewritten for 2.5 by Martin Schwidefsky <schwidefsky@de.ibm.com>
8  *      -- Copyright IBM Corp. 2003
9  */
10
11 #include <linux/module.h>
12 #include <linux/types.h>
13 #include <linux/kdev_t.h>
14 #include <linux/tty.h>
15 #include <linux/vt_kern.h>
16 #include <linux/init.h>
17 #include <linux/console.h>
18 #include <linux/interrupt.h>
19 #include <linux/workqueue.h>
20 #include <linux/panic_notifier.h>
21 #include <linux/reboot.h>
22 #include <linux/slab.h>
23 #include <linux/memblock.h>
24 #include <linux/compat.h>
25
26 #include <asm/ccwdev.h>
27 #include <asm/cio.h>
28 #include <asm/ebcdic.h>
29 #include <asm/cpcmd.h>
30 #include <linux/uaccess.h>
31
32 #include "raw3270.h"
33 #include "keyboard.h"
34
35 #define TTY3270_CHAR_BUF_SIZE 256
36 #define TTY3270_OUTPUT_BUFFER_SIZE 4096
37 #define TTY3270_SCREEN_PAGES 8 /* has to be power-of-two */
38 #define TTY3270_RECALL_SIZE 16 /* has to be power-of-two */
39 #define TTY3270_STATUS_AREA_SIZE 40
40
41 static struct tty_driver *tty3270_driver;
42 static int tty3270_max_index;
43 static struct raw3270_fn tty3270_fn;
44
45 #define TTY3270_HIGHLIGHT_BLINK         1
46 #define TTY3270_HIGHLIGHT_REVERSE       2
47 #define TTY3270_HIGHLIGHT_UNDERSCORE    4
48
49 struct tty3270_attribute {
50         unsigned char alternate_charset:1;      /* Graphics charset */
51         unsigned char highlight:3;              /* Blink/reverse/underscore */
52         unsigned char f_color:4;                /* Foreground color */
53         unsigned char b_color:4;                /* Background color */
54 };
55
56 struct tty3270_cell {
57         u8 character;
58         struct tty3270_attribute attributes;
59 };
60
61 struct tty3270_line {
62         struct tty3270_cell *cells;
63         int len;
64         int dirty;
65 };
66
67 static const unsigned char sfq_read_partition[] = {
68         0x00, 0x07, 0x01, 0xff, 0x03, 0x00, 0x81
69 };
70
71 #define ESCAPE_NPAR 8
72
73 /*
74  * The main tty view data structure.
75  * FIXME:
76  * 1) describe line orientation & lines list concept against screen
77  * 2) describe conversion of screen to lines
78  * 3) describe line format.
79  */
80 struct tty3270 {
81         struct raw3270_view view;
82         struct tty_port port;
83
84         /* Output stuff. */
85         unsigned char wcc;              /* Write control character. */
86         int nr_up;                      /* # lines up in history. */
87         unsigned long update_flags;     /* Update indication bits. */
88         struct raw3270_request *write;  /* Single write request. */
89         struct timer_list timer;        /* Output delay timer. */
90         char *converted_line;           /* RAW 3270 data stream */
91         unsigned int line_view_start;   /* Start of visible area */
92         unsigned int line_write_start;  /* current write position */
93         unsigned int oops_line;         /* line counter used when print oops */
94
95         /* Current tty screen. */
96         unsigned int cx, cy;            /* Current output position. */
97         struct tty3270_attribute attributes;
98         struct tty3270_attribute saved_attributes;
99         int allocated_lines;
100         struct tty3270_line *screen;
101
102         /* Input stuff. */
103         char *prompt;                   /* Output string for input area. */
104         char *input;                    /* Input string for read request. */
105         struct raw3270_request *read;   /* Single read request. */
106         struct raw3270_request *kreset; /* Single keyboard reset request. */
107         struct raw3270_request *readpartreq;
108         unsigned char inattr;           /* Visible/invisible input. */
109         int throttle, attn;             /* tty throttle/unthrottle. */
110         struct tasklet_struct readlet;  /* Tasklet to issue read request. */
111         struct tasklet_struct hanglet;  /* Tasklet to hang up the tty. */
112         struct kbd_data *kbd;           /* key_maps stuff. */
113
114         /* Escape sequence parsing. */
115         int esc_state, esc_ques, esc_npar;
116         int esc_par[ESCAPE_NPAR];
117         unsigned int saved_cx, saved_cy;
118
119         /* Command recalling. */
120         char **rcl_lines;               /* Array of recallable lines */
121         int rcl_write_index;            /* Write index of recallable items */
122         int rcl_read_index;             /* Read index of recallable items */
123
124         /* Character array for put_char/flush_chars. */
125         unsigned int char_count;
126         u8 char_buf[TTY3270_CHAR_BUF_SIZE];
127 };
128
129 /* tty3270->update_flags. See tty3270_update for details. */
130 #define TTY_UPDATE_INPUT        0x1     /* Update input line. */
131 #define TTY_UPDATE_STATUS       0x2     /* Update status line. */
132 #define TTY_UPDATE_LINES        0x4     /* Update visible screen lines */
133 #define TTY_UPDATE_ALL          0x7     /* Recreate screen. */
134
135 #define TTY3270_INPUT_AREA_ROWS 2
136
137 /*
138  * Setup timeout for a device. On timeout trigger an update.
139  */
140 static void tty3270_set_timer(struct tty3270 *tp, int expires)
141 {
142         mod_timer(&tp->timer, jiffies + expires);
143 }
144
145 static int tty3270_tty_rows(struct tty3270 *tp)
146 {
147         return tp->view.rows - TTY3270_INPUT_AREA_ROWS;
148 }
149
150 static char *tty3270_add_ba(struct tty3270 *tp, char *cp, char order, int x, int y)
151 {
152         *cp++ = order;
153         raw3270_buffer_address(tp->view.dev, cp, x, y);
154         return cp + 2;
155 }
156
157 static char *tty3270_add_ra(struct tty3270 *tp, char *cp, int x, int y, char c)
158 {
159         cp = tty3270_add_ba(tp, cp, TO_RA, x, y);
160         *cp++ = c;
161         return cp;
162 }
163
164 static char *tty3270_add_sa(struct tty3270 *tp, char *cp, char attr, char value)
165 {
166         *cp++ = TO_SA;
167         *cp++ = attr;
168         *cp++ = value;
169         return cp;
170 }
171
172 static char *tty3270_add_ge(struct tty3270 *tp, char *cp, char c)
173 {
174         *cp++ = TO_GE;
175         *cp++ = c;
176         return cp;
177 }
178
179 static char *tty3270_add_sf(struct tty3270 *tp, char *cp, char type)
180 {
181         *cp++ = TO_SF;
182         *cp++ = type;
183         return cp;
184 }
185
186 static int tty3270_line_increment(struct tty3270 *tp, unsigned int line, unsigned int incr)
187 {
188         return (line + incr) & (tp->allocated_lines - 1);
189 }
190
191 static struct tty3270_line *tty3270_get_write_line(struct tty3270 *tp, unsigned int num)
192 {
193         return tp->screen + tty3270_line_increment(tp, tp->line_write_start, num);
194 }
195
196 static struct tty3270_line *tty3270_get_view_line(struct tty3270 *tp, unsigned int num)
197 {
198         return tp->screen + tty3270_line_increment(tp, tp->line_view_start, num - tp->nr_up);
199 }
200
201 static int tty3270_input_size(int cols)
202 {
203         return cols * 2 - 11;
204 }
205
206 static void tty3270_update_prompt(struct tty3270 *tp, char *input)
207 {
208         strcpy(tp->prompt, input);
209         tp->update_flags |= TTY_UPDATE_INPUT;
210         tty3270_set_timer(tp, 1);
211 }
212
213 /*
214  * The input line are the two last lines of the screen.
215  */
216 static int tty3270_add_prompt(struct tty3270 *tp)
217 {
218         int count = 0;
219         char *cp;
220
221         cp = tp->converted_line;
222         cp = tty3270_add_ba(tp, cp, TO_SBA, 0, -2);
223         *cp++ = tp->view.ascebc['>'];
224
225         if (*tp->prompt) {
226                 cp = tty3270_add_sf(tp, cp, TF_INMDT);
227                 count = min_t(int, strlen(tp->prompt),
228                               tp->view.cols * 2 - TTY3270_STATUS_AREA_SIZE - 2);
229                 memcpy(cp, tp->prompt, count);
230                 cp += count;
231         } else {
232                 cp = tty3270_add_sf(tp, cp, tp->inattr);
233         }
234         *cp++ = TO_IC;
235         /* Clear to end of input line. */
236         if (count < tp->view.cols * 2 - 11)
237                 cp = tty3270_add_ra(tp, cp, -TTY3270_STATUS_AREA_SIZE, -1, 0);
238         return cp - tp->converted_line;
239 }
240
241 static char *tty3270_ebcdic_convert(struct tty3270 *tp, char *d, char *s)
242 {
243         while (*s)
244                 *d++ = tp->view.ascebc[(int)*s++];
245         return d;
246 }
247
248 /*
249  * The status line is the last line of the screen. It shows the string
250  * "Running"/"History X" in the lower right corner of the screen.
251  */
252 static int tty3270_add_status(struct tty3270 *tp)
253 {
254         char *cp = tp->converted_line;
255         int len;
256
257         cp = tty3270_add_ba(tp, cp, TO_SBA, -TTY3270_STATUS_AREA_SIZE, -1);
258         cp = tty3270_add_sf(tp, cp, TF_LOG);
259         cp = tty3270_add_sa(tp, cp, TAT_FGCOLOR, TAC_GREEN);
260         cp = tty3270_ebcdic_convert(tp, cp, " 7");
261         cp = tty3270_add_sa(tp, cp, TAT_EXTHI, TAX_REVER);
262         cp = tty3270_ebcdic_convert(tp, cp, "PrevPg");
263         cp = tty3270_add_sa(tp, cp, TAT_EXTHI, TAX_RESET);
264         cp = tty3270_ebcdic_convert(tp, cp, " 8");
265         cp = tty3270_add_sa(tp, cp, TAT_EXTHI, TAX_REVER);
266         cp = tty3270_ebcdic_convert(tp, cp, "NextPg");
267         cp = tty3270_add_sa(tp, cp, TAT_EXTHI, TAX_RESET);
268         cp = tty3270_ebcdic_convert(tp, cp, " 12");
269         cp = tty3270_add_sa(tp, cp, TAT_EXTHI, TAX_REVER);
270         cp = tty3270_ebcdic_convert(tp, cp, "Recall");
271         cp = tty3270_add_sa(tp, cp, TAT_EXTHI, TAX_RESET);
272         cp = tty3270_ebcdic_convert(tp, cp, "  ");
273         if (tp->nr_up) {
274                 len = sprintf(cp, "History %d", -tp->nr_up);
275                 codepage_convert(tp->view.ascebc, cp, len);
276                 cp += len;
277         } else {
278                 cp = tty3270_ebcdic_convert(tp, cp, oops_in_progress ? "Crashed" : "Running");
279         }
280         cp = tty3270_add_sf(tp, cp, TF_LOG);
281         cp = tty3270_add_sa(tp, cp, TAT_FGCOLOR, TAC_RESET);
282         return cp - (char *)tp->converted_line;
283 }
284
285 static void tty3270_blank_screen(struct tty3270 *tp)
286 {
287         struct tty3270_line *line;
288         int i;
289
290         for (i = 0; i < tty3270_tty_rows(tp); i++) {
291                 line = tty3270_get_write_line(tp, i);
292                 line->len = 0;
293                 line->dirty = 1;
294         }
295         tp->nr_up = 0;
296 }
297
298 /*
299  * Write request completion callback.
300  */
301 static void tty3270_write_callback(struct raw3270_request *rq, void *data)
302 {
303         struct tty3270 *tp = container_of(rq->view, struct tty3270, view);
304
305         if (rq->rc != 0) {
306                 /* Write wasn't successful. Refresh all. */
307                 tp->update_flags = TTY_UPDATE_ALL;
308                 tty3270_set_timer(tp, 1);
309         }
310         raw3270_request_reset(rq);
311         xchg(&tp->write, rq);
312 }
313
314 static int tty3270_required_length(struct tty3270 *tp, struct tty3270_line *line)
315 {
316         unsigned char f_color, b_color, highlight;
317         struct tty3270_cell *cell;
318         int i, flen = 3;                /* Prefix (TO_SBA). */
319
320         flen += line->len;
321         highlight = 0;
322         f_color = TAC_RESET;
323         b_color = TAC_RESET;
324
325         for (i = 0, cell = line->cells; i < line->len; i++, cell++) {
326                 if (cell->attributes.highlight != highlight) {
327                         flen += 3;      /* TO_SA to switch highlight. */
328                         highlight = cell->attributes.highlight;
329                 }
330                 if (cell->attributes.f_color != f_color) {
331                         flen += 3;      /* TO_SA to switch color. */
332                         f_color = cell->attributes.f_color;
333                 }
334                 if (cell->attributes.b_color != b_color) {
335                         flen += 3;      /* TO_SA to switch color. */
336                         b_color = cell->attributes.b_color;
337                 }
338                 if (cell->attributes.alternate_charset)
339                         flen += 1;      /* TO_GE to switch to graphics extensions */
340         }
341         if (highlight)
342                 flen += 3;      /* TO_SA to reset hightlight. */
343         if (f_color != TAC_RESET)
344                 flen += 3;      /* TO_SA to reset color. */
345         if (b_color != TAC_RESET)
346                 flen += 3;      /* TO_SA to reset color. */
347         if (line->len < tp->view.cols)
348                 flen += 4;      /* Postfix (TO_RA). */
349
350         return flen;
351 }
352
353 static char *tty3270_add_reset_attributes(struct tty3270 *tp, struct tty3270_line *line,
354                                           char *cp, struct tty3270_attribute *attr, int lineno)
355 {
356         if (attr->highlight)
357                 cp = tty3270_add_sa(tp, cp, TAT_EXTHI, TAX_RESET);
358         if (attr->f_color != TAC_RESET)
359                 cp = tty3270_add_sa(tp, cp, TAT_FGCOLOR, TAX_RESET);
360         if (attr->b_color != TAC_RESET)
361                 cp = tty3270_add_sa(tp, cp, TAT_BGCOLOR, TAX_RESET);
362         if (line->len < tp->view.cols)
363                 cp = tty3270_add_ra(tp, cp, 0, lineno + 1, 0);
364         return cp;
365 }
366
367 static char tty3270_graphics_translate(struct tty3270 *tp, char ch)
368 {
369         switch (ch) {
370         case 'q': /* - */
371                 return 0xa2;
372         case 'x': /* '|' */
373                 return 0x85;
374         case 'l': /* |- */
375                 return 0xc5;
376         case 't': /* |_ */
377                 return 0xc6;
378         case 'u': /* _| */
379                 return 0xd6;
380         case 'k': /* -| */
381                 return 0xd5;
382         case 'j':
383                 return 0xd4;
384         case 'm':
385                 return 0xc4;
386         case 'n': /* + */
387                 return 0xd3;
388         case 'v':
389                 return 0xc7;
390         case 'w':
391                 return 0xd7;
392         default:
393                 return ch;
394         }
395 }
396
397 static char *tty3270_add_attributes(struct tty3270 *tp, struct tty3270_line *line,
398                                     struct tty3270_attribute *attr, char *cp, int lineno)
399 {
400         const unsigned char colors[16] = {
401                 [0] = TAC_DEFAULT,
402                 [1] = TAC_RED,
403                 [2] = TAC_GREEN,
404                 [3] = TAC_YELLOW,
405                 [4] = TAC_BLUE,
406                 [5] = TAC_PINK,
407                 [6] = TAC_TURQ,
408                 [7] = TAC_WHITE,
409                 [9] = TAC_DEFAULT
410         };
411
412         const unsigned char highlights[8] = {
413                 [TTY3270_HIGHLIGHT_BLINK] = TAX_BLINK,
414                 [TTY3270_HIGHLIGHT_REVERSE] = TAX_REVER,
415                 [TTY3270_HIGHLIGHT_UNDERSCORE] = TAX_UNDER,
416         };
417
418         struct tty3270_cell *cell;
419         int c, i;
420
421         cp = tty3270_add_ba(tp, cp, TO_SBA, 0, lineno);
422
423         for (i = 0, cell = line->cells; i < line->len; i++, cell++) {
424                 if (cell->attributes.highlight != attr->highlight) {
425                         attr->highlight = cell->attributes.highlight;
426                         cp = tty3270_add_sa(tp, cp, TAT_EXTHI, highlights[attr->highlight]);
427                 }
428                 if (cell->attributes.f_color != attr->f_color) {
429                         attr->f_color = cell->attributes.f_color;
430                         cp = tty3270_add_sa(tp, cp, TAT_FGCOLOR, colors[attr->f_color]);
431                 }
432                 if (cell->attributes.b_color != attr->b_color) {
433                         attr->b_color = cell->attributes.b_color;
434                         cp = tty3270_add_sa(tp, cp, TAT_BGCOLOR, colors[attr->b_color]);
435                 }
436                 c = cell->character;
437                 if (cell->attributes.alternate_charset)
438                         cp = tty3270_add_ge(tp, cp, tty3270_graphics_translate(tp, c));
439                 else
440                         *cp++ = tp->view.ascebc[c];
441         }
442         return cp;
443 }
444
445 static void tty3270_reset_attributes(struct tty3270_attribute *attr)
446 {
447         attr->highlight = TAX_RESET;
448         attr->f_color = TAC_RESET;
449         attr->b_color = TAC_RESET;
450 }
451
452 /*
453  * Convert a tty3270_line to a 3270 data fragment usable for output.
454  */
455 static unsigned int tty3270_convert_line(struct tty3270 *tp, struct tty3270_line *line, int lineno)
456 {
457         struct tty3270_attribute attr;
458         int flen;
459         char *cp;
460
461         /* Determine how long the fragment will be. */
462         flen = tty3270_required_length(tp, line);
463         if (flen > PAGE_SIZE)
464                 return 0;
465         /* Write 3270 data fragment. */
466         tty3270_reset_attributes(&attr);
467         cp = tty3270_add_attributes(tp, line, &attr, tp->converted_line, lineno);
468         cp = tty3270_add_reset_attributes(tp, line, cp, &attr, lineno);
469         return cp - (char *)tp->converted_line;
470 }
471
472 static void tty3270_update_lines_visible(struct tty3270 *tp, struct raw3270_request *rq)
473 {
474         struct tty3270_line *line;
475         int len, i;
476
477         for (i = 0; i < tty3270_tty_rows(tp); i++) {
478                 line = tty3270_get_view_line(tp, i);
479                 if (!line->dirty)
480                         continue;
481                 len = tty3270_convert_line(tp, line, i);
482                 if (raw3270_request_add_data(rq, tp->converted_line, len))
483                         break;
484                 line->dirty = 0;
485         }
486         if (i == tty3270_tty_rows(tp)) {
487                 for (i = 0; i < tp->allocated_lines; i++)
488                         tp->screen[i].dirty = 0;
489                 tp->update_flags &= ~TTY_UPDATE_LINES;
490         }
491 }
492
493 static void tty3270_update_lines_all(struct tty3270 *tp, struct raw3270_request *rq)
494 {
495         struct tty3270_line *line;
496         char buf[4];
497         int len, i;
498
499         for (i = 0; i < tp->allocated_lines; i++) {
500                 line = tty3270_get_write_line(tp, i + tp->cy + 1);
501                 if (!line->dirty)
502                         continue;
503                 len = tty3270_convert_line(tp, line, tp->oops_line);
504                 if (raw3270_request_add_data(rq, tp->converted_line, len))
505                         break;
506                 line->dirty = 0;
507                 if (++tp->oops_line >= tty3270_tty_rows(tp))
508                         tp->oops_line = 0;
509         }
510
511         if (i == tp->allocated_lines) {
512                 if (tp->oops_line < tty3270_tty_rows(tp)) {
513                         tty3270_add_ra(tp, buf, 0, tty3270_tty_rows(tp), 0);
514                         if (raw3270_request_add_data(rq, buf, sizeof(buf)))
515                                 return;
516                 }
517                 tp->update_flags &= ~TTY_UPDATE_LINES;
518         }
519 }
520
521 /*
522  * Update 3270 display.
523  */
524 static void tty3270_update(struct timer_list *t)
525 {
526         struct tty3270 *tp = from_timer(tp, t, timer);
527         struct raw3270_request *wrq;
528         u8 cmd = TC_WRITE;
529         int rc, len;
530
531         wrq = xchg(&tp->write, 0);
532         if (!wrq) {
533                 tty3270_set_timer(tp, 1);
534                 return;
535         }
536
537         spin_lock_irq(&tp->view.lock);
538         if (tp->update_flags == TTY_UPDATE_ALL)
539                 cmd = TC_EWRITEA;
540
541         raw3270_request_set_cmd(wrq, cmd);
542         raw3270_request_add_data(wrq, &tp->wcc, 1);
543         tp->wcc = TW_NONE;
544
545         /*
546          * Update status line.
547          */
548         if (tp->update_flags & TTY_UPDATE_STATUS) {
549                 len = tty3270_add_status(tp);
550                 if (raw3270_request_add_data(wrq, tp->converted_line, len) == 0)
551                         tp->update_flags &= ~TTY_UPDATE_STATUS;
552         }
553
554         /*
555          * Write input line.
556          */
557         if (tp->update_flags & TTY_UPDATE_INPUT) {
558                 len = tty3270_add_prompt(tp);
559                 if (raw3270_request_add_data(wrq, tp->converted_line, len) == 0)
560                         tp->update_flags &= ~TTY_UPDATE_INPUT;
561         }
562
563         if (tp->update_flags & TTY_UPDATE_LINES) {
564                 if (oops_in_progress)
565                         tty3270_update_lines_all(tp, wrq);
566                 else
567                         tty3270_update_lines_visible(tp, wrq);
568         }
569
570         wrq->callback = tty3270_write_callback;
571         rc = raw3270_start(&tp->view, wrq);
572         if (rc == 0) {
573                 if (tp->update_flags)
574                         tty3270_set_timer(tp, 1);
575         } else {
576                 raw3270_request_reset(wrq);
577                 xchg(&tp->write, wrq);
578         }
579         spin_unlock_irq(&tp->view.lock);
580 }
581
582 /*
583  * Command recalling.
584  */
585 static void tty3270_rcl_add(struct tty3270 *tp, char *input, int len)
586 {
587         char *p;
588
589         if (len <= 0)
590                 return;
591         p = tp->rcl_lines[tp->rcl_write_index++];
592         tp->rcl_write_index &= TTY3270_RECALL_SIZE - 1;
593         memcpy(p, input, len);
594         p[len] = '\0';
595         tp->rcl_read_index = tp->rcl_write_index;
596 }
597
598 static void tty3270_rcl_backward(struct kbd_data *kbd)
599 {
600         struct tty3270 *tp = container_of(kbd->port, struct tty3270, port);
601         int i = 0;
602
603         spin_lock_irq(&tp->view.lock);
604         if (tp->inattr == TF_INPUT) {
605                 do {
606                         tp->rcl_read_index--;
607                         tp->rcl_read_index &= TTY3270_RECALL_SIZE - 1;
608                 } while (!*tp->rcl_lines[tp->rcl_read_index] &&
609                          i++ < TTY3270_RECALL_SIZE - 1);
610                 tty3270_update_prompt(tp, tp->rcl_lines[tp->rcl_read_index]);
611         }
612         spin_unlock_irq(&tp->view.lock);
613 }
614
615 /*
616  * Deactivate tty view.
617  */
618 static void tty3270_exit_tty(struct kbd_data *kbd)
619 {
620         struct tty3270 *tp = container_of(kbd->port, struct tty3270, port);
621
622         raw3270_deactivate_view(&tp->view);
623 }
624
625 static void tty3270_redraw(struct tty3270 *tp)
626 {
627         int i;
628
629         for (i = 0; i < tty3270_tty_rows(tp); i++)
630                 tty3270_get_view_line(tp, i)->dirty = 1;
631         tp->update_flags = TTY_UPDATE_ALL;
632         tty3270_set_timer(tp, 1);
633 }
634
635 /*
636  * Scroll forward in history.
637  */
638 static void tty3270_scroll_forward(struct kbd_data *kbd)
639 {
640         struct tty3270 *tp = container_of(kbd->port, struct tty3270, port);
641
642         spin_lock_irq(&tp->view.lock);
643
644         if (tp->nr_up >= tty3270_tty_rows(tp))
645                 tp->nr_up -= tty3270_tty_rows(tp) / 2;
646         else
647                 tp->nr_up = 0;
648         tty3270_redraw(tp);
649         spin_unlock_irq(&tp->view.lock);
650 }
651
652 /*
653  * Scroll backward in history.
654  */
655 static void tty3270_scroll_backward(struct kbd_data *kbd)
656 {
657         struct tty3270 *tp = container_of(kbd->port, struct tty3270, port);
658
659         spin_lock_irq(&tp->view.lock);
660         tp->nr_up += tty3270_tty_rows(tp) / 2;
661         if (tp->nr_up > tp->allocated_lines - tty3270_tty_rows(tp))
662                 tp->nr_up = tp->allocated_lines - tty3270_tty_rows(tp);
663         tty3270_redraw(tp);
664         spin_unlock_irq(&tp->view.lock);
665 }
666
667 /*
668  * Pass input line to tty.
669  */
670 static void tty3270_read_tasklet(unsigned long data)
671 {
672         struct raw3270_request *rrq = (struct raw3270_request *)data;
673         static char kreset_data = TW_KR;
674         struct tty3270 *tp = container_of(rrq->view, struct tty3270, view);
675         char *input;
676         int len;
677
678         spin_lock_irq(&tp->view.lock);
679         /*
680          * Two AID keys are special: For 0x7d (enter) the input line
681          * has to be emitted to the tty and for 0x6d the screen
682          * needs to be redrawn.
683          */
684         input = NULL;
685         len = 0;
686         switch (tp->input[0]) {
687         case AID_ENTER:
688                 /* Enter: write input to tty. */
689                 input = tp->input + 6;
690                 len = tty3270_input_size(tp->view.cols) - 6 - rrq->rescnt;
691                 if (tp->inattr != TF_INPUTN)
692                         tty3270_rcl_add(tp, input, len);
693                 if (tp->nr_up > 0)
694                         tp->nr_up = 0;
695                 /* Clear input area. */
696                 tty3270_update_prompt(tp, "");
697                 tty3270_set_timer(tp, 1);
698                 break;
699         case AID_CLEAR:
700                 /* Display has been cleared. Redraw. */
701                 tp->update_flags = TTY_UPDATE_ALL;
702                 tty3270_set_timer(tp, 1);
703                 if (!list_empty(&tp->readpartreq->list))
704                         break;
705                 raw3270_start_request(&tp->view, tp->readpartreq, TC_WRITESF,
706                                       (char *)sfq_read_partition, sizeof(sfq_read_partition));
707                 break;
708         case AID_READ_PARTITION:
709                 raw3270_read_modified_cb(tp->readpartreq, tp->input);
710                 break;
711         default:
712                 break;
713         }
714         spin_unlock_irq(&tp->view.lock);
715
716         /* Start keyboard reset command. */
717         raw3270_start_request(&tp->view, tp->kreset, TC_WRITE, &kreset_data, 1);
718
719         while (len-- > 0)
720                 kbd_keycode(tp->kbd, *input++);
721         /* Emit keycode for AID byte. */
722         kbd_keycode(tp->kbd, 256 + tp->input[0]);
723
724         raw3270_request_reset(rrq);
725         xchg(&tp->read, rrq);
726         raw3270_put_view(&tp->view);
727 }
728
729 /*
730  * Read request completion callback.
731  */
732 static void tty3270_read_callback(struct raw3270_request *rq, void *data)
733 {
734         struct tty3270 *tp = container_of(rq->view, struct tty3270, view);
735
736         raw3270_get_view(rq->view);
737         /* Schedule tasklet to pass input to tty. */
738         tasklet_schedule(&tp->readlet);
739 }
740
741 /*
742  * Issue a read request. Call with device lock.
743  */
744 static void tty3270_issue_read(struct tty3270 *tp, int lock)
745 {
746         struct raw3270_request *rrq;
747         int rc;
748
749         rrq = xchg(&tp->read, 0);
750         if (!rrq)
751                 /* Read already scheduled. */
752                 return;
753         rrq->callback = tty3270_read_callback;
754         rrq->callback_data = tp;
755         raw3270_request_set_cmd(rrq, TC_READMOD);
756         raw3270_request_set_data(rrq, tp->input, tty3270_input_size(tp->view.cols));
757         /* Issue the read modified request. */
758         if (lock)
759                 rc = raw3270_start(&tp->view, rrq);
760         else
761                 rc = raw3270_start_irq(&tp->view, rrq);
762         if (rc) {
763                 raw3270_request_reset(rrq);
764                 xchg(&tp->read, rrq);
765         }
766 }
767
768 /*
769  * Hang up the tty
770  */
771 static void tty3270_hangup_tasklet(unsigned long data)
772 {
773         struct tty3270 *tp = (struct tty3270 *)data;
774
775         tty_port_tty_hangup(&tp->port, true);
776         raw3270_put_view(&tp->view);
777 }
778
779 /*
780  * Switch to the tty view.
781  */
782 static int tty3270_activate(struct raw3270_view *view)
783 {
784         struct tty3270 *tp = container_of(view, struct tty3270, view);
785
786         tp->update_flags = TTY_UPDATE_ALL;
787         tty3270_set_timer(tp, 1);
788         return 0;
789 }
790
791 static void tty3270_deactivate(struct raw3270_view *view)
792 {
793         struct tty3270 *tp = container_of(view, struct tty3270, view);
794
795         del_timer(&tp->timer);
796 }
797
798 static void tty3270_irq(struct tty3270 *tp, struct raw3270_request *rq, struct irb *irb)
799 {
800         /* Handle ATTN. Schedule tasklet to read aid. */
801         if (irb->scsw.cmd.dstat & DEV_STAT_ATTENTION) {
802                 if (!tp->throttle)
803                         tty3270_issue_read(tp, 0);
804                 else
805                         tp->attn = 1;
806         }
807
808         if (rq) {
809                 if (irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK) {
810                         rq->rc = -EIO;
811                         raw3270_get_view(&tp->view);
812                         tasklet_schedule(&tp->hanglet);
813                 } else {
814                         /* Normal end. Copy residual count. */
815                         rq->rescnt = irb->scsw.cmd.count;
816                 }
817         } else if (irb->scsw.cmd.dstat & DEV_STAT_DEV_END) {
818                 /* Interrupt without an outstanding request -> update all */
819                 tp->update_flags = TTY_UPDATE_ALL;
820                 tty3270_set_timer(tp, 1);
821         }
822 }
823
824 /*
825  * Allocate tty3270 structure.
826  */
827 static struct tty3270 *tty3270_alloc_view(void)
828 {
829         struct tty3270 *tp;
830
831         tp = kzalloc(sizeof(*tp), GFP_KERNEL);
832         if (!tp)
833                 goto out_err;
834
835         tp->write = raw3270_request_alloc(TTY3270_OUTPUT_BUFFER_SIZE);
836         if (IS_ERR(tp->write))
837                 goto out_tp;
838         tp->read = raw3270_request_alloc(0);
839         if (IS_ERR(tp->read))
840                 goto out_write;
841         tp->kreset = raw3270_request_alloc(1);
842         if (IS_ERR(tp->kreset))
843                 goto out_read;
844         tp->readpartreq = raw3270_request_alloc(sizeof(sfq_read_partition));
845         if (IS_ERR(tp->readpartreq))
846                 goto out_reset;
847         tp->kbd = kbd_alloc();
848         if (!tp->kbd)
849                 goto out_readpartreq;
850
851         tty_port_init(&tp->port);
852         timer_setup(&tp->timer, tty3270_update, 0);
853         tasklet_init(&tp->readlet, tty3270_read_tasklet,
854                      (unsigned long)tp->read);
855         tasklet_init(&tp->hanglet, tty3270_hangup_tasklet,
856                      (unsigned long)tp);
857         return tp;
858
859 out_readpartreq:
860         raw3270_request_free(tp->readpartreq);
861 out_reset:
862         raw3270_request_free(tp->kreset);
863 out_read:
864         raw3270_request_free(tp->read);
865 out_write:
866         raw3270_request_free(tp->write);
867 out_tp:
868         kfree(tp);
869 out_err:
870         return ERR_PTR(-ENOMEM);
871 }
872
873 /*
874  * Free tty3270 structure.
875  */
876 static void tty3270_free_view(struct tty3270 *tp)
877 {
878         kbd_free(tp->kbd);
879         raw3270_request_free(tp->kreset);
880         raw3270_request_free(tp->read);
881         raw3270_request_free(tp->write);
882         free_page((unsigned long)tp->converted_line);
883         tty_port_destroy(&tp->port);
884         kfree(tp);
885 }
886
887 /*
888  * Allocate tty3270 screen.
889  */
890 static struct tty3270_line *tty3270_alloc_screen(struct tty3270 *tp, unsigned int rows,
891                                                  unsigned int cols, int *allocated_out)
892 {
893         struct tty3270_line *screen;
894         int allocated, lines;
895
896         allocated = __roundup_pow_of_two(rows) * TTY3270_SCREEN_PAGES;
897         screen = kcalloc(allocated, sizeof(struct tty3270_line), GFP_KERNEL);
898         if (!screen)
899                 goto out_err;
900         for (lines = 0; lines < allocated; lines++) {
901                 screen[lines].cells = kcalloc(cols, sizeof(struct tty3270_cell), GFP_KERNEL);
902                 if (!screen[lines].cells)
903                         goto out_screen;
904         }
905         *allocated_out = allocated;
906         return screen;
907 out_screen:
908         while (lines--)
909                 kfree(screen[lines].cells);
910         kfree(screen);
911 out_err:
912         return ERR_PTR(-ENOMEM);
913 }
914
915 static char **tty3270_alloc_recall(int cols)
916 {
917         char **lines;
918         int i;
919
920         lines = kmalloc_array(TTY3270_RECALL_SIZE, sizeof(char *), GFP_KERNEL);
921         if (!lines)
922                 return NULL;
923         for (i = 0; i < TTY3270_RECALL_SIZE; i++) {
924                 lines[i] = kcalloc(1, tty3270_input_size(cols) + 1, GFP_KERNEL);
925                 if (!lines[i])
926                         break;
927         }
928
929         if (i == TTY3270_RECALL_SIZE)
930                 return lines;
931
932         while (i--)
933                 kfree(lines[i]);
934         kfree(lines);
935         return NULL;
936 }
937
938 static void tty3270_free_recall(char **lines)
939 {
940         int i;
941
942         for (i = 0; i < TTY3270_RECALL_SIZE; i++)
943                 kfree(lines[i]);
944         kfree(lines);
945 }
946
947 /*
948  * Free tty3270 screen.
949  */
950 static void tty3270_free_screen(struct tty3270_line *screen, int old_lines)
951 {
952         int lines;
953
954         for (lines = 0; lines < old_lines; lines++)
955                 kfree(screen[lines].cells);
956         kfree(screen);
957 }
958
959 /*
960  * Resize tty3270 screen
961  */
962 static void tty3270_resize(struct raw3270_view *view,
963                            int new_model, int new_rows, int new_cols,
964                            int old_model, int old_rows, int old_cols)
965 {
966         struct tty3270 *tp = container_of(view, struct tty3270, view);
967         struct tty3270_line *screen, *oscreen;
968         char **old_rcl_lines, **new_rcl_lines;
969         char *old_prompt, *new_prompt;
970         char *old_input, *new_input;
971         struct tty_struct *tty;
972         struct winsize ws;
973         int new_allocated, old_allocated = tp->allocated_lines;
974
975         if (old_model == new_model &&
976             old_cols == new_cols &&
977             old_rows == new_rows) {
978                 spin_lock_irq(&tp->view.lock);
979                 tty3270_redraw(tp);
980                 spin_unlock_irq(&tp->view.lock);
981                 return;
982         }
983
984         new_input = kzalloc(tty3270_input_size(new_cols), GFP_KERNEL | GFP_DMA);
985         if (!new_input)
986                 return;
987         new_prompt = kzalloc(tty3270_input_size(new_cols), GFP_KERNEL);
988         if (!new_prompt)
989                 goto out_input;
990         screen = tty3270_alloc_screen(tp, new_rows, new_cols, &new_allocated);
991         if (IS_ERR(screen))
992                 goto out_prompt;
993         new_rcl_lines = tty3270_alloc_recall(new_cols);
994         if (!new_rcl_lines)
995                 goto out_screen;
996
997         /* Switch to new output size */
998         spin_lock_irq(&tp->view.lock);
999         tty3270_blank_screen(tp);
1000         oscreen = tp->screen;
1001         tp->screen = screen;
1002         tp->allocated_lines = new_allocated;
1003         tp->view.rows = new_rows;
1004         tp->view.cols = new_cols;
1005         tp->view.model = new_model;
1006         tp->update_flags = TTY_UPDATE_ALL;
1007         old_input = tp->input;
1008         old_prompt = tp->prompt;
1009         old_rcl_lines = tp->rcl_lines;
1010         tp->input = new_input;
1011         tp->prompt = new_prompt;
1012         tp->rcl_lines = new_rcl_lines;
1013         tp->rcl_read_index = 0;
1014         tp->rcl_write_index = 0;
1015         spin_unlock_irq(&tp->view.lock);
1016         tty3270_free_screen(oscreen, old_allocated);
1017         kfree(old_input);
1018         kfree(old_prompt);
1019         tty3270_free_recall(old_rcl_lines);
1020         tty3270_set_timer(tp, 1);
1021         /* Informat tty layer about new size */
1022         tty = tty_port_tty_get(&tp->port);
1023         if (!tty)
1024                 return;
1025         ws.ws_row = tty3270_tty_rows(tp);
1026         ws.ws_col = tp->view.cols;
1027         tty_do_resize(tty, &ws);
1028         tty_kref_put(tty);
1029         return;
1030 out_screen:
1031         tty3270_free_screen(screen, new_rows);
1032 out_prompt:
1033         kfree(new_prompt);
1034 out_input:
1035         kfree(new_input);
1036 }
1037
1038 /*
1039  * Unlink tty3270 data structure from tty.
1040  */
1041 static void tty3270_release(struct raw3270_view *view)
1042 {
1043         struct tty3270 *tp = container_of(view, struct tty3270, view);
1044         struct tty_struct *tty = tty_port_tty_get(&tp->port);
1045
1046         if (tty) {
1047                 tty->driver_data = NULL;
1048                 tty_port_tty_set(&tp->port, NULL);
1049                 tty_hangup(tty);
1050                 raw3270_put_view(&tp->view);
1051                 tty_kref_put(tty);
1052         }
1053 }
1054
1055 /*
1056  * Free tty3270 data structure
1057  */
1058 static void tty3270_free(struct raw3270_view *view)
1059 {
1060         struct tty3270 *tp = container_of(view, struct tty3270, view);
1061
1062         del_timer_sync(&tp->timer);
1063         tty3270_free_screen(tp->screen, tp->allocated_lines);
1064         free_page((unsigned long)tp->converted_line);
1065         kfree(tp->input);
1066         kfree(tp->prompt);
1067         tty3270_free_view(tp);
1068 }
1069
1070 /*
1071  * Delayed freeing of tty3270 views.
1072  */
1073 static void tty3270_del_views(void)
1074 {
1075         int i;
1076
1077         for (i = RAW3270_FIRSTMINOR; i <= tty3270_max_index; i++) {
1078                 struct raw3270_view *view = raw3270_find_view(&tty3270_fn, i);
1079
1080                 if (!IS_ERR(view))
1081                         raw3270_del_view(view);
1082         }
1083 }
1084
1085 static struct raw3270_fn tty3270_fn = {
1086         .activate = tty3270_activate,
1087         .deactivate = tty3270_deactivate,
1088         .intv = (void *)tty3270_irq,
1089         .release = tty3270_release,
1090         .free = tty3270_free,
1091         .resize = tty3270_resize
1092 };
1093
1094 static int
1095 tty3270_create_view(int index, struct tty3270 **newtp)
1096 {
1097         struct tty3270 *tp;
1098         int rc;
1099
1100         if (tty3270_max_index < index + 1)
1101                 tty3270_max_index = index + 1;
1102
1103         /* Allocate tty3270 structure on first open. */
1104         tp = tty3270_alloc_view();
1105         if (IS_ERR(tp))
1106                 return PTR_ERR(tp);
1107
1108         rc = raw3270_add_view(&tp->view, &tty3270_fn,
1109                               index + RAW3270_FIRSTMINOR,
1110                               RAW3270_VIEW_LOCK_IRQ);
1111         if (rc)
1112                 goto out_free_view;
1113
1114         tp->screen = tty3270_alloc_screen(tp, tp->view.rows, tp->view.cols,
1115                                           &tp->allocated_lines);
1116         if (IS_ERR(tp->screen)) {
1117                 rc = PTR_ERR(tp->screen);
1118                 goto out_put_view;
1119         }
1120
1121         tp->converted_line = (void *)__get_free_page(GFP_KERNEL);
1122         if (!tp->converted_line) {
1123                 rc = -ENOMEM;
1124                 goto out_free_screen;
1125         }
1126
1127         tp->input = kzalloc(tty3270_input_size(tp->view.cols), GFP_KERNEL | GFP_DMA);
1128         if (!tp->input) {
1129                 rc = -ENOMEM;
1130                 goto out_free_converted_line;
1131         }
1132
1133         tp->prompt = kzalloc(tty3270_input_size(tp->view.cols), GFP_KERNEL);
1134         if (!tp->prompt) {
1135                 rc = -ENOMEM;
1136                 goto out_free_input;
1137         }
1138
1139         tp->rcl_lines = tty3270_alloc_recall(tp->view.cols);
1140         if (!tp->rcl_lines) {
1141                 rc = -ENOMEM;
1142                 goto out_free_prompt;
1143         }
1144
1145         /* Create blank line for every line in the tty output area. */
1146         tty3270_blank_screen(tp);
1147
1148         tp->kbd->port = &tp->port;
1149         tp->kbd->fn_handler[KVAL(K_INCRCONSOLE)] = tty3270_exit_tty;
1150         tp->kbd->fn_handler[KVAL(K_SCROLLBACK)] = tty3270_scroll_backward;
1151         tp->kbd->fn_handler[KVAL(K_SCROLLFORW)] = tty3270_scroll_forward;
1152         tp->kbd->fn_handler[KVAL(K_CONS)] = tty3270_rcl_backward;
1153         kbd_ascebc(tp->kbd, tp->view.ascebc);
1154
1155         raw3270_activate_view(&tp->view);
1156         raw3270_put_view(&tp->view);
1157         *newtp = tp;
1158         return 0;
1159
1160 out_free_prompt:
1161         kfree(tp->prompt);
1162 out_free_input:
1163         kfree(tp->input);
1164 out_free_converted_line:
1165         free_page((unsigned long)tp->converted_line);
1166 out_free_screen:
1167         tty3270_free_screen(tp->screen, tp->view.rows);
1168 out_put_view:
1169         raw3270_put_view(&tp->view);
1170         raw3270_del_view(&tp->view);
1171 out_free_view:
1172         tty3270_free_view(tp);
1173         return rc;
1174 }
1175
1176 /*
1177  * This routine is called whenever a 3270 tty is opened first time.
1178  */
1179 static int
1180 tty3270_install(struct tty_driver *driver, struct tty_struct *tty)
1181 {
1182         struct raw3270_view *view;
1183         struct tty3270 *tp;
1184         int rc;
1185
1186         /* Check if the tty3270 is already there. */
1187         view = raw3270_find_view(&tty3270_fn, tty->index + RAW3270_FIRSTMINOR);
1188         if (IS_ERR(view)) {
1189                 rc = tty3270_create_view(tty->index, &tp);
1190                 if (rc)
1191                         return rc;
1192         } else {
1193                 tp = container_of(view, struct tty3270, view);
1194                 tty->driver_data = tp;
1195                 tp->inattr = TF_INPUT;
1196         }
1197
1198         tty->winsize.ws_row = tty3270_tty_rows(tp);
1199         tty->winsize.ws_col = tp->view.cols;
1200         rc = tty_port_install(&tp->port, driver, tty);
1201         if (rc) {
1202                 raw3270_put_view(&tp->view);
1203                 return rc;
1204         }
1205         tty->driver_data = tp;
1206         return 0;
1207 }
1208
1209 /*
1210  * This routine is called whenever a 3270 tty is opened.
1211  */
1212 static int tty3270_open(struct tty_struct *tty, struct file *filp)
1213 {
1214         struct tty3270 *tp = tty->driver_data;
1215         struct tty_port *port = &tp->port;
1216
1217         port->count++;
1218         tty_port_tty_set(port, tty);
1219         return 0;
1220 }
1221
1222 /*
1223  * This routine is called when the 3270 tty is closed. We wait
1224  * for the remaining request to be completed. Then we clean up.
1225  */
1226 static void tty3270_close(struct tty_struct *tty, struct file *filp)
1227 {
1228         struct tty3270 *tp = tty->driver_data;
1229
1230         if (tty->count > 1)
1231                 return;
1232         if (tp)
1233                 tty_port_tty_set(&tp->port, NULL);
1234 }
1235
1236 static void tty3270_cleanup(struct tty_struct *tty)
1237 {
1238         struct tty3270 *tp = tty->driver_data;
1239
1240         if (tp) {
1241                 tty->driver_data = NULL;
1242                 raw3270_put_view(&tp->view);
1243         }
1244 }
1245
1246 /*
1247  * We always have room.
1248  */
1249 static unsigned int tty3270_write_room(struct tty_struct *tty)
1250 {
1251         return INT_MAX;
1252 }
1253
1254 /*
1255  * Insert character into the screen at the current position with the
1256  * current color and highlight. This function does NOT do cursor movement.
1257  */
1258 static void tty3270_put_character(struct tty3270 *tp, u8 ch)
1259 {
1260         struct tty3270_line *line;
1261         struct tty3270_cell *cell;
1262
1263         line = tty3270_get_write_line(tp, tp->cy);
1264         if (line->len <= tp->cx) {
1265                 while (line->len < tp->cx) {
1266                         cell = line->cells + line->len;
1267                         cell->character = ' ';
1268                         cell->attributes = tp->attributes;
1269                         line->len++;
1270                 }
1271                 line->len++;
1272         }
1273         cell = line->cells + tp->cx;
1274         cell->character = ch;
1275         cell->attributes = tp->attributes;
1276         line->dirty = 1;
1277 }
1278
1279 /*
1280  * Do carriage return.
1281  */
1282 static void tty3270_cr(struct tty3270 *tp)
1283 {
1284         tp->cx = 0;
1285 }
1286
1287 /*
1288  * Do line feed.
1289  */
1290 static void tty3270_lf(struct tty3270 *tp)
1291 {
1292         struct tty3270_line *line;
1293         int i;
1294
1295         if (tp->cy < tty3270_tty_rows(tp) - 1) {
1296                 tp->cy++;
1297         } else {
1298                 tp->line_view_start = tty3270_line_increment(tp, tp->line_view_start, 1);
1299                 tp->line_write_start = tty3270_line_increment(tp, tp->line_write_start, 1);
1300                 for (i = 0; i < tty3270_tty_rows(tp); i++)
1301                         tty3270_get_view_line(tp, i)->dirty = 1;
1302         }
1303
1304         line = tty3270_get_write_line(tp, tp->cy);
1305         line->len = 0;
1306         line->dirty = 1;
1307 }
1308
1309 static void tty3270_ri(struct tty3270 *tp)
1310 {
1311         if (tp->cy > 0)
1312                 tp->cy--;
1313 }
1314
1315 static void tty3270_reset_cell(struct tty3270 *tp, struct tty3270_cell *cell)
1316 {
1317         cell->character = ' ';
1318         tty3270_reset_attributes(&cell->attributes);
1319 }
1320
1321 /*
1322  * Insert characters at current position.
1323  */
1324 static void tty3270_insert_characters(struct tty3270 *tp, int n)
1325 {
1326         struct tty3270_line *line;
1327         int k;
1328
1329         line = tty3270_get_write_line(tp, tp->cy);
1330         while (line->len < tp->cx)
1331                 tty3270_reset_cell(tp, &line->cells[line->len++]);
1332         if (n > tp->view.cols - tp->cx)
1333                 n = tp->view.cols - tp->cx;
1334         k = min_t(int, line->len - tp->cx, tp->view.cols - tp->cx - n);
1335         while (k--)
1336                 line->cells[tp->cx + n + k] = line->cells[tp->cx + k];
1337         line->len += n;
1338         if (line->len > tp->view.cols)
1339                 line->len = tp->view.cols;
1340         while (n-- > 0) {
1341                 line->cells[tp->cx + n].character = ' ';
1342                 line->cells[tp->cx + n].attributes = tp->attributes;
1343         }
1344 }
1345
1346 /*
1347  * Delete characters at current position.
1348  */
1349 static void tty3270_delete_characters(struct tty3270 *tp, int n)
1350 {
1351         struct tty3270_line *line;
1352         int i;
1353
1354         line = tty3270_get_write_line(tp, tp->cy);
1355         if (line->len <= tp->cx)
1356                 return;
1357         if (line->len - tp->cx <= n) {
1358                 line->len = tp->cx;
1359                 return;
1360         }
1361         for (i = tp->cx; i + n < line->len; i++)
1362                 line->cells[i] = line->cells[i + n];
1363         line->len -= n;
1364 }
1365
1366 /*
1367  * Erase characters at current position.
1368  */
1369 static void tty3270_erase_characters(struct tty3270 *tp, int n)
1370 {
1371         struct tty3270_line *line;
1372         struct tty3270_cell *cell;
1373
1374         line = tty3270_get_write_line(tp, tp->cy);
1375         while (line->len > tp->cx && n-- > 0) {
1376                 cell = line->cells + tp->cx++;
1377                 tty3270_reset_cell(tp, cell);
1378         }
1379         tp->cx += n;
1380         tp->cx = min_t(int, tp->cx, tp->view.cols - 1);
1381 }
1382
1383 /*
1384  * Erase line, 3 different cases:
1385  *  Esc [ 0 K   Erase from current position to end of line inclusive
1386  *  Esc [ 1 K   Erase from beginning of line to current position inclusive
1387  *  Esc [ 2 K   Erase entire line (without moving cursor)
1388  */
1389 static void tty3270_erase_line(struct tty3270 *tp, int mode)
1390 {
1391         struct tty3270_line *line;
1392         struct tty3270_cell *cell;
1393         int i, start, end;
1394
1395         line = tty3270_get_write_line(tp, tp->cy);
1396
1397         switch (mode) {
1398         case 0:
1399                 start = tp->cx;
1400                 end = tp->view.cols;
1401                 break;
1402         case 1:
1403                 start = 0;
1404                 end = tp->cx;
1405                 break;
1406         case 2:
1407                 start = 0;
1408                 end = tp->view.cols;
1409                 break;
1410         default:
1411                 return;
1412         }
1413
1414         for (i = start; i < end; i++) {
1415                 cell = line->cells + i;
1416                 tty3270_reset_cell(tp, cell);
1417                 cell->attributes.b_color = tp->attributes.b_color;
1418         }
1419
1420         if (line->len <= end)
1421                 line->len = end;
1422 }
1423
1424 /*
1425  * Erase display, 3 different cases:
1426  *  Esc [ 0 J   Erase from current position to bottom of screen inclusive
1427  *  Esc [ 1 J   Erase from top of screen to current position inclusive
1428  *  Esc [ 2 J   Erase entire screen (without moving the cursor)
1429  */
1430 static void tty3270_erase_display(struct tty3270 *tp, int mode)
1431 {
1432         struct tty3270_line *line;
1433         int i, start, end;
1434
1435         switch (mode) {
1436         case 0:
1437                 tty3270_erase_line(tp, 0);
1438                 start = tp->cy + 1;
1439                 end = tty3270_tty_rows(tp);
1440                 break;
1441         case 1:
1442                 start = 0;
1443                 end = tp->cy;
1444                 tty3270_erase_line(tp, 1);
1445                 break;
1446         case 2:
1447                 start = 0;
1448                 end = tty3270_tty_rows(tp);
1449                 break;
1450         default:
1451                 return;
1452         }
1453         for (i = start; i < end; i++) {
1454                 line = tty3270_get_write_line(tp, i);
1455                 line->len = 0;
1456                 line->dirty = 1;
1457         }
1458 }
1459
1460 /*
1461  * Set attributes found in an escape sequence.
1462  *  Esc [ <attr> ; <attr> ; ... m
1463  */
1464 static void tty3270_set_attributes(struct tty3270 *tp)
1465 {
1466         int i, attr;
1467
1468         for (i = 0; i <= tp->esc_npar; i++) {
1469                 attr = tp->esc_par[i];
1470                 switch (attr) {
1471                 case 0:         /* Reset */
1472                         tty3270_reset_attributes(&tp->attributes);
1473                         break;
1474                 /* Highlight. */
1475                 case 4:         /* Start underlining. */
1476                         tp->attributes.highlight = TTY3270_HIGHLIGHT_UNDERSCORE;
1477                         break;
1478                 case 5:         /* Start blink. */
1479                         tp->attributes.highlight = TTY3270_HIGHLIGHT_BLINK;
1480                         break;
1481                 case 7:         /* Start reverse. */
1482                         tp->attributes.highlight = TTY3270_HIGHLIGHT_REVERSE;
1483                         break;
1484                 case 24:        /* End underlining */
1485                         tp->attributes.highlight &= ~TTY3270_HIGHLIGHT_UNDERSCORE;
1486                         break;
1487                 case 25:        /* End blink. */
1488                         tp->attributes.highlight &= ~TTY3270_HIGHLIGHT_BLINK;
1489                         break;
1490                 case 27:        /* End reverse. */
1491                         tp->attributes.highlight &= ~TTY3270_HIGHLIGHT_REVERSE;
1492                         break;
1493                 /* Foreground color. */
1494                 case 30:        /* Black */
1495                 case 31:        /* Red */
1496                 case 32:        /* Green */
1497                 case 33:        /* Yellow */
1498                 case 34:        /* Blue */
1499                 case 35:        /* Magenta */
1500                 case 36:        /* Cyan */
1501                 case 37:        /* White */
1502                 case 39:        /* Black */
1503                         tp->attributes.f_color = attr - 30;
1504                         break;
1505                 /* Background color. */
1506                 case 40:        /* Black */
1507                 case 41:        /* Red */
1508                 case 42:        /* Green */
1509                 case 43:        /* Yellow */
1510                 case 44:        /* Blue */
1511                 case 45:        /* Magenta */
1512                 case 46:        /* Cyan */
1513                 case 47:        /* White */
1514                 case 49:        /* Black */
1515                         tp->attributes.b_color = attr - 40;
1516                         break;
1517                 }
1518         }
1519 }
1520
1521 static inline int tty3270_getpar(struct tty3270 *tp, int ix)
1522 {
1523         return (tp->esc_par[ix] > 0) ? tp->esc_par[ix] : 1;
1524 }
1525
1526 static void tty3270_goto_xy(struct tty3270 *tp, int cx, int cy)
1527 {
1528         struct tty3270_line *line;
1529         struct tty3270_cell *cell;
1530         int max_cx = max(0, cx);
1531         int max_cy = max(0, cy);
1532
1533         tp->cx = min_t(int, tp->view.cols - 1, max_cx);
1534         line = tty3270_get_write_line(tp, tp->cy);
1535         while (line->len < tp->cx) {
1536                 cell = line->cells + line->len;
1537                 cell->character = ' ';
1538                 cell->attributes = tp->attributes;
1539                 line->len++;
1540         }
1541         tp->cy = min_t(int, tty3270_tty_rows(tp) - 1, max_cy);
1542 }
1543
1544 /*
1545  * Process escape sequences. Known sequences:
1546  *  Esc 7                       Save Cursor Position
1547  *  Esc 8                       Restore Cursor Position
1548  *  Esc [ Pn ; Pn ; .. m        Set attributes
1549  *  Esc [ Pn ; Pn H             Cursor Position
1550  *  Esc [ Pn ; Pn f             Cursor Position
1551  *  Esc [ Pn A                  Cursor Up
1552  *  Esc [ Pn B                  Cursor Down
1553  *  Esc [ Pn C                  Cursor Forward
1554  *  Esc [ Pn D                  Cursor Backward
1555  *  Esc [ Pn G                  Cursor Horizontal Absolute
1556  *  Esc [ Pn X                  Erase Characters
1557  *  Esc [ Ps J                  Erase in Display
1558  *  Esc [ Ps K                  Erase in Line
1559  * // FIXME: add all the new ones.
1560  *
1561  *  Pn is a numeric parameter, a string of zero or more decimal digits.
1562  *  Ps is a selective parameter.
1563  */
1564 static void tty3270_escape_sequence(struct tty3270 *tp, u8 ch)
1565 {
1566         enum { ES_NORMAL, ES_ESC, ES_SQUARE, ES_PAREN, ES_GETPARS };
1567
1568         if (tp->esc_state == ES_NORMAL) {
1569                 if (ch == 0x1b)
1570                         /* Starting new escape sequence. */
1571                         tp->esc_state = ES_ESC;
1572                 return;
1573         }
1574         if (tp->esc_state == ES_ESC) {
1575                 tp->esc_state = ES_NORMAL;
1576                 switch (ch) {
1577                 case '[':
1578                         tp->esc_state = ES_SQUARE;
1579                         break;
1580                 case '(':
1581                         tp->esc_state = ES_PAREN;
1582                         break;
1583                 case 'E':
1584                         tty3270_cr(tp);
1585                         tty3270_lf(tp);
1586                         break;
1587                 case 'M':
1588                         tty3270_ri(tp);
1589                         break;
1590                 case 'D':
1591                         tty3270_lf(tp);
1592                         break;
1593                 case 'Z':               /* Respond ID. */
1594                         kbd_puts_queue(&tp->port, "\033[?6c");
1595                         break;
1596                 case '7':               /* Save cursor position. */
1597                         tp->saved_cx = tp->cx;
1598                         tp->saved_cy = tp->cy;
1599                         tp->saved_attributes = tp->attributes;
1600                         break;
1601                 case '8':               /* Restore cursor position. */
1602                         tty3270_goto_xy(tp, tp->saved_cx, tp->saved_cy);
1603                         tp->attributes = tp->saved_attributes;
1604                         break;
1605                 case 'c':               /* Reset terminal. */
1606                         tp->cx = 0;
1607                         tp->cy = 0;
1608                         tp->saved_cx = 0;
1609                         tp->saved_cy = 0;
1610                         tty3270_reset_attributes(&tp->attributes);
1611                         tty3270_reset_attributes(&tp->saved_attributes);
1612                         tty3270_erase_display(tp, 2);
1613                         break;
1614                 }
1615                 return;
1616         }
1617
1618         switch (tp->esc_state) {
1619         case ES_PAREN:
1620                 tp->esc_state = ES_NORMAL;
1621                 switch (ch) {
1622                 case 'B':
1623                         tp->attributes.alternate_charset = 0;
1624                         break;
1625                 case '0':
1626                         tp->attributes.alternate_charset = 1;
1627                         break;
1628                 }
1629                 return;
1630         case ES_SQUARE:
1631                 tp->esc_state = ES_GETPARS;
1632                 memset(tp->esc_par, 0, sizeof(tp->esc_par));
1633                 tp->esc_npar = 0;
1634                 tp->esc_ques = (ch == '?');
1635                 if (tp->esc_ques)
1636                         return;
1637                 fallthrough;
1638         case ES_GETPARS:
1639                 if (ch == ';' && tp->esc_npar < ESCAPE_NPAR - 1) {
1640                         tp->esc_npar++;
1641                         return;
1642                 }
1643                 if (ch >= '0' && ch <= '9') {
1644                         tp->esc_par[tp->esc_npar] *= 10;
1645                         tp->esc_par[tp->esc_npar] += ch - '0';
1646                         return;
1647                 }
1648                 break;
1649         default:
1650                 break;
1651         }
1652         tp->esc_state = ES_NORMAL;
1653         if (ch == 'n' && !tp->esc_ques) {
1654                 if (tp->esc_par[0] == 5)                /* Status report. */
1655                         kbd_puts_queue(&tp->port, "\033[0n");
1656                 else if (tp->esc_par[0] == 6) { /* Cursor report. */
1657                         char buf[40];
1658
1659                         sprintf(buf, "\033[%d;%dR", tp->cy + 1, tp->cx + 1);
1660                         kbd_puts_queue(&tp->port, buf);
1661                 }
1662                 return;
1663         }
1664         if (tp->esc_ques)
1665                 return;
1666         switch (ch) {
1667         case 'm':
1668                 tty3270_set_attributes(tp);
1669                 break;
1670         case 'H':       /* Set cursor position. */
1671         case 'f':
1672                 tty3270_goto_xy(tp, tty3270_getpar(tp, 1) - 1,
1673                                 tty3270_getpar(tp, 0) - 1);
1674                 break;
1675         case 'd':       /* Set y position. */
1676                 tty3270_goto_xy(tp, tp->cx, tty3270_getpar(tp, 0) - 1);
1677                 break;
1678         case 'A':       /* Cursor up. */
1679         case 'F':
1680                 tty3270_goto_xy(tp, tp->cx, tp->cy - tty3270_getpar(tp, 0));
1681                 break;
1682         case 'B':       /* Cursor down. */
1683         case 'e':
1684         case 'E':
1685                 tty3270_goto_xy(tp, tp->cx, tp->cy + tty3270_getpar(tp, 0));
1686                 break;
1687         case 'C':       /* Cursor forward. */
1688         case 'a':
1689                 tty3270_goto_xy(tp, tp->cx + tty3270_getpar(tp, 0), tp->cy);
1690                 break;
1691         case 'D':       /* Cursor backward. */
1692                 tty3270_goto_xy(tp, tp->cx - tty3270_getpar(tp, 0), tp->cy);
1693                 break;
1694         case 'G':       /* Set x position. */
1695         case '`':
1696                 tty3270_goto_xy(tp, tty3270_getpar(tp, 0), tp->cy);
1697                 break;
1698         case 'X':       /* Erase Characters. */
1699                 tty3270_erase_characters(tp, tty3270_getpar(tp, 0));
1700                 break;
1701         case 'J':       /* Erase display. */
1702                 tty3270_erase_display(tp, tp->esc_par[0]);
1703                 break;
1704         case 'K':       /* Erase line. */
1705                 tty3270_erase_line(tp, tp->esc_par[0]);
1706                 break;
1707         case 'P':       /* Delete characters. */
1708                 tty3270_delete_characters(tp, tty3270_getpar(tp, 0));
1709                 break;
1710         case '@':       /* Insert characters. */
1711                 tty3270_insert_characters(tp, tty3270_getpar(tp, 0));
1712                 break;
1713         case 's':       /* Save cursor position. */
1714                 tp->saved_cx = tp->cx;
1715                 tp->saved_cy = tp->cy;
1716                 tp->saved_attributes = tp->attributes;
1717                 break;
1718         case 'u':       /* Restore cursor position. */
1719                 tty3270_goto_xy(tp, tp->saved_cx, tp->saved_cy);
1720                 tp->attributes = tp->saved_attributes;
1721                 break;
1722         }
1723 }
1724
1725 /*
1726  * String write routine for 3270 ttys
1727  */
1728 static void tty3270_do_write(struct tty3270 *tp, struct tty_struct *tty,
1729                              const u8 *buf, size_t count)
1730 {
1731         int i_msg, i;
1732
1733         spin_lock_irq(&tp->view.lock);
1734         for (i_msg = 0; !tty->flow.stopped && i_msg < count; i_msg++) {
1735                 if (tp->esc_state != 0) {
1736                         /* Continue escape sequence. */
1737                         tty3270_escape_sequence(tp, buf[i_msg]);
1738                         continue;
1739                 }
1740
1741                 switch (buf[i_msg]) {
1742                 case 0x00:
1743                         break;
1744                 case 0x07:              /* '\a' -- Alarm */
1745                         tp->wcc |= TW_PLUSALARM;
1746                         break;
1747                 case 0x08:              /* Backspace. */
1748                         if (tp->cx > 0) {
1749                                 tp->cx--;
1750                                 tty3270_put_character(tp, ' ');
1751                         }
1752                         break;
1753                 case 0x09:              /* '\t' -- Tabulate */
1754                         for (i = tp->cx % 8; i < 8; i++) {
1755                                 if (tp->cx >= tp->view.cols) {
1756                                         tty3270_cr(tp);
1757                                         tty3270_lf(tp);
1758                                         break;
1759                                 }
1760                                 tty3270_put_character(tp, ' ');
1761                                 tp->cx++;
1762                         }
1763                         break;
1764                 case 0x0a:              /* '\n' -- New Line */
1765                         tty3270_cr(tp);
1766                         tty3270_lf(tp);
1767                         break;
1768                 case 0x0c:              /* '\f' -- Form Feed */
1769                         tty3270_erase_display(tp, 2);
1770                         tp->cx = 0;
1771                         tp->cy = 0;
1772                         break;
1773                 case 0x0d:              /* '\r' -- Carriage Return */
1774                         tp->cx = 0;
1775                         break;
1776                 case 0x0e:
1777                         tp->attributes.alternate_charset = 1;
1778                         break;
1779                 case 0x0f:              /* SuSE "exit alternate mode" */
1780                         tp->attributes.alternate_charset = 0;
1781                         break;
1782                 case 0x1b:              /* Start escape sequence. */
1783                         tty3270_escape_sequence(tp, buf[i_msg]);
1784                         break;
1785                 default:                /* Insert normal character. */
1786                         if (tp->cx >= tp->view.cols) {
1787                                 tty3270_cr(tp);
1788                                 tty3270_lf(tp);
1789                         }
1790                         tty3270_put_character(tp, buf[i_msg]);
1791                         tp->cx++;
1792                         break;
1793                 }
1794         }
1795         /* Setup timer to update display after 1/10 second */
1796         tp->update_flags |= TTY_UPDATE_LINES;
1797         if (!timer_pending(&tp->timer))
1798                 tty3270_set_timer(tp, msecs_to_jiffies(100));
1799
1800         spin_unlock_irq(&tp->view.lock);
1801 }
1802
1803 /*
1804  * String write routine for 3270 ttys
1805  */
1806 static ssize_t tty3270_write(struct tty_struct *tty, const u8 *buf,
1807                              size_t count)
1808 {
1809         struct tty3270 *tp;
1810
1811         tp = tty->driver_data;
1812         if (!tp)
1813                 return 0;
1814         if (tp->char_count > 0) {
1815                 tty3270_do_write(tp, tty, tp->char_buf, tp->char_count);
1816                 tp->char_count = 0;
1817         }
1818         tty3270_do_write(tp, tty, buf, count);
1819         return count;
1820 }
1821
1822 /*
1823  * Put single characters to the ttys character buffer
1824  */
1825 static int tty3270_put_char(struct tty_struct *tty, u8 ch)
1826 {
1827         struct tty3270 *tp;
1828
1829         tp = tty->driver_data;
1830         if (!tp || tp->char_count >= TTY3270_CHAR_BUF_SIZE)
1831                 return 0;
1832         tp->char_buf[tp->char_count++] = ch;
1833         return 1;
1834 }
1835
1836 /*
1837  * Flush all characters from the ttys characeter buffer put there
1838  * by tty3270_put_char.
1839  */
1840 static void tty3270_flush_chars(struct tty_struct *tty)
1841 {
1842         struct tty3270 *tp;
1843
1844         tp = tty->driver_data;
1845         if (!tp)
1846                 return;
1847         if (tp->char_count > 0) {
1848                 tty3270_do_write(tp, tty, tp->char_buf, tp->char_count);
1849                 tp->char_count = 0;
1850         }
1851 }
1852
1853 /*
1854  * Check for visible/invisible input switches
1855  */
1856 static void tty3270_set_termios(struct tty_struct *tty, const struct ktermios *old)
1857 {
1858         struct tty3270 *tp;
1859         int new;
1860
1861         tp = tty->driver_data;
1862         if (!tp)
1863                 return;
1864         spin_lock_irq(&tp->view.lock);
1865         if (L_ICANON(tty)) {
1866                 new = L_ECHO(tty) ? TF_INPUT : TF_INPUTN;
1867                 if (new != tp->inattr) {
1868                         tp->inattr = new;
1869                         tty3270_update_prompt(tp, "");
1870                         tty3270_set_timer(tp, 1);
1871                 }
1872         }
1873         spin_unlock_irq(&tp->view.lock);
1874 }
1875
1876 /*
1877  * Disable reading from a 3270 tty
1878  */
1879 static void tty3270_throttle(struct tty_struct *tty)
1880 {
1881         struct tty3270 *tp;
1882
1883         tp = tty->driver_data;
1884         if (!tp)
1885                 return;
1886         tp->throttle = 1;
1887 }
1888
1889 /*
1890  * Enable reading from a 3270 tty
1891  */
1892 static void tty3270_unthrottle(struct tty_struct *tty)
1893 {
1894         struct tty3270 *tp;
1895
1896         tp = tty->driver_data;
1897         if (!tp)
1898                 return;
1899         tp->throttle = 0;
1900         if (tp->attn)
1901                 tty3270_issue_read(tp, 1);
1902 }
1903
1904 /*
1905  * Hang up the tty device.
1906  */
1907 static void tty3270_hangup(struct tty_struct *tty)
1908 {
1909         struct tty3270 *tp;
1910
1911         tp = tty->driver_data;
1912         if (!tp)
1913                 return;
1914         spin_lock_irq(&tp->view.lock);
1915         tp->cx = 0;
1916         tp->cy = 0;
1917         tp->saved_cx = 0;
1918         tp->saved_cy = 0;
1919         tty3270_reset_attributes(&tp->attributes);
1920         tty3270_reset_attributes(&tp->saved_attributes);
1921         tty3270_blank_screen(tp);
1922         tp->update_flags = TTY_UPDATE_ALL;
1923         spin_unlock_irq(&tp->view.lock);
1924         tty3270_set_timer(tp, 1);
1925 }
1926
1927 static void tty3270_wait_until_sent(struct tty_struct *tty, int timeout)
1928 {
1929 }
1930
1931 static int tty3270_ioctl(struct tty_struct *tty, unsigned int cmd,
1932                          unsigned long arg)
1933 {
1934         struct tty3270 *tp;
1935
1936         tp = tty->driver_data;
1937         if (!tp)
1938                 return -ENODEV;
1939         if (tty_io_error(tty))
1940                 return -EIO;
1941         return kbd_ioctl(tp->kbd, cmd, arg);
1942 }
1943
1944 #ifdef CONFIG_COMPAT
1945 static long tty3270_compat_ioctl(struct tty_struct *tty,
1946                                  unsigned int cmd, unsigned long arg)
1947 {
1948         struct tty3270 *tp;
1949
1950         tp = tty->driver_data;
1951         if (!tp)
1952                 return -ENODEV;
1953         if (tty_io_error(tty))
1954                 return -EIO;
1955         return kbd_ioctl(tp->kbd, cmd, (unsigned long)compat_ptr(arg));
1956 }
1957 #endif
1958
1959 static const struct tty_operations tty3270_ops = {
1960         .install = tty3270_install,
1961         .cleanup = tty3270_cleanup,
1962         .open = tty3270_open,
1963         .close = tty3270_close,
1964         .write = tty3270_write,
1965         .put_char = tty3270_put_char,
1966         .flush_chars = tty3270_flush_chars,
1967         .write_room = tty3270_write_room,
1968         .throttle = tty3270_throttle,
1969         .unthrottle = tty3270_unthrottle,
1970         .hangup = tty3270_hangup,
1971         .wait_until_sent = tty3270_wait_until_sent,
1972         .ioctl = tty3270_ioctl,
1973 #ifdef CONFIG_COMPAT
1974         .compat_ioctl = tty3270_compat_ioctl,
1975 #endif
1976         .set_termios = tty3270_set_termios
1977 };
1978
1979 static void tty3270_create_cb(int minor)
1980 {
1981         tty_register_device(tty3270_driver, minor - RAW3270_FIRSTMINOR, NULL);
1982 }
1983
1984 static void tty3270_destroy_cb(int minor)
1985 {
1986         tty_unregister_device(tty3270_driver, minor - RAW3270_FIRSTMINOR);
1987 }
1988
1989 static struct raw3270_notifier tty3270_notifier = {
1990         .create = tty3270_create_cb,
1991         .destroy = tty3270_destroy_cb,
1992 };
1993
1994 /*
1995  * 3270 tty registration code called from tty_init().
1996  * Most kernel services (incl. kmalloc) are available at this poimt.
1997  */
1998 static int __init tty3270_init(void)
1999 {
2000         struct tty_driver *driver;
2001         int ret;
2002
2003         driver = tty_alloc_driver(RAW3270_MAXDEVS,
2004                                   TTY_DRIVER_REAL_RAW |
2005                                   TTY_DRIVER_DYNAMIC_DEV |
2006                                   TTY_DRIVER_RESET_TERMIOS);
2007         if (IS_ERR(driver))
2008                 return PTR_ERR(driver);
2009
2010         /*
2011          * Initialize the tty_driver structure
2012          * Entries in tty3270_driver that are NOT initialized:
2013          * proc_entry, set_termios, flush_buffer, set_ldisc, write_proc
2014          */
2015         driver->driver_name = "tty3270";
2016         driver->name = "3270/tty";
2017         driver->major = IBM_TTY3270_MAJOR;
2018         driver->minor_start = RAW3270_FIRSTMINOR;
2019         driver->name_base = RAW3270_FIRSTMINOR;
2020         driver->type = TTY_DRIVER_TYPE_SYSTEM;
2021         driver->subtype = SYSTEM_TYPE_TTY;
2022         driver->init_termios = tty_std_termios;
2023         tty_set_operations(driver, &tty3270_ops);
2024         ret = tty_register_driver(driver);
2025         if (ret) {
2026                 tty_driver_kref_put(driver);
2027                 return ret;
2028         }
2029         tty3270_driver = driver;
2030         raw3270_register_notifier(&tty3270_notifier);
2031         return 0;
2032 }
2033
2034 static void __exit tty3270_exit(void)
2035 {
2036         struct tty_driver *driver;
2037
2038         raw3270_unregister_notifier(&tty3270_notifier);
2039         driver = tty3270_driver;
2040         tty3270_driver = NULL;
2041         tty_unregister_driver(driver);
2042         tty_driver_kref_put(driver);
2043         tty3270_del_views();
2044 }
2045
2046 #if IS_ENABLED(CONFIG_TN3270_CONSOLE)
2047
2048 static struct tty3270 *condev;
2049
2050 static void
2051 con3270_write(struct console *co, const char *str, unsigned int count)
2052 {
2053         struct tty3270 *tp = co->data;
2054         unsigned long flags;
2055         u8 c;
2056
2057         spin_lock_irqsave(&tp->view.lock, flags);
2058         while (count--) {
2059                 c = *str++;
2060                 if (c == 0x0a) {
2061                         tty3270_cr(tp);
2062                         tty3270_lf(tp);
2063                 } else {
2064                         if (tp->cx >= tp->view.cols) {
2065                                 tty3270_cr(tp);
2066                                 tty3270_lf(tp);
2067                         }
2068                         tty3270_put_character(tp, c);
2069                         tp->cx++;
2070                 }
2071         }
2072         spin_unlock_irqrestore(&tp->view.lock, flags);
2073 }
2074
2075 static struct tty_driver *
2076 con3270_device(struct console *c, int *index)
2077 {
2078         *index = c->index;
2079         return tty3270_driver;
2080 }
2081
2082 static void
2083 con3270_wait_write(struct tty3270 *tp)
2084 {
2085         while (!tp->write) {
2086                 raw3270_wait_cons_dev(tp->view.dev);
2087                 barrier();
2088         }
2089 }
2090
2091 /*
2092  * The below function is called as a panic/reboot notifier before the
2093  * system enters a disabled, endless loop.
2094  *
2095  * Notice we must use the spin_trylock() alternative, to prevent lockups
2096  * in atomic context (panic routine runs with secondary CPUs, local IRQs
2097  * and preemption disabled).
2098  */
2099 static int con3270_notify(struct notifier_block *self,
2100                           unsigned long event, void *data)
2101 {
2102         struct tty3270 *tp;
2103         unsigned long flags;
2104         int rc;
2105
2106         tp = condev;
2107         if (!tp->view.dev)
2108                 return NOTIFY_DONE;
2109         if (!raw3270_view_lock_unavailable(&tp->view)) {
2110                 rc = raw3270_activate_view(&tp->view);
2111                 if (rc)
2112                         return NOTIFY_DONE;
2113         }
2114         if (!spin_trylock_irqsave(&tp->view.lock, flags))
2115                 return NOTIFY_DONE;
2116         con3270_wait_write(tp);
2117         tp->nr_up = 0;
2118         tp->update_flags = TTY_UPDATE_ALL;
2119         while (tp->update_flags != 0) {
2120                 spin_unlock_irqrestore(&tp->view.lock, flags);
2121                 tty3270_update(&tp->timer);
2122                 spin_lock_irqsave(&tp->view.lock, flags);
2123                 con3270_wait_write(tp);
2124         }
2125         spin_unlock_irqrestore(&tp->view.lock, flags);
2126         return NOTIFY_DONE;
2127 }
2128
2129 static struct notifier_block on_panic_nb = {
2130         .notifier_call = con3270_notify,
2131         .priority = INT_MIN + 1, /* run the callback late */
2132 };
2133
2134 static struct notifier_block on_reboot_nb = {
2135         .notifier_call = con3270_notify,
2136         .priority = INT_MIN + 1, /* run the callback late */
2137 };
2138
2139 static struct console con3270 = {
2140         .name    = "tty3270",
2141         .write   = con3270_write,
2142         .device  = con3270_device,
2143         .flags   = CON_PRINTBUFFER,
2144 };
2145
2146 static int __init
2147 con3270_init(void)
2148 {
2149         struct raw3270_view *view;
2150         struct raw3270 *rp;
2151         struct tty3270 *tp;
2152         int rc;
2153
2154         /* Check if 3270 is to be the console */
2155         if (!CONSOLE_IS_3270)
2156                 return -ENODEV;
2157
2158         /* Set the console mode for VM */
2159         if (MACHINE_IS_VM) {
2160                 cpcmd("TERM CONMODE 3270", NULL, 0, NULL);
2161                 cpcmd("TERM AUTOCR OFF", NULL, 0, NULL);
2162         }
2163
2164         rp = raw3270_setup_console();
2165         if (IS_ERR(rp))
2166                 return PTR_ERR(rp);
2167
2168         /* Check if the tty3270 is already there. */
2169         view = raw3270_find_view(&tty3270_fn, RAW3270_FIRSTMINOR);
2170         if (IS_ERR(view)) {
2171                 rc = tty3270_create_view(0, &tp);
2172                 if (rc)
2173                         return rc;
2174         } else {
2175                 tp = container_of(view, struct tty3270, view);
2176                 tp->inattr = TF_INPUT;
2177         }
2178         con3270.data = tp;
2179         condev = tp;
2180         atomic_notifier_chain_register(&panic_notifier_list, &on_panic_nb);
2181         register_reboot_notifier(&on_reboot_nb);
2182         register_console(&con3270);
2183         return 0;
2184 }
2185 console_initcall(con3270_init);
2186 #endif
2187
2188 MODULE_LICENSE("GPL");
2189 MODULE_ALIAS_CHARDEV_MAJOR(IBM_TTY3270_MAJOR);
2190
2191 module_init(tty3270_init);
2192 module_exit(tty3270_exit);