         << LINES .001/.009 ARE RESERVED FOR SYSTEMS INTEGRATION >>     00000001
$EDIT VOID=00505025                                            <<09474>>00505025
***** Version change -- " " ==> "0"       (in fix 07114) ***** <<09562>>00556000
  WAITFORDISC now works properly when switching volumes.       <<M9108>>00566000
  Fix possible buffer data segment underflow in CTRLSDISC      << 9108>>00585005
(BSF function).                                                << 9108>>00585010
  Change PVPROC interference test in WAITFORDISC to check  for <<S9203>>00585015
different  gap  table segments in the LDTX.  Lock the LDT here <<S9203>>00585020
and in PVPROC to synchronize LDTX access.                      <<09474>>00585025
SDISCIO                                                        <<09474>>00585030
  Add VOLUME'FATAL errors, allow SDISC to continue when a  new <<09474>>00585035
volume is mounted, unless a truly fatal error has occurred. In <<09474>>00585040
either case, allow REWIND, UNLOAD, DEVICE CLOSE, etc., so vol- <<09474>>00585045
ume can be dismounted/deallocated.                             <<09474>>00585050
DISPLAY'STATUS                                                 <<09474>>00585055
  Displays ATTACHIO status if not normal completion.  This     <<09474>>00585060
procedure is new and calls to it were added to ATACHIO and     <<09474>>00585065
WAIT'FOR'COMPLETION.                                           <<09474>>00585070
GPTMOD                                                         <<09474>>00585075
  Cuts back Gap Table XDS to the size actually needed for  the <<09474>>00585080
Gap  Table.  Makes  the  working set a lot smaller for minimum <<09474>>00585085
memory systems using cartridge tape.                           <<09474>>00585090
STRUCTURE AND OPERATION (leading comments)                     <<09491>>00585095
  Updated comments at front of listing to reflect the  double- <<09491>>00585100
buffering  enhancement,  and other improvements to SDISC since <<09491>>00585105
the comments were last modified.                               <<09491>>00585110
SDISCIO                                                        <<09491>>00585115
  Added comments explaining SDISCIO operation, made sure FATAL <<09491>>00585120
and VOL'FATAL are cleared for each new command.                <<09491>>00585125
  WAITFORDISC                                                  <<09556>>00585130
Now checks for (and rejects) SERDISC volumes which  have  been <<09556>>00585135
SCRATCHed by VINIT.                                            <<09556>>00585140
  DISPLAY'STATUS                                               <<09556>>00585145
Treats external aborts and powerfails as volume fatal errors.  <<09556>>00585150
  Message catalog                                              <<09556>>00585155
Add SDERRs 39 (external abort) and 41 (powerfail).             <<09556>>00585160
  UNLOAD'CARTRIDGE'TAPE                                        <<09556>>00585165
"New" procedure, created from code in CTRLSDISC so that  WAIT- <<09556>>00585170
FORDISC can call it also.                                      <<09556>>00585175
SDISCIO                                                        <<09562>>00585180
  Added calls to OBTAIN and RELEASE to force serial access  by <<09562>>00585185
processes using the same SDISC GPT XDS.                        <<09562>>00585190
GPT XDS                                                        <<09562>>00585195
  Added four-word data structure at DB+12 to DB+15 for use  by <<09562>>00585200
OBTAIN and RELEASE.                                            <<09562>>00585205
ALLOCATE (in Module 54)                                        <<09562>>00585210
  Added code to initialize above data structure when acquiring <<09562>>00585215
the GPT XDS.                                                   <<09562>>00585220
ATACHIO                                                        <<09576>>00585225
  Added ability to retry 3 times if blocked read  I/O  returns <<09576>>00585230
power fail status by system or serial disc device.             <<09576>>00585235
READ'BUFFER                                                    <<09576>>00585240
  Does similar (blocked) retries if nowait  (unblocked)  reads <<09576>>00585245
return either power fail status.                               <<09576>>00585250
CTRLSDISC                                                      <<09576>>00585255
  REW'UNLOAD now runs to completion regardless of  errors,  to <<09576>>00585260
ensure  that SDISC is left JUSTALLOCATED.  Without this, SDISC <<09576>>00585261
unloads 2nd STORE reel without writing to it.                  <<09576>>00585262
RITESDISC                                                      <<01040>>00585265
  A contiguous block fill which ends exactly on an SDISC  buf- <<01040>>00585270
fer boundary is now immediately dumped to the device.          <<01040>>00585275
GPTMOD                                                         <<01193>>00585280
$EDIT VOID=00585282                                                     00585281
  Fix 09474, cutting the Gap Table XDS to only as much  as  it <<01193>>00585285
needs, introduced a bug.  If the first volume is a Small cart- <<01193>>00585290
ridge and a subsequent volume is a Large cartridge, there will <<01193>>00585295
not be enough XDS for the larger Gap Table required, and SDISC <<01193>>00585300
will complain (fatally).  This fix causes SDISC to adjust  its <<01193>>00585305
Gap Table XDS size up or down, as required. Now SDISC only ob- <<01193>>00585310
jects if the XDS expansion attempt fails.                      <<01193>>00585315
GPTMOD                                                         <<01192>>00585320
  Now properly updates SDISC version when  writing  from  load <<01192>>00585325
point. Before, would only update if media had new or blown Gap <<01192>>00585330
Table when writing.                                            <<01192>>00585335
SDISCIO                                                        <<c1602>>00585340
  Allows REWIND AND UNLOAD to operate on a JUST'ALLOCATED      <<c1602>>00585345
cartridge.                                                     <<c1602>>00585346
  Help handle User Logging Powerfail Recovery:                 <<u2249>>00585350
1.  Retry powerfail errors even if write operation except for  <<u2249>>00585351
BUFFALO because BUFFALO has immediate reporting enabled.       <<u2249>>00585352
2.  Reduce size of data buffers to 6K so User Logging will     <<u2249>>00585354
contain all that data in its buffers.                          <<u2249>>00585355
3.  Once called by User Logging to do special write for one    <<u2249>>00585358
volume, do the same for all succeeding volumes.   SDISC knows  <<u2249>>00585359
when to do this because REELSWITCH will call it with special   <<u2249>>00585360
function code of %4001 when it is all done with other I/O.     <<u2249>>00585361
4.  Reset VOLUME'FATAL after a rewind command is issued by     <<u2249>>00585362
User Logging so User Logging can do recovery.                  <<u2249>>00585363
5.  Don't set EOFCODE if an EOF is detected while doing FSF    <<u2249>>00585364
or BSF as real tapes don't report that status back.            <<u2249>>00585365
CTRLSDISC                                                      <<u2249>>00585370
  Reset VOLUME'FATAL after a rewind command.  This is done so  <<u2249>>00585371
STORE like User Logging can do recovery after power failure.   <<u2249>>00585372
MERLIN                                                         <<m2249>>00585380
  Add changes to support Merlin which are Cartridge'Tape       <<m2249>>00585381
definition and specific Buffalo related code changed to        <<m2249>>00585382
also include Merlin since it is only a Buffalo in disguise.    <<m2249>>00585383
ATACHIO                                                        <<*2182>>00585400
  Pass a zero DST # to P'ATTACHIO if DST is user stack.        <<*2182>>00585401
Corrects FCONTROL 3 problem with serial discs. SR 5000-111575. <<*2182>>00585402
  This is the Serial Disc Interface (SDISC), Module 87 of MPE. <<09491>>00610000
The purpose of SDISC is to simulate magnetic  tape  operations <<09491>>00615000
on a direct access device. As of the current release, the fol- <<09491>>00620000
lowing peripherals may be used as serial discs:                <<09491>>00625000
       HP7920         50-megabyte hard disc                    <<09491>>00635000
       HP7925        120-megabyte hard disc                    <<09491>>00640000
       HP7933/7935   404-megabyte hard disc                    <<09491>>00645000
       HP7902/9895       Floppy discs                          <<09491>>00650000
$EDIT VOID=00655000                                            <<09491>>00655000
       HP9110/9144    17- or 65-Mbyte cartridge tape (CTAPE)   <<09491>>00660000
$EDIT VOID=00665000                                            <<09491>>00665000
The CTAPE is supported only as a serial disc.                  <<09491>>00675000
although the differences are invisible at the SDISC level.     <<09491>>00685000
2.  The HP7920, HP7925 and HP7933/HP7935 may also be supported <<09491>>00750000
    as private volumes in the non-system domain.  In this mode <<09491>>00755000
    of operation the device is sharable and is  therefore  not <<09491>>00760000
    owned.                                                     <<09491>>00761000
  SDISC is  entered  via  the  uncallable  procedure  SDISCIO, <<09491>>00805000
called  only  from  the general I/O system entry procedure AT- <<09491>>00810000
TACHIO.  (Another procedure, FINDSDISCGAP, is called  by  SYS- <<09491>>00815000
DUMP,  TPSTOMP and other processes which must write contiguous <<09491>>00820000
blocks.  More on this later).  ATTACHIO calls us only if LPDT' <<09491>>00825000
SERIAL'DISC is set.  The ALLOCATE procedure sets the bit when- <<09491>>00830000
ever a device is assigned to a process as a serial disc.  When <<09491>>00835000
the device is closed, DEALLOCATE clears the bit.               <<09491>>00840000
$EDIT VOID=00865000                                            <<09491>>00845000
priate to a magnetic tape I/O request. ATTACHIO, finding LPDT' <<09491>>00890000
SERIAL'DISC set, calls SDISCIO, passing on all the  parameters <<09491>>00895000
of its own call.  SDISCIO massages the parameters and fashions <<09491>>00900000
a  P'ATTACHIO  call, if necessary, with parameters appropriate <<09491>>00905000
to a disc I/O request. P'ATTACHIO handles the disc I/O request <<09491>>00910000
and returns two words to SDISC in normal fashion. SDISCIO pro- <<09491>>00915000
cesses this so that its two word return to ATTACHIO is  appro- <<09491>>00920000
priate  for  a magnetic tape completion status.  ATTACHIO then <<09491>>00925000
returns these two words to the original caller, in our example <<09491>>00930000
the File System.                                               <<09491>>00935000
$EDIT VOID=00945000                                            <<09491>>00940000
length environment of a disc or  CTAPE.  To  accomplish  this, <<09491>>00985000
data  is  buffered  within  SDISC.  To  maximize physical I/O, <<09491>>00990000
starting with MPEV/E two alternating  data  buffers  are  used <<09491>>00991000
with  NOWAIT I/O.  This will be described later.  We limit the <<09491>>00992000
present discussion to data record structures.                  <<09491>>00993000
  The buffers are an integral number of  sectors  (blocks  for <<09491>>00994000
a  CTAPE) long [minimum 8192 words, maximum 32640 words (disc) <<09491>>00995000
or 32256 words (CTAPE)]. If SDISC is called by User Logging,   <<u2249>>01000000
the buffers are reduced in size to 6144 words.  This is done   <<u2249>>01000100
to ensure that user logging can recover data in these buffers  <<u2249>>01000200
in case of a power fail. Files always start on a sector bound- <<u2249>>01000300
$EDIT VOID=01001000                                                     01001000
ary,  but  data  records  within  files may start anywhere and <<09491>>01005000
straddle sector boundaries. A record in a buffer is structured <<09491>>01010000
as follows:                                                    <<09491>>01011000
                                                               <<09491>>01705400
  Contiguous blocks may be written by any program  running  in <<09491>>01705800
privileged mode. A carriage-control (CCTL) code of %1001 tells <<09491>>01706200
SDISC to start a contiguous block, while a CCTL of %2001  ends <<09491>>01706600
it. A CCTL of %1001 while already in a contiguous block closes <<09491>>01707000
that block and opens another.  A CCTL of %2001 without an ear- <<09491>>01707400
lier %1001 is an error. While in the contiguous block, no spe- <<09491>>01707800
cial CCTL codes are needed. In practice, SYSDUMP and its cous- <<09491>>01708200
ins SDUP and TPSTOMP are the only programs which use this fea- <<09491>>01708600
ture, because they all write bootstrap  channel  programs  re- <<09491>>01709000
quired for cold loading.                                       <<09491>>01709400
  Starting with MPEV/E, holes are obsolete except when encoun- <<09491>>01720100
