USB: option.c: add support for D-Link DWM-162-U5
[safe/jmp/linux-2.6] / drivers / char / mxser.c
index 08ba6eb..5e28d39 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/errno.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
+#include <linux/smp_lock.h>
 #include <linux/timer.h>
 #include <linux/interrupt.h>
 #include <linux/tty.h>
@@ -47,7 +48,7 @@
 
 #include "mxser.h"
 
-#define        MXSER_VERSION   "2.0.4"         /* 1.12 */
+#define        MXSER_VERSION   "2.0.5"         /* 1.14 */
 #define        MXSERMAJOR       174
 
 #define MXSER_BOARDS           4       /* Max. boards */
@@ -68,6 +69,7 @@
 #define PCI_DEVICE_ID_POS104UL 0x1044
 #define PCI_DEVICE_ID_CB108    0x1080
 #define PCI_DEVICE_ID_CP102UF  0x1023
+#define PCI_DEVICE_ID_CP112UL  0x1120
 #define PCI_DEVICE_ID_CB114    0x1142
 #define PCI_DEVICE_ID_CP114UL  0x1143
 #define PCI_DEVICE_ID_CB134I   0x1341
@@ -138,7 +140,8 @@ static const struct mxser_cardinfo mxser_cards[] = {
        { "CP-138U series",     8, },
        { "POS-104UL series",   4, },
        { "CP-114UL series",    4, },
-/*30*/ { "CP-102UF series",    2, }
+/*30*/ { "CP-102UF series",    2, },
+       { "CP-112UL series",    2, },
 };
 
 /* driver_data correspond to the lines in the structure above
@@ -169,6 +172,7 @@ static struct pci_device_id mxser_pcibrds[] = {
        { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_POS104UL),    .driver_data = 28 },
        { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP114UL),     .driver_data = 29 },
        { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP102UF),     .driver_data = 30 },
+       { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP112UL),     .driver_data = 31 },
        { }
 };
 MODULE_DEVICE_TABLE(pci, mxser_pcibrds);
@@ -257,7 +261,6 @@ struct mxser_port {
        struct mxser_mon mon_data;
 
        spinlock_t slock;
-       wait_queue_head_t delta_msr_wait;
 };
 
 struct mxser_board {
@@ -547,14 +550,18 @@ static int mxser_carrier_raised(struct tty_port *port)
        return (inb(mp->ioaddr + UART_MSR) & UART_MSR_DCD)?1:0;
 }
 
-static void mxser_raise_dtr_rts(struct tty_port *port)
+static void mxser_dtr_rts(struct tty_port *port, int on)
 {
        struct mxser_port *mp = container_of(port, struct mxser_port, port);
        unsigned long flags;
 
        spin_lock_irqsave(&mp->slock, flags);
-       outb(inb(mp->ioaddr + UART_MCR) |
-               UART_MCR_DTR | UART_MCR_RTS, mp->ioaddr + UART_MCR);
+       if (on)
+               outb(inb(mp->ioaddr + UART_MCR) |
+                       UART_MCR_DTR | UART_MCR_RTS, mp->ioaddr + UART_MCR);
+       else
+               outb(inb(mp->ioaddr + UART_MCR)&~(UART_MCR_DTR | UART_MCR_RTS),
+                       mp->ioaddr + UART_MCR);
        spin_unlock_irqrestore(&mp->slock, flags);
 }
 
@@ -813,14 +820,13 @@ static void mxser_check_modem_status(struct tty_struct *tty,
        if (status & UART_MSR_DCTS)
                port->icount.cts++;
        port->mon_data.modem_status = status;
-       wake_up_interruptible(&port->delta_msr_wait);
+       wake_up_interruptible(&port->port.delta_msr_wait);
 
        if ((port->port.flags & ASYNC_CHECK_CD) && (status & UART_MSR_DDCD)) {
                if (status & UART_MSR_DCD)
                        wake_up_interruptible(&port->port.open_wait);
        }
 
-       tty = tty_port_tty_get(&port->port);
        if (port->port.flags & ASYNC_CTS_FLOW) {
                if (tty->hw_stopped) {
                        if (status & UART_MSR_CTS) {
@@ -969,7 +975,7 @@ static void mxser_shutdown(struct tty_struct *tty)
         * clear delta_msr_wait queue to avoid mem leaks: we may free the irq
         * here so the queue might never be waken up
         */
-       wake_up_interruptible(&info->delta_msr_wait);
+       wake_up_interruptible(&info->port.delta_msr_wait);
 
        /*
         * Free the IRQ, if necessary
@@ -1045,8 +1051,6 @@ static int mxser_open(struct tty_struct *tty, struct file *filp)
        if (retval)
                return retval;
 
-       /* unmark here for very high baud rate (ex. 921600 bps) used */
-       tty->low_latency = 1;
        return 0;
 }
 
@@ -1071,67 +1075,19 @@ static void mxser_flush_buffer(struct tty_struct *tty)
 }
 
 
