$CONTROL MAP,CODE,USLINIT                                               00010000
<<  MPE MODULE 19, IOLPRT0  >>                                          00012000
<< HP32002C MPE SOURCE C.00.00 >>                                       00014000
<< COPYRIGHT     "(C) COPYRIGHT HEWLETT-PACKARD CO. 1980.           >>  00016000
<<     THIS PROGRAM MAY BE USED WITH ONE COMPUTER SYSTEM AT A       >>  00018000
<<     TIME AND SHALL NOT OTHERWISE BE RECORDED, TRANSMITTED OR     >>  00020000
<<     STORED IN A RETRIEVAL SYSTEM.  COPYING OR OTHER REPRODUCTION >>  00022000
<<     OF THIS PROGRAM EXCEPT FOR ARCHIVAL PURPOSES IS PROHIBITED   >>  00024000
<<     WITHOUT THE PRIOR WRITTEN CONSENT OF HEWLETT-PACKARD COMPANY.>>  00026000
<< **** Note - Dollar Copyright cannot be used with this module *** >>  00028000
                                                                        00030000
<<                                                                      00032000
  COPYRIGHT (C) 1978, HEWLETT-PACKARD CO.  This program may  be  used   00034000
with  one  computer  system  at  a  time  and  shall not otherwise be   00036000
recorded, transmitted or stored in a  retrieval  system.  Copying  or   00038000
other  reproduction  of  this program except for archival purposes is   00040000
prohibited without  the  prior  written  consent  of  Hewlett-Packard   00042000
Company.                                                                00044000
>>                                                                      00046000
<<                                                                      00048000
  NOTE:  Do NOT use $COPYRIGHT to enter the above  copyright  notice.   00050000
INITIAL will get very unhappy, and so will MPE.                         00052000
>>                                                                      00054000
                                                                        00056000
$TITLE "CDC, TALLY, DATAPRODUCTS, DATAPRINTER AND HP2608 DRIVER",&      00058000
$      " - IOLPRT0 (19)"                                       <<00464>>00060000
$CONTROL PRIVILEGED, UNCALLABLE, MAIN=IOLPRT0                           00062000
                                                                        00064000
  The fix number in the right margin is  an  enhancement,  de- <<00770>>00066000
scribed more fully on page 16.                                 <<00769>>00068000
                                                               <<00769>>00070000
  The fix number in the right margin denotes a redesign of the <<00769>>00072000
control algorithm to correct errors when the driver is running <<00769>>00074000
in prespace mode.                                              <<00769>>00076000
                                                               <<00773>>00078000
  The fix number in the right margin is a correction which al- <<00773>>00080000
lows the driver to properly handle a prespace request  with  a <<00773>>00082000
transfer  length of 1 byte, where the byte is an imbeeded car- <<00773>>00084000
riage control byte (that is, no data in the  request).  Before <<01061>>00086000
this  fix,  such a request would cause the driver to wait for- <<00773>>00088000
ever for a completion interrupt because interrupts  were  dis- <<00773>>00090000
abled on the U.I. card.                                        <<00773>>00092000
                                                               <<00785>>00094000
  The fix denoted by the number in the  right  margin  assures <<00785>>00096000
that  the  proper buffer address is placed in the channel pro- <<00785>>00098000
gram after returning from Not Ready.  See additional  comments <<00785>>00100000
near  the  end  of  the Operation description and at the label <<00785>>00102000
WAIT'CODE3.                                                    <<00785>>00104000
                                                               <<01061>>00106000
  The fix denoted by the number in the right margin allows re- <<01061>>00108000
quests using a "0" (double space) or  "-"  (triple  space)  to <<01061>>00110000
base their execution on the state of the NO'AUTO'PAGE bit.     <<01061>>00112000
$PAGE                                                          <<00773>>00114000
COMMENT                                                        <<00464>>00116000
  This is IOLPRT0, MPE Module 19, the driver for all (line)  printing   00118000
devices  currently  supported on the Universal Interface (U.I.) card.   00120000
Line printers are I/O Device Type  32.  Differences  between  various   00122000
line  printers are resolved through the use of subtypes.  The current   00124000
range of subtypes is 0-4, with the following subtype assignments:       00126000
                                                                        00128000
   SUBTYPE     LINE PRINTER                                             00130000
   -------     ------------                                             00132000
                                                                        00134000
      0        HP2610, HP2614          (manufactured by CDC)            00136000
      1        HP2607                  (manufactured by Tally) <<00770>>00138000
      2        HP2613, HP2617, HP2618  (manufactured by Dataproducts)   00140000
      2        HP2619                  (manufactured by Dataprinter)    00142000
      3        HP2617J                 (manufactured by Dataproducts)   00144000
      4        HP2608                  (manufactured by HP, finally!)   00146000
                                                                        00148000
Further information on the various hardware subsystems can  be  found   00150000
in the following manuals:                                               00152000
                                                                        00154000
  30108-90001  HP2610 line printer                                      00156000
  30109-90001  HP2614 line printer                                      00158000
  30209-90006  HP2607, HP2613, HP2617, HP2618 line printers             00160000
  30209-90008  Line Printer Operating and Programming Manual            00162000
$PAGE                                                                   00164000
Operation of IOLPRT0:                                                   00166000
                                                               <<00769>>00168000
General Description:                                           <<00769>>00170000
                                                               <<00769>>00172000
  IOLPRT0  processes  control  and  data  information supplied by the   00174000
Series III I/O system.  The result is an SIO  channel  program  which   00176000
transmits  the  proper sequence of signals to the Universal Interface   00178000
card, and then to the line printer for printing and/or paper advance.   00180000
  The  primary  working code of IOLPRT0 is a procedure, LPDRVR.  (See   00182000
the next section for  a  description  of  the  overall  structure  of   00184000
IOLPRT0).  LPDRVR  is called with six parameters.  Two of these, BANK   00186000
and BUFADDR, are the absolute  memory  address  of  the  data  to  be   00188000
processed.  Three  others,  DITP,  IOQP and SIOP, are pointers to the   00190000
first elements of three arrays (tables) used  for  control  purposes.   00192000
The  DIT  (Device  Information  Table) contains information about the   00194000
printer and any driver  information  which  must  be  stored  between   00196000
requests  to  the  driver.  The  IOQ (Input/Output Queue) consists of   00198000
information relevant to the current request.  The SIO array  is  read   00200000
by the I/O Processor during execution of the SIO channel program.  It   00202000
must be configured by the driver, based on the  requirements  of  the   00204000
current   request.   These  three  tables  are  described  in  detail   00206000
elsewhere in this listing.                                              00208000
  The  final  parameter, DRTNUMB, is the Device Reference Table (DRT)   00210000
number, or the hardware address  in  the  system,  of  the  Universal   00212000
Interface card.                                                         00214000
  LPDRVR is always called by the SIO Device Monitor (SIODM),  but  it   00216000
is  up  to LPDRVR to find out the reason why it was called.  This may   00218000
be anything from a normal start of a  new  request  to  a  completion   00220000
interrupt  of the present request to a printer or U.I. card interrupt   00222000
due to an error or unusual condition (such as the printer  being  Not   00224000
Ready  or Off Line) to a command from the system to abort the current   00226000
request.  (The driver must process these aborts in order to terminate   00228000
the associated requests in an orderly manner, including provision for   00230000
making I/O resources available to the system once more).                00232000
  When  a  new request is initiated, LPDRVR examines a function field   00234000
and up to two modifying parameters to find out what its current  task   00236000
is.  This  information  is contained in the current IOQ entry.  Based   00238000
on this, and on  the  particular  subtype  of  line  printer,  LPDRVR   00240000
configures  an  SIO  channel  program  to perform the task, calls the   00242000
external procedure STARTIO to start executing  the  channel  program,   00244000
then  returns  to  SIODM with an indication that the request has been   00246000
initiated.                                                              00248000
  Upon  completion of the request, an interrupt is generated.  LPDRVR   00250000
makes sure that no errors have occurred and  cleans  up  its  working   00252000
area  for  the current request, then exits to SIODM with a completion   00254000
status in the IOQ entry.                                                00256000
  There are five basic modes of operation:                     <<00769>>00258000
1.  Postspace mode.  The default and most prevalent mode.  All <<00769>>00260000
    HP printers mechanically operate this way.  Data is print- <<00769>>00262000
    ed, then paper is advanced as required by the request.     <<00769>>00264000
2.  Prespace mode.  Paper is advanced, then data  is  printed. <<00769>>00266000
    This  mode  must  be  simulated  by ending each request by <<00769>>00268000
    filling the printer buffer but  not  printing.   The  next <<00769>>00270000
    request  prints  this  data, advances paper as required by <<00769>>00272000
    the next request, and fills the buffer with data from  the <<00769>>00274000
    next  request,  thus completing the request with data left <<00769>>00276000
    in the printer.                                            <<00769>>00278000
3.  Current request is postspace, previous  request  was  pre- <<00769>>00280000
    space. As described in 2, data has been left in the print- <<00769>>00282000
    er by the previous request.  We must print both this  data <<00769>>00284000
    and  our  current data with this request, but we have only <<00769>>00286000
    one carriage control specification and it must be  applied <<00769>>00288000
    to the postspace request. Therefore we assume a specifica- <<00769>>00290000
    tion of %302 (skip to VFC channel 3, usually single  space <<00769>>00292000
    with  auto  page  eject)  when we print the data left over <<00769>>00294000
    from the previous (prespace) request.                      <<00769>>00296000
4.  Current request is prespace, previous  request  was  post- <<00769>>00298000
    space.  This is not a real mode to the driver, since it is <<00769>>00300000
    logically the same as 2.  The user may experience  one  or <<00769>>00302000
    more  extra  spaces  at the changeover, since the previous <<00769>>00304000
    request spaced after printing and this one will space  be- <<00769>>00306000
    fore printing.                                             <<00769>>00308000
5.  Current carriage control specification is  %320,  pre-  or <<00769>>00310000
    postspace.    No printing or paper advance takes place, so <<00769>>00312000
    it makes no difference which mode we're  in.   Using  this <<00769>>00314000
    specification,  data  from the current request is appended <<00769>>00316000
    to any data which may already exist in the printer buffer. <<00769>>00318000
  The  above  description  is for normal requests.  Errors or unusual   00320000
occurrences, such as a paper out or printer off line, must  be  dealt   00322000
with  as  they  occur.  Both  SIODM  and  IOLPRT0  have provisions to   00324000
suspend a request indefinitely while a condition such as paper out is   00326000
corrected  by  the  operator.  The act of placing the printer on line   00328000
again generates an interrupt.  The driver, after verifying  that  the   00330000
printer   is  again  operable,  continues  with  the  request.  Other   00332000
conditions, such as a data parity  error  during  the  transfer,  are   00334000
considered non-recoverable and result in a request completion with an   00336000
error status.                                                           00338000
                                                               <<00769>>00340000
Detailed Considerations:                                       <<00769>>00342000
                                                               <<00769>>00344000
  Some requests require multiple interrupts before the request <<00769>>00346000
can be completed.  This is because IOLPRT0 must check  printer <<00769>>00348000
status  after  every physical print command, and some requests <<00769>>00350000
must be broken up into multiple physical prints.  Printer sub- <<00769>>00352000
types 1, 2 and 3, for example,  cannot  slew  (advance)  paper <<00769>>00354000
more  than 15 lines at a time (except for VFC skips), so print <<00769>>00356000
requests which must space further than that must be done  with <<00769>>00358000
multiple slews of 15 lines or less.  (An obvious example would <<00769>>00360000
be the header/trailers of print  outputs  which  have  sixteen <<00769>>00362000
spaces  between  the groups of three lines).  If requests were <<00769>>00364000
not so divided, the integrity of the printed output could  not <<00769>>00366000
be  guaranteed in the event paper ran out or the operator took <<00769>>00368000
the printer off-line.  By "integrity", we mean that output  is <<00769>>00370000
not  shifted  right  or left, and lines are not lost nor blank <<00769>>00372000
lines inserted.  Prior to the current fix, we tried  one  long <<00769>>00374000
SIO channel program encompassing all required physical prints. <<00769>>00376000
It worked fine -- as long as the printer remained on-line.   A <<00769>>00378000
word to the wise.                                              <<00769>>00380000
  A discussion is in order about  the  state  of  the  various <<00769>>00382000
printers  when  they go (or are taken) off-line.  Those of you <<00769>>00384000
not concerned about such esoterica can skip the following sec- <<00769>>00386000
tion, which is quite long-winded.                              <<00769>>00388000
$PAGE                                                          <<00769>>00390000
  Data is sent to the printer via  an  asynchronous  handshake <<00769>>00392000
between the U.I. card and the printer.  One or more such hand- <<00769>>00394000
shakes occur for every WIO CPU instruction  or  channel  Write <<00769>>00396000
order -- in fact, one per word transmitted (or two, if in byte <<00769>>00398000
unpacking mode).  You must understand the handshake  mechanism <<00769>>00400000
to  grasp  the off-line behavior of each printer, so it is de- <<00769>>00402000
scribed here.                                                  <<00769>>00404000
  The handshake consists of two signals,  and  therefore  four <<00769>>00406000
states.    One  signal,  Command, is managed by the U.I. card. <<00769>>00408000
The other, called Demand, is managed by the printer.   In  the <<00769>>00410000
idle  state,  Command  is de-asserted (false), while Demand is <<00769>>00412000
asserted (true).  A data transfer works as follows:            <<00769>>00414000
1.  U.I. card asserts Command, signifying that a  transfer  is <<00769>>00416000
    beginning.                                                 <<00769>>00418000
2.  Printer, upon recognizing Command, de-asserts Demand.      <<00769>>00420000
3.  U.I. card, seeing change in Demand,  removes  (de-asserts) <<00769>>00422000
    Command.   While Demand is false, the printer is executing <<00769>>00424000
    the command.                                               <<00769>>00426000
4.  After finishing command execution, Demand  is  re-asserted <<00769>>00428000
    and the idle state is obtained once more.                  <<00769>>00430000
The complement of the Demand line is available as  the  Device <<00769>>00432000
Flag  bit  of the Interrupt Status Word.  That is, Device Flag <<00769>>00434000
is true when Demand is false.                                  <<00769>>00436000
  Clearly the U.I. card (and therefore the  driver)  must  re- <<00769>>00438000
spect  the instantaneous state of the Demand line.  If Command <<00769>>00440000
is asserted while Demand is false, the printer will ignore  it <<00769>>00442000
and  data will be lost.  In fact, this was the cause of numer- <<00769>>00444000
ous problems in earlier releases of this driver.               <<00769>>00446000
  The other villains in this drama  are  the  three  Interrupt <<00769>>00448000
