linux/drivers/char/lp.c

// SPDX-License-Identifier: GPL-2.0-only
/*
 * Generic parallel printer driver
 *
 * Copyright (C) 1992 by Jim Weigand and Linus Torvalds
 * Copyright (C) 1992,1993 by Michael K. Johnson
 * - Thanks much to Gunter Windau for pointing out to me where the error
 *   checking ought to be.
 * Copyright (C) 1993 by Nigel Gamble (added interrupt code)
 * Copyright (C) 1994 by Alan Cox (Modularised it)
 * LPCAREFUL, LPABORT, LPGETSTATUS added by Chris Metcalf, [email protected]
 * Statistics and support for slow printers by Rob Janssen, [email protected]
 * "lp=" command line parameters added by Grant Guenther, [email protected]
 * lp_read (Status readback) support added by Carsten Gross,
 *                                             [email protected]
 * Support for parport by Philip Blundell <[email protected]>
 * Parport sharing hacking by Andrea Arcangeli
 * Fixed kernel_(to/from)_user memory copy to check for errors
 * 				by Riccardo Facchetti <[email protected]>
 * 22-JAN-1998  Added support for devfs  Richard Gooch <[email protected]>
 * 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
 * understood the meaning of the strange handshake). This is done sending new
 * characters if the interrupt is just happened, even if the printer say to
 * be still BUSY. This is needed at least with Epson Stylus Color. To enable
 * the new TRUST_IRQ mode read the `LP OPTIMIZATION' section below...
 * Fixed the irq on the rising edge of the strobe case.
 * Obsoleted the CAREFUL flag since a printer that doesn' t work with
 * CAREFUL will block a bit after in lp_check_status().
 *				Andrea Arcangeli, 15 Oct 1998
 * Obsoleted and removed all the lowlevel stuff implemented in the last
 * month to use the IEEE1284 functions (that handle the _new_ compatibilty
 * mode fine).
 */

/* This driver should, in theory, work with any parallel port that has an
 * appropriate low-level driver; all I/O is done through the parport
 * abstraction layer.
 *
 * If this driver is built into the kernel, you can configure it using the
 * kernel command-line.  For example:
 *
 *	lp=parport1,none,parport2	(bind lp0 to parport1, disable lp1 and
 *					 bind lp2 to parport2)
 *
 *	lp=auto				(assign lp devices to all ports that
 *				         have printers attached, as determined
 *					 by the IEEE-1284 autoprobe)
 *
 *	lp=reset			(reset the printer during
 *					 initialisation)
 *
 *	lp=off				(disable the printer driver entirely)
 *
 * If the driver is loaded as a module, similar functionality is available
 * using module parameters.  The equivalent of the above commands would be:
 *
 *	# insmod lp.o parport=1,none,2
 *
 *	# insmod lp.o parport=auto
 *
 *	# insmod lp.o reset=1
 */

/* COMPATIBILITY WITH OLD KERNELS
 *
 * Under Linux 2.0 and previous versions, lp devices were bound to ports at
 * particular I/O addresses, as follows:
 *
 *	lp0		0x3bc
 *	lp1		0x378
 *	lp2		0x278
 *
 * The new driver, by default, binds lp devices to parport devices as it
 * finds them.  This means that if you only have one port, it will be bound
 * to lp0 regardless of its I/O address.  If you need the old behaviour, you
 * can force it using the parameters described above.
 */

/*
 * The new interrupt handling code take care of the buggy handshake
 * of some HP and Epson printer:
 * ___
 * ACK    _______________    ___________
 *                       |__|
 * ____
 * BUSY   _________              _______
 *                 |____________|
 *
 * I discovered this using the printer scanner that you can find at:
 *
 *	ftp://e-mind.com/pub/linux/pscan/
 *
 *					11 May 98, Andrea Arcangeli
 *
 * My printer scanner run on an Epson Stylus Color show that such printer
 * generates the irq on the _rising_ edge of the STROBE. Now lp handle
 * this case fine too.
 *
 *					15 Oct 1998, Andrea Arcangeli
 *
 * The so called `buggy' handshake is really the well documented
 * compatibility mode IEEE1284 handshake. They changed the well known
 * Centronics handshake acking in the middle of busy expecting to not
 * break drivers or legacy application, while they broken linux lp
 * until I fixed it reverse engineering the protocol by hand some
 * month ago...
 *
 *                                     14 Dec 1998, Andrea Arcangeli
 *
 * Copyright (C) 2000 by Tim Waugh (added LPSETTIMEOUT ioctl)
 */

