patch-2.3.46 linux/drivers/char/lp.c
Next file: linux/drivers/char/mem.c
Previous file: linux/drivers/char/keyboard.c
Back to the patch index
Back to the overall index
- Lines: 337
- Date:
Wed Feb 16 15:42:05 2000
- Orig file:
v2.3.45/linux/drivers/char/lp.c
- Orig date:
Sat Feb 12 11:22:10 2000
diff -u --recursive --new-file v2.3.45/linux/drivers/char/lp.c linux/drivers/char/lp.c
@@ -16,6 +16,7 @@
* Parport sharing hacking by Andrea Arcangeli
* Fixed kernel_(to/from)_user memory copy to check for errors
* by Riccardo Facchetti <fizban@tin.it>
+ * 22-JAN-1998 Added support for devfs Richard Gooch <rgooch@atnf.csiro.au>
* Redesigned interrupt handling for handle printers with buggy handshake
* by Andrea Arcangeli, 11 May 1998
* Full efficient handling of printer with buggy irq handshake (now I have
@@ -118,6 +119,7 @@
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/sched.h>
+#include <linux/devfs_fs_kernel.h>
#include <linux/malloc.h>
#include <linux/fcntl.h>
#include <linux/delay.h>
@@ -138,6 +140,8 @@
/* ROUND_UP macro from fs/select.c */
#define ROUND_UP(x,y) (((x)+(y)-1)/(y))
+static devfs_handle_t devfs_handle = NULL;
+
struct lp_struct lp_table[LP_NO];
static unsigned int lp_count = 0;
@@ -151,72 +155,6 @@
#undef LP_DEBUG
-/* If you want to see if you can get lp_poll working, define this. */
-#undef SUPPORT_POLL
-
-/* --- parport support ----------------------------------------- */
-
-static int lp_preempt(void *handle)
-{
- struct lp_struct *lps = (struct lp_struct *)handle;
-
- if (!(lps->flags & LP_PORT_BUSY)) {
- /* Let the port go. */
- clear_bit (LP_HAVE_PORT_BIT, &lps->flags);
- return 0;
- }
-
- if (!(lps->flags & LP_PORT_BUSY)) {
- /* Let the port go. */
- clear_bit (LP_HAVE_PORT_BIT, &lps->flags);
- return 0;
- }
-
- /* Don't actually release the port now */
- return 1;
-}
-
-static void lp_check_data (struct lp_struct *lp)
-{
-#if !defined(CONFIG_PARPORT_1284) || !defined (SUPPORT_POLL)
- return;
-#else
- struct pardevice *dev = lp->dev;
- if (!(lp->flags & LP_NO_REVERSE)) {
- int err = parport_negotiate (dev->port, IEEE1284_MODE_NIBBLE);
- if (err)
- lp->flags |= LP_NO_REVERSE;
- else {
- unsigned char s = parport_read_status (dev->port);
- if (s & PARPORT_STATUS_ERROR)
- lp->flags &= ~LP_DATA_AVAIL;
- else {
- lp->flags |= LP_DATA_AVAIL;
- if (waitqueue_active (&lp->dataq))
- wake_up_interruptible (&lp->dataq);
- }
- }
- }
-#endif /* IEEE 1284 support */
-}
-
-static void lp_parport_release (int minor)
-{
- lp_check_data (&lp_table[minor]);
- if (test_and_clear_bit (LP_HAVE_PORT_BIT, &lp_table[minor].flags))
- parport_release (lp_table[minor].dev);
-
- lp_table[minor].flags &= ~LP_PORT_BUSY;
-}
-
-static void lp_parport_claim (int minor)
-{
- if (!test_and_set_bit (LP_HAVE_PORT_BIT, &lp_table[minor].flags))
- parport_claim_or_block (lp_table[minor].dev);
-
- lp_table[minor].flags |= LP_PORT_BUSY;
-}
-
/* --- low-level port access ----------------------------------- */
#define r_dtr(x) (parport_read_data(lp_table[(x)].dev->port))
@@ -227,42 +165,15 @@
static int lp_reset(int minor)
{
int retval;
- lp_parport_claim (minor);
+ parport_claim_or_block (lp_table[minor].dev);
w_ctr(minor, LP_PSELECP);
udelay (LP_DELAY);
w_ctr(minor, LP_PSELECP | LP_PINITP);
retval = r_str(minor);
- lp_parport_release (minor);
+ parport_release (lp_table[minor].dev);
return retval;
}
-static void lp_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
- struct lp_struct *lp_dev = (struct lp_struct *) dev_id;
- if (!(lp_dev->flags & LP_PORT_BUSY))
- /* We must have the port since we got an interrupt. */
- lp_check_data (lp_dev);
- if (waitqueue_active (&lp_dev->waitq))
- wake_up_interruptible (&lp_dev->waitq);
-}
-
-static void lp_wakeup (void *handle)
-{
- struct lp_struct *lp_dev = handle;
-
- if (lp_dev->flags & LP_PORT_BUSY)
- return;
-
- /* Grab the port if it can help (i.e. reverse mode is possible). */
- if (!(lp_dev->flags & LP_NO_REVERSE)) {
- parport_claim (lp_dev->dev);
- set_bit (LP_HAVE_PORT_BIT, &lp_dev->flags);
- lp_check_data (lp_dev);
- if (waitqueue_active (&lp_dev->waitq))
- wake_up_interruptible (&lp_dev->waitq);
- }
-}
-
static void lp_error (int minor)
{
int polling;
@@ -271,10 +182,10 @@
return;
polling = lp_table[minor].dev->port->irq == PARPORT_IRQ_NONE;
- if (polling) lp_parport_release (minor);
+ if (polling) parport_release (lp_table[minor].dev);
interruptible_sleep_on_timeout (&lp_table[minor].waitq,
LP_TIMEOUT_POLLED);
- if (polling) lp_parport_claim (minor);
+ if (polling) parport_claim_or_block (lp_table[minor].dev);
else parport_yield_blocking (lp_table[minor].dev);
}
@@ -347,7 +258,7 @@
/* Claim Parport or sleep until it becomes available
*/
- lp_parport_claim (minor);
+ parport_claim_or_block (lp_table[minor].dev);
/* Go to compatibility mode. */
parport_negotiate (port, IEEE1284_MODE_COMPAT);
@@ -402,7 +313,7 @@
/* Not really necessary, but polite. */
parport_set_timeout (lp_table[minor].dev, old_to);
- lp_parport_release (minor);
+ parport_release (lp_table[minor].dev);
up (&lp_table[minor].port_mutex);
@@ -426,7 +337,7 @@
if (down_interruptible (&lp_table[minor].port_mutex))
return -EINTR;
- lp_parport_claim (minor);
+ parport_claim_or_block (lp_table[minor].dev);
for (;;) {
retval = parport_read (port, kbuf, count);
@@ -447,7 +358,7 @@
}
}
- lp_parport_release (minor);
+ parport_release (lp_table[minor].dev);
if (retval > 0 && copy_to_user (buf, kbuf, retval))
retval = -EFAULT;
@@ -479,9 +390,9 @@
should most likely only ever be used by the tunelp application. */
if ((LP_F(minor) & LP_ABORTOPEN) && !(file->f_flags & O_NONBLOCK)) {
int status;
- lp_parport_claim (minor);
+ parport_claim_or_block (lp_table[minor].dev);
status = r_str(minor);
- lp_parport_release (minor);
+ parport_release (lp_table[minor].dev);
if (status & LP_POUTPA) {
printk(KERN_INFO "lp%d out of paper\n", minor);
MOD_DEC_USE_COUNT;
@@ -573,9 +484,9 @@
return -EFAULT;
break;
case LPGETSTATUS:
- lp_parport_claim(minor);
+ parport_claim_or_block (lp_table[minor].dev);
status = r_str(minor);
- lp_parport_release(minor);
+ parport_release (lp_table[minor].dev);
if (copy_to_user((int *) arg, &status, sizeof(int)))
return -EFAULT;
@@ -624,21 +535,6 @@
return retval;
}
-#ifdef CONFIG_PARPORT_1284
-static unsigned int lp_poll (struct file *filp, struct poll_table_struct *wait)
-{
- unsigned int minor = MINOR (filp->f_dentry->d_inode->i_rdev);
- unsigned int mask = POLLOUT | POLLWRNORM; /* always writable */
-
- poll_wait (filp, &lp_table[minor].dataq, wait);
-
- if (lp_table[minor].flags & LP_DATA_AVAIL)
- mask |= POLLIN | POLLRDNORM;
-
- return mask;
-}
-#endif /* IEEE 1284 support */
-
static struct file_operations lp_fops = {
write: lp_write,
ioctl: lp_ioctl,
@@ -646,7 +542,6 @@
release: lp_release,
#ifdef CONFIG_PARPORT_1284
read: lp_read,
- poll: lp_poll,
#endif
};
@@ -661,6 +556,8 @@
* non-zero to get the latter behaviour. */
#define CONSOLE_LP_STRICT 1
+/* The console_lock must be held when we get here. */
+
static void lp_console_write (struct console *co, const char *s,
unsigned count)
{
@@ -669,12 +566,9 @@
ssize_t written;
signed long old_to;
- if (!(lp_table[CONSOLE_LP].flags & (1<<LP_HAVE_PORT_BIT))) {
- if (parport_claim (dev))
- /* Nothing we can do. */
- return;
- set_bit (LP_HAVE_PORT_BIT, &lp_table[CONSOLE_LP].flags);
- }
+ if (parport_claim (dev))
+ /* Nothing we can do. */
+ return;
old_to = parport_set_timeout (dev, 0);
@@ -715,6 +609,7 @@
} while (count > 0 && (CONSOLE_LP_STRICT || written > 0));
parport_set_timeout (dev, old_to);
+ parport_release (dev);
}
static kdev_t lp_console_device (struct console *c)
@@ -786,9 +681,7 @@
static int lp_register(int nr, struct parport *port)
{
lp_table[nr].dev = parport_register_device(port, "lp",
- lp_preempt, lp_wakeup,
- lp_interrupt,
- 0,
+ NULL, NULL, NULL, 0,
(void *) &lp_table[nr]);
if (lp_table[nr].dev == NULL)
return 1;
@@ -883,7 +776,7 @@
lp_table[i].timeout = 10 * HZ;
}
- if (register_chrdev (LP_MAJOR, "lp", &lp_fops)) {
+ if (devfs_register_chrdev (LP_MAJOR, "lp", &lp_fops)) {
printk ("lp: unable to get major %d\n", LP_MAJOR);
return -EIO;
}
@@ -893,6 +786,22 @@
return -EIO;
}
+ devfs_handle = devfs_mk_dir (NULL, "printers", 0, NULL);
+ if (lp_count) {
+ for (i = 0; i < LP_NO; ++i)
+ {
+ char name[8];
+
+ if (!(lp_table[i].flags & LP_EXIST))
+ continue; /* skip this entry: it doesn't exist. */
+ sprintf (name, "%d", i);
+ devfs_register (devfs_handle, name, 0,
+ DEVFS_FL_DEFAULT, LP_MAJOR, i,
+ S_IFCHR | S_IRUGO | S_IWUGO, 0, 0,
+ &lp_fops, NULL);
+ }
+ }
+
if (!lp_count) {
printk (KERN_INFO "lp: driver loaded but no devices found\n");
#ifndef CONFIG_PARPORT_12843
@@ -943,12 +852,11 @@
unregister_console (&lpcons);
#endif
- unregister_chrdev(LP_MAJOR, "lp");
+ devfs_unregister (devfs_handle);
+ devfs_unregister_chrdev(LP_MAJOR, "lp");
for (offset = 0; offset < LP_NO; offset++) {
if (lp_table[offset].dev == NULL)
continue;
- if (lp_table[offset].flags & (1<<LP_HAVE_PORT_BIT))
- parport_release (lp_table[offset].dev);
parport_unregister_device(lp_table[offset].dev);
}
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)