fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / drivers / char / tipar.c
index 3632e28..47fb20f 100644 (file)
  * the minor number.
  *
  */
-
-#include <linux/config.h>
+#undef DEBUG                           /* change to #define to get debugging
+                                        * output - for pr_debug() */
 #include <linux/module.h>
-#include <linux/version.h>
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
@@ -55,9 +54,9 @@
 #include <asm/uaccess.h>
 #include <linux/ioport.h>
 #include <asm/io.h>
-#include <asm/bitops.h>
-#include <linux/devfs_fs_kernel.h>     /* DevFs support */
-#include <linux/parport.h>     /* Our code depend on parport */
+#include <linux/bitops.h>
+#include <linux/parport.h>             /* Our code depend on parport */
+#include <linux/device.h>
 
 /*
  * TI definitions
@@ -73,9 +72,6 @@
 #define DRIVER_LICENSE "GPL"
 
 #define VERSION(ver,rel,seq) (((ver)<<16) | ((rel)<<8) | (seq))
-#if LINUX_VERSION_CODE < VERSION(2,5,0)
-# define need_resched() (current->need_resched)
-#endif
 
 /* ----- global variables --------------------------------------------- */
 
@@ -92,6 +88,8 @@ static int timeout = TIMAXTIME;       /* timeout in tenth of seconds     */
 static unsigned int tp_count;  /* tipar count */
 static unsigned long opened;   /* opened devices */
 
+static struct class *tipar_class;
+
 /* --- macros for parport access -------------------------------------- */
 
 #define r_dtr(x)        (parport_read_data(table[(x)].dev->port))
