* "lp=" command line parameters added by Grant Guenther, grant@torque.net
* lp_read (Status readback) support added by Carsten Gross,
* carsten@sol.wohnheim.uni-ulm.de
- * Support for parport by Philip Blundell <Philip.Blundell@pobox.com>
+ * Support for parport by Philip Blundell <philb@gnu.org>
* Parport sharing hacking by Andrea Arcangeli
* Fixed kernel_(to/from)_user memory copy to check for errors
* by Riccardo Facchetti <fizban@tin.it>
#include <linux/poll.h>
#include <linux/console.h>
#include <linux/device.h>
+#include <linux/wait.h>
+#include <linux/jiffies.h>
#include <linux/parport.h>
#undef LP_STATS
/* ROUND_UP macro from fs/select.c */
#define ROUND_UP(x,y) (((x)+(y)-1)/(y))
-struct lp_struct lp_table[LP_NO];
+static struct lp_struct lp_table[LP_NO];
static unsigned int lp_count = 0;
-static struct class_simple *lp_class;
+static struct class *lp_class;
#ifdef CONFIG_LP_CONSOLE
static struct parport *console_registered; // initially NULL
static void lp_error (int minor)
{
+ DEFINE_WAIT(wait);
int polling;
if (LP_F(minor) & LP_ABORT)
polling = lp_table[minor].dev->port->irq == PARPORT_IRQ_NONE;
if (polling) lp_release_parport (&lp_table[minor]);
- interruptible_sleep_on_timeout (&lp_table[minor].waitq,
- LP_TIMEOUT_POLLED);
+ prepare_to_wait(&lp_table[minor].waitq, &wait, TASK_INTERRUPTIBLE);
+ schedule_timeout(LP_TIMEOUT_POLLED);
+ finish_wait(&lp_table[minor].waitq, &wait);
if (polling) lp_claim_parport_or_block (&lp_table[minor]);
else parport_yield_blocking (lp_table[minor].dev);
}
return error;
}
-static ssize_t lp_write(struct file * file, const char * buf,
+static ssize_t lp_write(struct file * file, const char __user * buf,
size_t count, loff_t *ppos)
{
unsigned int minor = iminor(file->f_dentry->d_inode);
(LP_F(minor) & LP_ABORT));
#ifdef LP_STATS
- if (jiffies-lp_table[minor].lastcall > LP_TIME(minor))
+ if (time_after(jiffies, lp_table[minor].lastcall + LP_TIME(minor)))
lp_table[minor].runchars = 0;
lp_table[minor].lastcall = jiffies;
if (copy_size > LP_BUFFER_SIZE)
copy_size = LP_BUFFER_SIZE;
- if (copy_from_user (kbuf, buf, copy_size))
- return -EFAULT;
-
if (down_interruptible (&lp_table[minor].port_mutex))
return -EINTR;
+ if (copy_from_user (kbuf, buf, copy_size)) {
+ retv = -EFAULT;
+ goto out_unlock;
+ }
+
/* Claim Parport or sleep until it becomes available
*/
lp_claim_parport_or_block (&lp_table[minor]);
lp_table[minor].current_mode = IEEE1284_MODE_COMPAT;
lp_release_parport (&lp_table[minor]);
}
-
+out_unlock:
up (&lp_table[minor].port_mutex);
return retv;
#ifdef CONFIG_PARPORT_1284
/* Status readback conforming to ieee1284 */
-static ssize_t lp_read(struct file * file, char * buf,
+static ssize_t lp_read(struct file * file, char __user * buf,
size_t count, loff_t *ppos)
{
+ DEFINE_WAIT(wait);
unsigned int minor=iminor(file->f_dentry->d_inode);
struct parport *port = lp_table[minor].dev->port;
ssize_t retval = 0;
retval = -EIO;
goto out;
}
- } else
- interruptible_sleep_on_timeout (&lp_table[minor].waitq,
- LP_TIMEOUT_POLLED);
+ } else {
+ prepare_to_wait(&lp_table[minor].waitq, &wait, TASK_INTERRUPTIBLE);
+ schedule_timeout(LP_TIMEOUT_POLLED);
+ finish_wait(&lp_table[minor].waitq, &wait);
+ }
if (signal_pending (current)) {
retval = -ERESTARTSYS;
unsigned int minor = iminor(inode);
int status;
int retval = 0;
+ void __user *argp = (void __user *)arg;
#ifdef LP_DEBUG
printk(KERN_DEBUG "lp%d ioctl, cmd: 0x%x, arg: 0x%lx\n", minor, cmd, arg);
return -EINVAL;
break;
case LPGETIRQ:
- if (copy_to_user((int *) arg, &LP_IRQ(minor),
+ if (copy_to_user(argp, &LP_IRQ(minor),
sizeof(int)))
return -EFAULT;
break;
status = r_str(minor);
lp_release_parport (&lp_table[minor]);
- if (copy_to_user((int *) arg, &status, sizeof(int)))
+ if (copy_to_user(argp, &status, sizeof(int)))
return -EFAULT;
break;
case LPRESET:
break;
#ifdef LP_STATS
case LPGETSTATS:
- if (copy_to_user((int *) arg, &LP_STAT(minor),
+ if (copy_to_user(argp, &LP_STAT(minor),
sizeof(struct lp_stats)))
return -EFAULT;
if (capable(CAP_SYS_ADMIN))
#endif
case LPGETFLAGS:
status = LP_F(minor);
- if (copy_to_user((int *) arg, &status, sizeof(int)))
+ if (copy_to_user(argp, &status, sizeof(int)))
return -EFAULT;
break;
case LPSETTIMEOUT:
- if (copy_from_user (&par_timeout,
- (struct timeval *) arg,
+ if (copy_from_user (&par_timeout, argp,
sizeof (struct timeval))) {
return -EFAULT;
}
static char *parport[LP_NO] = { NULL, };
static int reset = 0;
-MODULE_PARM(parport, "1-" __MODULE_STRING(LP_NO) "s");
-MODULE_PARM(reset, "i");
+module_param_array(parport, charp, NULL, 0);
+module_param(reset, bool, 0);
#ifndef MODULE
static int __init lp_setup (char *str)
if (reset)
lp_reset(nr);
- class_simple_device_add(lp_class, MKDEV(LP_MAJOR, nr), NULL,
+ class_device_create(lp_class, NULL, MKDEV(LP_MAJOR, nr), NULL,
"lp%d", nr);
devfs_mk_cdev(MKDEV(LP_MAJOR, nr), S_IFCHR | S_IRUGO | S_IWUGO,
"printers/%d", nr);
.detach = lp_detach,
};
-int __init lp_init (void)
+static int __init lp_init (void)
{
int i, err = 0;
}
devfs_mk_dir("printers");
- lp_class = class_simple_create(THIS_MODULE, "printer");
+ lp_class = class_create(THIS_MODULE, "printer");
if (IS_ERR(lp_class)) {
err = PTR_ERR(lp_class);
goto out_devfs;
return 0;
out_class:
- class_simple_destroy(lp_class);
+ class_destroy(lp_class);
out_devfs:
devfs_remove("printers");
unregister_chrdev(LP_MAJOR, "lp");
continue;
parport_unregister_device(lp_table[offset].dev);
devfs_remove("printers/%d", offset);
- class_simple_device_remove(MKDEV(LP_MAJOR, offset));
+ class_device_destroy(lp_class, MKDEV(LP_MAJOR, offset));
}
devfs_remove("printers");
- class_simple_destroy(lp_class);
+ class_destroy(lp_class);
}
__setup("lp=", lp_setup);