tered on pre-MPEV/E serial discs.  Eliminating the  hole  data <<09491>>01720200
structure  forced  an SDISC version change, which is described <<09491>>01720300
more fully in the comments for  procedure  SDISC'FINDGAP.  The <<09491>>01720400
discussion of holes below has been left in for historical pur- <<09491>>01720500
poses.                                                         <<09491>>01720600
HP9895.  The CTAPE and its physical driver automatically  deal <<09491>>01755000
physically contiguous on the disc.  Holes are generated  auto- <<09491>>01855000
matically by SDISC whenever required.                          <<09491>>01860000
$EDIT VOID=01910000                                            <<09491>>01865000
         Device           Number of sectors (or CTAPE blocks)  <<09491>>01970000
         HP7935           250                                  <<09491>>01995000
         HP9110/9144      4 blocks (Small cart), 15 (Large)    <<09491>>02005000
because the Gap Table is a sector (or CTAPE block) address ta- <<09491>>02100000
  The HP7933/7935 is an exception.  With 404 Mbytes of storage <<09491>>02165000
it  is so large that the Gap Table called for by the above ra- <<09491>>02170000
tio requires 355 sectors, or 45.4 Kwords.  This is  more  than <<09491>>02175000
the  largest  MPE  data segment can hold (32,764 words).  Time <<09491>>02180000
constraints on the current release prevented implementation of <<09491>>02185000
a paging scheme or multiple extra data segments,  so  the  Gap <<09491>>02190000
Table  length  has been arbitrarily set to 32,000 words.  This <<09491>>02195000
allows for the other storage which must also live in the  data <<09491>>02200000
segment. This means the early warning mentioned above will oc- <<09491>>02205000
cur when the HP7933/7935 is about 70% full (assuming the magic <<09491>>02210000
69.44 sectors/Gap Table entry ratio).                          <<09491>>02215000
    the  "defect"  was  encountered.  Obsolete  starting  with <<09491>>02430000
    MPEV/E.                                                    <<09491>>02431000
    hole type, or else procedure SDISCFINDGAP will  not  work. <<09491>>02450000
    Obsolete starting with MPEV/E.                             <<09491>>02451000
$PAGE                                                          <<09491>>02452000
$EDIT VOID=02490000                                            <<09491>>02490000
$EDIT VOID=02675000                                            <<09491>>02580000
have the user support a 32K Gap Table  (for  a  7935)  on  his <<09491>>02720000
stack.  (SDISC allocates two additional extra data segments as <<09491>>02725000
data buffers.  These are described in the next section).       <<09491>>02726000
  In addition to the Gap Table already described, the XDS con- <<09491>>02790000
tains SDISC's global storage area, a  data  buffer  management <<09491>>02795000
(control block) area called BUFFER'INFO, and a one CTAPE block <<09491>>02800000
buffer (called WORKTABLE) which holds the contents of the ser- <<09562>>02805000
ial disc label sector (or block) when SDISC updates the serial <<09562>>02810000
disc version or when it reads the label in as part of its self <<09562>>02815000
configuration. The latter function is done in GPTMOD, function <<09562>>02820000
2 (NEW'VOLUME), and further comments may be found there. WORK- <<09562>>02825000
TABLE also holds the Defective Track Table (MAC discs) or  De- <<09562>>02826000
fective  Sector  Table  (CS80 discs) while assigning alternate <<09562>>02827000
tracks.                                                        <<09562>>02828000
  The three arrays in the XDS (WORKTABLE, BUFFER'INFO and  GPT <<09491>>02830000
(Gap Table) are all dynamically configured by SDISC as vanilla <<09491>>02835000
indirect arrays, such as might have been constructed  by  SPL. <<09491>>02840000
This  is  done  by declaring the array names as pointers, then <<09491>>02845000
inserting appropriately computed element-0 addresses in  them. <<09491>>02850000
The  pointers  used to reside immediately after XMITLOG, which <<09491>>02855000
was the last simple variable declared. The first condition was <<09491>>02860000
a holdover from when we actually used fixed length arrays con- <<09491>>02865000
structed by SPL. With the present scheme the pointers may live <<09491>>02870000
anywhere in the XDS, but XMITLOG must still be the last varia- <<09491>>02875000
ble so that we know where "secondary DB" starts  for  the  ar- <<09491>>02880000
rays.                                                          <<09491>>02885000
  Once the size of the Gap Table (GPTLEN) has been calculated, <<09491>>02886000
the unused segment area is returned to MPE via an  ALTDSEGSIZE <<09491>>02887000
call.  This helps the memory manager in minimum memory systems <<09491>>02888000
by reducing SDISC's working set.                               <<09491>>02889000
$PAGE                                                          <<09491>>02890000
    +-------------------+   These sixteen words are  reserved  <<09562>>02905000
  1 | SECTORSPERTRAK    |   LOCATE only stuffs the last nine   <<09562>>02920000
$EDIT VOID=02960000                                            <<09491>>02955000
  9 | FATALERROR        |   Disables SDISC permanently when    <<09491>>03010000
    |. . . . . . . . . .|     TRUE.                            <<09491>>03015000
 10 | VOLUME'FATAL      |   If TRUE, disables SDISC until a    <<09491>>03020000
$EDIT VOID=03030000                                            <<09491>>03025000
    |. . . . . . . . . .|     new volume is mounted.           <<09491>>03035000
    |. . . . . . . . . .|     check that it's big enough.      <<09562>>03041000
 12 | Owner PIN         | \                                    <<09562>>03042000
    |. . . . . . . . . .|  \                                   <<09562>>03043000
 13 | HEAD pointer      |   \                                  <<09562>>03044000
    |. . . . . . . . . .|    Collectively, XDS'LOCK,  the  OB- <<09562>>03045000
 14 | TAIL pointer      |    TAIN/RELEASE data structure.      <<09562>>03046000
    |. . . . . . . . . .|   /                                  <<09562>>03047000
 15 | Queue length      |  /                                   <<09562>>03048000
    +-------------------+ /                                    <<09562>>03049000
    |                   |                                      <<09491>>03070000
    |     WORKTABLE     |   Length is MAX'SECTOR'SIZE.         <<09491>>03075000
    |                   |                                      <<09491>>03080000
$EDIT VOID=03110000                                            <<09491>>03085000
    |                   |                                      <<09491>>03120000
    |    BUFFER'INFO    |   Length is MAX'NUM'BUFFERS *        <<09491>>03125000
    |                   |     INFO'ENTRY'SIZE.                 <<09491>>03130000
$EDIT VOID=03150000                                            <<09491>>03135000
    |                   |   Length is GPTLEN, which is calcu-  <<09491>>03160000
    |                   |     lated as (STARTADDRESS -         <<09491>>03165000
    |  GPT (Gap Table)  |     GPTBASESECTOR) * WORDSPERSECTR.  <<09491>>03170000
    |                   |     Currently GPTBASESECTOR is       <<09491>>03175000
    |                   |     EQUATEd to 4.                    <<09491>>03180000
$EDIT VOID=03200000                                            <<09491>>03185000
$PAGE                                                          <<09491>>03205010
  Data structures -- data buffers and BUFFER'INFO area:        <<09491>>03205020
                                                               <<09491>>03205030
  To improve performance, SDISC maintains and manages two  ex- <<09491>>03205040
tra  data  segments  used as alternating data buffers.  One is <<09491>>03205050
available to SDISC's caller for logical I/O while the other is <<09491>>03205060
used by the device for physical I/O.  These are in addition to <<09491>>03205070
any File System buffers which might also be in use.            <<09491>>03205080
  Using a write operation as an example, if  a  logical  write <<09491>>03205090
request fills one buffer, SDISC generates a physical write re- <<09491>>03205100
quest to post that buffer to the device.  If a previous physi- <<09491>>03205110
cal write request using the other buffer has completed,  SDISC <<09491>>03205120
switches buffers so that the caller may continue writing while <<09491>>03205130
the newly filled buffer is being written to the  device.  Per- <<09491>>03205140
formance is thus limited by whichever is slower: the device or <<09491>>03205150
the caller.  A similar algorithm is used for reading.          <<09491>>03205160
  The most prevalent mode of access is serial, so we have  not <<09491>>03205170
designed a full-blown buffer (or cache) mechanism. That is, we <<09491>>03205180
check only that the subsequent buffer  logically  follows  the <<09491>>03205190
current  one.  If  this check fails, access is something other <<09491>>03205200
than serial and we abandon any data we might have  pre-accumu- <<09491>>03205210
lated.  Note  that this cannot happen during a write operation <<09491>>03205220
without terminating the operation. When a write operation ter- <<09491>>03205230
minates, either by a backspace or  rewind  operation  (nothing <<09491>>03205240
else  is  allowed and the File System guarantees that the last <<09491>>03205250
thing written is a File Mark), SDISC posts whatever data is in <<09491>>03205260
the current buffer to the device.                              <<09491>>03205270
  Any I/O to the Gap Table, Defective Track/Sector Table or to <<09491>>03205280
the label sector (see the next two sections) is independent of <<09491>>03205290
data I/O and uses different buffers.  Another relevant  detail <<09491>>03205300
is  that  Forward  Space Files do not force a buffer read (al- <<09491>>03205310
though they cause any data already read to be abandoned). Thus <<09491>>03205320
multiple files may be skipped without physical  I/O.  This  is <<09491>>03205330
because  it is only necessary to advance the Gap Table pointer <<09491>>03205340
to the next EOF entry and mark  the  buffer  empty.  Backspace <<09491>>03205350
Files,  on the other hand, do force physical I/O because SDISC <<09491>>03205360
must logically position itself in front of the File Mark,  and <<09491>>03205370
this location is not known without reading the sector contain- <<09491>>03205380
ing the File Mark.                                             <<09491>>03205390
  SDISC tries to acquire two 32K- buffers for  optimal  device <<09491>>03205400
performance (and, for a CTAPE, longest life).  Should these be <<09491>>03205410
unavailable, a graceful degradation as low as one 8 Kword buf- <<09491>>03205420
fer is possible.  Details of this can be found in the comments <<09491>>03205430
for procedure ALLOCATE'BUFFERS.                                <<09491>>03205440
  The two data buffers are managed using information  kept  in <<09491>>03205450
the  BUFFER'INFO  area of the Gap Table extra data segment de- <<09491>>03205460
scribed in the previous section.  Only the lowest level proce- <<09491>>03205470
dures (READ'BUFFER and WRITE'BUFFER) know or care which buffer <<09491>>03205480
is presently doing what. The BUFFER'INFO declarations are such <<09491>>03205490
that other procedures are always talking to the proper buffer. <<09491>>03205500
$PAGE                                                          <<09491>>03205510
  The BUFFER'INFO area consists of MAX'NUM'BUFFERS  (currently <<09491>>03205520
two) control blocks, each of which looks like this:            <<09491>>03205530
                                                               <<09491>>03205540
     0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15            <<09491>>03205550
   +--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--+           <<09491>>03205560
  0|                 DATABUF'IOQX                  |           <<09491>>03205570
   +-----+--------------------------------+--+--+--+           <<09491>>03205580
  1| Stat|////////////////////////////////|Wr|Us|IO|           <<09491>>03205590
   +-----------------------+--------------+--+--+--+           <<09491>>03205600
  2|///////////////////////| Specific Stat|GenlStat|           <<09491>>03205610
   +-----------------------+--------------+--------+           <<09491>>03205620
  3|              DATABUF'ATTIO'TLOG               |           <<09491>>03205630
   +-----------------------------------------------+           <<09491>>03205640
  4|                 DATABUF'DST                   |           <<09491>>03205650
   +-----------------------------------------------+           <<09491>>03205660
  5|             DATABUF'WORDS'IN'BUF              |           <<09491>>03205670
   +-----------------------------------------------+           <<09491>>03205680
  6|                                               |           <<09491>>03205690
   |                 DATABUFD'SA                   |           <<09491>>03205700
  7|                                               |           <<09491>>03205710
   +-----------------------------------------------+           <<09491>>03205720
                                                               <<09491>>03205730
Discussion:                                                    <<09491>>03205740
  Word 0        -- When doing NOWAIT I/O,  P'ATTACHIO  returns <<09491>>03205750
                   the  IOQ  or  DRQ index, stored here, to be <<09491>>03205760
                   used in a subsequent WAITFORIO call.        <<09491>>03205770
  Word 1.( 0:2) -- DATABUF'STATUS, the acquisition status of a <<09491>>03205780
                   data buffer extra data segment:             <<09491>>03205790
                   0 -- Not allocated.                         <<09491>>03205800
                   1 -- Allocated, but not locked or frozen.   <<09491>>03205810
                   2 -- Allocated and locked in memory.        <<09491>>03205820
                   3 -- Allocated, locked and frozen.          <<09491>>03205830
  Word 1.(13:1) -- DATABUF'WRITE. If TRUE, this buffer is dir- <<09491>>03205840
                   ty (in use for writing and not empty).      <<09491>>03205850
  Word 1.(14:1) -- DATABUF'IN'USE.  If TRUE, this buffer is in <<09491>>03205860
                   use (contains valid data).                  <<09491>>03205870
  Word 1.(15:1) -- DATABUF'DOING'IO.  If TRUE, we have started <<09491>>03205880
                   a NOWAIT I/O with P'ATTACHIO, but have  not <<09491>>03205890
                   yet finished it with WAITFORIO.             <<09491>>03205900
  Words 2 and 3 -- The functional result of the last P'ATTACH- <<09491>>03205910
                   IO call using this buffer.                  <<09491>>03205920
  Word 4        -- The DST number of this buffer data segment. <<09491>>03205930
  Word 5        -- The number of valid words  in  the  buffer. <<09491>>03205940
                   Usually  the same as the buffer length, but <<09491>>03205950
                   may be less for partial reads or writes.    <<09491>>03205960
  Words 6 and 7 -- The disc address corresponding to  data  at <<09491>>03205970
                   the start of the buffer.  For writes, tells <<09491>>03205980
                   P'ATTACHIO where to put it on the disc. For <<09491>>03205990
                   pre-reads, checks for serial  access  [that <<09491>>03206000
                   is,  RECBUFFSA  (where  the  rest  of SDISC <<09491>>03206010
                   thinks it is) = DATABUFD'SA (where the data <<09491>>03206020
                   really came from)].                         <<09491>>03206030
    | Dfctv Trk/Sct Tbl |   1                                  <<09491>>03250000
    +-------------------+                                      <<09491>>03255000
  6 |0|0|1|/////|   TYPE    |Media* |   6   Bit 0 = 1 ==>      <<09491>>03495000
 14 |      "I"      |      "S"      |  12   |    "SERDISC0"    <<09491>>03555000
 15 |      "C"      |      "0"      |  13 /                    <<09491>>03565000
                                                               <<09491>>03655100