@@ -140,7 +138,7 @@ White:  ________            |        ______      |          _______
 static int
 put_ti_parallel(int minor, unsigned char data)
 {
-       int bit;
+       unsigned int bit;
        unsigned long max;
 
        for (bit = 0; bit < 8; bit++) {
@@ -184,7 +182,7 @@ put_ti_parallel(int minor, unsigned char data)
 static int
 get_ti_parallel(int minor)
 {
-       int bit;
+       unsigned int bit;
        unsigned char v, data = 0;
        unsigned long max;
 
@@ -226,13 +224,16 @@ probe_ti_parallel(int minor)
 {
        int i;
        int seq[] = { 0x00, 0x20, 0x10, 0x30 };
+       int data;
 
        for (i = 3; i >= 0; i--) {
                outbyte(3, minor);
                outbyte(i, minor);
                udelay(delay);
-               /*printk(KERN_DEBUG "Probing -> %i: 0x%02x 0x%02x\n", i, data & 0x30, seq[i]); */
-               if ((inbyte(minor) & 0x30) != seq[i]) {
+               data = inbyte(minor) & 0x30;
+               pr_debug("tipar: Probing -> %i: 0x%02x 0x%02x\n", i,
+                       data, seq[i]);
+               if (data != seq[i]) {
                        outbyte(3, minor);
                        return -1;
                }
@@ -249,17 +250,22 @@ tipar_open(struct inode *inode, struct file *file)
 {
        unsigned int minor = iminor(inode) - TIPAR_MINOR;
 
-       if (minor > tp_count - 1)
+       if (tp_count == 0 || minor > tp_count - 1)
                return -ENXIO;
 
        if (test_and_set_bit(minor, &opened))
                return -EBUSY;
 
+       if (!table[minor].dev) {
+               printk(KERN_ERR "%s: NULL device for minor %u\n",
+                               __FUNCTION__, minor);
+               return -ENXIO;
+       }
        parport_claim_or_block(table[minor].dev);
        init_ti_parallel(minor);
        parport_release(table[minor].dev);
 
-       return 0;
+       return nonseekable_open(inode, file);
 }
 
 static int
@@ -276,9 +282,10 @@ tipar_close(struct inode *inode, struct file *file)
 }
 
 static ssize_t
-tipar_write(struct file *file, const char *buf, size_t count, loff_t * ppos)
+tipar_write (struct file *file, const char __user *buf, size_t count,
+               loff_t * ppos)
 {
-       unsigned int minor = iminor(file->f_dentry->d_inode) - TIPAR_MINOR;
+       unsigned int minor = iminor(file->f_path.dentry->d_inode) - TIPAR_MINOR;
        ssize_t n;
 
        parport_claim_or_block(table[minor].dev);
@@ -303,19 +310,16 @@ tipar_write(struct file *file, const char *buf, size_t count, loff_t * ppos)
 }
 
 static ssize_t
-tipar_read(struct file *file, char *buf, size_t count, loff_t * ppos)
+tipar_read(struct file *file, char __user *buf, size_t count, loff_t * ppos)
 {
        int b = 0;
-       unsigned int minor = iminor(file->f_dentry->d_inode) - TIPAR_MINOR;
+       unsigned int minor = iminor(file->f_path.dentry->d_inode) - TIPAR_MINOR;
        ssize_t retval = 0;
        ssize_t n = 0;
 
        if (count == 0)
                return 0;
 
-       if (ppos != &file->f_pos)
-               return -ESPIPE;
-
        parport_claim_or_block(table[minor].dev);
 
        while (n < count) {
@@ -325,7 +329,7 @@ tipar_read(struct file *file, char *buf, size_t count, loff_t * ppos)
                        retval = -ETIMEDOUT;
                        goto out;
                } else {
-                       if (put_user(b, ((unsigned char *) buf) + n)) {
+                       if (put_user(b, buf + n)) {
                                retval = -EFAULT;
                                break;
                        } else
@@ -379,7 +383,7 @@ tipar_ioctl(struct inode *inode, struct file *file,
 
 /* ----- kernel module registering ------------------------------------ */
 
-static struct file_operations tipar_fops = {
+static const struct file_operations tipar_fops = {
        .owner = THIS_MODULE,
        .llseek = no_llseek,
        .read = tipar_read,
@@ -397,7 +401,7 @@ static struct file_operations tipar_fops = {
 static int __init
 tipar_setup(char *str)
 {
-       int ints[2];
+       int ints[3];
 
        str = get_options(str, ARRAY_SIZE(ints), ints);
 
@@ -405,7 +409,8 @@ tipar_setup(char *str)
                if (ints[1] != 0)
                         timeout = ints[1];
                 else
-                        printk("tipar: wrong timeout value (0), using default value instead.");
+                        printk(KERN_WARNING "tipar: bad timeout value (0), "
+                               "using default value instead");
                if (ints[0] > 1) {
                        delay = ints[2];
                }
@@ -424,37 +429,41 @@ tipar_setup(char *str)
 static int
 tipar_register(int nr, struct parport *port)
 {
+       int err = 0;
+
        /* Register our module into parport */
        table[nr].dev = parport_register_device(port, "tipar",
                                                NULL, NULL, NULL, 0,
                                                (void *) &table[nr]);
 
-       if (table[nr].dev == NULL)
-               return 1;
+       if (table[nr].dev == NULL) {
+               err = 1;
+               goto out;
+       }
 
-       /* Use devfs, tree: /dev/ticables/par/[0..2] */
-       devfs_mk_cdev(MKDEV(TIPAR_MAJOR, TIPAR_MINOR + nr),
-                       S_IFCHR | S_IRUGO | S_IWUGO,
-                       "ticables/par/%d", nr);
+       class_device_create(tipar_class, NULL, MKDEV(TIPAR_MAJOR,
+                       TIPAR_MINOR + nr), NULL, "par%d", nr);
 
        /* Display informations */
-       printk(KERN_INFO "tipar%d: using %s (%s).\n", nr, port->name,
-              (port->irq ==
+       pr_info("tipar%d: using %s (%s)\n", nr, port->name, (port->irq ==
                PARPORT_IRQ_NONE) ? "polling" : "interrupt-driven");
 
        if (probe_ti_parallel(nr) != -1)
-               printk("tipar%d: link cable found !\n", nr);
+               pr_info("tipar%d: link cable found\n", nr);
        else
-               printk("tipar%d: link cable not found.\n", nr);
+               pr_info("tipar%d: link cable not found\n", nr);
 
-       return 0;
+       err = 0;
+
+out:
+       return err;
 }
 
 static void
 tipar_attach(struct parport *port)
 {
        if (tp_count == PP_NO) {
-               printk("tipar: ignoring parallel port (max. %d)\n", PP_NO);
+               pr_info("tipar: ignoring parallel port (max. %d)\n", PP_NO);
                return;
        }
 
@@ -474,29 +483,44 @@ static struct parport_driver tipar_driver = {
        .detach = tipar_detach,
 };
 
-int __init
+static int __init
 tipar_init_module(void)
 {
-       printk("tipar: parallel link cable driver, version %s\n",
-              DRIVER_VERSION);
+       int err = 0;
+
+       pr_info("tipar: parallel link cable driver, version %s\n",
+               DRIVER_VERSION);
 
        if (register_chrdev(TIPAR_MAJOR, "tipar", &tipar_fops)) {
-               printk("tipar: unable to get major %d\n", TIPAR_MAJOR);
-               return -EIO;
+               printk(KERN_ERR "tipar: unable to get major %d\n", TIPAR_MAJOR);
+               err = -EIO;
+               goto out;
        }
 
-       /* Use devfs with tree: /dev/ticables/par/[0..2] */
-       devfs_mk_dir("ticables/par");
-
+       tipar_class = class_create(THIS_MODULE, "ticables");
+       if (IS_ERR(tipar_class)) {
+               err = PTR_ERR(tipar_class);
+               goto out_chrdev;
+       }
        if (parport_register_driver(&tipar_driver)) {
-               printk("tipar: unable to register with parport\n");
-               return -EIO;
+               printk(KERN_ERR "tipar: unable to register with parport\n");
+               err = -EIO;
+               goto out_class;
        }
 
-       return 0;
+       err = 0;
+       goto out;
+
+out_class:
+       class_destroy(tipar_class);
+
+out_chrdev:
+       unregister_chrdev(TIPAR_MAJOR, "tipar");
+out:
+       return err;     
 }
 
-void __exit
+static void __exit
 tipar_cleanup_module(void)
 {
        unsigned int i;
@@ -510,11 +534,11 @@ tipar_cleanup_module(void)
                if (table[i].dev == NULL)
                        continue;
                parport_unregister_device(table[i].dev);
-               devfs_remove("ticables/par/%d", i);
+               class_device_destroy(tipar_class, MKDEV(TIPAR_MAJOR, i));
        }
-       devfs_remove("ticables/par");
+       class_destroy(tipar_class);
 
-       printk("tipar: module unloaded !\n");
+       pr_info("tipar: module unloaded\n");
 }
 
 /* --------------------------------------------------------------------- */
@@ -527,7 +551,7 @@ MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE(DRIVER_LICENSE);
 
-MODULE_PARM(timeout, "i");
+module_param(timeout, int, 0);
 MODULE_PARM_DESC(timeout, "Timeout (default=1.5 seconds)");
-MODULE_PARM(delay, "i");
+module_param(delay, int, 0);
 MODULE_PARM_DESC(delay, "Inter-bit delay (default=10 microseconds)");