mirror of
https://github.com/adulau/aha.git
synced 2024-12-27 19:26:25 +00:00
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: Alan Cox <alan@redhat.com> Acked-by: Greg Kroah-Hartman <gregkh@suse.de> Cc: Jason Wessel <jason.wessel@windriver.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
251b8dd7ee
commit
f34d7a5b70
30 changed files with 539 additions and 666 deletions
|
@ -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)
|
||||||
* 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:
|
||||||
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)
|
||||||
|
|
||||||
/* 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)
|
||||||
|
|
||||||
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
|
||||||
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;
|
||||||
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 )
|
||||||
|
|
||||||
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)
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
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 )
|
||||||
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,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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)
|
||||||
|
|
||||||
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)
|
||||||
#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)
|
||||||
|
|
||||||
/* 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,
|
||||||
|
|
||||||
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)
|
||||||
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)
|
||||||
{
|
{
|
||||||
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)
|
||||||
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)
|
||||||
{
|
{
|
||||||
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)
|
||||||
{
|
{
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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,
|
||||||
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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
/* 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)
|
||||||
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)
|
||||||
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:
|
||||||
*/
|
*/
|
||||||
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:
|
||||||
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:
|
||||||
if (c == '\n') {
|
if (c == '\n') {
|
||||||
if (L_ECHO(tty) || L_ECHONL(tty)) {
|
if (L_ECHO(tty) || L_ECHONL(tty)) {
|
||||||
if (tty->read_cnt >= N_TTY_BUF_SIZE-1)
|
if (tty->read_cnt >= N_TTY_BUF_SIZE-1)
|
||||||
put_char('\a', tty);
|
tty_put_char(tty, '\a');
|
||||||
opost('\n', tty);
|
opost('\n', tty);
|
||||||
}
|
}
|
||||||
goto handle_newline;
|
goto handle_newline;
|
||||||
|
@ -846,7 +831,7 @@ send_signal:
|
||||||
*/
|
*/
|
||||||
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);
|
tty_put_char(tty, '\a');
|
||||||
/* Record the column of first canon char. */
|
/* Record the column of first canon char. */
|
||||||
if (tty->canon_head == tty->read_head)
|
if (tty->canon_head == tty->read_head)
|
||||||
tty->canon_column = tty->column;
|
tty->canon_column = tty->column;
|
||||||
|
@ -876,7 +861,7 @@ handle_newline:
|
||||||
finish_erasing(tty);
|
finish_erasing(tty);
|
||||||
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;
|
||||||
}
|
}
|
||||||
if (c == '\n')
|
if (c == '\n')
|
||||||
|
@ -980,8 +965,8 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (tty->driver->flush_chars)
|
if (tty->ops->flush_chars)
|
||||||
tty->driver->flush_chars(tty);
|
tty->ops->flush_chars(tty);
|
||||||
}
|
}
|
||||||
|
|
||||||
n_tty_set_room(tty);
|
n_tty_set_room(tty);
|
||||||
|
@ -1000,8 +985,8 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
|
||||||
if (tty->receive_room < TTY_THRESHOLD_THROTTLE) {
|
if (tty->receive_room < TTY_THRESHOLD_THROTTLE) {
|
||||||
/* check TTY_THROTTLED first so it indicates our state */
|
/* check TTY_THROTTLED first so it indicates our state */
|
||||||
if (!test_and_set_bit(TTY_THROTTLED, &tty->flags) &&
|
if (!test_and_set_bit(TTY_THROTTLED, &tty->flags) &&
|
||||||
tty->driver->throttle)
|
tty->ops->throttle)
|
||||||
tty->driver->throttle(tty);
|
tty->ops->throttle(tty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1086,6 +1071,9 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old)
|
||||||
tty->real_raw = 0;
|
tty->real_raw = 0;
|
||||||
}
|
}
|
||||||
n_tty_set_room(tty);
|
n_tty_set_room(tty);
|
||||||
|
/* The termios change make the tty ready for I/O */
|
||||||
|
wake_up_interruptible(&tty->write_wait);
|
||||||
|
wake_up_interruptible(&tty->read_wait);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1513,11 +1501,11 @@ static ssize_t write_chan(struct tty_struct *tty, struct file *file,
|
||||||
break;
|
break;
|
||||||
b++; nr--;
|
b++; nr--;
|
||||||
}
|
}
|
||||||
if (tty->driver->flush_chars)
|
if (tty->ops->flush_chars)
|
||||||
tty->driver->flush_chars(tty);
|
tty->ops->flush_chars(tty);
|
||||||
} else {
|
} else {
|
||||||
while (nr > 0) {
|
while (nr > 0) {
|
||||||
c = tty->driver->write(tty, b, nr);
|
c = tty->ops->write(tty, b, nr);
|
||||||
if (c < 0) {
|
if (c < 0) {
|
||||||
retval = c;
|
retval = c;
|
||||||
goto break_out;
|
goto break_out;
|
||||||
|
@ -1554,11 +1542,6 @@ break_out:
|
||||||
*
|
*
|
||||||
* This code must be sure never to sleep through a hangup.
|
* This code must be sure never to sleep through a hangup.
|
||||||
* Called without the kernel lock held - fine
|
* Called without the kernel lock held - fine
|
||||||
*
|
|
||||||
* FIXME: if someone changes the VMIN or discipline settings for the
|
|
||||||
* terminal while another process is in poll() the poll does not
|
|
||||||
* recompute the new limits. Possibly set_termios should issue
|
|
||||||
* a read wakeup to fix this bug.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static unsigned int normal_poll(struct tty_struct *tty, struct file *file,
|
static unsigned int normal_poll(struct tty_struct *tty, struct file *file,
|
||||||
|
@ -1582,9 +1565,9 @@ static unsigned int normal_poll(struct tty_struct *tty, struct file *file,
|
||||||
else
|
else
|
||||||
tty->minimum_to_wake = 1;
|
tty->minimum_to_wake = 1;
|
||||||
}
|
}
|
||||||
if (!tty_is_writelocked(tty) &&
|
if (tty->ops->write && !tty_is_writelocked(tty) &&
|
||||||
tty->driver->chars_in_buffer(tty) < WAKEUP_CHARS &&
|
tty_chars_in_buffer(tty) < WAKEUP_CHARS &&
|
||||||
tty->driver->write_room(tty) > 0)
|
tty_write_room(tty) > 0)
|
||||||
mask |= POLLOUT | POLLWRNORM;
|
mask |= POLLOUT | POLLWRNORM;
|
||||||
return mask;
|
return mask;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1108,8 +1108,8 @@ restart:
|
||||||
a reference to the old ldisc. If we ended up flipping back
|
a reference to the old ldisc. If we ended up flipping back
|
||||||
to the existing ldisc we have two references to it */
|
to the existing ldisc we have two references to it */
|
||||||
|
|
||||||
if (tty->ldisc.num != o_ldisc.num && tty->driver->set_ldisc)
|
if (tty->ldisc.num != o_ldisc.num && tty->ops->set_ldisc)
|
||||||
tty->driver->set_ldisc(tty);
|
tty->ops->set_ldisc(tty);
|
||||||
|
|
||||||
tty_ldisc_put(o_ldisc.num);
|
tty_ldisc_put(o_ldisc.num);
|
||||||
|
|
||||||
|
@ -1181,9 +1181,8 @@ struct tty_driver *tty_find_polling_driver(char *name, int *line)
|
||||||
if (*str == '\0')
|
if (*str == '\0')
|
||||||
str = NULL;
|
str = NULL;
|
||||||
|
|
||||||
if (tty_line >= 0 && tty_line <= p->num && p->poll_init &&
|
if (tty_line >= 0 && tty_line <= p->num && p->ops &&
|
||||||
!p->poll_init(p, tty_line, str)) {
|
p->ops->poll_init && !p->ops->poll_init(p, tty_line, str)) {
|
||||||
|
|
||||||
res = p;
|
res = p;
|
||||||
*line = tty_line;
|
*line = tty_line;
|
||||||
break;
|
break;
|
||||||
|
@ -1452,8 +1451,7 @@ static void do_tty_hangup(struct work_struct *work)
|
||||||
/* We may have no line discipline at this point */
|
/* We may have no line discipline at this point */
|
||||||
if (ld->flush_buffer)
|
if (ld->flush_buffer)
|
||||||
ld->flush_buffer(tty);
|
ld->flush_buffer(tty);
|
||||||
if (tty->driver->flush_buffer)
|
tty_driver_flush_buffer(tty);
|
||||||
tty->driver->flush_buffer(tty);
|
|
||||||
if ((test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags)) &&
|
if ((test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags)) &&
|
||||||
ld->write_wakeup)
|
ld->write_wakeup)
|
||||||
ld->write_wakeup(tty);
|
ld->write_wakeup(tty);
|
||||||
|
@ -1516,11 +1514,11 @@ static void do_tty_hangup(struct work_struct *work)
|
||||||
* So we just call close() the right number of times.
|
* So we just call close() the right number of times.
|
||||||
*/
|
*/
|
||||||
if (cons_filp) {
|
if (cons_filp) {
|
||||||
if (tty->driver->close)
|
if (tty->ops->close)
|
||||||
for (n = 0; n < closecount; n++)
|
for (n = 0; n < closecount; n++)
|
||||||
tty->driver->close(tty, cons_filp);
|
tty->ops->close(tty, cons_filp);
|
||||||
} else if (tty->driver->hangup)
|
} else if (tty->ops->hangup)
|
||||||
(tty->driver->hangup)(tty);
|
(tty->ops->hangup)(tty);
|
||||||
/*
|
/*
|
||||||
* We don't want to have driver/ldisc interactions beyond
|
* We don't want to have driver/ldisc interactions beyond
|
||||||
* the ones we did here. The driver layer expects no
|
* the ones we did here. The driver layer expects no
|
||||||
|
@ -1752,8 +1750,8 @@ void stop_tty(struct tty_struct *tty)
|
||||||
wake_up_interruptible(&tty->link->read_wait);
|
wake_up_interruptible(&tty->link->read_wait);
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&tty->ctrl_lock, flags);
|
spin_unlock_irqrestore(&tty->ctrl_lock, flags);
|
||||||
if (tty->driver->stop)
|
if (tty->ops->stop)
|
||||||
(tty->driver->stop)(tty);
|
(tty->ops->stop)(tty);
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_SYMBOL(stop_tty);
|
EXPORT_SYMBOL(stop_tty);
|
||||||
|
@ -1786,8 +1784,8 @@ void start_tty(struct tty_struct *tty)
|
||||||
wake_up_interruptible(&tty->link->read_wait);
|
wake_up_interruptible(&tty->link->read_wait);
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&tty->ctrl_lock, flags);
|
spin_unlock_irqrestore(&tty->ctrl_lock, flags);
|
||||||
if (tty->driver->start)
|
if (tty->ops->start)
|
||||||
(tty->driver->start)(tty);
|
(tty->ops->start)(tty);
|
||||||
/* If we have a running line discipline it may need kicking */
|
/* If we have a running line discipline it may need kicking */
|
||||||
tty_wakeup(tty);
|
tty_wakeup(tty);
|
||||||
}
|
}
|
||||||
|
@ -1972,10 +1970,13 @@ static ssize_t tty_write(struct file *file, const char __user *buf,
|
||||||
tty = (struct tty_struct *)file->private_data;
|
tty = (struct tty_struct *)file->private_data;
|
||||||
if (tty_paranoia_check(tty, inode, "tty_write"))
|
if (tty_paranoia_check(tty, inode, "tty_write"))
|
||||||
return -EIO;
|
return -EIO;
|
||||||
if (!tty || !tty->driver->write ||
|
if (!tty || !tty->ops->write ||
|
||||||
(test_bit(TTY_IO_ERROR, &tty->flags)))
|
(test_bit(TTY_IO_ERROR, &tty->flags)))
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
/* Short term debug to catch buggy drivers */
|
||||||
|
if (tty->ops->write_room == NULL)
|
||||||
|
printk(KERN_ERR "tty driver %s lacks a write_room method.\n",
|
||||||
|
tty->driver->name);
|
||||||
ld = tty_ldisc_ref_wait(tty);
|
ld = tty_ldisc_ref_wait(tty);
|
||||||
if (!ld->write)
|
if (!ld->write)
|
||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
|
@ -2122,6 +2123,7 @@ static int init_dev(struct tty_driver *driver, int idx,
|
||||||
goto fail_no_mem;
|
goto fail_no_mem;
|
||||||
initialize_tty_struct(tty);
|
initialize_tty_struct(tty);
|
||||||
tty->driver = driver;
|
tty->driver = driver;
|
||||||
|
tty->ops = driver->ops;
|
||||||
tty->index = idx;
|
tty->index = idx;
|
||||||
tty_line_name(driver, idx, tty->name);
|
tty_line_name(driver, idx, tty->name);
|
||||||
|
|
||||||
|
@ -2152,6 +2154,7 @@ static int init_dev(struct tty_driver *driver, int idx,
|
||||||
goto free_mem_out;
|
goto free_mem_out;
|
||||||
initialize_tty_struct(o_tty);
|
initialize_tty_struct(o_tty);
|
||||||
o_tty->driver = driver->other;
|
o_tty->driver = driver->other;
|
||||||
|
o_tty->ops = driver->ops;
|
||||||
o_tty->index = idx;
|
o_tty->index = idx;
|
||||||
tty_line_name(driver->other, idx, o_tty->name);
|
tty_line_name(driver->other, idx, o_tty->name);
|
||||||
|
|
||||||
|
@ -2456,8 +2459,8 @@ static void release_dev(struct file *filp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (tty->driver->close)
|
if (tty->ops->close)
|
||||||
tty->driver->close(tty, filp);
|
tty->ops->close(tty, filp);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Sanity check: if tty->count is going to zero, there shouldn't be
|
* Sanity check: if tty->count is going to zero, there shouldn't be
|
||||||
|
@ -2740,8 +2743,8 @@ got_driver:
|
||||||
printk(KERN_DEBUG "opening %s...", tty->name);
|
printk(KERN_DEBUG "opening %s...", tty->name);
|
||||||
#endif
|
#endif
|
||||||
if (!retval) {
|
if (!retval) {
|
||||||
if (tty->driver->open)
|
if (tty->ops->open)
|
||||||
retval = tty->driver->open(tty, filp);
|
retval = tty->ops->open(tty, filp);
|
||||||
else
|
else
|
||||||
retval = -ENODEV;
|
retval = -ENODEV;
|
||||||
}
|
}
|
||||||
|
@ -2840,7 +2843,7 @@ static int ptmx_open(struct inode *inode, struct file *filp)
|
||||||
goto out1;
|
goto out1;
|
||||||
|
|
||||||
check_tty_count(tty, "tty_open");
|
check_tty_count(tty, "tty_open");
|
||||||
retval = ptm_driver->open(tty, filp);
|
retval = ptm_driver->ops->open(tty, filp);
|
||||||
if (!retval)
|
if (!retval)
|
||||||
return 0;
|
return 0;
|
||||||
out1:
|
out1:
|
||||||
|
@ -3336,25 +3339,20 @@ static int tiocsetd(struct tty_struct *tty, int __user *p)
|
||||||
|
|
||||||
static int send_break(struct tty_struct *tty, unsigned int duration)
|
static int send_break(struct tty_struct *tty, unsigned int duration)
|
||||||
{
|
{
|
||||||
int retval = -EINTR;
|
|
||||||
|
|
||||||
lock_kernel();
|
|
||||||
if (tty_write_lock(tty, 0) < 0)
|
if (tty_write_lock(tty, 0) < 0)
|
||||||
goto out;
|
return -EINTR;
|
||||||
tty->driver->break_ctl(tty, -1);
|
tty->ops->break_ctl(tty, -1);
|
||||||
if (!signal_pending(current))
|
if (!signal_pending(current))
|
||||||
msleep_interruptible(duration);
|
msleep_interruptible(duration);
|
||||||
tty->driver->break_ctl(tty, 0);
|
tty->ops->break_ctl(tty, 0);
|
||||||
tty_write_unlock(tty);
|
tty_write_unlock(tty);
|
||||||
if (!signal_pending(current))
|
if (!signal_pending(current))
|
||||||
retval = 0;
|
return -EINTR;
|
||||||
out:
|
return 0;
|
||||||
unlock_kernel();
|
|
||||||
return retval;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* tiocmget - get modem status
|
* tty_tiocmget - get modem status
|
||||||
* @tty: tty device
|
* @tty: tty device
|
||||||
* @file: user file pointer
|
* @file: user file pointer
|
||||||
* @p: pointer to result
|
* @p: pointer to result
|
||||||
|
@ -3369,10 +3367,8 @@ static int tty_tiocmget(struct tty_struct *tty, struct file *file, int __user *p
|
||||||
{
|
{
|
||||||
int retval = -EINVAL;
|
int retval = -EINVAL;
|
||||||
|
|
||||||
if (tty->driver->tiocmget) {
|
if (tty->ops->tiocmget) {
|
||||||
lock_kernel();
|
retval = tty->ops->tiocmget(tty, file);
|
||||||
retval = tty->driver->tiocmget(tty, file);
|
|
||||||
unlock_kernel();
|
|
||||||
|
|
||||||
if (retval >= 0)
|
if (retval >= 0)
|
||||||
retval = put_user(retval, p);
|
retval = put_user(retval, p);
|
||||||
|
@ -3381,7 +3377,7 @@ static int tty_tiocmget(struct tty_struct *tty, struct file *file, int __user *p
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* tiocmset - set modem status
|
* tty_tiocmset - set modem status
|
||||||
* @tty: tty device
|
* @tty: tty device
|
||||||
* @file: user file pointer
|
* @file: user file pointer
|
||||||
* @cmd: command - clear bits, set bits or set all
|
* @cmd: command - clear bits, set bits or set all
|
||||||
|
@ -3398,7 +3394,7 @@ static int tty_tiocmset(struct tty_struct *tty, struct file *file, unsigned int
|
||||||
{
|
{
|
||||||
int retval = -EINVAL;
|
int retval = -EINVAL;
|
||||||
|
|
||||||
if (tty->driver->tiocmset) {
|
if (tty->ops->tiocmset) {
|
||||||
unsigned int set, clear, val;
|
unsigned int set, clear, val;
|
||||||
|
|
||||||
retval = get_user(val, p);
|
retval = get_user(val, p);
|
||||||
|
@ -3422,9 +3418,7 @@ static int tty_tiocmset(struct tty_struct *tty, struct file *file, unsigned int
|
||||||
set &= TIOCM_DTR|TIOCM_RTS|TIOCM_OUT1|TIOCM_OUT2|TIOCM_LOOP;
|
set &= TIOCM_DTR|TIOCM_RTS|TIOCM_OUT1|TIOCM_OUT2|TIOCM_LOOP;
|
||||||
clear &= TIOCM_DTR|TIOCM_RTS|TIOCM_OUT1|TIOCM_OUT2|TIOCM_LOOP;
|
clear &= TIOCM_DTR|TIOCM_RTS|TIOCM_OUT1|TIOCM_OUT2|TIOCM_LOOP;
|
||||||
|
|
||||||
lock_kernel();
|
retval = tty->ops->tiocmset(tty, file, set, clear);
|
||||||
retval = tty->driver->tiocmset(tty, file, set, clear);
|
|
||||||
unlock_kernel();
|
|
||||||
}
|
}
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
@ -3455,23 +3449,25 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||||
|
|
||||||
retval = -EINVAL;
|
retval = -EINVAL;
|
||||||
|
|
||||||
if (!tty->driver->break_ctl) {
|
if (!tty->ops->break_ctl) {
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case TIOCSBRK:
|
case TIOCSBRK:
|
||||||
case TIOCCBRK:
|
case TIOCCBRK:
|
||||||
if (tty->driver->ioctl)
|
if (tty->ops->ioctl)
|
||||||
retval = tty->driver->ioctl(tty, file, cmd, arg);
|
retval = tty->ops->ioctl(tty, file, cmd, arg);
|
||||||
|
if (retval != -EINVAL && retval != -ENOIOCTLCMD)
|
||||||
|
printk(KERN_WARNING "tty: driver %s needs updating to use break_ctl\n", tty->driver->name);
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
/* These two ioctl's always return success; even if */
|
/* These two ioctl's always return success; even if */
|
||||||
/* the driver doesn't support them. */
|
/* the driver doesn't support them. */
|
||||||
case TCSBRK:
|
case TCSBRK:
|
||||||
case TCSBRKP:
|
case TCSBRKP:
|
||||||
if (!tty->driver->ioctl)
|
if (!tty->ops->ioctl)
|
||||||
return 0;
|
return 0;
|
||||||
lock_kernel();
|
retval = tty->ops->ioctl(tty, file, cmd, arg);
|
||||||
retval = tty->driver->ioctl(tty, file, cmd, arg);
|
if (retval != -EINVAL && retval != -ENOIOCTLCMD)
|
||||||
unlock_kernel();
|
printk(KERN_WARNING "tty: driver %s needs updating to use break_ctl\n", tty->driver->name);
|
||||||
if (retval == -ENOIOCTLCMD)
|
if (retval == -ENOIOCTLCMD)
|
||||||
retval = 0;
|
retval = 0;
|
||||||
return retval;
|
return retval;
|
||||||
|
@ -3491,9 +3487,7 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||||
if (retval)
|
if (retval)
|
||||||
return retval;
|
return retval;
|
||||||
if (cmd != TIOCCBRK) {
|
if (cmd != TIOCCBRK) {
|
||||||
lock_kernel();
|
|
||||||
tty_wait_until_sent(tty, 0);
|
tty_wait_until_sent(tty, 0);
|
||||||
unlock_kernel();
|
|
||||||
if (signal_pending(current))
|
if (signal_pending(current))
|
||||||
return -EINTR;
|
return -EINTR;
|
||||||
}
|
}
|
||||||
|
@ -3531,7 +3525,6 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||||
case TIOCGSID:
|
case TIOCGSID:
|
||||||
return tiocgsid(tty, real_tty, p);
|
return tiocgsid(tty, real_tty, p);
|
||||||
case TIOCGETD:
|
case TIOCGETD:
|
||||||
/* FIXME: check this is ok */
|
|
||||||
return put_user(tty->ldisc.num, (int __user *)p);
|
return put_user(tty->ldisc.num, (int __user *)p);
|
||||||
case TIOCSETD:
|
case TIOCSETD:
|
||||||
return tiocsetd(tty, p);
|
return tiocsetd(tty, p);
|
||||||
|
@ -3543,15 +3536,13 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||||
* Break handling
|
* Break handling
|
||||||
*/
|
*/
|
||||||
case TIOCSBRK: /* Turn break on, unconditionally */
|
case TIOCSBRK: /* Turn break on, unconditionally */
|
||||||
lock_kernel();
|
if (tty->ops->break_ctl)
|
||||||
tty->driver->break_ctl(tty, -1);
|
tty->ops->break_ctl(tty, -1);
|
||||||
unlock_kernel();
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case TIOCCBRK: /* Turn break off, unconditionally */
|
case TIOCCBRK: /* Turn break off, unconditionally */
|
||||||
lock_kernel();
|
if (tty->ops->break_ctl)
|
||||||
tty->driver->break_ctl(tty, 0);
|
tty->ops->break_ctl(tty, 0);
|
||||||
unlock_kernel();
|
|
||||||
return 0;
|
return 0;
|
||||||
case TCSBRK: /* SVID version: non-zero arg --> no break */
|
case TCSBRK: /* SVID version: non-zero arg --> no break */
|
||||||
/* non-zero arg means wait for all output data
|
/* non-zero arg means wait for all output data
|
||||||
|
@ -3580,8 +3571,8 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (tty->driver->ioctl) {
|
if (tty->ops->ioctl) {
|
||||||
retval = (tty->driver->ioctl)(tty, file, cmd, arg);
|
retval = (tty->ops->ioctl)(tty, file, cmd, arg);
|
||||||
if (retval != -ENOIOCTLCMD)
|
if (retval != -ENOIOCTLCMD)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
@ -3608,8 +3599,8 @@ static long tty_compat_ioctl(struct file *file, unsigned int cmd,
|
||||||
if (tty_paranoia_check(tty, inode, "tty_ioctl"))
|
if (tty_paranoia_check(tty, inode, "tty_ioctl"))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (tty->driver->compat_ioctl) {
|
if (tty->ops->compat_ioctl) {
|
||||||
retval = (tty->driver->compat_ioctl)(tty, file, cmd, arg);
|
retval = (tty->ops->compat_ioctl)(tty, file, cmd, arg);
|
||||||
if (retval != -ENOIOCTLCMD)
|
if (retval != -ENOIOCTLCMD)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
@ -3659,8 +3650,7 @@ void __do_SAK(struct tty_struct *tty)
|
||||||
|
|
||||||
tty_ldisc_flush(tty);
|
tty_ldisc_flush(tty);
|
||||||
|
|
||||||
if (tty->driver->flush_buffer)
|
tty_driver_flush_buffer(tty);
|
||||||
tty->driver->flush_buffer(tty);
|
|
||||||
|
|
||||||
read_lock(&tasklist_lock);
|
read_lock(&tasklist_lock);
|
||||||
/* Kill the entire session */
|
/* Kill the entire session */
|
||||||
|
@ -3871,15 +3861,27 @@ static void initialize_tty_struct(struct tty_struct *tty)
|
||||||
INIT_WORK(&tty->SAK_work, do_SAK_work);
|
INIT_WORK(&tty->SAK_work, do_SAK_work);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* The default put_char routine if the driver did not define one.
|
* tty_put_char - write one character to a tty
|
||||||
|
* @tty: tty
|
||||||
|
* @ch: character
|
||||||
|
*
|
||||||
|
* Write one byte to the tty using the provided put_char method
|
||||||
|
* if present. Returns the number of characters successfully output.
|
||||||
|
*
|
||||||
|
* Note: the specific put_char operation in the driver layer may go
|
||||||
|
* away soon. Don't call it directly, use this method
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void tty_default_put_char(struct tty_struct *tty, unsigned char ch)
|
int tty_put_char(struct tty_struct *tty, unsigned char ch)
|
||||||
{
|
{
|
||||||
tty->driver->write(tty, &ch, 1);
|
if (tty->ops->put_char)
|
||||||
|
return tty->ops->put_char(tty, ch);
|
||||||
|
return tty->ops->write(tty, &ch, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EXPORT_SYMBOL_GPL(tty_put_char);
|
||||||
|
|
||||||
static struct class *tty_class;
|
static struct class *tty_class;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -3962,37 +3964,8 @@ void put_tty_driver(struct tty_driver *driver)
|
||||||
void tty_set_operations(struct tty_driver *driver,
|
void tty_set_operations(struct tty_driver *driver,
|
||||||
const struct tty_operations *op)
|
const struct tty_operations *op)
|
||||||
{
|
{
|
||||||
driver->open = op->open;
|
driver->ops = op;
|
||||||
driver->close = op->close;
|
};
|
||||||
driver->write = op->write;
|
|
||||||
driver->put_char = op->put_char;
|
|
||||||
driver->flush_chars = op->flush_chars;
|
|
||||||
driver->write_room = op->write_room;
|
|
||||||
driver->chars_in_buffer = op->chars_in_buffer;
|
|
||||||
driver->ioctl = op->ioctl;
|
|
||||||
driver->compat_ioctl = op->compat_ioctl;
|
|
||||||
driver->set_termios = op->set_termios;
|
|
||||||
driver->throttle = op->throttle;
|
|
||||||
driver->unthrottle = op->unthrottle;
|
|
||||||
driver->stop = op->stop;
|
|
||||||
driver->start = op->start;
|
|
||||||
driver->hangup = op->hangup;
|
|
||||||
driver->break_ctl = op->break_ctl;
|
|
||||||
driver->flush_buffer = op->flush_buffer;
|
|
||||||
driver->set_ldisc = op->set_ldisc;
|
|
||||||
driver->wait_until_sent = op->wait_until_sent;
|
|
||||||
driver->send_xchar = op->send_xchar;
|
|
||||||
driver->read_proc = op->read_proc;
|
|
||||||
driver->write_proc = op->write_proc;
|
|
||||||
driver->tiocmget = op->tiocmget;
|
|
||||||
driver->tiocmset = op->tiocmset;
|
|
||||||
#ifdef CONFIG_CONSOLE_POLL
|
|
||||||
driver->poll_init = op->poll_init;
|
|
||||||
driver->poll_get_char = op->poll_get_char;
|
|
||||||
driver->poll_put_char = op->poll_put_char;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
EXPORT_SYMBOL(alloc_tty_driver);
|
EXPORT_SYMBOL(alloc_tty_driver);
|
||||||
EXPORT_SYMBOL(put_tty_driver);
|
EXPORT_SYMBOL(put_tty_driver);
|
||||||
|
@ -4055,9 +4028,6 @@ int tty_register_driver(struct tty_driver *driver)
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!driver->put_char)
|
|
||||||
driver->put_char = tty_default_put_char;
|
|
||||||
|
|
||||||
mutex_lock(&tty_mutex);
|
mutex_lock(&tty_mutex);
|
||||||
list_add(&driver->tty_drivers, &tty_drivers);
|
list_add(&driver->tty_drivers, &tty_drivers);
|
||||||
mutex_unlock(&tty_mutex);
|
mutex_unlock(&tty_mutex);
|
||||||
|
|
|
@ -40,6 +40,34 @@
|
||||||
#define TERMIOS_OLD 8
|
#define TERMIOS_OLD 8
|
||||||
|
|
||||||
|
|
||||||
|
int tty_chars_in_buffer(struct tty_struct *tty)
|
||||||
|
{
|
||||||
|
if (tty->ops->chars_in_buffer)
|
||||||
|
return tty->ops->chars_in_buffer(tty);
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPORT_SYMBOL(tty_chars_in_buffer);
|
||||||
|
|
||||||
|
int tty_write_room(struct tty_struct *tty)
|
||||||
|
{
|
||||||
|
if (tty->ops->write_room)
|
||||||
|
return tty->ops->write_room(tty);
|
||||||
|
return 2048;
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPORT_SYMBOL(tty_write_room);
|
||||||
|
|
||||||
|
void tty_driver_flush_buffer(struct tty_struct *tty)
|
||||||
|
{
|
||||||
|
if (tty->ops->flush_buffer)
|
||||||
|
tty->ops->flush_buffer(tty);
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPORT_SYMBOL(tty_driver_flush_buffer);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* tty_wait_until_sent - wait for I/O to finish
|
* tty_wait_until_sent - wait for I/O to finish
|
||||||
* @tty: tty we are waiting for
|
* @tty: tty we are waiting for
|
||||||
|
@ -58,17 +86,13 @@ void tty_wait_until_sent(struct tty_struct *tty, long timeout)
|
||||||
|
|
||||||
printk(KERN_DEBUG "%s wait until sent...\n", tty_name(tty, buf));
|
printk(KERN_DEBUG "%s wait until sent...\n", tty_name(tty, buf));
|
||||||
#endif
|
#endif
|
||||||
if (!tty->driver->chars_in_buffer)
|
|
||||||
return;
|
|
||||||
if (!timeout)
|
if (!timeout)
|
||||||
timeout = MAX_SCHEDULE_TIMEOUT;
|
timeout = MAX_SCHEDULE_TIMEOUT;
|
||||||
lock_kernel();
|
|
||||||
if (wait_event_interruptible_timeout(tty->write_wait,
|
if (wait_event_interruptible_timeout(tty->write_wait,
|
||||||
!tty->driver->chars_in_buffer(tty), timeout) >= 0) {
|
!tty_chars_in_buffer(tty), timeout) >= 0) {
|
||||||
if (tty->driver->wait_until_sent)
|
if (tty->ops->wait_until_sent)
|
||||||
tty->driver->wait_until_sent(tty, timeout);
|
tty->ops->wait_until_sent(tty, timeout);
|
||||||
}
|
}
|
||||||
unlock_kernel();
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(tty_wait_until_sent);
|
EXPORT_SYMBOL(tty_wait_until_sent);
|
||||||
|
|
||||||
|
@ -444,8 +468,8 @@ static void change_termios(struct tty_struct *tty, struct ktermios *new_termios)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tty->driver->set_termios)
|
if (tty->ops->set_termios)
|
||||||
(*tty->driver->set_termios)(tty, &old_termios);
|
(*tty->ops->set_termios)(tty, &old_termios);
|
||||||
else
|
else
|
||||||
tty_termios_copy_hw(tty->termios, &old_termios);
|
tty_termios_copy_hw(tty->termios, &old_termios);
|
||||||
|
|
||||||
|
@ -748,8 +772,8 @@ static int send_prio_char(struct tty_struct *tty, char ch)
|
||||||
{
|
{
|
||||||
int was_stopped = tty->stopped;
|
int was_stopped = tty->stopped;
|
||||||
|
|
||||||
if (tty->driver->send_xchar) {
|
if (tty->ops->send_xchar) {
|
||||||
tty->driver->send_xchar(tty, ch);
|
tty->ops->send_xchar(tty, ch);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -758,7 +782,7 @@ static int send_prio_char(struct tty_struct *tty, char ch)
|
||||||
|
|
||||||
if (was_stopped)
|
if (was_stopped)
|
||||||
start_tty(tty);
|
start_tty(tty);
|
||||||
tty->driver->write(tty, &ch, 1);
|
tty->ops->write(tty, &ch, 1);
|
||||||
if (was_stopped)
|
if (was_stopped)
|
||||||
stop_tty(tty);
|
stop_tty(tty);
|
||||||
tty_write_unlock(tty);
|
tty_write_unlock(tty);
|
||||||
|
@ -778,13 +802,14 @@ static int tty_change_softcar(struct tty_struct *tty, int arg)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
int bit = arg ? CLOCAL : 0;
|
int bit = arg ? CLOCAL : 0;
|
||||||
struct ktermios old = *tty->termios;
|
struct ktermios old;
|
||||||
|
|
||||||
mutex_lock(&tty->termios_mutex);
|
mutex_lock(&tty->termios_mutex);
|
||||||
|
old = *tty->termios;
|
||||||
tty->termios->c_cflag &= ~CLOCAL;
|
tty->termios->c_cflag &= ~CLOCAL;
|
||||||
tty->termios->c_cflag |= bit;
|
tty->termios->c_cflag |= bit;
|
||||||
if (tty->driver->set_termios)
|
if (tty->ops->set_termios)
|
||||||
tty->driver->set_termios(tty, &old);
|
tty->ops->set_termios(tty, &old);
|
||||||
if ((tty->termios->c_cflag & CLOCAL) != bit)
|
if ((tty->termios->c_cflag & CLOCAL) != bit)
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
mutex_unlock(&tty->termios_mutex);
|
mutex_unlock(&tty->termios_mutex);
|
||||||
|
@ -926,8 +951,7 @@ int tty_perform_flush(struct tty_struct *tty, unsigned long arg)
|
||||||
ld->flush_buffer(tty);
|
ld->flush_buffer(tty);
|
||||||
/* fall through */
|
/* fall through */
|
||||||
case TCOFLUSH:
|
case TCOFLUSH:
|
||||||
if (tty->driver->flush_buffer)
|
tty_driver_flush_buffer(tty);
|
||||||
tty->driver->flush_buffer(tty);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
tty_ldisc_deref(ld);
|
tty_ldisc_deref(ld);
|
||||||
|
@ -984,9 +1008,7 @@ int n_tty_ioctl(struct tty_struct *tty, struct file *file,
|
||||||
case TCFLSH:
|
case TCFLSH:
|
||||||
return tty_perform_flush(tty, arg);
|
return tty_perform_flush(tty, arg);
|
||||||
case TIOCOUTQ:
|
case TIOCOUTQ:
|
||||||
return put_user(tty->driver->chars_in_buffer ?
|
return put_user(tty_chars_in_buffer(tty), (int __user *) arg);
|
||||||
tty->driver->chars_in_buffer(tty) : 0,
|
|
||||||
(int __user *) arg);
|
|
||||||
case TIOCINQ:
|
case TIOCINQ:
|
||||||
retval = tty->read_cnt;
|
retval = tty->read_cnt;
|
||||||
if (L_ICANON(tty))
|
if (L_ICANON(tty))
|
||||||
|
|
|
@ -46,7 +46,7 @@ struct serport {
|
||||||
static int serport_serio_write(struct serio *serio, unsigned char data)
|
static int serport_serio_write(struct serio *serio, unsigned char data)
|
||||||
{
|
{
|
||||||
struct serport *serport = serio->port_data;
|
struct serport *serport = serio->port_data;
|
||||||
return -(serport->tty->driver->write(serport->tty, &data, 1) != 1);
|
return -(serport->tty->ops->write(serport->tty, &data, 1) != 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int serport_serio_open(struct serio *serio)
|
static int serport_serio_open(struct serio *serio)
|
||||||
|
|
|
@ -68,10 +68,10 @@ static int write_modem(struct cardstate *cs)
|
||||||
struct tty_struct *tty = cs->hw.ser->tty;
|
struct tty_struct *tty = cs->hw.ser->tty;
|
||||||
struct bc_state *bcs = &cs->bcs[0]; /* only one channel */
|
struct bc_state *bcs = &cs->bcs[0]; /* only one channel */
|
||||||
struct sk_buff *skb = bcs->tx_skb;
|
struct sk_buff *skb = bcs->tx_skb;
|
||||||
int sent;
|
int sent = -EOPNOTSUPP;
|
||||||
|
|
||||||
if (!tty || !tty->driver || !skb)
|
if (!tty || !tty->driver || !skb)
|
||||||
return -EFAULT;
|
return -EINVAL;
|
||||||
|
|
||||||
if (!skb->len) {
|
if (!skb->len) {
|
||||||
dev_kfree_skb_any(skb);
|
dev_kfree_skb_any(skb);
|
||||||
|
@ -80,7 +80,8 @@ static int write_modem(struct cardstate *cs)
|
||||||
}
|
}
|
||||||
|
|
||||||
set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
|
set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
|
||||||
sent = tty->driver->write(tty, skb->data, skb->len);
|
if (tty->ops->write)
|
||||||
|
sent = tty->ops->write(tty, skb->data, skb->len);
|
||||||
gig_dbg(DEBUG_OUTPUT, "write_modem: sent %d", sent);
|
gig_dbg(DEBUG_OUTPUT, "write_modem: sent %d", sent);
|
||||||
if (sent < 0) {
|
if (sent < 0) {
|
||||||
/* error */
|
/* error */
|
||||||
|
@ -120,7 +121,7 @@ static int send_cb(struct cardstate *cs)
|
||||||
|
|
||||||
if (cb->len) {
|
if (cb->len) {
|
||||||
set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
|
set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
|
||||||
sent = tty->driver->write(tty, cb->buf + cb->offset, cb->len);
|
sent = tty->ops->write(tty, cb->buf + cb->offset, cb->len);
|
||||||
if (sent < 0) {
|
if (sent < 0) {
|
||||||
/* error */
|
/* error */
|
||||||
gig_dbg(DEBUG_OUTPUT, "send_cb: write error %d", sent);
|
gig_dbg(DEBUG_OUTPUT, "send_cb: write error %d", sent);
|
||||||
|
@ -440,14 +441,14 @@ static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state, unsi
|
||||||
struct tty_struct *tty = cs->hw.ser->tty;
|
struct tty_struct *tty = cs->hw.ser->tty;
|
||||||
unsigned int set, clear;
|
unsigned int set, clear;
|
||||||
|
|
||||||
if (!tty || !tty->driver || !tty->driver->tiocmset)
|
if (!tty || !tty->driver || !tty->ops->tiocmset)
|
||||||
return -EFAULT;
|
return -EINVAL;
|
||||||
set = new_state & ~old_state;
|
set = new_state & ~old_state;
|
||||||
clear = old_state & ~new_state;
|
clear = old_state & ~new_state;
|
||||||
if (!set && !clear)
|
if (!set && !clear)
|
||||||
return 0;
|
return 0;
|
||||||
gig_dbg(DEBUG_IF, "tiocmset set %x clear %x", set, clear);
|
gig_dbg(DEBUG_IF, "tiocmset set %x clear %x", set, clear);
|
||||||
return tty->driver->tiocmset(tty, NULL, set, clear);
|
return tty->ops->tiocmset(tty, NULL, set, clear);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int gigaset_baud_rate(struct cardstate *cs, unsigned cflag)
|
static int gigaset_baud_rate(struct cardstate *cs, unsigned cflag)
|
||||||
|
|
|
@ -148,13 +148,13 @@ static void sp_xmit_on_air(unsigned long channel)
|
||||||
|
|
||||||
if (((sp->status1 & SIXP_DCD_MASK) == 0) && (random < sp->persistence)) {
|
if (((sp->status1 & SIXP_DCD_MASK) == 0) && (random < sp->persistence)) {
|
||||||
sp->led_state = 0x70;
|
sp->led_state = 0x70;
|
||||||
sp->tty->driver->write(sp->tty, &sp->led_state, 1);
|
sp->tty->ops->write(sp->tty, &sp->led_state, 1);
|
||||||
sp->tx_enable = 1;
|
sp->tx_enable = 1;
|
||||||
actual = sp->tty->driver->write(sp->tty, sp->xbuff, sp->status2);
|
actual = sp->tty->ops->write(sp->tty, sp->xbuff, sp->status2);
|
||||||
sp->xleft -= actual;
|
sp->xleft -= actual;
|
||||||
sp->xhead += actual;
|
sp->xhead += actual;
|
||||||
sp->led_state = 0x60;
|
sp->led_state = 0x60;
|
||||||
sp->tty->driver->write(sp->tty, &sp->led_state, 1);
|
sp->tty->ops->write(sp->tty, &sp->led_state, 1);
|
||||||
sp->status2 = 0;
|
sp->status2 = 0;
|
||||||
} else
|
} else
|
||||||
mod_timer(&sp->tx_t, jiffies + ((when + 1) * HZ) / 100);
|
mod_timer(&sp->tx_t, jiffies + ((when + 1) * HZ) / 100);
|
||||||
|
@ -220,13 +220,13 @@ static void sp_encaps(struct sixpack *sp, unsigned char *icp, int len)
|
||||||
*/
|
*/
|
||||||
if (sp->duplex == 1) {
|
if (sp->duplex == 1) {
|
||||||
sp->led_state = 0x70;
|
sp->led_state = 0x70;
|
||||||
sp->tty->driver->write(sp->tty, &sp->led_state, 1);
|
sp->tty->ops->write(sp->tty, &sp->led_state, 1);
|
||||||
sp->tx_enable = 1;
|
sp->tx_enable = 1;
|
||||||
actual = sp->tty->driver->write(sp->tty, sp->xbuff, count);
|
actual = sp->tty->ops->write(sp->tty, sp->xbuff, count);
|
||||||
sp->xleft = count - actual;
|
sp->xleft = count - actual;
|
||||||
sp->xhead = sp->xbuff + actual;
|
sp->xhead = sp->xbuff + actual;
|
||||||
sp->led_state = 0x60;
|
sp->led_state = 0x60;
|
||||||
sp->tty->driver->write(sp->tty, &sp->led_state, 1);
|
sp->tty->ops->write(sp->tty, &sp->led_state, 1);
|
||||||
} else {
|
} else {
|
||||||
sp->xleft = count;
|
sp->xleft = count;
|
||||||
sp->xhead = sp->xbuff;
|
sp->xhead = sp->xbuff;
|
||||||
|
@ -444,7 +444,7 @@ static void sixpack_write_wakeup(struct tty_struct *tty)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sp->tx_enable) {
|
if (sp->tx_enable) {
|
||||||
actual = tty->driver->write(tty, sp->xhead, sp->xleft);
|
actual = tty->ops->write(tty, sp->xhead, sp->xleft);
|
||||||
sp->xleft -= actual;
|
sp->xleft -= actual;
|
||||||
sp->xhead += actual;
|
sp->xhead += actual;
|
||||||
}
|
}
|
||||||
|
@ -492,8 +492,8 @@ static void sixpack_receive_buf(struct tty_struct *tty,
|
||||||
|
|
||||||
sp_put(sp);
|
sp_put(sp);
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -554,8 +554,8 @@ static void resync_tnc(unsigned long channel)
|
||||||
/* resync the TNC */
|
/* resync the TNC */
|
||||||
|
|
||||||
sp->led_state = 0x60;
|
sp->led_state = 0x60;
|
||||||
sp->tty->driver->write(sp->tty, &sp->led_state, 1);
|
sp->tty->ops->write(sp->tty, &sp->led_state, 1);
|
||||||
sp->tty->driver->write(sp->tty, &resync_cmd, 1);
|
sp->tty->ops->write(sp->tty, &resync_cmd, 1);
|
||||||
|
|
||||||
|
|
||||||
/* Start resync timer again -- the TNC might be still absent */
|
/* Start resync timer again -- the TNC might be still absent */
|
||||||
|
@ -573,7 +573,7 @@ static inline int tnc_init(struct sixpack *sp)
|
||||||
|
|
||||||
tnc_set_sync_state(sp, TNC_UNSYNC_STARTUP);
|
tnc_set_sync_state(sp, TNC_UNSYNC_STARTUP);
|
||||||
|
|
||||||
sp->tty->driver->write(sp->tty, &inbyte, 1);
|
sp->tty->ops->write(sp->tty, &inbyte, 1);
|
||||||
|
|
||||||
del_timer(&sp->resync_t);
|
del_timer(&sp->resync_t);
|
||||||
sp->resync_t.data = (unsigned long) sp;
|
sp->resync_t.data = (unsigned long) sp;
|
||||||
|
@ -601,6 +601,8 @@ static int sixpack_open(struct tty_struct *tty)
|
||||||
|
|
||||||
if (!capable(CAP_NET_ADMIN))
|
if (!capable(CAP_NET_ADMIN))
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
|
if (tty->ops->write == NULL)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
dev = alloc_netdev(sizeof(struct sixpack), "sp%d", sp_setup);
|
dev = alloc_netdev(sizeof(struct sixpack), "sp%d", sp_setup);
|
||||||
if (!dev) {
|
if (!dev) {
|
||||||
|
@ -914,9 +916,9 @@ static void decode_prio_command(struct sixpack *sp, unsigned char cmd)
|
||||||
} else { /* output watchdog char if idle */
|
} else { /* output watchdog char if idle */
|
||||||
if ((sp->status2 != 0) && (sp->duplex == 1)) {
|
if ((sp->status2 != 0) && (sp->duplex == 1)) {
|
||||||
sp->led_state = 0x70;
|
sp->led_state = 0x70;
|
||||||
sp->tty->driver->write(sp->tty, &sp->led_state, 1);
|
sp->tty->ops->write(sp->tty, &sp->led_state, 1);
|
||||||
sp->tx_enable = 1;
|
sp->tx_enable = 1;
|
||||||
actual = sp->tty->driver->write(sp->tty, sp->xbuff, sp->status2);
|
actual = sp->tty->ops->write(sp->tty, sp->xbuff, sp->status2);
|
||||||
sp->xleft -= actual;
|
sp->xleft -= actual;
|
||||||
sp->xhead += actual;
|
sp->xhead += actual;
|
||||||
sp->led_state = 0x60;
|
sp->led_state = 0x60;
|
||||||
|
@ -926,7 +928,7 @@ static void decode_prio_command(struct sixpack *sp, unsigned char cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* needed to trigger the TNC watchdog */
|
/* needed to trigger the TNC watchdog */
|
||||||
sp->tty->driver->write(sp->tty, &sp->led_state, 1);
|
sp->tty->ops->write(sp->tty, &sp->led_state, 1);
|
||||||
|
|
||||||
/* if the state byte has been received, the TNC is present,
|
/* if the state byte has been received, the TNC is present,
|
||||||
so the resync timer can be reset. */
|
so the resync timer can be reset. */
|
||||||
|
@ -956,12 +958,12 @@ static void decode_std_command(struct sixpack *sp, unsigned char cmd)
|
||||||
if ((sp->status & SIXP_RX_DCD_MASK) ==
|
if ((sp->status & SIXP_RX_DCD_MASK) ==
|
||||||
SIXP_RX_DCD_MASK) {
|
SIXP_RX_DCD_MASK) {
|
||||||
sp->led_state = 0x68;
|
sp->led_state = 0x68;
|
||||||
sp->tty->driver->write(sp->tty, &sp->led_state, 1);
|
sp->tty->ops->write(sp->tty, &sp->led_state, 1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sp->led_state = 0x60;
|
sp->led_state = 0x60;
|
||||||
/* fill trailing bytes with zeroes */
|
/* fill trailing bytes with zeroes */
|
||||||
sp->tty->driver->write(sp->tty, &sp->led_state, 1);
|
sp->tty->ops->write(sp->tty, &sp->led_state, 1);
|
||||||
rest = sp->rx_count;
|
rest = sp->rx_count;
|
||||||
if (rest != 0)
|
if (rest != 0)
|
||||||
for (i = rest; i <= 3; i++)
|
for (i = rest; i <= 3; i++)
|
||||||
|
|
|
@ -516,7 +516,7 @@ static void ax_encaps(struct net_device *dev, unsigned char *icp, int len)
|
||||||
spin_unlock_bh(&ax->buflock);
|
spin_unlock_bh(&ax->buflock);
|
||||||
|
|
||||||
set_bit(TTY_DO_WRITE_WAKEUP, &ax->tty->flags);
|
set_bit(TTY_DO_WRITE_WAKEUP, &ax->tty->flags);
|
||||||
actual = ax->tty->driver->write(ax->tty, ax->xbuff, count);
|
actual = ax->tty->ops->write(ax->tty, ax->xbuff, count);
|
||||||
ax->stats.tx_packets++;
|
ax->stats.tx_packets++;
|
||||||
ax->stats.tx_bytes += actual;
|
ax->stats.tx_bytes += actual;
|
||||||
|
|
||||||
|
@ -546,7 +546,7 @@ static int ax_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||||
}
|
}
|
||||||
|
|
||||||
printk(KERN_ERR "mkiss: %s: transmit timed out, %s?\n", dev->name,
|
printk(KERN_ERR "mkiss: %s: transmit timed out, %s?\n", dev->name,
|
||||||
(ax->tty->driver->chars_in_buffer(ax->tty) || ax->xleft) ?
|
(ax->tty->ops->chars_in_buffer(ax->tty) || ax->xleft) ?
|
||||||
"bad line quality" : "driver error");
|
"bad line quality" : "driver error");
|
||||||
|
|
||||||
ax->xleft = 0;
|
ax->xleft = 0;
|
||||||
|
@ -736,6 +736,8 @@ static int mkiss_open(struct tty_struct *tty)
|
||||||
|
|
||||||
if (!capable(CAP_NET_ADMIN))
|
if (!capable(CAP_NET_ADMIN))
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
|
if (tty->ops->write == NULL)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
dev = alloc_netdev(sizeof(struct mkiss), "ax%d", ax_setup);
|
dev = alloc_netdev(sizeof(struct mkiss), "ax%d", ax_setup);
|
||||||
if (!dev) {
|
if (!dev) {
|
||||||
|
@ -754,8 +756,7 @@ static int mkiss_open(struct tty_struct *tty)
|
||||||
tty->disc_data = ax;
|
tty->disc_data = ax;
|
||||||
tty->receive_room = 65535;
|
tty->receive_room = 65535;
|
||||||
|
|
||||||
if (tty->driver->flush_buffer)
|
tty_driver_flush_buffer(tty);
|
||||||
tty->driver->flush_buffer(tty);
|
|
||||||
|
|
||||||
/* Restore default settings */
|
/* Restore default settings */
|
||||||
dev->type = ARPHRD_AX25;
|
dev->type = ARPHRD_AX25;
|
||||||
|
@ -936,8 +937,8 @@ static void mkiss_receive_buf(struct tty_struct *tty, const unsigned char *cp,
|
||||||
|
|
||||||
mkiss_put(ax);
|
mkiss_put(ax);
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -962,7 +963,7 @@ static void mkiss_write_wakeup(struct tty_struct *tty)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
actual = tty->driver->write(tty, ax->xhead, ax->xleft);
|
actual = tty->ops->write(tty, ax->xhead, ax->xleft);
|
||||||
ax->xleft -= actual;
|
ax->xleft -= actual;
|
||||||
ax->xhead += actual;
|
ax->xhead += actual;
|
||||||
|
|
||||||
|
|
|
@ -64,7 +64,7 @@ static int irtty_chars_in_buffer(struct sir_dev *dev)
|
||||||
IRDA_ASSERT(priv != NULL, return -1;);
|
IRDA_ASSERT(priv != NULL, return -1;);
|
||||||
IRDA_ASSERT(priv->magic == IRTTY_MAGIC, return -1;);
|
IRDA_ASSERT(priv->magic == IRTTY_MAGIC, return -1;);
|
||||||
|
|
||||||
return priv->tty->driver->chars_in_buffer(priv->tty);
|
return tty_chars_in_buffer(priv->tty);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wait (sleep) until underlaying hardware finished transmission
|
/* Wait (sleep) until underlaying hardware finished transmission
|
||||||
|
@ -93,10 +93,8 @@ static void irtty_wait_until_sent(struct sir_dev *dev)
|
||||||
IRDA_ASSERT(priv->magic == IRTTY_MAGIC, return;);
|
IRDA_ASSERT(priv->magic == IRTTY_MAGIC, return;);
|
||||||
|
|
||||||
tty = priv->tty;
|
tty = priv->tty;
|
||||||
if (tty->driver->wait_until_sent) {
|
if (tty->ops->wait_until_sent) {
|
||||||
lock_kernel();
|
tty->ops->wait_until_sent(tty, msecs_to_jiffies(100));
|
||||||
tty->driver->wait_until_sent(tty, msecs_to_jiffies(100));
|
|
||||||
unlock_kernel();
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
msleep(USBSERIAL_TX_DONE_DELAY);
|
msleep(USBSERIAL_TX_DONE_DELAY);
|
||||||
|
@ -125,48 +123,14 @@ static int irtty_change_speed(struct sir_dev *dev, unsigned speed)
|
||||||
|
|
||||||
tty = priv->tty;
|
tty = priv->tty;
|
||||||
|
|
||||||
lock_kernel();
|
mutex_lock(&tty->termios_mutex);
|
||||||
old_termios = *(tty->termios);
|
old_termios = *(tty->termios);
|
||||||
cflag = tty->termios->c_cflag;
|
cflag = tty->termios->c_cflag;
|
||||||
|
tty_encode_baud_rate(tty, speed, speed);
|
||||||
cflag &= ~CBAUD;
|
if (tty->ops->set_termios)
|
||||||
|
tty->ops->set_termios(tty, &old_termios);
|
||||||
IRDA_DEBUG(2, "%s(), Setting speed to %d\n", __FUNCTION__, speed);
|
|
||||||
|
|
||||||
switch (speed) {
|
|
||||||
case 1200:
|
|
||||||
cflag |= B1200;
|
|
||||||
break;
|
|
||||||
case 2400:
|
|
||||||
cflag |= B2400;
|
|
||||||
break;
|
|
||||||
case 4800:
|
|
||||||
cflag |= B4800;
|
|
||||||
break;
|
|
||||||
case 19200:
|
|
||||||
cflag |= B19200;
|
|
||||||
break;
|
|
||||||
case 38400:
|
|
||||||
cflag |= B38400;
|
|
||||||
break;
|
|
||||||
case 57600:
|
|
||||||
cflag |= B57600;
|
|
||||||
break;
|
|
||||||
case 115200:
|
|
||||||
cflag |= B115200;
|
|
||||||
break;
|
|
||||||
case 9600:
|
|
||||||
default:
|
|
||||||
cflag |= B9600;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
tty->termios->c_cflag = cflag;
|
|
||||||
if (tty->driver->set_termios)
|
|
||||||
tty->driver->set_termios(tty, &old_termios);
|
|
||||||
unlock_kernel();
|
|
||||||
|
|
||||||
priv->io.speed = speed;
|
priv->io.speed = speed;
|
||||||
|
mutex_unlock(&tty->termios_mutex);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -202,8 +166,8 @@ static int irtty_set_dtr_rts(struct sir_dev *dev, int dtr, int rts)
|
||||||
* This function is not yet defined for all tty driver, so
|
* This function is not yet defined for all tty driver, so
|
||||||
* let's be careful... Jean II
|
* let's be careful... Jean II
|
||||||
*/
|
*/
|
||||||
IRDA_ASSERT(priv->tty->driver->tiocmset != NULL, return -1;);
|
IRDA_ASSERT(priv->tty->ops->tiocmset != NULL, return -1;);
|
||||||
priv->tty->driver->tiocmset(priv->tty, NULL, set, clear);
|
priv->tty->ops->tiocmset(priv->tty, NULL, set, clear);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -225,17 +189,13 @@ static int irtty_do_write(struct sir_dev *dev, const unsigned char *ptr, size_t
|
||||||
IRDA_ASSERT(priv->magic == IRTTY_MAGIC, return -1;);
|
IRDA_ASSERT(priv->magic == IRTTY_MAGIC, return -1;);
|
||||||
|
|
||||||
tty = priv->tty;
|
tty = priv->tty;
|
||||||
if (!tty->driver->write)
|
if (!tty->ops->write)
|
||||||
return 0;
|
return 0;
|
||||||
tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
|
tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
|
||||||
if (tty->driver->write_room) {
|
writelen = tty_write_room(tty);
|
||||||
writelen = tty->driver->write_room(tty);
|
if (writelen > len)
|
||||||
if (writelen > len)
|
|
||||||
writelen = len;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
writelen = len;
|
writelen = len;
|
||||||
return tty->driver->write(tty, ptr, writelen);
|
return tty->ops->write(tty, ptr, writelen);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------- */
|
/* ------------------------------------------------------- */
|
||||||
|
@ -321,7 +281,7 @@ static inline void irtty_stop_receiver(struct tty_struct *tty, int stop)
|
||||||
struct ktermios old_termios;
|
struct ktermios old_termios;
|
||||||
int cflag;
|
int cflag;
|
||||||
|
|
||||||
lock_kernel();
|
mutex_lock(&tty->termios_mutex);
|
||||||
old_termios = *(tty->termios);
|
old_termios = *(tty->termios);
|
||||||
cflag = tty->termios->c_cflag;
|
cflag = tty->termios->c_cflag;
|
||||||
|
|
||||||
|
@ -331,9 +291,9 @@ static inline void irtty_stop_receiver(struct tty_struct *tty, int stop)
|
||||||
cflag |= CREAD;
|
cflag |= CREAD;
|
||||||
|
|
||||||
tty->termios->c_cflag = cflag;
|
tty->termios->c_cflag = cflag;
|
||||||
if (tty->driver->set_termios)
|
if (tty->ops->set_termios)
|
||||||
tty->driver->set_termios(tty, &old_termios);
|
tty->ops->set_termios(tty, &old_termios);
|
||||||
unlock_kernel();
|
mutex_unlock(&tty->termios_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************/
|
/*****************************************************************/
|
||||||
|
@ -359,8 +319,8 @@ static int irtty_start_dev(struct sir_dev *dev)
|
||||||
|
|
||||||
tty = priv->tty;
|
tty = priv->tty;
|
||||||
|
|
||||||
if (tty->driver->start)
|
if (tty->ops->start)
|
||||||
tty->driver->start(tty);
|
tty->ops->start(tty);
|
||||||
/* Make sure we can receive more data */
|
/* Make sure we can receive more data */
|
||||||
irtty_stop_receiver(tty, FALSE);
|
irtty_stop_receiver(tty, FALSE);
|
||||||
|
|
||||||
|
@ -388,8 +348,8 @@ static int irtty_stop_dev(struct sir_dev *dev)
|
||||||
|
|
||||||
/* Make sure we don't receive more data */
|
/* Make sure we don't receive more data */
|
||||||
irtty_stop_receiver(tty, TRUE);
|
irtty_stop_receiver(tty, TRUE);
|
||||||
if (tty->driver->stop)
|
if (tty->ops->stop)
|
||||||
tty->driver->stop(tty);
|
tty->ops->stop(tty);
|
||||||
|
|
||||||
mutex_unlock(&irtty_mutex);
|
mutex_unlock(&irtty_mutex);
|
||||||
|
|
||||||
|
@ -483,11 +443,10 @@ static int irtty_open(struct tty_struct *tty)
|
||||||
|
|
||||||
/* stop the underlying driver */
|
/* stop the underlying driver */
|
||||||
irtty_stop_receiver(tty, TRUE);
|
irtty_stop_receiver(tty, TRUE);
|
||||||
if (tty->driver->stop)
|
if (tty->ops->stop)
|
||||||
tty->driver->stop(tty);
|
tty->ops->stop(tty);
|
||||||
|
|
||||||
if (tty->driver->flush_buffer)
|
tty_driver_flush_buffer(tty);
|
||||||
tty->driver->flush_buffer(tty);
|
|
||||||
|
|
||||||
/* apply mtt override */
|
/* apply mtt override */
|
||||||
sir_tty_drv.qos_mtt_bits = qos_mtt_bits;
|
sir_tty_drv.qos_mtt_bits = qos_mtt_bits;
|
||||||
|
@ -564,8 +523,8 @@ static void irtty_close(struct tty_struct *tty)
|
||||||
/* Stop tty */
|
/* Stop tty */
|
||||||
irtty_stop_receiver(tty, TRUE);
|
irtty_stop_receiver(tty, TRUE);
|
||||||
tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
|
tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
|
||||||
if (tty->driver->stop)
|
if (tty->ops->stop)
|
||||||
tty->driver->stop(tty);
|
tty->ops->stop(tty);
|
||||||
|
|
||||||
kfree(priv);
|
kfree(priv);
|
||||||
|
|
||||||
|
|
|
@ -158,6 +158,9 @@ ppp_asynctty_open(struct tty_struct *tty)
|
||||||
struct asyncppp *ap;
|
struct asyncppp *ap;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
if (tty->ops->write == NULL)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
ap = kzalloc(sizeof(*ap), GFP_KERNEL);
|
ap = kzalloc(sizeof(*ap), GFP_KERNEL);
|
||||||
if (!ap)
|
if (!ap)
|
||||||
|
@ -359,8 +362,8 @@ ppp_asynctty_receive(struct tty_struct *tty, const unsigned char *buf,
|
||||||
tasklet_schedule(&ap->tsk);
|
tasklet_schedule(&ap->tsk);
|
||||||
ap_put(ap);
|
ap_put(ap);
|
||||||
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 void
|
static void
|
||||||
|
@ -676,7 +679,7 @@ ppp_async_push(struct asyncppp *ap)
|
||||||
if (!tty_stuffed && ap->optr < ap->olim) {
|
if (!tty_stuffed && ap->optr < ap->olim) {
|
||||||
avail = ap->olim - ap->optr;
|
avail = ap->olim - ap->optr;
|
||||||
set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
|
set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
|
||||||
sent = tty->driver->write(tty, ap->optr, avail);
|
sent = tty->ops->write(tty, ap->optr, avail);
|
||||||
if (sent < 0)
|
if (sent < 0)
|
||||||
goto flush; /* error, e.g. loss of CD */
|
goto flush; /* error, e.g. loss of CD */
|
||||||
ap->optr += sent;
|
ap->optr += sent;
|
||||||
|
|
|
@ -207,6 +207,9 @@ ppp_sync_open(struct tty_struct *tty)
|
||||||
struct syncppp *ap;
|
struct syncppp *ap;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
if (tty->ops->write == NULL)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
ap = kzalloc(sizeof(*ap), GFP_KERNEL);
|
ap = kzalloc(sizeof(*ap), GFP_KERNEL);
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
if (!ap)
|
if (!ap)
|
||||||
|
@ -399,8 +402,8 @@ ppp_sync_receive(struct tty_struct *tty, const unsigned char *buf,
|
||||||
tasklet_schedule(&ap->tsk);
|
tasklet_schedule(&ap->tsk);
|
||||||
sp_put(ap);
|
sp_put(ap);
|
||||||
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 void
|
static void
|
||||||
|
@ -653,7 +656,7 @@ ppp_sync_push(struct syncppp *ap)
|
||||||
tty_stuffed = 0;
|
tty_stuffed = 0;
|
||||||
if (!tty_stuffed && ap->tpkt) {
|
if (!tty_stuffed && ap->tpkt) {
|
||||||
set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
|
set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
|
||||||
sent = tty->driver->write(tty, ap->tpkt->data, ap->tpkt->len);
|
sent = tty->ops->write(tty, ap->tpkt->data, ap->tpkt->len);
|
||||||
if (sent < 0)
|
if (sent < 0)
|
||||||
goto flush; /* error, e.g. loss of CD */
|
goto flush; /* error, e.g. loss of CD */
|
||||||
if (sent < ap->tpkt->len) {
|
if (sent < ap->tpkt->len) {
|
||||||
|
|
|
@ -396,14 +396,14 @@ static void sl_encaps(struct slip *sl, unsigned char *icp, int len)
|
||||||
|
|
||||||
/* Order of next two lines is *very* important.
|
/* Order of next two lines is *very* important.
|
||||||
* When we are sending a little amount of data,
|
* When we are sending a little amount of data,
|
||||||
* the transfer may be completed inside driver.write()
|
* the transfer may be completed inside the ops->write()
|
||||||
* routine, because it's running with interrupts enabled.
|
* routine, because it's running with interrupts enabled.
|
||||||
* In this case we *never* got WRITE_WAKEUP event,
|
* In this case we *never* got WRITE_WAKEUP event,
|
||||||
* if we did not request it before write operation.
|
* if we did not request it before write operation.
|
||||||
* 14 Oct 1994 Dmitry Gorodchanin.
|
* 14 Oct 1994 Dmitry Gorodchanin.
|
||||||
*/
|
*/
|
||||||
sl->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
|
sl->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
|
||||||
actual = sl->tty->driver->write(sl->tty, sl->xbuff, count);
|
actual = sl->tty->ops->write(sl->tty, sl->xbuff, count);
|
||||||
#ifdef SL_CHECK_TRANSMIT
|
#ifdef SL_CHECK_TRANSMIT
|
||||||
sl->dev->trans_start = jiffies;
|
sl->dev->trans_start = jiffies;
|
||||||
#endif
|
#endif
|
||||||
|
@ -437,7 +437,7 @@ static void slip_write_wakeup(struct tty_struct *tty)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
actual = tty->driver->write(tty, sl->xhead, sl->xleft);
|
actual = tty->ops->write(tty, sl->xhead, sl->xleft);
|
||||||
sl->xleft -= actual;
|
sl->xleft -= actual;
|
||||||
sl->xhead += actual;
|
sl->xhead += actual;
|
||||||
}
|
}
|
||||||
|
@ -462,7 +462,7 @@ static void sl_tx_timeout(struct net_device *dev)
|
||||||
}
|
}
|
||||||
printk(KERN_WARNING "%s: transmit timed out, %s?\n",
|
printk(KERN_WARNING "%s: transmit timed out, %s?\n",
|
||||||
dev->name,
|
dev->name,
|
||||||
(sl->tty->driver->chars_in_buffer(sl->tty) || sl->xleft) ?
|
(tty_chars_in_buffer(sl->tty) || sl->xleft) ?
|
||||||
"bad line quality" : "driver error");
|
"bad line quality" : "driver error");
|
||||||
sl->xleft = 0;
|
sl->xleft = 0;
|
||||||
sl->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
|
sl->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
|
||||||
|
@ -830,6 +830,9 @@ static int slip_open(struct tty_struct *tty)
|
||||||
if (!capable(CAP_NET_ADMIN))
|
if (!capable(CAP_NET_ADMIN))
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
|
|
||||||
|
if (tty->ops->write == NULL)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
/* RTnetlink lock is misused here to serialize concurrent
|
/* RTnetlink lock is misused here to serialize concurrent
|
||||||
opens of slip channels. There are better ways, but it is
|
opens of slip channels. There are better ways, but it is
|
||||||
the simplest one.
|
the simplest one.
|
||||||
|
@ -1432,7 +1435,7 @@ static void sl_outfill(unsigned long sls)
|
||||||
/* put END into tty queue. Is it right ??? */
|
/* put END into tty queue. Is it right ??? */
|
||||||
if (!netif_queue_stopped(sl->dev)) {
|
if (!netif_queue_stopped(sl->dev)) {
|
||||||
/* if device busy no outfill */
|
/* if device busy no outfill */
|
||||||
sl->tty->driver->write(sl->tty, &s, 1);
|
sl->tty->ops->write(sl->tty, &s, 1);
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
set_bit(SLF_OUTWAIT, &sl->flags);
|
set_bit(SLF_OUTWAIT, &sl->flags);
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
|
|
||||||
#include <asm/system.h>
|
#include <asm/system.h>
|
||||||
#include <asm/uaccess.h>
|
#include <linux/uaccess.h>
|
||||||
#include <linux/bitops.h>
|
#include <linux/bitops.h>
|
||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
|
@ -95,7 +95,7 @@ static struct x25_asy *x25_asy_alloc(void)
|
||||||
x25_asy_devs[i] = dev;
|
x25_asy_devs[i] = dev;
|
||||||
return sl;
|
return sl;
|
||||||
} else {
|
} else {
|
||||||
printk("x25_asy_alloc() - register_netdev() failure.\n");
|
printk(KERN_WARNING "x25_asy_alloc() - register_netdev() failure.\n");
|
||||||
free_netdev(dev);
|
free_netdev(dev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -112,23 +112,22 @@ static void x25_asy_free(struct x25_asy *sl)
|
||||||
kfree(sl->xbuff);
|
kfree(sl->xbuff);
|
||||||
sl->xbuff = NULL;
|
sl->xbuff = NULL;
|
||||||
|
|
||||||
if (!test_and_clear_bit(SLF_INUSE, &sl->flags)) {
|
if (!test_and_clear_bit(SLF_INUSE, &sl->flags))
|
||||||
printk("%s: x25_asy_free for already free unit.\n", sl->dev->name);
|
printk(KERN_ERR "%s: x25_asy_free for already free unit.\n",
|
||||||
}
|
sl->dev->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int x25_asy_change_mtu(struct net_device *dev, int newmtu)
|
static int x25_asy_change_mtu(struct net_device *dev, int newmtu)
|
||||||
{
|
{
|
||||||
struct x25_asy *sl = dev->priv;
|
struct x25_asy *sl = dev->priv;
|
||||||
unsigned char *xbuff, *rbuff;
|
unsigned char *xbuff, *rbuff;
|
||||||
int len = 2* newmtu;
|
int len = 2 * newmtu;
|
||||||
|
|
||||||
xbuff = kmalloc(len + 4, GFP_ATOMIC);
|
xbuff = kmalloc(len + 4, GFP_ATOMIC);
|
||||||
rbuff = kmalloc(len + 4, GFP_ATOMIC);
|
rbuff = kmalloc(len + 4, GFP_ATOMIC);
|
||||||
|
|
||||||
if (xbuff == NULL || rbuff == NULL)
|
if (xbuff == NULL || rbuff == NULL) {
|
||||||
{
|
printk(KERN_WARNING "%s: unable to grow X.25 buffers, MTU change cancelled.\n",
|
||||||
printk("%s: unable to grow X.25 buffers, MTU change cancelled.\n",
|
|
||||||
dev->name);
|
dev->name);
|
||||||
kfree(xbuff);
|
kfree(xbuff);
|
||||||
kfree(rbuff);
|
kfree(rbuff);
|
||||||
|
@ -193,25 +192,23 @@ static void x25_asy_bump(struct x25_asy *sl)
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
count = sl->rcount;
|
count = sl->rcount;
|
||||||
sl->stats.rx_bytes+=count;
|
sl->stats.rx_bytes += count;
|
||||||
|
|
||||||
skb = dev_alloc_skb(count+1);
|
skb = dev_alloc_skb(count+1);
|
||||||
if (skb == NULL)
|
if (skb == NULL) {
|
||||||
{
|
printk(KERN_WARNING "%s: memory squeeze, dropping packet.\n",
|
||||||
printk("%s: memory squeeze, dropping packet.\n", sl->dev->name);
|
sl->dev->name);
|
||||||
sl->stats.rx_dropped++;
|
sl->stats.rx_dropped++;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
skb_push(skb,1); /* LAPB internal control */
|
skb_push(skb, 1); /* LAPB internal control */
|
||||||
memcpy(skb_put(skb,count), sl->rbuff, count);
|
memcpy(skb_put(skb, count), sl->rbuff, count);
|
||||||
skb->protocol = x25_type_trans(skb, sl->dev);
|
skb->protocol = x25_type_trans(skb, sl->dev);
|
||||||
if((err=lapb_data_received(skb->dev, skb))!=LAPB_OK)
|
err = lapb_data_received(skb->dev, skb);
|
||||||
{
|
if (err != LAPB_OK) {
|
||||||
kfree_skb(skb);
|
kfree_skb(skb);
|
||||||
printk(KERN_DEBUG "x25_asy: data received err - %d\n",err);
|
printk(KERN_DEBUG "x25_asy: data received err - %d\n", err);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
netif_rx(skb);
|
netif_rx(skb);
|
||||||
sl->dev->last_rx = jiffies;
|
sl->dev->last_rx = jiffies;
|
||||||
sl->stats.rx_packets++;
|
sl->stats.rx_packets++;
|
||||||
|
@ -224,10 +221,11 @@ static void x25_asy_encaps(struct x25_asy *sl, unsigned char *icp, int len)
|
||||||
unsigned char *p;
|
unsigned char *p;
|
||||||
int actual, count, mtu = sl->dev->mtu;
|
int actual, count, mtu = sl->dev->mtu;
|
||||||
|
|
||||||
if (len > mtu)
|
if (len > mtu) {
|
||||||
{ /* Sigh, shouldn't occur BUT ... */
|
/* Sigh, shouldn't occur BUT ... */
|
||||||
len = mtu;
|
len = mtu;
|
||||||
printk ("%s: truncating oversized transmit packet!\n", sl->dev->name);
|
printk(KERN_DEBUG "%s: truncating oversized transmit packet!\n",
|
||||||
|
sl->dev->name);
|
||||||
sl->stats.tx_dropped++;
|
sl->stats.tx_dropped++;
|
||||||
x25_asy_unlock(sl);
|
x25_asy_unlock(sl);
|
||||||
return;
|
return;
|
||||||
|
@ -245,7 +243,7 @@ static void x25_asy_encaps(struct x25_asy *sl, unsigned char *icp, int len)
|
||||||
* 14 Oct 1994 Dmitry Gorodchanin.
|
* 14 Oct 1994 Dmitry Gorodchanin.
|
||||||
*/
|
*/
|
||||||
sl->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
|
sl->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
|
||||||
actual = sl->tty->driver->write(sl->tty, sl->xbuff, count);
|
actual = sl->tty->ops->write(sl->tty, sl->xbuff, count);
|
||||||
sl->xleft = count - actual;
|
sl->xleft = count - actual;
|
||||||
sl->xhead = sl->xbuff + actual;
|
sl->xhead = sl->xbuff + actual;
|
||||||
/* VSV */
|
/* VSV */
|
||||||
|
@ -265,8 +263,7 @@ static void x25_asy_write_wakeup(struct tty_struct *tty)
|
||||||
if (!sl || sl->magic != X25_ASY_MAGIC || !netif_running(sl->dev))
|
if (!sl || sl->magic != X25_ASY_MAGIC || !netif_running(sl->dev))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (sl->xleft <= 0)
|
if (sl->xleft <= 0) {
|
||||||
{
|
|
||||||
/* Now serial buffer is almost free & we can start
|
/* Now serial buffer is almost free & we can start
|
||||||
* transmission of another packet */
|
* transmission of another packet */
|
||||||
sl->stats.tx_packets++;
|
sl->stats.tx_packets++;
|
||||||
|
@ -275,14 +272,14 @@ static void x25_asy_write_wakeup(struct tty_struct *tty)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
actual = tty->driver->write(tty, sl->xhead, sl->xleft);
|
actual = tty->ops->write(tty, sl->xhead, sl->xleft);
|
||||||
sl->xleft -= actual;
|
sl->xleft -= actual;
|
||||||
sl->xhead += actual;
|
sl->xhead += actual;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void x25_asy_timeout(struct net_device *dev)
|
static void x25_asy_timeout(struct net_device *dev)
|
||||||
{
|
{
|
||||||
struct x25_asy *sl = (struct x25_asy*)(dev->priv);
|
struct x25_asy *sl = dev->priv;
|
||||||
|
|
||||||
spin_lock(&sl->lock);
|
spin_lock(&sl->lock);
|
||||||
if (netif_queue_stopped(dev)) {
|
if (netif_queue_stopped(dev)) {
|
||||||
|
@ -290,7 +287,7 @@ static void x25_asy_timeout(struct net_device *dev)
|
||||||
* 14 Oct 1994 Dmitry Gorodchanin.
|
* 14 Oct 1994 Dmitry Gorodchanin.
|
||||||
*/
|
*/
|
||||||
printk(KERN_WARNING "%s: transmit timed out, %s?\n", dev->name,
|
printk(KERN_WARNING "%s: transmit timed out, %s?\n", dev->name,
|
||||||
(sl->tty->driver->chars_in_buffer(sl->tty) || sl->xleft) ?
|
(tty_chars_in_buffer(sl->tty) || sl->xleft) ?
|
||||||
"bad line quality" : "driver error");
|
"bad line quality" : "driver error");
|
||||||
sl->xleft = 0;
|
sl->xleft = 0;
|
||||||
sl->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
|
sl->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
|
||||||
|
@ -303,31 +300,34 @@ static void x25_asy_timeout(struct net_device *dev)
|
||||||
|
|
||||||
static int x25_asy_xmit(struct sk_buff *skb, struct net_device *dev)
|
static int x25_asy_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||||
{
|
{
|
||||||
struct x25_asy *sl = (struct x25_asy*)(dev->priv);
|
struct x25_asy *sl = dev->priv;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (!netif_running(sl->dev)) {
|
if (!netif_running(sl->dev)) {
|
||||||
printk("%s: xmit call when iface is down\n", dev->name);
|
printk(KERN_ERR "%s: xmit call when iface is down\n",
|
||||||
|
dev->name);
|
||||||
kfree_skb(skb);
|
kfree_skb(skb);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(skb->data[0])
|
switch (skb->data[0]) {
|
||||||
{
|
case 0x00:
|
||||||
case 0x00:break;
|
break;
|
||||||
case 0x01: /* Connection request .. do nothing */
|
case 0x01: /* Connection request .. do nothing */
|
||||||
if((err=lapb_connect_request(dev))!=LAPB_OK)
|
err = lapb_connect_request(dev);
|
||||||
printk(KERN_ERR "x25_asy: lapb_connect_request error - %d\n", err);
|
if (err != LAPB_OK)
|
||||||
kfree_skb(skb);
|
printk(KERN_ERR "x25_asy: lapb_connect_request error - %d\n", err);
|
||||||
return 0;
|
kfree_skb(skb);
|
||||||
case 0x02: /* Disconnect request .. do nothing - hang up ?? */
|
return 0;
|
||||||
if((err=lapb_disconnect_request(dev))!=LAPB_OK)
|
case 0x02: /* Disconnect request .. do nothing - hang up ?? */
|
||||||
printk(KERN_ERR "x25_asy: lapb_disconnect_request error - %d\n", err);
|
err = lapb_disconnect_request(dev);
|
||||||
default:
|
if (err != LAPB_OK)
|
||||||
kfree_skb(skb);
|
printk(KERN_ERR "x25_asy: lapb_disconnect_request error - %d\n", err);
|
||||||
return 0;
|
default:
|
||||||
|
kfree_skb(skb);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
skb_pull(skb,1); /* Remove control byte */
|
skb_pull(skb, 1); /* Remove control byte */
|
||||||
/*
|
/*
|
||||||
* If we are busy already- too bad. We ought to be able
|
* If we are busy already- too bad. We ought to be able
|
||||||
* to queue things at this point, to allow for a little
|
* to queue things at this point, to allow for a little
|
||||||
|
@ -338,10 +338,10 @@ static int x25_asy_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||||
* So, no queues !
|
* So, no queues !
|
||||||
* 14 Oct 1994 Dmitry Gorodchanin.
|
* 14 Oct 1994 Dmitry Gorodchanin.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if((err=lapb_data_request(dev,skb))!=LAPB_OK)
|
err = lapb_data_request(dev, skb);
|
||||||
{
|
if (err != LAPB_OK) {
|
||||||
printk(KERN_ERR "lapbeth: lapb_data_request error - %d\n", err);
|
printk(KERN_ERR "x25_asy: lapb_data_request error - %d\n", err);
|
||||||
kfree_skb(skb);
|
kfree_skb(skb);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -357,7 +357,7 @@ static int x25_asy_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||||
* Called when I frame data arrives. We did the work above - throw it
|
* Called when I frame data arrives. We did the work above - throw it
|
||||||
* at the net layer.
|
* at the net layer.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int x25_asy_data_indication(struct net_device *dev, struct sk_buff *skb)
|
static int x25_asy_data_indication(struct net_device *dev, struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
skb->dev->last_rx = jiffies;
|
skb->dev->last_rx = jiffies;
|
||||||
|
@ -369,24 +369,22 @@ static int x25_asy_data_indication(struct net_device *dev, struct sk_buff *skb)
|
||||||
* busy cases too well. Its tricky to see how to do this nicely -
|
* busy cases too well. Its tricky to see how to do this nicely -
|
||||||
* perhaps lapb should allow us to bounce this ?
|
* perhaps lapb should allow us to bounce this ?
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void x25_asy_data_transmit(struct net_device *dev, struct sk_buff *skb)
|
static void x25_asy_data_transmit(struct net_device *dev, struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
struct x25_asy *sl=dev->priv;
|
struct x25_asy *sl = dev->priv;
|
||||||
|
|
||||||
spin_lock(&sl->lock);
|
spin_lock(&sl->lock);
|
||||||
if (netif_queue_stopped(sl->dev) || sl->tty == NULL)
|
if (netif_queue_stopped(sl->dev) || sl->tty == NULL) {
|
||||||
{
|
|
||||||
spin_unlock(&sl->lock);
|
spin_unlock(&sl->lock);
|
||||||
printk(KERN_ERR "x25_asy: tbusy drop\n");
|
printk(KERN_ERR "x25_asy: tbusy drop\n");
|
||||||
kfree_skb(skb);
|
kfree_skb(skb);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* We were not busy, so we are now... :-) */
|
/* We were not busy, so we are now... :-) */
|
||||||
if (skb != NULL)
|
if (skb != NULL) {
|
||||||
{
|
|
||||||
x25_asy_lock(sl);
|
x25_asy_lock(sl);
|
||||||
sl->stats.tx_bytes+=skb->len;
|
sl->stats.tx_bytes += skb->len;
|
||||||
x25_asy_encaps(sl, skb->data, skb->len);
|
x25_asy_encaps(sl, skb->data, skb->len);
|
||||||
dev_kfree_skb(skb);
|
dev_kfree_skb(skb);
|
||||||
}
|
}
|
||||||
|
@ -396,15 +394,16 @@ static void x25_asy_data_transmit(struct net_device *dev, struct sk_buff *skb)
|
||||||
/*
|
/*
|
||||||
* LAPB connection establish/down information.
|
* LAPB connection establish/down information.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void x25_asy_connected(struct net_device *dev, int reason)
|
static void x25_asy_connected(struct net_device *dev, int reason)
|
||||||
{
|
{
|
||||||
struct x25_asy *sl = dev->priv;
|
struct x25_asy *sl = dev->priv;
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
unsigned char *ptr;
|
unsigned char *ptr;
|
||||||
|
|
||||||
if ((skb = dev_alloc_skb(1)) == NULL) {
|
skb = dev_alloc_skb(1);
|
||||||
printk(KERN_ERR "lapbeth: out of memory\n");
|
if (skb == NULL) {
|
||||||
|
printk(KERN_ERR "x25_asy: out of memory\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -422,7 +421,8 @@ static void x25_asy_disconnected(struct net_device *dev, int reason)
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
unsigned char *ptr;
|
unsigned char *ptr;
|
||||||
|
|
||||||
if ((skb = dev_alloc_skb(1)) == NULL) {
|
skb = dev_alloc_skb(1);
|
||||||
|
if (skb == NULL) {
|
||||||
printk(KERN_ERR "x25_asy: out of memory\n");
|
printk(KERN_ERR "x25_asy: out of memory\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -449,7 +449,7 @@ static struct lapb_register_struct x25_asy_callbacks = {
|
||||||
/* Open the low-level part of the X.25 channel. Easy! */
|
/* Open the low-level part of the X.25 channel. Easy! */
|
||||||
static int x25_asy_open(struct net_device *dev)
|
static int x25_asy_open(struct net_device *dev)
|
||||||
{
|
{
|
||||||
struct x25_asy *sl = (struct x25_asy*)(dev->priv);
|
struct x25_asy *sl = dev->priv;
|
||||||
unsigned long len;
|
unsigned long len;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
@ -466,13 +466,11 @@ static int x25_asy_open(struct net_device *dev)
|
||||||
len = dev->mtu * 2;
|
len = dev->mtu * 2;
|
||||||
|
|
||||||
sl->rbuff = kmalloc(len + 4, GFP_KERNEL);
|
sl->rbuff = kmalloc(len + 4, GFP_KERNEL);
|
||||||
if (sl->rbuff == NULL) {
|
if (sl->rbuff == NULL)
|
||||||
goto norbuff;
|
goto norbuff;
|
||||||
}
|
|
||||||
sl->xbuff = kmalloc(len + 4, GFP_KERNEL);
|
sl->xbuff = kmalloc(len + 4, GFP_KERNEL);
|
||||||
if (sl->xbuff == NULL) {
|
if (sl->xbuff == NULL)
|
||||||
goto noxbuff;
|
goto noxbuff;
|
||||||
}
|
|
||||||
|
|
||||||
sl->buffsize = len;
|
sl->buffsize = len;
|
||||||
sl->rcount = 0;
|
sl->rcount = 0;
|
||||||
|
@ -480,11 +478,12 @@ static int x25_asy_open(struct net_device *dev)
|
||||||
sl->flags &= (1 << SLF_INUSE); /* Clear ESCAPE & ERROR flags */
|
sl->flags &= (1 << SLF_INUSE); /* Clear ESCAPE & ERROR flags */
|
||||||
|
|
||||||
netif_start_queue(dev);
|
netif_start_queue(dev);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now attach LAPB
|
* Now attach LAPB
|
||||||
*/
|
*/
|
||||||
if((err=lapb_register(dev, &x25_asy_callbacks))==LAPB_OK)
|
err = lapb_register(dev, &x25_asy_callbacks);
|
||||||
|
if (err == LAPB_OK)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Cleanup */
|
/* Cleanup */
|
||||||
|
@ -499,18 +498,20 @@ norbuff:
|
||||||
/* Close the low-level part of the X.25 channel. Easy! */
|
/* Close the low-level part of the X.25 channel. Easy! */
|
||||||
static int x25_asy_close(struct net_device *dev)
|
static int x25_asy_close(struct net_device *dev)
|
||||||
{
|
{
|
||||||
struct x25_asy *sl = (struct x25_asy*)(dev->priv);
|
struct x25_asy *sl = dev->priv;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
spin_lock(&sl->lock);
|
spin_lock(&sl->lock);
|
||||||
if (sl->tty)
|
if (sl->tty)
|
||||||
sl->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
|
sl->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
|
||||||
|
|
||||||
netif_stop_queue(dev);
|
netif_stop_queue(dev);
|
||||||
sl->rcount = 0;
|
sl->rcount = 0;
|
||||||
sl->xleft = 0;
|
sl->xleft = 0;
|
||||||
if((err=lapb_unregister(dev))!=LAPB_OK)
|
err = lapb_unregister(dev);
|
||||||
printk(KERN_ERR "x25_asy_close: lapb_unregister error -%d\n",err);
|
if (err != LAPB_OK)
|
||||||
|
printk(KERN_ERR "x25_asy_close: lapb_unregister error -%d\n",
|
||||||
|
err);
|
||||||
spin_unlock(&sl->lock);
|
spin_unlock(&sl->lock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -521,8 +522,9 @@ static int x25_asy_close(struct net_device *dev)
|
||||||
* a block of X.25 data has been received, which can now be decapsulated
|
* a block of X.25 data has been received, which can now be decapsulated
|
||||||
* and sent on to some IP layer for further processing.
|
* and sent on to some IP layer for further processing.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void x25_asy_receive_buf(struct tty_struct *tty, const unsigned char *cp, char *fp, int count)
|
static void x25_asy_receive_buf(struct tty_struct *tty,
|
||||||
|
const unsigned char *cp, char *fp, int count)
|
||||||
{
|
{
|
||||||
struct x25_asy *sl = (struct x25_asy *) tty->disc_data;
|
struct x25_asy *sl = (struct x25_asy *) tty->disc_data;
|
||||||
|
|
||||||
|
@ -533,9 +535,8 @@ static void x25_asy_receive_buf(struct tty_struct *tty, const unsigned char *cp,
|
||||||
/* Read the characters out of the buffer */
|
/* Read the characters out of the buffer */
|
||||||
while (count--) {
|
while (count--) {
|
||||||
if (fp && *fp++) {
|
if (fp && *fp++) {
|
||||||
if (!test_and_set_bit(SLF_ERROR, &sl->flags)) {
|
if (!test_and_set_bit(SLF_ERROR, &sl->flags))
|
||||||
sl->stats.rx_errors++;
|
sl->stats.rx_errors++;
|
||||||
}
|
|
||||||
cp++;
|
cp++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -556,31 +557,31 @@ static int x25_asy_open_tty(struct tty_struct *tty)
|
||||||
struct x25_asy *sl = (struct x25_asy *) tty->disc_data;
|
struct x25_asy *sl = (struct x25_asy *) tty->disc_data;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
if (tty->ops->write == NULL)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
/* First make sure we're not already connected. */
|
/* First make sure we're not already connected. */
|
||||||
if (sl && sl->magic == X25_ASY_MAGIC) {
|
if (sl && sl->magic == X25_ASY_MAGIC)
|
||||||
return -EEXIST;
|
return -EEXIST;
|
||||||
}
|
|
||||||
|
|
||||||
/* OK. Find a free X.25 channel to use. */
|
/* OK. Find a free X.25 channel to use. */
|
||||||
if ((sl = x25_asy_alloc()) == NULL) {
|
sl = x25_asy_alloc();
|
||||||
|
if (sl == NULL)
|
||||||
return -ENFILE;
|
return -ENFILE;
|
||||||
}
|
|
||||||
|
|
||||||
sl->tty = tty;
|
sl->tty = tty;
|
||||||
tty->disc_data = sl;
|
tty->disc_data = sl;
|
||||||
tty->receive_room = 65536;
|
tty->receive_room = 65536;
|
||||||
if (tty->driver->flush_buffer) {
|
tty_driver_flush_buffer(tty);
|
||||||
tty->driver->flush_buffer(tty);
|
|
||||||
}
|
|
||||||
tty_ldisc_flush(tty);
|
tty_ldisc_flush(tty);
|
||||||
|
|
||||||
/* Restore default settings */
|
/* Restore default settings */
|
||||||
sl->dev->type = ARPHRD_X25;
|
sl->dev->type = ARPHRD_X25;
|
||||||
|
|
||||||
/* Perform the low-level X.25 async init */
|
|
||||||
if ((err = x25_asy_open(sl->dev)))
|
|
||||||
return err;
|
|
||||||
|
|
||||||
|
/* Perform the low-level X.25 async init */
|
||||||
|
err = x25_asy_open(sl->dev);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
/* Done. We have linked the TTY line to a channel. */
|
/* Done. We have linked the TTY line to a channel. */
|
||||||
return sl->dev->base_addr;
|
return sl->dev->base_addr;
|
||||||
}
|
}
|
||||||
|
@ -601,9 +602,7 @@ static void x25_asy_close_tty(struct tty_struct *tty)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (sl->dev->flags & IFF_UP)
|
if (sl->dev->flags & IFF_UP)
|
||||||
{
|
dev_close(sl->dev);
|
||||||
(void) dev_close(sl->dev);
|
|
||||||
}
|
|
||||||
|
|
||||||
tty->disc_data = NULL;
|
tty->disc_data = NULL;
|
||||||
sl->tty = NULL;
|
sl->tty = NULL;
|
||||||
|
@ -613,8 +612,7 @@ static void x25_asy_close_tty(struct tty_struct *tty)
|
||||||
|
|
||||||
static struct net_device_stats *x25_asy_get_stats(struct net_device *dev)
|
static struct net_device_stats *x25_asy_get_stats(struct net_device *dev)
|
||||||
{
|
{
|
||||||
struct x25_asy *sl = (struct x25_asy*)(dev->priv);
|
struct x25_asy *sl = dev->priv;
|
||||||
|
|
||||||
return &sl->stats;
|
return &sl->stats;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -641,21 +639,19 @@ int x25_asy_esc(unsigned char *s, unsigned char *d, int len)
|
||||||
* character sequence, according to the X.25 protocol.
|
* character sequence, according to the X.25 protocol.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
while (len-- > 0)
|
while (len-- > 0) {
|
||||||
{
|
switch (c = *s++) {
|
||||||
switch(c = *s++)
|
case X25_END:
|
||||||
{
|
*ptr++ = X25_ESC;
|
||||||
case X25_END:
|
*ptr++ = X25_ESCAPE(X25_END);
|
||||||
*ptr++ = X25_ESC;
|
break;
|
||||||
*ptr++ = X25_ESCAPE(X25_END);
|
case X25_ESC:
|
||||||
break;
|
*ptr++ = X25_ESC;
|
||||||
case X25_ESC:
|
*ptr++ = X25_ESCAPE(X25_ESC);
|
||||||
*ptr++ = X25_ESC;
|
break;
|
||||||
*ptr++ = X25_ESCAPE(X25_ESC);
|
default:
|
||||||
break;
|
*ptr++ = c;
|
||||||
default:
|
break;
|
||||||
*ptr++ = c;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*ptr++ = X25_END;
|
*ptr++ = X25_END;
|
||||||
|
@ -665,31 +661,25 @@ int x25_asy_esc(unsigned char *s, unsigned char *d, int len)
|
||||||
static void x25_asy_unesc(struct x25_asy *sl, unsigned char s)
|
static void x25_asy_unesc(struct x25_asy *sl, unsigned char s)
|
||||||
{
|
{
|
||||||
|
|
||||||
switch(s)
|
switch (s) {
|
||||||
{
|
case X25_END:
|
||||||
case X25_END:
|
if (!test_and_clear_bit(SLF_ERROR, &sl->flags)
|
||||||
if (!test_and_clear_bit(SLF_ERROR, &sl->flags) && (sl->rcount > 2))
|
&& sl->rcount > 2)
|
||||||
{
|
x25_asy_bump(sl);
|
||||||
x25_asy_bump(sl);
|
clear_bit(SLF_ESCAPE, &sl->flags);
|
||||||
}
|
sl->rcount = 0;
|
||||||
clear_bit(SLF_ESCAPE, &sl->flags);
|
return;
|
||||||
sl->rcount = 0;
|
case X25_ESC:
|
||||||
return;
|
set_bit(SLF_ESCAPE, &sl->flags);
|
||||||
|
return;
|
||||||
case X25_ESC:
|
case X25_ESCAPE(X25_ESC):
|
||||||
set_bit(SLF_ESCAPE, &sl->flags);
|
case X25_ESCAPE(X25_END):
|
||||||
return;
|
if (test_and_clear_bit(SLF_ESCAPE, &sl->flags))
|
||||||
|
s = X25_UNESCAPE(s);
|
||||||
case X25_ESCAPE(X25_ESC):
|
break;
|
||||||
case X25_ESCAPE(X25_END):
|
|
||||||
if (test_and_clear_bit(SLF_ESCAPE, &sl->flags))
|
|
||||||
s = X25_UNESCAPE(s);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
if (!test_bit(SLF_ERROR, &sl->flags))
|
if (!test_bit(SLF_ERROR, &sl->flags)) {
|
||||||
{
|
if (sl->rcount < sl->buffsize) {
|
||||||
if (sl->rcount < sl->buffsize)
|
|
||||||
{
|
|
||||||
sl->rbuff[sl->rcount++] = s;
|
sl->rbuff[sl->rcount++] = s;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -709,7 +699,7 @@ static int x25_asy_ioctl(struct tty_struct *tty, struct file *file,
|
||||||
if (!sl || sl->magic != X25_ASY_MAGIC)
|
if (!sl || sl->magic != X25_ASY_MAGIC)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
switch(cmd) {
|
switch (cmd) {
|
||||||
case SIOCGIFNAME:
|
case SIOCGIFNAME:
|
||||||
if (copy_to_user((void __user *)arg, sl->dev->name,
|
if (copy_to_user((void __user *)arg, sl->dev->name,
|
||||||
strlen(sl->dev->name) + 1))
|
strlen(sl->dev->name) + 1))
|
||||||
|
@ -724,8 +714,8 @@ static int x25_asy_ioctl(struct tty_struct *tty, struct file *file,
|
||||||
|
|
||||||
static int x25_asy_open_dev(struct net_device *dev)
|
static int x25_asy_open_dev(struct net_device *dev)
|
||||||
{
|
{
|
||||||
struct x25_asy *sl = (struct x25_asy*)(dev->priv);
|
struct x25_asy *sl = dev->priv;
|
||||||
if(sl->tty==NULL)
|
if (sl->tty == NULL)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -741,9 +731,9 @@ static void x25_asy_setup(struct net_device *dev)
|
||||||
set_bit(SLF_INUSE, &sl->flags);
|
set_bit(SLF_INUSE, &sl->flags);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Finish setting up the DEVICE info.
|
* Finish setting up the DEVICE info.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
dev->mtu = SL_MTU;
|
dev->mtu = SL_MTU;
|
||||||
dev->hard_start_xmit = x25_asy_xmit;
|
dev->hard_start_xmit = x25_asy_xmit;
|
||||||
dev->tx_timeout = x25_asy_timeout;
|
dev->tx_timeout = x25_asy_timeout;
|
||||||
|
@ -778,9 +768,10 @@ static int __init init_x25_asy(void)
|
||||||
x25_asy_maxdev = 4; /* Sanity */
|
x25_asy_maxdev = 4; /* Sanity */
|
||||||
|
|
||||||
printk(KERN_INFO "X.25 async: version 0.00 ALPHA "
|
printk(KERN_INFO "X.25 async: version 0.00 ALPHA "
|
||||||
"(dynamic channels, max=%d).\n", x25_asy_maxdev );
|
"(dynamic channels, max=%d).\n", x25_asy_maxdev);
|
||||||
|
|
||||||
x25_asy_devs = kcalloc(x25_asy_maxdev, sizeof(struct net_device*), GFP_KERNEL);
|
x25_asy_devs = kcalloc(x25_asy_maxdev, sizeof(struct net_device *),
|
||||||
|
GFP_KERNEL);
|
||||||
if (!x25_asy_devs) {
|
if (!x25_asy_devs) {
|
||||||
printk(KERN_WARNING "X25 async: Can't allocate x25_asy_ctrls[] "
|
printk(KERN_WARNING "X25 async: Can't allocate x25_asy_ctrls[] "
|
||||||
"array! Uaargh! (-> No X.25 available)\n");
|
"array! Uaargh! (-> No X.25 available)\n");
|
||||||
|
@ -802,7 +793,7 @@ static void __exit exit_x25_asy(void)
|
||||||
struct x25_asy *sl = dev->priv;
|
struct x25_asy *sl = dev->priv;
|
||||||
|
|
||||||
spin_lock_bh(&sl->lock);
|
spin_lock_bh(&sl->lock);
|
||||||
if (sl->tty)
|
if (sl->tty)
|
||||||
tty_hangup(sl->tty);
|
tty_hangup(sl->tty);
|
||||||
|
|
||||||
spin_unlock_bh(&sl->lock);
|
spin_unlock_bh(&sl->lock);
|
||||||
|
|
|
@ -96,12 +96,14 @@ static void cleanup_kgdboc(void)
|
||||||
|
|
||||||
static int kgdboc_get_char(void)
|
static int kgdboc_get_char(void)
|
||||||
{
|
{
|
||||||
return kgdb_tty_driver->poll_get_char(kgdb_tty_driver, kgdb_tty_line);
|
return kgdb_tty_driver->ops->poll_get_char(kgdb_tty_driver,
|
||||||
|
kgdb_tty_line);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void kgdboc_put_char(u8 chr)
|
static void kgdboc_put_char(u8 chr)
|
||||||
{
|
{
|
||||||
kgdb_tty_driver->poll_put_char(kgdb_tty_driver, kgdb_tty_line, chr);
|
kgdb_tty_driver->ops->poll_put_char(kgdb_tty_driver,
|
||||||
|
kgdb_tty_line, chr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int param_set_kgdboc_var(const char *kmessage, struct kernel_param *kp)
|
static int param_set_kgdboc_var(const char *kmessage, struct kernel_param *kp)
|
||||||
|
|
|
@ -532,15 +532,25 @@ uart_write(struct tty_struct *tty, const unsigned char *buf, int count)
|
||||||
static int uart_write_room(struct tty_struct *tty)
|
static int uart_write_room(struct tty_struct *tty)
|
||||||
{
|
{
|
||||||
struct uart_state *state = tty->driver_data;
|
struct uart_state *state = tty->driver_data;
|
||||||
|
unsigned long flags;
|
||||||
|
int ret;
|
||||||
|
|
||||||
return uart_circ_chars_free(&state->info->xmit);
|
spin_lock_irqsave(&state->port->lock, flags);
|
||||||
|
ret = uart_circ_chars_free(&state->info->xmit);
|
||||||
|
spin_unlock_irqrestore(&state->port->lock, flags);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int uart_chars_in_buffer(struct tty_struct *tty)
|
static int uart_chars_in_buffer(struct tty_struct *tty)
|
||||||
{
|
{
|
||||||
struct uart_state *state = tty->driver_data;
|
struct uart_state *state = tty->driver_data;
|
||||||
|
unsigned long flags;
|
||||||
|
int ret;
|
||||||
|
|
||||||
return uart_circ_chars_pending(&state->info->xmit);
|
spin_lock_irqsave(&state->port->lock, flags);
|
||||||
|
ret = uart_circ_chars_pending(&state->info->xmit);
|
||||||
|
spin_unlock_irqrestore(&state->port->lock, flags);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void uart_flush_buffer(struct tty_struct *tty)
|
static void uart_flush_buffer(struct tty_struct *tty)
|
||||||
|
@ -622,6 +632,11 @@ static int uart_get_info(struct uart_state *state,
|
||||||
struct serial_struct tmp;
|
struct serial_struct tmp;
|
||||||
|
|
||||||
memset(&tmp, 0, sizeof(tmp));
|
memset(&tmp, 0, sizeof(tmp));
|
||||||
|
|
||||||
|
/* Ensure the state we copy is consistent and no hardware changes
|
||||||
|
occur as we go */
|
||||||
|
mutex_lock(&state->mutex);
|
||||||
|
|
||||||
tmp.type = port->type;
|
tmp.type = port->type;
|
||||||
tmp.line = port->line;
|
tmp.line = port->line;
|
||||||
tmp.port = port->iobase;
|
tmp.port = port->iobase;
|
||||||
|
@ -641,6 +656,8 @@ static int uart_get_info(struct uart_state *state,
|
||||||
tmp.iomem_reg_shift = port->regshift;
|
tmp.iomem_reg_shift = port->regshift;
|
||||||
tmp.iomem_base = (void *)(unsigned long)port->mapbase;
|
tmp.iomem_base = (void *)(unsigned long)port->mapbase;
|
||||||
|
|
||||||
|
mutex_unlock(&state->mutex);
|
||||||
|
|
||||||
if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
|
if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -918,14 +935,12 @@ static void uart_break_ctl(struct tty_struct *tty, int break_state)
|
||||||
struct uart_state *state = tty->driver_data;
|
struct uart_state *state = tty->driver_data;
|
||||||
struct uart_port *port = state->port;
|
struct uart_port *port = state->port;
|
||||||
|
|
||||||
lock_kernel();
|
|
||||||
mutex_lock(&state->mutex);
|
mutex_lock(&state->mutex);
|
||||||
|
|
||||||
if (port->type != PORT_UNKNOWN)
|
if (port->type != PORT_UNKNOWN)
|
||||||
port->ops->break_ctl(port, break_state);
|
port->ops->break_ctl(port, break_state);
|
||||||
|
|
||||||
mutex_unlock(&state->mutex);
|
mutex_unlock(&state->mutex);
|
||||||
unlock_kernel();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int uart_do_autoconfig(struct uart_state *state)
|
static int uart_do_autoconfig(struct uart_state *state)
|
||||||
|
@ -1074,7 +1089,6 @@ uart_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd,
|
||||||
int ret = -ENOIOCTLCMD;
|
int ret = -ENOIOCTLCMD;
|
||||||
|
|
||||||
|
|
||||||
lock_kernel();
|
|
||||||
/*
|
/*
|
||||||
* These ioctls don't rely on the hardware to be present.
|
* These ioctls don't rely on the hardware to be present.
|
||||||
*/
|
*/
|
||||||
|
@ -1144,10 +1158,9 @@ uart_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
out_up:
|
out_up:
|
||||||
mutex_unlock(&state->mutex);
|
mutex_unlock(&state->mutex);
|
||||||
out:
|
out:
|
||||||
unlock_kernel();
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1173,7 +1186,6 @@ static void uart_set_termios(struct tty_struct *tty,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
lock_kernel();
|
|
||||||
uart_change_speed(state, old_termios);
|
uart_change_speed(state, old_termios);
|
||||||
|
|
||||||
/* Handle transition to B0 status */
|
/* Handle transition to B0 status */
|
||||||
|
@ -1206,7 +1218,6 @@ static void uart_set_termios(struct tty_struct *tty,
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&state->port->lock, flags);
|
spin_unlock_irqrestore(&state->port->lock, flags);
|
||||||
}
|
}
|
||||||
unlock_kernel();
|
|
||||||
#if 0
|
#if 0
|
||||||
/*
|
/*
|
||||||
* No need to wake up processes in open wait, since they
|
* No need to wake up processes in open wait, since they
|
||||||
|
@ -1322,11 +1333,11 @@ static void uart_wait_until_sent(struct tty_struct *tty, int timeout)
|
||||||
struct uart_port *port = state->port;
|
struct uart_port *port = state->port;
|
||||||
unsigned long char_time, expire;
|
unsigned long char_time, expire;
|
||||||
|
|
||||||
BUG_ON(!kernel_locked());
|
|
||||||
|
|
||||||
if (port->type == PORT_UNKNOWN || port->fifosize == 0)
|
if (port->type == PORT_UNKNOWN || port->fifosize == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
lock_kernel();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set the check interval to be 1/5 of the estimated time to
|
* Set the check interval to be 1/5 of the estimated time to
|
||||||
* send a single character, and make it at least 1. The check
|
* send a single character, and make it at least 1. The check
|
||||||
|
@ -1372,6 +1383,7 @@ static void uart_wait_until_sent(struct tty_struct *tty, int timeout)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
set_current_state(TASK_RUNNING); /* might not be needed */
|
set_current_state(TASK_RUNNING); /* might not be needed */
|
||||||
|
unlock_kernel();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2085,7 +2097,9 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *port)
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
uart_change_pm(state, 0);
|
uart_change_pm(state, 0);
|
||||||
|
spin_lock_irq(&port->lock);
|
||||||
ops->set_mctrl(port, 0);
|
ops->set_mctrl(port, 0);
|
||||||
|
spin_unlock_irq(&port->lock);
|
||||||
ret = ops->startup(port);
|
ret = ops->startup(port);
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
uart_change_speed(state, NULL);
|
uart_change_speed(state, NULL);
|
||||||
|
|
|
@ -1421,8 +1421,7 @@ static void digi_close(struct usb_serial_port *port, struct file *filp)
|
||||||
tty_wait_until_sent(tty, DIGI_CLOSE_TIMEOUT);
|
tty_wait_until_sent(tty, DIGI_CLOSE_TIMEOUT);
|
||||||
|
|
||||||
/* flush driver and line discipline buffers */
|
/* flush driver and line discipline buffers */
|
||||||
if (tty->driver->flush_buffer)
|
tty_driver_flush_buffer(tty);
|
||||||
tty->driver->flush_buffer(tty);
|
|
||||||
tty_ldisc_flush(tty);
|
tty_ldisc_flush(tty);
|
||||||
|
|
||||||
if (port->serial->dev) {
|
if (port->serial->dev) {
|
||||||
|
|
|
@ -296,16 +296,14 @@ static int serial_write (struct tty_struct * tty, const unsigned char *buf, int
|
||||||
struct usb_serial_port *port = tty->driver_data;
|
struct usb_serial_port *port = tty->driver_data;
|
||||||
int retval = -ENODEV;
|
int retval = -ENODEV;
|
||||||
|
|
||||||
if (!port || port->serial->dev->state == USB_STATE_NOTATTACHED)
|
if (port->serial->dev->state == USB_STATE_NOTATTACHED)
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
dbg("%s - port %d, %d byte(s)", __func__, port->number, count);
|
dbg("%s - port %d, %d byte(s)", __func__, port->number, count);
|
||||||
|
|
||||||
if (!port->open_count) {
|
/* open_count is managed under the mutex lock for the tty so cannot
|
||||||
retval = -EINVAL;
|
drop to zero until after the last close completes */
|
||||||
dbg("%s - port not opened", __func__);
|
WARN_ON(!port->open_count);
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* pass on to the driver specific version of this function */
|
/* pass on to the driver specific version of this function */
|
||||||
retval = port->serial->type->write(port, buf, count);
|
retval = port->serial->type->write(port, buf, count);
|
||||||
|
@ -317,61 +315,28 @@ exit:
|
||||||
static int serial_write_room (struct tty_struct *tty)
|
static int serial_write_room (struct tty_struct *tty)
|
||||||
{
|
{
|
||||||
struct usb_serial_port *port = tty->driver_data;
|
struct usb_serial_port *port = tty->driver_data;
|
||||||
int retval = -ENODEV;
|
|
||||||
|
|
||||||
if (!port)
|
|
||||||
goto exit;
|
|
||||||
|
|
||||||
dbg("%s - port %d", __func__, port->number);
|
dbg("%s - port %d", __func__, port->number);
|
||||||
|
WARN_ON(!port->open_count);
|
||||||
if (!port->open_count) {
|
|
||||||
dbg("%s - port not open", __func__);
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* pass on to the driver specific version of this function */
|
/* pass on to the driver specific version of this function */
|
||||||
retval = port->serial->type->write_room(port);
|
return port->serial->type->write_room(port);
|
||||||
|
|
||||||
exit:
|
|
||||||
return retval;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int serial_chars_in_buffer (struct tty_struct *tty)
|
static int serial_chars_in_buffer (struct tty_struct *tty)
|
||||||
{
|
{
|
||||||
struct usb_serial_port *port = tty->driver_data;
|
struct usb_serial_port *port = tty->driver_data;
|
||||||
int retval = -ENODEV;
|
|
||||||
|
|
||||||
if (!port)
|
|
||||||
goto exit;
|
|
||||||
|
|
||||||
dbg("%s = port %d", __func__, port->number);
|
dbg("%s = port %d", __func__, port->number);
|
||||||
|
|
||||||
if (!port->open_count) {
|
WARN_ON(!port->open_count);
|
||||||
dbg("%s - port not open", __func__);
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* pass on to the driver specific version of this function */
|
/* pass on to the driver specific version of this function */
|
||||||
retval = port->serial->type->chars_in_buffer(port);
|
return port->serial->type->chars_in_buffer(port);
|
||||||
|
|
||||||
exit:
|
|
||||||
return retval;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void serial_throttle (struct tty_struct * tty)
|
static void serial_throttle (struct tty_struct * tty)
|
||||||
{
|
{
|
||||||
struct usb_serial_port *port = tty->driver_data;
|
struct usb_serial_port *port = tty->driver_data;
|
||||||
|
|
||||||
if (!port)
|
|
||||||
return;
|
|
||||||
|
|
||||||
dbg("%s - port %d", __func__, port->number);
|
dbg("%s - port %d", __func__, port->number);
|
||||||
|
|
||||||
if (!port->open_count) {
|
WARN_ON(!port->open_count);
|
||||||
dbg ("%s - port not open", __func__);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* pass on to the driver specific version of this function */
|
/* pass on to the driver specific version of this function */
|
||||||
if (port->serial->type->throttle)
|
if (port->serial->type->throttle)
|
||||||
port->serial->type->throttle(port);
|
port->serial->type->throttle(port);
|
||||||
|
@ -380,17 +345,9 @@ static void serial_throttle (struct tty_struct * tty)
|
||||||
static void serial_unthrottle (struct tty_struct * tty)
|
static void serial_unthrottle (struct tty_struct * tty)
|
||||||
{
|
{
|
||||||
struct usb_serial_port *port = tty->driver_data;
|
struct usb_serial_port *port = tty->driver_data;
|
||||||
|
|
||||||
if (!port)
|
|
||||||
return;
|
|
||||||
|
|
||||||
dbg("%s - port %d", __func__, port->number);
|
dbg("%s - port %d", __func__, port->number);
|
||||||
|
|
||||||
if (!port->open_count) {
|
WARN_ON(!port->open_count);
|
||||||
dbg("%s - port not open", __func__);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* pass on to the driver specific version of this function */
|
/* pass on to the driver specific version of this function */
|
||||||
if (port->serial->type->unthrottle)
|
if (port->serial->type->unthrottle)
|
||||||
port->serial->type->unthrottle(port);
|
port->serial->type->unthrottle(port);
|
||||||
|
@ -401,42 +358,27 @@ static int serial_ioctl (struct tty_struct *tty, struct file * file, unsigned in
|
||||||
struct usb_serial_port *port = tty->driver_data;
|
struct usb_serial_port *port = tty->driver_data;
|
||||||
int retval = -ENODEV;
|
int retval = -ENODEV;
|
||||||
|
|
||||||
lock_kernel();
|
|
||||||
if (!port)
|
|
||||||
goto exit;
|
|
||||||
|
|
||||||
dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd);
|
dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd);
|
||||||
|
|
||||||
/* Caution - port->open_count is BKL protected */
|
WARN_ON(!port->open_count);
|
||||||
if (!port->open_count) {
|
|
||||||
dbg ("%s - port not open", __func__);
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* pass on to the driver specific version of this function if it is available */
|
/* pass on to the driver specific version of this function if it is available */
|
||||||
if (port->serial->type->ioctl)
|
if (port->serial->type->ioctl) {
|
||||||
|
lock_kernel();
|
||||||
retval = port->serial->type->ioctl(port, file, cmd, arg);
|
retval = port->serial->type->ioctl(port, file, cmd, arg);
|
||||||
|
unlock_kernel();
|
||||||
|
}
|
||||||
else
|
else
|
||||||
retval = -ENOIOCTLCMD;
|
retval = -ENOIOCTLCMD;
|
||||||
exit:
|
|
||||||
unlock_kernel();
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void serial_set_termios (struct tty_struct *tty, struct ktermios * old)
|
static void serial_set_termios (struct tty_struct *tty, struct ktermios * old)
|
||||||
{
|
{
|
||||||
struct usb_serial_port *port = tty->driver_data;
|
struct usb_serial_port *port = tty->driver_data;
|
||||||
|
|
||||||
if (!port)
|
|
||||||
return;
|
|
||||||
|
|
||||||
dbg("%s - port %d", __func__, port->number);
|
dbg("%s - port %d", __func__, port->number);
|
||||||
|
|
||||||
if (!port->open_count) {
|
WARN_ON(!port->open_count);
|
||||||
dbg("%s - port not open", __func__);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* pass on to the driver specific version of this function if it is available */
|
/* pass on to the driver specific version of this function if it is available */
|
||||||
if (port->serial->type->set_termios)
|
if (port->serial->type->set_termios)
|
||||||
port->serial->type->set_termios(port, old);
|
port->serial->type->set_termios(port, old);
|
||||||
|
@ -448,24 +390,15 @@ static void serial_break (struct tty_struct *tty, int break_state)
|
||||||
{
|
{
|
||||||
struct usb_serial_port *port = tty->driver_data;
|
struct usb_serial_port *port = tty->driver_data;
|
||||||
|
|
||||||
lock_kernel();
|
|
||||||
if (!port) {
|
|
||||||
unlock_kernel();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
dbg("%s - port %d", __func__, port->number);
|
dbg("%s - port %d", __func__, port->number);
|
||||||
|
|
||||||
if (!port->open_count) {
|
WARN_ON(!port->open_count);
|
||||||
dbg("%s - port not open", __func__);
|
|
||||||
unlock_kernel();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* pass on to the driver specific version of this function if it is available */
|
/* pass on to the driver specific version of this function if it is available */
|
||||||
if (port->serial->type->break_ctl)
|
if (port->serial->type->break_ctl) {
|
||||||
|
lock_kernel();
|
||||||
port->serial->type->break_ctl(port, break_state);
|
port->serial->type->break_ctl(port, break_state);
|
||||||
unlock_kernel();
|
unlock_kernel();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int serial_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data)
|
static int serial_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data)
|
||||||
|
@ -519,19 +452,11 @@ static int serial_tiocmget (struct tty_struct *tty, struct file *file)
|
||||||
{
|
{
|
||||||
struct usb_serial_port *port = tty->driver_data;
|
struct usb_serial_port *port = tty->driver_data;
|
||||||
|
|
||||||
if (!port)
|
|
||||||
return -ENODEV;
|
|
||||||
|
|
||||||
dbg("%s - port %d", __func__, port->number);
|
dbg("%s - port %d", __func__, port->number);
|
||||||
|
|
||||||
if (!port->open_count) {
|
WARN_ON(!port->open_count);
|
||||||
dbg("%s - port not open", __func__);
|
|
||||||
return -ENODEV;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (port->serial->type->tiocmget)
|
if (port->serial->type->tiocmget)
|
||||||
return port->serial->type->tiocmget(port, file);
|
return port->serial->type->tiocmget(port, file);
|
||||||
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -540,19 +465,11 @@ static int serial_tiocmset (struct tty_struct *tty, struct file *file,
|
||||||
{
|
{
|
||||||
struct usb_serial_port *port = tty->driver_data;
|
struct usb_serial_port *port = tty->driver_data;
|
||||||
|
|
||||||
if (!port)
|
|
||||||
return -ENODEV;
|
|
||||||
|
|
||||||
dbg("%s - port %d", __func__, port->number);
|
dbg("%s - port %d", __func__, port->number);
|
||||||
|
|
||||||
if (!port->open_count) {
|
WARN_ON(!port->open_count);
|
||||||
dbg("%s - port not open", __func__);
|
|
||||||
return -ENODEV;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (port->serial->type->tiocmset)
|
if (port->serial->type->tiocmset)
|
||||||
return port->serial->type->tiocmset(port, file, set, clear);
|
return port->serial->type->tiocmset(port, file, set, clear);
|
||||||
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -673,15 +673,13 @@ static void whiteheat_close(struct usb_serial_port *port, struct file * filp)
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (port->tty->driver->flush_buffer)
|
tty_driver_flush_buffer(port->tty);
|
||||||
port->tty->driver->flush_buffer(port->tty);
|
|
||||||
tty_ldisc_flush(port->tty);
|
tty_ldisc_flush(port->tty);
|
||||||
|
|
||||||
firm_report_tx_done(port);
|
firm_report_tx_done(port);
|
||||||
|
|
||||||
firm_close(port);
|
firm_close(port);
|
||||||
|
|
||||||
printk(KERN_ERR"Before processing rx_urbs_submitted.\n");
|
|
||||||
/* shutdown our bulk reads and writes */
|
/* shutdown our bulk reads and writes */
|
||||||
mutex_lock(&info->deathwarrant);
|
mutex_lock(&info->deathwarrant);
|
||||||
spin_lock_irq(&info->lock);
|
spin_lock_irq(&info->lock);
|
||||||
|
|
|
@ -1053,7 +1053,7 @@ static int vt_check(struct file *file)
|
||||||
if (tty_paranoia_check(tty, inode, "tty_ioctl"))
|
if (tty_paranoia_check(tty, inode, "tty_ioctl"))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (tty->driver->ioctl != vt_ioctl)
|
if (tty->ops->ioctl != vt_ioctl)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
vc = (struct vc_data *)tty->driver_data;
|
vc = (struct vc_data *)tty->driver_data;
|
||||||
|
|
|
@ -192,16 +192,14 @@ void proc_tty_register_driver(struct tty_driver *driver)
|
||||||
{
|
{
|
||||||
struct proc_dir_entry *ent;
|
struct proc_dir_entry *ent;
|
||||||
|
|
||||||
if ((!driver->read_proc && !driver->write_proc) ||
|
if (!driver->ops->read_proc || !driver->driver_name ||
|
||||||
!driver->driver_name ||
|
|
||||||
driver->proc_entry)
|
driver->proc_entry)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ent = create_proc_entry(driver->driver_name, 0, proc_tty_driver);
|
ent = create_proc_entry(driver->driver_name, 0, proc_tty_driver);
|
||||||
if (!ent)
|
if (!ent)
|
||||||
return;
|
return;
|
||||||
ent->read_proc = driver->read_proc;
|
ent->read_proc = driver->ops->read_proc;
|
||||||
ent->write_proc = driver->write_proc;
|
|
||||||
ent->owner = driver->owner;
|
ent->owner = driver->owner;
|
||||||
ent->data = driver;
|
ent->data = driver;
|
||||||
|
|
||||||
|
|
|
@ -177,9 +177,13 @@ struct signal_struct;
|
||||||
* size each time the window is created or resized anyway.
|
* size each time the window is created or resized anyway.
|
||||||
* - TYT, 9/14/92
|
* - TYT, 9/14/92
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
struct tty_operations;
|
||||||
|
|
||||||
struct tty_struct {
|
struct tty_struct {
|
||||||
int magic;
|
int magic;
|
||||||
struct tty_driver *driver;
|
struct tty_driver *driver;
|
||||||
|
const struct tty_operations *ops;
|
||||||
int index;
|
int index;
|
||||||
struct tty_ldisc ldisc;
|
struct tty_ldisc ldisc;
|
||||||
struct mutex termios_mutex;
|
struct mutex termios_mutex;
|
||||||
|
@ -295,6 +299,10 @@ extern void tty_unregister_device(struct tty_driver *driver, unsigned index);
|
||||||
extern int tty_read_raw_data(struct tty_struct *tty, unsigned char *bufp,
|
extern int tty_read_raw_data(struct tty_struct *tty, unsigned char *bufp,
|
||||||
int buflen);
|
int buflen);
|
||||||
extern void tty_write_message(struct tty_struct *tty, char *msg);
|
extern void tty_write_message(struct tty_struct *tty, char *msg);
|
||||||
|
extern int tty_put_char(struct tty_struct *tty, unsigned char c);
|
||||||
|
extern int tty_chars_in_buffer(struct tty_struct *tty);
|
||||||
|
extern int tty_write_room(struct tty_struct *tty);
|
||||||
|
extern void tty_driver_flush_buffer(struct tty_struct *tty);
|
||||||
|
|
||||||
extern int is_current_pgrp_orphaned(void);
|
extern int is_current_pgrp_orphaned(void);
|
||||||
extern struct pid *tty_get_pgrp(struct tty_struct *tty);
|
extern struct pid *tty_get_pgrp(struct tty_struct *tty);
|
||||||
|
|
|
@ -12,11 +12,15 @@
|
||||||
* This routine is called when a particular tty device is opened.
|
* This routine is called when a particular tty device is opened.
|
||||||
* This routine is mandatory; if this routine is not filled in,
|
* This routine is mandatory; if this routine is not filled in,
|
||||||
* the attempted open will fail with ENODEV.
|
* the attempted open will fail with ENODEV.
|
||||||
|
*
|
||||||
|
* Required method.
|
||||||
*
|
*
|
||||||
* void (*close)(struct tty_struct * tty, struct file * filp);
|
* void (*close)(struct tty_struct * tty, struct file * filp);
|
||||||
*
|
*
|
||||||
* This routine is called when a particular tty device is closed.
|
* This routine is called when a particular tty device is closed.
|
||||||
*
|
*
|
||||||
|
* Required method.
|
||||||
|
*
|
||||||
* int (*write)(struct tty_struct * tty,
|
* int (*write)(struct tty_struct * tty,
|
||||||
* const unsigned char *buf, int count);
|
* const unsigned char *buf, int count);
|
||||||
*
|
*
|
||||||
|
@ -26,7 +30,9 @@
|
||||||
* number of characters actually accepted for writing. This
|
* number of characters actually accepted for writing. This
|
||||||
* routine is mandatory.
|
* routine is mandatory.
|
||||||
*
|
*
|
||||||
* void (*put_char)(struct tty_struct *tty, unsigned char ch);
|
* Optional: Required for writable devices.
|
||||||
|
*
|
||||||
|
* int (*put_char)(struct tty_struct *tty, unsigned char ch);
|
||||||
*
|
*
|
||||||
* This routine is called by the kernel to write a single
|
* This routine is called by the kernel to write a single
|
||||||
* character to the tty device. If the kernel uses this routine,
|
* character to the tty device. If the kernel uses this routine,
|
||||||
|
@ -34,10 +40,18 @@
|
||||||
* done stuffing characters into the driver. If there is no room
|
* done stuffing characters into the driver. If there is no room
|
||||||
* in the queue, the character is ignored.
|
* in the queue, the character is ignored.
|
||||||
*
|
*
|
||||||
|
* Optional: Kernel will use the write method if not provided.
|
||||||
|
*
|
||||||
|
* Note: Do not call this function directly, call tty_put_char
|
||||||
|
*
|
||||||
* void (*flush_chars)(struct tty_struct *tty);
|
* void (*flush_chars)(struct tty_struct *tty);
|
||||||
*
|
*
|
||||||
* This routine is called by the kernel after it has written a
|
* This routine is called by the kernel after it has written a
|
||||||
* series of characters to the tty device using put_char().
|
* series of characters to the tty device using put_char().
|
||||||
|
*
|
||||||
|
* Optional:
|
||||||
|
*
|
||||||
|
* Note: Do not call this function directly, call tty_driver_flush_chars
|
||||||
*
|
*
|
||||||
* int (*write_room)(struct tty_struct *tty);
|
* int (*write_room)(struct tty_struct *tty);
|
||||||
*
|
*
|
||||||
|
@ -45,6 +59,10 @@
|
||||||
* will accept for queuing to be written. This number is subject
|
* will accept for queuing to be written. This number is subject
|
||||||
* to change as output buffers get emptied, or if the output flow
|
* to change as output buffers get emptied, or if the output flow
|
||||||
* control is acted.
|
* control is acted.
|
||||||
|
*
|
||||||
|
* Required if write method is provided else not needed.
|
||||||
|
*
|
||||||
|
* Note: Do not call this function directly, call tty_write_room
|
||||||
*
|
*
|
||||||
* int (*ioctl)(struct tty_struct *tty, struct file * file,
|
* int (*ioctl)(struct tty_struct *tty, struct file * file,
|
||||||
* unsigned int cmd, unsigned long arg);
|
* unsigned int cmd, unsigned long arg);
|
||||||
|
@ -53,22 +71,29 @@
|
||||||
* device-specific ioctl's. If the ioctl number passed in cmd
|
* device-specific ioctl's. If the ioctl number passed in cmd
|
||||||
* is not recognized by the driver, it should return ENOIOCTLCMD.
|
* is not recognized by the driver, it should return ENOIOCTLCMD.
|
||||||
*
|
*
|
||||||
|
* Optional
|
||||||
|
*
|
||||||
* long (*compat_ioctl)(struct tty_struct *tty, struct file * file,
|
* long (*compat_ioctl)(struct tty_struct *tty, struct file * file,
|
||||||
* unsigned int cmd, unsigned long arg);
|
* unsigned int cmd, unsigned long arg);
|
||||||
*
|
*
|
||||||
* implement ioctl processing for 32 bit process on 64 bit system
|
* implement ioctl processing for 32 bit process on 64 bit system
|
||||||
|
*
|
||||||
|
* Optional
|
||||||
*
|
*
|
||||||
* void (*set_termios)(struct tty_struct *tty, struct ktermios * old);
|
* void (*set_termios)(struct tty_struct *tty, struct ktermios * old);
|
||||||
*
|
*
|
||||||
* This routine allows the tty driver to be notified when
|
* This routine allows the tty driver to be notified when
|
||||||
* device's termios settings have changed. Note that a
|
* device's termios settings have changed.
|
||||||
* well-designed tty driver should be prepared to accept the case
|
*
|
||||||
* where old == NULL, and try to do something rational.
|
* Optional: Called under the termios lock
|
||||||
|
*
|
||||||
*
|
*
|
||||||
* void (*set_ldisc)(struct tty_struct *tty);
|
* void (*set_ldisc)(struct tty_struct *tty);
|
||||||
*
|
*
|
||||||
* This routine allows the tty driver to be notified when the
|
* This routine allows the tty driver to be notified when the
|
||||||
* device's termios settings have changed.
|
* device's termios settings have changed.
|
||||||
|
*
|
||||||
|
* Optional: Called under BKL (currently)
|
||||||
*
|
*
|
||||||
* void (*throttle)(struct tty_struct * tty);
|
* void (*throttle)(struct tty_struct * tty);
|
||||||
*
|
*
|
||||||
|
@ -86,17 +111,27 @@
|
||||||
*
|
*
|
||||||
* This routine notifies the tty driver that it should stop
|
* This routine notifies the tty driver that it should stop
|
||||||
* outputting characters to the tty device.
|
* outputting characters to the tty device.
|
||||||
|
*
|
||||||
|
* Optional:
|
||||||
|
*
|
||||||
|
* Note: Call stop_tty not this method.
|
||||||
*
|
*
|
||||||
* void (*start)(struct tty_struct *tty);
|
* void (*start)(struct tty_struct *tty);
|
||||||
*
|
*
|
||||||
* This routine notifies the tty driver that it resume sending
|
* This routine notifies the tty driver that it resume sending
|
||||||
* characters to the tty device.
|
* characters to the tty device.
|
||||||
|
*
|
||||||
|
* Optional:
|
||||||
|
*
|
||||||
|
* Note: Call start_tty not this method.
|
||||||
*
|
*
|
||||||
* void (*hangup)(struct tty_struct *tty);
|
* void (*hangup)(struct tty_struct *tty);
|
||||||
*
|
*
|
||||||
* This routine notifies the tty driver that it should hangup the
|
* This routine notifies the tty driver that it should hangup the
|
||||||
* tty device.
|
* tty device.
|
||||||
*
|
*
|
||||||
|
* Required:
|
||||||
|
*
|
||||||
* void (*break_ctl)(struct tty_stuct *tty, int state);
|
* void (*break_ctl)(struct tty_stuct *tty, int state);
|
||||||
*
|
*
|
||||||
* This optional routine requests the tty driver to turn on or
|
* This optional routine requests the tty driver to turn on or
|
||||||
|
@ -106,18 +141,26 @@
|
||||||
*
|
*
|
||||||
* If this routine is implemented, the high-level tty driver will
|
* If this routine is implemented, the high-level tty driver will
|
||||||
* handle the following ioctls: TCSBRK, TCSBRKP, TIOCSBRK,
|
* handle the following ioctls: TCSBRK, TCSBRKP, TIOCSBRK,
|
||||||
* TIOCCBRK. Otherwise, these ioctls will be passed down to the
|
* TIOCCBRK.
|
||||||
* driver to handle.
|
*
|
||||||
|
* Optional: Required for TCSBRK/BRKP/etc handling.
|
||||||
*
|
*
|
||||||
* void (*wait_until_sent)(struct tty_struct *tty, int timeout);
|
* void (*wait_until_sent)(struct tty_struct *tty, int timeout);
|
||||||
*
|
*
|
||||||
* This routine waits until the device has written out all of the
|
* This routine waits until the device has written out all of the
|
||||||
* characters in its transmitter FIFO.
|
* characters in its transmitter FIFO.
|
||||||
*
|
*
|
||||||
|
* Optional: If not provided the device is assumed to have no FIFO
|
||||||
|
*
|
||||||
|
* Note: Usually correct to call tty_wait_until_sent
|
||||||
|
*
|
||||||
* void (*send_xchar)(struct tty_struct *tty, char ch);
|
* void (*send_xchar)(struct tty_struct *tty, char ch);
|
||||||
*
|
*
|
||||||
* This routine is used to send a high-priority XON/XOFF
|
* This routine is used to send a high-priority XON/XOFF
|
||||||
* character to the device.
|
* character to the device.
|
||||||
|
*
|
||||||
|
* Optional: If not provided then the write method is called under
|
||||||
|
* the atomic write lock to keep it serialized with the ldisc.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
|
@ -132,7 +175,7 @@ struct tty_operations {
|
||||||
void (*close)(struct tty_struct * tty, struct file * filp);
|
void (*close)(struct tty_struct * tty, struct file * filp);
|
||||||
int (*write)(struct tty_struct * tty,
|
int (*write)(struct tty_struct * tty,
|
||||||
const unsigned char *buf, int count);
|
const unsigned char *buf, int count);
|
||||||
void (*put_char)(struct tty_struct *tty, unsigned char ch);
|
int (*put_char)(struct tty_struct *tty, unsigned char ch);
|
||||||
void (*flush_chars)(struct tty_struct *tty);
|
void (*flush_chars)(struct tty_struct *tty);
|
||||||
int (*write_room)(struct tty_struct *tty);
|
int (*write_room)(struct tty_struct *tty);
|
||||||
int (*chars_in_buffer)(struct tty_struct *tty);
|
int (*chars_in_buffer)(struct tty_struct *tty);
|
||||||
|
@ -153,8 +196,6 @@ struct tty_operations {
|
||||||
void (*send_xchar)(struct tty_struct *tty, char ch);
|
void (*send_xchar)(struct tty_struct *tty, char ch);
|
||||||
int (*read_proc)(char *page, char **start, off_t off,
|
int (*read_proc)(char *page, char **start, off_t off,
|
||||||
int count, int *eof, void *data);
|
int count, int *eof, void *data);
|
||||||
int (*write_proc)(struct file *file, const char __user *buffer,
|
|
||||||
unsigned long count, void *data);
|
|
||||||
int (*tiocmget)(struct tty_struct *tty, struct file *file);
|
int (*tiocmget)(struct tty_struct *tty, struct file *file);
|
||||||
int (*tiocmset)(struct tty_struct *tty, struct file *file,
|
int (*tiocmset)(struct tty_struct *tty, struct file *file,
|
||||||
unsigned int set, unsigned int clear);
|
unsigned int set, unsigned int clear);
|
||||||
|
@ -190,48 +231,13 @@ struct tty_driver {
|
||||||
struct tty_struct **ttys;
|
struct tty_struct **ttys;
|
||||||
struct ktermios **termios;
|
struct ktermios **termios;
|
||||||
struct ktermios **termios_locked;
|
struct ktermios **termios_locked;
|
||||||
void *driver_state; /* only used for the PTY driver */
|
void *driver_state;
|
||||||
|
|
||||||
/*
|
|
||||||
* Interface routines from the upper tty layer to the tty
|
|
||||||
* driver. Will be replaced with struct tty_operations.
|
|
||||||
*/
|
|
||||||
int (*open)(struct tty_struct * tty, struct file * filp);
|
|
||||||
void (*close)(struct tty_struct * tty, struct file * filp);
|
|
||||||
int (*write)(struct tty_struct * tty,
|
|
||||||
const unsigned char *buf, int count);
|
|
||||||
void (*put_char)(struct tty_struct *tty, unsigned char ch);
|
|
||||||
void (*flush_chars)(struct tty_struct *tty);
|
|
||||||
int (*write_room)(struct tty_struct *tty);
|
|
||||||
int (*chars_in_buffer)(struct tty_struct *tty);
|
|
||||||
int (*ioctl)(struct tty_struct *tty, struct file * file,
|
|
||||||
unsigned int cmd, unsigned long arg);
|
|
||||||
long (*compat_ioctl)(struct tty_struct *tty, struct file * file,
|
|
||||||
unsigned int cmd, unsigned long arg);
|
|
||||||
void (*set_termios)(struct tty_struct *tty, struct ktermios * old);
|
|
||||||
void (*throttle)(struct tty_struct * tty);
|
|
||||||
void (*unthrottle)(struct tty_struct * tty);
|
|
||||||
void (*stop)(struct tty_struct *tty);
|
|
||||||
void (*start)(struct tty_struct *tty);
|
|
||||||
void (*hangup)(struct tty_struct *tty);
|
|
||||||
void (*break_ctl)(struct tty_struct *tty, int state);
|
|
||||||
void (*flush_buffer)(struct tty_struct *tty);
|
|
||||||
void (*set_ldisc)(struct tty_struct *tty);
|
|
||||||
void (*wait_until_sent)(struct tty_struct *tty, int timeout);
|
|
||||||
void (*send_xchar)(struct tty_struct *tty, char ch);
|
|
||||||
int (*read_proc)(char *page, char **start, off_t off,
|
|
||||||
int count, int *eof, void *data);
|
|
||||||
int (*write_proc)(struct file *file, const char __user *buffer,
|
|
||||||
unsigned long count, void *data);
|
|
||||||
int (*tiocmget)(struct tty_struct *tty, struct file *file);
|
|
||||||
int (*tiocmset)(struct tty_struct *tty, struct file *file,
|
|
||||||
unsigned int set, unsigned int clear);
|
|
||||||
#ifdef CONFIG_CONSOLE_POLL
|
|
||||||
int (*poll_init)(struct tty_driver *driver, int line, char *options);
|
|
||||||
int (*poll_get_char)(struct tty_driver *driver, int line);
|
|
||||||
void (*poll_put_char)(struct tty_driver *driver, int line, char ch);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Driver methods
|
||||||
|
*/
|
||||||
|
|
||||||
|
const struct tty_operations *ops;
|
||||||
struct list_head tty_drivers;
|
struct list_head tty_drivers;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1272,8 +1272,8 @@ late_initcall(disable_boot_consoles);
|
||||||
*/
|
*/
|
||||||
void tty_write_message(struct tty_struct *tty, char *msg)
|
void tty_write_message(struct tty_struct *tty, char *msg)
|
||||||
{
|
{
|
||||||
if (tty && tty->driver->write)
|
if (tty && tty->ops->write)
|
||||||
tty->driver->write(tty, msg, strlen(msg));
|
tty->ops->write(tty, msg, strlen(msg));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -555,10 +555,8 @@ static void ircomm_tty_close(struct tty_struct *tty, struct file *filp)
|
||||||
|
|
||||||
ircomm_tty_shutdown(self);
|
ircomm_tty_shutdown(self);
|
||||||
|
|
||||||
if (tty->driver->flush_buffer)
|
tty_driver_flush_buffer(tty);
|
||||||
tty->driver->flush_buffer(tty);
|
tty_ldisc_flush(tty);
|
||||||
if (tty->ldisc.flush_buffer)
|
|
||||||
tty->ldisc.flush_buffer(tty);
|
|
||||||
|
|
||||||
tty->closing = 0;
|
tty->closing = 0;
|
||||||
self->tty = NULL;
|
self->tty = NULL;
|
||||||
|
|
Loading…
Reference in a new issue