Commit 0587102c authored by Alan Cox's avatar Alan Cox Committed by Greg Kroah-Hartman

tty: icount changeover for other main devices

Again basically cut and paste

Convert the main driver set to use the hooks for GICOUNT
Signed-off-by: default avatarAlan Cox <alan@linux.intel.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 0bca1b91
...@@ -395,7 +395,7 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file, ...@@ -395,7 +395,7 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
{ {
if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
(cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) && (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) &&
(cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) { (cmd != TIOCMIWAIT)) {
if (tty->flags & (1 << TTY_IO_ERROR)) if (tty->flags & (1 << TTY_IO_ERROR))
return -EIO; return -EIO;
} }
...@@ -433,16 +433,6 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file, ...@@ -433,16 +433,6 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
case TIOCMIWAIT: case TIOCMIWAIT:
printk(KERN_INFO "rs_ioctl: TIOCMIWAIT: called\n"); printk(KERN_INFO "rs_ioctl: TIOCMIWAIT: called\n");
return 0; return 0;
/*
* Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
* Return: write counters to the user passed counter struct
* NB: both 1->0 and 0->1 transitions are counted except for
* RI where only 0->1 is counted.
*/
case TIOCGICOUNT:
printk(KERN_INFO "rs_ioctl: TIOCGICOUNT called\n");
return 0;
case TIOCSERGWILD: case TIOCSERGWILD:
case TIOCSERSWILD: case TIOCSERSWILD:
/* "setserial -W" is called in Debian boot */ /* "setserial -W" is called in Debian boot */
......
...@@ -1263,6 +1263,36 @@ static int rs_break(struct tty_struct *tty, int break_state) ...@@ -1263,6 +1263,36 @@ static int rs_break(struct tty_struct *tty, int break_state)
return 0; return 0;
} }
/*
* Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
* Return: write counters to the user passed counter struct
* NB: both 1->0 and 0->1 transitions are counted except for
* RI where only 0->1 is counted.
*/
static int rs_get_icount(struct tty_struct *tty,
struct serial_icounter_struct *icount)
{
struct async_struct *info = tty->driver_data;
struct async_icount cnow;
unsigned long flags;
local_irq_save(flags);
cnow = info->state->icount;
local_irq_restore(flags);
icount->cts = cnow.cts;
icount->dsr = cnow.dsr;
icount->rng = cnow.rng;
icount->dcd = cnow.dcd;
icount->rx = cnow.rx;
icount->tx = cnow.tx;
icount->frame = cnow.frame;
icount->overrun = cnow.overrun;
icount->parity = cnow.parity;
icount->brk = cnow.brk;
icount->buf_overrun = cnow.buf_overrun;
return 0;
}
static int rs_ioctl(struct tty_struct *tty, struct file * file, static int rs_ioctl(struct tty_struct *tty, struct file * file,
unsigned int cmd, unsigned long arg) unsigned int cmd, unsigned long arg)
...@@ -1332,31 +1362,6 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file, ...@@ -1332,31 +1362,6 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
} }
/* NOTREACHED */ /* NOTREACHED */
/*
* Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
* Return: write counters to the user passed counter struct
* NB: both 1->0 and 0->1 transitions are counted except for
* RI where only 0->1 is counted.
*/
case TIOCGICOUNT:
local_irq_save(flags);
cnow = info->state->icount;
local_irq_restore(flags);
icount.cts = cnow.cts;
icount.dsr = cnow.dsr;
icount.rng = cnow.rng;
icount.dcd = cnow.dcd;
icount.rx = cnow.rx;
icount.tx = cnow.tx;
icount.frame = cnow.frame;
icount.overrun = cnow.overrun;
icount.parity = cnow.parity;
icount.brk = cnow.brk;
icount.buf_overrun = cnow.buf_overrun;
if (copy_to_user(argp, &icount, sizeof(icount)))
return -EFAULT;
return 0;
case TIOCSERGWILD: case TIOCSERGWILD:
case TIOCSERSWILD: case TIOCSERSWILD:
/* "setserial -W" is called in Debian boot */ /* "setserial -W" is called in Debian boot */
...@@ -1958,6 +1963,7 @@ static const struct tty_operations serial_ops = { ...@@ -1958,6 +1963,7 @@ static const struct tty_operations serial_ops = {
.wait_until_sent = rs_wait_until_sent, .wait_until_sent = rs_wait_until_sent,
.tiocmget = rs_tiocmget, .tiocmget = rs_tiocmget,
.tiocmset = rs_tiocmset, .tiocmset = rs_tiocmset,
.get_icount = rs_get_icount,
.proc_fops = &rs_proc_fops, .proc_fops = &rs_proc_fops,
}; };
......
...@@ -2790,29 +2790,6 @@ cy_ioctl(struct tty_struct *tty, struct file *file, ...@@ -2790,29 +2790,6 @@ cy_ioctl(struct tty_struct *tty, struct file *file,
* NB: both 1->0 and 0->1 transitions are counted except for * NB: both 1->0 and 0->1 transitions are counted except for
* RI where only 0->1 is counted. * RI where only 0->1 is counted.
*/ */
case TIOCGICOUNT: {
struct serial_icounter_struct sic = { };
spin_lock_irqsave(&info->card->card_lock, flags);
cnow = info->icount;
spin_unlock_irqrestore(&info->card->card_lock, flags);
sic.cts = cnow.cts;
sic.dsr = cnow.dsr;
sic.rng = cnow.rng;
sic.dcd = cnow.dcd;
sic.rx = cnow.rx;
sic.tx = cnow.tx;
sic.frame = cnow.frame;
sic.overrun = cnow.overrun;
sic.parity = cnow.parity;
sic.brk = cnow.brk;
sic.buf_overrun = cnow.buf_overrun;
if (copy_to_user(argp, &sic, sizeof(sic)))
ret_val = -EFAULT;
break;
}
default: default:
ret_val = -ENOIOCTLCMD; ret_val = -ENOIOCTLCMD;
} }
...@@ -2823,6 +2800,31 @@ cy_ioctl(struct tty_struct *tty, struct file *file, ...@@ -2823,6 +2800,31 @@ cy_ioctl(struct tty_struct *tty, struct file *file,
return ret_val; return ret_val;
} /* cy_ioctl */ } /* cy_ioctl */
static int cy_get_icount(struct tty_struct *tty,
struct serial_icounter_struct *sic)
{
struct cyclades_port *info = tty->driver_data;
struct cyclades_icount cnow; /* Used to snapshot */
unsigned long flags;
spin_lock_irqsave(&info->card->card_lock, flags);
cnow = info->icount;
spin_unlock_irqrestore(&info->card->card_lock, flags);
sic->cts = cnow.cts;
sic->dsr = cnow.dsr;
sic->rng = cnow.rng;
sic->dcd = cnow.dcd;
sic->rx = cnow.rx;
sic->tx = cnow.tx;
sic->frame = cnow.frame;
sic->overrun = cnow.overrun;
sic->parity = cnow.parity;
sic->brk = cnow.brk;
sic->buf_overrun = cnow.buf_overrun;
return 0;
}
/* /*
* 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. Note that a
...@@ -4084,6 +4086,7 @@ static const struct tty_operations cy_ops = { ...@@ -4084,6 +4086,7 @@ static const struct tty_operations cy_ops = {
.wait_until_sent = cy_wait_until_sent, .wait_until_sent = cy_wait_until_sent,
.tiocmget = cy_tiocmget, .tiocmget = cy_tiocmget,
.tiocmset = cy_tiocmset, .tiocmset = cy_tiocmset,
.get_icount = cy_get_icount,
.proc_fops = &cyclades_proc_fops, .proc_fops = &cyclades_proc_fops,
}; };
......
...@@ -183,6 +183,8 @@ static void ip2_hangup(PTTY); ...@@ -183,6 +183,8 @@ static void ip2_hangup(PTTY);
static int ip2_tiocmget(struct tty_struct *tty, struct file *file); static int ip2_tiocmget(struct tty_struct *tty, struct file *file);
static int ip2_tiocmset(struct tty_struct *tty, struct file *file, static int ip2_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear); unsigned int set, unsigned int clear);
static int ip2_get_icount(struct tty_struct *tty,
struct serial_icounter_struct *icount);
static void set_irq(int, int); static void set_irq(int, int);
static void ip2_interrupt_bh(struct work_struct *work); static void ip2_interrupt_bh(struct work_struct *work);
...@@ -454,6 +456,7 @@ static const struct tty_operations ip2_ops = { ...@@ -454,6 +456,7 @@ static const struct tty_operations ip2_ops = {
.hangup = ip2_hangup, .hangup = ip2_hangup,
.tiocmget = ip2_tiocmget, .tiocmget = ip2_tiocmget,
.tiocmset = ip2_tiocmset, .tiocmset = ip2_tiocmset,
.get_icount = ip2_get_icount,
.proc_fops = &ip2_proc_fops, .proc_fops = &ip2_proc_fops,
}; };
...@@ -2128,7 +2131,6 @@ ip2_ioctl ( PTTY tty, struct file *pFile, UINT cmd, ULONG arg ) ...@@ -2128,7 +2131,6 @@ ip2_ioctl ( PTTY tty, struct file *pFile, UINT cmd, ULONG arg )
i2ChanStrPtr pCh = DevTable[tty->index]; i2ChanStrPtr pCh = DevTable[tty->index];
i2eBordStrPtr pB; i2eBordStrPtr pB;
struct async_icount cprev, cnow; /* kernel counter temps */ struct async_icount cprev, cnow; /* kernel counter temps */
struct serial_icounter_struct __user *p_cuser;
int rc = 0; int rc = 0;
unsigned long flags; unsigned long flags;
void __user *argp = (void __user *)arg; void __user *argp = (void __user *)arg;
...@@ -2296,34 +2298,6 @@ ip2_ioctl ( PTTY tty, struct file *pFile, UINT cmd, ULONG arg ) ...@@ -2296,34 +2298,6 @@ ip2_ioctl ( PTTY tty, struct file *pFile, UINT cmd, ULONG arg )
return rc; return rc;
break; break;
/*
* Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
* Return: write counters to the user passed counter struct
* NB: both 1->0 and 0->1 transitions are counted except for RI where
* only 0->1 is counted. The controller is quite capable of counting
* both, but this done to preserve compatibility with the standard
* serial driver.
*/
case TIOCGICOUNT:
ip2trace (CHANN, ITRC_IOCTL, 11, 1, rc );
write_lock_irqsave(&pB->read_fifo_spinlock, flags);
cnow = pCh->icount;
write_unlock_irqrestore(&pB->read_fifo_spinlock, flags);
p_cuser = argp;
rc = put_user(cnow.cts, &p_cuser->cts);
rc = put_user(cnow.dsr, &p_cuser->dsr);
rc = put_user(cnow.rng, &p_cuser->rng);
rc = put_user(cnow.dcd, &p_cuser->dcd);
rc = put_user(cnow.rx, &p_cuser->rx);
rc = put_user(cnow.tx, &p_cuser->tx);
rc = put_user(cnow.frame, &p_cuser->frame);
rc = put_user(cnow.overrun, &p_cuser->overrun);
rc = put_user(cnow.parity, &p_cuser->parity);
rc = put_user(cnow.brk, &p_cuser->brk);
rc = put_user(cnow.buf_overrun, &p_cuser->buf_overrun);
break;
/* /*
* The rest are not supported by this driver. By returning -ENOIOCTLCMD they * The rest are not supported by this driver. By returning -ENOIOCTLCMD they
* will be passed to the line discipline for it to handle. * will be passed to the line discipline for it to handle.
...@@ -2348,6 +2322,46 @@ ip2_ioctl ( PTTY tty, struct file *pFile, UINT cmd, ULONG arg ) ...@@ -2348,6 +2322,46 @@ ip2_ioctl ( PTTY tty, struct file *pFile, UINT cmd, ULONG arg )
return rc; return rc;
} }
static int ip2_get_icount(struct tty_struct *tty,
struct serial_icounter_struct *icount)
{
i2ChanStrPtr pCh = DevTable[tty->index];
i2eBordStrPtr pB;
struct async_icount cnow; /* kernel counter temp */
unsigned long flags;
if ( pCh == NULL )
return -ENODEV;
pB = pCh->pMyBord;
/*
* Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
* Return: write counters to the user passed counter struct
* NB: both 1->0 and 0->1 transitions are counted except for RI where
* only 0->1 is counted. The controller is quite capable of counting
* both, but this done to preserve compatibility with the standard
* serial driver.
*/
write_lock_irqsave(&pB->read_fifo_spinlock, flags);
cnow = pCh->icount;
write_unlock_irqrestore(&pB->read_fifo_spinlock, flags);
icount->cts = cnow.cts;
icount->dsr = cnow.dsr;
icount->rng = cnow.rng;
icount->dcd = cnow.dcd;
icount->rx = cnow.rx;
icount->tx = cnow.tx;
icount->frame = cnow.frame;
icount->overrun = cnow.overrun;
icount->parity = cnow.parity;
icount->brk = cnow.brk;
icount->buf_overrun = cnow.buf_overrun;
return 0;
}
/******************************************************************************/ /******************************************************************************/
/* Function: GetSerialInfo() */ /* Function: GetSerialInfo() */
/* Parameters: Pointer to channel structure */ /* Parameters: Pointer to channel structure */
......
...@@ -1700,7 +1700,7 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, ...@@ -1700,7 +1700,7 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file,
return 0; return 0;
} }
if (cmd != TIOCGSERIAL && cmd != TIOCMIWAIT && cmd != TIOCGICOUNT && if (cmd != TIOCGSERIAL && cmd != TIOCMIWAIT &&
test_bit(TTY_IO_ERROR, &tty->flags)) test_bit(TTY_IO_ERROR, &tty->flags))
return -EIO; return -EIO;
...@@ -1730,32 +1730,6 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, ...@@ -1730,32 +1730,6 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file,
return wait_event_interruptible(info->port.delta_msr_wait, return wait_event_interruptible(info->port.delta_msr_wait,
mxser_cflags_changed(info, arg, &cnow)); mxser_cflags_changed(info, arg, &cnow));
/*
* Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
* Return: write counters to the user passed counter struct
* NB: both 1->0 and 0->1 transitions are counted except for
* RI where only 0->1 is counted.
*/
case TIOCGICOUNT: {
struct serial_icounter_struct icnt = { 0 };
spin_lock_irqsave(&info->slock, flags);
cnow = info->icount;
spin_unlock_irqrestore(&info->slock, flags);
icnt.frame = cnow.frame;
icnt.brk = cnow.brk;
icnt.overrun = cnow.overrun;
icnt.buf_overrun = cnow.buf_overrun;
icnt.parity = cnow.parity;
icnt.rx = cnow.rx;
icnt.tx = cnow.tx;
icnt.cts = cnow.cts;
icnt.dsr = cnow.dsr;
icnt.rng = cnow.rng;
icnt.dcd = cnow.dcd;
return copy_to_user(argp, &icnt, sizeof(icnt)) ? -EFAULT : 0;
}
case MOXA_HighSpeedOn: case MOXA_HighSpeedOn:
return put_user(info->baud_base != 115200 ? 1 : 0, (int __user *)argp); return put_user(info->baud_base != 115200 ? 1 : 0, (int __user *)argp);
case MOXA_SDS_RSTICOUNTER: case MOXA_SDS_RSTICOUNTER:
...@@ -1828,6 +1802,39 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, ...@@ -1828,6 +1802,39 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file,
return 0; return 0;
} }
/*
* Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
* Return: write counters to the user passed counter struct
* NB: both 1->0 and 0->1 transitions are counted except for
* RI where only 0->1 is counted.
*/
static int mxser_get_icount(struct tty_struct *tty,
struct serial_icounter_struct *icount)
{
struct mxser_port *info = tty->driver_data;
struct async_icount cnow;
unsigned long flags;
spin_lock_irqsave(&info->slock, flags);
cnow = info->icount;
spin_unlock_irqrestore(&info->slock, flags);
icount->frame = cnow.frame;
icount->brk = cnow.brk;
icount->overrun = cnow.overrun;
icount->buf_overrun = cnow.buf_overrun;
icount->parity = cnow.parity;
icount->rx = cnow.rx;
icount->tx = cnow.tx;
icount->cts = cnow.cts;
icount->dsr = cnow.dsr;
icount->rng = cnow.rng;
icount->dcd = cnow.dcd;
return 0;
}
static void mxser_stoprx(struct tty_struct *tty) static void mxser_stoprx(struct tty_struct *tty)
{ {
struct mxser_port *info = tty->driver_data; struct mxser_port *info = tty->driver_data;
...@@ -2326,6 +2333,7 @@ static const struct tty_operations mxser_ops = { ...@@ -2326,6 +2333,7 @@ static const struct tty_operations mxser_ops = {
.wait_until_sent = mxser_wait_until_sent, .wait_until_sent = mxser_wait_until_sent,
.tiocmget = mxser_tiocmget, .tiocmget = mxser_tiocmget,
.tiocmset = mxser_tiocmset, .tiocmset = mxser_tiocmset,
.get_icount = mxser_get_icount,
}; };
struct tty_port_operations mxser_port_ops = { struct tty_port_operations mxser_port_ops = {
......
...@@ -1804,24 +1804,24 @@ static int ntty_cflags_changed(struct port *port, unsigned long flags, ...@@ -1804,24 +1804,24 @@ static int ntty_cflags_changed(struct port *port, unsigned long flags,
return ret; return ret;
} }
static int ntty_ioctl_tiocgicount(struct port *port, void __user *argp) static int ntty_tiocgicount(struct tty_struct *tty,
struct serial_icounter_struct *icount)
{ {
struct port *port = tty->driver_data;
const struct async_icount cnow = port->tty_icount; const struct async_icount cnow = port->tty_icount;
struct serial_icounter_struct icount;
icount->cts = cnow.cts;
icount.cts = cnow.cts; icount->dsr = cnow.dsr;
icount.dsr = cnow.dsr; icount->rng = cnow.rng;
icount.rng = cnow.rng; icount->dcd = cnow.dcd;
icount.dcd = cnow.dcd; icount->rx = cnow.rx;
icount.rx = cnow.rx; icount->tx = cnow.tx;
icount.tx = cnow.tx; icount->frame = cnow.frame;
icount.frame = cnow.frame; icount->overrun = cnow.overrun;
icount.overrun = cnow.overrun; icount->parity = cnow.parity;
icount.parity = cnow.parity; icount->brk = cnow.brk;
icount.brk = cnow.brk; icount->buf_overrun = cnow.buf_overrun;
icount.buf_overrun = cnow.buf_overrun; return 0;
return copy_to_user(argp, &icount, sizeof(icount)) ? -EFAULT : 0;
} }
static int ntty_ioctl(struct tty_struct *tty, struct file *file, static int ntty_ioctl(struct tty_struct *tty, struct file *file,
...@@ -1840,9 +1840,7 @@ static int ntty_ioctl(struct tty_struct *tty, struct file *file, ...@@ -1840,9 +1840,7 @@ static int ntty_ioctl(struct tty_struct *tty, struct file *file,
rval = wait_event_interruptible(port->tty_wait, rval = wait_event_interruptible(port->tty_wait,
ntty_cflags_changed(port, arg, &cprev)); ntty_cflags_changed(port, arg, &cprev));
break; break;
} case TIOCGICOUNT: }
rval = ntty_ioctl_tiocgicount(port, argp);
break;
default: default:
DBG1("ERR: 0x%08X, %d", cmd, cmd); DBG1("ERR: 0x%08X, %d", cmd, cmd);
break; break;
...@@ -1922,6 +1920,7 @@ static const struct tty_operations tty_ops = { ...@@ -1922,6 +1920,7 @@ static const struct tty_operations tty_ops = {
.chars_in_buffer = ntty_chars_in_buffer, .chars_in_buffer = ntty_chars_in_buffer,
.tiocmget = ntty_tiocmget, .tiocmget = ntty_tiocmget,
.tiocmset = ntty_tiocmset, .tiocmset = ntty_tiocmset,
.get_icount = ntty_tiocgicount,
.install = ntty_install, .install = ntty_install,
.cleanup = ntty_cleanup, .cleanup = ntty_cleanup,
}; };
......
...@@ -2215,6 +2215,32 @@ static int mgslpc_break(struct tty_struct *tty, int break_state) ...@@ -2215,6 +2215,32 @@ static int mgslpc_break(struct tty_struct *tty, int break_state)
return 0; return 0;
} }
static int mgslpc_get_icount(struct tty_struct *tty,
struct serial_icounter_struct *icount)
{
MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data;
struct mgsl_icount cnow; /* kernel counter temps */
unsigned long flags;
spin_lock_irqsave(&info->lock,flags);
cnow = info->icount;
spin_unlock_irqrestore(&info->lock,flags);
icount->cts = cnow.cts;
icount->dsr = cnow.dsr;
icount->rng = cnow.rng;
icount->dcd = cnow.dcd;
icount->rx = cnow.rx;
icount->tx = cnow.tx;
icount->frame = cnow.frame;
icount->overrun = cnow.overrun;
icount->parity = cnow.parity;
icount->brk = cnow.brk;
icount->buf_overrun = cnow.buf_overrun;
return 0;
}
/* Service an IOCTL request /* Service an IOCTL request
* *
* Arguments: * Arguments:
...@@ -2230,11 +2256,7 @@ static int mgslpc_ioctl(struct tty_struct *tty, struct file * file, ...@@ -2230,11 +2256,7 @@ static int mgslpc_ioctl(struct tty_struct *tty, struct file * file,
unsigned int cmd, unsigned long arg) unsigned int cmd, unsigned long arg)
{ {
MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data; MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data;
int error;
struct mgsl_icount cnow; /* kernel counter temps */
struct serial_icounter_struct __user *p_cuser; /* user space */
void __user *argp = (void __user *)arg; void __user *argp = (void __user *)arg;
unsigned long flags;
if (debug_level >= DEBUG_LEVEL_INFO) if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):mgslpc_ioctl %s cmd=%08X\n", __FILE__,__LINE__, printk("%s(%d):mgslpc_ioctl %s cmd=%08X\n", __FILE__,__LINE__,
...@@ -2244,7 +2266,7 @@ static int mgslpc_ioctl(struct tty_struct *tty, struct file * file, ...@@ -2244,7 +2266,7 @@ static int mgslpc_ioctl(struct tty_struct *tty, struct file * file,
return -ENODEV; return -ENODEV;
if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
(cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) { (cmd != TIOCMIWAIT)) {
if (tty->flags & (1 << TTY_IO_ERROR)) if (tty->flags & (1 << TTY_IO_ERROR))
return -EIO; return -EIO;
} }
...@@ -2274,34 +2296,6 @@ static int mgslpc_ioctl(struct tty_struct *tty, struct file * file, ...@@ -2274,34 +2296,6 @@ static int mgslpc_ioctl(struct tty_struct *tty, struct file * file,
return wait_events(info, argp); return wait_events(info, argp);
case TIOCMIWAIT: case TIOCMIWAIT:
return modem_input_wait(info,(int)arg); return modem_input_wait(info,(int)arg);
case TIOCGICOUNT:
spin_lock_irqsave(&info->lock,flags);
cnow = info->icount;
spin_unlock_irqrestore(&info->lock,flags);
p_cuser = argp;
PUT_USER(error,cnow.cts, &p_cuser->cts);
if (error) return error;
PUT_USER(error,cnow.dsr, &p_cuser->dsr);
if (error) return error;
PUT_USER(error,cnow.rng, &p_cuser->rng);
if (error) return error;
PUT_USER(error,cnow.dcd, &p_cuser->dcd);
if (error) return error;
PUT_USER(error,cnow.rx, &p_cuser->rx);
if (error) return error;
PUT_USER(error,cnow.tx, &p_cuser->tx);
if (error) return error;
PUT_USER(error,cnow.frame, &p_cuser->frame);
if (error) return error;
PUT_USER(error,cnow.overrun, &p_cuser->overrun);
if (error) return error;
PUT_USER(error,cnow.parity, &p_cuser->parity);
if (error) return error;
PUT_USER(error,cnow.brk, &p_cuser->brk);
if (error) return error;
PUT_USER(error,cnow.buf_overrun, &p_cuser->buf_overrun);
if (error) return error;
return 0;
default: default:
return -ENOIOCTLCMD; return -ENOIOCTLCMD;
} }
......
...@@ -2925,6 +2925,38 @@ static int mgsl_break(struct tty_struct *tty, int break_state) ...@@ -2925,6 +2925,38 @@ static int mgsl_break(struct tty_struct *tty, int break_state)
} /* end of mgsl_break() */ } /* end of mgsl_break() */
/*
* Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
* Return: write counters to the user passed counter struct
* NB: both 1->0 and 0->1 transitions are counted except for
* RI where only 0->1 is counted.
*/
static int msgl_get_icount(struct tty_struct *tty,
struct serial_icounter_struct *icount)
{
struct mgsl_struct * info = tty->driver_data;
struct mgsl_icount cnow; /* kernel counter temps */
unsigned long flags;
spin_lock_irqsave(&info->irq_spinlock,flags);
cnow = info->icount;
spin_unlock_irqrestore(&info->irq_spinlock,flags);
icount->cts = cnow.cts;
icount->dsr = cnow.dsr;
icount->rng = cnow.rng;
icount->dcd = cnow.dcd;
icount->rx = cnow.rx;
icount->tx = cnow.tx;
icount->frame = cnow.frame;
icount->overrun = cnow.overrun;
icount->parity = cnow.parity;
icount->brk = cnow.brk;
icount->buf_overrun = cnow.buf_overrun;
return 0;
}
/* mgsl_ioctl() Service an IOCTL request /* mgsl_ioctl() Service an IOCTL request
* *
* Arguments: * Arguments:
...@@ -2949,7 +2981,7 @@ static int mgsl_ioctl(struct tty_struct *tty, struct file * file, ...@@ -2949,7 +2981,7 @@ static int mgsl_ioctl(struct tty_struct *tty, struct file * file,
return -ENODEV; return -ENODEV;
if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
(cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) { (cmd != TIOCMIWAIT)) {
if (tty->flags & (1 << TTY_IO_ERROR)) if (tty->flags & (1 << TTY_IO_ERROR))
return -EIO; return -EIO;
} }
...@@ -2959,11 +2991,7 @@ static int mgsl_ioctl(struct tty_struct *tty, struct file * file, ...@@ -2959,11 +2991,7 @@ static int mgsl_ioctl(struct tty_struct *tty, struct file * file,
static int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigned long arg) static int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigned long arg)
{ {
int error;
struct mgsl_icount cnow; /* kernel counter temps */
void __user *argp = (void __user *)arg; void __user *argp = (void __user *)arg;
struct serial_icounter_struct __user *p_cuser; /* user space */
unsigned long flags;
switch (cmd) { switch (cmd) {
case MGSL_IOCGPARAMS: case MGSL_IOCGPARAMS:
...@@ -2992,40 +3020,6 @@ static int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigne ...@@ -2992,40 +3020,6 @@ static int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigne
case TIOCMIWAIT: case TIOCMIWAIT:
return modem_input_wait(info,(int)arg); return modem_input_wait(info,(int)arg);
/*
* Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
* Return: write counters to the user passed counter struct
* NB: both 1->0 and 0->1 transitions are counted except for
* RI where only 0->1 is counted.
*/
case TIOCGICOUNT:
spin_lock_irqsave(&info->irq_spinlock,flags);
cnow = info->icount;
spin_unlock_irqrestore(&info->irq_spinlock,flags);
p_cuser = argp;
PUT_USER(error,cnow.cts, &p_cuser->cts);
if (error) return error;
PUT_USER(error,cnow.dsr, &p_cuser->dsr);
if (error) return error;
PUT_USER(error,cnow.rng, &p_cuser->rng);
if (error) return error;
PUT_USER(error,cnow.dcd, &p_cuser->dcd);
if (error) return error;
PUT_USER(error,cnow.rx, &p_cuser->rx);
if (error) return error;
PUT_USER(error,cnow.tx, &p_cuser->tx);
if (error) return error;
PUT_USER(error,cnow.frame, &p_cuser->frame);
if (error) return error;
PUT_USER(error,cnow.overrun, &p_cuser->overrun);
if (error) return error;
PUT_USER(error,cnow.parity, &p_cuser->parity);
if (error) return error;
PUT_USER(error,cnow.brk, &p_cuser->brk);
if (error) return error;
PUT_USER(error,cnow.buf_overrun, &p_cuser->buf_overrun);
if (error) return error;
return 0;
default: default:
return -ENOIOCTLCMD; return -ENOIOCTLCMD;
} }
...@@ -4328,6 +4322,7 @@ static const struct tty_operations mgsl_ops = { ...@@ -4328,6 +4322,7 @@ static const struct tty_operations mgsl_ops = {
.hangup = mgsl_hangup, .hangup = mgsl_hangup,
.tiocmget = tiocmget, .tiocmget = tiocmget,
.tiocmset = tiocmset, .tiocmset = tiocmset,
.get_icount = msgl_get_icount,
.proc_fops = &mgsl_proc_fops, .proc_fops = &mgsl_proc_fops,
}; };
......
...@@ -1032,9 +1032,6 @@ static int ioctl(struct tty_struct *tty, struct file *file, ...@@ -1032,9 +1032,6 @@ static int ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg) unsigned int cmd, unsigned long arg)
{ {
struct slgt_info *info = tty->driver_data; struct slgt_info *info = tty->driver_data;
struct mgsl_icount cnow; /* kernel counter temps */
struct serial_icounter_struct __user *p_cuser; /* user space */
unsigned long flags;
void __user *argp = (void __user *)arg; void __user *argp = (void __user *)arg;
int ret; int ret;
...@@ -1043,7 +1040,7 @@ static int ioctl(struct tty_struct *tty, struct file *file, ...@@ -1043,7 +1040,7 @@ static int ioctl(struct tty_struct *tty, struct file *file,
DBGINFO(("%s ioctl() cmd=%08X\n", info->device_name, cmd)); DBGINFO(("%s ioctl() cmd=%08X\n", info->device_name, cmd));
if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
(cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) { (cmd != TIOCMIWAIT)) {
if (tty->flags & (1 << TTY_IO_ERROR)) if (tty->flags & (1 << TTY_IO_ERROR))
return -EIO; return -EIO;
} }
...@@ -1053,24 +1050,6 @@ static int ioctl(struct tty_struct *tty, struct file *file, ...@@ -1053,24 +1050,6 @@ static int ioctl(struct tty_struct *tty, struct file *file,
return wait_mgsl_event(info, argp); return wait_mgsl_event(info, argp);
case TIOCMIWAIT: case TIOCMIWAIT:
return modem_input_wait(info,(int)arg); return modem_input_wait(info,(int)arg);
case TIOCGICOUNT:
spin_lock_irqsave(&info->lock,flags);
cnow = info->icount;
spin_unlock_irqrestore(&info->lock,flags);
p_cuser = argp;
if (put_user(cnow.cts, &p_cuser->cts) ||
put_user(cnow.dsr, &p_cuser->dsr) ||
put_user(cnow.rng, &p_cuser->rng) ||
put_user(cnow.dcd, &p_cuser->dcd) ||
put_user(cnow.rx, &p_cuser->rx) ||
put_user(cnow.tx, &p_cuser->tx) ||
put_user(cnow.frame, &p_cuser->frame) ||
put_user(cnow.overrun, &p_cuser->overrun) ||
put_user(cnow.parity, &p_cuser->parity) ||
put_user(cnow.brk, &p_cuser->brk) ||
put_user(cnow.buf_overrun, &p_cuser->buf_overrun))
return -EFAULT;
return 0;
case MGSL_IOCSGPIO: case MGSL_IOCSGPIO:
return set_gpio(info, argp); return set_gpio(info, argp);
case MGSL_IOCGGPIO: case MGSL_IOCGGPIO:
...@@ -1117,6 +1096,33 @@ static int ioctl(struct tty_struct *tty, struct file *file, ...@@ -1117,6 +1096,33 @@ static int ioctl(struct tty_struct *tty, struct file *file,
return ret; return ret;
} }
static int get_icount(struct tty_struct *tty,
struct serial_icounter_struct *icount)
{
struct slgt_info *info = tty->driver_data;
struct mgsl_icount cnow; /* kernel counter temps */
unsigned long flags;
spin_lock_irqsave(&info->lock,flags);
cnow = info->icount;
spin_unlock_irqrestore(&info->lock,flags);
icount->cts = cnow.cts;
icount->dsr = cnow.dsr;
icount->rng = cnow.rng;
icount->dcd = cnow.dcd;
icount->rx = cnow.rx;
icount->tx = cnow.tx;
icount->frame = cnow.frame;
icount->overrun = cnow.overrun;
icount->parity = cnow.parity;
icount->brk = cnow.brk;
icount->buf_overrun = cnow.buf_overrun;
return 0;
}
/* /*
* support for 32 bit ioctl calls on 64 bit systems * support for 32 bit ioctl calls on 64 bit systems
*/ */
...@@ -1206,10 +1212,6 @@ static long slgt_compat_ioctl(struct tty_struct *tty, struct file *file, ...@@ -1206,10 +1212,6 @@ static long slgt_compat_ioctl(struct tty_struct *tty, struct file *file,
case MGSL_IOCSGPIO: case MGSL_IOCSGPIO:
case MGSL_IOCGGPIO: case MGSL_IOCGGPIO:
case MGSL_IOCWAITGPIO: case MGSL_IOCWAITGPIO:
case TIOCGICOUNT:
rc = ioctl(tty, file, cmd, (unsigned long)(compat_ptr(arg)));
break;
case MGSL_IOCSTXIDLE: case MGSL_IOCSTXIDLE:
case MGSL_IOCTXENABLE: case MGSL_IOCTXENABLE:
case MGSL_IOCRXENABLE: case MGSL_IOCRXENABLE:
...@@ -3642,6 +3644,7 @@ static const struct tty_operations ops = { ...@@ -3642,6 +3644,7 @@ static const struct tty_operations ops = {
.hangup = hangup, .hangup = hangup,
.tiocmget = tiocmget, .tiocmget = tiocmget,
.tiocmset = tiocmset, .tiocmset = tiocmset,
.get_icount = get_icount,
.proc_fops = &synclink_gt_proc_fops, .proc_fops = &synclink_gt_proc_fops,
}; };
......
...@@ -1258,10 +1258,6 @@ static int ioctl(struct tty_struct *tty, struct file *file, ...@@ -1258,10 +1258,6 @@ static int ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg) unsigned int cmd, unsigned long arg)
{ {
SLMP_INFO *info = tty->driver_data; SLMP_INFO *info = tty->driver_data;
int error;
struct mgsl_icount cnow; /* kernel counter temps */
struct serial_icounter_struct __user *p_cuser; /* user space */
unsigned long flags;
void __user *argp = (void __user *)arg; void __user *argp = (void __user *)arg;
if (debug_level >= DEBUG_LEVEL_INFO) if (debug_level >= DEBUG_LEVEL_INFO)
...@@ -1272,7 +1268,7 @@ static int ioctl(struct tty_struct *tty, struct file *file, ...@@ -1272,7 +1268,7 @@ static int ioctl(struct tty_struct *tty, struct file *file,
return -ENODEV; return -ENODEV;
if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
(cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) { (cmd != TIOCMIWAIT)) {
if (tty->flags & (1 << TTY_IO_ERROR)) if (tty->flags & (1 << TTY_IO_ERROR))
return -EIO; return -EIO;
} }
...@@ -1310,40 +1306,38 @@ static int ioctl(struct tty_struct *tty, struct file *file, ...@@ -1310,40 +1306,38 @@ static int ioctl(struct tty_struct *tty, struct file *file,
* NB: both 1->0 and 0->1 transitions are counted except for * NB: both 1->0 and 0->1 transitions are counted except for
* RI where only 0->1 is counted. * RI where only 0->1 is counted.
*/ */
case TIOCGICOUNT:
spin_lock_irqsave(&info->lock,flags);
cnow = info->icount;
spin_unlock_irqrestore(&info->lock,flags);
p_cuser = argp;
PUT_USER(error,cnow.cts, &p_cuser->cts);
if (error) return error;
PUT_USER(error,cnow.dsr, &p_cuser->dsr);
if (error) return error;
PUT_USER(error,cnow.rng, &p_cuser->rng);
if (error) return error;
PUT_USER(error,cnow.dcd, &p_cuser->dcd);
if (error) return error;
PUT_USER(error,cnow.rx, &p_cuser->rx);
if (error) return error;
PUT_USER(error,cnow.tx, &p_cuser->tx);
if (error) return error;
PUT_USER(error,cnow.frame, &p_cuser->frame);
if (error) return error;
PUT_USER(error,cnow.overrun, &p_cuser->overrun);
if (error) return error;
PUT_USER(error,cnow.parity, &p_cuser->parity);
if (error) return error;
PUT_USER(error,cnow.brk, &p_cuser->brk);
if (error) return error;
PUT_USER(error,cnow.buf_overrun, &p_cuser->buf_overrun);
if (error) return error;
return 0;
default: default:
return -ENOIOCTLCMD; return -ENOIOCTLCMD;
} }
return 0; return 0;
} }
static int get_icount(struct tty_struct *tty,
struct serial_icounter_struct *icount)
{
SLMP_INFO *info = tty->driver_data;
struct mgsl_icount cnow; /* kernel counter temps */
unsigned long flags;
spin_lock_irqsave(&info->lock,flags);
cnow = info->icount;
spin_unlock_irqrestore(&info->lock,flags);
icount->cts = cnow.cts;
icount->dsr = cnow.dsr;
icount->rng = cnow.rng;
icount->dcd = cnow.dcd;
icount->rx = cnow.rx;
icount->tx = cnow.tx;
icount->frame = cnow.frame;
icount->overrun = cnow.overrun;
icount->parity = cnow.parity;
icount->brk = cnow.brk;
icount->buf_overrun = cnow.buf_overrun;
return 0;
}
/* /*
* /proc fs routines.... * /proc fs routines....
*/ */
...@@ -3909,6 +3903,7 @@ static const struct tty_operations ops = { ...@@ -3909,6 +3903,7 @@ static const struct tty_operations ops = {
.hangup = hangup, .hangup = hangup,
.tiocmget = tiocmget, .tiocmget = tiocmget,
.tiocmset = tiocmset, .tiocmset = tiocmset,
.get_icount = get_icount,
.proc_fops = &synclinkmp_proc_fops, .proc_fops = &synclinkmp_proc_fops,
}; };
......
...@@ -1381,6 +1381,30 @@ static void send_break(ser_info_t *info, unsigned int duration) ...@@ -1381,6 +1381,30 @@ static void send_break(ser_info_t *info, unsigned int duration)
} }
/*
* Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
* Return: write counters to the user passed counter struct
* NB: both 1->0 and 0->1 transitions are counted except for
* RI where only 0->1 is counted.
*/
static int rs_360_get_icount(struct tty_struct *tty,
struct serial_icounter_struct *icount)
{
ser_info_t *info = (ser_info_t *)tty->driver_data;
struct async_icount cnow;
local_irq_disable();
cnow = info->state->icount;
local_irq_enable();
icount->cts = cnow.cts;
icount->dsr = cnow.dsr;
icount->rng = cnow.rng;
icount->dcd = cnow.dcd;
return 0;
}
static int rs_360_ioctl(struct tty_struct *tty, struct file * file, static int rs_360_ioctl(struct tty_struct *tty, struct file * file,
unsigned int cmd, unsigned long arg) unsigned int cmd, unsigned long arg)
{ {
...@@ -1394,7 +1418,7 @@ static int rs_360_ioctl(struct tty_struct *tty, struct file * file, ...@@ -1394,7 +1418,7 @@ static int rs_360_ioctl(struct tty_struct *tty, struct file * file,
if (serial_paranoia_check(info, tty->name, "rs_ioctl")) if (serial_paranoia_check(info, tty->name, "rs_ioctl"))
return -ENODEV; return -ENODEV;
if ((cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) { if (cmd != TIOCMIWAIT) {
if (tty->flags & (1 << TTY_IO_ERROR)) if (tty->flags & (1 << TTY_IO_ERROR))
return -EIO; return -EIO;
} }
...@@ -1477,31 +1501,6 @@ static int rs_360_ioctl(struct tty_struct *tty, struct file * file, ...@@ -1477,31 +1501,6 @@ static int rs_360_ioctl(struct tty_struct *tty, struct file * file,
return 0; return 0;
#endif #endif
/*
* Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
* Return: write counters to the user passed counter struct
* NB: both 1->0 and 0->1 transitions are counted except for
* RI where only 0->1 is counted.
*/
case TIOCGICOUNT:
local_irq_disable();
cnow = info->state->icount;
local_irq_enable();
p_cuser = (struct serial_icounter_struct *) arg;
/* error = put_user(cnow.cts, &p_cuser->cts); */
/* if (error) return error; */
/* error = put_user(cnow.dsr, &p_cuser->dsr); */
/* if (error) return error; */
/* error = put_user(cnow.rng, &p_cuser->rng); */
/* if (error) return error; */
/* error = put_user(cnow.dcd, &p_cuser->dcd); */
/* if (error) return error; */
put_user(cnow.cts, &p_cuser->cts);
put_user(cnow.dsr, &p_cuser->dsr);
put_user(cnow.rng, &p_cuser->rng);
put_user(cnow.dcd, &p_cuser->dcd);
return 0;
default: default:
return -ENOIOCTLCMD; return -ENOIOCTLCMD;
......
...@@ -844,10 +844,6 @@ static int rfcomm_tty_ioctl(struct tty_struct *tty, struct file *filp, unsigned ...@@ -844,10 +844,6 @@ static int rfcomm_tty_ioctl(struct tty_struct *tty, struct file *filp, unsigned
BT_DBG("TIOCMIWAIT"); BT_DBG("TIOCMIWAIT");
break; break;
case TIOCGICOUNT:
BT_DBG("TIOCGICOUNT");
break;
case TIOCGSERIAL: case TIOCGSERIAL:
BT_ERR("TIOCGSERIAL is not supported"); BT_ERR("TIOCGSERIAL is not supported");
return -ENOIOCTLCMD; return -ENOIOCTLCMD;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment