diff options
Diffstat (limited to 'drivers/char/mxser.c')
-rw-r--r-- | drivers/char/mxser.c | 337 |
1 files changed, 139 insertions, 198 deletions
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c index 4c756bbba948..e30575e87648 100644 --- a/drivers/char/mxser.c +++ b/drivers/char/mxser.c | |||
@@ -16,7 +16,6 @@ | |||
16 | * Fed through a cleanup, indent and remove of non 2.6 code by Alan Cox | 16 | * Fed through a cleanup, indent and remove of non 2.6 code by Alan Cox |
17 | * <alan@redhat.com>. The original 1.8 code is available on www.moxa.com. | 17 | * <alan@redhat.com>. The original 1.8 code is available on www.moxa.com. |
18 | * - Fixed x86_64 cleanness | 18 | * - Fixed x86_64 cleanness |
19 | * - Fixed sleep with spinlock held in mxser_send_break | ||
20 | */ | 19 | */ |
21 | 20 | ||
22 | #include <linux/module.h> | 21 | #include <linux/module.h> |
@@ -49,18 +48,12 @@ | |||
49 | 48 | ||
50 | #define MXSER_VERSION "2.0.4" /* 1.12 */ | 49 | #define MXSER_VERSION "2.0.4" /* 1.12 */ |
51 | #define MXSERMAJOR 174 | 50 | #define MXSERMAJOR 174 |
52 | #define MXSERCUMAJOR 175 | ||
53 | 51 | ||
54 | #define MXSER_BOARDS 4 /* Max. boards */ | 52 | #define MXSER_BOARDS 4 /* Max. boards */ |
55 | #define MXSER_PORTS_PER_BOARD 8 /* Max. ports per board */ | 53 | #define MXSER_PORTS_PER_BOARD 8 /* Max. ports per board */ |
56 | #define MXSER_PORTS (MXSER_BOARDS * MXSER_PORTS_PER_BOARD) | 54 | #define MXSER_PORTS (MXSER_BOARDS * MXSER_PORTS_PER_BOARD) |
57 | #define MXSER_ISR_PASS_LIMIT 100 | 55 | #define MXSER_ISR_PASS_LIMIT 100 |
58 | 56 | ||
59 | #define MXSER_ERR_IOADDR -1 | ||
60 | #define MXSER_ERR_IRQ -2 | ||
61 | #define MXSER_ERR_IRQ_CONFLIT -3 | ||
62 | #define MXSER_ERR_VECTOR -4 | ||
63 | |||
64 | /*CheckIsMoxaMust return value*/ | 57 | /*CheckIsMoxaMust return value*/ |
65 | #define MOXA_OTHER_UART 0x00 | 58 | #define MOXA_OTHER_UART 0x00 |
66 | #define MOXA_MUST_MU150_HWID 0x01 | 59 | #define MOXA_MUST_MU150_HWID 0x01 |
@@ -179,14 +172,15 @@ static struct pci_device_id mxser_pcibrds[] = { | |||
179 | }; | 172 | }; |
180 | MODULE_DEVICE_TABLE(pci, mxser_pcibrds); | 173 | MODULE_DEVICE_TABLE(pci, mxser_pcibrds); |
181 | 174 | ||
182 | static int ioaddr[MXSER_BOARDS] = { 0, 0, 0, 0 }; | 175 | static unsigned long ioaddr[MXSER_BOARDS]; |
183 | static int ttymajor = MXSERMAJOR; | 176 | static int ttymajor = MXSERMAJOR; |
184 | 177 | ||
185 | /* Variables for insmod */ | 178 | /* Variables for insmod */ |
186 | 179 | ||
187 | MODULE_AUTHOR("Casper Yang"); | 180 | MODULE_AUTHOR("Casper Yang"); |
188 | MODULE_DESCRIPTION("MOXA Smartio/Industio Family Multiport Board Device Driver"); | 181 | MODULE_DESCRIPTION("MOXA Smartio/Industio Family Multiport Board Device Driver"); |
189 | module_param_array(ioaddr, int, NULL, 0); | 182 | module_param_array(ioaddr, ulong, NULL, 0); |
183 | MODULE_PARM_DESC(ioaddr, "ISA io addresses to look for a moxa board"); | ||
190 | module_param(ttymajor, int, 0); | 184 | module_param(ttymajor, int, 0); |
191 | MODULE_LICENSE("GPL"); | 185 | MODULE_LICENSE("GPL"); |
192 | 186 | ||
@@ -196,7 +190,6 @@ struct mxser_log { | |||
196 | unsigned long txcnt[MXSER_PORTS]; | 190 | unsigned long txcnt[MXSER_PORTS]; |
197 | }; | 191 | }; |
198 | 192 | ||
199 | |||
200 | struct mxser_mon { | 193 | struct mxser_mon { |
201 | unsigned long rxcnt; | 194 | unsigned long rxcnt; |
202 | unsigned long txcnt; | 195 | unsigned long txcnt; |
@@ -287,19 +280,9 @@ struct mxser_mstatus { | |||
287 | int dcd; | 280 | int dcd; |
288 | }; | 281 | }; |
289 | 282 | ||
290 | static struct mxser_mstatus GMStatus[MXSER_PORTS]; | ||
291 | |||
292 | static int mxserBoardCAP[MXSER_BOARDS] = { | ||
293 | 0, 0, 0, 0 | ||
294 | /* 0x180, 0x280, 0x200, 0x320 */ | ||
295 | }; | ||
296 | |||
297 | static struct mxser_board mxser_boards[MXSER_BOARDS]; | 283 | static struct mxser_board mxser_boards[MXSER_BOARDS]; |
298 | static struct tty_driver *mxvar_sdriver; | 284 | static struct tty_driver *mxvar_sdriver; |
299 | static struct mxser_log mxvar_log; | 285 | static struct mxser_log mxvar_log; |
300 | static int mxvar_diagflag; | ||
301 | static unsigned char mxser_msr[MXSER_PORTS + 1]; | ||
302 | static struct mxser_mon_ext mon_data_ext; | ||
303 | static int mxser_set_baud_method[MXSER_PORTS + 1]; | 286 | static int mxser_set_baud_method[MXSER_PORTS + 1]; |
304 | 287 | ||
305 | static void mxser_enable_must_enchance_mode(unsigned long baseio) | 288 | static void mxser_enable_must_enchance_mode(unsigned long baseio) |
@@ -543,6 +526,7 @@ static void process_txrx_fifo(struct mxser_port *info) | |||
543 | 526 | ||
544 | static unsigned char mxser_get_msr(int baseaddr, int mode, int port) | 527 | static unsigned char mxser_get_msr(int baseaddr, int mode, int port) |
545 | { | 528 | { |
529 | static unsigned char mxser_msr[MXSER_PORTS + 1]; | ||
546 | unsigned char status = 0; | 530 | unsigned char status = 0; |
547 | 531 | ||
548 | status = inb(baseaddr + UART_MSR); | 532 | status = inb(baseaddr + UART_MSR); |
@@ -1319,13 +1303,9 @@ static void mxser_flush_chars(struct tty_struct *tty) | |||
1319 | struct mxser_port *info = tty->driver_data; | 1303 | struct mxser_port *info = tty->driver_data; |
1320 | unsigned long flags; | 1304 | unsigned long flags; |
1321 | 1305 | ||
1322 | if (info->xmit_cnt <= 0 || | 1306 | if (info->xmit_cnt <= 0 || tty->stopped || !info->port.xmit_buf || |
1323 | tty->stopped || | 1307 | (tty->hw_stopped && info->type != PORT_16550A && |
1324 | !info->port.xmit_buf || | 1308 | !info->board->chip_flag)) |
1325 | (tty->hw_stopped && | ||
1326 | (info->type != PORT_16550A) && | ||
1327 | (!info->board->chip_flag) | ||
1328 | )) | ||
1329 | return; | 1309 | return; |
1330 | 1310 | ||
1331 | spin_lock_irqsave(&info->slock, flags); | 1311 | spin_lock_irqsave(&info->slock, flags); |
@@ -1343,9 +1323,7 @@ static int mxser_write_room(struct tty_struct *tty) | |||
1343 | int ret; | 1323 | int ret; |
1344 | 1324 | ||
1345 | ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1; | 1325 | ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1; |
1346 | if (ret < 0) | 1326 | return ret < 0 ? 0 : ret; |
1347 | ret = 0; | ||
1348 | return ret; | ||
1349 | } | 1327 | } |
1350 | 1328 | ||
1351 | static int mxser_chars_in_buffer(struct tty_struct *tty) | 1329 | static int mxser_chars_in_buffer(struct tty_struct *tty) |
@@ -1634,6 +1612,8 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp) | |||
1634 | 1612 | ||
1635 | switch (cmd) { | 1613 | switch (cmd) { |
1636 | case MOXA_GET_MAJOR: | 1614 | case MOXA_GET_MAJOR: |
1615 | printk(KERN_WARNING "mxser: '%s' uses deprecated ioctl %x, fix " | ||
1616 | "your userspace\n", current->comm, cmd); | ||
1637 | return put_user(ttymajor, (int __user *)argp); | 1617 | return put_user(ttymajor, (int __user *)argp); |
1638 | 1618 | ||
1639 | case MOXA_CHKPORTENABLE: | 1619 | case MOXA_CHKPORTENABLE: |
@@ -1651,62 +1631,60 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp) | |||
1651 | ret = -EFAULT; | 1631 | ret = -EFAULT; |
1652 | unlock_kernel(); | 1632 | unlock_kernel(); |
1653 | return ret; | 1633 | return ret; |
1654 | case MOXA_GETMSTATUS: | 1634 | case MOXA_GETMSTATUS: { |
1635 | struct mxser_mstatus ms, __user *msu = argp; | ||
1655 | lock_kernel(); | 1636 | lock_kernel(); |
1656 | for (i = 0; i < MXSER_BOARDS; i++) | 1637 | for (i = 0; i < MXSER_BOARDS; i++) |
1657 | for (j = 0; j < MXSER_PORTS_PER_BOARD; j++) { | 1638 | for (j = 0; j < MXSER_PORTS_PER_BOARD; j++) { |
1658 | port = &mxser_boards[i].ports[j]; | 1639 | port = &mxser_boards[i].ports[j]; |
1640 | memset(&ms, 0, sizeof(ms)); | ||
1659 | 1641 | ||
1660 | GMStatus[i].ri = 0; | 1642 | if (!port->ioaddr) |
1661 | if (!port->ioaddr) { | 1643 | goto copy; |
1662 | GMStatus[i].dcd = 0; | ||
1663 | GMStatus[i].dsr = 0; | ||
1664 | GMStatus[i].cts = 0; | ||
1665 | continue; | ||
1666 | } | ||
1667 | 1644 | ||
1668 | if (!port->port.tty || !port->port.tty->termios) | 1645 | if (!port->port.tty || !port->port.tty->termios) |
1669 | GMStatus[i].cflag = | 1646 | ms.cflag = port->normal_termios.c_cflag; |
1670 | port->normal_termios.c_cflag; | ||
1671 | else | 1647 | else |
1672 | GMStatus[i].cflag = | 1648 | ms.cflag = port->port.tty->termios->c_cflag; |
1673 | port->port.tty->termios->c_cflag; | ||
1674 | 1649 | ||
1675 | status = inb(port->ioaddr + UART_MSR); | 1650 | status = inb(port->ioaddr + UART_MSR); |
1676 | if (status & 0x80 /*UART_MSR_DCD */ ) | 1651 | if (status & UART_MSR_DCD) |
1677 | GMStatus[i].dcd = 1; | 1652 | ms.dcd = 1; |
1678 | else | 1653 | if (status & UART_MSR_DSR) |
1679 | GMStatus[i].dcd = 0; | 1654 | ms.dsr = 1; |
1680 | 1655 | if (status & UART_MSR_CTS) | |
1681 | if (status & 0x20 /*UART_MSR_DSR */ ) | 1656 | ms.cts = 1; |
1682 | GMStatus[i].dsr = 1; | 1657 | copy: |
1683 | else | 1658 | if (copy_to_user(msu, &ms, sizeof(ms))) { |
1684 | GMStatus[i].dsr = 0; | 1659 | unlock_kernel(); |
1685 | 1660 | return -EFAULT; | |
1686 | 1661 | } | |
1687 | if (status & 0x10 /*UART_MSR_CTS */ ) | 1662 | msu++; |
1688 | GMStatus[i].cts = 1; | ||
1689 | else | ||
1690 | GMStatus[i].cts = 0; | ||
1691 | } | 1663 | } |
1692 | unlock_kernel(); | 1664 | unlock_kernel(); |
1693 | if (copy_to_user(argp, GMStatus, | ||
1694 | sizeof(struct mxser_mstatus) * MXSER_PORTS)) | ||
1695 | return -EFAULT; | ||
1696 | return 0; | 1665 | return 0; |
1666 | } | ||
1697 | case MOXA_ASPP_MON_EXT: { | 1667 | case MOXA_ASPP_MON_EXT: { |
1698 | int p, shiftbit; | 1668 | struct mxser_mon_ext *me; /* it's 2k, stack unfriendly */ |
1699 | unsigned long opmode; | 1669 | unsigned int cflag, iflag, p; |
1700 | unsigned cflag, iflag; | 1670 | u8 opmode; |
1671 | |||
1672 | me = kzalloc(sizeof(*me), GFP_KERNEL); | ||
1673 | if (!me) | ||
1674 | return -ENOMEM; | ||
1701 | 1675 | ||
1702 | lock_kernel(); | 1676 | lock_kernel(); |
1703 | for (i = 0; i < MXSER_BOARDS; i++) { | 1677 | for (i = 0, p = 0; i < MXSER_BOARDS; i++) { |
1704 | for (j = 0; j < MXSER_PORTS_PER_BOARD; j++) { | 1678 | for (j = 0; j < MXSER_PORTS_PER_BOARD; j++, p++) { |
1679 | if (p >= ARRAY_SIZE(me->rx_cnt)) { | ||
1680 | i = MXSER_BOARDS; | ||
1681 | break; | ||
1682 | } | ||
1705 | port = &mxser_boards[i].ports[j]; | 1683 | port = &mxser_boards[i].ports[j]; |
1706 | if (!port->ioaddr) | 1684 | if (!port->ioaddr) |
1707 | continue; | 1685 | continue; |
1708 | 1686 | ||
1709 | status = mxser_get_msr(port->ioaddr, 0, i); | 1687 | status = mxser_get_msr(port->ioaddr, 0, p); |
1710 | 1688 | ||
1711 | if (status & UART_MSR_TERI) | 1689 | if (status & UART_MSR_TERI) |
1712 | port->icount.rng++; | 1690 | port->icount.rng++; |
@@ -1718,16 +1696,13 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp) | |||
1718 | port->icount.cts++; | 1696 | port->icount.cts++; |
1719 | 1697 | ||
1720 | port->mon_data.modem_status = status; | 1698 | port->mon_data.modem_status = status; |
1721 | mon_data_ext.rx_cnt[i] = port->mon_data.rxcnt; | 1699 | me->rx_cnt[p] = port->mon_data.rxcnt; |
1722 | mon_data_ext.tx_cnt[i] = port->mon_data.txcnt; | 1700 | me->tx_cnt[p] = port->mon_data.txcnt; |
1723 | mon_data_ext.up_rxcnt[i] = | 1701 | me->up_rxcnt[p] = port->mon_data.up_rxcnt; |
1724 | port->mon_data.up_rxcnt; | 1702 | me->up_txcnt[p] = port->mon_data.up_txcnt; |
1725 | mon_data_ext.up_txcnt[i] = | 1703 | me->modem_status[p] = |
1726 | port->mon_data.up_txcnt; | ||
1727 | mon_data_ext.modem_status[i] = | ||
1728 | port->mon_data.modem_status; | 1704 | port->mon_data.modem_status; |
1729 | mon_data_ext.baudrate[i] = | 1705 | me->baudrate[p] = tty_get_baud_rate(port->port.tty); |
1730 | tty_get_baud_rate(port->port.tty); | ||
1731 | 1706 | ||
1732 | if (!port->port.tty || !port->port.tty->termios) { | 1707 | if (!port->port.tty || !port->port.tty->termios) { |
1733 | cflag = port->normal_termios.c_cflag; | 1708 | cflag = port->normal_termios.c_cflag; |
@@ -1737,40 +1712,31 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp) | |||
1737 | iflag = port->port.tty->termios->c_iflag; | 1712 | iflag = port->port.tty->termios->c_iflag; |
1738 | } | 1713 | } |
1739 | 1714 | ||
1740 | mon_data_ext.databits[i] = cflag & CSIZE; | 1715 | me->databits[p] = cflag & CSIZE; |
1741 | 1716 | me->stopbits[p] = cflag & CSTOPB; | |
1742 | mon_data_ext.stopbits[i] = cflag & CSTOPB; | 1717 | me->parity[p] = cflag & (PARENB | PARODD | |
1743 | 1718 | CMSPAR); | |
1744 | mon_data_ext.parity[i] = | ||
1745 | cflag & (PARENB | PARODD | CMSPAR); | ||
1746 | |||
1747 | mon_data_ext.flowctrl[i] = 0x00; | ||
1748 | 1719 | ||
1749 | if (cflag & CRTSCTS) | 1720 | if (cflag & CRTSCTS) |
1750 | mon_data_ext.flowctrl[i] |= 0x03; | 1721 | me->flowctrl[p] |= 0x03; |
1751 | 1722 | ||
1752 | if (iflag & (IXON | IXOFF)) | 1723 | if (iflag & (IXON | IXOFF)) |
1753 | mon_data_ext.flowctrl[i] |= 0x0C; | 1724 | me->flowctrl[p] |= 0x0C; |
1754 | 1725 | ||
1755 | if (port->type == PORT_16550A) | 1726 | if (port->type == PORT_16550A) |
1756 | mon_data_ext.fifo[i] = 1; | 1727 | me->fifo[p] = 1; |
1757 | else | ||
1758 | mon_data_ext.fifo[i] = 0; | ||
1759 | 1728 | ||
1760 | p = i % 4; | 1729 | opmode = inb(port->opmode_ioaddr) >> |
1761 | shiftbit = p * 2; | 1730 | ((p % 4) * 2); |
1762 | opmode = inb(port->opmode_ioaddr) >> shiftbit; | ||
1763 | opmode &= OP_MODE_MASK; | 1731 | opmode &= OP_MODE_MASK; |
1764 | 1732 | me->iftype[p] = opmode; | |
1765 | mon_data_ext.iftype[i] = opmode; | ||
1766 | |||
1767 | } | 1733 | } |
1768 | } | 1734 | } |
1769 | unlock_kernel(); | 1735 | unlock_kernel(); |
1770 | if (copy_to_user(argp, &mon_data_ext, | 1736 | if (copy_to_user(argp, me, sizeof(*me))) |
1771 | sizeof(mon_data_ext))) | 1737 | ret = -EFAULT; |
1772 | return -EFAULT; | 1738 | kfree(me); |
1773 | return 0; | 1739 | return ret; |
1774 | } | 1740 | } |
1775 | default: | 1741 | default: |
1776 | return -ENOIOCTLCMD; | 1742 | return -ENOIOCTLCMD; |
@@ -1804,7 +1770,6 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, | |||
1804 | { | 1770 | { |
1805 | struct mxser_port *info = tty->driver_data; | 1771 | struct mxser_port *info = tty->driver_data; |
1806 | struct async_icount cnow; | 1772 | struct async_icount cnow; |
1807 | struct serial_icounter_struct __user *p_cuser; | ||
1808 | unsigned long flags; | 1773 | unsigned long flags; |
1809 | void __user *argp = (void __user *)arg; | 1774 | void __user *argp = (void __user *)arg; |
1810 | int retval; | 1775 | int retval; |
@@ -1884,30 +1849,26 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, | |||
1884 | * NB: both 1->0 and 0->1 transitions are counted except for | 1849 | * NB: both 1->0 and 0->1 transitions are counted except for |
1885 | * RI where only 0->1 is counted. | 1850 | * RI where only 0->1 is counted. |
1886 | */ | 1851 | */ |
1887 | case TIOCGICOUNT: | 1852 | case TIOCGICOUNT: { |
1853 | struct serial_icounter_struct icnt = { 0 }; | ||
1888 | spin_lock_irqsave(&info->slock, flags); | 1854 | spin_lock_irqsave(&info->slock, flags); |
1889 | cnow = info->icount; | 1855 | cnow = info->icount; |
1890 | spin_unlock_irqrestore(&info->slock, flags); | 1856 | spin_unlock_irqrestore(&info->slock, flags); |
1891 | p_cuser = argp; | 1857 | |
1892 | if (put_user(cnow.frame, &p_cuser->frame)) | 1858 | icnt.frame = cnow.frame; |
1893 | return -EFAULT; | 1859 | icnt.brk = cnow.brk; |
1894 | if (put_user(cnow.brk, &p_cuser->brk)) | 1860 | icnt.overrun = cnow.overrun; |
1895 | return -EFAULT; | 1861 | icnt.buf_overrun = cnow.buf_overrun; |
1896 | if (put_user(cnow.overrun, &p_cuser->overrun)) | 1862 | icnt.parity = cnow.parity; |
1897 | return -EFAULT; | 1863 | icnt.rx = cnow.rx; |
1898 | if (put_user(cnow.buf_overrun, &p_cuser->buf_overrun)) | 1864 | icnt.tx = cnow.tx; |
1899 | return -EFAULT; | 1865 | icnt.cts = cnow.cts; |
1900 | if (put_user(cnow.parity, &p_cuser->parity)) | 1866 | icnt.dsr = cnow.dsr; |
1901 | return -EFAULT; | 1867 | icnt.rng = cnow.rng; |
1902 | if (put_user(cnow.rx, &p_cuser->rx)) | 1868 | icnt.dcd = cnow.dcd; |
1903 | return -EFAULT; | 1869 | |
1904 | if (put_user(cnow.tx, &p_cuser->tx)) | 1870 | return copy_to_user(argp, &icnt, sizeof(icnt)) ? -EFAULT : 0; |
1905 | return -EFAULT; | 1871 | } |
1906 | put_user(cnow.cts, &p_cuser->cts); | ||
1907 | put_user(cnow.dsr, &p_cuser->dsr); | ||
1908 | put_user(cnow.rng, &p_cuser->rng); | ||
1909 | put_user(cnow.dcd, &p_cuser->dcd); | ||
1910 | return 0; | ||
1911 | case MOXA_HighSpeedOn: | 1872 | case MOXA_HighSpeedOn: |
1912 | return put_user(info->baud_base != 115200 ? 1 : 0, (int __user *)argp); | 1873 | return put_user(info->baud_base != 115200 ? 1 : 0, (int __user *)argp); |
1913 | case MOXA_SDS_RSTICOUNTER: | 1874 | case MOXA_SDS_RSTICOUNTER: |
@@ -2503,7 +2464,8 @@ static int __devinit mxser_initbrd(struct mxser_board *brd, | |||
2503 | unsigned int i; | 2464 | unsigned int i; |
2504 | int retval; | 2465 | int retval; |
2505 | 2466 | ||
2506 | printk(KERN_INFO "max. baud rate = %d bps.\n", brd->ports[0].max_baud); | 2467 | printk(KERN_INFO "mxser: max. baud rate = %d bps\n", |
2468 | brd->ports[0].max_baud); | ||
2507 | 2469 | ||
2508 | for (i = 0; i < brd->info->nports; i++) { | 2470 | for (i = 0; i < brd->info->nports; i++) { |
2509 | info = &brd->ports[i]; | 2471 | info = &brd->ports[i]; |
@@ -2586,28 +2548,32 @@ static int __init mxser_get_ISA_conf(int cap, struct mxser_board *brd) | |||
2586 | irq = regs[9] & 0xF000; | 2548 | irq = regs[9] & 0xF000; |
2587 | irq = irq | (irq >> 4); | 2549 | irq = irq | (irq >> 4); |
2588 | if (irq != (regs[9] & 0xFF00)) | 2550 | if (irq != (regs[9] & 0xFF00)) |
2589 | return MXSER_ERR_IRQ_CONFLIT; | 2551 | goto err_irqconflict; |
2590 | } else if (brd->info->nports == 4) { | 2552 | } else if (brd->info->nports == 4) { |
2591 | irq = regs[9] & 0xF000; | 2553 | irq = regs[9] & 0xF000; |
2592 | irq = irq | (irq >> 4); | 2554 | irq = irq | (irq >> 4); |
2593 | irq = irq | (irq >> 8); | 2555 | irq = irq | (irq >> 8); |
2594 | if (irq != regs[9]) | 2556 | if (irq != regs[9]) |
2595 | return MXSER_ERR_IRQ_CONFLIT; | 2557 | goto err_irqconflict; |
2596 | } else if (brd->info->nports == 8) { | 2558 | } else if (brd->info->nports == 8) { |
2597 | irq = regs[9] & 0xF000; | 2559 | irq = regs[9] & 0xF000; |
2598 | irq = irq | (irq >> 4); | 2560 | irq = irq | (irq >> 4); |
2599 | irq = irq | (irq >> 8); | 2561 | irq = irq | (irq >> 8); |
2600 | if ((irq != regs[9]) || (irq != regs[10])) | 2562 | if ((irq != regs[9]) || (irq != regs[10])) |
2601 | return MXSER_ERR_IRQ_CONFLIT; | 2563 | goto err_irqconflict; |
2602 | } | 2564 | } |
2603 | 2565 | ||
2604 | if (!irq) | 2566 | if (!irq) { |
2605 | return MXSER_ERR_IRQ; | 2567 | printk(KERN_ERR "mxser: interrupt number unset\n"); |
2568 | return -EIO; | ||
2569 | } | ||
2606 | brd->irq = ((int)(irq & 0xF000) >> 12); | 2570 | brd->irq = ((int)(irq & 0xF000) >> 12); |
2607 | for (i = 0; i < 8; i++) | 2571 | for (i = 0; i < 8; i++) |
2608 | brd->ports[i].ioaddr = (int) regs[i + 1] & 0xFFF8; | 2572 | brd->ports[i].ioaddr = (int) regs[i + 1] & 0xFFF8; |
2609 | if ((regs[12] & 0x80) == 0) | 2573 | if ((regs[12] & 0x80) == 0) { |
2610 | return MXSER_ERR_VECTOR; | 2574 | printk(KERN_ERR "mxser: invalid interrupt vector\n"); |
2575 | return -EIO; | ||
2576 | } | ||
2611 | brd->vector = (int)regs[11]; /* interrupt vector */ | 2577 | brd->vector = (int)regs[11]; /* interrupt vector */ |
2612 | if (id == 1) | 2578 | if (id == 1) |
2613 | brd->vector_mask = 0x00FF; | 2579 | brd->vector_mask = 0x00FF; |
@@ -2634,13 +2600,26 @@ static int __init mxser_get_ISA_conf(int cap, struct mxser_board *brd) | |||
2634 | else | 2600 | else |
2635 | brd->uart_type = PORT_16450; | 2601 | brd->uart_type = PORT_16450; |
2636 | if (!request_region(brd->ports[0].ioaddr, 8 * brd->info->nports, | 2602 | if (!request_region(brd->ports[0].ioaddr, 8 * brd->info->nports, |
2637 | "mxser(IO)")) | 2603 | "mxser(IO)")) { |
2638 | return MXSER_ERR_IOADDR; | 2604 | printk(KERN_ERR "mxser: can't request ports I/O region: " |
2605 | "0x%.8lx-0x%.8lx\n", | ||
2606 | brd->ports[0].ioaddr, brd->ports[0].ioaddr + | ||
2607 | 8 * brd->info->nports - 1); | ||
2608 | return -EIO; | ||
2609 | } | ||
2639 | if (!request_region(brd->vector, 1, "mxser(vector)")) { | 2610 | if (!request_region(brd->vector, 1, "mxser(vector)")) { |
2640 | release_region(brd->ports[0].ioaddr, 8 * brd->info->nports); | 2611 | release_region(brd->ports[0].ioaddr, 8 * brd->info->nports); |
2641 | return MXSER_ERR_VECTOR; | 2612 | printk(KERN_ERR "mxser: can't request interrupt vector region: " |
2613 | "0x%.8lx-0x%.8lx\n", | ||
2614 | brd->ports[0].ioaddr, brd->ports[0].ioaddr + | ||
2615 | 8 * brd->info->nports - 1); | ||
2616 | return -EIO; | ||
2642 | } | 2617 | } |
2643 | return brd->info->nports; | 2618 | return brd->info->nports; |
2619 | |||
2620 | err_irqconflict: | ||
2621 | printk(KERN_ERR "mxser: invalid interrupt number\n"); | ||
2622 | return -EIO; | ||
2644 | } | 2623 | } |
2645 | 2624 | ||
2646 | static int __devinit mxser_probe(struct pci_dev *pdev, | 2625 | static int __devinit mxser_probe(struct pci_dev *pdev, |
@@ -2657,20 +2636,20 @@ static int __devinit mxser_probe(struct pci_dev *pdev, | |||
2657 | break; | 2636 | break; |
2658 | 2637 | ||
2659 | if (i >= MXSER_BOARDS) { | 2638 | if (i >= MXSER_BOARDS) { |
2660 | printk(KERN_ERR "Too many Smartio/Industio family boards found " | 2639 | dev_err(&pdev->dev, "too many boards found (maximum %d), board " |
2661 | "(maximum %d), board not configured\n", MXSER_BOARDS); | 2640 | "not configured\n", MXSER_BOARDS); |
2662 | goto err; | 2641 | goto err; |
2663 | } | 2642 | } |
2664 | 2643 | ||
2665 | brd = &mxser_boards[i]; | 2644 | brd = &mxser_boards[i]; |
2666 | brd->idx = i * MXSER_PORTS_PER_BOARD; | 2645 | brd->idx = i * MXSER_PORTS_PER_BOARD; |
2667 | printk(KERN_INFO "Found MOXA %s board (BusNo=%d, DevNo=%d)\n", | 2646 | dev_info(&pdev->dev, "found MOXA %s board (BusNo=%d, DevNo=%d)\n", |
2668 | mxser_cards[ent->driver_data].name, | 2647 | mxser_cards[ent->driver_data].name, |
2669 | pdev->bus->number, PCI_SLOT(pdev->devfn)); | 2648 | pdev->bus->number, PCI_SLOT(pdev->devfn)); |
2670 | 2649 | ||
2671 | retval = pci_enable_device(pdev); | 2650 | retval = pci_enable_device(pdev); |
2672 | if (retval) { | 2651 | if (retval) { |
2673 | printk(KERN_ERR "Moxa SmartI/O PCI enable fail !\n"); | 2652 | dev_err(&pdev->dev, "PCI enable failed\n"); |
2674 | goto err; | 2653 | goto err; |
2675 | } | 2654 | } |
2676 | 2655 | ||
@@ -2772,11 +2751,8 @@ static struct pci_driver mxser_driver = { | |||
2772 | static int __init mxser_module_init(void) | 2751 | static int __init mxser_module_init(void) |
2773 | { | 2752 | { |
2774 | struct mxser_board *brd; | 2753 | struct mxser_board *brd; |
2775 | unsigned long cap; | 2754 | unsigned int b, i, m; |
2776 | unsigned int i, m, isaloop; | 2755 | int retval; |
2777 | int retval, b; | ||
2778 | |||
2779 | pr_debug("Loading module mxser ...\n"); | ||
2780 | 2756 | ||
2781 | mxvar_sdriver = alloc_tty_driver(MXSER_PORTS + 1); | 2757 | mxvar_sdriver = alloc_tty_driver(MXSER_PORTS + 1); |
2782 | if (!mxvar_sdriver) | 2758 | if (!mxvar_sdriver) |
@@ -2806,74 +2782,43 @@ static int __init mxser_module_init(void) | |||
2806 | goto err_put; | 2782 | goto err_put; |
2807 | } | 2783 | } |
2808 | 2784 | ||
2809 | mxvar_diagflag = 0; | ||
2810 | |||
2811 | m = 0; | ||
2812 | /* Start finding ISA boards here */ | 2785 | /* Start finding ISA boards here */ |
2813 | for (isaloop = 0; isaloop < 2; isaloop++) | 2786 | for (m = 0, b = 0; b < MXSER_BOARDS; b++) { |
2814 | for (b = 0; b < MXSER_BOARDS && m < MXSER_BOARDS; b++) { | 2787 | if (!ioaddr[b]) |
2815 | if (!isaloop) | 2788 | continue; |
2816 | cap = mxserBoardCAP[b]; /* predefined */ | 2789 | |
2817 | else | 2790 | brd = &mxser_boards[m]; |
2818 | cap = ioaddr[b]; /* module param */ | 2791 | retval = mxser_get_ISA_conf(!ioaddr[b], brd); |
2819 | 2792 | if (retval <= 0) { | |
2820 | if (!cap) | 2793 | brd->info = NULL; |
2821 | continue; | 2794 | continue; |
2795 | } | ||
2822 | 2796 | ||
2823 | brd = &mxser_boards[m]; | 2797 | printk(KERN_INFO "mxser: found MOXA %s board (CAP=0x%lx)\n", |
2824 | retval = mxser_get_ISA_conf(cap, brd); | 2798 | brd->info->name, ioaddr[b]); |
2825 | |||
2826 | if (retval != 0) | ||
2827 | printk(KERN_INFO "Found MOXA %s board " | ||
2828 | "(CAP=0x%x)\n", | ||
2829 | brd->info->name, ioaddr[b]); | ||
2830 | |||
2831 | if (retval <= 0) { | ||
2832 | if (retval == MXSER_ERR_IRQ) | ||
2833 | printk(KERN_ERR "Invalid interrupt " | ||
2834 | "number, board not " | ||
2835 | "configured\n"); | ||
2836 | else if (retval == MXSER_ERR_IRQ_CONFLIT) | ||
2837 | printk(KERN_ERR "Invalid interrupt " | ||
2838 | "number, board not " | ||
2839 | "configured\n"); | ||
2840 | else if (retval == MXSER_ERR_VECTOR) | ||
2841 | printk(KERN_ERR "Invalid interrupt " | ||
2842 | "vector, board not " | ||
2843 | "configured\n"); | ||
2844 | else if (retval == MXSER_ERR_IOADDR) | ||
2845 | printk(KERN_ERR "Invalid I/O address, " | ||
2846 | "board not configured\n"); | ||
2847 | |||
2848 | brd->info = NULL; | ||
2849 | continue; | ||
2850 | } | ||
2851 | 2799 | ||
2852 | /* mxser_initbrd will hook ISR. */ | 2800 | /* mxser_initbrd will hook ISR. */ |
2853 | if (mxser_initbrd(brd, NULL) < 0) { | 2801 | if (mxser_initbrd(brd, NULL) < 0) { |
2854 | brd->info = NULL; | 2802 | brd->info = NULL; |
2855 | continue; | 2803 | continue; |
2856 | } | 2804 | } |
2857 | 2805 | ||
2858 | brd->idx = m * MXSER_PORTS_PER_BOARD; | 2806 | brd->idx = m * MXSER_PORTS_PER_BOARD; |
2859 | for (i = 0; i < brd->info->nports; i++) | 2807 | for (i = 0; i < brd->info->nports; i++) |
2860 | tty_register_device(mxvar_sdriver, brd->idx + i, | 2808 | tty_register_device(mxvar_sdriver, brd->idx + i, NULL); |
2861 | NULL); | ||
2862 | 2809 | ||
2863 | m++; | 2810 | m++; |
2864 | } | 2811 | } |
2865 | 2812 | ||
2866 | retval = pci_register_driver(&mxser_driver); | 2813 | retval = pci_register_driver(&mxser_driver); |
2867 | if (retval) { | 2814 | if (retval) { |
2868 | printk(KERN_ERR "Can't register pci driver\n"); | 2815 | printk(KERN_ERR "mxser: can't register pci driver\n"); |
2869 | if (!m) { | 2816 | if (!m) { |
2870 | retval = -ENODEV; | 2817 | retval = -ENODEV; |
2871 | goto err_unr; | 2818 | goto err_unr; |
2872 | } /* else: we have some ISA cards under control */ | 2819 | } /* else: we have some ISA cards under control */ |
2873 | } | 2820 | } |
2874 | 2821 | ||
2875 | pr_debug("Done.\n"); | ||
2876 | |||
2877 | return 0; | 2822 | return 0; |
2878 | err_unr: | 2823 | err_unr: |
2879 | tty_unregister_driver(mxvar_sdriver); | 2824 | tty_unregister_driver(mxvar_sdriver); |
@@ -2886,8 +2831,6 @@ static void __exit mxser_module_exit(void) | |||
2886 | { | 2831 | { |
2887 | unsigned int i, j; | 2832 | unsigned int i, j; |
2888 | 2833 | ||
2889 | pr_debug("Unloading module mxser ...\n"); | ||
2890 | |||
2891 | pci_unregister_driver(&mxser_driver); | 2834 | pci_unregister_driver(&mxser_driver); |
2892 | 2835 | ||
2893 | for (i = 0; i < MXSER_BOARDS; i++) /* ISA remains */ | 2836 | for (i = 0; i < MXSER_BOARDS; i++) /* ISA remains */ |
@@ -2901,8 +2844,6 @@ static void __exit mxser_module_exit(void) | |||
2901 | for (i = 0; i < MXSER_BOARDS; i++) | 2844 | for (i = 0; i < MXSER_BOARDS; i++) |
2902 | if (mxser_boards[i].info != NULL) | 2845 | if (mxser_boards[i].info != NULL) |
2903 | mxser_release_res(&mxser_boards[i], NULL, 1); | 2846 | mxser_release_res(&mxser_boards[i], NULL, 1); |
2904 | |||
2905 | pr_debug("Done.\n"); | ||
2906 | } | 2847 | } |
2907 | 2848 | ||
2908 | module_init(mxser_module_init); | 2849 | module_init(mxser_module_init); |