$CONTROL MAP,CODE,USLINIT                                               00010000
<<  MPE MODULE 19, IOLPRT0  >>                                          00015000
<< HP32002C MPE SOURCE C.00.00 >>                                       00020000
<< COPYRIGHT     "(C) COPYRIGHT HEWLETT-PACKARD CO. 1980.           >>  00025000
<<     THIS PROGRAM MAY BE USED WITH ONE COMPUTER SYSTEM AT A       >>  00030000
<<     TIME AND SHALL NOT OTHERWISE BE RECORDED, TRANSMITTED OR     >>  00035000
<<     STORED IN A RETRIEVAL SYSTEM.  COPYING OR OTHER REPRODUCTION >>  00040000
<<     OF THIS PROGRAM EXCEPT FOR ARCHIVAL PURPOSES IS PROHIBITED   >>  00045000
<<     WITHOUT THE PRIOR WRITTEN CONSENT OF HEWLETT-PACKARD COMPANY.>>  00050000
<< **** Note - Dollar Copyright cannot be used with this module *** >>  00055000
                                                                        00060000
<<                                                                      00065000
  COPYRIGHT (C) 1978, HEWLETT-PACKARD CO.  This program may  be  used   00070000
with  one  computer  system  at  a  time  and  shall not otherwise be   00075000
recorded, transmitted or stored in a  retrieval  system.  Copying  or   00080000
other  reproduction  of  this program except for archival purposes is   00085000
prohibited without  the  prior  written  consent  of  Hewlett-Packard   00090000
Company.                                                                00095000
>>                                                                      00100000
<<                                                                      00105000
  NOTE:  Do NOT use $COPYRIGHT to enter the above  copyright  notice.   00110000
INITIAL will get very unhappy, and so will MPE.                         00115000
>>                                                                      00120000
                                                                        00125000
$TITLE "CDC, TALLY, DATAPRODUCTS, DATAPRINTER AND HP2608 DRIVER",&      00130000
$      " - IOLPRT0 (19)"                                       <<00464>>00135000
$CONTROL PRIVILEGED, UNCALLABLE, MAIN=IOLPRT0                           00140000
                                                                        00145000
  The fix number in the right margin is  an  enhancement,  de- <<00770>>00150000
scribed more fully on page 16.                                 <<00769>>00155000
                                                               <<00769>>00160000
  The fix number in the right margin denotes a redesign of the <<00769>>00165000
control algorithm to correct errors when the driver is running <<00769>>00170000
in prespace mode.                                              <<00769>>00175000
                                                               <<00773>>00180000
  The fix number in the right margin is a correction which al- <<00773>>00185000
lows the driver to properly handle a prespace request  with  a <<00773>>00190000
transfer  length of 1 byte, where the byte is an imbeeded car- <<00773>>00195000
riage control byte (that is, no data in the  request).  Before <<01061>>00200000
this  fix,  such a request would cause the driver to wait for- <<00773>>00205000
ever for a completion interrupt because interrupts  were  dis- <<00773>>00210000
abled on the U.I. card.                                        <<00773>>00215000
                                                               <<00785>>00220000
  The fix denoted by the number in the  right  margin  assures <<00785>>00225000
that  the  proper buffer address is placed in the channel pro- <<00785>>00230000
gram after returning from Not Ready.  See additional  comments <<00785>>00235000
near  the  end  of  the Operation description and at the label <<00785>>00240000
WAIT'CODE3.                                                    <<00785>>00245000
                                                               <<01061>>00250000
  The fix denoted by the number in the right margin allows re- <<01061>>00255000
quests using a "0" (double space) or  "-"  (triple  space)  to <<01061>>00260000
base their execution on the state of the NO'AUTO'PAGE bit.     <<01061>>00265000
$PAGE                                                          <<00773>>00270000
COMMENT                                                        <<00464>>00275000
  This is IOLPRT0, MPE Module 19, the driver for all (line)  printing   00280000
devices  currently  supported on the Universal Interface (U.I.) card.   00285000
Line printers are I/O Device Type  32.  Differences  between  various   00290000
line  printers are resolved through the use of subtypes.  The current   00295000
range of subtypes is 0-4, with the following subtype assignments:       00300000
                                                                        00305000
   SUBTYPE     LINE PRINTER                                             00310000
   -------     ------------                                             00315000
                                                                        00320000
      0        HP2610, HP2614          (manufactured by CDC)            00325000
      1        HP2607                  (manufactured by Tally) <<00770>>00330000
      2        HP2613, HP2617, HP2618  (manufactured by Dataproducts)   00335000
      2        HP2619                  (manufactured by Dataprinter)    00340000
      3        HP2617J                 (manufactured by Dataproducts)   00345000
      4        HP2608                  (manufactured by HP, finally!)   00350000
                                                                        00355000
Further information on the various hardware subsystems can  be  found   00360000
in the following manuals:                                               00365000
                                                                        00370000
  30108-90001  HP2610 line printer                                      00375000
  30109-90001  HP2614 line printer                                      00380000
  30209-90006  HP2607, HP2613, HP2617, HP2618 line printers             00385000
  30209-90008  Line Printer Operating and Programming Manual            00390000
$PAGE                                                                   00395000
Operation of IOLPRT0:                                                   00400000
                                                               <<00769>>00405000
General Description:                                           <<00769>>00410000
                                                               <<00769>>00415000
  IOLPRT0  processes  control  and  data  information supplied by the   00420000
Series III I/O system.  The result is an SIO  channel  program  which   00425000
transmits  the  proper sequence of signals to the Universal Interface   00430000
card, and then to the line printer for printing and/or paper advance.   00435000
  The  primary  working code of IOLPRT0 is a procedure, LPDRVR.  (See   00440000
the next section for  a  description  of  the  overall  structure  of   00445000
IOLPRT0).  LPDRVR  is called with six parameters.  Two of these, BANK   00450000
and BUFADDR, are the absolute  memory  address  of  the  data  to  be   00455000
processed.  Three  others,  DITP,  IOQP and SIOP, are pointers to the   00460000
first elements of three arrays (tables) used  for  control  purposes.   00465000
The  DIT  (Device  Information  Table) contains information about the   00470000
printer and any driver  information  which  must  be  stored  between   00475000
requests  to  the  driver.  The  IOQ (Input/Output Queue) consists of   00480000
information relevant to the current request.  The SIO array  is  read   00485000
by the I/O Processor during execution of the SIO channel program.  It   00490000
must be configured by the driver, based on the  requirements  of  the   00495000
current   request.   These  three  tables  are  described  in  detail   00500000
elsewhere in this listing.                                              00505000
  The  final  parameter, DRTNUMB, is the Device Reference Table (DRT)   00510000
number, or the hardware address  in  the  system,  of  the  Universal   00515000
Interface card.                                                         00520000
  LPDRVR is always called by the SIO Device Monitor (SIODM),  but  it   00525000
is  up  to LPDRVR to find out the reason why it was called.  This may   00530000
be anything from a normal start of a  new  request  to  a  completion   00535000
interrupt  of the present request to a printer or U.I. card interrupt   00540000
due to an error or unusual condition (such as the printer  being  Not   00545000
Ready  or Off Line) to a command from the system to abort the current   00550000
request.  (The driver must process these aborts in order to terminate   00555000
the associated requests in an orderly manner, including provision for   00560000
making I/O resources available to the system once more).                00565000
  When  a  new request is initiated, LPDRVR examines a function field   00570000
and up to two modifying parameters to find out what its current  task   00575000
is.  This  information  is contained in the current IOQ entry.  Based   00580000
on this, and on  the  particular  subtype  of  line  printer,  LPDRVR   00585000
configures  an  SIO  channel  program  to perform the task, calls the   00590000
external procedure STARTIO to start executing  the  channel  program,   00595000
then  returns  to  SIODM with an indication that the request has been   00600000
initiated.                                                              00605000
  Upon  completion of the request, an interrupt is generated.  LPDRVR   00610000
makes sure that no errors have occurred and  cleans  up  its  working   00615000
area  for  the current request, then exits to SIODM with a completion   00620000
status in the IOQ entry.                                                00625000
  There are five basic modes of operation:                     <<00769>>00630000
1.  Postspace mode.  The default and most prevalent mode.  All <<00769>>00635000
    HP printers mechanically operate this way.  Data is print- <<00769>>00640000
    ed, then paper is advanced as required by the request.     <<00769>>00645000
2.  Prespace mode.  Paper is advanced, then data  is  printed. <<00769>>00650000
    This  mode  must  be  simulated  by ending each request by <<00769>>00655000
    filling the printer buffer but  not  printing.   The  next <<00769>>00660000
    request  prints  this  data, advances paper as required by <<00769>>00665000
    the next request, and fills the buffer with data from  the <<00769>>00670000
    next  request,  thus completing the request with data left <<00769>>00675000
    in the printer.                                            <<00769>>00680000
3.  Current request is postspace, previous  request  was  pre- <<00769>>00685000
    space. As described in 2, data has been left in the print- <<00769>>00690000
    er by the previous request.  We must print both this  data <<00769>>00695000
    and  our  current data with this request, but we have only <<00769>>00700000
    one carriage control specification and it must be  applied <<00769>>00705000
    to the postspace request. Therefore we assume a specifica- <<00769>>00710000
    tion of %302 (skip to VFC channel 3, usually single  space <<00769>>00715000
    with  auto  page  eject)  when we print the data left over <<00769>>00720000
    from the previous (prespace) request.                      <<00769>>00725000
4.  Current request is prespace, previous  request  was  post- <<00769>>00730000
    space.  This is not a real mode to the driver, since it is <<00769>>00735000
    logically the same as 2.  The user may experience  one  or <<00769>>00740000
    more  extra  spaces  at the changeover, since the previous <<00769>>00745000
    request spaced after printing and this one will space  be- <<00769>>00750000
    fore printing.                                             <<00769>>00755000
5.  Current carriage control specification is  %320,  pre-  or <<00769>>00760000
    postspace.    No printing or paper advance takes place, so <<00769>>00765000
    it makes no difference which mode we're  in.   Using  this <<00769>>00770000
    specification,  data  from the current request is appended <<00769>>00775000
    to any data which may already exist in the printer buffer. <<00769>>00780000
  The  above  description  is for normal requests.  Errors or unusual   00785000
occurrences, such as a paper out or printer off line, must  be  dealt   00790000
with  as  they  occur.  Both  SIODM  and  IOLPRT0  have provisions to   00795000
suspend a request indefinitely while a condition such as paper out is   00800000
corrected  by  the  operator.  The act of placing the printer on line   00805000
again generates an interrupt.  The driver, after verifying  that  the   00810000
printer   is  again  operable,  continues  with  the  request.  Other   00815000
conditions, such as a data parity  error  during  the  transfer,  are   00820000
considered non-recoverable and result in a request completion with an   00825000
error status.                                                           00830000
                                                               <<00769>>00835000
Detailed Considerations:                                       <<00769>>00840000
                                                               <<00769>>00845000
  Some requests require multiple interrupts before the request <<00769>>00850000
can be completed.  This is because IOLPRT0 must check  printer <<00769>>00855000
status  after  every physical print command, and some requests <<00769>>00860000
must be broken up into multiple physical prints.  Printer sub- <<00769>>00865000
types 1, 2 and 3, for example,  cannot  slew  (advance)  paper <<00769>>00870000
more  than 15 lines at a time (except for VFC skips), so print <<00769>>00875000
requests which must space further than that must be done  with <<00769>>00880000
multiple slews of 15 lines or less.  (An obvious example would <<00769>>00885000
be the header/trailers of print  outputs  which  have  sixteen <<00769>>00890000
spaces  between  the groups of three lines).  If requests were <<00769>>00895000
not so divided, the integrity of the printed output could  not <<00769>>00900000
be  guaranteed in the event paper ran out or the operator took <<00769>>00905000
the printer off-line.  By "integrity", we mean that output  is <<00769>>00910000
not  shifted  right  or left, and lines are not lost nor blank <<00769>>00915000
lines inserted.  Prior to the current fix, we tried  one  long <<00769>>00920000
SIO channel program encompassing all required physical prints. <<00769>>00925000
It worked fine -- as long as the printer remained on-line.   A <<00769>>00930000
word to the wise.                                              <<00769>>00935000
  A discussion is in order about  the  state  of  the  various <<00769>>00940000
printers  when  they go (or are taken) off-line.  Those of you <<00769>>00945000
not concerned about such esoterica can skip the following sec- <<00769>>00950000
tion, which is quite long-winded.                              <<00769>>00955000
$PAGE                                                          <<00769>>00960000
  Data is sent to the printer via  an  asynchronous  handshake <<00769>>00965000
between the U.I. card and the printer.  One or more such hand- <<00769>>00970000
shakes occur for every WIO CPU instruction  or  channel  Write <<00769>>00975000
order -- in fact, one per word transmitted (or two, if in byte <<00769>>00980000
unpacking mode).  You must understand the handshake  mechanism <<00769>>00985000
to  grasp  the off-line behavior of each printer, so it is de- <<00769>>00990000
scribed here.                                                  <<00769>>00995000
  The handshake consists of two signals,  and  therefore  four <<00769>>01000000
states.    One  signal,  Command, is managed by the U.I. card. <<00769>>01005000
The other, called Demand, is managed by the printer.   In  the <<00769>>01010000
idle  state,  Command  is de-asserted (false), while Demand is <<00769>>01015000
asserted (true).  A data transfer works as follows:            <<00769>>01020000
1.  U.I. card asserts Command, signifying that a  transfer  is <<00769>>01025000
    beginning.                                                 <<00769>>01030000
2.  Printer, upon recognizing Command, de-asserts Demand.      <<00769>>01035000
3.  U.I. card, seeing change in Demand,  removes  (de-asserts) <<00769>>01040000
    Command.   While Demand is false, the printer is executing <<00769>>01045000
    the command.                                               <<00769>>01050000
4.  After finishing command execution, Demand  is  re-asserted <<00769>>01055000
    and the idle state is obtained once more.                  <<00769>>01060000
The complement of the Demand line is available as  the  Device <<00769>>01065000
Flag  bit  of the Interrupt Status Word.  That is, Device Flag <<00769>>01070000
is true when Demand is false.                                  <<00769>>01075000
  Clearly the U.I. card (and therefore the  driver)  must  re- <<00769>>01080000
spect  the instantaneous state of the Demand line.  If Command <<00769>>01085000
is asserted while Demand is false, the printer will ignore  it <<00769>>01090000
and  data will be lost.  In fact, this was the cause of numer- <<00769>>01095000
ous problems in earlier releases of this driver.               <<00769>>01100000
  The other villains in this drama  are  the  three  Interrupt <<00769>>01105000
Status bits (Interrupt Status word (8:3)), enabled or disabled <<00769>>01110000
by jumpers in the connecting cable, but managed by the printer <<00769>>01115000
if they are enabled.  Setting any one or more  of  these  with <<00769>>01120000
interrupts enabled will cause an interrupt to the driver.  The <<00769>>01125000
meanings of these bits vary with  the  different  subtypes  of <<00769>>01130000
printers  (see  the  comments  in CHECK'STATUS), but generally <<00769>>01135000
include an off-line and on-line interrupt capability.          <<00769>>01140000
  With this background, we're ready to  examine  what  happens <<00769>>01145000
when the different subtypes of printers go off-line.           <<00769>>01150000
1.  Subtype 0, the 2610/2614 CDC printers, set their  off-line <<00769>>01155000
    interrupt bit the moment the button is pressed.  The driv- <<00769>>01160000
    er may be given control at any point in the  print  cycle. <<00769>>01165000
    The  channel  program is not aborted by the interrupt, and <<00769>>01170000
    so continues to handshake data to the printer, which  con- <<00769>>01175000
    tinues  to  Demand  it  UNTIL the data is a print command. <<00769>>01180000
    Once the print command has been accepted,  Demand  remains <<00769>>01185000
    false  even  after  the  line is printed.  Since the print <<00769>>01190000
    command is the last one in the channel program,  the  pro- <<00769>>01195000
    gram  would complete if the last Demand were received.  It <<00769>>01200000
    therefore remains incomplete.                              <<00769>>01205000
2.  Subtypes 2 and 3, the  2613/17/17J/18  (Dataproducts)  and <<00769>>01210000
    2619 (Dataprinter) printers, are very similar to subtype 0 <<00769>>01215000
    in their off-line behavior.  The only difference  is  that <<00769>>01220000
    the  off-line interrupt bit is not set immediately, but is <<00769>>01225000
    held pending until the current line  is  printed  and  the <<00769>>01230000
    paper is advanced to within one line of its final destina- <<00769>>01235000
    tion.  They too keep Demand false after the final line  is <<00769>>01240000
    printed.                                                   <<00769>>01245000
3.  Subtype 1, the 2607 (Tally) printer behaves much like sub- <<00769>>01250000
    type 2, in that it holds the off-line interrupt bit  pend- <<00769>>01255000
    ing  until the line being printed has finished, then keeps <<00769>>01260000
    Demand false.  The big difference here is  that  the  line <<00769>>01265000
    being  printed  is  NOT the line for which the final hand- <<00769>>01270000
    shake is frozen, but  the  previous  line.   That's  right <<00769>>01275000
    folks,  the 2607 has a one-line buffer in addition to that <<00769>>01280000
    for the line currently being printed.  Betcha didn't  know <<00769>>01285000
    that.    Neither  did your humble scribe until (literally) <<00769>>01290000
    the day before this fix went in.  The  printer  goes  off- <<00769>>01295000
    line  with this line still unprinted.  It is printed auto- <<00769>>01300000
    matically the moment the printer goes back on-line,  which <<00769>>01305000
    creates a special problem for us, about which more below.  <<00769>>01310000
4.  This leaves subtype 4, our own home-grown HP2608.  Whatev- <<00769>>01315000
    er else you say about it, it has both the friendliest  and <<00769>>01320000
    the most unfriendly off-line behavior of all the printers. <<00769>>01325000
    First the good news.  Like the 2607, it has an extra  line <<00769>>01330000
    buffer.   Now the better news.  Unlike the 2607, it prints <<00769>>01335000
    both the current line and the buffered line  before  going <<00769>>01340000
    off-line,  so  no  data  is left unprinted in the printer. <<00769>>01345000
    (You of little faith who wonder how the last line  can  be <<00769>>01350000
    printed  in  a  paper  out  situation should know that the <<00769>>01355000
    printer detects the  impending  end-of-paper  in  time  to <<00769>>01360000
    switch  to a current-line-only mode, accepting no new data <<00769>>01365000
    until it knows there is paper to print it  on).   Now  the <<00769>>01370000
    best  news.   At the completion of this final line, Demand <<00769>>01375000
    wiggles true momentarily (about 1 microsecond)  which  al- <<00769>>01380000
    lows the channel program to complete.                      <<00769>>01385000
      Now some indifferent news.  On-Line and  Not  Ready  are <<00769>>01390000
    two  different  machine  status  bits.  Not Ready causes a <<00769>>01395000
    false On-Line (that is, an off-line indication), but a Not <<00769>>01400000
    On-Line does not cause a Not Ready.   Not  On-Line  occurs <<00769>>01405000
    alone  when  the operator cycles the printer off-line with <<00769>>01410000
    the front panel button.  Not Ready is a  printer-generated <<00769>>01415000
    status which occurs when the printer is unable to continue <<00769>>01420000
    (paper has run out or is jammed, ribbon  is  jammed,  some <<00769>>01425000
    yock opened the platen, etc.).                             <<00769>>01430000
      Finally the bad news.  Although Not Ready causes an  in- <<00769>>01435000
    terrupt  and On-Line causes an interrupt, Not On-Line does <<00769>>01440000
    not.  Thus no interrupt is generated when the operator cy- <<00769>>01445000
    cles the printer off-line.  The only saving grace is  that <<00769>>01450000
    Demand  wiggles one last time, thus completing the channel <<00769>>01455000
    program and causing an interrupt that way.                 <<00769>>01460000
  How do we handle this broad  spectrum  of  operation?   Very <<00769>>01465000
carefully,  I  know.   It turns out that one general algorithm <<00769>>01470000
works very well except when the 2607 goes off-line.  For this, <<00769>>01475000
we introduce some special handling.  The algorithm depends  on <<00769>>01480000
the  fact  that  despite the wide differences in printers, all <<00769>>01485000
printers generate an interrupt at the  end  of  each  physical <<00769>>01490000
print, whether they happen to be on-line or not. The algorithm <<00769>>01495000
also makes use of the property that even  if  the  printer  is <<00769>>01500000
off-line at the time of interrupt, the line we were processing <<00769>>01505000
has been printed. The exception, of course, is the 2607, which <<00769>>01510000
has not printed our current line yet, and this is why  it  re- <<00769>>01515000
quires special handling.                                       <<00769>>01520000
$PAGE                                                          <<00769>>01525000
  The SIO channel program has sections which can  handle  each <<00769>>01530000
type  of request.  For example, there is a section devoted ex- <<00769>>01535000
clusively to printing the previously-buffered  line  during  a <<00769>>01540000
pre-  to postspace print request (mode 3 above).  Another sec- <<00769>>01545000
tion fills the printer buffer.  A third section sends a  print <<00769>>01550000
command  to  the printer.  This last section is repeatedly in- <<00769>>01555000
voked for >15 line slews on those printers which can slew only <<00769>>01560000
15 lines at a time.  Then there are other  specialty  sections <<00769>>01565000
which  support  functions exclusive to the 2608 (such as Down- <<00769>>01570000
load VFC, Download Left Margin, etc.).  For a  given  request, <<00769>>01575000
IOLPRT0  sets  up all the parameters for all the required sec- <<00769>>01580000
tions of the channel program in the initiation section.   This <<00769>>01585000
means  that  all  the continuation section must do is redirect <<00769>>01590000
the start of the channel program to the  next  section  to  be <<00769>>01595000
run  (if any), and re-start the channel program (after verify- <<00769>>01600000
ing that the printer is still on-line).                        <<00769>>01605000
  For normal requests (all  but  2607  off-lines),  there  are <<00769>>01610000
three controlling flags:                                       <<00769>>01615000
1.  A PRE'TO'POSTspace flag, indicating a mode 3 operation.    <<00769>>01620000
2.  A PRESPACE flag, indicating a mode 2 operation.            <<00769>>01625000
3.  A LINES'LEFT'OVER flag indicating:                         <<01061>>01630000
  a)  Multiple slews of <=15 lines each for slew requests  >15 <<01061>>01635000
      lines on subtype 1, 2 and 3 printers.                    <<01061>>01640000
  b)  Multiple skips to VFC channel 3 (advance one  line  with <<01061>>01645000
      auto  page  eject is standard) when a "0" (double space) <<01061>>01650000
      or "-" (triple space) carriage control character is  re- <<01061>>01655000
      ceived and the NO'AUTO'PAGE eject bit (IOQ(QPAR2).(14:1))<<01061>>01660000
      is off.                                                  <<01061>>01665000
    This flag operates in any of modes 1-4.                    <<01061>>01670000
The continuation  section  then  operates  as  follows  (after <<01061>>01675000
checking for grossities such as transfer and timeout errors):  <<01061>>01680000
                                                               <<01061>>01685000
  IF TALLY WENT OFFLINE THEN                                   <<01061>>01690000
    SET TALLY'NOT'READY (special flag saying so).              <<01061>>01695000
                                                               <<01061>>01700000
  IF PRE'TO'POST THEN                                          <<01061>>01705000
    BEGIN  (dumped last line, now do what we came for)         <<01061>>01710000
    CLEAR PRE'TO'POST.                                         <<01061>>01715000
    RE-DIRECT CHANNEL PROGRAM TO BUFFER FILL SECTION,          <<01061>>01720000
      IT WILL AUTOMATICALLY PRINT AFTER FILLING BUFFER.        <<01061>>01725000
    SEE IF PRINTER IS STILL ON LINE (assume yes for now).      <<01061>>01730000
    RE-START CHANNEL PROGRAM.                                  <<01061>>01735000
    END                                                        <<01061>>01740000
$PAGE                                                          <<01061>>01745000
  IF LINES'LEFT'OVER <> 0 THEN                                 <<01061>>01750000
    IF MULTIPLE SLEWS OF <=15 LINES                            <<01061>>01755000
      THEN IF LINES'LEFT'OVER > 15                             <<01061>>01760000
        THEN                                                   <<01061>>01765000
           BEGIN                                               <<01061>>01770000
           REDUCE LINES'LEFT'OVER BY 15.                       <<01061>>01775000
           SPACE 15 MORE LINES (if printer on line).           <<01061>>01780000
           END                                                 <<01061>>01785000
        ELSE                                                   <<01061>>01790000
           BEGIN                                               <<01061>>01795000
           SPACE LINES'LEFT'OVER MORE LINES.                   <<01061>>01800000
           SET LINES'LEFT'OVER TO 0 (to end this loop).        <<01061>>01805000
           END                                                 <<01061>>01810000
      ELSE                                                     <<01061>>01815000
         BEGIN (multiple skips to channel 3)                   <<01061>>01820000
         REDUCE LINES'LEFT'OVER BY 1.                          <<01061>>01825000
         DO ONE SKIP TO VFC CHANNEL 3 (if on line)             <<01061>>01830000
         END                                                   <<01061>>01835000
                                                               <<01061>>01840000
  IF PRESPACE (mode 2)                                         <<01061>>01845000
    THEN RE-DIRECT TO BUFFER FILL SECTION AND GO DO IT.        <<01061>>01850000
                                                               <<01061>>01855000
  CLEAN UP AND EXIT if none of the above.                      <<01061>>01860000
                                                               <<01061>>01865000
It can be seen that the channel  program  is  always  properly <<01061>>01870000
configured when we leave here, whether we continue the request <<01061>>01875000
or complete it and come back in for the next request.   There- <<01061>>01880000
fore, if the printer should be off-line when we check it (just <<01061>>01885000
before starting the channel program), we can always react  the <<01061>>01890000
same  way  (except for Tally, see below), namely to notify the <<01061>>01895000
operator and wait for  him/her  to  put  the  printer  on-line <<01061>>01900000
again.  We can then begin or continue our request.             <<01061>>01905000
  If we are returning from a Not Ready wait, we may  find  the <<LB.09>>01910000
absolute  memory  address  we put in the channel program is no <<LB.09>>01915000
longer valid. This is because SIODM (see Structure of IOLPRT0) <<LB.09>>01920000
unfreezes the data segment containing our buffer when we enter <<LB.09>>01925000
SIODM's Not Ready wait state.  This in turn allows the  Memory <<LB.09>>01930000
Manager  to  swap out the data segment rather than tie up real <<LB.09>>01935000
memory while the printer is idle. The data segment is returned <<LB.09>>01940000
to real memory before the driver is called again, but  (usual- <<LB.09>>01945000
ly) not at the same address. When we come back on line, there- <<LB.09>>01950000
fore, the channel program is updated with new addresses if re- <<LB.09>>01955000
quired by the current request.                                 <<LB.09>>01960000
  The Tally presents a unique problem.  When it goes  on-line, <<01061>>01965000
it still has a line to print, and immediately sets about doing <<01061>>01970000
it.  If we check the printer immediately,  its  Demand  signal <<01061>>01975000
will be false, causing us to assume that it is still off-line, <<01061>>01980000
and we will report it as such.  The operator will be confused, <<01061>>01985000
because s/he can see it is really on-line.  So, for Tally  on- <<01061>>01990000
ly,  we  institute a three-second delay when it comes on line, <<01061>>01995000
just to get that line out, THEN we  recheck  the  printer  and <<01061>>02000000
continue.  Three seconds may be required if the buffered print <<01061>>02005000
command skips an entire page (Tally's are SLOW).               <<01061>>02010000
  Now you know the major pitfalls to avoid.   Minor  ones  are <<01061>>02015000
commented on in the body of the text.  You're on your own now. <<01061>>02020000
Good luck!                                                     <<01061>>02025000
$PAGE                                                                   02030000
Structure of IOLPRT0:                                                   02035000
  IOLPRT0, together with the SIO Device Monitor (SIODM) constitute  a   02040000
standard  MPE Type 1 I/O Driver/Monitor, which means that it does not   02045000
run  in  its  own  process,  but  executes  on  any  stack.    During   02050000
initialization   it   executes  on  PROGEN's  stack,  during  request   02055000
initiation it executes on  ATTACHIO's  stack,  and  during  interrupt   02060000
processing  it executes on the Interrupt Control Stack (ICS).  Type 1   02065000
monitors have other requirements which differentiate them from Type 2   02070000
and Type 3 monitors.  A more complete description may be found in the   02075000
MPE/30 I/O System IMS, dated December 12, 1975.                         02080000
  IOLPRT0 consists of a global area, three procedures (LPDRVR, <<00769>>02085000
CHECK'STATUS and LPINIT) which are the guts of the driver, and <<00769>>02090000
an "outer block" which is really a linkage area  for  INITIAL.          02095000
The  global  area  contains three arrays.  The first of these,          02100000
DRIVER'CONFIG, specifies the size of the other two as well  as          02105000
providing  some  other  parameters for INITIAL.  It is deleted          02110000
after INITIAL is through with it.  The other  two  arrays  are          02115000
the  Device  Information  Table (DIT) and the unconfigured SIO          02120000
channel program area.  INITIAL will put each of these  in  the          02125000
area  of  memory where it belongs.  The linkage area specifies          02130000
the procedure labels  (p-labels)  of  the  associated  monitor          02135000
(SIODM), the request initiator (LPDRVR), the request completor          02140000
(again LPDRVR), the initialization procedure  (LPINIT,  called          02145000
by PROGEN at system startup) and the interrupt handler (GIP).           02150000
  IOLPRT0 cannot be readily understood without a good picture of  the   02155000
DIT  and  the  IOQ  as  they apply to line printers, and so these are   02160000
shown pictorially and described on the  next  few  pages.   Following   02165000
this  is  a  summary of supported functions and the statuses returned   02170000
when a request is complete.                                             02175000
$PAGE                                                                   02180000
                   Device Information Table (DIT)                       02185000
                   ------------------------------                       02190000
                                                                        02195000
                                                                        02200000
  There is one  DIT  per  physical  device.   If  a  physical  device   02205000
represents more than one logical device, the logical device number is   02210000
obtained from the IOQ element.  The following diagram shows  the  DIT   02215000
used for IOLPRT0.                                                       02220000
                                                                        02225000
     0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15    MNEMONIC         02230000
   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+                    02235000
  0| 0| 0|AC|RQ| 0| 0| 0|IO|AK|PS|NE|TF|   STATE   |   DFLAG            02240000
   +--+--+--+--+--+--+--+--+--+--+--+--+-----------+                    02245000
  1| SYSDB relative pointer to the DIT for the next|   DLINK            02250000
   | device requesting this resource or service    |                    02255000
   +-----------------------------------------------+                    02260000
  2| SYSDB relative pointer to the first IOQ in    |   DIOQP            02265000
   | request list for this device                  |                    02270000
   +--------+--------------------------------------+                    02275000
  3|        | Phys unit #  | Logical device number |   DLDEV            02280000
   +--------+--------------------------------------+                    02285000
  4| SYSDB relative pointer to Device Linkage Table|   DDLTP            02290000
   +-----------------------------------------------+                    02295000
  5| SYSDB relative ptr to Interrupt Linkage Table |   DILTP            02300000
   +-----------------------------------------------+                    02305000
  6| Controller interrupt status.  Set by GIP each |   DSTAT            02310000
   | time it processes an interrupt for this DIT.  |                    02315000
   | See individual field descriptions on nxt page.|                    02320000
   +-----------------------------------------------+                    02325000
  7| Hardware error pointer. Set when the driver   |   DSERR   <<01339>>02330000
   | detects an error.  Whenever <> 0, the driver  |                    02335000
   | monitor logs an I/O error and clears this word|                    02340000
   +-----------------------------------------------+                    02345000
%10| Bit 0 is set at completion of 2-second timer. |   DTIME            02350000
   +-----------------------------------------------+                    02355000
%11| Timer Request List Index.  Not used except to |   DTRLX            02360000
   | clear the request after timing out.           |                    02365000
   +-----------------------+-----------------------+                    02370000
%12|                       |Last byte if odd bytcnt|   DLAST            02375000
   |                       | Data byte for VFC or  |                    02380000
   |                       | left margin download  |                    02385000
   +--+--+--+--+-----------+-----------------------+           <<00464>>02390000
%13|VF|PF|BT|TL|Left margin| Vertical Format Code  |   DVFC1   <<00769>>02395000
   |MD|RS|JB|NR|           |                       |           <<00769>>02400000
   +--+--+--+--+-----------+-----------------------+           <<00464>>02405000
%14| Lines left to skip    | %202 (2608) or %102.  |   DVFC2   <<00769>>02410000
   | (subtypes 1, 2, >15   | Skip to channel 3 pre-|           <<00769>>02415000
   | line slew request)    | to postspace print.   |           <<00769>>02420000
   +-----------------------+-----------------------+                    02425000
%15|       HARDWARE ERROR LOGGING STATUS           | DLOGERROR <<01339>>02430000
   +-----------------------------------------------+           <<01339>>02435000
%16| DVR DEPENDENT FLAGS =>   |PS|NE|TF|           |   DDF              02440000
   +--+--+--+--+--+--+--+--+--+--+--+--+-----------+                    02445000
$PAGE                                                                   02450000
DFLAG.AC - Active.  A monitor is currently servicing this device. *     02455000
DFLAG.RQ - Request.  A service request is pending while  the  monitor   02460000
             is active. *                                               02465000
DFLAG.IO - An I/O channel program is in progress.  Decrement SIOCOUNT   02470000
             and check for multiple channels when complete. *           02475000
DFLAG.AK - Interrupt Acknowledge.  An interrupt has occurred. *         02480000
DDF  .PS - Prespace.  The last request was  a  prespace  (space  then   02485000
             fill buffer) operation.                                    02490000
DDF  .NE - Not Empty.  The print buffer is not empty.  Causes a print   02495000
             when changing from pre- to postspace or before  ejecting   02500000
             a page for a File Open, File Close or Device Close.        02505000
DDF  .TF - Top of Form.  The  last  request  ended  with  a  skip  to   02510000
             channel 1 (page eject).                                    02515000
                                                                        02520000
           * Not examined or modified by IOLPRT0.                       02525000
                                                                        02530000
DFLAG.STATE - State of the device monitor.  Specifies the next action   02535000
                to be taken by SIODM in servicing  the  request.  Not   02540000
                used within IOLPRT0.                                    02545000
                                                                        02550000
DSTAT.(0:1) - SIO OK. Set when no SIO channel program is in progress,   02555000
                that is, it is OK to start one.                         02560000
     .(1:1) - WIO OK.  Set when it is OK to execute a WIO instruction   02565000
                or  a  doubleword  WRITE  channel  order.  If  clear,   02570000
                indicates that a one word transfer is in progress.      02575000
     .(2:1) - Interrupt Pending.  If set, indicates one or more  bits   02580000
                of the Interrupt Status Byte (DSTAT.(8:8) are set.      02585000
     .(3:2) - U.I. Transfer State.  Used mostly for hardware mainten-   02590000
                ance. See U.I. card manual (30051-90001) for details.   02595000
     .(5:1) - Device   Flag.  Indicates   a   print-and-advance-paper   02600000
                sequence in progress.  Since the  2608  buffers  such   02605000
                commands,  this signal may be shorter than with other   02610000
                printers.                                               02615000
     .(6:1) - Always 0.  DSTAT.(8:8) always  contains  the  Interrupt   02620000
                Status Byte.                                            02625000
     .(7:1) - Not used.  Always 0.                                      02630000
     .(8:3) - Varies among HP-supported line  printers  according  to   02635000
                the table below:                                        02640000
                                                                        02645000
  SUBTYPE   MODEL(S)          BIT 8     BIT 9     BIT 10                02650000
  -------   --------          -----     -----     ------                02655000
                                                                        02660000
     0      2610, 2614        LINE      READY     NOT                   02665000
                              PRINTED             READY                 02670000
                                                                        02675000
     1      2607              Not       READY     NOT                   02680000
                              used                READY                 02685000
                                                                        02690000
     2      2613, 2617, 2618, Not       READY     NOT                   02695000
            2619              used                READY                 02700000
                                                                        02705000
     3      2617J (KATAKANA)  Not       READY     NOT                   02710000
                              used                READY                 02715000
                                                                        02720000
     4      2608              ON        NOT       VFC                   02725000
                              LINE      READY     CHAN 9                02730000
$PAGE                                                                   02735000
    .(11:1) - Data Transfer Interrupt bit.  Always 0.                   02740000
    .(12:1) - Not used.  Always 0.                                      02745000
    .(13:1) - Programmed Interrupt bit.  True  if  interrupt  request   02750000
                was generated by:                                       02755000
              a)  SIN machine instruction,                              02760000
              b)  INTERRUPT channel order, or                           02765000
              c)  END-WITH-INTERRUPT channel order.                     02770000
    .(14:1) - Transfer Error Interrupt bit.  True  if  interrupt  was   02775000
                generated by:                                           02780000
              a)  an illegal memory address,                            02785000
              b)  a memory parity error, or                             02790000
              c)  a multiplexer parity error during data xfr to  U.I.   02795000
    .(15:1) - Time-out Interrupt bit.  Set if 5-second timer on  U.I.   02800000
                card  is  enabled,  then  times  out  without   being   02805000
                cleared.                                                02810000
                                                                        02815000
DLAST.(8:8) - Request dependent.  If  a  print  request  has  an  odd   02820000
                number of bytes, this word holds the final byte.  For   02825000
                VFC downloads, contains the associated data  byte  (6   02830000
                or 8 lines per inch and number of lines in VFC).  For   02835000
                left margin downloads, also contains  the  associated   02840000
                data byte (the number of columns to offset).            02845000
DVFC1.(0:1) - VFC Modified.  2608 only.  Indicates that  an  external   02850000
                VFC has been downloaded into the 2608.                  02855000
DVFC1.(1:1) - Power Fail/Reset.  2608 only.  The 2608 has suffered  a   02860000
                Power  Failure or someone has pressed the front panel   02865000
                Reset button. In either case, the printer's operating   02870000
                environment has been destroyed, and must be  reloaded   02875000
                by the operator.                                        02880000
DVFC1.(2:1) - Between Jobs.  Set when a  Device  Close  is  executed,   02885000
                cleared when an FOPEN is performed.  2608 Power Fail/   02890000
                Master Reset's will be cleared but not reported while   02895000
                this  bit is set (thus avoiding an extraneous console   02900000
                message when the printer is powered up).                02905000
DVFC1.(3:1) - TALLY'NOT'READY.  Set when an off-line condition <<00769>>02910000
              is detected on a  2607.  Causes  a  three-second <<00769>>02915000
              delay when the 2607 comes back on-line.          <<00769>>02920000
DVFC1.(4:4) - Left margin offset (2608  only).  Stored  during <<00770>>02925000
                each  :DOWNLOAD  which specifies a left margin <<00770>>02930000
                and restored to printer following a 2608 power <<00770>>02935000
                fail or reset.  Set to 0 when system  is  ini- <<00770>>02940000
                tialized.                                      <<00770>>02945000
DVFC1.(8:8) - Request dependent.  Contains the carriage control  byte   02950000
                sent to the printer during a print request.             02955000
$PAGE                                                                   02960000
DVFC2.(0:8) - LINES'LEFT'OVER.  Has two functions:             <<01061>>02965000
            1)  The 2607/13/17/18/19 can only  slew  (skip)  a <<01061>>02970000
                maximum  of  15  lines  per print command (not <<01061>>02975000
                counting  VFC  skips,  which  can  be  of  any <<01061>>02980000
                length).    Slew  requests  > 15 lines must be <<01061>>02985000
                broken up.  This  byte  holds  the  number  of <<01061>>02990000
                lines  (greater  than  15)  which remain to be <<01061>>02995000
                slewed at any point of a  request  to  such  a <<01061>>03000000
                printer,  or  0 if the number of lines to skip <<01061>>03005000
                is <= 15.  This mechanism is not  needed  (and <<01061>>03010000
                this  field  is  therefore 0) for CDC and 2608 <<01061>>03015000
                line printers, which can slew up to  63  lines <<01061>>03020000
                at a time.                                     <<01061>>03025000
            2)  The carriage control  characters  "0"  in  "-" <<01061>>03030000
                specify double and triple spacing, respective- <<01061>>03035000
                ly.  But if you  use  the  equivalent  channel <<01061>>03040000
                skip,  you get skips to the next odd and third <<01061>>03045000
                lines, respectively, which is not the same  as <<01061>>03050000
                double  and  triple spacing.  If you slew (ad- <<01061>>03055000
                vance paper) 2 or  3  lines,  you  can  easily <<01061>>03060000
                print  over the paper perforations unless your <<01061>>03065000
                program watches out for such things.  We avoid <<01061>>03070000
                this by examining the NO'AUTO'PAGE  eject  bit <<01061>>03075000
                (IOQ(QPAR2).(14:1)).    If it is set, then the <<01061>>03080000
                request is treated  like  a  normal  slew  and <<01061>>03085000
                LINES'LEFT'OVER  is  not used.  If it is clear <<01061>>03090000
                (auto eject desired),  then  we  simulate  the <<01061>>03095000
                multiple line skip by doing two ("0") or three <<01061>>03100000
                ("-") skips to channel 3 (single  spaces  with <<01061>>03105000
                auto  page  eject  for  the standard VFC).  In <<01061>>03110000
                this case, LINES'LEFT'OVER holds the number of <<01061>>03115000
                such single spaces remaining in the request.   <<01061>>03120000
DVFC2.(8:8) - %202 for 2608, %102 otherwise.  Causes skip to  channel   03125000
                3  (single  space  with  auto page eject).  Used when   03130000
                last request left data in print buffer (prespace) and   03135000
                current operation  is  postspace.  Buffer  is  dumped   03140000
                first, using this byte as carriage control.             03145000
$PAGE                                                                   03150000
                       I/O QUEUE ELEMENT (IOQ)                          03155000
                       -----------------------                          03160000
                                                                        03165000
                                                                        03170000
     0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15    MNEMONIC         03175000
   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+                    03180000
  0|      Request dependent flags (see below)      |   QFLAG            03185000
   +--+--+--+--+--+--+--+--+--+--+--+--+-----+--+--+                    03190000
  1| SYSDB relative pointer to next IOQ element.   |   QLINK            03195000
   | Points to first word of element.              |                    03200000
   +-----------------------+-----------------------+                    03205000
  2| Physical unit number  | Logical device number |   QLDEV            03210000
   +--------------------+--+-----+-----+--+--+--+--+           <<00571>>03215000
  3|                    | WAITFLD|     |RT|MC|PS|PP|   QMISC   <<00769>>03220000
   +--+-----------------+--------+-----+--+--+--+--+           <<00571>>03225000
  4| S| If QFLAG.(3:1) is clear then this is the   |   QDSTN            03230000
   |  | DST number of the target data segment.  If |                    03235000
   |  | S is set, QADDR is DB relative.            |                    03240000
   +--+--------------------------------------------+                    03245000
  5| Offset in the data segment or system buffer   |   QADDR            03250000
   | table to the target data buffer.              |                    03255000
   +-----------------------+-----------------------+                    03260000
  6|       Not used        | Function code for     |   QFUNC            03265000
   |                       | this request.  See    |                    03270000
   |                       | next section.         |                    03275000
   +-----------------------------------------------+                    03280000
  7| On initiation, specifies the word count (>0)  |   QWBCT            03285000
   | or byte count (<0).  At completion of the     |                    03290000
   | request this location contains the actual     |                    03295000
   | transmission count in the same units (bytes   |                    03300000
   | or words) as in the request.  The count is    |                    03305000
   | truncated to produce a max of 256 characters. |           <<00464>>03310000
   +-----------------------------------------------+                    03315000
%10|    Parameter 1 of QFUNC.  See next section.   |   QPAR1            03320000
   +-----------------------------------------------+                    03325000
%11|    Parameter 2 of QFUNC.  See next section.   |   QPAR2            03330000
   +-----------------------+--------------+--------+                    03335000
%12|         PCBN          |  QUALIFIER   | STATUS |   QSTAT            03340000
   +-----------------------+--------------+--------+                    03345000
                                                                        03350000
QFLAG - Request dependent flags                                         03355000
                                                                        03360000
Bit 0  .ABORT     - Request has been aborted  externally,  either  by   03365000
                    the operator or a system intrinsic.                 03370000
Bit 1  .SPECIAL   - Not used.                                           03375000
Bit 2  .DIAG      - Not used.                                           03380000
Bit 3  .SYSBUFRS  - Target is a system-buffer-relative index  to  the   03385000
                    data buffer. *                                      03390000
Bit 4  .IOWAKE    - Wake caller on completion of request. *             03395000
Bit 5  .BLOCKED   - Blocked  I/O.   The  caller is waited in ATTACHIO   03400000
                    until the request is completed. Implies IOWAKE. *   03405000
Bit 6  .COMPLETED - Request   has  been  completed,  and  the  caller   03410000
                    awakened if s/he had requested (with IOWAKE). *     03415000
Bit 7  .DATAFRZN  - If  set,  then  the  data  segment  has been made   03420000
                    present and frozen in memory.  Set by the  memory   03425000
                    management  routines  (MAM)  when  a  MAKEPRESENT   03430000
                    request is successfully completed. *                03435000
Bit 8  .MAMERRORD - An error has occurred while  MAM  was  trying  to   03440000
                    make  the  target data segment present and freeze   03445000
                    it in memory. *                                     03450000
Bit 9  .PREQ      - Not used.                                           03455000
Bit 10 .SFAIL     - Delayed failure of SIO instruction.  If a call to   03460000
                    STARTIO  resulted  in  the request being added to   03465000
                    the channel queue, this bit  indicates  that  the   03470000
                    SIO  instruction  failed  when  the  request  was   03475000
                    selected for execution.                             03480000
Bit 11 .PFAIL     - The request was aborted because of a system power   03485000
                    failure.                                            03490000
Bits12-13 .PREMPT - Not used.                                           03495000
Bit 14 .          - Not used.                                           03500000
Bit 15 .MSGDONE   - Not used.                                           03505000
                                                                        03510000
QMISC.WAITFLD - This  field  contains  a  code describing the current   03515000
                idle state of the driver.  The driver orients  itself   03520000
                at  each  entry,  based  on  the state of this field.   03525000
              0 - The current entry is the start of a new request.      03530000
              1 - The  normal  state  while  waiting for a completion   03535000
                  interrupt of a print, fill or control operation.      03540000
              2 - An SIO channel program was in progress  when <<00769>>03545000
                  an asynchronous interrupt (usually an exter- <<00769>>03550000
                  nal abort) occurred, or a 2607  printer  was <<00769>>03555000
                  placed  on-line  after  going off-line while <<00769>>03560000
                  printing.  The driver enters this state  and <<00769>>03565000
                  waits for three seconds for the channel pro- <<00769>>03570000
                  gram or 2607 printer to complete, so as  not <<00769>>03575000
                  to  pose  control conflicts to the U.I. card <<00769>>03580000
                  between the driver and the program.          <<00769>>03585000
              3 - A  Not  Ready,  Off  Line  or Paper Out (or Jammed)   03590000
                  condition has been detected.  The request  will  be   03595000
                  continued   or   retried   when  the  operator  has   03600000
                  corrected the condition and placed the  printer  on   03605000
                  line.                                                 03610000
              4 - A 2607 (Tally) printer has come on-line  af- <<00769>>03615000
                  ter going off-line while printing.  One line <<00769>>03620000
                  of data is buffered in  the  printer.   This <<00769>>03625000
                  state  causes the driver to shift to state 2 <<00769>>03630000
                  to allow the 2607 to  print  and  space  the <<00769>>03635000
                  buffered  line  before  sending  it the next <<00769>>03640000
                  line.                                        <<00769>>03645000
QMISC.(12:1)  - RETRY (RT).  Kludge to catch an LDEV configured as  a   03650000
                2608 when the physical device is a different subtype.   03655000
                Prevents Master Clear'ing and retrying a request more   03660000
                than once when the Power Fail/Reset device status bit   03665000
                is "set" by a non-2608.                        <<00571>>03670000
QMISC.(13:1)  - MASTER'CLEAR (MC).  Set when  a  2608  Master  Reset,   03675000
                required  because  of  a printer Power Fail/Reset, is   03680000
                configured and executed.                                03685000
QMISC.(14:1)  - PRESPACE (PS). The current operation is a pre- <<00769>>03690000
                space (space then print) request.  This bit a- <<00769>>03695000
                lerts the continuation  section  to  fill  the <<00769>>03700000
                print buffer after spacing.                    <<00769>>03705000
$PAGE                                                          <<00769>>03710000
QMISC.(15:1)  - PRE'TO'POST (PP). The previous request was a prespace   03715000
                operation while the current operation is a postspace.   03720000
                                                               <<00769>>03725000
QSTAT.PCBN    - The Process Control Block (PCB) number of the process   03730000
                which made this request.  If zero, the request is not   03735000
                associated with any process, and the IOQ  element  is   03740000
                to  be  returned  by  the system when the request has   03745000
                completed. *                                            03750000
QSTAT.STATUS  - General status.  Indicates the  final  state  of  the   03755000
                request.  The following codes are used:                 03760000
                  0 - Not started, or awaiting completion.              03765000
                  1 - Successful completion.                            03770000
                  2 - Not used.                                         03775000
                  3 - Unusual, but recoverable,  condition  (such  as   03780000
                      Request Aborted Externally).                      03785000
                  4 - Irrecoverable  error  (such  as  SIO   failure,   03790000
                      memory parity error, etc.).                       03795000
QSTAT.QUALIFIER - A  code  which  further  defines  or  qualifies the   03800000
                  general status. See the section after the next one.   03805000
                                                                        03810000
                  * Not examined or modified by IOLPRT0.                03815000
                                                               <<00770>>03820000
  The fix denoted by the number in the right margin is an  en- <<00770>>03825000
hancement.   This enhancement deletes the Master Clear hereto- <<00770>>03830000
fore sent to a 2608 line printer as part of the  Device  Close <<00770>>03835000
function.  The Master Clear was originally put in to guarantee <<00770>>03840000
that a previous output file using a special print  environment <<00770>>03845000
(VFC,  left  margin,  etc.) would not affect the current file. <<00770>>03850000
Unfortunately, we did not at the same time  give  the  user  a <<00770>>03855000
method  of  maintaining  a  custom environment throughout many <<00770>>03860000
output files, and many users operate in this  fashion.   Their <<00770>>03865000
complaints  have  prompted  this  enhancement which, in retro- <<00770>>03870000
spect, is far more consistent with the other printers.  Once a <<00770>>03875000
VFU tape has been installed in a 2617 (for example), it  stays <<00770>>03880000
there  until  replaced.  The same will now be (logically) true <<00770>>03885000
for a 2608.  The only difference is that 2617  VFU  tapes  can <<00770>>03890000
survive  a  power failure, whereas 2608 VFC's and left margins <<00770>>03895000
cannot.  Destruction of a 2608's custom  environment  will  be <<00770>>03900000
reported  to  the associated user or to the console, as in the <<00770>>03905000
past, and it will be up to that user to restore the lost envi- <<00770>>03910000
ronment, until a more comprehensive recovery mechanism is  de- <<00770>>03915000
veloped.                                                       <<00770>>03920000
  One exception to the above -- 2608 left margin settings will <<00770>>03925000
be maintained by the driver.  Should the 2608 be reset, either <<00770>>03930000
because of a power failure or the RESET button being  pressed, <<00770>>03935000
the  most  current  left  margin  sent  to the printer via the <<00770>>03940000
:DOWNLOAD command will be restored to the  printer.   This  is <<00770>>03945000
done  both as a convenience to the user (read "operator"), and <<00770>>03950000
to allow us to keep the "between jobs" concept,  whereby  2608 <<00770>>03955000
Master  Resets  are  not  reported if they occur between jobs. <<00770>>03960000
Since left margin settings are also destroyed by a Master  Re- <<00770>>03965000
set, we would have to report them between jobs as well as dur- <<00770>>03970000
ing jobs if the driver did not maintain the left  margin  set- <<00770>>03975000
ting  on  its  own.  Note that if a custom VFC is destroyed by <<00770>>03980000
the Master Reset, it will be reported as a  "VFC  Initialized" <<00770>>03985000
condition, no matter when it occurs.                           <<00770>>03990000
$PAGE                                                                   03995000
  The following table summarizes the tasks (functions)  supported  by   04000000
IOLPRT0:                                                                04005000
                                                                        04010000
                                                                        04015000
  OPERATION  QFUNC  PARAMETERS (QPAR1, QPAR2, QWBCT)                    04020000
  --------------------------------------------------                    04025000
                                                                        04030000
    WRITE      1     QPAR1 -- Vertical Format Specification.            04035000
                     QPAR2 -- Mode control flags.                       04040000
                     QWBCT -- <0 ==> bytes,  >0  ==>  words,  =0  ==>   04045000
                              advance paper only.                       04050000
                                                                        04055000
    FILE OPEN  2     No params.  Page eject if not already at top  of   04060000
                     form.                                              04065000
                                                                        04070000
    FILE CLOSE 3     Same as FILE OPEN.                                 04075000
                                                                        04080000
    DEVICE     4     Same as FILE OPEN.                        <<00770>>04085000
    CLOSE                                                      <<00770>>04090000
                                                               <<00770>>04095000
                                                                        04100000
    DOWNLOAD  %100   QPAR1 -- 6 or 8  (lines  per  inch).  Any  other   04105000
    VFC                       value ==> 6.                              04110000
    (2608 only)      QPAR2 -- Not used.                                 04115000
                     QWBCT -- Form (VFC) length.  <0  ==>  bytes,  >0   04120000
                              ==>  words,  =0  ==>  reload  printer's   04125000
                              internal VFC.                             04130000
                     BANK/ -- Address of VFC buffer to be sent to the   04135000
                   BUFADDR    printer.                                  04140000
                                                                        04145000
    SET LEFT  %101   QPAR1 -- Logical to physical column offset, 0 to   04150000
    MARGIN                    15.  Any other value ==> 15.              04155000
    (2608 only)      QPAR2 -- Not used.                        <<00770>>04160000
                                                               <<00770>>04165000
                                                                        04170000
  If function code %100 or %101 is sent to a printer which  is          04175000
not  a  2608, or if any function code not listed above is sent          04180000
to any printer, it will be rejected as an invalid request (see          04185000
completion statuses below).  Should you want to add new  func- <<00769>>04190000
tions,  they can be inserted where the appropriate comment in- <<00769>>04195000
dicates (just before the start of the completion section).     <<00769>>04200000
$PAGE                                                                   04205000
  For QFUNC = 1 (write), QPAR1 and QPAR2 are interpreted as  follows:   04210000
                                                                        04215000
  QPAR1          MEANING                                                04220000
  ------------------------------------------------------------          04225000
                                                                        04230000
  %53,       ASCII "+", suppress space (single space on 2607)  <<00770>>04235000
  %55,       ASCII "-", triple space, with/without auto eject  <<01061>>04240000
  %60,       ASCII "0", double space, with/without auto eject  <<01061>>04245000
  %61,       ASCII "1", top of form*                                    04250000
                                                                        04255000
  %200-%277, slew n-%200 lines (0-63)  (0 ==> 1 on 2607)       <<00770>>04260000
  %300-%317, skip to VFC channel N-%277 (within limits of printer)      04265000
                                                                        04270000
  %320,      append to current buffer without printing                  04275000
                                                                        04280000
   1,        the Vertical Format character is the first byte  in  the   04285000
             data  buffer. It is not sent to the printer as data.  If   04290000
             the first byte is not one of the above, a  single  space   04295000
             is  assumed.  Use QPAR2.(14:1) to determine if the space   04300000
             is with or without automatic  page  eject.   The  format   04305000
             character  is  included in the word/byte count in QWBCT,   04310000
             therefore QWBCT may not be 0  if  QPAR1  =  1.   Such  a   04315000
             condition   will  cause  an  immediate  completion  with   04320000
             Invalid Request status (QSTAT.(8:8) = 4).                  04325000
                                                                        04330000
  ANY OTHER, assume single space.  Check QPAR2.(14:1), as above.        04335000
                                                                        04340000
  *   Page ejects (skips to VFC channel 1)  are  suppressed  whenever   04345000
      the previous operation ended with a page eject.                   04350000
                                                                        04355000
QPAR2 -- Mode control flags.  These are two 1-bit flags.                04360000
  QPAR2.(15:1) -- Prespace flag.   If  set,  the  request  is  for  a   04365000
space-then-print,  or prespace, operation.  Since all HP printers are   04370000
mechanically postspace printers, prespace  mode  must  be  simulated.   04375000
This  is  done  by printing any previously transmitted data using the   04380000
Vertical Format specification of the current QPAR1, then filling  the   04385000
printer  buffer  (without  printing)  with  the  current  contents of   04390000
BANK/BUFADDR.                                                           04395000
  If  the  Prespace  flag  is  clear,  IOLPRT0  performs  a postspace   04400000
operation, filling the printer buffer from BANK/BUFADDR and  printing   04405000
using the Vertical Format specification of QPAR1.                       04410000
  NOTE:  If a  postspace  operation  follows  a  prespace  operation,   04415000
IOLPRT0  first prints any previously existing data with a skip to VFC   04420000
channel 3 (single space with automatic page  eject  --  QPAR2.(14:1),   04425000
the  no-auto-page-eject flag, is not examined).  It then executes the   04430000
postspace request.                                                      04435000
  QPAR2.(14:1) -- No automatic page eject flag.  If  set,  the <<01061>>04440000
single/double/triple  space  called for by the default/"0"/"-" <<01061>>04445000
carriage control will be executed as a slew, that is,  without <<01061>>04450000
regard to the logical bottom of form or the paper perforation. <<01061>>04455000
If the flag is clear, the default/"0"/"-" carriage control  is <<01061>>04460000
executed as 1/2/3 skips to VFC channel 3.  When using the 6 or <<01061>>04465000
8 lines per inch standard VFC pattern, this causes a  skip  to <<01061>>04470000
the  top  of  the next form if the spacing would go beyond the <<01061>>04475000
logical bottom of form.                                        <<01061>>04480000
$PAGE                                                                   04485000
  The following table lists the possible status  values  returned  by   04490000
IOLPRT0 at request completion:                                          04495000
                                                                        04500000
                                                                        04505000
GENERAL             QUALIFYING   OVERALL                                04510000
(13:3)                (8:5)       (8:8)                                 04515000
----------------------------------------                                04520000
                                                                        04525000
1 - Successful          0           1     Operation    complete,   no   04530000
                                          errors.                       04535000
                                                                        04540000
3 - Unusual             3          %33    Request aborted externally.   04545000
                                                                        04550000
                        6          %63    Power fail abort.             04555000
                                                                        04560000
                       %21         %213   Printer   powered   on   or   04565000
                                          master  cleared.   VFC/left   04570000
                                          margin/top      of     form   04575000
                                          environment     must     be   04580000
                                          restored.                     04585000
                                                                        04590000
                       %27         %273   VFC  has  been   reset   to   04595000
                                          default   at  the  printer.   04600000
                                          Custom VFC environment must   04605000
                                          be restored.                  04610000
                                                                        04615000
4 - Irrecoverable       0           4     Invalid  request  (function   04620000
                                          or parameter.                 04625000
                                                                        04630000
                        1          %14    Transfer error:               04635000
                                          a) Illegal  memory  address   04640000
                                          b) Memory   parity    error   04645000
                                          c) Parity error in transfer   04650000
                                                                        04655000
                        2          %24    Timeout error, printer took   04660000
                                          too long.                     04665000
                                                                        04670000
                        4          %44    SIO failure, couldn't start   04675000
                                          SIO program.                  04680000
                                                                        04685000
                       %12         %124   No  message  link  buffers,   04690000
                                          couldn't  write  message to   04695000
                                          operator console.             04700000
;                                                              <<00464>>04705000
BEGIN                                                                   04710000
$PAGE                                                                   04715000
<<---------------------------- EQUATES ---------------------------->>   04720000
                                                                        04725000
EQUATE                                                                  04730000
                                                                        04735000
<<----------------------- Printer Subtypes ------------------------>>   04740000
                                                                        04745000
CDC                  = 0,                                               04750000
DATAPRODUCTS         = 2,                                               04755000
HP2608               = 4,                                               04760000
KATAKANA             = 3,                          << 2617J >>          04765000
TALLY                = 1,                                      <<00770>>04770000
                                                                        04775000
<<----------------------- Function Codes -------------------------->>   04780000
                                                                        04785000
DEVICE'CLOSE         = 4,                                               04790000
DOWNLOAD'LEFT'MARGIN = %101,                                            04795000
DOWNLOAD'VFC         = %100,                                            04800000
FCLOSE               = 3,                                               04805000
FOPEN                = 2,                                               04810000
WRITE                = 1,                                               04815000
                                                                        04820000
<<---------------------- Completion Statuses ---------------------->>   04825000
                                                                        04830000
GOOD'STATUS          =    1,                                            04835000
INVALID'FUNCTION     =    4,                                            04840000
NO'MSG'BUFF'ERROR    = %124,                                            04845000
OPERATOR'ABORT       =  %33,                                            04850000
POWER'FAIL'ABORT     =  %63,                                            04855000
PWRFL'RESET'ERROR    = %213,                                            04860000
SIO'FAIL'ERROR       =  %44,                                            04865000
TIMEOUT'ERROR        =  %24,                                            04870000
TRANSFER'ERROR       =  %14,                                            04875000
VFC'RESET'ERROR      = %273,                                            04880000
                                                                        04885000
<<------------------------ DITP Parameters ------------------------>>   04890000
                                                                        04895000
DDF                  = %16,   <<DRIVER DEPENDENT FLAGS >>      <<01382>>04900000
DILTP                =   5,   << Interrupt Linkage Table pointer >>     04905000
DLAST                = %12,   << Odd byte of write request,             04910000
                                 # lines of DOWNLOAD VFC request,       04915000
                                 left margin param of LEFT MARGIN       04920000
                                   request or DEVICE CLOSE >>           04925000
DLDEV                =   3,   << Holds logical devno of printer >>      04930000
DLOGERROR            =   13,  <<ERROR LOG STATUS>>             <<01339>>04935000
DSERR                =   7,   << I/O error status if <> 0 >>            04940000
DSTAT                =   6,   << Request completion status >>           04945000
DTIME                = %10,   << Bit 0 set at end of 2-second timer >>  04950000
DTRLX                = %11,   << Timer Request List Index, see above >> 04955000
DVFC1                = %13,   << VFC'MOD bit (0:1), PWRFL'RE->><<00770>>04960000
                                << SET (1:1), BETWEEN'JOBS  >> <<00770>>04965000
                                << (2:1), left margin (4:4), >><<00770>>04970000
                              << carriage control for request (8:8) >>  04975000
DVFC2                = %14,   << LINES'LEFT'OVER (0:8), and >> <<00769>>04980000
                              << %102 (%202, 2608) in (8:8) >> <<00769>>04985000
                              << for pre- to postspace print>> <<00769>>04990000
LP'DIT'SIZE          = %17,   << Number of words in the DIT >> <<01382>>04995000
$PAGE                                                                   05000000
<<------------------------- IOQP Indices -------------------------->>   05005000
                                                                        05010000
QFUNC                =   6,   << Drvr request code (1-4, %100, %101) >> 05015000
QMISC                =   3,   << (7:3) = WAIT'FIELD (driver state),     05020000
                                 (12:1) = RETRY if non-2608 >> <<00769>>05025000
                              << configured as subtype 4    >> <<00769>>05030000
                              << (13:1) = MASTER'CLEAR for 2608's,      05035000
                                 (14:1) = PRESPACE request  >> <<00769>>05040000
                              << (15:1) = PRE'TO'POST write requests >> 05045000
QPAR1                = %10,   << Carriage control param for writes,     05050000
                                 6/8 LPI for Download VFC,              05055000
                                 left marg offset for Dwnld Lft Mrg >>  05060000
QPAR2                = %11,   << Prespace and no auto page eject        05065000
                                   flags for write request. >> <<00770>>05070000
QSTAT                = %12,   << Gets request completion status >>      05075000
QWBCT                =   7,   << Word or byte count for write and       05080000
                                   Download VFC requests >>             05085000
                                                                        05090000
<<------------------------- SIOP Indices -------------------------->>   05095000
                                                                        05100000
<< These equates are arranged so that a change to the channel program   05105000
   length  requires  changing  only references to the block where the   05110000
   change occurred, both here and in the driver.                   >>   05115000
                                                                        05120000
SIO'SETUP            =                        0,               <<00769>>05125000
SIO'VFC              = SIO'SETUP           +  8,               <<00773>>05130000
SIO'PRE'TO'POST      = SIO'VFC             + 14,                        05135000
SIO'BUFFER'FILL      = SIO'PRE'TO'POST     +  6,                        05140000
                                                               <<00769>>05145000
SIO'PRINT'AND'SPACE  = SIO'BUFFER'FILL     + 26,               <<00769>>05150000
SIO'MASTER'CLEAR     = SIO'PRINT'AND'SPACE +  6,                        05155000
SIO'LEFT'MARGIN      = SIO'MASTER'CLEAR    +  4,               <<00770>>05160000
LP'SIO'SIZE          = SIO'LEFT'MARGIN     +  6,                        05165000
LP'SIO'SIZED2        = LP'SIO'SIZE/2, << SIO SIZE / 2 >>       <<01300>>05170000
                                                                        05175000
<<-------------------------- I/O Orders --------------------------->>   05180000
                                                                        05185000
CONTROL              = %40000,                                          05190000
JUMP                 =      0,   << Unconditional jump >>               05195000
                                                               <<00769>>05200000
SETBANK              = %14000,   << Sets memory bank for next I/O >>    05205000
SIOEND               = %30000,   << without interrupt  >>               05210000
SIOENDI              = %34000,   << with    interrupt  >>               05215000
SIOWRT1              = %67777,   << Write one word     >>               05220000
                                                                        05225000
<<------------------------ Driver States -------------------------->>   05230000
                                                                        05235000
COMPLETION'WAIT      = 1,        << Waiting for completion interrupt >> 05240000
LET'PRINTER'FINISH   = 2,        << Waiting for 2-second timer >>       05245000
NEW'REQUEST          = 0,        << State at start of request>><<00464>>05250000
NOT'READY'WAIT       = 3,        << Waiting for oprat to fix printer >> 05255000
WAIT'FOR'TALLY       = 4,        << 3 sec for Tally to print >><<00769>>05260000
$PAGE                                                          <<00769>>05265000
<<------------------------ SIODM States --------------------------->>   05270000
                                                                        05275000
<< These are states returned by the driver to its monitor, SIODM,  to   05280000
   determine SIODM's next operation.                               >>   05285000
                                                                        05290000
INTERRUPT'WAIT       = %13,      << Waiting for completion interrupt >> 05295000
NOT'READY            =   7,      << Waiting for oprat to fix printer >> 05300000
REQUEST'DONE         =   5,      << All done, whether errors or not >>  05305000
                                                               <<00769>>05310000
<<--------------------- IOMESSAGE Parameters ---------------------->>   05315000
                                                                        05320000
<< These numbers represent  message  numbers  within  $SET1  (console   05325000
   operator messages) of the MPE message catalog, CATALOG.PUB.SYS. >>   05330000
                                                                        05335000
GOOD'DOWNLOAD'MSG    = 22,                                     <<00571>>05340000
NOT'READY'MESSAGE    = 11,                                              05345000
PAPER'OUT'MESSAGE    = 14,                                              05350000
PWRFL'RESET'MESSAGE  = 13,                                              05355000
SYS'CONSOLE          =  0,   << Directs message to system console >>    05360000
VFC'RESET'MESSAGE    = 15,                                              05365000
                                                                        05370000
<<------------------------ Miscellaneous -------------------------->>   05375000
                                                                        05380000
BIT'10               =   %40,                                           05385000
ISIOP                =     8,   << ILT pointer to      >>      <<01300>>05390000
                                <<   the SIO channel program >><<01300>>05395000
SYSDB                = %1000,   << Base of system DB area >>            05400000
SYSLPDT              =   %10,   << DB-relative base of logical-to-      05405000
                                     physical device table >>           05410000
                                                                        05415000
ENDEQ                =     0;                                           05420000
                                                               <<00464>>05425000
                                                               <<00464>>05430000
<<---------------- Miscellaneous useful declarations -------------->>   05435000
                                                               <<00464>>05440000
INTEGER X = X,      << Index register >>                       <<00464>>05445000
        S0 = S-0;   << Top of stack >>                         <<00464>>05450000
DOUBLE ARRAY LPDTD(@) = DB + SYSLPDT;   << Starting address of logical- 05455000
                                           to-physical device table >>  05460000
$PAGE                                                                   05465000
<<--------------------------- DEFINES ----------------------------->>   05470000
                                                                        05475000
DEFINE                                                                  05480000
                                                                        05485000
<<------------------------- DITP Fields --------------------------->>   05490000
                                                                        05495000
BETWEEN'JOBS      =(2:1)#,   << of DVFC1             >>        <<00464>>05500000
CCTL              =(8:8)#,   << of DVFC1             >>                 05505000
DEV'STAT'INTRUPT  =(8:3)#,   << of DSTAT             >>                 05510000
DEVICE'FLAG       =(5:1)#,   << of DSTAT             >>        <<00656>>05515000
DLDEVN            =(8:8)#,   << of DLDEV             >>                 05520000
LEFT'MARGIN       =(4:4)#,   << of DVFC1             >>                 05525000
LINES'LEFT'OVER   =(0:8)#,   << of DVFC2             >>        <<00769>>05530000
ONLINE'08         =(8:1)#,   << of DSTAT             >>                 05535000
PRE'TO'POST'CCTL  =(8:8)#,   << of DVFC2             >>        <<00769>>05540000
PWRFL'RESET       =(1:1)#,   << of DVFC1             >>                 05545000
TALLY'NOT'READY   =(3:1)#,   << of DVFC1             >>        <<00769>>05550000
VFC'MOD           =(0:1)#,   << of DVFC1             >>                 05555000
XFER'ERROR        =(14:1)#,  << of DSTAT             >>                 05560000
DITDDF            =DITPL(DDF)#, << DRIVER DEPENDENT FLAGS >>  <<WEOSH>> 05565000
NOT'EMPTY         =(10:1)#,  << of DITDDF             >>       <<01382>>05570000
PRESPACE'LAST     =(9:1)#,   << of DITDDF             >>       <<01382>>05575000
PRESPACE'NOTEMPTY =(9:2)#,   << of DITDDF             >>       <<01382>>05580000
TOP'OF'FORM       =(11:1)#,  << of DITDDF             >>       <<01382>>05585000
                                                                        05590000
<<------------------------- IOQP Fields --------------------------->>   05595000
                                                                        05600000
FUNCT             =(8:8)#,   << of QFUNC             >>                 05605000
MASTER'CLEAR      =(13:1)#,  << of QMISC             >>                 05610000
NO'AUTO'PAGE      =(14:1)#,  << of QPAR2             >>        <<00769>>05615000
PRESPACE          =(14:1)#,  << of QMISC             >>        <<00769>>05620000
PRE'TO'POST       =(15:1)#,  << of QMISC             >>                 05625000
RETRY             =(12:1)#,  << of QMISC             >>        <<00571>>05630000
SIO'FAILURE       =(10:1)#,  << of QFLAG (= IOQP(0)) >>                 05635000
STATS             =(8:8)#,   << of QSTAT             >>                 05640000
SYSTEM'POWER'FAIL =(11:1)#,  << of QFLAG             >>                 05645000
WAIT'FIELD        =(7:3)#,   << of QMISC             >>                 05650000
                                                                        05655000
<<------------------------ STATUS Fields -------------------------->>   05660000
                                                                        05665000
DEFAULT'VFC       =(12:1)#,                                             05670000
NOT'RDY           =(10:1)#,   << Not Ready bit for all but 2608 >>      05675000
ONLINE'NOT'RDY'08 =(8:2)#,    << 2608 On Line and Not Ready bits >>     05680000
PAPER'OUT         =(11:1)#,                                             05685000
POWER'FAIL'08     =(15:1)#,   << 2608 Power Fail bit >>                 05690000
READY             =(9:1)#,    << Ready bit for all but 2608 >>          05695000
READY'NOT'READY   =(9:2)#,    << Ready and Not Ready bits               05700000
                                   for all but 2608 >>                  05705000
READY'NTRDY'NOPAP =(9:3)#,    << Rdy, Not Rdy, Paper Out for CDC >>     05710000
                                                                        05715000
<<------------------------ Miscellaneous -------------------------->>   05720000
                                                                        05725000
ASMB              = ASSEMBLE#,                                          05730000
LOAD'MEMORY       = ASMB (LSEA)#,                                       05735000
SUBTYPE'FIELD     =(12:4)#,   << of LPDT entry for logical device >>    05740000
END'DEF           =0#;                                                  05745000
                                                                        05750000
