aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char')
-rw-r--r--drivers/char/amiserial.c56
-rw-r--r--drivers/char/cyclades.c49
-rw-r--r--drivers/char/ip2/ip2main.c72
-rw-r--r--drivers/char/mxser.c62
-rw-r--r--drivers/char/nozomi.c37
-rw-r--r--drivers/char/pcmcia/synclink_cs.c60
-rw-r--r--drivers/char/synclink.c73
-rw-r--r--drivers/char/synclink_gt.c55
-rw-r--r--drivers/char/synclinkmp.c61
9 files changed, 271 insertions, 254 deletions
diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c
index a11c8c9ca3d4..b0a70461a12c 100644
--- a/drivers/char/amiserial.c
+++ b/drivers/char/amiserial.c
@@ -1263,6 +1263,36 @@ static int rs_break(struct tty_struct *tty, int break_state)
1263 return 0; 1263 return 0;
1264} 1264}
1265 1265
1266/*
1267 * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
1268 * Return: write counters to the user passed counter struct
1269 * NB: both 1->0 and 0->1 transitions are counted except for
1270 * RI where only 0->1 is counted.
1271 */
1272static int rs_get_icount(struct tty_struct *tty,
1273 struct serial_icounter_struct *icount)
1274{
1275 struct async_struct *info = tty->driver_data;
1276 struct async_icount cnow;
1277 unsigned long flags;
1278
1279 local_irq_save(flags);
1280 cnow = info->state->icount;
1281 local_irq_restore(flags);
1282 icount->cts = cnow.cts;
1283 icount->dsr = cnow.dsr;
1284 icount->rng = cnow.rng;
1285 icount->dcd = cnow.dcd;
1286 icount->rx = cnow.rx;
1287 icount->tx = cnow.tx;
1288 icount->frame = cnow.frame;
1289 icount->overrun = cnow.overrun;
1290 icount->parity = cnow.parity;
1291 icount->brk = cnow.brk;
1292 icount->buf_overrun = cnow.buf_overrun;
1293
1294 return 0;
1295}
1266 1296
1267static int rs_ioctl(struct tty_struct *tty, struct file * file, 1297static int rs_ioctl(struct tty_struct *tty, struct file * file,
1268 unsigned int cmd, unsigned long arg) 1298 unsigned int cmd, unsigned long arg)
@@ -1332,31 +1362,6 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
1332 } 1362 }
1333 /* NOTREACHED */ 1363 /* NOTREACHED */
1334 1364
1335 /*
1336 * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
1337 * Return: write counters to the user passed counter struct
1338 * NB: both 1->0 and 0->1 transitions are counted except for
1339 * RI where only 0->1 is counted.
1340 */
1341 case TIOCGICOUNT:
1342 local_irq_save(flags);
1343 cnow = info->state->icount;
1344 local_irq_restore(flags);
1345 icount.cts = cnow.cts;
1346 icount.dsr = cnow.dsr;
1347 icount.rng = cnow.rng;
1348 icount.dcd = cnow.dcd;
1349 icount.rx = cnow.rx;
1350 icount.tx = cnow.tx;
1351 icount.frame = cnow.frame;
1352 icount.overrun = cnow.overrun;
1353 icount.parity = cnow.parity;
1354 icount.brk = cnow.brk;
1355 icount.buf_overrun = cnow.buf_overrun;
1356
1357 if (copy_to_user(argp, &icount, sizeof(icount)))
1358 return -EFAULT;
1359 return 0;
1360 case TIOCSERGWILD: 1365 case TIOCSERGWILD:
1361 case TIOCSERSWILD: 1366 case TIOCSERSWILD:
1362 /* "setserial -W" is called in Debian boot */ 1367 /* "setserial -W" is called in Debian boot */
@@ -1958,6 +1963,7 @@ static const struct tty_operations serial_ops = {
1958 .wait_until_sent = rs_wait_until_sent, 1963 .wait_until_sent = rs_wait_until_sent,
1959 .tiocmget = rs_tiocmget, 1964 .tiocmget = rs_tiocmget,
1960 .tiocmset = rs_tiocmset, 1965 .tiocmset = rs_tiocmset,
1966 .get_icount = rs_get_icount,
1961 .proc_fops = &rs_proc_fops, 1967 .proc_fops = &rs_proc_fops,
1962}; 1968};
1963 1969
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c
index 27aad9422332..4f152c28f40e 100644
--- a/drivers/char/cyclades.c
+++ b/drivers/char/cyclades.c
@@ -2790,29 +2790,6 @@ cy_ioctl(struct tty_struct *tty, struct file *file,
2790 * NB: both 1->0 and 0->1 transitions are counted except for 2790 * NB: both 1->0 and 0->1 transitions are counted except for
2791 * RI where only 0->1 is counted. 2791 * RI where only 0->1 is counted.
2792 */ 2792 */
2793 case TIOCGICOUNT: {
2794 struct serial_icounter_struct sic = { };
2795
2796 spin_lock_irqsave(&info->card->card_lock, flags);
2797 cnow = info->icount;
2798 spin_unlock_irqrestore(&info->card->card_lock, flags);
2799
2800 sic.cts = cnow.cts;
2801 sic.dsr = cnow.dsr;
2802 sic.rng = cnow.rng;
2803 sic.dcd = cnow.dcd;
2804 sic.rx = cnow.rx;
2805 sic.tx = cnow.tx;
2806 sic.frame = cnow.frame;
2807 sic.overrun = cnow.overrun;
2808 sic.parity = cnow.parity;
2809 sic.brk = cnow.brk;
2810 sic.buf_overrun = cnow.buf_overrun;
2811
2812 if (copy_to_user(argp, &sic, sizeof(sic)))
2813 ret_val = -EFAULT;
2814 break;
2815 }
2816 default: 2793 default:
2817 ret_val = -ENOIOCTLCMD; 2794 ret_val = -ENOIOCTLCMD;
2818 } 2795 }
@@ -2823,6 +2800,31 @@ cy_ioctl(struct tty_struct *tty, struct file *file,
2823 return ret_val; 2800 return ret_val;
2824} /* cy_ioctl */ 2801} /* cy_ioctl */
2825 2802
2803static int cy_get_icount(struct tty_struct *tty,
2804 struct serial_icounter_struct *sic)
2805{
2806 struct cyclades_port *info = tty->driver_data;
2807 struct cyclades_icount cnow; /* Used to snapshot */
2808 unsigned long flags;
2809
2810 spin_lock_irqsave(&info->card->card_lock, flags);
2811 cnow = info->icount;
2812 spin_unlock_irqrestore(&info->card->card_lock, flags);
2813
2814 sic->cts = cnow.cts;
2815 sic->dsr = cnow.dsr;
2816 sic->rng = cnow.rng;
2817 sic->dcd = cnow.dcd;
2818 sic->rx = cnow.rx;
2819 sic->tx = cnow.tx;
2820 sic->frame = cnow.frame;
2821 sic->overrun = cnow.overrun;
2822 sic->parity = cnow.parity;
2823 sic->brk = cnow.brk;
2824 sic->buf_overrun = cnow.buf_overrun;
2825 return 0;
2826}
2827
2826/* 2828/*
2827 * This routine allows the tty driver to be notified when 2829 * This routine allows the tty driver to be notified when
2828 * device's termios settings have changed. Note that a 2830 * device's termios settings have changed. Note that a
@@ -4084,6 +4086,7 @@ static const struct tty_operations cy_ops = {
4084 .wait_until_sent = cy_wait_until_sent, 4086 .wait_until_sent = cy_wait_until_sent,
4085 .tiocmget = cy_tiocmget, 4087 .tiocmget = cy_tiocmget,
4086 .tiocmset = cy_tiocmset, 4088 .tiocmset = cy_tiocmset,
4089 .get_icount = cy_get_icount,
4087 .proc_fops = &cyclades_proc_fops, 4090 .proc_fops = &cyclades_proc_fops,
4088}; 4091};
4089 4092
diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c
index d4b71e8d0d23..438272ca9e08 100644
--- a/drivers/char/ip2/ip2main.c
+++ b/drivers/char/ip2/ip2main.c
@@ -183,6 +183,8 @@ static void ip2_hangup(PTTY);
183static int ip2_tiocmget(struct tty_struct *tty, struct file *file); 183static int ip2_tiocmget(struct tty_struct *tty, struct file *file);
184static int ip2_tiocmset(struct tty_struct *tty, struct file *file, 184static int ip2_tiocmset(struct tty_struct *tty, struct file *file,
185 unsigned int set, unsigned int clear); 185 unsigned int set, unsigned int clear);
186static int ip2_get_icount(struct tty_struct *tty,
187 struct serial_icounter_struct *icount);
186 188
187static void set_irq(int, int); 189static void set_irq(int, int);
188static void ip2_interrupt_bh(struct work_struct *work); 190static void ip2_interrupt_bh(struct work_struct *work);
@@ -454,6 +456,7 @@ static const struct tty_operations ip2_ops = {
454 .hangup = ip2_hangup, 456 .hangup = ip2_hangup,
455 .tiocmget = ip2_tiocmget, 457 .tiocmget = ip2_tiocmget,
456 .tiocmset = ip2_tiocmset, 458 .tiocmset = ip2_tiocmset,
459 .get_icount = ip2_get_icount,
457 .proc_fops = &ip2_proc_fops, 460 .proc_fops = &ip2_proc_fops,
458}; 461};
459 462
@@ -2128,7 +2131,6 @@ ip2_ioctl ( PTTY tty, struct file *pFile, UINT cmd, ULONG arg )
2128 i2ChanStrPtr pCh = DevTable[tty->index]; 2131 i2ChanStrPtr pCh = DevTable[tty->index];
2129 i2eBordStrPtr pB; 2132 i2eBordStrPtr pB;
2130 struct async_icount cprev, cnow; /* kernel counter temps */ 2133 struct async_icount cprev, cnow; /* kernel counter temps */
2131 struct serial_icounter_struct __user *p_cuser;
2132 int rc = 0; 2134 int rc = 0;
2133 unsigned long flags; 2135 unsigned long flags;
2134 void __user *argp = (void __user *)arg; 2136 void __user *argp = (void __user *)arg;
@@ -2297,34 +2299,6 @@ ip2_ioctl ( PTTY tty, struct file *pFile, UINT cmd, ULONG arg )
2297 break; 2299 break;
2298 2300
2299 /* 2301 /*
2300 * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
2301 * Return: write counters to the user passed counter struct
2302 * NB: both 1->0 and 0->1 transitions are counted except for RI where
2303 * only 0->1 is counted. The controller is quite capable of counting
2304 * both, but this done to preserve compatibility with the standard
2305 * serial driver.
2306 */
2307 case TIOCGICOUNT:
2308 ip2trace (CHANN, ITRC_IOCTL, 11, 1, rc );
2309
2310 write_lock_irqsave(&pB->read_fifo_spinlock, flags);
2311 cnow = pCh->icount;
2312 write_unlock_irqrestore(&pB->read_fifo_spinlock, flags);
2313 p_cuser = argp;
2314 rc = put_user(cnow.cts, &p_cuser->cts);
2315 rc = put_user(cnow.dsr, &p_cuser->dsr);
2316 rc = put_user(cnow.rng, &p_cuser->rng);
2317 rc = put_user(cnow.dcd, &p_cuser->dcd);
2318 rc = put_user(cnow.rx, &p_cuser->rx);
2319 rc = put_user(cnow.tx, &p_cuser->tx);
2320 rc = put_user(cnow.frame, &p_cuser->frame);
2321 rc = put_user(cnow.overrun, &p_cuser->overrun);
2322 rc = put_user(cnow.parity, &p_cuser->parity);
2323 rc = put_user(cnow.brk, &p_cuser->brk);
2324 rc = put_user(cnow.buf_overrun, &p_cuser->buf_overrun);
2325 break;
2326
2327 /*
2328 * The rest are not supported by this driver. By returning -ENOIOCTLCMD they 2302 * The rest are not supported by this driver. By returning -ENOIOCTLCMD they
2329 * will be passed to the line discipline for it to handle. 2303 * will be passed to the line discipline for it to handle.
2330 */ 2304 */
@@ -2348,6 +2322,46 @@ ip2_ioctl ( PTTY tty, struct file *pFile, UINT cmd, ULONG arg )
2348 return rc; 2322 return rc;
2349} 2323}
2350 2324
2325static int ip2_get_icount(struct tty_struct *tty,
2326 struct serial_icounter_struct *icount)
2327{
2328 i2ChanStrPtr pCh = DevTable[tty->index];
2329 i2eBordStrPtr pB;
2330 struct async_icount cnow; /* kernel counter temp */
2331 unsigned long flags;
2332
2333 if ( pCh == NULL )
2334 return -ENODEV;
2335
2336 pB = pCh->pMyBord;
2337
2338 /*
2339 * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
2340 * Return: write counters to the user passed counter struct
2341 * NB: both 1->0 and 0->1 transitions are counted except for RI where
2342 * only 0->1 is counted. The controller is quite capable of counting
2343 * both, but this done to preserve compatibility with the standard
2344 * serial driver.
2345 */
2346
2347 write_lock_irqsave(&pB->read_fifo_spinlock, flags);
2348 cnow = pCh->icount;
2349 write_unlock_irqrestore(&pB->read_fifo_spinlock, flags);
2350
2351 icount->cts = cnow.cts;
2352 icount->dsr = cnow.dsr;
2353 icount->rng = cnow.rng;
2354 icount->dcd = cnow.dcd;
2355 icount->rx = cnow.rx;
2356 icount->tx = cnow.tx;
2357 icount->frame = cnow.frame;
2358 icount->overrun = cnow.overrun;
2359 icount->parity = cnow.parity;
2360 icount->brk = cnow.brk;
2361 icount->buf_overrun = cnow.buf_overrun;
2362 return 0;
2363}
2364
2351/******************************************************************************/ 2365/******************************************************************************/
2352/* Function: GetSerialInfo() */ 2366/* Function: GetSerialInfo() */
2353/* Parameters: Pointer to channel structure */ 2367/* Parameters: Pointer to channel structure */
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c
index 9d243de795df..463df27494bd 100644
--- a/drivers/char/mxser.c
+++ b/drivers/char/mxser.c
@@ -1700,7 +1700,7 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file,
1700 return 0; 1700 return 0;
1701 } 1701 }
1702 1702
1703 if (cmd != TIOCGSERIAL && cmd != TIOCMIWAIT && cmd != TIOCGICOUNT && 1703 if (cmd != TIOCGSERIAL && cmd != TIOCMIWAIT &&
1704 test_bit(TTY_IO_ERROR, &tty->flags)) 1704 test_bit(TTY_IO_ERROR, &tty->flags))
1705 return -EIO; 1705 return -EIO;
1706 1706
@@ -1730,32 +1730,6 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file,
1730 1730
1731 return wait_event_interruptible(info->port.delta_msr_wait, 1731 return wait_event_interruptible(info->port.delta_msr_wait,
1732 mxser_cflags_changed(info, arg, &cnow)); 1732 mxser_cflags_changed(info, arg, &cnow));
1733 /*
1734 * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
1735 * Return: write counters to the user passed counter struct
1736 * NB: both 1->0 and 0->1 transitions are counted except for
1737 * RI where only 0->1 is counted.
1738 */
1739 case TIOCGICOUNT: {
1740 struct serial_icounter_struct icnt = { 0 };
1741 spin_lock_irqsave(&info->slock, flags);
1742 cnow = info->icount;
1743 spin_unlock_irqrestore(&info->slock, flags);
1744
1745 icnt.frame = cnow.frame;
1746 icnt.brk = cnow.brk;
1747 icnt.overrun = cnow.overrun;
1748 icnt.buf_overrun = cnow.buf_overrun;
1749 icnt.parity = cnow.parity;
1750 icnt.rx = cnow.rx;
1751 icnt.tx = cnow.tx;
1752 icnt.cts = cnow.cts;
1753 icnt.dsr = cnow.dsr;
1754 icnt.rng = cnow.rng;
1755 icnt.dcd = cnow.dcd;
1756
1757 return copy_to_user(argp, &icnt, sizeof(icnt)) ? -EFAULT : 0;
1758 }
1759 case MOXA_HighSpeedOn: 1733 case MOXA_HighSpeedOn:
1760 return put_user(info->baud_base != 115200 ? 1 : 0, (int __user *)argp); 1734 return put_user(info->baud_base != 115200 ? 1 : 0, (int __user *)argp);
1761 case MOXA_SDS_RSTICOUNTER: 1735 case MOXA_SDS_RSTICOUNTER:
@@ -1828,6 +1802,39 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file,
1828 return 0; 1802 return 0;
1829} 1803}
1830 1804
1805 /*
1806 * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
1807 * Return: write counters to the user passed counter struct
1808 * NB: both 1->0 and 0->1 transitions are counted except for
1809 * RI where only 0->1 is counted.
1810 */
1811
1812static int mxser_get_icount(struct tty_struct *tty,
1813 struct serial_icounter_struct *icount)
1814
1815{
1816 struct mxser_port *info = tty->driver_data;
1817 struct async_icount cnow;
1818 unsigned long flags;
1819
1820 spin_lock_irqsave(&info->slock, flags);
1821 cnow = info->icount;
1822 spin_unlock_irqrestore(&info->slock, flags);
1823
1824 icount->frame = cnow.frame;
1825 icount->brk = cnow.brk;
1826 icount->overrun = cnow.overrun;
1827 icount->buf_overrun = cnow.buf_overrun;
1828 icount->parity = cnow.parity;
1829 icount->rx = cnow.rx;
1830 icount->tx = cnow.tx;
1831 icount->cts = cnow.cts;
1832 icount->dsr = cnow.dsr;
1833 icount->rng = cnow.rng;
1834 icount->dcd = cnow.dcd;
1835 return 0;
1836}
1837
1831static void mxser_stoprx(struct tty_struct *tty) 1838static void mxser_stoprx(struct tty_struct *tty)
1832{ 1839{
1833 struct mxser_port *info = tty->driver_data; 1840 struct mxser_port *info = tty->driver_data;
@@ -2326,6 +2333,7 @@ static const struct tty_operations mxser_ops = {
2326 .wait_until_sent = mxser_wait_until_sent, 2333 .wait_until_sent = mxser_wait_until_sent,
2327 .tiocmget = mxser_tiocmget, 2334 .tiocmget = mxser_tiocmget,
2328 .tiocmset = mxser_tiocmset, 2335 .tiocmset = mxser_tiocmset,
2336 .get_icount = mxser_get_icount,
2329}; 2337};
2330 2338
2331struct tty_port_operations mxser_port_ops = { 2339struct tty_port_operations mxser_port_ops = {
diff --git a/drivers/char/nozomi.c b/drivers/char/nozomi.c
index 817169cbb245..dd3f9b1f11b4 100644
--- a/drivers/char/nozomi.c
+++ b/drivers/char/nozomi.c
@@ -1804,24 +1804,24 @@ static int ntty_cflags_changed(struct port *port, unsigned long flags,
1804 return ret; 1804 return ret;
1805} 1805}
1806 1806
1807static int ntty_ioctl_tiocgicount(struct port *port, void __user *argp) 1807static int ntty_tiocgicount(struct tty_struct *tty,
1808 struct serial_icounter_struct *icount)
1808{ 1809{
1810 struct port *port = tty->driver_data;
1809 const struct async_icount cnow = port->tty_icount; 1811 const struct async_icount cnow = port->tty_icount;
1810 struct serial_icounter_struct icount; 1812
1811 1813 icount->cts = cnow.cts;
1812 icount.cts = cnow.cts; 1814 icount->dsr = cnow.dsr;
1813 icount.dsr = cnow.dsr; 1815 icount->rng = cnow.rng;
1814 icount.rng = cnow.rng; 1816 icount->dcd = cnow.dcd;
1815 icount.dcd = cnow.dcd; 1817 icount->rx = cnow.rx;
1816 icount.rx = cnow.rx; 1818 icount->tx = cnow.tx;
1817 icount.tx = cnow.tx; 1819 icount->frame = cnow.frame;
1818 icount.frame = cnow.frame; 1820 icount->overrun = cnow.overrun;
1819 icount.overrun = cnow.overrun; 1821 icount->parity = cnow.parity;
1820 icount.parity = cnow.parity; 1822 icount->brk = cnow.brk;
1821 icount.brk = cnow.brk; 1823 icount->buf_overrun = cnow.buf_overrun;
1822 icount.buf_overrun = cnow.buf_overrun; 1824 return 0;
1823
1824 return copy_to_user(argp, &icount, sizeof(icount)) ? -EFAULT : 0;
1825} 1825}
1826 1826
1827static int ntty_ioctl(struct tty_struct *tty, struct file *file, 1827static 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 rval = wait_event_interruptible(port->tty_wait, 1840 rval = wait_event_interruptible(port->tty_wait,
1841 ntty_cflags_changed(port, arg, &cprev)); 1841 ntty_cflags_changed(port, arg, &cprev));
1842 break; 1842 break;
1843 } case TIOCGICOUNT: 1843 }
1844 rval = ntty_ioctl_tiocgicount(port, argp);
1845 break;
1846 default: 1844 default:
1847 DBG1("ERR: 0x%08X, %d", cmd, cmd); 1845 DBG1("ERR: 0x%08X, %d", cmd, cmd);
1848 break; 1846 break;
@@ -1922,6 +1920,7 @@ static const struct tty_operations tty_ops = {
1922 .chars_in_buffer = ntty_chars_in_buffer, 1920 .chars_in_buffer = ntty_chars_in_buffer,
1923 .tiocmget = ntty_tiocmget, 1921 .tiocmget = ntty_tiocmget,
1924 .tiocmset = ntty_tiocmset, 1922 .tiocmset = ntty_tiocmset,
1923 .get_icount = ntty_tiocgicount,
1925 .install = ntty_install, 1924 .install = ntty_install,
1926 .cleanup = ntty_cleanup, 1925 .cleanup = ntty_cleanup,
1927}; 1926};
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
index 9ecd6bef5d3b..8e7c78131e32 100644
--- a/drivers/char/pcmcia/synclink_cs.c
+++ b/drivers/char/pcmcia/synclink_cs.c
@@ -2215,6 +2215,32 @@ static int mgslpc_break(struct tty_struct *tty, int break_state)
2215 return 0; 2215 return 0;
2216} 2216}
2217 2217
2218static int mgslpc_get_icount(struct tty_struct *tty,
2219 struct serial_icounter_struct *icount)
2220{
2221 MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data;
2222 struct mgsl_icount cnow; /* kernel counter temps */
2223 unsigned long flags;
2224
2225 spin_lock_irqsave(&info->lock,flags);
2226 cnow = info->icount;
2227 spin_unlock_irqrestore(&info->lock,flags);
2228
2229 icount->cts = cnow.cts;
2230 icount->dsr = cnow.dsr;
2231 icount->rng = cnow.rng;
2232 icount->dcd = cnow.dcd;
2233 icount->rx = cnow.rx;
2234 icount->tx = cnow.tx;
2235 icount->frame = cnow.frame;
2236 icount->overrun = cnow.overrun;
2237 icount->parity = cnow.parity;
2238 icount->brk = cnow.brk;
2239 icount->buf_overrun = cnow.buf_overrun;
2240
2241 return 0;
2242}
2243
2218/* Service an IOCTL request 2244/* Service an IOCTL request
2219 * 2245 *
2220 * Arguments: 2246 * Arguments:
@@ -2230,11 +2256,7 @@ static int mgslpc_ioctl(struct tty_struct *tty, struct file * file,
2230 unsigned int cmd, unsigned long arg) 2256 unsigned int cmd, unsigned long arg)
2231{ 2257{
2232 MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data; 2258 MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data;
2233 int error;
2234 struct mgsl_icount cnow; /* kernel counter temps */
2235 struct serial_icounter_struct __user *p_cuser; /* user space */
2236 void __user *argp = (void __user *)arg; 2259 void __user *argp = (void __user *)arg;
2237 unsigned long flags;
2238 2260
2239 if (debug_level >= DEBUG_LEVEL_INFO) 2261 if (debug_level >= DEBUG_LEVEL_INFO)
2240 printk("%s(%d):mgslpc_ioctl %s cmd=%08X\n", __FILE__,__LINE__, 2262 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 return -ENODEV; 2266 return -ENODEV;
2245 2267
2246 if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && 2268 if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
2247 (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) { 2269 (cmd != TIOCMIWAIT)) {
2248 if (tty->flags & (1 << TTY_IO_ERROR)) 2270 if (tty->flags & (1 << TTY_IO_ERROR))
2249 return -EIO; 2271 return -EIO;
2250 } 2272 }
@@ -2274,34 +2296,6 @@ static int mgslpc_ioctl(struct tty_struct *tty, struct file * file,
2274 return wait_events(info, argp); 2296 return wait_events(info, argp);
2275 case TIOCMIWAIT: 2297 case TIOCMIWAIT:
2276 return modem_input_wait(info,(int)arg); 2298 return modem_input_wait(info,(int)arg);
2277 case TIOCGICOUNT:
2278 spin_lock_irqsave(&info->lock,flags);
2279 cnow = info->icount;
2280 spin_unlock_irqrestore(&info->lock,flags);
2281 p_cuser = argp;
2282 PUT_USER(error,cnow.cts, &p_cuser->cts);
2283 if (error) return error;
2284 PUT_USER(error,cnow.dsr, &p_cuser->dsr);
2285 if (error) return error;
2286 PUT_USER(error,cnow.rng, &p_cuser->rng);
2287 if (error) return error;
2288 PUT_USER(error,cnow.dcd, &p_cuser->dcd);
2289 if (error) return error;
2290 PUT_USER(error,cnow.rx, &p_cuser->rx);
2291 if (error) return error;
2292 PUT_USER(error,cnow.tx, &p_cuser->tx);
2293 if (error) return error;
2294 PUT_USER(error,cnow.frame, &p_cuser->frame);
2295 if (error) return error;
2296 PUT_USER(error,cnow.overrun, &p_cuser->overrun);
2297 if (error) return error;
2298 PUT_USER(error,cnow.parity, &p_cuser->parity);
2299 if (error) return error;
2300 PUT_USER(error,cnow.brk, &p_cuser->brk);
2301 if (error) return error;
2302 PUT_USER(error,cnow.buf_overrun, &p_cuser->buf_overrun);
2303 if (error) return error;
2304 return 0;
2305 default: 2299 default:
2306 return -ENOIOCTLCMD; 2300 return -ENOIOCTLCMD;
2307 } 2301 }
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c
index a2a58004e188..3a6824f12be2 100644
--- a/drivers/char/synclink.c
+++ b/drivers/char/synclink.c
@@ -2925,6 +2925,38 @@ static int mgsl_break(struct tty_struct *tty, int break_state)
2925 2925
2926} /* end of mgsl_break() */ 2926} /* end of mgsl_break() */
2927 2927
2928/*
2929 * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
2930 * Return: write counters to the user passed counter struct
2931 * NB: both 1->0 and 0->1 transitions are counted except for
2932 * RI where only 0->1 is counted.
2933 */
2934static int msgl_get_icount(struct tty_struct *tty,
2935 struct serial_icounter_struct *icount)
2936
2937{
2938 struct mgsl_struct * info = tty->driver_data;
2939 struct mgsl_icount cnow; /* kernel counter temps */
2940 unsigned long flags;
2941
2942 spin_lock_irqsave(&info->irq_spinlock,flags);
2943 cnow = info->icount;
2944 spin_unlock_irqrestore(&info->irq_spinlock,flags);
2945
2946 icount->cts = cnow.cts;
2947 icount->dsr = cnow.dsr;
2948 icount->rng = cnow.rng;
2949 icount->dcd = cnow.dcd;
2950 icount->rx = cnow.rx;
2951 icount->tx = cnow.tx;
2952 icount->frame = cnow.frame;
2953 icount->overrun = cnow.overrun;
2954 icount->parity = cnow.parity;
2955 icount->brk = cnow.brk;
2956 icount->buf_overrun = cnow.buf_overrun;
2957 return 0;
2958}
2959
2928/* mgsl_ioctl() Service an IOCTL request 2960/* mgsl_ioctl() Service an IOCTL request
2929 * 2961 *
2930 * Arguments: 2962 * Arguments:
@@ -2949,7 +2981,7 @@ static int mgsl_ioctl(struct tty_struct *tty, struct file * file,
2949 return -ENODEV; 2981 return -ENODEV;
2950 2982
2951 if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && 2983 if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
2952 (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) { 2984 (cmd != TIOCMIWAIT)) {
2953 if (tty->flags & (1 << TTY_IO_ERROR)) 2985 if (tty->flags & (1 << TTY_IO_ERROR))
2954 return -EIO; 2986 return -EIO;
2955 } 2987 }
@@ -2959,11 +2991,7 @@ static int mgsl_ioctl(struct tty_struct *tty, struct file * file,
2959 2991
2960static int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigned long arg) 2992static int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigned long arg)
2961{ 2993{
2962 int error;
2963 struct mgsl_icount cnow; /* kernel counter temps */
2964 void __user *argp = (void __user *)arg; 2994 void __user *argp = (void __user *)arg;
2965 struct serial_icounter_struct __user *p_cuser; /* user space */
2966 unsigned long flags;
2967 2995
2968 switch (cmd) { 2996 switch (cmd) {
2969 case MGSL_IOCGPARAMS: 2997 case MGSL_IOCGPARAMS:
@@ -2992,40 +3020,6 @@ static int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigne
2992 case TIOCMIWAIT: 3020 case TIOCMIWAIT:
2993 return modem_input_wait(info,(int)arg); 3021 return modem_input_wait(info,(int)arg);
2994 3022
2995 /*
2996 * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
2997 * Return: write counters to the user passed counter struct
2998 * NB: both 1->0 and 0->1 transitions are counted except for
2999 * RI where only 0->1 is counted.
3000 */
3001 case TIOCGICOUNT:
3002 spin_lock_irqsave(&info->irq_spinlock,flags);
3003 cnow = info->icount;
3004 spin_unlock_irqrestore(&info->irq_spinlock,flags);
3005 p_cuser = argp;
3006 PUT_USER(error,cnow.cts, &p_cuser->cts);
3007 if (error) return error;
3008 PUT_USER(error,cnow.dsr, &p_cuser->dsr);
3009 if (error) return error;
3010 PUT_USER(error,cnow.rng, &p_cuser->rng);
3011 if (error) return error;
3012 PUT_USER(error,cnow.dcd, &p_cuser->dcd);
3013 if (error) return error;
3014 PUT_USER(error,cnow.rx, &p_cuser->rx);
3015 if (error) return error;
3016 PUT_USER(error,cnow.tx, &p_cuser->tx);
3017 if (error) return error;
3018 PUT_USER(error,cnow.frame, &p_cuser->frame);
3019 if (error) return error;
3020 PUT_USER(error,cnow.overrun, &p_cuser->overrun);
3021 if (error) return error;
3022 PUT_USER(error,cnow.parity, &p_cuser->parity);
3023 if (error) return error;
3024 PUT_USER(error,cnow.brk, &p_cuser->brk);
3025 if (error) return error;
3026 PUT_USER(error,cnow.buf_overrun, &p_cuser->buf_overrun);
3027 if (error) return error;
3028 return 0;
3029 default: 3023 default:
3030 return -ENOIOCTLCMD; 3024 return -ENOIOCTLCMD;
3031 } 3025 }
@@ -4328,6 +4322,7 @@ static const struct tty_operations mgsl_ops = {
4328 .hangup = mgsl_hangup, 4322 .hangup = mgsl_hangup,
4329 .tiocmget = tiocmget, 4323 .tiocmget = tiocmget,
4330 .tiocmset = tiocmset, 4324 .tiocmset = tiocmset,
4325 .get_icount = msgl_get_icount,
4331 .proc_fops = &mgsl_proc_fops, 4326 .proc_fops = &mgsl_proc_fops,
4332}; 4327};
4333 4328
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c
index e63b830c86cc..1746d91205f7 100644
--- a/drivers/char/synclink_gt.c
+++ b/drivers/char/synclink_gt.c
@@ -1032,9 +1032,6 @@ static int ioctl(struct tty_struct *tty, struct file *file,
1032 unsigned int cmd, unsigned long arg) 1032 unsigned int cmd, unsigned long arg)
1033{ 1033{
1034 struct slgt_info *info = tty->driver_data; 1034 struct slgt_info *info = tty->driver_data;
1035 struct mgsl_icount cnow; /* kernel counter temps */
1036 struct serial_icounter_struct __user *p_cuser; /* user space */
1037 unsigned long flags;
1038 void __user *argp = (void __user *)arg; 1035 void __user *argp = (void __user *)arg;
1039 int ret; 1036 int ret;
1040 1037
@@ -1043,7 +1040,7 @@ static int ioctl(struct tty_struct *tty, struct file *file,
1043 DBGINFO(("%s ioctl() cmd=%08X\n", info->device_name, cmd)); 1040 DBGINFO(("%s ioctl() cmd=%08X\n", info->device_name, cmd));
1044 1041
1045 if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && 1042 if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
1046 (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) { 1043 (cmd != TIOCMIWAIT)) {
1047 if (tty->flags & (1 << TTY_IO_ERROR)) 1044 if (tty->flags & (1 << TTY_IO_ERROR))
1048 return -EIO; 1045 return -EIO;
1049 } 1046 }
@@ -1053,24 +1050,6 @@ static int ioctl(struct tty_struct *tty, struct file *file,
1053 return wait_mgsl_event(info, argp); 1050 return wait_mgsl_event(info, argp);
1054 case TIOCMIWAIT: 1051 case TIOCMIWAIT:
1055 return modem_input_wait(info,(int)arg); 1052 return modem_input_wait(info,(int)arg);
1056 case TIOCGICOUNT:
1057 spin_lock_irqsave(&info->lock,flags);
1058 cnow = info->icount;
1059 spin_unlock_irqrestore(&info->lock,flags);
1060 p_cuser = argp;
1061 if (put_user(cnow.cts, &p_cuser->cts) ||
1062 put_user(cnow.dsr, &p_cuser->dsr) ||
1063 put_user(cnow.rng, &p_cuser->rng) ||
1064 put_user(cnow.dcd, &p_cuser->dcd) ||
1065 put_user(cnow.rx, &p_cuser->rx) ||
1066 put_user(cnow.tx, &p_cuser->tx) ||
1067 put_user(cnow.frame, &p_cuser->frame) ||
1068 put_user(cnow.overrun, &p_cuser->overrun) ||
1069 put_user(cnow.parity, &p_cuser->parity) ||
1070 put_user(cnow.brk, &p_cuser->brk) ||
1071 put_user(cnow.buf_overrun, &p_cuser->buf_overrun))
1072 return -EFAULT;
1073 return 0;
1074 case MGSL_IOCSGPIO: 1053 case MGSL_IOCSGPIO:
1075 return set_gpio(info, argp); 1054 return set_gpio(info, argp);
1076 case MGSL_IOCGGPIO: 1055 case MGSL_IOCGGPIO:
@@ -1117,6 +1096,33 @@ static int ioctl(struct tty_struct *tty, struct file *file,
1117 return ret; 1096 return ret;
1118} 1097}
1119 1098
1099static int get_icount(struct tty_struct *tty,
1100 struct serial_icounter_struct *icount)
1101
1102{
1103 struct slgt_info *info = tty->driver_data;
1104 struct mgsl_icount cnow; /* kernel counter temps */
1105 unsigned long flags;
1106
1107 spin_lock_irqsave(&info->lock,flags);
1108 cnow = info->icount;
1109 spin_unlock_irqrestore(&info->lock,flags);
1110
1111 icount->cts = cnow.cts;
1112 icount->dsr = cnow.dsr;
1113 icount->rng = cnow.rng;
1114 icount->dcd = cnow.dcd;
1115 icount->rx = cnow.rx;
1116 icount->tx = cnow.tx;
1117 icount->frame = cnow.frame;
1118 icount->overrun = cnow.overrun;
1119 icount->parity = cnow.parity;
1120 icount->brk = cnow.brk;
1121 icount->buf_overrun = cnow.buf_overrun;
1122
1123 return 0;
1124}
1125
1120/* 1126/*
1121 * support for 32 bit ioctl calls on 64 bit systems 1127 * support for 32 bit ioctl calls on 64 bit systems
1122 */ 1128 */
@@ -1206,10 +1212,6 @@ static long slgt_compat_ioctl(struct tty_struct *tty, struct file *file,
1206 case MGSL_IOCSGPIO: 1212 case MGSL_IOCSGPIO:
1207 case MGSL_IOCGGPIO: 1213 case MGSL_IOCGGPIO:
1208 case MGSL_IOCWAITGPIO: 1214 case MGSL_IOCWAITGPIO:
1209 case TIOCGICOUNT:
1210 rc = ioctl(tty, file, cmd, (unsigned long)(compat_ptr(arg)));
1211 break;
1212
1213 case MGSL_IOCSTXIDLE: 1215 case MGSL_IOCSTXIDLE:
1214 case MGSL_IOCTXENABLE: 1216 case MGSL_IOCTXENABLE:
1215 case MGSL_IOCRXENABLE: 1217 case MGSL_IOCRXENABLE:
@@ -3642,6 +3644,7 @@ static const struct tty_operations ops = {
3642 .hangup = hangup, 3644 .hangup = hangup,
3643 .tiocmget = tiocmget, 3645 .tiocmget = tiocmget,
3644 .tiocmset = tiocmset, 3646 .tiocmset = tiocmset,
3647 .get_icount = get_icount,
3645 .proc_fops = &synclink_gt_proc_fops, 3648 .proc_fops = &synclink_gt_proc_fops,
3646}; 3649};
3647 3650
diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c
index e56caf7d82aa..2f9eb4b0dec1 100644
--- a/drivers/char/synclinkmp.c
+++ b/drivers/char/synclinkmp.c
@@ -1258,10 +1258,6 @@ static int ioctl(struct tty_struct *tty, struct file *file,
1258 unsigned int cmd, unsigned long arg) 1258 unsigned int cmd, unsigned long arg)
1259{ 1259{
1260 SLMP_INFO *info = tty->driver_data; 1260 SLMP_INFO *info = tty->driver_data;
1261 int error;
1262 struct mgsl_icount cnow; /* kernel counter temps */
1263 struct serial_icounter_struct __user *p_cuser; /* user space */
1264 unsigned long flags;
1265 void __user *argp = (void __user *)arg; 1261 void __user *argp = (void __user *)arg;
1266 1262
1267 if (debug_level >= DEBUG_LEVEL_INFO) 1263 if (debug_level >= DEBUG_LEVEL_INFO)
@@ -1272,7 +1268,7 @@ static int ioctl(struct tty_struct *tty, struct file *file,
1272 return -ENODEV; 1268 return -ENODEV;
1273 1269
1274 if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && 1270 if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
1275 (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) { 1271 (cmd != TIOCMIWAIT)) {
1276 if (tty->flags & (1 << TTY_IO_ERROR)) 1272 if (tty->flags & (1 << TTY_IO_ERROR))
1277 return -EIO; 1273 return -EIO;
1278 } 1274 }
@@ -1310,40 +1306,38 @@ static int ioctl(struct tty_struct *tty, struct file *file,
1310 * NB: both 1->0 and 0->1 transitions are counted except for 1306 * NB: both 1->0 and 0->1 transitions are counted except for
1311 * RI where only 0->1 is counted. 1307 * RI where only 0->1 is counted.
1312 */ 1308 */
1313 case TIOCGICOUNT:
1314 spin_lock_irqsave(&info->lock,flags);
1315 cnow = info->icount;
1316 spin_unlock_irqrestore(&info->lock,flags);
1317 p_cuser = argp;
1318 PUT_USER(error,cnow.cts, &p_cuser->cts);
1319 if (error) return error;
1320 PUT_USER(error,cnow.dsr, &p_cuser->dsr);
1321 if (error) return error;
1322 PUT_USER(error,cnow.rng, &p_cuser->rng);
1323 if (error) return error;
1324 PUT_USER(error,cnow.dcd, &p_cuser->dcd);
1325 if (error) return error;
1326 PUT_USER(error,cnow.rx, &p_cuser->rx);
1327 if (error) return error;
1328 PUT_USER(error,cnow.tx, &p_cuser->tx);
1329 if (error) return error;
1330 PUT_USER(error,cnow.frame, &p_cuser->frame);
1331 if (error) return error;
1332 PUT_USER(error,cnow.overrun, &p_cuser->overrun);
1333 if (error) return error;
1334 PUT_USER(error,cnow.parity, &p_cuser->parity);
1335 if (error) return error;
1336 PUT_USER(error,cnow.brk, &p_cuser->brk);
1337 if (error) return error;
1338 PUT_USER(error,cnow.buf_overrun, &p_cuser->buf_overrun);
1339 if (error) return error;
1340 return 0;
1341 default: 1309 default:
1342 return -ENOIOCTLCMD; 1310 return -ENOIOCTLCMD;
1343 } 1311 }
1344 return 0; 1312 return 0;
1345} 1313}
1346 1314
1315static int get_icount(struct tty_struct *tty,
1316 struct serial_icounter_struct *icount)
1317{
1318 SLMP_INFO *info = tty->driver_data;
1319 struct mgsl_icount cnow; /* kernel counter temps */
1320 unsigned long flags;
1321
1322 spin_lock_irqsave(&info->lock,flags);
1323 cnow = info->icount;
1324 spin_unlock_irqrestore(&info->lock,flags);
1325
1326 icount->cts = cnow.cts;
1327 icount->dsr = cnow.dsr;
1328 icount->rng = cnow.rng;
1329 icount->dcd = cnow.dcd;
1330 icount->rx = cnow.rx;
1331 icount->tx = cnow.tx;
1332 icount->frame = cnow.frame;
1333 icount->overrun = cnow.overrun;
1334 icount->parity = cnow.parity;
1335 icount->brk = cnow.brk;
1336 icount->buf_overrun = cnow.buf_overrun;
1337
1338 return 0;
1339}
1340
1347/* 1341/*
1348 * /proc fs routines.... 1342 * /proc fs routines....
1349 */ 1343 */
@@ -3909,6 +3903,7 @@ static const struct tty_operations ops = {
3909 .hangup = hangup, 3903 .hangup = hangup,
3910 .tiocmget = tiocmget, 3904 .tiocmget = tiocmget,
3911 .tiocmset = tiocmset, 3905 .tiocmset = tiocmset,
3906 .get_icount = get_icount,
3912 .proc_fops = &synclinkmp_proc_fops, 3907 .proc_fops = &synclinkmp_proc_fops,
3913}; 3908};
3914 3909