<< LINES .001/.009 ARE RESERVED FOR SYSTEMS INTEGRATION>>               00000001
$CONTROL USLINIT,ADR,MAP,CODE,PRIVILEGED,MAIN=DFS              <<04823>>00012000
BEGIN                                                                   00014000
                                                                        00016000
                                                                        00018000
<<============================================================>>        00020000
<<                                                            >>        00022000
<<                                                            >>        00024000
<<        DFS - Disc Free Space management - Module 56        >>        00026000
<<                                                            >>        00028000
<<                                                            >>        00030000
<<============================================================>>        00032000
                                                                        00034000
                                                                        00036000
<< HP32002C MPE SOURCE C.00.00 >>                                       00038000
                                                                        00040000
$COPYRIGHT     "(C) COPYRIGHT HEWLETT-PACKARD CO. 1981. ",            & 00042000
$     "THIS PROGRAM MAY BE USED WITH ONE COMPUTER SYSTEM AT A ",      & 00044000
$     "TIME AND SHALL NOT OTHERWISE BE RECORDED, TRANSMITTED OR ",    & 00046000
$     "STORED IN A RETRIEVAL SYSTEM.  COPYING OR OTHER REPRODUCTION ",& 00048000
$     "OF THIS PROGRAM EXCEPT FOR ARCHIVAL PURPOSES IS PROHIBITED ",  & 00050000
$     "WITHOUT THE PRIOR WRITTEN CONSENT OF HEWLETT-PACKARD COMPANY."   00052000
                                                                        00054000
<<------------------------------------------------------------>>        00056000
<<                                                            >>        00058000
<<   Compile time options:                                    >>        00060000
<<                                                            >>        00062000
<<      X2 OFF - Bit map pages are always written out to disc >>        00064000
<<               after updating, this means no dirty pages    >>        00066000
<<               will be left in the buffers between calls to >>        00068000
<<               free space management routines, thus less    >>        00070000
<<               disc space will be lost if the system crashs >>        00072000
<<               but returning space will be slower.          >>        00074000
<<                                                            >>        00076000
<<      X2 ON  - Bit map pages are not always written to disc >>        00078000
<<               when returning space, the page is just mark- >>        00080000
<<               ed as dirty and not written until the buffer >>        00082000
<<               is needed.  The pages are always written out >>        00084000
<<               when getting space to avoid having space     >>        00086000
<<               both allocated and free if the system        >>        00088000
<<               crashs. This is dirty buffer management.     >>        00090000
<<                                                            >>        00092000
<<                                                            >>        00094000
<<      X3 ON  - Special error checking code is compiled into >>        00096000
<<               some procedures that try and detect probelms.>>        00098000
<<               Suddendeath (421) is called when a problem   >>        00100000
<<               is found.  This is mainly for testing and    >>        00102000
<<               debugging.                                   >>        00104000
<<                                                            >>        00106000
<<      X3 OFF - Don't compile bug catching code. Problems    >>        00108000
<<               will generally be handled with out crashing  >>        00110000
<<               the system, but problems may be harder to    >>        00112000
<<               find.                                        >>        00114000
<<                                                            >>        00116000
<<------------------------------------------------------------>>        00118000
                                                                        00120000
                                                                        00122000
$SET X2=OFF << ALWAYS WRITE DIRTY PAGES >>                              00124000
$SET X3=OFF  << DISABLE BUG CATCHERS >>                                 00126000
$PAGE "DFS - DISC FREE SPACE MANAGEMENT - INTERNAL SPECIFICATION"       00128000
COMMENT                                                                 00130000
                                                                        00132000
                                                                        00134000
                                                                        00136000
    DFS - Disc Free Space management - Internal Specification           00138000
                                                                        00140000
                                                                        00142000
1.0 - Introduction                                                      00144000
2.0 - Disc Resident Data Structures                                     00146000
  2.1 - Bit Map                                                         00148000
  2.2 - Descriptor Table                                                00150000
  2.3 - Disc Label                                                      00152000
3.0 - Virtual Memory Resident Data Structures                           00154000
  3.1 - Disc Free Space Data Segment                                    00156000
  3.2 - Logical Device Table Extension (LDTX)                           00158000
4.0 - System Discs                                                      00160000
  4.1 - System Startup                                                  00162000
  4.2 - System Shutdown                                                 00164000
5.0 - Private Volumes                                                   00166000
  5.1 - Physical Mount of a Private Volume                              00168000
  5.2 - Physical Dismount of a Private Volume                           00170000
  5.3 - Logical Mount of a Private Volume                               00172000
  5.4 - Logical Dismount of a Private Volume                            00174000
6.0 - Allocation and Deallocation Disc Space                            00176000
  6.1 - Allocating Disc Space                                           00178000
  6.2 - Deallocating Disc Space                                         00180000
  6.3 - Allocating Disc Space in a Specific Location                    00182000
7.0 - Error Handling                                                    00184000
  7.1 - Standard Format Error Status                                    00186000
  7.2 - Bitmap I/O and Checksum Errors                                  00188000
  7.3 - Fatal Dfs Errors                                                00190000
    7.3.1 - Errors During Physical Mount of a Disc                      00192000
    7.3.2 - Errors During Logical Mount of a Disc                       00194000
    7.3.3 - Errors During Logical Dismount of a Disc                    00196000
    7.3.4 - Damaged Bitmap                                              00198000
    7.3.5 - Unexpected Errors                                           00200000
  7.4 - DSTAT command                                                   00202000
  7.5 - Defective Areas Overlaping the Descriptor Table or Bitmap       00204000
  7.6 - Bug Catchers                                                    00206000
8.0 - Segmentation of the DFS module                                    00208000
9.0 - UP and DOWN commands                                              00210000
10.0 - Disc Free Space Management in INITIAL                            00212000
11.0 - INCLUDE files                                                    00214000
12.0 - Change History                                                   00216000
$PAGE                                                                   00218000
1.0) Introduction                                                       00220000
                                                                        00222000
      Disc free space management in MPE was rewritten primarly to       00224000
   support larger discs than the old disc free space table.  The        00226000
   old method was also unreliable and had a great deal of disc          00228000
   I/O overhead, the new system has attempted to solve these pro-       00230000
   blems.  Since MPE allocates disc space in variable length            00232000
   blocks, the data structures and algorithm required to achieve        00234000
   the goals of speed and the ability to handle almost any sized        00236000
   discs are not always simple.  This is a like running a hotel         00238000
   where everyone wants a different sized suite.                        00240000
                                                                        00242000
                                                                        00244000
2.0) Disc Resident Data Structures                                      00246000
                                                                        00248000
      There are two disc resident free space data structures, the       00250000
   bit map and the descriptor table, for each disc volume that          00252000
   has a free space map, i.e. system discs and private volumes.         00254000
   The addresses of these data structures are kept in the disc          00256000
   label.  The symbols that define the descriptor table and bit         00258000
   map are in the include file INCLDFS2.                                00260000
                                                                        00262000
                                                                        00264000
2.1) Bit map                                                            00266000
                                                                        00268000
      The bit map is divided up into pages, which is the physical       00270000
   block of the map that is read or written.  At the moment, a          00272000
   page is defined to be one sector (128 words) long, this may be       00274000
   changed by changing a compile time constant.  The last word of       00276000
   the page is a checksum for that page, all other words are            00278000
   data.  There is a one to one correspondence between bits in          00280000
   the map and sectors of the disc.  A one bit represents a free        00282000
   sector and a zero bit represents an allocated sector.  The bit       00284000
   map is a contiguous set of pages, enough to represent the en-        00286000
   tire disc, excluding spare tracks and spare sectors.                 00288000
                                                                        00290000
                                                                        00292000
2.2) Descriptor table (DT)                                              00294000
                                                                        00296000
      The descriptor table is an array of three word entries, one       00298000
   entry for each page of the bit map. Each entry looks like            00300000
   this:                                                                00302000
                                                                        00304000
                                                                        00306000
                ====================                                    00308000
                =                  =                                    00310000
      word 0    =  largest space   =                                    00312000
                =                  =                                    00314000
                ====================                                    00316000
                =                  =                                    00318000
      word 1    =  starting space  =                                    00320000
                =                  =                                    00322000
                ====================                                    00324000
                =                  =                                    00326000
      word 2    =  ending space    =                                    00328000
                =                  =                                    00330000
                ====================                                    00332000
                                                                        00334000
                                                                        00336000
      Thus the descriptor table looks like this.                        00338000
                                                                        00340000
      ------------                                                      00342000
      =          =  entry for page 0                                    00344000
      ------------                                                      00346000
      =          =  entry for page 1                                    00348000
      ------------                                                      00350000
      =          =  entry for page 2                                    00352000
      ------------                                                      00354000
      =          =  entry for page 3                                    00356000
      ------------                                                      00358000
           .                                                            00360000
           .                                                            00362000
           .                                                            00364000
      ------------                                                      00366000
      =          =  entry for last page                                 00368000
      ------------                                                      00370000
                                                                        00372000
      Each entry describes the free space on the corresponding          00374000
   page of the bit map.  The largest space word is the size of          00376000
   the largest contiguous block of free space on the page, which        00378000
   is not at the very beginning or very end of the page.  That          00380000
   is, the first bit physically representing the space is not the       00382000
   first bit of data on the page or the last bit representing the       00384000
   space is not the last bit of data on the page.  Starting space       00386000
   is the number of sectors of contiguous space represented by          00388000
   the set of bits whose first bit is the first bit of data on          00390000
   the page.  Ending space is the number of sectors of contiguous       00392000
   space represented by the set of bits whose last bit is the           00394000
   last bit of data on the page.  The starting space and ending         00396000
   space fields allow looking across page boundries, thus pre-          00398000
   venting fragmentation on page boundries.  Thus, if all sectors       00400000
   represented on a page are free, then starting and ending space       00402000
   will be the same and have the total number of free sectors           00404000
   represented on the page.  Largest space will be zero, as there       00406000
   is no block of space that is not at the beginning or end of          00408000
   the page.  A value of -1 for all the fields in an entry in-          00410000
   dicates the corresponding page is bad, either from a checksum        00412000
   or I/O error.                                                        00414000
                                                                        00416000
                                                                        00418000
2.3) Disc Label                                                         00420000
                                                                        00422000
      The disc label, sector zero, has the disc addresses of the        00424000
   bitmap and descriptor table, a checksum of the descriptor            00426000
   table and a flag the indicates if the descriptor table on the        00428000
   disc is an uptodate copy.  Words 126 & 127 (%176 & %177) have        00430000
   the disc address of the bit map, words 124 & 125 (%174 & %175)       00432000
   have the disc address of the descriptor table.  Word 122    <<04281>>00434000
   (%172) is the descriptor table checksum and word 123 (%173) is       00436000
   the descriptor table dirty flag, a value of TRUE indicates           00438000
   that the copy of the descriptor on disc is not uptodate and          00440000
   may not reflect the true state of the bit map.  A value of           00442000
   FALSE indicates an uptodate copy.  All these fields are de-          00444000
   fined in the include file INCDISC1.                                  00446000
                                                                        00448000
                                                                        00450000
3.0) Virtual Memory Resident Data Structures                            00452000
                                                                        00454000
      For each system disc or physically mounted private volume         00456000
   there is a data segment which has information about the disc         00458000
   free space map, the current copy of the descriptor table, some       00460000
   work space for the procedures while in spilt stack mode and          00462000
   buffers for pages of the bitmap.  The DST number of the data         00464000
   segment for a given disc is found in the LDTX entry for that         00466000
   disc.                                                                00468000
                                                                        00470000
                                                                        00472000
3.1) Disc Free Space Data Segment                                       00474000
                                                                        00476000
      For each system disc or physically mounted private volume         00478000
   in the up and running system there is a DST which contains           00480000
   info about  the disc free space map for that disc, some work         00482000
   area, a copy of the descriptor table and buffers for the pages       00484000
   of the bit map.  All symbols that define these data segments         00486000
   are in the include file INCLDFS1, and they are prefixed with         00488000
   "ds'".  The structure of the data segment is as follows:             00490000
                                                                        00492000
                                                                        00494000
                ===================================                     00496000
         0 (%0) =             ds'ldev             =                     00498000
                =---------------------------------=                     00500000
         1 (%1) =             ds'dst              =                     00502000
                =---------------------------------=                     00504000
         2 (%2) =                                 =                     00506000
                =--------- ds'disc'size ----------=                     00508000
         3 (%3) =                                 =                     00510000
                =---------------------------------=                     00512000
         4 (%4) =       ds'last'page'of'map       =                     00514000
                =---------------------------------=                     00516000
         5 (%5) =      ds'last'buffer'index       =                     00518000
                =---------------------------------=                     00520000
         6 (%6) =                                 =                     00522000
                =-------- ds'map'address ---------=                     00524000
         7 (%7) =                                 =                     00526000
                =---------------------------------=                     00528000
        8 (%10) =             ds'lock             =                     00530000
                =---------------------------------=                     00532000
        9 (%11) =          ds'lock'count          =                     00534000
                =---------------------------------=                     00536000
       10 (%12) =          ds'queue'head          =                     00538000
                =---------------------------------=                     00540000
       11 (%13) =          ds'queue'tail          =                     00542000
                =---------------------------------=                     00544000
       12 (%14) =       ds'descriptor'table       =                     00546000
                =---------------------------------=                     00548000
       13 (%15) =      ds'buffer'page'number      =                     00550000
                =---------------------------------=                     00552000
       14 (%16) =         ds'buffer'dirty         =                     00554000
                =---------------------------------=                     00556000
       15 (%17) =         ds'buffer'area          =                     00558000
                =---------------------------------=                     00560000
       16 (%18) =     ds'first'threshold'page     =                     00562000
                =---------------------------------=                     00564000
       17 (%21) =                                 =                     00566000
                =-- ds'size'of'last'allocation  --=                     00568000
       18 (%22) =                                 =                     00570000
                =---------------------------------=                     00572000
       19 (%23) =   ds'last'page'allocated'from   =                     00574000
                =---------------------------------=                     00576000
       20 (%24) =      ds'next'buffer'index       =                     00578000
                =---------------------------------=                     00580000
       21 (%25) =         ds'page'number          =                     00582000
                =---------------------------------=                     00584000
       22 (%26) =         ds'word'number          =                     00586000
                =---------------------------------=                     00588000
       23 (%27) =          ds'bit'number          =                     00590000
                =---------------------------------=                     00592000
       24 (%30) =         ds'page'pointer         =                     00594000
                =---------------------------------=                     00596000
       25 (%31) =     ds'starting'word'number     =                     00598000
                =---------------------------------=                     00600000
       26 (%32) =     ds'starting'bit'number      =                     00602000
                =---------------------------------=                     00604000
       27 (%33) =                                 =                     00606000
                =----- ds'number'of'sectors  -----=                     00608000
       28 (%34) =                                 =                     00610000
                =---------------------------------=                     00612000
       29 (%35) =          ds'bit'count           =                     00614000
                =---------------------------------=                     00616000
       30 (%36) =          ds'entry'type          =                     00618000
                =---------------------------------=                     00620000
       31 (%37) =         ds'buffer'index         =                     00622000
                =---------------------------------=                     00624000
       32 (%40) =                                 =                     00626000
                =-------- ds'disc'address --------=                     00628000
       33 (%41) =                                 =                     00630000
                =---------------------------------=                     00632000
       34 (%42) =         ds'error'status         =                     00634000
                =---------------------------------=                     00636000
                                                                        00638000
      The rest of the data segment contains tables whose size and       00640000
   location is dependent on the size of the disc and or the num-        00642000
   ber of buffers in the data segment.  They are shown below just       00644000
   to demonstarate there relation to one another, for there ac-         00646000
   tual location, the pointers should be examined.  The symbol          00648000
   "ds'array'area" defines the start of the area.                       00650000
                                                                        00652000
      The first table is the descriptor table, it is in the same        00654000
   format as the disc copy, but a dummy entry of all zeros is           00656000
   added before and after the table, these are needed by proced-        00658000
   ures "Find'Page" and "Build'Descriptor'Entry".  The pointer to       00660000
   this table is "ds'descriptor'table", it points to the entry          00662000
   for page zero, not the dummy entry.                                  00664000
                                                                        00666000
                                                                        00668000
$PAGE                                                                   00670000
                ===================================                     00672000
                =                0                =                     00674000
                =---------------------------------=   dummy             00676000
                =                0                =                     00678000
                =---------------------------------=   entry             00680000
                =                0                =                     00682000
                ===================================                     00684000
                =          largest space          =                     00686000
                =---------------------------------=  entry for          00688000
                =         starting space          =                     00690000
                =---------------------------------=    page 0           00692000
                =          ending space           =                     00694000
                ===================================                     00696000
                =          largest space          =                     00698000
                =---------------------------------=  entry for          00700000
                =         starting space          =                     00702000
                =---------------------------------=    page 1           00704000
                =          ending space           =                     00706000
                ===================================                     00708000
                                 :                                      00710000
                                 :                                      00712000
                                 :                                      00714000
                ===================================                     00716000
                =          largest space          =                     00718000
                =---------------------------------=  entry for          00720000
                =         starting space          =                     00722000
                =---------------------------------=  last page          00724000
                =          ending space           =                     00726000
                ===================================                     00728000
                =                0                =                     00730000
                =---------------------------------=   dummy             00732000
                =                0                =                     00734000
                =---------------------------------=   entry             00736000
                =                0                =                     00738000
                ===================================                     00740000
                                                                        00742000
      The next table is ds'buffer'page'number table, it has a one       00744000
   word entry for each buffer in the data segment. Each entry           00746000
   contains the page number of the page currently in the corre-         00748000
   sponding buffer or -1 if the buffer is empty.  This is pointed       00750000
   to by "ds'buffer'page'number".                                       00752000
                                                                        00754000
                ===================================                     00756000
                =         buffer 0 entry          =                     00758000
                ===================================                     00760000
                =         buffer 1 entry          =                     00762000
                ===================================                     00764000
                                 :                                      00766000
                                 :                                      00768000
                                 :                                      00770000
                ===================================                     00772000
                =        last buffer entry        =                     00774000
                ===================================                     00776000
                                                                        00778000
                                                                        00780000
      The next table is the ds'buffer'dirty table, which has a          00782000
   one word entry for each buffer.  A TRUE indicates the page in        00784000
   the correspnding buffer is dirty, i.e. the disc copy is not          00786000
   uptodate.  A FALSE indicates that the buffer is clean.               00788000
   If DFS was compiled with dirty buffer management turned off,         00790000
   this table is not present and the ds'buffer'dirty pointer is         00792000
   zero.                                                                00794000
                                                                        00796000
                ===================================                     00798000
                =         buffer 0 entry          =                     00800000
                ===================================                     00802000
                =         buffer 1 entry          =                     00804000
                ===================================                     00806000
                                 :                                      00808000
                                 :                                      00810000
                                 :                                      00812000
                ===================================                     00814000
                =        last buffer entry        =                     00816000
                ===================================                     00818000
                                                                        00820000
                                                                        00822000
      The remainder of the data segment contains the buffers,           00824000
   each buffer is the size of one page of the bit map, which is         00826000
   currently one sector (128 words).  The beginning of the buffer       00828000
   area is pointed to by "ds'buffer'area" and the number of buf-        00830000
   fers is the value in "ds'last'buffer'index" plus one.                00832000
                                                                        00834000
                ===================================                     00836000
                =                                 =                     00838000
                =                                 =                     00840000
                =                                 =                     00842000
                =            buffer 0             =                     00844000
                =                                 =                     00846000
                =                                 =                     00848000
                =                                 =                     00850000
                ===================================                     00852000
                =                                 =                     00854000
                =                                 =                     00856000
                =                                 =                     00858000
                =            buffer 1             =                     00860000
                =                                 =                     00862000
                =                                 =                     00864000
                =                                 =                     00866000
                ===================================                     00868000
                                 :                                      00870000
                                 :                                      00872000
                                 :                                      00874000
                ===================================                     00876000
                =                                 =                     00878000
                =                                 =                     00880000
                =                                 =                     00882000
                =           last buffer           =                     00884000
                =                                 =                     00886000
                =                                 =                     00888000
                =                                 =                     00890000
                ===================================                     00892000
                                                                        00894000
      Each of the fields of the data segment is described in the        00896000
   include file INCLDFS1, where they are defined.  It should be         00898000
   noted that the following fields are just workspace, used to          00900000
   pass information between procedures while in spilt stack mode        00902000
   and have no meaning between calls to the disc free space man-        00904000
   agement subsystem:                                                   00906000
                                                                        00908000
      ds'page'number              ds'word'number                        00910000
      ds'bit'number               ds'page'ptr                           00912000
      ds'starting'word'number     ds'starting'bit'number                00914000
      ds'number'of'sectors        ds'entry'type                         00916000
      ds'bit'count                ds'buffer'index                       00918000
      ds'disc'address                                                   00920000
                                                                        00922000
   The field ds'error'status normally has no meaning between            00924000
   calls unless the error'type field has a value greater than           00926000
   "fatal'dfs'error", in which case it means that disc space may        00928000
   nolonger be allocated on this disc.  This will be explained in       00930000
   greater detail in the error handling section.                        00932000
                                                                        00934000
3.2) Logical Device Table Extension (LDTX)                              00936000
                                                                        00938000
      The LDTX entry for a system disc or private volume has two        00940000
   fields relevant to disc free space management.  Word 2 of the        00942000
   LDTX entry contains the DST number of the disc free space man-       00944000
   agement extra data segment.  Word 3 is the error word, it will       00946000
   contain a standard format error status for the disc.  A error        00948000
   that is fatal to disc free space allocation occures, the error       00950000
   status is placed in this word, indicating that free space al-        00952000
   location is disabled on this device.  If all is o.k., this           00954000
   field will have a value of "no'error".  See the section on           00956000
   error handling for more information.                                 00958000
                                                                        00960000
                                                                        00962000
4.0)  System Discs                                                      00964000
                                                                        00966000
      PROGEN handles the setup/deallocation of the disc free            00968000
   space data segments for each of the system discs at system           00970000
   startup/shutdown.                                                    00972000
                                                                        00974000
                                                                        00976000
4.0) System Startup                                                     00978000
                                                                        00980000
      PROGEN setsup the data segment for each system disc at sys-       00982000
   tem startup, before the date/time dialog.  The data segment is       00984000
   allocated and the fields and arrays are initialized.  The de-        00986000
   scriptor table is read in from disc.  If it is marked as dirty       00988000
   in the disc label  or the checksum of the DT does not match          00990000
   the checksum in the disc label, then the descriptor table is         00992000
   re-built from the bitmap.  The old descriptor table is used to       00994000
   check to see which pages are marked as bad, the entries are          00996000
   not re-built for such pages.  The descriptor table is marked         00998000
   as dirty in the disc label, as the updated copy now resides in       01000000
   the data segment.  The DST number of the data segment is plac-       01002000
   ed in the LDTX entry for the disc and the error status in the        01004000
   LDTX entry is set to no error.  How errors are handled during        01006000
   this process will be explained later on.  This is all done by        01008000
   procedure "Create'Dfs'Data'Seg".                                     01010000
                                                                        01012000
4.1) System Shutdown                                                    01014000
                                                                        01016000
      At system shutdown, PROGEN handles deallocating the data          01018000
   segment for each of the system discs.  if dirty buffer manage-       01020000
   ment is being used, then all dirty pages of the bitmap are           01022000
   written to disc.  The descriptor is written to disc and is           01024000
   marked as clean in the disc label.  This is done by procedure        01026000
   "Deallocate'Dfs'Data'Seg".                                           01028000
                                                                        01030000
                                                                        01032000
5.0) Private Volumes                                                    01034000
                                                                        01036000
      The physical mounting and dismounting of a private volume         01038000
   is handled by the process PVPROC, the logical mounting and           01040000
   dismounting of a private volume is handled by module PVSYS,          01042000
   whose procedures run on the users stack.  Both PVPROC and            01044000
   PVSYS must be involved with setting up and deallocating the          01046000
   disc free space management data segment, what goes on is ex-         01048000
   plained below.                                                       01050000
                                                                        01052000
                                                                        01054000
5.1) Physical Mount of a Private Volume                                 01056000
                                                                        01058000
      When a private volume is physically mounted, DEVREC awakens       01060000
   PVPROC to process the mount.  The disc free space data segment       01062000
   is allocated and initialized in the same manner as for a sys-        01064000
   tem disc at system startup.  The descriptor table is not, how-       01066000
   ever, flagged as dirty in the disc label, as no one is cur-          01068000
   rently accessing the private volume.  This is all done by pro-       01070000
   cedure "Create'Dfs'Data'Seg".  How errors, such as no virtual        01072000
   memory, no DST entries or and I/O error are handled is de-           01074000
   scribed later.  When the system first comes up, PVPROC is            01076000
   awakened to check to see if any private volumes are already on       01078000
   line, if they are, disc free space data segments are set up          01080000
   for them.                                                            01082000
                                                                        01084000
                                                                        01086000
5.2) Physical Dismount of a Private Volume                              01088000
                                                                        01090000
      When a private volume that is not logically mounted is            01092000
   taken offline the disc free space data segment is returned to        01094000
   the system and the DST number is zeroed out in the LDTX entry        01096000
   for the disc.                                                        01098000
                                                                        01100000
                                                                        01102000
5.3) Logical Mount of a Private Volume                                  01104000
                                                                        01106000
      The logical mount of a private volume set is the result of        01108000
   a MOUNT or LMOUNT command or opening a file on the private           01110000
   volume.  This establishes access to the disc free space maps         01112000
   on all of the volumes in the volume set.  The descriptor table       01114000
   is marked as dirty in the disc label, this is done by pro-           01116000
   cedure "Allocate'Dfs'Data'Seg", called from module PVSYS.            01118000
                                                                        01120000
                                                                        01122000
5.4) Logical Dismount of a Private Volume                               01124000
                                                                        01126000
      A logical dismount of a private volume set happens when the       01128000
   last user of the set finishes accessing it.  The disc free           01130000
   space data segment is deallocated at this time.  If dirty buf-       01132000
   fer management is being used, then any dirty buffers are writ-       01134000
   ten to disc.  The descriptor table is written to disc and            01136000
   marked as clean in the disc label.  The data segment is left         01138000
   as-is, ready for the next logical mount.  This is performed by       01140000
   the procedure "Deallocate'Dfs'Data'Seg", called from module          01142000
   PVSYS.  There is considerably less over head, both with di-          01144000
   rectory binding and disc free space data segment allocation/         01146000
   deallocation if the volume set is left logically mounted bet-        01148000
   ween file accesses.                                                  01150000
                                                                        01152000
6.0) Allocation and Deallocation of Disc Space                          01154000
                                                                        01156000
      The general allocation of disc space is preformed by pro-         01158000
   cedure "Get'Disc'Space", the deallocation of disc space is           01160000
   handled by "Return'Disc'Space" and the allocation of disc            01162000
   space at a specific location is handled by                           01164000
   "Get'Specific'Disc'Space".  Since the disc free space data           01166000
   segments are locked separatly, disc space allocation/                01168000
   deallocation can happen in parallel.                                 01170000
                                                                        01172000
                                                                        01174000
6.1) Allocating Disc Space                                              01176000
                                                                        01178000
      The general allocation of disc space is done by procedure         01180000
   Get'Disc'Space.  It is passed a logical device number of a           01182000
   disc and the number of sectors desired.  It returns status and       01184000
   the first sector address of the space that was allocated.            01186000
   First procedure "Lock'Dfs'Data'Seg" is called to gain ex-            01188000
   clusive access to the data segment for the ldev and set DB to        01190000
   that data segment.                                                   01192000
                                                                        01194000
      Procedure Find'Page is called to locate the first page of         01196000
   the bit map where sufficient space can be found.  It deter-          01198000
   mines this by searching the descriptor table.  Two pieces of         01200000
   information are used to lessen the number of descriptor table        01202000
   entries that have to be looked at.  The first helper is              01204000
   "ds'size'of'last'allocation" and                                     01206000
   "ds'last'page'allocated'from".  These indicate the size of the       01208000
   last block of space that was allocated on this ldev and the          01210000
   page on which it started.  If the space that is being searched       01212000
   for is greater than or equal to the size of the last block           01214000
   allocated , then sufficient space may be found only on or            01216000
   after "ds'last'page'allocated'from", since this is a first fit       01218000
   algorithm.  "Find'Page" resets these values when it locates          01220000
   space, "Return'Disc'Space" resets them when a block of space         01222000
   that size is greater than or equal to the value in                   01224000
   "ds'size'of'last'allocation" and the first page of the bitmap        01226000
   that represents the space being returned is before the last          01228000
   page allocated from.  "Get'Specific'Disc'Space" sets the value       01230000
   to a size larger that the disc, thus it will not be used until       01232000
   reset.  If the amount of space being requested is less than          01234000
   "ds'size'of'last'allcoation", and the space is greater than or       01236000
   equal to "threshold'size", then "ds'first'threshold'page" is         01238000
   used as the first page to start the descriptor table search          01240000
   on.  This is the first page that has at least "threshold'size"       01242000
   space on it, "threshold'size" is currently set to two sectors,       01244000
   since it was observed that one sector allocations are very           01246000
   rare.  So scanning descriptor table entries with no space or         01248000
   only one sector blocks is a waste of CPU time, this will be          01250000
   significant for large discs with very little free space on           01252000
   them.  If neither one of these helpers are useful, the search        01254000
   starts with the first descriptor table entry.                        01256000
                                                                        01258000
      At this point, the page of the bit map on which the space         01260000
   will start has been located, or it was determined that suf-          01262000
   ficient space was not available on the ldev.  Note, that at          01264000
   this point no I/O, save by the memory manager, has been done.        01266000
   If space was found, procedure Locate'Free'Space is called to         01268000
   determine the word and bit at which the space starts.                01270000
   Set'Reset'Bit'Map is then called to mark the space as allocat-       01272000
   ed.  Even if dirty buffer management is being used, disc             01274000
   copies of the pages that are altered are always updated during       01276000
   allocation of space.  If this was not done and the system            01278000
   crashed before the disc copy was updated, the space would be         01280000
   both free in the bit map and allocated to a file. The de-            01282000
   scriptor table entry is rebuilt for each page as it is chang-        01284000
   ed.                                                                  01286000
                                                                        01288000
                                                                        01290000
6.2) Deallocating Disc Space                                            01292000
                                                                        01294000
      Deallocating space is a very simple matter with the bit           01296000
   map.  The disc address of the space being returned is convert-       01298000
   ed to a bit map address (i.e. page, word and bit number) and         01300000
   "Set'Reset'Bit'Map" is called to mark the space as free in the       01302000
   bit map.  If dirty buffer management is being used, then pages       01304000
   that are altered are only marked as dirty and not necessarly         01306000
   written to disc.  If dirty buffer management is not being            01308000
   used, then the disc copy is updated as each page is altered.         01310000
   The descriptor entry for all pages that are altered are re-          01312000
   built.                                                               01314000
                                                                        01316000
                                                                        01318000
6.3) Allocating Disc Space in a Specific Location                       01320000
                                                                        01322000
      Disc space may be allcoated at a specific address by using        01324000
   the procedure "Get'Specific'Disc'Space".  It is passed an ldev       01326000
   number, starting address of the space desired and the number         01328000
   of sectors desired.  It first verifies that the space is actu-       01330000
   ally free, then marks the space as allocated with                    01332000
   "Set'Reset'Bit'Map".                                                 01334000
                                                                        01336000
                                                                        01338000
7.0) Error Handling                                                     01340000
                                                                        01342000
      Error handling in disc free space management attempts to          01344000
   detect as many dangerous situations as possible and handle           01346000
   them in a way that is not fatal to the system (i.e few sudden-       01348000
   deaths), in many cases this means space can no longer be al-         01350000
   located on a certain disc, but files may still be accessed and       01352000
   most system activity may continue.                                   01354000
                                                                        01356000
                                                                        01358000
7.1) Standard Format Error Status                                       01360000
                                                                        01362000
      All error status internal to the disc free space management       01364000
   code is in a standard format.  It has the characteristic that        01366000
   if bit 15 is set it is a ok status and if bit 15 is zero it          01368000
   means an error has occured.  Thus the status word, if tested         01370000
   as a logical, will be TRUE if all is ok and FALSE if an error        01372000
   occured.  The format and values for each field in the standard       01374000
   format status word are defined in the INCLDFS2 include file.         01376000
   The format is as follows:                                            01378000
                                                                        01380000
        0  1  2  3  4  5  6  7  8  9  10  11  12  13  14  15            01382000
       =----------------------------------------------------=           01384000
       =  attachio'status      /  error'type                =           01386000
       =----------------------------------------------------=           01388000
                                                                        01390000
   "Attachio'status" is the 8 bit status returned by procedure          01392000
   "Attachio".  It will be zero for errors not involving I/O.           01394000
   "Error'type" is the code that tells what was going on when the       01396000
   error occured, the values are defined symbolicly in INCLDFS2.        01398000
   A value of 1 ("no'error") indicates that all is o.k., all oth-       01400000
   er values are even, indicating an error has occured.  Values         01402000
   of error type greater than %15 ("fatal'dfs'error") indicate          01404000
   that an error occured which prevents further allocation of           01406000
   space on that disc.                                                  01408000
                                                                        01410000
                                                                        01412000
7.2) Bitmap I/O and Checksum Errors                                     01414000
                                                                        01416000
      If an error occures while reading or writting a page of the       01418000
   bitmap or upon reading in the page, the current checksum and         01420000
   the checksum with the page don't match, the page will be flag-       01422000
   ged as bad.  This is done by procedure                               01424000
   "Process'Page'Io'Error".  The page is marked as bad by setting       01426000
   all three words to "bad'page" (value is -1) .  The descriptor        01428000
   table is then written to disc, thus, even if the system crash-       01430000
   es and the disc copy does not get updated, the copy on disc          01432000
   will have all the bad pages marked.  Next a console message is       01434000
   generated telling what error occured, the ldev on which it           01436000
   occured and the status from "Attachio".  This is not done on         01438000
   the users stack, but by   PROGEN to prevent a possible dead-         01440000
   lock if the log process has to get a file extent to log the          01442000
   console message and so that we don't have to insure that there       01444000
   is enough stack space to process the errors, as they should          01446000
   not happend very often.  If space was being allocated, the the       01448000
   whole search process is restarted, if it was being returned,         01450000
   then the page is just skipped.  Any attempt to to return space       01452000
   on a bad page will result in the space being lost, but no            01454000
   other problems will occur, and, to the caller it will appear         01456000
   that the space was returned.  Procedure "Soft'Death" is called       01458000
   before any processing is done, so if the soft'death flag is          01460000
   set, the system will crash.  This might be helpfull in finding       01462000
   problems in the field.                                               01464000
                                                                        01466000
                                                                        01468000
7.3) Fatal Dfs Errors                                                   01470000
                                                                        01472000
      Fatal disc free space errors are errors that are fatal to         01474000
   continued allocation of space on a particiular disc.  These          01476000
   errors do not crash the system. They fit into five catagories:       01478000
                                                                        01480000
       - Error during processing the physical mount of a disc           01482000
       - Error during processing the logical mount of a disc            01484000
       - Error during processing the logical dismount of a disc         01486000
       - Damaged bit map                                                01488000
       - Unexpected error.                                              01490000
                                                                        01492000
      All errors are handled by procedure "Process'Dfs'Error".          01494000
   For if the error occures in the PROGEN or PVPROC process, the        01496000
   processing takes place on that process stack, otherwise, (e.g.       01498000
   the error occures on a users stack), then a message is sent to       01500000
   PROGEN via the low level message system and processing of the        01502000
   error occures on its stack.  This is because processing the          01504000
   error on the users stack would require setting aside the stack       01506000
   space, which would be a waste as such errors will rarely oc-         01508000
   cur.  This also prevents any deadlock between the user pro-          01510000
   cessing and the logging process while trying to log the con-         01512000
   sole messages that are generated.                                    01514000
                                                                        01516000
      The handling of all types of fatal disc free space errors         01518000
   is very similar.  First the type and subtype of the ldev is          01520000
   checked just to make sure its really a disc, if it is not,           01522000
   something is really wrong, and the "Suddendeath" will be call-       01524000
   ed.  Next a console message is generated, containing the ldev,       01526000
   description of the problem, and, if necessary, the error stat-       01528000
   us.  The "ldtx'dfs'error'word" of the LDTX entry for the disc        01530000
   will have the error status set in it, this word is checked           01532000
   before accessing the free space map for a given disc, and if         01534000
   it does not have the value of "no'error'", it means that al-         01536000
   location has been disabled on this disc.  The DSTAT command          01538000
   can be used to display a message associated with this error          01540000
   (DSTAT ALL or DSTAT ldev need to be used for system discs).          01542000
   If the DST for the ldev is setup, then the error status will         01544000
   also be placed in "ds'error'status", which will be checked by        01546000
   any process that might be already queued on access the free          01548000
   space map for that ldev.                                             01550000
                                                                        01552000
      If an attempt is made to build a file on a disc with al-          01554000
   location disabled and its the only qualified disc, then file         01556000
   system error 4 will be returned, otherwise the next disc in          01558000
   the domain will be tried.  If space is returned on a disc with       01560000
   free space allocation disabled, it will just be lost, the cal-       01562000
   ler will never know.  Files may still be accessed on a disc          01564000
   with allocation disabled.  Damaged bitmap errors may be clear-       01566000
   ed by a recover lost disc space for system disc or a VINIT           01568000
   COND ldev RECOVER for private volumes.                               01570000
                                                                        01572000
      Before any processing is done for fatal errors,                   01574000
   "Soft'Death" is called, so if the soft'death flag is set in          01576000
   sysglob, the system will crash.                                      01578000
                                                                        01580000
                                                                        01582000
7.3.1) Errors During Physical Mount of a Disc                           01584000
                                                                        01586000
      Physical mount errors occur when setting up the disc free         01588000
   space data segment when a private volume is physically mounted       01590000
   on the system or when PROGEN sets up the data segments for the       01592000
   system discs at startup time.  The errors that can occur in-         01594000
   clude I/O errors on disc data structures or inability to al-         01596000
   locate the data segment.  If a bit map damaged error occured         01598000
   previously, it was flagged as damaged in the disc label, so          01600000
   remounting the volume will result in a physical mount error.         01602000
   If a private volume with an old format disc free space table         01604000
   is mounted, this is also a physical mount error.  Thus files         01606000
   on an old format disc can still be accessed, but no new ones         01608000
   can be built.                                                        01610000
                                                                        01612000
                                                                        01614000
7.3.2) Errors During Logical Mount of a Disc                            01616000
                                                                        01618000
      The only disc free space errors that can occur during the         01620000
   logical mount of a private volume is not being able to read or       01622000
   write the disc label.  The logical mount will complete, but no       01624000
   space can be allocated on the volume that got the error.             01626000
                                                                        01628000
                                                                        01630000
7.3.3) Errors During Logical Dismount of a Disc                         01632000
                                                                        01634000
      Errors trying to read or write the disc label or an error         01636000
   writting the descriptor table to disc are the only errors that       01638000
   can occur during the logical dismount of a private volume.           01640000
   The volume set may be logically mounted at a future time, but        01642000
   free space can not be allocated on the volume that got the           01644000
   error.                                                               01646000
                                                                        01648000
                                                                        01650000
7.3.4) Damaged Bitmap                                                   01652000
                                                                        01654000
      Damaged bitmap errors occur when trying to get space that         01656000
   is already marked as allocated in the bit map (which may be a        01658000
   bad descriptor table) or trying to return space that is al-          01660000
   ready free (which may be a error in calling                          01662000
   "Return'Disc'Space").  In addition to disabling allocation on        01664000
   the particular disc, the bit map is flagged as damaged by set-       01666000
   ting the "disc'lab'dfs'map'ok" word in the disc label to the         01668000
   standard format error status that was passed to                      01670000
   "Process'Dfs'Error".  This will prevent any further access to        01672000
   the disc free space map on that disc until a recover lost disc       01674000
   space is done (system disc) or VINIT COND ldev RECOVER is done       01676000
   (private volume).                                                    01678000
                                                                        01680000
                                                                        01682000
7.3.5) Unexpected Errors                                                01684000
                                                                        01686000
      Certain unexpected errors will be handled by                      01688000
   "Process'Dfs'Data'Seg", these are error conditions that should       01690000
   never happen, but may not be worth crashing the system for.          01692000
   A unique i.d. number is passed to "Process'Dfs'Error", which         01694000
   will be printed on the console .  If this should occur at any        01696000
   frequency, the soft'death flag should be set to help track the       01698000
   problem.                                                             01700000
                                                                        01702000
                                                                        01704000
7.4) DSTAT Command                                                      01706000
                                                                        01708000
      The DSTAT command will now print out information about disc       01710000
   free space fatal errors after each disc that is listed and has       01712000
   free space allocation disabled.                                      01714000
                                                                        01716000
                                                                        01718000
7.5)  Defective Areas Overlaping the Descriptor Table or Bitmap         01720000
                                                                        01722000
      If a suspect track is found to overlap either the descript-       01724000
   or table or the bit map, INITIAL will only allow the track to        01726000
   be reassigned, recovered or ignored (responding with a car-          01728000
   riage return to the suspect track disposition question).  If         01730000
   the track is reassigned, the INITIAL forces a recover lost           01732000
   disc space, which rebuilds the descriptor table and bit map.         01734000
   Thus such a track should always be reassigned if possible.           01736000
   VINIT however will only let you recover such a track, so the         01738000
   best bet is to recover the track, store of all the files on          01740000
   the private volume and re-initialize the disc.  VINIT should         01742000
   be changed in the future to work like INITIAL.                       01744000
                                                                        01746000
                                                                        01748000
7.6) Bug Catchers                                                       01750000
                                                                        01752000
      There a set of bug catchers in the DFS module which are           01754000
   compiled in if X3 is turned on.  They test various values to         01756000
   see if they correct, and upon finding any inconsistencies,           01758000
   call SUDDENDEATH (421).  These are intended to be used to help       01760000
   find problems in the lab, and should normally not be turned on       01762000
   in the field.                                                        01764000
                                                                        01766000
                                                                        01768000
8.0) Segmentation of the DFS Module                                     01770000
                                                                        01772000
      The disc free space module has two logical segments, DFS          01774000
   and DFSUTIL.  DFS contains all the procedures that are used in       01776000
   the normal allocation and deallocation of disc space, they           01778000
   are:                                                                 01780000
                                                                        01782000
       Read'Page                Write'Page                              01784000
       Convert'Address'To'Map   Convert'Map'To'Address                  01786000
       Make'Check'Sum           Scan'Page                               01788000
       Get'Page                 Build'Descriptor'Entry                  01790000
       Set'Reset'Bit'Map        Find'Page                               01792000
       Locate'Free'Space        Lock'Dfs'Data'Seg                       01794000
       Unlock'Dfs'Data'Seg      Get'Disc'Space                          01796000
       Return'Disc'Space        Get'Specific'Disc'Space                 01798000
                                                                        01800000
   Segment DFSUTIL contains all the other utility procedures in-        01802000
   volved with mounting and dismounting of discs, system startup        01804000
   and shutdown, and processing page and fatal errors.  These           01806000
   procedures are:                                                      01808000
                                                                        01810000
       Read'Disc                Write'Disc                              01812000
       Write'Disc'Label         Move'From'Data'Seg                      01814000
       Move'To'Data'Seg         Get'Disc'Info                           01816000
       Process'Dfs'Error        Send'Process'Dfs'Error                  01818000
       Print'Page'Io'Error      Page'Io'Error                           01820000
       Create'Dfs'Data'Seg      Delete'Dfs'Data'Seg                     01822000
       Allocate'Dfs'Data'Seg    Deallocate'Dfs'Data'Seg                 01824000
       Process'Sys'Disc'Free'Space'Maps                                 01826000
                                                                        01828000
   NOTE: Due to the current problem with the limitation of the          01830000
   CST table segment DFSUTIL and DFS have been combined into seg-       01832000
   ment DFS, when the CST expansion is completed the original           01834000
   segmentation should be restored.                                     01836000
                                                                        01838000
                                                                        01840000
9.0) UP and DOWN Commands.                                              01842000
                                                                        01844000
      The DOWN command will delete the disc free space data seg-        01846000
   ment for any disc that has them.  The UP command will set up a       01848000
   disc free space data segment for any disc that is down and           01850000
   will have a free space map (e.g private volume).                     01852000
                                                                        01854000
                                                                        01856000
10.0) Disc Free Space Management in INITIAL                             01858000
                                                                        01860000
      The original goal when developing the disc free space man-        01862000
   agement subsystem was to use most of the same code for INITIAL       01864000
   and up and running system.  Due to the fact that INITIAL does        01866000
   not manage data segments, it was impossible to guarantee that        01868000
   there would be enough space to manage the disc free space            01870000
   "data segment".  Thus INITIAL does not use the descriptor            01872000
   table to find space.  The descriptor table for an ldev is            01874000
   scaned when the disc is first accessed, to see if there are          01876000
   any bad pages.  If bad pages are found, then each time a page        01878000
   is accessed on that disc, the sector containing the descriptor       01880000
   table entry for the page will be checked to see if it is a bad       01882000
   page.  The descriptor table is not looked at if it was dis-          01884000
   covered that there are no bad pages on a particular ldev.  The       01886000
   descriptor table will be flaged as dirty in the disc label for       01888000
   each disc that INITIAL access, thus these descriptor tables          01890000
   will be rebuilt by PROGEN when the system comes up.  The bit         01892000
   map must be scanned to find space, however the size and page         01894000
   from which the last block of space was allocated is remember-        01896000
   ed, so this can be used to help in the search.  For further          01898000
   details on disc free space management in INITIAL, consult the        01900000
   code.  The following routines are common to INITIAL and DFS          01902000
   module the DFS module and are in the include file INCLDFSC:          01904000
                                                                        01906000
      Convert'Address'To'Map                                            01908000
      Convert'Map'To'Address                                            01910000
      Make'Check'Sum                                                    01912000
      Scan'Page                                                         01914000
                                                                        01916000
                                                                        01918000
11.0) INCLUDE files                                                     01920000
                                                                        01922000
      The following include files where added to the system for         01924000
   this project:                                                        01926000
                                                                        01928000
   INCLDFS1 - module B2 - Defines the disc free space management        01930000
                          data segment.                                 01932000
                                                                        01934000
   INCLDFS2 - module B3 - Various equates and defines relevent to       01936000
                          DFS, including error codes and message        01938000
                          numbers.                                      01940000
                                                                        01942000
   INCLDFSC - module B4 - Code that is common to INITIAL and DFS.       01944000
                                                                        01946000
   INCDISC1 - module B5 - Defines information about discs.              01948000
                                                                        01950000
   INCDISC2 - module B6 - Sets up arrays that define that               01952000
                          characteristics of different disc types       01954000
                          and subtypes.                                 01956000
                                                                        01958000
                                                                        01960000
12.0) Change History                                                    01962000
                                                                        01964000
                                                               <<03653>>01966000
    23 Dec 81                                                  <<03653>>01968000
                                                               <<03653>>01970000
    Changes where made to allow LYNX to work with the          <<03653>>01972000
    disc free space map.  PROGEN was initializing LYNX         <<03653>>01974000
    in the call to INITIO the sets up the system console.      <<03653>>01976000
    But the LYNX initialiazition routines called LOADPROC,     <<03653>>01978000
    which resulted in attempts to allocate disc space.  This   <<03653>>01980000
    was being done before the free space data segments where   <<03653>>01982000
    set up.  In order to get around this, the call to          <<03653>>01984000
    Process'Sys'Disc'Free'Space'Maps was moved to before the   <<03653>>01986000
    call to INITIO.  But, since the console and message system <<03653>>01988000
    was not initialized at this time, there would be no way    <<03653>>01990000
    to generate error message on PROGENs stack at this time.   <<03653>>01992000
    The solution: PROGEN sends requests via the low level msg  <<03653>>01994000
    system to its self, which it later picks up and processes. <<03653>>01996000
                                                               <<03653>>01998000
    26 April 1982                                              <<04281>>02000000
                                                               <<04281>>02002000
    Added missing GENMSGs in Process'Dfs'Error for disc label  <<04281>>02004000
    read and write errors during the physical mount of a disc. <<04281>>02006000
    These had been left out by an oversite. Also corrected a   <<04281>>02008000
    mistake in section 2.3 of the IMS.                         <<04281>>02010000
                                                               <<04281>>02012000
                                                               <<04281>>02014000
                                                                        02016000
                                                    ;                   02018000