Status bits (Interrupt Status word (8:3)), enabled or disabled <<00769>>00450000
by jumpers in the connecting cable, but managed by the printer <<00769>>00452000
if they are enabled.  Setting any one or more  of  these  with <<00769>>00454000
interrupts enabled will cause an interrupt to the driver.  The <<00769>>00456000
meanings of these bits vary with  the  different  subtypes  of <<00769>>00458000
printers  (see  the  comments  in CHECK'STATUS), but generally <<00769>>00460000
include an off-line and on-line interrupt capability.          <<00769>>00462000
  With this background, we're ready to  examine  what  happens <<00769>>00464000
when the different subtypes of printers go off-line.           <<00769>>00466000
1.  Subtype 0, the 2610/2614 CDC printers, set their  off-line <<00769>>00468000
    interrupt bit the moment the button is pressed.  The driv- <<00769>>00470000
    er may be given control at any point in the  print  cycle. <<00769>>00472000
    The  channel  program is not aborted by the interrupt, and <<00769>>00474000
    so continues to handshake data to the printer, which  con- <<00769>>00476000
    tinues  to  Demand  it  UNTIL the data is a print command. <<00769>>00478000
    Once the print command has been accepted,  Demand  remains <<00769>>00480000
    false  even  after  the  line is printed.  Since the print <<00769>>00482000
    command is the last one in the channel program,  the  pro- <<00769>>00484000
    gram  would complete if the last Demand were received.  It <<00769>>00486000
    therefore remains incomplete.                              <<00769>>00488000
2.  Subtypes 2 and 3, the  2613/17/17J/18  (Dataproducts)  and <<00769>>00490000
    2619 (Dataprinter) printers, are very similar to subtype 0 <<00769>>00492000
    in their off-line behavior.  The only difference  is  that <<00769>>00494000
    the  off-line interrupt bit is not set immediately, but is <<00769>>00496000
    held pending until the current line  is  printed  and  the <<00769>>00498000
    paper is advanced to within one line of its final destina- <<00769>>00500000
    tion.  They too keep Demand false after the final line  is <<00769>>00502000
    printed.                                                   <<00769>>00504000
3.  Subtype 1, the 2607 (Tally) printer behaves much like sub- <<00769>>00506000
    type 2, in that it holds the off-line interrupt bit  pend- <<00769>>00508000
    ing  until the line being printed has finished, then keeps <<00769>>00510000
    Demand false.  The big difference here is  that  the  line <<00769>>00512000
    being  printed  is  NOT the line for which the final hand- <<00769>>00514000
    shake is frozen, but  the  previous  line.   That's  right <<00769>>00516000
    folks,  the 2607 has a one-line buffer in addition to that <<00769>>00518000
    for the line currently being printed.  Betcha didn't  know <<00769>>00520000
    that.    Neither  did your humble scribe until (literally) <<00769>>00522000
    the day before this fix went in.  The  printer  goes  off- <<00769>>00524000
    line  with this line still unprinted.  It is printed auto- <<00769>>00526000
    matically the moment the printer goes back on-line,  which <<00769>>00528000
    creates a special problem for us, about which more below.  <<00769>>00530000
4.  This leaves subtype 4, our own home-grown HP2608.  Whatev- <<00769>>00532000
    er else you say about it, it has both the friendliest  and <<00769>>00534000
    the most unfriendly off-line behavior of all the printers. <<00769>>00536000
    First the good news.  Like the 2607, it has an extra  line <<00769>>00538000
    buffer.   Now the better news.  Unlike the 2607, it prints <<00769>>00540000
    both the current line and the buffered line  before  going <<00769>>00542000
    off-line,  so  no  data  is left unprinted in the printer. <<00769>>00544000
    (You of little faith who wonder how the last line  can  be <<00769>>00546000
    printed  in  a  paper  out  situation should know that the <<00769>>00548000
    printer detects the  impending  end-of-paper  in  time  to <<00769>>00550000
    switch  to a current-line-only mode, accepting no new data <<00769>>00552000
    until it knows there is paper to print it  on).   Now  the <<00769>>00554000
    best  news.   At the completion of this final line, Demand <<00769>>00556000
    wiggles true momentarily (about 1 microsecond)  which  al- <<00769>>00558000
    lows the channel program to complete.                      <<00769>>00560000
      Now some indifferent news.  On-Line and  Not  Ready  are <<00769>>00562000
    two  different  machine  status  bits.  Not Ready causes a <<00769>>00564000
    false On-Line (that is, an off-line indication), but a Not <<00769>>00566000
    On-Line does not cause a Not Ready.   Not  On-Line  occurs <<00769>>00568000
    alone  when  the operator cycles the printer off-line with <<00769>>00570000
    the front panel button.  Not Ready is a  printer-generated <<00769>>00572000
    status which occurs when the printer is unable to continue <<00769>>00574000
    (paper has run out or is jammed, ribbon  is  jammed,  some <<00769>>00576000
    yock opened the platen, etc.).                             <<00769>>00578000
      Finally the bad news.  Although Not Ready causes an  in- <<00769>>00580000
    terrupt  and On-Line causes an interrupt, Not On-Line does <<00769>>00582000
    not.  Thus no interrupt is generated when the operator cy- <<00769>>00584000
    cles the printer off-line.  The only saving grace is  that <<00769>>00586000
    Demand  wiggles one last time, thus completing the channel <<00769>>00588000
    program and causing an interrupt that way.                 <<00769>>00590000
  How do we handle this broad  spectrum  of  operation?   Very <<00769>>00592000
carefully,  I  know.   It turns out that one general algorithm <<00769>>00594000
works very well except when the 2607 goes off-line.  For this, <<00769>>00596000
we introduce some special handling.  The algorithm depends  on <<00769>>00598000
the  fact  that  despite the wide differences in printers, all <<00769>>00600000
printers generate an interrupt at the  end  of  each  physical <<00769>>00602000
print, whether they happen to be on-line or not. The algorithm <<00769>>00604000
also makes use of the property that even  if  the  printer  is <<00769>>00606000
off-line at the time of interrupt, the line we were processing <<00769>>00608000
has been printed. The exception, of course, is the 2607, which <<00769>>00610000
has not printed our current line yet, and this is why  it  re- <<00769>>00612000
quires special handling.                                       <<00769>>00614000
$PAGE                                                          <<00769>>00616000
  The SIO channel program has sections which can  handle  each <<00769>>00618000
type  of request.  For example, there is a section devoted ex- <<00769>>00620000
clusively to printing the previously-buffered  line  during  a <<00769>>00622000
pre-  to postspace print request (mode 3 above).  Another sec- <<00769>>00624000
tion fills the printer buffer.  A third section sends a  print <<00769>>00626000
command  to  the printer.  This last section is repeatedly in- <<00769>>00628000
voked for >15 line slews on those printers which can slew only <<00769>>00630000
15 lines at a time.  Then there are other  specialty  sections <<00769>>00632000
which  support  functions exclusive to the 2608 (such as Down- <<00769>>00634000
load VFC, Download Left Margin, etc.).  For a  given  request, <<00769>>00636000
IOLPRT0  sets  up all the parameters for all the required sec- <<00769>>00638000
tions of the channel program in the initiation section.   This <<00769>>00640000
means  that  all  the continuation section must do is redirect <<00769>>00642000
the start of the channel program to the  next  section  to  be <<00769>>00644000
run  (if any), and re-start the channel program (after verify- <<00769>>00646000
ing that the printer is still on-line).                        <<00769>>00648000
  For normal requests (all  but  2607  off-lines),  there  are <<00769>>00650000
three controlling flags:                                       <<00769>>00652000
1.  A PRE'TO'POSTspace flag, indicating a mode 3 operation.    <<00769>>00654000
2.  A PRESPACE flag, indicating a mode 2 operation.            <<00769>>00656000
3.  A LINES'LEFT'OVER flag indicating:                         <<01061>>00658000
  a)  Multiple slews of <=15 lines each for slew requests  >15 <<01061>>00660000
      lines on subtype 1, 2 and 3 printers.                    <<01061>>00662000
  b)  Multiple skips to VFC channel 3 (advance one  line  with <<01061>>00664000
      auto  page  eject is standard) when a "0" (double space) <<01061>>00666000
      or "-" (triple space) carriage control character is  re- <<01061>>00668000
      ceived and the NO'AUTO'PAGE eject bit (IOQ(QPAR2).(14:1))<<01061>>00670000
      is off.                                                  <<01061>>00672000
    This flag operates in any of modes 1-4.                    <<01061>>00674000
The continuation  section  then  operates  as  follows  (after <<01061>>00676000
checking for grossities such as transfer and timeout errors):  <<01061>>00678000
                                                               <<01061>>00680000
  IF TALLY WENT OFFLINE THEN                                   <<01061>>00682000
    SET TALLY'NOT'READY (special flag saying so).              <<01061>>00684000
                                                               <<01061>>00686000
  IF PRE'TO'POST THEN                                          <<01061>>00688000
    BEGIN  (dumped last line, now do what we came for)         <<01061>>00690000
    CLEAR PRE'TO'POST.                                         <<01061>>00692000
    RE-DIRECT CHANNEL PROGRAM TO BUFFER FILL SECTION,          <<01061>>00694000
      IT WILL AUTOMATICALLY PRINT AFTER FILLING BUFFER.        <<01061>>00696000
    SEE IF PRINTER IS STILL ON LINE (assume yes for now).      <<01061>>00698000
    RE-START CHANNEL PROGRAM.                                  <<01061>>00700000
    END                                                        <<01061>>00702000
$PAGE                                                          <<01061>>00704000
  IF LINES'LEFT'OVER <> 0 THEN                                 <<01061>>00706000
    IF MULTIPLE SLEWS OF <=15 LINES                            <<01061>>00708000
      THEN IF LINES'LEFT'OVER > 15                             <<01061>>00710000
        THEN                                                   <<01061>>00712000
           BEGIN                                               <<01061>>00714000
           REDUCE LINES'LEFT'OVER BY 15.                       <<01061>>00716000
           SPACE 15 MORE LINES (if printer on line).           <<01061>>00718000
           END                                                 <<01061>>00720000
        ELSE                                                   <<01061>>00722000
           BEGIN                                               <<01061>>00724000
           SPACE LINES'LEFT'OVER MORE LINES.                   <<01061>>00726000
           SET LINES'LEFT'OVER TO 0 (to end this loop).        <<01061>>00728000
           END                                                 <<01061>>00730000
      ELSE                                                     <<01061>>00732000
         BEGIN (multiple skips to channel 3)                   <<01061>>00734000
         REDUCE LINES'LEFT'OVER BY 1.                          <<01061>>00736000
         DO ONE SKIP TO VFC CHANNEL 3 (if on line)             <<01061>>00738000
         END                                                   <<01061>>00740000
                                                               <<01061>>00742000
  IF PRESPACE (mode 2)                                         <<01061>>00744000
    THEN RE-DIRECT TO BUFFER FILL SECTION AND GO DO IT.        <<01061>>00746000
                                                               <<01061>>00748000
  CLEAN UP AND EXIT if none of the above.                      <<01061>>00750000
                                                               <<01061>>00752000
It can be seen that the channel  program  is  always  properly <<01061>>00754000
configured when we leave here, whether we continue the request <<01061>>00756000
or complete it and come back in for the next request.   There- <<01061>>00758000
fore, if the printer should be off-line when we check it (just <<01061>>00760000
before starting the channel program), we can always react  the <<01061>>00762000
same  way  (except for Tally, see below), namely to notify the <<01061>>00764000
operator and wait for  him/her  to  put  the  printer  on-line <<01061>>00766000
again.  We can then begin or continue our request.             <<01061>>00768000
  If we are returning from a Not Ready wait, we may  find  the <<LB.09>>00770000
absolute  memory  address  we put in the channel program is no <<LB.09>>00772000
longer valid. This is because SIODM (see Structure of IOLPRT0) <<LB.09>>00774000
unfreezes the data segment containing our buffer when we enter <<LB.09>>00776000
SIODM's Not Ready wait state.  This in turn allows the  Memory <<LB.09>>00778000
Manager  to  swap out the data segment rather than tie up real <<LB.09>>00780000
memory while the printer is idle. The data segment is returned <<LB.09>>00782000
to real memory before the driver is called again, but  (usual- <<LB.09>>00784000
ly) not at the same address. When we come back on line, there- <<LB.09>>00786000
fore, the channel program is updated with new addresses if re- <<LB.09>>00788000
quired by the current request.                                 <<LB.09>>00790000
  The Tally presents a unique problem.  When it goes  on-line, <<01061>>00792000
it still has a line to print, and immediately sets about doing <<01061>>00794000
it.  If we check the printer immediately,  its  Demand  signal <<01061>>00796000
will be false, causing us to assume that it is still off-line, <<01061>>00798000
and we will report it as such.  The operator will be confused, <<01061>>00800000
because s/he can see it is really on-line.  So, for Tally  on- <<01061>>00802000
ly,  we  institute a three-second delay when it comes on line, <<01061>>00804000
just to get that line out, THEN we  recheck  the  printer  and <<01061>>00806000
continue.  Three seconds may be required if the buffered print <<01061>>00808000
command skips an entire page (Tally's are SLOW).               <<01061>>00810000
  Now you know the major pitfalls to avoid.   Minor  ones  are <<01061>>00812000
commented on in the body of the text.  You're on your own now. <<01061>>00814000
Good luck!                                                     <<01061>>00816000
$PAGE                                                                   00818000
Structure of IOLPRT0:                                                   00820000
  IOLPRT0, together with the SIO Device Monitor (SIODM) constitute  a   00822000
standard  MPE Type 1 I/O Driver/Monitor, which means that it does not   00824000
run  in  its  own  process,  but  executes  on  any  stack.    During   00826000
initialization   it   executes  on  PROGEN's  stack,  during  request   00828000
initiation it executes on  ATTACHIO's  stack,  and  during  interrupt   00830000
processing  it executes on the Interrupt Control Stack (ICS).  Type 1   00832000
monitors have other requirements which differentiate them from Type 2   00834000
and Type 3 monitors.  A more complete description may be found in the   00836000
MPE/30 I/O System IMS, dated December 12, 1975.                         00838000
  IOLPRT0 consists of a global area, three procedures (LPDRVR, <<00769>>00840000
CHECK'STATUS and LPINIT) which are the guts of the driver, and <<00769>>00842000
an "outer block" which is really a linkage area  for  INITIAL.          00844000
The  global  area  contains three arrays.  The first of these,          00846000
DRIVER'CONFIG, specifies the size of the other two as well  as          00848000
providing  some  other  parameters for INITIAL.  It is deleted          00850000
after INITIAL is through with it.  The other  two  arrays  are          00852000
the  Device  Information  Table (DIT) and the unconfigured SIO          00854000
channel program area.  INITIAL will put each of these  in  the          00856000
area  of  memory where it belongs.  The linkage area specifies          00858000
the procedure labels  (p-labels)  of  the  associated  monitor          00860000
(SIODM), the request initiator (LPDRVR), the request completor          00862000
(again LPDRVR), the initialization procedure  (LPINIT,  called          00864000
by PROGEN at system startup) and the interrupt handler (GIP).           00866000
  IOLPRT0 cannot be readily understood without a good picture of  the   00868000
DIT  and  the  IOQ  as  they apply to line printers, and so these are   00870000
shown pictorially and described on the  next  few  pages.   Following   00872000
this  is  a  summary of supported functions and the statuses returned   00874000
when a request is complete.                                             00876000
$PAGE                                                                   00878000
                   Device Information Table (DIT)                       00880000
                   ------------------------------                       00882000
                                                                        00884000
                                                                        00886000
  There is one  DIT  per  physical  device.   If  a  physical  device   00888000
represents more than one logical device, the logical device number is   00890000
obtained from the IOQ element.  The following diagram shows  the  DIT   00892000
used for IOLPRT0.                                                       00894000
                                                                        00896000
     0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15    MNEMONIC         00898000
   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+                    00900000
  0| 0| 0|AC|RQ| 0| 0| 0|IO|AK|PS|NE|TF|   STATE   |   DFLAG            00902000
   +--+--+--+--+--+--+--+--+--+--+--+--+-----------+                    00904000
  1| SYSDB relative pointer to the DIT for the next|   DLINK            00906000
   | device requesting this resource or service    |                    00908000
   +-----------------------------------------------+                    00910000
  2| SYSDB relative pointer to the first IOQ in    |   DIOQP            00912000
   | request list for this device                  |                    00914000
   +--------+--------------------------------------+                    00916000
  3|        | Phys unit #  | Logical device number |   DLDEV            00918000
   +--------+--------------------------------------+                    00920000
  4| SYSDB relative pointer to Device Linkage Table|   DDLTP            00922000
   +-----------------------------------------------+                    00924000
  5| SYSDB relative ptr to Interrupt Linkage Table |   DILTP            00926000
   +-----------------------------------------------+                    00928000
  6| Controller interrupt status.  Set by GIP each |   DSTAT            00930000
   | time it processes an interrupt for this DIT.  |                    00932000
   | See individual field descriptions on nxt page.|                    00934000
   +-----------------------------------------------+                    00936000
  7| Hardware error pointer. Set when the driver   |   DSERR   <<01339>>00938000
   | detects an error.  Whenever <> 0, the driver  |                    00940000
   | monitor logs an I/O error and clears this word|                    00942000
   +-----------------------------------------------+                    00944000
%10| Bit 0 is set at completion of 2-second timer. |   DTIME            00946000
   +-----------------------------------------------+                    00948000
%11| Timer Request List Index.  Not used except to |   DTRLX            00950000
   | clear the request after timing out.           |                    00952000
   +-----------------------+-----------------------+                    00954000
%12|                       |Last byte if odd bytcnt|   DLAST            00956000
   |                       | Data byte for VFC or  |                    00958000
   |                       | left margin download  |                    00960000
   +--+--+--+--+-----------+-----------------------+           <<00464>>00962000
%13|VF|PF|BT|TL|Left margin| Vertical Format Code  |   DVFC1   <<00769>>00964000
   |MD|RS|JB|NR|           |                       |           <<00769>>00966000
   +--+--+--+--+-----------+-----------------------+           <<00464>>00968000
%14| Lines left to skip    | %202 (2608) or %102.  |   DVFC2   <<00769>>00970000
   | (subtypes 1, 2, >15   | Skip to channel 3 pre-|           <<00769>>00972000
   | line slew request)    | to postspace print.   |           <<00769>>00974000
   +-----------------------+-----------------------+                    00976000
%15|       HARDWARE ERROR LOGGING STATUS           | DLOGERROR <<01339>>00978000
   +-----------------------------------------------+           <<01339>>00980000
%16| DVR DEPENDENT FLAGS =>   |PS|NE|TF|           |   DDF              00982000
   +--+--+--+--+--+--+--+--+--+--+--+--+-----------+                    00984000
$PAGE                                                                   00986000
DFLAG.AC - Active.  A monitor is currently servicing this device. *     00988000
DFLAG.RQ - Request.  A service request is pending while  the  monitor   00990000
             is active. *                                               00992000
DFLAG.IO - An I/O channel program is in progress.  Decrement SIOCOUNT   00994000
             and check for multiple channels when complete. *           00996000
DFLAG.AK - Interrupt Acknowledge.  An interrupt has occurred. *         00998000
DDF  .PS - Prespace.  The last request was  a  prespace  (space  then   01000000
             fill buffer) operation.                                    01002000
DDF  .NE - Not Empty.  The print buffer is not empty.  Causes a print   01004000
             when changing from pre- to postspace or before  ejecting   01006000
             a page for a File Open, File Close or Device Close.        01008000
DDF  .TF - Top of Form.  The  last  request  ended  with  a  skip  to   01010000
             channel 1 (page eject).                                    01012000
                                                                        01014000
           * Not examined or modified by IOLPRT0.                       01016000
                                                                        01018000
DFLAG.STATE - State of the device monitor.  Specifies the next action   01020000
                to be taken by SIODM in servicing  the  request.  Not   01022000
                used within IOLPRT0.                                    01024000
                                                                        01026000
DSTAT.(0:1) - SIO OK. Set when no SIO channel program is in progress,   01028000
                that is, it is OK to start one.                         01030000
     .(1:1) - WIO OK.  Set when it is OK to execute a WIO instruction   01032000
                or  a  doubleword  WRITE  channel  order.  If  clear,   01034000
                indicates that a one word transfer is in progress.      01036000
     .(2:1) - Interrupt Pending.  If set, indicates one or more  bits   01038000
                of the Interrupt Status Byte (DSTAT.(8:8) are set.      01040000
     .(3:2) - U.I. Transfer State.  Used mostly for hardware mainten-   01042000
                ance. See U.I. card manual (30051-90001) for details.   01044000
     .(5:1) - Device   Flag.  Indicates   a   print-and-advance-paper   01046000
                sequence in progress.  Since the  2608  buffers  such   01048000
                commands,  this signal may be shorter than with other   01050000
                printers.                                               01052000
     .(6:1) - Always 0.  DSTAT.(8:8) always  contains  the  Interrupt   01054000
                Status Byte.                                            01056000
     .(7:1) - Not used.  Always 0.                                      01058000
     .(8:3) - Varies among HP-supported line  printers  according  to   01060000
                the table below:                                        01062000
                                                                        01064000
  SUBTYPE   MODEL(S)          BIT 8     BIT 9     BIT 10                01066000
  -------   --------          -----     -----     ------                01068000
                                                                        01070000
     0      2610, 2614        LINE      READY     NOT                   01072000
                              PRINTED             READY                 01074000
                                                                        01076000
     1      2607              Not       READY     NOT                   01078000
                              used                READY                 01080000
                                                                        01082000
     2      2613, 2617, 2618, Not       READY     NOT                   01084000
            2619              used                READY                 01086000
                                                                        01088000
     3      2617J (KATAKANA)  Not       READY     NOT                   01090000
                              used                READY                 01092000
                                                                        01094000
     4      2608              ON        NOT       VFC                   01096000
                              LINE      READY     CHAN 9                01098000
$PAGE                                                                   01100000
    .(11:1) - Data Transfer Interrupt bit.  Always 0.                   01102000
    .(12:1) - Not used.  Always 0.                                      01104000
    .(13:1) - Programmed Interrupt bit.  True  if  interrupt  request   01106000
                was generated by:                                       01108000
              a)  SIN machine instruction,                              01110000
              b)  INTERRUPT channel order, or                           01112000
              c)  END-WITH-INTERRUPT channel order.                     01114000
    .(14:1) - Transfer Error Interrupt bit.  True  if  interrupt  was   01116000
                generated by:                                           01118000
              a)  an illegal memory address,                            01120000
              b)  a memory parity error, or                             01122000
              c)  a multiplexer parity error during data xfr to  U.I.   01124000
    .(15:1) - Time-out Interrupt bit.  Set if 5-second timer on  U.I.   01126000
                card  is  enabled,  then  times  out  without   being   01128000
                cleared.                                                01130000
                                                                        01132000
