<<==============================================================        00010000
                                                                        00012000
                         INCLDFSC - B4                                  00014000
                                                                        00016000
      Disc free space management code common to both INITIAL and        00018000
   the system. This has the procedures Convert'Address'To'Map,          00020000
   Convert'Map'To'Address, Make'Check'Sum & Scan'Page.                  00022000
                                                                        00024000
==============================================================>>        00026000
$PAGE "CONVERT'ADDRESS'TO'MAP"                                          00028000
PROCEDURE Convert'Address'To'Map;                                       00030000
   OPTION PRIVILEGED,UNCALLABLE;                                        00032000
                                                                        00034000
<<==============================================================        00036000
                                                                        00038000
      This procedure takes a double word disc sector address            00040000
   and converts it to a bit map address (i.e. page, word and            00042000
   bit numbers).                                                        00044000
                                                                        00046000
   Returns:                                                             00048000
                                                                        00050000
   Assumptions on entry:                                                00052000
      DB is at the free space data segment for the ldev and             00054000
      the data segment is locked.                                       00056000
                                                                        00058000
   Exit conditions:                                                     00060000
      DB is unchanged.                                                  00062000
                                                                        00064000
   Globals:                                                             00066000
                                                                        00068000
      Input:                                                            00070000
         ds'disc'address - Double word sector disc address to           00072000
                           convert.                                     00074000
                                                                        00076000
      Output:                                                           00078000
         ds'page'number - Page number that contains sector.             00080000
         ds'word'number - Word number in page containing                00082000
                          sector.                                       00084000
         ds'bit'number - Bit number in word that represents             00086000
                         the sector.                                    00088000
                                                                        00090000
      Others:                                                           00092000
         ds'disc'size - (X3 = ON bug catcher)                           00094000
         ds'last'page'of'map - (X3 = ON bug catcher)                    00096000
                                                                        00098000
      Equates:                                                          00100000
         bits'per'page {INCLDFS2}                                       00102000
         bit'per'word  {INCLDFS2}                                       00104000
         words'per'page - (X3 = ON bug catcher) {INCLDFS2}              00106000
                                                                        00108000
   Externals:                                                           00110000
      Suddendeath - (X3 = ON bug catcher)                               00112000
                                                                        00114000
   Intrinsics:                                                          00116000
      None.                                                             00118000
                                                                        00120000
   Callers:                                                             00122000
      Return'Disc'Space                                                 00124000
      Get'Specific'Disc'Space                                           00126000
      VINIT module 32                                                   00128000
      INITIAL - Return'Disc'Space                                       00130000
      INITIAL - Get'Specific'Disc'Space                                 00132000
                                                                        00134000
   Changes:                                                             00136000
                                                                        00138000
                                                                        00140000
==============================================================>>        00142000
                                                                        00144000
BEGIN << Convert'Address'To'Map >>                                      00146000
                                                                        00148000
$IF X3=ON  << BUG CATCHER >>                                            00150000
                                                                        00152000
   IF (ds'disc'address < 0D) OR (ds'disc'address > ds'disc'size) THEN   00154000
      Suddendeath (700);                                                00156000
                                                                        00158000
$IF        << BUG CATCHER >>                                            00160000
                                                                        00162000
                                                                        00164000
   << Calculate page number,                                            00166000
      page := address / bits'per'page,                                  00168000
      and leave remainder on TOS.          >>                           00170000
                                                                        00172000
   TOS := ds'disc'address;                                              00174000
   TOS := DOUBLE(bits'per'page);                                        00176000
   ASSEMBLE (DDIV;   << double divide >>                                00178000
             DXCH;   << Exchange double word quotient/remainder,        00180000
                        so that the quotient is TOS.            >>      00182000
             DELB);  << Convert quotient to integer. >>                 00184000
   ds'page'number := TOS;                                               00186000
                                                                        00188000
                                                                        00190000
   << calculate word and bit,                                           00192000
        word := remainder/bits'per'word                                 00194000
        bit := remainder from above div   >>                            00196000
                                                                        00198000
   DELB;  << Convert double remainder on TOS to integer. >>             00200000
   TOS := bits'per'word;                                                00202000
   ASSEMBLE (DIV);                                                      00204000
   ds'bit'number := TOS;                                                00206000
   ds'word'number := TOS;                                               00208000
                                                                        00210000
                                                                        00212000
