aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/char/sclp_tty.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/char/sclp_tty.c')
-rw-r--r--drivers/s390/char/sclp_tty.c217
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
58struct tty_driver *sclp_tty_driver; 58struct tty_driver *sclp_tty_driver;
59 59
60static struct sclp_ioctls sclp_ioctls; 60static int sclp_tty_tolower;
61static struct sclp_ioctls sclp_ioctls_init = 61static 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. */
75static int 67static 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 */
94static int
95sclp_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 */
518static int 367static int sclp_switch_cases(unsigned char *buf, int count)
519sclp_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
721static int __init 549static 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