tty: rework break handling
[pandora-kernel.git] / drivers / char / sx.c
index a6e1c9b..2162439 100644 (file)
@@ -1,4 +1,3 @@
-
 /* sx.c -- driver for the Specialix SX series cards. 
  *
  *  This driver will also support the older SI, and XIO cards.
@@ -384,11 +383,11 @@ static struct real_driver sx_real_driver = {
 #define sx_dprintk(f, str...)  /* nothing */
 #endif
 
-#define func_enter()   sx_dprintk(SX_DEBUG_FLOW, "sx: enter %s\n",__FUNCTION__)
-#define func_exit()    sx_dprintk(SX_DEBUG_FLOW, "sx: exit  %s\n",__FUNCTION__)
+#define func_enter()   sx_dprintk(SX_DEBUG_FLOW, "sx: enter %s\n",__func__)
+#define func_exit()    sx_dprintk(SX_DEBUG_FLOW, "sx: exit  %s\n",__func__)
 
 #define func_enter2()  sx_dprintk(SX_DEBUG_FLOW, "sx: enter %s (port %d)\n", \
-                               __FUNCTION__, port->line)
+                               __func__, port->line)
 
 /* 
  *  Firmware loader driver specific routines
@@ -930,7 +929,7 @@ static int sx_set_real_termios(void *ptr)
 
        func_enter2();
 
-       if (!port->gs.tty)
+       if (!port->gs.port.tty)
                return 0;
 
        /* What is this doing here? -- REW
@@ -941,19 +940,19 @@ static int sx_set_real_termios(void *ptr)
 
        sx_set_baud(port);
 
-#define CFLAG port->gs.tty->termios->c_cflag
+#define CFLAG port->gs.port.tty->termios->c_cflag
        sx_write_channel_byte(port, hi_mr1,
-                       (C_PARENB(port->gs.tty) ? MR1_WITH : MR1_NONE) |
-                       (C_PARODD(port->gs.tty) ? MR1_ODD : MR1_EVEN) |
-                       (C_CRTSCTS(port->gs.tty) ? MR1_RTS_RXFLOW : 0) |
+                       (C_PARENB(port->gs.port.tty) ? MR1_WITH : MR1_NONE) |
+                       (C_PARODD(port->gs.port.tty) ? MR1_ODD : MR1_EVEN) |
+                       (C_CRTSCTS(port->gs.port.tty) ? MR1_RTS_RXFLOW : 0) |
                        (((CFLAG & CSIZE) == CS8) ? MR1_8_BITS : 0) |
                        (((CFLAG & CSIZE) == CS7) ? MR1_7_BITS : 0) |
                        (((CFLAG & CSIZE) == CS6) ? MR1_6_BITS : 0) |
                        (((CFLAG & CSIZE) == CS5) ? MR1_5_BITS : 0));
 
        sx_write_channel_byte(port, hi_mr2,
-                       (C_CRTSCTS(port->gs.tty) ? MR2_CTS_TXFLOW : 0) |
-                       (C_CSTOPB(port->gs.tty) ? MR2_2_STOP :
+                       (C_CRTSCTS(port->gs.port.tty) ? MR2_CTS_TXFLOW : 0) |
+                       (C_CSTOPB(port->gs.port.tty) ? MR2_2_STOP :
                        MR2_1_STOP));
 
        switch (CFLAG & CSIZE) {
@@ -970,47 +969,50 @@ static int sx_set_real_termios(void *ptr)
                sx_write_channel_byte(port, hi_mask, 0x1f);
                break;
        default:
-               printk(KERN_INFO "sx: Invalid wordsize: %u\n", CFLAG & CSIZE);
+               printk(KERN_INFO "sx: Invalid wordsize: %u\n",
+                       (unsigned int)CFLAG & CSIZE);
                break;
        }
 
        sx_write_channel_byte(port, hi_prtcl,
-                       (I_IXON(port->gs.tty) ? SP_TXEN : 0) |
-                       (I_IXOFF(port->gs.tty) ? SP_RXEN : 0) |
-                       (I_IXANY(port->gs.tty) ? SP_TANY : 0) | SP_DCEN);
+                       (I_IXON(port->gs.port.tty) ? SP_TXEN : 0) |
+                       (I_IXOFF(port->gs.port.tty) ? SP_RXEN : 0) |
+                       (I_IXANY(port->gs.port.tty) ? SP_TANY : 0) | SP_DCEN);
 
        sx_write_channel_byte(port, hi_break,
-                       (I_IGNBRK(port->gs.tty) ? BR_IGN : 0 |
-                       I_BRKINT(port->gs.tty) ? BR_INT : 0));
+                       (I_IGNBRK(port->gs.port.tty) ? BR_IGN : 0 |
+                       I_BRKINT(port->gs.port.tty) ? BR_INT : 0));
 
-       sx_write_channel_byte(port, hi_txon, START_CHAR(port->gs.tty));
-       sx_write_channel_byte(port, hi_rxon, START_CHAR(port->gs.tty));
-       sx_write_channel_byte(port, hi_txoff, STOP_CHAR(port->gs.tty));
-       sx_write_channel_byte(port, hi_rxoff, STOP_CHAR(port->gs.tty));
+       sx_write_channel_byte(port, hi_txon, START_CHAR(port->gs.port.tty));
+       sx_write_channel_byte(port, hi_rxon, START_CHAR(port->gs.port.tty));
+       sx_write_channel_byte(port, hi_txoff, STOP_CHAR(port->gs.port.tty));
+       sx_write_channel_byte(port, hi_rxoff, STOP_CHAR(port->gs.port.tty));
 
        sx_reconfigure_port(port);
 
        /* Tell line discipline whether we will do input cooking */
