*** linux/drivers/char/lp.c.old	Tue Mar 22 00:26:07 1994
--- linux/drivers/char/lp.c	Fri Jul 15 11:21:57 1994
***************
*** 24,29 ****
--- 24,81 ----
  
  #undef LP_DEBUG
  
+ /*
+  * LP OFFLINE SUPPORT (for the polling and interrupt lp drivers)
+  * Patched by Yan ZHOU (yanz@staff.cs.su.oz.au), July 1994
+  *
+  * Why this patch?  Because :-)
+  * "if a printer (/dev/lp?) is off-line, then it acts like /dev/null"
+  *
+  * Guidelines to support off-line (powered-off) printers:
+  *
+  *  o lp_open()  fails if the printer is off-line.
+  *    `lpd' relies on this to check if a printer is available.
+  *
+  *  o lp_write() fails if the printer is off-line (even if LP_ABORT is off).
+  *    Off-line error is treated differently from other kinds of errors,
+  *    (such as `out of paper'), as most print jobs cannot continue and 
+  *    have to abort.
+  *    `lpd' restarts a print job from beginning if the job is aborted.
+  *
+  *  o Data transfer only happens when 
+  *      THERE IS NO ERROR and THE PRINTER IS ONLINE and THE PRINTER IS NOT BUSY
+  *    The ACKLNG signal (LP_PACK) is no longer checked, for 2 reasons:
+  *      1. ACKLNG is some kind of `pulse', while BUSY is a `state'
+  *      2. ACKLNG is unstable during printer power on/off.
+  *    When a printer is off-line, data transfer (thus) will never happen,
+  *    so no data will be lost.
+  */
+ 
+ /* Enable LP OFFLINE SUPPORT	*/
+ #define LP_OFFLINE_SUPPORT
+ #ifdef LP_OFFLINE_SUPPORT
+ 
+ /*
+  * Allow first n lp_open() to be successful,
+  * even if the printer is off-line.  So that
+  * `tunelp(8)' can have a chance to do its
+  * job during startup (in /etc/rc.*), even if
+  * the printers are off-line.
+  * 
+  * (n = LP_NO seems to be a good value.)
+  */
+ #define LP_OFFLINE_SUPPORT_OPEN_N_ALLOW		LP_NO
+ 
+ /*
+  * Some macros for printer status testing
+  */
+ #define LP_SERROR(x) (!((x) & LP_PERRORP))		/* Error	*/
+ #define LP_SBUSY(x) (!((x) & LP_PBUSY))			/* Busy		*/
+ #define LP_SOFFLINE(x) (!((x) & LP_PSELECD))		/* Off-line	*/
+ #define LP_SREADY(x)  (!LP_SERROR((x)) && !LP_SOFFLINE((x)) && !LP_SBUSY((x)))
+ 
+ #endif	/* LP_OFFLINE_SUPPORT	*/
+ 
  static int lp_reset(int minor)
  {
  	int testvalue;
***************
*** 53,59 ****
--- 105,115 ----
  		count ++;
  		if(need_resched)
  			schedule();
+ #ifdef LP_OFFLINE_SUPPORT
+ 	} while(!LP_SREADY(status) && count < LP_CHAR(minor));
+ #else
  	} while(!(status & LP_PBUSY) && count < LP_CHAR(minor));
