aboutsummaryrefslogblamecommitdiffstats
path: root/drivers/char/lp.c
blob: c59e2a0996cc9a11c87447b0e34bbd41412f9340 (plain) (tree)



















































































































                                                                              



                         






                          
                          











                                                                  


                                        
                              





















































































































































                                                                                             
                                                                  








                                                         
                                                                           











































































































                                                                                
                                                                












































































































                                                                                           
                                                                        





























































































































                                                                                  
                                                                                   












                                                                     
                                               







































































































































                                                                                              
                                                                            

































































































                                                                                         
                                                        

                                        
                             


















                                                                                   
                                
        














































                                                                                                             
                                                                  
         
                                







                                     
/*
 * 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, metcalf@lcs.mit.edu
 * Statistics and support for slow printers by Rob Janssen, rob@knoware.nl
 * "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 <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>
 * 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
 * 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.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/parport.h>
#undef LP_STATS
#include <linux/lp.h>

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

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

static struct lp_struct lp_table[LP_NO];

static unsigned int lp_count = 0;
static struct class *lp_class;

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

#undef LP_DEBUG

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

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

#define r_dtr(x)	(parport_read_data(lp_table[(x)].dev->port))
#define r_str(x)	(parport_read_status(lp_table[(x)].dev->port))
#define w_ctr(x,y)	do { parport_write_control(lp_table[(x)].dev->port, (y)); } while (0)
#define w_dtr(x,y)	do { parport_write_data(lp_table[(x)].dev->port, (y)); } while (0)

/* Claim the parport or block trying unless we've already claimed it */
static void lp_claim_parport_or_block(struct lp_struct *this_lp)
{
	if (!test_and_set_bit(LP_PARPORT_CLAIMED, &this_lp->bits)) {
		parport_claim_or_block (this_lp->dev);
	}
}

/* Claim the parport or block trying unless we've already claimed it */
static void lp_release_parport(struct lp_struct *this_lp)
{
	if (test_and_clear_bit(LP_PARPORT_CLAIMED, &this_lp->bits)) {
		parport_release (this_lp->dev);
	}
}



static int lp_preempt(void *handle)
{
	struct lp_struct *this_lp = (struct lp_struct *)handle;
	set_bit(LP_PREEMPT_REQUEST, &this_lp->bits);
	return (1);
}


/* 
 * 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)
{
	if (parport_negotiate (port, mode) != 0) {
		mode = IEEE1284_MODE_COMPAT;
		parport_negotiate (port, mode);
	}

	return (mode);
}

static int lp_reset(int minor)
{
	int retval;
	lp_claim_parport_or_block (&lp_table[minor]);
	w_ctr(minor, LP_PSELECP);
	udelay (LP_DELAY);
	w_ctr(minor, LP_PSELECP | LP_PINITP);
	retval = r_str(minor);
	lp_release_parport (&lp_table[minor]);
	return retval;
}

static void lp_error (int minor)
{
	DEFINE_WAIT(wait);
	int polling;

	if (LP_F(minor) & LP_ABORT)
		return;

	polling = lp_table[minor].dev->port->irq == PARPORT_IRQ_NONE;
	if (polling) lp_release_parport (&lp_table[minor]);
	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);
}

static int lp_check_status(int minor)
{
	int error = 0;
	unsigned int last = lp_table[minor].last_error;
	unsigned char status = r_str(minor);
	if ((status & LP_PERRORP) && !(LP_F(minor) & LP_CAREFUL))
		/* No error. */
		last = 0;
	else if ((status & LP_POUTPA)) {
		if (last != LP_POUTPA) {
			last = LP_POUTPA;
			printk(KERN_INFO "lp%d out of paper\n", minor);
		}
		error = -ENOSPC;
	} else if (!(status & LP_PSELECD)) {
		if (last != LP_PSELECD) {
			last = LP_PSELECD;
			printk(KERN_INFO "lp%d off-line\n", minor);
		}
		error = -EIO;
	} else if (!(status & LP_PERRORP)) {
		if (last != LP_PERRORP) {
			last = LP_PERRORP;
			printk(KERN_INFO "lp%d on fire\n", minor);
		}
		error = -EIO;
	} else {
		last = 0; /* Come here if LP_CAREFUL is set and no
                             errors are reported. */
	}

	lp_table[minor].last_error = last;

	if (last != 0)
		lp_error(minor);

	return error;
}

static int lp_wait_ready(int minor, int nonblock)
{
	int error = 0;

	/* If we're not in compatibility mode, we're ready now! */
	if (lp_table[minor].current_mode != IEEE1284_MODE_COMPAT) {
	  return (0);
	}

	do {
		error = lp_check_status (minor);
		if (error && (nonblock || (LP_F(minor) & LP_ABORT)))
			break;
		if (signal_pending (current)) {
			error = -EINTR;
			break;
		}
	} while (error);
	return error;
}

static ssize_t lp_write(struct file * file, const char __user * buf,
		        size_t count, loff_t *ppos)
{
	unsigned int minor = iminor(file->f_path.dentry->d_inode);
	struct parport *port = lp_table[minor].dev->port;
	char *kbuf = lp_table[minor].lp_buffer;
	ssize_t retv = 0;
	ssize_t written;
	size_t copy_size = count;
	int nonblock = ((file->f_flags & O_NONBLOCK) ||
			(LP_F(minor) & LP_ABORT));

#ifdef LP_STATS
	if (time_after(jiffies, lp_table[minor].lastcall + LP_TIME(minor)))
		lp_table[minor].runchars = 0;

	lp_table[minor].lastcall = jiffies;
#endif

	/* Need to copy the data from user-space. */
	if (copy_size > LP_BUFFER_SIZE)
		copy_size = LP_BUFFER_SIZE;

	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]);
	/* Go to the proper mode. */
	lp_table[minor].current_mode = lp_negotiate (port, 
						     lp_table[minor].best_mode);

	parport_set_timeout (lp_table[minor].dev,
			     (nonblock ? PARPORT_INACTIVITY_O_NONBLOCK
			      : lp_table[minor].timeout));

	if ((retv = lp_wait_ready (minor, nonblock)) == 0)
	do {
		/* Write the data. */
		written = parport_write (port, kbuf, copy_size);
		if (written > 0) {
			copy_size -= written;
			count -= written;
			buf  += written;
			retv += written;
		}

		if (signal_pending (current)) {
			if (retv == 0)
				retv = -EINTR;

			break;
		}

		if (copy_size > 0) {
			/* incomplete write -> check error ! */
			int error;

			parport_negotiate (lp_table[minor].dev->port, 
					   IEEE1284_MODE_COMPAT);
			lp_table[minor].current_mode = IEEE1284_MODE_COMPAT;

			error = lp_wait_ready (minor, nonblock);

			if (error) {
				if (retv == 0)
					retv = error;
				break;
			} else if (nonblock) {
				if (retv == 0)
					retv = -EAGAIN;
				break;
			}

			parport_yield_blocking (lp_table[minor].dev);
			lp_table[minor].current_mode 
			  = lp_negotiate (port, 
					  lp_table[minor].best_mode);

		} else if (need_resched())
			schedule ();

		if (count) {
			copy_size = count;
			if (copy_size > LP_BUFFER_SIZE)
				copy_size = LP_BUFFER_SIZE;

			if (copy_from_user(kbuf, buf, copy_size)) {
				if (retv == 0)
					retv = -EFAULT;
				break;
			}
		}	
	} while (count > 0);

	if (test_and_clear_bit(LP_PREEMPT_REQUEST, 
			       &lp_table[minor].bits)) {
		printk(KERN_INFO "lp%d releasing parport\n", minor);
		parport_negotiate (lp_table[minor].dev->port, 
				   IEEE1284_MODE_COMPAT);
		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 __user * buf,
		       size_t count, loff_t *ppos)
{
	DEFINE_WAIT(wait);
	unsigned int minor=iminor(file->f_path.dentry->d_inode);
	struct parport *port = lp_table[minor].dev->port;
	ssize_t retval = 0;
	char *kbuf = lp_table[minor].lp_buffer;
	int nonblock = ((file->f_flags & O_NONBLOCK) ||
			(LP_F(minor) & LP_ABORT));

	if (count > LP_BUFFER_SIZE)
		count = LP_BUFFER_SIZE;

	if (down_interruptible (&lp_table[minor].port_mutex))
		return -EINTR;

	lp_claim_parport_or_block (&lp_table[minor]);

	parport_set_timeout (lp_table[minor].dev,
			     (nonblock ? PARPORT_INACTIVITY_O_NONBLOCK
			      : lp_table[minor].timeout));

	parport_negotiate (lp_table[minor].dev->port, IEEE1284_MODE_COMPAT);
	if (parport_negotiate (lp_table[minor].dev->port,
			       IEEE1284_MODE_NIBBLE)) {
		retval = -EIO;
		goto out;
	}

	while (retval == 0) {
		retval = parport_read (port, kbuf, count);

		if (retval > 0)
			break;

		if (nonblock) {
			retval = -EAGAIN;
			break;
		}

		/* Wait for data. */

		if (lp_table[minor].dev->port->irq == PARPORT_IRQ_NONE) {
			parport_negotiate (lp_table[minor].dev->port,
					   IEEE1284_MODE_COMPAT);
			lp_error (minor);
			if (parport_negotiate (lp_table[minor].dev->port,
					       IEEE1284_MODE_NIBBLE)) {
				retval = -EIO;
				goto out;
			}
		} 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;
			break;
		}

		cond_resched ();
	}
	parport_negotiate (lp_table[minor].dev->port, IEEE1284_MODE_COMPAT);
 out:
	lp_release_parport (&lp_table[minor]);

	if (retval > 0 && copy_to_user (buf, kbuf, retval))
		retval = -EFAULT;

	up (&lp_table[minor].port_mutex);

	return retval;
}

