Subject: Re: interrupting parallel port lossage
To: Bruce Evans <bde@zeta.org.au>
From: Bakul Shah <bakul@netcom.com>
List: port-i386
Date: 03/23/1995 01:06:57
> Some printers raise *ACK before lowering BUSY. This isn't related to
> the current problem, but causes very slow printing if the interrupt
> handler gets control while BUSY is still low.
Then they are violating the Centronics interface. After a
long search I found at least a timing diagram in the good
old Art of Electronics, Second ed. (page 731) That might
be of some help:
A B C D
________ _ _ _ _ _
DATA ------------<________>------S S---------<_ _ _ _ _
_______________ _________ ____________
*STROBE \__/ S S \_
__________ _________
BUSY _________________/ S S \________
____________________________ ____ ____
*ACK S S \_______/
E F G
A->B == DATA out to *STROBE low time = 0.5 us min.
B->C == *STROBE low to *STROBE high time = 0.5 us min.
C->D == *STROBE high to DATA tri-state == 0.5 us min.
E->F == *ACK low to BUSY low == 7 us min.
F->G == BUSY low to *ACK high = 5 us min.
Notice that BUSY must be _low_ before outputting the DATA
and must go =high= some time soon after *STROBE goes low.
So one more thing the driver can do is check that BUSY is
really low *before* outputting and right after setting
*STROBE low, check BUSY goes high (via a timed loop;
breakout after 5 us or BUSY hight).
To guard against errant printers, lptintr() should check
BUSY is low in a timed loop (breakout 5 us or BUSY low).
Normal printers won't cause any slow down.
I also noticed that the printer is never reset. Normally I
woulnd't want my printer reset on every close but it'll be
nice to allow resetting under user control. Shouldn't there
be an ioctl or something for that?
> everything, but there are still problems, perhaps because some printers
> don't meet the 500 nsec spec.
The 500ns spec is on the PC side: the data should be stable
for that period on both sides of the *STROBE pulse. I'd be
very surprised if any printer controller does worse than
that. Also note that data is latched so the C->D timing is
always met (and may only matter for bidir. PIOs).
Another thing. The initial check in lptintr does check
status twice in quick succession:
> if (NOT_READY() && NOT_READY_ERR())
> return 0;
This should probably along the lines of:
for (i=5; ;i--) {
status = inb(..) ...
if (status-has-error)
print-error and return 0;
if (i == 0)
return 0;
wait-for-a-microsecond
}
Parallel port stuff is usually so solid under MSDOS that
everyone takes it for granted.
-- Bakul