Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / drivers / char / sx.c
index 533d286..3b47472 100644 (file)
@@ -4,7 +4,7 @@
  *  This driver will also support the older SI, and XIO cards.
  *
  *
- *   (C) 1998 - 2000  R.E.Wolff@BitWizard.nl
+ *   (C) 1998 - 2004  R.E.Wolff@BitWizard.nl
  *
  *  Simon Allen (simonallen@cix.compulink.co.uk) wrote a previous
  *  version of this driver. Some fragments may have been copied. (none
@@ -345,22 +345,22 @@ static int si_probe_addrs[]= {0xc0000, 0xd0000, 0xe0000,
                               0xc8000, 0xd8000, 0xe8000, 0xa0000};
 static int si1_probe_addrs[]= { 0xd0000};
 
-#define NR_SX_ADDRS (sizeof(sx_probe_addrs)/sizeof (int))
-#define NR_SI_ADDRS (sizeof(si_probe_addrs)/sizeof (int))
-#define NR_SI1_ADDRS (sizeof(si1_probe_addrs)/sizeof (int))
+#define NR_SX_ADDRS ARRAY_SIZE(sx_probe_addrs)
+#define NR_SI_ADDRS ARRAY_SIZE(si_probe_addrs)
+#define NR_SI1_ADDRS ARRAY_SIZE(si1_probe_addrs)
 
 
 /* Set the mask to all-ones. This alas, only supports 32 interrupts. 
    Some architectures may need more. */
 static int sx_irqmask = -1;
 
-MODULE_PARM(sx_probe_addrs, "i");
-MODULE_PARM(si_probe_addrs, "i");
-MODULE_PARM(sx_poll, "i");
-MODULE_PARM(sx_slowpoll, "i");
-MODULE_PARM(sx_maxints, "i");
-MODULE_PARM(sx_debug, "i");
-MODULE_PARM(sx_irqmask, "i");
+module_param_array(sx_probe_addrs, int, NULL, 0);
+module_param_array(si_probe_addrs, int, NULL, 0);
+module_param(sx_poll, int, 0);
+module_param(sx_slowpoll, int, 0);
+module_param(sx_maxints, int, 0);
+module_param(sx_debug, int, 0);
+module_param(sx_irqmask, int, 0);
 
 MODULE_LICENSE("GPL");
 
@@ -396,7 +396,7 @@ static struct real_driver sx_real_driver = {
 
 
 
-#define func_enter() sx_dprintk (SX_DEBUG_FLOW, "sx: enter %s\b",__FUNCTION__)
+#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_enter2() sx_dprintk (SX_DEBUG_FLOW, "sx: enter %s (port %d)\n", \
@@ -931,7 +931,7 @@ static int sx_set_real_termios (void *ptr)
        case CS6:sx_write_channel_byte (port, hi_mask, 0x3f);break;
        case CS5:sx_write_channel_byte (port, hi_mask, 0x1f);break;
        default:
-               printk (KERN_INFO "sx: Invalid wordsize: %d\n", CFLAG & CSIZE);
+               printk (KERN_INFO "sx: Invalid wordsize: %u\n", CFLAG & CSIZE);
                break;
        }
 
@@ -958,7 +958,7 @@ static int sx_set_real_termios (void *ptr)
        } else {
                set_bit(TTY_HW_COOK_IN, &port->gs.tty->flags);
        }
-       sx_dprintk (SX_DEBUG_TERMIOS, "iflags: %x(%d) ", 
+       sx_dprintk (SX_DEBUG_TERMIOS, "iflags: %x(%d) ",
                    port->gs.tty->termios->c_iflag, 
                    I_OTHER(port->gs.tty));
 
@@ -973,7 +973,7 @@ static int sx_set_real_termios (void *ptr)
        } else {
                clear_bit(TTY_HW_COOK_OUT, &port->gs.tty->flags);
        }
