[PARPORT] [patch] lp needed testers [Re: lp fix against pre-2.1.127-7]


Andrea Arcangeli (andrea@e-mind.com)
Fri, 6 Nov 1998 22:02:50 +0100 (CET)


On Fri, 6 Nov 1998, Andrea Arcangeli wrote:

>to cut it out. In the weekend I'll try to submit to Linus a patch that fix
>lp without cutting out the trustirq thing.

Here the patch that includes the trustirq hack and should fix everything.

If new code fails to print somewhere you can try:

- change the `#if 1 /* needed at least for Epson....' in lp_char() to #if 0.

If lp still will not work you can try to change:

        if (LP_NO_ERROR(status))
        {
                ...
        }

to

        if (1)
        {

        }

always in lp_char().

I don' t think that this second case can help. If it will make differences
I' ll reinsert the LP_CAREFUL flag and I' ll take care of it in
LP_NO_ERROR...

Many thanks for the past and future ;-) reports.

This patch is against clean pre-2.1.127-7.

Index: linux/include/linux/lp.h
diff -u linux/include/linux/lp.h:1.1.1.4 linux/include/linux/lp.h:1.1.1.1.12.6
--- linux/include/linux/lp.h:1.1.1.4 Wed Nov 4 13:09:24 1998
+++ linux/include/linux/lp.h Fri Nov 6 02:02:54 1998
@@ -25,9 +25,7 @@
 #define LP_NOPA 0x0010
 #define LP_ERR 0x0020
 #define LP_ABORT 0x0040
-#if 0
 #define LP_CAREFUL 0x0080
-#endif
 #define LP_ABORTOPEN 0x0100
 
 /* timeout for each character. This is relative to bus cycles -- it
@@ -67,11 +65,9 @@
                             or 0 for polling (no IRQ) */
 #define LPGETIRQ 0x0606 /* get the current IRQ number */
 #define LPWAIT 0x0608 /* corresponds to LP_INIT_WAIT */
-#ifdef LP_NEED_CAREFUL
 #define LPCAREFUL 0x0609 /* call with TRUE arg to require out-of-paper, off-
                             line, and error indicators good on all writes,
                             FALSE to ignore them. Default is ignore. */
-#endif
 #define LPABORTOPEN 0x060a /* call with TRUE arg to abort open() on error,
                             FALSE to ignore error. Default is ignore. */
 #define LPGETSTATUS 0x060b /* return LP_S(minor) */
Index: linux/drivers/char/lp.c
diff -u linux/drivers/char/lp.c:1.1.1.4 linux/drivers/char/lp.c:1.1.1.1.12.16
--- linux/drivers/char/lp.c:1.1.1.4 Wed Nov 4 13:06:06 1998
+++ linux/drivers/char/lp.c Fri Nov 6 21:52:18 1998
@@ -22,7 +22,9 @@
  * 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.
- * I also fixed the irq on the rising edge of the strobe problem.
+ * 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
  */
 
@@ -55,6 +57,18 @@
  * # insmod lp.o reset=1
  */
 
+/*
+ * CUSTOM OPTIMIZATIONS
+ *
+ * If your printer is fast enough (most of hardware will work fine)
+ *
+ * tunelp /dev/lp? -w 0
+ *
+ * If printing with irq I suggest also:
+ *
+ * tunelp /dev/lp? -c 1
+ */
+
 /* COMPATIBILITY WITH OLD KERNELS
  *
  * Under Linux 2.0 and previous versions, lp devices were bound to ports at
@@ -84,13 +98,12 @@
  *
  * 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.
  *
- * I also understood that on such printer we are just allowed to send
- * new characters after the interrupt even if the BUSY line is still active.
- *
  * 15 Oct 1998, Andrea Arcangeli
  */
 
@@ -124,24 +137,17 @@
 #ifdef LP_STATS
                            0, 0, {0},
 #endif
- NULL, 0, 0, 0}
+ NULL, 0, 0, 0, 0}
 };
-
-/*
- * Test if printer is ready.
- */
-#define LP_READY(status) \
- ((status) & (LP_PBUSY|LP_POUTPA|LP_PSELECD|LP_PERRORP)) == \
- (LP_PBUSY|LP_PSELECD|LP_PERRORP)
-
-/*
- * Test if the printer has error conditions.
- */
-#define LP_NO_ERROR(status) \
- ((status) & (LP_POUTPA|LP_PSELECD|LP_PERRORP)) == \
- (LP_PSELECD|LP_PERRORP)
 
-#define LP_NO_ACKING(status) ((status) & LP_PACK)
+/* Test if printer is ready */
+#define LP_READY(status) ((status) & LP_PBUSY)
+/* Test if the printer is not acking the strobe */
+#define LP_NO_ACKING(status) ((status) & LP_PACK)
+/* Test if the printer has error conditions */
+#define LP_NO_ERROR(status) \
+ (((status) & (LP_POUTPA|LP_PSELECD|LP_PERRORP)) == \
+ (LP_PSELECD|LP_PERRORP))
 
 #undef LP_DEBUG
 #undef LP_READ_DEBUG
@@ -189,7 +195,7 @@
                 schedule_timeout(timeout);
                 lp_parport_claim(minor);
         } else
- schedule();
+ schedule_timeout(timeout);
 }
 
 static int lp_reset(int minor)
@@ -204,10 +210,7 @@
         return retval;
 }
 
-static inline void lp_wait(int minor)
-{
- udelay(LP_WAIT(minor));
-}
+#define lp_wait(minor) udelay(LP_WAIT(minor))
 
 static inline int lp_char(char lpchar, int minor)
 {
@@ -222,25 +225,30 @@
         for (;;)
         {
                 unsigned char status;
- lp_yield(minor);
 
- status = r_str(minor);
                 /*
- * On Epson Stylus Color we must continue even if LP_READY()
- * is false to be efficient. This way is backwards
- * compatible with old not-buggy printers. -arca
+ * Give a chance to other pardevice to run in the meantime.
                  */
- if (LP_NO_ERROR(status) &&
- ((lp_table[minor].irq_detected && LP_NO_ACKING(status)) ||
- LP_READY(status)))
- break;
+ lp_yield(minor);
+
+ status = r_str(minor);
+ if (LP_NO_ERROR(status))
+ {
+ if (LP_READY(status))
+ break;
+#if 1 /* needed at least for Epson Stylus Color printers */
+ /*
+ * This is a crude hack that should to be known
+ * at least by Epson guys. -arca
+ */
+ if (!LP_POLLED(minor) && LP_NO_ACKING(status) &&
+ lp_table[minor].irq_detected)
+ break;
+#endif
+ }
                 /*
- * To have a chance to sleep on the interrupt we should break
- * the polling loop ASAP. Unfortunately there seems to be
- * some hardware that underperform so we leave this
- * configurable at runtime. So when printing with irqs
- * `tunelp /dev/lp0 -c 1' is a must to take the full
- * advantage of the irq. -arca
+ * NOTE: if you run with irqs you _must_ use
+ * `tunelp /dev/lp? -c 1' to be rasonable efficient!
                  */
                 if (++count == LP_CHAR(minor))
                         return 0;
@@ -253,19 +261,6 @@
         stats->chars++;
 #endif
 
- /*
- * Epson Stylus Color generate the IRQ on the rising edge of
- * strobe so clean the irq's information before playing with
- * the strobe. -arca
- */
- lp_table[minor].irq_detected = 0;
- lp_table[minor].irq_missed = 0;
- /*
- * Be sure that the CPU doesn' t reorder instruction. I am not sure
- * if it' s needed also before an outb(). If not tell me ;-). -arca
- */
- mb();
-
         /* must wait before taking strobe high, and after taking strobe
            low, according spec. Some printers need it, others don't. */
         lp_wait(minor);
@@ -277,11 +272,32 @@
                 lp_wait(minor);
                 w_ctr(minor, LP_PSELECP | LP_PINITP);
         } else {
+ /*
+ * Epson Stylus Color generate the IRQ on the rising edge of
+ * strobe so clean the irq's information before playing with
+ * the strobe. -arca
+ */
+ lp_table[minor].irq_detected = 0;
+ lp_table[minor].irq_missed = 0;
+ /*
+ * Be sure that the CPU doesn' t reorder instructions.
+ * I am not sure if it' s needed also before an outb().
+ * If not tell me ;-). -arca
+ */
+ mb();
                 w_ctr(minor, LP_PSELECP | LP_PINITP | LP_PSTROBE | LP_PINTEN);
                 lp_wait(minor);
                 w_ctr(minor, LP_PSELECP | LP_PINITP | LP_PINTEN);
         }
 
+ /*
+ * Give to the printer a chance to put BUSY low. Really we could
+ * remove this because we could _guess_ that we are slower to reach
+ * again lp_char() than the printer to put BUSY low, but I' d like
+ * to remove this variable when I read bug reports ;-). -arca
+ */
+ lp_wait(minor);
+
 #ifdef LP_STATS
         /* update waittime statistics */
         if (count > stats->maxwait) {
@@ -371,7 +387,6 @@
         lp_table[minor].last_error = 0;
         lp_table[minor].irq_detected = 0;
         lp_table[minor].irq_missed = 1;
- LP_POLLED(minor) = lp_table[minor].dev->port->irq == PARPORT_IRQ_NONE;
 
         if (LP_POLLED(minor))
                 w_ctr(minor, LP_PSELECP | LP_PINITP);
@@ -480,6 +495,12 @@
           */
          lp_parport_claim (minor);
 
+ /*
+ * We can set the polled flag here since once we have parport claimed
+ * the parport irq remains locked. -arca
+ */
+ LP_POLLED(minor) = lp_table[minor].dev->port->irq == PARPORT_IRQ_NONE;
+
         retv = lp_write_buf(minor, buf, count);
 
          lp_parport_release (minor);
@@ -694,6 +715,14 @@
                         else
                                 LP_F(minor) &= ~LP_ABORTOPEN;
                         break;
+#ifdef OBSOLETED
+ case LPCAREFUL:
+ if (arg)
+ LP_F(minor) |= LP_CAREFUL;
+ else
+ LP_F(minor) &= ~LP_CAREFUL;
+ break;
+#endif
                 case LPWAIT:
                         LP_WAIT(minor) = arg;
                         break;
@@ -736,7 +765,6 @@
         }
         return retval;
 }
-
 
 static struct file_operations lp_fops = {
         lp_lseek,

-- To unsubscribe, send mail to: linux-parport-request@torque.net --
-- with the single word "unsubscribe" in the body of the message. --



This archive was generated by hypermail 2.0b3 on Wed 30 Dec 1998 - 10:18:45 EST