#endif /* IEEE 1284 support */

static int lp_open(struct inode * inode, struct file * file)
{
	unsigned int minor = iminor(inode);

	if (minor >= LP_NO)
		return -ENXIO;
	if ((LP_F(minor) & LP_EXIST) == 0)
		return -ENXIO;
	if (test_and_set_bit(LP_BUSY_BIT_POS, &LP_F(minor)))
		return -EBUSY;

	/* If ABORTOPEN is set and the printer is offline or out of paper,
	   we may still want to open it to perform ioctl()s.  Therefore we
	   have commandeered O_NONBLOCK, even though it is being used in
	   a non-standard manner.  This is strictly a Linux hack, and
	   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_claim_parport_or_block (&lp_table[minor]);
		status = r_str(minor);
		lp_release_parport (&lp_table[minor]);
		if (status & LP_POUTPA) {
			printk(KERN_INFO "lp%d out of paper\n", minor);
			LP_F(minor) &= ~LP_BUSY;
			return -ENOSPC;
		} else if (!(status & LP_PSELECD)) {
			printk(KERN_INFO "lp%d off-line\n", minor);
			LP_F(minor) &= ~LP_BUSY;
			return -EIO;
		} else if (!(status & LP_PERRORP)) {
			printk(KERN_ERR "lp%d printer error\n", minor);
			LP_F(minor) &= ~LP_BUSY;
			return -EIO;
		}
	}
	lp_table[minor].lp_buffer = kmalloc(LP_BUFFER_SIZE, GFP_KERNEL);
	if (!lp_table[minor].lp_buffer) {
		LP_F(minor) &= ~LP_BUSY;
		return -ENOMEM;
	}
	/* Determine if the peripheral supports ECP mode */
	lp_claim_parport_or_block (&lp_table[minor]);
	if ( (lp_table[minor].dev->port->modes & PARPORT_MODE_ECP) &&
             !parport_negotiate (lp_table[minor].dev->port, 
                                 IEEE1284_MODE_ECP)) {
		printk (KERN_INFO "lp%d: ECP mode\n", minor);
		lp_table[minor].best_mode = IEEE1284_MODE_ECP;
	} else {
		lp_table[minor].best_mode = IEEE1284_MODE_COMPAT;
	}
	/* Leave peripheral in compatibility mode */
	parport_negotiate (lp_table[minor].dev->port, IEEE1284_MODE_COMPAT);
	lp_release_parport (&lp_table[minor]);
	lp_table[minor].current_mode = IEEE1284_MODE_COMPAT;
	return 0;
}

static int lp_release(struct inode * inode, struct file * file)
{
	unsigned int minor = iminor(inode);

	lp_claim_parport_or_block (&lp_table[minor]);
	parport_negotiate (lp_table[minor].dev->port, IEEE1284_MODE_COMPAT);
	lp_table[minor].current_mode = IEEE1284_MODE_COMPAT;
	lp_release_parport (&lp_table[minor]);
	kfree(lp_table[minor].lp_buffer);
	lp_table[minor].lp_buffer = NULL;
	LP_F(minor) &= ~LP_BUSY;
	return 0;
}

static int lp_ioctl(struct inode *inode, struct file *file,
		    unsigned int cmd, unsigned long arg)
{
	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);
#endif
	if (minor >= LP_NO)
		return -ENODEV;
	if ((LP_F(minor) & LP_EXIST) == 0)
		return -ENODEV;
	switch ( cmd ) {
		struct timeval par_timeout;
		long to_jiffies;

		case LPTIME:
			LP_TIME(minor) = arg * HZ/100;
			break;
		case LPCHAR:
			LP_CHAR(minor) = arg;
			break;
		case LPABORT:
			if (arg)
				LP_F(minor) |= LP_ABORT;
			else
				LP_F(minor) &= ~LP_ABORT;
			break;
		case LPABORTOPEN:
			if (arg)
				LP_F(minor) |= LP_ABORTOPEN;
			else
				LP_F(minor) &= ~LP_ABORTOPEN;
			break;
		case LPCAREFUL:
			if (arg)
				LP_F(minor) |= LP_CAREFUL;
			else
				LP_F(minor) &= ~LP_CAREFUL;
			break;
		case LPWAIT:
			LP_WAIT(minor) = arg;
			break;
		case LPSETIRQ: 
			return -EINVAL;
			break;
		case LPGETIRQ:
			if (copy_to_user(argp, &LP_IRQ(minor),
					sizeof(int)))
				return -EFAULT;
			break;
		case LPGETSTATUS:
			lp_claim_parport_or_block (&lp_table[minor]);
			status = r_str(minor);
			lp_release_parport (&lp_table[minor]);

			if (copy_to_user(argp, &status, sizeof(int)))
				return -EFAULT;
			break;
		case LPRESET:
			lp_reset(minor);
			break;
#ifdef LP_STATS
		case LPGETSTATS:
			if (copy_to_user(argp, &LP_STAT(minor),
					sizeof(struct lp_stats)))
				return -EFAULT;
			if (capable(CAP_SYS_ADMIN))
				memset(&LP_STAT(minor), 0,
						sizeof(struct lp_stats));
			break;
#endif
 		case LPGETFLAGS:
 			status = LP_F(minor);
			if (copy_to_user(argp, &status, sizeof(int)))
				return -EFAULT;
			break;

		case LPSETTIMEOUT:
			if (copy_from_user (&par_timeout, argp,
					    sizeof (struct timeval))) {
				return -EFAULT;
			}
			/* Convert to jiffies, place in lp_table */
			if ((par_timeout.tv_sec < 0) ||
			    (par_timeout.tv_usec < 0)) {
				return -EINVAL;
			}
			to_jiffies = DIV_ROUND_UP(par_timeout.tv_usec, 1000000/HZ);
			to_jiffies += par_timeout.tv_sec * (long) HZ;
			if (to_jiffies <= 0) {
				return -EINVAL;
			}
			lp_table[minor].timeout = to_jiffies;
			break;

		default:
			retval = -EINVAL;
	}
	return retval;
}

static const struct file_operations lp_fops = {
	.owner		= THIS_MODULE,
	.write		= lp_write,
	.ioctl		= lp_ioctl,
	.open		= lp_open,
	.release	= lp_release,
#ifdef CONFIG_PARPORT_1284
	.read		= lp_read,
#endif
};

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

#ifdef CONFIG_LP_CONSOLE

#define CONSOLE_LP 0

/* 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 1

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

static void lp_console_write (struct console *co, const char *s,
			      unsigned count)
{
	struct pardevice *dev = lp_table[CONSOLE_LP].dev;
	struct parport *port = dev->port;
	ssize_t written;

	if (parport_claim (dev))
		/* Nothing we can do. */
		return;

	parport_set_timeout (dev, 0);

	/* Go to compatibility mode. */
	parport_negotiate (port, IEEE1284_MODE_COMPAT);

	do {
		/* Write the data, converting LF->CRLF as we go. */
		ssize_t canwrite = count;
		char *lf = memchr (s, '\n', count);
		if (lf)
			canwrite = lf - s;

		if (canwrite > 0) {
			written = parport_write (port, s, canwrite);

			if (written <= 0)
				continue;

			s += written;
			count -= written;
			canwrite -= written;
		}

		if (lf && canwrite <= 0) {
			const char *crlf = "\r\n";
			int i = 2;

			/* Dodge the original '\n', and put '\r\n' instead. */
			s++;
			count--;
			do {
				written = parport_write (port, crlf, i);
				if (written > 0)
					i -= written, crlf += written;
			} while (i > 0 && (CONSOLE_LP_STRICT || written > 0));
		}
	} while (count > 0 && (CONSOLE_LP_STRICT || written > 0));

	parport_release (dev);
}

static struct console lpcons = {
	.name		= "lp",
	.write		= lp_console_write,
	.flags		= CON_PRINTBUFFER,
};

#endif /* console on line printer */

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

static int parport_nr[LP_NO] = { [0 ... LP_NO-1] = LP_PARPORT_UNSPEC };
static char *parport[LP_NO] = { NULL,  };
static int reset = 0;

module_param_array(parport, charp, NULL, 0);
module_param(reset, bool, 0);

#ifndef MODULE
static int __init lp_setup (char *str)
{
	static int parport_ptr; // initially zero
	int x;

	if (get_option (&str, &x)) {
		if (x == 0) {
			/* disable driver on "lp=" or "lp=0" */
			parport_nr[0] = LP_PARPORT_OFF;
		} else {
			printk(KERN_WARNING "warning: 'lp=0x%x' is deprecated, ignored\n", x);
			return 0;
		}
	} else if (!strncmp(str, "parport", 7)) {
		int n = simple_strtoul(str+7, NULL, 10);
		if (parport_ptr < LP_NO)
			parport_nr[parport_ptr++] = n;
		else
			printk(KERN_INFO "lp: too many ports, %s ignored.\n",
			       str);
	} else if (!strcmp(str, "auto")) {
		parport_nr[0] = LP_PARPORT_AUTO;
	} else if (!strcmp(str, "none")) {
		parport_nr[parport_ptr++] = LP_PARPORT_NONE;
	} else if (!strcmp(str, "reset")) {
		reset = 1;
	}
	return 1;
}
#endif