-       sx_dprintk (SX_DEBUG_TERMIOS, "oflags: %x(%d)\n", 
+       sx_dprintk (SX_DEBUG_TERMIOS, "oflags: %x(%d)\n",
                    port->gs.tty->termios->c_oflag, 
                    O_OTHER(port->gs.tty));
        /* port->c_dcd = sx_get_CD (port); */
@@ -1085,6 +1085,7 @@ static inline void sx_receive_chars (struct sx_port *port)
        int rx_op;
        struct tty_struct *tty;
        int copied=0;
+       unsigned char *rp;
 
        func_enter2 ();
        tty = port->gs.tty;
@@ -1094,31 +1095,25 @@ static inline void sx_receive_chars (struct sx_port *port)
 
                sx_dprintk (SX_DEBUG_RECEIVE, "rxop=%d, c = %d.\n", rx_op, c); 
 
-               /* Don't copy more bytes than there is room for in the buffer */
-               if (tty->flip.count + c > TTY_FLIPBUF_SIZE) 
-                       c = TTY_FLIPBUF_SIZE - tty->flip.count;
-
-               sx_dprintk (SX_DEBUG_RECEIVE, "c = %d.\n", c); 
-
                /* Don't copy past the end of the hardware receive buffer */
                if (rx_op + c > 0x100) c = 0x100 - rx_op;
 
                sx_dprintk (SX_DEBUG_RECEIVE, "c = %d.\n", c);
 
+               /* Don't copy more bytes than there is room for in the buffer */
+
+               c = tty_prepare_flip_string(tty, &rp, c);
+
+               sx_dprintk (SX_DEBUG_RECEIVE, "c = %d.\n", c); 
+
                /* If for one reason or another, we can't copy more data, we're done! */
                if (c == 0) break;
 
                sx_dprintk (SX_DEBUG_RECEIVE , "Copying over %d chars. First is %d at %lx\n", c, 
                            read_sx_byte (port->board, CHAN_OFFSET(port,hi_rxbuf) + rx_op),
                            CHAN_OFFSET(port, hi_rxbuf)); 
-               memcpy_fromio (tty->flip.char_buf_ptr, 
+               memcpy_fromio (rp,
                               port->board->base + CHAN_OFFSET(port,hi_rxbuf) + rx_op, c);
-               memset(tty->flip.flag_buf_ptr, TTY_NORMAL, c);
-
-               /* Update the kernel buffer end */
-               tty->flip.count += c;
-               tty->flip.char_buf_ptr += c;
-               tty->flip.flag_buf_ptr += c;
 
                /* This one last. ( Not essential.)
                   It allows the card to start putting more data into the buffer! 
@@ -1158,7 +1153,6 @@ static inline void sx_check_modem_signals (struct sx_port *port)
        if (hi_state & ST_BREAK) {
                hi_state &= ~ST_BREAK;
                sx_dprintk (SX_DEBUG_MODEMSIGNALS, "got a break.\n");
-
                sx_write_channel_byte (port, hi_state, hi_state);
                gs_got_break (&port->gs);
        }
@@ -1206,7 +1200,7 @@ static irqreturn_t sx_interrupt (int irq, void *ptr, struct pt_regs *regs)
        struct sx_port *port;
        int i;
 
-       /*   func_enter ();  */
+       func_enter ();
        sx_dprintk (SX_DEBUG_FLOW, "sx: enter sx_interrupt (%d/%d)\n", irq, board->irq); 
 
        /* AAargh! The order in which to do these things is essential and
@@ -1297,7 +1291,7 @@ static irqreturn_t sx_interrupt (int irq, void *ptr, struct pt_regs *regs)
        clear_bit (SX_BOARD_INTR_LOCK, &board->locks);
 
        sx_dprintk (SX_DEBUG_FLOW, "sx: exit sx_interrupt (%d/%d)\n", irq, board->irq); 
-       /*  func_exit ();  */
+        func_exit ();
        return IRQ_HANDLED;
 }
 
@@ -1428,6 +1422,7 @@ static int sx_open  (struct tty_struct * tty, struct file * filp)
 {
        struct sx_port *port;
        int retval, line;
+       unsigned long flags;
 
        func_enter();
 
@@ -1449,9 +1444,12 @@ static int sx_open  (struct tty_struct * tty, struct file * filp)
 
        sx_dprintk (SX_DEBUG_OPEN, "port = %p c_dcd = %d\n", port, port->c_dcd);
 
+       spin_lock_irqsave(&port->gs.driver_lock, flags);
+
        tty->driver_data = port;
        port->gs.tty = tty;
        port->gs.count++;
+       spin_unlock_irqrestore(&port->gs.driver_lock, flags);
 
        sx_dprintk (SX_DEBUG_OPEN, "starting port\n");
 
@@ -1466,7 +1464,8 @@ static int sx_open  (struct tty_struct * tty, struct file * filp)
        }
 
        port->gs.flags |= GS_ACTIVE;
-       sx_setsignals (port, 1,1);
+       if (port->gs.count <= 1)
+               sx_setsignals (port, 1,1);
 
 #if 0
        if (sx_debug & SX_DEBUG_OPEN)
@@ -1476,10 +1475,14 @@ static int sx_open  (struct tty_struct * tty, struct file * filp)
                my_hd_io (port->board->base + port->ch_base, sizeof (*port));
 #endif
 
-       if (sx_send_command (port, HS_LOPEN, -1, HS_IDLE_OPEN) != 1) {
-               printk (KERN_ERR "sx: Card didn't respond to LOPEN command.\n");
-               port->gs.count--;
-               return -EIO;
+       if (port->gs.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--;
+                       spin_unlock_irqrestore(&port->gs.driver_lock, flags);
+                       return -EIO;
+               }
        }
 
        retval = gs_block_til_ready(port, filp);
@@ -1497,6 +1500,7 @@ static int sx_open  (struct tty_struct * tty, struct file * filp)
 
        port->c_dcd = sx_get_CD (port);
        sx_dprintk (SX_DEBUG_OPEN, "at open: cd=%d\n", port->c_dcd);
+
        func_exit();
        return 0;
 
@@ -1515,13 +1519,9 @@ static void sx_close (void *ptr)
        sx_reconfigure_port(port);      
        sx_send_command (port, HS_CLOSE, 0, 0);
 
-       while (to-- && (sx_read_channel_byte (port, hi_hstat) != HS_IDLE_CLOSED)) {
-               set_current_state(TASK_INTERRUPTIBLE);
-               schedule_timeout (1);
-               if (signal_pending (current))
-                               break;
-       }
-       current->state = TASK_RUNNING;
+       while (to-- && (sx_read_channel_byte (port, hi_hstat) != HS_IDLE_CLOSED))
+               if (msleep_interruptible(10))
+                       break;
        if (sx_read_channel_byte (port, hi_hstat) != HS_IDLE_CLOSED) {
                if (sx_send_command (port, HS_FORCE_CLOSED, -1, HS_IDLE_CLOSED) != 1) {
                        printk (KERN_ERR 
@@ -1535,7 +1535,8 @@ static void sx_close (void *ptr)
 
        if(port->gs.count) {
                sx_dprintk(SX_DEBUG_CLOSE, "WARNING port count:%d\n", port->gs.count);
-               port->gs.count = 0;
+               //printk ("%s SETTING port count to zero: %p count: %d\n", __FUNCTION__, port, port->gs.count);
+               //port->gs.count = 0;
        }
 
        func_exit ();
@@ -1751,12 +1752,16 @@ static void sx_break (struct tty_struct * tty, int flag)
        struct sx_port *port = tty->driver_data;
        int rv;
 
+       func_enter ();
+
        if (flag) 
                rv = sx_send_command (port, HS_START, -1, HS_IDLE_BREAK);
        else 
                rv = sx_send_command (port, HS_STOP, -1, HS_IDLE_OPEN);
        if (rv != 1) printk (KERN_ERR "sx: couldn't send break (%x).\n",
                        read_sx_byte (port->board, CHAN_OFFSET (port, hi_hstat)));
+
+       func_exit ();
 }
 
 
@@ -2105,7 +2110,7 @@ static int probe_sx (struct sx_board *board)
                }
 
                if (((vpdp.uniqid >> 24) & SX_UNIQUEID_MASK) == SX_ISA_UNIQUEID1) {
-                       if (board->hw_base & 0x8000) {
+                       if (((unsigned long)board->hw_base) & 0x8000) {
                                printk (KERN_WARNING "sx: Warning: There may be hardware problems with the card at %lx.\n", board->hw_base);
                                printk (KERN_WARNING "sx: Read sx.txt for more info.\n");
                        }
@@ -2154,6 +2159,7 @@ static int probe_si (struct sx_board *board)
            }
                for (i=0;i<8;i++) {
                        if ((read_sx_byte (board, SI2_ISA_ID_BASE+7-i) & 7) != i) {
+                               func_exit ();
                                return 0;
                        }
                }
@@ -2167,13 +2173,17 @@ static int probe_si (struct sx_board *board)
        if ( IS_SI1_BOARD(board)) {
                /* This should be an SI1 board, which has this
                   location writable... */
-               if (read_sx_byte (board, SI2_ISA_ID_BASE) != 0x10)
+               if (read_sx_byte (board, SI2_ISA_ID_BASE) != 0x10) {
+                       func_exit ();
                        return 0; 
+               }
        } else {
                /* This should be an SI2 board, which has the bottom
                   3 bits non-writable... */
-               if (read_sx_byte (board, SI2_ISA_ID_BASE) == 0x10)
+               if (read_sx_byte (board, SI2_ISA_ID_BASE) == 0x10) {
+                       func_exit ();
                        return 0; 
+               }
        }
 
        /* Now we're pretty much convinced that there is an SI board here, 
@@ -2184,13 +2194,17 @@ static int probe_si (struct sx_board *board)
        if ( IS_SI1_BOARD(board)) {
                /* This should be an SI1 board, which has this
                   location writable... */
-               if (read_sx_byte (board, SI2_ISA_ID_BASE) != 0x10)
+               if (read_sx_byte (board, SI2_ISA_ID_BASE) != 0x10) {
+                       func_exit();
                        return 0; 
+               }
        } else {
                /* This should be an SI2 board, which has the bottom
                   3 bits non-writable... */
-               if (read_sx_byte (board, SI2_ISA_ID_BASE) == 0x10)
+               if (read_sx_byte (board, SI2_ISA_ID_BASE) == 0x10) {
+                       func_exit ();
                        return 0; 
+               }
        }
 
        printheader ();
@@ -2304,8 +2318,9 @@ static int sx_init_portstructs (int nboards, int nports)
                        port->board = board;
                        port->gs.rd = &sx_real_driver;
 #ifdef NEW_WRITE_LOCKING
-                       port->gs.port_write_sem = MUTEX;
+                       port->gs.port_write_mutex = MUTEX;
 #endif
+                       port->gs.driver_lock = SPIN_LOCK_UNLOCKED;
                        /*
                         * Initializing wait queue
                         */
@@ -2477,7 +2492,7 @@ static int __init sx_init(void)
                        found++;
                        fix_sx_pci (pdev, board);
                } else 
-                       iounmap(board->base);
+                       iounmap(board->base2);
        }
 #endif