$PAGE "INCLDFS1 - DISC FREE SPACE DATA SEGMENT DEFINITION"              02020000
$INCLUDE INCLDFS1                                                       02022000
$PAGE "INCLDFS2 - DISC FREE SPACE MANAGEMENT CONSTANTS"                 02024000
$INCLUDE INCLDFS2                                                       02026000
$PAGE "INCDISC1 - DISC INFORMATION AND CONSTANTS"                       02028000
$INCLUDE INCDISC1                                                       02030000
$PAGE "GLOBAL DEFINITIONS"                                              02032000
   DEFINE DBL = DOUBLE#;                                                02034000
                                                                        02036000
   DEFINE max'double = 2147483647D#;  << Max double integer >>          02038000
                                                                        02040000
   << PCB definitions >>                                                02042000
                                                                        02044000
   EQUATE                                                               02046000
      PCBB = 3,       << PCB base in low core >>                        02048000
      CPCB = 4,       << Current process PCB pointer in low core >>     02050000
      PCBSIZE = 16;   << PCB entry size >>                              02052000
                                                                        02054000
   INTEGER POINTER pcb = 3;   << Pointer to PCB >>                      02056000
                                                                        02058000
                                                                        02060000
   << LDT/LDTX definitions >>                                           02062000
                                                                        02064000
   EQUATE                                                               02066000
      ldt'dst = 14,            << DST number of LDT/LDTX >>             02068000
                                                                        02070000
      ldt'sir = 10,            << SIR number of LDT/LDTX >>             02072000
                                                                        02074000
      ldt'entry'size = 5,      << Size of LDT/LDTX entry in words >>    02076000
                                                                        02078000
      ldtx'dfs'dst'word = 2,   << Word of LDTX entry containing the >>  02080000
                               << DST number of the disc free space >>  02082000
                               << data segment for the disc ldev.   >>  02084000
                                                                        02086000
      ldtx'dfs'error'word = 3; << Word of LDTX entry containing the >>  02088000
                               << standard format error status for  >>  02090000
                               << the disc drive if it has a free   >>  02092000
                               << space map.  If it does not have a >>  02094000
                               << value of "no'error", free space   >>  02096000
                               << allocation is disabled on this    >>  02098000
                               << disc.                             >>  02100000
                                                                        02102000
    DEFINE                                                              02104000
       ldt'type = 2).(10:6#,        << Device type >>                   02106000
       ldt'vtab'index = 1).(0:8#;   << Volume table index >>            02108000
                                                                        02110000
                                                                        02112000
   << LPDT definitions >>                                               02114000
                                                                        02116000
   LOGICAL POINTER lpdt = 8;                                            02118000
                                                                        02120000
   EQUATE lpdt'entry'size = 2;                                          02122000
                                                                        02124000
   DEFINE                                                               02126000
      lpdt'pv = 1).(4:1#,                                               02128000
      lpdt'high'entry'num = 0).(0:8#;                                   02130000
                                                                        02132000
                                                                        02134000
   << Volume table definitions >>                                       02136000
                                                                        02138000
   EQUATE                                                               02140000
      vtab'dst = 29,                                                    02142000
      vtab'entry'size = 14;                                             02144000
                                                                        02146000
   DEFINE                                                               02148000
      vtab'non'sys'domain  = 12).(14:1#,                                02150000
      vtab'ldev = 12).(0:8#;                                            02152000
                                                                        02154000
   << Attachio parameters >>                                            02156000
                                                                        02158000
   EQUATE                                                               02160000
      read'io'func = 0,                                                 02162000
      write'io'func = 1,                                                02164000
      write'label'io'func = 11,                                         02166000
      get'vol'limit'io'func = 13,                                       02168000
      unblocked'io'flag = 0,                                            02170000
      blocked'io'flag = 1;                                              02172000
                                                                        02174000
                                                                        02176000
   << Find'Page type values >>                                          02178000
                                                                        02180000
   EQUATE                                                               02182000
      no'space'type = -1,                                               02184000
      middle'type = 0,                                                  02186000
      starting'type = 1,                                                02188000
      ending'type = 2;                                                  02190000
                                                                        02192000
                                                                        02194000
   << This defines the bits in low core which override normal           02196000
      error processing if set, and causes a Suddendeath instead.        02198000
      This is for trying to find bugs in the field.             >>      02200000
                                                                        02202000
   DEFINE                                                               02204000
      crash'on'fatal'dfs'error = ABSOLUTE(%1350).(15:1)#,               02206000
      crash'on'non'fatal'dfs'error = ABSOLUTE(%1350).(14:1)#;           02208000
                                                                        02210000
   << Stuff used to send messages to PROGEN >>                          02212000
                                                                        02214000
   EQUATE dfs'error'progen'msg = 0;                                     02216000
   EQUATE page'io'error'progen'msg = 1;                                 02218000
                                                                        02220000
   DEFINE progen'pin = 1#; << PROGEN's PIN is always 1 >>               02222000
                                                                        02224000
                                                                        02226000
                                                                        02228000
$PAGE "MACRO DEFINITIONS"                                               02230000
<<------------------------------------------------------------>>        02232000
<<                                                            >>        02234000
<<                    Macro definitions                       >>        02236000
<<                                                            >>        02238000
<<------------------------------------------------------------>>        02240000
                                                                        02242000
                                                                        02244000
   << Getprocnum - determines the PIN of the current process >>         02246000
                                                                        02248000
   DEFINE                                                               02250000
      Getprocnum = (ABSOLUTE(CPCB) - ABSOLUTE(PCBB))&LSR(4)#;           02252000
                                                                        02254000
   << Pseudoenable/Pseudodisable >>                                     02256000
                                                                        02258000
   DEFINE                                                               02260000
      Pseudoenable = ASSEMBLE (PSEB)#,                                  02262000
      Pseudodisable = ASSEMBLE (PSDB)#;                                 02264000
                                                                        02266000
   << Enable/Disable >>                                                 02268000
                                                                        02270000
   DEFINE                                                               02272000
      Enable = ASSEMBLE (SED 1)#,                                       02274000
      Disable = ASSEMBLE (SED 0)#;                                      02276000
                                                                        02278000
   << Checkdb - determines if DB is currently at the stack by           02280000
      comparing current DB address with DB address in the ICS.          02282000
      CC is "=" if DB is at the stack.                         >>       02284000
                                                                        02286000
   EQUATE Qi = 5;   << Initial Q location in the ICS >>                 02288000
   INTEGER x = X;   << X-register >>                                    02290000
                                                                        02292000
   DEFINE Checkdb =                                                     02294000
             BEGIN  << Checkdb >>                                       02296000
                                                                        02298000
                Disable;                                                02300000
                PUSH (DB);   << Get current DB address >>               02302000
                                                                        02304000
                << Get DB for ICS >>                                    02306000
                                                                        02308000
                x := ABSOLUTE (Qi) - 5;                                 02310000
                TOS := ABSOLUTE (x);                                    02312000
                x := x + 1;                                             02314000
                TOS := ABSOLUTE (x);                                    02316000
                                                                        02318000
                Enable;                                                 02320000
                ASSEMBLE (DCMP);  << Compare address >>                 02322000
                                                                        02324000
             END    << Checkdb >>#;                                     02326000
                                                                        02328000
   << This macro check to see if the specified ldev is really a         02330000
      disc ldev. The ldev number should be on TOS an it will            02332000
      leave a logical value on TOS, TRUE if it is a disc,               02334000
      FALSE otherwise.                                           >>     02336000
                                                                        02338000
   INTEGER s0 = S-0;                                                    02340000
                                                                        02342000
   DEFINE Check'If'Disc =                                               02344000
             BEGIN  << Check'If'Disc >>                                 02346000
                                                                        02348000
                IF s0 > INTEGER(lpdt (lpdt'high'entry'num)) OR          02350000
                s0 <= 0 THEN                                            02352000
                   s0 := FALSE   << Ldev not legal >>                   02354000
                ELSE                                                    02356000
                   BEGIN  << Check if its a disc >>                     02358000
                                                                        02360000
                      ASSEMBLE (ZERO,  << Leave room whats returned >>  02362000
                                XCH);  << Put parm on top           >>  02364000
                                                                        02366000
                      TOS := Ldevtotype (*);                            02368000
                                                                        02370000
                      IF (s0 = mh'disc'type) LOR (s0 = fh'disc'type)    02372000
                      LOR (s0 = floppy'disc'type) LOR                   02374000
                      (s0 = cs'80'type) THEN                            02376000
                         s0 := TRUE                                     02378000
                      ELSE                                              02380000
                         s0 := FALSE;                                   02382000
                                                                        02384000
                   END;   << Check if its a disc >>                     02386000
                                                                        02388000
             END    << Check'If'Disc >>#;                               02390000
                                                                        02392000
   << This macro insures that there is enough stack space               02394000
      available so that a stack overflow will not occure                02396000
      while the process is critical.                      >>            02398000
                                                                        02400000
   EQUATE stack'space'to'insure = %460;                                 02402000
                                                                        02404000
   DEFINE Insure'Stack'Space =                                          02406000
             BEGIN  << Insure'Stack'Space >>                            02408000
                                                                        02410000
                TOS := stack'space'to'insure;                           02412000
                ASSEMBLE (ADDS 0);                                      02414000
                                                                        02416000
                TOS := stack'space'to'insure;                           02418000
                ASSEMBLE (SUBS 0);                                      02420000
                                                                        02422000
             END    << Insure'Stack'Space >>#;                          02424000
                                                                        02426000
$PAGE "EXTERNAL PROCEDURE DEFINITIONS"                                  02428000
<<------------------------------------------------------------>>        02430000
<<                                                            >>        02432000
<<               External procedure definitions               >>        02434000
<<                                                            >>        02436000
<<------------------------------------------------------------>>        02438000
                                                                        02440000
   DOUBLE PROCEDURE Attachio (ldev, qmisc, dstx, addr, func, cnt,       02442000
                              p1, p2, flags);                           02444000
      VALUE ldev, qmisc, dstx, addr, func, cnt, p1, p2, flags;          02446000
      INTEGER ldev, qmisc, dstx, addr, func, cnt, p1, p2, flags;        02448000
      OPTION EXTERNAL;                                                  02450000
                                                                        02452000
   PROCEDURE Awake (pin, af, wf);                                       02454000
      VALUE pin, af, wf;                                                02456000
      INTEGER pin, af, wf;                                              02458000
      OPTION EXTERNAL;                                                  02460000
                                                                        02462000
   LOGICAL PROCEDURE Exchangedb (dst);                                  02464000
      VALUE dst;                                                        02466000
      LOGICAL dst;                                                      02468000
      OPTION EXTERNAL;                                                  02470000
                                                                        02472000
   INTEGER PROCEDURE Genmsg (setno, msgno, mask, parm1, parm2,          02474000
                             parm3, parm4, parm5, dest, reply,          02476000
                             offset, dst, control);                     02478000
      VALUE setno, msgno, mask, parm1, parm2, parm3, parm4,             02480000
            parm5, dest, reply, offset, dst, control;                   02482000
      INTEGER setno, msgno, dest, dst;                                  02484000
      LOGICAL mask, parm1, parm2, parm3, parm4, parm5, reply,           02486000
              offset, control;                                          02488000
      OPTION VARIABLE, EXTERNAL;                                        02490000
                                                                        02492000
   INTEGER PROCEDURE Getdataseg (memsize, vdsize);                      02494000
      VALUE memsize, vdsize;                                            02496000
      INTEGER memsize, vdsize;                                          02498000
      OPTION EXTERNAL;                                                  02500000
                                                                        02502000
   LOGICAL PROCEDURE Getsir (sirnum);                                   02504000
      VALUE sirnum;                                                     02506000
      INTEGER sirnum;                                                   02508000
      OPTION EXTERNAL;                                                  02510000
                                                                        02512000
   PROCEDURE Impede (pcbpt);                                            02514000
      VALUE pcbpt;                                                      02516000
      INTEGER pcbpt;                                                    02518000
      OPTION EXTERNAL;                                                  02520000
                                                                        02522000
   INTEGER PROCEDURE Ldevtosubtype (ldev);                              02524000
      VALUE ldev;                                                       02526000
      INTEGER ldev;                                                     02528000
      OPTION EXTERNAL;                                                  02530000
                                                                        02532000
   INTEGER PROCEDURE Ldevtotype (ldev);                                 02534000
      VALUE ldev;                                                       02536000
      INTEGER ldev;                                                     02538000
      OPTION EXTERNAL;                                                  02540000
                                                                        02542000
   PROCEDURE Relsir (sirnum, a);                                        02544000
      VALUE sirnum, a;                                                  02546000
      INTEGER sirnum;                                                   02548000
      LOGICAL a;                                                        02550000
      OPTION EXTERNAL;                                                  02552000
                                                                        02554000
   PROCEDURE Reldataseg (dstx);                                         02556000
      VALUE dstx;                                                       02558000
      INTEGER dstx;                                                     02560000
      OPTION EXTERNAL;                                                  02562000
                                                                        02564000
   DOUBLE PROCEDURE Reqstatus (ldev);                                   02566000
      VALUE ldev;                                                       02568000
      INTEGER ldev;                                                     02570000
      OPTION EXTERNAL;                                                  02572000
                                                                        02574000
   PROCEDURE Resetcritical (oldval);                                    02576000
      VALUE oldval;                                                     02578000
      INTEGER oldval;                                                   02580000
      OPTION EXTERNAL;                                                  02582000
                                                                        02584000
   PROCEDURE Sendmsg (destpin, destport, msglength, flags);             02586000
      VALUE destpin, destport, msglength, flags;                        02588000
      INTEGER destpin, destport, msglength;                             02590000
      LOGICAL flags;                                                    02592000
      OPTION EXTERNAL;                                                  02594000
                                                                        02596000
   LOGICAL PROCEDURE Setcritical;                                       02598000
      OPTION EXTERNAL;                                                  02600000
                                                                        02602000
   PROCEDURE Soft'Death (num);                                          02604000
      VALUE num;                                                        02606000
      INTEGER num;                                                      02608000
      OPTION EXTERNAL;                                                  02610000
                                                                        02612000
   PROCEDURE Suddendeath (num);                                         02614000
      VALUE num;                                                        02616000
      INTEGER num;                                                      02618000
      OPTION EXTERNAL;                                                  02620000
                                                                        02622000
   PROCEDURE Unimpede (pcbpt);                                          02624000
      VALUE pcbpt;                                                      02626000
      INTEGER pcbpt;                                                    02628000
      OPTION EXTERNAL;                                                  02630000
                                                                        02632000
$PAGE "FORWARD PROCEDURE DEFINITIONS"                                   02634000
<<------------------------------------------------------------>>        02636000
<<                                                            >>        02638000
<<               Forward procedure definitions                >>        02640000
<<                                                            >>        02642000
<<------------------------------------------------------------>>        02644000
                                                                        02646000
   PROCEDURE Build'Descriptor'Entry (page);                             02648000
      VALUE page;                                                       02650000
      INTEGER page;                                                     02652000
      OPTION VARIABLE, FORWARD;                                         02654000
                                                                        02656000
   PROCEDURE Delete'Dfs'Data'Seg (ldev);                                02658000
      VALUE ldev;                                                       02660000
      INTEGER ldev;                                                     02662000
      OPTION FORWARD;                                                   02664000
                                                                        02666000
   LOGICAL PROCEDURE Lock'Dfs'Data'Seg (ldev);                          02668000
      VALUE ldev;                                                       02670000
      INTEGER ldev;                                                     02672000
      OPTION FORWARD;                                                   02674000
                                                                        02676000
   LOGICAL PROCEDURE Make'Check'Sum (buffer, count);                    02678000
      VALUE count;                                                      02680000
      ARRAY buffer;                                                     02682000
      INTEGER count;                                                    02684000
      OPTION FORWARD;                                                   02686000
                                                                        02688000
   PROCEDURE Unlock'Dfs'Data'Seg;                                       02690000
      OPTION FORWARD;                                                   02692000
                                                                        02694000
   PROCEDURE Write'Page (page, buffer'index);                           02696000
      VALUE page, buffer'index;                                         02698000
      INTEGER page, buffer'index;                                       02700000
      OPTION FORWARD;                                                   02702000
                                                                        02704000
$CONTROL SEGMENT=DFS     << DFSUTIL >>                                  02706000
$PAGE "READ'DISK"                                                       02708000
LOGICAL PROCEDURE Read'Disc (ldev, add, dst, target, count);            02710000
   VALUE ldev, add, dst, count;                                         02712000
   INTEGER ldev;                                                        02714000
   DOUBLE add;                                                          02716000
   INTEGER dst;                                                         02718000
   ARRAY target;                                                        02720000
   INTEGER count;                                                       02722000
   OPTION PRIVILEGED,UNCALLABLE;                                        02724000
                                                                        02726000
<<==============================================================        02728000
                                                                        02730000
      This procedure is an interface to "ATTACHIO" for                  02732000
   performing disc reads.                                               02734000
                                                                        02736000
   Parameters:                                                          02738000
      ldev - Ldev of disc drive to read from.                           02740000
      add - Double word disc address of first sector to read.           02742000
      dst - DST number of data segment to read data into, or            02744000
            zero if data is to be read into stack.                      02746000
      target - Location to read data into.                              02748000
      count - Number of WORDS to read.                                  02750000
                                                                        02752000
   Returns:                                                             02754000
      A standard format error word.  The "error'type" field             02756000
      of the word will have a value of "disc'read'error" if             02758000
      an error occured.                                                 02760000
                                                                        02762000
   Assumptions on entry:                                                02764000
      None.                                                             02766000
                                                                        02768000
   Exit conditions:                                                     02770000
      DB is unchanged.                                                  02772000
                                                                        02774000
   Globals:                                                             02776000
                                                                        02778000
      Equates:                                                          02780000
         no'error                                                       02782000
         ok'io'status                                                   02784000
         disc'read'error                                                02786000
         read'io'func                                                   02788000
         blocked'io'flag                                                02790000
                                                                        02792000
      Defines:                                                          02794000
         general'io'status                                              02796000
         error'type                                                     02798000
                                                                        02800000
   Externals:                                                           02802000
      Attachio                                                          02804000
                                                                        02806000
   Intrinsics:                                                          02808000
      None.                                                             02810000
                                                                        02812000
   Callers:                                                             02814000
      Get'Disc'Info                                                     02816000
      Process'Dfs'Error                                                 02818000
      Create'Dfs'Data'Seg                                               02820000
      Allocate'Dfs'Data'Seg                                             02822000
      VINIT module 32                                                   02824000
                                                                        02826000
   Changes:                                                             02828000
                                                                        02830000
                                                                        02832000
==============================================================>>        02834000
                                                                        02836000
BEGIN                                                                   02838000
                                                                        02840000
   INTEGER add'high = add + 0;   << High order part of address >>       02842000
   INTEGER add'low  = add + 1;   << Low order part of address  >>       02844000
                                                                        02846000
   LOGICAL return'value = Read'Disc;                                    02848000
                                                                        02850000
   << - - - - - - - - - - >>                                            02852000
                                                                        02854000
   TOS := Attachio(ldev, 0, dst, @target, read'io'func, count,          02856000
                   add'high, add'low, blocked'io'flag);                 02858000
   DEL;   << Delete transmission log >>                                 02860000
                                                                        02862000
   << Form status word >>                                               02864000
                                                                        02866000
   return'value := TOS&LSL(8) + no'error;                               02868000
                                                                        02870000
   IF return'value.general'io'status <> ok'io'status THEN               02872000
     return'value.error'type := disc'read'error;                        02874000
                                                                        02876000
END;  << Read'Disc >>                                                   02878000
$PAGE "WRITE'DISC"                                                      02880000
LOGICAL PROCEDURE Write'Disc (ldev, add, dst, source, count);           02882000
   VALUE ldev, add, dst, count;                                         02884000
   INTEGER ldev;                                                        02886000
   DOUBLE add;                                                          02888000
   INTEGER dst;                                                         02890000
   ARRAY source;                                                        02892000
   INTEGER count;                                                       02894000
   OPTION PRIVILEGED,UNCALLABLE;                                        02896000
                                                                        02898000
<<==============================================================        02900000
                                                                        02902000
      This procedure is an interface to "ATTACHIO" for                  02904000
   performing disc writes.                                              02906000
                                                                        02908000
   Parameters:                                                          02910000
      ldev - Ldev of disc drive to write to.                            02912000
      add - Double word disc address of first sector to                 02914000
            write.                                                      02916000
      dst - DST number of data segment to write data from, or           02918000
            zero if data is to be written from stack.                   02920000
      source - Location to write data from.                             02922000
      count - Number of WORDS to write.                                 02924000
                                                                        02926000
   Returns:                                                             02928000
      A standard format error word.  The "error'type" field             02930000
      of the word will have a value of "disc'write'error" if            02932000
      an error occured.                                                 02934000
                                                                        02936000
   Assumptions on entry:                                                02938000
      None.                                                             02940000
                                                                        02942000
   Exit conditions:                                                     02944000
      DB is unchanged.                                                  02946000
                                                                        02948000
   Globals:                                                             02950000
                                                                        02952000
      Equates:                                                          02954000
         no'error                                                       02956000
         ok'io'status                                                   02958000
         disc'write'error                                               02960000
         write'io'func                                                  02962000
         blocked'io'flag                                                02964000
                                                                        02966000
      Defines:                                                          02968000
         general'io'status                                              02970000
         error'type                                                     02972000
                                                                        02974000
   Externals:                                                           02976000
      Attachio                                                          02978000
                                                                        02980000
   Intrinsics:                                                          02982000
      None.                                                             02984000
                                                                        02986000
   Callers:                                                             02988000
      Page'Io'Error                                                     02990000
      Create'Dfs'Data'Seg                                               02992000
      Deallocate'Dfs'Data'Seg                                           02994000
      VINIT module 32                                                   02996000
                                                                        02998000
   Changes:                                                             03000000
                                                                        03002000
                                                                        03004000
==============================================================>>        03006000
                                                                        03008000
BEGIN                                                                   03010000
                                                                        03012000
   INTEGER add'high = add + 0;   << High order part of address >>       03014000
   INTEGER add'low  = add + 1;   << Low order part of address  >>       03016000
                                                                        03018000
   LOGICAL return'value = Write'Disc;                                   03020000
                                                                        03022000
   << - - - - - - - - - - >>                                            03024000
                                                                        03026000
   TOS := Attachio(ldev, 0, dst, @source, write'io'func, count,         03028000
                   add'high, add'low, blocked'io'flag);                 03030000
   DEL;  << Delete tranmission log >>                                   03032000
                                                                        03034000
   << Form status word >>                                               03036000
                                                                        03038000
   return'value := TOS&LSL(8) + no'error;                               03040000
                                                                        03042000
   IF return'value.general'io'status <> ok'io'status THEN               03044000
     return'value.error'type := disc'write'error;                       03046000
                                                                        03048000
END;  << Write'Disc >>                                                  03050000
$PAGE "WRITE'DISC'LABEL"                                                03052000
LOGICAL PROCEDURE Write'Disc'Label (ldev, dst, source);                 03054000
   VALUE ldev, dst;                                                     03056000
   INTEGER ldev;                                                        03058000
   INTEGER dst;                                                         03060000
   ARRAY source;                                                        03062000
   OPTION PRIVILEGED,UNCALLABLE;                                        03064000
                                                                        03066000
<<==============================================================        03068000
                                                                        03070000
      This procedure is an interface to "ATTACHIO" for                  03072000
   writting the disc label (sector number zero).                        03074000
                                                                        03076000
   Parameters:                                                          03078000
      ldev - Ldev of disc drive to write label to.                      03080000
      dst - DST number of data segment to write label from,             03082000
            or zero if label is to be written from stack.               03084000
      source - Location to write label from.                            03086000
                                                                        03088000
   Returns:                                                             03090000
      A standard format error word.  The "error'type" field             03092000
      of the word will have a value of                                  03094000
      "disc'label'write'error" if an error occured.                     03096000
                                                                        03098000
   Assumptions on entry:                                                03100000
      None.                                                             03102000
                                                                        03104000
   Exit conditions:                                                     03106000
      DB is unchanged.                                                  03108000
                                                                        03110000
   Globals:                                                             03112000
                                                                        03114000
      Equates:                                                          03116000
         no'error                                                       03118000
         ok'io'status                                                   03120000
         disc'label'write'error                                         03122000
         blocked'io'flag                                                03124000
         write'label'io'func                                            03126000
         sector'size                                                    03128000
                                                                        03130000
      Defines:                                                          03132000
         general'io'status                                              03134000
         error'type                                                     03136000
                                                                        03138000
   Externals:                                                           03140000
      Attachio                                                          03142000
                                                                        03144000
   Intrinsics:                                                          03146000
      None.                                                             03148000
                                                                        03150000
   Callers:                                                             03152000
      Process'Dfs'Error                                                 03154000
      Create'Dfs'Data'Seg                                               03156000
      Allocate'Dfs'Data'Seg                                             03158000
      Deallocate'Dfs'Data'Seg                                           03160000
      VINIT module 32                                                   03162000
                                                                        03164000
   Changes:                                                             03166000
                                                                        03168000
                                                                        03170000
==============================================================>>        03172000
                                                                        03174000
BEGIN                                                                   03176000
                                                                        03178000
   LOGICAL return'value = Write'Disc'Label;                             03180000
                                                                        03182000
   << - - - - - - - - - - >>                                            03184000
                                                                        03186000
   TOS := Attachio(ldev, 0, dst, @source, write'label'io'func,          03188000
                   sector'size, 0, 0, blocked'io'flag);                 03190000
   DEL;  << Delete tranmission log >>                                   03192000
                                                                        03194000
   << Form status word >>                                               03196000
                                                                        03198000
   return'value := TOS&LSL(8) + no'error;                               03200000
                                                                        03202000
   IF return'value.general'io'status <> ok'io'status THEN               03204000
     return'value.error'type := disc'label'write'error;                 03206000
                                                                        03208000
END;  << Write'Disc'Label >>                                            03210000
$PAGE "MOVE'FROM'DATA'SEG"                                              03212000
PROCEDURE Move'From'Data'Seg (dst, offset, count, target);              03214000
   VALUE dst, offset, count;                                            03216000
   INTEGER dst, offset, count;                                          03218000
   ARRAY target;                                                        03220000
   OPTION PRIVILEGED,UNCALLABLE;                                        03222000
                                                                        03224000
<<==============================================================        03226000
                                                                        03228000
      This procedure does a move from data segment.                     03230000
                                                                        03232000
   Parameters:                                                          03234000
      dst -  DST number of data segment.                                03236000
      offset - Offset relative to the beginning of the data             03238000
               segment, of the data to move.                            03240000
      count - Number of words to move.                                  03242000
      target - Array in stack to move data to.                          03244000
                                                                        03246000
   Assumptions on entry:                                                03248000
      None.                                                             03250000
                                                                        03252000
   Exit conditions:                                                     03254000
      DB is unchanged.                                                  03256000
                                                                        03258000
   Globals:                                                             03260000
      None.                                                             03262000
                                                                        03264000
   Externals:                                                           03266000
      None.                                                             03268000
                                                                        03270000
   Intrinsics:                                                          03272000
      None.                                                             03274000
                                                                        03276000
   Callers:                                                             03278000
      Process'Dfs'Error                                                 03280000
      Send'Process'Dfs'Error                                            03282000
      Create'Dfs'Data'Seg                                               03284000
      Delete'Dfs'Data'Seg                                               03286000
      Allocate'Dfs'Data'Seg                                             03288000
      Process'Sys'Disc'Free'Space'Maps                                  03290000
      VINIT module 32                                                   03292000
                                                                        03294000
   Changes:                                                             03296000
                                                                        03298000
                                                                        03300000
==============================================================>>        03302000
                                                                        03304000
BEGIN                                                                   03306000
                                                                        03308000
   TOS := @target;                                                      03310000
   TOS := dst;                                                          03312000
   TOS := offset;                                                       03314000
   TOS := count;                                                        03316000
                                                                        03318000
   ASSEMBLE(MFDS 4);                                                    03320000
                                                                        03322000
END;  << Move'From'Data'Seg >>                                          03324000
$PAGE "MOVE'TO'DATA'SEG"                                                03326000
                                                                        03328000
PROCEDURE Move'To'Data'Seg (source, count, dst, offset);                03330000
   VALUE count, dst, offset;                                            03332000
   ARRAY source;                                                        03334000
   INTEGER count, dst, offset;                                          03336000
   OPTION PRIVILEGED,UNCALLABLE;                                        03338000
                                                                        03340000
<<==============================================================        03342000
                                                                        03344000
      This procedure does a move to data segment.                       03346000
                                                                        03348000
   Parameters:                                                          03350000
      source - Array in stack to move data from.                        03352000
      count - Number of words to move.                                  03354000
      dst - DST number of data segment to move data to.                 03356000
      offset - Data segment relative offset of starting                 03358000
               location to move data to.                                03360000
                                                                        03362000
   Assumptions on entry:                                                03364000
      None.                                                             03366000
                                                                        03368000
   Exit conditions:                                                     03370000
      DB is unchanged.                                                  03372000
                                                                        03374000
   Globals:                                                             03376000
      None.                                                             03378000
                                                                        03380000
   Externals:                                                           03382000
      None.                                                             03384000
                                                                        03386000
   Intrinsics:                                                          03388000
      None.                                                             03390000
                                                                        03392000
   Callers:                                                             03394000
      Process'Dfs'Error                                                 03396000
      Send'Process'Dfs'Error                                            03398000
      Create'Dfs'Data'Seg                                               03400000
      Delete'Dfs'Data'Seg                                               03402000
      Allocate'Dfs'Data'Seg                                             03404000
      Process'Sys'Disc'Free'Space'Maps                                  03406000
                                                                        03408000
   Changes:                                                             03410000
                                                                        03412000
                                                                        03414000
==============================================================>>        03416000
                                                                        03418000
BEGIN                                                                   03420000
                                                                        03422000
   TOS := dst;                                                          03424000
   TOS := offset;                                                       03426000
   TOS := @source;                                                      03428000
   TOS := count;                                                        03430000
                                                                        03432000
   ASSEMBLE (MTDS 4);                                                   03434000
                                                                        03436000
END;  << Move'To'Data'Seg >>                                            03438000
$PAGE "GET'DISC'INFO"                                                   03440000
LOGICAL PROCEDURE Get'Disc'Info (ldev, disc'label, read'label, dtt,     03442000
                                 type, subtype, disc'size,              03444000
                                 bit'map'address, bit'map'size'pages,   03446000
                                 dt'address, dt'size'words,             03448000
                                 dt'dirty'flag, number'of'buffers,      03450000
                                 dt'check'sum, sectors'per'track,       03452000
                                 default'logical'pack'size,             03454000
                                 max'logical'pack'size,                 03456000
                                 tracks'per'cylinder,                   03458000
                                 starting'head'number,                  03460000
                                 track'multiplier);                     03462000
                                                                        03464000
   VALUE ldev, read'label;                                              03466000
   INTEGER ldev;                                                        03468000
   ARRAY disc'label;                                                    03470000
   LOGICAL read'label;                                                  03472000
   INTEGER ARRAY dtt;                                                   03474000
   INTEGER type;                                                        03476000
   INTEGER subtype;                                                     03478000
   DOUBLE disc'size;                                                    03480000
   DOUBLE bit'map'address;                                              03482000
   INTEGER bit'map'size'pages;                                          03484000
   DOUBLE dt'address;                                                   03486000
   INTEGER dt'size'words;                                               03488000
   LOGICAL dt'dirty'flag;                                               03490000
   INTEGER number'of'buffers;                                           03492000
   LOGICAL dt'check'sum;                                                03494000
   INTEGER sectors'per'track;                                           03496000
   INTEGER default'logical'pack'size;                                   03498000
   INTEGER max'logical'pack'size;                                       03500000
   INTEGER tracks'per'cylinder;                                         03502000
   INTEGER starting'head'number;                                        03504000
   INTEGER track'multiplier;                                            03506000
   OPTION VARIABLE,PRIVILEGED,UNCALLABLE;                               03508000
                                                                        03510000
<<==============================================================        03512000
                                                                        03514000
                                                                        03516000
      This procedure returns all sorts of information about a           03518000
   particular disc ldev.  The information returned is de-               03520000
   scribed below, but a few notes are necessary about the               03522000
   "disc'label", "read'label", and "dtt" parameters.  If                03524000
   "disc'label" is passed and "read'label" is FALSE or omit-            03526000
   ted, then "disc'label" is assumed to be a valid copy of              03528000
   the "disc'label" for the ldev. If "read'label" is TRUE,              03530000
   then the disc label is read into the buffer.  If                     03532000
   "disc'label" is not passed and a copy of the disc label is           03534000
   needed to return other info that was requested, then a               03536000
   local buffer is allocated and the disc label is read into            03538000
   it.  The "dtt" buffer is used for returning the defective            03540000
   tracks table only. If it is not passed, and the DTT is               03542000
   needed, a local buffer is allocated and the DTT read into            03544000
   it.                                                                  03546000
                                                                        03548000
                                                                        03550000
   Parameters:                                                          03552000
      ldev - Logical device number of disc drive.                       03554000
      disc'label - (optional) - buffer for disc label or                03556000
                   containing disc label, see above comment.            03558000
      read'label - (optional) - TRUE = read in disc label,              03560000
                   FALSE don't read label, see above comment.           03562000
      dtt - (optional) - buffer for returning defective                 03564000
            tracks table, (NOT for defective sectors                    03566000
            devices).                                                   03568000
      type - (optional) - for return of device type code.               03570000
      subtype - (optional) - For return of subtype code.                03572000
      disc'size - (optional) - For return of logical size of            03574000
                  disc in sectors.                                      03576000
      bit'map'address - (optional) - For return of disc                 03578000
                        addreess of disc free space bit map.            03580000
      bit'map'size'pages - (optional) - For return of the               03582000
                           size of the bit map (in pages).              03584000
      dt'address - (optional) - For return of the disc                  03586000
                   address of the disc free space descriptor            03588000
                   table.                                               03590000
      dt'size'words - (optional) - For return  of the size of           03592000
                      the descriptor table (in words).                  03594000
      dt'dirty'flag - (optional) - For return of the value of           03596000
                      the descriptor table dirty flag from              03598000
                      the disc label.                                   03600000
      number'of'buffers - (optional) - Number of buffer to be           03602000
                          used for the disc free space map              03604000
                          for this ldev.                                03606000
      dt'check'sum - (optional) - For return of the                     03608000
                     descriptor table checksum from the disc            03610000
                     label.                                             03612000
      sectors'per'track - (optional) - For return of the the            03614000
                          number of sectors per track.                  03616000
      default'logical'pack'size - (optional) - For return of            03618000
                                  default logical pack size.            03620000
      max'logical'pack'size - (optional) - For return of                03622000
                              maximum logical pack size.                03624000
      tracks'per'cylinder - (optional) - For return of number           03626000
                            of tracks per cylinder.                     03628000
      starting'head'number - (optional) - For return of                 03630000
                             starting head number.                      03632000
      track'multiplier - (optional) - For return of the track           03634000
                         multiplier.  This value is to con-             03636000
                         vert a track number to a cylinder &            03638000
                         head number.  It is only needed for            03640000
                         the 7900 disc.  For all other discs            03642000
                         it has a value of 1.                           03644000
                                                                        03646000
   Assumptions on entry:                                                03648000
      DB is at the stack.                                               03650000
                                                                        03652000
   Exit conditions:                                                     03654000
      DB is unchanged.                                                  03656000
                                                                        03658000
   Globals:                                                             03660000
                                                                        03662000
      Others:                                                           03664000
         mh'tracks'per'cylinder {INCDISC2}                              03666000
         mh'sectors'per'track {INCDISC2}                                03668000
         mh'default'logical'pack'size {INCDISC2}                        03670000
         fh'log'pack'size {INCDISC2}                                    03672000
         mh'max'log'pack'size {INCDISC2}                                03674000
         mh'tracks'per'cylinder {INCDISC2}                              03676000
         mh'starting'head'number {INCDISC2}                             03678000
         lpdt                                                           03680000
                                                                        03682000
      Equates:                                                          03684000
         sector'size                                                    03686000
         mh'disc'type {INCDISC1}                                        03688000
         fh'disc'type {INCDISC1}                                        03690000
         floppy'disc'type {INCDISC1}                                    03692000
         cs'80'type {INCDISC1}                                          03694000
         dtt'logical'pack'size {INCDISC1}                               03696000
         fh'sectors'per'track {INCDISC2}                                03698000
         bits'per'page                                                  03700000
         disc'lab'map'high {INCDISC1}                                   03702000
         disc'lab'map'low {INCDISC1}                                    03704000
         disc'lab'dt'high {INCDISC1}                                    03706000
         disc'lab'dt'low {INCDISC1}                                     03708000
         dt'entry'size                                                  03710000
         disc'lab'dirty'dt'flag {INCDISC1}                              03712000
         disc'lab'dt'check'sum {INCDISC1}                               03714000
         fh'tracks'per'cylinder {INCDISC2}                              03716000
         fh'starting'head'number {INCDISC2}                             03718000
         mh'track'multiplier {INCDISC2}                                 03720000
         fh'track'multiplier {INCDISC2}                                 03722000
         disc'label'read'error {INCLDFS2}                               03724000
         dtt'read'error {INCLDFS2}                                      03726000
         fp'single'tracks'per'cylinder {INCDISC2}                       03728000
         fp'double'tracks'per'cylinder {INCDISC2}                       03730000
         get'vol'limit'io'func                                          03732000
         no'error {INCLDFS2}                                            03734000
         disc'limit'read'error {INCLDFS2}                               03736000
         lptd'entry'size                                                03738000
         fp'default'log'pack'size {INCDISC2}                            03740000
         fp'max'log'pack'size {INCDISC2}                                03742000
         fp'starting'head'number {INCDISC2}                             03744000
         fp'track'multiplier {INCDISC2}                                 03746000
                                                                        03748000
      Defines:                                                          03750000
         disc'label'address {INCDISC1}                                  03752000
         dtt'disc'address {INCDISC1}                                    03754000
         DBL                                                            03756000
         error'type                                                     03758000
         Check'If'Disc                                                  03760000
         lpdt'pv                                                        03762000
                                                                        03764000
   Externals:                                                           03766000
      Ldevtotype                                                        03768000
      Ldevtosubtype                                                     03770000
      Suddendeath - (X3 = ON bug catcher)                               03772000
      Read'Disc                                                         03774000
      Reqstatus                                                         03776000
      Attachio                                                          03778000
                                                                        03780000
   Intrinsics:                                                          03782000
      None.                                                             03784000
                                                                        03786000
   Callers:                                                             03788000
      Page'Io'Error                                                     03790000
      Create'Dfs'Data'Seg                                               03792000
      Deallocate'Dfs'Data'Seg                                           03794000
      VINIT module 32                                                   03796000
                                                                        03798000
   Changes:                                                             03800000
                                                                        03802000
                                                                        03804000
==============================================================>>        03806000
                                                                        03808000
BEGIN                                                                   03810000
                                                                        03812000
   << Parameter map definitions >>                                      03814000
                                                                        03816000
   LOGICAL pmap0 = Q-5,                                                 03818000
           pmap1 = Q-4;                                                 03820000
                                                                        03822000
   DEFINE                                                               03824000
      passed'ldev = pmap0.(12:1)#,                                      03826000
      passed'disc'label = pmap0.(13:1)#,                                03828000
      passed'read'label = pmap0.(14:1)#,                                03830000
      passed'dtt = pmap0.(15:1)#,                                       03832000
      passed'type = pmap1.(0:1)#,                                       03834000
      passed'subtype = pmap1.(1:1)#,                                    03836000
      passed'disc'size = pmap1.(2:1)#,                                  03838000
      passed'b'm'address = pmap1.(3:1)#,                                03840000
      passed'b'm'size'pages = pmap1.(4:1)#,                             03842000
      passed'dt'address = pmap1.(5:1)#,                                 03844000
      passed'dt'size'words = pmap1.(6:1)#,                              03846000
      passed'dt'dirty'flag = pmap1.(7:1)#,                              03848000
      passed'number'of'buffer = pmap1.(8:1)#,                           03850000
      passed'dt'check'sum = pmap1.(9:1)#,                               03852000
      passed'sectors'per'track = pmap1.(10:1)#,                         03854000
      passed'default'logical'pack'size = pmap1.(11:1)#,                 03856000
      passed'max'logical'pack'size = pmap1.(12:1)#,                     03858000
      passed'tracks'per'cylinder = pmap1.(13:1)#,                       03860000
      passed'starting'head'number = pmap1.(14:1)#,                      03862000
      passed'track'multiplier = pmap1.(15:1)#;                          03864000
                                                                        03866000
   << Local vars to hold values that are needed to generate             03868000
      info that is to be returned.                          >>          03870000
                                                                        03872000
   INTEGER local'type;                                                  03874000
   INTEGER local'subtype;                                               03876000
   DOUBLE local'disc'size;                                              03878000
   INTEGER ARRAY vector'volume'limit (0:2) = Q;                         03880000
   INTEGER local'bit'map'size'pages;                                    03882000
   INTEGER floppy'tracks'per'cylinder;                                  03884000
                                                                        03886000
   LOGICAL return'status = Get'Disc'Info;                               03888000
                                                                        03890000
$SET X7=ON                                                              03892000
$INCLUDE INCDISC2                                                       03894000
                                                                        03896000
                                                                        03898000
   << - - - - - - - - - - >>                                            03900000
                                                                        03902000
$IF X3=ON  << BUG CATCHER >>                                            03904000
                                                                        03906000
   << Check for situations that should not be. >>                       03908000
                                                                        03910000
   IF NOT passed'ldev THEN                                              03912000
      Suddendeath (421);                                                03914000
   IF NOT passed'disc'label AND passed'read'label AND read'label THEN   03916000
      Suddendeath (421);                                                03918000
                                                                        03920000
   << Check if its really a disc >>                                     03922000
                                                                        03924000
   TOS := ldev;                                                         03926000
   Check'If'Disc;                                                       03928000
   IF NOT TOS THEN                                                      03930000
      Suddendeath (421);                                                03932000
                                                                        03934000
$IF        << BUG CATCHER >>                                            03936000
                                                                        03938000
                                                                        03940000
   << Get type and subtype >>                                           03942000
                                                                        03944000
   local'type := Ldevtotype (ldev);                                     03946000
   local'subtype := Ldevtosubtype (ldev);                               03948000
                                                                        03950000
   << Check and see if we need to allocate a buffer for the             03952000
      disc label, (i.e. disc'label was not passed, but information      03954000
      is needed from the disc label to return other info).         >>   03956000
                                                                        03958000
   IF (passed'b'm'address OR passed'dt'address OR passed'dt'dirty)      03960000
   AND NOT passed'disc'label THEN                                       03962000
      BEGIN  << Allocate disc label buffer >>                           03964000
                                                                        03966000
         PUSH (S);                                                      03968000
         @disc'label := TOS + 1;  << ptr to buffer >>                   03970000
         TOS := sector'size + 1;  << size of buffer >>                  03972000
         ASSEMBLE (ADDS 0);                                             03974000
                                                                        03976000
         << Remember to read the label >>                               03978000
                                                                        03980000
         read'label := TRUE;                                            03982000
                                                                        03984000
      END    << Allocate disc label buffer >>                           03986000
   ELSE                                                                 03988000
      IF NOT passed'read'label THEN                                     03990000
         read'label := FALSE;                                           03992000
                                                                        03994000
   << Read in disc label if needed. >>                                  03996000
                                                                        03998000
   IF read'label THEN                                                   04000000
      BEGIN  << Read disc label >>                                      04002000
                                                                        04004000
         return'status := Read'Disc (ldev, disc'label'address, 0,       04006000
                                     disc'label, sector'size);          04008000
         IF NOT return'status THEN                                      04010000
            BEGIN  << I/O error >>                                      04012000
                                                                        04014000
               return'status.error'type := disc'label'read'error;       04016000
               RETURN;  << Exit procedure >>                            04018000
                                                                        04020000
            END;   << I/O error >>                                      04022000
                                                                        04024000
     END;   << Read disc label >>                                       04026000
                                                                        04028000
   << Read in defective tracks table, if we will need it. >>            04030000
                                                                        04032000
   IF passed'dtt OR (passed'disc'size LAND                              04034000
   NOT (local'type = cs'80'type)) OR                                    04036000
   passed'b'm'size'pages OR passed'dt'size'words THEN                   04038000
      BEGIN  << Read in DTT >>                                          04040000
                                                                        04042000
         << Allocate buffer for DTT if not passsed >>                   04044000
                                                                        04046000
         IF NOT passed'dtt THEN                                         04048000
            BEGIN  << Allocate DTT buffer >>                            04050000
                                                                        04052000
               PUSH (S);                                                04054000
               @dtt := TOS + 1;                                         04056000
               TOS := sector'size + 1;                                  04058000
               ASSEMBLE (ADDS 0);                                       04060000
                                                                        04062000
            END;   << Allocate DTT buffer >>                            04064000
                                                                        04066000
         return'status := Read'Disc (ldev, dtt'disc'address, 0, dtt,    04068000
                                     sector'size);                      04070000
         IF NOT return'status THEN                                      04072000
            BEGIN  << I/O error >>                                      04074000
                                                                        04076000
              return'status.error'type := dtt'read'error;               04078000
              RETURN;                                                   04080000
                                                                        04082000
            END;   << I/O error >>                                      04084000
                                                                        04086000
                                                                        04088000
      END;   << Read in DTT >>                                          04090000
                                                                        04092000
   << If this is one of those shitty floppies, determine if it          04094000
      is single or double sided and set floppy'tracks'per'cylinder  >>  04096000
                                                                        04098000
   IF local'type = floppy'disc'type THEN                                04100000
      BEGIN  << Floppy >>                                               04102000
                                                                        04104000
         TOS := Reqstatus (ldev);                                       04106000
         IF TOS.(4:1) = 0 THEN                                          04108000
            floppy'tracks'per'cylinder :=                               04110000
                fp'single'tracks'per'cylinder                           04112000
         ELSE                                                           04114000
            floppy'tracks'per'cylinder :=                               04116000
                fp'double'tracks'per'cylinder;                          04118000
         DEL;  << Delete remaining status word >>                       04120000
                                                                        04122000
      END;   << Floppy >>                                               04124000
                                                                        04126000
   << Determine size of disc and size of bit map. >>                    04128000
                                                                        04130000
   IF passed'disc'size OR passed'b'm'size'pages OR                      04132000
   passed'dt'size'words THEN                                            04134000
      BEGIN  << Calculate size of disc >>                               04136000
                                                                        04138000
         IF local'type = mh'disc'type THEN                              04140000
            local'disc'size := DBL(dtt(dtt'logical'pack'size)) *        04142000
                  DBL(mh'tracks'per'cylinder (local'subtype)) *         04144000
                  DBL(mh'sectors'per'track (local'subtype))             04146000
                                                                        04148000
         ELSE                                                           04150000
         IF local'type = fh'disc'type THEN                              04152000
            local'disc'size := DBL(dtt(dtt'logical'pack'size)) *        04154000
                  DBL(fh'sectors'per'track)                             04156000
                                                                        04158000
         ELSE                                                           04160000
         IF local'type = floppy'disc'type THEN                          04162000
            local'disc'size := DBL(dtt(dtt'logical'pack'size)) *        04164000
                  DBL(floppy'tracks'per'cylinder) *                     04166000
                  DBL(fp'sectors'per'track)                             04168000
                                                                        04170000
         ELSE                                                           04172000
         IF local'type = cs'80'type THEN                                04174000
            BEGIN  << Command set 80 disc >>                            04176000
                                                                        04178000
               TOS := Attachio (ldev, 0, 0, @local'disc'size,           04180000
                                 get'vol'limit'io'func,-2,0,0, <<04388>>04182000
                                blocked'io'flag);                       04184000
               DEL;  << Delete transmission log >>                      04186000
                                                                        04188000
               << Convert to standard format status word >>             04190000
                                                                        04192000
               return'status := TOS&LSL(8) + no'error;                  04194000
               IF return'status.general'io'status <> ok'io'status THEN  04196000
                  BEGIN  << I/O error >>                                04198000
                                                                        04200000
                     return'status.error'type := disc'limit'read'error; 04202000
                     RETURN;                                            04204000
                                                                        04206000
                  END;   << I/O error >>                                04208000
                                                                        04210000
               << The value returned is actually the max sector         04212000
                  address, so convert it to disc size.           >>     04214000
                                                                        04216000
               local'disc'size := local'disc'size + 1D;                 04218000
                                                                        04220000
            END    << Command set 89 disc >>                            04222000
                                                                        04224000
         ELSE;                                                          04226000
                                                                        04228000
         local'bit'map'size'pages := local'disc'size // bits'per'page;  04230000
         IF (local'disc'size MODD bits'per'page) <> 0 THEN              04232000
            local'bit'map'size'pages := local'bit'map'size'pages + 1;   04234000
                                                                        04236000
      END;   << Calculate size of disc >>                               04238000
                                                                        04240000
   << Get volume limit in vector form for cs'80 device if it            04242000
      will be needed.                                        >>         04244000
                                                                        04246000
   IF                                                                   04248000
   (local'type = cs'80'type)                                   <<03780>>04250000
           AND                                                          04252000
   (passed'sectors'per'track                                            04254000
           OR                                                           04256000
    passed'tracks'per'cylinder)                                         04258000
   THEN                                                                 04260000
      BEGIN  << Get vector volume limit >>                              04262000
                                                                        04264000
         TOS := Attachio (ldev, 0, 0, @vector'volume'limit,             04266000
                          get'vol'limit'io'func, -2, 1, 0,     <<03780>>04268000
                          blocked'io'flag);                             04270000
         DEL;                                                           04272000
                                                                        04274000
         << Convert to standard format error word >>                    04276000
                                                                        04278000
         return'status := TOS&LSL(8) + no'error;                        04280000
         IF return'status.general'io'status <> ok'io'status THEN        04282000
            BEGIN  << I/O error >>                                      04284000
                                                                        04286000
               return'status.error'type := disc'limit'read'error;       04288000
               RETURN;                                                  04290000
                                                                        04292000
            END;   << I/O error >>                                      04294000
                                                                        04296000
      END;   << Get vector volume limit >>                              04298000
                                                                        04300000
                                                                        04302000
   << Return values for passed parameters. >>                           04304000
                                                                        04306000
   IF passed'type THEN                                                  04308000
      type := local'type;                                               04310000
                                                                        04312000
   IF passed'subtype THEN                                               04314000
      subtype := local'subtype;                                         04316000
                                                                        04318000
   IF passed'disc'size THEN                                             04320000
      disc'size := local'disc'size;                                     04322000
                                                                        04324000
   IF passed'b'm'address THEN                                           04326000
      BEGIN  << return bit map address >>                               04328000
                                                                        04330000
         TOS := disc'label (disc'lab'map'high);                         04332000
         TOS := disc'label (disc'lab'map'low);                          04334000
         bit'map'address := TOS;                                        04336000
                                                                        04338000
      END;   << Return bit map address >>                               04340000
                                                                        04342000
   IF passed'b'm'size'pages THEN                                        04344000
      bit'map'size'pages := local'bit'map'size'pages;                   04346000
                                                                        04348000
   IF passed'dt'address THEN                                            04350000
      BEGIN  << Descriptor table address >>                             04352000
                                                                        04354000
         TOS := disc'label (disc'lab'dt'high);                          04356000
         TOS := disc'label (disc'lab'dt'low);                           04358000
         dt'address := TOS;                                             04360000
                                                                        04362000
      END;   << descriptor table address >>                             04364000
                                                                        04366000
   IF passed'dt'size'words THEN                                         04368000
      BEGIN  << Return size of descriptor table >>                      04370000
                                                                        04372000
         dt'size'words := local'bit'map'size'pages * dt'entry'size;     04374000
                                                                        04376000
         << Increment size if it is odd, thus making it even. This      04378000
            is necessary so "Make'Check'Sum" will have an even          04380000
            number of words to work with.  This will mean that a        04382000
            word may be wasted. Big shit.                         >>    04384000
                                                                        04386000
         IF dt'size'words.(15:1) = 1 THEN                               04388000
            dt'size'words := dt'size'words + 1;                         04390000
                                                                        04392000
      END;   << Return size of descriptor table >>                      04394000
                                                                        04396000
   IF passed'dt'dirty'flag THEN                                         04398000
      dt'dirty'flag := disc'label (disc'lab'dirty'dt'flag);             04400000
                                                                        04402000
   IF passed'number'of'buffers THEN                                     04404000
      BEGIN  << Return number of DFS buffers >>                         04406000
                                                                        04408000
$IF X2=ON  << USE DIRTY BUFFER MANAGEMENT >>                            04410000
                                                                        04412000
         IF NOT lpdt((ldev * lpdt'entry'size) + lpdt'pv) THEN           04414000
            BEGIN  << System disc >>                                    04416000
                                                                        04418000
               number'of'buffers := 3;                                  04420000
                                                                        04422000
            END    << System disc >>                                    04424000
         ELSE                                                           04426000
            BEGIN  << Private volume >>                                 04428000
                                                                        04430000
               IF local'type = floppy'disc'type THEN                    04432000
                  number'of'buffers := 1                                04434000
               ELSE                                                     04436000
                  number'of'buffers := 2;                               04438000
                                                                        04440000
            END;   << Private volume >>                                 04442000
                                                                        04444000
$IF X2=OFF << DON'T USE DIRTY BUFFER MANAGEMENT >>                      04446000
                                                                        04448000
         IF NOT lpdt((ldev * lpdt'entry'size) + lpdt'pv) THEN           04450000
            BEGIN  << System disc >>                                    04452000
                                                                        04454000
               number'of'buffers := 10;                                 04456000
                                                                        04458000
            END    << System disc >>                                    04460000
         ELSE                                                           04462000
            BEGIN  << Private volume >>                                 04464000
                                                                        04466000
               IF local'type = floppy'disc'type THEN                    04468000
                  number'of'buffers := 1                                04470000
               ELSE                                                     04472000
                  number'of'buffers := 5;                               04474000
                                                                        04476000
            END;   << Private volume >>                                 04478000
                                                                        04480000
$IF                                                                     04482000
                                                                        04484000
      END;   << Return number of DFS buffers >>                         04486000
                                                                        04488000
   IF passed'dt'check'sum THEN                                          04490000
         dt'check'sum := disc'label (disc'lab'dt'check'sum);            04492000
                                                                        04494000
   IF passed'sectors'per'track THEN                                     04496000
      BEGIN   << Return sectors per track >>                            04498000
                                                                        04500000
         IF local'type = mh'disc'type THEN                              04502000
            sectors'per'track := mh'sectors'per'track (local'subtype)   04504000
                                                                        04506000
         ELSE                                                           04508000
         IF local'type = fh'disc'type THEN                              04510000
            sectors'per'track := fh'sectors'per'track                   04512000
                                                                        04514000
         ELSE                                                           04516000
         IF local'type = floppy'disc'type THEN                          04518000
            sectors'per'track := fp'sectors'per'track                   04520000
                                                                        04522000
         ELSE                                                           04524000
         IF local'type = cs'80'type THEN                                04526000
            sectors'per'track := vector'volume'limit(1).(8:8)+1<<03780>>04528000
                                                                        04530000
         ELSE;                                                          04532000
                                                                        04534000
      END;    << Return sectors per track >>                            04536000
                                                                        04538000
   IF passed'default'logical'pack'size THEN                             04540000
      BEGIN  << Return default logical pack size >>                     04542000
                                                                        04544000
         IF local'type = mh'disc'type THEN                              04546000
            default'logical'pack'size :=                                04548000
                  mh'default'log'pack'size (local'subtype)              04550000
                                                                        04552000
         ELSE                                                           04554000
         IF local'type = fh'disc'type THEN                              04556000
            default'logical'pack'size :=                                04558000
                  fh'log'pack'size (local'subtype)                      04560000
                                                                        04562000
         ELSE                                                           04564000
         IF local'type = floppy'disc'type THEN                          04566000
            default'logical'pack'size :=                                04568000
                  fp'default'log'pack'size                              04570000
                                                                        04572000
         ELSE                                                           04574000
         IF local'type = cs'80'type THEN                                04576000
            default'logical'pack'size := 0   << Not valid for cs'80 >>  04578000
                                                                        04580000
         ELSE;                                                          04582000
                                                                        04584000
      END;   << Return default logical pack size >>                     04586000
                                                                        04588000
   IF passed'max'logical'pack'size THEN                                 04590000
      BEGIN  << Return max logical pack size >>                         04592000
                                                                        04594000
         IF local'type = mh'disc'type THEN                              04596000
            max'logical'pack'size :=                                    04598000
                  mh'max'log'pack'size (local'subtype)                  04600000
                                                                        04602000
         ELSE                                                           04604000
         IF local'type = fh'disc'type THEN                              04606000
            max'logical'pack'size :=                                    04608000
                  fh'log'pack'size (local'subtype)                      04610000
                                                                        04612000
         ELSE                                                           04614000
         IF local'type = floppy'disc'type THEN                          04616000
            max'logical'pack'size :=                                    04618000
                  fp'max'log'pack'size                                  04620000
                                                                        04622000
         ELSE                                                           04624000
         IF local'type = cs'80'type THEN                                04626000
            max'logical'pack'size := 0   << Not valid for cs'80 dev >>  04628000
                                                                        04630000
         ELSE;                                                          04632000
                                                                        04634000
      END;   << Return max logical pack size >>                         04636000
                                                                        04638000
   IF passed'tracks'per'cylinder THEN                                   04640000
      BEGIN  << Return tracks per cylinder >>                           04642000
                                                                        04644000
         IF local'type = mh'disc'type THEN                              04646000
            tracks'per'cylinder :=                                      04648000
                  mh'tracks'per'cylinder (local'subtype)                04650000
                                                                        04652000
         ELSE                                                           04654000
         IF local'type = fh'disc'type THEN                              04656000
               tracks'per'cylinder := fh'tracks'per'cylinder            04658000
                                                                        04660000
         ELSE                                                           04662000
         IF local'type = floppy'disc'type THEN                          04664000
            tracks'per'cylinder := floppy'tracks'per'cylinder           04666000
                                                                        04668000
         ELSE                                                           04670000
         IF local'type = cs'80'type THEN                                04672000
            tracks'per'cylinder:=vector'volume'limit(1).(0:8)+1<<03780>>04674000
                                                                        04676000
         ELSE;                                                          04678000
                                                                        04680000
     END;   << Return tracks per cylinder >>                            04682000
                                                                        04684000
  IF passed'starting'head'number THEN                                   04686000
     BEGIN  << Return starting head number >>                           04688000
                                                                        04690000
        IF local'type = mh'disc'type THEN                               04692000
           starting'head'number :=                                      04694000
                mh'starting'head'number (local'subtype)                 04696000
                                                                        04698000
        ELSE                                                            04700000
        IF local'type = fh'disc'type THEN                               04702000
           starting'head'number := fh'starting'head'number              04704000
                                                                        04706000
        ELSE                                                            04708000
        IF local'type = floppy'disc'type THEN                           04710000
           starting'head'number := fp'starting'head'number              04712000
                                                                        04714000
        ELSE                                                            04716000
        IF local'type = cs'80'type THEN                                 04718000
           starting'head'number := 0                                    04720000
                                                                        04722000
        ELSE;                                                           04724000
                                                                        04726000
     END;  << Return starting head number >>                            04728000
                                                                        04730000
                                                                        04732000
   << Return track multiplier, this value is a kludge for the           04734000
      7900 disc, which is also a kludge.                      >>        04736000
                                                                        04738000
   IF passed'track'multiplier THEN                                      04740000
      BEGIN  << Return track multiplier >>                              04742000
                                                                        04744000
         IF local'type = mh'disc'type THEN                              04746000
            track'multiplier :=                                         04748000
                  mh'track'multiplier (local'subtype)                   04750000
                                                                        04752000
         ELSE                                                           04754000
         IF local'type = fh'disc'type THEN                              04756000
            track'multiplier := fh'track'multiplier                     04758000
                                                                        04760000
         ELSE                                                           04762000
         IF local'type = floppy'disc'type THEN                          04764000
            track'multiplier := fp'track'multiplier                     04766000
                                                                        04768000
         ELSE                                                           04770000
         IF local'type = cs'80'type THEN                                04772000
             track'multiplier := 1  << Not valid for cs'80 disc >>      04774000
                                                                        04776000
         ELSE;                                                          04778000
                                                                        04780000
      END;   << Return track multiplier >>                              04782000
                                                                        04784000
                                                                        04786000
   return'status := no'error;                                           04788000
                                                                        04790000
END;   << Get'Disc'Info >>                                              04792000
$PAGE "PROCEDURE PROCESS'DFS'ERROR"                                     04794000
PROCEDURE Process'Dfs'Error (ldev, error'status, type'of'error);        04796000
   VALUE ldev, error'status, type'of'error;                             04798000
   INTEGER ldev;                                                        04800000
   LOGICAL error'status;                                                04802000
   INTEGER type'of'error;                                               04804000
   OPTION PRIVILEGED,UNCALLABLE;                                        04806000
                                                                        04808000
<<==============================================================        04810000
                                                                        04812000
      This procedure handles errors that are  fatal  to  free           04814000
   space allocation/deallocation on a particular device.  The           04816000
   errors fit in five catagories: physical mount error,  log-           04818000
   ical  mount error, logical dismount error, damaged bit map           04820000
   error and unexpected error.   An  appropriate  message  is           04822000
   sent  to  the console, including the ldev number and other           04824000
   information, such as the status  returned  by  "Attachio".           04826000
   Free  space  allocation/deallocation  is  disabled on that           04828000
   ldev by setting the "ldtx'dfs'error'word" in the LDTX entry          04830000
   for that ldev. If a damaged bit map error occured, then a            04832000
   flag is set in the "disc'lab'dfs'map'ok" field of the disc           04834000
   label to  prevent the pack from being mounted without                04836000
   recovering the free space map.  Soft'Death (422) is called           04838000
   before processing begins, so if the Soft'Death flag is set           04840000
   the system will crash.  This may be usefull for finding              04842000
   problems in the field.                                               04844000
                                                                        04846000
                                                                        04848000
   Parameters:                                                          04850000
      ldev - ldev of disc.                                              04852000
      error'status - standard format error status word that             04854000
                     indicated what type of error occured.              04856000
      type'of'error - Further info about what was going on              04858000
                      when the error occured, it can have the           04860000
                      following values:                                 04862000
                    0 = Physical mount error.                           04864000
                    1 = Logical mount error.                            04866000
                    2 = Logical dismount error.                         04868000
                    3 = Damaged bit map error (i.e. the bits            04870000
                        aren't what we expected).                       04872000
                    4 = Unexpected error. (Catch-all for                04874000
                        errors we don't know how to deal                04876000
                        with).  Bits 0:8 contain an i.d.                04878000
                        number that is printed with the                 04880000
                        message, each call should have a                04882000
                        unique number to make it easy to                04884000
                        these problems.                                 04886000
                        ID = 5 (Set'Reset'Bit'Map),            ((si.42))04888000
                        ID = 6 (Locate'Free'Space) -           ((si.42))04890000
                        discrepancy between Descriptor Table   ((si.42))04892000
                        and Bit Map,                           ((si.42))04894000
                        ID = 7 (Diskdealloc) - corrupted a     ((si.42))04896000
                        file usage count in LDT,               ((si.42))04898000
                        ID = 8 (Lock'Dfs'Data'Seg) - bad DFS   ((si.42))04900000
                        data seg,                              ((si.42))04902000
                        ID = 9 (Unlock'Dfs'Data'Seg),          ((si.42))04904000
                        ID = 10 (Return'Disc'Space) - returned ((si.42))04906000
                        space belongs to restricted area,      ((si.42))04908000
                        ID = 11 (Get'Disc'Space).              ((si.42))04910000
                                                                        04912000
   Assumptions on entry:                                                04914000
      DB can be anywhere, but should be at the stack for                04916000
      type'of'error = 0, 1, or 2.                                       04918000
                                                                        04920000
   Exit conditions:                                                     04922000
      DB is unchanged.                                                  04924000
                                                                        04926000
   Globals:                                                             04928000
                                                                        04930000
      Output:                                                           04932000
         LDTX entry for ldev - ldtx'dfs'error'word and                  04934000
                               ldtx'dfs'dst'word fields.                04936000
         DISC LABEL - disc'lab'dfs'map'ok field.                        04938000
         ds'error'status                                                04940000
                                                                        04942000
      Equates:                                                          04944000
         dfs'msg'set'num                                                04946000
         dt'read'error                                                  04948000
         pm'msg'read'dt'error                                           04950000
         dt'write'error                                                 04952000
         pm'msg'write'dt'error                                          04954000
         dtt'read'error                                                 04956000
         pm'msg'read'dtt'error                                          04958000
         get'dst'error                                                  04960000
         pm'msg'get'dst'error                                           04962000
         get'vm'error                                                   04964000
         pm'msg'get'vm'error                                            04966000
         old'dfs'error                                                  04968000
         pm'msg'old'dfs'error                                           04970000
         map'damaged'error                                              04972000
         pm'msg'map'damaged                                             04974000
         disc'limit'read'error                                          04976000
         pm'read'vol'limit'error                                        04978000
         disc'label'read'error                                          04980000
         lm'msg'read'disc'label'error                                   04982000
         disc'label'write'error                                         04984000
         lm'msg'write'disc'label'error                                  04986000
         ld'msg'read'disc'label'error                                   04988000
         ld'msg'write'disc'label'error                                  04990000
         dt'write'error                                                 04992000
         ld'msg'dt'write'error                                          04994000
         vinit'error                                                    04996000
         msg'vinit'error                                                04998000
         msg'bit'map'damaged                                            05000000
         msg'unexpected'error                                           05002000
         msg'disable'allocation                                         05004000
         ldt'sir                                                        05006000
         ldt'entry'size                                                 05008000
         ldt'dst                                                        05010000
         ldtx'dfs'error'word                                            05012000
         ldtx'dfs'dst'word                                              05014000
         disc'lab'dfs'map'ok                                            05016000
         sector'size                                                    05018000
                                                                        05020000
      Defines:                                                          05022000
         attach'io'status                                               05024000
         Check'If'Disc                                                  05026000
         error'type                                                     05028000
         disc'label'address                                             05030000
                                                                        05032000
   Externals:                                                           05034000
      Exchangedb                                                        05036000
      Genmsg                                                            05038000
      Soft'Death                                                        05040000
      Suddendeath  (X3 = ON bug catcher)                                05042000
      Getsir                                                            05044000
      Move'From'Data'Seg                                                05046000
      Move'To'Data'Seg                                                  05048000
      Read'Disc                                                         05050000
      Write'Disc'Label                                                  05052000
                                                                        05054000
   Intrinsics:                                                          05056000
      Ascii                                                             05058000
                                                                        05060000
   Callers:                                                             05062000
      Send'Process'Dfs'Error                                            05064000
      PROGEN module 09                                                  05066000
      PVPROC module 31                                                  05068000
      OPCOMMAND module 85                                               05070000
      VINIT module 32                                                   05072000
                                                                        05074000
   Changes:                                                             05076000
                                                                        05078000
                                                                        05080000
==============================================================>>        05082000
                                                                        05084000
BEGIN                                                                   05086000
                                                                        05088000
   << Buffers for coversion to ascii >>                                 05090000
                                                                        05092000
   BYTE ARRAY io'error'buffer (0:6) = Q;                                05094000
                                                                        05096000
   INTEGER caller'dst;                                                  05098000
                                                                        05100000
   INTEGER ldt'sir'info;                                                05102000
   INTEGER ARRAY ldt'entry (0:ldt'entry'size-1) = Q;                    05104000
   INTEGER ldtx'entry'offset;                                           05106000
                                                                        05108000
   ARRAY disc'label (0:sector'size-1) = Q;                              05110000
                                                                        05112000
   INTRINSIC Ascii;                                                     05114000
                                                                        05116000
   << - - - - - - - - - - >>                                            05118000
                                                                        05120000
   << If Soft'Death flag is set, then all will stop here >>             05122000
                                                                        05124000
   Soft'Death (422);                                                    05126000
                                                                        05128000
                                                                        05130000
   caller'dst := Exchangedb (0);    << Set DB to stack >>               05132000
                                                                        05134000
                                                                        05136000
   << Check to see if its really a disc >>                              05138000
                                                                        05140000
   TOS := ldev;                                                         05142000
   Check'If'Disc;                                                       05144000
   IF NOT TOS THEN  Suddendeath (423);                                  05146000
                                                                        05148000
                                                                        05150000
   << Generate message, according to "type'of'error" and                05152000
      "error'status".                                    >>             05154000
                                                                        05156000
   CASE type'of'error.(8:8) OF                                          05158000
      BEGIN  << case >>                                                 05160000
                                                                        05162000
         BEGIN  << 0 = physical mount >>                                05164000
                                                                        05166000
            MOVE io'error'buffer := 7 (0);                              05168000
            Ascii (error'status.attach'io'status, 8, io'error'buffer);  05170000
                                                                        05172000
            IF error'status.error'type = disc'label'read'error <<04281>>05174000
            THEN                                               <<04281>>05176000
                Genmsg (dfs'msg'set'num,                       <<04281>>05178000
                        pm'msg'read'disc'label'error,          <<04281>>05180000
                        [1/0,3/1,3/0,9/0], ldev,               <<04281>>05182000
                        io'error'buffer,                       <<04281>>05184000
                        <<3>>, <<4>>, <<5>>, 0)                <<04281>>05186000
            ELSE                                               <<04281>>05188000
            IF error'status.error'type = disc'label'write'error<<04281>>05190000
            THEN                                               <<04281>>05192000
               Genmsg (dfs'msg'set'num,                        <<04281>>05194000
                       pm'msg'write'disc'label'error,          <<04281>>05196000
                       [1/0,3/1,3/0,9/0], ldev,                <<04281>>05198000
                       io'error'buffer,                        <<04281>>05200000
                       <<3>>, <<4>>, <<5>>, 0)                 <<04281>>05202000
            ELSE                                               <<04281>>05204000
            IF error'status.error'type = dt'read'error THEN             05206000
                Genmsg (dfs'msg'set'num, pm'msg'read'dt'error,          05208000
                        [1/0,3/1,3/0,9/0], ldev, @io'error'buffer,      05210000
                        <<3>>, <<4>>, <<5>>, 0)                         05212000
            ELSE                                                        05214000
            IF error'status.error'type = dt'write'error THEN            05216000
               Genmsg (dfs'msg'set'num, pm'msg'write'dt'error,          05218000
                       [1/0,3/1,3/0,9/0], ldev, @io'error'buffer,       05220000
                       <<3>>, <<4>>, <<5>>, 0)                          05222000
            ELSE                                                        05224000
            IF error'status.error'type = dtt'read'error THEN            05226000
               Genmsg (dfs'msg'set'num, pm'msg'read'dtt'error,          05228000
                       [1/0,3/1,3/0,9/0], ldev, @io'error'buffer,       05230000
                       <<3>>, <<4>>, <<5>>, 0)                          05232000
            ELSE                                                        05234000
            IF error'status.error'type = get'dst'error THEN             05236000
               Genmsg (dfs'msg'set'num, pm'msg'get'dst'error,           05238000
                       [1/0,3/1,12/0], ldev, <<2>>, <<3>>,              05240000
                       <<4>>, <<5>>, 0)                                 05242000
            ELSE                                                        05244000
            IF error'status.error'type = get'vm'error THEN              05246000
               Genmsg (dfs'msg'set'num, pm'msg'get'vm'error,            05248000
                       [1/0,3/1,12/0], ldev, <<2>>, <<3>>,              05250000
                       <<4>>, <<5>>, 0)                                 05252000
            ELSE                                                        05254000
            IF error'status.error'type = old'dfs'error THEN             05256000
               Genmsg (dfs'msg'set'num, pm'msg'old'dfs'error,           05258000
                       [1/0,3/1,12/0], ldev, <<2>>, <<3>>,              05260000
                       <<4>>, <<5>>, 0)                                 05262000
            ELSE                                                        05264000
            IF error'status.error'type = map'damaged'error THEN         05266000
               Genmsg (dfs'msg'set'number, pm'msg'map'damaged,          05268000
                       [1/0,3/1,12/0], ldev, <<2>>, <<3>>, <<4>>,       05270000
                       <<5>>, 0)                                        05272000
            ELSE                                                        05274000
            IF error'status.error'type = disc'limit'read'error THEN     05276000
               Genmsg (dfs'msg'set'number, pm'msg'get'vol'limit'error,  05278000
                       [1/0,3/1,3/0,9/0], ldev, @io'error'buffer,       05280000
                       <<3>>, <<4>>, <<5>>, 0)                          05282000
                                                                        05284000
            ELSE                                                        05286000
                                                                        05288000
$IF X3=ON   << BUG CATCHER >>                                           05290000
               Suddendeath (421);                                       05292000
$IF X3=OFF  << BUG CATCHER >>                                           05294000
               Soft'Death (424);                                        05296000
$IF                                                                     05298000
                                                                        05300000
         END;   << 0 = physical mount >>                                05302000
                                                                        05304000
         << - - - - - - - - - - - - - - - - - - - - - - - - - >>        05306000
                                                                        05308000
         BEGIN  << 1 = Logical mount >>                                 05310000
                                                                        05312000
            MOVE io'error'buffer := 7 (0);                              05314000
            Ascii (error'status.attach'io'status, 8, io'error'buffer);  05316000
                                                                        05318000
            IF error'status.error'type = disc'label'read'error THEN     05320000
                Genmsg (dfs'msg'set'num,                                05322000
                        lm'msg'read'disc'label'error,                   05324000
                        [1/0,3/1,3/0,9/0], ldev, io'error'buffer,       05326000
                        <<3>>, <<4>>, <<5>>, 0)                         05328000
            ELSE                                                        05330000
            IF error'status.error'type = disc'label'write'error THEN    05332000
               Genmsg (dfs'msg'set'num,                                 05334000
                       lm'msg'write'disc'label'error,                   05336000
                       [1/0,3/1,3/0,9/0], ldev, io'error'buffer,        05338000
                       <<3>>, <<4>>, <<5>>, 0)                          05340000
            ELSE                                                        05342000
                                                                        05344000
$IF X3=ON   << BUG CATCHER >>                                           05346000
              Suddendeath (421);                                        05348000
$IF X3=OFF  << BUG CATCHER >>                                           05350000
              Soft'Death (424);                                         05352000
$IF                                                                     05354000
                                                                        05356000
         END;   << 1 = Logical mount >>                                 05358000
                                                                        05360000
         << - - - - - - - - - - - - - - - - - - - - - - - - - >>        05362000
                                                                        05364000
         BEGIN  << 2 = Logical dismount >>                              05366000
                                                                        05368000
            MOVE io'error'buffer := 7 (0);                              05370000
            Ascii (error'status.attach'io'status, 8, io'error'buffer);  05372000
                                                                        05374000
            IF error'status.error'type = disc'label'read'error THEN     05376000
               Genmsg (dfs'msg'set'num,                                 05378000
                       ld'msg'read'disc'label'error,                    05380000
                       [1/0,3/1,3/0,9/0], ldev, @io'error'buffer,       05382000
                       <<3>>, <<4>>, <<5>>, 0)                          05384000
            ELSE                                                        05386000
            IF error'status.error'type = disc'label'write'error THEN    05388000
               Genmsg (dfs'msg'set'num,                                 05390000
                       ld'msg'write'disc'label'error,                   05392000
                       [1/0,3/1,3/0,9/0], ldev, @io'error'buffer,       05394000
                       <<3>>, <<4>>, <<5>>, 0)                          05396000
            ELSE                                                        05398000
            IF error'status.error'type = dt'write'error THEN            05400000
               Genmsg (dfs'msg'set'num,                                 05402000
                       ld'msg'write'dt'error,                           05404000
                       [1/0,3/1,3/0,9/0], ldev, io'error'buffer,        05406000
                       <<3>>, <<4>>, <<5>>, 0)                          05408000
            ELSE                                                        05410000
                                                                        05412000
$IF X3=ON   << BUG CATCHER >>                                           05414000
              Suddendeath (421);                                        05416000
$IF X3=OFF  << BUG CATCHER >>                                           05418000
              Soft'Death (424);                                         05420000
$IF                                                                     05422000
                                                                        05424000
                                                                        05426000
         END;   << 2 = Logical dismount >>                              05428000
                                                                        05430000
         << - - - - - - - - - - - - - - - - - - - - - - - - - >>        05432000
                                                                        05434000
         BEGIN  << 3 = Bit map damaged >>                               05436000
                                                                        05438000
            MOVE io'error'buffer := 7 (0);                              05440000
            Ascii (error'status, 8, io'error'buffer);                   05442000
                                                                        05444000
            << Inform operator about damage, and if it                  05446000
               was caused by VINIT problems.           >>               05448000
                                                                        05450000
            IF error'status.error'type = vinit'error THEN               05452000
               Genmsg (dfs'msg'set'num, msg'vinit'error,                05454000
                       [1/0,3/1,12/0], ldev, <<2>>, <<3>>,              05456000
                       <<4>>, <<5>>, 0)                                 05458000
                                                                        05460000
            ELSE                                                        05462000
               Genmsg (dfs'msg'set'num, msg'bit'map'damaged,            05464000
                       [1/0,3/1,3/0,9/0], ldev, @io'error'buffer,       05466000
                       <<3>>, <<4>>, <<5>>, 0);                         05468000
                                                                        05470000
            << Set a flag in the disc label indicating that the         05472000
               bit map is damaged, this will prevent further            05474000
               allocation when the pack is re-mounted.         >>       05476000
                                                                        05478000
                                                                        05480000
            << Read disc label, if we can't read it, we don't try       05482000
               to set flag.                                      >>     05484000
                                                                        05486000
            TOS := Read'Disc (ldev, disc'label'address, 0, disc'label,  05488000
                              sector'size);                             05490000
                                                                        05492000
            IF TOS THEN                                                 05494000
               BEGIN  << Got label >>                                   05496000
                                                                        05498000
                  disc'label (disc'lab'dfs'map'ok) := FALSE;            05500000
                                                                        05502000
                  Write'Disc'Label (ldev, 0, disc'label);               05504000
                                                                        05506000
               END;   << Got label >>                                   05508000
                                                                        05510000
         END;   << 3 = Bit map damaged >>                               05512000
                                                                        05514000
         << - - - - - - - - - - - - - - - - - - - - - - - - - >>        05516000
                                                                        05518000
         BEGIN  << 4 = Unexpected error >>                              05520000
                                                                        05522000
            << Unexpected error,  this is a catch-all for               05524000
               errors we really don't know what to do with.             05526000
               Print ldev, error'status, i.d. number from               05528000
               type'of'error parameter.                      >>         05530000
                                                                        05532000
            MOVE io'error'buffer := 7 (0);                              05534000
            Ascii (error'status, 8, io'error'buffer);                   05536000
                                                                        05538000
            Genmsg (dfs'msg'set'num, msg'unexpected'error,              05540000
                    [1/0,3/1,3/0,3/1,6/0], ldev, @io'error'buffer,      05542000
                    type'of'error.(0:8), <<4>> , <<5>>, 0);             05544000
                                                                        05546000
         END;   << 4 = Unexpected error >>                              05548000
                                                                        05550000
      END;  << Case >>                                                  05552000
                                                                        05554000
                                                                        05556000
                                                                        05558000
   << Inform operator that we are disabling allocation on this          05560000
      ldev.                                                    >>       05562000
                                                                        05564000
   Genmsg (dfs'msg'set'num, msg'disable'allocation,                     05566000
           [1/0,3/1,12/0], ldev, <<2>>, <<3>>, <<4>>, <<5>>,            05568000
           0);                                                          05570000
                                                                        05572000
                                                                        05574000
   << Disable allocation by setting flag in the LDTX >>                 05576000
                                                                        05578000
   ldt'sir'info := Getsir (ldt'sir);                                    05580000
                                                                        05582000
   << Get offset to LDTX entry >>                                       05584000
                                                                        05586000
   Move'From'Data'Seg (ldt'dst, 0, ldt'entry'size, ldt'entry);          05588000
                                                                        05590000
   ldtx'entry'offset := ldt'entry (1) + ldt'entry (3) +                 05592000
                        (ldev * ldt'entry'size);                        05594000
                                                                        05596000
   Move'From'Data'Seg (ldt'dst, ldtx'entry'offset, ldt'entry'size,      05598000
                       ldt'entry);                                      05600000
                                                                        05602000
   ldt'entry (ldtx'dfs'error'word) := error'status;                     05604000
                                                                        05606000
                                                                        05608000
   Move'To'Data'Seg (ldt'entry, ldt'entry'size, ldt'dst,                05610000
                     ldtx'entry'offset);                                05612000
                                                                        05614000
   Relsir (ldt'sir, ldt'sir'info);                                      05616000
                                                                        05618000
   << If a data segment is allocated for this ldev, then set  >>        05620000
   << the ds'error'status field to error'status. This is so   >>        05622000
   << any process queued on the data segment can also find    >>        05624000
   << out about free space allocation being disabled.         >>        05626000
                                                                        05628000
   IF ldt'entry (ldtx'dfs'dst'word) <> 0 THEN                           05630000
      Move'To'Data'Seg (error'status, 1, ldt'entry (ldtx'dfs'dst'word), 05632000
                        @ds'error'status);                              05634000
                                                                        05636000
                                                                        05638000
                                                                        05640000
   Exchangedb (caller'dst);                                             05642000
                                                                        05644000
                                                                        05646000
END;   << Process'Dfs'Error >>                                          05648000
$PAGE "SEND'PROCESS'DFS'ERROR"                                          05650000
PROCEDURE Send'Process'Dfs'Error (ldev, error'status, type'of'error);   05652000
   VALUE ldev, error'status, type'of'error;                             05654000
   INTEGER ldev;                                                        05656000
   LOGICAL error'status;                                                05658000
   INTEGER type'of'error;                                               05660000
    OPTION PRIVILEGED,UNCALLABLE;                                       05662000
                                                                        05664000
                                                                        05666000
<<==============================================================        05668000
                                                                        05670000
      This procedure is the interface to Process'Dfs'Error.             05672000
   It is used to send a message to PROGEN to have it call               05674000
   Process'Dfs'Error .  This way, stack space does not have             05676000
   to be available  on the users stack to process the error             05678000
   and there is no danger of getting deadlocked with the log-           05680000
   ging process if it tries to get disc space to log the mes-           05682000
   sages that Process'Dfs'Error generates.  First Soft'Death            05684000
   (422) is called, so if the Soft'Death flag is set, then              05686000
   its crash time.  Then the error status                      ((DFS03))05688000
   is stuffed in the LDTX entry and in the                              05692000
   ds'error'status word of the DFS data segment, if it                  05694000
   is allocated.  This prevents other processes from trying             05696000
   to allocate space before PROGEN gets around to processing            05698000
   the message.  Then a message is sent to progen, containing           05700000
   the ldev, error'status and type'of'error parameters.                 05702000
                                                                        05704000
   Parameters:                                                          05706000
      ldev - ldev of disc.                                              05708000
      error'status - standard format error status word that             05710000
                     indicated what type of error occured.              05712000
      type'of'error - Further info about what was going on              05714000
                      when the error occured, it can have the           05716000
                      following values:                                 05718000
                    0 = Physical mount error.                           05720000
                    1 = Logical mount error.                            05722000
                    2 = Logical dismount error.                         05724000
                    3 = Damaged bit map error (i.e. the bits            05726000
                        aren't what we expected).                       05728000
                    4 = Unexpected error. (Catch-all for                05730000
                        errors we don't know how to deal                05732000
                        with).  Bits 0:8 contain an i.d.                05734000
                        number that is printed with the                 05736000
                        message, each call should have a                05738000
                        unique number to make it easy to                05740000
                        find these problems.                            05742000
                                                                        05744000
                                                                        05746000
   Assumptions on entry:                                                05748000
      DB can be anywhere.                                               05750000
                                                                        05752000
   Exit conditions:                                                     05754000
      DB is unchanged.                                                  05756000
                                                                        05758000
   Globals:                                                             05760000
                                                                        05762000
      Others:                                                           05764000
         ds'error'status                                                05766000
                                                                        05768000
      Equates:                                                          05770000
         progen'pin                                                     05772000
         ldt'sir                                                        05774000
         ldt'entry'size                                                 05776000
         ldtx'dfs'error'word                                            05778000
         ldtx'dfs'dst'word                                              05780000
         pcbsize                                                        05782000
                                                                        05784000
      Defines:                                                          05786000
         Getprocnum                                                     05788000
                                                                        05790000
   Externals:                                                           05792000
      Soft'Death                                                        05794000
      Exchangedb                                                        05798000
      Getsir                                                            05800000
      Move'From'Data'Seg                                                05802000
      Move'To'Data'Seg                                                  05804000
      Relsir                                                            05806000
      Sendmsg                                                           05808000
      Awake                                                             05810000
                                                                        05812000
   Intrinsics:                                                          05814000
      None.                                                             05816000
                                                                        05818000
   Callers:                                                             05820000
      Page'Io'Error                                                     05822000
      Process'Sys'Disc'Free'Space'Maps                                  05824000
      Set'Reset'Bit'Map                                                 05826000
      Locate'Free'Space                                                 05828000
      PVSYS module 81                                                   05830000
                                                                        05832000
   Changes:                                                             05834000
                                                               ((DFS03))05836000
       Changes made so that PROGEN sends its self a message    ((DFS03))05838000
       using the primary message table, this is so the DFS     ((DFS03))05840000
       data segments can be initialized before the system      ((DFS03))05842000
       console is initialized.  These changes where made to    ((DFS03))05844000
       allow LYNX to possible allocate space when calling      ((DFS03))05846000
       LOADPROC (this is part of the console initialization).  ((DFS03))05848000
                                                               ((DFS03))05850000
                                                                        05852000
                                                                        05854000
==============================================================>>        05856000
                                                                        05858000
BEGIN                                                                   05860000
                                                                        05862000
   INTEGER caller'dst;                                                  05864000
                                                                        05866000
   INTEGER ldt'sir'info;                                                05868000
   INTEGER ARRAY ldt'entry (0:ldt'entry'size-1) = Q;                    05870000
   INTEGER ldtx'entry'offset;                                           05872000
   LOGICAL send'flags;  << Flags for Sendmsg >>                <<03653>>05874000
                                                                        05876000
   << - - - - - - - - - - >>                                            05878000
                                                                        05880000
   << If the Soft'Death flag is set, its bye-bye >>                     05882000
                                                                        05884000
   Soft'Death (422);                                                    05886000
                                                                        05888000
                                                                        05890000
   << If this is PROGEN, use the primary message table >>      <<03653>>05892000
                                                                        05894000
   IF Getprocnum = progen'pin THEN                                      05896000
      send'flags := 0                                          <<03653>>05898000
    ELSE                                                       <<03653>>05900000
      send'flags := %100000;   << Use the secondary table >>   <<03653>>05902000
                                                               <<03653>>05904000
    << Indintation is strange here because of deleteing a >>   <<03653>>05906000
    << pair of BEGIN/ENDS.                                >>   <<03653>>05908000
                                                               <<03653>>05910000
                                                                        05912000
         << Set DB to the stack >>                                      05914000
                                                                        05916000
         caller'dst := Exchangedb (0);                                  05918000
                                                                        05920000
         << Disable allocation by setting flag in the LDTX.  The same   05922000
            thing is done bye Process'Dfs'Error, but we do it here      05924000
            too, so any process that might slip in before PROGEN gets   05926000
            it done will know about the problem.                    >>  05928000
                                                                        05930000
         ldt'sir'info := Getsir (ldt'sir);                              05932000
                                                                        05934000
         << Get offset to LDTX entry >>                                 05936000
                                                                        05938000
         Move'From'Data'Seg (ldt'dst, 0, ldt'entry'size, ldt'entry);    05940000
                                                                        05942000
         ldtx'entry'offset := ldt'entry (1) + ldt'entry (3) +           05944000
                              (ldev * ldt'entry'size);                  05946000
                                                                        05948000
         Move'From'Data'Seg (ldt'dst, ldtx'entry'offset,                05950000
                             ldt'entry'size, ldt'entry);                05952000
                                                                        05954000
         ldt'entry (ldtx'dfs'error'word) := error'status;               05956000
                                                                        05958000
                                                                        05960000
         Move'To'Data'Seg (ldt'entry, ldt'entry'size, ldt'dst,          05962000
                           ldtx'entry'offset);                          05964000
                                                                        05966000
         Relsir (ldt'sir, ldt'sir'info);                                05968000
                                                                        05970000
         << If a data segment is allocated for this ldev, then set  >>  05972000
         << the ds'error'status field to error'status. This is so   >>  05974000
         << any process queued on the data segment can also find    >>  05976000
         << out about free space allocation being disabled.         >>  05978000
                                                                        05980000
         IF ldt'entry (ldtx'dfs'dst'word) <> 0 THEN                     05982000
            Move'To'Data'Seg (error'status, 1,                          05984000
               ldt'entry (ldtx'dfs'dst'word), @ds'error'status);        05986000
                                                                        05988000
         << Send message to PROGEN, asking it to call                   05990000
            Process'Dfs'Error                         >>                05992000
                                                                        05994000
         << Push 4 word message on stack >>                             05996000
                                                                        05998000
         TOS := ldev;                                                   06000000
         TOS := error'status;                                           06002000
         TOS := type'of'error;                                          06004000
         TOS := dfs'error'progen'msg;   << Type of PROGEN msg >>        06006000
                                                                        06008000
         << Send message to PROGEN >>                                   06010000
                                                                        06012000
         Sendmsg (progen'pin, 0, 4, send'flags);               <<03653>>06014000
                                                                        06016000
         << Wake up PROGEN >>                                           06018000
                                                                        06020000
         Awake (progen'pin*pcbsize, %20, 0);                            06022000
                                                                        06024000
         << Set DB back to where it was >>                              06026000
                                                                        06028000
         Exchangedb (caller'dst);                                       06030000
                                                                        06032000
END;  << Send'Process'Dfs'Error >>                                      06038000
$PAGE "PROCESS'PAGE'IO'ERROR"                                           06040000
PROCEDURE Process'Page'Io'Error (ldev, page, error'status);             06042000
   VALUE ldev, page, error'status;                                      06044000
   INTEGER ldev, page;                                                  06046000
   LOGICAL error'status;                                                06048000
   OPTION PRIVILEGED,UNCALLABLE;                                        06050000
                                                                        06052000
<<==============================================================        06054000
                                                                        06056000
      This procedure handles I/O or checksum errors that  oc-           06058000
   cure  while  reading  or writting pages of the bit map.  A           06060000
   message is sent to the  console  indicating  the  ldev  on           06062000
   which  the  error  occured and the type of error.  The de-           06064000
   scriptor table entry for the page is set to the "bad'page"           06066000
   state (-1s).  The descriptor table is written out to  disc           06068000
   so  that  we have a copy that has all the bad pages flaged           06070000
   on it.  If an error occures while trying to write out  the           06072000
   descriptor  table, "Process'Dfs'Error" is called, treating           06074000
   it as an unexpected error.  First, Soft'Death (422) is               06076000
   called, so if the Soft'Death flag is set, then the system            06078000
   will crash.  This may be a handy field bug catcher.                  06080000
                                                                        06082000
                                                                        06084000
   Parameters:                                                          06086000
      ldev - Logical device number of the disc on which                 06088000
             the error occured.                                         06090000
      page - Page number of the page that got the I/O or                06092000
             checksum error.                                            06094000
      error'status - standard format error status, describing           06096000
                     the problem.                                       06098000
                                                                        06100000
   Assumptions on entry:                                                06102000
      DB can be any where.                                              06104000
                                                                        06106000
   Exit conditions:                                                     06108000
      DB is unchanged.                                                  06110000
                                                                        06112000
   Globals:                                                             06114000
                                                                        06116000
      Output:                                                           06118000
         ds'descriptor'table - Entry for page is set to                 06120000
                               "bad'page" state.                        06122000
                                                                        06124000
      Equates:                                                          06126000
        dt'entry'size                                                   06128000
        largest'space                                                   06130000
        starting'space                                                  06132000
        ending'space                                                    06134000
        bad'page                                                        06136000
        bit'map'read'error                                              06138000
        msg'bit'map'read'error                                          06140000
        bit'map'write'error                                             06142000
        msg'bit'map'write'error                                         06144000
        bit'map'check'sum'error                                         06146000
        msg'bit'map'check'sum'error                                     06148000
        dt'write'error                                                  06150000
        pcbsize                                                         06152000
        ldt'dst                                                         06154000
        ldt'entry'size                                                  06156000
        ldtx'dst'dst'word                                               06158000
                                                                        06160000
                                                                        06162000
      Defines:                                                          06164000
         attach'io'status                                               06166000
         error'type                                                     06168000
         Check'If'Disc                                                  06170000
         Getprocnum                                                     06172000
         progen'pin                                                     06174000
                                                                        06176000
   Externals:                                                           06178000
      Exchangedb                                                        06180000
      Get'Disc'Info                                                     06182000
      Write'Disc                                                        06184000
      Genmsg                                                            06186000
      Soft'Death                                                        06188000
      Suddendeath                                                       06190000
      Awake                                                             06192000
      Genmsg                                                            06194000
      Ascii                                                             06196000
      Process'Dfs'Error                                                 06198000
      Move'From'Data'Seg                                                06200000
      Move'To'Data'Seg                                                  06202000
                                                                        06204000
   Intrinsics:                                                          06206000
      None.                                                             06208000
                                                                        06210000
   Callers:                                                             06212000
      Send'Page'Io'Error                                                06214000
      PROGEN module 09                                                  06216000
                                                                        06218000
   Changes:                                                             06220000
                                                                        06222000
                                                                        06224000
==============================================================>>        06226000
                                                                        06228000
BEGIN                                                                   06230000
                                                                        06232000
   INTEGER ARRAY ldt'entry (0:ldt'entry'size-1) = Q;                    06234000
   INTEGER ldtx'entry'offset;                                           06236000
   BYTE ARRAY io'error'buffer (0:6) = Q;                                06238000
                                                                        06240000
   DOUBLE dt'disc'address;   << For address of descriptor table >>      06242000
   INTEGER dt'size'words;    << For size of descriptor table    >>      06244000
                                                                        06246000
   INTEGER caller'dst;                                                  06248000
                                                                        06250000
   INTRINSIC Ascii;                                                     06252000
                                                                        06254000
   << - - - - - - - - - - >>                                            06256000
                                                                        06258000
   << If the Soft'Death flag is set, this is the end. >>                06260000
                                                                        06262000
   Soft'Death (422);                                                    06264000
                                                                        06266000
                                                                        06268000
   << Set DB to the stack >>                                            06270000
                                                                        06272000
   caller'dst := Exchangedb (0);                                        06274000
                                                                        06276000
                                                                        06278000
   << Check to see if "ldev" has a ldev number of a disc, if            06280000
      not something is really messed up.                        >>      06282000
                                                                        06284000
   TOS := ldev;                                                         06286000
   Check'If'Disc;                                                       06288000
   IF NOT TOS THEN Suddendeath (423);                                   06290000
                                                                        06292000
                                                                        06294000
   << Convert I/O error field to Ascii string in case we                06296000
      need it.                                           >>             06298000
                                                                        06300000
   MOVE io'error'buffer := 7 (0);                                       06302000
   Ascii (error'status.attach'io'status, 8, io'error'buffer);           06304000
                                                                        06306000
   << Genmsg according to error type >>                                 06308000
                                                                        06310000
   IF error'status.error'type = bit'map'read'error THEN                 06312000
       Genmsg (dfs'msg'set'num, msg'bit'map'read'error,                 06314000
        [1/0,3/1,3/1,3/0,6/0], ldev, page, @io'error'buffer,            06316000
        <<4>>, <<5>>, 0)                                                06318000
   ELSE                                                                 06320000
   IF error'status.error'type = bit'map'write'error THEN                06322000
      Genmsg (dfs'msg'set'num, msg'bit'map'write'error,                 06324000
              [1/0,3/1,3/1,3/0,6/0], ldev, page,                        06326000
              @io'error'buffer, <<4>>, <<5>>, 0)                        06328000
   ELSE                                                                 06330000
   IF error'status.error'type = bit'map'check'sum'error THEN            06332000
      Genmsg (dfs'msg'set'num, msg'bit'map'check'sum'error,             06334000
              [1/0,3/1,3/1,9/0], ldev, page,  <<3>>, <<4>>,             06336000
              <<5>>, 0)                                                 06338000
   ELSE                                                                 06340000
                                                                        06342000
      << Unknown error code. Something must have got clobered >>        06344000
                                                                        06346000
$IF X3=ON   << BUG CATCHER >>                                           06348000
      Suddendeath (421);                                                06350000
$IF X3=OFF                                                              06352000
      Process'Dfs'Error (ldev, error'status, [8/10, 8/4]);              06354000
$IF                                                                     06356000
                                                                        06358000
                                                                        06360000
   << Get descriptor table address and size while Db is at              06362000
      the stack.                                           >>           06364000
                                                                        06366000
   error'status := Get'Disc'Info (ldev,  ,  ,  ,  ,  ,  ,  ,  ,         06368000
                                  dt'disc'address, dt'size'words);      06370000
   IF NOT error'status THEN                                             06372000
      BEGIN  << Get'Disc'Info error >>                                  06374000
                                                                        06376000
         Process'Dfs'Error (ldev, error'status, [8/2, 8/4]);            06378000
         RETURN;                                                        06380000
                                                                        06382000
      END;   << Get'Disc'Info error >>                                  06384000
                                                                        06386000
                                                                        06388000
   << Set DB to DFS DST for the ldev, but first we must get the         06390000
      DST number from the LDTX.                                  >>     06392000
                                                                        06394000
   Move'From'Data'Seg (ldt'dst, 0, ldt'entry'size, ldt'entry);          06396000
                                                                        06398000
   ldtx'entry'offset := ldt'entry (1) + ldt'entry (3) +                 06400000
                        (ldev * ldt'entry'size);                        06402000
                                                                        06404000
   Move'From'Data'Seg (ldt'dst, ldtx'entry'offset, ldt'entry'size,      06406000
                       ldt'entry);                                      06408000
                                                                        06410000
   Exchangedb (ldt'entry (ldtx'dfs'dst'word));                          06412000
                                                                        06414000
                                                                        06416000
   << Flag page as bad in the descriptor table >>                       06418000
                                                                        06420000
   ds'descriptor'table((page * dt'entry'size) + largest'space) :=       06422000
      bad'page;                                                         06424000
   ds'descriptor'table((page * dt'entry'size) + starting'space) :=      06426000
      bad'page;                                                         06428000
   ds'descriptor'table((page * dt'entry'size) + ending'space) :=        06430000
      bad'page;                                                         06432000
                                                                        06434000
                                                                        06436000
   << Write descriptor table to disc so that the disc copy has          06438000
      updated info on bad pages.                              >>        06440000
                                                                        06442000
   error'status := Write'Disc (ldev, dt'disc'address, ds'dst,           06444000
                               ds'descriptor'table, dt'size'words);     06446000
   IF NOT error'status THEN                                             06448000
      BEGIN  << I/O error >>                                            06450000
                                                                        06452000
         Exchangedb (caller'dst);                                       06454000
         error'status.error'type := dt'write'error;                     06456000
         Process'Dfs'Error (ldev, error'status, [8/3, 8/4]);            06458000
         RETURN;                                                        06460000
                                                                        06462000
      END;   << I/O error >>                                            06464000
                                                                        06466000
   << Set DB back to the stack >>                                       06468000
                                                                        06470000
   Exchangedb (caller'dst);                                             06472000
                                                                        06474000
END;  << Page'Io'Error >>                                               06476000
$PAGE "SEND'PAGE'IO'ERROR"                                              06478000
PROCEDURE Send'Page'Io'Error (page);                                    06480000
   VALUE page;                                                          06482000
   INTEGER page;                                                        06484000
                                                                        06486000
<<==============================================================        06488000
                                                                        06490000
      This procedure handles bitmap page I/O and checksum               06492000
   errors.  The actual processing is done by                            06494000
   "Process'Page'I/O'Error", which is called by PROGEN.  This           06496000
   is done because of two problems that could happen if the             06498000
   prcessing was done on the users stack.  First the descrip-           06500000
   tor table must be written to disc, this involves reading             06502000
   in the disc label to get the descriptor table address.               06504000
   Since this procedure is called while critical, we would              06506000
   have had to make sure there was enough stack stack space             06508000
   to do this.  It would be a waste to require the extra                06510000
   space when it is hardly ever used.  Second, since a con-             06512000
   sole message is generated, if the log process had to get             06514000
   disc space to complete logging of the message, a deadlock            06516000
   could occur.  A message is sent via the low level message            06518000
   system, telling PROGEN to call "Process'Page'Io'Error".              06520000
   After sending the message, the descriptor table entry is             06522000
   marked as bad, even thought this will be done again, to              06524000
   keep us from trying to use the page over again before                06526000
   PROGEN does its thing.  Soft'Death (423) is called before            06528000
   any thing is done, so if the Soft'Death flag is set, the             06530000
   system will crash (a bug catcher).                                   06532000
                                                                        06534000
   Parameters:                                                          06536000
      page - Number of the page that got the error.                     06538000
                                                                        06540000
   Assumptions on entry:                                                06542000
      DB is at the free space data segment for the ldev and             06544000
      the data segment is locked.                                       06546000
                                                                        06548000
   Exit conditions:                                                     06550000
      DB is unchanged.                                                  06552000
                                                                        06554000
   Globals:                                                             06556000
                                                                        06558000
      Input:                                                            06560000
         ds'ldev - Ldev number of the disc.                             06562000
         ds'error'status - standard format error status                 06564000
                           describing the error.                        06566000
                                                                        06568000
      Output:                                                           06570000
         ds'descriptor'table - the entry for the page is set            06572000
                               to the "bad'page state                   06574000
                                                                        06576000
      Equates:                                                          06578000
         page'io'progen'message                                         06580000
         pcbsize                                                        06582000
         dt'entry'size                                                  06584000
         largest'space                                                  06586000
         starting'space                                                 06588000
         ending'space                                                   06590000
         bad'page                                                       06592000
                                                                        06594000
      Defines:                                                          06596000
         Check'If'Disc                                                  06598000
         Getprocnum                                                     06600000
         progen'pin                                                     06602000
                                                                        06604000
   Externals:                                                           06606000
      Soft'Death                                                        06608000
      Process'Page'Io'Error                                             06610000
      Sendmsg                                                           06612000
      Awake                                                             06614000
                                                                        06616000
   Intrinsics:                                                          06618000
      None.                                                             06620000
                                                                        06622000
   Callers:                                                             06624000
      Read'Page                                                         06626000
      Write'Page                                                        06628000
                                                                        06630000
   Changes:                                                             06632000
                                                               ((DFS03))06634000
       Changes made so that PROGEN sends its self a message    ((DFS03))06636000
       using the primary message table, this is so the DFS     ((DFS03))06638000
       data segments can be initialized before the system      ((DFS03))06640000
       console is initialized.  These changes where made to    ((DFS03))06642000
       allow LYNX to possible allocate space when calling      ((DFS03))06644000
       LOADPROC (this is part of the console initialization).  ((DFS03))06646000
                                                               ((DFS03))06648000
                                                                        06650000
                                                                        06652000
==============================================================>>        06654000
                                                                        06656000
BEGIN                                                                   06658000
                                                                        06660000
   LOGICAL send'flags;  << Sendmsg flags >>                    <<03653>>06662000
                                                                        06664000
   << - - - - - - - - - - >>                                            06666000
                                                                        06668000
   << If soft'death flag is set, this is the END >>                     06670000
                                                                        06672000
   Soft'Death (422);                                                    06674000
                                                                        06676000
   << Check to see if "ds'ldev" has a ldev number of a disc, if         06678000
      not something is really wrong.                            >>      06680000
                                                                        06682000
   TOS := ds'ldev;                                                      06684000
   Check'If'Disc;                                                       06686000
   IF NOT TOS THEN Suddendeath (423);                                   06688000
                                                                        06690000
   << If we are PROGEN, send the message to our selves via >>  <<03653>>06692000
   << the primary message table.                           >>  <<03653>>06694000
                                                                        06696000
   IF Getprocnum = progen'pin THEN                                      06698000
      send'flags := 0                                          <<03653>>06700000
                                                               <<03653>>06702000
   ELSE                                                        <<03653>>06704000
      send'flags := %100000;                                   <<03653>>06706000
                                                               <<03653>>06708000
   << Indintation is strange because of changes >>             <<03653>>06710000
                                                               <<03653>>06712000
                                                                        06714000
         << Push message on stack >>                                    06716000
                                                                        06718000
         TOS := ds'ldev;                                                06720000
         TOS := page;                                                   06722000
         TOS := ds'error'status;                                        06724000
         TOS := page'io'error'progen'msg;                               06726000
                                                                        06728000
         << Send message to PROGEN >>                                   06730000
                                                                        06732000
         Sendmsg (progen'pin, 0, 4, send'flags);               <<03653>>06734000
                                                                        06736000
         << wake up PROGEN >>                                           06738000
                                                                        06740000
         Awake (progen'pin*pcbsize, %20, 0);                            06742000
                                                                        06744000
         << Flag the page as bad in the descriptor so it is not         06746000
            used before PROGEN gets a chance to flag it and             06748000
            complete processing of the error.                   >>      06750000
                                                                        06752000
         ds'descriptor'table((page * dt'entry'size) +                   06754000
                              largest'space) := bad'page;               06756000
         ds'descriptor'table((page * dt'entry'size) +                   06758000
                              starting'space) := bad'page;              06760000
         ds'descriptor'table((page * dt'entry'size) +                   06762000
                              ending'space) := bad'page;                06764000
                                                                        06766000
END;  << Send'Process'Page'Io'Error >>                                  06772000
$PAGE "LOGICAL PROCEDURE CREATE'DFS'DATA'SEG"                           06774000
LOGICAL PROCEDURE Create'Dfs'Data'Seg (ldev, disc'label,                06776000
                  assume'dt'is'dirty, flag'dt'as'dirty);                06778000
   VALUE ldev, assume'dt'is'dirty, flag'dt'as'dirty;                    06780000
   INTEGER ldev;                                                        06782000
   LOGICAL assume'dt'is'dirty;                                          06784000
   LOGICAL flag'dt'as'dirty;                                            06786000
   ARRAY disc'label;                                                    06788000
   OPTION VARIABLE,PRIVILEGED,UNCALLABLE;                               06790000
                                                                        06792000
<<==============================================================        06794000
                                                                        06796000
      This procedure sets up the  DFS  data  segment  for  an           06798000
   ldev.  It  is  called  when a Private Volume is physically           06800000
   mounted and for each system volume when the  system  comes           06802000
   up.   First the disc label is checked to see that the pack           06804000
   has the new free space table on it. If it is an old format           06806000
   pack, an error status is returned.  The data  segement  is           06808000
   allocated  and  the  information in the LDTX entry for the           06810000
   ldev is set.  The variables in the data segment  are  ini-           06812000
   tialized  and  pointers to the arrays are set up.  The de-           06814000
   scriptor table is read into  the  data  segement  and  the           06816000
   checksum  is  verfied.   If the checksum is bad, the dirty           06818000
   descriptor table field  of  the  disc  label  is  TRUE  or           06820000
   "assume'dt'is'dirty"  is TRUE then the descriptor table is           06822000
   rebuilt from the bitmap.  The copy  off  of  the  disc  is           06824000
   still  used  to locate bad pages.  New descriptor table is           06826000
   then written to disc.  The dirty descriptor table flag  in           06828000
   the  disc  label  is set to TRUE or FALSE according to the           06830000
   value of "flag'dt'as'dirty".  This parameter  will be TRUE           06832000
   for  the  mount of a system volume and FALSE for a private           06834000
   volume physical mount.  The "ds'buffer'dirty"  array  will           06836000
   only be set up if X2 is ON.                                          06838000
                                                                        06840000
   Parameters:                                                          06842000
      ldev - Ldev of disc.                                              06844000
      disc'label - optional - Copy of disc label, if it is              06846000
                   not supplied, the disc label will be read            06848000
                   in.                                                  06850000
      assume'dt'is'dirty - optional - If TRUE, then assume              06852000
                           that the descriptor table is dir-            06854000
                           ty, if omitted or FALSE, then the            06856000
                           dirty descriptor table flag in the           06858000
                           disc label will be used to deter-            06860000
                           mine if the table on disc is good.           06862000
      flag'dt'as'dirty - optional - If FALSE, then the                  06864000
                         descriptor table will be flaged as             06866000
                         clean in the disc label, if TRUE or            06868000
                         omitted, the table will be flaged as           06870000
                         dirty.                                         06872000
                                                                        06874000
   Returns:                                                             06876000
      Standard format status word, indicating what error, if            06878000
      any, occured.                                                     06880000
                                                                        06882000
   Assumptions on entry:                                                06884000
      DB must be at the stack.                                          06886000
                                                                        06888000
   Exit conditions:                                                     06890000
      DB is unchanged.                                                  06892000
                                                                        06894000
   Globals:                                                             06896000
                                                                        06898000
      Output:                                                           06900000
         ds'array'area                                                  06902000
         LDTX entry for ldev.                                           06904000
         DISC LABEL for ldev.                                           06906000
         ds'ldev                                                        06908000
         ds'disc'size                                                   06910000
         ds'last'pages'of'map                                           06912000
         ds'last'buffer'index                                           06914000
         ds'map'address                                                 06916000
         ds'lock                                                        06918000
         ds'lock'count                                                  06920000
         ds'queue'head                                                  06922000
         ds'queue'tail                                                  06924000
         ds'dst                                                         06926000
         ds'next'buffer'index                                           06928000
         ds'size'of'last'allocation                                     06930000
         ds'first'threshold'page                                        06932000
         ds'descriptor'table                                            06934000
         ds'buffer'page'number                                          06936000
         ds'buffer'dirty  {X2=ON Dirty buffer management enabled}       06938000
         ds'buffer'area                                                 06940000
         ds'error'status                                                06942000
                                                                        06944000
      Others:                                                           06946000
         ds'pages'number                                                06948000
         ds'error'status                                                06950000
                                                                        06952000
      Equates:                                                          06954000
         old'dfs'error                                                  06956000
         map'damaged'error                                              06958000
         disc'lab'dfs'map'ok                                            06960000
         dt'entry'size                                                  06962000
         sector'size                                                    06964000
         get'dst'error                                                  06966000
         get'vm'error                                                   06968000
         ldt'sir                                                        06970000
         ldt'dst                                                        06972000
         ldt'entry'size                                                 06974000
         ldtx'dfs'dst'word                                              06976000
         ldtx'dfs'error'word                                            06978000
         no'error                                                       06980000
         disc'lab'dt'check'sum                                          06982000
         bad'page                                                       06984000
         largest'space                                                  06986000
         starting'space                                                 06988000
         ending'space                                                   06990000
         threshold'size                                                 06992000
         dt'write'error                                                 06994000
         disc'lab'dirty'dt'flag                                         06996000
                                                                        06998000
      Defines:                                                          07000000
         error'type                                                     07002000
         Checkdb - (X3=ON bug catcher)                                  07004000
         Check'If'Disc - (X3 = ON bug catcher)                          07006000
                                                                        07008000
   Externals:                                                           07010000
      Get'Disc'Info                                                     07012000
      Getdataseg                                                        07014000
      Getsir                                                            07016000
      Move'From'Data'Seg                                                07018000
      Move'To'Data'Seg                                                  07020000
      Reldataseg                                                        07022000
      Relsir                                                            07024000
      Exchangedb                                                        07026000
      Read'Disc                                                         07028000
      Make'Check'Sum                                                    07030000
      Build'Descriptor'Table                                            07032000
      Write'Disc                                                        07034000
      Write'Disc'Label                                                  07036000
      Delete'Dfs'Data'Seg                                               07038000
      Suddendeath - (X3=ON bug catching)                                07040000
                                                                        07042000
   Intrinsics:                                                          07044000
      None.                                                             07046000
                                                                        07048000
   Callers:                                                             07050000
      Process'Sys'Disc'Free'Space'Maps                                  07052000
      PVPROC module 31                                                  07054000
      OPCOMMAND module 85                                               07056000
      VINIT module 32                                                   07058000
                                                                        07060000
   Changes:                                                             07062000
                                                                        07064000
                                                                        07066000
==============================================================>>        07068000
                                                                        07070000
BEGIN                                                                   07072000
                                                                        07074000
   DOUBLE disc'size;                                                    07076000
                                                                        07078000
   INTEGER number'of'buffers;  << Number of buffers in DFS DST >>       07080000
   INTEGER bit'map'size'pages;                                          07082000
   DOUBLE map'disc'address;                                             07084000
   INTEGER dt'size'words;                                               07086000
   DOUBLE dt'disc'address;                                              07088000
                                                                        07090000
   INTEGER data'seg'size;                                               07092000
   INTEGER dfs'dst;            << DST number of data segement >>        07094000
   LOGICAL dt'is'dirty;                                                 07096000
   LOGICAL dt'check'sum;                                                07098000
                                                                        07100000
   INTEGER ARRAY ldt'entry (0:ldt'entry'size-1);                        07102000
   LOGICAL ldt'sir'info;                                                07104000
   INTEGER ldtx'entry'offset;                                           07106000
                                                                        07108000
   INTEGER index;                                                       07110000
                                                                        07112000
   INTEGER POINTER current'dt'entry;   << Pointers into descriptor >>   07114000
   INTEGER POINTER next'dt'entry;      << table.                   >>   07116000
   INTEGER POINTER last'dt'entry;                                       07118000
                                                                        07120000
   << Parameter map >>                                                  07122000
                                                                        07124000
   LOGICAL pmap = Q-4;                                                  07126000
   DEFINE passed'disc'label = pmap.(13:1)#,                             07128000
          passed'assume'dt'is'dirty = pmap.(14:1)#,                     07130000
          passed'flag'dt'as'dirty = pmap.(15:1)#;                       07132000
                                                                        07134000
   LOGICAL return'status = Create'Dfs'Data'Seg;                         07136000
                                                                        07138000
   << - - - - - - - - - - >>                                            07140000
                                                                        07142000
$IF X3=ON   << BUG CATCHER >>                                           07144000
                                                                        07146000
   << Check if DB is at the stack >>                                    07148000
                                                                        07150000
   Checkdb;                                                             07152000
   IF <> THEN Suddendeath (421);   << Not at the stack >>               07154000
                                                                        07156000
   << Make sure it is really a disc >>                                  07158000
                                                                        07160000
   TOS := ldev;                                                         07162000
   Check'If'Disc;                                                       07164000
   IF NOT TOS THEN Suddendeath (421);                                   07166000
                                                                        07168000
$IF         << BUG CATCHER >>                                           07170000
                                                                        07172000
                                                                        07174000
   << If disc label was not passed, we need to allocate a buffer        07176000
      for it, it will be read in by "Get'Disc'Info".             >>     07178000
                                                                        07180000
   IF NOT passed'disc'label THEN                                        07182000
      BEGIN  << Disc label not passed >>                                07184000
                                                                        07186000
         << Allocate disc label buffer >>                               07188000
                                                                        07190000
         PUSH (S);                                                      07192000
         @disc'label := TOS + 1;   << ptr to buffer >>                  07194000
         TOS := sector'size + 1;   << size of buffer >>                 07196000
         ASSEMBLE (ADDS 0);                                             07198000
                                                                        07200000
      END;   << Disc label not passed >>                                07202000
                                                                        07204000
   << Default optional parameters, if not passed >>                     07206000
                                                                        07208000
   IF NOT passed'assume'dt'as'dirty THEN                                07210000
      assume'dt'is'dirty := FALSE;                                      07212000
                                                                        07214000
   IF NOT passed'flag'dt'as'dirty THEN                                  07216000
      flag'dt'as'dirty := TRUE;                                         07218000
                                                                        07220000
                                                                        07222000
   << Get information about the disc, including disc label              07224000
      if it was not passed.                          >>                 07226000
                                                                        07228000
   return'status := Get'Disc'Info (ldev, disc'label,                    07230000
                                   NOT passed'disc'label,  ,  ,  ,      07232000
                                   disc'size, map'disc'address,         07234000
                                   bit'map'size'pages, dt'disc'address ,07236000
                                   dt'size'words, dt'is'dirty,          07238000
                                   number'of'buffers, dt'check'sum);    07240000
                                                                        07242000
   IF NOT return'status THEN                                            07244000
      RETURN;  << Get'Disc'Info error >>                                07246000
                                                                        07248000
                                                                        07250000
   << Check to see if the pack has the old format free space table >>   07252000
                                                                        07254000
   IF dt'disc'address <= 0D OR map'disc'address <= 0D THEN              07256000
      BEGIN  << Pack does not have free space map >>                    07258000
                                                                        07260000
         return'status := old'dfs'error;                                07262000
         RETURN;                                                        07264000
                                                                        07266000
      END;   << pack does not have free space map >>                    07268000
                                                                        07270000
                                                                        07272000
   << Check disc label, "disc'lab'dfs'map'ok" field to see              07274000
      if a damaged bit map has been previously detected, if so,         07276000
      don't complete mount.                                    >>       07278000
                                                                        07280000
   IF NOT disc'label (disc'lab'dfs'map'ok) THEN                         07282000
      BEGIN  << Map has been damaged >>                                 07284000
                                                                        07286000
         return'status := map'damaged'error;                            07288000
         RETURN;                                                        07290000
                                                                        07292000
      END;   << Map has been damaged >>                                 07294000
                                                                        07296000
                                                                        07298000
   << Calculate size of DST >>                                          07300000
                                                                        07302000
$IF X2=ON   << USING DIRTY BUFFER MANAGEMENT >>                         07304000
                                                                        07306000
   data'seg'size := @ds'array'area + (bit'map'size'pages *              07308000
                    dt'entry'size) + dt'entry'size + 1 +                07310000
                    (number'of'buffers * (sector'size * page'size)) +   07312000
                    (number'of'buffers * 2);                            07314000
                                                                        07316000
$IF X2=OFF  << NOT USING DIRTY BUFFER MANAGEMENT >>                     07318000
                                                                        07320000
   data'seg'size := @ds'array'area + (bit'map'size'pages *              07322000
                    dt'entry'size) + dt'entry'size + 1 +                07324000
                    (number'of'buffers * (sector'size * page'size)) +   07326000
                    number'of'buffers;                                  07328000
                                                                        07330000
$IF                                                                     07332000
                                                                        07334000
   << Allocate data segment >>                                          07336000
                                                                        07338000
   dfs'dst := Getdataseg (data'seg'size, data'seg'size);                07340000
   IF > THEN                                                            07342000
       BEGIN << No DST entries >>                                       07344000
                                                                        07346000
         return'status := get'dst'error;                                07348000
         RETURN                                                         07350000
                                                                        07352000
      END   << No DST entries >>                                        07354000
   ELSE                                                                 07356000
      IF < THEN                                                         07358000
         BEGIN  << No Virtual memory >>                                 07360000
                                                                        07362000
            return'status := get'vm'error;                              07364000
            RETURN;                                                     07366000
                                                                        07368000
         END;   << No virtual memory >>                                 07370000
                                                                        07372000
                                                                        07374000
   << Stuff dst number in LDTX >>                                       07376000
                                                                        07378000
   ldt'sir'info := Getsir (ldt'sir);                                    07380000
                                                                        07382000
   << Get offset to LDTX >>                                             07384000
                                                                        07386000
   Move'From'Data'Seg (ldt'dst, 0, ldt'entry'size, ldt'entry);          07388000
                                                                        07390000
   ldtx'entry'offset := ldt'entry (1) + ldt'entry (3) +                 07392000
                        (ldev * ldt'entry'size);                        07394000
                                                                        07396000
   Move'From'Data'Seg (ldt'dst, ldtx'entry'offset, ldt'entry'size,      07398000
                       ldt'entry);                                      07400000
                                                                        07402000
   << If there is a DST number already in the LDTX and it is not        07404000
      the same as the current DST number, then try to release that      07406000
      DST.  This is to prevent forgetting about a data segment          07408000
      when PVPROC calls this routine more than one time for the         07410000
      same physical mount of a pack, as would be the case when a        07412000
      pack is taken offline and put back online before a mount is       07414000
      completed.                                                  >>    07416000
                                                                        07418000
   IF ldt'entry (ldtx'dfs'dst'word) <> 0 AND                            07420000
   ldt'entry (ldtx'dfs'dst'word) <> dfs'dst THEN                        07422000
      Reldataseg (ldt'entry (ldtx'dfs'dst'word));                       07424000
                                                                        07426000
   ldt'entry (ldtx'dfs'dst'word) := dfs'dst;                            07428000
   ldt'entry (ldtx'dfs'error'word) := no'error;                         07430000
                                                                        07432000
   Move'To'Data'Seg (ldt'entry, ldt'entry'size, ldt'dst,                07434000
                     ldtx'entry'offset);                                07436000
                                                                        07438000
                                                                        07440000
   Relsir (ldt'sir, ldt'sir'info);                                      07442000
                                                                        07444000
                                                                        07446000
   << Initialize data segment >>                                        07448000
                                                                        07450000
   Exchangedb (dfs'dst);                                                07452000
                                                                        07454000
   ds'ldev := ldev;                                                     07456000
   ds'disc'size := disc'size;                                           07458000
   ds'last'page'of'map := bit'map'size'pages - 1;                       07460000
   ds'last'buffer'index := number'of'buffers - 1;                       07462000
   ds'map'address := map'disc'address;                                  07464000
   ds'lock := 0;                                                        07466000
   ds'lock'count := 0;                                                  07468000
   ds'queue'head := 0;                                                  07470000
   ds'queue'tail := 0;                                                  07472000
   ds'dst := dfs'dst;                                                   07474000
   ds'error'status := no'error;                                         07476000
   ds'next'buffer'index := 0;                                           07478000
   ds'size'of'last'allocation := max'double;   << Set to very large     07480000
                                                  value >>              07482000
                                                                        07484000
   << Set up pointers to arrays, set up an extra entry before           07486000
      and after the descriptor table.  These are needed by Find'Page    07488000
      and Build'Descriptor'Entry.                                   >>  07490000
                                                                        07492000
   @ds'descriptor'table := @ds'array'area + dt'entry'size;              07494000
   @ds'buffer'page'number := @ds'descriptor'table + dt'size'words +     07496000
                             dt'entry'size;                             07498000
                                                                        07500000
$IF X2=ON   << USING DIRTY BUFFER MANAGEMENT >>                         07502000
                                                                        07504000
   @ds'buffer'dirty := @ds'buffer'page'number + number'of'buffers;      07506000
   @ds'buffer'area  := @ds'buffer'dirty + number'of'buffers;            07508000
                                                                        07510000
$IF X2=OFF  << NOT USING DIRTY BUFFER MANAGEMENT >>                     07512000
                                                                        07514000
   @ds'buffer'dirty := 0;                                               07516000
   @ds'buffer'area := @ds'buffer'page'number + number'of'buffers;       07518000
                                                                        07520000
$IF                                                                     07522000
                                                                        07524000
                                                                        07526000
   << Initialize ds'buffer'page'number & ds'buffer'dirty arrays >>      07528000
                                                                        07530000
   index := 0;                                                          07532000
   WHILE index < number'of'buffers DO                                   07534000
      BEGIN  << Init buffer info >>                                     07536000
                                                                        07538000
$IF X2=ON   << USING DIRTY BUFFER MANAGEMENT >>                         07540000
                                                                        07542000
         ds'buffer'dirty (index) := FALSE;                              07544000
                                                                        07546000
$IF         << USING DIRTY BUFFER MANAGEMENT >>                         07548000
                                                                        07550000
         ds'buffer'page'number (index) := empty'buffer;                 07552000
         index := index + 1;                                            07554000
                                                                        07556000
      END;   << Init buffer info >>                                     07558000
                                                                        07560000
                                                                        07562000
   << Init dummy entries before and after the descriptor table >>       07564000
                                                                        07566000
   MOVE ds'descriptor'table (-dt'entry'size) :=                         07568000
        dt'entry'size (0);                                              07570000
                                                                        07572000
   MOVE ds'descriptor'table (dt'size'words) :=                          07574000
        dt'entry'size (0);                                              07576000
                                                                        07578000
                                                                        07580000
   << Read in descriptor table from disc >>                             07582000
                                                                        07584000
   return'status := Read'Disc (ldev, dt'disc'address, dfs'dst,          07586000
                           ds'descriptor'table, dt'size'words);         07588000
   IF NOT return'status THEN                                            07590000
      BEGIN  << I/O Error >>                                            07592000
                                                                        07594000
        Exchangedb (0);  << Reset DB to stack >>                        07596000
        return'status.error'type := dt'read'error;                      07598000
        Delete'Dfs'Data'Seg (ldev);                                     07600000
        RETURN;                                                         07602000
                                                                        07604000
      END;   << I/O error >>                                            07606000
                                                                        07608000
                                                                        07610000
   << If descriptor table is dirty or we are to assume that it is       07612000
      dirty or check sum is bad, then rebuild DT from bit map, using    07614000
      old DT to locate pages that have been flaged as bad.          >>  07616000
                                                                        07618000
   IF dt'is'dirty OR assume'dt'is'dirty OR                              07620000
   (dt'check'sum <>                                                     07622000
   Make'Check'Sum (ds'descriptor'table, dt'size'words)) THEN            07624000
      BEGIN  << Rebuild DT >>                                           07626000
                                                                        07628000
         ds'page'number := bit'map'size'pages - 1;                      07630000
                                                                        07632000
         << Set threshold pointer past end of the map, we will          07634000
            go through the map backwards, so the threshold page         07636000
            will be moved by "Build'Descriptor'Entry".          >>      07638000
                                                                        07640000
         ds'first'threshold'page := bit'map'size'pages;                 07642000
                                                                        07644000
         WHILE ds'page'number >= 0 DO                                   07646000
            BEGIN  << Run through bit map >>                            07648000
                                                                        07650000
               IF                                                       07652000
               ds'descriptor'table((ds'page'number*dt'entry'size)       07654000
               + largest'space)= bad'page OR                            07656000
               ds'descriptor'table((ds'page'number*dt'entry'size)       07658000
               + starting'space) = bad'page OR                          07660000
               ds'descriptor'table((ds'page'number*dt'entry'size)       07662000
               + ending'space) = bad'page                               07664000
               THEN                                                     07666000
                  BEGIN  << Page has been flag as bad >>                07668000
                                                                        07670000
                     << Just make sure all words in entry contain       07672000
                        bad page flag.                            >>    07674000
                                                                        07676000
                     MOVE ds'descriptor'table (ds'page'number *         07678000
                     dt'entry'size) := dt'entry'size (bad'page);        07680000
                                                                        07682000
                  END    << Page has been flag as bad >>                07684000
               ELSE                                                     07686000
                  BEGIN  << Page is O.K. >>                             07688000
                                                                        07690000
                     Build'Descriptor'Entry (ds'page'number);           07692000
                                                                        07694000
                     << Just ignore any error from above, as            07696000
                        it has allready been processed and should       07698000
                        not matter to the caller.                >>     07700000
                                                                        07702000
                  END;   << Page is O.K. >>                             07704000
                                                                        07706000
               ds'page'number := ds'page'number - 1;                    07708000
                                                                        07710000
            END;   << Run through bit map >>                            07712000
                                                                        07714000
                                                                        07716000
         << Generate new checksum >>                                    07718000
                                                                        07720000
         dt'check'sum := Make'Check'Sum (ds'descriptor'table,           07722000
                                         dt'size'words);                07724000
                                                                        07726000
         << Write descriptor table back to disc >>                      07728000
                                                                        07730000
         return'status := Write'Disc (ldev, dt'disc'address, dfs'dst,   07732000
                                  ds'descriptor'table,                  07734000
                                  dt'size'words);                       07736000
                                                                        07738000
         IF NOT return'status THEN                                      07740000
            BEGIN << I/O error >>                                       07742000
                                                                        07744000
               Exchangedb (0);   << Reset DB to stack >>                07746000
               return'status.error'type := dt'write'error;              07748000
               Delete'Dfs'Data'Seg (ldev);                              07750000
               RETURN;                                                  07752000
                                                                        07754000
            END;  << I/O error >>                                       07756000
                                                                        07758000
      END    << Rebuild DT >>                                           07760000
   ELSE                                                                 07762000
      BEGIN  << Find first threshold page >>                            07764000
                                                                        07766000
        << Scan through descriptor table to find the entry to           07768000
           set "ds'threshold'page" to.                       >>         07770000
                                                                        07772000
        @current'dt'entry := @ds'descriptor'table;                      07774000
        @next'dt'entry := @current'dt'entry + dt'entry'size;            07776000
        @last'dt'entry := @ds'descriptor'table +                        07778000
                          (ds'last'page'of'map * dt'entry'size);        07780000
                                                                        07782000
        WHILE                                                           07784000
        @current'dt'entry <= @last'dt'entry LAND                        07786000
        NOT((current'dt'entry (starting'space) >= threshold'size) LOR   07788000
        (current'dt'entry (largest'space) >= threshold'size) LOR        07790000
        ((current'dt'entry (ending'space) > 0 ) LAND                    07792000
        ((current'dt'entry (ending'space) +                             07794000
        next'dt'entry (starting'space)) >= threshold'size)))            07796000
        DO                                                              07798000
           BEGIN  << Check next entry >>                                07800000
                                                                        07802000
             @current'dt'entry := @next'dt'entry;                       07804000
             @next'dt'entry := @next'dt'entry + dt'entry'size;          07806000
                                                                        07808000
           END;   << Check next entry >>                                07810000
                                                                        07812000
        ds'first'threshold'page := (@current'dt'entry -                 07814000
                          @ds'descriptor'table) / dt'entry'size;        07816000
                                                                        07818000
      END;   << Find dirst threshold page >>                            07820000
                                                                        07822000
                                                                        07824000
   << Restore DB to caller's DST >>                                     07826000
                                                                        07828000
   Exchangedb (0);                                                      07830000
                                                                        07832000
                                                                        07834000
   << Set dirty descriptor table flag and checksum                      07836000
      in disc label and write back to disc.          >>                 07838000
                                                                        07840000
   disc'label (disc'lab'dirty'dt'flag) := flag'dt'as'dirty;             07842000
   disc'label (disc'lab'dt'check'sum) := dt'check'sum;                  07844000
                                                                        07846000
   return'status := Write'Disc'Label (ldev, 0, disc'label);             07848000
                                                                        07850000
   IF NOT return'status THEN                                            07852000
      BEGIN  << I/O error >>                                            07854000
                                                                        07856000
         Delete'Dfs'Data'Seg (ldev);                                    07858000
         RETURN;                                                        07860000
                                                                        07862000
      END;   << I/O error >>                                            07864000
                                                                        07866000
                                                                        07868000
   << Set status and return >>                                          07870000
                                                                        07872000
   return'status  := no'error;                                          07874000
                                                                        07876000
END;  << Create'Dfs'Data'Seg >>                                         07878000
$PAGE "PROCEDURE DELETE'DFS'DATA'SEG"                                   07880000
PROCEDURE Delete'Dfs'Data'Seg (ldev);                                   07882000
   VALUE ldev;                                                          07884000
   INTEGER ldev;                                                        07886000
   OPTION PRIVILEGED,UNCALLABLE;                                        07888000
                                                                        07890000
<<==============================================================        07892000
                                                                        07894000
      This procedure deletes the DFS data segment for the               07896000
   specified ldev.  The LDTX ldtx'dfs'dst'word is set to zero           07898000
   for that ldev.                                                       07900000
                                                                        07902000
   Parameters:                                                          07904000
      ldev - Ldev of disc.                                              07906000
                                                                        07908000
   Assumptions on entry:                                                07910000
      DB is at the stack.                                               07912000
                                                                        07914000
   Exit conditions:                                                     07916000
      DB is unchanged.                                                  07918000
                                                                        07920000
   Globals:                                                             07922000
                                                                        07924000
      Input:                                                            07926000
         LDTX ldtx'dfs'dst'word                                         07928000
                                                                        07930000
      Output:                                                           07932000
         LDTX ldtx'dfs'dst'word and ldtx'dfs'error'word                 07934000
                                                                        07936000
      Equates:                                                          07938000
         ldt'sir                                                        07940000
         ldt'dst                                                        07942000
         ldt'entry'size                                                 07944000
         ldtx'dfs'dst'word                                              07946000
         ldtx'dfs'error'word                                            07948000
                                                                        07950000
      Defines:                                                          07952000
         Checkdb - (X3=ON bug catching)                                 07954000
                                                                        07956000
   Externals:                                                           07958000
      Getsir                                                            07960000
      Move'From'Data'Seg                                                07962000
      Move'To'Data'Seg                                                  07964000
      Relsir                                                            07966000
      Reldataseg                                                        07968000
      Suddendeath - (X3=ON bug catching)                                07970000
                                                                        07972000
   Intrinsics:                                                          07974000
      None.                                                             07976000
                                                                        07978000
   Callers:                                                             07980000
      Create'Dfs'Data'Seg                                               07982000
      PVPROC module 31                                                  07984000
      PVSYS module 81                                                   07986000
      OPCOMMAND module 81                                               07988000
      ALLOCATE module 54                                                07990000
      VINIT module 32                                                   07992000
                                                                        07994000
   Changes:                                                             07996000
                                                                        07998000
                                                                        08000000
==============================================================>>        08002000
                                                                        08004000
BEGIN                                                                   08006000
                                                                        08008000
   LOGICAL ldt'sir'info;                                                08010000
   INTEGER ldtx'entry'offset;                                           08012000
                                                                        08014000
   INTEGER ARRAY ldt'entry (0:ldt'entry'size-1) = Q;                    08016000
                                                                        08018000
   << - - - - - - - - - - >>                                            08020000
                                                                        08022000
$IF X3=ON   << BUG CATCHER >>                                           08024000
                                                                        08026000
   << Check if DB is at the stack >>                                    08028000
                                                                        08030000
   Checkdb;                                                             08032000
   IF <> THEN Suddendeath (421);                                        08034000
                                                                        08036000
$IF         << BUG CATCHER >>                                           08038000
                                                                        08040000
   << Get DST from LDT and zero DST field >>                            08042000
                                                                        08044000
   ldt'sir'info := Getsir (ldt'sir);                                    08046000
                                                                        08048000
   << Get offset to LDTX >>                                             08050000
                                                                        08052000
   Move'From'Data'Seg (ldt'dst, 0, ldt'entry'size, ldt'entry);          08054000
                                                                        08056000
   ldtx'entry'offset := ldt'entry (1) + ldt'entry (3) +                 08058000
                        (ldev * ldt'entry'size);                        08060000
                                                                        08062000
   Move'From'Data'Seg (ldt'dst, ldtx'entry'offset, ldt'entry'size,      08064000
                       ldt'entry);                                      08066000
                                                                        08068000
   IF ldt'entry (ldtx'dfs'dst'word) <> 0 THEN                           08070000
      Reldataseg (ldt'entry (ldtx'dfs'dst'word));                       08072000
                                                                        08074000
   ldt'entry (ldtx'dfs'dst'word) := 0;                                  08076000
   ldt'entry (ldtx'dfs'error'word) := 0;                                08078000
                                                                        08080000
   Move'To'Data'Seg (ldt'entry, ldt'entry'size, ldt'dst,                08082000
                     ldtx'entry'offset);                                08084000
                                                                        08086000
                                                                        08088000
   Relsir (ldt'sir, ldt'sir'info);                                      08090000
                                                                        08092000
END; << Delete'Dfs'Data'Seg >>                                          08094000
$PAGE "PROCEDURE ALLOCATE'DFS'DATA'SEG"                                 08096000
LOGICAL PROCEDURE Allocate'Dfs'Data'Seg (ldev);                         08098000
   VALUE ldev;                                                          08100000
   INTEGER ldev;                                                        08102000
   OPTION PRIVILEGED,UNCALLABLE;                                        08104000
                                                                        08106000
<<==============================================================        08108000
                                                                        08110000
      This procedure allocates the DFS  data  segment  for  a           08112000
   particular ldev.  This is done for the first logical mount           08114000
   of a private volume.  First the LDTX entry is  checked  to           08116000
   see  if  free space allocation is enabled on this ldev, if           08118000
   it is then the descriptor table is flaged as dirty in  the           08120000
   disc label.                                                          08122000
                                                                        08124000
   Parameters:                                                          08126000
      ldev - Ldev of disc.                                              08128000
                                                                        08130000
   Returns:                                                             08132000
      Standard format status word, indicating if any error              08134000
      occured.                                                          08136000
                                                                        08138000
   Assumptions on entry:                                                08140000
       DB is at the stack.                                              08142000
                                                                        08144000
   Exit conditions:                                                     08146000
      DB is unchanged.                                                  08148000
                                                                        08150000
   Globals:                                                             08152000
                                                                        08154000
      Input:                                                            08156000
         LDTX ldtx'dfs'error'word for ldev.                             08158000
                                                                        08160000
      Output:                                                           08162000
         DISC LABEL disc'lab'dirty'dt'flag for ldev.                    08164000
                                                                        08166000
      Equates:                                                          08168000
         ldt'dst                                                        08170000
         ldt'entry'size                                                 08172000
         ldtx'dfs'error'word                                            08174000
         no'error                                                       08176000
         sector'size                                                    08178000
         disc'lab'dirty'dt'flag                                         08180000
         disc'label'read'error                                          08182000
                                                                        08184000
      Defines:                                                          08186000
         disc'label'address                                             08188000
         error'type                                                     08190000
         Checkdb - (X3=ON bug catching)                                 08192000
                                                                        08194000
   Externals:                                                           08196000
      Move'From'Data'Seg                                                08198000
      Move'To'Data'Seg                                                  08200000
      Read'Disc                                                         08202000
      Write'Disc'Label                                                  08204000
      Suddendeath - (X3=ON bug catching)                                08206000
                                                                        08208000
   Intrinsics:                                                          08210000
      None.                                                             08212000
                                                                        08214000
   Callers:                                                             08216000
      PVSYS module 81                                                   08218000
                                                                        08220000
   Changes:                                                             08222000
                                                                        08224000
                                                                        08226000
==============================================================>>        08228000
                                                                        08230000
BEGIN                                                                   08232000
                                                                        08234000
   INTEGER ARRAY ldt'entry (0:ldt'entry'size-1);                        08236000
   INTEGER ldtx'entry'offset;                                           08238000
   ARRAY disc'label (0:sector'size-1);                                  08240000
                                                                        08242000
   LOGICAL return'status = Allocate'Dfs'Data'Seg;                       08244000
                                                                        08246000
   << - - - - - - - - - - >>                                            08248000
                                                                        08250000
$IF X3=ON   << BUG CATCHER >>                                           08252000
                                                                        08254000
   << Check if DB is at the stack >>                                    08256000
                                                                        08258000
   Checkdb;                                                             08260000
   IF <> THEN Suddendeath (421);                                        08262000
                                                                        08264000
$IF         << BUG CATCHER >>                                           08266000
                                                                        08268000
                                                                        08270000
   << Get  mount error flags from LDTX, first we                        08272000
      must get offset of LDTX from LDT header    >>                     08274000
                                                                        08276000
   Move'From'Data'Seg (ldt'dst, 0, ldt'entry'size, ldt'entry);          08278000
                                                                        08280000
   ldtx'entry'offset := ldt'entry (1) + ldt'entry (3) +                 08282000
                        (ldev * ldt'entry'size);                        08284000
                                                                        08286000
   Move'From'Data'Seg (ldt'dst, ldtx'entry'offset, ldt'entry'size,      08288000
                       ldt'entry);                                      08290000
                                                                        08292000
   << Check to see if no mount error occured >>                         08294000
                                                                        08296000
   IF NOT LOGICAL(ldt'entry(ldtx'dfs'error'word)) THEN                  08298000
      BEGIN   << Mount error - no DST >>                                08300000
                                                                        08302000
         << Return o.k. status, as the error has already                08304000
            been reported                                >>             08306000
                                                                        08308000
         return'status := no'error;                                     08310000
         RETURN;                                                        08312000
                                                                        08314000
     END;     << Mount error - no DST >>                                08316000
                                                                        08318000
                                                                        08320000
   << Flag descriptor table as dirty in disc label. >>                  08322000
                                                                        08324000
   return'status := Read'Disc (ldev, disc'label'address, 0,             08326000
                               disc'label, sector'size);                08328000
                                                                        08330000
   IF NOT return'status THEN                                            08332000
      BEGIN   << Disc label read error >>                               08334000
                                                                        08336000
         return'status.error'type := disc'label'read'error;             08338000
         RETURN;                                                        08340000
                                                                        08342000
      END;    << Disc label read error >>                               08344000
                                                                        08346000
   disc'label (disc'lab'dirty'dt'flag) := TRUE;                         08348000
                                                                        08350000
   return'status := Write'Disc'Label (ldev, 0, disc'label);             08352000
                                                                        08354000
END;  << Allocate'Dfs'Data'Seg >>                                       08356000
$PAGE "LOGICAL PROCEDURE DEALLOCATE'DFS'DATA'SEG"                       08358000
LOGICAL PROCEDURE Deallocate'Dfs'Data'Seg (ldev);                       08360000
   VALUE ldev;                                                          08362000
   INTEGER ldev;                                                        08364000
   OPTION PRIVILEGED,UNCALLABLE;                                        08366000
                                                                        08368000
<<==============================================================        08370000
                                                                        08372000
      This procedure deallocates the DFS data segment for the           08374000
   specified ldev.  This procedure is called on the last log-           08376000
   ical dismount of a private volume, (i.e. no  more  users).           08378000
   It  first  writes  all  dirty pages that are in buffers to           08380000
   disc, if dirty buffer management is enabled.  If then cal-           08382000
   culates the checksum for the descriptor  table and  writes           08384000
   the descriptor table to disc.  The dirty descriptor  table           08386000
   flag in the disc label is then set to FALSE.                         08388000
                                                                        08390000
   Parameters:                                                          08392000
      ldev - Ldev of disc.                                              08394000
                                                                        08396000
   Returns:                                                             08398000
      A standard format status word indicating if an error              08400000
      occured.                                                          08402000
                                                                        08404000
   Assumptions on entry:                                                08406000
      DB is at stack.                                                   08408000
                                                                        08410000
   Exit conditions:                                                     08412000
      DB is unchanged.                                                  08414000
                                                                        08416000
   Globals:                                                             08418000
                                                                        08420000
      Input:                                                            08422000
         ds'buffer'dirty - indicates which pages in buffers             08424000
                           are dirty.  {X2=On, using dirty              08426000
                           buffer management}                           08428000
                                                                        08430000
      Output:                                                           08432000
         DISC LABEL for ldev.                                           08434000
                                                                        08436000
      Others:                                                           08438000
         ds'buffer'index                                                08440000
         ds'last'buffer'index                                           08442000
         ds'buffer'page'number                                          08444000
         ds'descriptor'table                                            08446000
         ds'dst                                                         08448000
                                                                        08450000
      Equates:                                                          08452000
         no'error                                                       08454000
         disc'lab'dt'check'sum                                          08456000
         disc'lab'dirty'dt'flag                                         08458000
         dt'write'error                                                 08460000
         sector'size                                                    08462000
                                                                        08464000
      Define:                                                           08466000
         error'type                                                     08468000
         Checkdb - (X3=ON bug catching)                                 08470000
                                                                        08472000
   Externals:                                                           08474000
      Get'Disc'Info                                                     08476000
      Lock'Dfs'Data'Seg                                                 08478000
      Unlock'Dfs'Data'Seg                                               08480000
      Write'Page                                                        08482000
      Make'Check'Sum                                                    08484000
      Write'Disc                                                        08486000
      Write'Disc'Label                                                  08488000
      Suddendeath - (X3=ON bug catching)                                08490000
                                                                        08492000
   Intrinsics:                                                          08494000
      None.                                                             08496000
                                                                        08498000
   Callers:                                                             08500000
      Process'Sys'Disc'Free'Space'Maps                                  08502000
      PVSYS module 81                                                   08504000
      OPCOMMAND module 85                                               08506000
      ALLOCATE module 54                                                08508000
      VINIT module 32                                                   08510000
                                                                        08512000
   Changes:                                                             08514000
                                                                        08516000
                                                                        08518000
==============================================================>>        08520000
                                                                        08522000
BEGIN                                                                   08524000
                                                                        08526000
   INTEGER dt'size'words;                                               08528000
   DOUBLE dt'disc'address;                                              08530000
                                                                        08532000
   ARRAY disc'label (0:sector'size-1) = Q;                              08534000
                                                                        08536000
   LOGICAL return'status = Deallocate'Dfs'Data'Seg;                     08538000
                                                                        08540000
   << - - - - - - - - - - >>                                            08542000
                                                                        08544000
$IF X3=ON   << BUG CATCHING >>                                          08546000
                                                                        08548000
   << Verify that DB is at the stack >>                                 08550000
                                                                        08552000
   Checkdb;                                                             08554000
   IF <> THEN Suddendeath (421);                                        08556000
                                                                        08558000
$IF         << BUG CATCHING >>                                          08560000
                                                                        08562000
                                                                        08564000
  << Get disc label and info about descriptor table. >>                 08566000
                                                                        08568000
   return'status := Get'Disc'Info (ldev, disc'label, TRUE,  ,  ,  ,  ,  08570000
                                 ,  , dt'disc'address, dt'size'words);  08572000
                                                                        08574000
   IF NOT return'status THEN                                            08576000
      RETURN;   << Get'Disc'Info error >>                               08578000
                                                                        08580000
                                                                        08582000
   << Access data segment >>                                            08584000
                                                                        08586000
   TOS := Lock'Dfs'Data'Seg (ldev);                                     08588000
                                                                        08590000
   IF NOT TOS THEN                                                      08592000
      BEGIN  << Allocation disabled, no DST >>                          08594000
                                                                        08596000
         << Since the fact that free space allocation has               08598000
            been disabled has already been reported to the              08600000
            operator, return an o.k. status.               >>           08602000
                                                                        08604000
         return'status := no'error;                                     08606000
         RETURN;                                                        08608000
                                                                        08610000
      END;   << Allocation disabled, no DST >>                          08612000
                                                                        08614000
                                                                        08616000
   << Write dirty buffers to disc >>                                    08618000
                                                                        08620000
$IF X2=ON  << USING DIRTY BUFFER MANAGEMENT >>                          08622000
                                                                        08624000
   ds'buffer'index := 0;                                                08626000
                                                                        08628000
   WHILE ds'buffer'index <= ds'last'buffer'index DO                     08630000
      BEGIN  << Scan for dirty pages >>                                 08632000
                                                                        08634000
         IF ds'buffer'dirty (ds'buffer'index) THEN                      08636000
             Write'Page (ds'buffer'page'number (ds'buffer'index),       08638000
                         ds'buffer'index);                              08640000
                                                                        08642000
             << Just ignore error status from above >>                  08644000
                                                                        08646000
         ds'buffer'index := ds'buffer'index + 1;                        08648000
                                                                        08650000
      END;   << Scan for dirty pages >>                                 08652000
                                                                        08654000
$IF        << USING DIRTY BUFFER MANAGEMENT >>                          08656000
                                                                        08658000
   << Calculate check sum and write out descriptor table >>             08660000
                                                                        08662000
   disc'label (disc'lab'dt'check'sum) :=                                08664000
         Make'Check'Sum (ds'descriptor'table, dt'size'words);           08666000
                                                                        08668000
   return'status := Write'Disc (ldev, dt'disc'address, ds'dst,          08670000
                            ds'descriptor'table, dt'size'words);        08672000
   IF NOT return'status THEN                                            08674000
      BEGIN  << DT write error >>                                       08676000
                                                                        08678000
         return'status.error'type := dt'write'error;                    08680000
         RETURN;                                                        08682000
                                                                        08684000
      END;   << Dt write error >>                                       08686000
                                                                        08688000
                                                                        08690000
   Unlock'Dfs'Data'Seg;   << Resets DB to stack >>                      08692000
                                                                        08694000
                                                                        08696000
   << Write disc label to disc >>                                       08698000
                                                                        08700000
   disc'label (disc'lab'dirty'dt'flag) := FALSE;                        08702000
                                                                        08704000
   return'status := Write'Disc'Label (ldev, 0, disc'label);             08706000
                                                                        08708000
END;  << Deallocate'Dfs'Data'Seg >>                                     08710000
$PAGE "PROCESS'SYS'DISC'FREE'SPACE'MAPS"                                08712000
PROCEDURE Process'Sys'Disc'Free'Space'Maps (init);                      08714000
   VALUE init;                                                          08716000
   LOGICAL init;                                                        08718000
                                                                        08720000
<<==============================================================        08722000
                                                                        08724000
      This procedure is called by PROGEN at system startup &            08726000
   shutdown time to allocate/deallocate the disc free space             08728000
   data segments for system discs.  Also, at system startup             08730000
   time it zeros out the ldtx'dfs'dst'word and                          08732000
   ldtx'dfs'error'word fields of the LDTX for all discs on              08734000
   the system.  This is so that info that might be on the               08736000
   cold load copy will not be used.                                     08738000
                                                                        08740000
   Parameters:                                                          08742000
      init - If TRUE, then this is system start up time and             08744000
             the data segments should be set up, if FALSE,              08746000
             the this is shutdown time and the data segments            08748000
             should be deallocated.                                     08750000
                                                                        08752000
   Assumptions on entry:                                                08754000
      DB is at the stack.                                               08756000
                                                                        08758000
   Exit conditions:                                                     08760000
      DB is unchanged.                                                  08762000
                                                                        08764000
   Globals:                                                             08766000
                                                                        08768000
      Input:                                                            08770000
         logical device table (LDT)                                     08772000
         volume table                                                   08774000
                                                                        08776000
      Output:                                                           08778000
         logical device table extension (LDTX)                          08780000
                                                                        08782000
      Equates:                                                          08784000
         ldt'dst                                                        08786000
         ldt'entry'size                                                 08788000
         ldt'sir                                                        08790000
         ldtx'dfs'dst'word                                              08792000
         ldtx'dfs'error'word                                            08794000
         vtab'dst                                                       08796000
         vtab'entry'size                                                08798000
                                                                        08800000
      Defines:                                                          08802000
         ldt'type                                                       08804000
         vtab'non'sys'domain                                            08806000
         vtab'ldev                                                      08808000
                                                                        08810000
   Externals:                                                           08812000
      Move'From'Data'Seg                                                08814000
      Getsir                                                            08816000
      Move'To'Data'Seg                                                  08818000
      Create'Dfs'Data'Seg                                               08820000
      Send'Process'Dfs'Error                                            08822000
      Deallocate'Dfs'Data'Seg                                           08824000
                                                                        08826000
   Intrinsics:                                                          08828000
                                                                        08830000
   Callers:                                                             08832000
      PROGEN module 09                                                  08834000
                                                                        08836000
   Changes:                                                             08838000
                                                                        08840000
                                                                        08842000
==============================================================>>        08844000
                                                                        08846000
BEGIN                                                                   08848000
                                                                        08850000
   LOGICAL ARRAY ldt'entry (0:ldt'entry'size-1);                        08852000
   LOGICAL ARRAY ldtx'entry (0:ldt'entry'size-1);                       08854000
   LOGICAL ARRAY vtab'entry (0:vtab'entry'size-1);                      08856000
                                                                        08858000
   INTEGER ldtx'offset;                                                 08860000
   INTEGER ldt'sir'info;                                                08862000
                                                                        08864000
   INTEGER ldev;                                                        08866000
   INTEGER highest'ldev'number;                                         08868000
   LOGICAL stat;                                                        08870000
                                                                        08872000
   << - - - - - - - - - - >>                                            08874000
                                                                        08876000
   << Get highest ldev number and LDTX offset from the LDT              08878000
      header.                                               >>          08880000
                                                                        08882000
   Move'From'Data'Seg (ldt'dst, 0, ldt'entry'size, ldt'entry);          08884000
                                                                        08886000
   highest'ldev'number := ldt'entry (0).(0:8);                          08888000
                                                                        08890000
   ldtx'offset := ldt'entry (1) + ldt'entry (3);                        08892000
                                                                        08894000
                                                                        08896000
   << Run through LDT, finding all discs >>                             08898000
                                                                        08900000
   FOR ldev := 1 UNTIL highest'ldev'number DO                           08902000
      BEGIN  << Run through LDT >>                                      08904000
                                                                        08906000
         << Get LDT entry for this ldev >>                              08908000
                                                                        08910000
         Move'From'Data'Seg (ldt'dst, (ldev * ldt'entry'size),          08912000
                             ldt'entry'size, ldt'entry);                08914000
                                                                        08916000
         IF ldt'entry (ldt'type) < 8 AND ldt'entry (2) <> 0 THEN        08918000
            BEGIN  << Its a disc >>                                     08920000
                                                                        08922000
               << If this is system startup, then zero the free         08924000
                  space related info in the LDTX, as there may be       08926000
                  garbage.  This is done for all disc drives.    >>     08928000
                                                                        08930000
               IF init THEN                                             08932000
                  BEGIN  << Zero info in LDTX >>                        08934000
                                                                        08936000
                     ldt'sir'info := Getsir (ldt'sir);                  08938000
                                                                        08940000
                     Move'From'Data'Seg (ldt'dst, ldtx'offset +         08942000
                           (ldev * ldt'entry'size), ldt'entry'size,     08944000
                           ldtx'entry);                                 08946000
                                                                        08948000
                     ldtx'entry (ldtx'dfs'dst'word) := 0;               08950000
                     ldtx'entry (ldtx'dfs'error'word) := 0;             08952000
                                                                        08954000
                     Move'To'Data'Seg (ldtx'entry, ldt'entry'size,      08956000
                           ldt'dst, ldtx'offset +                       08958000
                           (ldev * ldt'entry'size));                    08960000
                                                                        08962000
                     Relsir (ldt'sir, ldt'sir'info);                    08964000
                                                                        08966000
                  END;   << Zero info in LDTX >>                        08968000
                                                                        08970000
               << Figure out if it is a sys-disc. The ldev field        08972000
                  in the volume table is checked to se that it is       08974000
                  non-zero, as would be the case for a offline          08976000
                  drive.                                          >>    08978000
                                                                        08980000
                                                                        08982000
               Move'From'Data'Seg (vtab'dst, vtab'entry'size *          08984000
                     ldt'entry (ldt'vtab'index), vtab'entry'size,       08986000
                     vtab'entry);                                       08988000
                                                                        08990000
               IF vtab'entry (vtab'non'sys'domain) = 0 AND              08992000
               vtab'entry (vtab'ldev) <> 0 THEN                         08994000
                  BEGIN  << Found a sys disc >>                         08996000
                                                                        08998000
                     IF init THEN                                       09000000
                        BEGIN  << System startup - init >>              09002000
                                                                        09004000
                           stat := Create'Dfs'Data'Seg (ldev,  ,  ,     09006000
                                                        TRUE);          09008000
                           IF NOT stat THEN                             09010000
                              Send'Process'Dfs'Error (ldev, stat, 0);   09012000
                                                                        09014000
                        END    << System startup - init >>              09016000
                     ELSE                                               09018000
                        BEGIN  << System shutdown - deallocate >>       09020000
                                                                        09022000
                           stat := Deallocate'Dfs'Data'Seg (ldev);      09024000
                           IF NOT stat THEN                             09026000
                              Send'Process'Dfs'Error (ldev, stat, 2);   09028000
                                                                        09030000
                        END;   << System shutdown - deallocate >>       09032000
                                                                        09034000
                  END;   << Found a sys disc >>                         09036000
                                                                        09038000
            END;   << Its a disc >>                                     09040000
                                                                        09042000
      END;   << Run through LDT >>                                      09044000
                                                                        09046000
END;  << Process'Sys'Disc'Free'Space'Maps >>                            09048000
$PAGE "READ'PAGE"                                                       09050000
$CONTROL SEGMENT=DFS                                                    09052000
                                                                        09054000
LOGICAL PROCEDURE Read'Page (page, buffer'index);                       09056000
   VALUE page, buffer'index;                                            09058000
   INTEGER page, buffer'index;                                          09060000
   OPTION PRIVILEGED, UNCALLABLE;                                       09062000
                                                                        09064000
<<==============================================================        09066000
                                                                        09068000
      This procedure reads the specified page of the bit  map           09070000
   from  disk  into the buffer whose index is "buffer'index".           09072000
   The checksum for the page  is  verified.   If  an  I/O  or           09074000
   checksum error occures, "Send'Page'Io'Error" is called to pro-       09076000
   cess the error.  The buffer is then marked as empty and  a           09078000
   standard  format  status is returned in "ds'error'status",           09080000
   indicating the type of error that occured.  If no error is           09082000
   encountered,   the   page   number     is     added     to           09084000
   "ds'buffer'page'number" and the buffer is marked as clean,           09086000
   if using dirty buffer management (X2 = ON).  A DB relative           09088000
   pointer to the buffer is returned and and ok status is set           09090000
   in "ds'error'status".                                                09092000
                                                                        09094000
   Parameters:                                                          09096000
      page - The bit map page number of the the page to be              09098000
             read.                                                      09100000
      buffer'index - The index of the buffer to read the page           09102000
                     into.                                              09104000
                                                                        09106000
   Returns:                                                             09108000
      DB relative pointer to the buffer.                                09110000
                                                                        09112000
   Assumptions on entry:                                                09114000
      DB is at the free space data segment for the ldev and             09116000
      the data segment is locked.                                       09118000
                                                                        09120000
   Exit conditions:                                                     09122000
      DB is unchanged.                                                  09124000
                                                                        09126000
   Globals:                                                             09128000
                                                                        09130000
      Output:                                                           09132000
         ds'error'status - Standard format status is returned           09134000
                           here.                                        09136000
         ds'buffer'page'number - Page number is added for the           09138000
                                 entry for the buffer.                  09140000
         ds'buffer'dirty - Entry for the buffer is set to               09142000
                           FALSE (i.e. clean). {X2 =ON,                 09144000
                           Using dirty buffer management}               09146000
                                                                        09148000
      Others:                                                           09150000
         ds'map'address                                                 09152000
         ds'buffer'area                                                 09154000
         ds'ldev                                                        09156000
         ds'dst                                                         09158000
         ds'last'buffer'index - (X3 = ON bug catching)                  09160000
         ds'last'page'of'map - (X3 = ON bug catching)                   09162000
                                                                        09164000
      Equates:                                                          09166000
         actual'words'per'page                                          09168000
         read'io'func                                                   09170000
         blocked'io'flag                                                09172000
         no'error                                                       09174000
         ok'io'status                                                   09176000
         bit'map'read'error                                             09178000
         empty'buffer                                                   09180000
         check'sum'word                                                 09182000
         bit'map'check'sum'error                                        09184000
                                                                        09186000
      Defines:                                                          09188000
         general'io'status                                              09190000
         error'type                                                     09192000
                                                                        09194000
   Externals:                                                           09196000
      Attachio                                                          09198000
      Send'Page'Io'Error                                                09200000
      Make'Check'Sum                                                    09202000
      Suddendeath - (X3 = ON bug catching)                              09204000
                                                                        09206000
   Intrinsics:                                                          09208000
      None.                                                             09210000
                                                                        09212000
   Callers:                                                             09214000
      Get'Page                                                          09216000
                                                                        09218000
   Changes:                                                             09220000
                                                                        09222000
                                                                        09224000
==============================================================>>        09226000
                                                                        09228000
BEGIN                                                                   09230000
                                                                        09232000
   DOUBLE  page'address;       << Disc address of page >>               09234000
   INTEGER page'address'high = page'address + 0;                        09236000
   INTEGER page'address'low  = page'address + 1;                        09238000
                                                                        09240000
   LOGICAL check'sum;   << To hold checksum >>                          09242000
                                                                        09244000
   POINTER buffer'ptr = Read'Page;     << DB rel pointer to buffer, >>  09246000
                                       << this is the value the     >>  09248000
                                       << procedure returns.        >>  09250000
                                                                        09252000
   << - - - - - - - - - - >>                                            09254000
                                                                        09256000
$IF X3=ON  << BUG CATCHER >>                                            09258000
                                                                        09260000
   IF NOT (0 <= page <= ds'last'page'of'map) THEN                       09262000
      Suddendeath (421);                                                09264000
   IF NOT (0 <= buffer'index <= ds'last'buffer'index) THEN              09266000
      Suddendeath (421);                                                09268000
                                                                        09270000
$IF        << BUG CATCHER >>                                            09272000
                                                                        09274000
                                                                        09276000
   << Calculate page disc address and buffer address. >>                09278000
                                                                        09280000
   page'address := DOUBLE(page) + ds'map'address;                       09282000
   @buffer'ptr := @ds'buffer'area + (buffer'index *                     09284000
                      actual'words'per'page);                           09286000
                                                                        09288000
   << Read in page >>                                                   09290000
                                                                        09292000
   TOS := Attachio (ds'ldev, 0, ds'dst, @buffer'ptr, read'io'func,      09294000
                    actual'words'per'page, page'address'high,           09296000
                    page'address'low, blocked'io'flag);                 09298000
                                                                        09300000
   DEL;             << Delete transmission log >>                       09302000
                                                                        09304000
   << Form error word, assume no error >>                               09306000
                                                                        09308000
   ds'error'status := TOS&LSL(8) LOR no'error;                          09310000
                                                                        09312000
   IF ds'error'status.general'io'status <> ok'io'status THEN            09314000
      BEGIN  << I/O error >>                                            09316000
                                                                        09318000
         ds'error'status.error'type := bit'map'read'error;              09320000
         Send'Page'Io'Error (page);                                     09322000
                                                                        09324000
         << Flag buffer as empty >>                                     09326000
                                                                        09328000
         ds'buffer'page'number (buffer'index) := empty'buffer;          09330000
                                                                        09332000
$IF X2=ON   << USING DIRTY BUFFER MANAGEMENT >>                         09334000
                                                                        09336000
         ds'buffer'dirty (buffer'index) := FALSE;                       09338000
                                                                        09340000
$IF         << USING DIRTY BUFFER MANAGEMENT >>                         09342000
                                                                        09344000
      END    << I/O error >>                                            09346000
   ELSE                                                                 09348000
      BEGIN  << I/O o.k. >>                                             09350000
                                                                        09352000
         << Verify Checksum >>                                          09354000
                                                                        09356000
         check'sum := buffer'ptr (check'sum'word);                      09358000
         buffer'ptr (check'sum'word) := 0;                              09360000
                                                                        09362000
         IF check'sum <> Make'Check'Sum (buffer'ptr,                    09364000
         actual'words'per'page) THEN                                    09366000
            BEGIN  << Checksum error >>                                 09368000
                                                                        09370000
               ds'error'status.error'type := bit'map'check'sum'error;   09372000
               Send'Page'Io'Error (page);                               09374000
                                                                        09376000
               << Mark buffer as empty >>                               09378000
                                                                        09380000
               ds'buffer'page'number (buffer'index) := empty'buffer;    09382000
                                                                        09384000
$IF X2=ON   << USING DIRTY BUFFER MANAGEMENT >>                         09386000
                                                                        09388000
               ds'buffer'dirty (buffer'index) := FALSE;                 09390000
                                                                        09392000
$IF         << USING DIRTY BUFFER MANAGEMENT >>                         09394000
                                                                        09396000
            END    << Checksum error >>                                 09398000
         ELSE                                                           09400000
            BEGIN  << No checksum error >>                              09402000
                                                                        09404000
               << Set buffer info >>                                    09406000
                                                                        09408000
               ds'buffer'page'number (buffer'index) := page;            09410000
                                                                        09412000
$IF X2=ON   << USING DIRTY BUFFER MANAGEMENT >>                         09414000
                                                                        09416000
               ds'buffer'dirty (buffer'index) := FALSE;                 09418000
                                                                        09420000
$IF         << USING DIRTY BUFFER MANAGEMENT >>                         09422000
                                                                        09424000
                                                                        09426000
            END;   << No checksum error >>                              09428000
                                                                        09430000
      END;   << I/O o.k. >>                                             09432000
                                                                        09434000
END;  << Read'Page >>                                                   09436000
$PAGE "WRITE'PAGE"                                                      09438000
PROCEDURE Write'Page (page, buffer'index);                              09440000
   VALUE page, buffer'index;                                            09442000
   INTEGER page, buffer'index;                                          09444000
   OPTION PRIVILEGED, UNCALLABLE;                                       09446000
                                                                        09448000
<<==============================================================        09450000
                                                                        09452000
      This procedure writes the specified page of the bit map           09454000
   from the buffer indicated by "buffer'index"  to  disk.   A           09456000
   new  checksum is generated for the page before it is writ-           09458000
   ten.  If an I/O error occures, "Send'Page'Io'Error"  is  called      09460000
   to  process the error.  The buffer is then marked as empty           09462000
   and error info is returned in  "ds'error'status".   If  no           09464000
   error occures, the  page is marked as clean, if dirty buf-           09466000
   fer management  is in use (X2 = ON),  and an ok  status is           09468000
   returned in "ds'error'status".                                       09470000
                                                                        09472000
   Parameters:                                                          09474000
      page - The bit map page number of the page to be read.            09476000
      buffer'index - The index of the buffer to read the page           09478000
                     into.                                              09480000
                                                                        09482000
   Assumptions on entry:                                                09484000
      DB is at the free space data segment for the ldev and             09486000
      the data segment is locked.                                       09488000
                                                                        09490000
   Exit conditions:                                                     09492000
      DB is unchanged.                                                  09494000
                                                                        09496000
   Globals:                                                             09498000
                                                                        09500000
      Output:                                                           09502000
         ds'error'status - Standard format status is returned           09504000
                           here.                                        09506000
         ds'buffer'dirty - The entry for this buffer is set             09508000
                           to FALSE (i.e. clean).  {X2 = ON,            09510000
                           using dirty buffer management}               09512000
      Others:                                                           09514000
         ds'map'address                                                 09516000
         ds'buffer'area                                                 09518000
         ds'ldev                                                        09520000
         ds'dst                                                         09522000
         ds'last'buffer'index - (X3 = ON bug catcher)                   09524000
         ds'last'page'of'map - (X3 = ON bug catcher)                    09526000
         ds'buffer'page'number - (X3 = ON bug catcher)                  09528000
                                                                        09530000
      Equates:                                                          09532000
         actual'words'per'page                                          09534000
         check'sum'word                                                 09536000
         no'error                                                       09538000
         write'io'func                                                  09540000
         blocked'io'flag                                                09542000
         ok'io'status                                                   09544000
         bit'map'write'error                                            09546000
         empty'buffer                                                   09548000
                                                                        09550000
      Defines:                                                          09552000
         general'io'status                                              09554000
         error'type                                                     09556000
                                                                        09558000
   Externals:                                                           09560000
      Make'Check'Sum                                                    09562000
      Attachio                                                          09564000
      Send'Page'Io'Error                                                09566000
      Suddendeath - (X3 = ON bug catcher)                               09568000
      Send'Process'Dfs'Error - (X3 = OFF no bug catcher)                09570000
                                                                        09572000
   Intrinsics:                                                          09574000
      None.                                                             09576000
                                                                        09578000
   Callers:                                                             09580000
      Get'Page                                                          09582000
      Set'Reset'Bit'Map                                                 09584000
      Deallocate'Dfs'Data'Seg                                           09586000
                                                                        09588000
   Changes:                                                             09590000
                                                                        09592000
                                                                        09594000
==============================================================>>        09596000
                                                                        09598000
BEGIN                                                                   09600000
                                                                        09602000
   DOUBLE page'address;  << Disc address of page >>                     09604000
   INTEGER page'address'high = page'address + 0;                        09606000
   INTEGER page'address'low  = page'address + 1;                        09608000
                                                                        09610000
   POINTER buffer'ptr;    << DB rel pointer to buffer. >>               09612000
                                                                        09614000
   << - - - - - - - - - - >>                                            09616000
                                                                        09618000
$IF X3 = ON  << BUG CATCHER >>                                          09620000
                                                                        09622000
   IF NOT (0 <= page <= ds'last'page'of'map) THEN                       09624000
      Suddendeath (421);                                                09626000
   IF NOT (0 <= buffer'index <= ds'last'buffer'index) THEN              09628000
      Suddendeath (421);                                                09630000
   IF ds'buffer'page'number (buffer'index) <> page THEN                 09632000
      Suddendeath (421);                                                09634000
                                                                        09636000
$IF X3=OFF   << BUG CATCHER >>                                          09638000
                                                                        09640000
   << This is to try and prevent us from writing to the  >>             09642000
   << wrong part of the disc.                            >>             09644000
                                                                        09646000
   IF NOT (0 <= page <= ds'last'page'of'map) THEN                       09648000
      Send'Process'Dfs'Error (ds'ldev, 0, [8/4, 8/4]);                  09650000
                                                                        09652000
$IF                                                                     09654000
                                                                        09656000
                                                                        09658000
   << Calculate page disc address and buffer address. >>                09660000
                                                                        09662000
   page'address := DOUBLE(page) + ds'map'address;                       09664000
   @buffer'ptr := @ds'buffer'area + (buffer'index *                     09666000
                      actual'words'per'page);                           09668000
                                                                        09670000
   << Generate checksum >>                                              09672000
                                                                        09674000
   buffer'ptr (check'sum'word) := 0;                                    09676000
   buffer'ptr (check'sum'word) :=                                       09678000
      Make'Check'Sum (buffer'ptr, actual'words'per'page);               09680000
                                                                        09682000
   << Write out page >>                                                 09684000
                                                                        09686000
   TOS := Attachio (ds'ldev, 0, ds'dst, @buffer'ptr, write'io'func,     09688000
                    actual'words'per'page, page'address'high,           09690000
                    page'address'low, blocked'io'flag);                 09692000
                                                                        09694000
   DEL;             << Delete transmission log >>                       09696000
                                                                        09698000
   << Form error word, assume no error >>                               09700000
                                                                        09702000
   ds'error'status := TOS&LSL(8) LOR no'error;                          09704000
                                                                        09706000
   IF ds'error'status.general'io'status <> ok'io'status THEN            09708000
      BEGIN  << I/O error >>                                            09710000
                                                                        09712000
         ds'error'status.error'type := bit'map'write'error;             09714000
         Send'Page'IO'Error (page);                                     09716000
                                                                        09718000
         << Flag buffer as empty >>                                     09720000
                                                                        09722000
         ds'buffer'page'number (buffer'index) := empty'buffer;          09724000
                                                                        09726000
$IF X2=ON   << USING DIRTY BUFFER MANAGEMENT >>                         09728000
                                                                        09730000
         ds'buffer'dirty (buffer'index) := FALSE;                       09732000
                                                                        09734000
$IF         << USING DIRTY BUFFER MANAGEMENT >>                         09736000
                                                                        09738000
                                                                        09740000
      END    << I/O error >>                                            09742000
   ELSE                                                                 09744000
      BEGIN  << I/O o.k. >>                                             09746000
                                                                        09748000
         << set buffer info >>                                          09750000
                                                                        09752000
$IF X2=ON   << USING DIRTY BUFFER MANAGEMENT >>                         09754000
                                                                        09756000
         ds'buffer'dirty (buffer'index) := FALSE;                       09758000
                                                                        09760000
$IF         << USING DIRTY BUFFER MANAGEMENT >>                         09762000
                                                                        09764000
                                                                        09766000
      END;   << I/O o.k. >>                                             09768000
                                                                        09770000
END;  << Write'Page >>                                                  09772000
$INCLUDE INCLDFSC                                                       09774000
$PAGE "GET'PAGE"                                                        09776000
LOGICAL PROCEDURE Get'Page (page);                                      09778000
   VALUE page;                                                          09780000
   INTEGER page;                                                        09782000
   OPTION PRIVILEGED, UNCALLABLE;                                       09784000
                                                                        09786000
<<==============================================================        09788000
                                                                        09790000
      Procedure to read the requested page into a buffer  and           09792000
   return a pointer to it.   First the descriptor table is              09794000
   check to see if the page is marked as bad, if it is, status          09796000
   is returned and we exit.  First "ds'buffer'page'number" is           09798000
   scanned to see if the page is in a buffer, also the  first           09800000
   empty  page  found is remembered.  If the page is found, a           09802000
   ok status is set in "ds'error'status" and a pointer to the           09804000
   buffer is returned.  If the page is not in a  buffer,  and           09806000
   an  empty  buffer  is available, the page is read into the           09808000
   empty buffer.  If no empties are available the buffer  in-           09810000
   dicated by "ds'next'buffer'index" is used.  If the page in           09812000
   the buffer is dirty, it  is  written  out  to  disc.   I/O           09814000
   errors  occuring  during  this  write are ignored, as they           09816000
   have already been processed by "Write'Page" and  the  page           09818000
   is not necessary for getting the requested page.  The page           09820000
   is then read into the buffer.  If  an  I/O  error  occures           09822000
   while  reading in the page, a standard format error is re-           09824000
   turned in "ds'error'status".   On  exit  "ds'buffer'index"           09826000
   will  have the index of the buffer containing the page and           09828000
   the procedure will return a data segment relative  pointer           09830000
   to  the  buffer.    "ds'next'buffer'index"  will be set to           09832000
   point to the buffer following the buffer used,  with  wrap           09834000
   around.                                                              09836000
                                                                        09838000
   Parameters:                                                          09840000
      page - Number of page to get.                                     09842000
                                                                        09844000
   Returns:                                                             09846000
      If no error, a data segement relative pointer to the              09848000
      buffer containing the page.                                       09850000
                                                                        09852000
   Assumptions on entry:                                                09854000
      DB is at the free space data segment for the ldev and             09856000
      the data segment is locked.                                       09858000
                                                                        09860000
   Exit conditions:                                                     09862000
      DB is unchanged.                                                  09864000
                                                                        09866000
   Globals:                                                             09868000
                                                                        09870000
      Input:                                                            09872000
         ds'descriptor'table                                            09874000
                                                                        09876000
      Output:                                                           09878000
         ds'buffer'index - Set to index of buffer containing            09880000
                           the page just read.                          09882000
         ds'next'buffer'index - Set to point to next buffer             09884000
                                to use when we are hard up              09886000
                                for a buffer.                           09888000
         ds'buffer'page'number - Entry for buffer used is               09890000
                                 set by "Read'Page" if page             09892000
                                 had to be read in.                     09894000
         ds'buffer'dirty - Entry for buffer used is set by              09896000
                           "Read'Page" to FALSE (i.e clean)             09898000
                           if page had to be read in. {X2=ON,           09900000
                           using dirty buffer management}               09902000
         ds'error'status - Has standard format error code.              09904000
                                                                        09906000
      Others:                                                           09908000
         ds'last'buffer'index                                           09910000
         ds'buffer'area                                                 09912000
         ds'last'page'of'map - (X3 = ON bug catcher)                    09914000
         dt'entry'size                                                  09916000
         bad'page                                                       09918000
         page'marked'as'bad'error                                       09920000
                                                                        09922000
      Equates:                                                          09924000
         empty'buffer                                                   09926000
         actual'words'per'page                                          09928000
         no'error                                                       09930000
                                                                        09932000
   Externals:                                                           09934000
      Write'Page                                                        09936000
      Read'Page                                                         09938000
      Suddendeath - (X3 = ON bug catcher)                               09940000
                                                                        09942000
   Callers:                                                             09944000
      Build'Descriptor'Entry                                            09946000
      Set'Reset'Bit'Map                                                 09948000
      Locate'Free'Space                                                 09950000
      Get'Specific'Disc'Space                                           09952000
      VINIT module 32                                                   09954000
      FREE2 module FR                                                   09956000
                                                                        09958000
   Changes:                                                             09960000
                                                                        09962000
                                                                        09964000
==============================================================>>        09966000
                                                                        09968000
BEGIN                                                                   09970000
                                                                        09972000
   LOGICAL found;            << For flagging that we found the page >>  09974000
   INTEGER empty'buffer'index;  << Used to remember an empty buffer >>  09976000
                                                                        09978000
   POINTER page'ptr = Get'Page; << Return value, ptr to the page    >>  09980000
                                                                        09982000
   << - - - - - - - - - - >>                                            09984000
                                                                        09986000
$IF X3=ON  << BUG CATCHER >>                                            09988000
                                                                        09990000
   IF NOT (0 <= page <= ds'last'page'of'map) THEN                       09992000
      Suddendeath (421);                                                09994000
                                                                        09996000
$IF        << BUG CATCHER >>                                            09998000
                                                                        10000000
                                                                        10002000
   << Check to see if page is marked as bad in the descriptor table >>  10004000
                                                                        10006000
   IF ds'descriptor'table (page * dt'entry'size) = bad'page THEN        10008000
      BEGIN  << Page is marked as bad >>                                10010000
                                                                        10012000
         ds'error'status := page'marked'as'bad'error;                   10014000
         RETURN;                                                        10016000
                                                                        10018000
      END;   << Page is marked as bad >>                                10020000
                                                                        10022000
                                                                        10024000
   << Scan "ds'buffer'page'number" to see if the page is in             10026000
      a buffer.  Also remember the first empty buffer found. >>         10028000
                                                                        10030000
   found := FALSE;                                                      10032000
   empty'buffer'index := -1;                                            10034000
   ds'buffer'index := 0;                                                10036000
                                                                        10038000
   WHILE ds'buffer'index <= ds'last'buffer'index AND NOT found DO       10040000
      BEGIN  << Look for page in buffer >>                              10042000
                                                                        10044000
         IF ds'buffer'page'number (ds'buffer'index) = page THEN         10046000
                                                                        10048000
            found := TRUE                                               10050000
         ELSE                                                           10052000
            IF ds'buffer'page'number (ds'buffer'index) = empty'buffer   10054000
            AND empty'buffer'index < 0 THEN                             10056000
               BEGIN  << First empty buffer >>                          10058000
                                                                        10060000
                  empty'buffer'index := ds'buffer'index;                10062000
                  ds'buffer'index := ds'buffer'index + 1;               10064000
                                                                        10066000
               END    << First empty buffer >>                          10068000
            ELSE                                                        10070000
                                                                        10072000
               ds'buffer'index := ds'buffer'index + 1;                  10074000
                                                                        10076000
      END;   << Look for page in buffer >>                              10078000
                                                                        10080000
                                                                        10082000
   << At this point, if "found" is TRUE then we have found the page     10084000
      in a buffer and "ds'buffer'index" is pointing to it.  If it       10086000
      is FALSE, the either "empty'buffer'index" points to a empty       10088000
      buffer or we will have to through out a page.                 >>  10090000
                                                                        10092000
   IF found THEN                                                        10094000
      BEGIN  << Page is in a buffer >>                                  10096000
                                                                        10098000
         @page'ptr := @ds'buffer'area + (ds'buffer'index *              10100000
                      actual'words'per'page);                           10102000
         ds'error'status := no'error;                                   10104000
                                                                        10106000
      END   << Page is in a buffer >>                                   10108000
   ELSE                                                                 10110000
      BEGIN  << Page is not in a buffer >>                              10112000
                                                                        10114000
         IF empty'buffer'index < 0 THEN                                 10116000
            BEGIN  << No empty buffers >>                               10118000
                                                                        10120000
               ds'buffer'index := ds'next'buffer'index;                 10122000
                                                                        10124000
$IF X2=ON   << USING DIRTY BUFFER MANAGEMENT >>                         10126000
                                                                        10128000
               IF ds'buffer'dirty (ds'buffer'index) THEN                10130000
                  BEGIN  << Page in buffer is dirty >>                  10132000
                                                                        10134000
                     Write'Page (                                       10136000
                           ds'buffer'page'number (ds'buffer'index),     10138000
                           ds'buffer'index);                            10140000
                                                                        10142000
                     << Just ignore I/O error, as it has already        10144000
                        been handled by "Write'Page".  The error        10146000
                        status will be reset when the page we           10148000
                        want is read in.                        >>      10150000
                                                                        10152000
                  END;   << Page in buffer is dirty >>                  10154000
$IF         << USING DIRTY BUFFER MANAGEMENT >>                         10156000
                                                                        10158000
                                                                        10160000
            END    << No empty buffers >>                               10162000
         ELSE                                                           10164000
                                                                        10166000
            << An empty buffer, use it. >>                              10168000
                                                                        10170000
            ds'buffer'index := empty'buffer'index;                      10172000
                                                                        10174000
                                                                        10176000
         << Read page into buffer >>                                    10178000
                                                                        10180000
         @page'ptr := Read'Page (page, ds'buffer'index);                10182000
                                                                        10184000
         IF NOT ds'error'status THEN                                    10186000
            RETURN;  << Let caller handle the error >>                  10188000
                                                                        10190000
      END;  << Page not in buffer >>                                    10192000
                                                                        10194000
                                                                        10196000
   << Set next buffer index to point to next buffer >>                  10198000
                                                                        10200000
   IF ds'next'buffer'index >= ds'last'buffer'index THEN                 10202000
      ds'next'buffer'index := 0                                         10204000
   ELSE                                                                 10206000
      ds'next'buffer'index := ds'next'buffer'index + 1;                 10208000
                                                                        10210000
END;  << Get'Page >>                                                    10212000
$PAGE "BUILD'DESCRIPTOR'ENTRY"                                          10214000
PROCEDURE Build'Descriptor'Entry (page);                                10216000
   VALUE page;                                                          10218000
   INTEGER page;                                                        10220000
   OPTION VARIABLE,PRIVILEGED,UNCALLABLE;                               10222000
                                                                        10224000
<<==============================================================        10226000
                                                                        10228000
      Procedure to build  a  descriptor  table  entry  for  a           10230000
   specified  page  of  the bit map.  The page is scanned and           10232000
   the amount free space at the beginning and the end of  the           10234000
   page  and  the  largest  continuous  free space blocks not           10236000
   at the beginning or end of the page  are put  in  the  de-           10238000
   scriptor  table entry for that page.   If "Get'Page"  gets           10240000
   an I/O error, the procedure is exited, leaving status info           10242000
   in "ds'error'status".   The threshold pointer is then  up-           10244000
   dated if necessary.                                                  10246000
                                                                        10248000
   Parameters:                                                          10250000
      page - page number of page to build descriptor entry              10252000
             for. (optional) If this parameter is not passed            10254000
             then it is assumed that the page number is in              10256000
             ds'page'number and the page is already in a                10258000
             buffer and pointed to by ds'page'ptr.  This saves          10260000
             a call to Get'Page.                                        10262000
                                                                        10264000
   Assumptions on entry:                                                10266000
      DB is at the free space data segment for the ldev and             10268000
      the data segment is locked.                                       10270000
                                                                        10272000
   Exit conditions:                                                     10274000
      DB is unchanged.                                                  10276000
                                                                        10278000
   Globals:                                                             10280000
                                                                        10282000
      Input:                                                            10284000
         ds'page'number - will have page number of page on exit.        10286000
         ds'page'ptr  - will point to page on exit.                     10288000
                                                                        10290000
      Output:                                                           10292000
         ds'error'status - Will have the standard format                10294000
                           error status returned by                     10296000
                           "Get'Page".                                  10298000
         ds'descriptor'table - The entry for the page will be           10300000
                               updated.                                 10302000
         ds'first'threshold'page                                        10304000
                                                                        10306000
      Others:                                                           10308000
         ds'word'number                                                 10310000
         ds'bit'number                                                  10312000
         ds'starting'word'number                                        10314000
         ds'starting'bit'number                                         10316000
         ds'bit'count                                                   10318000
         ds'last'page'of'map - (X3=ON bug catcher)                      10320000
                                                                        10322000
      Equates:                                                          10324000
         bits'per'page                                                  10326000
         dt'entry'size                                                  10328000
         largest'space                                                  10330000
         starting'space                                                 10332000
         ending'space                                                   10334000
         bad'page                                                       10336000
         threshold'size                                                 10338000
                                                                        10340000
   Externals:                                                           10342000
      Get'Page                                                          10344000
      Scan'Page                                                         10346000
      Suddendeath (X3 = ON bug catcher)                                 10348000
                                                                        10350000
   Intrinsics:                                                          10352000
      None.                                                             10354000
                                                                        10356000
   Callers:                                                             10358000
      Create'Dfs'Data'Seg                                               10360000
      Set'Reset'Bit'Map                                                 10362000
                                                                        10364000
   Changes:                                                             10366000
                                                                        10368000
                                                                        10370000
==============================================================>>        10372000
                                                                        10374000
BEGIN << Build'Descriptor'Entry >>                                      10376000
                                                                        10378000
   LOGICAL end'of'page;  << Flag to indicate the end of page >>         10380000
                                                                        10382000
   << These are used for a local descriptor entry, they                 10384000
      are later move to the descriptor table.               >>          10386000
                                                                        10388000
   INTEGER largest'size;                                                10390000
   INTEGER starting'size;                                               10392000
   INTEGER ending'size;                                                 10394000
                                                                        10396000
   << These are pointers into the descriptor table >>                   10398000
                                                                        10400000
   INTEGER POINTER current'dt'entry;                                    10402000
   INTEGER POINTER last'dt'entry;                                       10404000
   INTEGER POINTER next'dt'entry;                                       10406000
                                                                        10408000
   << Parameter map >>                                                  10410000
                                                                        10412000
   LOGICAL pmap = Q-4;                                                  10414000
   DEFINE passed'page = pmap.(15:1)#;                                   10416000
                                                                        10418000
   << - - - - - - - - - - >>                                            10420000
                                                                        10422000
                                                                        10424000
   IF passed'page THEN                                                  10426000
      BEGIN  << Must get the page >>                                    10428000
                                                                        10430000
         @ds'page'ptr := Get'Page (page);                               10432000
                                                                        10434000
         IF NOT ds'error'status THEN                                    10436000
            RETURN;  << I/O error - let caller handle >>                10438000
                                                                        10440000
      END    << Must get the page >>                                    10442000
   ELSE                                                                 10444000
      BEGIN  << Page already in a buffer >>                             10446000
                                                                        10448000
         page := ds'page'number;                                        10450000
                                                                        10452000
      END;   << Page already in a buffer >>                             10454000
                                                                        10456000
$IF X3=ON  << BUG CATCHER >>                                            10458000
                                                                        10460000
   IF NOT (0 <= page <= ds'last'page'of'map) THEN                       10462000
      Suddendeath (421);                                                10464000
                                                                        10466000
   << Check to make sure this is not a bad page. >>                     10468000
                                                                        10470000
   IF                                                                   10472000
   ds'descriptor'table ((page*dt'entry'size) + largest'space) =         10474000
   bad'page OR                                                          10476000
   ds'descriptor'table ((page*dt'entry'size) + starting'space) =        10478000
   bad'page OR                                                          10480000
   ds'descriptor'table ((page*dt'entry'size) + ending'space) =          10482000
   bad'page                                                             10484000
   THEN                                                                 10486000
      Suddendeath (421);                                                10488000
                                                                        10490000
$IF        << BUG CATCHER >>                                            10492000
                                                                        10494000
   << Initialize local descriptor table entry. >>                       10496000
                                                                        10498000
   largest'size := 0;                                                   10500000
   starting'size := 0;                                                  10502000
   ending'size := 0;                                                    10504000
                                                                        10506000
                                                                        10508000
   << Scan through page, finding each block of free space and           10510000
      maybe saving it in the local descriptor entry.          >>        10512000
                                                                        10514000
   end'of'page := FALSE;                                                10516000
   ds'word'number := 0;                                                 10518000
   ds'bit'number := 0;                                                  10520000
                                                                        10522000
   WHILE NOT end'of'page DO                                             10524000
      BEGIN << scan page >>                                             10526000
                                                                        10528000
         end'of'page := Scan'Page;                                      10530000
                                                                        10532000
         IF ds'bit'count <> 0 THEN                                      10534000
            BEGIN << found some space >>                                10536000
                                                                        10538000
               IF ds'starting'word'number = 0 AND                       10540000
               ds'starting'bit'number = 0 THEN                          10542000
                                                                        10544000
                  << set size of area at start of page >>               10546000
                                                                        10548000
                  starting'size := ds'bit'count                         10550000
                                                                        10552000
               ELSE                                                     10554000
                  IF end'of'page THEN                                   10556000
                                                                        10558000
                     << set size of area at end of page >>              10560000
                                                                        10562000
                     ending'size := ds'bit'count                        10564000
                                                                        10566000
                  ELSE                                                  10568000
                                                                        10570000
                     << Its somewhere in the middle of the page,        10572000
                        is it largest so far?                    >>     10574000
                                                                        10576000
                     IF ds'bit'count > largest'size THEN                10578000
                        largest'size := ds'bit'count;                   10580000
                                                                        10582000
            END;  << found some space >>                                10584000
                                                                        10586000
      END;  << scan page >>                                             10588000
                                                                        10590000
                                                                        10592000
   << If page is full, then set ending size. >>                         10594000
                                                                        10596000
   IF starting'size = bits'per'page THEN                                10598000
      ending'size := bits'per'page;                                     10600000
                                                                        10602000
                                                                        10604000
   << store in descriptor table >>                                      10606000
                                                                        10608000
   ds'descriptor'table((page*dt'entry'size) + largest'space) :=         10610000
      largest'size;                                                     10612000
   ds'descriptor'table((page*dt'entry'size) + starting'space) :=        10614000
      starting'size;                                                    10616000
   ds'descriptor'table((page*dt'entry'size) + ending'space) :=          10618000
      ending'size;                                                      10620000
                                                                        10622000
                                                                        10624000
   << Update "ds'first'threshold'page".  This needs to be done if       10626000
      the current page is less than the first threshold page and there  10628000
      is a block larger than the threshold size starting on this page,  10630000
      or starting on the previous page and continuing on this page.     10632000
      If this page is currently the page pointed to by                  10634000
      "ds'first'threshold'page" and there is no longer a threshold      10636000
      block starting on this page, then the pointer needs to be moved   10638000
      forward.  NOTE:  This code will not work if the threshold size    10640000
      is greater than or equal to the amount of space that can be       10642000
      represented on one page. It also depends on the null entry        10644000
      before the descriptor table.                                 >>   10646000
                                                                        10648000
                                                                        10650000
      IF page < ds'first'threshold'page THEN                            10652000
         BEGIN  << May need to set back threshold >>                    10654000
                                                                        10656000
            IF (largest'size >= threshold'size) OR                      10658000
            ((ds'descriptor'table(((page + 1) * dt'entry'size) +        10660000
            starting'space) + ending'size) >= threshold'size) OR        10662000
            ((ds'descriptor'table((page * dt'entry'size) +              10664000
            previous'adjacent'space) = 0) LAND                          10666000
            starting'size >= threshold'size) THEN                       10668000
                                                                        10670000
               ds'first'threshold'page := page                          10672000
                                                                        10674000
            ELSE                                                        10676000
               IF (starting'size + ds'descriptor'table((page *          10678000
               dt'entry'size) + previous'adjacent'space)) >=            10680000
               threshold'size THEN                                      10682000
                                                                        10684000
                  ds'first'threshold'page := page - 1;                  10686000
                                                                        10688000
         END    << May need to set back threshold >>                    10690000
      ELSE                                                              10692000
         IF ds'first'threshold'page = page THEN                         10694000
            BEGIN  << Move first threshold page forward >>              10696000
                                                                        10698000
               @current'dt'entry := (page * dt'entry'size) +            10700000
                                    @ds'descriptor'table;               10702000
               @last'dt'entry := @ds'descriptor'table +                 10704000
                           (ds'last'page'of'map * dt'entry'size);       10706000
               @next'dt'entry := @current'dt'entry + dt'entry'size;     10708000
                                                                        10710000
               WHILE                                                    10712000
               @current'dt'entry <= @last'dt'entry LAND NOT(            10714000
               (current'dt'entry (starting'space) >= threshold'size) LOR10716000
               (current'dt'entry (largest'space) >= threshold'size) LOR 10718000
               ((current'dt'entry (ending'space) > 0) LAND              10720000
               ((current'dt'entry (ending'space) +                      10722000
               next'dt'entry (starting'space)) >= threshold'size)))     10724000
               DO                                                       10726000
                  BEGIN  << Try next page >>                            10728000
                                                                        10730000
                     @current'dt'entry := @next'dt'entry;               10732000
                     @next'dt'entry := @next'dt'entry + dt'entry'size;  10734000
                                                                        10736000
                  END;   << Try next page >>                            10738000
                                                                        10740000
                                                                        10742000
               ds'first'threshold'page := (@current'dt'entry -          10744000
                     @ds'descriptor'table) / dt'entry'size;             10746000
                                                                        10748000
            END;   << Move first threshold page forward >>              10750000
                                                                        10752000
END;  << Build'Descriptor'Table >>                                      10754000
$PAGE "SET'RESET'BIT'MAP"                                               10756000
PROCEDURE Set'Reset'Bit'Map (set'bits);                                 10758000
   VALUE set'bits;                                                      10760000
   LOGICAL set'bits;                                                    10762000
   OPTION PRIVILEGED,UNCALLABLE;                                        10764000
                                                                        10766000
<<==============================================================        10768000
                                                                        10770000
      This procedure turns on or off a set of continous  bits           10772000
   in the map.  The starting location in the map should be in           10774000
   "ds'page'number",  "ds'word'number"  and  "ds'bit'number".           10776000
   The  number  of  bits  to  turn  on  or  off  should be in           10778000
   "ds'number'of'sectors".  If turning off bits (i.e  getting           10780000
   space) each page is written out after it has been changed.           10782000
   If turning on bits (i.e returning space), then the page is           10784000
   flag as dirty, but not written out until a buffer is need-           10786000
   ed if the procedure was compiled with X2 ON.  If  compiled           10788000
   with  X2  OFF, pages of the map are always written to disc           10790000
   after being changed.  Each page  must  always  be  written           10792000
   when  allocating  space  to prevent space form being allo-           10794000
   cated to a file but also in the free  map  if  the  system           10796000
   crashed  before  the buffer was written.  On deallocation,           10798000
   system crashs will cause some space to be lost  because  a           10800000
   buffer  has  not  been written, but nothing dangerous will           10802000
   occure.  Compiling with X2 on will lead to faster  return-           10804000
   ing  of  space,  but undesireable loss of large amounts of           10806000
   free space if the system crash often. (This space  can  be           10808000
   recovered  with recover lost disc space or a condense.) If           10810000
   an Get'Page error occures while returning space, the  page           10812000
   is just skiped , having already been flaged as bad.  If an           10814000
   Get'Page error occures while getting space, the  procedure           10816000
   is exited, leaving error information in "ds'error'status".           10818000
   If an I/O error occures while writting a page, the  status           10820000
   is reset to the "no'error" state, as the error has already           10822000
   been processed, and it should not matter to the caller.              10824000
                                                                        10826000
      A special entry point, "Must'Set'Reset'Bit'Map" is pro-           10828000
   vided for VINIT.  This only difference with this entry  is           10830000
   that  no  checking is done to see if the map is in the ex-           10832000
   pected state before changing it.                                     10834000
                                                                        10836000
   Parameters:                                                          10838000
      set'bits - TRUE to turn on bits (i.e return space)                10840000
                 FALSE to turn off bits (i.e. allocate space)           10842000
                                                                        10844000
   Assumptions on entry:                                                10846000
      DB is at the free space data segment for the ldev and             10848000
      the data segment is locked.                                       10850000
                                                                        10852000
   Exit conditions:                                                     10854000
      DB is unchanged.                                                  10856000
                                                                        10858000
   Globals:                                                             10860000
                                                                        10862000
      Input:                                                            10864000
         ds'page'number - Changed on exit.                              10866000
         ds'word'number - Changed on exit.                              10868000
         ds'bit'number - Changed on exit.                               10870000
         ds'number'of'sectors                                           10872000
                                                                        10874000
      Output:                                                           10876000
         ds'error'status                                                10878000
         ds'buffer'dirty - {X2=ON, using dirty buffer management}       10880000
                                                                        10882000
      Others:                                                           10884000
         ds'last'page'of'map                                            10886000
         ds'page'ptr                                                    10888000
         ds'buffer'index                                                10890000
                                                                        10892000
      Equates:                                                          10894000
         no'error                                                       10896000
         bits'per'page                                                  10898000
         words'per'page                                                 10900000
         space'already'free'error                                       10902000
         space'not'free'error                                           10904000
         unexpected'dfs'error                                           10906000
                                                                        10908000
      Defines:                                                          10910000
         error'type                                                     10912000
         DBL                                                            10914000
                                                                        10916000
   Externals:                                                           10918000
      Get'Page                                                          10920000
      Send'Process'Dfs'Error                                            10922000
      Suddendeath - (X3 = ON  cub catcher)                              10924000
      Build'Descriptor'Entry                                            10926000
      Write'Page                                                        10928000
                                                                        10930000
   Intrinsics:                                                          10932000
      None.                                                             10934000
                                                                        10936000
   Callers:                                                             10938000
      Get'Disc'Space                                                    10940000
      Return'Disc'Space                                                 10942000
      Get'Specific'Disc'Space                                           10944000
      VINIT module 32 (also calls Must'Set'Reset'Bit'Map entry)         10946000
                                                                        10948000
   Changes:                                                             10950000
                                                                        10952000
                                                                        10954000
==============================================================>>        10956000
                                                                        10958000
BEGIN                                                                   10960000
                                                                        10962000
   ENTRY must'set'reset'bit'map;  << Special entry point >>             10964000
                                                                        10966000
   LOGICAL must;   << Flag to indicate special entry >>                 10968000
                                                                        10970000
   LOGICAL set'pattern;   << a whole word of the value to  >>           10972000
                          << set the bits to. i.e. all     >>           10974000
                          << ones if set'bits = TRUE else  >>           10976000
                          << all zeros if set'bits = FALSE >>           10978000
                                                                        10980000
   LOGICAL test'pattern;  << inverse of set'pattern, used  >>           10982000
                          << to test if the bits are in    >>           10984000
                          << the correct state before      >>           10986000
                          << changing.                     >>           10988000
                                                                        10990000
   DOUBLE bits'needed;    << count of bits left to change  >>           10992000
                                                                        10994000
   LOGICAL current'word;                                                10996000
   LOGICAL mask;          << for masking out partial words >>           10998000
   INTEGER bits'in'word;  << bits to set/reset in current word >>       11000000
                                                                        11002000
   << - - - - - - - - - - >>                                            11004000
                                                                        11006000
   << Remember which entry was used >>                                  11008000
                                                                        11010000
   must := FALSE;   << indicate normal call >>                          11012000
                                                                        11014000
   IF FALSE THEN                                                        11016000
      BEGIN   << must entry point >>                                    11018000
                                                                        11020000
         must'set'reset'bit'map:                                        11022000
            must := TRUE;   << indicate special call >>                 11024000
                                                                        11026000
      END;    << must entry point >>                                    11028000
                                                                        11030000
                                                                        11032000
   << Assign patterns for test and changing bits according to           11034000
      whether this a a call to allocate or deallocate space.  >>        11036000
                                                                        11038000
   set'pattern := IF set'bits THEN %177777 ELSE 0;                      11040000
   test'pattern := NOT set'pattern;                                     11042000
                                                                        11044000
                                                                        11046000
   << Set counter of bits left to turn on or off. >>                    11048000
                                                                        11050000
   bits'needed := ds'number'of'sectors;                                 11052000
                                                                        11054000
                                                                        11056000
                                                                        11058000
   << scan through map, until all bits have been set/reset >>           11060000
                                                                        11062000
   WHILE ds'page'number <= ds'last'page'of'map DO                       11064000
      BEGIN  << scan map >>                                             11066000
                                                                        11068000
         @ds'page'ptr := Get'Page (ds'page'number);                     11070000
                                                                        11072000
         IF NOT ds'error'status THEN                                    11074000
            BEGIN  << error getting page >>                             11076000
                                                                        11078000
               << If we are returning space, then the I/O error         11080000
                  doesn't matter, we can just skip this page.           11082000
                  IF getting space, the we must exit the procedure      11084000
                  and allow calling routines to handle the error >>     11086000
                                                                        11088000
               IF set'bits THEN                                         11090000
                  BEGIN  << returning space >>                          11092000
                                                                        11094000
                     ds'error'status := no'error;                       11096000
                     bits'needed := bits'needed - DBL(bits'per'page);   11098000
                                                                        11100000
                     IF bits'needed <= 0D THEN                          11102000
                         RETURN;                                        11104000
                                                                        11106000
                  END    << returning space >>                          11108000
               ELSE                                                     11110000
                                                                        11112000
                  << Getting space >>                                   11114000
                                                                        11116000
                  RETURN;                                               11118000
                                                                        11120000
            END    << error getting page >>                             11122000
         ELSE                                                           11124000
            BEGIN  << No I/O error >>                                   11126000
                                                                        11128000
               << Mark page as dirty >>                                 11130000
                                                                        11132000
$IF X2=ON  << USING DIRTY BUFFER MANAGEMENT >>                          11134000
                                                                        11136000
               ds'buffer'dirty (ds'buffer'index) := TRUE;               11138000
                                                                        11140000
$IF        << USING DIRTY BUFFER MANAGEMENT >>                          11142000
                                                                        11144000
               WHILE ds'word'number < words'per'page DO                 11146000
                  BEGIN << scan page >>                                 11148000
                                                                        11150000
                     current'word := ds'page'ptr (ds'word'number);      11152000
                                                                        11154000
                     << build mask for current word >>                  11156000
                                                                        11158000
                     mask := %100000;                                   11160000
                                                                        11162000
                     IF bits'needed < DBL(16 - ds'bit'number) THEN      11164000
                                                                        11166000
                        << all bits needed are in current word >>       11168000
                                                                        11170000
                        bits'in'word := INTEGER(bits'needed) - 1        11172000
                                                                        11174000
                     ELSE                                               11176000
                                                                        11178000
                        << All bits not in current word >>              11180000
                                                                        11182000
                        bits'in'word := 15 - ds'bit'number;             11184000
                                                                        11186000
                                                                        11188000
                     << Build mask for this word. >>                    11190000
                                                                        11192000
                     TOS := mask&ASR(bits'in'word);                     11194000
                     mask := TOS&LSR(ds'bit'number);                    11196000
                                                                        11198000
                                                                        11200000
                     << Test if bits are currently in expected          11202000
                        state, unless special "must" call.     >>       11204000
                                                                        11206000
                     IF NOT must AND NOT ((current'word LAND mask) =    11208000
                     (test'pattern LAND mask)) THEN                     11210000
                        BEGIN  << Bits not in correct state >>          11212000
                                                                        11214000
                           IF set'bits THEN                             11216000
                               ds'error'status :=                       11218000
                                     space'already'free'error           11220000
                           ELSE                                         11222000
                               ds'error'status :=                       11224000
                                     space'not'free'error;              11226000
                                                                        11228000
                           Send'Process'Dfs'Error (ds'ldev,             11230000
                                          ds'error'status, 3);          11232000
                                                                        11234000
                           RETURN;                                      11236000
                                                                        11238000
                        END;   << Bits not in correct state >>          11240000
                                                                        11242000
                                                                        11244000
                     << Set or reset bits in the word. >>               11246000
                                                                        11248000
                     ds'page'ptr(ds'word'number) :=                     11250000
                           (set'pattern LAND mask) LOR                  11252000
                           (current'word LAND NOT mask);                11254000
                                                                        11256000
                     bits'needed := bits'needed - DBL(bits'in'word + 1);11258000
                                                                        11260000
                     << Exit procedure if all bits are set/reset. >>    11262000
                                                                        11264000
$IF X3=ON  << BUG CATCHER >>                                            11266000
                     IF bits'needed < 0D THEN                           11268000
                        Suddendeath (421);                              11270000
$IF        << BUG CATCHER >>                                            11272000
                                                                        11274000
                     IF bits'needed = 0D THEN                           11276000
                        BEGIN << All done >>                            11278000
                                                                        11280000
                           Build'Descriptor'Entry;                      11282000
                                                                        11284000
                           << There should never be an error returned   11286000
                              from Build'Descriptor'Entry, as the       11288000
                              page must already be in a buffer.     >>  11290000
                                                                        11292000
$IF X3=ON   << BUG CATCHER >>                                           11294000
                           IF NOT ds'error'status THEN                  11296000
                              Suddendeath (421);                        11298000
$IF         << BUG CATCHER >>                                           11300000
                                                                        11302000
$IF X2=ON  << WRITE PAGE ONLY WHEN ALLOCATING, USING DIRTY BUFFER >>    11304000
           << management.                                         >>    11306000
                                                                        11308000
                           IF NOT set'bits THEN                         11310000
                                                                        11312000
$IF        << OTHERWISE ALLWAYS WRITE >>                                11314000
                                                                        11316000
                              BEGIN  << Write page to disc >>           11318000
                                                                        11320000
                                 Write'Page (ds'page'number,            11322000
                                             ds'buffer'index);          11324000
                                 IF NOT ds'error'status THEN            11326000
                                                                        11328000
                                    << Just ignore I/O error as page    11330000
                                       has already been flaged bad and  11332000
                                       the error should not matter to   11334000
                                       the caller.                  >>  11336000
                                                                        11338000
                                    ds'error'status := no'error;        11340000
                                                                        11342000
                              END;   << Write page to disc >>           11344000
                                                                        11346000
                           RETURN;                                      11348000
                                                                        11350000
                        END;   << All done >>                           11352000
                                                                        11354000
                     ds'word'number := ds'word'number + 1;              11356000
                     ds'bit'number := 0;                                11358000
                                                                        11360000
                  END;  << scan page >>                                 11362000
                                                                        11364000
                                                                        11366000
               << update descriptor and maybe write out page >>         11368000
                                                                        11370000
               Build'Descriptor'Entry;                                  11372000
                                                                        11374000
               << There should never be an error returned               11376000
                  from Build'Descriptor'Entry, as the                   11378000
                  page must already be in a buffer.     >>              11380000
                                                                        11382000
$IF X3=ON   << BUG CATCHER >>                                           11384000
               IF NOT ds'error'status THEN                              11386000
                  Suddendeath (421);                                    11388000
$IF         << BUG CATCHER >>                                           11390000
                                                                        11392000
$IF X2=ON  << ONLY WRITE PAGES WHEN ALLOCAING SPACE, USING DIRTY >>     11394000
           << buffer management.                                 >>     11396000
                                                                        11398000
               IF NOT set'bits  THEN                                    11400000
                                                                        11402000
$IF        << OTHERWISE WRITE ALL THE TIME >>                           11404000
                                                                        11406000
                  BEGIN  << Write page to disc >>                       11408000
                                                                        11410000
                     Write'Page (ds'page'number, ds'buffer'index);      11412000
                     IF NOT ds'error'status THEN                        11414000
                                                                        11416000
                         << Ignore I/O error, page has                  11418000
                            already been flaged bad.   >>               11420000
                                                                        11422000
                         ds'error'status := no'error;                   11424000
                                                                        11426000
                  END;   << Write page to disc >>                       11428000
                                                                        11430000
               ds'page'number := ds'page'number + 1;                    11432000
                                                                        11434000
               ds'word'number := 0;  << these where changed by >>       11436000
               ds'bit'number := 0;   << Build'Descriptor'Table >>       11438000
                                                                        11440000
            END;   << not I/O error >>                                  11442000
                                                                        11444000
      END;  << scan map >>                                              11446000
                                                                        11448000
                                                                        11450000
   << We should never make it here >>                                   11452000
                                                                        11454000
$IF X3=ON   << BUG CATCHER >>                                           11456000
   Suddendeath (421);                                                   11458000
$IF                                                                     11460000
                                                                        11462000
   ds'error'status := unexpected'dfs'error;                             11464000
   Send'Process'Dfs'Error (ds'ldev, ds'error'status, [8/5, 8/4]);       11466000
                                                                        11468000
                                                                        11470000
END;  << Set'Reset'Bit'Map >>                                           11472000
$PAGE "FIND'PAGE"                                                       11474000
PROCEDURE Find'Page;                                                    11476000
   OPTION PRIVILEGED,UNCALLABLE;                                        11478000
                                                                        11480000
<<==============================================================        11482000
                                                                        11484000
      This procedure locates the first  page  containing  the           11486000
   requested  space and determines if the space starts at the           11488000
   beginning, end or somewhere in the  middle  of  the  page.           11490000
   The  search  of the descriptor table does not start at the           11492000
   first entry all the time.  If space requested  is  greater           11494000
   than  or  equal to the size of the last allocation, as re-           11496000
   membered in "ds'size'of'last'allocation", then  it  starts           11498000
   with  the  page  the previous space was allocated from. If           11500000
   the space is less than the last space allocated and great-           11502000
   er than or equal to the threshold  size  then  the  search           11504000
   starts at "ds'first'threshold'page".  Otherwise the search           11506000
   starts at the first entry.                                           11508000
                                                                        11510000
   Assumptions on entry:                                                11512000
      DB is at the free space data segment for the ldev and             11514000
      the data segment is locked.                                       11516000
                                                                        11518000
   Exit conditions:                                                     11520000
      DB is unchanged.                                                  11522000
                                                                        11524000
   Globals:                                                             11526000
                                                                        11528000
      Input:                                                            11530000
         ds'number'of'sectors - Size of block to search for.            11532000
                                                                        11534000
      Output:                                                           11536000
         ds'page'number - Page space was found on.                      11538000
                          and where on the page it starts. It           11540000
                          will have one of the following val-           11542000
                          ues: "no'space'type",                         11544000
                          "starting'type", "ending'type" or             11546000
                          "middle'type".                                11548000
         ds'size'of'last'allocation - Updated if space found.           11550000
         ds'last'page'allocated'from - Updated if space                 11552000
                                       found.                           11554000
                                                                        11556000
      Others:                                                           11558000
         ds'descriptor'table                                            11560000
         ds'first'threshold'page                                        11562000
                                                                        11564000
      Equates:                                                          11566000
         dt'entry'size                                                  11568000
         no'space'type                                                  11570000
         largest'space                                                  11572000
         middle'type                                                    11574000
         previous'adjacent'space                                        11576000
         starting'space                                                 11578000
         starting'type                                                  11580000
         ending'space                                                   11582000
         bits'per'page                                                  11584000
         ending'type                                                    11586000
                                                                        11588000
      Defines:                                                          11590000
         DBL                                                            11592000
                                                                        11594000
   Externals:                                                           11596000
      None.                                                             11598000
                                                                        11600000
   Intrinsics:                                                          11602000
      None.                                                             11604000
                                                                        11606000
   Callers:                                                             11608000
      Get'Disc'Space                                                    11610000
                                                                        11612000
   Changes:                                                             11614000
                                                                        11616000
                                                                        11618000
==============================================================>>        11620000
                                                                        11622000
BEGIN                                                                   11624000
                                                                        11626000
   << Pointers to descriptor table entries >>                           11628000
                                                                        11630000
   INTEGER POINTER current'entry;                                       11632000
   INTEGER POINTER next'entry;                                          11634000
   INTEGER POINTER last'entry;                                          11636000
                                                                        11638000
   LOGICAL no'more'space;                                               11640000
   DOUBLE continuous'space;                                             11642000
                                                                        11644000
   << - - - - - - - - - - >>                                            11646000
                                                                        11648000
   << Initialize pointers to first descriptor entry to look at and      11650000
      end of table.                                                >>   11652000
                                                                        11654000
   IF ds'number'of'sectors >= ds'size'of'last'allocation THEN           11656000
      @next'entry := (ds'last'page'allocated'from * dt'entry'size) +    11658000
                     @ds'descriptor'table                               11660000
                                                                        11662000
   ELSE                                                                 11664000
      IF ds'number'of'sectors >= DBL(threshold'size) THEN               11666000
         @next'entry := (ds'first'threshold'page * dt'entry'size) +     11668000
                        @ds'descriptor'table                            11670000
                                                                        11672000
      ELSE                                                              11674000
         @next'entry := @ds'descriptor'table;                           11676000
                                                                        11678000
   @last'entry := (ds'last'page'of'map * dt'entry'size) +               11680000
                  @ds'descriptor'table;                                 11682000
                                                                        11684000
                                                                        11686000
   << ds'entry'type indicates if space has been found or not, and       11688000
      if found, where in the page.                                >>    11690000
                                                                        11692000
                                                                        11694000
   ds'entry'type := no'space'type;                                      11696000
                                                                        11698000
                                                                        11700000
   << Scan descriptor table looking for the first fit >>                11702000
                                                                        11704000
   WHILE @next'entry <= @last'entry AND ds'entry'type = no'space'type DO11706000
      BEGIN   << Scan DT >>                                             11708000
                                                                        11710000
         << Advance pointers >>                                         11712000
                                                                        11714000
         @current'entry := @next'entry;                                 11716000
         @next'entry := @next'entry + dt'entry'size;                    11718000
                                                                        11720000
                                                                        11722000
         << Test if it will fit at the beginning of the page, provided  11724000
            there is no adjacent space on the previous page.  This      11726000
            code could depend on the null entry before the descriptor   11728000
            table, however, since sector zero, the disc label, will     11730000
            never be free, this should not make a difference.       >>  11732000
                                                                        11734000
         IF current'entry(previous'adjacent'space) = 0 AND              11736000
         ds'number'of'sectors <= DBL(current'entry(starting'space))     11738000
         THEN                                                           11740000
            ds'entry'type := starting'type                              11742000
                                                                        11744000
         ELSE                                                           11746000
                                                                        11748000
         << Test if it will fit in the largest space on the page >>     11750000
                                                                        11752000
         IF ds'number'of'sectors <= DBL(current'entry(largest'space))   11754000
         THEN                                                           11756000
            ds'entry'type := middle'type                                11758000
                                                                        11760000
         ELSE                                                           11762000
                                                                        11764000
         << test if it will fit at the end of the page and beyond >>    11766000
                                                                        11768000
         IF current'entry(ending'space) > 0 THEN                        11770000
            BEGIN   << Space at end of page? >>                         11772000
                                                                        11774000
               continuous'space := DBL(current'entry(ending'space));    11776000
               no'more'space := FALSE;                                  11778000
                                                                        11780000
               WHILE NOT no'more'space AND                              11782000
               continuous'space < ds'number'of'sectors DO               11784000
                  BEGIN  << Look ahead in DT >>                         11786000
                                                                        11788000
                     continuous'space := continuous'space +             11790000
                           DBL(next'entry(starting'space));             11792000
                                                                        11794000
                     << Check if we have any farther to look >>         11796000
                                                                        11798000
                     IF next'entry(starting'space) = bits'per'page AND  11800000
                     @next'entry < @last'entry THEN                     11802000
                        @next'entry := @next'entry + dt'entry'size      11804000
                                                                        11806000
                     ELSE                                               11808000
                        no'more'space := TRUE;                          11810000
                                                                        11812000
                  END;   << Look ahead in DT >>                         11814000
                                                                        11816000
               << Test if the continous block is big enough >>          11818000
                                                                        11820000
               IF ds'number'of'sectors <= continuous'space THEN         11822000
                  ds'entry'type := ending'type;                         11824000
                                                                        11826000
            END;    << Space at end of page? >>                         11828000
                                                                        11830000
      END;    << Scan DT >>                                             11832000
                                                                        11834000
                                                                        11836000
   << At this point, if space has been found, "ds'entry'type" will      11838000
      have a value indicating if the space was at the start, end or     11840000
      somewhere in the middle of the page and "current'entry" will      11842000
      point to the entry.  If there is not enough space,                11844000
      "ds'entry'type" will have a value of "no'space'type".        >>   11846000
                                                                        11848000
   IF ds'entry'type <> no'space'type THEN                               11850000
      BEGIN  << We found space >>                                       11852000
                                                                        11854000
         ds'page'number := (@current'entry - @ds'descriptor'table) /    11856000
                           dt'entry'size;                               11858000
                                                                        11860000
         << Remember size of entry and where we found it, to            11862000
            help with next search.                           >>         11864000
                                                                        11866000
         ds'size'of'last'allocation := ds'number'of'sectors;            11868000
         ds'last'page'allocated'from := ds'page'number;                 11870000
                                                                        11872000
      END;   << We found space >>                                       11874000
                                                                        11876000
END;   << Find'Page >>                                                  11878000
$PAGE "LOCATE'FREE'SPACE"                                               11880000
PROCEDURE Locate'Free'Space;                                            11882000
   OPTION PRIVILEGED,UNCALLABLE;                                        11884000
                                                                        11886000
<<==============================================================        11888000
                                                                        11890000
      This procedure takes the page found by "Find'Page"  and           11892000
   finds  the exact location of the free space block, in word           11894000
   and bit number within the page.   The  value  returned  by           11896000
   "Find'Page"  in  "ds'entry'type"  is important in locating           11898000
   the space.   For  "middle'type",  the  page  is  searched,           11900000
   starting  just  after  the space at the start of the page,           11902000
   until space is found .  For  "starting'type",  we  already           11904000
   know  where  the  space  is,  word zero and bit zero.  For           11906000
   "ending'type", it takes the size of the block at  the  end           11908000
   of the page and figures out the starting word and bit.  If           11910000
   "Get'Page"   gets   an   error,   status   is   left    in           11912000
   "ds'error'status" and the procedure is exited.                       11914000
                                                                        11916000
   Assumptions on entry:                                                11918000
      DB is at the free space data segment for the ldev and             11920000
      the data segment is locked.                                       11922000
                                                                        11924000
   Exit conditions:                                                     11926000
      DB is unchanged.                                                  11928000
                                                                        11930000
   Globals:                                                             11932000
                                                                        11934000
      Input:                                                            11936000
         ds'entry'type - As returned by "Find'Page".                    11938000
         ds'page'number - From "Find'Page"                              11940000
         ds'number'of'sectors - Size of space we are looking            11942000
                                for.                                    11944000
         ds'descriptor'table - Entry for this page is looked            11946000
                               at.                                      11948000
                                                                        11950000
      Output:                                                           11952000
         ds'error'status - If "Get'Page" encounters an error,           11954000
                           it is returned here.                         11956000
         ds'word'number - Number of word in page on which the           11958000
                          block of space starts.                        11960000
         ds'bit'number - Number of bit at which space starts.           11962000
                                                                        11964000
      Others:                                                           11966000
         ds'page'ptr                                                    11968000
         ds'starting'word'number                                        11970000
         ds'starting'bit'number                                         11972000
         ds'bit'count                                                   11974000
                                                                        11976000
      Equates:                                                          11978000
         bits'per'word                                                  11980000
         no'error                                                       11982000
         dt'entry'size                                                  11984000
         starting'space                                                 11986000
         unexpected'dfs'error                                           11988000
         words'per'page                                                 11990000
         ending'space                                                   11992000
                                                                        11994000
   Externals:                                                           11996000
      Get'Page                                                          11998000
      Scan'Page                                                         12000000
      Suddendeath - (X3 Bug catching)                                   12002000
      Send'Process'Dfs'Error                                            12004000
                                                                        12006000
   Intrinsics:                                                          12008000
      None.                                                             12010000
                                                                        12012000
   Callers:                                                             12014000
      Get'Disc'Space                                                    12016000
                                                                        12018000
   Changes:                                                             12020000
                                                                        12022000
                                                                        12024000
==============================================================>>        12026000
                                                                        12028000
BEGIN                                                                   12030000
                                                                        12032000
   LOGICAL done;  << flag >>                                            12034000
                                                                        12036000
   INTEGER starting'word;                                               12038000
   INTEGER starting'bit;                                                12040000
                                                                        12042000
   << - - - - - - - - - >>                                              12044000
                                                                        12046000
   << These are for the subroutine >>                                   12048000
                                                                        12050000
   INTEGER bits'not'in'current'word;                                    12052000
   INTEGER not'mod'bits'per'word;    << This is above MOD 16 >>         12054000
                                                                        12056000
   SUBROUTINE Convert'End'To'Start (ending'word, ending'bit, size);     12058000
      VALUE ending'word, ending'bit, size;                              12060000
      INTEGER ending'word, ending'bit, size;                            12062000
                                                                        12064000
   <<=============================================================      12066000
                                                                        12068000
        This subroutine takes the block whose ending word and bit       12070000
     are passed, along with the size of the block in bits, and          12072000
     returns the starting word and bit in "starting word" and           12074000
     "starting'bit". NOTE:  The block must be with in a single          12076000
     page.                                                              12078000
                                                                        12080000
   ==============================================================>>     12082000
                                                                        12084000
   BEGIN  << Convert'End'To'Start >>                                    12086000
                                                                        12088000
      IF size = 0 THEN                                                  12090000
         BEGIN << size = 0 >>                                           12092000
                                                                        12094000
            starting'word := ending'word;                               12096000
            starting'bit := ending'bit;                                 12098000
                                                                        12100000
         END                                                            12102000
      ELSE                                                              12104000
         BEGIN << size <> 0 >>                                          12106000
                                                                        12108000
            bits'not'in'current'word := size - (ending'bit + 1);        12110000
                                                                        12112000
            << test if all bits are in the current word >>              12114000
                                                                        12116000
            IF bits'not'in'current'word > 0 THEN                        12118000
               BEGIN << in more than one word >>                        12120000
                                                                        12122000
                  not'mod'bits'per'word := bits'not'in'current'word     12124000
                                           MOD bits'per'word;           12126000
                  starting'word := ending'word -                        12128000
                     (bits'not'in'current'word / bits'per'word) - 1;    12130000
                                                                        12132000
                  IF not'mod'bits'per'word = 0 THEN                     12134000
                     BEGIN                                              12136000
                                                                        12138000
                        starting'word := starting'word  + 1;            12140000
                        starting'bit := 0;                              12142000
                                                                        12144000
                     END                                                12146000
                  ELSE                                                  12148000
                     starting'bit := bits'per'word -                    12150000
                                     not'mod'bits'per'word;             12152000
                                                                        12154000
               END   << in more than one word >>                        12156000
            ELSE                                                        12158000
               BEGIN << all bits in one word >>                         12160000
                                                                        12162000
                  starting'word := ending'word;                         12164000
                  starting'bit := ending'bit - size + 1;                12166000
                                                                        12168000
               END;  << all bits in one word >>                         12170000
                                                                        12172000
         END;  << size <> 0 >>                                          12174000
                                                                        12176000
   END;   << Convert'End'To'Start >>                                    12178000
                                                                        12180000
   << - - - - - - - - - - >>                                            12182000
                                                                        12184000
   << process according to type of entry >>                             12186000
                                                                        12188000
   CASE ds'entry'type OF                                                12190000
      BEGIN << case >>                                                  12192000
                                                                        12194000
         << 0 - middle'type >>                                          12196000
                                                                        12198000
         BEGIN << space is not adjacent to edge of page >>              12200000
                                                                        12202000
            @ds'page'ptr := Get'Page (ds'page'number);                  12204000
                                                                        12206000
            IF NOT ds'error'status THEN                                 12208000
               RETURN;  << let calling routines handle the error >>     12210000
                                                                        12212000
                                                                        12214000
            << calculate word and bit to start with as first bit        12216000
               beyond free space at start of page. First calculate      12218000
               space at the start of the page, the word number is       12220000
               the size DIV bits'per'word and the bit number is         12222000
               size MOD bits'per'word                             >>    12224000
                                                                        12226000
            TOS := ds'descriptor'table((ds'page'number *                12228000
                   dt'entry'size) + starting'space) + 1;                12230000
                                                                        12232000
            TOS := bits'per'word;                                       12234000
            ASSEMBLE (DIV);                                             12236000
            ds'bit'number := TOS;  << remainder >>                      12238000
            ds'word'number := TOS; << quotient >>                       12240000
                                                                        12242000
                                                                        12244000
            << scan page, looking for the best fit >>                   12246000
                                                                        12248000
            done := FALSE;                                              12250000
                                                                        12252000
            WHILE NOT done DO                                           12254000
               BEGIN  << scan page >>                                   12256000
                                                                        12258000
                  done := Scan'Page;                                    12260000
                                                                        12262000
                  << Check if enough space has been found >>            12264000
                                                                        12266000
                  IF ds'bit'count >= INTEGER(ds'number'of'sectors)      12268000
                  THEN                                                  12270000
                     done := TRUE;                                      12272000
                                                                        12274000
               END;   << scan page >>                                   12276000
                                                                        12278000
                                                                        12280000
            << Check to see if space was actually found, if not         12282000
               something is screwed up in the descriptor table. >>      12284000
                                                                        12286000
            IF ds'bit'count <= 0 THEN                                   12288000
               BEGIN  << Space was not there >>                         12290000
                                                                        12292000
$IF X3=ON   << BUG CATCHER >>                                           12294000
                                                                        12296000
                  Suddendeath (421);                                    12298000
                                                                        12300000
$IF         << BUG CATCHER >>                                           12302000
                                                                        12304000
                  ds'error'status := unexpected'dfs'error;              12306000
                  Send'Process'Dfs'Error (ds'ldev, ds'error'status,     12308000
                                          [8/6, 8/4]);                  12310000
                                                                        12312000
               END;   << Space was not there >>                         12314000
                                                                        12316000
                                                                        12318000
            ds'word'number := ds'starting'word'number;                  12320000
            ds'bit'number  := ds'starting'bit'number;                   12322000
                                                                        12324000
         END;  << space is not adjacent to edge of page >>              12326000
                                                                        12328000
         << 1 - starting'type >>                                        12330000
                                                                        12332000
         BEGIN << space is at the start of the page >>                  12334000
                                                                        12336000
            ds'word'number := 0;                                        12338000
            ds'bit'number := 0;                                         12340000
                                                                        12342000
         END;  << space is at the start of the page >>                  12344000
                                                                        12346000
         << 2 - ending'space >>                                         12348000
                                                                        12350000
         BEGIN << space is at the end of the page >>                    12352000
                                                                        12354000
            Convert'End'To'Start (words'per'page-1, bits'per'word-1,    12356000
                  ds'descriptor'table((ds'page'number *                 12358000
                  dt'entry'size) + ending'space));                      12360000
                                                                        12362000
            ds'word'number := starting'word;                            12364000
            ds'bit'number := starting'bit;                              12366000
                                                                        12368000
         END;  << space is at the end of the page >>                    12370000
                                                                        12372000
      END;  << case >>                                                  12374000
                                                                        12376000
END;  << Locate'Free'Space >>                                           12378000
$PAGE "LOCK'DFS'DATE'SEG"                                               12380000
LOGICAL PROCEDURE Lock'Dfs'Data'Seg (ldev);                             12382000
   VALUE ldev;                                                          12384000
   INTEGER ldev;                                                        12386000
   OPTION PRIVILEGED,UNCALLABLE;                                        12388000
                                                                        12390000
<<==============================================================        12392000
                                                                        12394000
      This procedure gains exclusive access to the  DFS  data           12396000
   segment for the given disc ldev.  First the LDTX entry for           12398000
   the ldev is checked to see is allocation is disabled.   If           12400000
   it is, the status word from the LDTX is returned, the pro-           12402000
   cedure is exited leaving DB at the stack.   If  allocation           12404000
   is enabled, the DST number is gotten out of LDTX and DB is           12406000
   switched to the data segment.  If no one has  the  segment           12408000
   locked, it is locked by this PIN and the procedured exits.           12410000
   If it is locked by another PIN, we place the current  pro-           12412000
   cess in queue and IMPEDE.  When we are unimpeded, the LDTX           12414000
   is checked again to see if allocation  has  been  disabled           12416000
   while  we  where  waiting,  if it was, the error status is           12418000
   returned and "Unlock'Dfs'Data'Seg" is called to  reset  DB           12420000
   to the stack and also unimpede other process in the queue,           12422000
   letting them find out about allocation being disabled.               12424000
   A lock count is kept so that a given process can lock a              12426000
   data segment more than once, thus preventing access between          12428000
   calls to get/return space, however DB must be at the stack           12430000
   when the procedure is called and it will always be set to            12432000
   the data segment if no error occured.                                12434000
                                                                        12436000
   Parameters:                                                          12438000
      ldev - Ldev number of disc.                                       12440000
                                                                        12442000
   Returns:                                                             12444000
      Standard format error status, indicating if an error              12446000
      occure which caused allocation to be disabled. If all             12448000
      is ok, "no'error" will be returned.                               12450000
                                                                        12452000
   Assumptions on entry:                                                12454000
      DB must be at the stack.                                          12456000
                                                                        12458000
   Exit conditions:                                                     12460000
      DB is set to the DFS data segment for the ldev.                   12462000
                                                                        12464000
   Globals:                                                             12466000
                                                                        12468000
      Input:                                                            12470000
         LDTX entry for ldev, ldtx'dfs'dst'word &                       12472000
         ldtx'dfs'error'word fields.                                    12474000
                                                                        12476000
      Output:                                                           12478000
         ds'lock                                                        12480000
         ds'lock'count                                                  12482000
         ds'queue'head                                                  12484000
         ds'queue'tail                                                  12486000
                                                                        12488000
      Others:                                                           12490000
         ds'ldev - (X3 = ON bug catching)                               12492000
         ds'error'status                                                12494000
         PCB - pointer to PCB table.                                    12496000
                                                                        12498000
      Equates:                                                          12500000
         ldt'dst                                                        12502000
         ldt'entry'size                                                 12504000
         ldtx'dfs'dst'word                                              12506000
         ldtx'dfs'error'word                                            12508000
         pcbsize                                                        12510000
         fatal'dfs'error                                                12512000
                                                                        12514000
      Defines:                                                          12516000
         Checkdb - (X3 = ON bug catching)                               12518000
         Getprocnum                                                     12520000
         Check'If'Disc - (X3 = ON bug catching)                         12522000
         Pseudodiable                                                   12524000
         Pseudoenable                                                   12526000
                                                                        12528000
   Externals:                                                           12530000
      Suddendeath - (X3 = ON bug catching)                              12532000
      Exchangedb                                                        12534000
      Impede                                                            12536000
      Unlock'Dfs'Data'Seg                                               12538000
                                                                        12540000
   Intrinsics:                                                          12542000
      None.                                                             12544000
                                                                        12546000
   Callers:                                                             12548000
      Deallocate'Dfs'Data'Seg                                           12550000
      Get'Disc'Space                                                    12552000
      Return'Disc'Space                                                 12554000
      Get'Specific'Disc'Space                                           12556000
      VINIT module 32                                                   12558000
      FREE2 module FR                                                   12560000
                                                                        12562000
   Changes:                                                             12564000
                                                                        12566000
                                                                        12568000
==============================================================>>        12570000
                                                                        12572000
BEGIN                                                                   12574000
                                                                        12576000
   INTEGER dfs'dst;                                                     12578000
   INTEGER ARRAY ldt'entry (0:ldt'entry'size-1) = Q;                    12580000
   INTEGER ldtx'entry'offset;                                           12582000
   LOGICAL pin;  << PIN of this process >>                              12584000
   LOGICAL return'value = Lock'Dfs'Data'Seg;                            12586000
                                                                        12588000
   << - - - - - - - - - - >>                                            12590000
                                                                        12592000
$IF X3=ON   << BUG CATCHER >>                                           12594000
                                                                        12596000
   << Check if DB is at the stack >>                                    12598000
                                                                        12600000
   Checkdb;                                                             12602000
   IF <> THEN Suddendeath (421);   << Not at stack >>                   12604000
                                                                        12606000
   << Check if its really a disc >>                                     12608000
                                                                        12610000
   TOS := ldev;                                                         12612000
   Check'If'Disc;                                                       12614000
   IF NOT TOS THEN Suddendeath (421);                                   12616000
                                                                        12618000
$IF         << BUG CATCHER >>                                           12620000
                                                                        12622000
                                                                        12624000
   << Get DST number and mount error word from LDTX,                    12626000
      first we must get offset of LDTX from LDT header >>               12628000
                                                                        12630000
   TOS := @ldt'entry;      << Target address >>                         12632000
   TOS := ldt'dst;         << DST number     >>                         12634000
   TOS := 0;               << header offset  >>                         12636000
   TOS := ldt'entry'size;  << Size of header >>                         12638000
   ASSEMBLE (MFDS 4);                                                   12640000
                                                                        12642000
   ldtx'entry'offset := ldt'entry (1) + ldt'entry (3) +                 12644000
                        (ldev * ldt'entry'size);                        12646000
                                                                        12648000
   TOS := @ldt'entry;      << Target address >>                         12650000
   TOS := ldt'dst;         << DST number     >>                         12652000
   TOS := ldtx'entry'offset;                                            12654000
   TOS := ldt'entry'size;  << Size of entry  >>                         12656000
   ASSEMBLE (MFDS 4);                                                   12658000
                                                                        12660000
   dfs'dst := ldt'entry (ldtx'dfs'dst'word);                            12662000
                                                                        12664000
   << Return mount error word from LDTX, if there was an error, (i.e.   12666000
      "ldtx'dfs'error'word" <> "no'error"), then free space allocation  12668000
      is disbled on this ldev, so just return status and exit.      >>  12670000
                                                                        12672000
   return'value := ldt'entry(ldtx'dfs'error'word);                      12674000
                                                                        12676000
   IF NOT return'value THEN                                             12678000
      RETURN;                                                           12680000
                                                                        12682000
                                                                        12684000
   IF dfs'dst <= 0 THEN                                                 12688000
      GOTO error;                                              <<04823>>12690000
                                                                        12692000
$IF         << BUG CATCHER >>                                           12694000
                                                                        12696000
                                                                        12698000
   << Switch DB to DFS data segment >>                                  12700000
                                                                        12702000
   Exchangedb (dfs'dst);                                                12704000
                                                                        12706000
                                                                        12708000
   <<Check if it is a DFS data segment>>                       <<04823>>12710000
                                                               <<04823>>12712000
   IF ds'ldev <> ldev or dfs'dst <> ds'dst THEN                <<04823>>12714000
      BEGIN                                                    <<04823>>12716000
      exchangedb(0);                                           <<04823>>12718000
                                                               <<04823>>12720000
error:                                                         <<04823>>12722000
      Process'Dfs'Error(ldev,unexpected'dfs'error,[8/8,8/4]);  <<04823>>12724000
      Soft'Death (421);                                        <<04823>>12726000
      return'value := unexpected'dfs'error;                    <<04823>>12728000
      RETURN;                                                  <<04823>>12730000
      END;                                                     <<04823>>12732000
                                                                        12734000
                                                                        12736000
   << Lock data segment >>                                              12738000
                                                                        12740000
   pin := Getprocnum;                                                   12742000
   Pseudodisable;                                                       12744000
                                                                        12746000
   IF ds'lock = 0 THEN                                                  12748000
      BEGIN  << not locked >>                                           12750000
                                                                        12752000
         ds'lock := pin; << lock it >>                                  12754000
         ds'lock'count := 1;                                            12756000
         Pseudoenable;                                                  12758000
                                                                        12760000
      END    << not locked >>                                           12762000
   ELSE                                                                 12764000
      IF pin = ds'lock THEN                                             12766000
         BEGIN  << Already locked by this PIN >>                        12768000
                                                                        12770000
            << This prcess already has the data seg locked,             12772000
               just increment the lock count.               >>          12774000
                                                                        12776000
            ds'lock'count := ds'lock'count + 1;                         12778000
            Pseudoenable;                                               12780000
                                                                        12782000
         END    << Already locked by this PIN >>                        12784000
      ELSE                                                              12786000
         BEGIN  << locked >>                                            12788000
                                                                        12790000
            IF ds'queue'head = 0 THEN                                   12792000
               ds'queue'head := pin   << Empty queue >>                 12794000
                                                                        12796000
            ELSE                                                        12798000
                                                                        12800000
               << Queue not empty. Add this process to tail of list >>  12802000
                                                                        12804000
               PCB((ds'queue'tail*pcbsize)+8).(8:8) := pin;             12806000
                                                                        12808000
                                                                        12810000
            PCB ((pin*pcbsize)+8).(8:8) := 0;                  <<04693>>12812000
            ds'queue'tail := pin;  << set tail pointer >>               12814000
                                                                        12816000
            Impede (0);  << Impede self >>                              12818000
                                                                        12820000
            << Make sure that no one has disabled free space            12822000
               allocation on this ldev while we where waiting, as       12824000
               could be the case if an unexpected error occured.   >>   12826000
                                                                        12828000
            IF ds'error'status.error'type >= fatal'dfs'error THEN       12830000
               BEGIN  << A fatal error has occured >>                   12832000
                                                                        12834000
                  return'value := ds'error'status;                      12836000
                                                                        12838000
                  << Unlock and return >>                               12840000
                                                                        12842000
                  Unlock'Dfs'Data'Seg;                                  12844000
                  RETURN;                                               12846000
                                                                        12848000
               END;   << A fatal error has occured >>                   12850000
                                                                        12852000
         END;   << locked >>                                            12854000
                                                                        12856000
                                                                        12858000
END;  << Lock'Dfs'Data'Seg >>                                           12860000
$PAGE "UNLOCK'DFS'DATA'SEG"                                             12862000
PROCEDURE Unlock'Dfs'Data'Seg;                                          12864000
   OPTION PRIVILEGED,UNCALLABLE;                                        12866000
                                                                        12868000
<<==============================================================        12870000
                                                                        12872000
      This procedure releases exclusive  access  to  the  DFS           12874000
   data  segment that DB is currently at and resets DB to the           12876000
   stack.  If the lock count is not one, then the lock count            12878000
   just be decremented and DB will be reset to the stack, the           12880000
   data segment will remain locked by the calling process.              12882000
   If any other PINs are waiting in  the  queue,  the first             12884000
   one is UNIMPEDEd.                                                    12886000
                                                                        12888000
   Assumptions on entry:                                                12890000
      DB is at the free space data segment for the ldev and             12892000
      the data segment is locked.                                       12894000
                                                                        12896000
   Exit conditions:                                                     12898000
      DB is reset to the stack.                                         12900000
                                                                        12902000
   Globals:                                                             12904000
                                                                        12906000
      Input:                                                            12908000
         ds'queue'head                                                  12910000
         ds'queue'tail                                                  12912000
                                                                        12914000
      Output:                                                           12916000
         ds'lock                                                        12918000
         ds'lock'count                                                  12920000
                                                                        12922000
      Others:                                                           12924000
         PCB                                                            12926000
                                                                        12928000
      Equates:                                                          12930000
         pcbsize                                                        12932000
                                                                        12934000
      Defines:                                                          12936000
         Pseudodisable                                                  12938000
         Getprocnum - (X3 = ON bug catching)                            12940000
         Pseudoenable                                                   12942000
                                                                        12944000
   Externals:                                                           12946000
      Suddendeath - (X3 = ON bug catching)                              12948000
      Unimpede                                                          12950000
      Exchangedb                                                        12952000
                                                                        12954000
   Intrinsics:                                                          12956000
      None.                                                             12958000
                                                                        12960000
   Callers:                                                             12962000
      Deallocate'Dfs'Data'Seg                                           12964000
      Lock'Dfs'Data'Seg                                                 12966000
      Get'Disc'Space                                                    12968000
      Return'Disc'Space                                                 12970000
      VINIT module 32                                                   12972000
      FREE2 module FR                                                   12974000
                                                                        12976000
   Changes:                                                             12978000
                                                                        12980000
                                                                        12982000
==============================================================>>        12984000
                                                                        12986000
BEGIN                                                                   12988000
                                                                        12990000
   << unlock data segment >>                                            12992000
                                                                        12994000
   Pseudodisable;                                                       12996000
                                                                        12998000
                                                                        13000000
   <<Check if DB points to DFS data segment>>                  <<04823>>13002000
                                                               <<04823>>13004000
   IF Getprocnum <> ds'lock or ds'lock'count <= 0 THEN         <<04823>>13006000
      BEGIN                                                    <<04823>>13008000
      Genmsg (dfs'msg'set'num, msg'unexpected'error,           <<04823>>13010000
             [1/0,3/1,3/1,3/1,6/0],ds'ldev,44,9,,,0);          <<04823>>13012000
      Soft'Death (421);                                        <<04823>>13014000
      exchangedb(0);                                           <<04823>>13016000
      RETURN;                                                  <<04823>>13018000
      END;                                                     <<04823>>13020000
                                                                        13022000
                                                                        13024000
   ds'lock'count := ds'lock'count - 1;                                  13026000
                                                                        13028000
   IF ds'lock'count = 0 THEN                                            13030000
      IF ds'queue'head = 0 THEN                                         13032000
                                                                        13034000
         ds'lock := 0   << no one wants lock >>                         13036000
                                                                        13038000
      ELSE                                                              13040000
         BEGIN  << someone is waiting on lock >>                        13042000
                                                                        13044000
            PCB ((ds'lock*pcbsize)+8).(8:8) := 0;              <<04476>>13046000
            ds'lock := ds'queue'head;  << give lock to head PIN >>      13048000
            ds'lock'count := 1;                                         13050000
                                                                        13052000
            << check is anyone else is on list >>                       13054000
                                                                        13056000
            IF PCB((ds'lock*pcbsize)+8).(8:8) = 0 THEN                  13058000
               ds'queue'head := 0   << No other PINs in queue >>        13060000
                                                                        13062000
            ELSE                                                        13064000
                                                                        13066000
               << other PINs in queue >>                                13068000
                                                                        13070000
               ds'queue'head := PCB((ds'lock*pcbsize)+8).(8:8);         13072000
                                                                        13074000
            Unimpede (ds'lock*pcbsize);                                 13076000
                                                                        13078000
         END;   << someone is waiting on lock >>                        13080000
                                                                        13082000
                                                                        13084000
   Pseudoenable;                                                        13086000
                                                                        13088000
                                                                        13090000
   << Reset DB to the stack >>                                          13092000
                                                                        13094000
   Exchangedb (0);                                                      13096000
                                                                        13098000
END;  << Unlock'Dfs'Data'Seg >>                                         13100000
$PAGE "GET'DISC'SPACE"                                                  13102000
INTEGER PROCEDURE Get'Disc'Space (ldev, number'of'sectors,              13104000
                                  disc'address);                        13106000
   VALUE ldev, number'of'sectors;                                       13108000
   INTEGER ldev;                                                        13110000
   DOUBLE number'of'sectors, disc'address;                              13112000
   OPTION PRIVILEGED,UNCALLABLE;                                        13114000
                                                                        13116000
<<==============================================================        13118000
                                                                        13120000
      This procedure is used to  allocate  disc  space  on  a           13122000
   ldev.  The number of sectors of continuous space needed is           13124000
   passed and the procedure returns status and  the   address           13126000
   of the space allocated.                                              13128000
                                                                        13130000
   Parameters:                                                          13132000
      ldev - Ldev number of disc drive to try and allocate              13134000
             space on.                                                  13136000
      number'of'sectors - Number of sectors to allocate.                13138000
      disc'address - Address of space allocated is returned             13140000
                     here.                                              13142000
                                                                        13144000
   Returns:                                                             13146000
      0 = Alls o.k., space allocated.                                   13148000
      1 = Space was not available.                                      13150000
      2 = Space not allocated because of I/O or other errors.           13152000
      3 = Free space allocation is disabled on this ldev.               13154000
                                                                        13156000
   Assumptions on entry:                                                13158000
      DB must be set to the stack.                                      13160000
                                                                        13162000
   Exit conditions:                                                     13164000
      DB is unchanged.                                                  13166000
                                                                        13168000
   Globals:                                                             13170000
                                                                        13172000
      Others:                                                           13174000
         ds'number'of'sectors                                           13176000
         ds'error'status                                                13178000
         ds'entry'type                                                  13180000
                                                                        13182000
      Equates:                                                          13184000
         no'error                                                       13186000
         no'space'type                                                  13188000
         fatal'dfs'error                                                13190000
                                                                        13192000
      Defines:                                                          13194000
         Checkdb - (X3 = ON bug catching)                               13196000
         Insure'Stack'Space                                             13198000
                                                                        13200000
   Externals:                                                           13202000
      Setcritical                                                       13204000
      Resetcritical                                                     13206000
      Lock'Dfs'Data'Seg                                                 13208000
      Suddendeath - (X3 = ON bug catching)                              13210000
      Find'Page                                                         13212000
      Locate'Free'Space                                                 13214000
      Convert'Map'To'Address                                            13216000
      Set'Reset'Bit'Map                                                 13218000
                                                                        13220000
   Intrinsics:                                                          13222000
      None.                                                             13224000
                                                                        13226000
   Callers:                                                             13228000
      ALLOCATE module 54                                                13230000
      UTILITY module 70                                                 13232000
      VINIT module 32                                                   13234000
                                                                        13236000
   Changes:                                                             13238000
                                                                        13240000
                                                                        13242000
==============================================================>>        13244000
                                                                        13246000
BEGIN                                                                   13248000
                                                                        13250000
   DOUBLE local'disc'address;  << To hold address of space while in >>  13252000
                               << spilt stack mode.                 >>  13254000
                                                                        13256000
   INTEGER try'count;     << Count of number of tries to get space >>   13258000
   LOGICAL critical'flag;                                               13260000
                                                                        13262000
   INTEGER return'value = Get'Disc'Space;                               13264000
                                                                        13266000
   << - - - - - - - - - - >>                                            13268000
                                                                        13270000
$IF X3=ON  << BUG CATCHER >>                                            13272000
                                                                        13274000
   PUSH (STATUS);   << Enable user traps, this should find >>           13276000
   TOS.(2:1) := 1;  << some problems.                      >>           13278000
   SET (STATUS);                                                        13280000
                                                                        13282000
   << Check to see if DB is at the stack >>                             13284000
                                                                        13286000
   Checkdb;                                                             13288000
   IF <> THEN Suddendeath (421);                                        13290000
                                                                        13292000
$IF        << BUG CATCHER >>                                            13294000
                                                                        13296000
                                                                        13298000
   Insure'Stack'Space;                                                  13300000
                                                                        13302000
   critical'flag := Setcritical;                                        13304000
                                                                        13306000
   << Lock data segment and set DB to it. >>                            13308000
                                                                        13310000
   TOS := Lock'Dfs'Data'Seg (ldev);                                     13312000
                                                                        13314000
   IF NOT TOS THEN                                                      13316000
      BEGIN  << Free space allocation is disabled on this ldev >>       13318000
                                                                        13320000
         return'value := 3;                                             13322000
                                                                        13324000
         Resetcritical (critical'flag);                                 13326000
                                                                        13328000
         RETURN;                                                        13330000
                                                                        13332000
      END;   << Free space allocation is disabled on this ldev >>       13334000
                                                                        13336000
                                                                        13338000
   ds'number'of'sectors := number'of'sectors;                           13340000
   try'count := 0;     << Count the number of retries because of >>     13342000
                       << I/O errors.                            >>     13344000
                                                                        13346000
   << This loop executes until no error occured, (either got space or   13348000
      it was not there) or we have tried 12 times and still got         13350000
      errors or a fatal error occured.                              >>  13352000
                                                                        13354000
   DO                                                                   13356000
      BEGIN   << Try to get space >>                                    13358000
                                                                        13360000
         ds'error'status := no'error;   << Initialize error status >>   13362000
                                                                        13364000
         << Locate page with space >>                                   13366000
                                                                        13368000
         Find'Page;                                                     13370000
                                                                        13372000
         IF ds'entry'type = no'space'type THEN                          13374000
            return'value := 1  << No space available >>                 13376000
                                                                        13378000
         ELSE                                                           13380000
            BEGIN  << space is available >>                             13382000
                                                                        13384000
               << Locate space with in page >>                          13386000
                                                                        13388000
               Locate'Free'Space;                                       13390000
                                                                        13392000
               IF ds'error'status THEN                                  13394000
                  BEGIN  << No I/O or Checksum errors >>                13396000
                                                                        13398000
                     << Convert map address to disc address >>          13400000
                                                                        13402000
                     local'disc'address := Convert'Map'To'Address;      13404000
                                                                        13406000
                     << Remove space from map >>                        13408000
                                                                        13410000
                     Set'Reset'Bit'Map (FALSE);                         13412000
                                                                        13414000
                     << If not error occured, return got it status >>   13416000
                                                                        13418000
                     IF ds'error'status THEN                            13420000
                        return'value := 0;                              13422000
                                                                        13424000
                  END;   << No I/O or Checksum errors >>                13426000
                                                                        13428000
            END;   << space is available >>                             13430000
                                                                        13432000
         try'count := try'count + 1;                                    13434000
                                                                        13436000
      END    << Try to get space >>                                     13438000
                                                                        13440000
   UNTIL (ds'error'status) OR (try'count >= 12) OR                      13442000
         (ds'error'status.error'type >= fatal'dfs'error);               13444000
                                                                        13446000
   IF NOT ds'error'status THEN                                          13448000
      return'value := 2;  << Can't get space because of errors >>       13450000
   IF return'value = 0 THEN                                    <<04945>>13451000
                                                                        13452000
   <<Check if obtained space belongs to restricted area>>      <<04823>>13454000
                                                               <<04823>>13456000
   IF local'disc'address < 10D OR                              <<04823>>13458000
      ldev = 1 AND local'disc'address < 400D OR                <<04823>>13460000
      (local'disc'address + number'of'sectors) > ds'map'address<<04823>>13462000
      AND (ds'map'address + DBL(ds'last'page'of'map)) >=       <<04823>>13464000
      local'disc'address THEN                                  <<04823>>13468000
      BEGIN                                                    <<04823>>13470000
      Unlock'Dfs'Data'Seg;                                     <<04823>>13472000
      Resetcritical (critical'flag);                           <<04823>>13474000
      Process'Dfs'Error(ldev,unexpected'dfs'error,[8/11,8/4]); <<04823>>13476000
      Soft'Death (421);                                        <<04823>>13478000
      return'value := 2;                                       <<04823>>13480000
      RETURN;                                                  <<04823>>13482000
      END;                                                     <<04823>>13484000
                                                               <<04823>>13486000
                                                                        13488000
   Unlock'Dfs'Data'Seg;                                                 13490000
                                                                        13492000
   disc'address := local'disc'address;                                  13494000
                                                                        13496000
   Resetcritical (critical'flag);                                       13498000
                                                                        13500000
END;  << Get'Disc'Space >>                                              13502000
$PAGE "RETURN'DISC'SPACE"                                               13504000
PROCEDURE Return'Disc'Space (ldev, disc'address, number'of'sectors);    13506000
   VALUE ldev, disc'address, number'of'sectors;                         13508000
   INTEGER ldev;                                                        13510000
   DOUBLE disc'address, number'of'sectors;                              13512000
   OPTION PRIVILEGED,UNCALLABLE;                                        13514000
                                                                        13516000
BEGIN                                                                   13518000
                                                                        13520000
<<==============================================================        13522000
                                                                        13524000
      This  procedure  deallocates  (returns)  the  specified           13526000
   space  on  ldev.   No error status is ever returned to the           13528000
   caller, as all errors have already been processed  and  it           13530000
   should  not  matter  to the caller if the space was really           13532000
   returned.  If free space allocation is disabled, the space           13534000
   is just thrown away.                                                 13536000
                                                                        13538000
   Parameters:                                                          13540000
      ldev - Ldev number of disc drive.                                 13542000
      disc'address - Starting sector address of space to                13544000
                      return.                                           13546000
      number'of'sectors - Number of sectors to be returned.             13548000
                                                                        13550000
   Assumptions on entry:                                                13552000
      DB must be at the stack.                                          13554000
                                                                        13556000
   Exit conditions:                                                     13558000
      DB is unchanged.                                                  13560000
                                                                        13562000
   Globals:                                                             13564000
                                                                        13566000
      Others:                                                           13568000
         ds'error'status                                                13570000
         ds'disc'address                                                13572000
         ds'number'of'sectors                                           13574000
         ds'size'of'last'allocation                                     13576000
         ds'last'page'allocated'from                                    13578000
                                                                        13580000
      Equates:                                                          13582000
         no'error                                                       13584000
                                                                        13586000
      Defines:                                                          13588000
         Checkdb - (X3 = ON bug catching)                               13590000
         Insure'Stack'Space                                             13592000
                                                                        13594000
   Externals:                                                           13596000
      Suddendeath - (X3 = ON bug catching)                              13598000
      Setcritical                                                       13600000
      Resetcritical                                                     13602000
      Lock'Dfs'Data'Seg                                                 13604000
      Convert'Address'To'Map                                            13606000
      Set'Reset'Bit'Map                                                 13608000
      Unlock'Dfs'Data'Seg                                               13610000
                                                                        13612000
   Intrinsics:                                                          13614000
      None.                                                             13616000
                                                                        13618000
   Callers:                                                             13620000
      FILEACC module 50                                                 13622000
      RESTORE module 52                                                 13624000
      ALLOCATE module 54                                                13626000
      UTILITY module 70                                                 13628000
      VINIT module 32                                                   13630000
                                                                        13632000
   Changes:                                                             13634000
                                                                        13636000
                                                                        13638000
==============================================================>>        13640000
                                                                        13642000
   LOGICAL critical'flag;                                               13644000
                                                                        13646000
   << - - - - - - - - - - >>                                            13648000
                                                                        13650000
$IF X3=ON   << BUG CATCHER >>                                           13652000
                                                                        13654000
   PUSH (STATUS);  << Enable user traps >>                              13656000
   TOS.(2:1) := 1;                                                      13658000
   SET (STATUS);                                                        13660000
                                                                        13662000
   << Check if DB is at the stack >>                                    13664000
                                                                        13666000
   Checkdb;                                                             13668000
   IF <> THEN Suddendeath (421);                                        13670000
                                                                        13672000
$IF         << BUG CATCHER >>                                           13674000
                                                                        13676000
   Insure'Stack'Space;                                                  13678000
                                                                        13680000
   critical'flag := Setcritical;                                        13682000
                                                                        13684000
   << Lock data segment and set DB to it >>                             13686000
                                                                        13688000
   TOS  := Lock'Dfs'Data'Segment (ldev);                                13690000
                                                                        13692000
   IF NOT TOS THEN                                                      13696000
      BEGIN                                                             13698000
                                                                        13700000
         Resetcritical (critical'flag);                                 13702000
                                                                        13704000
         RETURN;                                                        13706000
                                                                        13708000
      END;                                                              13710000
                                                                        13712000
   <<Check if returned space belongs to restricted area>>      <<04823>>13714000
                                                               <<04823>>13716000
   IF disc'address < 10D OR                                    <<04823>>13718000
      ldev = 1 AND disc'address < 400D OR                      <<04823>>13720000
      (disc'address + number'of'sectors) > ds'map'address AND  <<04823>>13722000
      (ds'map'address + DBL(ds'last'page'of'map)) >=           <<04823>>13724000
      disc'address THEN                                        <<04823>>13726000
      BEGIN                                                    <<04823>>13728000
      Unlock'Dfs'Data'Seg;                                     <<04823>>13730000
      Resetcritical (critical'flag);                           <<04823>>13732000
      Process'Dfs'Error(ldev,unexpected'dfs'error,[8/10,8/4]); <<04823>>13734000
      Soft'Death (421);                                        <<04823>>13736000
      RETURN;                                                  <<04823>>13738000
      END;                                                     <<04823>>13740000
                                                               <<04823>>13742000
   ds'error'status := no'error;   << Init error status >>               13744000
                                                                        13746000
                                                                        13748000
   << set parameters in data segment >>                                 13750000
                                                                        13752000
   ds'disc'address := disc'address;                                     13754000
   ds'number'of'sectors := number'of'sectors;                           13756000
                                                                        13758000
   Convert'Address'To'Map;                                              13760000
                                                                        13762000
   << Before marking map, we must reset "ds'size'of'last'allocation",   13764000
      since it will no longer be meaningfull after returning space. >>  13766000
                                                                        13768000
   IF (ds'page'number <= ds'last'page'allocated'from) THEN     <<06161>>13770000
      IF = THEN                                                <<06161>>13772000
         IF number'of'sectors > ds'size'of'last'allocation THEN<<06161>>13774000
           ds'size'of'last'allocation := number'of'sectors     <<06161>>13776000
         ELSE                                                  <<06161>>13777000
      ELSE                                                     <<06161>>13778000
         BEGIN                                                 <<06161>>13780000
         ds'size'of'last'allocation := number'of'sectors;      <<06161>>13782000
         ds'last'page'allocated'from := ds'page'number;        <<06161>>13784000
         END;                                                  <<06161>>13786000
                                                                        13788000
   << Mark space as free in map, errors are not passed back to          13790000
      caller, as they have already been processed.             >>       13792000
                                                                        13794000
   Set'Reset'Bit'Map (TRUE);                                            13796000
                                                                        13798000
   << Release data segment and set DB back to stack >>                  13800000
                                                                        13802000
   Unlock'Dfs'Data'Seg;                                                 13804000
                                                                        13806000
   Resetcritical (critical'flag);                                       13808000
                                                                        13810000
END;  << Return'Disc'Space >>                                           13812000
$PAGE "GET'SPECIFIC'DISC'SPACE"                                         13814000
INTEGER PROCEDURE Get'Specific'Disc'Space (ldev, disc'address,          13816000
                                           number'of'sectors);          13818000
   VALUE ldev, disc'address, number'of'sectors;                         13820000
   INTEGER ldev;                                                        13822000
   DOUBLE disc'address, number'of'sectors;                              13824000
   OPTION PRIVILEGED,UNCALLABLE;                                        13826000
                                                                        13828000
<<==============================================================        13830000
                                                                        13832000
      This procedure allocates disc space starting at a spec-           13834000
   ified address .  The map is first checked to  see  if  the           13836000
   space is actually free, if it is, then it is allocated.              13838000
                                                                        13840000
   Parameters:                                                          13842000
      ldev - Ldev number of disc drive.                                 13844000
      disc'address - Sector address of where space is                   13846000
                     desired.                                           13848000
      number'of'sectors - Number of sectors desired.                    13850000
                                                                        13852000
   Returns:                                                             13854000
      0 - Space allocated                                               13856000
      1 - Space not available.                                          13858000
      2 - Space not allocated because of I/O or check sum               13860000
          errors.                                                       13862000
      3 - Free space deallocation is disabled on this ldev.             13864000
                                                                        13866000
                                                                        13868000
   Assumptions on entry:                                                13870000
      Db is at the stack.                                               13872000
                                                                        13874000
   Exit conditions:                                                     13876000
      DB is unchanged.                                                  13878000
                                                                        13880000
   Globals:                                                             13882000
                                                                        13884000
      Others:                                                           13886000
         ds'number'of'sectors                                           13888000
         ds'disc'address                                                13890000
         ds'error'status                                                13892000
         ds'page'ptr                                                    13894000
         ds'page'number                                                 13896000
         ds'word'number                                                 13898000
         ds'bit'number                                                  13900000
         ds'starting'word'number                                        13902000
         ds'starting'bit'number                                         13904000
         ds'bit'count                                                   13906000
         ds'size'of'last'allocation                                     13908000
         ds'disc'size                                                   13910000
                                                                        13912000
      Equates:                                                          13914000
         no'error                                                       13916000
                                                                        13918000
      Defines:                                                          13920000
         Checkdb - (X3 = ON bug catcher)                                13922000
         DBL                                                            13924000
         Insure'Stack'Space                                             13926000
                                                                        13928000
   Externals:                                                           13930000
      Suddendeath - (X3 = ON bug catcher)                               13932000
      Setcritical                                                       13934000
      Resetcritical                                                     13936000
      Lock'Dfs'Data'Seg                                                 13938000
      Get'Page                                                          13940000
      Scan'Page                                                         13942000
      Set'Reset'Bit'Map                                                 13944000
      Unlock'Dfs'Data'Seg                                               13946000
                                                                        13948000
   Intrinsics:                                                          13950000
      None.                                                             13952000
                                                                        13954000
   Callers:                                                             13956000
      VINIT module 32                                                   13958000
                                                                        13960000
   Changes:                                                             13962000
                                                                        13964000
                                                                        13966000
==============================================================>>        13968000
                                                                        13970000
BEGIN                                                                   13972000
                                                                        13974000
   LOGICAL done;                                                        13976000
   LOGICAL end'of'page;                                                 13978000
   LOGICAL critical'flag;                                               13980000
   INTEGER starting'page'number;                                        13982000
   INTEGER starting'word'number;                                        13984000
   INTEGER starting'bit'number;                                         13986000
                                                                        13988000
   INTEGER return'value = Get'Specific'Disc'Space;                      13990000
                                                                        13992000
   << - - - - - - - - - - >>                                            13994000
                                                                        13996000
$IF X3=ON   << BUG CATCHER >>                                           13998000
                                                                        14000000
   PUSH (STATUS);   << Enable user traps >>                             14002000
   TOS.(2:1) := 1;                                                      14004000
   SET (STATUS);                                                        14006000
                                                                        14008000
   << Check that DB is at the stack >>                                  14010000
                                                                        14012000
   Checkdb;                                                             14014000
   IF <> THEN Suddendeath (421);                                        14016000
                                                                        14018000
$IF         << BUG CATCHER >>                                           14020000
                                                                        14022000
   Insure'Stack'Space;                                                  14024000
                                                                        14026000
   critical'flag := Setcritical;                                        14028000
                                                                        14030000
   TOS := Lock'Dfs'Data'Seg (ldev);                                     14032000
                                                                        14034000
   IF NOT TOS THEN                                                      14036000
      BEGIN  << Free space disabled >>                                  14038000
                                                                        14040000
         return'value := 3;                                             14042000
         Resetcritical (critical'flag);                                 14044000
         RETURN;                                                        14046000
                                                                        14048000
      END;   << Free space disabled >>                                  14050000
                                                                        14052000
                                                                        14054000
   ds'number'of'sectors := 0D;  << Used for counting availble sectors >>14056000
                                                                        14058000
   << Convert sector address to map address >>                          14060000
                                                                        14062000
   ds'disc'address := disc'address;                                     14064000
   Convert'Address'To'Map;                                              14066000
                                                                        14068000
   << Remember start of space >>                                        14070000
                                                                        14072000
   starting'page'number := ds'page'number;                              14074000
   starting'word'number := ds'word'number;                              14076000
   starting'bit'number := ds'bit'number;                                14078000
                                                                        14080000
   ds'error'status := no'error;    << Init error status >>              14082000
                                                                        14084000
   done := FALSE;   << Flag to indicate no more searching >>            14086000
                                                                        14088000
                                                                        14090000
   << Scan map to see if space is all free >>                           14092000
                                                                        14094000
   WHILE NOT done AND ds'error'status Do                                14096000
      BEGIN  << Scan for space >>                                       14098000
                                                                        14100000
         << Get page into a buffer >>                                   14102000
                                                                        14104000
         @ds'page'ptr := Get'Page (ds'page'number);                     14106000
                                                                        14108000
         IF ds'error'status THEN                                        14110000
            BEGIN   << No error, got the page >>                        14112000
                                                                        14114000
               << Scan the page. If enough space was found the search   14116000
                  will end.  If no space was found, or the end of the   14118000
                  page was not reached, then the search will end, as    14120000
                  we have found a block of allocated space.  If space   14122000
                  is found and it is the first page, we will make       14124000
                  sure that the space really starts in the right spot,  14126000
                  as Scan'Page would have skiped over any allocated     14128000
                  space at the beginning of the block we are looking    14130000
                  for.                                              >>  14132000
                                                                        14134000
               end'of'page := Scan'Page;                                14136000
                                                                        14138000
               << Count space that was found >>                         14140000
                                                                        14142000
               ds'number'of'sectors := ds'number'of'sectors +           14144000
                                       DBL(ds'bit'count);               14146000
                                                                        14148000
               << If this is the first page of the block, make          14150000
                  damn sure that the block really starts at the         14152000
                  specified address.                          >>        14154000
                                                                        14156000
               IF (starting'page'number = ds'page'number) AND           14158000
               ((starting'word'number <> ds'starting'word'number)       14160000
               OR (starting'bit'number <> ds'starting'bit'number))      14162000
               THEN                                                     14164000
                  BEGIN  << Not the space we are looking for >>         14166000
                                                                        14168000
                     done := TRUE;                                      14170000
                     ds'number'of'sectors := 0D;                        14172000
                                                                        14174000
                  END;   << Not the space we are looking for >>         14176000
                                                                        14178000
                                                                        14180000
               << If we have found enough space or found no space       14182000
                  or did not reach the end of the page, then we         14184000
                  are done scanning pages.                        >>    14186000
                                                                        14188000
               IF ds'number'of'sectors >= number'of'sectors OR          14190000
               ds'bit'count = 0 OR NOT end'of'page THEN                 14192000
                  done := TRUE;                                         14194000
                                                                        14196000
                                                                        14198000
               ds'page'number := ds'page'number + 1;                    14200000
               ds'word'number := 0;                                     14202000
               ds'bit'number := 0;                                      14204000
                                                                        14206000
            END;    << No error, got the page >>                        14208000
                                                                        14210000
      END;   << Scan for space >>                                       14212000
                                                                        14214000
                                                                        14216000
   << If the space was not found or an error occured, return the        14218000
      appropriate status, otherwise, if its there, delete the           14220000
      space form the map.                                        >>     14222000
                                                                        14224000
   IF NOT ds'error'status THEN                                          14226000
      return'value := 2                                                 14228000
                                                                        14230000
   ELSE                                                                 14232000
      IF ds'number'of'sectors < number'of'sectors THEN                  14234000
         return'value := 1                                              14236000
                                                                        14238000
      ELSE                                                              14240000
         BEGIN  << Delete space from map >>                             14242000
                                                                        14244000
            << Reset map address, as it was changed by the scan >>      14246000
                                                                        14248000
            Convert'Address'To'Map;                                     14250000
                                                                        14252000
            ds'number'of'sectors := number'of'sectors;                  14254000
                                                                        14256000
            Set'Reset'Bit'Map (FALSE);                                  14258000
                                                                        14260000
            IF ds'error'status THEN                                     14262000
               return'value := 0   << Got the space >>                  14264000
                                                                        14266000
            ELSE                                                        14268000
               return'value := 2;  << Did not get it because an         14270000
                                      error occured.            >>      14272000
                                                                        14274000
         END;   << Delete space from map >>                             14276000
                                                                        14278000
                                                                        14280000
   << Reset "ds'size'of'last'allocation", as it is no longer            14282000
      meaningful after this allocation.                      >>         14284000
                                                                        14286000
   ds'size'of'last'allocation := max'double;                            14288000
                                                                        14290000
                                                                        14292000
   << Unlock data segment and return DB to stack. >>                    14294000
                                                                        14296000
   Unlock'Dfs'Data'Seg;                                                 14298000
                                                                        14300000
   Resetcritical (critical'flag);                                       14302000
                                                                        14304000
END;  << Get'Specific'Disc'Space >>                                     14306000
$CONTROL SEGMENT=MAIN                                                   14308000
$PAGE "DFS - OUTER BLOCK"                                               14310000
END.  << DFS - Disc Free Space >>                                       14312000