DLAST.(8:8) - Request dependent.  If  a  print  request  has  an  odd   01134000
                number of bytes, this word holds the final byte.  For   01136000
                VFC downloads, contains the associated data  byte  (6   01138000
                or 8 lines per inch and number of lines in VFC).  For   01140000
                left margin downloads, also contains  the  associated   01142000
                data byte (the number of columns to offset).            01144000
DVFC1.(0:1) - VFC Modified.  2608 only.  Indicates that  an  external   01146000
                VFC has been downloaded into the 2608.                  01148000
DVFC1.(1:1) - Power Fail/Reset.  2608 only.  The 2608 has suffered  a   01150000
                Power  Failure or someone has pressed the front panel   01152000
                Reset button. In either case, the printer's operating   01154000
                environment has been destroyed, and must be  reloaded   01156000
                by the operator.                                        01158000
DVFC1.(2:1) - Between Jobs.  Set when a  Device  Close  is  executed,   01160000
                cleared when an FOPEN is performed.  2608 Power Fail/   01162000
                Master Reset's will be cleared but not reported while   01164000
                this  bit is set (thus avoiding an extraneous console   01166000
                message when the printer is powered up).                01168000
DVFC1.(3:1) - TALLY'NOT'READY.  Set when an off-line condition <<00769>>01170000
              is detected on a  2607.  Causes  a  three-second <<00769>>01172000
              delay when the 2607 comes back on-line.          <<00769>>01174000
DVFC1.(4:4) - Left margin offset (2608  only).  Stored  during <<00770>>01176000
                each  :DOWNLOAD  which specifies a left margin <<00770>>01178000
                and restored to printer following a 2608 power <<00770>>01180000
                fail or reset.  Set to 0 when system  is  ini- <<00770>>01182000
                tialized.                                      <<00770>>01184000
DVFC1.(8:8) - Request dependent.  Contains the carriage control  byte   01186000
                sent to the printer during a print request.             01188000
$PAGE                                                                   01190000
DVFC2.(0:8) - LINES'LEFT'OVER.  Has two functions:             <<01061>>01192000
            1)  The 2607/13/17/18/19 can only  slew  (skip)  a <<01061>>01194000
                maximum  of  15  lines  per print command (not <<01061>>01196000
                counting  VFC  skips,  which  can  be  of  any <<01061>>01198000
                length).    Slew  requests  > 15 lines must be <<01061>>01200000
                broken up.  This  byte  holds  the  number  of <<01061>>01202000
                lines  (greater  than  15)  which remain to be <<01061>>01204000
                slewed at any point of a  request  to  such  a <<01061>>01206000
                printer,  or  0 if the number of lines to skip <<01061>>01208000
                is <= 15.  This mechanism is not  needed  (and <<01061>>01210000
                this  field  is  therefore 0) for CDC and 2608 <<01061>>01212000
                line printers, which can slew up to  63  lines <<01061>>01214000
                at a time.                                     <<01061>>01216000
            2)  The carriage control  characters  "0"  in  "-" <<01061>>01218000
                specify double and triple spacing, respective- <<01061>>01220000
                ly.  But if you  use  the  equivalent  channel <<01061>>01222000
                skip,  you get skips to the next odd and third <<01061>>01224000
                lines, respectively, which is not the same  as <<01061>>01226000
                double  and  triple spacing.  If you slew (ad- <<01061>>01228000
                vance paper) 2 or  3  lines,  you  can  easily <<01061>>01230000
                print  over the paper perforations unless your <<01061>>01232000
                program watches out for such things.  We avoid <<01061>>01234000
                this by examining the NO'AUTO'PAGE  eject  bit <<01061>>01236000
                (IOQ(QPAR2).(14:1)).    If it is set, then the <<01061>>01238000
                request is treated  like  a  normal  slew  and <<01061>>01240000
                LINES'LEFT'OVER  is  not used.  If it is clear <<01061>>01242000
                (auto eject desired),  then  we  simulate  the <<01061>>01244000
                multiple line skip by doing two ("0") or three <<01061>>01246000
                ("-") skips to channel 3 (single  spaces  with <<01061>>01248000
                auto  page  eject  for  the standard VFC).  In <<01061>>01250000
                this case, LINES'LEFT'OVER holds the number of <<01061>>01252000
                such single spaces remaining in the request.   <<01061>>01254000
DVFC2.(8:8) - %202 for 2608, %102 otherwise.  Causes skip to  channel   01256000
                3  (single  space  with  auto page eject).  Used when   01258000
                last request left data in print buffer (prespace) and   01260000
                current operation  is  postspace.  Buffer  is  dumped   01262000
                first, using this byte as carriage control.             01264000
$PAGE                                                                   01266000
                       I/O QUEUE ELEMENT (IOQ)                          01268000
                       -----------------------                          01270000
                                                                        01272000
                                                                        01274000
     0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15    MNEMONIC         01276000
   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+                    01278000
  0|      Request dependent flags (see below)      |   QFLAG            01280000
   +--+--+--+--+--+--+--+--+--+--+--+--+-----+--+--+                    01282000
  1| SYSDB relative pointer to next IOQ element.   |   QLINK            01284000
   | Points to first word of element.              |                    01286000
   +-----------------------+-----------------------+                    01288000
  2| Physical unit number  | Logical device number |   QLDEV            01290000
   +--------------------+--+-----+-----+--+--+--+--+           <<00571>>01292000
  3|                    | WAITFLD|     |RT|MC|PS|PP|   QMISC   <<00769>>01294000
   +--+-----------------+--------+-----+--+--+--+--+           <<00571>>01296000
  4| S| If QFLAG.(3:1) is clear then this is the   |   QDSTN            01298000
   |  | DST number of the target data segment.  If |                    01300000
   |  | S is set, QADDR is DB relative.            |                    01302000
   +--+--------------------------------------------+                    01304000
  5| Offset in the data segment or system buffer   |   QADDR            01306000
   | table to the target data buffer.              |                    01308000
   +-----------------------+-----------------------+                    01310000
  6|       Not used        | Function code for     |   QFUNC            01312000
   |                       | this request.  See    |                    01314000
   |                       | next section.         |                    01316000
   +-----------------------------------------------+                    01318000
  7| On initiation, specifies the word count (>0)  |   QWBCT            01320000
   | or byte count (<0).  At completion of the     |                    01322000
   | request this location contains the actual     |                    01324000
   | transmission count in the same units (bytes   |                    01326000
   | or words) as in the request.  The count is    |                    01328000
   | truncated to produce a max of 256 characters. |           <<00464>>01330000
   +-----------------------------------------------+                    01332000
%10|    Parameter 1 of QFUNC.  See next section.   |   QPAR1            01334000
   +-----------------------------------------------+                    01336000
%11|    Parameter 2 of QFUNC.  See next section.   |   QPAR2            01338000
   +-----------------------+--------------+--------+                    01340000
%12|         PCBN          |  QUALIFIER   | STATUS |   QSTAT            01342000
   +-----------------------+--------------+--------+                    01344000
                                                                        01346000
QFLAG - Request dependent flags                                         01348000
                                                                        01350000
Bit 0  .ABORT     - Request has been aborted  externally,  either  by   01352000
                    the operator or a system intrinsic.                 01354000
Bit 1  .SPECIAL   - Not used.                                           01356000
Bit 2  .DIAG      - Not used.                                           01358000
Bit 3  .SYSBUFRS  - Target is a system-buffer-relative index  to  the   01360000
                    data buffer. *                                      01362000
Bit 4  .IOWAKE    - Wake caller on completion of request. *             01364000
Bit 5  .BLOCKED   - Blocked  I/O.   The  caller is waited in ATTACHIO   01366000
                    until the request is completed. Implies IOWAKE. *   01368000
Bit 6  .COMPLETED - Request   has  been  completed,  and  the  caller   01370000
                    awakened if s/he had requested (with IOWAKE). *     01372000
Bit 7  .DATAFRZN  - If  set,  then  the  data  segment  has been made   01374000
                    present and frozen in memory.  Set by the  memory   01376000
                    management  routines  (MAM)  when  a  MAKEPRESENT   01378000
                    request is successfully completed. *                01380000
Bit 8  .MAMERRORD - An error has occurred while  MAM  was  trying  to   01382000
                    make  the  target data segment present and freeze   01384000
                    it in memory. *                                     01386000
Bit 9  .PREQ      - Not used.                                           01388000
Bit 10 .SFAIL     - Delayed failure of SIO instruction.  If a call to   01390000
                    STARTIO  resulted  in  the request being added to   01392000
                    the channel queue, this bit  indicates  that  the   01394000
                    SIO  instruction  failed  when  the  request  was   01396000
                    selected for execution.                             01398000
Bit 11 .PFAIL     - The request was aborted because of a system power   01400000
                    failure.                                            01402000
Bits12-13 .PREMPT - Not used.                                           01404000
Bit 14 .          - Not used.                                           01406000
Bit 15 .MSGDONE   - Not used.                                           01408000
                                                                        01410000
QMISC.WAITFLD - This  field  contains  a  code describing the current   01412000
                idle state of the driver.  The driver orients  itself   01414000
                at  each  entry,  based  on  the state of this field.   01416000
              0 - The current entry is the start of a new request.      01418000
              1 - The  normal  state  while  waiting for a completion   01420000
                  interrupt of a print, fill or control operation.      01422000
              2 - An SIO channel program was in progress  when <<00769>>01424000
                  an asynchronous interrupt (usually an exter- <<00769>>01426000
                  nal abort) occurred, or a 2607  printer  was <<00769>>01428000
                  placed  on-line  after  going off-line while <<00769>>01430000
                  printing.  The driver enters this state  and <<00769>>01432000
                  waits for three seconds for the channel pro- <<00769>>01434000
                  gram or 2607 printer to complete, so as  not <<00769>>01436000
                  to  pose  control conflicts to the U.I. card <<00769>>01438000
                  between the driver and the program.          <<00769>>01440000
              3 - A  Not  Ready,  Off  Line  or Paper Out (or Jammed)   01442000
                  condition has been detected.  The request  will  be   01444000
                  continued   or   retried   when  the  operator  has   01446000
                  corrected the condition and placed the  printer  on   01448000
                  line.                                                 01450000
              4 - A 2607 (Tally) printer has come on-line  af- <<00769>>01452000
                  ter going off-line while printing.  One line <<00769>>01454000
                  of data is buffered in  the  printer.   This <<00769>>01456000
                  state  causes the driver to shift to state 2 <<00769>>01458000
                  to allow the 2607 to  print  and  space  the <<00769>>01460000
                  buffered  line  before  sending  it the next <<00769>>01462000
                  line.                                        <<00769>>01464000
QMISC.(12:1)  - RETRY (RT).  Kludge to catch an LDEV configured as  a   01466000
                2608 when the physical device is a different subtype.   01468000
                Prevents Master Clear'ing and retrying a request more   01470000
                than once when the Power Fail/Reset device status bit   01472000
                is "set" by a non-2608.                        <<00571>>01474000
QMISC.(13:1)  - MASTER'CLEAR (MC).  Set when  a  2608  Master  Reset,   01476000
                required  because  of  a printer Power Fail/Reset, is   01478000
                configured and executed.                                01480000
QMISC.(14:1)  - PRESPACE (PS). The current operation is a pre- <<00769>>01482000
                space (space then print) request.  This bit a- <<00769>>01484000
                lerts the continuation  section  to  fill  the <<00769>>01486000
                print buffer after spacing.                    <<00769>>01488000
$PAGE                                                          <<00769>>01490000
QMISC.(15:1)  - PRE'TO'POST (PP). The previous request was a prespace   01492000
                operation while the current operation is a postspace.   01494000
                                                               <<00769>>01496000
QSTAT.PCBN    - The Process Control Block (PCB) number of the process   01498000
                which made this request.  If zero, the request is not   01500000
                associated with any process, and the IOQ  element  is   01502000
                to  be  returned  by  the system when the request has   01504000
                completed. *                                            01506000
QSTAT.STATUS  - General status.  Indicates the  final  state  of  the   01508000
                request.  The following codes are used:                 01510000
                  0 - Not started, or awaiting completion.              01512000
                  1 - Successful completion.                            01514000
                  2 - Not used.                                         01516000
                  3 - Unusual, but recoverable,  condition  (such  as   01518000
                      Request Aborted Externally).                      01520000
                  4 - Irrecoverable  error  (such  as  SIO   failure,   01522000
                      memory parity error, etc.).                       01524000
QSTAT.QUALIFIER - A  code  which  further  defines  or  qualifies the   01526000
                  general status. See the section after the next one.   01528000
                                                                        01530000
                  * Not examined or modified by IOLPRT0.                01532000
                                                               <<00770>>01534000
  The fix denoted by the number in the right margin is an  en- <<00770>>01536000
hancement.   This enhancement deletes the Master Clear hereto- <<00770>>01538000
fore sent to a 2608 line printer as part of the  Device  Close <<00770>>01540000
function.  The Master Clear was originally put in to guarantee <<00770>>01542000
that a previous output file using a special print  environment <<00770>>01544000
(VFC,  left  margin,  etc.) would not affect the current file. <<00770>>01546000
Unfortunately, we did not at the same time  give  the  user  a <<00770>>01548000
method  of  maintaining  a  custom environment throughout many <<00770>>01550000
output files, and many users operate in this  fashion.   Their <<00770>>01552000
complaints  have  prompted  this  enhancement which, in retro- <<00770>>01554000
spect, is far more consistent with the other printers.  Once a <<00770>>01556000
VFU tape has been installed in a 2617 (for example), it  stays <<00770>>01558000
there  until  replaced.  The same will now be (logically) true <<00770>>01560000
for a 2608.  The only difference is that 2617  VFU  tapes  can <<00770>>01562000
survive  a  power failure, whereas 2608 VFC's and left margins <<00770>>01564000
cannot.  Destruction of a 2608's custom  environment  will  be <<00770>>01566000
reported  to  the associated user or to the console, as in the <<00770>>01568000
past, and it will be up to that user to restore the lost envi- <<00770>>01570000
ronment, until a more comprehensive recovery mechanism is  de- <<00770>>01572000
veloped.                                                       <<00770>>01574000
  One exception to the above -- 2608 left margin settings will <<00770>>01576000
be maintained by the driver.  Should the 2608 be reset, either <<00770>>01578000
because of a power failure or the RESET button being  pressed, <<00770>>01580000
the  most  current  left  margin  sent  to the printer via the <<00770>>01582000
:DOWNLOAD command will be restored to the  printer.   This  is <<00770>>01584000
done  both as a convenience to the user (read "operator"), and <<00770>>01586000
to allow us to keep the "between jobs" concept,  whereby  2608 <<00770>>01588000
Master  Resets  are  not  reported if they occur between jobs. <<00770>>01590000
Since left margin settings are also destroyed by a Master  Re- <<00770>>01592000
set, we would have to report them between jobs as well as dur- <<00770>>01594000
ing jobs if the driver did not maintain the left  margin  set- <<00770>>01596000
ting  on  its  own.  Note that if a custom VFC is destroyed by <<00770>>01598000
the Master Reset, it will be reported as a  "VFC  Initialized" <<00770>>01600000
condition, no matter when it occurs.                           <<00770>>01602000
$PAGE                                                                   01604000
  The following table summarizes the tasks (functions)  supported  by   01606000
IOLPRT0:                                                                01608000
                                                                        01610000
                                                                        01612000
  OPERATION  QFUNC  PARAMETERS (QPAR1, QPAR2, QWBCT)                    01614000
  --------------------------------------------------                    01616000
                                                                        01618000
    WRITE      1     QPAR1 -- Vertical Format Specification.            01620000
                     QPAR2 -- Mode control flags.                       01622000
                     QWBCT -- <0 ==> bytes,  >0  ==>  words,  =0  ==>   01624000
                              advance paper only.                       01626000
                                                                        01628000
    FILE OPEN  2     No params.  Page eject if not already at top  of   01630000
                     form.                                              01632000
                                                                        01634000
    FILE CLOSE 3     Same as FILE OPEN.                                 01636000
                                                                        01638000
    DEVICE     4     Same as FILE OPEN.                        <<00770>>01640000
    CLOSE                                                      <<00770>>01642000
                                                               <<00770>>01644000
                                                                        01646000
    DOWNLOAD  %100   QPAR1 -- 6 or 8  (lines  per  inch).  Any  other   01648000
    VFC                       value ==> 6.                              01650000
    (2608 only)      QPAR2 -- Not used.                                 01652000
                     QWBCT -- Form (VFC) length.  <0  ==>  bytes,  >0   01654000
                              ==>  words,  =0  ==>  reload  printer's   01656000
                              internal VFC.                             01658000
                     BANK/ -- Address of VFC buffer to be sent to the   01660000
                   BUFADDR    printer.                                  01662000
                                                                        01664000
    SET LEFT  %101   QPAR1 -- Logical to physical column offset, 0 to   01666000
    MARGIN                    15.  Any other value ==> 15.              01668000
    (2608 only)      QPAR2 -- Not used.                        <<00770>>01670000
                                                               <<00770>>01672000
                                                                        01674000
  If function code %100 or %101 is sent to a printer which  is          01676000