$IF X3=ON  << BUG CATCHER >>                                            00214000
                                                                        00216000
   IF NOT (0 <= ds'page'number <= ds'last'page'of'map) THEN             00218000
      Suddendeath (700);                                                00220000
   IF NOT (0 <= ds'word'number <= words'per'page-1) THEN                00222000
      Suddendeath (700);                                                00224000
   IF NOT (0 <= ds'bit'number <= bits'per'word-1) THEN                  00226000
      Suddendeath (700);                                                00228000
                                                                        00230000
$IF        << BUG CATCHER >>                                            00232000
                                                                        00234000
END; << Convert'Address'To'Map >>                                       00236000
$PAGE "CONVERT'MAP'TO'ADDRESS"                                          00238000
DOUBLE PROCEDURE Convert'Map'To'Address;                                00240000
   OPTION PRIVILEGED,UNCALLABLE;                                        00242000
                                                                        00244000
<<==============================================================        00246000
                                                                        00248000
      This procedure converts a map address (i.e. page, word            00250000
   and bit number) to a sector address.                                 00252000
                                                                        00254000
   Returns:                                                             00256000
      Double word disc sector address.                                  00258000
                                                                        00260000
   Assumptions on entry:                                                00262000
      DB is at the free space data segment for the ldev and             00264000
      the data segment is locked.                                       00266000
                                                                        00268000
   Exit conditions:                                                     00270000
      DB is unchanged.                                                  00272000
                                                                        00274000
   Globals:                                                             00276000
                                                                        00278000
      Input:                                                            00280000
         ds'page'number                                                 00282000
         ds'word'number                                                 00284000
         ds'bit'number                                                  00286000
                                                                        00288000
      Others:                                                           00290000
         ds'last'page'of'map - (X3 = ON Bug catcher)                    00292000
         ds'disc'size - (X3 = ON Bug catcher)                           00294000
                                                                        00296000
      Equates:                                                          00298000
         bits'per'word {INCLDFS2}                                       00300000
         bits'per'page {INCLDFS2}                                       00302000
         words'per'page - (X3 = ON Bug catcher) {INCLDFS2}              00304000
                                                                        00306000
      Defines:                                                          00308000
         DBL                                                            00310000
                                                                        00312000
   Externals:                                                           00314000
      Suddendeath - (X3 = ON Bug catcher)                               00316000
                                                                        00318000
   Intrinsics:                                                          00320000
      None.                                                             00322000
                                                                        00324000
   Callers:                                                             00326000
      Get'Disc'Space                                                    00328000
      INITIAL - Get'Disc'Space                                          00330000
                                                                        00332000
   Changes:                                                             00334000
                                                                        00336000
                                                                        00338000
==============================================================>>        00340000
                                                                        00342000
BEGIN << Convert'Map'To'Address >>                                      00344000
                                                                        00346000
   DOUBLE return'value = Convert'Map'To'Address;                        00348000
                                                                        00350000
   << - - - - - - - - - - >>                                            00352000
                                                                        00354000
$IF X3=ON  << BUG CATCHER >>                                            00356000
                                                                        00358000
   IF NOT (0 <= ds'page'number <= ds'last'page'of'map) THEN             00360000
      Suddendeath (700);                                                00362000
   IF NOT (0 <= ds'word'number <= words'per'page-1) THEN                00364000
      Suddendeath (700);                                                00366000
   IF NOT (0<= ds'bit'number <= bits'per'word-1) THEN                   00368000
      Suddendeath (700);                                                00370000
                                                                        00372000
$IF        << BUG CATCHER >>                                            00374000
                                                                        00376000
                                                                        00378000
   return'value := (DBL(ds'page'number) * DBL(bits'per'page)) +         00380000
                   DBL ((ds'word'number * bits'per'word) +              00382000
                   ds'bit'number);                                      00384000
                                                                        00386000
                                                                        00388000
