diff options
Diffstat (limited to 'drivers/s390/char/sclp_tty.c')
-rw-r--r-- | drivers/s390/char/sclp_tty.c | 217 |
1 files changed, 22 insertions, 195 deletions
diff --git a/drivers/s390/char/sclp_tty.c b/drivers/s390/char/sclp_tty.c index d3b1957cd2f3..bcf691af5336 100644 --- a/drivers/s390/char/sclp_tty.c +++ b/drivers/s390/char/sclp_tty.c | |||
@@ -57,19 +57,11 @@ static unsigned short int sclp_tty_chars_count; | |||
57 | 57 | ||
58 | struct tty_driver *sclp_tty_driver; | 58 | struct tty_driver *sclp_tty_driver; |
59 | 59 | ||
60 | static struct sclp_ioctls sclp_ioctls; | 60 | static int sclp_tty_tolower; |
61 | static struct sclp_ioctls sclp_ioctls_init = | 61 | static int sclp_tty_columns = 80; |
62 | { | 62 | |
63 | 8, /* 1 hor. tab. = 8 spaces */ | 63 | #define SPACES_PER_TAB 8 |
64 | 0, /* no echo of input by this driver */ | 64 | #define CASE_DELIMITER 0x6c /* to separate upper and lower case (% in EBCDIC) */ |
65 | 80, /* 80 characters/line */ | ||
66 | 1, /* write after 1/10 s without final new line */ | ||
67 | MAX_KMEM_PAGES, /* quick fix: avoid __alloc_pages */ | ||
68 | MAX_KMEM_PAGES, /* take 32/64 pages from kernel memory, */ | ||
69 | 0, /* do not convert to lower case */ | ||
70 | 0x6c /* to seprate upper and lower case */ | ||
71 | /* ('%' in EBCDIC) */ | ||
72 | }; | ||
73 | 65 | ||
74 | /* This routine is called whenever we try to open a SCLP terminal. */ | 66 | /* This routine is called whenever we try to open a SCLP terminal. */ |
75 | static int | 67 | static int |
@@ -90,136 +82,6 @@ sclp_tty_close(struct tty_struct *tty, struct file *filp) | |||
90 | sclp_tty = NULL; | 82 | sclp_tty = NULL; |
91 | } | 83 | } |
92 | 84 | ||
93 | /* execute commands to control the i/o behaviour of the SCLP tty at runtime */ | ||
94 | static int | ||
95 | sclp_tty_ioctl(struct tty_struct *tty, struct file * file, | ||
96 | unsigned int cmd, unsigned long arg) | ||
97 | { | ||
98 | unsigned long flags; | ||
99 | unsigned int obuf; | ||
100 | int check; | ||
101 | int rc; | ||
102 | |||
103 | if (tty->flags & (1 << TTY_IO_ERROR)) | ||
104 | return -EIO; | ||
105 | rc = 0; | ||
106 | check = 0; | ||
107 | switch (cmd) { | ||
108 | case TIOCSCLPSHTAB: | ||
109 | /* set width of horizontal tab */ | ||
110 | if (get_user(sclp_ioctls.htab, (unsigned short __user *) arg)) | ||
111 | rc = -EFAULT; | ||
112 | else | ||
113 | check = 1; | ||
114 | break; | ||
115 | case TIOCSCLPGHTAB: | ||
116 | /* get width of horizontal tab */ | ||
117 | if (put_user(sclp_ioctls.htab, (unsigned short __user *) arg)) | ||
118 | rc = -EFAULT; | ||
119 | break; | ||
120 | case TIOCSCLPSECHO: | ||
121 | /* enable/disable echo of input */ | ||
122 | if (get_user(sclp_ioctls.echo, (unsigned char __user *) arg)) | ||
123 | rc = -EFAULT; | ||
124 | break; | ||
125 | case TIOCSCLPGECHO: | ||
126 | /* Is echo of input enabled ? */ | ||
127 | if (put_user(sclp_ioctls.echo, (unsigned char __user *) arg)) | ||
128 | rc = -EFAULT; | ||
129 | break; | ||
130 | case TIOCSCLPSCOLS: | ||
131 | /* set number of columns for output */ | ||
132 | if (get_user(sclp_ioctls.columns, (unsigned short __user *) arg)) | ||
133 | rc = -EFAULT; | ||
134 | else | ||
135 | check = 1; | ||
136 | break; | ||
137 | case TIOCSCLPGCOLS: | ||
138 | /* get number of columns for output */ | ||
139 | if (put_user(sclp_ioctls.columns, (unsigned short __user *) arg)) | ||
140 | rc = -EFAULT; | ||
141 | break; | ||
142 | case TIOCSCLPSNL: | ||
143 | /* enable/disable writing without final new line character */ | ||
144 | if (get_user(sclp_ioctls.final_nl, (signed char __user *) arg)) | ||
145 | rc = -EFAULT; | ||
146 | break; | ||
147 | case TIOCSCLPGNL: | ||
148 | /* Is writing without final new line character enabled ? */ | ||
149 | if (put_user(sclp_ioctls.final_nl, (signed char __user *) arg)) | ||
150 | rc = -EFAULT; | ||
151 | break; | ||
152 | case TIOCSCLPSOBUF: | ||
153 | /* | ||
154 | * set the maximum buffers size for output, will be rounded | ||
155 | * up to next 4kB boundary and stored as number of SCCBs | ||
156 | * (4kB Buffers) limitation: 256 x 4kB | ||
157 | */ | ||
158 | if (get_user(obuf, (unsigned int __user *) arg) == 0) { | ||
159 | if (obuf & 0xFFF) | ||
160 | sclp_ioctls.max_sccb = (obuf >> 12) + 1; | ||
161 | else | ||
162 | sclp_ioctls.max_sccb = (obuf >> 12); | ||
163 | } else | ||
164 | rc = -EFAULT; | ||
165 | break; | ||
166 | case TIOCSCLPGOBUF: | ||
167 | /* get the maximum buffers size for output */ | ||
168 | obuf = sclp_ioctls.max_sccb << 12; | ||
169 | if (put_user(obuf, (unsigned int __user *) arg)) | ||
170 | rc = -EFAULT; | ||
171 | break; | ||
172 | case TIOCSCLPGKBUF: | ||
173 | /* get the number of buffers got from kernel at startup */ | ||
174 | if (put_user(sclp_ioctls.kmem_sccb, (unsigned short __user *) arg)) | ||
175 | rc = -EFAULT; | ||
176 | break; | ||
177 | case TIOCSCLPSCASE: | ||
178 | /* enable/disable conversion from upper to lower case */ | ||
179 | if (get_user(sclp_ioctls.tolower, (unsigned char __user *) arg)) | ||
180 | rc = -EFAULT; | ||
181 | break; | ||
182 | case TIOCSCLPGCASE: | ||
183 | /* Is conversion from upper to lower case of input enabled? */ | ||
184 | if (put_user(sclp_ioctls.tolower, (unsigned char __user *) arg)) | ||
185 | rc = -EFAULT; | ||
186 | break; | ||
187 | case TIOCSCLPSDELIM: | ||
188 | /* | ||
189 | * set special character used for separating upper and | ||
190 | * lower case, 0x00 disables this feature | ||
191 | */ | ||
192 | if (get_user(sclp_ioctls.delim, (unsigned char __user *) arg)) | ||
193 | rc = -EFAULT; | ||
194 | break; | ||
195 | case TIOCSCLPGDELIM: | ||
196 | /* | ||
197 | * get special character used for separating upper and | ||
198 | * lower case, 0x00 disables this feature | ||
199 | */ | ||
200 | if (put_user(sclp_ioctls.delim, (unsigned char __user *) arg)) | ||
201 | rc = -EFAULT; | ||
202 | break; | ||
203 | case TIOCSCLPSINIT: | ||
204 | /* set initial (default) sclp ioctls */ | ||
205 | sclp_ioctls = sclp_ioctls_init; | ||
206 | check = 1; | ||
207 | break; | ||
208 | default: | ||
209 | rc = -ENOIOCTLCMD; | ||
210 | break; | ||
211 | } | ||
212 | if (check) { | ||
213 | spin_lock_irqsave(&sclp_tty_lock, flags); | ||
214 | if (sclp_ttybuf != NULL) { | ||
215 | sclp_set_htab(sclp_ttybuf, sclp_ioctls.htab); | ||
216 | sclp_set_columns(sclp_ttybuf, sclp_ioctls.columns); | ||
217 | } | ||
218 | spin_unlock_irqrestore(&sclp_tty_lock, flags); | ||
219 | } | ||
220 | return rc; | ||
221 | } | ||
222 | |||
223 | /* | 85 | /* |
224 | * This routine returns the numbers of characters the tty driver | 86 | * This routine returns the numbers of characters the tty driver |
225 | * will accept for queuing to be written. This number is subject | 87 | * will accept for queuing to be written. This number is subject |
@@ -339,9 +201,8 @@ sclp_tty_write_string(const unsigned char *str, int count) | |||
339 | } | 201 | } |
340 | page = sclp_tty_pages.next; | 202 | page = sclp_tty_pages.next; |
341 | list_del((struct list_head *) page); | 203 | list_del((struct list_head *) page); |
342 | sclp_ttybuf = sclp_make_buffer(page, | 204 | sclp_ttybuf = sclp_make_buffer(page, sclp_tty_columns, |
343 | sclp_ioctls.columns, | 205 | SPACES_PER_TAB); |
344 | sclp_ioctls.htab); | ||
345 | } | 206 | } |
346 | /* try to write the string to the current output buffer */ | 207 | /* try to write the string to the current output buffer */ |
347 | written = sclp_write(sclp_ttybuf, str, count); | 208 | written = sclp_write(sclp_ttybuf, str, count); |
@@ -361,25 +222,13 @@ sclp_tty_write_string(const unsigned char *str, int count) | |||
361 | count -= written; | 222 | count -= written; |
362 | } while (count > 0); | 223 | } while (count > 0); |
363 | /* Setup timer to output current console buffer after 1/10 second */ | 224 | /* Setup timer to output current console buffer after 1/10 second */ |
364 | if (sclp_ioctls.final_nl) { | 225 | if (sclp_ttybuf && sclp_chars_in_buffer(sclp_ttybuf) && |
365 | if (sclp_ttybuf != NULL && | 226 | !timer_pending(&sclp_tty_timer)) { |
366 | sclp_chars_in_buffer(sclp_ttybuf) != 0 && | 227 | init_timer(&sclp_tty_timer); |
367 | !timer_pending(&sclp_tty_timer)) { | 228 | sclp_tty_timer.function = sclp_tty_timeout; |
368 | init_timer(&sclp_tty_timer); | 229 | sclp_tty_timer.data = 0UL; |
369 | sclp_tty_timer.function = sclp_tty_timeout; | 230 | sclp_tty_timer.expires = jiffies + HZ/10; |
370 | sclp_tty_timer.data = 0UL; | 231 | add_timer(&sclp_tty_timer); |
371 | sclp_tty_timer.expires = jiffies + HZ/10; | ||
372 | add_timer(&sclp_tty_timer); | ||
373 | } | ||
374 | } else { | ||
375 | if (sclp_ttybuf != NULL && | ||
376 | sclp_chars_in_buffer(sclp_ttybuf) != 0) { | ||
377 | buf = sclp_ttybuf; | ||
378 | sclp_ttybuf = NULL; | ||
379 | spin_unlock_irqrestore(&sclp_tty_lock, flags); | ||
380 | __sclp_ttybuf_emit(buf); | ||
381 | spin_lock_irqsave(&sclp_tty_lock, flags); | ||
382 | } | ||
383 | } | 232 | } |
384 | spin_unlock_irqrestore(&sclp_tty_lock, flags); | 233 | spin_unlock_irqrestore(&sclp_tty_lock, flags); |
385 | } | 234 | } |
@@ -515,9 +364,7 @@ sclp_tty_input(unsigned char* buf, unsigned int count) | |||
515 | * modifiy original string, | 364 | * modifiy original string, |
516 | * returns length of resulting string | 365 | * returns length of resulting string |
517 | */ | 366 | */ |
518 | static int | 367 | static int sclp_switch_cases(unsigned char *buf, int count) |
519 | sclp_switch_cases(unsigned char *buf, int count, | ||
520 | unsigned char delim, int tolower) | ||
521 | { | 368 | { |
522 | unsigned char *ip, *op; | 369 | unsigned char *ip, *op; |
523 | int toggle; | 370 | int toggle; |
@@ -527,9 +374,9 @@ sclp_switch_cases(unsigned char *buf, int count, | |||
527 | ip = op = buf; | 374 | ip = op = buf; |
528 | while (count-- > 0) { | 375 | while (count-- > 0) { |
529 | /* compare with special character */ | 376 | /* compare with special character */ |
530 | if (*ip == delim) { | 377 | if (*ip == CASE_DELIMITER) { |
531 | /* followed by another special character? */ | 378 | /* followed by another special character? */ |
532 | if (count && ip[1] == delim) { | 379 | if (count && ip[1] == CASE_DELIMITER) { |
533 | /* | 380 | /* |
534 | * ... then put a single copy of the special | 381 | * ... then put a single copy of the special |
535 | * character to the output string | 382 | * character to the output string |
@@ -548,7 +395,7 @@ sclp_switch_cases(unsigned char *buf, int count, | |||
548 | /* not the special character */ | 395 | /* not the special character */ |
549 | if (toggle) | 396 | if (toggle) |
550 | /* but case switching is on */ | 397 | /* but case switching is on */ |
551 | if (tolower) | 398 | if (sclp_tty_tolower) |
552 | /* switch to uppercase */ | 399 | /* switch to uppercase */ |
553 | *op++ = _ebc_toupper[(int) *ip++]; | 400 | *op++ = _ebc_toupper[(int) *ip++]; |
554 | else | 401 | else |
@@ -568,30 +415,12 @@ sclp_get_input(unsigned char *start, unsigned char *end) | |||
568 | int count; | 415 | int count; |
569 | 416 | ||
570 | count = end - start; | 417 | count = end - start; |
571 | /* | 418 | if (sclp_tty_tolower) |
572 | * if set in ioctl convert EBCDIC to lower case | ||
573 | * (modify original input in SCCB) | ||
574 | */ | ||
575 | if (sclp_ioctls.tolower) | ||
576 | EBC_TOLOWER(start, count); | 419 | EBC_TOLOWER(start, count); |
577 | 420 | count = sclp_switch_cases(start, count); | |
578 | /* | ||
579 | * if set in ioctl find out characters in lower or upper case | ||
580 | * (depends on current case) separated by a special character, | ||
581 | * works on EBCDIC | ||
582 | */ | ||
583 | if (sclp_ioctls.delim) | ||
584 | count = sclp_switch_cases(start, count, | ||
585 | sclp_ioctls.delim, | ||
586 | sclp_ioctls.tolower); | ||
587 | |||
588 | /* convert EBCDIC to ASCII (modify original input in SCCB) */ | 421 | /* convert EBCDIC to ASCII (modify original input in SCCB) */ |
589 | sclp_ebcasc_str(start, count); | 422 | sclp_ebcasc_str(start, count); |
590 | 423 | ||
591 | /* if set in ioctl write operators input to console */ | ||
592 | if (sclp_ioctls.echo) | ||
593 | sclp_tty_write(sclp_tty, start, count); | ||
594 | |||
595 | /* transfer input to high level driver */ | 424 | /* transfer input to high level driver */ |
596 | sclp_tty_input(start, count); | 425 | sclp_tty_input(start, count); |
597 | } | 426 | } |
@@ -715,7 +544,6 @@ static const struct tty_operations sclp_ops = { | |||
715 | .write_room = sclp_tty_write_room, | 544 | .write_room = sclp_tty_write_room, |
716 | .chars_in_buffer = sclp_tty_chars_in_buffer, | 545 | .chars_in_buffer = sclp_tty_chars_in_buffer, |
717 | .flush_buffer = sclp_tty_flush_buffer, | 546 | .flush_buffer = sclp_tty_flush_buffer, |
718 | .ioctl = sclp_tty_ioctl, | ||
719 | }; | 547 | }; |
720 | 548 | ||
721 | static int __init | 549 | static int __init |
@@ -758,11 +586,10 @@ sclp_tty_init(void) | |||
758 | * save 4 characters for the CPU number | 586 | * save 4 characters for the CPU number |
759 | * written at start of each line by VM/CP | 587 | * written at start of each line by VM/CP |
760 | */ | 588 | */ |
761 | sclp_ioctls_init.columns = 76; | 589 | sclp_tty_columns = 76; |
762 | /* case input lines to lowercase */ | 590 | /* case input lines to lowercase */ |
763 | sclp_ioctls_init.tolower = 1; | 591 | sclp_tty_tolower = 1; |
764 | } | 592 | } |
765 | sclp_ioctls = sclp_ioctls_init; | ||
766 | sclp_tty_chars_count = 0; | 593 | sclp_tty_chars_count = 0; |
767 | sclp_tty = NULL; | 594 | sclp_tty = NULL; |
768 | 595 | ||