Commit f64c84a1 authored by Jiri Slaby's avatar Jiri Slaby Committed by Linus Torvalds

[PATCH] Char: mxser_new, upgrade to 1.9.15

- allow special rates
- break when bad status
Signed-off-by: default avatarJiri Slaby <jirislaby@gmail.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 1a221026
...@@ -49,7 +49,7 @@ ...@@ -49,7 +49,7 @@
#include "mxser_new.h" #include "mxser_new.h"
#define MXSER_VERSION "2.0" #define MXSER_VERSION "2.0.1" /* 1.9.15 */
#define MXSERMAJOR 174 #define MXSERMAJOR 174
#define MXSERCUMAJOR 175 #define MXSERCUMAJOR 175
...@@ -179,6 +179,18 @@ static struct pci_device_id mxser_pcibrds[] = { ...@@ -179,6 +179,18 @@ static struct pci_device_id mxser_pcibrds[] = {
}; };
MODULE_DEVICE_TABLE(pci, mxser_pcibrds); MODULE_DEVICE_TABLE(pci, mxser_pcibrds);
static int mxvar_baud_table[] = {
0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400,
4800, 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600
};
static unsigned int mxvar_baud_table1[] = {
0, B50, B75, B110, B134, B150, B200, B300, B600, B1200, B1800, B2400,
B4800, B9600, B19200, B38400, B57600, B115200, B230400, B460800, B921600
};
#define BAUD_TABLE_NO ARRAY_SIZE(mxvar_baud_table)
#define B_SPEC B2000000
static int ioaddr[MXSER_BOARDS] = { 0, 0, 0, 0 }; static int ioaddr[MXSER_BOARDS] = { 0, 0, 0, 0 };
static int ttymajor = MXSERMAJOR; static int ttymajor = MXSERMAJOR;
static int calloutmajor = MXSERCUMAJOR; static int calloutmajor = MXSERCUMAJOR;
...@@ -240,6 +252,7 @@ struct mxser_port { ...@@ -240,6 +252,7 @@ struct mxser_port {
long realbaud; long realbaud;
int type; /* UART type */ int type; /* UART type */
int flags; /* defined in tty.h */ int flags; /* defined in tty.h */
int speed;
int x_char; /* xon/xoff character */ int x_char; /* xon/xoff character */
int IER; /* Interrupt Enable Register */ int IER; /* Interrupt Enable Register */
...@@ -444,10 +457,10 @@ static int mxser_block_til_ready(struct tty_struct *tty, struct file *filp, ...@@ -444,10 +457,10 @@ static int mxser_block_til_ready(struct tty_struct *tty, struct file *filp,
static int mxser_set_baud(struct mxser_port *info, long newspd) static int mxser_set_baud(struct mxser_port *info, long newspd)
{ {
unsigned int i;
int quot = 0; int quot = 0;
unsigned char cval; unsigned char cval;
int ret = 0; int ret = 0;
unsigned long flags;
if (!info->tty || !info->tty->termios) if (!info->tty || !info->tty->termios)
return ret; return ret;
...@@ -459,6 +472,14 @@ static int mxser_set_baud(struct mxser_port *info, long newspd) ...@@ -459,6 +472,14 @@ static int mxser_set_baud(struct mxser_port *info, long newspd)
return 0; return 0;
info->realbaud = newspd; info->realbaud = newspd;
for (i = 0; i < BAUD_TABLE_NO; i++)
if (newspd == mxvar_baud_table[i])
break;
if (i == BAUD_TABLE_NO) {
quot = info->baud_base / info->speed;
if (info->speed <= 0 || info->speed > info->max_baud)
quot = 0;
} else {
if (newspd == 134) { if (newspd == 134) {
quot = (2 * info->baud_base / 269); quot = (2 * info->baud_base / 269);
} else if (newspd) { } else if (newspd) {
...@@ -468,20 +489,17 @@ static int mxser_set_baud(struct mxser_port *info, long newspd) ...@@ -468,20 +489,17 @@ static int mxser_set_baud(struct mxser_port *info, long newspd)
} else { } else {
quot = 0; quot = 0;
} }
}
info->timeout = ((info->xmit_fifo_size * HZ * 10 * quot) / info->baud_base); info->timeout = ((info->xmit_fifo_size * HZ * 10 * quot) / info->baud_base);
info->timeout += HZ / 50; /* Add .02 seconds of slop */ info->timeout += HZ / 50; /* Add .02 seconds of slop */
if (quot) { if (quot) {
spin_lock_irqsave(&info->slock, flags);
info->MCR |= UART_MCR_DTR; info->MCR |= UART_MCR_DTR;
outb(info->MCR, info->ioaddr + UART_MCR); outb(info->MCR, info->ioaddr + UART_MCR);
spin_unlock_irqrestore(&info->slock, flags);
} else { } else {
spin_lock_irqsave(&info->slock, flags);
info->MCR &= ~UART_MCR_DTR; info->MCR &= ~UART_MCR_DTR;
outb(info->MCR, info->ioaddr + UART_MCR); outb(info->MCR, info->ioaddr + UART_MCR);
spin_unlock_irqrestore(&info->slock, flags);
return ret; return ret;
} }
...@@ -493,6 +511,18 @@ static int mxser_set_baud(struct mxser_port *info, long newspd) ...@@ -493,6 +511,18 @@ static int mxser_set_baud(struct mxser_port *info, long newspd)
outb(quot >> 8, info->ioaddr + UART_DLM); /* MS of divisor */ outb(quot >> 8, info->ioaddr + UART_DLM); /* MS of divisor */
outb(cval, info->ioaddr + UART_LCR); /* reset DLAB */ outb(cval, info->ioaddr + UART_LCR); /* reset DLAB */
if (i == BAUD_TABLE_NO) {
quot = info->baud_base % info->speed;
quot *= 8;
if ((quot % info->speed) > (info->speed / 2)) {
quot /= info->speed;
quot++;
} else {
quot /= info->speed;
}
SET_MOXA_MUST_ENUM_VALUE(info->ioaddr, quot);
} else
SET_MOXA_MUST_ENUM_VALUE(info->ioaddr, 0);
return ret; return ret;
} }
...@@ -508,7 +538,6 @@ static int mxser_change_speed(struct mxser_port *info, ...@@ -508,7 +538,6 @@ static int mxser_change_speed(struct mxser_port *info,
int ret = 0; int ret = 0;
unsigned char status; unsigned char status;
long baud; long baud;
unsigned long flags;
if (!info->tty || !info->tty->termios) if (!info->tty || !info->tty->termios)
return ret; return ret;
...@@ -517,6 +546,9 @@ static int mxser_change_speed(struct mxser_port *info, ...@@ -517,6 +546,9 @@ static int mxser_change_speed(struct mxser_port *info,
return ret; return ret;
if (mxser_set_baud_method[info->tty->index] == 0) { if (mxser_set_baud_method[info->tty->index] == 0) {
if ((cflag & CBAUD) == B_SPEC)
baud = info->speed;
else
baud = tty_get_baud_rate(info->tty); baud = tty_get_baud_rate(info->tty);
mxser_set_baud(info, baud); mxser_set_baud(info, baud);
} }
...@@ -656,7 +688,6 @@ static int mxser_change_speed(struct mxser_port *info, ...@@ -656,7 +688,6 @@ static int mxser_change_speed(struct mxser_port *info,
} }
} }
if (info->board->chip_flag) { if (info->board->chip_flag) {
spin_lock_irqsave(&info->slock, flags);
SET_MOXA_MUST_XON1_VALUE(info->ioaddr, START_CHAR(info->tty)); SET_MOXA_MUST_XON1_VALUE(info->ioaddr, START_CHAR(info->tty));
SET_MOXA_MUST_XOFF1_VALUE(info->ioaddr, STOP_CHAR(info->tty)); SET_MOXA_MUST_XOFF1_VALUE(info->ioaddr, STOP_CHAR(info->tty));
if (I_IXON(info->tty)) { if (I_IXON(info->tty)) {
...@@ -669,7 +700,6 @@ static int mxser_change_speed(struct mxser_port *info, ...@@ -669,7 +700,6 @@ static int mxser_change_speed(struct mxser_port *info,
} else { } else {
DISABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(info->ioaddr); DISABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(info->ioaddr);
} }
spin_unlock_irqrestore(&info->slock, flags);
} }
...@@ -822,8 +852,8 @@ static int mxser_startup(struct mxser_port *info) ...@@ -822,8 +852,8 @@ static int mxser_startup(struct mxser_port *info)
/* /*
* and set the speed of the serial port * and set the speed of the serial port
*/ */
spin_unlock_irqrestore(&info->slock, flags);
mxser_change_speed(info, NULL); mxser_change_speed(info, NULL);
spin_unlock_irqrestore(&info->slock, flags);
info->flags |= ASYNC_INITIALIZED; info->flags |= ASYNC_INITIALIZED;
return 0; return 0;
...@@ -1195,6 +1225,7 @@ static int mxser_set_serial_info(struct mxser_port *info, ...@@ -1195,6 +1225,7 @@ static int mxser_set_serial_info(struct mxser_port *info,
struct serial_struct __user *new_info) struct serial_struct __user *new_info)
{ {
struct serial_struct new_serial; struct serial_struct new_serial;
unsigned long sl_flags;
unsigned int flags; unsigned int flags;
int retval = 0; int retval = 0;
...@@ -1237,8 +1268,11 @@ static int mxser_set_serial_info(struct mxser_port *info, ...@@ -1237,8 +1268,11 @@ static int mxser_set_serial_info(struct mxser_port *info,
process_txrx_fifo(info); process_txrx_fifo(info);
if (info->flags & ASYNC_INITIALIZED) { if (info->flags & ASYNC_INITIALIZED) {
if (flags != (info->flags & ASYNC_SPD_MASK)) if (flags != (info->flags & ASYNC_SPD_MASK)) {
spin_lock_irqsave(&info->slock, sl_flags);
mxser_change_speed(info, NULL); mxser_change_speed(info, NULL);
spin_unlock_irqrestore(&info->slock, sl_flags);
}
} else } else
retval = mxser_startup(info); retval = mxser_startup(info);
...@@ -1615,6 +1649,7 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, ...@@ -1615,6 +1649,7 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file,
struct serial_icounter_struct __user *p_cuser; struct serial_icounter_struct __user *p_cuser;
unsigned long templ; unsigned long templ;
unsigned long flags; unsigned long flags;
unsigned int i;
void __user *argp = (void __user *)arg; void __user *argp = (void __user *)arg;
int retval; int retval;
...@@ -1653,6 +1688,36 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, ...@@ -1653,6 +1688,36 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file,
return 0; return 0;
} }
if (cmd == MOXA_SET_SPECIAL_BAUD_RATE) {
int speed;
if (get_user(speed, (int __user *)argp))
return -EFAULT;
if (speed <= 0 || speed > info->max_baud)
return -EFAULT;
if (!info->tty || !info->tty->termios || !info->ioaddr)
return 0;
info->tty->termios->c_cflag &= ~(CBAUD | CBAUDEX);
for (i = 0; i < BAUD_TABLE_NO; i++)
if (speed == mxvar_baud_table[i])
break;
if (i == BAUD_TABLE_NO) {
info->tty->termios->c_cflag |= B_SPEC;
} else if (speed != 0)
info->tty->termios->c_cflag |= mxvar_baud_table1[i];
info->speed = speed;
spin_lock_irqsave(&info->slock, flags);
mxser_change_speed(info, 0);
spin_unlock_irqrestore(&info->slock, flags);
return 0;
} else if (cmd == MOXA_GET_SPECIAL_BAUD_RATE) {
if (copy_to_user(argp, &info->speed, sizeof(int)))
return -EFAULT;
return 0;
}
if (cmd != TIOCGSERIAL && cmd != TIOCMIWAIT && cmd != TIOCGICOUNT && if (cmd != TIOCGSERIAL && cmd != TIOCMIWAIT && cmd != TIOCGICOUNT &&
test_bit(TTY_IO_ERROR, &tty->flags)) test_bit(TTY_IO_ERROR, &tty->flags))
return -EIO; return -EIO;
...@@ -1770,7 +1835,9 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, ...@@ -1770,7 +1835,9 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file,
long baud; long baud;
if (get_user(baud, (long __user *)argp)) if (get_user(baud, (long __user *)argp))
return -EFAULT; return -EFAULT;
spin_lock_irqsave(&info->slock, flags);
mxser_set_baud(info, baud); mxser_set_baud(info, baud);
spin_unlock_irqrestore(&info->slock, flags);
return 0; return 0;
} }
case MOXA_ASPP_GETBAUD: case MOXA_ASPP_GETBAUD:
...@@ -1947,7 +2014,9 @@ static void mxser_set_termios(struct tty_struct *tty, struct ktermios *old_termi ...@@ -1947,7 +2014,9 @@ static void mxser_set_termios(struct tty_struct *tty, struct ktermios *old_termi
if ((tty->termios->c_cflag != old_termios->c_cflag) || if ((tty->termios->c_cflag != old_termios->c_cflag) ||
(RELEVANT_IFLAG(tty->termios->c_iflag) != RELEVANT_IFLAG(old_termios->c_iflag))) { (RELEVANT_IFLAG(tty->termios->c_iflag) != RELEVANT_IFLAG(old_termios->c_iflag))) {
spin_lock_irqsave(&info->slock, flags);
mxser_change_speed(info, old_termios); mxser_change_speed(info, old_termios);
spin_unlock_irqrestore(&info->slock, flags);
if ((old_termios->c_cflag & CRTSCTS) && if ((old_termios->c_cflag & CRTSCTS) &&
!(tty->termios->c_cflag & CRTSCTS)) { !(tty->termios->c_cflag & CRTSCTS)) {
...@@ -2137,7 +2206,8 @@ static void mxser_receive_chars(struct mxser_port *port, int *status) ...@@ -2137,7 +2206,8 @@ static void mxser_receive_chars(struct mxser_port *port, int *status)
} else if (*status & UART_LSR_OE) { } else if (*status & UART_LSR_OE) {
flag = TTY_OVERRUN; flag = TTY_OVERRUN;
port->icount.overrun++; port->icount.overrun++;
} } else
flag = TTY_BREAK;
} }
tty_insert_flip_char(tty, ch, flag); tty_insert_flip_char(tty, ch, flag);
cnt++; cnt++;
...@@ -2385,6 +2455,7 @@ static int __devinit mxser_initbrd(struct mxser_board *brd, ...@@ -2385,6 +2455,7 @@ static int __devinit mxser_initbrd(struct mxser_board *brd,
info->normal_termios = mxvar_sdriver->init_termios; info->normal_termios = mxvar_sdriver->init_termios;
init_waitqueue_head(&info->open_wait); init_waitqueue_head(&info->open_wait);
init_waitqueue_head(&info->delta_msr_wait); init_waitqueue_head(&info->delta_msr_wait);
info->speed = 9600;
memset(&info->mon_data, 0, sizeof(struct mxser_mon)); memset(&info->mon_data, 0, sizeof(struct mxser_mon));
info->err_shadow = 0; info->err_shadow = 0;
spin_lock_init(&info->slock); spin_lock_init(&info->slock);
......
...@@ -35,6 +35,8 @@ ...@@ -35,6 +35,8 @@
#define MOXA_ASPP_LSTATUS (MOXA + 74) #define MOXA_ASPP_LSTATUS (MOXA + 74)
#define MOXA_ASPP_MON_EXT (MOXA + 75) #define MOXA_ASPP_MON_EXT (MOXA + 75)
#define MOXA_SET_BAUD_METHOD (MOXA + 76) #define MOXA_SET_BAUD_METHOD (MOXA + 76)
#define MOXA_SET_SPECIAL_BAUD_RATE (MOXA + 77)
#define MOXA_GET_SPECIAL_BAUD_RATE (MOXA + 78)
/* --------------------------------------------------- */ /* --------------------------------------------------- */
...@@ -212,6 +214,18 @@ ...@@ -212,6 +214,18 @@
outb(__oldlcr, (info)->ioaddr+UART_LCR); \ outb(__oldlcr, (info)->ioaddr+UART_LCR); \
} while (0) } while (0)
#define SET_MOXA_MUST_ENUM_VALUE(baseio, Value) do { \
u8 __oldlcr, __efr; \
__oldlcr = inb((baseio)+UART_LCR); \
outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
__efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
__efr &= ~MOXA_MUST_EFR_BANK_MASK; \
__efr |= MOXA_MUST_EFR_BANK2; \
outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
outb((u8)(Value), (baseio)+MOXA_MUST_ENUM_REGISTER); \
outb(__oldlcr, (baseio)+UART_LCR); \
} while (0)
#define GET_MOXA_MUST_HARDWARE_ID(baseio, pId) do { \ #define GET_MOXA_MUST_HARDWARE_ID(baseio, pId) do { \
u8 __oldlcr, __efr; \ u8 __oldlcr, __efr; \
__oldlcr = inb((baseio)+UART_LCR); \ __oldlcr = inb((baseio)+UART_LCR); \
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment