patch-2.3.14 linux/drivers/char/lp_m68k.c

Next file: linux/drivers/char/mem.c
Previous file: linux/drivers/char/lp_intern.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.13/linux/drivers/char/lp_m68k.c linux/drivers/char/lp_m68k.c
@@ -1,556 +0,0 @@
-/*
- * split in two parts for better support of different hardware
- * by Joerg Dorchain (dorchain@mpi-sb.mpg.de)
- *
- * Amiga printer device by Michael Rausch (linux@uni-koblenz.de);
- * Atari support added by Andreas Schwab (schwab@ls5.informatik.uni-dortmund.de);
- * based upon work from
- *
- * 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)
- */
-
-/* 01/17/95: Matthias Welwarsky (dg8y@rs11.hrz.th-darmstadt.de)
- * lp_write(): rewritten from scratch
- * lp_interrupt(): fixed cli()/sti()-bug
- * 
- * 95/05/28: Andreas Schwab (schwab@issan.informatik.uni-dortmund.de)
- * lp_write() fixed to make it work again.
- * 95/08/18: Andreas Schwab
- * lp_write_interrupt: fix race condition
- *
- *  * CAUTION, please do check! *    
- * 
- *  on 68000-based machines sti() must NEVER appear in interrupt driven
- *  code. The 68k-CPU has a priority-based interrupt scheme. while an interrupt
- *  with a certain priority is executed, all requests with lower or same
- *  priority get locked out. executing the sti()-macro allows ANY interrupt
- *  to be served. this really causes BIG trouble!
- *  to protect an interrupt driven routine against being interrupted 
- *  (if absolutely needed!) one should use save_flags();cli()/restore_flags()!
- *
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/major.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/init.h>
-#include <linux/kmod.h>
-
-#ifdef CONFIG_AMIGA
-#ifdef CONFIG_MULTIFACE_III_LP
-#include <linux/lp_mfc.h>
-#endif
-#endif
-
-#include <linux/lp_m68k.h>
-#include <linux/lp_intern.h>
-#include <linux/malloc.h>
-#include <linux/interrupt.h>
-
-#include <asm/irq.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-
-
-/*
- *  why bother around with the pio driver when the interrupt works;
- *  so, for "security" reasons only, it's configurable here.
- *  saves some bytes, at least ...
- */
-#define FORCE_POLLING	 0
-#define FORCE_INTERRUPT	 1
-/*
- *  PREFER_INTERRUPT doesn't make much sense on m68k.
- *  it is preserved here in case of joining with the i386 driver
- *
-#define PREFER_INTERRUPT 2
- */
-
-#define WHICH_DRIVER	FORCE_INTERRUPT
-
-struct lp_struct *lp_table[MAX_LP] = {NULL,};
-
-static int max_lp; /* the real number of devices */
-
-/* 
- * All my debugging code assumes that you debug with only one printer at
- * a time. RWWH
- */
-
-#define LP_DEBUG 
-#undef LP_DEBUG 
-
-
-#if WHICH_DRIVER != FORCE_INTERRUPT
-#ifdef LP_DEBUG
-static int lp_max_count = 1;
-#endif
-
-static int lp_char_polled(char lpchar, int dev)
-{
-	unsigned long count  = 0; 
-
-	do {
-		count ++;
-		if (current->need_resched)
-			schedule();
-	} while (lp_table[dev]->lp_is_busy(dev) && count < lp_table[dev]->chars);
-
-	if (count == lp_table[dev]->chars) {
-		return 0;
-		/* we timed out, and the character was /not/ printed */
-	}
-#ifdef LP_DEBUG
-	if (count > lp_max_count) {
-		printk("lp success after %d counts.\n",count);
-		lp_max_count = count;
-	}
-#endif
-	lp_table[dev]->lp_out(lpchar, dev);
-	return 1;
-}
-#endif
-
-
-#ifdef LP_DEBUG
-unsigned int lp_total_chars = 0;
-unsigned int lp_last_call = 0;
-#endif
-
-
-#if WHICH_DRIVER != FORCE_POLLING
-static __inline__ int lp_char_interrupt(char lpchar, int dev)
-{
-	if (!lp_table[dev]->lp_is_busy(dev)) {
-		lp_table[dev]->lp_out(lpchar,dev);
-		return 1;
-	}
-	return 0;
-}
-
-static int lp_error;
-
-void lp_interrupt(int dev)
-{
-    if (dev >= 0 && dev < MAX_LP && lp_table[dev]->do_print)
-    {
-	if (lp_table[dev]->copy_size)
-	{
-    		unsigned long flags;
-		save_flags(flags);
-		cli();
-		if (lp_char_interrupt(lp_table[dev]->lp_buffer[lp_table[dev]->bytes_written], dev)) {
-			--lp_table[dev]->copy_size;
-			++lp_table[dev]->bytes_written;
-			restore_flags(flags);
-		}
-		else
-		{
-			lp_table[dev]->do_print = 0;
-			restore_flags(flags);
-			lp_error = 1;
-			wake_up_interruptible(&lp_table[dev]->lp_wait_q);
-		}
-	}
-	else
-	{
-		lp_table[dev]->do_print = 0;
-		lp_error = 0;
-		wake_up_interruptible(&lp_table[dev]->lp_wait_q);
-	}
-
-    }
-}
-
-#if WHICH_DRIVER == FORCE_INTERRUPT
-static ssize_t lp_write(struct file *file, const char *buf,
-			size_t count, loff_t *ppos)
-#else
-static ssize_t lp_write_interrupt(struct file *file, const char *buf,
-				  size_t count, loff_t *ppos)
-#endif
-{
-  struct inode *inode = file->f_dentry->d_inode;
-  unsigned long total_bytes_written = 0;
-  unsigned int flags;
-  long timeout;
-  int rc;
-  int dev = MINOR(inode->i_rdev);
-
-  do {
-    lp_table[dev]->do_print = 0;		/* disable lp_interrupt()   */
-    lp_table[dev]->bytes_written = 0;	/* init buffer read-pointer */
-    lp_error = 0;
-    lp_table[dev]->copy_size = (count <= LP_BUFFER_SIZE ? count : LP_BUFFER_SIZE);
-    if (copy_from_user(lp_table[dev]->lp_buffer, buf,
-		       lp_table[dev]->copy_size))
-      return -EFAULT;
-    while (lp_table[dev]->copy_size) {
-      save_flags(flags);
-      cli();				/* no interrupts now */
-      lp_table[dev]->do_print = 1;	/* enable lp_interrupt() */
-      if (lp_char_interrupt(lp_table[dev]->lp_buffer[lp_table[dev]->bytes_written], dev)) {
-	++lp_table[dev]->bytes_written;
-	--lp_table[dev]->copy_size;
-	lp_error = 0;
-      } else {				/* something went wrong   */
-	lp_table[dev]->do_print = 0;	/* disable lp_interrupt() */
-	lp_error = 1;			/* printer caused error   */
-      }
-      if (lp_error) {
-
-	  /* something blocked printing, so we don't want to sleep too long,
-	     in case we have to rekick the interrupt */
-
-	  timeout = LP_TIMEOUT_POLLED;
-      } else {
-	  timeout = LP_TIMEOUT_INTERRUPT;
-      }
-  
-      interruptible_sleep_on_timeout(&lp_table[dev]->lp_wait_q, timeout);
-      restore_flags(flags);
-  
-      /* we're up again and running. we first disable lp_interrupt(), then
-	 check what happened meanwhile */
-
-      lp_table[dev]->do_print = 0;
-      rc = total_bytes_written + lp_table[dev]->bytes_written;
-
-      if (signal_pending(current)) {
-	if (rc == 0)
-	  rc = -EINTR;
-	return rc;
-      }
-      if (lp_error) {
-
-	/* an error has occurred, maybe in lp_interrupt().
-	   figure out the type of error, exit on request or if nothing has 
-	   been printed at all. */
-	
-	if (lp_table[dev]->lp_has_pout(dev)) {
-	  printk(KERN_NOTICE "lp%d: paper-out\n",dev);
-	  if (!rc) rc = -ENOSPC;
-	} else if (!lp_table[dev]->lp_is_online(dev)) {
-	  printk(KERN_NOTICE "lp%d: off-line\n",dev);
-	  if (!rc) rc = -EIO;
-	} else if (lp_table[dev]->lp_is_busy(dev)) {
-	  printk(KERN_NOTICE "lp%d: on fire\n",dev);
-	  if (!rc) rc = -EIO;
-	}
-	if (lp_table[dev]->flags & LP_ABORT)
-	  return rc;
-      }
-      /* check if our buffer was completely printed, if not, most likely
-	 an unsolved error blocks the printer. As we can`t do anything
-	 against, we start all over again. Else we set the read-pointer
-	 of the buffer and count the printed characters */
-      
-      if (!lp_table[dev]->copy_size) {
-	total_bytes_written += lp_table[dev]->bytes_written;
-	buf += lp_table[dev]->bytes_written;
-	count -= lp_table[dev]->bytes_written;
-      }
-    }
-  } while (count > 0);
-  return total_bytes_written;
-}
-#else
-void (*lp_interrupt)() = NULL;
-#endif
-
-#if WHICH_DRIVER != FORCE_INTERRUPT
-#if WHICH_DRIVER == FORCE_POLLING
-static ssize_t lp_write(struct file *file, const char *buf,
-			size_t count, loff_t *ppos)
-#else
-static ssize_t lp_write_polled(struct file *file, const char *buf,
-			size_t count, loff_t *ppos)
-#endif
-{
-	struct inode *inode = file->f_dentry->d_inode;
-	char *temp = buf;
-	int dev = MINOR(inode->i_rdev);
-
-#ifdef LP_DEBUG
-	if (time_after(jiffies, lp_last_call + lp_table[dev]->time)) {
-		lp_total_chars = 0;
-		lp_max_count = 1;
-	}
-	lp_last_call = jiffies;
-#endif
-
-	temp = buf;
-	while (count > 0) {
-		int c;
-		if (get_user(c, temp))
-			return -EFAULT;
-		if (lp_char_polled(c, dev)) {
-			/* only update counting vars if character was printed */
-			count--; temp++;
-#ifdef LP_DEBUG
-			lp_total_chars++;
-#endif
-		} else { /* if printer timed out */
-			unsigned long timeout = LP_TIMEOUT_POLLED;
-			int error = 0;
-			if (lp_table[dev]->lp_has_pout(dev)) {
-				printk(KERN_NOTICE "lp%d: out of paper\n",dev);
-				if (lp_table[dev]->flags & LP_ABORT)
-					error = -ENOSPC;
-			} else if (!lp_table[dev]->lp_is_online(dev)) {
-				printk(KERN_NOTICE "lp%d: off-line\n",dev);
-				if (lp_table[dev]->flags & LP_ABORT)
-					error = -EIO;
-			} else
-	                /* not offline or out of paper. on fire? */
-			if (lp_table[dev]->lp_is_busy(dev)) {
-				printk(KERN_NOTICE "lp%d: on fire\n",dev);
-				if (lp_table[dev]->flags & LP_ABORT)
-					error = -EIO;
-			}
-			else
-				timeout = lp_table[dev]->time;
-
-			/* check for signals before going to sleep */
-			if (error == 0 && signal_pending(current))
-				error = -EINTR;
-			if (error) {
-				if (temp != buf)
-					return temp-buf;
-				else
-					return error;
-			}
-
-#ifdef LP_DEBUG
-			printk("lp sleeping at %d characters for %d jiffies\n",
-				lp_total_chars, timeout);
-			lp_total_chars = 0;
-#endif
-			current->state = TASK_INTERRUPTIBLE;
-			schedule_timeout(timeout);
-		}
-	}
-	return temp - buf;
-}
-#endif
-
-unsigned int lp_irq = 0;
-
-#if WHICH_DRIVER == PREFER_INTERRUPT
-static ssize_t lp_write(struct file *file, const char *buf, size_t count,
-			loff_t *ppos)
-{
-	if (lp_irq)
-		return lp_write_interrupt(file, buf, count, ppos);
-	else
-		return lp_write_polled(file, buf, count, ppos);
-}
-#endif
-
-static long long lp_lseek(struct file * file, long long offset, int origin)
-{
-	return -ESPIPE;
-}
-
-static int lp_open(struct inode *inode, struct file *file)
-{
-	int dev = MINOR(inode->i_rdev);
-	int ret;
-
-	MOD_INC_USE_COUNT;
-
-	ret = -ENODEV;
-	if (dev >= MAX_LP)
-		goto out_err;
-
-	if (!lp_table[dev]) {
-		char modname[30];
-
-		sprintf(modname, "char-major-%d-%d", LP_MAJOR, dev);
-		request_module(modname);
-	}
-	if (!lp_table[dev])
-		goto out_err;
-	if (!(lp_table[dev]->flags & LP_EXIST))
-		goto out_err;
-	ret = -EBUSY;
-	if (lp_table[dev]->flags & LP_BUSY)
-		goto out_err;
-
-	lp_table[dev]->flags |= LP_BUSY;
-
-	ret = lp_table[dev]->lp_open(dev);
-	if (ret != 0) {
-		lp_table[dev]->flags &= ~LP_BUSY;
-		goto out_err;
-	}
-	return ret;
-
-out_err:
-	MOD_DEC_USE_COUNT;
-	return ret;
-}
-
-static int lp_release(struct inode *inode, struct file *file)
-{
-	int dev =MINOR(inode->i_rdev);
-
-	lp_table[dev]->flags &= ~LP_BUSY;
-	lp_table[dev]->lp_release(dev);
-	MOD_DEC_USE_COUNT;
-	return 0;
-}
-
-
-static int lp_ioctl(struct inode *inode, struct file *file,
-		    unsigned int cmd, unsigned long arg)
-{
-	unsigned int minor = MINOR(inode->i_rdev);
-	int retval = -ENODEV;
-
-#ifdef LP_DEBUG
-	printk("lp%d ioctl, cmd: 0x%x, arg: 0x%x\n", minor, cmd, arg);
-#endif
-	if (minor >= max_lp)
-		goto out;
-	if (!(lp_table[minor]->flags & LP_EXIST))
-		goto out;
-	retval = 0;
-	switch (cmd) {
-	case LPTIME:
-		lp_table[minor]->time = arg;
-		break;
-	case LPCHAR:
-		lp_table[minor]->chars = arg;
-		break;
-	case LPABORT:
-		if (arg)
-			lp_table[minor]->flags |= LP_ABORT;
-		else
-			lp_table[minor]->flags &= ~LP_ABORT;
-		break;
-	case LPWAIT:
-		lp_table[minor]->wait = arg;
-		break;
-	case LPSETIRQ:
-	case LPGETIRQ:
-	        retval = lp_irq;
-		break;
-	default:
-		retval = -EINVAL;
-		if (lp_table[minor]->lp_ioctl)
-			retval = lp_table[minor]->lp_ioctl(minor, cmd, arg);
-	}
-out:
-	return retval;
-}
-
-
-static struct file_operations lp_fops = {
-	lp_lseek,
-	NULL,		/* lp_read */
-	lp_write,
-	NULL,		/* lp_readdir */
-	NULL,		/* lp_poll */
-	lp_ioctl,
-	NULL,		/* lp_mmap */
-	lp_open,
-	NULL,		/* flush */
-	lp_release
-};
-
-EXPORT_SYMBOL(lp_table);
-EXPORT_SYMBOL(lp_irq);
-EXPORT_SYMBOL(lp_interrupt);
-EXPORT_SYMBOL(register_parallel);
-EXPORT_SYMBOL(unregister_parallel);
-
-int __init lp_m68k_init(void)
-{
-	extern char m68k_debug_device[];
-
-	if (!strcmp( m68k_debug_device, "par" ))
-		return -EBUSY;
-
-	if (register_chrdev(LP_MAJOR,"lp", &lp_fops)) {
-		printk(KERN_ERR "unable to get major %d for line printer\n", LP_MAJOR);
-		return -ENXIO;
-	}
-
-#if WHICH_DRIVER == FORCE_POLLING
-	lp_irq = 0;
-	printk(KERN_INFO "lp_init: lp using polling driver\n");
-#else
-
-	lp_irq = 1;
-	printk(KERN_INFO "lp_init: lp using interrupt driver\n");
-#endif
-
-#ifndef MODULE
-	lp_internal_init();
-#ifdef CONFIG_MULTIFACE_III_LP
-	lp_mfc_init();
-#endif
-#endif
-	return 0;
-}
-
-/*
- * Currently we do not accept any lp-parameters, but that may change.
- */
-void __init lp_setup(char *str, int *ints)
-{	
-}
-
-#ifdef MODULE
-int init_module(void)
-{
-	return lp_m68k_init();
-}
-
-void cleanup_module(void)
-{
-	unregister_chrdev(LP_MAJOR, "lp");
-}
-#endif
-
-/*
- * (un-)register for hardware drivers
- * tab is an inititalised lp_struct, dev the desired minor
- * if dev < 0, let the driver choose the first free minor
- * if successful return the minor, else -1
- */
-int register_parallel(struct lp_struct *tab, int dev)
-{
-if (dev < 0) {
-	dev = 0;
-	while ((dev < MAX_LP) && (lp_table[dev] != NULL))
-		dev++;
-}
-if (dev > MAX_LP)
-	return -1;
-if (lp_table[dev] != NULL)
-	return -1;
-lp_table[dev] = tab;
-printk(KERN_INFO "lp%d: %s at 0x%08lx\n", dev, tab->name, (long)tab->base);
-return dev;
-}
-
-#ifdef CONFIG_MODULES
-void unregister_parallel(int dev)
-{
-if ((dev < 0) || (dev > MAX_LP) || (lp_table[dev] == NULL))
-	printk(KERN_ERR "WARNING: unregister_parallel for non-existant device ignored!\n");
-else
-	lp_table[dev] = NULL;
-}
-#endif

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)