[comp.unix.i386] Fast parallel driver for Unix/Xenix AT?

chip@ateng.com (Chip Salzenberg) (11/23/89)

SCO Xenix, like all AT Unixen, is shipped with a driver for IBM parallel
ports.  Unfortunately, at least with SCO Xenix, the parallel driver uses the
internal kernel data structures (clists) intended for use with serial lines.
The use of clists lowers the speed of parallel to something far slower than
the hardware could support otherwise.

We need a fast parallel driver.  Perhaps some one of you, out there, has
also seen the need for a simple, fast parallel driver for IBM parallel
ports.  If you have such a beast, or know where I can get one, please let me
know.  It's a crying shame to have slow printer output when it's the driver
causing the slowdown.

Please E-Mail replies (and/or code :-)).  I'll summarize to the net.
-- 
You may redistribute this article only to those who may freely do likewise.
Chip Salzenberg at A T Engineering;  <chip@ateng.com> or <uunet!ateng!chip>
    "Did I ever tell you the Jim Gladding story about the binoculars?"

emmo@moncam.co.uk (Dave Emmerson) (11/23/89)

In article <256ADBB5.19093@ateng.com>, chip@ateng.com (Chip Salzenberg) writes:
> [stuff omitted]
> know.  It's a crying shame to have slow printer output when it's the driver
> causing the slowdown.

Forget it, the printer itself is usually the bottleneck, there's no point in
worrying about getting > 1k char/sec to a printer which can only output at
80 cps and only has an 4k buffer.
Use a large-ish printer spooler buffer and let it trundle away in the
background.

Dave E.

campbell@Thalatta.COM (Bill Campbell) (11/25/89)

In article <256ADBB5.19093@ateng.com> chip@ateng.com (Chip Salzenberg) writes:
>SCO Xenix, like all AT Unixen, is shipped with a driver for IBM parallel
>ports.  Unfortunately, at least with SCO Xenix, the parallel driver uses the
>internal kernel data structures (clists) intended for use with serial lines.
>The use of clists lowers the speed of parallel to something far slower than
>the hardware could support otherwise.

There are problems with slow printing from Xenix with Tandy
printers in particular.  Most of these problems can be solved by
using the Tandy printer cables (they have some non-standard
crossovers).  There is also a patch to Xenix available from Tandy
to help speed up the printer.

Without the Tandy cables on Tandy printers the drivers shift into
a polling mode and the resulting print seems to have about a
half-second timeout between lines.

Another thing that will eliminate the problem is to use an
intermediate smart printer switch such as the $99.95 intelligent
switch from Tandy.
-- 
....microsoft--\					Bill Campbell; Celestial Software
...uw-beaver-----!thebes!camco!bill	6641 East Mercer Way
....fluke------/					Mercer Island, Wa 98040
....hplsla----/						(206) 232-4164

mike@cimcor.MN.ORG (Michael Grenier) (11/25/89)

From article <2316@thebes.Thalatta.COM>, by campbell@Thalatta.COM (Bill Campbell):
> In article <256ADBB5.19093@ateng.com> chip@ateng.com (Chip Salzenberg) writes:
>>SCO Xenix, like all AT Unixen, is shipped with a driver for IBM parallel
>>ports.  Unfortunately, at least with SCO Xenix, the parallel driver uses the
>>internal kernel data structures (clists) intended for use with serial lines.
>>The use of clists lowers the speed of parallel to something far slower than
>>the hardware could support otherwise.
> 
> There are problems with slow printing from Xenix with Tandy
> printers in particular.  Most of these problems can be solved by
> using the Tandy printer cables (they have some non-standard
> crossovers).  There is also a patch to Xenix available from Tandy
> to help speed up the printer.

I can't speak to the problem with Tandy printers but I had a problem
with this Epson under Microport UNIX where the printer *DOES* generate
an interrupt with every character sent. With my old Microport V/AT
sending bitmaps to the epson, this overhead brought my system to a
standstill. It wasn't bad with V/386 but still more than what I 
wanted so I wrote my own driver. 

This driver does NOT use interrupts and does NOT do any character
translations. If you want the goofy translations put them into
your /usr/spool/lp/interface file for this printer (I use
unix2dos to cat the file to the printer to add the CRs. This
allows a raw interface via /dev/lp to dump bitmaps to.)

The driver relies on the fact that the printer has a buffer.  The driver
will output as many characters as it can until it sees that the printer
is not giving an acknowledge for the next byte within some time window. 
At which point the driver assumes that the buffer is full and goes to
sleep for awhile.  It wakes up periodically to see if the printer is now
available and repeats the process.  No clists or other goofy things are
used...its about as simple as they get.  One nice benefit with this
driver is that none of the scarce interrupt lines are used. 

Still, the driver has worked great for sending the output of
my TeX dvi driver to the epson while supporting general use.

There are two variables of interest in this driver. The first is lpdelay
which is number of clockticks to wait before waking up to retry
sending data to the printer. The second is lpstobe which is the delay
in a timing loop to wait before giving up getting an acknowledge and
going to sleep. Both can be set using the Microport /etc/patch
program to dynamically tune this for your system. If you don't have
the kernel patcher (Eat your heart out!), the values given here work
fine for me.

Here it is :
  -Mike Grenier
   mike@cimcor.mn.org

#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
#	config
#	lp.c
#	space.c
# This archive created: Sat Nov 25 09:33:27 1989
export PATH; PATH=/bin:/usr/bin:$PATH
echo shar: "extracting 'config'" '(71 characters)'
if test -f 'config'
then
	echo shar: "will not over-write existing file 'config'"
else
sed 's/^	X//' << \SHAR_EOF > 'config'
	X
	Xcharacter(7)
	X
	Xprefix = lp
	Xfunctions = init, open, close, write, ioctl
SHAR_EOF
if test 71 -ne "`wc -c < 'config'`"
then
	echo shar: "error transmitting 'config'" '(should have been 71 characters)'
fi
fi
echo shar: "extracting 'lp.c'" '(2508 characters)'
if test -f 'lp.c'
then
	echo shar: "will not over-write existing file 'lp.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'lp.c'
	X
	X/*
	X	Fast printer driver		Copyright(c) 1989 Michael Grenier
	X*/
	X
	X
	X#include "sys/param.h"
	X#include "sys/types.h"
	X#include "sys/dir.h"
	X#include "sys/signal.h"
	X#include "sys/user.h"
	X#include "sys/errno.h"
	X#include "sys/tty.h"
	X
	X#define MAXLP   3       /* Make this as large as needed     */
	X
	Xstruct lp_config {
	X    short data_port;
	X    short ctrl_port;
	X    short status_port;
	X} lp_config[MAXLP] = 
	X
	X{
	X    { 0x3bc, 0x3be, 0x3bd },  /* Printer /dev/lp0           		*/
	X    { 0x378, 0x37a, 0x27a },  /* Printer /dev/lp1           		*/
	X    { 0x278, 0x27a, 0x279 }   /* Printer /dev/lp2           		*/
	X};
	X
	Xint lpdebug= 0;		/* 1 to turn on some debugging			*/
	Xint lpstrobe = 50;	/* Loop count delay for strobe line		*/
	Xint lpdelay = 1;	/* Number of clock tics before retrying printer	*/
	X#define minor(x)	(x & 0xff)
	X
	X/*	Status port defines						*/
	X
	X#define NOT_BUSY	(1 << 7)
	X#define NOT_ACK		(1 << 6)
	X#define END_OF_PAPER	(1 << 5)
	X#define SELECT		(1 << 4)
	X#define NOT_ERROR	(1 << 3)
	X
	X/* 	Control port defines						*/
	X
	X#define IRQ_ENABLE	(1 << 4)
	X#define SELECT_IN	(1 << 3)
	X#define NOT_INIT	(1 << 2)
	X#define AUTO_LF		(1 << 1)
	X#define STROBE		1
	X
	X
	Xlpinit()
	X{
	X	int unit;
	X	for (unit = 0; unit < MAXLP; unit++)
	X	{
	X		outb(lp_config[unit].ctrl_port, SELECT_IN | NOT_INIT);
	X		if (lpdebug)
	X			printf("Initial status of /dev/lp%d is %x\n", 
	X				unit, inb(lp_config[unit].status_port));
	X	}
	X}
	X
	X
	Xlpopen(dev, mode)
	Xint dev, mode;
	X{
	X	register unit = minor(dev);
	X
	X        if ( unit >= MAXLP ) 
	X	{
	X        	u.u_error = EIO;
	X                return;
	X        }
	X
	X	if ((inb(lp_config[unit].status_port) & NOT_ERROR) == 0) 
	X	{
	X		u.u_error = EIO;	/*	Error detected at printer */
	X		if (lpdebug)
	X			printf("Printer error detected on /dev/lp%d\n", unit);
	X		return;	
	X	}
	X}
	X
	X
	Xlpclose(dev)
	Xint dev;
	X{
	X	/* Nothing exciting */
	X}
	X
	Xlpioctl(dev)
	Xint dev;
	X{
	X	/* Nothing exciting */
	X}
	X
	X
	Xlpwrite(dev)
	Xint dev;
	X{
	X	int strobe_cnt, ch;
	X	struct lp_config lp;
	X	
	X	lp = lp_config[ minor(dev) ]; /* lp holds params for selected printer */
	X
	X	/* Loop, getting characters from user space and sending them out      */
	X
	X        while ((ch = cpass()) >= 0) { 
	X
	X                /* while printer is busy, sleep awhile			*/
	X
	X                while ( !(inb(lp.status_port) & NOT_BUSY)) 
	X                	delay(lpdelay);
	X
	X		/* OK, send the character out				*/
	X		
	X                outb( lp.data_port, ch );
	X		outb( lp.ctrl_port, SELECT_IN | NOT_INIT | STROBE);
	X		for ( strobe_cnt = lpstrobe; strobe_cnt; strobe_cnt--);
	X                outb( lp.ctrl_port, SELECT_IN | NOT_INIT);
	X	}
	X}
SHAR_EOF
if test 2508 -ne "`wc -c < 'lp.c'`"
then
	echo shar: "error transmitting 'lp.c'" '(should have been 2508 characters)'
fi
fi
echo shar: "extracting 'space.c'" '(52 characters)'
if test -f 'space.c'
then
	echo shar: "will not over-write existing file 'space.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'space.c'
	X/*
	X * lp/space.c, created 8/27/89, cimcor!mike
	X */
	X
SHAR_EOF
if test 52 -ne "`wc -c < 'space.c'`"
then
	echo shar: "error transmitting 'space.c'" '(should have been 52 characters)'
fi
fi
exit 0
#	End of shell archive

pete@romed.UUCP (Pete Rourke) (11/27/89)

In article <289@marvin.moncam.co.uk> emmo@moncam.co.uk (Dave Emmerson) writes:
>In article <256ADBB5.19093@ateng.com>, chip@ateng.com (Chip Salzenberg) writes:
>> [stuff omitted]
>> know.  It's a crying shame to have slow printer output when it's the driver
>> causing the slowdown.
>
>Forget it, the printer itself is usually the bottleneck, there's no point in
>worrying about getting > 1k char/sec to a printer which can only output at
> [stuff omitted]

I am probably entering late in this discussion, but I have the same problem
with the printer output being slow. I have a Compaq 386 portable running XENIX
2.3.2 and it is terribly slow at printing on a HP Laserjet II. The same system
has a DOS partition, and when printing from DOS the speed improves dramatically.Both DOS and XENIX are printing from Microsoft Word 5.  

This would implicate that the driver was part of the speed problem.

If others have improved the printer speed, I'd sure like to know how.


-- 
Pete Rourke                                                ..texbell!romed!pete
MicroAge Technical Support Group                     ..sun!sunburn!mcsitsg!pete
Tempe, AZ                                                     ..ucsd!romed!pete
(602) 968-3168 Ext 2273                                     ..asuvax!romed!pete

davidc@vlsisj.VLSI.COM (David Chapman) (11/28/89)