-       if (I_OTHER(port->gs.tty)) {
-               clear_bit(TTY_HW_COOK_IN, &port->gs.tty->flags);
+       if (I_OTHER(port->gs.port.tty)) {
+               clear_bit(TTY_HW_COOK_IN, &port->gs.port.tty->flags);
        } else {
-               set_bit(TTY_HW_COOK_IN, &port->gs.tty->flags);
+               set_bit(TTY_HW_COOK_IN, &port->gs.port.tty->flags);
        }
        sx_dprintk(SX_DEBUG_TERMIOS, "iflags: %x(%d) ",
-                       port->gs.tty->termios->c_iflag, I_OTHER(port->gs.tty));
+                       (unsigned int)port->gs.port.tty->termios->c_iflag,
+                       I_OTHER(port->gs.port.tty));
 
 /* Tell line discipline whether we will do output cooking.
  * If OPOST is set and no other output flags are set then we can do output
  * processing.  Even if only *one* other flag in the O_OTHER group is set
  * we do cooking in software.
  */
-       if (O_OPOST(port->gs.tty) && !O_OTHER(port->gs.tty)) {
-               set_bit(TTY_HW_COOK_OUT, &port->gs.tty->flags);
+       if (O_OPOST(port->gs.port.tty) && !O_OTHER(port->gs.port.tty)) {
+               set_bit(TTY_HW_COOK_OUT, &port->gs.port.tty->flags);
        } else {
-               clear_bit(TTY_HW_COOK_OUT, &port->gs.tty->flags);
+               clear_bit(TTY_HW_COOK_OUT, &port->gs.port.tty->flags);
        }
        sx_dprintk(SX_DEBUG_TERMIOS, "oflags: %x(%d)\n",
-                       port->gs.tty->termios->c_oflag, O_OTHER(port->gs.tty));
+                       (unsigned int)port->gs.port.tty->termios->c_oflag,
+                       O_OTHER(port->gs.port.tty));
        /* port->c_dcd = sx_get_CD (port); */
        func_exit();
        return 0;
@@ -1099,8 +1101,8 @@ static void sx_transmit_chars(struct sx_port *port)
                sx_disable_tx_interrupts(port);
        }
 
