* 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>
#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
#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 --------------------------------------------- */
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))
static int
put_ti_parallel(int minor, unsigned char data)
{
- int bit;
+ unsigned int bit;
unsigned long max;
for (bit = 0; bit < 8; bit++) {
static int
get_ti_parallel(int minor)
{
- int bit;
+ unsigned int bit;
unsigned char v, data = 0;
unsigned long max;
{
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;
}
{
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
}
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);
}
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) {
retval = -ETIMEDOUT;
goto out;
} else {
- if (put_user(b, ((unsigned char *) buf) + n)) {
+ if (put_user(b, buf + n)) {
retval = -EFAULT;
break;
} else
/* ----- 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,
static int __init
tipar_setup(char *str)
{
- int ints[2];
+ int ints[3];
str = get_options(str, ARRAY_SIZE(ints), ints);
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];
}
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;
}
.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;
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");
}
/* --------------------------------------------------------------------- */
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)");