In article <522@romed.UUCP> pete@romed.UUCP (Pete Rourke) writes:
|In article <289@marvin.moncam.co.uk> emmo@moncam.co.uk (Dave Emmerson) writes:
|>In article <256ADBB5.19093@ateng.com>, chip@ateng.com (Chip Salzenberg) writes:
|>> [stuff omitted]
|>> know.  It's a crying shame to have slow printer output when it's the driver
|>> causing the slowdown.
|>
|>Forget it, the printer itself is usually the bottleneck, there's no point in
|>worrying about getting > 1k char/sec to a printer which can only output at
|> [stuff omitted]
|
|I am probably entering late in this discussion, but I have the same problem
|with the printer output being slow. I have a Compaq 386 portable running XENIX
|2.3.2 and it is terribly slow at printing on a HP Laserjet II. The same system
|has a DOS partition, and when printing from DOS the speed improves dramatically.Both DOS and XENIX are printing from Microsoft Word 5.  
|
|This would implicate that the driver was part of the speed problem.

One problem with IBM PC-class machines is that the parallel printer port
doesn't have hardware for interrupt-driven servicing.  As a result it must
be polled.  In a multi-tasking environment on a busy machine it might not
get enough opportunity to poll.  Under DOS the printer driver is attached
to the clock interrupt, guaranteeing plenty of polling opportunities.  My
guess is that XENIX doesn't do this; a printer driver would probably not
be "special" (i.e. part of the kernel) but would instead be a normal process.

It's conceivable that it is a "stupid software" problem, but I think it is
unlikely.  Can't you call your OS vendor?  (Yes, I know you can't do that
for DOS, but maybe SCO or Microsoft will treat you better if you've spent a
lot more money. :-)
-- 
		David Chapman

{known world}!decwrl!vlsisj!fndry!davidc
vlsisj!fndry!davidc@decwrl.dec.com

chip@ateng.com (Chip Salzenberg) (11/30/89)

According to emmo@moncam.co.uk (Dave Emmerson):
>Forget it, the printer itself is usually the bottleneck...

Bzzt!  You lose the answer-the-poster's-question contest.

When printing to an HP LaserJet II or a Printronix 600, the printer most
definitely is _not_ the bottleneck.
-- 
You may redistribute this article only to those who may freely do likewise.
Chip Salzenberg at A T Engineering;  <chip@ateng.com> or <uunet!ateng!chip>
	  "The Usenet, in a very real sense, does not exist."

zeeff@b-tech.ann-arbor.mi.us (Jon Zeeff) (12/01/89)

I've given up on getting good parallel port performance and have 
switched to a 19200 bps serial link to a HP Series II.  You might look 
into serial->parallel adapters if your printer only supports 
parallel.  


-- 
Jon Zeeff    		<zeeff@b-tech.ann-arbor.mi.us>
Branch Technology 	<zeeff@b-tech.mi.org>

brad@looking.on.ca (Brad Templeton) (12/01/89)

On SCO Unix 3.2, the parallel performance was dreadful to my laserjet.

The reason is the IPL level.  The kernel is compiled with serial ports at
an IPL level of 7 (the highest) and the printer at level 2 or 3, I think.

Raise the IPL level to 5, and you can print quickly.

Of course, SCO 3.2.0 has an annoying bug of not being able to handle
bytes with the MSB turned on, so you have to write a filter, and that's
a pain, so going to 19.2k serial may be the way to go anyway, particularly
if you have a smart serial card.
-- 
Brad Templeton, ClariNet Communications Corp. -- Waterloo, Ontario 519/884-7473

rick@pcrat.uucp (Rick Richardson) (12/02/89)

In article <FZL6GM@b-tech.mi.org> Jon Zeeff writes:

>I've given up on getting good parallel port performance and have 
>switched to a 19200 bps serial link to a HP Series II.  You might look 
>into serial->parallel adapters if your printer only supports 
>parallel.  

I missed the first part of this discussion, and am surprised that
you find the serial interface faster.

I measure 52,000 bits per second through the parallel interface.

The environment is 386/ix 2.0.2 talking parallel thru a Taiwan, Inc.
parallel port.  6 feet from the parallel port is a "Bravo Communications"
parallel line extender.  25 feet from that is a Taiwan, Inc. PB-64-2
parallel in/parallel out 2 port 64K printer buffer.  And 6 feet from that
is the HP LaserJet Series II.

The test is to take the printer off-line and then "lp bigfile".
I measured the time from issuing the command until the printer
buffer LEDs indicated it was full.  This worked out to 52,000 bps.

Even at 52,000 bps, the bottleneck is still the link to the printer
for printing bitmaps and images.  I don't know how anybody could
get by with less than half of that speed.