#include <linux/module.h>
#include <linux/init.h>

#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/sched/signal.h>
#include <linux/slab.h>
#include <linux/fcntl.h>
#include <linux/delay.h>
#include <linux/poll.h>
#include <linux/console.h>
#include <linux/device.h>
#include <linux/wait.h>
#include <linux/jiffies.h>
#include <linux/mutex.h>
#include <linux/compat.h>

#include <linux/parport.h>
#undef LP_STATS
#include <linux/lp.h>

#include <asm/irq.h>
#include <linux/uaccess.h>

/* if you have more than 8 printers, remember to increase LP_NO */
#define LP_NO

static DEFINE_MUTEX(lp_mutex);
static struct lp_struct lp_table[LP_NO];
static int port_num[LP_NO];

static unsigned int lp_count =;
static const struct class lp_class =;

#ifdef CONFIG_LP_CONSOLE
static struct parport *console_registered;
#endif /* CONFIG_LP_CONSOLE */

#undef LP_DEBUG

/* Bits used to manage claiming the parport device */
#define LP_PREEMPT_REQUEST
#define LP_PARPORT_CLAIMED

/* --- low-level port access ----------------------------------- */

#define r_dtr(x)
#define r_str(x)
#define w_ctr(x,y)
#define w_dtr(x,y)

/* Claim the parport or block trying unless we've already claimed it */
static void lp_claim_parport_or_block(struct lp_struct *this_lp)
{}

/* Claim the parport or block trying unless we've already claimed it */
static void lp_release_parport(struct lp_struct *this_lp)
{}



static int lp_preempt(void *handle)
{}


/*
 * Try to negotiate to a new mode; if unsuccessful negotiate to
 * compatibility mode.  Return the mode we ended up in.
 */
static int lp_negotiate(struct parport *port, int mode)
{}

static int lp_reset(int minor)
{}

static void lp_error(int minor)
{}

static int lp_check_status(int minor)
{}

static int lp_wait_ready(int minor, int nonblock)
{}

static ssize_t lp_write(struct file *file, const char __user *buf,
			size_t count, loff_t *ppos)
{}

#ifdef CONFIG_PARPORT_1284

/* Status readback conforming to ieee1284 */
static ssize_t lp_read(struct file *file, char __user *buf,
		       size_t count, loff_t *ppos)
{}

#endif /* IEEE 1284 support */

static int lp_open(struct inode *inode, struct file *file)
{}

static int lp_release(struct inode *inode, struct file *file)
{}

static int lp_do_ioctl(unsigned int minor, unsigned int cmd,
	unsigned long arg, void __user *argp)
{}

static int lp_set_timeout(unsigned int minor, s64 tv_sec, long tv_usec)
{}

static int lp_set_timeout32(unsigned int minor, void __user *arg)
{}

static int lp_set_timeout64(unsigned int minor, void __user *arg)
{}

static long lp_ioctl(struct file *file, unsigned int cmd,
			unsigned long arg)
{}

#ifdef CONFIG_COMPAT
static long lp_compat_ioctl(struct file *file, unsigned int cmd,
			unsigned long arg)
{}
#endif

static const struct file_operations lp_fops =;

/* --- support for console on the line printer ----------------- */

#ifdef CONFIG_LP_CONSOLE

#define CONSOLE_LP

/* If the printer is out of paper, we can either lose the messages or
 * stall until the printer is happy again.  Define CONSOLE_LP_STRICT
 * non-zero to get the latter behaviour. */
#define CONSOLE_LP_STRICT

/* The console must be locked when we get here. */

static void lp_console_write(struct console *co, const char *s,
			     unsigned count)
{}

static struct console lpcons =;

#endif /* console on line printer */

/* --- initialisation code ------------------------------------- */

static int parport_nr[LP_NO] =;
static char *parport[LP_NO];
static bool reset;

module_param_array();
module_param(reset, bool, 0);

#ifndef MODULE
static int __init lp_setup(char *str)
{}
#endif

static int lp_register(int nr, struct parport *port)
{}

static void lp_attach(struct parport *port)
{}

static void lp_detach(struct parport *port)
{}

static struct parport_driver lp_driver =;

static int __init lp_init(void)
{}

static int __init lp_init_module(void)
{}

static void lp_cleanup_module(void)
{}

__setup();
module_init();
module_exit(lp_cleanup_module);

MODULE_ALIAS_CHARDEV_MAJOR();
MODULE_DESCRIPTION();
MODULE_LICENSE();