not  a  2608, or if any function code not listed above is sent          01678000
to any printer, it will be rejected as an invalid request (see          01680000
completion statuses below).  Should you want to add new  func- <<00769>>01682000
tions,  they can be inserted where the appropriate comment in- <<00769>>01684000
dicates (just before the start of the completion section).     <<00769>>01686000
$PAGE                                                                   01688000
  For QFUNC = 1 (write), QPAR1 and QPAR2 are interpreted as  follows:   01690000
                                                                        01692000
  QPAR1          MEANING                                                01694000
  ------------------------------------------------------------          01696000
                                                                        01698000
  %53,       ASCII "+", suppress space (single space on 2607)  <<00770>>01700000
  %55,       ASCII "-", triple space, with/without auto eject  <<01061>>01702000
  %60,       ASCII "0", double space, with/without auto eject  <<01061>>01704000
  %61,       ASCII "1", top of form*                                    01706000
                                                                        01708000
  %200-%277, slew n-%200 lines (0-63)  (0 ==> 1 on 2607)       <<00770>>01710000
  %300-%317, skip to VFC channel N-%277 (within limits of printer)      01712000
                                                                        01714000
  %320,      append to current buffer without printing                  01716000
                                                                        01718000
   1,        the Vertical Format character is the first byte  in  the   01720000
             data  buffer. It is not sent to the printer as data.  If   01722000
             the first byte is not one of the above, a  single  space   01724000
             is  assumed.  Use QPAR2.(14:1) to determine if the space   01726000
             is with or without automatic  page  eject.   The  format   01728000
             character  is  included in the word/byte count in QWBCT,   01730000
             therefore QWBCT may not be 0  if  QPAR1  =  1.   Such  a   01732000
             condition   will  cause  an  immediate  completion  with   01734000
             Invalid Request status (QSTAT.(8:8) = 4).                  01736000
                                                                        01738000
  ANY OTHER, assume single space.  Check QPAR2.(14:1), as above.        01740000
                                                                        01742000
  *   Page ejects (skips to VFC channel 1)  are  suppressed  whenever   01744000
      the previous operation ended with a page eject.                   01746000
                                                                        01748000
QPAR2 -- Mode control flags.  These are two 1-bit flags.                01750000
  QPAR2.(15:1) -- Prespace flag.   If  set,  the  request  is  for  a   01752000
space-then-print,  or prespace, operation.  Since all HP printers are   01754000
mechanically postspace printers, prespace  mode  must  be  simulated.   01756000
This  is  done  by printing any previously transmitted data using the   01758000
Vertical Format specification of the current QPAR1, then filling  the   01760000
printer  buffer  (without  printing)  with  the  current  contents of   01762000
BANK/BUFADDR.                                                           01764000
  If  the  Prespace  flag  is  clear,  IOLPRT0  performs  a postspace   01766000
operation, filling the printer buffer from BANK/BUFADDR and  printing   01768000
using the Vertical Format specification of QPAR1.                       01770000
  NOTE:  If a  postspace  operation  follows  a  prespace  operation,   01772000
IOLPRT0  first prints any previously existing data with a skip to VFC   01774000
channel 3 (single space with automatic page  eject  --  QPAR2.(14:1),   01776000
the  no-auto-page-eject flag, is not examined).  It then executes the   01778000
postspace request.                                                      01780000
  QPAR2.(14:1) -- No automatic page eject flag.  If  set,  the <<01061>>01782000
single/double/triple  space  called for by the default/"0"/"-" <<01061>>01784000
carriage control will be executed as a slew, that is,  without <<01061>>01786000
regard to the logical bottom of form or the paper perforation. <<01061>>01788000
If the flag is clear, the default/"0"/"-" carriage control  is <<01061>>01790000
executed as 1/2/3 skips to VFC channel 3.  When using the 6 or <<01061>>01792000
8 lines per inch standard VFC pattern, this causes a  skip  to <<01061>>01794000
the  top  of  the next form if the spacing would go beyond the <<01061>>01796000
logical bottom of form.                                        <<01061>>01798000
$PAGE                                                                   01800000
  The following table lists the possible status  values  returned  by   01802000
IOLPRT0 at request completion:                                          01804000
                                                                        01806000
                                                                        01808000
GENERAL             QUALIFYING   OVERALL                                01810000
(13:3)                (8:5)       (8:8)                                 01812000
----------------------------------------                                01814000
                                                                        01816000
1 - Successful          0           1     Operation    complete,   no   01818000
                                          errors.                       01820000
                                                                        01822000
3 - Unusual             3          %33    Request aborted externally.   01824000
                                                                        01826000
                        6          %63    Power fail abort.             01828000
                                                                        01830000
                       %21         %213   Printer   powered   on   or   01832000
                                          master  cleared.   VFC/left   01834000
                                          margin/top      of     form   01836000
                                          environment     must     be   01838000
                                          restored.                     01840000
                                                                        01842000
                       %27         %273   VFC  has  been   reset   to   01844000
                                          default   at  the  printer.   01846000
                                          Custom VFC environment must   01848000
                                          be restored.                  01850000
                                                                        01852000
4 - Irrecoverable       0           4     Invalid  request  (function   01854000
                                          or parameter.                 01856000
                                                                        01858000
                        1          %14    Transfer error:               01860000
                                          a) Illegal  memory  address   01862000
                                          b) Memory   parity    error   01864000
                                          c) Parity error in transfer   01866000
                                                                        01868000
                        2          %24    Timeout error, printer took   01870000
                                          too long.                     01872000
                                                                        01874000
                        4          %44    SIO failure, couldn't start   01876000
                                          SIO program.                  01878000
                                                                        01880000
                       %12         %124   No  message  link  buffers,   01882000
                                          couldn't  write  message to   01884000
                                          operator console.             01886000
;                                                              <<00464>>01888000
BEGIN                                                                   01890000
$PAGE                                                                   01892000
<<---------------------------- EQUATES ---------------------------->>   01894000
                                                                        01896000
EQUATE                                                                  01898000
                                                                        01900000
<<----------------------- Printer Subtypes ------------------------>>   01902000
                                                                        01904000
CDC                  = 0,                                               01906000
DATAPRODUCTS         = 2,                                               01908000
HP2608               = 4,                                               01910000
KATAKANA             = 3,                          << 2617J >>          01912000
TALLY                = 1,                                      <<00770>>01914000
                                                                        01916000
<<----------------------- Function Codes -------------------------->>   01918000
                                                                        01920000
DEVICE'CLOSE         = 4,                                               01922000
DOWNLOAD'LEFT'MARGIN = %101,                                            01924000
DOWNLOAD'VFC         = %100,                                            01926000
FCLOSE               = 3,                                               01928000
FOPEN                = 2,                                               01930000
WRITE                = 1,                                               01932000
                                                                        01934000
<<---------------------- Completion Statuses ---------------------->>   01936000
                                                                        01938000
GOOD'STATUS          =    1,                                            01940000
INVALID'FUNCTION     =    4,                                            01942000
NO'MSG'BUFF'ERROR    = %124,                                            01944000
OPERATOR'ABORT       =  %33,                                            01946000
POWER'FAIL'ABORT     =  %63,                                            01948000
PWRFL'RESET'ERROR    = %213,                                            01950000
SIO'FAIL'ERROR       =  %44,                                            01952000
TIMEOUT'ERROR        =  %24,                                            01954000
TRANSFER'ERROR       =  %14,                                            01956000
VFC'RESET'ERROR      = %273,                                            01958000
                                                                        01960000
<<------------------------ DITP Parameters ------------------------>>   01962000
                                                                        01964000
DDF                  = %16,   <<DRIVER DEPENDENT FLAGS >>      <<01382>>01966000
DILTP                =   5,   << Interrupt Linkage Table pointer >>     01968000
DLAST                = %12,   << Odd byte of write request,             01970000
                                 # lines of DOWNLOAD VFC request,       01972000
                                 left margin param of LEFT MARGIN       01974000
                                   request or DEVICE CLOSE >>           01976000
DLDEV                =   3,   << Holds logical devno of printer >>      01978000
DLOGERROR            =   13,  <<ERROR LOG STATUS>>             <<01339>>01980000
DSERR                =   7,   << I/O error status if <> 0 >>            01982000
DSTAT                =   6,   << Request completion status >>           01984000
DTIME                = %10,   << Bit 0 set at end of 2-second timer >>  01986000
DTRLX                = %11,   << Timer Request List Index, see above >> 01988000
DVFC1                = %13,   << VFC'MOD bit (0:1), PWRFL'RE->><<00770>>01990000
                                << SET (1:1), BETWEEN'JOBS  >> <<00770>>01992000
                                << (2:1), left margin (4:4), >><<00770>>01994000
                              << carriage control for request (8:8) >>  01996000
DVFC2                = %14,   << LINES'LEFT'OVER (0:8), and >> <<00769>>01998000
                              << %102 (%202, 2608) in (8:8) >> <<00769>>02000000
                              << for pre- to postspace print>> <<00769>>02002000
LP'DIT'SIZE          = %17,   << Number of words in the DIT >> <<01382>>02004000
$PAGE                                                                   02006000
<<------------------------- IOQP Indices -------------------------->>   02008000
                                                                        02010000
QFUNC                =   6,   << Drvr request code (1-4, %100, %101) >> 02012000
QMISC                =   3,   << (7:3) = WAIT'FIELD (driver state),     02014000
                                 (12:1) = RETRY if non-2608 >> <<00769>>02016000
                              << configured as subtype 4    >> <<00769>>02018000
                              << (13:1) = MASTER'CLEAR for 2608's,      02020000
                                 (14:1) = PRESPACE request  >> <<00769>>02022000
                              << (15:1) = PRE'TO'POST write requests >> 02024000
QPAR1                = %10,   << Carriage control param for writes,     02026000
                                 6/8 LPI for Download VFC,              02028000
                                 left marg offset for Dwnld Lft Mrg >>  02030000
QPAR2                = %11,   << Prespace and no auto page eject        02032000
                                   flags for write request. >> <<00770>>02034000
QSTAT                = %12,   << Gets request completion status >>      02036000
QWBCT                =   7,   << Word or byte count for write and       02038000
                                   Download VFC requests >>             02040000
                                                                        02042000
<<------------------------- SIOP Indices -------------------------->>   02044000
                                                                        02046000
<< These equates are arranged so that a change to the channel program   02048000
   length  requires  changing  only references to the block where the   02050000
   change occurred, both here and in the driver.                   >>   02052000
                                                                        02054000
SIO'SETUP            =                        0,               <<00769>>02056000
SIO'VFC              = SIO'SETUP           +  8,               <<00773>>02058000
SIO'PRE'TO'POST      = SIO'VFC             + 14,                        02060000
SIO'BUFFER'FILL      = SIO'PRE'TO'POST     +  6,                        02062000
                                                               <<00769>>02064000
SIO'PRINT'AND'SPACE  = SIO'BUFFER'FILL     + 26,               <<00769>>02066000
SIO'MASTER'CLEAR     = SIO'PRINT'AND'SPACE +  6,                        02068000
SIO'LEFT'MARGIN      = SIO'MASTER'CLEAR    +  4,               <<00770>>02070000
LP'SIO'SIZE          = SIO'LEFT'MARGIN     +  6,                        02072000
LP'SIO'SIZED2        = LP'SIO'SIZE/2, << SIO SIZE / 2 >>       <<01300>>02074000
                                                                        02076000
<<-------------------------- I/O Orders --------------------------->>   02078000
                                                                        02080000
CONTROL              = %40000,                                          02082000
JUMP                 =      0,   << Unconditional jump >>               02084000
                                                               <<00769>>02086000
SETBANK              = %14000,   << Sets memory bank for next I/O >>    02088000
SIOEND               = %30000,   << without interrupt  >>               02090000
SIOENDI              = %34000,   << with    interrupt  >>               02092000
SIOWRT1              = %67777,   << Write one word     >>               02094000
                                                                        02096000
<<------------------------ Driver States -------------------------->>   02098000
                                                                        02100000
COMPLETION'WAIT      = 1,        << Waiting for completion interrupt >> 02102000
LET'PRINTER'FINISH   = 2,        << Waiting for 2-second timer >>       02104000
NEW'REQUEST          = 0,        << State at start of request>><<00464>>02106000
NOT'READY'WAIT       = 3,        << Waiting for oprat to fix printer >> 02108000
WAIT'FOR'TALLY       = 4,        << 3 sec for Tally to print >><<00769>>02110000
$PAGE                                                          <<00769>>02112000
<<------------------------ SIODM States --------------------------->>   02114000
                                                                        02116000
<< These are states returned by the driver to its monitor, SIODM,  to   02118000
   determine SIODM's next operation.                               >>   02120000
                                                                        02122000
INTERRUPT'WAIT       = %13,      << Waiting for completion interrupt >> 02124000
NOT'READY            =   7,      << Waiting for oprat to fix printer >> 02126000
REQUEST'DONE         =   5,      << All done, whether errors or not >>  02128000
                                                               <<00769>>02130000
<<--------------------- IOMESSAGE Parameters ---------------------->>   02132000
                                                                        02134000
<< These numbers represent  message  numbers  within  $SET1  (console   02136000
   operator messages) of the MPE message catalog, CATALOG.PUB.SYS. >>   02138000
                                                                        02140000
GOOD'DOWNLOAD'MSG    = 22,                                     <<00571>>02142000
NOT'READY'MESSAGE    = 11,                                              02144000
PAPER'OUT'MESSAGE    = 14,                                              02146000
PWRFL'RESET'MESSAGE  = 13,                                              02148000
SYS'CONSOLE          =  0,   << Directs message to system console >>    02150000
VFC'RESET'MESSAGE    = 15,                                              02152000
                                                                        02154000
<<------------------------ Miscellaneous -------------------------->>   02156000
                                                                        02158000
BIT'10               =   %40,                                           02160000
ISIOP                =     8,   << ILT pointer to      >>      <<01300>>02162000
                                <<   the SIO channel program >><<01300>>02164000
SYSDB                = %1000,   << Base of system DB area >>            02166000
SYSLPDT              =   %10,   << DB-relative base of logical-to-      02168000
                                     physical device table >>           02170000
                                                                        02172000
ENDEQ                =     0;                                           02174000
                                                               <<00464>>02176000
                                                               <<00464>>02178000
<<---------------- Miscellaneous useful declarations -------------->>   02180000
                                                               <<00464>>02182000
INTEGER X = X,      << Index register >>                       <<00464>>02184000
        S0 = S-0;   << Top of stack >>                         <<00464>>02186000
DOUBLE ARRAY LPDTD(@) = DB + SYSLPDT;   << Starting address of logical- 02188000
                                           to-physical device table >>  02190000
$PAGE                                                                   02192000
<<--------------------------- DEFINES ----------------------------->>   02194000
                                                                        02196000
DEFINE                                                                  02198000
                                                                        02200000
<<------------------------- DITP Fields --------------------------->>   02202000
                                                                        02204000
BETWEEN'JOBS      =(2:1)#,   << of DVFC1             >>        <<00464>>02206000
CCTL              =(8:8)#,   << of DVFC1             >>                 02208000
DEV'STAT'INTRUPT  =(8:3)#,   << of DSTAT             >>                 02210000
DEVICE'FLAG       =(5:1)#,   << of DSTAT             >>        <<00656>>02212000
DLDEVN            =(8:8)#,   << of DLDEV             >>                 02214000
LEFT'MARGIN       =(4:4)#,   << of DVFC1             >>                 02216000
LINES'LEFT'OVER   =(0:8)#,   << of DVFC2             >>        <<00769>>02218000
ONLINE'08         =(8:1)#,   << of DSTAT             >>                 02220000
PRE'TO'POST'CCTL  =(8:8)#,   << of DVFC2             >>        <<00769>>02222000
PWRFL'RESET       =(1:1)#,   << of DVFC1             >>                 02224000
TALLY'NOT'READY   =(3:1)#,   << of DVFC1             >>        <<00769>>02226000
VFC'MOD           =(0:1)#,   << of DVFC1             >>                 02228000
XFER'ERROR        =(14:1)#,  << of DSTAT             >>                 02230000
DITDDF            =DITPL(DDF)#, << DRIVER DEPENDENT FLAGS >>  <<WEOSH>> 02232000
NOT'EMPTY         =(10:1)#,  << of DITDDF             >>       <<01382>>02234000
PRESPACE'LAST     =(9:1)#,   << of DITDDF             >>       <<01382>>02236000
PRESPACE'NOTEMPTY =(9:2)#,   << of DITDDF             >>       <<01382>>02238000
TOP'OF'FORM       =(11:1)#,  << of DITDDF             >>       <<01382>>02240000
                                                                        02242000
<<------------------------- IOQP Fields --------------------------->>   02244000
                                                                        02246000
FUNCT             =(8:8)#,   << of QFUNC             >>                 02248000
MASTER'CLEAR      =(13:1)#,  << of QMISC             >>                 02250000
NO'AUTO'PAGE      =(14:1)#,  << of QPAR2             >>        <<00769>>02252000
PRESPACE          =(14:1)#,  << of QMISC             >>        <<00769>>02254000
PRE'TO'POST       =(15:1)#,  << of QMISC             >>                 02256000
RETRY             =(12:1)#,  << of QMISC             >>        <<00571>>02258000
SIO'FAILURE       =(10:1)#,  << of QFLAG (= IOQP(0)) >>                 02260000
STATS             =(8:8)#,   << of QSTAT             >>                 02262000
SYSTEM'POWER'FAIL =(11:1)#,  << of QFLAG             >>                 02264000
WAIT'FIELD        =(7:3)#,   << of QMISC             >>                 02266000
                                                                        02268000
<<------------------------ STATUS Fields -------------------------->>   02270000
                                                                        02272000
DEFAULT'VFC       =(12:1)#,                                             02274000
NOT'RDY           =(10:1)#,   << Not Ready bit for all but 2608 >>      02276000
ONLINE'NOT'RDY'08 =(8:2)#,    << 2608 On Line and Not Ready bits >>     02278000
PAPER'OUT         =(11:1)#,                                             02280000
POWER'FAIL'08     =(15:1)#,   << 2608 Power Fail bit >>                 02282000
READY             =(9:1)#,    << Ready bit for all but 2608 >>          02284000
READY'NOT'READY   =(9:2)#,    << Ready and Not Ready bits               02286000
                                   for all but 2608 >>                  02288000
READY'NTRDY'NOPAP =(9:3)#,    << Rdy, Not Rdy, Paper Out for CDC >>     02290000
                                                                        02292000
<<------------------------ Miscellaneous -------------------------->>   02294000
                                                                        02296000
ASMB              = ASSEMBLE#,                                          02298000
LOAD'MEMORY       = ASMB (LSEA)#,                                       02300000
SUBTYPE'FIELD     =(12:4)#,   << of LPDT entry for logical device >>    02302000
END'DEF           =0#;                                                  02304000
                                                                        02306000