FYI, my Series II manual lists "typical" printer BUSY times
of 143 microseconds for font and image data and 2 milliseconds
for text data.  This works out to 55,000 bps and 4,000 bps,
respectively.  The Series IIP lists only one "typical" BUSY
time of 200 microseconds, which is 40,000 bps.

When I first got the printer buffer, I recall that it had
two effects, both good.  During parallel printing, 386/ix
performance suffers noticeably.  The first effect was that the
buffer shortened the elapsed time that 386/ix performance was
poorer.  The second effect, though, was that the total throughput
to the printer went up tremendously.  This was back when I had
386/ix 1.0.6, and I haven't done any testing without the buffer
since.  I suspect that the reason for this is that the buffer
takes data with BUSY asserted only for a very brief time,
no matter what kind of data is being transmitted to the printer.
Apparently, this time is short enough that the 386/ix printer
driver keeps blasting data down the pipe.  But if BUSY exceeds
some (unknown) length of time, then the driver appears to take
a clock tick or some other timeout before starting to transfer
again.

Anyhow, I'm happy, and the buffer was cheap.  If I had to do it
again, I think I'd get a 256K buffer with automatic switching
between the two ports (the one I have has a pushbutton to
switch the source).

Oh yeah, the Taiwan, Inc. parallel port couldn't reliably
drive the most significant data bit the 25 feet to the buffer,
so that's why I have the parallel line extender.  Don't ask
how I know it was the MSB that was getting smashed...

Finally, if I read my parallel interface spec's correctly,
the maximum theoretical throughput should be around 600,000 bps.
But don't try this at home, kids.

-Rick

-- 
Rick Richardson |       Looking for FAX software for UNIX/386 ??????     mention
PC Research,Inc.|                  WE'RE SHIPPING			 your
uunet!pcrat!rick|    Ask about FaxiX - UNIX Facsimile System (tm)        FAX #
(201) 389-8963  | Or JetRoff - troff postprocessor for the HP {Laser,Desk}Jet

jim@bahamut.fsc.com (James O'Connor) (12/06/89)

In article <25747D15.4126@ateng.com>, chip@ateng.com (Chip Salzenberg) writes:
> 
> When printing to an HP LaserJet II or a Printronix 600, the printer most
> definitely is _not_ the bottleneck.

Sorry, no real help, just more info.

I was also getting very slow throughput on our HP LaserJet II.  Then, due to
some hardware swapping, the LaserJet ended up connected to a parallel port
on a Hercules monochrome card, rather than a parallel port on a generic
ser/par I/O card.  Lo and behold, the LJ just screams now.

My theory here is that some I/O cards are just not built to use the interrupts
like they're supposed to, and hence don't always work under Xenix.

My proposed solution is different from Chip's though.  I don't want to see
new drivers for old boards, I'd like to see some bright, young engineer
come up with a new board.  My wish list:

- multiple parallel ports on one board.  you could use ribbon cable and the
  openings on most AT cases to mount the jacks.

- use 16-bit IO so the port interrupts could be set to the higher numbers.

- emulate the standard PC parallel ports, or use a shared interrupt scheme and
  let some bright, young software engineer write a device driver to take
  advantage of it

Parallel ports are just so easy to use when connecting printers, it's a pity
that getting two or three of them in a machine uses up so many interrupts
and card slots.
------------- 
James B. O'Connor			Work:	jim@tiamat.fsc.com
Filtration Sciences --			Play:   jim@bahamut.fsc.com
A division of Ahlstrom			UUCP:	uunet!tiamat!jim

emmo@moncam.co.uk (Dave Emmerson) (12/06/89)

In article <25747D15.4126@ateng.com>, chip@ateng.com (Chip Salzenberg) writes:
> According to emmo@moncam.co.uk (Dave Emmerson):
> >Forget it, the printer itself is usually the bottleneck...
> 
> Bzzt!  You lose the answer-the-poster's-question contest.
> 
> When printing to an HP LaserJet II or a Printronix 600, the printer most
> definitely is _not_ the bottleneck.
> -- 
As I recall, the poster only said 'printer', not 'laserprinter'. Sure there's
a world of difference. 
If you use a dedicated board which you can make yourself in about 4 hours for 
<100 USD, you can do away with OS calls and 'print' at well over 100Kchar/sec
- if you can write your code tightly enough, that is - and leave your PRN:
port for more mundane tasks. A lash-up I tested recently for satellite comms
averaged 50Kb/sec including run-time packet generation, similar to Kermit.
For occasional (personal) use I would have no qualms about accessing the PRN:
port directly anyway, it may be dirty, but it's cheap and I can do it today...

NB It wasn't my software, if *I* were paying for satellite time, the data
would have been pre-packeted on disk, and spooled out directly from file.

ATB

Dave E.

tanner@ki4pv.uucp (Dr. T. Andrews) (12/07/89)

In article <256@bahamut.fsc.com>, jim@bahamut.fsc.com (James O'Connor) writes:
) My proposed solution is different from Chip's though.  I don't want
) to see new drivers for old boards, I'd like to see some bright, young
) engineer come up with a new board.
My wish list is a little simpler.  I'd settle for a couple of
one-port para boards if they had some smarts.  I hate like taxes
to pay an interrupt per character with troff heading to a laser
printer.  I even find it bad to pay to drive a lousy dot matrix
printer with my listings, and my fast dot matrix printer is still
in the shop.

