This commit was manufactured by cvs2svn to create tag
[linux-2.6.git] / drivers / char / pcxx.c
index b20a941..061237b 100644 (file)
@@ -65,7 +65,6 @@
 #include <linux/tty_driver.h>
 #include <linux/slab.h>
 #include <linux/init.h>
-#include <linux/bitops.h>
 
 #ifndef MODULE
 #include <linux/ctype.h> /* We only need it for parsing the "digi="-line */
@@ -74,6 +73,7 @@
 #include <asm/system.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
+#include <asm/bitops.h>
 #include <asm/semaphore.h>
 
 #define VERSION        "1.6.3"
@@ -112,13 +112,13 @@ static int numports[]     = {0, 0, 0, 0};
 MODULE_AUTHOR("Bernhard Kaindl");
 MODULE_DESCRIPTION("Digiboard PC/X{i,e,eve} driver");
 MODULE_LICENSE("GPL");
-module_param(verbose,     bool, 0644);
-module_param(debug,       bool, 0644);
-module_param_array(io,          int, NULL, 0);
-module_param_array(membase,     int, NULL, 0);
-module_param_array(memsize,     int, NULL, 0);
-module_param_array(altpin,      int, NULL, 0);
-module_param_array(numports,    int, NULL, 0);
+MODULE_PARM(verbose,     "i");
+MODULE_PARM(debug,       "i");
+MODULE_PARM(io,          "1-4i");
+MODULE_PARM(membase,     "1-4i");
+MODULE_PARM(memsize,     "1-4i");
+MODULE_PARM(altpin,      "1-4i");
+MODULE_PARM(numports,    "1-4i");
 
 #endif /* MODULE */
 
@@ -148,7 +148,7 @@ static void pcxx_error(int, char *);
 static void pcxe_close(struct tty_struct *, struct file *);
 static int pcxe_ioctl(struct tty_struct *, struct file *, unsigned int, unsigned long);
 static void pcxe_set_termios(struct tty_struct *, struct termios *);
-static int pcxe_write(struct tty_struct *, const unsigned char *, int);
+static int pcxe_write(struct tty_struct *, int, const unsigned char *, int);
 static int pcxe_write_room(struct tty_struct *);
 static int pcxe_chars_in_buffer(struct tty_struct *);
 static void pcxe_flush_buffer(struct tty_struct *);
@@ -538,7 +538,8 @@ static void pcxe_close(struct tty_struct * tty, struct file * filp)
                info->tty = NULL;
                if(info->blocked_open) {
                        if(info->close_delay) {
-                               msleep_interruptible(jiffies_to_msecs(info->close_delay));
+                               current->state = TASK_INTERRUPTIBLE;
+                               schedule_timeout(info->close_delay);
                        }
                        wake_up_interruptible(&info->open_wait);
                }
@@ -570,7 +571,7 @@ void pcxe_hangup(struct tty_struct *tty)
 
 
 
-static int pcxe_write(struct tty_struct * tty, const unsigned char *buf, int count)
+static int pcxe_write(struct tty_struct * tty, int from_user, const unsigned char *buf, int count)
 {
        struct channel *ch;
        volatile struct board_chan *bc;
@@ -585,6 +586,33 @@ static int pcxe_write(struct tty_struct * tty, const unsigned char *buf, int cou
        bc = ch->brdchan;
        size = ch->txbufsize;
 
+       if (from_user) {
+
+               down(&ch->tmp_buf_sem);
+               save_flags(flags);
+               cli();
+               globalwinon(ch);
+               head = bc->tin & (size - 1);
+               /* It seems to be necessary to make sure that the value is stable here somehow
+                  This is a rather odd pice of code here. */
+               do
+               {
+                       tail = bc->tout;
+               } while (tail != bc->tout);
+               
+               tail &= (size - 1);
+               stlen = (head >= tail) ? (size - (head - tail) - 1) : (tail - head - 1);
+               count = min(stlen, count);
+               memoff(ch);
+               restore_flags(flags);
+
+               if (count)
+                       if (copy_from_user(ch->tmp_buf, buf, count))
+                               count = 0;
+
+               buf = ch->tmp_buf;
+       }
+
        /*
         * All data is now local
         */
@@ -631,13 +659,16 @@ static int pcxe_write(struct tty_struct * tty, const unsigned char *buf, int cou
        memoff(ch);
        restore_flags(flags);
        
+       if(from_user)
+               up(&ch->tmp_buf_sem);
+
        return(total);
 }
 
 
 static void pcxe_put_char(struct tty_struct *tty, unsigned char c)
 {
-       pcxe_write(tty, &c, 1);
+       pcxe_write(tty, 0, &c, 1);
        return;
 }