$PAGE                                                                   02308000
<<------------- Driver linkage area and DIT definition ------------>>   02310000
                                                                        02312000
BYTE ARRAY DRIVER'CONFIG (0:7) = DB :=                                  02314000
                                                                        02316000
  LP'DIT'SIZE,  << The number of words in the DIT >>                    02318000
          1,    << .(10:1) = 0, driver non-resident >>                  02320000
                << .(13:1) = 0, can be 1 only if Type 3 driver >>       02322000
                << .(14:2) = 1, Type 1 driver, executes on any          02324000
                     stack, including the Interrupt Control Stack >>    02326000
          0,    << Not used >>                                          02328000
          0,    << Not applicable to Type 1 drivers >>                  02330000
          0,    << Unit extract instruction, >>                         02332000
          0,    <<   used only in multi-unit controllers >>             02334000
  LP'SIO'SIZED2,<< The number of words in the SIO PGM. / 2 >>  <<01300>>02336000
          0;    << Not used >>                                          02338000
                                                                        02340000
INTEGER ARRAY DIT (0:LP'DIT'SIZE-1) = DB :=                             02342000
                                                                        02344000
          0,    << .(0:1) = 0, device is not a terminal >>              02346000
                << .(1:1) = 0, device is not a disc >>                  02348000
                << .(4:1) = 0, no special interrupt handler >>          02350000
                << .(9:1) = 0, not a moving head disc >>                02352000
  0,0,0,0,0,    << These five words must be 0. >>                       02354000
  0,0,0,0,0,    << Remaining words may be set as desired. >>            02356000
  0,0,                                                         <<01339>>02358000
  0;    <<DLOGERROR>>                                          <<01339>>02360000
$PAGE                                                                   02362000
COMMENT                                                        <<00464>>02364000
  The following array is the unconfigured  SIO  channel  program  for   02366000
IOLPRT0.  It has been set up in task-oriented blocks:          <<00769>>02368000
                                                                        02370000
  1.    SETUP                  Clear interrupts, jump to first task.    02372000
                                                                        02374000
  2.    DOWNLOAD VFC           Used by subtype 4 (2608) only.           02376000
                                                                        02378000
  3.    PRINT AND SPACE        Dump buffer from previous request        02380000
                               during pre- to postspace request.        02382000
                                                                        02384000
  4.    FILL BUFFER            Transfer data to printer, no print.      02386000
                                                                        02388000
  5.    PRINT AND SPACE        Print data and advance paper.   <<00769>>02390000
                               Step 5 is repeated as required  <<00769>>02392000
                               to achieve slewing the request- <<00769>>02394000
                               ed number of lines 15 at a time <<00769>>02396000
                               (<= 15 the last time) for those <<00769>>02398000
                               printers limited to 15-line     <<00769>>02400000
                               slews.                          <<00769>>02402000
                                                                        02404000
  6.    MASTER CLEAR           2608  only.  Clears  the  Power <<00769>>02406000
                               Fail/Master  Reset printer sta- <<00770>>02408000
                               tus bit when detected. Not used <<00770>>02410000
                               otherwise.                      <<00770>>02412000
                                                               <<00770>>02414000
  7.    DOWNLOAD LEFT MARGIN   2608 only. Used during Function <<00769>>02416000
                               %101 or following a Master Clr. <<00770>>02418000
$PAGE                                                          <<00770>>02420000
  The above tasks are configured in the following order, depending on   02422000
the specific function:                                                  02424000
                                                                        02426000
WRITE, PRESPACE:  5 (as many times as required), 4.            <<00769>>02428000
                                                                        02430000
WRITE, POSTSPACE:  4, 5 (as many times as required).           <<00769>>02432000
                                                                        02434000
