aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/char/mxser_new.c111
-rw-r--r--drivers/char/mxser_new.h14
2 files changed, 105 insertions, 20 deletions
diff --git a/drivers/char/mxser_new.c b/drivers/char/mxser_new.c
index 0b66056cd400..4c805496fb36 100644
--- a/drivers/char/mxser_new.c
+++ b/drivers/char/mxser_new.c
@@ -49,7 +49,7 @@
49 49
50#include "mxser_new.h" 50#include "mxser_new.h"
51 51
52#define MXSER_VERSION "2.0" 52#define MXSER_VERSION "2.0.1" /* 1.9.15 */
53#define MXSERMAJOR 174 53#define MXSERMAJOR 174
54#define MXSERCUMAJOR 175 54#define MXSERCUMAJOR 175
55 55
@@ -179,6 +179,18 @@ static struct pci_device_id mxser_pcibrds[] = {
179}; 179};
180MODULE_DEVICE_TABLE(pci, mxser_pcibrds); 180MODULE_DEVICE_TABLE(pci, mxser_pcibrds);
181 181
182static int mxvar_baud_table[] = {
183 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400,
184 4800, 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600
185};
186static unsigned int mxvar_baud_table1[] = {
187 0, B50, B75, B110, B134, B150, B200, B300, B600, B1200, B1800, B2400,
188 B4800, B9600, B19200, B38400, B57600, B115200, B230400, B460800, B921600
189};
190#define BAUD_TABLE_NO ARRAY_SIZE(mxvar_baud_table)
191
192#define B_SPEC B2000000
193
182static int ioaddr[MXSER_BOARDS] = { 0, 0, 0, 0 }; 194static int ioaddr[MXSER_BOARDS] = { 0, 0, 0, 0 };
183static int ttymajor = MXSERMAJOR; 195static int ttymajor = MXSERMAJOR;
184static int calloutmajor = MXSERCUMAJOR; 196static int calloutmajor = MXSERCUMAJOR;
@@ -240,6 +252,7 @@ struct mxser_port {
240 long realbaud; 252 long realbaud;
241 int type; /* UART type */ 253 int type; /* UART type */
242 int flags; /* defined in tty.h */ 254 int flags; /* defined in tty.h */
255 int speed;
243 256
244 int x_char; /* xon/xoff character */ 257 int x_char; /* xon/xoff character */
245 int IER; /* Interrupt Enable Register */ 258 int IER; /* Interrupt Enable Register */
@@ -444,10 +457,10 @@ static int mxser_block_til_ready(struct tty_struct *tty, struct file *filp,
444 457
445static int mxser_set_baud(struct mxser_port *info, long newspd) 458static int mxser_set_baud(struct mxser_port *info, long newspd)
446{ 459{
460 unsigned int i;
447 int quot = 0; 461 int quot = 0;
448 unsigned char cval; 462 unsigned char cval;
449 int ret = 0; 463 int ret = 0;
450 unsigned long flags;
451 464
452 if (!info->tty || !info->tty->termios) 465 if (!info->tty || !info->tty->termios)
453 return ret; 466 return ret;
@@ -459,29 +472,34 @@ static int mxser_set_baud(struct mxser_port *info, long newspd)
459 return 0; 472 return 0;
460 473
461 info->realbaud = newspd; 474 info->realbaud = newspd;
462 if (newspd == 134) { 475 for (i = 0; i < BAUD_TABLE_NO; i++)
463 quot = (2 * info->baud_base / 269); 476 if (newspd == mxvar_baud_table[i])
464 } else if (newspd) { 477 break;
465 quot = info->baud_base / newspd; 478 if (i == BAUD_TABLE_NO) {
466 if (quot == 0) 479 quot = info->baud_base / info->speed;
467 quot = 1; 480 if (info->speed <= 0 || info->speed > info->max_baud)
481 quot = 0;
468 } else { 482 } else {
469 quot = 0; 483 if (newspd == 134) {
484 quot = (2 * info->baud_base / 269);
485 } else if (newspd) {
486 quot = info->baud_base / newspd;
487 if (quot == 0)
488 quot = 1;
489 } else {
490 quot = 0;
491 }
470 } 492 }
471 493
472 info->timeout = ((info->xmit_fifo_size * HZ * 10 * quot) / info->baud_base); 494 info->timeout = ((info->xmit_fifo_size * HZ * 10 * quot) / info->baud_base);
473 info->timeout += HZ / 50; /* Add .02 seconds of slop */ 495 info->timeout += HZ / 50; /* Add .02 seconds of slop */
474 496
475 if (quot) { 497 if (quot) {
476 spin_lock_irqsave(&info->slock, flags);
477 info->MCR |= UART_MCR_DTR; 498 info->MCR |= UART_MCR_DTR;
478 outb(info->MCR, info->ioaddr + UART_MCR); 499 outb(info->MCR, info->ioaddr + UART_MCR);
479 spin_unlock_irqrestore(&info->slock, flags);
480 } else { 500 } else {
481 spin_lock_irqsave(&info->slock, flags);
482 info->MCR &= ~UART_MCR_DTR; 501 info->MCR &= ~UART_MCR_DTR;
483 outb(info->MCR, info->ioaddr + UART_MCR); 502 outb(info->MCR, info->ioaddr + UART_MCR);
484 spin_unlock_irqrestore(&info->slock, flags);
485 return ret; 503 return ret;
486 } 504 }
487 505
@@ -493,6 +511,18 @@ static int mxser_set_baud(struct mxser_port *info, long newspd)
493 outb(quot >> 8, info->ioaddr + UART_DLM); /* MS of divisor */ 511 outb(quot >> 8, info->ioaddr + UART_DLM); /* MS of divisor */
494 outb(cval, info->ioaddr + UART_LCR); /* reset DLAB */ 512 outb(cval, info->ioaddr + UART_LCR); /* reset DLAB */
495 513
514 if (i == BAUD_TABLE_NO) {
515 quot = info->baud_base % info->speed;
516 quot *= 8;
517 if ((quot % info->speed) > (info->speed / 2)) {
518 quot /= info->speed;
519 quot++;
520 } else {
521 quot /= info->speed;
522 }
523 SET_MOXA_MUST_ENUM_VALUE(info->ioaddr, quot);
524 } else
525 SET_MOXA_MUST_ENUM_VALUE(info->ioaddr, 0);
496 526
497 return ret; 527 return ret;
498} 528}
@@ -508,7 +538,6 @@ static int mxser_change_speed(struct mxser_port *info,
508 int ret = 0; 538 int ret = 0;
509 unsigned char status; 539 unsigned char status;
510 long baud; 540 long baud;
511 unsigned long flags;
512 541
513 if (!info->tty || !info->tty->termios) 542 if (!info->tty || !info->tty->termios)
514 return ret; 543 return ret;
@@ -517,7 +546,10 @@ static int mxser_change_speed(struct mxser_port *info,
517 return ret; 546 return ret;
518 547
519 if (mxser_set_baud_method[info->tty->index] == 0) { 548 if (mxser_set_baud_method[info->tty->index] == 0) {
520 baud = tty_get_baud_rate(info->tty); 549 if ((cflag & CBAUD) == B_SPEC)
550 baud = info->speed;
551 else
552 baud = tty_get_baud_rate(info->tty);
521 mxser_set_baud(info, baud); 553 mxser_set_baud(info, baud);
522 } 554 }
523 555
@@ -656,7 +688,6 @@ static int mxser_change_speed(struct mxser_port *info,
656 } 688 }
657 } 689 }
658 if (info->board->chip_flag) { 690 if (info->board->chip_flag) {
659 spin_lock_irqsave(&info->slock, flags);
660 SET_MOXA_MUST_XON1_VALUE(info->ioaddr, START_CHAR(info->tty)); 691 SET_MOXA_MUST_XON1_VALUE(info->ioaddr, START_CHAR(info->tty));
661 SET_MOXA_MUST_XOFF1_VALUE(info->ioaddr, STOP_CHAR(info->tty)); 692 SET_MOXA_MUST_XOFF1_VALUE(info->ioaddr, STOP_CHAR(info->tty));
662 if (I_IXON(info->tty)) { 693 if (I_IXON(info->tty)) {
@@ -669,7 +700,6 @@ static int mxser_change_speed(struct mxser_port *info,
669 } else { 700 } else {
670 DISABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(info->ioaddr); 701 DISABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(info->ioaddr);
671 } 702 }
672 spin_unlock_irqrestore(&info->slock, flags);
673 } 703 }
674 704
675 705
@@ -822,8 +852,8 @@ static int mxser_startup(struct mxser_port *info)
822 /* 852 /*
823 * and set the speed of the serial port 853 * and set the speed of the serial port
824 */ 854 */
825 spin_unlock_irqrestore(&info->slock, flags);
826 mxser_change_speed(info, NULL); 855 mxser_change_speed(info, NULL);
856 spin_unlock_irqrestore(&info->slock, flags);
827 857
828 info->flags |= ASYNC_INITIALIZED; 858 info->flags |= ASYNC_INITIALIZED;
829 return 0; 859 return 0;
@@ -1195,6 +1225,7 @@ static int mxser_set_serial_info(struct mxser_port *info,
1195 struct serial_struct __user *new_info) 1225 struct serial_struct __user *new_info)
1196{ 1226{
1197 struct serial_struct new_serial; 1227 struct serial_struct new_serial;
1228 unsigned long sl_flags;
1198 unsigned int flags; 1229 unsigned int flags;
1199 int retval = 0; 1230 int retval = 0;
1200 1231
@@ -1237,8 +1268,11 @@ static int mxser_set_serial_info(struct mxser_port *info,
1237 process_txrx_fifo(info); 1268 process_txrx_fifo(info);
1238 1269
1239 if (info->flags & ASYNC_INITIALIZED) { 1270 if (info->flags & ASYNC_INITIALIZED) {
1240 if (flags != (info->flags & ASYNC_SPD_MASK)) 1271 if (flags != (info->flags & ASYNC_SPD_MASK)) {
1272 spin_lock_irqsave(&info->slock, sl_flags);
1241 mxser_change_speed(info, NULL); 1273 mxser_change_speed(info, NULL);
1274 spin_unlock_irqrestore(&info->slock, sl_flags);
1275 }
1242 } else 1276 } else
1243 retval = mxser_startup(info); 1277 retval = mxser_startup(info);
1244 1278
@@ -1615,6 +1649,7 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file,
1615 struct serial_icounter_struct __user *p_cuser; 1649 struct serial_icounter_struct __user *p_cuser;
1616 unsigned long templ; 1650 unsigned long templ;
1617 unsigned long flags; 1651 unsigned long flags;
1652 unsigned int i;
1618 void __user *argp = (void __user *)arg; 1653 void __user *argp = (void __user *)arg;
1619 int retval; 1654 int retval;
1620 1655
@@ -1653,6 +1688,36 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file,
1653 return 0; 1688 return 0;
1654 } 1689 }
1655 1690
1691 if (cmd == MOXA_SET_SPECIAL_BAUD_RATE) {
1692 int speed;
1693
1694 if (get_user(speed, (int __user *)argp))
1695 return -EFAULT;
1696 if (speed <= 0 || speed > info->max_baud)
1697 return -EFAULT;
1698 if (!info->tty || !info->tty->termios || !info->ioaddr)
1699 return 0;
1700 info->tty->termios->c_cflag &= ~(CBAUD | CBAUDEX);
1701 for (i = 0; i < BAUD_TABLE_NO; i++)
1702 if (speed == mxvar_baud_table[i])
1703 break;
1704 if (i == BAUD_TABLE_NO) {
1705 info->tty->termios->c_cflag |= B_SPEC;
1706 } else if (speed != 0)
1707 info->tty->termios->c_cflag |= mxvar_baud_table1[i];
1708
1709 info->speed = speed;
1710 spin_lock_irqsave(&info->slock, flags);
1711 mxser_change_speed(info, 0);
1712 spin_unlock_irqrestore(&info->slock, flags);
1713
1714 return 0;
1715 } else if (cmd == MOXA_GET_SPECIAL_BAUD_RATE) {
1716 if (copy_to_user(argp, &info->speed, sizeof(int)))
1717 return -EFAULT;
1718 return 0;
1719 }
1720
1656 if (cmd != TIOCGSERIAL && cmd != TIOCMIWAIT && cmd != TIOCGICOUNT && 1721 if (cmd != TIOCGSERIAL && cmd != TIOCMIWAIT && cmd != TIOCGICOUNT &&
1657 test_bit(TTY_IO_ERROR, &tty->flags)) 1722 test_bit(TTY_IO_ERROR, &tty->flags))
1658 return -EIO; 1723 return -EIO;
@@ -1770,7 +1835,9 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file,
1770 long baud; 1835 long baud;
1771 if (get_user(baud, (long __user *)argp)) 1836 if (get_user(baud, (long __user *)argp))
1772 return -EFAULT; 1837 return -EFAULT;
1838 spin_lock_irqsave(&info->slock, flags);
1773 mxser_set_baud(info, baud); 1839 mxser_set_baud(info, baud);
1840 spin_unlock_irqrestore(&info->slock, flags);
1774 return 0; 1841 return 0;
1775 } 1842 }
1776 case MOXA_ASPP_GETBAUD: 1843 case MOXA_ASPP_GETBAUD:
@@ -1947,7 +2014,9 @@ static void mxser_set_termios(struct tty_struct *tty, struct ktermios *old_termi
1947 if ((tty->termios->c_cflag != old_termios->c_cflag) || 2014 if ((tty->termios->c_cflag != old_termios->c_cflag) ||
1948 (RELEVANT_IFLAG(tty->termios->c_iflag) != RELEVANT_IFLAG(old_termios->c_iflag))) { 2015 (RELEVANT_IFLAG(tty->termios->c_iflag) != RELEVANT_IFLAG(old_termios->c_iflag))) {
1949 2016
2017 spin_lock_irqsave(&info->slock, flags);
1950 mxser_change_speed(info, old_termios); 2018 mxser_change_speed(info, old_termios);
2019 spin_unlock_irqrestore(&info->slock, flags);
1951 2020
1952 if ((old_termios->c_cflag & CRTSCTS) && 2021 if ((old_termios->c_cflag & CRTSCTS) &&
1953 !(tty->termios->c_cflag & CRTSCTS)) { 2022 !(tty->termios->c_cflag & CRTSCTS)) {
@@ -2137,7 +2206,8 @@ intr_old:
2137 } else if (*status & UART_LSR_OE) { 2206 } else if (*status & UART_LSR_OE) {
2138 flag = TTY_OVERRUN; 2207 flag = TTY_OVERRUN;
2139 port->icount.overrun++; 2208 port->icount.overrun++;
2140 } 2209 } else
2210 flag = TTY_BREAK;
2141 } 2211 }
2142 tty_insert_flip_char(tty, ch, flag); 2212 tty_insert_flip_char(tty, ch, flag);
2143 cnt++; 2213 cnt++;
@@ -2385,6 +2455,7 @@ static int __devinit mxser_initbrd(struct mxser_board *brd,
2385 info->normal_termios = mxvar_sdriver->init_termios; 2455 info->normal_termios = mxvar_sdriver->init_termios;
2386 init_waitqueue_head(&info->open_wait); 2456 init_waitqueue_head(&info->open_wait);
2387 init_waitqueue_head(&info->delta_msr_wait); 2457 init_waitqueue_head(&info->delta_msr_wait);
2458 info->speed = 9600;
2388 memset(&info->mon_data, 0, sizeof(struct mxser_mon)); 2459 memset(&info->mon_data, 0, sizeof(struct mxser_mon));
2389 info->err_shadow = 0; 2460 info->err_shadow = 0;
2390 spin_lock_init(&info->slock); 2461 spin_lock_init(&info->slock);
diff --git a/drivers/char/mxser_new.h b/drivers/char/mxser_new.h
index 04fa5fc9226d..d42f7766c652 100644
--- a/drivers/char/mxser_new.h
+++ b/drivers/char/mxser_new.h
@@ -35,6 +35,8 @@
35#define MOXA_ASPP_LSTATUS (MOXA + 74) 35#define MOXA_ASPP_LSTATUS (MOXA + 74)
36#define MOXA_ASPP_MON_EXT (MOXA + 75) 36#define MOXA_ASPP_MON_EXT (MOXA + 75)
37#define MOXA_SET_BAUD_METHOD (MOXA + 76) 37#define MOXA_SET_BAUD_METHOD (MOXA + 76)
38#define MOXA_SET_SPECIAL_BAUD_RATE (MOXA + 77)
39#define MOXA_GET_SPECIAL_BAUD_RATE (MOXA + 78)
38 40
39/* --------------------------------------------------- */ 41/* --------------------------------------------------- */
40 42
@@ -212,6 +214,18 @@
212 outb(__oldlcr, (info)->ioaddr+UART_LCR); \ 214 outb(__oldlcr, (info)->ioaddr+UART_LCR); \
213} while (0) 215} while (0)
214 216
217#define SET_MOXA_MUST_ENUM_VALUE(baseio, Value) do { \
218 u8 __oldlcr, __efr; \
219 __oldlcr = inb((baseio)+UART_LCR); \
220 outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
221 __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
222 __efr &= ~MOXA_MUST_EFR_BANK_MASK; \
223 __efr |= MOXA_MUST_EFR_BANK2; \
224 outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
225 outb((u8)(Value), (baseio)+MOXA_MUST_ENUM_REGISTER); \
226 outb(__oldlcr, (baseio)+UART_LCR); \
227} while (0)
228
215#define GET_MOXA_MUST_HARDWARE_ID(baseio, pId) do { \ 229#define GET_MOXA_MUST_HARDWARE_ID(baseio, pId) do { \
216 u8 __oldlcr, __efr; \ 230 u8 __oldlcr, __efr; \
217 __oldlcr = inb((baseio)+UART_LCR); \ 231 __oldlcr = inb((baseio)+UART_LCR); \