static int lp_register(int nr, struct parport *port)
{
	lp_table[nr].dev = parport_register_device(port, "lp", 
						   lp_preempt, NULL, NULL, 0,
						   (void *) &lp_table[nr]);
	if (lp_table[nr].dev == NULL)
		return 1;
	lp_table[nr].flags |= LP_EXIST;

	if (reset)
		lp_reset(nr);

	device_create(lp_class, port->dev, MKDEV(LP_MAJOR, nr), "lp%d", nr);

	printk(KERN_INFO "lp%d: using %s (%s).\n", nr, port->name, 
	       (port->irq == PARPORT_IRQ_NONE)?"polling":"interrupt-driven");

#ifdef CONFIG_LP_CONSOLE
	if (!nr) {
		if (port->modes & PARPORT_MODE_SAFEININT) {
			register_console (&lpcons);
			console_registered = port;
			printk (KERN_INFO "lp%d: console ready\n", CONSOLE_LP);
		} else
			printk (KERN_ERR "lp%d: cannot run console on %s\n",
				CONSOLE_LP, port->name);
	}
#endif

	return 0;
}

static void lp_attach (struct parport *port)
{
	unsigned int i;

	switch (parport_nr[0])
	{
	case LP_PARPORT_UNSPEC:
	case LP_PARPORT_AUTO:
		if (parport_nr[0] == LP_PARPORT_AUTO &&
		    port->probe_info[0].class != PARPORT_CLASS_PRINTER)
			return;
		if (lp_count == LP_NO) {
			printk(KERN_INFO "lp: ignoring parallel port (max. %d)\n",LP_NO);
			return;
		}
		if (!lp_register(lp_count, port))
			lp_count++;
		break;

	default:
		for (i = 0; i < LP_NO; i++) {
			if (port->number == parport_nr[i]) {
				if (!lp_register(i, port))
					lp_count++;
				break;
			}
		}
		break;
	}
}

static void lp_detach (struct parport *port)
{
	/* Write this some day. */
#ifdef CONFIG_LP_CONSOLE
	if (console_registered == port) {
		unregister_console (&lpcons);
		console_registered = NULL;
	}
#endif /* CONFIG_LP_CONSOLE */
}

static struct parport_driver lp_driver = {
	.name = "lp",
	.attach = lp_attach,
	.detach = lp_detach,
};

static int __init lp_init (void)
{
	int i, err = 0;

	if (parport_nr[0] == LP_PARPORT_OFF)
		return 0;

	for (i = 0; i < LP_NO; i++) {
		lp_table[i].dev = NULL;
		lp_table[i].flags = 0;
		lp_table[i].chars = LP_INIT_CHAR;
		lp_table[i].time = LP_INIT_TIME;
		lp_table[i].wait = LP_INIT_WAIT;
		lp_table[i].lp_buffer = NULL;
#ifdef LP_STATS
		lp_table[i].lastcall = 0;
		lp_table[i].runchars = 0;
		memset (&lp_table[i].stats, 0, sizeof (struct lp_stats));
#endif
		lp_table[i].last_error = 0;
		init_waitqueue_head (&lp_table[i].waitq);
		init_waitqueue_head (&lp_table[i].dataq);
		init_MUTEX (&lp_table[i].port_mutex);
		lp_table[i].timeout = 10 * HZ;
	}

	if (register_chrdev (LP_MAJOR, "lp", &lp_fops)) {
		printk (KERN_ERR "lp: unable to get major %d\n", LP_MAJOR);
		return -EIO;
	}

	lp_class = class_create(THIS_MODULE, "printer");
	if (IS_ERR(lp_class)) {
		err = PTR_ERR(lp_class);
		goto out_reg;
	}

	if (parport_register_driver (&lp_driver)) {
		printk (KERN_ERR "lp: unable to register with parport\n");
		err = -EIO;
		goto out_class;
	}

	if (!lp_count) {
		printk (KERN_INFO "lp: driver loaded but no devices found\n");
#ifndef CONFIG_PARPORT_1284
		if (parport_nr[0] == LP_PARPORT_AUTO)
			printk (KERN_INFO "lp: (is IEEE 1284 support enabled?)\n");
#endif
	}

	return 0;

out_class:
	class_destroy(lp_class);
out_reg:
	unregister_chrdev(LP_MAJOR, "lp");
	return err;
}

static int __init lp_init_module (void)
{
	if (parport[0]) {
		/* The user gave some parameters.  Let's see what they were.  */
		if (!strncmp(parport[0], "auto", 4))
			parport_nr[0] = LP_PARPORT_AUTO;
		else {
			int n;
			for (n = 0; n < LP_NO && parport[n]; n++) {
				if (!strncmp(parport[n], "none", 4))
					parport_nr[n] = LP_PARPORT_NONE;
				else {
					char *ep;
					unsigned long r = simple_strtoul(parport[n], &ep, 0);
					if (ep != parport[n]) 
						parport_nr[n] = r;
					else {
						printk(KERN_ERR "lp: bad port specifier `%s'\n", parport[n]);
						return -ENODEV;
					}
				}
			}
		}
	}

	return lp_init();
}

static void lp_cleanup_module (void)
{
	unsigned int offset;

	parport_unregister_driver (&lp_driver);

#ifdef CONFIG_LP_CONSOLE
	unregister_console (&lpcons);
#endif

	unregister_chrdev(LP_MAJOR, "lp");
	for (offset = 0; offset < LP_NO; offset++) {
		if (lp_table[offset].dev == NULL)
			continue;
		parport_unregister_device(lp_table[offset].dev);
		device_destroy(lp_class, MKDEV(LP_MAJOR, offset));
	}
	class_destroy(lp_class);
}

__setup("lp=", lp_setup);
module_init(lp_init_module);
module_exit(lp_cleanup_module);