-       if ((port->gs.xmit_cnt <= port->gs.wakeup_chars) && port->gs.tty) {
-               tty_wakeup(port->gs.tty);
+       if ((port->gs.xmit_cnt <= port->gs.wakeup_chars) && port->gs.port.tty) {
+               tty_wakeup(port->gs.port.tty);
                sx_dprintk(SX_DEBUG_TRANSMIT, "Waking up.... ldisc (%d)....\n",
                                port->gs.wakeup_chars);
        }
@@ -1123,7 +1125,7 @@ static inline void sx_receive_chars(struct sx_port *port)
        unsigned char *rp;
 
        func_enter2();
-       tty = port->gs.tty;
+       tty = port->gs.port.tty;
        while (1) {
                rx_op = sx_read_channel_byte(port, hi_rxopos);
                c = (sx_read_channel_byte(port, hi_rxipos) - rx_op) & 0xff;
@@ -1208,12 +1210,12 @@ static inline void sx_check_modem_signals(struct sx_port *port)
                                /* DCD went UP */
                                if ((sx_read_channel_byte(port, hi_hstat) !=
                                                HS_IDLE_CLOSED) &&
-                                               !(port->gs.tty->termios->
+                                               !(port->gs.port.tty->termios->
                                                        c_cflag & CLOCAL)) {
                                        /* Are we blocking in open? */
                                        sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD "
                                                "active, unblocking open\n");
-                                       wake_up_interruptible(&port->gs.
+                                       wake_up_interruptible(&port->gs.port.
                                                        open_wait);
                                } else {
                                        sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD "
@@ -1221,10 +1223,10 @@ static inline void sx_check_modem_signals(struct sx_port *port)
                                }
                        } else {
                                /* DCD went down! */
-                               if (!(port->gs.tty->termios->c_cflag & CLOCAL)){
+                               if (!(port->gs.port.tty->termios->c_cflag & CLOCAL)){
                                        sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD "
                                                "dropped. hanging up....\n");
-                                       tty_hangup(port->gs.tty);
+                                       tty_hangup(port->gs.port.tty);
                                } else {
                                        sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD "
                                                "dropped. ignoring.\n");
@@ -1322,7 +1324,7 @@ static irqreturn_t sx_interrupt(int irq, void *ptr)
 
        for (i = 0; i < board->nports; i++) {
                port = &board->ports[i];
-               if (port->gs.flags & GS_ACTIVE) {
+               if (port->gs.port.flags & GS_ACTIVE) {
                        if (sx_read_channel_byte(port, hi_state)) {
                                sx_dprintk(SX_DEBUG_INTERRUPTS, "Port %d: "
                                                "modem signal change?... \n",i);
@@ -1331,7 +1333,7 @@ static irqreturn_t sx_interrupt(int irq, void *ptr)
                        if (port->gs.xmit_cnt) {
                                sx_transmit_chars(port);
                        }
-                       if (!(port->gs.flags & SX_RX_THROTTLE)) {
+                       if (!(port->gs.port.flags & SX_RX_THROTTLE)) {
                                sx_receive_chars(port);
                        }
                }
@@ -1370,7 +1372,7 @@ static void sx_disable_tx_interrupts(void *ptr)
        struct sx_port *port = ptr;
        func_enter2();
 
-       port->gs.flags &= ~GS_TX_INTEN;
+       port->gs.port.flags &= ~GS_TX_INTEN;
 
        func_exit();
 }
@@ -1391,7 +1393,7 @@ static void sx_enable_tx_interrupts(void *ptr)
 
        /* XXX Must be "HIGH_WATER" for SI card according to doc. */
        if (data_in_buffer < LOW_WATER)
-               port->gs.flags &= ~GS_TX_INTEN;
+               port->gs.port.flags &= ~GS_TX_INTEN;
 
        func_exit();
 }
@@ -1439,8 +1441,8 @@ static void sx_shutdown_port(void *ptr)
 
        func_enter();
 
-       port->gs.flags &= ~GS_ACTIVE;
-       if (port->gs.tty && (port->gs.tty->termios->c_cflag & HUPCL)) {
+       port->gs.port.flags &= ~GS_ACTIVE;
+       if (port->gs.port.tty && (port->gs.port.tty->termios->c_cflag & HUPCL)) {
                sx_setsignals(port, 0, 0);
                sx_reconfigure_port(port);
        }
@@ -1482,8 +1484,8 @@ static int sx_open(struct tty_struct *tty, struct file *filp)
        spin_lock_irqsave(&port->gs.driver_lock, flags);
 
        tty->driver_data = port;
-       port->gs.tty = tty;
-       port->gs.count++;
+       port->gs.port.tty = tty;
+       port->gs.port.count++;
        spin_unlock_irqrestore(&port->gs.driver_lock, flags);
 
        sx_dprintk(SX_DEBUG_OPEN, "starting port\n");
@@ -1494,12 +1496,12 @@ static int sx_open(struct tty_struct *tty, struct file *filp)
        retval = gs_init_port(&port->gs);
        sx_dprintk(SX_DEBUG_OPEN, "done gs_init\n");
        if (retval) {
-               port->gs.count--;
+               port->gs.port.count--;
                return retval;
        }
 
-       port->gs.flags |= GS_ACTIVE;
-       if (port->gs.count <= 1)
+       port->gs.port.flags |= GS_ACTIVE;
+       if (port->gs.port.count <= 1)
                sx_setsignals(port, 1, 1);
 
 #if 0
@@ -1510,12 +1512,12 @@ static int sx_open(struct tty_struct *tty, struct file *filp)
                my_hd_io(port->board->base + port->ch_base, sizeof(*port));
 #endif
 
-       if (port->gs.count <= 1) {
+       if (port->gs.port.count <= 1) {
                if (sx_send_command(port, HS_LOPEN, -1, HS_IDLE_OPEN) != 1) {
                        printk(KERN_ERR "sx: Card didn't respond to LOPEN "
                                        "command.\n");
                        spin_lock_irqsave(&port->gs.driver_lock, flags);
-                       port->gs.count--;
+                       port->gs.port.count--;
                        spin_unlock_irqrestore(&port->gs.driver_lock, flags);
                        return -EIO;
                }
@@ -1523,11 +1525,11 @@ static int sx_open(struct tty_struct *tty, struct file *filp)
 
        retval = gs_block_til_ready(port, filp);
        sx_dprintk(SX_DEBUG_OPEN, "Block til ready returned %d. Count=%d\n",
-                       retval, port->gs.count);
+                       retval, port->gs.port.count);
 
        if (retval) {
 /*
- * Don't lower gs.count here because sx_close() will be called later
+ * Don't lower gs.port.count here because sx_close() will be called later
  */
 
                return retval;
@@ -1568,14 +1570,14 @@ static void sx_close(void *ptr)
        }
 
        sx_dprintk(SX_DEBUG_CLOSE, "waited %d jiffies for close. count=%d\n",
-                       5 * HZ - to - 1, port->gs.count);
+                       5 * HZ - to - 1, port->gs.port.count);
 
-       if (port->gs.count) {
+       if (port->gs.port.count) {
                sx_dprintk(SX_DEBUG_CLOSE, "WARNING port count:%d\n",
-                               port->gs.count);
+                               port->gs.port.count);
                /*printk("%s SETTING port count to zero: %p count: %d\n",
-                               __FUNCTION__, port, port->gs.count);
-               port->gs.count = 0;*/
+                               __func__, port, port->gs.port.count);
+               port->gs.port.count = 0;*/
        }
 
        func_exit();
@@ -1838,12 +1840,13 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp,
        return rc;
 }
 
-static void sx_break(struct tty_struct *tty, int flag)
+static int sx_break(struct tty_struct *tty, int flag)
 {
        struct sx_port *port = tty->driver_data;
        int rv;
 
        func_enter();
+       lock_kernel();
 
        if (flag)
                rv = sx_send_command(port, HS_START, -1, HS_IDLE_BREAK);
@@ -1852,8 +1855,9 @@ static void sx_break(struct tty_struct *tty, int flag)
        if (rv != 1)
                printk(KERN_ERR "sx: couldn't send break (%x).\n",
                        read_sx_byte(port->board, CHAN_OFFSET(port, hi_hstat)));
-
+       unlock_kernel();
        func_exit();
+       return 0;
 }
 
 static int sx_tiocmget(struct tty_struct *tty, struct file *file)
@@ -1888,23 +1892,12 @@ static int sx_ioctl(struct tty_struct *tty, struct file *filp,
        int rc;
        struct sx_port *port = tty->driver_data;
        void __user *argp = (void __user *)arg;
-       int ival;
 
        /* func_enter2(); */
 
        rc = 0;
+       lock_kernel();
        switch (cmd) {
-       case TIOCGSOFTCAR:
-               rc = put_user(((tty->termios->c_cflag & CLOCAL) ? 1 : 0),
-                               (unsigned __user *)argp);
-               break;
-       case TIOCSSOFTCAR:
-               if ((rc = get_user(ival, (unsigned __user *)argp)) == 0) {
-                       tty->termios->c_cflag =
-                               (tty->termios->c_cflag & ~CLOCAL) |
-                               (ival ? CLOCAL : 0);
-               }
-               break;
        case TIOCGSERIAL:
                rc = gs_getserial(&port->gs, argp);
                break;
@@ -1915,6 +1908,7 @@ static int sx_ioctl(struct tty_struct *tty, struct file *filp,
                rc = -ENOIOCTLCMD;
                break;
        }
+       unlock_kernel();
 
        /* func_exit(); */
        return rc;
@@ -1945,7 +1939,7 @@ static void sx_throttle(struct tty_struct *tty)
         * control then throttle the port.
         */
        if ((tty->termios->c_cflag & CRTSCTS) || (I_IXOFF(tty))) {
-               port->gs.flags |= SX_RX_THROTTLE;
+               port->gs.port.flags |= SX_RX_THROTTLE;
        }
        func_exit();
 }
@@ -1959,7 +1953,7 @@ static void sx_unthrottle(struct tty_struct *tty)
         * this port in case we disabled flow control while the port
         * was throttled
         */
-       port->gs.flags &= ~SX_RX_THROTTLE;
+       port->gs.port.flags &= ~SX_RX_THROTTLE;
        func_exit();
        return;
 }
@@ -2402,6 +2396,7 @@ static int sx_init_portstructs(int nboards, int nports)
                board->ports = port;
                for (j = 0; j < boards[i].nports; j++) {
                        sx_dprintk(SX_DEBUG_INIT, "initing port %d\n", j);
+                       tty_port_init(&port->gs.port);
                        port->gs.magic = SX_MAGIC;
                        port->gs.close_delay = HZ / 2;
                        port->gs.closing_wait = 30 * HZ;
@@ -2414,9 +2409,6 @@ static int sx_init_portstructs(int nboards, int nports)
                        /*
                         * Initializing wait queue
                         */
-                       init_waitqueue_head(&port->gs.open_wait);
-                       init_waitqueue_head(&port->gs.close_wait);
-
                        port++;
                }
        }
@@ -2549,7 +2541,7 @@ static int __devinit sx_eisa_probe(struct device *dev)
                goto err_flag;
        }
        board->base2 =
-       board->base = ioremap(board->hw_base, SI2_EISA_WINDOW_LEN);
+       board->base = ioremap_nocache(board->hw_base, SI2_EISA_WINDOW_LEN);
        if (!board->base) {
                dev_err(dev, "can't remap memory\n");
                goto err_reg;
@@ -2626,7 +2618,7 @@ static void __devinit fix_sx_pci(struct pci_dev *pdev, struct sx_board *board)
 
        pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &hwbase);
        hwbase &= PCI_BASE_ADDRESS_MEM_MASK;
-       rebase = ioremap(hwbase, 0x80);
+       rebase = ioremap_nocache(hwbase, 0x80);
        t = readl(rebase + CNTRL_REG_OFFSET);
        if (t != CNTRL_REG_GOODVALUE) {
                printk(KERN_DEBUG "sx: performing cntrl reg fix: %08x -> "
@@ -2770,7 +2762,7 @@ static int __init sx_init(void)
                if (!request_region(board->hw_base, board->hw_len, "sx"))
                        continue;
                board->base2 =
-               board->base = ioremap(board->hw_base, board->hw_len);
+               board->base = ioremap_nocache(board->hw_base, board->hw_len);
                if (!board->base)
                        goto err_sx_reg;
                board->flags &= ~SX_BOARD_TYPE;
@@ -2794,7 +2786,7 @@ err_sx_reg:
                if (!request_region(board->hw_base, board->hw_len, "sx"))
                        continue;
                board->base2 =
-               board->base = ioremap(board->hw_base, board->hw_len);
+               board->base = ioremap_nocache(board->hw_base, board->hw_len);
                if (!board->base)
                        goto err_si_reg;
                board->flags &= ~SX_BOARD_TYPE;
@@ -2817,7 +2809,7 @@ err_si_reg:
                if (!request_region(board->hw_base, board->hw_len, "sx"))
                        continue;
                board->base2 =
-               board->base = ioremap(board->hw_base, board->hw_len);
+               board->base = ioremap_nocache(board->hw_base, board->hw_len);
                if (!board->base)
                        goto err_si1_reg;
                board->flags &= ~SX_BOARD_TYPE;