+ #endif
  
  	if (count == LP_CHAR(minor)) {
  		return 0;
***************
*** 84,93 ****
  	unsigned char status;
  
  
  	if (!((status = LP_S(minor)) & LP_PACK) || (status & LP_PBUSY)
  	|| !((status = LP_S(minor)) & LP_PACK) || (status & LP_PBUSY)
  	|| !((status = LP_S(minor)) & LP_PACK) || (status & LP_PBUSY)) {
! 
  		outb_p(lpchar, LP_B(minor));
  		/* must wait before taking strobe high, and after taking strobe
  		   low, according spec.  Some printers need it, others don't. */
--- 140,155 ----
  	unsigned char status;
  
  
+ #ifdef LP_OFFLINE_SUPPORT
+ 	status = LP_S(minor);
+ 	if (!LP_SREADY(status)) status = LP_S(minor);
+ 	if (!LP_SREADY(status)) status = LP_S(minor);
+ 	if ( LP_SREADY(status)) {
+ #else
  	if (!((status = LP_S(minor)) & LP_PACK) || (status & LP_PBUSY)
  	|| !((status = LP_S(minor)) & LP_PACK) || (status & LP_PBUSY)
  	|| !((status = LP_S(minor)) & LP_PACK) || (status & LP_PBUSY)) {
! #endif
  		outb_p(lpchar, LP_B(minor));
  		/* must wait before taking strobe high, and after taking strobe
  		   low, according spec.  Some printers need it, others don't. */
***************
*** 140,146 ****
--- 202,213 ----
  				--copy_size;
  				++bytes_written;
  			} else {
+ #ifdef LP_OFFLINE_SUPPORT
+                                 status = LP_S(minor);
+                                 if (LP_SERROR(status)) {
+ #else
  				if (!((status = LP_S(minor)) & LP_PERRORP)) {
+ #endif
  					int rc = total_bytes_written + bytes_written;
  
  					if ((status & LP_POUTPA)) {
***************
*** 156,168 ****
--- 223,243 ----
  						if (!rc)
  							rc = -EIO;
  					}
+ 
  					if(LP_F(minor) & LP_ABORT)
  						return rc;
+ #ifdef LP_OFFLINE_SUPPORT
+                                         if (LP_SOFFLINE(status)) return rc;
+ #endif
  				}
  				cli();
  				outb_p((LP_PSELECP|LP_PINITP|LP_PINTEN), (LP_C(minor)));
  				status = LP_S(minor);
+ #ifdef LP_OFFLINE_SUPPORT
+                                 if (LP_SREADY(status)) {
+ #else
  				if (!(status & LP_PACK) || (status & LP_PBUSY)) {
+ #endif
  					outb_p((LP_PSELECP|LP_PINITP), (LP_C(minor)));
  					sti();
  					continue;
***************
*** 227,233 ****
--- 302,310 ----
  			} else
  			if (!(status & LP_PSELECD)) {
  				printk("lp%d off-line\n", minor);
+ #ifndef LP_OFFLINE_SUPPORT
  				if(LP_F(minor) & LP_ABORT)
+ #endif
  					return temp-buf?temp-buf:-EIO;
  				current->state = TASK_INTERRUPTIBLE;
  				current->timeout = jiffies + LP_TIMEOUT_POLLED;
***************
*** 291,296 ****
--- 368,388 ----
  	if (LP_F(minor) & LP_BUSY)
  		return -EBUSY;
  
+ #ifdef LP_OFFLINE_SUPPORT
+         /*
+          * Off-line ?
+          *   But the first several open requests are allowed anyway,
+          *   so that `tunelp' can have a chance to run, even if the
+          *   printers are off-line.
+          */
+         {
+           static int openCounter = 0;
+           if (openCounter >= LP_OFFLINE_SUPPORT_OPEN_N_ALLOW) {
+             if (LP_SOFFLINE(LP_S(minor))) return -EIO;
+           } else openCounter ++;
+         }
+ #endif
+ 
  	if ((irq = LP_IRQ(minor))) {
  		lp_table[minor].lp_buffer = (char *) kmalloc(LP_BUFFER_SIZE, GFP_KERNEL);
  		if (!lp_table[minor].lp_buffer)
***************
*** 458,462 ****
--- 550,559 ----
  	}
  	if (count == 0)
  		printk("lp_init: no lp devices found\n");
+ 
+ #ifdef LP_OFFLINE_SUPPORT
+ 	printk("lp driver: off-line support enabled.\n");
+ #endif
+ 
  	return kmem_start;
  }