$PAGE                                                                   05755000
<<------------- Driver linkage area and DIT definition ------------>>   05760000
                                                                        05765000
BYTE ARRAY DRIVER'CONFIG (0:7) = DB :=                                  05770000
                                                                        05775000
  LP'DIT'SIZE,  << The number of words in the DIT >>                    05780000
          1,    << .(10:1) = 0, driver non-resident >>                  05785000
                << .(13:1) = 0, can be 1 only if Type 3 driver >>       05790000
                << .(14:2) = 1, Type 1 driver, executes on any          05795000
                     stack, including the Interrupt Control Stack >>    05800000
          0,    << Not used >>                                          05805000
          0,    << Not applicable to Type 1 drivers >>                  05810000
          0,    << Unit extract instruction, >>                         05815000
          0,    <<   used only in multi-unit controllers >>             05820000
  LP'SIO'SIZED2,<< The number of words in the SIO PGM. / 2 >>  <<01300>>05825000
          0;    << Not used >>                                          05830000
                                                                        05835000
INTEGER ARRAY DIT (0:LP'DIT'SIZE-1) = DB :=                             05840000
                                                                        05845000
          0,    << .(0:1) = 0, device is not a terminal >>              05850000
                << .(1:1) = 0, device is not a disc >>                  05855000
                << .(4:1) = 0, no special interrupt handler >>          05860000
                << .(9:1) = 0, not a moving head disc >>                05865000
  0,0,0,0,0,    << These five words must be 0. >>                       05870000
  0,0,0,0,0,    << Remaining words may be set as desired. >>            05875000
  0,0,                                                         <<01339>>05880000
  0;    <<DLOGERROR>>                                          <<01339>>05885000
$PAGE                                                                   05890000
COMMENT                                                        <<00464>>05895000
  The following array is the unconfigured  SIO  channel  program  for   05900000
IOLPRT0.  It has been set up in task-oriented blocks:          <<00769>>05905000
                                                                        05910000
  1.    SETUP                  Clear interrupts, jump to first task.    05915000
                                                                        05920000
  2.    DOWNLOAD VFC           Used by subtype 4 (2608) only.           05925000
                                                                        05930000
  3.    PRINT AND SPACE        Dump buffer from previous request        05935000
                               during pre- to postspace request.        05940000
                                                                        05945000
  4.    FILL BUFFER            Transfer data to printer, no print.      05950000
                                                                        05955000
  5.    PRINT AND SPACE        Print data and advance paper.   <<00769>>05960000
                               Step 5 is repeated as required  <<00769>>05965000
                               to achieve slewing the request- <<00769>>05970000
                               ed number of lines 15 at a time <<00769>>05975000
                               (<= 15 the last time) for those <<00769>>05980000
                               printers limited to 15-line     <<00769>>05985000
                               slews.                          <<00769>>05990000
                                                                        05995000
  6.    MASTER CLEAR           2608  only.  Clears  the  Power <<00769>>06000000
                               Fail/Master  Reset printer sta- <<00770>>06005000
                               tus bit when detected. Not used <<00770>>06010000
                               otherwise.                      <<00770>>06015000
                                                               <<00770>>06020000
  7.    DOWNLOAD LEFT MARGIN   2608 only. Used during Function <<00769>>06025000
                               %101 or following a Master Clr. <<00770>>06030000
$PAGE                                                          <<00770>>06035000
  The above tasks are configured in the following order, depending on   06040000
the specific function:                                                  06045000
                                                                        06050000
WRITE, PRESPACE:  5 (as many times as required), 4.            <<00769>>06055000
                                                                        06060000
WRITE, POSTSPACE:  4, 5 (as many times as required).           <<00769>>06065000
                                                                        06070000