$IF X3=ON  << BUG CATCHER >>                                            00390000
                                                                        00392000
   IF (return'value < 0D) OR (return'value > ds'disc'size) THEN         00394000
      Suddendeath (700);                                                00396000
                                                                        00398000
$IF        << BUG CATCHER >>                                            00400000
                                                                        00402000
END; << Convert'Map'To'Address >>                                       00404000
$PAGE "MAKE'CHECK'SUM"                                                  00406000
LOGICAL PROCEDURE Make'Check'Sum (buffer, count);                       00408000
   VALUE count;                                                         00410000
   ARRAY buffer;                                                        00412000
   INTEGER count;                                                       00414000
   OPTION PRIVILEGED,UNCALLABLE;                                        00416000
                                                                        00418000
<<==============================================================        00420000
                                                                        00422000
      This procedure generates a checksum  for  data  in  the           00424000
   specified buffer (usually a bit map page). The checksum is           00426000
   generated for "count" words, however, count must be  even.           00428000
   The  checksum  is  generated  by  treating the buffer as a           00430000
   double array and summing each of the double word  elements           00432000
   (both  words  of  the sum are initialized to 1).  Then the           00434000
   two words from the double sum are added together  to  form           00436000
   the  checksum.  Overflows  are  ignored.  If the check sum           00438000
   word is part of the buffer, as in the case of  a  bit  map           00440000
   page,  the  sum  should be set to zero before calling this           00442000
   routine.  This routine is semiassembly language for  speed           00444000
   purposes.                                                            00446000
                                                                        00448000
   Returns:                                                             00450000
      The one word checksum.                                            00452000
                                                                        00454000
   Assumptions on entry:                                                00456000
      DB is set to the data segment containing the buffer.              00458000
                                                                        00460000
   Exit conditions:                                                     00462000
      DB is unchanged.                                                  00464000
                                                                        00466000
   Globals:                                                             00468000
      None.                                                             00470000
                                                                        00472000
   Externals:                                                           00474000
      None.                                                             00476000
                                                                        00478000
   Intrinsics:                                                          00480000
      None.                                                             00482000
                                                                        00484000
   Callers:                                                             00486000
      Create'Dfs'Data'Seg                                               00488000
      Deallocate'Dfs'Data'Seg                                           00490000
      Read'Page                                                         00492000
      Write'Page                                                        00494000
      VINIT module 32                                                   00496000
      INITIAL - Write'Page                                              00498000
      INITIAL - Get'Page                                                00500000
      INITIAL - Init'Disc'Free'Space'Map                                00502000
                                                                        00504000
   Changes:                                                             00506000
                                                                        00508000
                                                                        00510000
==============================================================>>        00512000
                                                                        00514000
BEGIN                                                                   00516000
                                                                        00518000
   DOUBLE ARRAY d'buffer (*) = buffer;                                  00520000
   INTEGER x = X;                                                       00522000
                                                                        00524000
   LOGICAL return'value = Make'Check'Sum;                               00526000
                                                                        00528000
   << - - - - - - - - - - >>                                            00530000
                                                                        00532000
   << Disable arithmatic traps >>                                       00534000
                                                                        00536000
   PUSH (STATUS);                                                       00538000
   TOS.(2:1) := 0;                                                      00540000
   SET (STATUS);                                                        00542000
                                                                        00544000
                                                                        00546000
   x := count&ASR(1) - 1;            << Set index into double array >>  00548000
   TOS := 1;                         << Init double word checksum >>    00550000
   ASSEMBLE (DUP);                                                      00552000
                                                                        00554000
                                                                        00556000
   << Generate checksum >>                                              00558000
                                                                        00560000
   Loop:                                                                00562000
      TOS := TOS + d'buffer (x);  << Sum next double word >>            00564000
      x := x - 1;                 << Decrement buffer index >>          00566000
      ASSEMBLE (BGE Loop);        << Continue if index >= 0 >>          00568000
                                                                        00570000
                                                                        00572000
   return'value := TOS + TOS;        << Return single word checksum >>  00574000
                                                                        00576000
