[comp.sys.ibm.pc.misc] Writing my own print spooler

chas@tira.uchicago.edu (Charles Blair) (12/28/90)

I've written my own int 5h handler. What I want to do is to make it
act like a print spooler, so that I can let the application it is a
part of get on with other work while stuff is printing -- this is a
problem when I drive the printer in graphics mode.

What's a good way to approach this problem? I've thought of installing
the int 5h handler as a device driver, but I still don't really
understand how to accomplish the spooling. What's the trick? Does the
driver grab some kind of interrupt and keep looking at a buffer from
which it prints, returning if the buffer has no data? Is this the
trick? (In that case, I could simply grab some interrupt in my
application, and accomplish the same thing.)

Thanks. I prefer e-mail, and I'll summarize, if there is interest.

--
Bitnet:                 pmrcjdb@uchimvs1
Internet:       cjdb@midway.uchicago.edu

steven@ozonebbs.UUCP (Steven Rubin) (12/29/90)

chas@tira.uchicago.edu (Charles Blair) writes:

> 
> I've written my own int 5h handler. What I want to do is to make it
> act like a print spooler, so that I can let the application it is a
> part of get on with other work while stuff is printing -- this is a
> problem when I drive the printer in graphics mode.
> 
> What's a good way to approach this problem? I've thought of installing
> the int 5h handler as a device driver, but I still don't really
> understand how to accomplish the spooling. What's the trick? Does the
> driver grab some kind of interrupt and keep looking at a buffer from
> which it prints, returning if the buffer has no data? Is this the
> trick? (In that case, I could simply grab some interrupt in my
> application, and accomplish the same thing.)
> 
> Thanks. I prefer e-mail, and I'll summarize, if there is interest.
> 
> --
> Bitnet:                 pmrcjdb@uchimvs1
> Internet:       cjdb@midway.uchicago.edu


I don't know if this is the "correct" way to do a spooler, but The way I do 
it would be something like this

1) Capture int 1Ch.
2) Every clock tick, print x amount of characters from the file
3) return control to the other program.

I suppose there is some other stuff to keep in mind when doing something 
like this, But basicly it is a very simple procedure.  


---
Steven Rubin                                           @      @
{netcom, crash!nusdecs}!nusjecs!ozonebbs!steven           oo
Disclaimer: I don't even speak for myself!           \__________/

frank@cavebbs.gen.nz (Frank van der Hulst) (12/30/90)

In article <CHAS.90Dec27202731@tira.uchicago.edu> chas@tira.uchicago.edu (Charles Blair) writes:
>
>I've written my own int 5h handler. What I want to do is to make it
>act like a print spooler, so that I can let the application it is a
>part of get on with other work while stuff is printing -- this is a
>problem when I drive the printer in graphics mode.
>
>What's a good way to approach this problem? I've thought of installing

The standard DOS print command grabs INT 8 (the timer tick interrupt) and
tries to send a character to the printer (if its not busy). I suggest you
try something like that.

You will also run into the problem of DOS's non-reentrancy. You can't call
DOS (from within your INT 5 to write to your spool file, or INT 8 to read
from your spool file) while some other program (your foreground task) is
calling DOS.
.

silver@xrtll.uucp (Hi Ho Silver) (12/31/90)

In article <uV5wu2w163w@ozonebbs.UUCP> steven@ozonebbs.UUCP (Steven Rubin) writes:
$I don't know if this is the "correct" way to do a spooler, but The way I do 
$it would be something like this
$1) Capture int 1Ch.
$2) Every clock tick, print x amount of characters from the file
$3) return control to the other program.

   Well, there isn't a "right" way and a "wrong" way; there are ways which
don't work, and there are ways which do work with varying degrees of
efficiency.  Yours would work, though it would tend to slow down the program
in the foreground once the printer's buffer filled up.  Also, you would have
to put in some code so that when it receives an int 1Ch, it would check to
see if it was still processing from the last interrupt (this is possible if
your number of characters is too large, if the printer is slow, or if the
printer is off-line, for example).  For a program which wakes up every
clock tick, you used the correct interrupt; it's not wise to add code
into the int 8h routine; int 1Ch is provided instead.

   A more efficient, though slightly more difficult, way might be to set
up the printer port to interrupt the CPU whenever it's ready for another
character.  If the base I/O address of your printer port is printer_base,
then bit 4 of the I/O register at printer_base+2 controls this.  If set,
the printer port will generate an interrupt 0Fh whenever the ACK line from
the printer does a high-to-low transition.  This happens just before the
BUSY line returns to 0, and signals that you should go grab another byte
because the printer is almost ready for it.

   The original poster referred to capturing int 5h.  This is the print
screen interrupt, not the BIOS printer output interrupt, so a print spooler
on int 5h would only spool screen prints.  Any other output would not be
captured.  Int 17h is the printer output interrupt.
-- 
 __            __  _  | ...!nexus.yorku.edu!xrtll!silver |  always
(__  | | |  | |_  |_) >----------------------------------< searching
 __) | |_ \/  |__ | \ | if you don't like my posts, type |    for
_____________________/  find / -print|xargs cat|compress |   SNTF

lairdb@crash.cts.com (Laird Broadfield) (12/31/90)

