From: belal@sco.COM (Bela Lubkin)
Newsgroups: biz.sco.general
Subject: more than you wanted to know about the parallel driver
Date: 16 Oct 92 10:36:31 GMT
Organization: [resent by] The SCOGEN gateway and Propagation Society
Resent-From: mmdf@xenitec.on.ca
Submit-To: scogen@xenitec.on.ca
Cc: Anthony P Lawrence <apl@world.std.com>
Precedence: bulk

Tony Lawrence wrote:

> Anyway, the engineer wanted to know if the slow printing would follow
> the port or follow the printer: he said he had different suggestions 
> depending on the answer.
> 
> That sounded reasonable to me (though I do wish there was some way to
> convince these people that they are dealing with an intelligent
> human being: just give me both fixes and I'll take it from there...
> plus I learn something for the future, but no, they won't do that).

Here at SCO Support, I do a lot of "2nd tier".  That's an assigned shift
where I sit at a station and help analysts who are directly on the phone
with customers.  They come to me with a description of a problem that's
stumped them and I try to help.  A very common exchange is that the
analyst describes the problem and I ask a couple of questions like
"well, does the slowness follow the printer or the port".  Analyst goes
"hmmm" and then asks "Well, suppose I know the answer to that.  Tell me
what it would mean if it followed the printer, or if it followed the
port."

And I have to say, "I don't know".  The question wasn't a clear-cut
"Answer this and that will select which of these two answers I will give
you" question, that was a *probe*.  The answer to the probe lets the
analyst concentrate on a smaller domain of possibilities.  Perhaps, when
the domain has been suitably restricted, the answer will just jump out
at you.  But even if there's only one branching left before that point,
the answer *won't* leap out until the branch has been passed.

The "suggestions" the analyst was going to give you probably weren't
going to be "answers", but further probes to continue narrowing down the
domain.  It would have been very difficult to build further layers of
probes without knowing which branch had already been taken.

Does that make sense?

> So I switched the cables so that the slow lp1 printer was now on lp0 and
> vice versa.
> 
> Guess what?  Both printers now print quickly.  Figure that one out.
> 
> I'll take the gift as is, but if anyone has a clue as to why, I'd 
> love to know.

I have a bunch of clues, but it would take some more probes to fully
explain the situation.

First, you'll just have to take my word for it, but if a parallel
printer is printing slowly it's because interrupts aren't getting
through.  One reason for that, which I hammered on in the previous
message, is if the kernel and the hardware disagree as to what interrupt
that port is using.  Another reason would be if there was something
wrong with the hardware.

The simplest thing that could be wrong with the hardware would be that
the pin on which the interrupt arrives (something like ACK or STROBE
from the printer) was disconnected.  What happens if you now switch the
printers back the way they were?  If they're still fast, maybe the slow
printer's cable was weakly seated and the interrupt pin wasn't
connecting reliably.

Another hardware possibility is that the interrupt signal from the
printer is weak.  Perhaps one of the two parallel cards has slightly
more sensitive circuitry on that pin and picks it up anyway, while the
other one doesn't.

The theory that I still favor is that one of the cards isn't
interrupting, either because it's misconfigured or because the kernel's
confused about what interrupt it's on.  You might then ask why the
"other" printer is fast on that port.  Good question.

SCO's parallel driver automatically falls back to polling if interrupts
don't seem to be doing the job.  The polling algorithm is rather
complex.  Every timer tick, if the port is in polling mode, the driver
goes into a nested loop.  In the outer loop, it limits the number of
characters to be sent during this timer tick (under 3.2v4, the limit is
150; can't say for other versions).  Inside that loop, the driver
attempts to send a single character.  This is another loop: it loops a
constant number of times, checking whether the printer is ready yet.  If
it isn't ready by the end of that spinloop, it drops out of the entire
poll routine.  If it *is* ready, the character is sent and we go back to
the outer loop.  There is also an innermost loop which sets the amount
of time between the "are you ready?" checks, but by default that loop is
disabled.

Now, let's examine that middle loop, the one that's waiting for the
printer to go ready.  What it's really waiting for is for the printer to
strobe some line, acknowledging that it is ready for the next character.
How fast that happens depends entirely on the printer: you might imagine
that a 3rd-generation PostScript printer with a RISC processor (and, not
unlikely, a separate dedicated Z80 chip for the parallel interface) will

There's a threshold.  If the printer always responds faster than the
completion of that middle loop, it will be fed 150 characters every
timer tick (100 times/sec., under 3.2v4, for a total of 15K
characters/sec.).  If it always responds slower than the middle loop, it
will only be fed *1* character per tick, 100/sec. under 3.2v4.  For most
printers today, 100 chars/sec will seem slow.  But wait!  There's more.
Actually, under 3.2v4.[01], the parallel driver has a bug that causes it
only to service the poll routine once a second.  That means that the
actual character rates will be 150/sec. for a fast-response printer, or
1/sec. for a slow one!  You might also see a printer in between those
speeds, but only if its character response time is variable and crosses
the threshold speed.

What does all this mean?  Don't use polling.  Get your parallel port to
interrupt.  Try the "other" interrupt from what it's currently
configured for.  If two ports are on interrupt 7, switch one to 5 (and
notify the driver) -- otherwise the faster printer is liable to steal
all the interrupts from the slower -- since AT bus interrupts are
edge-triggered, the driver can't tell whether one or two ports have
interrupted, and does the wrong thing.

Almost all of the loop behaviors described above are patchable.  I am
NOT going to give out the patch information today.  Don't ask.  I don't
have it and don't intend to spend 2 days collecting it for 9 different
compiles of the driver.  I do hope, in the future, that all of the
tunable parameters will be *tunable* parameters, not things that you can
patch if you can find the constant embedded in the right instruction in
the right routine.

>Bela<
Newsgroups: biz.sco.general