END;  << Make'Check'Sum >>                                              00578000
$PAGE "SCAN'PAGE"                                                       00580000
LOGICAL PROCEDURE Scan'Page;                                            00582000
   OPTION PRIVILEGED,UNCALLABLE;                                        00584000
                                                                        00586000
<<==============================================================        00588000
                                                                        00590000
      Procedure to scan a bit map page and locate  continuous           00592000
   blocks  of  free space.  Page to be scanned should be in a           00594000
   buffer and pointed  to  by  "ds'page'ptr".   The  scanning           00596000
   starts  at  the  word  and  bit  in the page pointed to by           00598000
   "ds'word'number" and "ds'bit'number".  The page is scanned           00600000
   until the first continous space is  found.   The  starting           00602000
   location     of     the     space     is    returned    in           00604000
   "ds'starting'word'number"  and   "ds'starting'bit'number".           00606000
   The  size of the block is returned in "ds'bit'count".  The           00608000
   next bit after the block is pointed to by "ds'word'number"           00610000
   and "ds'bit'number", ready for the next call to Scan'Page.           00612000
   If the end of the page was reached, the procedure  returns           00614000
   a  value of TRUE, otherwise FALSE.  If the end of the page           00616000
   was found and no space was found, then "ds'bit'count" will           00618000
   be zero.                                                             00620000
                                                                        00622000
   Returns:                                                             00624000
      FALSE - If the scan did not reach the end of the page.            00626000
      TRUE  - If the scan terminated on reaching the end of             00628000
              the page.                                                 00630000
                                                                        00632000
   Assumptions on entry:                                                00634000
      DB is at the free space data segment for the ldev and             00636000
      the data segment is locked.                                       00638000
                                                                        00640000
   Exit conditions:                                                     00642000
      DB is unchanged.                                                  00644000
                                                                        00646000
   Globals:                                                             00648000
                                                                        00650000
      Input:                                                            00652000
         ds'page'ptr                                                    00654000
         ds'word'number - changed on exit.                              00656000
         ds'bit'number  - chenged on exit.                              00658000
                                                                        00660000
      Output:                                                           00662000
         ds'starting'word'number                                        00664000
         ds'starting'bit'number                                         00666000
         ds'bit'count                                                   00668000
         ds'word'number                                                 00670000
         ds'bit'number                                                  00672000
                                                                        00674000
      Equates:                                                          00676000
         bits'per'word {INCLDFS2}                                       00678000
         words'per'page {INCLDFS2}                                      00680000
                                                                        00682000
   Externals:                                                           00684000
      None.                                                             00686000
                                                                        00688000
   Intrinsics:                                                          00690000
      None.                                                             00692000
                                                                        00694000
   Callers:                                                             00696000
      Build'Descriptor'Entry                                            00698000
      Locate'Free'Space                                                 00700000
      Get'Specific'Disc'Space                                           00702000
      VINIT module 32                                                   00704000
      FREE2 module FR                                                   00706000
      INITIAL - Get'Disc'Space                                          00708000
      INITIAL - Get'Specific'Disc'Space                                 00710000
                                                                        00712000
   Changes:                                                             00714000
                                                                        00716000
                                                                        00718000
==============================================================>>        00720000
                                                                        00722000