In <uV5wu2w163w@ozonebbs.UUCP> steven@ozonebbs.UUCP (Steven Rubin) writes:
>chas@tira.uchicago.edu (Charles Blair) writes:
>> I've written my own int 5h handler. What I want to do is to make it
>> act like a print spooler, so that I can let the application it is a
>> part of get on with other work while stuff is printing -- this is a
>> problem when I drive the printer in graphics mode.
>> 
>> What's a good way to approach this problem? I've thought of installing
>>...

>I don't know if this is the "correct" way to do a spooler, but The way I do 
>it would be something like this
>1) Capture int 1Ch.
>2) Every clock tick, print x amount of characters from the file
>3) return control to the other program.
>I suppose there is some other stuff to keep in mind when doing something 
>like this, But basicly it is a very simple procedure.  

Hmmm.  I've always got enough stuff tied to 1Ch that I'm a tad concerned
about performance impact, so instead I tie to the IRQ7 interrupt (0fh).

When it triggers, I check the busy line from the printer, stuff a 
character out if it's okay, expect the busy line to transition, and
bail.  This allows the printing to happen pretty much as fast as the 
printer can take it, without loading down the system (especially
significant when you consider that 99+% of the time, you're not
printing anything.)  If you have 4 channels of 9600 baud commo going,
as well as a user, responsiveness and load sensitivity are pretty 
important.

There are a few tricks to it (proper EOI for the 8259, circular buffer
mgmt., etc) but that's the outline.

-- 
--  Laird P. Broadfield                        | Year after year, site after
    UUCP: {akgua, sdcsvax, nosc}!crash!lairdb  | site, and I still can't think
    INET: lairdb@crash.cts.com                 | of a funny enough .sig.

madams@ecst.csuchico.edu (Michael E. Adams) (12/31/90)

<uV5wu2w163w@ozonebbs.UUCP> steven@ozonebbs.UUCP (Steven Rubin) writes:
>$I don't know if this is the "correct" way to do a spooler, but The way I do 
>$it would be something like this
>$1) Capture int 1Ch.
>$2) Every clock tick, print x amount of characters from the file
>$3) return control to the other program.

<1990Dec30.160422.27898@xrtll.uucp> silver@xrtll.UUCP (Hi Ho Silver) writes:
>  Well, there isn't a "right" way and a "wrong" way; there are ways which
>don't work, and there are ways which do work with varying degrees of
>efficiency.
>
>   A more efficient, though slightly more difficult, way might be to set
>up the printer port to interrupt the CPU whenever it's ready for another
>character. ... see int 0Fh.

Silver:
  Good posting!  I liked what you had to say, but my DOS reference
guide seems to think that int 0Fh should be AVOIDED!

"On the PC, int 0Fh was assigned to the printer controller to
detect printer errors and print completion.  Programmers typically
do not use it because many controllers DO NOT generate it RELIABLY.
Generaly, you can ignore this interrupt.  The IRQ7 request can also
be generated as a default by the 8259 Priority Interupt Controller,
if the controller is unable to determin which device requested service.
Thus, it is NEVER SAFE to assume that an interrupt reaching this
handler was originated by the Printer; it could originate anywhere."

This is not a flame, just somthing to think about :-)

         (___)      |  Michael E. Adams
         (o o)      |  Custom Computer Programming
  /-------\ /       |  P.O. Box 5027
 / |     ||O        |  Chico,  California  95927-5025    U.S.A.
*  ||,---||         |
   ~~    ~~         |  internet: madams@cscihp.ecst.csuchico.edu
No BULL bandwidth   |

ralerche@lindy.stanford.edu (Robert A. Lerche) (01/01/91)

It is true that the 8259A interrupt controller will generate IRQ7 as its
"default interrupt", but this is a symptom of a failing interrupt system
(e.g., two devices fighting over the same IRQ line).  In normal system
operation, default interrupts should not occur.

It is also true that some clones (e.g., early Olivetti models) do not
correctly implement IRQ7 on their parallel ports.  Oh well.  IBM machines,
of course, do it right.

My suggestion is to implement IRQ 7 processing, but also hook the timer
interrupt and, if a long timeout with no "ack" occurs, use the timer
interrupt to restart output.  Mainframes do this -- it's referred to as
"missing interrupt processing."

silver@xrtll.uucp (Hi Ho Silver) (01/02/91)

In article <1990Dec31.090454.13869@ecst.csuchico.edu> madams@ecst.csuchico.edu (Michael E. Adams) writes:
$  Good posting!  I liked what you had to say, but my DOS reference
$guide seems to think that int 0Fh should be AVOIDED!
[...int 0Fh may not come from the printer port...]

   Hmm, that sheds new light on the situation :-)  Well then, I suppose one
could still use an int 0Fh routine; you'd just have to make sure you checked
the printer port's status every time before trying to send a character (which
would be a Good Thing to do anyway).  And perhaps a clock tick hook would
also be useful in case an int 0Fh failed to get through.
-- 
 __            __  _  | ...!nexus.yorku.edu!xrtll!silver |  always
(__  | | |  | |_  |_) >----------------------------------< searching
 __) | |_ \/  |__ | \ | if you don't like my posts, type |    for
_____________________/  find / -print|xargs cat|compress |   SNTF