1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * SCLP line mode terminal driver. |
4 | * |
5 | * S390 version |
6 | * Copyright IBM Corp. 1999 |
7 | * Author(s): Martin Peschke <mpeschke@de.ibm.com> |
8 | * Martin Schwidefsky <schwidefsky@de.ibm.com> |
9 | */ |
10 | |
11 | #include <linux/kmod.h> |
12 | #include <linux/tty.h> |
13 | #include <linux/tty_driver.h> |
14 | #include <linux/tty_flip.h> |
15 | #include <linux/err.h> |
16 | #include <linux/init.h> |
17 | #include <linux/interrupt.h> |
18 | #include <linux/gfp.h> |
19 | #include <linux/uaccess.h> |
20 | |
21 | #include "ctrlchar.h" |
22 | #include "sclp.h" |
23 | #include "sclp_rw.h" |
24 | #include "sclp_tty.h" |
25 | |
26 | /* |
27 | * size of a buffer that collects single characters coming in |
28 | * via sclp_tty_put_char() |
29 | */ |
30 | #define SCLP_TTY_BUF_SIZE 512 |
31 | |
32 | /* |
33 | * There is exactly one SCLP terminal, so we can keep things simple |
34 | * and allocate all variables statically. |
35 | */ |
36 | |
37 | /* Lock to guard over changes to global variables. */ |
38 | static DEFINE_SPINLOCK(sclp_tty_lock); |
39 | /* List of free pages that can be used for console output buffering. */ |
40 | static LIST_HEAD(sclp_tty_pages); |
41 | /* List of full struct sclp_buffer structures ready for output. */ |
42 | static LIST_HEAD(sclp_tty_outqueue); |
43 | /* Counter how many buffers are emitted. */ |
44 | static int sclp_tty_buffer_count; |
45 | /* Pointer to current console buffer. */ |
46 | static struct sclp_buffer *sclp_ttybuf; |
47 | /* Timer for delayed output of console messages. */ |
48 | static struct timer_list sclp_tty_timer; |
49 | |
50 | static struct tty_port sclp_port; |
51 | static u8 sclp_tty_chars[SCLP_TTY_BUF_SIZE]; |
52 | static unsigned short int sclp_tty_chars_count; |
53 | |
54 | struct tty_driver *sclp_tty_driver; |
55 | |
56 | static int sclp_tty_tolower; |
57 | |
58 | #define SCLP_TTY_COLUMNS 320 |
59 | #define SPACES_PER_TAB 8 |
60 | #define CASE_DELIMITER 0x6c /* to separate upper and lower case (% in EBCDIC) */ |
61 | |
62 | /* This routine is called whenever we try to open a SCLP terminal. */ |
63 | static int |
64 | sclp_tty_open(struct tty_struct *tty, struct file *filp) |
65 | { |
66 | tty_port_tty_set(port: &sclp_port, tty); |
67 | tty->driver_data = NULL; |
68 | return 0; |
69 | } |
70 | |
71 | /* This routine is called when the SCLP terminal is closed. */ |
72 | static void |
73 | sclp_tty_close(struct tty_struct *tty, struct file *filp) |
74 | { |
75 | if (tty->count > 1) |
76 | return; |
77 | tty_port_tty_set(port: &sclp_port, NULL); |
78 | } |
79 | |
80 | /* |
81 | * This routine returns the numbers of characters the tty driver |
82 | * will accept for queuing to be written. This number is subject |
83 | * to change as output buffers get emptied, or if the output flow |
84 | * control is acted. This is not an exact number because not every |
85 | * character needs the same space in the sccb. The worst case is |
86 | * a string of newlines. Every newline creates a new message which |
87 | * needs 82 bytes. |
88 | */ |
89 | static unsigned int |
90 | sclp_tty_write_room (struct tty_struct *tty) |
91 | { |
92 | unsigned long flags; |
93 | struct list_head *l; |
94 | unsigned int count; |
95 | |
96 | spin_lock_irqsave(&sclp_tty_lock, flags); |
97 | count = 0; |
98 | if (sclp_ttybuf != NULL) |
99 | count = sclp_buffer_space(sclp_ttybuf) / sizeof(struct msg_buf); |
100 | list_for_each(l, &sclp_tty_pages) |
101 | count += NR_EMPTY_MSG_PER_SCCB; |
102 | spin_unlock_irqrestore(lock: &sclp_tty_lock, flags); |
103 | return count; |
104 | } |
105 | |
106 | static void |
107 | sclp_ttybuf_callback(struct sclp_buffer *buffer, int rc) |
108 | { |
109 | unsigned long flags; |
110 | void *page; |
111 | |
112 | do { |
113 | page = sclp_unmake_buffer(buffer); |
114 | spin_lock_irqsave(&sclp_tty_lock, flags); |
115 | /* Remove buffer from outqueue */ |
116 | list_del(entry: &buffer->list); |
117 | sclp_tty_buffer_count--; |
118 | list_add_tail(new: (struct list_head *) page, head: &sclp_tty_pages); |
119 | /* Check if there is a pending buffer on the out queue. */ |
120 | buffer = NULL; |
121 | if (!list_empty(head: &sclp_tty_outqueue)) |
122 | buffer = list_entry(sclp_tty_outqueue.next, |
123 | struct sclp_buffer, list); |
124 | spin_unlock_irqrestore(lock: &sclp_tty_lock, flags); |
125 | } while (buffer && sclp_emit_buffer(buffer, sclp_ttybuf_callback)); |
126 | |
127 | tty_port_tty_wakeup(port: &sclp_port); |
128 | } |
129 | |
130 | static inline void |
131 | __sclp_ttybuf_emit(struct sclp_buffer *buffer) |
132 | { |
133 | unsigned long flags; |
134 | int count; |
135 | int rc; |
136 | |
137 | spin_lock_irqsave(&sclp_tty_lock, flags); |
138 | list_add_tail(new: &buffer->list, head: &sclp_tty_outqueue); |
139 | count = sclp_tty_buffer_count++; |
140 | spin_unlock_irqrestore(lock: &sclp_tty_lock, flags); |
141 | if (count) |
142 | return; |
143 | rc = sclp_emit_buffer(buffer, sclp_ttybuf_callback); |
144 | if (rc) |
145 | sclp_ttybuf_callback(buffer, rc); |
146 | } |
147 | |
148 | /* |
149 | * When this routine is called from the timer then we flush the |
150 | * temporary write buffer. |
151 | */ |
152 | static void |
153 | sclp_tty_timeout(struct timer_list *unused) |
154 | { |
155 | unsigned long flags; |
156 | struct sclp_buffer *buf; |
157 | |
158 | spin_lock_irqsave(&sclp_tty_lock, flags); |
159 | buf = sclp_ttybuf; |
160 | sclp_ttybuf = NULL; |
161 | spin_unlock_irqrestore(lock: &sclp_tty_lock, flags); |
162 | |
163 | if (buf != NULL) { |
164 | __sclp_ttybuf_emit(buffer: buf); |
165 | } |
166 | } |
167 | |
168 | /* |
169 | * Write a string to the sclp tty. |
170 | */ |
171 | static int sclp_tty_write_string(const u8 *str, int count, int may_fail) |
172 | { |
173 | unsigned long flags; |
174 | void *page; |
175 | int written; |
176 | int overall_written; |
177 | struct sclp_buffer *buf; |
178 | |
179 | if (count <= 0) |
180 | return 0; |
181 | overall_written = 0; |
182 | spin_lock_irqsave(&sclp_tty_lock, flags); |
183 | do { |
184 | /* Create a sclp output buffer if none exists yet */ |
185 | if (sclp_ttybuf == NULL) { |
186 | while (list_empty(head: &sclp_tty_pages)) { |
187 | spin_unlock_irqrestore(lock: &sclp_tty_lock, flags); |
188 | if (may_fail) |
189 | goto out; |
190 | else |
191 | sclp_sync_wait(); |
192 | spin_lock_irqsave(&sclp_tty_lock, flags); |
193 | } |
194 | page = sclp_tty_pages.next; |
195 | list_del(entry: (struct list_head *) page); |
196 | sclp_ttybuf = sclp_make_buffer(page, SCLP_TTY_COLUMNS, |
197 | SPACES_PER_TAB); |
198 | } |
199 | /* try to write the string to the current output buffer */ |
200 | written = sclp_write(buffer: sclp_ttybuf, str, count); |
201 | overall_written += written; |
202 | if (written == count) |
203 | break; |
204 | /* |
205 | * Not all characters could be written to the current |
206 | * output buffer. Emit the buffer, create a new buffer |
207 | * and then output the rest of the string. |
208 | */ |
209 | buf = sclp_ttybuf; |
210 | sclp_ttybuf = NULL; |
211 | spin_unlock_irqrestore(lock: &sclp_tty_lock, flags); |
212 | __sclp_ttybuf_emit(buffer: buf); |
213 | spin_lock_irqsave(&sclp_tty_lock, flags); |
214 | str += written; |
215 | count -= written; |
216 | } while (count > 0); |
217 | /* Setup timer to output current console buffer after 1/10 second */ |
218 | if (sclp_ttybuf && sclp_chars_in_buffer(sclp_ttybuf) && |
219 | !timer_pending(timer: &sclp_tty_timer)) { |
220 | mod_timer(timer: &sclp_tty_timer, expires: jiffies + HZ / 10); |
221 | } |
222 | spin_unlock_irqrestore(lock: &sclp_tty_lock, flags); |
223 | out: |
224 | return overall_written; |
225 | } |
226 | |
227 | /* |
228 | * This routine is called by the kernel to write a series of characters to the |
229 | * tty device. The characters may come from user space or kernel space. This |
230 | * routine will return the number of characters actually accepted for writing. |
231 | */ |
232 | static ssize_t |
233 | sclp_tty_write(struct tty_struct *tty, const u8 *buf, size_t count) |
234 | { |
235 | if (sclp_tty_chars_count > 0) { |
236 | sclp_tty_write_string(str: sclp_tty_chars, count: sclp_tty_chars_count, may_fail: 0); |
237 | sclp_tty_chars_count = 0; |
238 | } |
239 | return sclp_tty_write_string(str: buf, count, may_fail: 1); |
240 | } |
241 | |
242 | /* |
243 | * This routine is called by the kernel to write a single character to the tty |
244 | * device. If the kernel uses this routine, it must call the flush_chars() |
245 | * routine (if defined) when it is done stuffing characters into the driver. |
246 | * |
247 | * Characters provided to sclp_tty_put_char() are buffered by the SCLP driver. |
248 | * If the given character is a '\n' the contents of the SCLP write buffer |
249 | * - including previous characters from sclp_tty_put_char() and strings from |
250 | * sclp_write() without final '\n' - will be written. |
251 | */ |
252 | static int |
253 | sclp_tty_put_char(struct tty_struct *tty, u8 ch) |
254 | { |
255 | sclp_tty_chars[sclp_tty_chars_count++] = ch; |
256 | if (ch == '\n' || sclp_tty_chars_count >= SCLP_TTY_BUF_SIZE) { |
257 | sclp_tty_write_string(str: sclp_tty_chars, count: sclp_tty_chars_count, may_fail: 0); |
258 | sclp_tty_chars_count = 0; |
259 | } |
260 | return 1; |
261 | } |
262 | |
263 | /* |
264 | * This routine is called by the kernel after it has written a series of |
265 | * characters to the tty device using put_char(). |
266 | */ |
267 | static void |
268 | sclp_tty_flush_chars(struct tty_struct *tty) |
269 | { |
270 | if (sclp_tty_chars_count > 0) { |
271 | sclp_tty_write_string(str: sclp_tty_chars, count: sclp_tty_chars_count, may_fail: 0); |
272 | sclp_tty_chars_count = 0; |
273 | } |
274 | } |
275 | |
276 | /* |
277 | * This routine returns the number of characters in the write buffer of the |
278 | * SCLP driver. The provided number includes all characters that are stored |
279 | * in the SCCB (will be written next time the SCLP is not busy) as well as |
280 | * characters in the write buffer (will not be written as long as there is a |
281 | * final line feed missing). |
282 | */ |
283 | static unsigned int |
284 | sclp_tty_chars_in_buffer(struct tty_struct *tty) |
285 | { |
286 | unsigned long flags; |
287 | struct sclp_buffer *t; |
288 | unsigned int count = 0; |
289 | |
290 | spin_lock_irqsave(&sclp_tty_lock, flags); |
291 | if (sclp_ttybuf != NULL) |
292 | count = sclp_chars_in_buffer(sclp_ttybuf); |
293 | list_for_each_entry(t, &sclp_tty_outqueue, list) { |
294 | count += sclp_chars_in_buffer(t); |
295 | } |
296 | spin_unlock_irqrestore(lock: &sclp_tty_lock, flags); |
297 | return count; |
298 | } |
299 | |
300 | /* |
301 | * removes all content from buffers of low level driver |
302 | */ |
303 | static void |
304 | sclp_tty_flush_buffer(struct tty_struct *tty) |
305 | { |
306 | if (sclp_tty_chars_count > 0) { |
307 | sclp_tty_write_string(str: sclp_tty_chars, count: sclp_tty_chars_count, may_fail: 0); |
308 | sclp_tty_chars_count = 0; |
309 | } |
310 | } |
311 | |
312 | /* |
313 | * push input to tty |
314 | */ |
315 | static void |
316 | sclp_tty_input(unsigned char* buf, unsigned int count) |
317 | { |
318 | struct tty_struct *tty = tty_port_tty_get(port: &sclp_port); |
319 | unsigned int cchar; |
320 | |
321 | /* |
322 | * If this tty driver is currently closed |
323 | * then throw the received input away. |
324 | */ |
325 | if (tty == NULL) |
326 | return; |
327 | cchar = ctrlchar_handle(buf, len: count, tty); |
328 | switch (cchar & CTRLCHAR_MASK) { |
329 | case CTRLCHAR_SYSRQ: |
330 | break; |
331 | case CTRLCHAR_CTRL: |
332 | tty_insert_flip_char(port: &sclp_port, ch: cchar, TTY_NORMAL); |
333 | tty_flip_buffer_push(port: &sclp_port); |
334 | break; |
335 | case CTRLCHAR_NONE: |
336 | /* send (normal) input to line discipline */ |
337 | if (count < 2 || |
338 | (strncmp((const char *) buf + count - 2, "^n" , 2) && |
339 | strncmp((const char *) buf + count - 2, "\252n" , 2))) { |
340 | /* add the auto \n */ |
341 | tty_insert_flip_string(port: &sclp_port, chars: buf, size: count); |
342 | tty_insert_flip_char(port: &sclp_port, ch: '\n', TTY_NORMAL); |
343 | } else |
344 | tty_insert_flip_string(port: &sclp_port, chars: buf, size: count - 2); |
345 | tty_flip_buffer_push(port: &sclp_port); |
346 | break; |
347 | } |
348 | tty_kref_put(tty); |
349 | } |
350 | |
351 | /* |
352 | * get a EBCDIC string in upper/lower case, |
353 | * find out characters in lower/upper case separated by a special character, |
354 | * modifiy original string, |
355 | * returns length of resulting string |
356 | */ |
357 | static int sclp_switch_cases(unsigned char *buf, int count) |
358 | { |
359 | unsigned char *ip, *op; |
360 | int toggle; |
361 | |
362 | /* initially changing case is off */ |
363 | toggle = 0; |
364 | ip = op = buf; |
365 | while (count-- > 0) { |
366 | /* compare with special character */ |
367 | if (*ip == CASE_DELIMITER) { |
368 | /* followed by another special character? */ |
369 | if (count && ip[1] == CASE_DELIMITER) { |
370 | /* |
371 | * ... then put a single copy of the special |
372 | * character to the output string |
373 | */ |
374 | *op++ = *ip++; |
375 | count--; |
376 | } else |
377 | /* |
378 | * ... special character follower by a normal |
379 | * character toggles the case change behaviour |
380 | */ |
381 | toggle = ~toggle; |
382 | /* skip special character */ |
383 | ip++; |
384 | } else |
385 | /* not the special character */ |
386 | if (toggle) |
387 | /* but case switching is on */ |
388 | if (sclp_tty_tolower) |
389 | /* switch to uppercase */ |
390 | *op++ = _ebc_toupper[(int) *ip++]; |
391 | else |
392 | /* switch to lowercase */ |
393 | *op++ = _ebc_tolower[(int) *ip++]; |
394 | else |
395 | /* no case switching, copy the character */ |
396 | *op++ = *ip++; |
397 | } |
398 | /* return length of reformatted string. */ |
399 | return op - buf; |
400 | } |
401 | |
402 | static void sclp_get_input(struct gds_subvector *sv) |
403 | { |
404 | unsigned char *str; |
405 | int count; |
406 | |
407 | str = (unsigned char *) (sv + 1); |
408 | count = sv->length - sizeof(*sv); |
409 | if (sclp_tty_tolower) |
410 | EBC_TOLOWER(str, count); |
411 | count = sclp_switch_cases(buf: str, count); |
412 | /* convert EBCDIC to ASCII (modify original input in SCCB) */ |
413 | sclp_ebcasc_str(str, nr: count); |
414 | |
415 | /* transfer input to high level driver */ |
416 | sclp_tty_input(buf: str, count); |
417 | } |
418 | |
419 | static inline void sclp_eval_selfdeftextmsg(struct gds_subvector *sv) |
420 | { |
421 | void *end; |
422 | |
423 | end = (void *) sv + sv->length; |
424 | for (sv = sv + 1; (void *) sv < end; sv = (void *) sv + sv->length) |
425 | if (sv->key == 0x30) |
426 | sclp_get_input(sv); |
427 | } |
428 | |
429 | static inline void sclp_eval_textcmd(struct gds_vector *v) |
430 | { |
431 | struct gds_subvector *sv; |
432 | void *end; |
433 | |
434 | end = (void *) v + v->length; |
435 | for (sv = (struct gds_subvector *) (v + 1); |
436 | (void *) sv < end; sv = (void *) sv + sv->length) |
437 | if (sv->key == GDS_KEY_SELFDEFTEXTMSG) |
438 | sclp_eval_selfdeftextmsg(sv); |
439 | |
440 | } |
441 | |
442 | static inline void sclp_eval_cpmsu(struct gds_vector *v) |
443 | { |
444 | void *end; |
445 | |
446 | end = (void *) v + v->length; |
447 | for (v = v + 1; (void *) v < end; v = (void *) v + v->length) |
448 | if (v->gds_id == GDS_ID_TEXTCMD) |
449 | sclp_eval_textcmd(v); |
450 | } |
451 | |
452 | |
453 | static inline void sclp_eval_mdsmu(struct gds_vector *v) |
454 | { |
455 | v = sclp_find_gds_vector(start: v + 1, end: (void *) v + v->length, GDS_ID_CPMSU); |
456 | if (v) |
457 | sclp_eval_cpmsu(v); |
458 | } |
459 | |
460 | static void sclp_tty_receiver(struct evbuf_header *evbuf) |
461 | { |
462 | struct gds_vector *v; |
463 | |
464 | v = sclp_find_gds_vector(start: evbuf + 1, end: (void *) evbuf + evbuf->length, |
465 | GDS_ID_MDSMU); |
466 | if (v) |
467 | sclp_eval_mdsmu(v); |
468 | } |
469 | |
470 | static void |
471 | sclp_tty_state_change(struct sclp_register *reg) |
472 | { |
473 | } |
474 | |
475 | static struct sclp_register sclp_input_event = |
476 | { |
477 | .receive_mask = EVTYP_OPCMD_MASK | EVTYP_PMSGCMD_MASK, |
478 | .state_change_fn = sclp_tty_state_change, |
479 | .receiver_fn = sclp_tty_receiver |
480 | }; |
481 | |
482 | static const struct tty_operations sclp_ops = { |
483 | .open = sclp_tty_open, |
484 | .close = sclp_tty_close, |
485 | .write = sclp_tty_write, |
486 | .put_char = sclp_tty_put_char, |
487 | .flush_chars = sclp_tty_flush_chars, |
488 | .write_room = sclp_tty_write_room, |
489 | .chars_in_buffer = sclp_tty_chars_in_buffer, |
490 | .flush_buffer = sclp_tty_flush_buffer, |
491 | }; |
492 | |
493 | static int __init |
494 | sclp_tty_init(void) |
495 | { |
496 | struct tty_driver *driver; |
497 | void *page; |
498 | int i; |
499 | int rc; |
500 | |
501 | /* z/VM multiplexes the line mode output on the 32xx screen */ |
502 | if (MACHINE_IS_VM && !CONSOLE_IS_SCLP) |
503 | return 0; |
504 | if (!sclp.has_linemode) |
505 | return 0; |
506 | driver = tty_alloc_driver(1, TTY_DRIVER_REAL_RAW); |
507 | if (IS_ERR(ptr: driver)) |
508 | return PTR_ERR(ptr: driver); |
509 | |
510 | rc = sclp_rw_init(); |
511 | if (rc) { |
512 | tty_driver_kref_put(driver); |
513 | return rc; |
514 | } |
515 | /* Allocate pages for output buffering */ |
516 | for (i = 0; i < MAX_KMEM_PAGES; i++) { |
517 | page = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA); |
518 | if (page == NULL) { |
519 | tty_driver_kref_put(driver); |
520 | return -ENOMEM; |
521 | } |
522 | list_add_tail(new: (struct list_head *) page, head: &sclp_tty_pages); |
523 | } |
524 | timer_setup(&sclp_tty_timer, sclp_tty_timeout, 0); |
525 | sclp_ttybuf = NULL; |
526 | sclp_tty_buffer_count = 0; |
527 | if (MACHINE_IS_VM) { |
528 | /* case input lines to lowercase */ |
529 | sclp_tty_tolower = 1; |
530 | } |
531 | sclp_tty_chars_count = 0; |
532 | |
533 | rc = sclp_register(reg: &sclp_input_event); |
534 | if (rc) { |
535 | tty_driver_kref_put(driver); |
536 | return rc; |
537 | } |
538 | |
539 | tty_port_init(port: &sclp_port); |
540 | |
541 | driver->driver_name = "sclp_line" ; |
542 | driver->name = "sclp_line" ; |
543 | driver->major = TTY_MAJOR; |
544 | driver->minor_start = 64; |
545 | driver->type = TTY_DRIVER_TYPE_SYSTEM; |
546 | driver->subtype = SYSTEM_TYPE_TTY; |
547 | driver->init_termios = tty_std_termios; |
548 | driver->init_termios.c_iflag = IGNBRK | IGNPAR; |
549 | driver->init_termios.c_oflag = ONLCR; |
550 | driver->init_termios.c_lflag = ISIG | ECHO; |
551 | tty_set_operations(driver, op: &sclp_ops); |
552 | tty_port_link_device(port: &sclp_port, driver, index: 0); |
553 | rc = tty_register_driver(driver); |
554 | if (rc) { |
555 | tty_driver_kref_put(driver); |
556 | tty_port_destroy(port: &sclp_port); |
557 | return rc; |
558 | } |
559 | sclp_tty_driver = driver; |
560 | return 0; |
561 | } |
562 | device_initcall(sclp_tty_init); |
563 | |