BEGIN << Scan'Page >>                                                   00724000
                                                                        00726000
   LOGICAL word;  << content of current word in page >>                 00728000
   LOGICAL done;  << flag for loop >>                                   00730000
   INTEGER x = X; << X-reg for use with SCAN instruction >>             00732000
                                                                        00734000
   LOGICAL return'value = Scan'Page;                                    00736000
                                                                        00738000
   << - - - - - - - - - - >>                                            00740000
                                                                        00742000
   SUBROUTINE Get'Next'Word;                                            00744000
                                                                        00746000
   <<--------------------------------------------------------           00748000
                                                                        00750000
        Subroutine to get the next word out of the page and             00752000
     stores it in "word".  "ds'word'number" is incremented              00754000
     and "ds'bit'number" is reset to zero.  If the end of the           00756000
     page is reached, "return'value" is set to TRUE and the             00758000
     procedure Scan'Page is EXITed.                                     00760000
                                                                        00762000
   -------------------------------------------------------->>           00764000
                                                                        00766000
   BEGIN << Get'Next'Word >>                                            00768000
                                                                        00770000
      ds'word'number := ds'word'number + 1;                             00772000
                                                                        00774000
      IF ds'word'number = words'per'page THEN                           00776000
         BEGIN << end of page >>                                        00778000
                                                                        00780000
            return'value := TRUE;                                       00782000
            ASSEMBLE (EXIT 0);  << exit procedure >>                    00784000
                                                                        00786000
         END   << end of page >>                                        00788000
      ELSE                                                              00790000
         BEGIN << fetch next word >>                                    00792000
                                                                        00794000
            word := ds'page'ptr (ds'word'number);                       00796000
            ds'bit'number := 0;                                         00798000
                                                                        00800000
         END;  << fetch next word >>                                    00802000
                                                                        00804000
   END;  << Get'Next'Word >>                                            00806000
                                                                        00808000
                                                                        00810000
   << - - - - - - - - - - >>                                            00812000
                                                                        00814000
                                                                        00816000
   ds'bit'count := 0;                                                   00818000
                                                                        00820000
   << get first word to look at and possition current bit               00822000
      as bit 0. Discard bits before that.                 >>            00824000
                                                                        00826000
   word := ds'page'ptr (ds'word'number)&LSL(ds'bit'number);             00828000
                                                                        00830000
                                                                        00832000
   << Look for a word that has some bits on >>                          00834000
                                                                        00836000
   WHILE word = 0 DO                                                    00838000
      Get'Next'Word;                                                    00840000
                                                                        00842000
                                                                        00844000
   << Scan for first on-bit and possition as bit-0,                     00846000
      remember starting word and bit.                >>                 00848000
                                                                        00850000
   TOS := word;                                                         00852000
   ASSEMBLE (SCAN;      << look for bit >>                              00854000
             TSBC 15);  << reset bit that was shifted off end >>        00856000
   word := TOS&CSR(1);                                                  00858000
   ds'bit'number := ds'bit'number + x;                                  00860000
                                                                        00862000
   ds'starting'bit'number := ds'bit'number;                             00864000
   ds'starting'word'number := ds'word'number;                           00866000
                                                                        00868000
                                                                        00870000
   << Loop to look for the end of the continous space,                  00872000
      counting bits as we go. Word.(0:1) will be 1 at                   00874000
      the start of the loop.                          >>                00876000
                                                                        00878000
   done := FALSE;                                                       00880000
                                                                        00882000
   WHILE NOT done DO                                                    00884000
      BEGIN << look for end of space >>                                 00886000
         IF word = 0 THEN                                               00888000
            done := TRUE                                                00890000
                                                                        00892000
         ELSE                                                           00894000
            IF word = %177777 THEN                                      00896000
               BEGIN << word is all ones >>                             00898000
                                                                        00900000
                  ds'bit'count := ds'bit'count + bits'per'word;         00902000
                  Get'Next'Word;                                        00904000
                                                                        00906000
               END   << word is all ones >>                             00908000
            ELSE                                                        00910000
               BEGIN << scan for zero bit >>                            00912000
                                                                        00914000
                  TOS := NOT word;  << so we can SCAN for a zero >>     00916000
                  ASSEMBLE (SCAN;                                       00918000
                            DEL);                                       00920000
                  ds'bit'count := ds'bit'count + x;                     00922000
                  ds'bit'number := ds'bit'number + x;                   00924000
                                                                        00926000
                  IF ds'bit'number = bits'per'word THEN                 00928000
                                                                        00930000
                     Get'Next'Word                                      00932000
                  ELSE                                                  00934000
                     done := TRUE;                                      00936000
                                                                        00938000
               END;  << scan for zero bit >>                            00940000
                                                                        00942000
      END;  << look for end of space >>                                 00944000
                                                                        00946000
                                                                        00948000
   return'value := FALSE;                                               00950000
                                                                        00952000
END;  << Scan'Page >>                                                   00954000
<<==============================================================        00956000
                                                                        00958000
                       End of INCLDFSC                                  00960000
                                                                        00962000
==============================================================>>        00964000