WRITE, PRE- TO POSTSPACE:  3, 4, 5 (as many times as req'd).   <<00769>>02436000
                                                               <<00769>>02438000
WRITE, PRE- OR POSTSPACE, FILL BUFFER ONLY:  4.                <<00769>>02440000
                                                                        02442000
FOPEN, FCLOSE, DEVICE CLOSE:  5, if not already at top of form.<<00769>>02444000
                                                                        02446000
MASTER CLEAR:  6, 7.                                           <<00769>>02448000
                                                                        02450000
DOWNLOAD VFC:  1.                                                       02452000
                                                                        02454000
DOWNLOAD LEFT MARGIN:  7.                                      <<00769>>02456000
                                                                        02458000
The channel program  originally  was  configured  to  progress <<00769>>02460000
without  interruption  from (3 to) 4 to 5 (pre- to) postspace, <<00769>>02462000
or from 5 to 4 (prespace).  However, I found it impossible  to <<00769>>02464000
properly recover from cycling off-line/on-line while printing. <<00769>>02466000
Each printer behaved a little differently,  depending  on  the <<00769>>02468000
printer  subtype and whether the request was prespace or post- <<00769>>02470000
space.  Therefore the present philosophy was adopted (really a <<00769>>02472000
return to that of the 1831 driver), whereby the driver is  in- <<00769>>02474000
terrupted  and checks status after each physical print command <<00769>>02476000
to the printer.  The driver reconfigures the  channel  program <<00769>>02478000
as required to properly continue the request.                  <<00769>>02480000
;                                                              <<00464>>02482000
$PAGE                                                                   02484000
INTEGER ARRAY SIOPROG (0:LP'SIO'SIZE-1) = DB :=                         02486000
                                                                        02488000
<<-------------------------- 1.  SETUP ---------------------------->>   02490000
                                                                        02492000
  CONTROL,  %40000,    << Clear all outstanding interrupts >>           02494000
  CONTROL,       2,    << Enable new ones >>                   <<00773>>02496000
  SETBANK,       0,    << Start all programs with memory bank 0 >>      02498000
  JUMP   ,       0,    << Jump to start of current program >>           02500000
                                                                        02502000
<<------------ 2.  DOWNLOAD VFC (HP2608 ONLY) --------------------->>   02504000
                                                                        02506000
  CONTROL,    %203,    << VFC Set/Reset command + U.I. timeout >>       02508000
  SIOWRT1,       0,    << 6/8 lines per inch, number of lines >>        02510000
  JUMP   ,       0,    << Changed to JUMP *+1 if line count <> 0,       02512000
                          changed to JUMP "SIOENDI" if count = 0 >>     02514000
  CONTROL,       7,    << Pass VFC contents with data command >>        02516000
  SETBANK,       0,    << Set to bank containing user's buffer >>       02518000
  SIOWRT1,       0,    << Set to line count and buffer address >>       02520000
  SIOENDI, %177777,                                                     02522000
                                                                        02524000
<<-- 3. PRE- TO POSTSPACE BUFFER CLEAR, ONE SPACE W/ AUTO EJECT -->>    02526000
                                                                        02528000
  CONTROL,     %43,    << Print command, changed to %1003 for 2608 >>   02530000
  SIOWRT1,       0,    << Skip to chan. 3, %202, 2608; %102 others >>   02532000
  SIOENDI, %177777,    << Changed to SIOEND, %177777 for CDC >><<00769>>02534000
                                                                        02536000
<<------------- 4.  FILL BUFFER (PRE- OR POSTSPACE) -------------->>    02538000
                                                                        02540000
  SETBANK,       0,    << Set to bank containing user's buffer >>       02542000
  JUMP   ,       0,    << Skip to "CONTROL, 7" if no imbedded CCTL >>   02544000
  CONTROL,       3,    << Write 1st (odd) byte if carriage control >>   02546000
  SIOWRT1,       0,    << There goes the first byte >>                  02548000
  JUMP   ,       0,    << Skip main buffer write if not required >>     02550000
  CONTROL,       7,    << Unpack main buffer except odd last byte >>    02552000
  SIOWRT1,       0,    << Send it to printer >>                         02554000
  JUMP   ,       0,    << Skip to last "SETBANK" if no odd byte >>      02556000
  SETBANK,       0,    << Last (odd) byte, or print command             02558000
                            is always in DIT (bank 0) >>                02560000
  CONTROL,       3,    << Write last (odd) byte >>                      02562000
  SIOWRT1,       0,                                                     02564000
  SETBANK,       0,    << Make sure we're in bank 0 when we leave >>    02566000
  SIOENDI, %177777,    << End if prespace or buffer fill (%320),        02568000
                            JUMP *+1 if postspace >>                    02570000
                                                                        02572000
<<---- 5.  PRINT BUFFER AND SLEW OR SKIP TO CHANNEL ----->>    <<00769>>02574000
                                                                        02576000
  CONTROL,     %43,                                                     02578000
  SIOWRT1,       0,    << Carriage control byte is in DIT >>            02580000
  SIOENDI, %177777,    << Changed to SIOEND if CDC >>          <<00769>>02582000
$PAGE                                                          <<00769>>02584000
<<------- 6.  MASTER CLEAR (SUBTYPE 4, HP2608 ONLY) --------- >>        02586000
                                                                        02588000
  CONTROL,    %503,    << 2608 Master Clear command >>                  02590000
  SIOWRT1,       0,    << Dummy to enable Master Clear command >>       02592000
                                                                        02594000
<<----- 7.  DOWNLOAD LEFT MARGIN (SUBTYPE 4, HP2608 ONLY) ----->>       02596000
                                                                        02598000
  CONTROL,    %703,    << 2608 Buffer Clear/Left Margin command >>      02600000
  SIOWRT1,       0,    << Left margin offset >>                <<00770>>02602000
  SIOENDI, %177777;    << End of SIO channel program >>                 02604000
$PAGE                                                                   02606000
<<------------------- External Procedure Heads -------------------->>   02608000
                                                                        02610000
<< The following procedures are called by or linked to  IOLPRT0.  See   02612000
   the  HP2608  Support on HP3000 Series II/III ERS for a description   02614000
   of their operation.                                             >>   02616000
                                                                        02618000
PROCEDURE ABORTTIMEREQ (TRLX);                                          02620000
  VALUE TRLX;                                                           02622000
  INTEGER TRLX;   << Timer Request List Index, only used here >>        02624000
  OPTION EXTERNAL;                                                      02626000
                                                                        02628000
PROCEDURE DOCIO(ORDER,DITP);                                            02630000
  VALUE ORDER;   INTEGER ORDER;                                         02632000
  ARRAY DITP;    OPTION EXTERNAL;                                       02634000
                                                                        02636000
PROCEDURE  GIP;   OPTION EXTERNAL;                                      02638000
                                                                        02640000
PROCEDURE HELP;   OPTION EXTERNAL;                                      02642000
                                                                        02644000
PROCEDURE IOFAILURE(DRTN,DITP);                                         02646000
  VALUE DRTN;  INTEGER DRTN;                                            02648000
  ARRAY DITP;  OPTION EXTERNAL;                                         02650000
                                                                        02652000
LOGICAL PROCEDURE IOMESSAGE(SETNO,MSGNO,MASK,P1,P2,P3,P4,P5,            02654000
   DEST,REPLY,OFFSET,DITP,IOTYPE);                                      02656000
VALUE SETNO,MSGNO,MASK,P1,P2,P3,P4,P5,DEST,REPLY,OFFSET,DITP,           02658000
   IOTYPE;                                                              02660000
INTEGER SETNO,MSGNO,MASK,P1,P2,P3,P4,P5,DEST,REPLY,OFFSET,              02662000
   IOTYPE;                                                              02664000
INTEGER POINTER DITP;                                                   02666000
OPTION VARIABLE,EXTERNAL;                                               02668000
                                                                        02670000
PROCEDURE MASTERCLEAR(DITP);                                            02672000
  ARRAY DITP;  OPTION EXTERNAL;                                         02674000
                                                                        02676000
PROCEDURE SIODM(DITP,FLAGS);                                            02678000
  VALUE DITP, FLAGS;   LOGICAL FLAGS;                                   02680000
  POINTER DITP;    OPTION  EXTERNAL;                                    02682000
                                                                        02684000
PROCEDURE STARTIO(DITP,SIOP,QFLAG);                                     02686000
  VALUE  DITP, SIOP, QFLAG;     LOGICAL QFLAG;                          02688000
  POINTER DITP, SIOP;    OPTION EXTERNAL;                               02690000
                                                                        02692000
INTEGER PROCEDURE TIMEREQ (CODE, DIT'ADDRESS, TIME);                    02694000
  VALUE CODE, DIT'ADDRESS, TIME;                                        02696000
  INTEGER CODE;   << %20 to %37, sets bit (CODE-%20) in DIT(8) >>       02698000
  INTEGER DIT'ADDRESS;                                                  02700000
  DOUBLE TIME;  << Desired interval in milliseconds >>                  02702000
  OPTION EXTERNAL;                                                      02704000
$PAGE                                                                   02706000
INTEGER PROCEDURE CHECK'STATUS (DITP, IOQP, DRTNUMB, MESSAGE'FLAG);     02708000
  VALUE DRTNUMB, MESSAGE'FLAG;                                          02710000
  INTEGER ARRAY DITP, IOQP;   << See LPDRVR procedure head... >>        02712000
  INTEGER DRTNUMB;            << ... for descriptions of these >>       02714000
LOGICAL MESSAGE'FLAG;        << Call Not Ready IOMESSAGE only if set >> 02716000
                                                                        02718000
BEGIN                                                                   02720000
COMMENT                                                        <<00770>>02722000
  CHECK'STATUS tests for a number  of  conditions  that  prevent  the   02724000
execution or completion of the current request. Some conditions, such   02726000
as NOT READY, only require suspension until the operator can fix  the   02728000
condition,  then  execution can continue.  Others, such as POWER FAIL   02730000
on a 2608, are unrecoverable in the sense that any remaining part  of   02732000
the request is lost.                                                    02734000
  CHECK'STATUS  builds  a  subtype-independent  word,  STATUS,  shown   02736000
below, which can then be checked by a general routine.  This makes it   02738000
possible to easily add sections to handle new subtypes.                 02740000
  CHECK'STATUS is called before starting or restarting  each  channel   02742000
program  to  make  sure that the printer is operable.  If there is no   02744000
problem, CHECK'STATUS has a value of 0 on return.  If the request can   02746000
be  suspended  for operator intervention, then continue, CHECK'STATUS   02748000
is given a value of %177777.  If an unrecoverable error  exists,  the   02750000
error status value (>0) is returned in  CHECK'STATUS.  Exception:  If   02752000
a  2608  Power  Fail/Reset  is  detected,  CHECK'STATUS just sets the   02754000
PWRFL'RESET bit in DVFC1.  External code is responsible  for  dealing   02756000
with this bit.                                                          02758000
  CHECK'STATUS should only be called if no  SIO  channel  program  is   02760000
active.  Otherwise  the  I/O performed here may conflict with channel   02762000
program I/O orders with unpredictable results.                          02764000
  A table of currently-supported subtypes and their status conditions   02766000
is  shown  below.  An empty entry means that particular status is not   02768000
supported on that subtype.                                              02770000
                                      NOT   PAPER   VFC    PWRFL/       02772000
  SUBTYPE  MODEL              READY  READY   OUT   RESET   RESET        02774000
  --------------------------------------------------------------        02776000
                                                                        02778000
     0     2610, 2614          INT    INT    DEV                        02780000
                                9     10     11                         02782000
                                                                        02784000
     1     2607                INT    INT                               02786000
                                9     10                                02788000
                                                                        02790000
     2     2613, 2617, 2618,   INT    INT                      <<00770>>02792000
           2619                 9     10                       <<00770>>02794000
                                                                        02796000
     3     2617J               INT    INT                               02798000
                                9     10                                02800000
                                                                        02802000
     4     2608                INT    INT           DEV     DEV         02804000
                                8      9            12      15          02806000
  NOTES:                                                                02808000
  1.  INT = Interrupt Status Word, DEV =  Device  Status  Word.         02810000
  2.  For subtypes 0-3, INT 9, 10 are always each other's complement.   02812000
For subtype 4, INT 8 is ON LINE status.  The 2608 may be off-line due   02814000
to the operator, but this does not cause it to go NOT READY (INT  9).   02816000
NOT READY occurs because of a machine problem (paper out, ribbon jam,   02818000
etc.), and of course removes ON LINE status as well.                    02820000
$PAGE                                                                   02822000
  The above bits are massaged into the following STATUS word:           02824000
                                                                        02826000
      ...  8      9     10     11     12     13     14     15   BIT     02828000
                                                                        02830000
                        NOT   PAPER   VFC                 PWRFL/        02832000
                READY  READY   OUT   RESET                RESET         02834000
;                                                              <<00770>>02836000
INTEGER STATUS,            << General status word >>                    02838000
        SUBTYPE,          << Printer subtype, which we have to fetch >> 02840000
        TEMP,                                                           02842000
        WAIT'CODE;                                                      02844000
                                                                        02846000
LOGICAL STATUSL = STATUS;                                               02848000
                                                                        02850000
LOGICAL ARRAY DITPL(*) = DITP;                                          02852000
                                                                        02854000
                                                                        02856000
STATUS := 0;   << Initialize internal status word >>                    02858000
WAIT'CODE := IOQP(QMISC).WAIT'FIELD;                           <<00769>>02860000
                                                                        02862000
<< Pick up printer subtype from the logical-to-physical device table >> 02864000
                                                                        02866000
TOS := LPDTD (DITP (DLDEV).DLDEVN);                                     02868000
SUBTYPE := TOS.SUBTYPE'FIELD;                                           02870000
                                                                        02872000
<< Get the interrupt and device status bytes >>                         02874000
                                                                        02876000
TOS := DRTNUMB;                                                         02878000
DOCIO (0, DITP);   << Select interrupt status byte >>                   02880000
ASMB (TIO 0);                                                           02882000
IF < THEN IOFAILURE (*, DITP);   << U.I. card does not respond >>       02884000
DITP(DSTAT) := TOS;                                                     02886000
DOCIO (%10, DITP);   << Select device status byte >>                    02888000
ASMB (TIO 0);                                                           02890000
IF < THEN IOFAILURE (*, DITP);   << U.I. card does not respond >>       02892000
TEMP := TOS;   << Save for selective picking >>                         02894000
ASMB (DEL);   << Delete the DRT number >>                               02896000
                                                                        02898000
IF (TALLY <= SUBTYPE <= KATAKANA) THEN                         <<00770>>02900000
     BEGIN   << INT 10 (Not Ready) is the complement of DEV 10 >>       02902000
     STATUS.READY'NOT'READY := TEMP.READY'NOT'READY;                    02904000
     STATUS := STATUSL XOR BIT'10;                                      02906000
     END   << of complementing bit 10 >>                                02908000
                                                                        02910000
ELSE IF SUBTYPE = CDC THEN                                              02912000
     BEGIN   << INT 10 (Not Ready) is the complement of DEV 10 >>       02914000
     STATUS.READY'NTRDY'NOPAP := TEMP.READY'NTRDY'NOPAP;                02916000
     STATUS := STATUSL XOR BIT'10;                                      02918000
     END   << of complementing bit 10 >>                                02920000
                                                                        02922000
ELSE IF SUBTYPE = HP2608 THEN                                           02924000
     BEGIN  << Must get device status for PWRFL/RESET and VFC INIT >>   02926000
     STATUS.READY'NOT'READY := TEMP.ONLINE'NOT'RDY'08;                  02928000
     STATUS.DEFAULT'VFC := TEMP.DEFAULT'VFC;                            02930000
     STATUS.POWER'FAIL'08 := TEMP.POWER'FAIL'08;                        02932000
     END   << of SUBTYPE = HP2608 >>                                    02934000
                                                                        02936000
ELSE;   << New subtypes go here >>                                      02938000
                                                                        02940000
IF STATUSL.POWER'FAIL'08 THEN DITP(DVFC1).PWRFL'RESET := 1;             02942000
                                                                        02944000
IF STATUSL.DEFAULT'VFC THEN                                             02946000
     BEGIN   << 2608 is using an internal VFC, may be O.K. >>           02948000
     IF DITPL(DVFC1).VFC'MOD THEN   << custom VFC installed >> <<00770>>02950000
          BEGIN   << VFC reset illegally, notify operator >>            02952000
          IF NOT IOMESSAGE (1, VFC'RESET'MESSAGE, %10000,               02954000
            DITP(DLDEV).DLDEVN,,,,, SYS'CONSOLE) THEN                   02956000
               BEGIN   << No system message buffer >>                   02958000
               CHECK'STATUS := NO'MSG'BUFF'ERROR;   << %124 >>          02960000
               RETURN;                                                  02962000
               END;   << of no message buffer >>                        02964000
          DITP(DVFC1).VFC'MOD := 0;   << Assures only one message >>    02966000
          CHECK'STATUS := VFC'RESET'ERROR;   << %273 >>                 02968000
          RETURN;                                                       02970000
          END;   << of illegal VFC reset >>                             02972000
     END;   << of default VFC active >>                                 02974000
                                                                        02976000
IF STATUSL.NOT'RDY                                             <<00656>>02978000
  OR NOT STATUSL.READY   << for 2608 >>                        <<00656>>02980000
  OR DITPL(DSTAT).DEVICE'FLAG THEN                             <<00769>>02982000
     BEGIN                                                              02984000
                                                                        02986000
<< The IOMESSAGE test must be the last one in the following statemnt >> 02988000
                                                                        02990000
     IF WAIT'CODE = NOT'READY'WAIT   << then message is already sent >> 02992000
       OR NOT MESSAGE'FLAG           << Don't want message sent >>      02994000
       OR IOMESSAGE (1, IF STATUSL.PAPER'OUT THEN PAPER'OUT'MESSAGE     02996000
            ELSE NOT'READY'MESSAGE, %10000, DITP(DLDEV).DLDEVN,,,,,     02998000
            SYS'CONSOLE)                                                03000000
       THEN CHECK'STATUS := %177777   << Set recoverable retn status >> 03002000
       ELSE CHECK'STATUS := NO'MSG'BUFF'ERROR;   << %124 >>             03004000
     RETURN;                                                            03006000
     END;  << of line printer not ready or off line >>                  03008000
                                                                        03010000
CHECK'STATUS := 0;   << No errors >>                                    03012000
END;   << of CHECK'STATUS >>                                            03014000
$PAGE                                                                   03016000
<<---------------- Driver Initialization Procedure ---------------->>   03018000
                                                                        03020000
PROCEDURE LPINIT (DITP);                                                03022000
  INTEGER ARRAY DITP;                                                   03024000
                                                                        03026000
BEGIN                                                                   03028000
<<                                                                      03030000
  LPINIT configures those areas of the SIO program which could not be   03032000
initialized during loading (pointers to addresses in the DIT,  etc.),   03034000
or  which  are  subtype-dependent  and therefore do not change during   03036000
execution.  Since we are only given the address of the DIT,  we  must   03038000
hop  and skip through that to the Interrupt Linkage Table to find the   03040000
starting address of the SIOP array.                                     03042000
>>                                                                      03044000
  INTEGER DITBASE;        << Starting address of the DIT >>             03046000
  INTEGER SUBTYPE;        << Printer subtype, which we have to fetch >> 03048000
  INTEGER POINTER ILTP,   << Pointer to the Interrupt Linkage Table >>  03050000
                  SIOP;   << Pointer to the SIO Channel Program >>      03052000
                                                                        03054000
DITBASE := @DITP + SYSDB;                                               03056000
@ILTP   := DITP(DILTP);                                                 03058000
@SIOP   := ILTP(ISIOP);                                                 03060000
                                                                        03062000
<< Pick up printer subtype from the logical-to-physical device table >> 03064000
                                                                        03066000
TOS := LPDTD (DITP (DLDEV).DLDEVN);                                     03068000
SUBTYPE := TOS.SUBTYPE'FIELD;                                           03070000
                                                                        03072000
<< Now we can configure -- finally! >>                                  03074000
                                                                        03076000
SIOP(SIO'PRE'TO'POST+3) := DITBASE + DVFC2;   << Skip to channel 3 >>   03078000
SIOP(SIO'BUFFER'FILL+21) := DITBASE + DLAST;  << Last (odd) byte in     03080000
                                                 buffer fill >>         03082000
SIOP(SIO'PRINT'AND'SPACE+3) := DITBASE + DVFC1;  << Pointer to CCTL >>  03084000
DITP(DVFC1).BETWEEN'JOBS := 1;   << Suppress PF/RST messages >><<00464>>03086000
DITP(DVFC2).PRE'TO'POST'CCTL := %102;  << All except 2608 >>   <<00769>>03088000
                                                                        03090000
<< Change all print commands from %43 to %1003 if we have a 2608 >>     03092000
                                                                        03094000
IF SUBTYPE = HP2608 THEN                                                03096000
     BEGIN                                                              03098000
     SIOP(SIO'VFC+3) := DITBASE + DLAST;   << # lines, 6/8 LPI >>       03100000
     SIOP(SIO'PRE'TO'POST+1) := %1003;                                  03102000
     SIOP (SIO'PRINT'AND'SPACE+1) := %1003;                    <<00769>>03104000
                                                               <<00769>>03106000
     SIOP(SIO'LEFT'MARGIN+3) := DITBASE + DLAST;  << Lft margn offst >> 03108000
     DITP(DVFC2).PRE'TO'POST'CCTL := %202;                     <<00769>>03110000
     END;   << of subtype = 2608 >>                                     03112000
                                                                        03114000
IF SUBTYPE = CDC THEN                                          <<00769>>03116000
     BEGIN   << CDC channel programs end without interrupt. >> <<00769>>03118000
     SIOP (SIO'PRE'TO'POST+4) := SIOEND;                       <<00769>>03120000
     SIOP (SIO'PRINT'AND'SPACE+4) := SIOEND;                   <<00769>>03122000
     END;                                                      <<00769>>03124000
                                                                        03126000
END;   << of LPINIT >>                                                  03128000
$PAGE                                                                   03130000
<<---------- Main line printer driver procedure, LPDRVR ----------->>   03132000
                                                                        03134000
INTEGER PROCEDURE LPDRVR (IOQP, DITP, BANK, BUFADDR, SIOP,              03136000
  DRTNUMB);                                                             03138000
  VALUE BANK, BUFADDR, DRTNUMB;                                         03140000
  INTEGER BANK,        << Absolute memory bank number of buffer >>      03142000
          BUFADDR,     << Absolute address of buffer in bank    >>      03144000
          DRTNUMB;     << DRT entry number of U.I. card         >>      03146000
  INTEGER ARRAY DITP,  << SYSDB-rel pointer to device's DIT(0)  >>      03148000
                IOQP,  << SYSDB-rel ptr to current IOQ(0) entry >>      03150000
                SIOP;  << SYSDB-relative pointer to SIO program >>      03152000
  OPTION PRIVILEGED,   << LPDRVR executes in privileged mode    >>      03154000
         UNCALLABLE;   << Calling procedure must be in privmode >>      03156000
                                                                        03158000
<< The possible results returned in LPDRVR are:                         03160000
       5 -- Request completed.                                          03162000
       7 -- Printer not ready, wait for on-line interrupt.              03164000
     %13 -- Wait for completion or other interrupt.                     03166000
>>                                                                      03168000
BEGIN                                                                   03170000
INTEGER CARRIAGE'CONTROL,   << Holds byte ultimately sent to printer >> 03172000
        CCTL'PARAM,         << Holds byte sent as part of request >>    03174000
        FUNCTION,           << IOQP request code, 1-4, %100, %101 >>    03176000
        IMBEDDED,           << =1 if CCTL in buffer, =0 if in QPAR1 >>  03178000
        LINK,               << Used to connect relevant parts of        03180000
                                 SIO'BUFFER'FILL block >>               03182000
        NEG'WORD'COUNT,                                                 03184000
        ODD'BYTE,           << = -1 if no odd byte >>                   03186000
        SIOPA,              << Absolute address of SIOP >>              03188000
        SUBTYPE,            << Printer subtype >>                       03190000
        TEMP,                                                           03192000
        WAIT'CODE;          << Internal driver state:                   03194000
                                 0 -- New request                       03196000
                                 1 -- Waiting for completion            03198000
                                 2 -- Three-second delay       <<00769>>03200000
                              << 3 -- Waiting for on-line interrupt     03202000
                                 4 -- 2607 off-line, 2 next    <<00769>>03204000
                                                                        03206000
LOGICAL IMBEDDEDL       = IMBEDDED,                                     03208000
        NEG'WORD'COUNTL = NEG'WORD'COUNT;                               03210000
                                                                        03212000
LOGICAL ARRAY DITPL(*) = DITP,                                          03214000
              IOQPL(*) = IOQP;                                          03216000
                                                                        03218000
<< Initialize local variables >>                                        03220000
                                                                        03222000
START'OVER:                                                    <<00464>>03224000
FUNCTION := IOQP(QFUNC).FUNCT;                                          03226000
IMBEDDED := IF IOQP(QPAR1) = 1                                          03228000
  THEN 1                                                                03230000
  ELSE 0;                                                               03232000
ODD'BYTE := %177777;   << Assume no odd byte >>                         03234000
LINK := SIO'BUFFER'FILL + 3;   << 1st jump in buffer fill block >>      03236000
SIOPA := @SIOP + SYSDB;                                                 03238000
TOS := LPDTD (DITP (DLDEV).DLDEVN);                                     03240000
SUBTYPE := TOS.SUBTYPE'FIELD;                                           03242000
WAIT'CODE := IOQP(QMISC).WAIT'FIELD;                                    03244000
                                                                        03246000
<< Now we're ready to go-o-o-o-o... >>                                  03248000
$PAGE                                                                   03250000
IF WAIT'CODE = LET'PRINTER'FINISH THEN                                  03252000
     BEGIN                                                              03254000
<<                                                                      03256000
  We're in a three-second wait to give the printer a chance to finish   03258000
whatever  it was doing.  Ignore any interrupt except the timer during   03260000
this period.                                                            03262000
>>                                                                      03264000
     IF DITP(DTIME) >= 0 THEN                                           03266000
          BEGIN   << Not timed out yet, bit 0 sets when timer pops >>   03268000
          LPDRVR := INTERRUPT'WAIT;                                     03270000
          RETURN;   << Ignore this interrupt >>                         03272000
          END;   << of extraneous interrupt >>                          03274000
     ABORTTIMEREQ (DITP(DTRLX));   << Timer popped, clear entry >>      03276000
     TOS := DRTNUMB;   << Get a fresh copy of status >>                 03278000
     DOCIO (0, DITP);  << Make sure it's interrupt status byte >>       03280000
     ASMB (TIO 0);                                                      03282000
     IF < THEN IOFAILURE (*, DITP);   << Non-responding module >>       03284000
     DITP(DSTAT) := TOS;                                                03286000
     END;   << of three-second timeout >>                               03288000
                                                                        03290000
IF IOQP < 0 THEN                                                        03292000
     BEGIN                                                     <<00656>>03294000
COMMENT                                                        <<00770>>03296000
Abort the I/O request.  The abort occurs asynchronously to the <<00770>>03298000
I/O request, and does not abort any printing in  progress.  We <<00770>>03300000
must wait for this printing to finish, or the next request may <<00770>>03302000
be lost due to starting it while the  printer  is  still  busy <<00770>>03304000
with  the previous one.  To avoid this problem give any opera- <<00770>>03306000
tion 3 seconds to finish, then abort.  This gives  normal  op- <<00769>>03308000
erations a chance, but still catches infinitely long hangups.  <<00770>>03310000
;                                                              <<00770>>03312000
     IF WAIT'CODE = COMPLETION'WAIT THEN                       <<00656>>03314000
          BEGIN   << Give printer three seconds to finish >>   <<00769>>03316000
START'DELAY:                                                   <<00769>>03318000
          DITP(DTRLX) := TIMEREQ (%20, @DITP, 3000D);          <<00769>>03320000
          IOQP(QMISC).WAIT'FIELD := LET'PRINTER'FINISH;        <<00656>>03322000
          LPDRVR := INTERRUPT'WAIT;                            <<00656>>03324000
          RETURN;                                              <<00656>>03326000
          END;   << of lighting off three second wait >>       <<00769>>03328000
     TOS := IF IOQPL.SYSTEM'POWER'FAIL                                  03330000
       THEN POWER'FAIL'ABORT                                            03332000
       ELSE OPERATOR'ABORT;                                             03334000
     GO CLEAR'CARD;                                                     03336000
     END;   << of abort >>                                              03338000
                                                                        03340000
IF IOQPL.SIO'FAILURE THEN                                               03342000
     BEGIN   << Delayed STARTIO failure on queued channel request >>    03344000
     TOS := SIO'FAIL'ERROR;                                             03346000
     GO TO IO'ERROR;                                                    03348000
     HELP;                 << Link to debug routine >>                  03350000
     END;  << of SIO failure >>                                         03352000
                                                                        03354000
<<--------- Examine WAIT'CODE to decide what to do next --------->>     03356000
                                                                        03358000
CASE * WAIT'CODE OF                                                     03360000
  BEGIN                                                                 03362000
$PAGE                                                                   03364000
<<------------------ WAIT'CODE = 0, new request ------------------>>    03366000
                                                                        03368000
     BEGIN                                                              03370000
     IF FUNCTION = WRITE THEN   << Code = 1 >>                          03372000
          BEGIN                                                         03374000
                                                                        03376000
<< Check first for pre- to postspace operation >>                       03378000
                                                                        03380000
          IF DITDDF.PRESPACE'NOTEMPTY = 3 <<Prespace last,bf>> <<01382>>03382000
            AND NOT IOQPL(QPAR2)         << This one's a postspace  >>  03384000
            THEN                                                        03386000
               BEGIN   << A hit, dump buffer w/ skip to channel 3 >>    03388000
               IOQP(QMISC).PRE'TO'POST := 1;                            03390000
                                                               <<00769>>03392000
<< Set jump to first channel program order >>                  <<00769>>03394000
                                                               <<00769>>03396000
               SIOP(SIO'SETUP+7) := SIOPA + SIO'PRE'TO'POST;   <<00773>>03398000
               SIOP (SIO'PRE'TO'POST+5) := %177777;            <<00769>>03400000
               END;  << of pre- to postspace configuration >>           03402000
                                                                        03404000
<< Limit the request word or byte count to 128 words (256 bytes) >>     03406000
                                                                        03408000
          IF IOQP(QWBCT) >  128 THEN IOQP(QWBCT) :=  128;               03410000
          IF IOQP(QWBCT) < -256 THEN IOQP(QWBCT) := -256;               03412000
          IF IMBEDDEDL                                                  03414000
            THEN  << carriage control param is 1st char in buffer >>    03416000
               BEGIN                                                    03418000
               IF IOQP(QWBCT) = 0 THEN                                  03420000
                    BEGIN  << QWBCT may not be 0 if CCTL is imbedded >> 03422000
                    TOS := INVALID'FUNCTION;                            03424000
                    GO TO IO'DONE;                                      03426000
                    END;   << of illegal count >>                       03428000
               TOS := BANK;                                             03430000
               TOS := BUFADDR;   << Get carriage control parameter >>   03432000
               LOAD'MEMORY;      <<   from wherever it is >>            03434000
               CCTL'PARAM := TOS & LSR(8);   << Right-justify & save >> 03436000
               END   << of imbedded carriage control parameter >>       03438000
            ELSE CCTL'PARAM := IOQP(QPAR1);   << QPAR1 is c.c. param >> 03440000
$PAGE                                                                   03442000
<<                                                                      03444000
  Parse the carriage control parameter.  Assume the  default  (single   03446000
space  with or without auto page eject), then modify as required.  If   03448000
a channel skip is required, assume a  subtype  <>  2608  until  we've   03450000
finished, then make the change.                                         03452000
>>                                                                      03454000
          CARRIAGE'CONTROL := IF IOQPL(QPAR2).NO'AUTO'PAGE              03456000
            THEN    1    << single space, no auto page eject >>         03458000
            ELSE %102;   << Skip to channel 3 (sngl spc, auto ejct) >>  03460000
                                                               <<00769>>03462000
                                                                        03464000
          IF CCTL'PARAM = "+" THEN                                      03466000
            CARRIAGE'CONTROL := 0   << Suppress spacing >>              03468000
                                                                        03470000
          ELSE IF CCTL'PARAM = "0" THEN   << Double space   >> <<01061>>03472000
            IF IOQPL(QPAR2).NO'AUTO'PAGE                       <<01061>>03474000
              THEN CARRIAGE'CONTROL := 2  << No auto eject >>  <<01061>>03476000
              ELSE DITP(DVFC2).LINES'LEFT'OVER := 1 << Auto >> <<01061>>03478000
                                                               <<01061>>03480000
          ELSE IF CCTL'PARAM = "-" THEN   << Triple space   >> <<01061>>03482000
            IF IOQPL(QPAR2).NO'AUTO'PAGE                       <<01061>>03484000
              THEN CARRIAGE'CONTROL := 3  << No auto eject >>  <<01061>>03486000
              ELSE DITP(DVFC2).LINES'LEFT'OVER := 2 << Auto >> <<01061>>03488000
                                                                        03490000
          ELSE IF CCTL'PARAM = "1" THEN                                 03492000
               BEGIN   << Skip to top of form >>                        03494000
               IF IOQP(QWBCT) = -IMBEDDED  << Nothing to do this time>> 03496000
                 AND DITDDF.TOP'OF'FORM  << Already at TOF >>  <<01382>>03498000
                 THEN GO TO NORMAL'COMPLETION;  <<Nothing to do, exit>> 03500000
               CARRIAGE'CONTROL := %100;  << Set skip to top-of-form >> 03502000
               END  << of CCTL'PARAM = 1 >>                             03504000
                                                                        03506000
          ELSE IF (%200 <= CCTL'PARAM <= %277) THEN  << Slew N lines >> 03508000
               BEGIN                                                    03510000
               CARRIAGE'CONTROL := CCTL'PARAM - %200;                   03512000
               IF (TALLY <= SUBTYPE <= KATAKANA)               <<00769>>03514000
                 AND CARRIAGE'CONTROL > 15 THEN                <<00769>>03516000
                    BEGIN   << Set up slews of <= 15 lines. >> <<00769>>03518000
                    DITP(DVFC2).LINES'LEFT'OVER :=             <<00769>>03520000
                      CARRIAGE'CONTROL - 15;                   <<00769>>03522000
                    CARRIAGE'CONTROL := 15;  << Set into... >> <<00769>>03524000
                    END;                     << ...DIT below>> <<00769>>03526000
               END  << of slewing N lines >>                            03528000
$PAGE                                                                   03530000
          ELSE IF %300 <= CCTL'PARAM <= %317 THEN                       03532000
<<                                                                      03534000
  Skip to a VFC channel.  The number  of  VFC  channels  varies  with   03536000
printer  subtype.  Subtypes  0  (CDC), 1 (2607) and 3 (2617J) have 8;   03538000
subtype 2 (2613, 2617, 2618 and 2619) has 12 and subtype 4 (2608) has   03540000
16.  If the request specifies an out-of-range channel for the current   03542000
subtype, ignore it (that is, use the carriage-control default).         03544000
>>                                                                      03546000
            IF CCTL'PARAM <= %307       << Works on any printer >>      03548000
              OR SUBTYPE = HP2608       << Any value O.K. >>            03550000
              OR CCTL'PARAM <= %313 AND SUBTYPE = DATAPRODUCTS          03552000
              THEN CARRIAGE'CONTROL := CCTL'PARAM - %200                03554000
              ELSE  << Null else >>                                     03556000
                                                                        03558000
          ELSE IF CCTL'PARAM = %320 THEN                                03560000
<<                                                                      03562000
  This parameter specifies that the data in the  current  request  be   03564000
concatenated  to  any  existing buffer, whether or not the buffer was   03566000
created as part of a pre- or postspace request, and  whether  or  not   03568000
the current request is pre- or postspace. As such, it is inconsistent   03570000
with a true emulation of a space-and-print (prespace) printer,  since   03572000
such  a  printer  would  have already printed a previous buffer.  The   03574000
current request could overlay the previous line,  but  could  not  be   03576000
concatenated to it.  On the postspace side, a %320 should concatenate   03578000
until a non-%320 is received; then the buffer should  be  dumped  and   03580000
the  non-%320  request processed normally.  This is not done; instead   03582000
the non-%320 is concatenated to any existing  buffer  and  the  whole   03584000
thing  is  then  printed.  Since these inconsistencies existed in the   03586000
previous  version,  they  have  been  preserved   here   for   upward   03588000
compatibility.                                                          03590000
>>                                                                      03592000
               BEGIN  << See if we have anything to do >>               03594000
               IF IOQP(QWBCT) = -IMBEDDED << Nothing this time >>       03596000
                 AND (NOT DITDDF.PRESPACE <<Nothing leftOVER>> <<01382>>03598000
                 OR IOQPL(QPAR2))         << Request is prespace >>     03600000
                 THEN GO TO NORMAL'COMPLETION;   << Nothing, exit >>    03602000
               IF NOT IOQPL(QMISC).PRE'TO'POST THEN                     03604000
                 SIOP(SIO'SETUP+7) := SIOPA + SIO'BUFFER'FILL; <<00773>>03606000
                                                               <<00769>>03608000
               SIOP(SIO'BUFFER'FILL+24) := SIOENDI;  << End SIO prog >> 03610000
               SIOP(X := X+1) := %177777;   << ... after buffer fill >> 03612000
               END;  << of CCTL'PARAM = %320 >>                         03614000
<<                                                                      03616000
  VFC channel skip command bytes for the HP2608 are of the form %2nn,   03618000
but the other subtypes use %1nn. We assumed %1nn until now, so change   03620000
to %2nn if we have a 2608.                                              03622000
>>                                                                      03624000
          IF SUBTYPE = HP2608 AND CARRIAGE'CONTROL >= %100 THEN         03626000
            CARRIAGE'CONTROL.(8:2) := 2;                                03628000
          DITP(DVFC1).CCTL := CARRIAGE'CONTROL;                         03630000
$PAGE                                                                   03632000
<< Set up the channel program for buffer fill and print control >>      03634000
                                                                        03636000
          IF CCTL'PARAM <> %320 THEN                                    03638000
               BEGIN  << We have to print something >>                  03640000
               IF IOQPL(QPAR2)                                          03642000
                 THEN   << Prespace >>                                  03644000
                    BEGIN                                               03646000
                    IOQP(QMISC).PRESPACE := 1;                 <<00769>>03648000
                    SIOP (SIO'SETUP+7) := SIOPA +              <<00773>>03650000
                      SIO'PRINT'AND'SPACE;                     <<00769>>03652000
                    SIOP(SIO'BUFFER'FILL+24) := SIOENDI;                03654000
                    SIOP(X := X+1) := %177777;   << End here >>         03656000
                    SIOP (SIO'PRINT'AND'SPACE+5) := %177777;   <<00769>>03658000
                    END   << of prespace >>                             03660000
                 ELSE   << Postspace >>                                 03662000
                    BEGIN                                               03664000
                    IF NOT IOQPL(QMISC).PRE'TO'POST THEN                03666000
                      SIOP(SIO'SETUP+7) := SIOPA +             <<00773>>03668000
                      SIO'BUFFER'FILL;                         <<00769>>03670000
                    SIOP(SIO'BUFFER'FILL+24) := JUMP;   << JUMP *+1 >>  03672000
                      SIOP (X := X+1) := SIOPA +               <<00769>>03674000
                        SIO'PRINT'AND'SPACE;                   <<00769>>03676000
                      SIOP (SIO'PRINT'AND'SPACE+5) := %177777; <<00769>>03678000
                    END;   << of postspace >>                           03680000
               END;   << of CCTL'PARAM <> %320 >>                       03682000
                                                                        03684000
          SIOP(SIO'BUFFER'FILL+1) := BANK;  << Mem bank addr of buff >> 03686000
          NEG'WORD'COUNT := -IOQP(QWBCT);                               03688000
          IF > THEN                                                     03690000
               BEGIN   << A byte transfer request >>                    03692000
                                                                        03694000
<< Save negative word count, rounded down.  It comes in handy later. >> 03696000
                                                                        03698000
               NEG'WORD'COUNT := -(NEG'WORD'COUNT & ASR(1));            03700000
               IF IOQPL(QWBCT)             << An odd number of bytes >> 03702000
                 AND (NEG'WORD'COUNT < 0   << Must be >= 3, but ... >>  03704000
                 OR NOT IMBEDDEDL)  << if CCTL imbedded, then 1 O.K. >> 03706000
                 THEN                                                   03708000
                    BEGIN   << An odd byte to output >>                 03710000
                    TOS := BANK;                                        03712000
                    TOS := BUFADDR;  << Get its address, then load >>   03714000
                    TOS := TOS - NEG'WORD'COUNT;                        03716000
                    LOAD'MEMORY;   << Odd byte is in left half word >>  03718000
                    ODD'BYTE := TOS & LSR(8);                           03720000
                    END;   << of odd byte processing >>                 03722000
               END;  << of byte transfer request >>                     03724000
$PAGE                                                                   03726000
<<                                                                      03728000
  Count is <= 0.  If = 0, we have at most a single byte of  data.  We   03730000
may  also  have  an  imbedded  carriage  control  byte.  This section   03732000
configures the SIO program to transmit the first  data  byte  (if  it   03734000
exists)  from  the  right  half  of  the first data word whenever the   03736000
carriage control byte is in the left half word.                         03738000
>>                                                                      03740000
          IF IMBEDDEDL   << Carriage control imbedded in data >>        03742000
            AND NEG'WORD'COUNT < 0 THEN  << At least one data byte >>   03744000
               BEGIN   << Must write first byte separately >>           03746000
               NEG'WORD'COUNT := NEG'WORD'COUNT + 1;  << Decrement >>   03748000
               SIOP(SIO'BUFFER'FILL+7) := BUFADDR; <<Addr of 1st byte>> 03750000
                                                                        03752000
<< Link start of buffer fill to the write first byte section >>         03754000
                                                                        03756000
               SIOP(LINK) := SIOPA + SIO'BUFFER'FILL + 4;               03758000
               LINK := SIO'BUFFER'FILL + 9;  << End of 1st byte wrt >>  03760000
               END;  << of writing first byte >>                        03762000
                                                                        03764000
          IF NEG'WORD'COUNT < 0 THEN                                    03766000
               BEGIN   << At least one full word to write >>            03768000
               SIOP(SIO'BUFFER'FILL+12) := SIOWRT1 LAND NEG'WORD'COUNTL;03770000
               SIOP(X := X+1) := BUFADDR + IMBEDDED;  << Start. addr >> 03772000
               SIOP(LINK) := SIOPA + SIO'BUFFER'FILL + 10;              03774000
               LINK := SIO'BUFFER'FILL + 15;  << End of main blk wrt >> 03776000
               END;   << of writing main block >>                       03778000
                                                                        03780000
          IF ODD'BYTE >= 0 THEN                                         03782000
               BEGIN  << We have an odd byte >>                         03784000
<<                                                                      03786000
  We can't use DITP(DLAST) for the odd byte all the time,  since  the   03788000
odd  byte  flag  is cleared (-1) at each entry to the driver.  We may   03790000
need to re-run the channel program in case  of  interruption,  so  we   03792000
can't automatically clear the current odd byte in DITP(DLAST).  Hence   03794000
the additional word, ODD'BYTE.  This is the only place where any  odd   03796000
byte should be stored into DITP(DLAST).                                 03798000
>>                                                                      03800000
               DITP(DLAST) := ODD'BYTE;                                 03802000
               SIOP(LINK) := SIOPA + SIO'BUFFER'FILL + 16;              03804000
               LINK := SIO'BUFFER'FILL + 21;  << Dummy end of           03806000
                                               odd byte wrt >>          03808000
               END;   << of writing odd byte >>                         03810000
                                                                        03812000
<< Set link to the last SETBANK order if we're not already there >>     03814000
                                                                        03816000
          IF LINK <> SIO'BUFFER'FILL + 21 THEN SIOP(LINK) :=            03818000
            SIOPA + SIO'BUFFER'FILL + 22;                               03820000
$PAGE                                                                   03822000
START'OUTPUT:                                                           03824000
COMMENT                                                        <<00769>>03826000
  The following test has two purposes:                         <<00769>>03828000
1)  To detect a Not Ready condition.  If  so,  the  Not  Ready <<00769>>03830000
    message is printed, we return the Not Ready state to SIODM <<00769>>03832000
    and we put the driver into a Not  Ready  Wait.  Exception: <<00769>>03834000
    If  a  Tally  printer went off-line, we enter the Wait For <<00769>>03836000
    Tally state.  See the comments under Operation of  IOLPRT0 <<00769>>03838000
    for further details.                                       <<00769>>03840000
2)  To detect the 2608 Power Fail/Reset status bit.  If it  is <<00769>>03842000
    set,  the 2608's operating environment has been destroyed, <<00769>>03844000
    requiring operator intervention to restore it.  Before the <<00769>>03846000
    operator can be notified, the status bit must be  cleared. <<00769>>03848000
    This can only be done with a 2608 Master Reset command, so <<00769>>03850000
    we unleash one followed by a Download Left Margin  to  re- <<00769>>03852000
    store the margin setting destroyed by the reset. When they <<00769>>03854000
    complete successfully (including any on-line/off-line side <<00769>>03856000
    trips which may occur), and if we are in a job, we  report <<00769>>03858000
    the  problem  to the operator (done in the completion sec- <<00769>>03860000
    tion).                                                     <<00769>>03862000
    ;                                                          <<00769>>03864000
          TEMP := CHECK'STATUS (DITP, IOQP, DRTNUMB, TRUE);    <<00770>>03866000
          IF TEMP < 0 THEN                                     <<00770>>03868000
               BEGIN   << Set Not Ready or Wait For Tally >>   <<00769>>03870000
               DOCIO (%40000, DITP); << Clear old interrupts >>         03872000
               DOCIO (2, DITP);  << Enable device interrupts >>         03874000
               IOQP(QMISC).WAIT'FIELD :=                       <<00769>>03876000
                 IF DITPL(DVFC1).TALLY'NOT'READY               <<00769>>03878000
                   THEN WAIT'FOR'TALLY                         <<00769>>03880000
                   ELSE NOT'READY'WAIT;                        <<00769>>03882000
               LPDRVR := NOT'READY;                                     03884000
               RETURN;                                                  03886000
               END;   << of Not Ready >>                                03888000
          IF DITPL(DVFC1).PWRFL'RESET                          <<00770>>03890000
            THEN                                               <<00770>>03892000
               BEGIN   << Well, the fan needed cleaning >>     <<00770>>03894000
COMMENT                                                        <<00770>>03896000
  A 2608 has undergone a power fail or master reset. This code <<00770>>03898000
configures the Master Reset command, which is the only command <<00770>>03900000
which clears the associated status bit.  The Left Margin  com- <<00770>>03902000
mand  follows  the  Master Reset, and restores the left margin <<00770>>03904000
which existed before the printer lost its mind.                <<00770>>03906000
;                                                              <<00770>>03908000
               IOQP(QMISC).MASTER'CLEAR := 1;                  <<00770>>03910000
               SIOP(SIO'SETUP+7) := SIOPA + SIO'MASTER'CLEAR;  <<00773>>03912000
               DITP(DLAST) := DITP(DVFC1).LEFT'MARGIN;         <<00770>>03914000
               SIOP(SIO'LEFT'MARGIN+5) := %177777;             <<00770>>03916000
               END   << of 2608 PWRFL'RESET bit being set >>   <<00770>>03918000
            ELSE IF TEMP > 0 THEN                              <<00770>>03920000
               BEGIN                                           <<00770>>03922000
               TOS := TEMP;                                    <<00770>>03924000
               IF S0 = NO'MSG'BUFF'ERROR                       <<00769>>03926000
                 THEN GO TO IO'ERROR                           <<00769>>03928000
                 ELSE GO TO IO'DONE;                           <<00769>>03930000
               END;   << of TEMP > 0 >>                        <<00770>>03932000
$PAGE                                                          <<00769>>03934000
<< Abort any still-running SIO  channel  program  to  avoid >> <<00769>>03936000
<< conflict with the one we're about to light off.          >> <<00769>>03938000
                                                               <<00769>>03940000
          IF WAIT'CODE >= NOT'READY'WAIT THEN                  <<00785>>03942000
            MASTERCLEAR (DITP);                                <<00769>>03944000
                                                               <<00769>>03946000
          STARTIO (DITP, SIOP, TRUE); << FINALLY, light off SIO prog >> 03948000
          IF > THEN   << controller busy, forget the whole thing >>     03950000
               BEGIN TOS := SIO'FAIL'ERROR;                             03952000
               GO TO IO'ERROR;                                          03954000
               END;   << of SIO failure >>                              03956000
                                                                        03958000
          IOQP(QMISC).WAIT'FIELD := COMPLETION'WAIT;                    03960000
          LPDRVR := INTERRUPT'WAIT;                                     03962000
          RETURN;                                                       03964000
          END;   << of function = WRITE >>                              03966000
                                                               <<00770>>03968000
                                                               <<00770>>03970000
                                                               <<00770>>03972000
<< WAIT'CODE = 0 (new request), FUNCTION = 2 (FOPEN),       >> <<00770>>03974000
<< 3 (FCLOSE) or 4 (DEVICE CLOSE)                           >> <<00770>>03976000
                                                                        03978000
     IF (FOPEN <= FUNCTION <= DEVICE'CLOSE) THEN               <<00770>>03980000
          BEGIN                                                         03982000
          IF DITDDF.TOP'OF'FORM THEN                           <<01382>>03984000
               BEGIN                                           <<00464>>03986000
                                                               <<00464>>03988000
<<   We're already at top  of  form.  Normally  this  means >> <<00464>>03990000
<< nothing to do. But if a 2608 has had a Power Fail/Master >> <<00464>>03992000
<< Reset, we must clear the condition before going on. This >> <<00656>>03994000
<< is  done  in rather roundabout fashion by going directly >> <<00656>>03996000
<< to START'OUTPUT, even though no channel program has been >> <<00656>>03998000
<< set  up.  This  allows  START'OUTPUT  to  process   this >> <<00656>>04000000
<< abnormal condition, even though it was detected here.    >> <<00656>>04002000
                                                               <<00656>>04004000
               CHECK'STATUS (DITP, IOQP, DRTNUMB, FALSE);      <<00656>>04006000
               IF DITPL(DVFC1).PWRFL'RESET THEN                <<00656>>04008000
                  GO START'OUTPUT;   << Got one >>             <<00656>>04010000
               GO CLEAN'UP;   << No problem, just leave >>     <<00656>>04012000
               END;   << of checking for Power Fail/Reset >>   <<00656>>04014000
          DITP(DVFC1).CCTL := IF SUBTYPE = HP2608                       04016000
            THEN %200   << Skip to channel 1 (top-of-form), 2608 >>     04018000
            ELSE %100;  << Same thing, all other printers >>            04020000
          SIOP (SIO'SETUP+7) := SIOPA + SIO'PRINT'AND'SPACE;   <<00773>>04022000
          SIOP (SIO'PRINT'AND'SPACE+5) := %177777;             <<00769>>04024000
          GO START'OUTPUT;   << Light off channel program >>            04026000
          END;   << of FOPEN or FCLOSE >>                               04028000
$PAGE                                                                   04030000
<< WAIT'CODE = 0 (new request), FUNCTION = %100 (Download VFC) >>       04032000
                                                                        04034000
     IF FUNCTION = DOWNLOAD'VFC AND SUBTYPE = HP2608 THEN               04036000
          BEGIN   << Code = %100 >>                                     04038000
          SIOP(SIO'SETUP+7) := SIOPA + SIO'VFC;                <<00773>>04040000
          IF IOQP(QWBCT) >  127 THEN IOQP(QWBCT) :=  127;  << Limit >>  04042000
          IF IOQP(QWBCT) < -254 THEN IOQP(QWBCT) := -254;  << count >>  04044000
          NEG'WORD'COUNT := -IOQP(QWBCT);                               04046000
          IF > THEN   << a byte transfer request >>                     04048000
            NEG'WORD'COUNT := -(NEG'WORD'COUNT & ASR(1));  <<Rnd down>> 04050000
          IF =  << either from words = 0 or from rounding bytes to 0 >> 04052000
            THEN                                                        04054000
               BEGIN  << Use a 2608 default VFC, 6 or 8 LPI >>          04056000
               DITP(DLAST) := IF IOQP(QPAR1) = 8                        04058000
                 THEN %200   << 8 LPI bit set >>                        04060000
                 ELSE 0;                                                04062000
               SIOP(SIO'VFC+5) := SIOPA + SIO'VFC + 12;  << Skip VFC    04064000
                                                     buffer write >>    04066000
               END   << of count = 0 >>                                 04068000
            ELSE                                                        04070000
               BEGIN  << Custom VFC required, configure it here >>      04072000
               DITP(DLAST) := IF IOQP(QPAR1) = 8                        04074000
                 THEN LOGICAL (-NEG'WORD'COUNT) LOR %200  << 8 LPI >>   04076000
                 ELSE -NEG'WORD'COUNT;                                  04078000
               SIOP(SIO'VFC+5) := SIOPA + SIO'VFC + 6;  << JUMP *+1 >>  04080000
               SIOP(X := X+4) := BANK;                                  04082000
               SIOP(X := X+1) := SIOWRT1 LAND NEG'WORD'COUNTL;          04084000
               SIOP(X := X+1) := BUFADDR;                               04086000
               END;  << of count <> 0 >>                                04088000
          SIOP(SIO'VFC+13) := %177777;   << Initialize END order >>     04090000
          GO START'OUTPUT;   << Light off channel program >>            04092000
          END;   << of function = DOWNLOAD'VFC >>                       04094000
                                                                        04096000
                                                                        04098000
                                                                        04100000
<< WAIT'CODE = 0 (new request), FUNCTION = %101 (Download Lft Margn) >> 04102000
                                                                        04104000
     IF FUNCTION = DOWNLOAD'LEFT'MARGIN AND SUBTYPE = HP2608 THEN       04106000
          BEGIN   << Code = %101 >>                                     04108000
          DITP(DVFC1).LEFT'MARGIN := DITP(DLAST) :=            <<00770>>04110000
            IF (0 <= IOQP(QPAR1) <= 15)                        <<00770>>04112000
            THEN X     << Index register has valid IOQP(QPAR1) >>       04114000
            ELSE 15;   << Value out of range, use default >>            04116000
          SIOP(SIO'SETUP+7) := SIOPA + SIO'LEFT'MARGIN;        <<00773>>04118000
          SIOP(SIO'LEFT'MARGIN+5) := %177777;  << Initialize END >>     04120000
          GO START'OUTPUT;   << Light off channel program >>            04122000
          END;  << of function = DOWNLOAD'LEFT'MARGIN >>                04124000
                                                                        04126000
<< Add new functions here, else fall through to error >>                04128000
                                                                        04130000
     TOS := INVALID'FUNCTION;                                           04132000
     GO TO IO'DONE;                                                     04134000
                                                                        04136000
     END;   << of WAIT'CODE = 0, new request >>                         04138000
$PAGE                                                                   04140000
<<---------------- WAIT'CODE = 1, completion section --------------->>  04142000
                                                                        04144000
<<                                                                      04146000
  This section processes all device completion interrupts (as opposed   04148000
to interrupts resulting from a device going from Not Ready to  Ready.   04150000
The latter interrupts are  handled  by  WAIT'CODE  =  3).  Note:  The   04152000
current TIO status is set in the DIT by GIP at each interrupt.          04154000
>>                                                                      04156000
     BEGIN                                                              04158000
                                                               <<00769>>04160000
     IF DITPL(DSTAT).XFER'ERROR THEN                                    04162000
          BEGIN   << Illegal mem addr, or mem or data parity error >>   04164000
          TOS := TRANSFER'ERROR;                                        04166000
          GO TO IO'ERROR;                                               04168000
          END;   << of transfer error >>                                04170000
                                                                        04172000
     IF DITPL(DSTAT) THEN                                               04174000
          BEGIN   << Bit 15 is the timeout bit >>                       04176000
          TOS := TIMEOUT'ERROR;   << A real timeout >>                  04178000
          GO TO IO'ERROR;                                               04180000
          END;   << of timeout >>                                       04182000
     IF IOQPL(QMISC).MASTER'CLEAR THEN                                  04184000
          BEGIN                                                         04186000
<<                                                                      04188000
  We've done the 2608 Master Reset required by a printer Power  Fail/   04190000
Reset.  If  we're  between  jobs  go retry the request, else tell the   04192000
operator about the reset and return the proper error status. >><<00464>>04194000
                                                               <<00464>>04196000
          IF DITPL(DVFC1).BETWEEN'JOBS THEN                    <<00464>>04198000
               BEGIN   << Power fail was safe, go retry >>     <<00464>>04200000
               DITP(DVFC1).PWRFL'RESET := 0;                   <<00464>>04202000
               IOQP(QMISC).MASTER'CLEAR := 0;                  <<00464>>04204000
               IOQP(X).WAIT'FIELD := NEW'REQUEST;              <<00464>>04206000
               IF NOT IOQPL(X).RETRY THEN                      <<00571>>04208000
                    BEGIN   << Prevent endless looping if...>> <<00571>>04210000
                    IOQP(X).RETRY := 1;  << ...wrong subtype >><<00571>>04212000
                    GO START'OVER;                             <<00571>>04214000
                    END;   << of endless loop test >>          <<00571>>04216000
               END;   << of Power Fail/Reset between jobs >>   <<00464>>04218000
          IF NOT IOMESSAGE (1, PWRFL'RESET'MESSAGE, %10000,             04220000
            DITP(DLDEV).DLDEVN,,,,, SYS'CONSOLE) THEN                   04222000
               BEGIN   << No system message buffer >>                   04224000
               TOS := NO'MSG'BUFF'ERROR;   << %124 >>                   04226000
               GO TO IO'ERROR;                                          04228000
               END;   << of unable to write error message >>            04230000
          DITP(DVFC1).PWRFL'RESET := 0;                                 04232000
          DITP(DVFC1).VFC'MOD := 0;   << No more custom VFC >> <<00464>>04234000
          TOS := PWRFL'RESET'ERROR;   << %213 >>                        04236000
          GO TO IO'DONE;                                                04238000
          END;   << of reporting PF/RST error >>                        04240000
$PAGE                                                          <<00769>>04242000
<< Check for Tally off-line -- it needs special handling. >>   <<00769>>04244000
                                                               <<00769>>04246000
     IF SUBTYPE = TALLY                                        <<00769>>04248000
       AND DITP(DSTAT) >= 0   << Channel program incomplete >> <<00769>>04250000
       AND DITPL(X).NOT'RDY THEN   << Printer off-line >>      <<00769>>04252000
         DITP(DVFC1).TALLY'NOT'READY := 1;                     <<00769>>04254000
                                                               <<00769>>04256000
     IF IOQPL(QMISC).PRE'TO'POST THEN                          <<00769>>04258000
          BEGIN   << Print buffer MT, continue w/ postspace >> <<00769>>04260000
          SIOP (SIO'SETUP+7) := SIOPA + SIO'BUFFER'FILL;       <<00773>>04262000
          IOQP(QMISC).PRE'TO'POST := 0;  << Don't come back >> <<00769>>04264000
          GO START'OUTPUT;                                     <<00769>>04266000
          END;                                                 <<00769>>04268000
                                                               <<00769>>04270000
     IF (TEMP := DITP(DVFC2).LINES'LEFT'OVER) <> 0 THEN        <<00769>>04272000
          BEGIN  << Multiple line skip, set up continuation >> <<00769>>04274000
          SIOP (SIO'SETUP+7) := SIOPA + SIO'PRINT'AND'SPACE;   <<00773>>04276000
          IF DITP(DVFC1).CCTL < %100                           <<01061>>04278000
            THEN  << Additional slews of <=15 lines >>         <<01061>>04280000
              IF TEMP <= 15                                    <<01061>>04282000
                THEN                                           <<01061>>04284000
                   BEGIN   << Last time through here >>        <<01061>>04286000
                   DITP(DVFC1).CCTL := TEMP;                   <<01061>>04288000
                   DITP(DVFC2).LINES'LEFT'OVER := 0;           <<01061>>04290000
                   END                                         <<01061>>04292000
                ELSE  << More than 15 lines left, do next 15 >><<01061>>04294000
                   DITP(DVFC2).LINES'LEFT'OVER := TEMP - 15    <<01061>>04296000
            ELSE  << "0" or "-" with auto eject, adv 1 line >> <<01061>>04298000
               DITP(DVFC2).LINES'LEFT'OVER := TEMP - 1;        <<01061>>04300000
          GO START'OUTPUT;                                     <<00769>>04302000
          END;                                                 <<00769>>04304000
                                                               <<00769>>04306000
     IF IOQPL(QMISC).PRESPACE THEN                             <<00769>>04308000
          BEGIN   << Prespace print done, fill buffer >>       <<00769>>04310000
          SIOP (SIO'SETUP+7) := SIOPA + SIO'BUFFER'FILL;       <<00773>>04312000
          IOQP(QMISC).PRESPACE := 0;  << One time only >>      <<00769>>04314000
          GO START'OUTPUT;                                     <<00769>>04316000
          END;                                                 <<00769>>04318000
                                                                        04320000
<< Fall through to normal completion.  Clean up and exit >>             04322000
$PAGE                                                                   04324000
CLEAN'UP:                                                      <<00464>>04326000
     IF (FOPEN <= FUNCTION <= DOWNLOAD'VFC) THEN               <<00464>>04328000
          BEGIN   << Must be at top of form >>                 <<00464>>04330000
          DITDDF.PRESPACE'NOTEMPTY := 0; <<Postspc,empty buf>> <<01382>>04332000
          DITDDF.TOP'OF'FORM := 1;                             <<01382>>04334000
          END;   << of control function >>                     <<00464>>04336000
     IF FUNCTION = FOPEN THEN DITP(DVFC1).BETWEEN'JOBS := 0;   <<00464>>04338000
     IF FUNCTION = DEVICE'CLOSE THEN                           <<00464>>04340000
       DITP(DVFC1).BETWEEN'JOBS := 1;                          <<00464>>04342000
     IF FUNCTION = WRITE THEN                                  <<00464>>04344000
          BEGIN   << Update prespace, not'empty and TOF >>     <<00464>>04346000
          DITDDF.PRESPACE'LAST := IOQPL(QPAR2);                <<01382>>04348000
          DITDDF.NOT'EMPTY := IF IOQPL(QPAR2)   << Prespace >> <<01382>>04350000
            AND IOQP(QWBCT) <> -IMBEDDED   << Some data sent >><<00464>>04352000
            THEN 1                                             <<00464>>04354000
            ELSE 0;                                            <<00464>>04356000
          DITDDF.TOP'OF'FORM :=                                <<01382>>04358000
            IF (DITP(DVFC1).CCTL = %200  << 2608 top of form >><<00464>>04360000
              OR DITP(X).CCTL = %100)   << TOF, all others >>  <<00464>>04362000
              AND NOT DITDDF.NOT'EMPTY <<Nothing sent since>>  <<01382>>04364000
              THEN 1                                           <<00464>>04366000
              ELSE 0;                                          <<00464>>04368000
          END;   << of FUNCTION = WRITE >>                     <<00464>>04370000
     IF SUBTYPE = HP2608 THEN                                           04372000
          BEGIN   << Set proper state of VFC'MOD bit >>                 04374000
          IF FUNCTION = DOWNLOAD'VFC THEN                               04376000
            DITP(DVFC1).VFC'MOD := IF IOQP(QWBCT) = 0                   04378000
            THEN 0            << No custom VFC installed >>             04380000
            ELSE 1;           <<    Custom VFC installed >>             04382000
          IF FUNCTION = DOWNLOAD'VFC                           <<00571>>04384000
            OR FUNCTION = DOWNLOAD'LEFT'MARGIN THEN            <<00571>>04386000
            IF NOT IOMESSAGE (1, GOOD'DOWNLOAD'MSG, %10000,    <<00571>>04388000
              DITP(DLDEV).DLDEVN,,,,, SYS'CONSOLE) THEN        <<00571>>04390000
               BEGIN   << No system message buffer >>          <<00571>>04392000
               TOS := NO'MSG'BUFF'ERROR;   << %124 >>          <<00571>>04394000
               GO TO IO'ERROR;                                 <<00571>>04396000
               END;   << of unable to write error message >>   <<00571>>04398000
          END;   << of SUBTYPE = 2608 >>                                04400000
                                                                        04402000
NORMAL'COMPLETION:                                                      04404000
     TOS := GOOD'STATUS;                                                04406000
                                                                        04408000
IO'DONE:                                                                04410000
     IOQP(QSTAT).STATS := TOS;                                          04412000
     LPDRVR := REQUEST'DONE;                                            04414000
     RETURN;                                                            04416000
                                                                        04418000
IO'ERROR:                                                               04420000
     DITP(DSERR):= [8/1,8/DLOGERROR];<<LOG COUNT # INDEX>>     <<01339>>04422000
     DITP(DLOGERROR):= DITP(DSTAT);   <<LOG ERROR>>            <<01339>>04424000
                                                                        04426000
CLEAR'CARD:                                                             04428000
     MASTERCLEAR (DITP);   << Clear the U.I. card >>                    04430000
     GO TO IO'DONE;        << Set completion status and return >>       04432000
     END;   << of normal request, and of WAIT'CODE = 1 >>               04434000
$PAGE                                                                   04436000
<< WAIT'CODE = 2, return after 3-second Tally on-line delay >> <<00769>>04438000
                                                                        04440000
     BEGIN                                                     <<00769>>04442000
     DITP(DVFC1).TALLY'NOT'READY := 0; <<No longer a problem>> <<00769>>04444000
     GO TO WAIT'CODE3;  << Rest is like normal Not Ready >>    <<00785>>04446000
     END;   << of WAIT'CODE = 2 >>                             <<00769>>04448000
                                                                        04450000
                                                                        04452000
                                                                        04454000
                                                                        04456000
                                                                        04458000
<<------- WAIT'CODE = 3, return from Not Ready condition ------->>      04460000
                                                                        04462000
COMMENT                                                        <<00785>>04464000
  SIODM unfreezes the caller's data segment whenever we return <<00785>>04466000
Not Ready to it.  This allows the Memory Manager  to  swap  it <<00785>>04468000
out  rather than tie up real memory while the printer is idle. <<00785>>04470000
The data segment is returned to  real  memory  before  we  are <<00785>>04472000
called again, but (usually) not at the same address.  The code <<00785>>04474000
below updates the channel program with the new address if  re- <<00785>>04476000
quired by the current request.                                 <<00785>>04478000
;                                                              <<00785>>04480000
     BEGIN                                                     <<00785>>04482000
WAIT'CODE3:                                                    <<00785>>04484000
     IF FUNCTION = WRITE THEN                                  <<00785>>04486000
          BEGIN                                                <<00785>>04488000
          SIOP (SIO'BUFFER'FILL+1) := BANK;                    <<00785>>04490000
          SIOP (X := X+6) := BUFADDR;                          <<00785>>04492000
          SIOP (X := X+6) := BUFADDR + IMBEDDED;               <<00785>>04494000
          END;                                                 <<00785>>04496000
                                                               <<00785>>04498000
     IF FUNCTION = DOWNLOAD'VFC THEN                           <<00785>>04500000
          BEGIN                                                <<00785>>04502000
          SIOP (SIO'VFC+9) := BANK;                            <<00785>>04504000
          SIOP (X := X+2) := BUFADDR;                          <<00785>>04506000
          END;                                                 <<00785>>04508000
     GO START'OUTPUT;   << Try once more to print >>           <<00769>>04510000
     END;   << of WAIT'CODE = 3 >>                             <<00785>>04512000
                                                               <<00769>>04514000
                                                               <<00769>>04516000
                                                               <<00769>>04518000
                                                               <<00769>>04520000
                                                               <<00769>>04522000
<<-- WAIT'CODE = 4, Tally placed on-line, allow 3 seconds -->> <<00769>>04524000
                                                               <<00769>>04526000
     GO START'DELAY;                                           <<00769>>04528000
                                                                        04530000
  END;   << of WAIT'CODE CASE statement >>                              04532000
                                                                        04534000
END;   << of LPDRVR >>                                                  04536000
$PAGE                                                                   04538000
<<--------------------- Driver Linkage Area ----------------------->>   04540000
                                                                        04542000
ASMB (                                                                  04544000
      PCAL SIODM;    << Monitor                >>                       04546000
      PCAL LPDRVR;   << Initiator ...          >>                       04548000
      PCAL LPDRVR;   << ... and completor      >>                       04550000
                                                                        04552000
      CON  0;        << No I/O process         >>                       04554000
                                                                        04556000
      PCAL LPINIT;   << Initialization routine >>                       04558000
                                                                        04560000
      CON  1;        << One interrupt handler  >>                       04562000
      PCAL GIP);     << The interrupt handler  >>                       04564000
                                                                        04566000
END.                 << of line printer driver, IOLPRT0 (19) >>         04568000
