summaryrefslogtreecommitdiffstats
path: root/drivers/char/n_tty.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1997-01-07 02:33:00 +0000
committer <ralf@linux-mips.org>1997-01-07 02:33:00 +0000
commitbeb116954b9b7f3bb56412b2494b562f02b864b1 (patch)
tree120e997879884e1b9d93b265221b939d2ef1ade1 /drivers/char/n_tty.c
parent908d4681a1dc3792ecafbe64265783a86c4cccb6 (diff)
Import of Linux/MIPS 2.1.14
Diffstat (limited to 'drivers/char/n_tty.c')
-rw-r--r--drivers/char/n_tty.c107
1 files changed, 62 insertions, 45 deletions
diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c
index 28964d27e..0c0e057f8 100644
--- a/drivers/char/n_tty.c
+++ b/drivers/char/n_tty.c
@@ -34,7 +34,7 @@
#include <linux/string.h>
#include <linux/malloc.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
#include <asm/system.h>
#include <asm/bitops.h>
@@ -76,8 +76,9 @@ void n_tty_flush_buffer(struct tty_struct * tty)
if (!tty->link)
return;
- if (tty->driver.unthrottle)
- (tty->driver.unthrottle)(tty);
+ if (tty->driver.unthrottle &&
+ clear_bit(TTY_THROTTLED, &tty->flags))
+ tty->driver.unthrottle(tty);
if (tty->link->packet) {
tty->ctrl_status |= TIOCPKT_FLUSHREAD;
wake_up_interruptible(&tty->link->read_wait);
@@ -201,7 +202,7 @@ static void eraser(unsigned char c, struct tty_struct *tty)
tty->read_head = tty->canon_head;
return;
}
- if (!L_ECHOK(tty) || !L_ECHOKE(tty)) {
+ if (!L_ECHOK(tty) || !L_ECHOKE(tty) || !L_ECHOE(tty)) {
tty->read_cnt -= ((tty->read_head - tty->canon_head) &
(N_TTY_BUF_SIZE - 1));
tty->read_head = tty->canon_head;
@@ -236,7 +237,7 @@ static void eraser(unsigned char c, struct tty_struct *tty)
tty->erasing = 1;
}
echo_char(c, tty);
- } else if (!L_ECHOE(tty)) {
+ } else if (kill_type == ERASE && !L_ECHOE(tty)) {
echo_char(ERASE_CHAR(tty), tty);
} else if (c == '\t') {
unsigned int col = tty->canon_column;
@@ -255,24 +256,31 @@ static void eraser(unsigned char c, struct tty_struct *tty)
tail = (tail+1) & (N_TTY_BUF_SIZE-1);
}
+ /* should never happen */
+ if (tty->column > 0x80000000)
+ tty->column = 0;
+
/* Now backup to that column. */
while (tty->column > col) {
/* Can't use opost here. */
put_char('\b', tty);
- tty->column--;
+ if (tty->column > 0)
+ tty->column--;
}
} else {
if (iscntrl(c) && L_ECHOCTL(tty)) {
put_char('\b', tty);
put_char(' ', tty);
put_char('\b', tty);
- tty->column--;
+ if (tty->column > 0)
+ tty->column--;
}
if (!iscntrl(c) || L_ECHOCTL(tty)) {
put_char('\b', tty);
put_char(' ', tty);
put_char('\b', tty);
- tty->column--;
+ if (tty->column > 0)
+ tty->column--;
}
}
}
@@ -283,11 +291,11 @@ static void eraser(unsigned char c, struct tty_struct *tty)
finish_erasing(tty);
}
-static void isig(int sig, struct tty_struct *tty)
+static inline void isig(int sig, struct tty_struct *tty, int flush)
{
if (tty->pgrp > 0)
kill_pg(tty->pgrp, sig, 1);
- if (!L_NOFLSH(tty)) {
+ if (flush || !L_NOFLSH(tty)) {
n_tty_flush_buffer(tty);
if (tty->driver.flush_buffer)
tty->driver.flush_buffer(tty);
@@ -299,7 +307,7 @@ static inline void n_tty_receive_break(struct tty_struct *tty)
if (I_IGNBRK(tty))
return;
if (I_BRKINT(tty)) {
- isig(SIGINT, tty);
+ isig(SIGINT, tty, 1);
return;
}
if (I_PARMRK(tty)) {
@@ -333,8 +341,10 @@ static inline void n_tty_receive_parity_error(struct tty_struct *tty,
put_tty_queue('\377', tty);
put_tty_queue('\0', tty);
put_tty_queue(c, tty);
- } else
+ } else if (I_INPCK(tty))
put_tty_queue('\0', tty);
+ else
+ put_tty_queue(c, tty);
wake_up_interruptible(&tty->read_wait);
}
@@ -408,17 +418,17 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
}
}
if (L_ISIG(tty)) {
- if (c == INTR_CHAR(tty)) {
- isig(SIGINT, tty);
- return;
- }
- if (c == QUIT_CHAR(tty)) {
- isig(SIGQUIT, tty);
- return;
- }
+ int signal;
+ signal = SIGINT;
+ if (c == INTR_CHAR(tty))
+ goto send_signal;
+ signal = SIGQUIT;
+ if (c == QUIT_CHAR(tty))
+ goto send_signal;
+ signal = SIGTSTP;
if (c == SUSP_CHAR(tty)) {
- if (!is_orphaned_pgrp(tty->pgrp))
- isig(SIGTSTP, tty);
+send_signal:
+ isig(signal, tty, 0);
return;
}
}
@@ -525,10 +535,10 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
put_tty_queue(c, tty);
}
-static void n_tty_receive_buf(struct tty_struct *tty, unsigned char *cp,
+static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
char *fp, int count)
{
- unsigned char *p;
+ const unsigned char *p;
char *f, flags = 0;
int i;
@@ -611,7 +621,7 @@ static int n_tty_receive_room(struct tty_struct *tty)
int is_ignored(int sig)
{
return ((current->blocked & (1<<(sig-1))) ||
- (current->sigaction[sig-1].sa_handler == SIG_IGN));
+ (current->sig->action[sig-1].sa_handler == SIG_IGN));
}
static void n_tty_set_termios(struct tty_struct *tty, struct termios * old)
@@ -620,6 +630,11 @@ static void n_tty_set_termios(struct tty_struct *tty, struct termios * old)
return;
tty->icanon = (L_ICANON(tty) != 0);
+ if (tty->flags & (1<<TTY_HW_COOK_IN)) {
+ tty->raw = 1;
+ tty->real_raw = 1;
+ return;
+ }
if (I_ISTRIP(tty) || I_IUCLC(tty) || I_IGNCR(tty) ||
I_ICRNL(tty) || I_INLCR(tty) || L_ICANON(tty) ||
I_IXON(tty) || L_ISIG(tty) || L_ECHO(tty) ||
@@ -696,6 +711,8 @@ static int n_tty_open(struct tty_struct *tty)
}
memset(tty->read_buf, 0, N_TTY_BUF_SIZE);
tty->read_head = tty->read_tail = tty->read_cnt = 0;
+ tty->canon_head = tty->canon_data = tty->erasing = 0;
+ tty->column = 0;
memset(tty->read_flags, 0, sizeof(tty->read_flags));
n_tty_set_termios(tty, 0);
tty->minimum_to_wake = 1;
@@ -732,7 +749,7 @@ static inline void copy_from_read_buf(struct tty_struct *tty,
n = MIN(*nr, MIN(tty->read_cnt, N_TTY_BUF_SIZE - tty->read_tail));
if (!n)
return;
- memcpy_tofs(*b, &tty->read_buf[tty->read_tail], n);
+ copy_to_user(*b, &tty->read_buf[tty->read_tail], n);
tty->read_tail = (tty->read_tail + n) & (N_TTY_BUF_SIZE-1);
tty->read_cnt -= n;
*b += n;
@@ -784,7 +801,7 @@ do_it_again:
current->timeout = (unsigned long) -1;
if (time)
tty->minimum_to_wake = 1;
- else if (!tty->read_wait ||
+ else if (!waitqueue_active(&tty->read_wait) ||
(tty->minimum_to_wake > minimum))
tty->minimum_to_wake = minimum;
} else {
@@ -798,12 +815,14 @@ do_it_again:
}
add_wait_queue(&tty->read_wait, &wait);
+
+ disable_bh(TQUEUE_BH);
while (1) {
/* First test for status change. */
if (tty->packet && tty->link->ctrl_status) {
if (b != buf)
break;
- put_fs_byte(tty->link->ctrl_status, b++);
+ put_user(tty->link->ctrl_status, b++);
tty->link->ctrl_status = 0;
break;
}
@@ -817,7 +836,7 @@ do_it_again:
tty->minimum_to_wake = (minimum - (b - buf));
if (!input_available_p(tty, 0)) {
- if (tty->flags & (1 << TTY_SLAVE_CLOSED)) {
+ if (tty->flags & (1 << TTY_OTHER_CLOSED)) {
retval = -EIO;
break;
}
@@ -833,14 +852,16 @@ do_it_again:
retval = -ERESTARTSYS;
break;
}
+ enable_bh(TQUEUE_BH);
schedule();
+ disable_bh(TQUEUE_BH);
continue;
}
current->state = TASK_RUNNING;
/* Deal with packet mode. */
if (tty->packet && b == buf) {
- put_fs_byte(TIOCPKT_DATA, b++);
+ put_user(TIOCPKT_DATA, b++);
nr--;
}
@@ -848,9 +869,7 @@ do_it_again:
while (1) {
int eol;
- disable_bh(TQUEUE_BH);
if (!tty->read_cnt) {
- enable_bh(TQUEUE_BH);
break;
}
eol = clear_bit(tty->read_tail,
@@ -859,9 +878,8 @@ do_it_again:
tty->read_tail = ((tty->read_tail+1) &
(N_TTY_BUF_SIZE-1));
tty->read_cnt--;
- enable_bh(TQUEUE_BH);
if (!eol) {
- put_fs_byte(c, b++);
+ put_user(c, b++);
if (--nr)
continue;
break;
@@ -870,16 +888,14 @@ do_it_again:
tty->canon_data = 0;
}
if (c != __DISABLED_CHAR) {
- put_fs_byte(c, b++);
+ put_user(c, b++);
nr--;
}
break;
}
} else {
- disable_bh(TQUEUE_BH);
copy_from_read_buf(tty, &b, &nr);
copy_from_read_buf(tty, &b, &nr);
- enable_bh(TQUEUE_BH);
}
/* If there is enough space in the read buffer now, let the
@@ -894,9 +910,10 @@ do_it_again:
if (time)
current->timeout = time + jiffies;
}
+ enable_bh(TQUEUE_BH);
remove_wait_queue(&tty->read_wait, &wait);
- if (!tty->read_wait)
+ if (!waitqueue_active(&tty->read_wait))
tty->minimum_to_wake = minimum;
current->state = TASK_RUNNING;
@@ -908,15 +925,15 @@ do_it_again:
goto do_it_again;
if (!size && !retval)
clear_bit(TTY_PUSH, &tty->flags);
- return (size ? size : retval);
+ return (size ? size : retval);
}
static int write_chan(struct tty_struct * tty, struct file * file,
- unsigned char * buf, unsigned int nr)
+ const unsigned char * buf, unsigned int nr)
{
struct wait_queue wait = { current, NULL };
int c;
- unsigned char *b = buf;
+ const unsigned char *b = buf;
int retval = 0;
/* Job control check -- must be done at start (POSIX.1 7.1.1.4). */
@@ -937,9 +954,9 @@ static int write_chan(struct tty_struct * tty, struct file * file,
retval = -EIO;
break;
}
- if (O_OPOST(tty)) {
+ if (O_OPOST(tty) && !(tty->flags & (1<<TTY_HW_COOK_OUT))) {
while (nr > 0) {
- c = get_fs_byte(b);
+ get_user(c, b);
if (opost(c, tty) < 0)
break;
b++; nr--;
@@ -976,11 +993,11 @@ static int normal_select(struct tty_struct * tty, struct inode * inode,
case SEL_EX:
if (tty->packet && tty->link->ctrl_status)
return 1;
- if (tty->flags & (1 << TTY_SLAVE_CLOSED))
+ if (tty->flags & (1 << TTY_OTHER_CLOSED))
return 1;
if (tty_hung_up_p(file))
return 1;
- if (!tty->read_wait) {
+ if (!waitqueue_active(&tty->read_wait)) {
if (MIN_CHAR(tty) && !TIME_CHAR(tty))
tty->minimum_to_wake = MIN_CHAR(tty);
else