* The "media" type, a hastily-coined attribute, is really  the <<09491>>03655200
  device  subtype -EXCEPT- for cartridge tapes for which it is <<09491>>03655300
  always 0, the subtype of the HP9110. This is for compatibil- <<09491>>03655400
  ity.  The HP9110 (subtype 0)  was  introduced  with  release <<09491>>03655500
  C.00.08,  the HP9144 with G.01.00, but cartridges are inter- <<09491>>03655600
  changeable between the two devices.  SDISC software  between <<09491>>03655700
  the two releases would not know how to deal with a subtype 3 <<09491>>03655800
  so subtype 0 has been forced for all cartridge tape labels.  <<09491>>03655900
DUMP, TPSTOMP, and other such utilities which generate a cold- <<09491>>03680000
loadable "tape". It scans the Gap Table and returns the start- <<09491>>03685000
ing disc address and the length of the contiguous block  whose <<09491>>03690000
ordinal  position is passed in.  Since it does return informa- <<09491>>03695000
tion (reference parameters), it must be called with DB at  the <<09491>>03700000
stack, although it operates in split-stack.                    <<09491>>03705000
  SYSDUMP, et al, must know the starting address of  the  con- <<09491>>03710000
tiguous blocks the cold-load channel program is to read. FIND- <<09491>>03715000
SDISCGAP removes the need for SYSDUMP to keep track  of  these <<09491>>03720000
addresses  while  it  is writing the blocks.  When SYSDUMP has <<09491>>03725000
written all the necessary blocks, it  calls  FINDSDISCGAP  re- <<09491>>03730000
peatedly  until  it  has determined all of their locations and <<09491>>03735000
lengths.  It then stuffs this information in the various parts <<09491>>03740000
of the channel program that require it.                        <<09491>>03745000
$EDIT VOID=03765000                                            <<09491>>03750000
       MESS304   =  304,  << LDEV \ GENERAL I/O STATUS...   >> <<09474>>04176000
       RETN'BUFS  = 10,   << Deallocate SDISC data buffers. >> <<09474>>04296000
       PRIV'WRITE'EOD  = %3001,   << Flush Gap Table with   >> <<u2249>>04390000
       SPEC'WRITE'EOD  = %4001;   << Same as %3001 but only >> <<u2249>>04391000
                                  <<   called by REELSWITCH.>> <<u2249>>04392000
   ATTIO'EOF      =   2, << General status = EOF.           >> <<09474>>04431000
   ATTIO'OK       =   1, << General status = No Error.      >> <<09474>>04432000
   MERLIN         =   6, << MERLIN subtype in CS80 type.    >> <<m2249>>04446000
   DEVICE'PFAIL   =%213, << ATTACHIO completion status.     >> <<09474>>04461000
   EXTERNAL'ABORT = %33, << ATTACHIO completion status.     >> <<09474>>04477000
   MAX'PFAIL'TRIES=   4,                                       <<09576>>04511000
   NONFATAL       = 100, << + SDERR = nonfatal error.       >> <<09474>>04518000
   SYSTEM'PFAIL   = %63, << ATTACHIO completion status.     >> <<09474>>04521000
   USERLOGGING'DATASEG'SIZE = 6144, << User Logging Data    >> <<u2249>>04522000
                         << Segment Size needed to be able  >> <<u2249>>04523000
                         << to do power fail recovery.      >> <<u2249>>04524000
                                 LOR SUBTYPE = BUFFALO         <<m2249>>04560000
                                 LOR SUBTYPE = MERLIN)#,       <<m2249>>04560100
       BUF'MER'DRIVE    = TYPE = CS80 LAND (SUBTYPE = BUFFALO  <<u2249>>04561000
                                 LOR SUBTYPE = MERLIN)#,       <<m2249>>04562000
       NO'ATIOERROR     = [16/ATTIO'OK, 16/0]D#,               <<09474>>04575000
                             NOT VOLUME'FATAL)#,               <<09474>>04590000
$PAGE                                                          <<09474>>04857000
                                                               <<09474>>04875000
      SDERR26=26, << Not a serial disc.                     >> <<S9203>>05070000
      SDERR34=34, << Not enough memory for data buffers.    >> <<S9203>>05110000
      SDERR39=39, << Request aborted externally.            >> <<09556>>05135000
      SDERR41=41, << System or device powerfail.            >> <<09556>>05145000
  INITARRAYSIZE = 17;   << Number of elements reserved for  >> <<u2249>>05210000
       IAS8=IAS+8;                                             <<09562>>05265000
$EDIT VOID=05275000                                            <<09562>>05270000
INTEGER ARRAY DBHOLD(0:IAS8) = DB;                             <<09562>>05305000
        FATALERROR=DB+9,      << Disables all  SDISC  func- >> <<09474>>05405000
                              << tions  except  Rewind, De- >> <<09474>>05406000
                              << vice Close, etc. (to allow >> <<09474>>05407000
                              << unloading).                >> <<09474>>05410000
        VOLUME'FATAL=DB+10,   << Similar to FATALERROR, ex- >> <<09474>>05415000
                              << cept is cleared when  vol- >> <<09474>>05416000
                              << ume is unloaded (if FATAL- >> <<09474>>05417000
                              << ERROR not set).  Used  for >> <<09474>>05418000
                              << media-related errors.      >> <<09474>>05420000
        NON'VOL'SPECIFIC'FLAGS=DB+11, <<Overall Sdisc flags.>> <<u2249>>05421000
        MAX'DSEG'SIZE = DB+12;   << Set by ALLOCATE, used   >> <<u2249>>05425000
                                                               <<09562>>05430100
LOGICAL ARRAY                                                  <<09562>>05430200
   XDS'LOCK(*) = DB+13;       << through DB+16.  Four  word >> <<u2249>>05430300
                              << data structure used by OB- >> <<09562>>05430400
                              << TAIN and RELEASE. See com- >> <<09562>>05430500
                              << ments at front of module.  >> <<09562>>05430600
DEFINE                                                         <<u2249>>05431000
   USER'LOGGING      = NON'VOL'SPECIFIC'FLAGS.(14:1) #;        <<u2249>>05433000
$EDIT VOID=05660000                                            <<09474>>05660000
   FATAL             = SDISC'FLAGS.( 5:1) #,                   <<09474>>05667000
   TAPEWRITTEN       = SDISC'FLAGS.( 6:1) #,                   <<09474>>05685000
   VOL'FATAL         = SDISC'FLAGS.( 4:1) #;                   <<09474>>05688000
   PFAIL'TRIES,         << Count of PFAIL (re)tries.        >> <<09576>>05876000
                                                               <<09556>>06535100
