diff options
| -rw-r--r-- | drivers/s390/char/sclp_con.c | 1 | ||||
| -rw-r--r-- | drivers/s390/char/sclp_tty.c | 217 | ||||
| -rw-r--r-- | drivers/s390/char/sclp_tty.h | 53 |
3 files changed, 23 insertions, 248 deletions
diff --git a/drivers/s390/char/sclp_con.c b/drivers/s390/char/sclp_con.c index 0ddf1b7c00da..7e619c534bf4 100644 --- a/drivers/s390/char/sclp_con.c +++ b/drivers/s390/char/sclp_con.c | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | #include <linux/timer.h> | 14 | #include <linux/timer.h> |
| 15 | #include <linux/jiffies.h> | 15 | #include <linux/jiffies.h> |
| 16 | #include <linux/bootmem.h> | 16 | #include <linux/bootmem.h> |
| 17 | #include <linux/termios.h> | ||
| 17 | #include <linux/err.h> | 18 | #include <linux/err.h> |
| 18 | 19 | ||
| 19 | #include "sclp.h" | 20 | #include "sclp.h" |
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 | ||
diff --git a/drivers/s390/char/sclp_tty.h b/drivers/s390/char/sclp_tty.h index 0ce2c1fc5340..4b965b22fecd 100644 --- a/drivers/s390/char/sclp_tty.h +++ b/drivers/s390/char/sclp_tty.h | |||
| @@ -11,61 +11,8 @@ | |||
| 11 | #ifndef __SCLP_TTY_H__ | 11 | #ifndef __SCLP_TTY_H__ |
| 12 | #define __SCLP_TTY_H__ | 12 | #define __SCLP_TTY_H__ |
| 13 | 13 | ||
| 14 | #include <linux/ioctl.h> | ||
| 15 | #include <linux/termios.h> | ||
| 16 | #include <linux/tty_driver.h> | 14 | #include <linux/tty_driver.h> |
| 17 | 15 | ||
| 18 | /* This is the type of data structures storing sclp ioctl setting. */ | ||
| 19 | struct sclp_ioctls { | ||
| 20 | unsigned short htab; | ||
| 21 | unsigned char echo; | ||
| 22 | unsigned short columns; | ||
| 23 | unsigned char final_nl; | ||
| 24 | unsigned short max_sccb; | ||
| 25 | unsigned short kmem_sccb; /* can't be modified at run time */ | ||
| 26 | unsigned char tolower; | ||
| 27 | unsigned char delim; | ||
| 28 | }; | ||
| 29 | |||
| 30 | /* must be unique, FIXME: must be added in Documentation/ioctl_number.txt */ | ||
| 31 | #define SCLP_IOCTL_LETTER 'B' | ||
| 32 | |||
| 33 | /* set width of horizontal tabulator */ | ||
| 34 | #define TIOCSCLPSHTAB _IOW(SCLP_IOCTL_LETTER, 0, unsigned short) | ||
| 35 | /* enable/disable echo of input (independent from line discipline) */ | ||
| 36 | #define TIOCSCLPSECHO _IOW(SCLP_IOCTL_LETTER, 1, unsigned char) | ||
| 37 | /* set number of colums for output */ | ||
| 38 | #define TIOCSCLPSCOLS _IOW(SCLP_IOCTL_LETTER, 2, unsigned short) | ||
| 39 | /* enable/disable writing without final new line character */ | ||
| 40 | #define TIOCSCLPSNL _IOW(SCLP_IOCTL_LETTER, 4, signed char) | ||
| 41 | /* set the maximum buffers size for output, rounded up to next 4kB boundary */ | ||
| 42 | #define TIOCSCLPSOBUF _IOW(SCLP_IOCTL_LETTER, 5, unsigned short) | ||
| 43 | /* set initial (default) sclp ioctls */ | ||
| 44 | #define TIOCSCLPSINIT _IO(SCLP_IOCTL_LETTER, 6) | ||
| 45 | /* enable/disable conversion from upper to lower case of input */ | ||
| 46 | #define TIOCSCLPSCASE _IOW(SCLP_IOCTL_LETTER, 7, unsigned char) | ||
| 47 | /* set special character used for separating upper and lower case, */ | ||
| 48 | /* 0x00 disables this feature */ | ||
| 49 | #define TIOCSCLPSDELIM _IOW(SCLP_IOCTL_LETTER, 9, unsigned char) | ||
| 50 | |||
| 51 | /* get width of horizontal tabulator */ | ||
| 52 | #define TIOCSCLPGHTAB _IOR(SCLP_IOCTL_LETTER, 10, unsigned short) | ||
| 53 | /* Is echo of input enabled ? (independent from line discipline) */ | ||
| 54 | #define TIOCSCLPGECHO _IOR(SCLP_IOCTL_LETTER, 11, unsigned char) | ||
| 55 | /* get number of colums for output */ | ||
| 56 | #define TIOCSCLPGCOLS _IOR(SCLP_IOCTL_LETTER, 12, unsigned short) | ||
| 57 | /* Is writing without final new line character enabled ? */ | ||
| 58 | #define TIOCSCLPGNL _IOR(SCLP_IOCTL_LETTER, 14, signed char) | ||
| 59 | /* get the maximum buffers size for output */ | ||
| 60 | #define TIOCSCLPGOBUF _IOR(SCLP_IOCTL_LETTER, 15, unsigned short) | ||
| 61 | /* Is conversion from upper to lower case of input enabled ? */ | ||
| 62 | #define TIOCSCLPGCASE _IOR(SCLP_IOCTL_LETTER, 17, unsigned char) | ||
| 63 | /* get special character used for separating upper and lower case, */ | ||
| 64 | /* 0x00 disables this feature */ | ||
| 65 | #define TIOCSCLPGDELIM _IOR(SCLP_IOCTL_LETTER, 19, unsigned char) | ||
| 66 | /* get the number of buffers/pages got from kernel at startup */ | ||
| 67 | #define TIOCSCLPGKBUF _IOR(SCLP_IOCTL_LETTER, 20, unsigned short) | ||
| 68 | |||
| 69 | extern struct tty_driver *sclp_tty_driver; | 16 | extern struct tty_driver *sclp_tty_driver; |
| 70 | 17 | ||
| 71 | #endif /* __SCLP_TTY_H__ */ | 18 | #endif /* __SCLP_TTY_H__ */ |