-/*
- * This routine is called when the serial port gets closed.  First, we
- * wait for the last remaining data to be sent.  Then, we unlink its
- * async structure from the interrupt chain if necessary, and we free
- * that IRQ if nothing is left in the chain.
- */
-static void mxser_close(struct tty_struct *tty, struct file *filp)
+static void mxser_close_port(struct tty_struct *tty, struct tty_port *port)
 {
-       struct mxser_port *info = tty->driver_data;
-
+       struct mxser_port *info = container_of(port, struct mxser_port, port);
        unsigned long timeout;
-       unsigned long flags;
-
-       if (tty->index == MXSER_PORTS)
-               return;
-       if (!info)
-               return;
-
-       spin_lock_irqsave(&info->port.lock, flags);
-
-       if (tty_hung_up_p(filp)) {
-               spin_unlock_irqrestore(&info->port.lock, flags);
-               return;
-       }
-       if ((tty->count == 1) && (info->port.count != 1)) {
-               /*
-                * Uh, oh.  tty->count is 1, which means that the tty
-                * structure will be freed.  Info->port.count should always
-                * be one in these conditions.  If it's greater than
-                * one, we've got real problems, since it means the
-                * serial port won't be shutdown.
-                */
-               printk(KERN_ERR "mxser_close: bad serial port count; "
-                       "tty->count is 1, info->port.count is %d\n", info->port.count);
-               info->port.count = 1;
-       }
-       if (--info->port.count < 0) {
-               printk(KERN_ERR "mxser_close: bad serial port count for "
-                       "ttys%d: %d\n", tty->index, info->port.count);
-               info->port.count = 0;
-       }
-       if (info->port.count) {
-               spin_unlock_irqrestore(&info->port.lock, flags);
-               return;
-       }
-       info->port.flags |= ASYNC_CLOSING;
-       spin_unlock_irqrestore(&info->port.lock, flags);
        /*
         * Save the termios structure, since this port may have
         * separate termios for callout and dialin.
+        *
+        * FIXME: Can this go ?
         */
-       if (info->port.flags & ASYNC_NORMAL_ACTIVE)
+       if (port->flags & ASYNC_NORMAL_ACTIVE)
                info->normal_termios = *tty->termios;
        /*
-        * Now we wait for the transmit buffer to clear; and we notify
-        * the line discipline to only process XON/XOFF characters.
-        */
-       tty->closing = 1;
-       if (info->port.closing_wait != ASYNC_CLOSING_WAIT_NONE)
-               tty_wait_until_sent(tty, info->port.closing_wait);
-       /*
         * At this point we stop accepting input.  To do this, we
         * disable the receive line status interrupts, and tell the
         * interrupt driver to stop checking the data ready bit in the
@@ -1141,7 +1097,7 @@ static void mxser_close(struct tty_struct *tty, struct file *filp)
        if (info->board->chip_flag)
                info->IER &= ~MOXA_MUST_RECV_ISR;
 
-       if (info->port.flags & ASYNC_INITIALIZED) {
+       if (port->flags & ASYNC_INITIALIZED) {
                outb(info->IER, info->ioaddr + UART_IER);
                /*
                 * Before we drop DTR, make sure the UART transmitter
@@ -1157,18 +1113,29 @@ static void mxser_close(struct tty_struct *tty, struct file *filp)
        }
        mxser_shutdown(tty);
 
-       mxser_flush_buffer(tty);
-       tty_ldisc_flush(tty);
+}
 
-       tty->closing = 0;
-       tty_port_tty_set(&info->port, NULL);
-       if (info->port.blocked_open) {
-               if (info->port.close_delay)
-                       schedule_timeout_interruptible(info->port.close_delay);
-               wake_up_interruptible(&info->port.open_wait);
-       }
+/*
+ * This routine is called when the serial port gets closed.  First, we
+ * wait for the last remaining data to be sent.  Then, we unlink its
+ * async structure from the interrupt chain if necessary, and we free
+ * that IRQ if nothing is left in the chain.
+ */
+static void mxser_close(struct tty_struct *tty, struct file *filp)
+{
+       struct mxser_port *info = tty->driver_data;
+       struct tty_port *port = &info->port;
 
-       info->port.flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING);
+       if (tty->index == MXSER_PORTS)
+               return;
+       if (tty_port_close_start(port, tty, filp) == 0)
+               return;
+       mxser_close_port(tty, port);
+       mxser_flush_buffer(tty);
+       /* Right now the tty_port set is done outside of the close_end helper
+          as we don't yet have everyone using refcounts */     
+       tty_port_close_end(port, tty);
+       tty_port_tty_set(port, NULL);
 }
 
 static int mxser_write(struct tty_struct *tty, const unsigned char *buf, int count)
@@ -1797,7 +1764,7 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file,
                cnow = info->icount;    /* note the counters on entry */
                spin_unlock_irqrestore(&info->slock, flags);
 
-               return wait_event_interruptible(info->delta_msr_wait,
+               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)
@@ -1839,7 +1806,7 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file,
 
                lock_kernel();
                len = mxser_chars_in_buffer(tty);
-               lsr = inb(info->ioaddr + UART_LSR) & UART_LSR_TEMT;
+               lsr = inb(info->ioaddr + UART_LSR) & UART_LSR_THRE;
                len += (lsr ? 0 : 1);
                unlock_kernel();
 
@@ -2395,7 +2362,7 @@ static const struct tty_operations mxser_ops = {
 
 struct tty_port_operations mxser_port_ops = {
        .carrier_raised = mxser_carrier_raised,
-       .raise_dtr_rts = mxser_raise_dtr_rts,
+       .dtr_rts = mxser_dtr_rts,
 };
 
 /*
@@ -2449,7 +2416,6 @@ static int __devinit mxser_initbrd(struct mxser_board *brd,
                info->port.close_delay = 5 * HZ / 10;
                info->port.closing_wait = 30 * HZ;
                info->normal_termios = mxvar_sdriver->init_termios;
-               init_waitqueue_head(&info->delta_msr_wait);
                memset(&info->mon_data, 0, sizeof(struct mxser_mon));
                info->err_shadow = 0;
                spin_lock_init(&info->slock);
@@ -2750,7 +2716,7 @@ static int __init mxser_module_init(void)
                        continue;
 
                brd = &mxser_boards[m];
-               retval = mxser_get_ISA_conf(!ioaddr[b], brd);
+               retval = mxser_get_ISA_conf(ioaddr[b], brd);
                if (retval <= 0) {
                        brd->info = NULL;
                        continue;