DEFINE                                                         <<09556>>06535200
   VLAB'SCRATCH'BIT = VLAB'TYPE'SUBTYPE).(0:1 #;               <<09556>>06535300
                                                               <<09474>>07150100
INTEGER PROCEDURE ALTDSEGSIZE (DST, SIZE);                     <<09474>>07150200
   VALUE   DST, SIZE;                                          <<09474>>07150300
   INTEGER DST, SIZE;                                          <<09474>>07150400
                                                               <<09474>>07150500
COMMENT --                                                     <<09474>>07150600
  Changes the size of segment DSEG by SIZE  words  (+  or  -). <<09474>>07150700
Fails  if  you would exceed the maximum size of the segment or <<09474>>07150800
if the segment is locked or frozen in memory.  The new size of <<09474>>07150900
the segment is returned in the result.                         <<09474>>07151000
;                                                              <<09474>>07151100
   OPTION PRIVILEGED, UNCALLABLE, EXTERNAL;                    <<09474>>07151200
                                                               <<09562>>07151300
INTEGER PROCEDURE OBTAIN (RESOURCE, ALT'RES);                  <<09562>>07151400
   VALUE                  RESOURCE, ALT'RES;                   <<09562>>07151500
   LOGICAL POINTER        RESOURCE;                            <<09562>>07151600
   LOGICAL                          ALT'RES;                   <<09562>>07151700
COMMENT --                                                     <<09562>>07151800
  Controls access to RESOURCE via PCB links.  If  RESOURCE  is <<09562>>07151900
unavailable,  queues  requesting PIN, optionally releasing AL- <<09562>>07152000
Ternate'RESource.  SDISC does not use ALT'RES.                 <<09562>>07152100
** NOTE ** NOTE ** NOTE ** NOTE ** NOTE ** NOTE ** NOTE ****** <<09562>>07152200
  In OBTAIN, ALT'RES is declared as a LOGICAL POINTER,  but  a <<09562>>07152300
parameter  value of -1 is required to specify no alternate re- <<09562>>07152400
source.  It is declared type LOGICAL here to be able to pass a <<09562>>07152500
-1 without causing SPL to generate a warning.                  <<09562>>07152600
;                                                              <<09562>>07152700
   OPTION PRIVILEGED, UNCALLABLE, EXTERNAL;                    <<09562>>07152800
$PAGE                                                                   07152900
PROCEDURE RELEASE (RESOURCE, ALT'RES, WAKEUP);                 <<09562>>07153000
   VALUE           RESOURCE, ALT'RES, WAKEUP;                  <<09562>>07153100
   LOGICAL POINTER RESOURCE;                                   <<09562>>07153200
   LOGICAL                   ALT'RES, WAKEUP;                  <<09562>>07153300
COMMENT --                                                     <<09562>>07153400
  Converse of OBTAIN, RELEASEs RESOURCE from  use  by  current <<09562>>07153500
PIN, optionally queueing PIN on ALTernate'RESource. SDISC does <<09562>>07153600
not use ALT'RES.  If WAKEUP is TRUE, wakes the  first  process <<09562>>07153700
queued on RESOURCE and massages queue appropriately. If WAKEUP <<09562>>07153800
is FALSE, wakes all processes queued on  RESOURCE.  WAKEUP  is <<09562>>07153900
TRUE for SDISC.  ** NOTE ** of OBTAIN applies here too.        <<09562>>07154000
;                                                              <<09562>>07154100
   OPTION PRIVILEGED, UNCALLABLE, EXTERNAL;                    <<09562>>07154200
$PAGE " SDISC - ERROR SETTING ROUTINES"                        <<09474>>07282500
INTEGER PROCEDURE SET'FATAL (SDNUM);                           <<09474>>07282510
VALUE   SDNUM;                                                 <<09474>>07282520
INTEGER SDNUM;                                                 <<09474>>07282530
OPTION  PRIVILEGED, UNCALLABLE, INTERNAL;                      <<09474>>07282540
                                                               <<09474>>07282550
BEGIN                                                          <<09474>>07282560
  COMMENT -- Sets FATAL and VOL'FATAL to indicate fatal error. <<09474>>07282570
Alternate entry point SET'VOL'FATAL only sets VOL'FATAL, while <<09474>>07282580
alternate entry point SET'NONFATAL  adds  100  to  a  positive <<09474>>07282590
parameter and doesn't change a negative one.  The comments for <<09474>>07282600
the SDERR declarations in the Global Declarations section  ex- <<09474>>07282610
plain the difference between positive (>100) and negative non- <<09474>>07282620
fatal error codes.                                             <<09474>>07282630
;                                                              <<09474>>07282640
ENTRY                                                          <<09474>>07282650
   SET'VOL'FATAL,                                              <<09474>>07282660
   SET'NONFATAL;                                               <<09474>>07282670
                                                               <<09474>>07282680
LOGICAL                                                        <<09474>>07282690
   NF'FLAG := FALSE;   << Set TRUE for SET'NONFATAL entry.  >> <<09474>>07282700
                                                               <<09474>>07282710
INTEGER                                                        <<09474>>07282720
   RESULT = SET'FATAL;                                         <<09474>>07282730
                                                               <<09474>>07282740
FATAL := TRUE;                                                 <<09474>>07282750
                                                               <<09474>>07282760
SET'VOL'FATAL:                                                 <<09474>>07282770
                                                               <<09474>>07282780
VOL'FATAL := TRUE;                                             <<09474>>07282790
IF FALSE THEN                                                  <<09474>>07282800
                                                               <<09474>>07282810
SET'NONFATAL:                                                  <<09474>>07282820
                                                               <<09474>>07282830
   NF'FLAG := TRUE;                                            <<09474>>07282840
RESULT := SDNUM;                                               <<09474>>07282850
IF NF'FLAG AND RESULT > 0 THEN RESULT := RESULT + NONFATAL;    <<09474>>07282860
SET'FATAL := RESULT;                                           <<09474>>07282870
END;   << SET'FATAL, SET'VOL'FATAL, SET'NONFATAL            >> <<09474>>07282880
$PAGE   "   *** Procedure UNLOAD'CARTRIDGE'TAPE ***"           <<09556>>07283000
PROCEDURE UNLOAD'CARTRIDGE'TAPE;                               <<09556>>07283010
   OPTION PRIVILEGED, UNCALLABLE, INTERNAL;                    <<09556>>07283020
                                                               <<09556>>07283030
BEGIN                                                          <<09556>>07283040
                                                               <<09556>>07283050
DOUBLE                                                         <<09556>>07283060
   DERR;                                                       <<09556>>07283070
                                                               <<09556>>07283080
INTEGER                                                        <<09556>>07283090
   ERR1 = DERR;                                                <<09556>>07283100
                                                               <<09556>>07283110
IF CARTRIDGE'TAPE THEN                                         <<09556>>07283120
   BEGIN   << Physical I/O required.                        >> <<09556>>07283130
   DERR := ATACHIO (LDNUM, QMISC', DSTX, ADDR,                 <<09556>>07283140
           UNLOAD, 0, P1, P2, BLOCKED);                        <<09556>>07283150
   IF ATIOERR THEN                                             <<09556>>07283160
      BEGIN                                                    <<09556>>07283170
      ERRORCODE := SET'VOL'FATAL (SDERR38);                    <<09556>>07283180
      RETURN;                                                  <<09556>>07283190
      END;                                                     <<09556>>07283200
   END;    << Physical I/O required.                        >> <<09556>>07283210
END;       << of UNLOAD'CARTRIDGE'TAPE                      >> <<09556>>07283220
by VINIT ("SERDISC" in the label sector, but no SCRATCH  bit), <<09556>>07350000
we return TRUE. If not, we notify the console and ask if prop- <<09556>>07355000
er media is available.  If so, we go back to sleep and  repeat <<09556>>07360000
all  of  the  above until we have proper media or the operator <<09556>>07365000
responds NO.  If the latter happens, we return FALSE.          <<09556>>07370000
$EDIT VOID=07515000                                            <<S9203>>07505000
2.  When we WAIT in here, put our process' PCB index into Word <<S9203>>07520000
3.  If the Gap Table extra data segment in the LDTX is differ- <<S9203>>07545100
ent from ours, it indicates PVPROC is using  another  copy  of <<S9203>>07545200
SDISC.  Wait  for  it  to  finish.  Acquire the LDT SIR before <<S9203>>07545300
testing to prevent PVPROC from acquiring it until we can stuff <<S9203>>07545400
our PCB index into the LDTX before WAITing on PVPROC.          <<S9203>>07545500
4.  Test the SDLF bit when returning from  an  operator  reply <<S9203>>07550000
(RIT)  wait.  If it's set, then the operator mounted media and <<S9203>>07555000
it came on-line before the operator REPLYed.                   <<S9203>>07560000
$EDIT VOID=07800000                                            <<S9203>>07765000
      SAVE'LDT'SIR := GETSIR (LDT'SIR);                        <<S9203>>07770000
      QXDS := LDTX'SDISC'GPT'XDS;                              <<S9203>>07771000
      IF QXDS <> QDSTN THEN RELSIR (LDT'SIR, SAVE'LDT'SIR);    <<S9203>>07772000
<< Note:  When we're here, we still hold  the  LDT'SIR.  If >> <<S9203>>07820000
<< we're  on-line,  release it and check for a proper label >> <<S9203>>07825000
<< ("SERDISC" in the volume label). If off-line, release it >> <<S9203>>07830000
<< after setting our PCB index into the LDTX so PVPROC will >> <<S9203>>07835000
<< wake us.  Then notify the operator and WAIT  for  a  new >> <<S9203>>07836000
<< volume.                                                  >> <<S9203>>07837000
      RELSIR (LDT'SIR, SAVE'LDT'SIR)                           <<S9203>>07850000
$EDIT VOID=07870000                                            <<S9203>>07865000
<< On-line with a new volume.  Check  that  it's  "SERDISC" >> <<09556>>07935000
<< and not SCRATCHed by VINIT.                              >> <<09556>>07936000
   IF WORKTABLE'B(VLAB'B'LABEL) = "SERDISC" AND                <<09556>>07965000
      NOT WORKTABLE(VLAB'SCRATCH'BIT) THEN                     <<09556>>07966000
   UNLOAD'CARTRIDGE'TAPE;                                      <<09556>>08001000
   IF SDERR THEN RETURN;                                       <<09556>>08002000
           REPLY'YESNO, @QREPLY);                              <<S9203>>08020000
$PAGE " *** Procedure DISPLAY'STATUS *** "                     <<09474>>08180100
PROCEDURE DISPLAY'STATUS(LDNUM,STATUS);                        <<09474>>08180200
VALUE   LDNUM, STATUS;                                         <<09474>>08180300
INTEGER LDNUM;                                                 <<09474>>08180400
LOGICAL STATUS;                                                <<09474>>08180500
OPTION  PRIVILEGED, UNCALLABLE, INTERNAL;                      <<09474>>08180600
                                                               <<09474>>08180700
BEGIN                                                          <<09474>>08180800
  COMMENT -- Displays status returned  by  ATTACHIO.  Modifies <<09556>>08180900
ERRORCODE for external abort or system/device powerfail.       <<09556>>08180910
;                                                              <<09474>>08181000
                                                               <<09474>>08181100
LOGICAL QDSTN, QLDNUM;                                         <<09474>>08181200
BYTE ARRAY STATUS'ASC(0:6) = Q;                                <<09474>>08181300
                                                               <<09474>>08181400
QLDNUM := LDNUM;                                               <<09556>>08181500
QDSTN := EXCHANGEDB (STACK);                                   <<09556>>08181600
ASCII (STATUS, 8, STATUS'ASC);                                 <<09556>>08181700
STATUS'ASC(6) := 0;                                            <<09556>>08181900
GENMSG (SET1, MESS304, %10000, QLDNUM, @STATUS'ASC);           <<09556>>08181910
EXCHANGEDB (QDSTN);                                            <<09556>>08181920
IF STATUS = EXTERNAL'ABORT THEN                                <<09556>>08182000
   ERRORCODE := SET'VOL'FATAL (SDERR39);                       <<09556>>08182100
IF STATUS = SYSTEM'PFAIL OR STATUS = DEVICE'PFAIL THEN         <<09556>>08182200
   ERRORCODE := SET'VOL'FATAL (SDERR41);                       <<09556>>08182300
$EDIT VOID=08182800                                            <<09556>>08182400
END;      << of DISPLAY'STATUS                              >> <<09474>>08182900
DOUBLE STATUS;                                                 <<09474>>08227000
LOGICAL ERR1 = STATUS;                                         <<09474>>08228000
INTEGER PCBPT;                                                 <<*2182>>08228010
INTEGER POINTER                                                <<*2182>>08228020
   PCB = SYSPCBINDEX;    << Required by PCB $INCLUDE file >>   <<*2182>>08228030
                                                               <<09576>>08229000
!                                                              <<*2182>>08229010
! IF USER STACK THEN PASS A DST # OF 0 TO P'ATTACHIO.          <<*2182>>08229020
!                                                              <<*2182>>08229030
                                                               <<*2182>>08229040
PCBPT := CURPRC;      << CURRENT PCB >>                        <<*2182>>08229050
IF DSTX = SPCBSTKDST THEN DSTX := 0;                           <<*2182>>08229060
                                                               <<*2182>>08229070
TRY'AGAIN:                                                     <<09576>>08229100
                                                               <<09576>>08229200
STATUS := P'ATTACHIO (LDNUM, QMISC, DSTX, ADDR, FUNC, CNT,     <<09474>>08230000
IF FLAGS = BLOCKED AND ATIOERR THEN                            <<09474>>08236000
   BEGIN                                                       <<09474>>08237000
                                                               <<09576>>08237010
<< Check for system or  device  power  fail.  Either  error >> <<09576>>08237020
<< in  non-write waited (blocked) I/O is retryable -- up to >> <<09576>>08237030
<< a point.                                                 >> <<09576>>08237040
                                                               <<09576>>08237050
   IF ERR1.(8:8) = DEVICE'PFAIL OR                             <<09576>>08237060
      ERR1.(8:8) = SYSTEM'PFAIL THEN                           <<09576>>08237070
      IF (BUF'MER'DRIVE LAND <<retry write on other devs>>     <<u2249>>08237071
        FUNC = WRITE) OR (BUF'MER'DRIVE LAND                   <<u2249>>08237080
        FUNC = WRITE'LABEL) THEN                               <<u2249>>08237081
      ELSE                                                     <<u2249>>08237082
         IF (PFAIL'TRIES := PFAIL'TRIES+1) <= MAX'PFAIL'TRIES  <<09576>>08237090
            THEN GO TRY'AGAIN;                                 <<09576>>08237100
                                                               <<09576>>08237110
<< Not a PFAIL error, or out of retries, if we're here.     >> <<09576>>08237120
                                                               <<09576>>08237130
   DISPLAY'STATUS (LDNUM, ERR1.(8:8));                         <<09474>>08238000
                                                               <<09474>>08238100
<< If BLOCKED callers get an ATIOERR, they will set  ERROR- >> <<09474>>08238200
<< CODE accordingly.  However, if an external abort, system >> <<09474>>08238300
<< powerfail or device powerfail occurs DISPLAY'STATUS will >> <<09474>>08238400
<< set an appropriate ERRORCODE to reflect it.  Since we do >> <<09474>>08238500
<< not want callers to change ERRORCODE,  we  will  pretend >> <<09474>>08238600
<< there is no error.                                       >> <<09474>>08238610
                                                               <<09474>>08238700
   TOS := ERR1.(8:8);                                          <<09474>>08238800
   IF S0 = EXTERNAL'ABORT OR                                   <<09474>>08238810
      S0 = DEVICE'PFAIL   OR                                   <<09474>>08238820
      S0 = SYSTEM'PFAIL   THEN STATUS := NO'ATIOERROR;         <<09474>>08238830
   END;                                                        <<09474>>08238900
IF NOT JUSTALLOCATED THEN PFAIL'TRIES := 0;                    <<09576>>08238910
ATACHIO := STATUS;                                             <<09474>>08239000
   ANY'ERROR := FALSE,                                         <<09474>>08590000
   PRINT'STATUS := FALSE;                                      <<09474>>08593000
         NORMAL'COMPLETION THEN ANY'ERROR := PRINT'STATUS :=   <<09474>>08640000
                                                         TRUE; <<09474>>08643000
         ERRORCODE := SET'VOL'FATAL (SDERR29);                 <<09474>>08765000
         IF PRINT'STATUS THEN                                  <<09474>>08767000
            DISPLAY'STATUS (LDNUM, DATABUF'ATTIO'STATUS);      <<09474>>08768000
ELSE ERRORCODE := SET'FATAL (SDERR26);  << Not serial disc? >> <<09474>>09220000
  The approach in fix 07114 has two problems:                  <<L9108>>09372000
1.  The memory manager is not smart enough to check its  work- <<L9108>>09372100
    ing set.  Thus it may allocate all this real memory at the <<L9108>>09372200
    expense of our stack or other extra  data  segment(s).  In <<L9108>>09372300
    this  case  we  will never be able to run, and will thrash <<L9108>>09372400
    anytime the memory manager tries to schedule us.           <<L9108>>09372500
2.  Even if the memory manager were smart enough,  neither  we <<L9108>>09372600
    nor  it  can  guard against our process trying to allocate <<L9108>>09372700
    additional data segments after we do.                      <<L9108>>09372800
  There is no sure way to avoid the first problem  (except  to <<L9108>>09372900
not lock and freeze the buffers and eat the performance penal- <<L9108>>09373000
ty), so we'll use an unsure one:  For minimum memory (512  Kb) <<L9108>>09373100
systems  we start our buffer allocation at 32 Kb (1/2 the nor- <<L9108>>09373200
mal).  This has been found to work (at least until MPE expands <<L9108>>09373300
again).                                                        <<L9108>>09373400
  Note:  SYSNUMBANKS is the configured number of 128 Kb memory <<L9108>>09373500
banks less 1.                                                  <<L9108>>09373600
data segment (with the exception noted above).  Current values <<L9108>>09400000
are:                                                           <<L9108>>09401000
                               (16384 words for 512Kb systems) <<L9108>>09436000
                               (16384 words for 512Kb systems) <<L9108>>09451000
      (amount by which we      may be smaller, to get us to an <<L9108>>09465000
      reduce size if space     8K boundary).                   <<L9108>>09470000
         ERRORCODE := SET'FATAL (SDERR26);                     <<09474>>09915000
ERRORCODE := SET'FATAL(SDERR34); << At the end of our rope. >> <<09474>>10045000
   ELSE ERRORCODE := SET'FATAL (SDERR26);                      <<09474>>10270000
IF ATIOERR THEN ERRORCODE := SET'VOL'FATAL (SDERR2);           <<09474>>10430000
      ERRORCODE := SET'VOL'FATAL (SDERR33); << Corrupt DTT. >> <<09474>>10840000
                  ERRORCODE := SET'VOL'FATAL (SDERR12);        <<09474>>13040000
                  ERRORCODE := SET'VOL'FATAL (SDERR12);        <<09474>>13105000
                  ERRORCODE := SET'VOL'FATAL (SDERR12);        <<09474>>13155000
      IF ATIOERR THEN ERRORCODE := SET'VOL'FATAL (SDERR8);     <<09474>>13220000
   ERRORCODE := SET'VOL'FATAL (SDERR33); << Corrupt DTT.    >> <<09474>>13240000
      ERRORCODE := SET'VOL'FATAL (SDERR33); << Corrupt DSCT >> <<09474>>13650000
               ERRORCODE := SET'VOL'FATAL (SDERR12);           <<09474>>14455000
         IF ATIOERR THEN ERRORCODE := SET'VOL'FATAL (SDERR8);  <<09474>>14545000
   ERRORCODE := SET'VOL'FATAL (SDERR33);   << Corrupt DSCT. >> <<09474>>14570000
         ERRORCODE := SET'VOL'FATAL (SDERR12);                 <<09474>>14925000
   ERRORCODE := SET'VOL'FATAL(SDERR6);<<ERR reading DTT/DSCT>> <<09474>>14995000
  INTEGER ERR1 = DERR, BLOCKNUMBER, BLOCK, I, TEMP,LPDT'INDEX; <<u2249>>15405000
      IF CARTRIDGE'TAPE THEN                                   <<u2249>>15710100
         BEGIN  << Need to know if Linus or Buffalo drive.  >> <<u2249>>15710200
         LPDT'INDEX := LDNUM * SIZE'OF'LPDT'ENTRY;             <<u2249>>15710300
         SUBTYPE := LPDT'SUBTYPE;                              <<u2249>>15710400
         END;                                                  <<u2249>>15710500
      TEMP := INTEGER (MAX'DSEG'SIZE) - @GPT - GPTLEN;         <<09474>>15811000
      IF TEMP < 0 THEN                                         <<09474>>15815000
         BEGIN   << Gap Table too small, try to expand it.  >> <<01193>>15820000
         MAX'DSEG'SIZE := ALTDSEGSIZE (DSTN, -TEMP);           <<01193>>15821000
         IF <> THEN                                            <<01193>>15822000
            BEGIN   << Couldn't expand it, can't continue.  >> <<01193>>15823000
            ERRORCODE := SET'FATAL (SDERR36);                  <<01193>>15825000
            RETURN;                                            <<01193>>15830000
            END;    << Couldn't expand it, can't continue.  >> <<01193>>15835000
         END     << Gap Table too small, try to expand it.  >> <<01193>>15835100
      ELSE IF TEMP > 0 THEN                                    <<01193>>15835200
                                                               <<09474>>15836000
<< Give back whatever DSTN we don't need.                   >> <<09474>>15837000
                                                               <<09474>>15838000
         MAX'DSEG'SIZE := ALTDSEGSIZE (DSTN, -TEMP);           <<01193>>15839000
         ERRORCODE := SET'VOL'FATAL (SDERR13);                 <<09474>>15875000
         ERRORCODE := SET'FATAL (SDERR43);                     <<09474>>15980000
         ERRORCODE := SET'VOL'FATAL (SDERR18);                 <<09474>>16010000
        ERRORCODE := SET'VOL'FATAL (SDERR15);                  <<09474>>16110000
         ERRORCODE := SET'FATAL (SDERR19);                     <<09474>>16165000
         ERRORCODE := SET'VOL'FATAL (SDERR28);                 <<09474>>16455000
      IF CURRENTGPTENT = GPT'START THEN UPDATE'SDISC'VERSION;  <<01192>>16621000
         IF TAPEWRITTEN THEN                                   <<09474>>16875000
            ERRORCODE := SET'NONFATAL (-SDERR5);               <<09474>>16876000
LOGICAL SUBROUTINE PFAIL'RECOVER;                              <<09576>>20095100
                                                               <<09576>>20095200
BEGIN COMMENT --                                               <<09576>>20095300
  PFAIL'RECOVER is called  from  WAIT'FOR'COMPLETION  if  that <<09576>>20095400
subroutine gets a system or  device  power  fail  status  from <<09576>>20095500
WAITFORIO.  We  retry  the  operation by doing another ATACHIO <<09576>>20095600
(this one blocked, or with wait). Since it is blocked, ATACHIO <<09576>>20095700
will handle additional pfail retries up to the SDISC limit.    <<09576>>20095800
  Because ATACHIO hides blocked pfail status from its callers, <<09576>>20095900
we must check ERRORCODE to return the proper result.           <<09576>>20096000
                                                               <<09576>>20096100
Output:  TRUE if the I/O completed successfully when retried.  <<09576>>20096200
         FALSE if other error while trying or too many pfails. <<09576>>20096300
;                                                              <<09576>>20096400
PFAIL'RECOVER := FALSE;   << Just in case.                  >> <<09576>>20096500
PFAIL'TRIES := 1;   << We've already done it once.          >> <<09576>>20096600
DATABUFD'ATTIO'RETURN := ATACHIO (LDNUM, QMISC', DATABUF'DST,  <<09576>>20096700
   0, READ, DATABUF'WORDS'IN'BUF, DATABUF'SA0, DATABUF'SA1,    <<09576>>20096800
   BLOCKED);                                                   <<09576>>20096900
IF DATABUF'ATTIO'GENL'STATUS = NORMAL'COMPLETION THEN          <<09576>>20097000
   IF ERRORCODE <> SDERR41 THEN PFAIL'RECOVER := TRUE;         <<09576>>20097100
END;   << of PFAIL'RECOVER.                                 >> <<09576>>20097200
$PAGE                                                          <<09576>>20097300
current  buffer  is  DOING'IO.  Any I/O error except system or <<09576>>20115000
device power fail is reported via SDERR32.  Power fail  errors <<09576>>20120000
are  retried  (with wait) up to three times.  If the buffer is <<09576>>20125000
not doing I/O, it should be. The only reason it can't be is if <<09576>>20130000
WORD'COUNT was 0, so START'IO didn't start the I/O.  If THAT's <<09576>>20135000
so, we've been asked to return data from beyond  EODSECTR,  so <<09576>>20140000
we return SDERR27 (Tape Runaway) instead.                      <<09576>>20141000
      BEGIN   << Error of some kind.                        >> <<09576>>20167000
      IF DATABUF'ATTIO'STATUS = SYSTEM'PFAIL OR                <<09576>>20167100
         DATABUF'ATTIO'STATUS = DEVICE'PFAIL THEN              <<09576>>20167200
         IF PFAIL'RECOVER THEN                                 <<09576>>20167300
            BEGIN   << Successful retry after pfail.        >> <<09576>>20167400
            DATABUF'DOING'IO := FALSE;                         <<09576>>20167500
            RETURN;                                            <<09576>>20167600
            END     << Successful retry after pfail.        >> <<09576>>20167700
         ELSE                                                  <<09576>>20167800
            BEGIN   << Error during retry/out of retries.   >> <<09576>>20167900
            IF ERRORCODE <> SDERR41 THEN                       <<09576>>20168000
               ERRORCODE := SDERR32;                           <<09576>>20168100
            END     << Error during retry/out of retries.   >> <<09576>>20168200
      ELSE                                                     <<09576>>20168300
         BEGIN   << Not a power fail status.                >> <<09576>>20168400
         ERRORCODE := SET'VOL'FATAL (SDERR32);                 <<09576>>20170000
         DISPLAY'STATUS (LDNUM, DATABUF'ATTIO'STATUS);         <<09576>>20171000
         END;    << Not a power fail status.                >> <<09576>>20172000
      END;    << Error of some kind.                        >> <<09576>>20173000
ELSE ERRORCODE := SET'VOL'FATAL (SDERR27);                     <<09474>>20185000
   IF ATIOERR THEN ERRORCODE := SET'VOL'FATAL (SDERR32);       <<09474>>20270000
         ERRORCODE := SET'NONFATAL (SDERR31);                  <<09474>>21035000
   ERRORCODE := SET'NONFATAL (SDERR22)   << Tell file sys-  >> <<09474>>21190000
     << tem that anticipatory read was beyond the physical  >> <<09474>>21193000
     << end of data.                                        >> <<09474>>21195000
   ERRORCODE := SET'NONFATAL (SDERR22);                        <<09474>>22030000
IF FLAGS.SYSBUFRS = 1 AND CNT <> 0 AND NOT NULLTRANSFER THEN   <<09474>>22065000
   ERRORCODE := SET'NONFATAL (SDERR1);                         <<09474>>22075000
   ERRORCODE := SET'NONFATAL (SDERR23);                        <<09474>>22125000
           ERRORCODE := SET'VOL'FATAL (SDERR17);               <<09474>>22325000
   ERRORCODE := SET'VOL'FATAL (SDERR22);                       <<09474>>22490000
         ERRORCODE := SET'NONFATAL (-SDERR30);                 <<09474>>22865000
      ERRORCODE := SET'VOL'FATAL (SDERR40);                    <<09474>>23175000
require jump sparing, inefficient as it is, to  preserve  user <<F9108>>23405000
data if a Gap Table block should require sparing.              <<09576>>23410000
   ERRORCODE := SET'FATAL (SDERR4);                            <<09474>>23660000
      ERRORCODE := SET'VOL'FATAL (SDERR7);                     <<09474>>23700000
            ERRORCODE := SET'VOL'FATAL (SDERR20)               <<09474>>23815000
            ERRORCODE := SET'VOL'FATAL (SDERR21)               <<09474>>23825000
         ELSE ERRORCODE := SET'VOL'FATAL(SDERR29) <<Catchall>> <<09474>>23830000
            THEN ERRORCODE := SET'VOL'FATAL(SDERR16) << R/O >> <<09474>>23855000
            ELSE ERRORCODE := SET'VOL'FATAL (SDERR29);         <<09474>>23860000
      IF ERRORCODE = SDERR29 THEN                              <<09474>>23873000
         DISPLAY'STATUS (LDNUM, DATABUF'ATTIO'STATUS);         <<09474>>23874000
   %4001-SAME AS %3001 BUT CALLED BY REELSWITCH                <<u2249>>23991000
    INTEGER TEMP, TEMP'ADDR, RECLENGTH, COUNT, WCOUNT,         <<u2249>>24055000
            SIZE'DIFF;                                         <<u2249>>24056000
     AND FUNC <> SPEC'WRITE'EOD                                <<u2249>>24246000
  IF FUNC = SPEC'WRITE'EOD AND NOT USER'LOGGING THEN RETURN;   <<u2249>>24251000
  IF FUNC = PRIV'WRITE'EOD OR FUNC = SPEC'WRITE'EOD THEN       <<u2249>>24255000
been  written  to the media (within 32K of all data.  The user <<09491>>24315000
logging facility should recover the remaining  data  from  its <<09491>>24320000
own  buffers).  Without  this  function and its resulting EOD, <<09491>>24325000
EOD on the media would point to the start  of  the  media  and <<09491>>24330000
SDISC would not be able to read beyond it.                     <<09491>>24335000
$EDIT VOID=24340000                                            <<09491>>24340000
  In order to provide for user logging powerfail recovery if   <<u2249>>24411000
there are more than 1 volume, this EOD needs to be written for <<u2249>>24412000
each one.  Since Serial Disc does not know when REELSWITCH is  <<u2249>>24413000
all done with its I/O,  REELSWITCH will need to tell us.  User <<u2249>>24414000
logging doesn't know about reel switches so it can't call us.  <<u2249>>24414100
However, REELSWITCH can be called by other callers other than  <<u2249>>24414200
User Logging and that is why there is the above check before   <<u2249>>24414300
writing that EOD.                                                       24414400
     USER'LOGGING := TRUE;                                     <<u2249>>24416000
     IF BUF'MER'DRIVE AND NOT (FUNC = SPEC'WRITE'EOD) THEN     <<u2249>>24425100
        IF BUFFERS'ALLOCATED THEN                              <<u2249>>24425300
           BEGIN                                               <<u2249>>24425400
           SIZE'DIFF := RECBUFFLEN - USERLOGGING'DATASEG'SIZE; <<u2249>>24425500
           TEMP := CURRENT'BUFFER;                             <<u2249>>24425600
           FOR CURRENT'BUFFER := 0 UNTIL MAX'NUM'BUFFERS - 1 DO<<u2249>>24425700
               ALTDSEGSIZE (DATABUF'DST,-SIZE'DIFF);           <<u2249>>24425800
           CURRENT'BUFFER := TEMP;                             <<u2249>>24425900
           RECBUFFLEN := USERLOGGING'DATASEG'SIZE-1;           <<u2249>>24426000
           END;  << reducing buffers >>                        <<u2249>>24426100
     ERRORCODE := SET'NONFATAL (SDERR1);                       <<09474>>24450000
     ERRORCODE := SET'VOL'FATAL (SDERR37);                     <<09474>>24570000
$EDIT VOID=24905000                                            <<01040>>24885000
         ERRORCODE := SET'FATAL (SDERR9);                      <<09474>>24930000
$EDIT VOID=25010000                                            <<01040>>25010000
    IF CURRENTBUFINDEX > RECBUFFLEN THEN                       <<01040>>25015100
       BEGIN   << Buffer is exactly full.                   >> <<01040>>25015200
       WRITE'BUFFER (CURRENTBUFINDEX);                         <<01040>>25015300
       IF SDERR THEN RETURN;                                   <<01040>>25015400
       END;    << Buffer is exactly full.                   >> <<01040>>25015500
    IF EOTSENSOR = EOTFOUND THEN TIME'TO'WRITE'EOT;            <<01040>>25015600
$PAGE " *** Procedures LOCK'CS80'DEVICE, UNLOCK'CS80'DEVICE ***"        25125000
IF ATIOERR THEN ERRORCODE := SET'VOL'FATAL (SDERR38);          <<09474>>25300000
$PAGE " *** Procedure CTRLSDISC ***"                           <<09491>>25310000
      ERRORCODE := SET'FATAL (SDERR14);   <<1>>                <<09474>>25760000
      ERRORCODE := SET'FATAL (SDERR14);   <<2>>                <<09474>>25765000
      ERRORCODE := SET'FATAL (SDERR14);   <<3>>                <<09474>>25770000
      ERRORCODE := SET'FATAL (SDERR14);   <<4>>                <<09474>>25775000
         ERRORCODE := SET'VOL'FATAL(SDERR37); <<Report error>> <<09474>>25845000
         ERRORCODE := SET'NONFATAL (SDERR22);                  <<09474>>26135000
         ERRORCODE := SET'VOL'FATAL (SDERR27);                 <<09474>>26195000
      EOFCODE := NO'EOF;  << don't report EOF status >>        <<u2249>>26250000
         ERRORCODE := SET'NONFATAL (-SDERR24);                 <<09474>>26375000
<<                                                          >> << 9108>>26543000
<< The two tests below must be performed in the order shown >> << 9108>>26543100
<< to avoid possible buffer data segment underflow (with SF >> << 9108>>26543200
<< 10 in PMBC systems) if the EOF fills the entire sector.  >> << 9108>>26543300
<<                                                          >> << 9108>>26543400
         WHILE CURRENTBUFINDEX >= 0       << Backspace over >> << 9108>>26545000
           AND GETRECBUFF (CURRENTBUFINDEX) = EOF'MARK DO      << 9108>>26550000
      EOFCODE := NO'EOF;  << don't report EOF status >>        <<u2249>>26571000
                                                               <<09576>>26585100
<< This function must execute to completion to ensure  that >> <<09576>>26585200
<< devices are unlocked, etc., and that SDISC is left JUST- >> <<09576>>26585300
<< LOCATED.  That's why this fix removes all SDERR checks.  >> <<09576>>26585400
                                                               <<09576>>26585500
$EDIT VOID=26635000                                            <<09576>>26635000
$EDIT VOID=26645000                                            <<09576>>26645000
$EDIT VOID=26710000                                            <<09576>>26710000
$EDIT VOID=26730000                                            <<09576>>26730000
$EDIT VOID=26780000                                            <<09556>>26735000
         UNLOAD'CARTRIDGE'TAPE;                                <<09556>>26736000
$EDIT VOID=26737000                                            <<09576>>26737000
                                                               <<09474>>26800100
<< The volume is now logically off-line and can  no  longer >> <<09474>>26800200
<< be accessed.  Therefore it is safe to reset VOLUME'FATAL >> <<09474>>26800300
<< now (unless FATALERROR was set, indicating we're  really >> <<09474>>26800400
<< dead.  In  that  case  we leave VOLUME'FATAL set because >> <<09474>>26800500
<< everything is driven by that).                           >> <<09474>>26800600
                                                               <<09474>>26800700
         IF NOT FATALERROR THEN VOL'FATAL := VOLUME'FATAL :=   <<09576>>26803000
            FALSE;                                             <<09576>>26804000
                                                                        26805100
<< In order to succeed in doing powerfail recovery for user  >><<u2249>>26805200
<< logging, we need to reset VOLUME'FATAL after a rewind     >><<u2249>>26805300
<< command is issued by user logging.                        >><<u2249>>26805400
      IF FUNC = REWIND AND NOT FATALERROR THEN                 <<u2249>>26806000
         VOL'FATAL := VOLUME'FATAL := FALSE;                   <<u2249>>26807000
      ERRORCODE := SET'NONFATAL(SDERR14);<<10-GAP not support>><<09474>>26820000
         ERRORCODE := SET'NONFATAL (-SDERR25);                 <<09474>>27100000
                     ERRORCODE := SET'VOL'FATAL (SDERR17);     <<09474>>27335000
            ERRORCODE := SET'FATAL (SDERR23);                  <<09474>>27590000
      ERRORCODE := SET'NONFATAL(SDERR14);<<13-invalid funct.>> <<09474>>27695000
      ERRORCODE := SET'NONFATAL(SDERR14);<<14-invalid funct.>> <<09474>>27705000
$PAGE " *** Procedure CLOSE'DEVICE ***"                        <<09491>>27745000
REW'UNLOAD function of CTRLSDISC.  Setting VOLUME'FATAL  disa- <<09474>>27790000
bles  all  the IF SDERR checks, because this function must run <<09474>>27795000
to completion (that is, we must guarantee to do  our  best  to <<09474>>27800000
unlock any CS80 device, lest a user think a crowbar works bet- <<09474>>27805000
ter).  CLOSE'DEVICE also gives back SDISCs data buffers.    >> <<09474>>27810000
VOLUME'FATAL := TRUE;   << A scam to fool IF SDERR...       >> <<09474>>27820000
VOLUME'FATAL := FALSE;   << So what, we're done anyway.     >> <<09474>>27835000
$PAGE " *** Procedure FINDSDISCGAP ***"                        <<09491>>27850000
ERRORCODE := SET'NONFATAL (SDERR0);                            <<09474>>28180000
$PAGE " *** Procedure SDISCIO ***"                             <<09491>>28340000
BEGIN COMMENT --                                               <<09491>>28375000
  SDISCIO is the outermost procedure of the serial disc inter- <<09491>>28375025
face.  ATTACHIO calls us when it determines that  the  request <<09491>>28375050
is  for  a  serial disc device.  Our interface is identical to <<09491>>28375075
that of ATTACHIO, namely we accept nine parameters of the same <<09491>>28375100
kind and in the same order and return a double result  in  the <<09491>>28375125
same  form as the standard ATTACHIO result.  In fact, ATTACHIO <<09491>>28375150
passes its nine parameters on to us  and  returns  our  result <<09491>>28375175
directly to its caller.                                        <<09491>>28375200
  SDISCIO is a logical driver, appearing to the outside  world <<09491>>28375225
as a tape device while hiding the underlying disc or cartridge <<09491>>28375250
tape below.  Thus ATTACHIO calls contain a parameter structure <<09491>>28375275
consistent with tapes and SDISCIO returns (as much  as  possi- <<09491>>28375300
ble)  completion statuses consistent with tapes.  For example, <<09491>>28375325
function code 7 to a disc would be a status request, but to  a <<09491>>28375350
tape  would  be  Forward  Space  File.  SDISCIO will interpret <<09491>>28375375
function code 7 as the latter.  Also, an I/O error while read- <<09491>>28375400
ing or writing the physical disc device will  be  reported  to <<09491>>28375425
our caller via completion status %74 -- Tape Parity Error.     <<09491>>28375450
  For all the similar outward appearances, there  are  several <<09491>>28375475
differences  in  implementation  which  maintainers  (and some <<09491>>28375500
users) must be aware of:                                       <<09491>>28375525
1.  Tapes are tapes and discs are discs. Tape properties which <<09491>>28375550
    do not exist for discs must be simulated. Thus, load point <<09491>>28375575
    and EOT are known sector or block  addresses,  not  little <<09491>>28375600
    pieces of stuck-on tape.  The End of File mark is a speci- <<09491>>28375625
    fic internal data structure, not  a  unique  data  record. <<09491>>28375650
    And so on.                                                 <<09491>>28375675
2.  Tapes are by  nature  variable  length  media.  When  data <<09491>>28375700
    stops,  that's  the  end  of the record.  Discs have fixed <<09491>>28375725
    length sectors.  When data stops you'd better  be  at  the <<09491>>28375750
    end  of  a  sector or you've wasted the rest of it (unless <<09491>>28375775
    you want to be  very  inefficient  with  read-update-write <<09491>>28375800
    cycles).  To  resolve this basic difference, SDISC buffers <<09491>>28375825
    data in both directions so that users see variable  length <<09491>>28375850
    (or  more  properly, undefined length) records, while data <<09491>>28375875
    on the disc or cartridge tape is compacted to make optimal <<09491>>28375900
    use of its fixed length storage constraints.               <<09491>>28375925
3.  But once you've buffered data you introduce a new  differ- <<09491>>28375950
    ence.  When  ATTACHIO writes to tape, the data is on tape. <<09491>>28375975
    When ATTACHIO calls SDISCIO, the data is in a buffer some- <<09491>>28376000
    where and doesn't hit the disc until the  buffer  is  full <<09491>>28376025
    (or the caller stops writing).  This has serious recovera- <<09491>>28376050
    bility implications if the system or disc should go  down, <<09491>>28376075
    or  even  if  there  is  a  hardware error on the physical <<09491>>28376100
    write.  The physical  write  encompasses  several  logical <<09491>>28376125
    (user)  writes,  and these happened some time in the past. <<09491>>28376150
    Even if we duly report the error, it  will  be  associated <<09491>>28376175
    with  a present logical write and the user has no easy way <<09491>>28376200
    to figure out where the problem is.  This is a basic prob- <<09491>>28376225
    lem whenever buffering is involved, and is only compounded <<09491>>28376250
    by file system buffering and device buffering (such as the <<09491>>28376275
    Immediate Reporting capability  of  the  HP9144  cartridge <<09491>>28376300
    tape drive).                                               <<09491>>28376325
  So much for philosophy.  Now let's talk  implementation  for <<09491>>28376350
awhile.  SDISCIO  is  a procedure, which means that all of its <<09491>>28376375
local variables disappear when we return to  our  caller.  Be- <<09491>>28376400
cause  we  need  to remember things from call to call, and for <<09491>>28376425
other reasons (see the comments at the beginning of this  mod- <<09491>>28376450
ule), we have concocted a "DB" area which is actually an extra <<09491>>28376475
data segment.  This segment is acquired when the  serial  disc <<09491>>28376500
device is allocated to a user, and it is returned when the de- <<09491>>28376525
vice is deallocated.  When we are called, our first job is  to <<09491>>28376550
identify this segment and switch DB to it.                     <<09491>>28376575
  Because we are a procedure we have no permanent storage,  so <<09491>>28376600
this  information must be kept elsewhere.  In this case, it is <<09491>>28376625
in a cell in the Logical Device Table Extension  (LDTX)  entry <<09491>>28376650
for  the  device.  If  somebody goofs and doesn't set the LDTX <<09491>>28376675
entry properly (or if the entry is trashed), we will crash the <<09491>>28376700
system by doing an EXCHANGEDB.  The test for a  positive  DSEG <<09491>>28376725
helps  guard  against  this.  A more thorough test would check <<09491>>28376750
the DSEG number against the maximum possible (in the DST head- <<09491>>28376775
er).  The next better test would check for  existence  of  the <<09491>>28376800
segment, and the best test would verify that the segment is an <<09491>>28376825
SDISC segment.  Historically the present code has  not  proved <<09491>>28376850
to be a problem, so it will probably remain as it is.          <<09491>>28376875
  If for some reason the DSEG test fails, we cannot EXCHANGEDB <<09491>>28376900
and must therefore avoid  referencing  any  SDISC  DB-relative <<09491>>28376925
variables.                                                     <<09562>>28376935
  A special case occurs when more than one process uses  SDISC <<09562>>28376946
with  the same extra data segment.  The most common example is <<09562>>28376947
a :SYSDUMP which later creates a STORE  child  process.  SDISC <<09562>>28376948
is  not  designed  for this kind of concurrent access.  Fortu- <<09562>>28376949
nately SYSDUMP stops calling us before STORE starts,  so  this <<09562>>28376950
results in the desired serial access.                          <<09562>>28376951
  A user who BREAKs and :ABORTs disrupts all this.  STORE han- <<09562>>28376952
dles :ABORT in a special manner, continuing to write until  it <<09562>>28376953
is killed.  However, STORE is not killed until SYSDUMP is ful- <<09562>>28376954
ly quiesced, and quiescing SYSDUMP requires (you  guessed  it) <<09562>>28376955
things  like  writing  EOF's, rewinding, etc., all while STORE <<09562>>28376956
blithely writes away.                                          <<09562>>28376957
  To avoid this, we use the  external  procedures  OBTAIN  and <<09562>>28376958
RELEASE  to  force  callers  into a serial access mode.  These <<09562>>28376959
procedures constitute a locking mechanism on our XDS  resource <<09562>>28376960
which  will queue callers (FIFO) to any depth.  Thus, the cur- <<09562>>28376961
rent two-PIN problem is solved for the general case as well.   <<09562>>28376962
  Because the XDS is our resource, the queueing data structure <<09562>>28376963
(defined by OBTAIN/RELEASE and described in  the  comments  at <<09562>>28376964
the  front  of  this module) must be kept in it.  We therefore <<09562>>28376965
call OBTAIN as soon as DB is switched to the XDS, and  we  RE- <<09562>>28376966
LEASE it just prior to CAN'T'DO'COMMAND.                       <<09562>>28376967
  Note that even though SDISC integrity is preserved, the  me- <<09562>>28376968
dia is subject to out-of-order calls and will probably not end <<09562>>28376969
up in any useable state.  This is acceptable in the BREAK  and <<09562>>28376970
:ABORT  situation  described,  but  applications contemplating <<09562>>28376971
concurrent access -- shouldn't.  It's like opening a  buffered <<09562>>28376972
file  for  Multi-Access, with similar pitfalls.  Read about it <<09562>>28376973
in the File System user documentation.                         <<09562>>28376974
  SDISC is not terribly robust, in that it depends heavily  on <<09491>>28376975
the integrity of its data structures.  For example, a physical <<09491>>28377000
read of the underlying disc device might cause 32000 words  to <<09491>>28377025
be transferred.  If for some reason (say, an I/O error) we got <<09491>>28377050
less than that, we would be unable to continue because buffers <<09491>>28377075
are deblocked into data records using information in the  buf- <<09491>>28377100
fer, and that information might not be there.                  <<09491>>28377125
  Whatever the reason, all except a small number of error con- <<09491>>28377150
ditions cause SDISC to disable itself.  While disabled,  SDISC <<09491>>28377175
will  not  execute any substantive functions (such as, Read or <<09491>>28377200
Write).  We cannot disable all functions, because callers must <<09491>>28377225
be able to Rewind and (for CS80 devices) unlock the devices so <<09491>>28377250
the operator can remove the media.  In addition, SDISC must be <<09491>>28377275
able to return its data buffers to the  system.  Therefore,  a <<09491>>28377300
subset  of functions (FCLOSE, Device Close, Rewind, Rewind and <<09491>>28377325
Unload and the internal (PVPROC) function Deallocate  Buffers) <<09491>>28377350
are  always allowed.  If they are executed while SDISC is dis- <<09491>>28377375
abled (the VOLUME'FATAL flag is set), all  error  returns  are <<09491>>28377400
also disabled so that the functions will always run to comple- <<09491>>28377425
tion.                                                          <<09491>>28377450
  Some errors are media-related (such as an I/O data error, or <<09491>>28377475
an incorrect table structure on a given volume).  Such  errors <<09491>>28377500
disable  SDISC only until a new volume is mounted, then opera- <<09491>>28377525
tion can continue.  Other errors,  mostly  internal  to  SDISC <<09491>>28377550
operation,  should  never happen.  If they do, data and system <<09491>>28377575
integrity cannot be guaranteed if we allow operation  to  con- <<09491>>28377600
tinue.  These errors disable SDISC permanently (except for the <<09491>>28377625
functions described earlier), that is, the caller  can  do  no <<09491>>28377650
more than clean up and deallocate the device.                  <<09491>>28377675
  With all this as a preview, here are the steps we go through <<09491>>28377700
while processing a command:                                    <<09491>>28377725
1.  Find out where DB is (SYSGLOB or a data segment)  and  re- <<09491>>28377750
    member it.                                                 <<09491>>28377775
2.  Extract our extra data segment from our device's LDTX  en- <<09491>>28377800
    try.  If  it is 0 (an error), skip to CAN'T'DO'COMMAND and <<09491>>28377825
    report it.                                                 <<09491>>28377850
3.  If it is > 0, EXCHANGEDB to it and set up to  process  the <<09491>>28377875
    command.  This  consists chiefly of moving the Q-minus pa- <<09491>>28377900
    rameters of SDISCIO to DB (read "XDS") relative  cells  so <<09491>>28377925
    that  the  command  processing  procedures  can find them. <<09491>>28377950
    Note that for consistency  (or  whatever)  the  parameters <<09491>>28377975
    have  the  same  name (such as FUNC) in SDISCIO as for the <<09491>>28378000
    rest of SDISC.  The only difference is that in SDISCIO the <<09491>>28378025
    symbols are local in scope (Q-relative) and supersede  the <<09491>>28378050
    global  (DB-relative)  symbols  used by the rest of SDISC. <<09491>>28378075
    References in SDISCIO to the  DB-relative  cells  use  the <<09491>>28378100
    equivalenced  global array PARMARRAY[index], since the ac- <<09491>>28378125
    tual names refer of course to the Q-relative cells.        <<09491>>28378150
4.  The XDS flag JUSTALLOCATED is pre-loaded to  TRUE  by  the <<09491>>28378175
    external  procedure  ALLOCATE when the XDS is acquired and <<09491>>28378200
    initialized.  It is also set TRUE whenever the Rewind  and <<09491>>28378225
    Unload  function  is executed.  If TRUE, it means that the <<09491>>28378250
    present volume is logically at Load Point, so all relevant <<09491>>28378275
    flags and variables should be set  to  reflect  this.  The <<09491>>28378300
    five  "special"  functions  described earlier need no more <<09491>>28378325
    than this to execute (a volume need not even  be  mounted) <<09491>>28378350
    so  they  are  allowed to proceed, whether or not SDISC is <<09491>>28378375
    disabled.  Since we haven't changed the environment, JUST- <<09491>>28378400
    ALLOCATED remains set.                                     <<09491>>28378425
      Any other function is allowed only if SDISC is not  dis- <<09491>>28378450
    abled.  Before the function can execute, we require that a <<09491>>28378475
    volume be physically mounted (WAITFORDISC) so that we  can <<09491>>28378500
    read its label sector [GPTMOD (NEW'VOLUME)] which contains <<09491>>28378525
    device-specific configuration information.                 <<09491>>28378550
      If neither procedure reports an error,  we're  ready  to <<09491>>28378575
    go,  so  set JUSTALLOCATED to FALSE and LOCK a CS80 device <<09491>>28378600
    to prevent an operator from unloading it while  it  is  in <<09491>>28378625
    use.  (Non-CS80  devices  do  not support this feature, so <<09491>>28378650
    operators are on their own).                               <<09491>>28378675
5.  If JUSTALLOCATED is FALSE at the start of the function  it <<09491>>28378700
    means  we  executed  Step  4 successfully earlier.  Do the <<09491>>28378725
    function unless SDISC is disabled.  Do it anyway if it  is <<09491>>28378750
    one of the five special functions.                         <<09491>>28378775
6.  The function executors are invoked via a CASE statement on <<09491>>28378800
    the low four bits of FUNC (some of the higher  order  bits <<09491>>28378825
    are  used  by  RITESDISC  to control privileged mode write <<09491>>28378850
    operations such as Open/Close Contiguous Block, etc.).     <<09491>>28378875
7.  Upon return from a command executor,  any  error  will  be <<09491>>28378900
    reflected  in  the XDS variable ERRORCODE.  Move it to the <<09491>>28378925
    Q-relative QERRORCODE so all error  processing  (including <<09491>>28378950
    the  "no  XDS"  error) can be done with QERRORCODE.  If no <<09491>>28378975
    error occurred, set appropriate SDISCIO return  status  (1 <<09491>>28379000
    for  normal, %x2 for EOF) and transmission log.  If we had <<09491>>28379025
    an error, it could be non-fatal, fatal for this volume, or <<09491>>28379050
    just plain fatal.  Update the long-term error  flags  from <<09491>>28379075
    the command-specific ones.                                 <<09491>>28379100
8.  A QERRORCODE between 1 and 99 represents a message  number <<09491>>28379125
    in  $SET19 of CATALOG.PUB.SYS, the system message catalog. <<09491>>28379150
    Use GENMSG to display the appropriate message.  DB must be <<09491>>28379175
    at the stack as a stack (that is, not  as  an  extra  data <<09491>>28379200
    segment).  Make  sure  to  EXCHANGEDB  (0), not EXCHANGEDB <<09491>>28379225
    (QUSERSTACK).  They both get you the  same  data  segment, <<09491>>28379250
    but the latter puts DB at the base of the segment.         <<09491>>28379275
      A QERRORCODE outside the 1-99 range does not  display  a <<09491>>28379300
    message.  However, such a QERRORCODE will be translated to <<09491>>28379325
    the 1-99 range so that it can be mapped (via the  associa- <<09491>>28379350
    tive array ERRORS) to an SDISCIO completion status.        <<09491>>28379375
9.  Finally, set DB to where it was at entry, and leave.       <<09491>>28379400
                                                               <<09491>>28379425
  You may be wondering why we have both command-specific (VOL' <<09491>>28379450
FATAL) and long term (VOLUME'FATAL) error flags.  It's a  cart <<09491>>28379475
and  horse problem.  Appropriate error events set the command- <<09491>>28379500
specific flags, while VOLUME'FATAL disables the  SDERR  checks <<09491>>28379525
so  that the five special functions can run to completion.  If <<09491>>28379550
error events set  VOLUME'FATAL,  the  SDERR  checks  following <<09491>>28379575
GPTMOD (NEW'VOLUME), for example, would not detect an error.   <<09491>>28379600
                                                               <<09491>>28379625
  O.K., break's over.  Back to work.                           <<09491>>28379650
;                                                              <<09491>>28379675
EQUATE                                                         <<09562>>28379700
   NO'ALTERNATE'RESOURCE = -1,   << For OBTAIN/RELEASE.     >> <<09562>>28379710
   WAKE'FIRST'WAITER     =  1;   << Ditto.                  >> <<09562>>28379720
                                                               <<09562>>28379730
   LPDT'INDEX,                                                 <<c1602>>28411000
   LDT'INDEX,                                                  <<u2249>>28412000
   PCBPT,                                                      <<u2249>>28415000
   TEMP;                                                       <<u2249>>28416000
       %124,%124, %74, %74,  %4,%124,%124,%124,%124,%124,      <<09474>>28485000
       %164,%154,%103,%124, %73, %73,%124,%103,  %0, %74,      <<09474>>28490000
       %124,%124, %74,%124,%124,%124,%124,%113,%124, %33,      <<09474>>28495000
       %124, %63,  %0,%124,  %0,  %0,  %0,  %0,  %0,  %0;      <<09474>>28500000
$PAGE                                                          <<09491>>28511000
LDT'INDEX := LDNUM * SIZE'OF'LDT'ENTRY;                        <<u2249>>28616000
TEMP := LDT'DEVICE'TYPE;                                       <<c2249>>28621000
$EDIT VOID=28650000                                            <<09474>>28635000
   BEGIN   << Gap Table XDS exists, safe to set up command. >> <<09474>>28655000
   EXCHANGEDB (QDSTN);     << We'll be here for awhile.     >> <<09474>>28656000
   OBTAIN (XDS'LOCK, NO'ALTERNATE'RESOURCE);                   <<09562>>28657000
   VOL'FATAL   := FALSE;                                       <<09491>>28661000
   FATAL       := FALSE;                                       <<09491>>28662000
   XMITLOG := 0;                                               <<09474>>28676000
      BEGIN   << New volume, set variables to load point.   >> <<09474>>28740000
      PFAIL'TRIES := 0;                                        <<09576>>28751000
$PAGE                                                          <<09491>>28755000
<< BACKSPACING, FATAL,  NEXTRECINBUF,  NULLTRANSFER,  TAPE- >> <<09474>>28765000
<< REWOUND, TAPEWRITTEN and VOL'FATAL to False and BOT'SEN- >> <<09474>>28770000
<< SOR and EOTSENSOR to Not Found.  This leaves TAPEREWOUND >> <<09474>>28775000
<< and BOT'SENSOR in the wrong state, so we fix that.       >> <<09474>>28780000
$EDIT VOID=28810000                                            <<09474>>28810000
      IF CLOSE'FILE <= FUNC <= CLOSE'DEVC OR                   <<c1602>>28815000
         REW'UNLOAD <= FUNC <= RETN'BUFS THEN                  <<09474>>28820000
         BEGIN   << Already at LP, dealloc bufrs & rew/unld >> <<c1602>>28825000
         TYPE := TEMP;   << Type and Subtype needed to do   >> <<c2249>>28826000
         LPDT'INDEX := LDNUM * SIZE'OF'LPDT'ENTRY; <<rw&unld>> <<c1602>>28827000
         SUBTYPE := LPDT'SUBTYPE;                              <<c1602>>28828000
$EDIT VOID=28835000                                            <<c1602>>28830000
         GO TO START'OF'COMMAND;                               <<c1602>>28836000
         END;    << Already at LP, dealloc bufrs if req'd.  >> <<09474>>28840000
<< Rewind on a new volume is a noop because at BOT.         >> <<c1602>>28840010
      IF FUNC = REWIND THEN GO TO END'OF'COMMAND;              <<c1602>>28840020
                                                               <<09474>>28840100
<< A full-blown command, see if we can do it.               >> <<09474>>28840200
                                                               <<09474>>28840300
      IF VOLUME'FATAL THEN                                     <<09474>>28840400
         BEGIN   << Can't do non-cleanup command, tell 'em. >> <<09474>>28840500
         QERRORCODE := SDERR3;                                 <<09474>>28840600
         GO TO CAN'T'DO'COMMAND;                               <<09474>>28840700
         END     << Can't do non-cleanup command, tell 'em. >> <<09474>>28840800
         BEGIN   << Starting new vol., wait if req'd, init. >> <<09474>>28850000
            IF NOT (SDERR) THEN SET'VOL'FATAL (SDERR26);       <<09474>>28910000
         IF SDERR THEN                                         <<09474>>28911000
            GO TO END'OF'COMMAND                               <<09474>>28912000
         ELSE                                                  <<09474>>28913000
            BEGIN   << All O.K., do 1st real cmd of volume. >> <<09474>>28914000
            JUSTALLOCATED := FALSE;                            <<09474>>28915000
            LOCK'CS80'DEVICE;                                  <<09474>>28916000
            END;    << Fall through to CASE stmt from here. >> <<09474>>28918000
         END;    << Starting new vol., wait if req'd, init. >> <<09474>>28920000
      END     << New volume, set variables to load point.   >> <<09474>>28925000
$EDIT VOID=28990000                                            <<09474>>28930000
   ELSE                                                        <<09474>>28935000
      BEGIN   << Not new volume, do command if we can/must. >> <<09474>>28940000
      IF VOLUME'FATAL THEN   << only a few commands allowed >> <<09474>>28945000
         IF CLOSE'FILE <= FUNC <= REWIND    OR                 <<09474>>28950000
            REW'UNLOAD <= FUNC <= RETN'BUFS THEN <<null>> ELSE <<09474>>28955000
            BEGIN   << Looks silly, but SPL made me do it!  >> <<09474>>28960000
            QERRORCODE := SDERR3;                              <<09474>>28965000
            GO TO CAN'T'DO'COMMAND;                            <<09474>>28970000
            END;                                               <<09474>>28975000
      END;    << Not new volume, do command if we can/must. >> <<09474>>28980000
                                                               <<09474>>28985000
START'OF'COMMAND:                                              <<c1602>>28990000
   CASE FUNC.(12:4) OF                                         <<09474>>28995000
                                                               <<09474>>29086000
END'OF'COMMAND:                                                <<09474>>29087000
                                                               <<09474>>29088000
   IF (QERRORCODE := ERRORCODE) = 0 THEN                       <<09474>>29095000
      BEGIN   << No errors during command, check for EOF.   >> <<09474>>29100000
      IF EOFCODE <> NO'EOF THEN                                <<09474>>29105000
         RETVAL0 := EOFCODE & LSL(3) + ATTIO'EOF               <<09474>>29110000
         RETVAL0 := ATTIO'OK;                                  <<09474>>29120000
      END;    << No errors during command, check for EOF.   >> <<09474>>29125000
   IF VOL'FATAL THEN VOLUME'FATAL := TRUE;                     <<09474>>29126000
   IF FATAL     THEN FATALERROR   := TRUE;                     <<09474>>29127000
                                                               <<09562>>29128000
CAN'T'DO'COMMAND:                                              <<09562>>29129000
                                                               <<09562>>29129100
$EDIT VOID=29315000                                            <<09474>>29130000
   RELEASE (XDS'LOCK, NO'ALTERNATE'RESOURCE,                   <<09562>>29133000
            WAKE'FIRST'WAITER);                                <<09562>>29134000
   END     << Gap Table XDS exists, safe to set up command. >> <<09474>>29135000
ELSE       << No Gap Table XDS??! -- shouldn't happen...    >> <<09474>>29140000
   QERRORCODE := SDERR35;                                      <<09474>>29145000
                                                               <<09474>>29150000
<< At this point DB is either at the LDT (couldn't find our >> <<09474>>29155000
<< XDS) or still at our XDS. Because of the ambiguity, make >> <<09474>>29160000
<< no references to XDS variables from here on.             >> <<09474>>29165000
                                                               <<09474>>29170000
$EDIT VOID=29180000                                            <<09562>>29175000
IF QERRORCODE <> 0 THEN                                        <<09474>>29185000
   BEGIN   << Some kind of problem.                         >> <<09474>>29190000
   IF 1 <= QERRORCODE <= 99 THEN                               <<09474>>29195000
      BEGIN   << Must display error message.                >> <<09474>>29200000
      EXCHANGEDB (STACK);   << Do NOT use QUSERSTACK!       >> <<09474>>29205000
      GENMSG (SET19, QERRORCODE, %10000, LDNUM);               <<09474>>29210000
      END;    << Must display error message.                >> <<09474>>29215000
   IF QERRORCODE > 99 THEN                                     <<09474>>29220000
      RETVAL0 := ERRORS(QERRORCODE-100)   << Non-fatal err. >> <<09474>>29225000
   ELSE                                                        <<09474>>29230000
      RETVAL0 := ERRORS(\QERRORCODE\);    << Either kind.   >> <<09474>>29235000
   END;    << Some kind of problem.                         >> <<09474>>29240000