MODULE_ALIAS_CHARDEV_MAJOR(LP_MAJOR);
MODULE_LICENSE("GPL");
_id_put(lun->id); kfree(lun); } kfree(sc); } /* * The "command allocator". */ static struct ub_scsi_cmd *ub_get_cmd(struct ub_lun *lun) { struct ub_scsi_cmd *ret; if (lun->cmda[0]) return NULL; ret = &lun->cmdv[0]; lun->cmda[0] = 1; return ret; } static void ub_put_cmd(struct ub_lun *lun, struct ub_scsi_cmd *cmd) { if (cmd != &lun->cmdv[0]) { printk(KERN_WARNING "%s: releasing a foreign cmd %p\n", lun->name, cmd); return; } if (!lun->cmda[0]) { printk(KERN_WARNING "%s: releasing a free cmd\n", lun->name); return; } lun->cmda[0] = 0; } /* * The command queue. */ static void ub_cmdq_add(struct ub_dev *sc, struct ub_scsi_cmd *cmd) { struct ub_scsi_cmd_queue *t = &sc->cmd_queue; if (t->qlen++ == 0) { t->head = cmd; t->tail = cmd; } else { t->tail->next = cmd; t->tail = cmd; } if (t->qlen > t->qmax) t->qmax = t->qlen; } static void ub_cmdq_insert(struct ub_dev *sc, struct ub_scsi_cmd *cmd) { struct ub_scsi_cmd_queue *t = &sc->cmd_queue; if (t->qlen++ == 0) { t->head = cmd; t->tail = cmd; } else { cmd->next = t->head; t->head = cmd; } if (t->qlen > t->qmax) t->qmax = t->qlen; } static struct ub_scsi_cmd *ub_cmdq_pop(struct ub_dev *sc) { struct ub_scsi_cmd_queue *t = &sc->cmd_queue; struct ub_scsi_cmd *cmd; if (t->qlen == 0) return NULL; if (--t->qlen == 0) t->tail = NULL; cmd = t->head; t->head = cmd->next; cmd->next = NULL; return cmd; } #define ub_cmdq_peek(sc) ((sc)->cmd_queue.head) /* * The request function is our main entry point */ static void ub_request_fn(request_queue_t *q) { struct ub_lun *lun = q->queuedata; struct request *rq; while ((rq = elv_next_request(q)) != NULL) { if (ub_request_fn_1(lun, rq) != 0) { blk_stop_queue(q); break; } } } static int ub_request_fn_1(struct ub_lun *lun, struct request *rq) { struct ub_dev *sc = lun->udev; struct ub_scsi_cmd *cmd; int rc; if (atomic_read(&sc->poison) || lun->changed) { blkdev_dequeue_request(rq); ub_end_rq(rq, 0); return 0; } if ((cmd = ub_get_cmd(lun)) == NULL) return -1; memset(cmd, 0, sizeof(struct ub_scsi_cmd)); blkdev_dequeue_request(rq); if (blk_pc_request(rq)) { rc = ub_cmd_build_packet(sc, lun, cmd, rq); } else { rc = ub_cmd_build_block(sc, lun, cmd, rq); } if (rc != 0) { ub_put_cmd(lun, cmd); ub_end_rq(rq, 0); return 0; } cmd->state = UB_CMDST_INIT; cmd->lun = lun; cmd->done = ub_rw_cmd_done; cmd->back = rq; cmd->tag = sc->tagcnt++; if (ub_submit_scsi(sc, cmd) != 0) { ub_put_cmd(lun, cmd); ub_end_rq(rq, 0); return 0; } return 0; } static int ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun, struct ub_scsi_cmd *cmd, struct request *rq) { int ub_dir; int n_elem; unsigned int block, nblks; if (rq_data_dir(rq) == WRITE) ub_dir = UB_DIR_WRITE; else ub_dir = UB_DIR_READ; cmd->dir = ub_dir; /* * get scatterlist from block layer */ n_elem = blk_rq_map_sg(lun->disk->queue, rq, &cmd->sgv[0]); if (n_elem <= 0) { printk(KERN_INFO "%s: failed request map (%d)\n", sc->name, n_elem); /* P3 */ return -1; /* request with no s/g entries? */ } if (n_elem > UB_MAX_REQ_SG) { /* Paranoia */ printk(KERN_WARNING "%s: request with %d segments\n", sc->name, n_elem); return -1; } cmd->nsg = n_elem; sc->sg_stat[n_elem < 5 ? n_elem : 5]++; /* * build the command * * The call to blk_queue_hardsect_size() guarantees that request * is aligned, but it is given in terms of 512 byte units, always. */ block = rq->sector >> lun->capacity.bshift; nblks = rq->nr_sectors >> lun->capacity.bshift; cmd->cdb[0] = (ub_dir == UB_DIR_READ)? READ_10: WRITE_10; /* 10-byte uses 4 bytes of LBA: 2147483648KB, 2097152MB, 2048GB */ cmd->cdb[2] = block >> 24; cmd->cdb[3] = block >> 16; cmd->cdb[4] = block >> 8; cmd->cdb[5] = block; cmd->cdb[7] = nblks >> 8; cmd->cdb[8] = nblks; cmd->cdb_len = 10; cmd->len = rq->nr_sectors * 512; return 0; } static int ub_cmd_build_packet(struct ub_dev *sc, struct ub_lun *lun, struct ub_scsi_cmd *cmd, struct request *rq) { int n_elem; if (rq->data_len == 0) { cmd->dir = UB_DIR_NONE; } else { if (rq_data_dir(rq) == WRITE) cmd->dir = UB_DIR_WRITE; else cmd->dir = UB_DIR_READ; } /* * get scatterlist from block layer */ n_elem = blk_rq_map_sg(lun->disk->queue, rq, &cmd->sgv[0]); if (n_elem < 0) { printk(KERN_INFO "%s: failed request map (%d)\n", sc->name, n_elem); /* P3 */ return -1; } if (n_elem > UB_MAX_REQ_SG) { /* Paranoia */ printk(KERN_WARNING "%s: request with %d segments\n", sc->name, n_elem); return -1; } cmd->nsg = n_elem; sc->sg_stat[n_elem < 5 ? n_elem : 5]++; memcpy(&cmd->cdb, rq->cmd, rq->cmd_len); cmd->cdb_len = rq->cmd_len; cmd->len = rq->data_len; return 0; } static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd) { struct request *rq = cmd->back; struct ub_lun *lun = cmd->lun; int uptodate; if (cmd->error == 0) { uptodate = 1; if (blk_pc_request(rq)) { if (cmd->act_len >= rq->data_len) rq->data_len = 0; else rq->data_len -= cmd->act_len; } } else { uptodate = 0; if (blk_pc_request(rq)) { /* UB_SENSE_SIZE is smaller than SCSI_SENSE_BUFFERSIZE */ memcpy(rq->sense, sc->top_sense, UB_SENSE_SIZE); rq->sense_len = UB_SENSE_SIZE; if (sc->top_sense[0] != 0) rq->errors = SAM_STAT_CHECK_CONDITION; else rq->errors = DID_ERROR << 16; } } ub_put_cmd(lun, cmd); ub_end_rq(rq, uptodate); blk_start_queue(lun->disk->queue); } static void ub_end_rq(struct request *rq, int uptodate) { int rc; rc = end_that_request_first(rq, uptodate, rq->hard_nr_sectors); // assert(rc == 0); end_that_request_last(rq); } /* * Submit a regular SCSI operation (not an auto-sense). * * The Iron Law of Good Submit Routine is: * Zero return - callback is done, Nonzero return - callback is not done. * No exceptions. * * Host is assumed locked. * * XXX We only support Bulk for the moment. */ static int ub_submit_scsi(struct ub_dev *sc, struct ub_scsi_cmd *cmd) { if (cmd->state != UB_CMDST_INIT || (cmd->dir != UB_DIR_NONE && cmd->len == 0)) { return -EINVAL; } ub_cmdq_add(sc, cmd); /* * We can call ub_scsi_dispatch(sc) right away here, but it's a little * safer to jump to a tasklet, in case upper layers do something silly. */ tasklet_schedule(&sc->tasklet); return 0; } /* * Submit the first URB for the queued command. * This function does not deal with queueing in any way. */ static int ub_scsi_cmd_start(struct ub_dev *sc, struct ub_scsi_cmd *cmd) { struct bulk_cb_wrap *bcb; int rc; bcb = &sc->work_bcb; /* * ``If the allocation length is eighteen or greater, and a device * server returns less than eithteen bytes of data, the application * client should assume that the bytes not transferred would have been * zeroes had the device server returned those bytes.'' * * We zero sense for all commands so that when a packet request * fails it does not return a stale sense. */ memset(&sc->top_sense, 0, UB_SENSE_SIZE); /* set up the command wrapper */ bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); bcb->Tag = cmd->tag; /* Endianness is not important */ bcb->DataTransferLength = cpu_to_le32(cmd->len); bcb->Flags = (cmd->dir == UB_DIR_READ) ? 0x80 : 0; bcb->Lun = (cmd->lun != NULL) ? cmd->lun->num : 0; bcb->Length = cmd->cdb_len; /* copy the command payload */ memcpy(bcb->CDB, cmd->cdb, UB_MAX_CDB_SIZE); UB_INIT_COMPLETION(sc->work_done); sc->last_pipe = sc->send_bulk_pipe; usb_fill_bulk_urb(&sc->work_urb, sc->dev, sc->send_bulk_pipe, bcb, US_BULK_CB_WRAP_LEN, ub_urb_complete, sc); /* Fill what we shouldn't be filling, because usb-storage did so. */ sc->work_urb.actual_length = 0; sc->work_urb.error_count = 0; sc->work_urb.status = 0; if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) { /* XXX Clear stalls */ ub_complete(&sc->work_done); return rc; } sc->work_timer.expires = jiffies + UB_URB_TIMEOUT; add_timer(&sc->work_timer); cmd->state = UB_CMDST_CMD; ub_cmdtr_state(sc, cmd); return 0; } /* * Timeout handler. */ static void ub_urb_timeout(unsigned long arg) { struct ub_dev *sc = (struct ub_dev *) arg; unsigned long flags; spin_lock_irqsave(&sc->lock, flags); usb_unlink_urb(&sc->work_urb); spin_unlock_irqrestore(&sc->lock, flags); } /* * Completion routine for the work URB. * * This can be called directly from usb_submit_urb (while we have * the sc->lock taken) and from an interrupt (while we do NOT have * the sc->lock taken). Therefore, bounce this off to a tasklet. */ static void ub_urb_complete(struct urb *urb, struct pt_regs *pt) { struct ub_dev *sc = urb->context; ub_complete(&sc->work_done); tasklet_schedule(&sc->tasklet); } static void ub_scsi_action(unsigned long _dev) { struct ub_dev *sc = (struct ub_dev *) _dev; unsigned long flags; spin_lock_irqsave(&sc->lock, flags); del_timer(&sc->work_timer); ub_scsi_dispatch(sc); spin_unlock_irqrestore(&sc->lock, flags); } static void ub_scsi_dispatch(struct ub_dev *sc) { struct ub_scsi_cmd *cmd; int rc; while ((cmd = ub_cmdq_peek(sc)) != NULL) { if (cmd->state == UB_CMDST_DONE) { ub_cmdq_pop(sc); (*cmd->done)(sc, cmd); } else if (cmd->state == UB_CMDST_INIT) { ub_cmdtr_new(sc, cmd); if ((rc = ub_scsi_cmd_start(sc, cmd)) == 0) break; cmd->error = rc; cmd->state = UB_CMDST_DONE; ub_cmdtr_state(sc, cmd); } else { if (!ub_is_completed(&sc->work_done)) break; ub_scsi_urb_compl(sc, cmd); } } } static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd) { struct urb *urb = &sc->work_urb; struct bulk_cs_wrap *bcs; int rc; if (atomic_read(&sc->poison)) { /* A little too simplistic, I feel... */ goto Bad_End; } if (cmd->state == UB_CMDST_CLEAR) { if (urb->status == -EPIPE) { /* * STALL while clearning STALL. * The control pipe clears itself - nothing to do. * XXX Might try to reset the device here and retry. */ printk(KERN_NOTICE "%s: stall on control pipe\n", sc->name); goto Bad_End; } /* * We ignore the result for the halt clear. */ /* reset the endpoint toggle */ usb_settoggle(sc->dev, usb_pipeendpoint(sc->last_pipe), usb_pipeout(sc->last_pipe), 0); ub_state_sense(sc, cmd); } else if (cmd->state == UB_CMDST_CLR2STS) { if (urb->status == -EPIPE) { /* * STALL while clearning STALL. * The control pipe clears itself - nothing to do. * XXX Might try to reset the device here and retry. */ printk(KERN_NOTICE "%s: stall on control pipe\n", sc->name); goto Bad_End; } /* * We ignore the result for the halt clear. */ /* reset the endpoint toggle */ usb_settoggle(sc->dev, usb_pipeendpoint(sc->last_pipe), usb_pipeout(sc->last_pipe), 0); ub_state_stat(sc, cmd); } else if (cmd->state == UB_CMDST_CLRRS) { if (urb->status == -EPIPE) { /* * STALL while clearning STALL. * The control pipe clears itself - nothing to do. * XXX Might try to reset the device here and retry. */ printk(KERN_NOTICE "%s: stall on control pipe\n", sc->name); goto Bad_End; } /* * We ignore the result for the halt clear. */ /* reset the endpoint toggle */ usb_settoggle(sc->dev, usb_pipeendpoint(sc->last_pipe), usb_pipeout(sc->last_pipe), 0); ub_state_stat_counted(sc, cmd); } else if (cmd->state == UB_CMDST_CMD) { if (urb->status == -EPIPE) { rc = ub_submit_clear_stall(sc, cmd, sc->last_pipe); if (rc != 0) { printk(KERN_NOTICE "%s: " "unable to submit clear (%d)\n", sc->name, rc); /* * This is typically ENOMEM or some other such shit. * Retrying is pointless. Just do Bad End on it... */ goto Bad_End; } cmd->state = UB_CMDST_CLEAR; ub_cmdtr_state(sc, cmd); return; } if (urb->status != 0) { goto Bad_End; } if (urb->actual_length != US_BULK_CB_WRAP_LEN) { /* XXX Must do reset here to unconfuse the device */ goto Bad_End; } if (cmd->dir == UB_DIR_NONE || cmd->nsg < 1) { ub_state_stat(sc, cmd); return; } // udelay(125); // usb-storage has this ub_data_start(sc, cmd); } else if (cmd->state == UB_CMDST_DATA) { if (urb->status == -EPIPE) { rc = ub_submit_clear_stall(sc, cmd, sc->last_pipe); if (rc != 0) { printk(KERN_NOTICE "%s: " "unable to submit clear (%d)\n", sc->name, rc); /* * This is typically ENOMEM or some other such shit. * Retrying is pointless. Just do Bad End on it... */ goto Bad_End; } cmd->state = UB_CMDST_CLR2STS; ub_cmdtr_state(sc, cmd); return; } if (urb->status == -EOVERFLOW) { /* * A babble? Failure, but we must transfer CSW now. * XXX This is going to end in perpetual babble. Reset. */ cmd->error = -EOVERFLOW; /* A cheap trick... */ ub_state_stat(sc, cmd); return; } if (urb->status != 0) goto Bad_End; cmd->act_len += urb->actual_length; ub_cmdtr_act_len(sc, cmd); if (++cmd->current_sg < cmd->nsg) { ub_data_start(sc, cmd); return; } ub_state_stat(sc, cmd); } else if (cmd->state == UB_CMDST_STAT) { if (urb->status == -EPIPE) { rc = ub_submit_clear_stall(sc, cmd, sc->last_pipe); if (rc != 0) { printk(KERN_NOTICE "%s: " "unable to submit clear (%d)\n", sc->name, rc); /* * This is typically ENOMEM or some other such shit. * Retrying is pointless. Just do Bad End on it... */ goto Bad_End; } /* * Having a stall when getting CSW is an error, so * make sure uppper levels are not oblivious to it. */ cmd->error = -EIO; /* A cheap trick... */ cmd->state = UB_CMDST_CLRRS; ub_cmdtr_state(sc, cmd); return; } if (urb->status == -EOVERFLOW) { /* * XXX We are screwed here. Retrying is pointless, * because the pipelined data will not get in until * we read with a big enough buffer. We must reset XXX. */ goto Bad_End; } if (urb->status != 0) goto Bad_End; if (urb->actual_length == 0) { ub_state_stat_counted(sc, cmd); return; } /* * Check the returned Bulk protocol status. * The status block has to be validated first. */ bcs = &sc->work_bcs; if (sc->signature == cpu_to_le32(0)) { /* * This is the first reply, so do not perform the check. * Instead, remember the signature the device uses * for future checks. But do not allow a nul. */ sc->signature = bcs->Signature; if (sc->signature == cpu_to_le32(0)) { ub_state_stat_counted(sc, cmd); return; } } else { if (bcs->Signature != sc->signature) { ub_state_stat_counted(sc, cmd); return; } } if (bcs->Tag != cmd->tag) { /* * This usually happens when we disagree with the * device's microcode about something. For instance, * a few of them throw this after timeouts. They buffer * commands and reply at commands we timed out before. * Without flushing these replies we loop forever. */ ub_state_stat_counted(sc, cmd); return; } rc = le32_to_cpu(bcs->Residue); if (rc != cmd->len - cmd->act_len) { /* * It is all right to transfer less, the caller has * to check. But it's not all right if the device * counts disagree with our counts. */ /* P3 */ printk("%s: resid %d len %d act %d\n", sc->name, rc, cmd->len, cmd->act_len); goto Bad_End; } switch (bcs->Status) { case US_BULK_STAT_OK: break; case US_BULK_STAT_FAIL: ub_state_sense(sc, cmd); return; case US_BULK_STAT_PHASE: /* XXX We must reset the transport here */ /* P3 */ printk("%s: status PHASE\n", sc->name); goto Bad_End; default: printk(KERN_INFO "%s: unknown CSW status 0x%x\n", sc->name, bcs->Status); goto Bad_End; } /* Not zeroing error to preserve a babble indicator */ if (cmd->error != 0) { ub_state_sense(sc, cmd); return; } cmd->state = UB_CMDST_DONE; ub_cmdtr_state(sc, cmd); ub_cmdq_pop(sc); (*cmd->done)(sc, cmd); } else if (cmd->state == UB_CMDST_SENSE) { ub_state_done(sc, cmd, -EIO); } else { printk(KERN_WARNING "%s: " "wrong command state %d\n", sc->name, cmd->state); goto Bad_End; } return; Bad_End: /* Little Excel is dead */ ub_state_done(sc, cmd, -EIO); } /* * Factorization helper for the command state machine: * Initiate a data segment transfer. */ static void ub_data_start(struct ub_dev *sc, struct ub_scsi_cmd *cmd) { struct scatterlist *sg = &cmd->sgv[cmd->current_sg]; int pipe; int rc; UB_INIT_COMPLETION(sc->work_done); if (cmd->dir == UB_DIR_READ) pipe = sc->recv_bulk_pipe; else pipe = sc->send_bulk_pipe; sc->last_pipe = pipe; usb_fill_bulk_urb(&sc->work_urb, sc->dev, pipe, page_address(sg->page) + sg->offset, sg->length, ub_urb_complete, sc); sc->work_urb.actual_length = 0; sc->work_urb.error_count = 0; sc->work_urb.status = 0; if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) { /* XXX Clear stalls */ ub_complete(&sc->work_done); ub_state_done(sc, cmd, rc); return; } sc->work_timer.expires = jiffies + UB_DATA_TIMEOUT; add_timer(&sc->work_timer); cmd->state = UB_CMDST_DATA; ub_cmdtr_state(sc, cmd); } /* * Factorization helper for the command state machine: * Finish the command. */ static void ub_state_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd, int rc) { cmd->error = rc; cmd->state = UB_CMDST_DONE; ub_cmdtr_state(sc, cmd); ub_cmdq_pop(sc); (*cmd->done)(sc, cmd); } /* * Factorization helper for the command state machine: * Submit a CSW read. */ static int __ub_state_stat(struct ub_dev *sc, struct ub_scsi_cmd *cmd) { int rc; UB_INIT_COMPLETION(sc->work_done); sc->last_pipe = sc->recv_bulk_pipe; usb_fill_bulk_urb(&sc->work_urb, sc->dev, sc->recv_bulk_pipe, &sc->work_bcs, US_BULK_CS_WRAP_LEN, ub_urb_complete, sc); sc->work_urb.actual_length = 0; sc->work_urb.error_count = 0; sc->work_urb.status = 0; if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) { /* XXX Clear stalls */ ub_complete(&sc->work_done); ub_state_done(sc, cmd, rc); return -1; } sc->work_timer.expires = jiffies + UB_STAT_TIMEOUT; add_timer(&sc->work_timer); return 0; } /* * Factorization helper for the command state machine: * Submit a CSW read and go to STAT state. */ static void ub_state_stat(struct ub_dev *sc, struct ub_scsi_cmd *cmd) { if (__ub_state_stat(sc, cmd) != 0) return; cmd->stat_count = 0; cmd->state = UB_CMDST_STAT; ub_cmdtr_state(sc, cmd); } /* * Factorization helper for the command state machine: * Submit a CSW read and go to STAT state with counter (along [C] path). */ static void ub_state_stat_counted(struct ub_dev *sc, struct ub_scsi_cmd *cmd) { if (++cmd->stat_count >= 4) { ub_state_sense(sc, cmd); return; } if (__ub_state_stat(sc, cmd) != 0) return; cmd->state = UB_CMDST_STAT; ub_cmdtr_state(sc, cmd); } /* * Factorization helper for the command state machine: * Submit a REQUEST SENSE and go to SENSE state. */ static void ub_state_sense(struct ub_dev *sc, struct ub_scsi_cmd *cmd) { struct ub_scsi_cmd *scmd; struct scatterlist *sg; int rc; if (cmd->cdb[0] == REQUEST_SENSE) { rc = -EPIPE; goto error; } scmd = &sc->top_rqs_cmd; memset(scmd, 0, sizeof(struct ub_scsi_cmd)); scmd->cdb[0] = REQUEST_SENSE; scmd->cdb[4] = UB_SENSE_SIZE; scmd->cdb_len = 6; scmd->dir = UB_DIR_READ; scmd->state = UB_CMDST_INIT; scmd->nsg = 1; sg = &scmd->sgv[0]; sg->page = virt_to_page(sc->top_sense); sg->offset = (unsigned int)sc->top_sense & (PAGE_SIZE-1); sg->length = UB_SENSE_SIZE; scmd->len = UB_SENSE_SIZE; scmd->lun = cmd->lun; scmd->done = ub_top_sense_done; scmd->back = cmd; scmd->tag = sc->tagcnt++; cmd->state = UB_CMDST_SENSE; ub_cmdtr_state(sc, cmd); ub_cmdq_insert(sc, scmd); return; error: ub_state_done(sc, cmd, rc); } /* * A helper for the command's state machine: * Submit a stall clear. */ static int ub_submit_clear_stall(struct ub_dev *sc, struct ub_scsi_cmd *cmd, int stalled_pipe) { int endp; struct usb_ctrlrequest *cr; int rc; endp = usb_pipeendpoint(stalled_pipe); if (usb_pipein (stalled_pipe)) endp |= USB_DIR_IN; cr = &sc->work_cr; cr->bRequestType = USB_RECIP_ENDPOINT; cr->bRequest = USB_REQ_CLEAR_FEATURE; cr->wValue = cpu_to_le16(USB_ENDPOINT_HALT); cr->wIndex = cpu_to_le16(endp); cr->wLength = cpu_to_le16(0); UB_INIT_COMPLETION(sc->work_done); usb_fill_control_urb(&sc->work_urb, sc->dev, sc->send_ctrl_pipe, (unsigned char*) cr, NULL, 0, ub_urb_complete, sc); sc->work_urb.actual_length = 0; sc->work_urb.error_count = 0; sc->work_urb.status = 0; if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) { ub_complete(&sc->work_done); return rc; } sc->work_timer.expires = jiffies + UB_CTRL_TIMEOUT; add_timer(&sc->work_timer); return 0; } /* */ static void ub_top_sense_done(struct ub_dev *sc, struct ub_scsi_cmd *scmd) { unsigned char *sense = sc->top_sense; struct ub_scsi_cmd *cmd; /* * Ignoring scmd->act_len, because the buffer was pre-zeroed. */ ub_cmdtr_sense(sc, scmd, sense); /* * Find the command which triggered the unit attention or a check, * save the sense into it, and advance its state machine. */ if ((cmd = ub_cmdq_peek(sc)) == NULL) { printk(KERN_WARNING "%s: sense done while idle\n", sc->name); return; } if (cmd != scmd->back) { printk(KERN_WARNING "%s: " "sense done for wrong command 0x%x\n", sc->name, cmd->tag); return; } if (cmd->state != UB_CMDST_SENSE) { printk(KERN_WARNING "%s: " "sense done with bad cmd state %d\n", sc->name, cmd->state); return; } cmd->key = sense[2] & 0x0F; cmd->asc = sense[12]; cmd->ascq = sense[13]; ub_scsi_urb_compl(sc, cmd); } /* * This is called from a process context. */ static void ub_revalidate(struct ub_dev *sc, struct ub_lun *lun) { lun->readonly = 0; /* XXX Query this from the device */ lun->capacity.nsec = 0; lun->capacity.bsize = 512; lun->capacity.bshift = 0; if (ub_sync_tur(sc, lun) != 0) return; /* Not ready */ lun->changed = 0; if (ub_sync_read_cap(sc, lun, &lun->capacity) != 0) { /* * The retry here means something is wrong, either with the * device, with the transport, or with our code. * We keep this because sd.c has retries for capacity. */ if (ub_sync_read_cap(sc, lun, &lun->capacity) != 0) { lun->capacity.nsec = 0; lun->capacity.bsize = 512; lun->capacity.bshift = 0; } } } /* * The open funcion. * This is mostly needed to keep refcounting, but also to support * media checks on removable media drives. */ static int ub_bd_open(struct inode *inode, struct file *filp) { struct gendisk *disk = inode->i_bdev->bd_disk; struct ub_lun *lun; struct ub_dev *sc; unsigned long flags; int rc; if ((lun = disk->private_data) == NULL) return -ENXIO; sc = lun->udev; spin_lock_irqsave(&ub_lock, flags); if (atomic_read(&sc->poison)) { spin_unlock_irqrestore(&ub_lock, flags); return -ENXIO; } sc->openc++; spin_unlock_irqrestore(&ub_lock, flags); /* * This is a workaround for a specific problem in our block layer. * In 2.6.9, register_disk duplicates the code from rescan_partitions. * However, if we do add_disk with a device which persistently reports * a changed media, add_disk calls register_disk, which does do_open, * which will call rescan_paritions for changed media. After that, * register_disk attempts to do it all again and causes double kobject * registration and a eventually an oops on module removal. * * The bottom line is, Al Viro says that we should not allow * bdev->bd_invalidated to be set when doing add_disk no matter what. */ if (lun->first_open) { lun->first_open = 0; if (lun->changed) { rc = -ENOMEDIUM; goto err_open; } } if (lun->removable || lun->readonly) check_disk_change(inode->i_bdev); /* * The sd.c considers ->media_present and ->changed not equivalent, * under some pretty murky conditions (a failure of READ CAPACITY). * We may need it one day. */ if (lun->removable && lun->changed && !(filp->f_flags & O_NDELAY)) { rc = -ENOMEDIUM; goto err_open; } if (lun->readonly && (filp->f_mode & FMODE_WRITE)) { rc = -EROFS; goto err_open; } return 0; err_open: ub_put(sc); return rc; } /* */ static int ub_bd_release(struct inode *inode, struct file *filp) { struct gendisk *disk = inode->i_bdev->bd_disk; struct ub_lun *lun = disk->private_data; struct ub_dev *sc = lun->udev; ub_put(sc); return 0; } /* * The ioctl interface. */ static int ub_bd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { struct gendisk *disk = inode->i_bdev->bd_disk; void __user *usermem = (void __user *) arg; return scsi_cmd_ioctl(filp, disk, cmd, usermem); } /* * This is called once a new disk was seen by the block layer or by ub_probe(). * The main onjective here is to discover the features of the media such as * the capacity, read-only status, etc. USB storage generally does not * need to be spun up, but if we needed it, this would be the place. * * This call can sleep. * * The return code is not used. */ static int ub_bd_revalidate(struct gendisk *disk) { struct ub_lun *lun = disk->private_data; ub_revalidate(lun->udev, lun); /* XXX Support sector size switching like in sr.c */ blk_queue_hardsect_size(disk->queue, lun->capacity.bsize); set_capacity(disk, lun->capacity.nsec); // set_disk_ro(sdkp->disk, lun->readonly); return 0; } /* * The check is called by the block layer to verify if the media * is still available. It is supposed to be harmless, lightweight and * non-intrusive in case the media was not changed. * * This call can sleep. * * The return code is bool! */ static int ub_bd_media_changed(struct gendisk *disk) { struct ub_lun *lun = disk->private_data; if (!lun->removable) return 0; /* * We clean checks always after every command, so this is not * as dangerous as it looks. If the TEST_UNIT_READY fails here, * the device is actually not ready with operator or software * intervention required. One dangerous item might be a drive which * spins itself down, and come the time to write dirty pages, this * will fail, then block layer discards the data. Since we never * spin drives up, such devices simply cannot be used with ub anyway. */ if (ub_sync_tur(lun->udev, lun) != 0) { lun->changed = 1; return 1; } return lun->changed; } static struct block_device_operations ub_bd_fops = { .owner = THIS_MODULE, .open = ub_bd_open, .release = ub_bd_release, .ioctl = ub_bd_ioctl, .media_changed = ub_bd_media_changed, .revalidate_disk = ub_bd_revalidate, }; /* * Common ->done routine for commands executed synchronously. */ static void ub_probe_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd) { struct completion *cop = cmd->back; complete(cop); } /* * Test if the device has a check condition on it, synchronously. */ static int ub_sync_tur(struct ub_dev *sc, struct ub_lun *lun) { struct ub_scsi_cmd *cmd; enum { ALLOC_SIZE = sizeof(struct ub_scsi_cmd) }; unsigned long flags; struct completion compl; int rc; init_completion(&compl); rc = -ENOMEM; if ((cmd = kmalloc(ALLOC_SIZE, GFP_KERNEL)) == NULL) goto err_alloc; memset(cmd, 0, ALLOC_SIZE); cmd->cdb[0] = TEST_UNIT_READY; cmd->cdb_len = 6; cmd->dir = UB_DIR_NONE; cmd->state = UB_CMDST_INIT; cmd->lun = lun; /* This may be NULL, but that's ok */ cmd->done = ub_probe_done; cmd->back = &compl; spin_lock_irqsave(&sc->lock, flags); cmd->tag = sc->tagcnt++; rc = ub_submit_scsi(sc, cmd); spin_unlock_irqrestore(&sc->lock, flags); if (rc != 0) { printk("ub: testing ready: submit error (%d)\n", rc); /* P3 */ goto err_submit; } wait_for_completion(&compl); rc = cmd->error; if (rc == -EIO && cmd->key != 0) /* Retries for benh's key */ rc = cmd->key; err_submit: kfree(cmd); err_alloc: return rc; } /* * Read the SCSI capacity synchronously (for probing). */ static int ub_sync_read_cap(struct ub_dev *sc, struct ub_lun *lun, struct ub_capacity *ret) { struct ub_scsi_cmd *cmd; struct scatterlist *sg; char *p; enum { ALLOC_SIZE = sizeof(struct ub_scsi_cmd) + 8 }; unsigned long flags; unsigned int bsize, shift; unsigned long nsec; struct completion compl; int rc; init_completion(&compl); rc = -ENOMEM; if ((cmd = kmalloc(ALLOC_SIZE, GFP_KERNEL)) == NULL) goto err_alloc; memset(cmd, 0, ALLOC_SIZE); p = (char *)cmd + sizeof(struct ub_scsi_cmd); cmd->cdb[0] = 0x25; cmd->cdb_len = 10; cmd->dir = UB_DIR_READ; cmd->state = UB_CMDST_INIT; cmd->nsg = 1; sg = &cmd->sgv[0]; sg->page = virt_to_page(p); sg->offset = (unsigned int)p & (PAGE_SIZE-1); sg->length = 8; cmd->len = 8; cmd->lun = lun; cmd->done = ub_probe_done; cmd->back = &compl; spin_lock_irqsave(&sc->lock, flags); cmd->tag = sc->tagcnt++; rc = ub_submit_scsi(sc, cmd); spin_unlock_irqrestore(&sc->lock, flags); if (rc != 0) { printk("ub: reading capacity: submit error (%d)\n", rc); /* P3 */ goto err_submit; } wait_for_completion(&compl); if (cmd->error != 0) { printk("ub: reading capacity: error %d\n", cmd->error); /* P3 */ rc = -EIO; goto err_read; } if (cmd->act_len != 8) { printk("ub: reading capacity: size %d\n", cmd->act_len); /* P3 */ rc = -EIO; goto err_read; } /* sd.c special-cases sector size of 0 to mean 512. Needed? Safe? */ nsec = be32_to_cpu(*(__be32 *)p) + 1; bsize = be32_to_cpu(*(__be32 *)(p + 4)); switch (bsize) { case 512: shift = 0; break; case 1024: shift = 1; break; case 2048: shift = 2; break; case 4096: shift = 3; break; default: printk("ub: Bad sector size %u\n", bsize); /* P3 */ rc = -EDOM; goto err_inv_bsize; } ret->bsize = bsize; ret->bshift = shift; ret->nsec = nsec << shift; rc = 0; err_inv_bsize: err_read: err_submit: kfree(cmd); err_alloc: return rc; } /* */ static void ub_probe_urb_complete(struct urb *urb, struct pt_regs *pt) { struct completion *cop = urb->context; complete(cop); } static void ub_probe_timeout(unsigned long arg) { struct completion *cop = (struct completion *) arg; complete(cop); } /* * Get number of LUNs by the way of Bulk GetMaxLUN command. */ static int ub_sync_getmaxlun(struct ub_dev *sc) { int ifnum = sc->intf->cur_altsetting->desc.bInterfaceNumber; unsigned char *p; enum { ALLOC_SIZE = 1 }; struct usb_ctrlrequest *cr; struct completion compl; struct timer_list timer; int nluns; int rc; init_completion(&compl); rc = -ENOMEM; if ((p = kmalloc(ALLOC_SIZE, GFP_KERNEL)) == NULL) goto err_alloc; *p = 55; cr = &sc->work_cr; cr->bRequestType = USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE; cr->bRequest = US_BULK_GET_MAX_LUN; cr->wValue = cpu_to_le16(0); cr->wIndex = cpu_to_le16(ifnum); cr->wLength = cpu_to_le16(1); usb_fill_control_urb(&sc->work_urb, sc->dev, sc->recv_ctrl_pipe, (unsigned char*) cr, p, 1, ub_probe_urb_complete, &compl); sc->work_urb.actual_length = 0; sc->work_urb.error_count = 0; sc->work_urb.status = 0; if ((rc = usb_submit_urb(&sc->work_urb, GFP_KERNEL)) != 0) { if (rc == -EPIPE) { printk("%s: Stall submitting GetMaxLUN, using 1 LUN\n", sc->name); /* P3 */ } else { printk(KERN_NOTICE "%s: Unable to submit GetMaxLUN (%d)\n", sc->name, rc); } goto err_submit; } init_timer(&timer); timer.function = ub_probe_timeout; timer.data = (unsigned long) &compl; timer.expires = jiffies + UB_CTRL_TIMEOUT; add_timer(&timer); wait_for_completion(&compl); del_timer_sync(&timer); usb_kill_urb(&sc->work_urb); if ((rc = sc->work_urb.status) < 0) { if (rc == -EPIPE) { printk("%s: Stall at GetMaxLUN, using 1 LUN\n", sc->name); /* P3 */ } else { printk(KERN_NOTICE "%s: Error at GetMaxLUN (%d)\n", sc->name, rc); } goto err_io; } if (sc->work_urb.actual_length != 1) { printk("%s: GetMaxLUN returned %d bytes\n", sc->name, sc->work_urb.actual_length); /* P3 */ nluns = 0; } else { if ((nluns = *p) == 55) { nluns = 0; } else { /* GetMaxLUN returns the maximum LUN number */ nluns += 1; if (nluns > UB_MAX_LUNS) nluns = UB_MAX_LUNS; } printk("%s: GetMaxLUN returned %d, using %d LUNs\n", sc->name, *p, nluns); /* P3 */ } kfree(p); return nluns; err_io: err_submit: kfree(p); err_alloc: return rc; } /* * Clear initial stalls. */ static int ub_probe_clear_stall(struct ub_dev *sc, int stalled_pipe) { int endp; struct usb_ctrlrequest *cr; struct completion compl; struct timer_list timer; int rc; init_completion(&compl); endp = usb_pipeendpoint(stalled_pipe); if (usb_pipein (stalled_pipe)) endp |= USB_DIR_IN; cr = &sc->work_cr; cr->bRequestType = USB_RECIP_ENDPOINT; cr->bRequest = USB_REQ_CLEAR_FEATURE; cr->wValue = cpu_to_le16(USB_ENDPOINT_HALT); cr->wIndex = cpu_to_le16(endp); cr->wLength = cpu_to_le16(0); usb_fill_control_urb(&sc->work_urb, sc->dev, sc->send_ctrl_pipe, (unsigned char*) cr, NULL, 0, ub_probe_urb_complete, &compl); sc->work_urb.actual_length = 0; sc->work_urb.error_count = 0; sc->work_urb.status = 0; if ((rc = usb_submit_urb(&sc->work_urb, GFP_KERNEL)) != 0) { printk(KERN_WARNING "%s: Unable to submit a probe clear (%d)\n", sc->name, rc); return rc; } init_timer(&timer); timer.function = ub_probe_timeout; timer.data = (unsigned long) &compl; timer.expires = jiffies + UB_CTRL_TIMEOUT; add_timer(&timer); wait_for_completion(&compl); del_timer_sync(&timer); usb_kill_urb(&sc->work_urb); /* reset the endpoint toggle */ usb_settoggle(sc->dev, endp, usb_pipeout(sc->last_pipe), 0); return 0; } /* * Get the pipe settings. */ static int ub_get_pipes(struct ub_dev *sc, struct usb_device *dev, struct usb_interface *intf) { struct usb_host_interface *altsetting = intf->cur_altsetting; struct usb_endpoint_descriptor *ep_in = NULL; struct usb_endpoint_descriptor *ep_out = NULL; struct usb_endpoint_descriptor *ep; int i; /* * Find the endpoints we need. * We are expecting a minimum of 2 endpoints - in and out (bulk). * We will ignore any others. */ for (i = 0; i < altsetting->desc.bNumEndpoints; i++) { ep = &altsetting->endpoint[i].desc; /* Is it a BULK endpoint? */ if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) { /* BULK in or out? */ if (ep->bEndpointAddress & USB_DIR_IN) ep_in = ep; else ep_out = ep; } } if (ep_in == NULL || ep_out == NULL) { printk(KERN_NOTICE "%s: failed endpoint check\n", sc->name); return -EIO; } /* Calculate and store the pipe values */ sc->send_ctrl_pipe = usb_sndctrlpipe(dev, 0); sc->recv_ctrl_pipe = usb_rcvctrlpipe(dev, 0); sc->send_bulk_pipe = usb_sndbulkpipe(dev, ep_out->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); sc->recv_bulk_pipe = usb_rcvbulkpipe(dev, ep_in->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); return 0; } /* * Probing is done in the process context, which allows us to cheat * and not to build a state machine for the discovery. */ static int ub_probe(struct usb_interface *intf, const struct usb_device_id *dev_id) { struct ub_dev *sc; int nluns; int rc; int i; rc = -ENOMEM; if ((sc = kmalloc(sizeof(struct ub_dev), GFP_KERNEL)) == NULL) goto err_core; memset(sc, 0, sizeof(struct ub_dev)); spin_lock_init(&sc->lock); INIT_LIST_HEAD(&sc->luns); usb_init_urb(&sc->work_urb); tasklet_init(&sc->tasklet, ub_scsi_action, (unsigned long)sc); atomic_set(&sc->poison, 0); init_timer(&sc->work_timer); sc->work_timer.data = (unsigned long) sc; sc->work_timer.function = ub_urb_timeout; ub_init_completion(&sc->work_done); sc->work_done.done = 1; /* A little yuk, but oh well... */ sc->dev = interface_to_usbdev(intf); sc->intf = intf; // sc->ifnum = intf->cur_altsetting->desc.bInterfaceNumber; usb_set_intfdata(intf, sc); usb_get_dev(sc->dev); // usb_get_intf(sc->intf); /* Do we need this? */ snprintf(sc->name, 12, DRV_NAME "(%d.%d)", sc->dev->bus->busnum, sc->dev->devnum); /* XXX Verify that we can handle the device (from descriptors) */ ub_get_pipes(sc, sc->dev, intf); if (device_create_file(&sc->intf->dev, &dev_attr_diag) != 0) goto err_diag; /* * At this point, all USB initialization is done, do upper layer. * We really hate halfway initialized structures, so from the * invariants perspective, this ub_dev is fully constructed at * this point. */ /* * This is needed to clear toggles. It is a problem only if we do * `rmmod ub && modprobe ub` without disconnects, but we like that. */ #if 0 /* iPod Mini fails if we do this (big white iPod works) */ ub_probe_clear_stall(sc, sc->recv_bulk_pipe); ub_probe_clear_stall(sc, sc->send_bulk_pipe); #endif /* * The way this is used by the startup code is a little specific. * A SCSI check causes a USB stall. Our common case code sees it * and clears the check, after which the device is ready for use. * But if a check was not present, any command other than * TEST_UNIT_READY ends with a lockup (including REQUEST_SENSE). * * If we neglect to clear the SCSI check, the first real command fails * (which is the capacity readout). We clear that and retry, but why * causing spurious retries for no reason. * * Revalidation may start with its own TEST_UNIT_READY, but that one * has to succeed, so we clear checks with an additional one here. * In any case it's not our business how revaliadation is implemented. */ for (i = 0; i < 3; i++) { /* Retries for benh's key */ if ((rc = ub_sync_tur(sc, NULL)) <= 0) break; if (rc != 0x6) break; msleep(10); } nluns = 1; for (i = 0; i < 3; i++) { if ((rc = ub_sync_getmaxlun(sc)) < 0) { /* * This segment is taken from usb-storage. They say * that ZIP-100 needs this, but my own ZIP-100 works * fine without this. * Still, it does not seem to hurt anything. */ if (rc == -EPIPE) { ub_probe_clear_stall(sc, sc->recv_bulk_pipe); ub_probe_clear_stall(sc, sc->send_bulk_pipe); } break; } if (rc != 0) { nluns = rc; break; } msleep(100); } for (i = 0; i < nluns; i++) { ub_probe_lun(sc, i); } return 0; /* device_remove_file(&sc->intf->dev, &dev_attr_diag); */ err_diag: usb_set_intfdata(intf, NULL); // usb_put_intf(sc->intf); usb_put_dev(sc->dev); kfree(sc); err_core: return rc; } static int ub_probe_lun(struct ub_dev *sc, int lnum) { struct ub_lun *lun; request_queue_t *q; struct gendisk *disk; int rc; rc = -ENOMEM; if ((lun = kmalloc(sizeof(struct ub_lun), GFP_KERNEL)) == NULL) goto err_alloc; memset(lun, 0, sizeof(struct ub_lun)); lun->num = lnum; rc = -ENOSR; if ((lun->id = ub_id_get()) == -1) goto err_id; lun->udev = sc; list_add(&lun->link, &sc->luns); snprintf(lun->name, 16, DRV_NAME "%c(%d.%d.%d)", lun->id + 'a', sc->dev->bus->busnum, sc->dev->devnum, lun->num); lun->removable = 1; /* XXX Query this from the device */ lun->changed = 1; /* ub_revalidate clears only */ lun->first_open = 1; ub_revalidate(sc, lun); rc = -ENOMEM; if ((disk = alloc_disk(UB_MINORS_PER_MAJOR)) == NULL) goto err_diskalloc; lun->disk = disk; sprintf(disk->disk_name, DRV_NAME "%c", lun->id + 'a'); sprintf(disk->devfs_name, DEVFS_NAME "/%c", lun->id + 'a'); disk->major = UB_MAJOR; disk->first_minor = lun->id * UB_MINORS_PER_MAJOR; disk->fops = &ub_bd_fops; disk->private_data = lun; disk->driverfs_dev = &sc->intf->dev; rc = -ENOMEM; if ((q = blk_init_queue(ub_request_fn, &sc->lock)) == NULL) goto err_blkqinit; disk->queue = q; blk_queue_bounce_limit(q, BLK_BOUNCE_HIGH); blk_queue_max_hw_segments(q, UB_MAX_REQ_SG); blk_queue_max_phys_segments(q, UB_MAX_REQ_SG); blk_queue_segment_boundary(q, 0xffffffff); /* Dubious. */ blk_queue_max_sectors(q, UB_MAX_SECTORS); blk_queue_hardsect_size(q, lun->capacity.bsize); q->queuedata = lun; set_capacity(disk, lun->capacity.nsec); if (lun->removable) disk->flags |= GENHD_FL_REMOVABLE; add_disk(disk); return 0; err_blkqinit: put_disk(disk); err_diskalloc: list_del(&lun->link); ub_id_put(lun->id); err_id: kfree(lun); err_alloc: return rc; } static void ub_disconnect(struct usb_interface *intf) { struct ub_dev *sc = usb_get_intfdata(intf); struct list_head *p; struct ub_lun *lun; struct gendisk *disk; unsigned long flags; /* * Prevent ub_bd_release from pulling the rug from under us. * XXX This is starting to look like a kref. * XXX Why not to take this ref at probe time? */ spin_lock_irqsave(&ub_lock, flags); sc->openc++; spin_unlock_irqrestore(&ub_lock, flags); /* * Fence stall clearnings, operations triggered by unlinkings and so on. * We do not attempt to unlink any URBs, because we do not trust the * unlink paths in HC drivers. Also, we get -84 upon disconnect anyway. */ atomic_set(&sc->poison, 1); /* * Blow away queued commands. * * Actually, this never works, because before we get here * the HCD terminates outstanding URB(s). It causes our * SCSI command queue to advance, commands fail to submit, * and the whole queue drains. So, we just use this code to * print warnings. */ spin_lock_irqsave(&sc->lock, flags); { struct ub_scsi_cmd *cmd; int cnt = 0; while ((cmd = ub_cmdq_pop(sc)) != NULL) { cmd->error = -ENOTCONN; cmd->state = UB_CMDST_DONE; ub_cmdtr_state(sc, cmd); ub_cmdq_pop(sc); (*cmd->done)(sc, cmd); cnt++; } if (cnt != 0) { printk(KERN_WARNING "%s: " "%d was queued after shutdown\n", sc->name, cnt); } } spin_unlock_irqrestore(&sc->lock, flags); /* * Unregister the upper layer. */ list_for_each (p, &sc->luns) { lun = list_entry(p, struct ub_lun, link); disk = lun->disk; if (disk->flags & GENHD_FL_UP) del_gendisk(disk); /* * I wish I could do: * set_bit(QUEUE_FLAG_DEAD, &q->queue_flags); * As it is, we rely on our internal poisoning and let * the upper levels to spin furiously failing all the I/O. */ } /* * Taking a lock on a structure which is about to be freed * is very nonsensual. Here it is largely a way to do a debug freeze, * and a bracket which shows where the nonsensual code segment ends. * * Testing for -EINPROGRESS is always a bug, so we are bending * the rules a little. */ spin_lock_irqsave(&sc->lock, flags); if (sc->work_urb.status == -EINPROGRESS) { /* janitors: ignore */ printk(KERN_WARNING "%s: " "URB is active after disconnect\n", sc->name); } spin_unlock_irqrestore(&sc->lock, flags); /* * There is virtually no chance that other CPU runs times so long * after ub_urb_complete should have called del_timer, but only if HCD * didn't forget to deliver a callback on unlink. */ del_timer_sync(&sc->work_timer); /* * At this point there must be no commands coming from anyone * and no URBs left in transit. */ device_remove_file(&sc->intf->dev, &dev_attr_diag); usb_set_intfdata(intf, NULL); // usb_put_intf(sc->intf); sc->intf = NULL; usb_put_dev(sc->dev); sc->dev = NULL; ub_put(sc); } static struct usb_driver ub_driver = { .owner = THIS_MODULE, .name = "ub", .probe = ub_probe, .disconnect = ub_disconnect, .id_table = ub_usb_ids, }; static int __init ub_init(void) { int rc; if ((rc = register_blkdev(UB_MAJOR, DRV_NAME)) != 0) goto err_regblkdev; devfs_mk_dir(DEVFS_NAME); if ((rc = usb_register(&ub_driver)) != 0) goto err_register; return 0; err_register: devfs_remove(DEVFS_NAME); unregister_blkdev(UB_MAJOR, DRV_NAME); err_regblkdev: return rc; } static void __exit ub_exit(void) { usb_deregister(&ub_driver); devfs_remove(DEVFS_NAME); unregister_blkdev(UB_MAJOR, DRV_NAME); } module_init(ub_init); module_exit(ub_exit); MODULE_LICENSE("GPL");