WRITE, PRE- TO POSTSPACE:  3, 4, 5 (as many times as req'd).   <<00769>>06075000
                                                               <<00769>>06080000
WRITE, PRE- OR POSTSPACE, FILL BUFFER ONLY:  4.                <<00769>>06085000
                                                                        06090000
FOPEN, FCLOSE, DEVICE CLOSE:  5, if not already at top of form.<<00769>>06095000
                                                                        06100000
MASTER CLEAR:  6, 7.                                           <<00769>>06105000
                                                                        06110000
DOWNLOAD VFC:  1.                                                       06115000
                                                                        06120000
DOWNLOAD LEFT MARGIN:  7.                                      <<00769>>06125000
                                                                        06130000
The channel program  originally  was  configured  to  progress <<00769>>06135000
without  interruption  from (3 to) 4 to 5 (pre- to) postspace, <<00769>>06140000
or from 5 to 4 (prespace).  However, I found it impossible  to <<00769>>06145000
properly recover from cycling off-line/on-line while printing. <<00769>>06150000
Each printer behaved a little differently,  depending  on  the <<00769>>06155000
printer  subtype and whether the request was prespace or post- <<00769>>06160000
space.  Therefore the present philosophy was adopted (really a <<00769>>06165000
return to that of the 1831 driver), whereby the driver is  in- <<00769>>06170000
terrupted  and checks status after each physical print command <<00769>>06175000
to the printer.  The driver reconfigures the  channel  program <<00769>>06180000
as required to properly continue the request.                  <<00769>>06185000
;                                                              <<00464>>06190000
$PAGE                                                                   06195000
INTEGER ARRAY SIOPROG (0:LP'SIO'SIZE-1) = DB :=                         06200000
                                                                        06205000
<<-------------------------- 1.  SETUP ---------------------------->>   06210000
                                                                        06215000
  CONTROL,  %40000,    << Clear all outstanding interrupts >>           06220000
  CONTROL,       2,    << Enable new ones >>                   <<00773>>06225000
  SETBANK,       0,    << Start all programs with memory bank 0 >>      06230000
  JUMP   ,       0,    << Jump to start of current program >>           06235000
                                                                        06240000
<<------------ 2.  DOWNLOAD VFC (HP2608 ONLY) --------------------->>   06245000
                                                                        06250000
  CONTROL,    %203,    << VFC Set/Reset command + U.I. timeout >>       06255000
  SIOWRT1,       0,    << 6/8 lines per inch, number of lines >>        06260000
  JUMP   ,       0,    << Changed to JUMP *+1 if line count <> 0,       06265000
                          changed to JUMP "SIOENDI" if count = 0 >>     06270000
  CONTROL,       7,    << Pass VFC contents with data command >>        06275000
  SETBANK,       0,    << Set to bank containing user's buffer >>       06280000
  SIOWRT1,       0,    << Set to line count and buffer address >>       06285000
  SIOENDI, %177777,                                                     06290000
                                                                        06295000
<<-- 3. PRE- TO POSTSPACE BUFFER CLEAR, ONE SPACE W/ AUTO EJECT -->>    06300000
                                                                        06305000
  CONTROL,     %43,    << Print command, changed to %1003 for 2608 >>   06310000
  SIOWRT1,       0,    << Skip to chan. 3, %202, 2608; %102 others >>   06315000
  SIOENDI, %177777,    << Changed to SIOEND, %177777 for CDC >><<00769>>06320000
                                                                        06325000
<<------------- 4.  FILL BUFFER (PRE- OR POSTSPACE) -------------->>    06330000
                                                                        06335000
  SETBANK,       0,    << Set to bank containing user's buffer >>       06340000
  JUMP   ,       0,    << Skip to "CONTROL, 7" if no imbedded CCTL >>   06345000
  CONTROL,       3,    << Write 1st (odd) byte if carriage control >>   06350000
  SIOWRT1,       0,    << There goes the first byte >>                  06355000
  JUMP   ,       0,    << Skip main buffer write if not required >>     06360000
  CONTROL,       7,    << Unpack main buffer except odd last byte >>    06365000
  SIOWRT1,       0,    << Send it to printer >>                         06370000
  JUMP   ,       0,    << Skip to last "SETBANK" if no odd byte >>      06375000
  SETBANK,       0,    << Last (odd) byte, or print command             06380000
                            is always in DIT (bank 0) >>                06385000
  CONTROL,       3,    << Write last (odd) byte >>                      06390000
  SIOWRT1,       0,                                                     06395000
  SETBANK,       0,    << Make sure we're in bank 0 when we leave >>    06400000
  SIOENDI, %177777,    << End if prespace or buffer fill (%320),        06405000
                            JUMP *+1 if postspace >>                    06410000
                                                                        06415000
<<---- 5.  PRINT BUFFER AND SLEW OR SKIP TO CHANNEL ----->>    <<00769>>06420000
                                                                        06425000
  CONTROL,     %43,                                                     06430000
  SIOWRT1,       0,    << Carriage control byte is in DIT >>            06435000
  SIOENDI, %177777,    << Changed to SIOEND if CDC >>          <<00769>>06440000
$PAGE                                                          <<00769>>06445000
<<------- 6.  MASTER CLEAR (SUBTYPE 4, HP2608 ONLY) --------- >>        06450000
                                                                        06455000
  CONTROL,    %503,    << 2608 Master Clear command >>                  06460000
  SIOWRT1,       0,    << Dummy to enable Master Clear command >>       06465000
                                                                        06470000
<<----- 7.  DOWNLOAD LEFT MARGIN (SUBTYPE 4, HP2608 ONLY) ----->>       06475000
                                                                        06480000
  CONTROL,    %703,    << 2608 Buffer Clear/Left Margin command >>      06485000
  SIOWRT1,       0,    << Left margin offset >>                <<00770>>06490000
  SIOENDI, %177777;    << End of SIO channel program >>                 06495000
$PAGE                                                                   06500000
<<------------------- External Procedure Heads -------------------->>   06505000
                                                                        06510000
<< The following procedures are called by or linked to  IOLPRT0.  See   06515000
   the  HP2608  Support on HP3000 Series II/III ERS for a description   06520000
   of their operation.                                             >>   06525000
                                                                        06530000
PROCEDURE ABORTTIMEREQ (TRLX);                                          06535000
  VALUE TRLX;                                                           06540000
  INTEGER TRLX;   << Timer Request List Index, only used here >>        06545000
  OPTION EXTERNAL;                                                      06550000
                                                                        06555000
PROCEDURE DOCIO(ORDER,DITP);                                            06560000
  VALUE ORDER;   INTEGER ORDER;                                         06565000
  ARRAY DITP;    OPTION EXTERNAL;                                       06570000
                                                                        06575000
PROCEDURE  GIP;   OPTION EXTERNAL;                                      06580000
                                                                        06585000
PROCEDURE HELP;   OPTION EXTERNAL;                                      06590000
                                                                        06595000
PROCEDURE IOFAILURE(DRTN,DITP);                                         06600000
  VALUE DRTN;  INTEGER DRTN;                                            06605000
  ARRAY DITP;  OPTION EXTERNAL;                                         06610000
                                                                        06615000
LOGICAL PROCEDURE IOMESSAGE(SETNO,MSGNO,MASK,P1,P2,P3,P4,P5,            06620000
   DEST,REPLY,OFFSET,DITP,IOTYPE);                                      06625000
VALUE SETNO,MSGNO,MASK,P1,P2,P3,P4,P5,DEST,REPLY,OFFSET,DITP,           06630000
   IOTYPE;                                                              06635000
INTEGER SETNO,MSGNO,MASK,P1,P2,P3,P4,P5,DEST,REPLY,OFFSET,              06640000
   IOTYPE;                                                              06645000
INTEGER POINTER DITP;                                                   06650000
OPTION VARIABLE,EXTERNAL;                                               06655000
                                                                        06660000
PROCEDURE MASTERCLEAR(DITP);                                            06665000
  ARRAY DITP;  OPTION EXTERNAL;                                         06670000
                                                                        06675000
PROCEDURE SIODM(DITP,FLAGS);                                            06680000
  VALUE DITP, FLAGS;   LOGICAL FLAGS;                                   06685000
  POINTER DITP;    OPTION  EXTERNAL;                                    06690000
                                                                        06695000
PROCEDURE STARTIO(DITP,SIOP,QFLAG);                                     06700000
  VALUE  DITP, SIOP, QFLAG;     LOGICAL QFLAG;                          06705000
  POINTER DITP, SIOP;    OPTION EXTERNAL;                               06710000
                                                                        06715000
INTEGER PROCEDURE TIMEREQ (CODE, DIT'ADDRESS, TIME);                    06720000
  VALUE CODE, DIT'ADDRESS, TIME;                                        06725000
  INTEGER CODE;   << %20 to %37, sets bit (CODE-%20) in DIT(8) >>       06730000
  INTEGER DIT'ADDRESS;                                                  06735000
  DOUBLE TIME;  << Desired interval in milliseconds >>                  06740000
  OPTION EXTERNAL;                                                      06745000
$PAGE                                                                   06750000
INTEGER PROCEDURE CHECK'STATUS (DITP, IOQP, DRTNUMB, MESSAGE'FLAG);     06755000
  VALUE DRTNUMB, MESSAGE'FLAG;                                          06760000
  INTEGER ARRAY DITP, IOQP;   << See LPDRVR procedure head... >>        06765000
  INTEGER DRTNUMB;            << ... for descriptions of these >>       06770000
LOGICAL MESSAGE'FLAG;        << Call Not Ready IOMESSAGE only if set >> 06775000
                                                                        06780000
BEGIN                                                                   06785000
COMMENT                                                        <<00770>>06790000
  CHECK'STATUS tests for a number  of  conditions  that  prevent  the   06795000
execution or completion of the current request. Some conditions, such   06800000
as NOT READY, only require suspension until the operator can fix  the   06805000
condition,  then  execution can continue.  Others, such as POWER FAIL   06810000
on a 2608, are unrecoverable in the sense that any remaining part  of   06815000
the request is lost.                                                    06820000
  CHECK'STATUS  builds  a  subtype-independent  word,  STATUS,  shown   06825000
below, which can then be checked by a general routine.  This makes it   06830000
possible to easily add sections to handle new subtypes.                 06835000
  CHECK'STATUS is called before starting or restarting  each  channel   06840000
program  to  make  sure that the printer is operable.  If there is no   06845000
problem, CHECK'STATUS has a value of 0 on return.  If the request can   06850000
be  suspended  for operator intervention, then continue, CHECK'STATUS   06855000
is given a value of %177777.  If an unrecoverable error  exists,  the   06860000
error status value (>0) is returned in  CHECK'STATUS.  Exception:  If   06865000
a  2608  Power  Fail/Reset  is  detected,  CHECK'STATUS just sets the   06870000
PWRFL'RESET bit in DVFC1.  External code is responsible  for  dealing   06875000
with this bit.                                                          06880000
  CHECK'STATUS should only be called if no  SIO  channel  program  is   06885000
active.  Otherwise  the  I/O performed here may conflict with channel   06890000
program I/O orders with unpredictable results.                          06895000
  A table of currently-supported subtypes and their status conditions   06900000
is  shown  below.  An empty entry means that particular status is not   06905000
supported on that subtype.                                              06910000
                                      NOT   PAPER   VFC    PWRFL/       06915000
  SUBTYPE  MODEL              READY  READY   OUT   RESET   RESET        06920000
  --------------------------------------------------------------        06925000
                                                                        06930000
     0     2610, 2614          INT    INT    DEV                        06935000
                                9     10     11                         06940000
                                                                        06945000
     1     2607                INT    INT                               06950000
                                9     10                                06955000
                                                                        06960000
     2     2613, 2617, 2618,   INT    INT                      <<00770>>06965000
           2619                 9     10                       <<00770>>06970000
                                                                        06975000
     3     2617J               INT    INT                               06980000
                                9     10                                06985000
                                                                        06990000
     4     2608                INT    INT           DEV     DEV         06995000
                                8      9            12      15          07000000
  NOTES:                                                                07005000
  1.  INT = Interrupt Status Word, DEV =  Device  Status  Word.         07010000
  2.  For subtypes 0-3, INT 9, 10 are always each other's complement.   07015000
For subtype 4, INT 8 is ON LINE status.  The 2608 may be off-line due   07020000
to the operator, but this does not cause it to go NOT READY (INT  9).   07025000
NOT READY occurs because of a machine problem (paper out, ribbon jam,   07030000
etc.), and of course removes ON LINE status as well.                    07035000
$PAGE                                                                   07040000
  The above bits are massaged into the following STATUS word:           07045000
                                                                        07050000
      ...  8      9     10     11     12     13     14     15   BIT     07055000
                                                                        07060000
                        NOT   PAPER   VFC                 PWRFL/        07065000
                READY  READY   OUT   RESET                RESET         07070000
;                                                              <<00770>>07075000
INTEGER STATUS,            << General status word >>                    07080000
        SUBTYPE,          << Printer subtype, which we have to fetch >> 07085000
        TEMP,                                                           07090000
        WAIT'CODE;                                                      07095000
                                                                        07100000
LOGICAL STATUSL = STATUS;                                               07105000
                                                                        07110000
LOGICAL ARRAY DITPL(*) = DITP;                                          07115000
                                                                        07120000
                                                                        07125000
STATUS := 0;   << Initialize internal status word >>                    07130000
WAIT'CODE := IOQP(QMISC).WAIT'FIELD;                           <<00769>>07135000
                                                                        07140000
<< Pick up printer subtype from the logical-to-physical device table >> 07145000
                                                                        07150000
TOS := LPDTD (DITP (DLDEV).DLDEVN);                                     07155000
SUBTYPE := TOS.SUBTYPE'FIELD;                                           07160000
                                                                        07165000
<< Get the interrupt and device status bytes >>                         07170000
                                                                        07175000
TOS := DRTNUMB;                                                         07180000
DOCIO (0, DITP);   << Select interrupt status byte >>                   07185000
ASMB (TIO 0);                                                           07190000
IF < THEN IOFAILURE (*, DITP);   << U.I. card does not respond >>       07195000
DITP(DSTAT) := TOS;                                                     07200000
DOCIO (%10, DITP);   << Select device status byte >>                    07205000
ASMB (TIO 0);                                                           07210000
IF < THEN IOFAILURE (*, DITP);   << U.I. card does not respond >>       07215000
TEMP := TOS;   << Save for selective picking >>                         07220000
ASMB (DEL);   << Delete the DRT number >>                               07225000
                                                                        07230000
IF (TALLY <= SUBTYPE <= KATAKANA) THEN                         <<00770>>07235000
     BEGIN   << INT 10 (Not Ready) is the complement of DEV 10 >>       07240000
     STATUS.READY'NOT'READY := TEMP.READY'NOT'READY;                    07245000
     STATUS := STATUSL XOR BIT'10;                                      07250000
     END   << of complementing bit 10 >>                                07255000
                                                                        07260000
ELSE IF SUBTYPE = CDC THEN                                              07265000
     BEGIN   << INT 10 (Not Ready) is the complement of DEV 10 >>       07270000
     STATUS.READY'NTRDY'NOPAP := TEMP.READY'NTRDY'NOPAP;                07275000
     STATUS := STATUSL XOR BIT'10;                                      07280000
     END   << of complementing bit 10 >>                                07285000
                                                                        07290000
ELSE IF SUBTYPE = HP2608 THEN                                           07295000
     BEGIN  << Must get device status for PWRFL/RESET and VFC INIT >>   07300000
     STATUS.READY'NOT'READY := TEMP.ONLINE'NOT'RDY'08;                  07305000
     STATUS.DEFAULT'VFC := TEMP.DEFAULT'VFC;                            07310000
     STATUS.POWER'FAIL'08 := TEMP.POWER'FAIL'08;                        07315000
     END   << of SUBTYPE = HP2608 >>                                    07320000
                                                                        07325000
ELSE;   << New subtypes go here >>                                      07330000
                                                                        07335000
IF STATUSL.POWER'FAIL'08 THEN DITP(DVFC1).PWRFL'RESET := 1;             07340000
                                                                        07345000
IF STATUSL.DEFAULT'VFC THEN                                             07350000
     BEGIN   << 2608 is using an internal VFC, may be O.K. >>           07355000
     IF DITPL(DVFC1).VFC'MOD THEN   << custom VFC installed >> <<00770>>07360000
          BEGIN   << VFC reset illegally, notify operator >>            07365000
          IF NOT IOMESSAGE (1, VFC'RESET'MESSAGE, %10000,               07370000
            DITP(DLDEV).DLDEVN,,,,, SYS'CONSOLE) THEN                   07375000
               BEGIN   << No system message buffer >>                   07380000
               CHECK'STATUS := NO'MSG'BUFF'ERROR;   << %124 >>          07385000
               RETURN;                                                  07390000
               END;   << of no message buffer >>                        07395000
          DITP(DVFC1).VFC'MOD := 0;   << Assures only one message >>    07400000
          CHECK'STATUS := VFC'RESET'ERROR;   << %273 >>                 07405000
          RETURN;                                                       07410000
          END;   << of illegal VFC reset >>                             07415000
     END;   << of default VFC active >>                                 07420000
                                                                        07425000
IF STATUSL.NOT'RDY                                             <<00656>>07430000
  OR NOT STATUSL.READY   << for 2608 >>                        <<00656>>07435000
  OR DITPL(DSTAT).DEVICE'FLAG THEN                             <<00769>>07440000
     BEGIN                                                              07445000
                                                                        07450000
<< The IOMESSAGE test must be the last one in the following statemnt >> 07455000
                                                                        07460000
     IF WAIT'CODE = NOT'READY'WAIT   << then message is already sent >> 07465000
       OR NOT MESSAGE'FLAG           << Don't want message sent >>      07470000
       OR IOMESSAGE (1, IF STATUSL.PAPER'OUT THEN PAPER'OUT'MESSAGE     07475000
            ELSE NOT'READY'MESSAGE, %10000, DITP(DLDEV).DLDEVN,,,,,     07480000
            SYS'CONSOLE)                                                07485000
       THEN CHECK'STATUS := %177777   << Set recoverable retn status >> 07490000
       ELSE CHECK'STATUS := NO'MSG'BUFF'ERROR;   << %124 >>             07495000
     RETURN;                                                            07500000
     END;  << of line printer not ready or off line >>                  07505000
                                                                        07510000
CHECK'STATUS := 0;   << No errors >>                                    07515000
END;   << of CHECK'STATUS >>                                            07520000
$PAGE                                                                   07525000
<<---------------- Driver Initialization Procedure ---------------->>   07530000
                                                                        07535000
PROCEDURE LPINIT (DITP);                                                07540000
  INTEGER ARRAY DITP;                                                   07545000
                                                                        07550000
BEGIN                                                                   07555000
<<                                                                      07560000
  LPINIT configures those areas of the SIO program which could not be   07565000
initialized during loading (pointers to addresses in the DIT,  etc.),   07570000
or  which  are  subtype-dependent  and therefore do not change during   07575000
execution.  Since we are only given the address of the DIT,  we  must   07580000
hop  and skip through that to the Interrupt Linkage Table to find the   07585000
starting address of the SIOP array.                                     07590000
>>                                                                      07595000
  INTEGER DITBASE;        << Starting address of the DIT >>             07600000
  INTEGER SUBTYPE;        << Printer subtype, which we have to fetch >> 07605000
  INTEGER POINTER ILTP,   << Pointer to the Interrupt Linkage Table >>  07610000
                  SIOP;   << Pointer to the SIO Channel Program >>      07615000
                                                                        07620000
DITBASE := @DITP + SYSDB;                                               07625000
@ILTP   := DITP(DILTP);                                                 07630000
@SIOP   := ILTP(ISIOP);                                                 07635000
                                                                        07640000
<< Pick up printer subtype from the logical-to-physical device table >> 07645000
                                                                        07650000
TOS := LPDTD (DITP (DLDEV).DLDEVN);                                     07655000
SUBTYPE := TOS.SUBTYPE'FIELD;                                           07660000
                                                                        07665000
<< Now we can configure -- finally! >>                                  07670000
                                                                        07675000
SIOP(SIO'PRE'TO'POST+3) := DITBASE + DVFC2;   << Skip to channel 3 >>   07680000
SIOP(SIO'BUFFER'FILL+21) := DITBASE + DLAST;  << Last (odd) byte in     07685000
                                                 buffer fill >>         07690000
SIOP(SIO'PRINT'AND'SPACE+3) := DITBASE + DVFC1;  << Pointer to CCTL >>  07695000
DITP(DVFC1).BETWEEN'JOBS := 1;   << Suppress PF/RST messages >><<00464>>07700000
DITP(DVFC2).PRE'TO'POST'CCTL := %102;  << All except 2608 >>   <<00769>>07705000
                                                                        07710000
<< Change all print commands from %43 to %1003 if we have a 2608 >>     07715000
                                                                        07720000
IF SUBTYPE = HP2608 THEN                                                07725000
     BEGIN                                                              07730000
     SIOP(SIO'VFC+3) := DITBASE + DLAST;   << # lines, 6/8 LPI >>       07735000
     SIOP(SIO'PRE'TO'POST+1) := %1003;                                  07740000
     SIOP (SIO'PRINT'AND'SPACE+1) := %1003;                    <<00769>>07745000
                                                               <<00769>>07750000
     SIOP(SIO'LEFT'MARGIN+3) := DITBASE + DLAST;  << Lft margn offst >> 07755000
     DITP(DVFC2).PRE'TO'POST'CCTL := %202;                     <<00769>>07760000
     END;   << of subtype = 2608 >>                                     07765000
                                                                        07770000
IF SUBTYPE = CDC THEN                                          <<00769>>07775000
     BEGIN   << CDC channel programs end without interrupt. >> <<00769>>07780000
     SIOP (SIO'PRE'TO'POST+4) := SIOEND;                       <<00769>>07785000
     SIOP (SIO'PRINT'AND'SPACE+4) := SIOEND;                   <<00769>>07790000
     END;                                                      <<00769>>07795000
                                                                        07800000
END;   << of LPINIT >>                                                  07805000
$PAGE                                                                   07810000
<<---------- Main line printer driver procedure, LPDRVR ----------->>   07815000
                                                                        07820000
INTEGER PROCEDURE LPDRVR (IOQP, DITP, BANK, BUFADDR, SIOP,              07825000
  DRTNUMB);                                                             07830000
  VALUE BANK, BUFADDR, DRTNUMB;                                         07835000
  INTEGER BANK,        << Absolute memory bank number of buffer >>      07840000
          BUFADDR,     << Absolute address of buffer in bank    >>      07845000
          DRTNUMB;     << DRT entry number of U.I. card         >>      07850000
  INTEGER ARRAY DITP,  << SYSDB-rel pointer to device's DIT(0)  >>      07855000
                IOQP,  << SYSDB-rel ptr to current IOQ(0) entry >>      07860000
                SIOP;  << SYSDB-relative pointer to SIO program >>      07865000
  OPTION PRIVILEGED,   << LPDRVR executes in privileged mode    >>      07870000
         UNCALLABLE;   << Calling procedure must be in privmode >>      07875000
                                                                        07880000
<< The possible results returned in LPDRVR are:                         07885000
       5 -- Request completed.                                          07890000
       7 -- Printer not ready, wait for on-line interrupt.              07895000
     %13 -- Wait for completion or other interrupt.                     07900000
>>                                                                      07905000
BEGIN                                                                   07910000
INTEGER CARRIAGE'CONTROL,   << Holds byte ultimately sent to printer >> 07915000
        CCTL'PARAM,         << Holds byte sent as part of request >>    07920000
        FUNCTION,           << IOQP request code, 1-4, %100, %101 >>    07925000
        IMBEDDED,           << =1 if CCTL in buffer, =0 if in QPAR1 >>  07930000
        LINK,               << Used to connect relevant parts of        07935000
                                 SIO'BUFFER'FILL block >>               07940000
        NEG'WORD'COUNT,                                                 07945000
        ODD'BYTE,           << = -1 if no odd byte >>                   07950000
        SIOPA,              << Absolute address of SIOP >>              07955000
        SUBTYPE,            << Printer subtype >>                       07960000
        TEMP,                                                           07965000
        WAIT'CODE;          << Internal driver state:                   07970000
                                 0 -- New request                       07975000
                                 1 -- Waiting for completion            07980000
                                 2 -- Three-second delay       <<00769>>07985000
                              << 3 -- Waiting for on-line interrupt     07990000
                                 4 -- 2607 off-line, 2 next    <<00769>>07995000
                                                                        08000000
LOGICAL IMBEDDEDL       = IMBEDDED,                                     08005000
        NEG'WORD'COUNTL = NEG'WORD'COUNT;                               08010000
                                                                        08015000
LOGICAL ARRAY DITPL(*) = DITP,                                          08020000
              IOQPL(*) = IOQP;                                          08025000
                                                                        08030000
<< Initialize local variables >>                                        08035000
                                                                        08040000
START'OVER:                                                    <<00464>>08045000
FUNCTION := IOQP(QFUNC).FUNCT;                                          08050000
IMBEDDED := IF IOQP(QPAR1) = 1                                          08055000
  THEN 1                                                                08060000
  ELSE 0;                                                               08065000
ODD'BYTE := %177777;   << Assume no odd byte >>                         08070000
LINK := SIO'BUFFER'FILL + 3;   << 1st jump in buffer fill block >>      08075000
SIOPA := @SIOP + SYSDB;                                                 08080000
TOS := LPDTD (DITP (DLDEV).DLDEVN);                                     08085000
SUBTYPE := TOS.SUBTYPE'FIELD;                                           08090000
WAIT'CODE := IOQP(QMISC).WAIT'FIELD;                                    08095000
                                                                        08100000
<< Now we're ready to go-o-o-o-o... >>                                  08105000
$PAGE                                                                   08110000
IF WAIT'CODE = LET'PRINTER'FINISH THEN                                  08115000
     BEGIN                                                              08120000
<<                                                                      08125000
  We're in a three-second wait to give the printer a chance to finish   08130000
whatever  it was doing.  Ignore any interrupt except the timer during   08135000
this period.                                                            08140000
>>                                                                      08145000
     IF DITP(DTIME) >= 0 THEN                                           08150000
          BEGIN   << Not timed out yet, bit 0 sets when timer pops >>   08155000
          LPDRVR := INTERRUPT'WAIT;                                     08160000
          RETURN;   << Ignore this interrupt >>                         08165000
          END;   << of extraneous interrupt >>                          08170000
     ABORTTIMEREQ (DITP(DTRLX));   << Timer popped, clear entry >>      08175000
     TOS := DRTNUMB;   << Get a fresh copy of status >>                 08180000
     DOCIO (0, DITP);  << Make sure it's interrupt status byte >>       08185000
     ASMB (TIO 0);                                                      08190000
     IF < THEN IOFAILURE (*, DITP);   << Non-responding module >>       08195000
     DITP(DSTAT) := TOS;                                                08200000
     END;   << of three-second timeout >>                               08205000
                                                                        08210000
IF IOQP < 0 THEN                                                        08215000
     BEGIN                                                     <<00656>>08220000
COMMENT                                                        <<00770>>08225000
Abort the I/O request.  The abort occurs asynchronously to the <<00770>>08230000
I/O request, and does not abort any printing in  progress.  We <<00770>>08235000
must wait for this printing to finish, or the next request may <<00770>>08240000
be lost due to starting it while the  printer  is  still  busy <<00770>>08245000
with  the previous one.  To avoid this problem give any opera- <<00770>>08250000
tion 3 seconds to finish, then abort.  This gives  normal  op- <<00769>>08255000
erations a chance, but still catches infinitely long hangups.  <<00770>>08260000
;                                                              <<00770>>08265000
     IF WAIT'CODE = COMPLETION'WAIT THEN                       <<00656>>08270000
          BEGIN   << Give printer three seconds to finish >>   <<00769>>08275000
START'DELAY:                                                   <<00769>>08280000
          DITP(DTRLX) := TIMEREQ (%20, @DITP, 3000D);          <<00769>>08285000
          IOQP(QMISC).WAIT'FIELD := LET'PRINTER'FINISH;        <<00656>>08290000
          LPDRVR := INTERRUPT'WAIT;                            <<00656>>08295000
          RETURN;                                              <<00656>>08300000
          END;   << of lighting off three second wait >>       <<00769>>08305000
     TOS := IF IOQPL.SYSTEM'POWER'FAIL                                  08310000
       THEN POWER'FAIL'ABORT                                            08315000
       ELSE OPERATOR'ABORT;                                             08320000
     GO CLEAR'CARD;                                                     08325000
     END;   << of abort >>                                              08330000
                                                                        08335000
IF IOQPL.SIO'FAILURE THEN                                               08340000
     BEGIN   << Delayed STARTIO failure on queued channel request >>    08345000
     TOS := SIO'FAIL'ERROR;                                             08350000
     GO TO IO'ERROR;                                                    08355000
     HELP;                 << Link to debug routine >>                  08360000
     END;  << of SIO failure >>                                         08365000
                                                                        08370000
<<--------- Examine WAIT'CODE to decide what to do next --------->>     08375000
                                                                        08380000
CASE * WAIT'CODE OF                                                     08385000
  BEGIN                                                                 08390000
$PAGE                                                                   08395000
<<------------------ WAIT'CODE = 0, new request ------------------>>    08400000
                                                                        08405000
     BEGIN                                                              08410000
     IF FUNCTION = WRITE THEN   << Code = 1 >>                          08415000
          BEGIN                                                         08420000
                                                                        08425000
<< Check first for pre- to postspace operation >>                       08430000
                                                                        08435000
          IF DITDDF.PRESPACE'NOTEMPTY = 3 <<Prespace last,bf>> <<01382>>08440000
            AND NOT IOQPL(QPAR2)         << This one's a postspace  >>  08445000
            THEN                                                        08450000
               BEGIN   << A hit, dump buffer w/ skip to channel 3 >>    08455000
               IOQP(QMISC).PRE'TO'POST := 1;                            08460000
                                                               <<00769>>08465000
<< Set jump to first channel program order >>                  <<00769>>08470000
                                                               <<00769>>08475000
               SIOP(SIO'SETUP+7) := SIOPA + SIO'PRE'TO'POST;   <<00773>>08480000
               SIOP (SIO'PRE'TO'POST+5) := %177777;            <<00769>>08485000
               END;  << of pre- to postspace configuration >>           08490000
                                                                        08495000
<< Limit the request word or byte count to 128 words (256 bytes) >>     08500000
                                                                        08505000
          IF IOQP(QWBCT) >  128 THEN IOQP(QWBCT) :=  128;               08510000
          IF IOQP(QWBCT) < -256 THEN IOQP(QWBCT) := -256;               08515000
          IF IMBEDDEDL                                                  08520000
            THEN  << carriage control param is 1st char in buffer >>    08525000
               BEGIN                                                    08530000
               IF IOQP(QWBCT) = 0 THEN                                  08535000
                    BEGIN  << QWBCT may not be 0 if CCTL is imbedded >> 08540000
                    TOS := INVALID'FUNCTION;                            08545000
                    GO TO IO'DONE;                                      08550000
                    END;   << of illegal count >>                       08555000
               TOS := BANK;                                             08560000
               TOS := BUFADDR;   << Get carriage control parameter >>   08565000
               LOAD'MEMORY;      <<   from wherever it is >>            08570000
               CCTL'PARAM := TOS & LSR(8);   << Right-justify & save >> 08575000
               END   << of imbedded carriage control parameter >>       08580000
            ELSE CCTL'PARAM := IOQP(QPAR1);   << QPAR1 is c.c. param >> 08585000
$PAGE                                                                   08590000
<<                                                                      08595000
  Parse the carriage control parameter.  Assume the  default  (single   08600000
space  with or without auto page eject), then modify as required.  If   08605000
a channel skip is required, assume a  subtype  <>  2608  until  we've   08610000
finished, then make the change.                                         08615000
>>                                                                      08620000
          CARRIAGE'CONTROL := IF IOQPL(QPAR2).NO'AUTO'PAGE              08625000
            THEN    1    << single space, no auto page eject >>         08630000
            ELSE %102;   << Skip to channel 3 (sngl spc, auto ejct) >>  08635000
                                                               <<00769>>08640000
                                                                        08645000
          IF CCTL'PARAM = "+" THEN                                      08650000
            CARRIAGE'CONTROL := 0   << Suppress spacing >>              08655000
                                                                        08660000
          ELSE IF CCTL'PARAM = "0" THEN   << Double space   >> <<01061>>08665000
            IF IOQPL(QPAR2).NO'AUTO'PAGE                       <<01061>>08670000
              THEN CARRIAGE'CONTROL := 2  << No auto eject >>  <<01061>>08675000
              ELSE DITP(DVFC2).LINES'LEFT'OVER := 1 << Auto >> <<01061>>08680000
                                                               <<01061>>08685000
          ELSE IF CCTL'PARAM = "-" THEN   << Triple space   >> <<01061>>08690000
            IF IOQPL(QPAR2).NO'AUTO'PAGE                       <<01061>>08695000
              THEN CARRIAGE'CONTROL := 3  << No auto eject >>  <<01061>>08700000
              ELSE DITP(DVFC2).LINES'LEFT'OVER := 2 << Auto >> <<01061>>08705000
                                                                        08710000
          ELSE IF CCTL'PARAM = "1" THEN                                 08715000
               BEGIN   << Skip to top of form >>                        08720000
               IF IOQP(QWBCT) = -IMBEDDED  << Nothing to do this time>> 08725000
                 AND DITDDF.TOP'OF'FORM  << Already at TOF >>  <<01382>>08730000
                 THEN GO TO NORMAL'COMPLETION;  <<Nothing to do, exit>> 08735000
               CARRIAGE'CONTROL := %100;  << Set skip to top-of-form >> 08740000
               END  << of CCTL'PARAM = 1 >>                             08745000
                                                                        08750000
          ELSE IF (%200 <= CCTL'PARAM <= %277) THEN  << Slew N lines >> 08755000
               BEGIN                                                    08760000
               CARRIAGE'CONTROL := CCTL'PARAM - %200;                   08765000
               IF (TALLY <= SUBTYPE <= KATAKANA)               <<00769>>08770000
                 AND CARRIAGE'CONTROL > 15 THEN                <<00769>>08775000
                    BEGIN   << Set up slews of <= 15 lines. >> <<00769>>08780000
                    DITP(DVFC2).LINES'LEFT'OVER :=             <<00769>>08785000
                      CARRIAGE'CONTROL - 15;                   <<00769>>08790000
                    CARRIAGE'CONTROL := 15;  << Set into... >> <<00769>>08795000
                    END;                     << ...DIT below>> <<00769>>08800000
               END  << of slewing N lines >>                            08805000
$PAGE                                                                   08810000
          ELSE IF %300 <= CCTL'PARAM <= %317 THEN                       08815000
<<                                                                      08820000
  Skip to a VFC channel.  The number  of  VFC  channels  varies  with   08825000
printer  subtype.  Subtypes  0  (CDC), 1 (2607) and 3 (2617J) have 8;   08830000
subtype 2 (2613, 2617, 2618 and 2619) has 12 and subtype 4 (2608) has   08835000
16.  If the request specifies an out-of-range channel for the current   08840000
subtype, ignore it (that is, use the carriage-control default).         08845000
>>                                                                      08850000
            IF CCTL'PARAM <= %307       << Works on any printer >>      08855000
              OR SUBTYPE = HP2608       << Any value O.K. >>            08860000
              OR CCTL'PARAM <= %313 AND SUBTYPE = DATAPRODUCTS          08865000
              THEN CARRIAGE'CONTROL := CCTL'PARAM - %200                08870000
              ELSE  << Null else >>                                     08875000
                                                                        08880000
          ELSE IF CCTL'PARAM = %320 THEN                                08885000
<<                                                                      08890000
  This parameter specifies that the data in the  current  request  be   08895000
concatenated  to  any  existing buffer, whether or not the buffer was   08900000
created as part of a pre- or postspace request, and  whether  or  not   08905000
the current request is pre- or postspace. As such, it is inconsistent   08910000
with a true emulation of a space-and-print (prespace) printer,  since   08915000
such  a  printer  would  have already printed a previous buffer.  The   08920000
current request could overlay the previous line,  but  could  not  be   08925000
concatenated to it.  On the postspace side, a %320 should concatenate   08930000
until a non-%320 is received; then the buffer should  be  dumped  and   08935000
the  non-%320  request processed normally.  This is not done; instead   08940000
the non-%320 is concatenated to any existing  buffer  and  the  whole   08945000
thing  is  then  printed.  Since these inconsistencies existed in the   08950000
previous  version,  they  have  been  preserved   here   for   upward   08955000
compatibility.                                                          08960000
>>                                                                      08965000
               BEGIN  << See if we have anything to do >>               08970000
               IF IOQP(QWBCT) = -IMBEDDED << Nothing this time >>       08975000
                 AND (NOT DITDDF.PRESPACE <<Nothing leftOVER>> <<01382>>08980000
                 OR IOQPL(QPAR2))         << Request is prespace >>     08985000
                 THEN GO TO NORMAL'COMPLETION;   << Nothing, exit >>    08990000
               IF NOT IOQPL(QMISC).PRE'TO'POST THEN                     08995000
                 SIOP(SIO'SETUP+7) := SIOPA + SIO'BUFFER'FILL; <<00773>>09000000
                                                               <<00769>>09005000
               SIOP(SIO'BUFFER'FILL+24) := SIOENDI;  << End SIO prog >> 09010000
               SIOP(X := X+1) := %177777;   << ... after buffer fill >> 09015000
               END;  << of CCTL'PARAM = %320 >>                         09020000
<<                                                                      09025000
  VFC channel skip command bytes for the HP2608 are of the form %2nn,   09030000
but the other subtypes use %1nn. We assumed %1nn until now, so change   09035000
to %2nn if we have a 2608.                                              09040000
>>                                                                      09045000
          IF SUBTYPE = HP2608 AND CARRIAGE'CONTROL >= %100 THEN         09050000
            CARRIAGE'CONTROL.(8:2) := 2;                                09055000
          DITP(DVFC1).CCTL := CARRIAGE'CONTROL;                         09060000
$PAGE                                                                   09065000
<< Set up the channel program for buffer fill and print control >>      09070000
                                                                        09075000
          IF CCTL'PARAM <> %320 THEN                                    09080000
               BEGIN  << We have to print something >>                  09085000
               IF IOQPL(QPAR2)                                          09090000
                 THEN   << Prespace >>                                  09095000
                    BEGIN                                               09100000
                    IOQP(QMISC).PRESPACE := 1;                 <<00769>>09105000
                    SIOP (SIO'SETUP+7) := SIOPA +              <<00773>>09110000
                      SIO'PRINT'AND'SPACE;                     <<00769>>09115000
                    SIOP(SIO'BUFFER'FILL+24) := SIOENDI;                09120000
                    SIOP(X := X+1) := %177777;   << End here >>         09125000
                    SIOP (SIO'PRINT'AND'SPACE+5) := %177777;   <<00769>>09130000
                    END   << of prespace >>                             09135000
                 ELSE   << Postspace >>                                 09140000
                    BEGIN                                               09145000
                    IF NOT IOQPL(QMISC).PRE'TO'POST THEN                09150000
                      SIOP(SIO'SETUP+7) := SIOPA +             <<00773>>09155000
                      SIO'BUFFER'FILL;                         <<00769>>09160000
                    SIOP(SIO'BUFFER'FILL+24) := JUMP;   << JUMP *+1 >>  09165000
                      SIOP (X := X+1) := SIOPA +               <<00769>>09170000
                        SIO'PRINT'AND'SPACE;                   <<00769>>09175000
                      SIOP (SIO'PRINT'AND'SPACE+5) := %177777; <<00769>>09180000
                    END;   << of postspace >>                           09185000
               END;   << of CCTL'PARAM <> %320 >>                       09190000
                                                                        09195000
          SIOP(SIO'BUFFER'FILL+1) := BANK;  << Mem bank addr of buff >> 09200000
          NEG'WORD'COUNT := -IOQP(QWBCT);                               09205000
          IF > THEN                                                     09210000
               BEGIN   << A byte transfer request >>                    09215000
                                                                        09220000
<< Save negative word count, rounded down.  It comes in handy later. >> 09225000
                                                                        09230000
               NEG'WORD'COUNT := -(NEG'WORD'COUNT & ASR(1));            09235000
               IF IOQPL(QWBCT)             << An odd number of bytes >> 09240000
                 AND (NEG'WORD'COUNT < 0   << Must be >= 3, but ... >>  09245000
                 OR NOT IMBEDDEDL)  << if CCTL imbedded, then 1 O.K. >> 09250000
                 THEN                                                   09255000
                    BEGIN   << An odd byte to output >>                 09260000
                    TOS := BANK;                                        09265000
                    TOS := BUFADDR;  << Get its address, then load >>   09270000
                    TOS := TOS - NEG'WORD'COUNT;                        09275000
                    LOAD'MEMORY;   << Odd byte is in left half word >>  09280000
                    ODD'BYTE := TOS & LSR(8);                           09285000
                    END;   << of odd byte processing >>                 09290000
               END;  << of byte transfer request >>                     09295000
$PAGE                                                                   09300000
<<                                                                      09305000
  Count is <= 0.  If = 0, we have at most a single byte of  data.  We   09310000
may  also  have  an  imbedded  carriage  control  byte.  This section   09315000
configures the SIO program to transmit the first  data  byte  (if  it   09320000
exists)  from  the  right  half  of  the first data word whenever the   09325000
carriage control byte is in the left half word.                         09330000
>>                                                                      09335000
          IF IMBEDDEDL   << Carriage control imbedded in data >>        09340000
            AND NEG'WORD'COUNT < 0 THEN  << At least one data byte >>   09345000
               BEGIN   << Must write first byte separately >>           09350000
               NEG'WORD'COUNT := NEG'WORD'COUNT + 1;  << Decrement >>   09355000
               SIOP(SIO'BUFFER'FILL+7) := BUFADDR; <<Addr of 1st byte>> 09360000
                                                                        09365000
<< Link start of buffer fill to the write first byte section >>         09370000
                                                                        09375000
               SIOP(LINK) := SIOPA + SIO'BUFFER'FILL + 4;               09380000
               LINK := SIO'BUFFER'FILL + 9;  << End of 1st byte wrt >>  09385000
               END;  << of writing first byte >>                        09390000
                                                                        09395000
          IF NEG'WORD'COUNT < 0 THEN                                    09400000
               BEGIN   << At least one full word to write >>            09405000
               SIOP(SIO'BUFFER'FILL+12) := SIOWRT1 LAND NEG'WORD'COUNTL;09410000
               SIOP(X := X+1) := BUFADDR + IMBEDDED;  << Start. addr >> 09415000
               SIOP(LINK) := SIOPA + SIO'BUFFER'FILL + 10;              09420000
               LINK := SIO'BUFFER'FILL + 15;  << End of main blk wrt >> 09425000
               END;   << of writing main block >>                       09430000
                                                                        09435000
          IF ODD'BYTE >= 0 THEN                                         09440000
               BEGIN  << We have an odd byte >>                         09445000
<<                                                                      09450000
  We can't use DITP(DLAST) for the odd byte all the time,  since  the   09455000
odd  byte  flag  is cleared (-1) at each entry to the driver.  We may   09460000
need to re-run the channel program in case  of  interruption,  so  we   09465000
can't automatically clear the current odd byte in DITP(DLAST).  Hence   09470000
the additional word, ODD'BYTE.  This is the only place where any  odd   09475000
byte should be stored into DITP(DLAST).                                 09480000
>>                                                                      09485000
               DITP(DLAST) := ODD'BYTE;                                 09490000
               SIOP(LINK) := SIOPA + SIO'BUFFER'FILL + 16;              09495000
               LINK := SIO'BUFFER'FILL + 21;  << Dummy end of           09500000
                                               odd byte wrt >>          09505000
               END;   << of writing odd byte >>                         09510000
                                                                        09515000
<< Set link to the last SETBANK order if we're not already there >>     09520000
                                                                        09525000
          IF LINK <> SIO'BUFFER'FILL + 21 THEN SIOP(LINK) :=            09530000
            SIOPA + SIO'BUFFER'FILL + 22;                               09535000
$PAGE                                                                   09540000
START'OUTPUT:                                                           09545000
COMMENT                                                        <<00769>>09550000
  The following test has two purposes:                         <<00769>>09555000
1)  To detect a Not Ready condition.  If  so,  the  Not  Ready <<00769>>09560000
    message is printed, we return the Not Ready state to SIODM <<00769>>09565000
    and we put the driver into a Not  Ready  Wait.  Exception: <<00769>>09570000
    If  a  Tally  printer went off-line, we enter the Wait For <<00769>>09575000
    Tally state.  See the comments under Operation of  IOLPRT0 <<00769>>09580000
    for further details.                                       <<00769>>09585000
2)  To detect the 2608 Power Fail/Reset status bit.  If it  is <<00769>>09590000
    set,  the 2608's operating environment has been destroyed, <<00769>>09595000
    requiring operator intervention to restore it.  Before the <<00769>>09600000
    operator can be notified, the status bit must be  cleared. <<00769>>09605000
    This can only be done with a 2608 Master Reset command, so <<00769>>09610000
    we unleash one followed by a Download Left Margin  to  re- <<00769>>09615000
    store the margin setting destroyed by the reset. When they <<00769>>09620000
    complete successfully (including any on-line/off-line side <<00769>>09625000
    trips which may occur), and if we are in a job, we  report <<00769>>09630000
    the  problem  to the operator (done in the completion sec- <<00769>>09635000
    tion).                                                     <<00769>>09640000
    ;                                                          <<00769>>09645000
          TEMP := CHECK'STATUS (DITP, IOQP, DRTNUMB, TRUE);    <<00770>>09650000
          IF TEMP < 0 THEN                                     <<00770>>09655000
               BEGIN   << Set Not Ready or Wait For Tally >>   <<00769>>09660000
               DOCIO (%40000, DITP); << Clear old interrupts >>         09665000
               DOCIO (2, DITP);  << Enable device interrupts >>         09670000
               IOQP(QMISC).WAIT'FIELD :=                       <<00769>>09675000
                 IF DITPL(DVFC1).TALLY'NOT'READY               <<00769>>09680000
                   THEN WAIT'FOR'TALLY                         <<00769>>09685000
                   ELSE NOT'READY'WAIT;                        <<00769>>09690000
               LPDRVR := NOT'READY;                                     09695000
               RETURN;                                                  09700000
               END;   << of Not Ready >>                                09705000
          IF DITPL(DVFC1).PWRFL'RESET                          <<00770>>09710000
            THEN                                               <<00770>>09715000
               BEGIN   << Well, the fan needed cleaning >>     <<00770>>09720000
COMMENT                                                        <<00770>>09725000
  A 2608 has undergone a power fail or master reset. This code <<00770>>09730000
configures the Master Reset command, which is the only command <<00770>>09735000
which clears the associated status bit.  The Left Margin  com- <<00770>>09740000
mand  follows  the  Master Reset, and restores the left margin <<00770>>09745000
which existed before the printer lost its mind.                <<00770>>09750000
;                                                              <<00770>>09755000
               IOQP(QMISC).MASTER'CLEAR := 1;                  <<00770>>09760000
               SIOP(SIO'SETUP+7) := SIOPA + SIO'MASTER'CLEAR;  <<00773>>09765000
               DITP(DLAST) := DITP(DVFC1).LEFT'MARGIN;         <<00770>>09770000
               SIOP(SIO'LEFT'MARGIN+5) := %177777;             <<00770>>09775000
               END   << of 2608 PWRFL'RESET bit being set >>   <<00770>>09780000
            ELSE IF TEMP > 0 THEN                              <<00770>>09785000
               BEGIN                                           <<00770>>09790000
               TOS := TEMP;                                    <<00770>>09795000
               IF S0 = NO'MSG'BUFF'ERROR                       <<00769>>09800000
                 THEN GO TO IO'ERROR                           <<00769>>09805000
                 ELSE GO TO IO'DONE;                           <<00769>>09810000
               END;   << of TEMP > 0 >>                        <<00770>>09815000
$PAGE                                                          <<00769>>09820000
<< Abort any still-running SIO  channel  program  to  avoid >> <<00769>>09825000
<< conflict with the one we're about to light off.          >> <<00769>>09830000
                                                               <<00769>>09835000
          IF WAIT'CODE >= NOT'READY'WAIT THEN                  <<00785>>09840000
            MASTERCLEAR (DITP);                                <<00769>>09845000
                                                               <<00769>>09850000
          STARTIO (DITP, SIOP, TRUE); << FINALLY, light off SIO prog >> 09855000
          IF > THEN   << controller busy, forget the whole thing >>     09860000
               BEGIN TOS := SIO'FAIL'ERROR;                             09865000
               GO TO IO'ERROR;                                          09870000
               END;   << of SIO failure >>                              09875000
                                                                        09880000
          IOQP(QMISC).WAIT'FIELD := COMPLETION'WAIT;                    09885000
          LPDRVR := INTERRUPT'WAIT;                                     09890000
          RETURN;                                                       09895000
          END;   << of function = WRITE >>                              09900000
                                                               <<00770>>09905000
                                                               <<00770>>09910000
                                                               <<00770>>09915000
<< WAIT'CODE = 0 (new request), FUNCTION = 2 (FOPEN),       >> <<00770>>09920000
<< 3 (FCLOSE) or 4 (DEVICE CLOSE)                           >> <<00770>>09925000
                                                                        09930000
     IF (FOPEN <= FUNCTION <= DEVICE'CLOSE) THEN               <<00770>>09935000
          BEGIN                                                         09940000
          IF DITDDF.TOP'OF'FORM THEN                           <<01382>>09945000
               BEGIN                                           <<00464>>09950000
                                                               <<00464>>09955000
<<   We're already at top  of  form.  Normally  this  means >> <<00464>>09960000
<< nothing to do. But if a 2608 has had a Power Fail/Master >> <<00464>>09965000
<< Reset, we must clear the condition before going on. This >> <<00656>>09970000
<< is  done  in rather roundabout fashion by going directly >> <<00656>>09975000
<< to START'OUTPUT, even though no channel program has been >> <<00656>>09980000
<< set  up.  This  allows  START'OUTPUT  to  process   this >> <<00656>>09985000
<< abnormal condition, even though it was detected here.    >> <<00656>>09990000
                                                               <<00656>>09995000
               CHECK'STATUS (DITP, IOQP, DRTNUMB, FALSE);      <<00656>>10000000
               IF DITPL(DVFC1).PWRFL'RESET THEN                <<00656>>10005000
                  GO START'OUTPUT;   << Got one >>             <<00656>>10010000
               GO CLEAN'UP;   << No problem, just leave >>     <<00656>>10015000
               END;   << of checking for Power Fail/Reset >>   <<00656>>10020000
          DITP(DVFC1).CCTL := IF SUBTYPE = HP2608                       10025000
            THEN %200   << Skip to channel 1 (top-of-form), 2608 >>     10030000
            ELSE %100;  << Same thing, all other printers >>            10035000
          SIOP (SIO'SETUP+7) := SIOPA + SIO'PRINT'AND'SPACE;   <<00773>>10040000
          SIOP (SIO'PRINT'AND'SPACE+5) := %177777;             <<00769>>10045000
          GO START'OUTPUT;   << Light off channel program >>            10050000
          END;   << of FOPEN or FCLOSE >>                               10055000
$PAGE                                                                   10060000
<< WAIT'CODE = 0 (new request), FUNCTION = %100 (Download VFC) >>       10065000
                                                                        10070000
     IF FUNCTION = DOWNLOAD'VFC AND SUBTYPE = HP2608 THEN               10075000
          BEGIN   << Code = %100 >>                                     10080000
          SIOP(SIO'SETUP+7) := SIOPA + SIO'VFC;                <<00773>>10085000
          IF IOQP(QWBCT) >  127 THEN IOQP(QWBCT) :=  127;  << Limit >>  10090000
          IF IOQP(QWBCT) < -254 THEN IOQP(QWBCT) := -254;  << count >>  10095000
          NEG'WORD'COUNT := -IOQP(QWBCT);                               10100000
          IF > THEN   << a byte transfer request >>                     10105000
            NEG'WORD'COUNT := -(NEG'WORD'COUNT & ASR(1));  <<Rnd down>> 10110000
          IF =  << either from words = 0 or from rounding bytes to 0 >> 10115000
            THEN                                                        10120000
               BEGIN  << Use a 2608 default VFC, 6 or 8 LPI >>          10125000
               DITP(DLAST) := IF IOQP(QPAR1) = 8                        10130000
                 THEN %200   << 8 LPI bit set >>                        10135000
                 ELSE 0;                                                10140000
               SIOP(SIO'VFC+5) := SIOPA + SIO'VFC + 12;  << Skip VFC    10145000
                                                     buffer write >>    10150000
               END   << of count = 0 >>                                 10155000
            ELSE                                                        10160000
               BEGIN  << Custom VFC required, configure it here >>      10165000
               DITP(DLAST) := IF IOQP(QPAR1) = 8                        10170000
                 THEN LOGICAL (-NEG'WORD'COUNT) LOR %200  << 8 LPI >>   10175000
                 ELSE -NEG'WORD'COUNT;                                  10180000
               SIOP(SIO'VFC+5) := SIOPA + SIO'VFC + 6;  << JUMP *+1 >>  10185000
               SIOP(X := X+4) := BANK;                                  10190000
               SIOP(X := X+1) := SIOWRT1 LAND NEG'WORD'COUNTL;          10195000
               SIOP(X := X+1) := BUFADDR;                               10200000
               END;  << of count <> 0 >>                                10205000
          SIOP(SIO'VFC+13) := %177777;   << Initialize END order >>     10210000
          GO START'OUTPUT;   << Light off channel program >>            10215000
          END;   << of function = DOWNLOAD'VFC >>                       10220000
                                                                        10225000
                                                                        10230000
                                                                        10235000
<< WAIT'CODE = 0 (new request), FUNCTION = %101 (Download Lft Margn) >> 10240000
                                                                        10245000
     IF FUNCTION = DOWNLOAD'LEFT'MARGIN AND SUBTYPE = HP2608 THEN       10250000
          BEGIN   << Code = %101 >>                                     10255000
          DITP(DVFC1).LEFT'MARGIN := DITP(DLAST) :=            <<00770>>10260000
            IF (0 <= IOQP(QPAR1) <= 15)                        <<00770>>10265000
            THEN X     << Index register has valid IOQP(QPAR1) >>       10270000
            ELSE 15;   << Value out of range, use default >>            10275000
          SIOP(SIO'SETUP+7) := SIOPA + SIO'LEFT'MARGIN;        <<00773>>10280000
          SIOP(SIO'LEFT'MARGIN+5) := %177777;  << Initialize END >>     10285000
          GO START'OUTPUT;   << Light off channel program >>            10290000
          END;  << of function = DOWNLOAD'LEFT'MARGIN >>                10295000
                                                                        10300000
<< Add new functions here, else fall through to error >>                10305000
                                                                        10310000
     TOS := INVALID'FUNCTION;                                           10315000
     GO TO IO'DONE;                                                     10320000
                                                                        10325000
     END;   << of WAIT'CODE = 0, new request >>                         10330000
$PAGE                                                                   10335000
<<---------------- WAIT'CODE = 1, completion section --------------->>  10340000
                                                                        10345000
<<                                                                      10350000
  This section processes all device completion interrupts (as opposed   10355000
to interrupts resulting from a device going from Not Ready to  Ready.   10360000
The latter interrupts are  handled  by  WAIT'CODE  =  3).  Note:  The   10365000
current TIO status is set in the DIT by GIP at each interrupt.          10370000
>>                                                                      10375000
     BEGIN                                                              10380000
                                                               <<00769>>10385000
     IF DITPL(DSTAT).XFER'ERROR THEN                                    10390000
          BEGIN   << Illegal mem addr, or mem or data parity error >>   10395000
          TOS := TRANSFER'ERROR;                                        10400000
          GO TO IO'ERROR;                                               10405000
          END;   << of transfer error >>                                10410000
                                                                        10415000
     IF DITPL(DSTAT) THEN                                               10420000
          BEGIN   << Bit 15 is the timeout bit >>                       10425000
          TOS := TIMEOUT'ERROR;   << A real timeout >>                  10430000
          GO TO IO'ERROR;                                               10435000
          END;   << of timeout >>                                       10440000
     IF IOQPL(QMISC).MASTER'CLEAR THEN                                  10445000
          BEGIN                                                         10450000
<<                                                                      10455000
  We've done the 2608 Master Reset required by a printer Power  Fail/   10460000
Reset.  If  we're  between  jobs  go retry the request, else tell the   10465000
operator about the reset and return the proper error status. >><<00464>>10470000
                                                               <<00464>>10475000
          IF DITPL(DVFC1).BETWEEN'JOBS THEN                    <<00464>>10480000
               BEGIN   << Power fail was safe, go retry >>     <<00464>>10485000
               DITP(DVFC1).PWRFL'RESET := 0;                   <<00464>>10490000
               IOQP(QMISC).MASTER'CLEAR := 0;                  <<00464>>10495000
               IOQP(X).WAIT'FIELD := NEW'REQUEST;              <<00464>>10500000
               IF NOT IOQPL(X).RETRY THEN                      <<00571>>10505000
                    BEGIN   << Prevent endless looping if...>> <<00571>>10510000
                    IOQP(X).RETRY := 1;  << ...wrong subtype >><<00571>>10515000
                    GO START'OVER;                             <<00571>>10520000
                    END;   << of endless loop test >>          <<00571>>10525000
               END;   << of Power Fail/Reset between jobs >>   <<00464>>10530000
          IF NOT IOMESSAGE (1, PWRFL'RESET'MESSAGE, %10000,             10535000
            DITP(DLDEV).DLDEVN,,,,, SYS'CONSOLE) THEN                   10540000
               BEGIN   << No system message buffer >>                   10545000
               TOS := NO'MSG'BUFF'ERROR;   << %124 >>                   10550000
               GO TO IO'ERROR;                                          10555000
               END;   << of unable to write error message >>            10560000
          DITP(DVFC1).PWRFL'RESET := 0;                                 10565000
          DITP(DVFC1).VFC'MOD := 0;   << No more custom VFC >> <<00464>>10570000
          TOS := PWRFL'RESET'ERROR;   << %213 >>                        10575000
          GO TO IO'DONE;                                                10580000
          END;   << of reporting PF/RST error >>                        10585000
$PAGE                                                          <<00769>>10590000
<< Check for Tally off-line -- it needs special handling. >>   <<00769>>10595000
                                                               <<00769>>10600000
     IF SUBTYPE = TALLY                                        <<00769>>10605000
       AND DITP(DSTAT) >= 0   << Channel program incomplete >> <<00769>>10610000
       AND DITPL(X).NOT'RDY THEN   << Printer off-line >>      <<00769>>10615000
         DITP(DVFC1).TALLY'NOT'READY := 1;                     <<00769>>10620000
                                                               <<00769>>10625000
     IF IOQPL(QMISC).PRE'TO'POST THEN                          <<00769>>10630000
          BEGIN   << Print buffer MT, continue w/ postspace >> <<00769>>10635000
          SIOP (SIO'SETUP+7) := SIOPA + SIO'BUFFER'FILL;       <<00773>>10640000
          IOQP(QMISC).PRE'TO'POST := 0;  << Don't come back >> <<00769>>10645000
          GO START'OUTPUT;                                     <<00769>>10650000
          END;                                                 <<00769>>10655000
                                                               <<00769>>10660000
     IF (TEMP := DITP(DVFC2).LINES'LEFT'OVER) <> 0 THEN        <<00769>>10665000
          BEGIN  << Multiple line skip, set up continuation >> <<00769>>10670000
          SIOP (SIO'SETUP+7) := SIOPA + SIO'PRINT'AND'SPACE;   <<00773>>10675000
          IF DITP(DVFC1).CCTL < %100                           <<01061>>10680000
            THEN  << Additional slews of <=15 lines >>         <<01061>>10685000
              IF TEMP <= 15                                    <<01061>>10690000
                THEN                                           <<01061>>10695000
                   BEGIN   << Last time through here >>        <<01061>>10700000
                   DITP(DVFC1).CCTL := TEMP;                   <<01061>>10705000
                   DITP(DVFC2).LINES'LEFT'OVER := 0;           <<01061>>10710000
                   END                                         <<01061>>10715000
                ELSE  << More than 15 lines left, do next 15 >><<01061>>10720000
                   DITP(DVFC2).LINES'LEFT'OVER := TEMP - 15    <<01061>>10725000
            ELSE  << "0" or "-" with auto eject, adv 1 line >> <<01061>>10730000
               DITP(DVFC2).LINES'LEFT'OVER := TEMP - 1;        <<01061>>10735000
          GO START'OUTPUT;                                     <<00769>>10740000
          END;                                                 <<00769>>10745000
                                                               <<00769>>10750000
     IF IOQPL(QMISC).PRESPACE THEN                             <<00769>>10755000
          BEGIN   << Prespace print done, fill buffer >>       <<00769>>10760000
          SIOP (SIO'SETUP+7) := SIOPA + SIO'BUFFER'FILL;       <<00773>>10765000
          IOQP(QMISC).PRESPACE := 0;  << One time only >>      <<00769>>10770000
          GO START'OUTPUT;                                     <<00769>>10775000
          END;                                                 <<00769>>10780000
                                                                        10785000
<< Fall through to normal completion.  Clean up and exit >>             10790000
$PAGE                                                                   10795000
CLEAN'UP:                                                      <<00464>>10800000
     IF (FOPEN <= FUNCTION <= DOWNLOAD'VFC) THEN               <<00464>>10805000
          BEGIN   << Must be at top of form >>                 <<00464>>10810000
          DITDDF.PRESPACE'NOTEMPTY := 0; <<Postspc,empty buf>> <<01382>>10815000
          DITDDF.TOP'OF'FORM := 1;                             <<01382>>10820000
          END;   << of control function >>                     <<00464>>10825000
     IF FUNCTION = FOPEN THEN DITP(DVFC1).BETWEEN'JOBS := 0;   <<00464>>10830000
     IF FUNCTION = DEVICE'CLOSE THEN                           <<00464>>10835000
       DITP(DVFC1).BETWEEN'JOBS := 1;                          <<00464>>10840000
     IF FUNCTION = WRITE THEN                                  <<00464>>10845000
          BEGIN   << Update prespace, not'empty and TOF >>     <<00464>>10850000
          DITDDF.PRESPACE'LAST := IOQPL(QPAR2);                <<01382>>10855000
          DITDDF.NOT'EMPTY := IF IOQPL(QPAR2)   << Prespace >> <<01382>>10860000
            AND IOQP(QWBCT) <> -IMBEDDED   << Some data sent >><<00464>>10865000
            THEN 1                                             <<00464>>10870000
            ELSE 0;                                            <<00464>>10875000
          DITDDF.TOP'OF'FORM :=                                <<01382>>10880000
            IF (DITP(DVFC1).CCTL = %200  << 2608 top of form >><<00464>>10885000
              OR DITP(X).CCTL = %100)   << TOF, all others >>  <<00464>>10890000
              AND NOT DITDDF.NOT'EMPTY <<Nothing sent since>>  <<01382>>10895000
              THEN 1                                           <<00464>>10900000
              ELSE 0;                                          <<00464>>10905000
          END;   << of FUNCTION = WRITE >>                     <<00464>>10910000
     IF SUBTYPE = HP2608 THEN                                           10915000
          BEGIN   << Set proper state of VFC'MOD bit >>                 10920000
          IF FUNCTION = DOWNLOAD'VFC THEN                               10925000
            DITP(DVFC1).VFC'MOD := IF IOQP(QWBCT) = 0                   10930000
            THEN 0            << No custom VFC installed >>             10935000
            ELSE 1;           <<    Custom VFC installed >>             10940000
          IF FUNCTION = DOWNLOAD'VFC                           <<00571>>10945000
            OR FUNCTION = DOWNLOAD'LEFT'MARGIN THEN            <<00571>>10950000
            IF NOT IOMESSAGE (1, GOOD'DOWNLOAD'MSG, %10000,    <<00571>>10955000
              DITP(DLDEV).DLDEVN,,,,, SYS'CONSOLE) THEN        <<00571>>10960000
               BEGIN   << No system message buffer >>          <<00571>>10965000
               TOS := NO'MSG'BUFF'ERROR;   << %124 >>          <<00571>>10970000
               GO TO IO'ERROR;                                 <<00571>>10975000
               END;   << of unable to write error message >>   <<00571>>10980000
          END;   << of SUBTYPE = 2608 >>                                10985000
                                                                        10990000
NORMAL'COMPLETION:                                                      10995000
     TOS := GOOD'STATUS;                                                11000000
                                                                        11005000
IO'DONE:                                                                11010000
     IOQP(QSTAT).STATS := TOS;                                          11015000
     LPDRVR := REQUEST'DONE;                                            11020000
     RETURN;                                                            11025000
                                                                        11030000
IO'ERROR:                                                               11035000
     DITP(DSERR):= [8/1,8/DLOGERROR];<<LOG COUNT # INDEX>>     <<01339>>11040000
     DITP(DLOGERROR):= DITP(DSTAT);   <<LOG ERROR>>            <<01339>>11045000
                                                                        11050000
CLEAR'CARD:                                                             11055000
     MASTERCLEAR (DITP);   << Clear the U.I. card >>                    11060000
     GO TO IO'DONE;        << Set completion status and return >>       11065000
     END;   << of normal request, and of WAIT'CODE = 1 >>               11070000
$PAGE                                                                   11075000
<< WAIT'CODE = 2, return after 3-second Tally on-line delay >> <<00769>>11080000
                                                                        11085000
     BEGIN                                                     <<00769>>11090000
     DITP(DVFC1).TALLY'NOT'READY := 0; <<No longer a problem>> <<00769>>11095000
     GO TO WAIT'CODE3;  << Rest is like normal Not Ready >>    <<00785>>11100000
     END;   << of WAIT'CODE = 2 >>                             <<00769>>11105000
                                                                        11110000
                                                                        11115000
                                                                        11120000
                                                                        11125000
                                                                        11130000
<<------- WAIT'CODE = 3, return from Not Ready condition ------->>      11135000
                                                                        11140000
COMMENT                                                        <<00785>>11145000
  SIODM unfreezes the caller's data segment whenever we return <<00785>>11150000
Not Ready to it.  This allows the Memory Manager  to  swap  it <<00785>>11155000
out  rather than tie up real memory while the printer is idle. <<00785>>11160000
The data segment is returned to  real  memory  before  we  are <<00785>>11165000
called again, but (usually) not at the same address.  The code <<00785>>11170000
below updates the channel program with the new address if  re- <<00785>>11175000
quired by the current request.                                 <<00785>>11180000
;                                                              <<00785>>11185000
     BEGIN                                                     <<00785>>11190000
WAIT'CODE3:                                                    <<00785>>11195000
     IF FUNCTION = WRITE THEN                                  <<00785>>11200000
          BEGIN                                                <<00785>>11205000
          SIOP (SIO'BUFFER'FILL+1) := BANK;                    <<00785>>11210000
          SIOP (X := X+6) := BUFADDR;                          <<00785>>11215000
          SIOP (X := X+6) := BUFADDR + IMBEDDED;               <<00785>>11220000
          END;                                                 <<00785>>11225000
                                                               <<00785>>11230000
     IF FUNCTION = DOWNLOAD'VFC THEN                           <<00785>>11235000
          BEGIN                                                <<00785>>11240000
          SIOP (SIO'VFC+9) := BANK;                            <<00785>>11245000
          SIOP (X := X+2) := BUFADDR;                          <<00785>>11250000
          END;                                                 <<00785>>11255000
     GO START'OUTPUT;   << Try once more to print >>           <<00769>>11260000
     END;   << of WAIT'CODE = 3 >>                             <<00785>>11265000
                                                               <<00769>>11270000
                                                               <<00769>>11275000
                                                               <<00769>>11280000
                                                               <<00769>>11285000
                                                               <<00769>>11290000
<<-- WAIT'CODE = 4, Tally placed on-line, allow 3 seconds -->> <<00769>>11295000
                                                               <<00769>>11300000
     GO START'DELAY;                                           <<00769>>11305000
                                                                        11310000
  END;   << of WAIT'CODE CASE statement >>                              11315000
                                                                        11320000
END;   << of LPDRVR >>                                                  11325000
$PAGE                                                                   11330000
<<--------------------- Driver Linkage Area ----------------------->>   11335000
                                                                        11340000
ASMB (                                                                  11345000
      PCAL SIODM;    << Monitor                >>                       11350000
      PCAL LPDRVR;   << Initiator ...          >>                       11355000
      PCAL LPDRVR;   << ... and completor      >>                       11360000
                                                                        11365000
      CON  0;        << No I/O process         >>                       11370000
                                                                        11375000
      PCAL LPINIT;   << Initialization routine >>                       11380000
                                                                        11385000
      CON  1;        << One interrupt handler  >>                       11390000
      PCAL GIP);     << The interrupt handler  >>                       11395000
                                                                        11400000
END.                 << of line printer driver, IOLPRT0 (19) >>         11405000
