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: 's avatarAlan Cox <alan@linux.intel.com>
Signed-off-by: 's avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 0bca1b91
......@@ -395,7 +395,7 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
{
if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
(cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) &&
(cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
(cmd != TIOCMIWAIT)) {
if (tty->flags & (1 << TTY_IO_ERROR))
return -EIO;
}
......@@ -433,16 +433,6 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
case TIOCMIWAIT:
printk(KERN_INFO "rs_ioctl: TIOCMIWAIT: called\n");
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 TIOCSERSWILD:
/* "setserial -W" is called in Debian boot */
......
......@@ -1263,6 +1263,36 @@ static int rs_break(struct tty_struct *tty, int break_state)
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,
unsigned int cmd, unsigned long arg)
......@@ -1332,31 +1362,6 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
}
/* 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 TIOCSERSWILD:
/* "setserial -W" is called in Debian boot */
......@@ -1958,6 +1963,7 @@ static const struct tty_operations serial_ops = {
.wait_until_sent = rs_wait_until_sent,
.tiocmget = rs_tiocmget,
.tiocmset = rs_tiocmset,
.get_icount = rs_get_icount,
.proc_fops = &rs_proc_fops,
};
......
......@@ -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
* 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:
ret_val = -ENOIOCTLCMD;
}
......@@ -2823,6 +2800,31 @@ cy_ioctl(struct tty_struct *tty, struct file *file,
return ret_val;
} /* 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
* device's termios settings have changed. Note that a
......@@ -4084,6 +4086,7 @@ static const struct tty_operations cy_ops = {
.wait_until_sent = cy_wait_until_sent,
.tiocmget = cy_tiocmget,
.tiocmset = cy_tiocmset,
.get_icount = cy_get_icount,
.proc_fops = &cyclades_proc_fops,
};
......
......@@ -183,6 +183,8 @@ static void ip2_hangup(PTTY);
static int ip2_tiocmget(struct tty_struct *tty, struct file *file);
static int ip2_tiocmset(struct tty_struct *tty, struct file *file,
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 ip2_interrupt_bh(struct work_struct *work);
......@@ -454,6 +456,7 @@ static const struct tty_operations ip2_ops = {
.hangup = ip2_hangup,
.tiocmget = ip2_tiocmget,
.tiocmset = ip2_tiocmset,
.get_icount = ip2_get_icount,
.proc_fops = &ip2_proc_fops,
};
......@@ -2128,7 +2131,6 @@ ip2_ioctl ( PTTY tty, struct file *pFile, UINT cmd, ULONG arg )
i2ChanStrPtr pCh = DevTable[tty->index];
i2eBordStrPtr pB;
struct async_icount cprev, cnow; /* kernel counter temps */
struct serial_icounter_struct __user *p_cuser;
int rc = 0;
unsigned long flags;
void __user *argp = (void __user *)arg;
......@@ -2296,34 +2298,6 @@ ip2_ioctl ( PTTY tty, struct file *pFile, UINT cmd, ULONG arg )
return rc;
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
* 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 )
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() */
/* Parameters: Pointer to channel structure */
......
......@@ -1700,7 +1700,7 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file,
return 0;
}
if (cmd != TIOCGSERIAL && cmd != TIOCMIWAIT && cmd != TIOCGICOUNT &&
if (cmd != TIOCGSERIAL && cmd != TIOCMIWAIT &&
test_bit(TTY_IO_ERROR, &tty->flags))
return -EIO;
......@@ -1730,32 +1730,6 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file,
return wait_event_interruptible(info->port.delta_msr_wait,
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:
return put_user(info->baud_base != 115200 ? 1 : 0, (int __user *)argp);
case MOXA_SDS_RSTICOUNTER:
......@@ -1828,6 +1802,39 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file,
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)
{
struct mxser_port *info = tty->driver_data;
......@@ -2326,6 +2333,7 @@ static const struct tty_operations mxser_ops = {
.wait_until_sent = mxser_wait_until_sent,
.tiocmget = mxser_tiocmget,
.tiocmset = mxser_tiocmset,
.get_icount = mxser_get_icount,
};
struct tty_port_operations mxser_port_ops = {
......
......@@ -1804,24 +1804,24 @@ static int ntty_cflags_changed(struct port *port, unsigned long flags,
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;
struct serial_icounter_struct icount;
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 copy_to_user(argp, &icount, sizeof(icount)) ? -EFAULT : 0;
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 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,
ntty_cflags_changed(port, arg, &cprev));
break;
} case TIOCGICOUNT:
rval = ntty_ioctl_tiocgicount(port, argp);
break;
}
default:
DBG1("ERR: 0x%08X, %d", cmd, cmd);
break;
......@@ -1922,6 +1920,7 @@ static const struct tty_operations tty_ops = {
.chars_in_buffer = ntty_chars_in_buffer,
.tiocmget = ntty_tiocmget,
.tiocmset = ntty_tiocmset,
.get_icount = ntty_tiocgicount,
.install = ntty_install,
.cleanup = ntty_cleanup,
};
......
......@@ -2215,6 +2215,32 @@ static int mgslpc_break(struct tty_struct *tty, int break_state)
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
*
* Arguments:
......@@ -2230,11 +2256,7 @@ static int mgslpc_ioctl(struct tty_struct *tty, struct file * file,
unsigned int cmd, unsigned long arg)
{
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;
unsigned long flags;
if (debug_level >= DEBUG_LEVEL_INFO)
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,
return -ENODEV;
if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
(cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
(cmd != TIOCMIWAIT)) {
if (tty->flags & (1 << TTY_IO_ERROR))
return -EIO;
}
......@@ -2274,34 +2296,6 @@ static int mgslpc_ioctl(struct tty_struct *tty, struct file * file,
return wait_events(info, argp);
case TIOCMIWAIT:
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:
return -ENOIOCTLCMD;
}
......
......@@ -2925,6 +2925,38 @@ static int mgsl_break(struct tty_struct *tty, int break_state)
} /* 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
*
* Arguments:
......@@ -2949,7 +2981,7 @@ static int mgsl_ioctl(struct tty_struct *tty, struct file * file,
return -ENODEV;
if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
(cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
(cmd != TIOCMIWAIT)) {
if (tty->flags & (1 << TTY_IO_ERROR))
return -EIO;
}
......@@ -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)
{
int error;
struct mgsl_icount cnow; /* kernel counter temps */
void __user *argp = (void __user *)arg;
struct serial_icounter_struct __user *p_cuser; /* user space */
unsigned long flags;
switch (cmd) {
case MGSL_IOCGPARAMS:
......@@ -2992,40 +3020,6 @@ static int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigne
case TIOCMIWAIT:
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:
return -ENOIOCTLCMD;
}
......@@ -4328,6 +4322,7 @@ static const struct tty_operations mgsl_ops = {
.hangup = mgsl_hangup,
.tiocmget = tiocmget,
.tiocmset = tiocmset,
.get_icount = msgl_get_icount,
.proc_fops = &mgsl_proc_fops,
};
......
......@@ -1032,9 +1032,6 @@ static int ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg)
{
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;
int ret;
......@@ -1043,7 +1040,7 @@ static int ioctl(struct tty_struct *tty, struct file *file,
DBGINFO(("%s ioctl() cmd=%08X\n", info->device_name, cmd));
if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
(cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
(cmd != TIOCMIWAIT)) {
if (tty->flags & (1 << TTY_IO_ERROR))
return -EIO;
}
......@@ -1053,24 +1050,6 @@ static int ioctl(struct tty_struct *tty, struct file *file,
return wait_mgsl_event(info, argp);
case TIOCMIWAIT:
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:
return set_gpio(info, argp);
case MGSL_IOCGGPIO:
......@@ -1117,6 +1096,33 @@ static int ioctl(struct tty_struct *tty, struct file *file,
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
*/
......@@ -1206,10 +1212,6 @@ static long slgt_compat_ioctl(struct tty_struct *tty, struct file *file,
case MGSL_IOCSGPIO:
case MGSL_IOCGGPIO:
case MGSL_IOCWAITGPIO:
case TIOCGICOUNT:
rc = ioctl(tty, file, cmd, (unsigned long)(compat_ptr(arg)));
break;
case MGSL_IOCSTXIDLE:
case MGSL_IOCTXENABLE:
case MGSL_IOCRXENABLE:
......@@ -3642,6 +3644,7 @@ static const struct tty_operations ops = {
.hangup = hangup,
.tiocmget = tiocmget,
.tiocmset = tiocmset,
.get_icount = get_icount,
.proc_fops = &synclink_gt_proc_fops,
};