X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fchar%2Fpcxx.c;h=061237bb0c33e0e0a5ee50770367437291ca3270;hb=3ec04f3d2903fdf6d9849a8633af59b8628164a5;hp=b20a94194ca3c1d1b1ed7908cca87af871f1b94e;hpb=8d40237c730b8be87c1b80a5d96b9c603fefa829;p=linux-2.6.git diff --git a/drivers/char/pcxx.c b/drivers/char/pcxx.c index b20a94194..061237bb0 100644 --- a/drivers/char/pcxx.c +++ b/drivers/char/pcxx.c @@ -65,7 +65,6 @@ #include #include #include -#include #ifndef MODULE #include /* We only need it for parsing the "digi="-line */ @@ -74,6 +73,7 @@ #include #include #include +#include #include #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; }