Commit f34d7a5b authored by Alan Cox's avatar Alan Cox Committed by Linus Torvalds

tty: The big operations rework

- Operations are now a shared const function block as with most other Linux
  objects

- Introduce wrappers for some optional functions to get consistent behaviour

- Wrap put_char which used to be patched by the tty layer

- Document which functions are needed/optional

- Make put_char report success/fail

- Cache the driver->ops pointer in the tty as tty->ops

- Remove various surplus lock calls we no longer need

- Remove proc_write method as noted by Alexey Dobriyan

- Introduce some missing sanity checks where certain driver/ldisc
  combinations would oops as they didn't check needed methods were present

[akpm@linux-foundation.org: fix fs/compat_ioctl.c build]
[akpm@linux-foundation.org: fix isicom]
[akpm@linux-foundation.org: fix arch/ia64/hp/sim/simserial.c build]
[akpm@linux-foundation.org: fix kgdb]
Signed-off-by: default avatarAlan Cox <alan@redhat.com>
Acked-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
Cc: Jason Wessel <jason.wessel@windriver.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 251b8dd7
...@@ -210,21 +210,23 @@ static void do_softint(struct work_struct *private_) ...@@ -210,21 +210,23 @@ static void do_softint(struct work_struct *private_)
printk(KERN_ERR "simserial: do_softint called\n"); printk(KERN_ERR "simserial: do_softint called\n");
} }
static void rs_put_char(struct tty_struct *tty, unsigned char ch) static int rs_put_char(struct tty_struct *tty, unsigned char ch)
{ {
struct async_struct *info = (struct async_struct *)tty->driver_data; struct async_struct *info = (struct async_struct *)tty->driver_data;
unsigned long flags; unsigned long flags;
if (!tty || !info->xmit.buf) return; if (!tty || !info->xmit.buf)
return 0;
local_irq_save(flags); local_irq_save(flags);
if (CIRC_SPACE(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE) == 0) { if (CIRC_SPACE(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE) == 0) {
local_irq_restore(flags); local_irq_restore(flags);
return; return 0;
} }
info->xmit.buf[info->xmit.head] = ch; info->xmit.buf[info->xmit.head] = ch;
info->xmit.head = (info->xmit.head + 1) & (SERIAL_XMIT_SIZE-1); info->xmit.head = (info->xmit.head + 1) & (SERIAL_XMIT_SIZE-1);
local_irq_restore(flags); local_irq_restore(flags);
return 1;
} }
static void transmit_chars(struct async_struct *info, int *intr_done) static void transmit_chars(struct async_struct *info, int *intr_done)
...@@ -621,7 +623,8 @@ static void rs_close(struct tty_struct *tty, struct file * filp) ...@@ -621,7 +623,8 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
* the line discipline to only process XON/XOFF characters. * the line discipline to only process XON/XOFF characters.
*/ */
shutdown(info); shutdown(info);
if (tty->driver->flush_buffer) tty->driver->flush_buffer(tty); if (tty->ops->flush_buffer)
tty->ops->flush_buffer(tty);
if (tty->ldisc.flush_buffer) tty->ldisc.flush_buffer(tty); if (tty->ldisc.flush_buffer) tty->ldisc.flush_buffer(tty);
info->event = 0; info->event = 0;
info->tty = NULL; info->tty = NULL;
......
...@@ -143,7 +143,7 @@ restart: ...@@ -143,7 +143,7 @@ restart:
int len; int len;
set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
len = tty->driver->write(tty, skb->data, skb->len); len = tty->ops->write(tty, skb->data, skb->len);
hdev->stat.byte_tx += len; hdev->stat.byte_tx += len;
skb_pull(skb, len); skb_pull(skb, len);
...@@ -190,8 +190,7 @@ static int hci_uart_flush(struct hci_dev *hdev) ...@@ -190,8 +190,7 @@ static int hci_uart_flush(struct hci_dev *hdev)
/* Flush any pending characters in the driver and discipline. */ /* Flush any pending characters in the driver and discipline. */
tty_ldisc_flush(tty); tty_ldisc_flush(tty);
if (tty->driver && tty->driver->flush_buffer) tty_driver_flush_buffer(tty);
tty->driver->flush_buffer(tty);
if (test_bit(HCI_UART_PROTO_SET, &hu->flags)) if (test_bit(HCI_UART_PROTO_SET, &hu->flags))
hu->proto->flush(hu); hu->proto->flush(hu);
...@@ -285,9 +284,7 @@ static int hci_uart_tty_open(struct tty_struct *tty) ...@@ -285,9 +284,7 @@ static int hci_uart_tty_open(struct tty_struct *tty)
if (tty->ldisc.flush_buffer) if (tty->ldisc.flush_buffer)
tty->ldisc.flush_buffer(tty); tty->ldisc.flush_buffer(tty);
tty_driver_flush_buffer(tty);
if (tty->driver && tty->driver->flush_buffer)
tty->driver->flush_buffer(tty);
return 0; return 0;
} }
...@@ -374,8 +371,8 @@ static void hci_uart_tty_receive(struct tty_struct *tty, const u8 *data, char *f ...@@ -374,8 +371,8 @@ static void hci_uart_tty_receive(struct tty_struct *tty, const u8 *data, char *f
spin_unlock(&hu->rx_lock); spin_unlock(&hu->rx_lock);
if (test_and_clear_bit(TTY_THROTTLED, &tty->flags) && if (test_and_clear_bit(TTY_THROTTLED, &tty->flags) &&
tty->driver->unthrottle) tty->ops->unthrottle)
tty->driver->unthrottle(tty); tty->ops->unthrottle(tty);
} }
static int hci_uart_register_dev(struct hci_uart *hu) static int hci_uart_register_dev(struct hci_uart *hu)
......
...@@ -169,7 +169,7 @@ static int Fip_firmware_size; ...@@ -169,7 +169,7 @@ static int Fip_firmware_size;
static int ip2_open(PTTY, struct file *); static int ip2_open(PTTY, struct file *);
static void ip2_close(PTTY, struct file *); static void ip2_close(PTTY, struct file *);
static int ip2_write(PTTY, const unsigned char *, int); static int ip2_write(PTTY, const unsigned char *, int);
static void ip2_putchar(PTTY, unsigned char); static int ip2_putchar(PTTY, unsigned char);
static void ip2_flush_chars(PTTY); static void ip2_flush_chars(PTTY);
static int ip2_write_room(PTTY); static int ip2_write_room(PTTY);
static int ip2_chars_in_buf(PTTY); static int ip2_chars_in_buf(PTTY);
...@@ -1616,10 +1616,9 @@ ip2_close( PTTY tty, struct file *pFile ) ...@@ -1616,10 +1616,9 @@ ip2_close( PTTY tty, struct file *pFile )
serviceOutgoingFifo ( pCh->pMyBord ); serviceOutgoingFifo ( pCh->pMyBord );
if ( tty->driver->flush_buffer ) if ( tty->driver->ops->flush_buffer )
tty->driver->flush_buffer(tty); tty->driver->ops->flush_buffer(tty);
if ( tty->ldisc.flush_buffer ) tty_ldisc_flush(tty);
tty->ldisc.flush_buffer(tty);
tty->closing = 0; tty->closing = 0;
pCh->pTTY = NULL; pCh->pTTY = NULL;
...@@ -1738,7 +1737,7 @@ ip2_write( PTTY tty, const unsigned char *pData, int count) ...@@ -1738,7 +1737,7 @@ ip2_write( PTTY tty, const unsigned char *pData, int count)
/* */ /* */
/* */ /* */
/******************************************************************************/ /******************************************************************************/
static void static int
ip2_putchar( PTTY tty, unsigned char ch ) ip2_putchar( PTTY tty, unsigned char ch )
{ {
i2ChanStrPtr pCh = tty->driver_data; i2ChanStrPtr pCh = tty->driver_data;
...@@ -1753,6 +1752,7 @@ ip2_putchar( PTTY tty, unsigned char ch ) ...@@ -1753,6 +1752,7 @@ ip2_putchar( PTTY tty, unsigned char ch )
ip2_flush_chars( tty ); ip2_flush_chars( tty );
} else } else
write_unlock_irqrestore(&pCh->Pbuf_spinlock, flags); write_unlock_irqrestore(&pCh->Pbuf_spinlock, flags);
return 1;
// ip2trace (CHANN, ITRC_PUTC, ITRC_RETURN, 1, ch ); // ip2trace (CHANN, ITRC_PUTC, ITRC_RETURN, 1, ch );
} }
......
...@@ -1140,28 +1140,29 @@ static int isicom_write(struct tty_struct *tty, const unsigned char *buf, ...@@ -1140,28 +1140,29 @@ static int isicom_write(struct tty_struct *tty, const unsigned char *buf,
} }
/* put_char et all */ /* put_char et all */
static void isicom_put_char(struct tty_struct *tty, unsigned char ch) static int isicom_put_char(struct tty_struct *tty, unsigned char ch)
{ {
struct isi_port *port = tty->driver_data; struct isi_port *port = tty->driver_data;
struct isi_board *card = port->card; struct isi_board *card = port->card;
unsigned long flags; unsigned long flags;
if (isicom_paranoia_check(port, tty->name, "isicom_put_char")) if (isicom_paranoia_check(port, tty->name, "isicom_put_char"))
return; return 0;
if (!port->xmit_buf) if (!port->xmit_buf)
return; return 0;
spin_lock_irqsave(&card->card_lock, flags); spin_lock_irqsave(&card->card_lock, flags);
if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1) if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1) {
goto out; spin_unlock_irqrestore(&card->card_lock, flags);
return 0;
}
port->xmit_buf[port->xmit_head++] = ch; port->xmit_buf[port->xmit_head++] = ch;
port->xmit_head &= (SERIAL_XMIT_SIZE - 1); port->xmit_head &= (SERIAL_XMIT_SIZE - 1);
port->xmit_cnt++; port->xmit_cnt++;
spin_unlock_irqrestore(&card->card_lock, flags); spin_unlock_irqrestore(&card->card_lock, flags);
out: return 1;
return;
} }
/* flush_chars et all */ /* flush_chars et all */
......
...@@ -1230,7 +1230,7 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw) ...@@ -1230,7 +1230,7 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw)
if (rep && if (rep &&
(!vc_kbd_mode(kbd, VC_REPEAT) || (!vc_kbd_mode(kbd, VC_REPEAT) ||
(tty && !L_ECHO(tty) && tty->driver->chars_in_buffer(tty)))) { (tty && !L_ECHO(tty) && tty_chars_in_buffer(tty)))) {
/* /*
* Don't repeat a key if the input buffers are not empty and the * Don't repeat a key if the input buffers are not empty and the
* characters get aren't echoed locally. This makes key repeat * characters get aren't echoed locally. This makes key repeat
......
...@@ -342,12 +342,10 @@ static int n_hdlc_tty_open (struct tty_struct *tty) ...@@ -342,12 +342,10 @@ static int n_hdlc_tty_open (struct tty_struct *tty)
#endif #endif
/* Flush any pending characters in the driver and discipline. */ /* Flush any pending characters in the driver and discipline. */
if (tty->ldisc.flush_buffer) if (tty->ldisc.flush_buffer)
tty->ldisc.flush_buffer (tty); tty->ldisc.flush_buffer(tty);
if (tty->driver->flush_buffer) tty_driver_flush_buffer(tty);
tty->driver->flush_buffer (tty);
if (debuglevel >= DEBUG_LEVEL_INFO) if (debuglevel >= DEBUG_LEVEL_INFO)
printk("%s(%d)n_hdlc_tty_open() success\n",__FILE__,__LINE__); printk("%s(%d)n_hdlc_tty_open() success\n",__FILE__,__LINE__);
...@@ -399,7 +397,7 @@ static void n_hdlc_send_frames(struct n_hdlc *n_hdlc, struct tty_struct *tty) ...@@ -399,7 +397,7 @@ static void n_hdlc_send_frames(struct n_hdlc *n_hdlc, struct tty_struct *tty)
/* Send the next block of data to device */ /* Send the next block of data to device */
tty->flags |= (1 << TTY_DO_WRITE_WAKEUP); tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
actual = tty->driver->write(tty, tbuf->buf, tbuf->count); actual = tty->ops->write(tty, tbuf->buf, tbuf->count);
/* rollback was possible and has been done */ /* rollback was possible and has been done */
if (actual == -ERESTARTSYS) { if (actual == -ERESTARTSYS) {
...@@ -752,8 +750,7 @@ static int n_hdlc_tty_ioctl(struct tty_struct *tty, struct file *file, ...@@ -752,8 +750,7 @@ static int n_hdlc_tty_ioctl(struct tty_struct *tty, struct file *file,
case TIOCOUTQ: case TIOCOUTQ:
/* get the pending tx byte count in the driver */ /* get the pending tx byte count in the driver */
count = tty->driver->chars_in_buffer ? count = tty_chars_in_buffer(tty);
tty->driver->chars_in_buffer(tty) : 0;
/* add size of next output frame in queue */ /* add size of next output frame in queue */
spin_lock_irqsave(&n_hdlc->tx_buf_list.spinlock,flags); spin_lock_irqsave(&n_hdlc->tx_buf_list.spinlock,flags);
if (n_hdlc->tx_buf_list.head) if (n_hdlc->tx_buf_list.head)
......
...@@ -376,8 +376,9 @@ static void put_char(struct r3964_info *pInfo, unsigned char ch) ...@@ -376,8 +376,9 @@ static void put_char(struct r3964_info *pInfo, unsigned char ch)
if (tty == NULL) if (tty == NULL)
return; return;
if (tty->driver->put_char) { /* FIXME: put_char should not be called from an IRQ */
tty->driver->put_char(tty, ch); if (tty->ops->put_char) {
tty->ops->put_char(tty, ch);
} }
pInfo->bcc ^= ch; pInfo->bcc ^= ch;
} }
...@@ -386,12 +387,9 @@ static void flush(struct r3964_info *pInfo) ...@@ -386,12 +387,9 @@ static void flush(struct r3964_info *pInfo)
{ {
struct tty_struct *tty = pInfo->tty; struct tty_struct *tty = pInfo->tty;
if (tty == NULL) if (tty == NULL || tty->ops->flush_chars == NULL)
return; return;
tty->ops->flush_chars(tty);
if (tty->driver->flush_chars) {
tty->driver->flush_chars(tty);
}
} }
static void trigger_transmit(struct r3964_info *pInfo) static void trigger_transmit(struct r3964_info *pInfo)
...@@ -449,12 +447,11 @@ static void transmit_block(struct r3964_info *pInfo) ...@@ -449,12 +447,11 @@ static void transmit_block(struct r3964_info *pInfo)
struct r3964_block_header *pBlock = pInfo->tx_first; struct r3964_block_header *pBlock = pInfo->tx_first;
int room = 0; int room = 0;
if ((tty == NULL) || (pBlock == NULL)) { if (tty == NULL || pBlock == NULL) {
return; return;
} }
if (tty->driver->write_room) room = tty_write_room(tty);
room = tty->driver->write_room(tty);
TRACE_PS("transmit_block %p, room %d, length %d", TRACE_PS("transmit_block %p, room %d, length %d",
pBlock, room, pBlock->length); pBlock, room, pBlock->length);
......
...@@ -149,8 +149,8 @@ static void check_unthrottle(struct tty_struct *tty) ...@@ -149,8 +149,8 @@ static void check_unthrottle(struct tty_struct *tty)
{ {
if (tty->count && if (tty->count &&
test_and_clear_bit(TTY_THROTTLED, &tty->flags) && test_and_clear_bit(TTY_THROTTLED, &tty->flags) &&
tty->driver->unthrottle) tty->ops->unthrottle)
tty->driver->unthrottle(tty); tty->ops->unthrottle(tty);
} }
/** /**
...@@ -273,7 +273,7 @@ static int opost(unsigned char c, struct tty_struct *tty) ...@@ -273,7 +273,7 @@ static int opost(unsigned char c, struct tty_struct *tty)
{ {
int space, spaces; int space, spaces;
space = tty->driver->write_room(tty); space = tty_write_room(tty);
if (!space) if (!space)
return -1; return -1;
...@@ -286,7 +286,7 @@ static int opost(unsigned char c, struct tty_struct *tty) ...@@ -286,7 +286,7 @@ static int opost(unsigned char c, struct tty_struct *tty)
if (O_ONLCR(tty)) { if (O_ONLCR(tty)) {
if (space < 2) if (space < 2)
return -1; return -1;
tty->driver->put_char(tty, '\r'); tty_put_char(tty, '\r');
tty->column = 0; tty->column = 0;
} }
tty->canon_column = tty->column; tty->canon_column = tty->column;
...@@ -308,7 +308,7 @@ static int opost(unsigned char c, struct tty_struct *tty) ...@@ -308,7 +308,7 @@ static int opost(unsigned char c, struct tty_struct *tty)
if (space < spaces) if (space < spaces)
return -1; return -1;
tty->column += spaces; tty->column += spaces;
tty->driver->write(tty, " ", spaces); tty->ops->write(tty, " ", spaces);
return 0; return 0;
} }
tty->column += spaces; tty->column += spaces;
...@@ -325,7 +325,7 @@ static int opost(unsigned char c, struct tty_struct *tty) ...@@ -325,7 +325,7 @@ static int opost(unsigned char c, struct tty_struct *tty)
break; break;
} }
} }
tty->driver->put_char(tty, c); tty_put_char(tty, c);
unlock_kernel(); unlock_kernel();
return 0; return 0;
} }
...@@ -352,7 +352,7 @@ static ssize_t opost_block(struct tty_struct *tty, ...@@ -352,7 +352,7 @@ static ssize_t opost_block(struct tty_struct *tty,
int i; int i;
const unsigned char *cp; const unsigned char *cp;
space = tty->driver->write_room(tty); space = tty_write_room(tty);
if (!space) if (!space)
return 0; return 0;
if (nr > space) if (nr > space)
...@@ -390,27 +390,14 @@ static ssize_t opost_block(struct tty_struct *tty, ...@@ -390,27 +390,14 @@ static ssize_t opost_block(struct tty_struct *tty,
} }
} }
break_out: break_out:
if (tty->driver->flush_chars) if (tty->ops->flush_chars)
tty->driver->flush_chars(tty); tty->ops->flush_chars(tty);
i = tty->driver->write(tty, buf, i); i = tty->ops->write(tty, buf, i);
unlock_kernel(); unlock_kernel();
return i; return i;
} }
/**
* put_char - write character to driver
* @c: character (or part of unicode symbol)
* @tty: terminal device
*
* Queue a byte to the driver layer for output
*/
static inline void put_char(unsigned char c, struct tty_struct *tty)
{
tty->driver->put_char(tty, c);
}
/** /**
* echo_char - echo characters * echo_char - echo characters
* @c: unicode byte to echo * @c: unicode byte to echo
...@@ -423,8 +410,8 @@ static inline void put_char(unsigned char c, struct tty_struct *tty) ...@@ -423,8 +410,8 @@ static inline void put_char(unsigned char c, struct tty_struct *tty)
static void echo_char(unsigned char c, struct tty_struct *tty) static void echo_char(unsigned char c, struct tty_struct *tty)
{ {
if (L_ECHOCTL(tty) && iscntrl(c) && c != '\t') { if (L_ECHOCTL(tty) && iscntrl(c) && c != '\t') {
put_char('^', tty); tty_put_char(tty, '^');
put_char(c ^ 0100, tty); tty_put_char(tty, c ^ 0100);
tty->column += 2; tty->column += 2;
} else } else
opost(c, tty); opost(c, tty);
...@@ -433,7 +420,7 @@ static void echo_char(unsigned char c, struct tty_struct *tty) ...@@ -433,7 +420,7 @@ static void echo_char(unsigned char c, struct tty_struct *tty)
static inline void finish_erasing(struct tty_struct *tty) static inline void finish_erasing(struct tty_struct *tty)
{ {
if (tty->erasing) { if (tty->erasing) {
put_char('/', tty); tty_put_char(tty, '/');
tty->column++; tty->column++;
tty->erasing = 0; tty->erasing = 0;
} }
...@@ -517,7 +504,7 @@ static void eraser(unsigned char c, struct tty_struct *tty) ...@@ -517,7 +504,7 @@ static void eraser(unsigned char c, struct tty_struct *tty)
if (L_ECHO(tty)) { if (L_ECHO(tty)) {
if (L_ECHOPRT(tty)) { if (L_ECHOPRT(tty)) {
if (!tty->erasing) { if (!tty->erasing) {
put_char('\\', tty); tty_put_char(tty, '\\');
tty->column++; tty->column++;
tty->erasing = 1; tty->erasing = 1;
} }
...@@ -525,7 +512,7 @@ static void eraser(unsigned char c, struct tty_struct *tty) ...@@ -525,7 +512,7 @@ static void eraser(unsigned char c, struct tty_struct *tty)
echo_char(c, tty); echo_char(c, tty);
while (--cnt > 0) { while (--cnt > 0) {
head = (head+1) & (N_TTY_BUF_SIZE-1); head = (head+1) & (N_TTY_BUF_SIZE-1);
put_char(tty->read_buf[head], tty); tty_put_char(tty, tty->read_buf[head]);
} }
} else if (kill_type == ERASE && !L_ECHOE(tty)) { } else if (kill_type == ERASE && !L_ECHOE(tty)) {
echo_char(ERASE_CHAR(tty), tty); echo_char(ERASE_CHAR(tty), tty);
...@@ -553,22 +540,22 @@ static void eraser(unsigned char c, struct tty_struct *tty) ...@@ -553,22 +540,22 @@ static void eraser(unsigned char c, struct tty_struct *tty)
/* Now backup to that column. */ /* Now backup to that column. */
while (tty->column > col) { while (tty->column > col) {
/* Can't use opost here. */ /* Can't use opost here. */
put_char('\b', tty); tty_put_char(tty, '\b');
if (tty->column > 0) if (tty->column > 0)
tty->column--; tty->column--;
} }
} else { } else {
if (iscntrl(c) && L_ECHOCTL(tty)) { if (iscntrl(c) && L_ECHOCTL(tty)) {
put_char('\b', tty); tty_put_char(tty, '\b');
put_char(' ', tty); tty_put_char(tty, ' ');
put_char('\b', tty); tty_put_char(tty, '\b');
if (tty->column > 0) if (tty->column > 0)
tty->column--; tty->column--;
} }
if (!iscntrl(c) || L_ECHOCTL(tty)) { if (!iscntrl(c) || L_ECHOCTL(tty)) {
put_char('\b', tty); tty_put_char(tty, '\b');
put_char(' ', tty); tty_put_char(tty, ' ');
put_char('\b', tty); tty_put_char(tty, '\b');
if (tty->column > 0) if (tty->column > 0)
tty->column--; tty->column--;
} }
...@@ -599,8 +586,7 @@ static inline void isig(int sig, struct tty_struct *tty, int flush) ...@@ -599,8 +586,7 @@ static inline void isig(int sig, struct tty_struct *tty, int flush)
kill_pgrp(tty->pgrp, sig, 1); kill_pgrp(tty->pgrp, sig, 1);
if (flush || !L_NOFLSH(tty)) { if (flush || !L_NOFLSH(tty)) {
n_tty_flush_buffer(tty); n_tty_flush_buffer(tty);
if (tty->driver->flush_buffer) tty_driver_flush_buffer(tty);
tty->driver->flush_buffer(tty);
} }
} }
...@@ -732,7 +718,7 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c) ...@@ -732,7 +718,7 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
tty->lnext = 0; tty->lnext = 0;
if (L_ECHO(tty)) { if (L_ECHO(tty)) {
if (tty->read_cnt >= N_TTY_BUF_SIZE-1) { if (tty->read_cnt >= N_TTY_BUF_SIZE-1) {
put_char('\a', tty); /* beep if no space */ tty_put_char(tty, '\a'); /* beep if no space */
return; return;
} }
/* Record the column of first canon char. */ /* Record the column of first canon char. */
...@@ -776,8 +762,7 @@ send_signal: ...@@ -776,8 +762,7 @@ send_signal:
*/ */
if (!L_NOFLSH(tty)) { if (!L_NOFLSH(tty)) {
n_tty_flush_buffer(tty); n_tty_flush_buffer(tty);
if (tty->driver->flush_buffer) tty_driver_flush_buffer(tty);
tty->driver->flush_buffer(tty);
} }
if (L_ECHO(tty)) if (L_ECHO(tty))
echo_char(c, tty); echo_char(c, tty);
...@@ -806,8 +791,8 @@ send_signal: ...@@ -806,8 +791,8 @@ send_signal:
if (L_ECHO(tty)) { if (L_ECHO(tty)) {
finish_erasing(tty); finish_erasing(tty);
if (L_ECHOCTL(tty)) { if (L_ECHOCTL(tty)) {
put_char('^', tty); tty_put_char(tty, '^');
put_char('\b', tty); tty_put_char(tty, '\b');
} }
} }
return; return;
...@@ -828,7 +813,7 @@ send_signal: ...@@ -828,7 +813,7 @@ send_signal:
if (c == '\n') { if (c == '\n') {
if (L_ECHO(tty) || L_ECHONL(tty)) {