patch-2.1.66 linux/drivers/char/tty_io.c
Next file: linux/drivers/char/tty_ioctl.c
Previous file: linux/drivers/char/serial.c
Back to the patch index
Back to the overall index
- Lines: 272
- Date:
Mon Nov 24 08:45:44 1997
- Orig file:
v2.1.65/linux/drivers/char/tty_io.c
- Orig date:
Sat Oct 25 02:44:15 1997
diff -u --recursive --new-file v2.1.65/linux/drivers/char/tty_io.c linux/drivers/char/tty_io.c
@@ -366,14 +366,18 @@
NULL /* hung_up_tty_fasync */
};
-void do_tty_hangup(struct tty_struct * tty, struct file_operations *fops)
+void do_tty_hangup(void *data)
{
-
+ struct tty_struct *tty = (struct tty_struct *) data;
struct file * filp;
struct task_struct *p;
+ unsigned long flags;
if (!tty)
return;
+
+ save_flags(flags); cli();
+
check_tty_count(tty, "do_tty_hangup");
for (filp = inuse_filps; filp; filp = filp->f_next) {
if (filp->private_data != tty)
@@ -387,7 +391,7 @@
if (filp->f_op != &tty_fops)
continue;
tty_fasync(filp, 0);
- filp->f_op = fops;
+ filp->f_op = &hung_up_tty_fops;
}
if (tty->ldisc.flush_buffer)
@@ -404,6 +408,8 @@
* Shutdown the current line discipline, and reset it to
* N_TTY.
*/
+ if (tty->driver.flags & TTY_DRIVER_RESET_TERMIOS)
+ *tty->termios = tty->driver.init_termios;
if (tty->ldisc.num != ldiscs[N_TTY].num) {
if (tty->ldisc.close)
(tty->ldisc.close)(tty);
@@ -435,10 +441,9 @@
tty->session = 0;
tty->pgrp = -1;
tty->ctrl_status = 0;
- if (tty->driver.flags & TTY_DRIVER_RESET_TERMIOS)
- *tty->termios = tty->driver.init_termios;
if (tty->driver.hangup)
(tty->driver.hangup)(tty);
+ restore_flags(flags);
}
void tty_hangup(struct tty_struct * tty)
@@ -446,7 +451,7 @@
#ifdef TTY_DEBUG_HANGUP
printk("%s hangup...\n", tty_name(tty));
#endif
- do_tty_hangup(tty, &hung_up_tty_fops);
+ queue_task(&tty->tq_hangup, &tq_timer);
}
void tty_vhangup(struct tty_struct * tty)
@@ -454,7 +459,7 @@
#ifdef TTY_DEBUG_HANGUP
printk("%s vhangup...\n", tty_name(tty));
#endif
- do_tty_hangup(tty, &hung_up_tty_fops);
+ do_tty_hangup((void *) tty);
}
int tty_hung_up_p(struct file * filp)
@@ -1490,15 +1495,26 @@
{
int retval, ldisc;
- retval = tty_check_change(tty);
- if (retval)
- return retval;
retval = get_user(ldisc, arg);
if (retval)
return retval;
return tty_set_ldisc(tty, ldisc);
}
+static int send_break(struct tty_struct *tty, int duration)
+{
+ current->state = TASK_INTERRUPTIBLE;
+ current->timeout = jiffies + duration;
+
+ tty->driver.break_ctl(tty, -1);
+ if (!signal_pending(current))
+ schedule();
+ tty->driver.break_ctl(tty, 0);
+ if (signal_pending(current))
+ return -EINTR;
+ return 0;
+}
+
/*
* Split this up, as gcc can choke on it otherwise..
*/
@@ -1506,6 +1522,7 @@
unsigned int cmd, unsigned long arg)
{
struct tty_struct *tty, *real_tty;
+ int retval;
tty = (struct tty_struct *)file->private_data;
if (tty_paranoia_check(tty, inode->i_rdev, "tty_ioctl"))
@@ -1516,6 +1533,46 @@
tty->driver.subtype == PTY_TYPE_MASTER)
real_tty = tty->link;
+ /*
+ * Break handling by driver
+ */
+ if (!tty->driver.break_ctl) {
+ switch(cmd) {
+ case TIOCSBRK:
+ case TIOCCBRK:
+ return tty->driver.ioctl(tty, file, cmd, arg);
+
+ /* These two ioctl's always return success; even if */
+ /* the driver doesn't support them. */
+ case TCSBRK:
+ case TCSBRKP:
+ retval = tty->driver.ioctl(tty, file, cmd, arg);
+ if (retval == -ENOIOCTLCMD)
+ retval = 0;
+ return retval;
+ }
+ }
+
+ /*
+ * Factor out some common prep work
+ */
+ switch (cmd) {
+ case TIOCSETD:
+ case TIOCSBRK:
+ case TIOCCBRK:
+ case TCSBRK:
+ case TCSBRKP:
+ retval = tty_check_change(tty);
+ if (retval)
+ return retval;
+ if (cmd != TIOCCBRK) {
+ tty_wait_until_sent(tty, 0);
+ if (signal_pending(current))
+ return -EINTR;
+ }
+ break;
+ }
+
switch (cmd) {
case TIOCSTI:
return tiocsti(tty, (char *)arg);
@@ -1556,6 +1613,28 @@
#endif
case TIOCTTYGSTRUCT:
return tiocttygstruct(tty, (struct tty_struct *) arg);
+
+ /*
+ * Break handling
+ */
+ case TIOCSBRK: /* Turn break on, unconditionally */
+ tty->driver.break_ctl(tty, -1);
+ return 0;
+
+ case TIOCCBRK: /* Turn break off, unconditionally */
+ tty->driver.break_ctl(tty, 0);
+ return 0;
+ case TCSBRK: /* SVID version: non-zero arg --> no break */
+ /*
+ * XXX is the above comment correct, or the
+ * code below correct? Is this ioctl used at
+ * all by anyone?
+ */
+ if (!arg)
+ return send_break(tty, HZ/4);
+ return 0;
+ case TCSBRKP: /* support for POSIX tcsendbreak() */
+ return send_break(tty, arg ? arg*(HZ/10) : HZ/4);
}
if (tty->driver.ioctl) {
int retval = (tty->driver.ioctl)(tty, file, cmd, arg);
@@ -1630,13 +1709,14 @@
unsigned char *cp;
char *fp;
int count;
+ unsigned long flags;
if (tty->flip.buf_num) {
cp = tty->flip.char_buf + TTY_FLIPBUF_SIZE;
fp = tty->flip.flag_buf + TTY_FLIPBUF_SIZE;
tty->flip.buf_num = 0;
- cli();
+ save_flags(flags); cli();
tty->flip.char_buf_ptr = tty->flip.char_buf;
tty->flip.flag_buf_ptr = tty->flip.flag_buf;
} else {
@@ -1644,22 +1724,57 @@
fp = tty->flip.flag_buf;
tty->flip.buf_num = 1;
- cli();
+ save_flags(flags); cli();
tty->flip.char_buf_ptr = tty->flip.char_buf + TTY_FLIPBUF_SIZE;
tty->flip.flag_buf_ptr = tty->flip.flag_buf + TTY_FLIPBUF_SIZE;
}
count = tty->flip.count;
tty->flip.count = 0;
- sti();
+ restore_flags(flags);
-#if 0
- if (count > tty->max_flip_cnt)
- tty->max_flip_cnt = count;
-#endif
tty->ldisc.receive_buf(tty, cp, fp, count);
}
/*
+ * Routine which returns the baud rate of the tty
+ */
+
+/*
+ * This is used to figure out the divisor speeds and the timeouts
+ */
+static int baud_table[] = {
+ 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
+ 9600, 19200, 38400, 57600, 115200, 230400, 460800, 0 };
+
+int tty_get_baud_rate(struct tty_struct *tty)
+{
+ unsigned int cflag, i;
+
+ cflag = tty->termios->c_cflag;
+
+ i = cflag & CBAUD;
+ if (i & CBAUDEX) {
+ i &= ~CBAUDEX;
+ if (i < 1 || i > 4)
+ tty->termios->c_cflag &= ~CBAUDEX;
+ else
+ i += 15;
+ }
+ if (i==15 && tty->alt_speed)
+ return(tty->alt_speed);
+
+ return baud_table[i];
+}
+
+void tty_flip_buffer_push(struct tty_struct *tty)
+{
+ if (tty->low_latency)
+ flush_to_ldisc((void *) tty);
+ else
+ queue_task(&tty->flip.tqueue, &tq_timer);
+}
+
+/*
* This subroutine initializes a tty structure.
*/
static void initialize_tty_struct(struct tty_struct *tty)
@@ -1673,6 +1788,8 @@
tty->flip.tqueue.routine = flush_to_ldisc;
tty->flip.tqueue.data = tty;
tty->flip.pty_sem = MUTEX;
+ tty->tq_hangup.routine = do_tty_hangup;
+ tty->tq_hangup.data = tty;
}
/*
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov