[comp.os.minix] patch for kernel/printer.c

hall@cod.NOSC.MIL (Robert R. Hall) (08/20/89)

With  printer driver version 1.3 and the protected mode version, after
printing 2 pages of a 3 page file the error message 'Printer error'
would apprear on the screen and the print job would terminate.
The following patch is what I found neccessary to correct this problem.
The cdiff is relative to Bruce Evan's protected mode version but patch
will also apply it to version 1.3d with offset warning messages thought.

Robert R. Hall
hall@nosc.mil
--------------------- kernel/printer.c.cdif ----------------------
echo x - printer.c.cdif
sed '/^X/s///' > printer.c.cdif << '/'
X*** /usr/m286pm/kernel/printer.c	Tue Jul 18 21:13:42 1989
X--- printer.c	Sat Aug 19 19:33:55 1989
X***************
X*** 32,44 ****
X  
X  #define NORMAL_STATUS   0x90	/* printer gives this status when idle */
X  #define BUSY_STATUS     0x10	/* printer gives this status when busy */
X  #define ASSERT_STROBE   0x1D	/* strobe a character to the interface */
X  #define NEGATE_STROBE   0x1C	/* enable interrupt on interface */
X  #define SELECT          0x0C	/* select printer bit */
X  #define INIT_PRINTER    0x08	/* init printer bits */
X  #define NO_PAPER        0x20	/* status bit saying that paper is up */
X  #define OFF_LINE        0x10	/* status bit saying that printer not online*/
X- #define PR_ERROR        0x08	/* something is wrong with the printer */
X  #define PR_COLOR_BASE  0x378	/* printer port when color display used */
X  #define PR_MONO_BASE   0x3BC	/* printer port when mono display used */
X  #define CANCELED        -999	/* indicates that command has been killed */
X--- 32,44 ----
X  
X  #define NORMAL_STATUS   0x90	/* printer gives this status when idle */
X  #define BUSY_STATUS     0x10	/* printer gives this status when busy */
X+ #define READY_BIT       0x80    /* printer ready status bit */
X  #define ASSERT_STROBE   0x1D	/* strobe a character to the interface */
X  #define NEGATE_STROBE   0x1C	/* enable interrupt on interface */
X  #define SELECT          0x0C	/* select printer bit */
X  #define INIT_PRINTER    0x08	/* init printer bits */
X  #define NO_PAPER        0x20	/* status bit saying that paper is up */
X  #define OFF_LINE        0x10	/* status bit saying that printer not online*/
X  #define PR_COLOR_BASE  0x378	/* printer port when color display used */
X  #define PR_MONO_BASE   0x3BC	/* printer port when mono display used */
X  #define CANCELED        -999	/* indicates that command has been killed */
X***************
X*** 208,215 ****
X  /* The printer is not ready.  Display a message on the console telling why. */
X  
X    if (status & NO_PAPER) printf("Printer is out of paper\n");
X!   if ((status & OFF_LINE) == 0) printf("Printer is not on line\n");
X!   if ((status & PR_ERROR) == 0) printf("Printer error\n");
X  }
X  
X  
X--- 208,215 ----
X  /* The printer is not ready.  Display a message on the console telling why. */
X  
X    if (status & NO_PAPER) printf("Printer is out of paper\n");
X!   else if ((status & OFF_LINE) == 0) printf("Printer is not on line\n");
X!   else printf("Printer status error is: 0x%x\n", status);
X  }
X  
X  
X***************
X*** 246,254 ****
X  
X    if (pr_busy == FALSE) return;	/* spurious 8259A interrupt */
X  
X!   while (pcount > 0) {
X!   	port_in(port_base + 1, &value);	/* get printer status */
X!   	if ((value&STATUS_MASK) == NORMAL_STATUS) {
X  		/* Everything is all right.  Output another character. */
X  		ch = get_phys_byte(offset);	/* fetch char from user buf */
X  		port_out(port_base, ch);	/* output character */
X--- 246,258 ----
X  
X    if (pr_busy == FALSE) return;	/* spurious 8259A interrupt */
X  
X!   if (pcount > 0) {
X!   	for (i = 0; i < DELAY_COUNT; i++) {
X!   	   port_in(port_base + 1, &value);	/* get printer status */
X!   	   if ((value&READY_BIT) == READY_BIT) break;
X!   	}
X!   	if ((value&STATUS_MASK) == BUSY_STATUS) return;	/* false alarm? */
X!   	else if ((value&STATUS_MASK) == NORMAL_STATUS) {
X  		/* Everything is all right.  Output another character. */
X  		ch = get_phys_byte(offset);	/* fetch char from user buf */
X  		port_out(port_base, ch);	/* output character */
X***************
X*** 257,267 ****
X  		offset++;
X  		pcount--;
X  		cum_count++;	/* count characters output */
X! 		for (i = 0; i < DELAY_COUNT; i++) ;	/* delay loop */
X! 	} else if ((value&STATUS_MASK) == BUSY_STATUS) {
X! 		 	return;		/* printer is busy; wait for interrupt*/
X! 	} else {
X! 		 	break;		/* err: send message to printer task */
X  	}
X    }
X    
X--- 261,267 ----
X  		offset++;
X  		pcount--;
X  		cum_count++;	/* count characters output */
X! 		return;         /* wait for next interrupt */
X  	}
X    }
X    
/

evans@ditsyda.oz (Bruce Evans) (09/07/89)

In article <1614@cod.NOSC.MIL> hall@cod.NOSC.MIL (Robert R. Hall) writes:
>With  printer driver version 1.3 and the protected mode version, after
>printing 2 pages of a 3 page file the error message 'Printer error'
>would apprear on the screen and the print job would terminate.
>The following patch is what I found neccessary to correct this problem.

I want to sort this out for 1.4b. Mail to Robert has never worked.

I don't see how the 1.3 version can give the error, although I don't
like its approach. Robert changed the error printing routine to print
the exact error status; what was it exactly? The error must be caused
by an invalid combination of the bits in 0xB0. 0x10 means printer-on-line;
it should stay on constantly during printing as far as I know. 0x20 means
not-out-of-paper; it should stay on. 0x80 means printer-ready; it should
oscillate as characters are strobed out, and the software takes account
of this. I suspect 0x10 is dropping out. ROM Bios's usually don't bother
looking at 0x10 or 0x20. This should be equivalent since the external
printer hardware is supposed to drop 0x80 when it is not ready, for
whatever reason. Maybe there is a problem with the cable.

Why does Robert's version work better? It tests the ready status in a
better way, avoiding a fixed delay. This should only affect performance.
More subtly, the possible delay becomes much longer, because more is done
in the delay loop. Finally, the on-line and paper-ready bits are ignored
while the ready bit is low. This probably allows some bad transient to be
ignored. It is a reasonable device interface to not guarantee anything
about the other bits while the "ready" bit is false; however, for the
printer I think the on-line bit has this duty.

Robert's version has a new error. When pcount goes from 1 to 0, the
interrupt handler is exited and a further interrupt is relied on to send
the output-done message. If this interrupt is lost, the message will
never be sent, because pr_restart() doesn't do anything when pcount is 0.
To fix it, I just restored the ugly busy-wait while loop from 1.3.

These problems would be more conveniently solved by ignoring most errors,
like serial drivers do. When the printer is not on line, or runs out of
paper on page 500 of 1000 (make that page 1 of 2 for me :-)), I don't
want printing to be stopped by a minor error.
-- 
Bruce Evans		evans@ditsyda.oz.au