Boss reports that he can't find out about any "smart" para boards.
I think even he realizes that it'd pay for itself in a few months.

Surely some enterprising company will invent such a beast, and
will perhaps be good enough to inform me of their products.  (If
you work for such a company, examine the "X-snail" header of this
article or send e-mail.)
-- 
...!{bikini.cis.ufl.edu allegra attctc bpa uunet!cdin-1}!ki4pv!tanner

chip@ateng.com (Chip Salzenberg) (12/08/89)

According to emmo@moncam.co.uk (Dave Emmerson):
>According to chip@ateng.com (Chip Salzenberg):
>> When printing to an HP LaserJet II or a Printronix 600, the printer most
>> definitely is _not_ the bottleneck.
>
>As I recall, the poster only said 'printer', not 'laserprinter'.
>Sure there's a world of difference.

I was the original poster.  I said 'printer'.  The 600 isn't a laser printer,
it's a dot-matrix line printer with a row of pixel hammers across the page.

In any case, the real application for which I want a fast parallel driver
isn't a printer at all.  It's another peripheral that, for software
compatibility reasons, pretends to be a standard IBM printer port.
-- 
You may redistribute this article only to those who may freely do likewise.
Chip Salzenberg at A T Engineering;  <chip@ateng.com> or <uunet!ateng!chip>
	  "The Usenet, in a very real sense, does not exist."

dave@pmafire.UUCP (Dave Remien) (12/08/89)

In article <7135@ki4pv.uucp> tanner@ki4pv.uucp (Dr. T. Andrews) writes:
-In article <256@bahamut.fsc.com>, jim@bahamut.fsc.com (James O'Connor) writes:
-) My proposed solution is different from Chip's though.  I don't want
-) to see new drivers for old boards, I'd like to see some bright, young
-) engineer come up with a new board.
-My wish list is a little simpler.  I'd settle for a couple of
-one-port para boards if they had some smarts.  I hate like taxes
-to pay an interrupt per character with troff heading to a laser
-printer.  I even find it bad to pay to drive a lousy dot matrix
-printer with my listings, and my fast dot matrix printer is still
-in the shop.

AT&T will sell you (if you can get them to) an IPC-802 board, with 6
serial ports and 2 parallel ports, all run by a Z-80, I think. Make sure
you get the lastest and greatest software if you go this route; earlier
version were definitely buggy. I've also had some bizarre problems with
them as far as what device you power up first; on one board, if you
power up the computer first, all's well, the other the printer has to be
powered up first for the system to come up. Both with AT&T (Olivetti)
computer hardware, HP PaintJet printers.

I'm not pimping for AT&T, I'm not even real happy with them. They're the
hardest folks in the world to buy something from. It might even work
when you get it. Just mentioning that there is such a thing as a smart
parallel port out there in the world.

Good luck.......
-- 
Dave Remien ++*+*+*+*+*+*+*+*+*+*+*+*+*+* WINCO Computer Engineering Group 
{uunet|bigtex}!pmafire!dave or rzd@inel.gov         "Dave Barry for President"