[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 from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/