<< LINES .001/.009 ARE RESERVED FOR SYSTEMS INTEGRATION>>               00005000
$CONTROL MAP,CODE,USLINIT                                               00010000
<<CACHESEG : MODULE 5E>>                                       <<06858>>00015000
$CONTROL PRIVILEGED,SEGMENT=CACHESEG,MAIN=CACHESEG                      00020000
<<*************************>>                                           00025000
<< Set X1=ON for debug, mmstat, and extra error checking >>             00030000
<< For debug ONLY!!!                                     >>    <<06858>>00035000
<<*************************>>                                           00040000
$set x1=off                                                    <<*7723>>00045000
<< Set X8=on for full INCL file listings >>                             00050000
$set x8=on                                                              00055000
<< Set x7=on for locking code- CURRENTLY NOT SUPPORTED! >>     <<06858>>00060000
$set x7=off                                                    <<06858>>00065000
<< X6 must always be on for full INCLLDR defines >>            <<*7724>>00070000
$set x6=on                                                     <<*7724>>00075000
                                                                        00080000
COMMENT                                                                 00085000
                                                                        00090000
This segment contains the disc cache manipulation procedures required   00095000
by the kernel.  The segment is locked and frozen into memory when       00100000
disc caching is first enabled for a device, and unlocked and unfrozen   00105000
when disc caching is last disabled.                                     00110000
                                                                        00115000
;                                                                       00120000
                                                                        00125000
BEGIN                                                                   00130000
                                                                        00135000
$Page "Cache Control Specific Defines"                         <<06858>>00140000
                                                               <<06858>>00145000
                                                               <<06858>>00150000
<<cache status returns>>                                       <<06858>>00155000
                                                               <<06858>>00160000
EQUATE stat'ok = 0,                                            <<06858>>00165000
       stat'no'dst=1,                                          <<06858>>00170000
       stat'int'error=2,                                       <<06858>>00175000
       stat'ldev'cached=3,                                     <<06858>>00180000
       stat'cdt'overflow=4,                                    <<06858>>00185000
       stat'dev'not'cachable=5,                                <<06858>>00190000
       stat'sys'not'cachable=6;                                <<06858>>00195000
                                                               <<06858>>00200000
                                                               <<06858>>00205000
                                                               <<06858>>00210000
                                                                        00215000
                                                               <<*7724>>00220000
                                                               <<*7551>>00225000
$IF X6 = ON                                                    <<*7724>>00230000
LOGICAL POINTER LPDT  = %10;                                   <<*7724>>00235000
$IF                                                            <<*7724>>00240000
                                                               <<*7724>>00245000
$INCLUDE inclstdd                                                       00250000
                                                               <<h8580>>00255000
INTEGER POINTER                                                <<h8580>>00260000
   DST  = DSTP,                                                <<h8580>>00265000
   PCB  = PCBP;                                                <<h8580>>00270000
                                                               <<h8580>>00275000
$INCLUDE inclst                                                <<h8580>>00280000
$INCLUDE incldrq                                               <<06858>>00285000
$INCLUDE incldqh                                               <<07308>>00290000
$INCLUDE inclobj                                                        00295000
$INCLUDE inclreg                                                        00300000
$INCLUDE inclsf                                                         00305000
$INCLUDE inclmmst                                                       00310000
$INCLUDE inclmsg                                                        00315000
$INCLUDE inclpcb5                                              <<06858>>00320000
$INCLUDE inclpcbx                                                       00325000
$INCLUDE inclparm                                                       00330000
$include inclknio                                              <<06856>>00335000
$include incllpdt                                              <<06856>>00340000
$INCLUDE inclcdef                                                       00345000
$INCLUDE INCLLDR                                               <<06859>>00350000
$INCLUDE inclmeas                                                       00355000
$INCLUDE inclmift                                              <<*7551>>00360000
$INCLUDE inclkcim                                                       00365000
$INCLUDE inclkdim                                                       00370000
$INCLUDE inclioim                                                       00375000
                                                               <<*7727>>00380000
                                                               <<*7727>>00385000
PROCEDURE RETURNSYSBUF(INDEX);                                 <<*7727>>00390000
VALUE INDEX;                                                   <<*7727>>00395000
INTEGER INDEX;                                                 <<*7727>>00400000
OPTION EXTERNAL;                                               <<*7727>>00405000
                                                               <<*7727>>00410000
                                                               <<*7727>>00415000
                                                               <<06858>>00420000
intrinsic ASCII,DASCII,PRINT;                                  <<06858>>00425000
intrinsic FREEDSEG,GETDSEG,DMOVIN,DMOVOUT;                     <<*7553>>00430000
                                                               <<06858>>00435000
                                                               <<06858>>00440000
                                                               <<06858>>00445000
                                                               <<06858>>00450000
$page " Forward Procedure Declarations"                                 00455000
<< Ask KERNEL to find cached domain, if it exists and is not mapped >>  00460000
logical procedure CDT'MAP'CACHED'DOMAIN(CDT'DISC'ENTRY,BASE'ADR,        00465000
                                        LIMIT'ADR,NEW'CDT,     <<07308>>00470000
                                        LDR'ENTRY'INDEX);      <<07308>>00475000
                                                                        00480000
value CDT'DISC'ENTRY,BASE'ADR,LIMIT'ADR,NEW'CDT,               <<07308>>00485000
      LDR'ENTRY'INDEX;                                                  00490000
integer CDT'DISC'ENTRY,NEW'CDT;                                         00495000
logical LDR'ENTRY'INDEX;                                       <<07308>>00500000
double BASE'ADR,LIMIT'ADR;                                              00505000
option forward;                                                         00510000
<<********************************************************************>>00515000
<< This procedure scans the unmapped region list pointed to by disc   >>00520000
<< entry CDT'DISC'ENTRY.  If a region is found which completely con-  >>00525000
<< tains the the disc sector range, then a CDT entry is obtained and  >>00530000
<< formatted to point to that region.  If partial or no overlaps are  >>00535000
<< found, any overlapping region is taken off the list and deleted,   >>00540000
<< and a "0" CDT number is returned to the caller.                    >>00545000
<<                                                                    >>00550000
<< Passed parameters:                                                 >>00555000
<<                                                                    >>00560000
<< CDT'DISC'ENTRY  - The index of the CDT disc entry for this LDEV.   >>00565000
<<                   It contains the list head for all the unmapped   >>00570000
<<                   regions.                                         >>00575000
<<                                                                    >>00580000
<< BASE'ADR        - This is the double word sector address of the    >>00585000
<<                   base sector requested.                           >>00590000
<<                                                                    >>00595000
<< LIMIT'ADR       - This is the upper limit disc address of the range>>00600000
<<                   of sectors required to complete a logical request>>00605000
<<                   The LIMIT'ADR is actually 1 sector greater than  >>00610000
<<                   the highest sector number required (ie sector 1  >>00615000
<<                   for 5 bytes would be BASE'ADR=1 and LIMIT'ADR=2).>>00620000
<<                                                                    >>00625000
<< NEW'CDT         - Only valid on a MAP call, this contains the CDT  >>00630000
<<                   entry number of a mapped domain that is absent   >>00635000
<<                   and has a strategy applied to it.                >>00640000
<< The caller will be PDISABLEd prior to calling this procedure.      >>00645000
<<********************************************************************>>00650000
LOGICAL PROCEDURE CDT'Flush'Cached'Range(devcdtentry,start'addr,        00655000
                                        limit'addr,new'cdt,    <<07308>>00660000
                                        ldr'entry'index);      <<07308>>00665000
VALUE devcdtentry,start'addr,limit'addr,new'cdt,               <<07308>>00670000
      ldr'entry'index;                                                  00675000
INTEGER devcdtentry,new'cdt;                                            00680000
LOGICAL ldr'entry'index;                                       <<07308>>00685000
DOUBLE start'addr,limit'addr;                                           00690000
OPTION FORWARD;                                                         00695000
                                                                        00700000
<<********************************************************************>>00705000
<< This procedure scans the unmapped region list pointed to by        >>00710000
<< CDT'DISC'ENTRY and deletes any region which is partially over-     >>00715000
<< lapping the disc address range specified.                          >>00720000
<<                                                                    >>00725000
<< The parameters are:                                                >>00730000
<<                                                                    >>00735000
<< CDT'DISC'ENTRY  - The index of the CDT disc entry for this LDEV.   >>00740000
<<                   It contains the list head for all the unmapped   >>00745000
<<                   regions.                                         >>00750000
<<                                                                    >>00755000
<< BASE'ADR        - This is the double word sector address of the    >>00760000
<<                   base sector requested.                           >>00765000
<<                                                                    >>00770000
<< LIMIT'ADR       - This is the upper limit disc address of the range>>00775000
<<                   of sectors required to complete a logical request>>00780000
<<                   The LIMIT'ADR is actually 1 sector greater than  >>00785000
<<                   the highest sector number required (ie sector 1  >>00790000
<<                   for 5 bytes would be BASE'ADR=1 and LIMIT'ADR=2).>>00795000
<<                                                                    >>00800000
<< NEW'CDT         - Ignored.                                         >>00805000
<< The caller will be PDISABLEd prior to calling this procedure.      >>00810000
<<********************************************************************>>00815000
                                                                        00820000
procedure CDT'UNMAP'REGION(CDT'DISC'ENTRY,CDT'ENTRY);                   00825000
value CDT'DISC'ENTRY,CDT'ENTRY;                                         00830000
integer CDT'DISC'ENTRY,CDT'ENTRY;                                       00835000
option forward;                                                         00840000
<<********************************************************************>>00845000
<< This procedure takes the memory region pointed to my mapped CDT    >>00850000
<< domain CDT'ENTRY and places it on the unmapped region list for a   >>00855000
<< disc pointed to by CDT'DISC'ENTRY.                                 >>00860000
<<                                                                    >>00865000
<< The parameters are:                                                >>00870000
<< CDT'DISC'ENTRY    - This is the CDT entry index of the disc entry  >>00875000
<<                      for this LDEV.                                >>00880000
<<                                                                    >>00885000
<< CDT'ENTRY         - This is the CDT entry index of the mapped disc >>00890000
<<                     domain.                                        >>00895000
<<                                                                    >>00900000
<< The caller is PDISABLEd prior to calling this procedure.           >>00905000
<<********************************************************************>>00910000
                                                                        00915000
procedure ZAPCACHEDDOMAIN(REGBASE);                            <<06858>>00920000
value REGBASE;                                                 <<06858>>00925000
double REGBASE;                                                <<06858>>00930000
option forward;                                                <<06858>>00935000
$page "PROCEDURE IsSysCachable"                                         00940000
                                                                        00945000
LOGICAL PROCEDURE IsSysCachable;                                        00950000
OPTION PRIVILEGED,UNCALLABLE;                                           00955000
                                                                        00960000
COMMENT                                                                 00965000
                                                                        00970000
If the customer purchases disc caching, then this procedure    <<07311>>00975000
and the full complement of procedures in this module will be   <<07311>>00980000
installed into SL.PUB.SYS. However, if they did not purchase   <<07311>>00985000
disc caching, this procedure would always return false and     <<07311>>00990000
this module would be "stubbed" out.                            <<07311>>00995000
                                                                        01000000
;                                                                       01005000
                                                                        01010000
BEGIN                                                                   01015000
                                                                        01020000
                                                               <<07311>>01025000
                                                                        01030000
IsSysCachable := TRUE;                                                  01035000
                                                                        01040000
END;  <<Procedure IsSysCachable>>                                       01045000
                                                                        01050000
$page "PROCEDURE IsDevCachable"                                         01055000
                                                                        01060000
LOGICAL PROCEDURE IsDevCachable(ldev);                                  01065000
VALUE ldev;                                                             01070000
INTEGER ldev;                                                           01075000
OPTION PRIVILEGED,UNCALLABLE;                                           01080000
                                                                        01085000
COMMENT                                                                 01090000
                                                                        01095000
Checks to see if the specified device is cachable. (Currently  <<07311>>01100000
checks to see if a disc.  should also check serial disc and             01105000
only disallow etc... this is yours,al)                         <<07311>>01110000
                                                                        01115000
;                                                                       01120000
                                                                        01125000
BEGIN                                                                   01130000
                                                               <<07311>>01135000
DEFINE                                                         <<07311>>01140000
   LPDT'INDEX = LDEV * SIZE'OF'LPDT'ENTRY#;                    <<07311>>01145000
                                                               <<07311>>01150000
                                                                        01155000
CHECKLDEV(LDEV);                                                        01160000
IF = AND CARRY << AND NOT LPDT'RDY'SER'FRN'DISC >>             <<07311>>01165000
   THEN IsDevCachable := TRUE                                  <<07311>>01170000
ELSE IsDevCachable := FALSE;                                            01175000
                                                                        01180000
END;  <<Procedure IsDevCachable>>                                       01185000
$page "PROCEDURE CDT'GET'ENTRY"                                         01190000
integer procedure CDT'GET'ENTRY;                                        01195000
option privileged,uncallable;                                           01200000
begin                                                                   01205000
                                                                        01210000
<<***********************************************************>>         01215000
<< This procedure obtains a FREE entry in the CDT table and  >>         01220000
<< returns its index.  If no entry is available, a value of  >>         01225000
<< zero is returned to the caller.                           >>         01230000
<<                                                           >>         01235000
<< DB can be set anywhere.                                   >>         01240000
<<***********************************************************>>         01245000
                                                                        01250000
integer CDT'ENTRY=CDT'GET'ENTRY; << Obtained CDT index       >>         01255000
                                                                        01260000
<< Make sure CDT DST exists >>                                          01265000
DISABLE;                                                                01270000
$if x1=on                                                               01275000
if CACHE'DST = 0 then                                                   01280000
  begin                                                                 01285000
  SUDDENDEATH(CDT'NOT'INITIALIZED);                                     01290000
  help; <<just to get an stt>>                                          01295000
  end;                                                                  01300000
$if                                                                     01305000
                                                                        01310000
<< Actually get an entry >>                                             01315000
                                                                        01320000
<< move DB to the CACHE DST >>                                          01325000
CDT'ABS'ON'TOS;                                                <<*7724>>01330000
                                                               <<*7724>>01335000
                                                                        01340000
EXCHDB;                                                                 01345000
                                                                        01350000
<< Get head of free list >>                                             01355000
CDT'ENTRY := CDT'ARRAY(CDT'FREE'HEAD); << Get first entry >>            01360000
if <> then                                                              01365000
  begin  << There is an available entry >>                              01370000
                                                                        01375000
  << Check that index passed is valid >>                                01380000
  << DB must be pointing to the CDT and integer CDT'ENTRY is   >>       01385000
  << used to perform a validity check against.                 >>       01390000
$if x1=on                                                               01395000
  if CDT'ARRAY(CDT'ENTRY) <> -1 then                                    01400000
    SUDDENDEATH(CDT'UNASSIGNED);  << Actually, reversed sense >>        01405000
  CDT'ARRAY(CDT'X) := 0;                                                01410000
  CDT'CHECK'INDEX;                                                      01415000
$if                                                                     01420000
                                                                        01425000
  << Place the next CDT pointer into the HEAD pointer >>                01430000
  CDT'ARRAY(CDT'FREE'HEAD) := CDT'ARRAY(CDT'ENTRY+CDT'FREE'HEAD);       01435000
                                                                        01440000
  << If head pointer is zero, this implies that the list is  >>         01445000
  << empty and the tail pointer must also be zeroed.         >>         01450000
  if CDT'ARRAY(CDT'FREE'HEAD) = 0 then                                  01455000
    CDT'ARRAY(CDT'FREE'TAIL) := 0;                                      01460000
                                                                        01465000
  << Increment the MAX in use count if it has been exceeded  >>         01470000
  CDT'ARRAY(CDT'FREE'COUNT) := CDT'ARRAY(CDT'FREE'COUNT) - 1;           01475000
  if (CDT'ARRAY(CDT'ENTRIES) - CDT'ARRAY(CDT'FREE'COUNT)) >             01480000
     CDT'ARRAY(CDT'MAX'USED) then                                       01485000
    CDT'ARRAY(CDT'MAX'USED) := CDT'ARRAY(CDT'ENTRIES) -                 01490000
                                 CDT'ARRAY(CDT'FREE'COUNT);             01495000
                                                                        01500000
  << Zero-out entry just obtained >>                                    01505000
  CDT'ARRAY(CDT'ENTRY) := 0;                                            01510000
  move CDT'ARRAY(CDT'ENTRY+1) := CDT'ARRAY(CDT'ENTRY),                  01515000
                               (CDT'ENTRY'SIZE-1);                      01520000
                                                                        01525000
  << Change index into entry >>                                         01530000
  CDT'GET'ENTRY := CDT'ENTRY / CDT'ENTRY'SIZE;                          01535000
  end                                                                   01540000
                                                                        01545000
else                                                                    01550000
                                                                        01555000
  << We should never run out of CDT entries >>                          01560000
  SUDDENDEATH(CDT'TABLE'EMPTY);                                         01565000
                                                                        01570000
<< Place DB back to caller's DB >>                                      01575000
EXCHDB;                                                                 01580000
                                                                        01585000
<< EXIT will place INTERRUPTs back to caller's state >>                 01590000
$if x1=on                                                               01595000
MMSTAT'(MMSTAT'GET'CDT,CDT'ENTRY,1,0,0,0,0);                   <<06859>>01600000
$if                                                                     01605000
end;  << of procedure GET'CDT'ENTRY >>                                  01610000
$page "CDT'FREE'ENTRY procedure"                                        01615000
procedure CDT'FREE'ENTRY(CDT'ENTRY);                                    01620000
value CDT'ENTRY;                                                        01625000
integer CDT'ENTRY;                                                      01630000
option privileged,uncallable;                                           01635000
begin                                                                   01640000
                                                                        01645000
<<***********************************************************>>         01650000
<< This procedure returns the CDT entry pointed to by        >>         01655000
<< CDT'ENTRY and returns it to the free list.                >>         01660000
<<                                                           >>         01665000
<< CDT'ENTRY   - This is the index into the CDT table of the >>         01670000
<<               entry to be released.                       >>         01675000
<<                                                           >>         01680000
<< DB can point anywhere before calling this procedure.      >>         01685000
<<***********************************************************>>         01690000
                                                                        01695000
<< Re-define entry into index >>                                        01700000
integer CDT'INDEX = CDT'ENTRY;                                          01705000
                                                                        01710000
<< Make sure CACHE DST exists >>                                        01715000
DISABLE;                                                                01720000
$if x1=on                                                               01725000
if CACHE'DST = 0 then                                                   01730000
  SUDDENDEATH(CDT'NOT'INITIALIZED);                                     01735000
                                                                        01740000
MMSTAT'(MMSTAT'GET'CDT,CDT'ENTRY,0,0,0,0,0);                   <<06859>>01745000
$if                                                                     01750000
                                                                        01755000
<< Place DB at the CACHE DST >>                                         01760000
CDT'ABS'ON'TOS;                                                <<*7724>>01765000
                                                               <<*7724>>01770000
EXCHDB;                                                                 01775000
                                                                        01780000
$if x1=on                                                               01785000
<< Check that index passed is valid >>                                  01790000
<< DB must be pointing to the CDT and integer CDT'ENTRY is   >>         01795000
<< used to perform a validity check against.                 >>         01800000
CDT'CHECK'ENTRY;                                                        01805000
$if                                                                     01810000
                                                                        01815000
<< Change entry into a index >>                                         01820000
CDT'INDEX := CDT'INDEX * CDT'ENTRY'SIZE;                                01825000
                                                                        01830000
<< Return index to tail of free list >>                                 01835000
if CDT'ARRAY(CDT'FREE'HEAD) = 0 then                                    01840000
  begin  << Free list is completely empty >>                            01845000
  CDT'ARRAY(CDT'FREE'HEAD) := CDT'ARRAY(CDT'FREE'TAIL) := CDT'ENTRY;    01850000
  end                                                                   01855000
                                                                        01860000
else                                                                    01865000
                                                                        01870000
  begin  << There is already something on the free list >>              01875000
                                                                        01880000
  << Put this entry's index into the prior tail's next pointer >>       01885000
  CDT'ARRAY(CDT'ARRAY(CDT'FREE'TAIL)+CDT'FREE'HEAD) := CDT'ENTRY;       01890000
                                                                        01895000
  << Place this entry's index into the new TAIL pointer >>              01900000
  CDT'ARRAY(CDT'FREE'TAIL) := CDT'ENTRY;                                01905000
                                                                        01910000
  end;                                                                  01915000
                                                                        01920000
<< Increment the free count >>                                          01925000
CDT'ARRAY(CDT'FREE'COUNT) := CDT'ARRAY(CDT'FREE'COUNT) + 1;             01930000
                                                                        01935000
<< Zero next pointer in entry just returned >>                          01940000
CDT'ARRAY(CDT'ENTRY) := -1;  << Mark entry available >>                 01945000
CDT'ARRAY(CDT'ENTRY + CDT'FREE'HEAD) := 0;                              01950000
                                                                        01955000
<< Place DB back to caller's DB >>                                      01960000
EXCHDB;                                                                 01965000
                                                                        01970000
<< EXIT will put INTERRUPT state back to caller's state >>              01975000
end;  << of procedure CDT'FREE'ENTRY >>                                 01980000
$page "CDT'SET'BIT CDT'GET'BIT procedure executor"                      01985000
logical procedure CDT'SET'BIT(CDT'ENTRY,BIT'NUMBER,BIT'VALUE);          01990000
value CDT'ENTRY,BIT'NUMBER,BIT'VALUE;                                   01995000
integer CDT'ENTRY,BIT'NUMBER;                                           02000000
logical BIT'VALUE;                                                      02005000
option privileged,uncallable;                                           02010000
begin                                                                   02015000
                                                                        02020000
entry CDT'GET'BIT;      << This entry point only returns the >>         02025000
                        << previous state of the bit, and it >>         02030000
                        << remains unchanged.                >>         02035000
                                                                        02040000
logical MOD'ENTRY;      << Flag if the GET ONLY entry point  >>         02045000
                        << was entered.                      >>         02050000
                                                                        02055000
<<***********************************************************>>         02060000
<< This procedure accepts a bit number, as defined in the    >>         02065000
<< INCLCDT file, and sets the bit in the FLAGS word of the   >>         02070000
<< CDT entry specified.  The old value of the bit is returned>>         02075000
<< as the function return value, bit (15:1).                 >>         02080000
<<                                                           >>         02085000
<< CDT'ENTRY   - The index of the CDT entry to be modified.  >>         02090000
<< BIT'NUMBER  - The relative BIT number in the FLAGS word   >>         02095000
<<               to be set TRUE or on.                       >>         02100000
<< BIT'VALUE   - If this value is TRUE, the bit is turned on,>>         02105000
<<               if false, then the bit is turned off.       >>         02110000
<<                                                           >>         02115000
<< CDT'SET'BIT - The prior value of the specified bit is     >>         02120000
<<               returned in this cell, bit (15:1).          >>         02125000
<<                                                           >>         02130000
<< DB can be set anywhere when calling this procedure.       >>         02135000
<<***********************************************************>>         02140000
                                                                        02145000
<< Re-define entry as index >>                                          02150000
integer CDT'INDEX = CDT'ENTRY;                                          02155000
                                                                        02160000
<< Normal entry point >>                                                02165000
MOD'ENTRY := true;                                                      02170000
go to START;                                                            02175000
                                                                        02180000
CDT'GET'BIT:                                                            02185000
                                                                        02190000
MOD'ENTRY := false;                                                     02195000
                                                                        02200000
START:                                                                  02205000
                                                                        02210000
<< First, we will check if the CDT DST exists.               >>         02215000
DISABLE;                                                                02220000
$if x1=on                                                               02225000
if CACHE'DST = 0 then                                                   02230000
  SUDDENDEATH(CDT'NOT'INITIALIZED);                                     02235000
$if                                                                     02240000
                                                                        02245000
<< Put DB to the CDT DST                                     >>         02250000
tos := CACHE'DST'BANK;                                                  02255000
tos := CACHE'DST'OFST;                                                  02260000
EXCHDB;                                                                 02265000
                                                                        02270000
$if x1=on                                                               02275000
<< Check that index passed is valid >>                                  02280000
<< DB must be pointing to the CDT and integer CDT'ENTRY is   >>         02285000
<< used to perform a validity check against.                 >>         02290000
CDT'CHECK'ENTRY;                                                        02295000
$if                                                                     02300000
                                                                        02305000
<< Change entry into an index >>                                        02310000
CDT'INDEX := CDT'INDEX * CDT'ENTRY'SIZE;                                02315000
                                                                        02320000
<< Turn on the appropriate bit >>                                       02325000
DISABLE;   << Protect from interrupts >>                       <<06858>>02330000
tos := CDT'ARRAY(CDT'ENTRY + CDT'MD'FLAGS);                             02335000
CDT'X := BIT'NUMBER;                                                    02340000
if MOD'ENTRY then                                                       02345000
  begin                                                                 02350000
  if BIT'VALUE then                                                     02355000
    assemble(tsbc 0,X)   << Turn on bit >>                              02360000
  else                                                                  02365000
    assemble(trbc 0,X);  << Turn off bit >>                             02370000
                                                                        02375000
  << If bit was set, turn on return bit >>                              02380000
  if <> then                                                            02385000
    CDT'SET'BIT := 1                                                    02390000
  else                                                                  02395000
    CDT'SET'BIT := 0;                                                   02400000
                                                                        02405000
  << Store back value >>                                                02410000
  CDT'ARRAY(CDT'ENTRY + CDT'MD'FLAGS) := tos;                           02415000
  end                                                                   02420000
                                                                        02425000
else                                                                    02430000
                                                                        02435000
  begin  << Just get existing value >>                                  02440000
                                                                        02445000
  assemble(tbc 0,X);                                                    02450000
  if <> then                                                            02455000
    CDT'SET'BIT := 1                                                    02460000
  else                                                                  02465000
    CDT'SET'BIT := 0;                                                   02470000
                                                                        02475000
  assemble(del);  << Just remove the stacked value (no mod) >>          02480000
  end;                                                                  02485000
                                                                        02490000
<< Put DB back to where caller had it >>                                02495000
EXCHDB;                                                                 02500000
                                                                        02505000
<< EXIT will return INTERRUPTs state >>                                 02510000
end;   << of procedure CDT'SET'BIT >>                                   02515000
$page "Procedure CDT'SET'WORD / CDT'GET'WORD / CDT'ADD'WORD"            02520000
integer procedure CDT'SET'WORD(CDT'ENTRY,WORD'NUMBER,WORD'VALUE);       02525000
value CDT'ENTRY,WORD'NUMBER,WORD'VALUE;                                 02530000
integer CDT'ENTRY,WORD'NUMBER,WORD'VALUE;                               02535000
option privileged,uncallable;                                           02540000
begin                                                                   02545000
                                                                        02550000
entry CDT'GET'WORD,    << This entry is used if the word is  >>         02555000
                       << to be retrieved w/o modification.  >>         02560000
                                                                        02565000
      CDT'ADD'WORD;    << This entry is to be used if the    >>         02570000
                       << value passed is to be 'added' to,  >>         02575000
                       << rather than 'replacing', the orig- >>         02580000
                       << inal value.                        >>         02585000
                                                                        02590000
logical MOD'WORD,      << If true, normal entry point.  If   >>         02595000
                       << false, then don't modify word.     >>         02600000
                                                                        02605000
        ADD'WORD;      << If true, then value is to be added >>         02610000
                       << to current value, rather than      >>         02615000
                       << replacing it.                      >>         02620000
                                                                        02625000
integer OLD'WORD = CDT'SET'WORD; << So we can read old word  >>         02630000
                                                                        02635000
<<***********************************************************>>         02640000
<< This procedure retrieves a word from the CDT entry speci- >>         02645000
<< fied, modifies it to the value provided, and returns the  >>         02650000
<< old value of the word as the function value.              >>         02655000
<<                                                           >>         02660000
<< CDT'ENTRY  - This is the CDT entry to be manipulated.     >>         02665000
<< WORD'NUMBER- This is the CDT offset of the word to be     >>         02670000
<<              modified.  The caller should use the equate  >>         02675000
<<              from the INCLCAC file to insure the proper   >>         02680000
<<              word is retrieved in case the entry values   >>         02685000
<<              are re-arranged in the future.               >>         02690000
<< WORD'VALUE - This is the value that the word is to be set >>         02695000
<<              to.  If CDT'ADD'WORD was called, this value  >>         02700000
<<              is added to the original value.              >>         02705000
<<                                                           >>         02710000
<< CDT'SET'WORD is set to the value of the word prior to     >>         02715000
<<              calling this procedure.  If CDT'ADD'WORD     >>         02720000
<<              was called, this is the NEW value of the     >>         02725000
<<              word.                                        >>         02730000
<<                                                           >>         02735000
<< DB can be anywhere prior to calling this procedure.       >>         02740000
<<***********************************************************>>         02745000
                                                                        02750000
<< Re-define entry as an index >>                                       02755000
integer CDT'INDEX = CDT'ENTRY;                                          02760000
                                                                        02765000
<< Normal entry point >>                                                02770000
MOD'WORD := true;                                                       02775000
ADD'WORD := false;                                                      02780000
go to START;                                                            02785000
                                                                        02790000
CDT'ADD'WORD:                                                           02795000
ADD'WORD := MOD'WORD := true;                                           02800000
go to START;                                                            02805000
                                                                        02810000
CDT'GET'WORD:                                                           02815000
MOD'WORD := false;                                                      02820000
                                                                        02825000
START:                                                                  02830000
                                                                        02835000
<< Make sure CDT table exists >>                                        02840000
DISABLE;                                                                02845000
$if x1=on                                                               02850000
if CACHE'DST = 0 then                                                   02855000
  SUDDENDEATH(CDT'NOT'INITIALIZED);                                     02860000
$if                                                                     02865000
                                                                        02870000
<< Place DB at DST >>                                                   02875000
tos := CACHE'DST'BANK;                                                  02880000
tos := CACHE'DST'OFST;                                                  02885000
EXCHDB;                                                                 02890000
                                                                        02895000
$if x1=on                                                               02900000
<< Check that index passed is valid >>                                  02905000
<< DB must be pointing to the CDT and integer CDT'ENTRY is   >>         02910000
<< used to perform a validity check against.                 >>         02915000
CDT'CHECK'ENTRY;                                                        02920000
$if                                                                     02925000
                                                                        02930000
<< Convert entry into index >>                                          02935000
CDT'INDEX := CDT'INDEX * CDT'ENTRY'SIZE;                                02940000
                                                                        02945000
<< Make sure word offset is valid >>                                    02950000
$if x1=on                                                               02955000
if WORD'NUMBER >= CDT'ENTRY'SIZE then                                   02960000
  SUDDENDEATH(CDT'BAD'WORD'OFST);                                       02965000
$if                                                                     02970000
                                                                        02975000
<< Retrieve word from DST and copy it to return cell >>                 02980000
<< * * DO NOT MODIFY INDEX REGISTER UNTIL NEW VALUE IS STORED >>        02985000
CDT'SET'WORD := CDT'ARRAY(CDT'ENTRY + WORD'NUMBER);                     02990000
                                                                        02995000
<< Place new value in cell >>                                           03000000
if MOD'WORD then                                                        03005000
  if ADD'WORD then                                                      03010000
    begin                                                               03015000
    CDT'ARRAY(CDT'X) := CDT'SET'WORD := WORD'VALUE + OLD'WORD;          03020000
    end                                                                 03025000
  else                                                                  03030000
    CDT'ARRAY(CDT'X) := WORD'VALUE;                                     03035000
                                                                        03040000
<< Place DB back to caller's DB >>                                      03045000
EXCHDB;                                                                 03050000
                                                                        03055000
<< EXIT will return INTERRUPTs to caller's state >>                     03060000
end;  << of procedure CDT'SET'WORD >>                                   03065000
$page "Procedure CDT'SET'DOUBLE / CDT'GET'DOUBLE / CDT'ADD'DOUBLE"      03070000
double procedure CDT'SET'DOUBLE(CDT'ENTRY,WORD'NUMBER,WORD'VALUE);      03075000
value CDT'ENTRY,WORD'NUMBER,WORD'VALUE;                                 03080000
integer CDT'ENTRY,WORD'NUMBER;                                          03085000
double WORD'VALUE;                                                      03090000
option privileged,uncallable;                                           03095000
begin                                                                   03100000
                                                                        03105000
entry CDT'GET'DOUBLE,   << This entry point is used if the   >>         03110000
                        << old value should be returned, but >>         03115000
                        << not modified.                     >>         03120000
                                                                        03125000
      CDT'ADD'DOUBLE;   << This entry point is used if       >>         03130000
                        << WORD'VALUE is to be added, rather >>         03135000
                        << than replace, the double word     >>         03140000
                        << specified by WORD'NUMBER.         >>         03145000
                                                                        03150000
logical MOD'DOUBLE,     << This flag is true if the normal   >>         03155000
                        << procedure entry point is used.    >>         03160000
                                                                        03165000
        ADD'DOUBLE;     << This flag signifies that WORD'VAL->>         03170000
                        << UE should be added to the current >>         03175000
                        << double word.                      >>         03180000
                                                                        03185000
double OLD'DOUBLE = CDT'SET'DOUBLE;  << Re-define return arg >>         03190000
                                                                        03195000
<<***********************************************************>>         03200000
<< This procedure retrieves double from the CDT entry speci- >>         03205000
<< fied, modifies it to the value provided, and returns the  >>         03210000
<< old value of the double word as the function value.       >>         03215000
<<                                                           >>         03220000
<< CDT'ENTRY  - This is the CDT entry to be manipulated.     >>         03225000
<< WORD'NUMBER- This is the CDT offset of the dbl word to be >>         03230000
<<              modified.  The caller should use the equate  >>         03235000
<<              from the INCLCAC file to insure the proper   >>         03240000
<<              word is retrieved in case the entry values   >>         03245000
<<              are re-arranged in the future.               >>         03250000
<< WORD'VALUE - This is the value that the dbl  is to be set >>         03255000
<<              to when CDT'SET'DOUBLE is called.  If CDT'   >>         03260000
<<              ADD'DOUBLE is called, this value is added to >>         03265000
<<              the original double-word value.              >>         03270000
<<                                                           >>         03275000
<< CDT'SET'WORD is set to the value of the dbl word prior to >>         03280000
<<              calling this procedure.  If CDT'ADD'DOUBLE is>>         03285000
<<              called, the value is the new double value of >>         03290000
<<              of the word after adding WORD'VALUE to it.   >>         03295000
<<                                                           >>         03300000
<< DB can be anywhere prior to calling this procedure.       >>         03305000
<<***********************************************************>>         03310000
                                                                        03315000
<< Re-define entry as index >>                                          03320000
integer CDT'INDEX = CDT'ENTRY;                                          03325000
                                                                        03330000
<< Normal entry point >>                                                03335000
MOD'DOUBLE := true;                                                     03340000
ADD'DOUBLE := false;                                                    03345000
go to START;                                                            03350000
                                                                        03355000
CDT'ADD'DOUBLE:                                                         03360000
MOD'DOUBLE := ADD'DOUBLE := true;                                       03365000
go to START;                                                            03370000
                                                                        03375000
CDT'GET'DOUBLE:                                                         03380000
MOD'DOUBLE := false;                                                    03385000
                                                                        03390000
START:                                                                  03395000
                                                                        03400000
<< Make sure CDT table exists >>                                        03405000
DISABLE;                                                                03410000
$if x1=on                                                               03415000
if CACHE'DST = 0 then                                                   03420000
  SUDDENDEATH(CDT'NOT'INITIALIZED);                                     03425000
$if                                                                     03430000
                                                                        03435000
<< Place DB at DST >>                                                   03440000
tos := CACHE'DST'BANK;                                                  03445000
tos := CACHE'DST'OFST;                                                  03450000
EXCHDB;                                                                 03455000
                                                                        03460000
$if x1=on                                                               03465000
<< Check that index passed is valid >>                                  03470000
<< DB must be pointing to the CDT and integer CDT'ENTRY is   >>         03475000
<< used to perform a validity check against.                 >>         03480000
CDT'CHECK'ENTRY;                                                        03485000
$if                                                                     03490000
                                                                        03495000
<< Convert entry into index >>                                          03500000
CDT'INDEX := CDT'INDEX * CDT'ENTRY'SIZE;                                03505000
                                                                        03510000
<< Make sure word offset is valid >>                                    03515000
$if x1=on                                                               03520000
if (WORD'NUMBER+1) >= CDT'ENTRY'SIZE then                               03525000
  SUDDENDEATH(CDT'BAD'WORD'OFST);                                       03530000
$if                                                                     03535000
                                                                        03540000
<< Retrieve word from DST and copy it to return cell >>                 03545000
tos := CDT'DARRAY((CDT'ENTRY + WORD'NUMBER)&asr(1));           <<*7724>>03550000
                                                               <<*7724>>03555000
<<* * INDEX REGISTER MUST NOT MODIFIED UNTIL NEW VALUE IS    >>         03560000
<<    STORED * *                                             >>         03565000
CDT'SET'DOUBLE := tos;                                                  03570000
                                                                        03575000
<< Place new value in cell >>                                           03580000
if MOD'DOUBLE then                                                      03585000
  begin                                                                 03590000
  if ADD'DOUBLE then                                                    03595000
    begin                                                               03600000
    tos := CDT'SET'DOUBLE := OLD'DOUBLE + WORD'VALUE;                   03605000
    end                                                                 03610000
  else                                                                  03615000
    begin                                                               03620000
    tos := WORD'VALUE;                                                  03625000
    end;                                                                03630000
  CDT'DARRAY(CDT'X) := tos;  << Store double word >>           <<*7724>>03635000
                                                               <<*7724>>03640000
  end;                                                                  03645000
                                                                        03650000
<< Place DB back to caller's DB >>                                      03655000
EXCHDB;                                                                 03660000
                                                                        03665000
<< EXIT will return INTERRUPTs to caller's state >>                     03670000
end;  << of procedure CDT'SET'DOUBLE >>                                 03675000
$page "CDT'GET'MD'ENTRY"                                                03680000
integer procedure CDT'GET'MD'ENTRY(LDEV'ENTRY,CD'BASE'SECTOR,           03685000
                                   MD'INDEX);                           03690000
value LDEV'ENTRY,CD'BASE'SECTOR,MD'INDEX;                               03695000
integer LDEV'ENTRY,MD'INDEX;                                            03700000
double CD'BASE'SECTOR;                                                  03705000
option privileged,uncallable,internal;                         <<06858>>03710000
begin                                                                   03715000
                                                                        03720000
<<********************************************************************>>03725000
<< This procedure obtains a free CDT table entry, places a disc req.  >>03730000
<< entry into it for KERNEL physical requests, and places it in the   >>03735000
<< appropriate place in the LDEV's mapped domain list.                >>03740000
<<                                                                    >>03745000
<< The passed parameters are:                                         >>03750000
<< LDEV'ENTRY        - This is the entry number in the CDT table of   >>03755000
<<                     the LDEV head of this cached disc.             >>03760000
<< CD'BASE'SECTOR    - The double base sector address used to position>>03765000
<<                     this mapped CDT entry into the mapped domain   >>03770000
<<                     list of this LDEV.                             >>03775000
<< MD'INDEX          - If this value is non-neg., it is the mapped    >>03780000
<<                     domain CDT entry number to put the newly-      >>03785000
<<                     obtained mapped CDT ahead of.                  >>03790000
<<                     <-1 - Search & add.                            >>03795000
<<                     =-1 - Add to tail.                             >>03800000
<<                     = 0 - Add to head.                             >>03805000
<<                     > 0 - Add before this CDT entry.               >>03810000
<<                                                                    >>03815000
<< The returned parameter is:                                         >>03820000
<<                                                                    >>03825000
<< CDT'GET'MD'ENTRY - The CDT entry index of the entry obtained.      >>03830000
<<********************************************************************>>03835000
                                                                        03840000
integer CDT'ENTRY  = CDT'GET'MD'ENTRY, << So we can access ptr >>       03845000
        LDREQ,                         << Disc request inx     >>       03850000
        PRIOR'PTR,                     << Previous CDT ptr     >>       03855000
        NEXT'PTR;                      << Next CDT pointer     >>       03860000
                                                                        03865000
<< Variables for fast CDT access >>                            <<*7724>>03870000
double SAVE'DB;                                                <<*7724>>03875000
                                                               <<*7724>>03880000
integer MAPD'OFFSET,                                           <<*7724>>03885000
        NEXT'MAPD'OFFSET,                                      <<*7724>>03890000
        LDEV'OFFSET;                                           <<*7724>>03895000
                                                               <<*7724>>03900000
logical LOOP'CONTROL;    << Loop exit flag >>                           03905000
                                                                        03910000
                                                                        03915000
                                                               <<*7724>>03920000
                                                               <<*7724>>03925000
                                                               <<*7724>>03930000
                                                               <<*7724>>03935000
                                                               <<*7724>>03940000
                                                               <<*7724>>03945000
<< Put DB at CDT >>                                            <<*7724>>03950000
CDT'ABS'ON'TOS;                                                <<*7724>>03955000
EXCHDB;                                                        <<*7724>>03960000
SAVE'DB := tos;                                                <<*7724>>03965000
                                                               <<*7724>>03970000
<< First, get an entry from the CDT table >>                            03975000
CDT'ENTRY := CDT'GET'ENTRY;                                             03980000
                                                               <<*7724>>03985000
LDEV'OFFSET := LDEV'ENTRY * CDT'ENTRY'SIZE;                    <<*7724>>03990000
MAPD'OFFSET := CDT'ENTRY * CDT'ENTRY'SIZE;                     <<*7724>>03995000
NEXT'MAPD'OFFSET := MD'INDEX * CDT'ENTRY'SIZE;                 <<*7724>>04000000
                                                                        04005000
<< Get a disc request element & place it in the CDT entry >>            04010000
tos := %1000 D;                                                <<*7724>>04015000
EXCHDB;                                                        <<*7724>>04020000
LDREQ := GETDISCREQ(2);  << Pri or secondary, no impede   >>            04025000
if LDREQ = 0 then                                                       04030000
  SUDDENDEATH(CDT'UNAVAIL'DRQ);                                         04035000
EXCHDB;  << Back to CDT >>                                     <<*7724>>04040000
ASMB(ddel);                                                    <<*7724>>04045000
                                                               <<*7724>>04050000
$if x1=on                                                      <<*7724>>04055000
CDT'SET'WORD(CDT'ENTRY,CDT'MD'DISCREQ,LDREQ);                  <<06856>>04060000
$if x1=off                                                     <<*7724>>04065000
CDT'ARRAY(MAPD'OFFSET+CDT'MD'DISCREQ) := LDREQ;                <<*7724>>04070000
$if                                                            <<*7724>>04075000
                                                                        04080000
<< Now place the CDT entry in the proper list position >>               04085000
                                                                        04090000
<<DISABLE;>> <<protect list structure>>                        <<06858>>04095000
                                                                        04100000
<< If a mapped CDT number was passed, this is a short-cut >>            04105000
NEXT'PTR := MD'INDEX;                                                   04110000
if > then                                                               04115000
  go to SHORT'CUT   << Busch won't like this... >>                      04120000
else if = then                                                          04125000
  go to SHORT'CUT'1                                                     04130000
else if MD'INDEX = -1 then                                              04135000
  begin                                                                 04140000
  PRIOR'PTR := CDT'ARRAY(LDEV'OFFSET+CDT'DE'MAPD'TAIL);        <<*7724>>04145000
  go to SHORT'CUT'2;                                                    04150000
  end;                                                                  04155000
                                                                        04160000
<< Get pointer to first entry on list >>                                04165000
tos := NEXT'PTR := CDT'ARRAY(LDEV'OFFSET+CDT'DE'MAPD'HEAD);    <<*7724>>04170000
if tos <<NEXT'PTR>> = 0 then                                   <<*7724>>04175000
  begin  << This is the first mapped domain on the list >>              04180000
                                                                        04185000
SHORT'CUT'1:                                                            04190000
                                                                        04195000
  CDT'ARRAY(LDEV'OFFSET+CDT'DE'MAPD'HEAD):=CDT'ENTRY;          <<*7724>>04200000
  CDT'ARRAY(LDEV'OFFSET+CDT'DE'MAPD'TAIL):=CDT'ENTRY;          <<*7724>>04205000
  << Pointers in obtained CDT should already be zero >>                 04210000
  end                                                                   04215000
else                                                                    04220000
  begin  << We must loop through mapped CDT regions >>                  04225000
  LOOP'CONTROL := false;                                       <<*7724>>04230000
  do                                                           <<*7724>>04235000
    begin                                                               04240000
    NEXT'MAPD'OFFSET := NEXT'PTR * CDT'ENTRY'SIZE;             <<*7724>>04245000
    << Check current mapped CDT's base  address against BASE >>         04250000
    tos := CDT'DARRAY((NEXT'MAPD'OFFSET+CDT'MD'SECTOR)&asr(1));<<*7724>>04255000
                                                               <<*7724>>04260000
    if tos > CD'BASE'SECTOR then                               <<*7724>>04265000
      begin  << Insert new mapped CDT entry in front of this >>         04270000
                                                                        04275000
SHORT'CUT:                                                              04280000
                                                                        04285000
      <<make this guy next's prior,save his old prior>>                 04290000
      PRIOR'PTR := CDT'ARRAY(NEXT'MAPD'OFFSET+CDT'MD'PREV);    <<*7724>>04295000
      CDT'ARRAY(CDT'X) := CDT'ENTRY;                           <<*7724>>04300000
      << Fix new CDT's pointers >>                                      04305000
      CDT'ARRAY(MAPD'OFFSET+CDT'MD'NEXT):=NEXT'PTR;            <<*7724>>04310000
      CDT'ARRAY(MAPD'OFFSET+CDT'MD'PREV):=PRIOR'PTR;           <<*7724>>04315000
      << Fix prev CDT entry's next pointer >>                           04320000
      if PRIOR'PTR = 0 then                                             04325000
        begin  << This new CDT is the newhead entry >>                  04330000
        CDT'ARRAY(LDEV'OFFSET+CDT'DE'MAPD'HEAD):=CDT'ENTRY;    <<*7724>>04335000
        end                                                             04340000
      else                                                              04345000
        begin  << There is another CDT entry preceding >>               04350000
        CDT'ARRAY((PRIOR'PTR*CDT'ENTRY'SIZE)+CDT'MD'NEXT)      <<*7724>>04355000
                  := CDT'ENTRY;                                <<*7724>>04360000
        end;                                                            04365000
      << Stop looping >>                                                04370000
      LOOP'CONTROL := true;                                    <<*7724>>04375000
      end  << Of inserting >>                                           04380000
    else if < then                                                      04385000
      begin   << Step to next mapped CDT domain >>                      04390000
      PRIOR'PTR := NEXT'PTR;  << Save current pointer >>                04395000
      NEXT'PTR := CDT'ARRAY(NEXT'MAPD'OFFSET+CDT'MD'NEXT);     <<*7724>>04400000
      if NEXT'PTR = 0 then                                              04405000
        begin  << This was the last mapped CDT, so append >>            04410000
                                                                        04415000
SHORT'CUT'2:                                                            04420000
                                                                        04425000
        << Put new CDT in last CDT's NEXT pointer >>                    04430000
        CDT'ARRAY((PRIOR'PTR*CDT'ENTRY'SIZE)+CDT'MD'NEXT) :=   <<*7724>>04435000
                  CDT'ENTRY;                                   <<*7724>>04440000
        << Update tail pointer in LDEV CDT entry >>                     04445000
        CDT'ARRAY(LDEV'OFFSET+CDT'DE'MAPD'TAIL):=CDT'ENTRY;    <<*7724>>04450000
        << Point new CDT back to old prior >>                           04455000
        CDT'ARRAY(MAPD'OFFSET+CDT'MD'PREV):=PRIOR'PTR;         <<*7724>>04460000
        << Stop looping >>                                              04465000
        LOOP'CONTROL := true;                                  <<*7724>>04470000
        end;  << of appending to end-of-chain >>                        04475000
      end   << of stepping through next mapped domain >>                04480000
    else                                                                04485000
                                                                        04490000
      << There should NEVER be a match-it means overlap !!! >>          04495000
      SUDDENDEATH(SFKERNCACHEINTBAD);                                   04500000
                                                                        04505000
    end until LOOP'CONTROL;  <<of do processing >>             <<*7724>>04510000
  end; << of processing mapped request that is not first >>             04515000
                                                                        04520000
<< Initialize CDT to proper state >>                                    04525000
CDT'ARRAY(MAPD'OFFSET+CDT'MD'FLAGS).(CDT'ABS'BIT:1):=1;        <<*7724>>04530000
                                                                        04535000
<< Increment mapped count >>                                            04540000
CDT'X := LDEV'OFFSET + CDT'DE'MAPD'CNT;                        <<*7724>>04545000
CDT'ARRAY(CDT'X) := CDT'ARRAY(CDT'X) + 1;                      <<*7724>>04550000
                                                                        04555000
<< Place LDEV in mapped CDT entry >>                                    04560000
CDT'ARRAY(MAPD'OFFSET+CDT'MD'LDEV) :=                          <<*7724>>04565000
   CDT'ARRAY(LDEV'OFFSET+CDT'DE'LDEV);                         <<*7724>>04570000
                                                                        04575000
<< Place device's entry index in MD entry >>                   <<d7726>>04580000
CDT'ARRAY(MAPD'OFFSET+CDT'MD'DE) := LDEV'ENTRY;                <<d7726>>04585000
                                                               <<d7726>>04590000
$if x1=on                                                               04595000
MMSTAT'(MMSTAT'GET'CDT,CDT'ENTRY,2,0,0,0,0);                   <<06859>>04600000
$if                                                                     04605000
end; << of procedure CDT'GET'MD'ENTRY >>                                04610000
$page "CDT'REL'MD'ENTRY"                                                04615000
procedure CDT'REL'MD'ENTRY(LDEV'ENTRY,CDT'ENTRY);                       04620000
value LDEV'ENTRY,CDT'ENTRY;                                             04625000
integer LDEV'ENTRY,CDT'ENTRY;                                           04630000
option privileged,uncallable,internal;                         <<06858>>04635000
begin                                                                   04640000
                                                                        04645000
<<********************************************************************>>04650000
<< This procedure releases a mapped CDT entry by returning the disc   >>04655000
<< request, delinking the mapped CDT, and returning it to the free    >>04660000
<< list.  The passed parameters are:                                  >>04665000
<<                                                                    >>04670000
<< LDEV'ENTRY     - The CDT device entry index for this mapped CDT.   >>04675000
<< CDT'ENTRY      - The mapped CDT entry to release.                  >>04680000
<<********************************************************************>>04685000
                                                                        04690000
integer PRIOR'PTR,       << Pointer to prior mapped domain >>           04695000
        NEXT'PTR,        << Pointer to next mapped domain >>            04700000
        DISCREQ;         << Disc request entry >>                       04705000
                                                                        04710000
<< Variables for fast CDT access >>                            <<*7724>>04715000
double SAVE'DB;                                                <<*7724>>04720000
                                                               <<*7724>>04725000
integer MAPD'OFFSET,                                           <<*7724>>04730000
        LDEV'OFFSET;                                           <<*7724>>04735000
                                                               <<*7724>>04740000
                                                                        04745000
                                                               <<*7724>>04750000
                                                               <<*7724>>04755000
                                                               <<*7724>>04760000
                                                               <<*7724>>04765000
$if x1=on                                                               04770000
MMSTAT'(MMSTAT'GET'CDT,CDT'ENTRY,3,LDEV'ENTRY,0,0,0);          <<06859>>04775000
$if                                                                     04780000
                                                                        04785000
<< Make sure we're at CDT >>                                   <<*7724>>04790000
CDT'ABS'ON'TOS;                                                <<*7724>>04795000
EXCHDB;                                                        <<*7724>>04800000
SAVE'DB := tos;                                                <<*7724>>04805000
                                                               <<*7724>>04810000
MAPD'OFFSET := CDT'ENTRY * CDT'ENTRY'SIZE;                     <<*7724>>04815000
LDEV'OFFSET := LDEV'ENTRY * CDT'ENTRY'SIZE;                    <<*7724>>04820000
  << Release disc request >>                                            04825000
$if x1=on                                                      <<*7724>>04830000
TOS:=CDT'SET'WORD(CDT'ENTRY,CDT'MD'DISCREQ,0);                 <<06856>>04835000
$if x1=off                                                     <<*7724>>04840000
tos := CDT'ARRAY(MAPD'OFFSET+CDT'MD'DISCREQ);                  <<*7724>>04845000
CDT'ARRAY(CDT'X) := 0;                                         <<*7724>>04850000
$if                                                            <<*7724>>04855000
<< Go to SYSDB >>                                              <<*7724>>04860000
tos := %1000 D;                                                <<*7724>>04865000
EXCHDB;                                                        <<*7724>>04870000
ASMB(ddel);                                                    <<*7724>>04875000
RETURNDISCREQ(*);                                                       04880000
<< Go back to CDT >>                                           <<*7724>>04885000
CDT'ABS'ON'TOS;                                                <<*7724>>04890000
EXCHDB;                                                        <<*7724>>04895000
ASMB(ddel);                                                    <<*7724>>04900000
                                                                        04905000
<<DISABLE;>> <<protect list structure>>                        <<06858>>04910000
                                                                        04915000
<< Now, delink the request >>                                           04920000
PRIOR'PTR := CDT'ARRAY(MAPD'OFFSET+CDT'MD'PREV);               <<*7724>>04925000
NEXT'PTR := CDT'ARRAY(MAPD'OFFSET+CDT'MD'NEXT);                <<*7724>>04930000
                                                                        04935000
<< If next pointer is zero, this is tail on list >>                     04940000
if NEXT'PTR = 0 then                                                    04945000
  begin  << Make prior ptr the new tail pointer >>                      04950000
  CDT'ARRAY(LDEV'OFFSET+CDT'DE'MAPD'TAIL):=PRIOR'PTR;          <<*7724>>04955000
  end                                                                   04960000
else                                                                    04965000
  begin  << Link next mapped CDT onto this one's prior CDT >>           04970000
  CDT'ARRAY((NEXT'PTR*CDT'ENTRY'SIZE)+CDT'MD'PREV):=PRIOR'PTR; <<*7724>>04975000
  end;                                                                  04980000
                                                                        04985000
<< If prior pointer is zero, this is first one on list >>               04990000
if PRIOR'PTR = 0 then                                                   04995000
  begin  << This is the first one >>                                    05000000
  CDT'ARRAY(LDEV'OFFSET+CDT'DE'MAPD'HEAD):=NEXT'PTR;           <<*7724>>05005000
  end                                                                   05010000
else                                                                    05015000
  begin << Make prior point to NEXT >>                                  05020000
  CDT'ARRAY((PRIOR'PTR*CDT'ENTRY'SIZE)+CDT'MD'NEXT):=NEXT'PTR; <<*7724>>05025000
  end;                                                                  05030000
                                                                        05035000
<< Decrement count of mapped domains >>                                 05040000
CDT'X := LDEV'OFFSET + CDT'DE'MAPD'CNT;                        <<*7724>>05045000
CDT'ARRAY(CDT'X) := CDT'ARRAY(CDT'X) - 1;                      <<*7724>>05050000
                                                                        05055000
<< Tell KERNEL to unmap this region >>                                  05060000
<< Go to SYSDB >>                                              <<*7724>>05065000
tos := %1000 D;                                                <<*7724>>05070000
EXCHDB;                                                        <<*7724>>05075000
CDT'UNMAP'REGION(LDEV'ENTRY,CDT'ENTRY);                                 05080000
                                                                        05085000
<< Release mapped CDT entry >>                                          05090000
CDT'FREE'ENTRY(CDT'ENTRY);                                              05095000
                                                                        05100000
<< Go to caller's DB >>                                        <<*7724>>05105000
tos := SAVE'DB;                                                <<*7724>>05110000
EXCHDB;                                                        <<*7724>>05115000
                                                               <<*7724>>05120000
end;  << of procedure CDT'REL'MD'ENTRY >>                               05125000
$page "CDT'QUEUE'LDR"                                                   05130000
procedure CDT'QUEUE'LDR(CDT'ENTRY,LDR'INDEX,QUEUE);                     05135000
value CDT'ENTRY,LDR'INDEX,QUEUE;                                        05140000
integer CDT'ENTRY,LDR'INDEX,QUEUE;                                      05145000
option privileged,uncallable;                                           05150000
begin                                                                   05155000
                                                                        05160000
<<********************************************************************>>05165000
<< This procedure takes the logical disc request pointed to by        >>05170000
<< LDR'INDEX and queues it to the end of the list pointed to by QUEUE >>05175000
<< on the specified CDT entry.                                        >>05180000
<<                                                                    >>05185000
<< The passed parameters are:                                         >>05190000
<<                                                                    >>05195000
<< CDT'ENTRY     - The entry number in the CDT table to queue this LDR>>05200000
<<                 onto.                                              >>05205000
<< LDR'INDEX     - The index of the logical disc request to queue onto>>05210000
<<                 the CDT entry.                                     >>05215000
<< QUEUE         - An offset (queue pointer) to the queue to place the>>05220000
<<                 request onto in the CDT entry.                     >>05225000
<<********************************************************************>>05230000
                                                                        05235000
logical LDR'ENTRY'INDEX;  << To satisfy INCLLDR req. >>                 05240000
integer LINK'PTR;                                                       05245000
                                                               <<*7724>>05250000
<< Variables for quick CDT access >>                           <<*7724>>05255000
double SAVE'DB;                                                <<*7724>>05260000
                                                               <<*7724>>05265000
integer MAPD'OFFSET;                                           <<*7724>>05270000
                                                                        05275000
                                                               <<*7724>>05280000
                                                               <<*7724>>05285000
                                                               <<*7724>>05290000
                                                               <<*7724>>05295000
$if x1=on                                                               05300000
MMSTAT'(MMSTAT'QUEUE'LDR,CDT'ENTRY,LDR'INDEX,QUEUE,0,0,0);     <<06859>>05305000
$if                                                                     05310000
                                                                        05315000
<< Put DB at CDT >>                                            <<*7724>>05320000
CDT'ABS'ON'TOS;                                                <<*7724>>05325000
EXCHDB;                                                        <<*7724>>05330000
SAVE'DB := tos;                                                <<*7724>>05335000
                                                               <<*7724>>05340000
MAPD'OFFSET := CDT'ENTRY * CDT'ENTRY'SIZE;                     <<*7724>>05345000
                                                               <<*7724>>05350000
<< Load current logical disc request pointer >>                         05355000
LDR'ENTRY'INDEX := LDR'INDEX;                                           05360000
                                                                        05365000
DISABLE;      << To protect link pointers >>                   <<07309>>05370000
<< If queue is empty, place it on the head >>                           05375000
$if x1=on                                                      <<*7724>>05380000
tos := LINK'PTR := CDT'GET'WORD(CDT'ENTRY,QUEUE,0);            <<*7724>>05385000
$if x1=off                                                     <<*7724>>05390000
tos := LINK'PTR := CDT'ARRAY(MAPD'OFFSET+QUEUE);               <<*7724>>05395000
$if                                                            <<*7724>>05400000
if tos <<LINK'PTR>> = 0 then                                   <<*7724>>05405000
  begin  << This is first on the list >>                                05410000
  CDT'ARRAY(MAPD'OFFSET+QUEUE) := LDR'INDEX;                   <<*7724>>05415000
  LDR'PREVQ := LDR'NEXTQ := 0;                                          05420000
  end                                                                   05425000
else                                                                    05430000
  begin   << We must go down the list until a tail is found >>          05435000
  while LINK'PTR <> 0 do                                                05440000
    begin                                                               05445000
    LDR'ENTRY'INDEX := LINK'PTR;                                        05450000
    LINK'PTR := LDR'NEXTQ;                                              05455000
    end;                                                                05460000
                                                                        05465000
  << At this point, we are at the end of the chain >>                   05470000
  << Load new request's pointer into last logical request's next ptr >> 05475000
  LDR'NEXTQ := LDR'INDEX;                                               05480000
                                                                        05485000
  << Save former tail LDR's index >>                                    05490000
  LINK'PTR := LDR'ENTRY'INDEX;                                          05495000
                                                                        05500000
  << Move pointer to new tail and fix its queue pointers >>             05505000
  LDR'ENTRY'INDEX := LDR'INDEX;                                         05510000
  LDR'PREVQ := LINK'PTR;                                                05515000
  LDR'NEXTQ := 0;                                                       05520000
  end;                                                                  05525000
                                                                        05530000
<< If placing LDR on active list, turn on QUEUED bit >>                 05535000
if QUEUE = CDT'MD'LDR'HEAD then                                         05540000
  begin                                                                 05545000
  LDR'CDTQUED := 1;                                                     05550000
  end;                                                                  05555000
                                                                        05560000
tos := SAVE'DB;                                                <<*7724>>05565000
EXCHDB;                                                        <<*7724>>05570000
end;  << of procedure CDT'QUEUE'REQUEST >>                              05575000
$page "CDT'DEQUEUE'LDR"                                                 05580000
procedure CDT'DEQUEUE'LDR(CDT'ENTRY,LDR'INDEX,QUEUE);                   05585000
value CDT'ENTRY,LDR'INDEX,QUEUE;                                        05590000
integer CDT'ENTRY,LDR'INDEX,QUEUE;                                      05595000
option privileged,uncallable;                                           05600000
begin                                                                   05605000
                                                                        05610000
<<********************************************************************>>05615000
<< This procedure takes the logical disc request pointed to by        >>05620000
<< LDR'INDEX and dequeues it from the list pointed to by QUEUE        >>05625000
<< on the specified CDT entry.                                        >>05630000
<<                                                                    >>05635000
<< The passed parameters are:                                         >>05640000
<<                                                                    >>05645000
<< CDT'ENTRY     - The entry number in the CDT table to dequeue this  >>05650000
<<                 LDR from.                                          >>05655000
<< LDR'INDEX     - The index of the logical disc request to dequeue   >>05660000
<<                 from the CDT entry.                                >>05665000
<< QUEUE         - An offset (queue pointer) to the queue to remove   >>05670000
<<                 the request from on the CDT entry.                 >>05675000
<<********************************************************************>>05680000
                                                                        05685000
logical LDR'ENTRY'INDEX,  << To satisfy INCLLDR req. >>                 05690000
        NOT'FND'FLAG;     << Loop control flag >>                       05695000
                                                                        05700000
<< Variables for fast CDT access >>                            <<*7724>>05705000
double SAVE'DB;                                                <<*7724>>05710000
                                                               <<*7724>>05715000
integer MAPD'OFFSET;                                           <<*7724>>05720000
                                                               <<*7724>>05725000
integer LINK'PTR,PRIOR'PTR,NEXT'PTR;                                    05730000
                                                                        05735000
                                                               <<*7724>>05740000
                                                               <<*7724>>05745000
                                                               <<*7724>>05750000
                                                               <<*7724>>05755000
$if x1=on                                                               05760000
MMSTAT'(MMSTAT'DEQUEUE'LDR,CDT'ENTRY,LDR'INDEX,QUEUE,0,0,0);   <<06859>>05765000
$if                                                                     05770000
                                                                        05775000
<< Put DB at CDT >>                                            <<*7724>>05780000
CDT'ABS'ON'TOS;                                                <<*7724>>05785000
EXCHDB;                                                        <<*7724>>05790000
SAVE'DB := tos;                                                <<*7724>>05795000
MAPD'OFFSET := CDT'ENTRY * CDT'ENTRY'SIZE;                     <<*7724>>05800000
                                                               <<*7724>>05805000
<< Load current logical disc request pointer >>                         05810000
LDR'ENTRY'INDEX := LDR'INDEX;                                           05815000
                                                                        05820000
DISABLE;       << To protect linkage structure >>              <<07309>>05825000
                                                                        05830000
<< If queue is empty, BAD NEWS! >>                                      05835000
$if x1=on                                                      <<*7724>>05840000
LINK'PTR := CDT'GET'WORD(CDT'ENTRY,QUEUE,0);                            05845000
$if x1=off                                                     <<*7724>>05850000
LINK'PTR := CDT'ARRAY(MAPD'OFFSET+QUEUE);                      <<*7724>>05855000
$if                                                            <<*7724>>05860000
if LINK'PTR = 0 then                                                    05865000
  SUDDENDEATH(CDT'BAD'LDR'INDEX)                                        05870000
else                                                                    05875000
  begin   << We must go down the list until a tail is found >>          05880000
  << If link pointer is first on the list, take care of it here >>      05885000
  if LINK'PTR = LDR'INDEX then                                          05890000
    begin  << Yes, it is >>                                             05895000
    << Get new list head >>                                             05900000
    LDR'ENTRY'INDEX := LDR'NEXTQ;                                       05905000
    IF <> THEN LDR'PREVQ := 0;                                 <<07311>>05910000
    CDT'SET'WORD(CDT'ENTRY,QUEUE,LDR'ENTRY'INDEX);                      05915000
    CDT'ARRAY(MAPD'OFFSET+QUEUE) := LDR'ENTRY'INDEX;           <<*7724>>05920000
    end                                                                 05925000
  else                                                                  05930000
    begin  << We must search down the list >>                           05935000
    NOT'FND'FLAG := true;                                               05940000
    while NOT'FND'FLAG do                                               05945000
      begin                                                             05950000
      LDR'ENTRY'INDEX := LINK'PTR;                                      05955000
      LINK'PTR := LDR'NEXTQ;                                            05960000
      if = then  << We didn't find it >>                                05965000
        SUDDENDEATH(CDT'BAD'LDR'INDEX);                                 05970000
      if LINK'PTR = LDR'INDEX then                                      05975000
        begin  << We found it >>                                        05980000
        NOT'FND'FLAG := false;                                          05985000
        PRIOR'PTR := LDR'ENTRY'INDEX;                                   05990000
        LDR'ENTRY'INDEX := LINK'PTR;  << Point to req we're deleting >> 05995000
        NEXT'PTR := LDR'NEXTQ;                                          06000000
        if NEXT'PTR <> 0 then                                           06005000
          begin  << There is a LDR following this one >>                06010000
          LDR'ENTRY'INDEX := NEXT'PTR;                                  06015000
          LDR'PREVQ := PRIOR'PTR;  << Point to the new prior LDR >>     06020000
          end;                                                          06025000
        << Set pointer back to prior LDR >>                             06030000
        LDR'ENTRY'INDEX := PRIOR'PTR;                                   06035000
        << Fix next pointer >>                                          06040000
        LDR'NEXTQ := NEXT'PTR;                                          06045000
        end; << of processing HIT >>                                    06050000
      end;  <<of processing WHILE loop >>                               06055000
    end; << of searching list >>                                        06060000
  end;  << of processing non-zero list >>                               06065000
                                                                        06070000
<< If the LDR was on the active list, turn off QUEUED bit >>            06075000
if QUEUE = CDT'MD'LDR'HEAD then                                         06080000
  begin                                                                 06085000
  LDR'ENTRY'INDEX := LDR'INDEX;                                         06090000
  LDR'CDTQUED := 0;                                                     06095000
  end;                                                                  06100000
                                                                        06105000
<< Put DB back to caller's DB >>                               <<*7724>>06110000
tos := SAVE'DB;                                                <<*7724>>06115000
EXCHDB;                                                        <<*7724>>06120000
                                                               <<*7724>>06125000
end;  << of procedure CDT'DEQUEUE'LDR >>                                06130000
$page "CDT'FIND'DE"                                                     06135000
integer procedure CDT'FIND'DE(LDEV);                                    06140000
value LDEV;                                                             06145000
integer LDEV;                                                           06150000
option privileged,uncallable;                                           06155000
begin                                                                   06160000
                                                                        06165000
<<********************************************************************>>06170000
<< This procedure scans the list of cached LDEVs and returns the entry>>06175000
<< of the CDT entry for this LDEV.  The passed parameter is:          >>06180000
<<                                                                    >>06185000
<< LDEV    - This is the logical device number to find the corres-    >>06190000
<<           ponding CDT disc entry for.                              >>06195000
<<                                                                    >>06200000
<< Returned parameter-                                                >>06205000
<<                                                                    >>06210000
<< CDT'FIND'LDEV - This is the CDT disc entry number of the LDEV.     >>06215000
<<                 Zero is returned if the LDEV is not cached. <<06858>>06220000
<<********************************************************************>>06225000
                                                                        06230000
integer LDEV'LINK'PTR = CDT'FIND'DE,   << Re-define return parameter  >>06235000
        DE'LDEV,                       << LDEV from CDT disc entry    >>06240000
        CDT'LINK'PTR;                  << Pointer link work variable  >>06245000
<< Variable for fast CDT access >>                             <<*7724>>06250000
integer LDEV'OFFSET;                                           <<*7724>>06255000
                                                                        06260000
                                                               <<*7724>>06265000
                                                               <<*7724>>06270000
                                                               <<*7724>>06275000
if CACHE'DST = 0 then  << Caching has been disabled >>         <<06858>>06280000
  CDT'FIND'DE := 0                                             <<06858>>06285000
else                                                           <<06858>>06290000
  begin                                                        <<06858>>06295000
  << Put DB to CDT >>                                          <<*7724>>06300000
  CDT'ABS'ON'TOS;                                              <<*7724>>06305000
  EXCHDB;                                                      <<*7724>>06310000
                                                               <<*7724>>06315000
  << Find LDEV CDT entry >>                                    <<06858>>06320000
  LDEV'LINK'PTR := 0;                                          <<06858>>06325000
  CDT'LINK'PTR := CDT'ARRAY(CDT'DISC'HEAD);                    <<*7724>>06330000
                                                                        06335000
  while CDT'LINK'PTR <> 0 do                                   <<06858>>06340000
    begin  << Look for LDEV >>                                 <<06858>>06345000
    LDEV'OFFSET := CDT'LINK'PTR * CDT'ENTRY'SIZE;              <<*7724>>06350000
    DE'LDEV := CDT'ARRAY(LDEV'OFFSET+CDT'DE'LDEV);             <<*7724>>06355000
    if LDEV = DE'LDEV then                                     <<06858>>06360000
      begin  << Found the LDEV >>                              <<06858>>06365000
      LDEV'LINK'PTR := CDT'LINK'PTR;                           <<06858>>06370000
      CDT'LINK'PTR := 0;  << To terminate search >>            <<06858>>06375000
      end                                                      <<06858>>06380000
    else                                                       <<06858>>06385000
      CDT'LINK'PTR:=CDT'ARRAY(LDEV'OFFSET+CDT'DE'NEXT'LDEV);   <<*7724>>06390000
    end;                                                       <<06858>>06395000
                                                               <<*7724>>06400000
  << Put DB back to caller's DB >>                             <<*7724>>06405000
  EXCHDB;                                                      <<*7724>>06410000
  ASMB(ddel);                                                  <<*7724>>06415000
  end;                                                         <<06858>>06420000
                                                                        06425000
$if x1=on                                                               06430000
MMSTAT'(MMSTAT'FIND'DE,LDEV,LDEV'LINK'PTR,0,0,0,0);            <<06859>>06435000
                                                               <<06858>>06440000
                                                               <<06858>>06445000
                                                               <<06858>>06450000
$if                                                                     06455000
                                                                        06460000
end;  << of procedure CDT'FIND'DE >>                                    06465000
$page "CDT'FORCE'LDR'COMPLETION"                                        06470000
procedure CDT'FORCE'LDR'COMPLETION(LDR'INDEX);                          06475000
value LDR'INDEX;                                                        06480000
integer LDR'INDEX;                                                      06485000
option privileged,uncallable;                                           06490000
begin                                                                   06495000
                                                                        06500000
<<***********************************************************>><<06858>>06505000
<< This procedure forces any pending I/O requests which are  >>         06510000
<< preventing the completion of the current I/O request, to  >>         06515000
<< be completed.  It is called from locking routines and from>>         06520000
<< WAITFORIO.  The passed parameter is:                      >>         06525000
<<                                                           >>         06530000
<< LDR'INDEX  - Disc request table relative offset to the    >>         06535000
<<              logical disc request.                        >>         06540000
<<                                                           >>         06545000
<< The caller is assumed to be DISABLED prior to calling.    >><<06858>>06550000
<< The caller must be able to withstand being "blocked".  No >>         06555000
<< assumption is made as to the location of DB.              >>         06560000
<<***********************************************************>>         06565000
                                                                        06570000
integer CDT'ENTRY,        << CDT entry associated w/LDR      >>         06575000
        CALLERS'PIN,      << PIN of WAITFORIOX caller        >>         06580000
        MY'PIN,           << Caller's PIN number             >><<06858>>06585000
        WORK'LDR,         << Current LDR trying to complete  >>         06590000
        LDR'INX,          << Logical disc req index          >><<07311>>06595000
        SAVE'DB,          << For call to SETSYSDB            >>         06600000
        DST,              << DST of LDR trying to complete   >>         06605000
                                                               <<06858>>06610000
        LDEV'ENTRY;       << LDEV CDT entry for this LDR     >>         06615000
<< this is a new measurement interface global counter. >>      <<*8735>>06620000
<< it SHOULD be added to the measurement interface include  >> <<*8735>>06625000
<< file as soon as possible.  >>                               <<*8735>>06630000
EQUATE  C'IMPEDECACHE = 74 ;                                   <<*8735>>06635000
                                                               <<*8735>>06640000
                                                                        06645000
double WORK'CDT;          << CDT entry trying to complete    >><<06855>>06650000
logical array WRK'CDT(*)=WORK'CDT;                             <<06855>>06655000
logical LDR'ENTRY'INDEX,  << To satisfy LDR equates/defines  >>         06660000
        SAVE'LDR,         << Save old LDR'ENTRY'INDEX        >><<06858>>06665000
        INHIBIT'PINSWITCH,<< Don't switch PINS in LDR        >><<06858>>06670000
        DONE'FLAG;        << Loop control flag               >>         06675000
                                                               <<06858>>06680000
entry CDT'FORCE'CDT'COMPLETION;                                <<06858>>06685000
$page                                                                   06690000
subroutine IMPEDE'ME(IMPEDE'CDT);                                       06695000
value IMPEDE'CDT;                                                       06700000
integer IMPEDE'CDT;                                                     06705000
begin                                                                   06710000
                                                                        06715000
<< This subroutine is used whenever a write of a cached >>              06720000
<< domain is in-progress, the region is in memory, and  >>              06725000
<< the LDR must wait for the write to finish.           >>              06730000
                                                                        06735000
MY'PIN := CURPRC / PCBSIZE;                                    <<06858>>06740000
                                                               <<06858>>06745000
<< Get in PCB list for this CDT >>                                      06750000
CALLERS'PIN:=CDT'GET'WORD(IMPEDE'CDT,CDT'MD'IMPEDED,0);                 06755000
if CALLERS'PIN = 0 then                                                 06760000
  CDT'SET'WORD(IMPEDE'CDT,CDT'MD'IMPEDED,MY'PIN);              <<06858>>06765000
                                                               <<06858>>06770000
STRINGPINATTAIL(CALLERS'PIN,0);                                         06775000
                                                               <<06858>>06780000
SAVE'LDR := LDR'ENTRY'INDEX;                                   <<06858>>06785000
LDR'ENTRY'INDEX := CDT'GET'WORD(IMPEDE'CDT,                    <<06858>>06790000
                   CDT'MD'DISCREQ,0);                          <<06858>>06795000
                                                               <<06858>>06800000
<< Adjust write priority if request is NOT completed >>        <<06858>>06805000
if not LDR'DONE then                                           <<06858>>06810000
                                                               <<06858>>06815000
  BUMPWRITEPRI(LDR'ENTRY'INDEX,PROCESSPRI(MY'PIN));            <<06858>>06820000
                                                               <<06858>>06825000
LDR'ENTRY'INDEX := SAVE'LDR;                                   <<06858>>06830000
<< Impede, waiting for WRITE to complete >>                             06835000
<< Count impedes due to disc caching.  This is a double count>><<*8735>>06840000
<< since it is also counted in procedure impede.             >><<*8735>>06845000
                                                               <<*8735>>06850000
if CLASS0STATSENABLED then                                     <<*8735>>06855000
  if FUPDATESTATISTICS(MEASCLASS0,MEASSUBCLASS0,MEASENTRY1,    <<*8735>>06860000
           C'IMPEDECACHE,NOTNEWVALUE,1D,NOTDOUBLE)             <<*8735>>06865000
   <> 0 then SUDDENDEATH(SFKernCacheIntBad) ;                  <<*8735>>06870000
                                                               <<*8735>>06875000
<< there is no room for additional process level counters. >>  <<*8735>>06880000
<< this uses the old counter cp'segcontract to count impedes >><<*8735>>06885000
<< due to caching.  the old counters for cp'segcontract have >><<*8735>>06890000
<< been removed from KERNELD.  this counter should be renamed>><<*8735>>06895000
<< CP'IMPEDECACHE in the measurement include file ASAP!!!!!!!>><<*8735>>06900000
if GCLASSENABLEDMASK.CLASS15 then                              <<*8735>>06905000
   begin                                                       <<*8735>>06910000
   TOS:=MEASPROCXDSBANK;                                       <<*8735>>06915000
   TOS:=MEASPROCXDSBASE;                                       <<*8735>>06920000
   TOS:=TOS + CURPRC / PCBSIZE * CLASS15'SUB0SIZE +            <<*8735>>06925000
        CP'SEGCONTRACT ;                                       <<*8735>>06930000
   ASMB(LSEA);                                                 <<*8735>>06935000
   TOS:=TOS+1;                                                 <<*8735>>06940000
   ASMB(SSEA;DDEL);                                            <<*8735>>06945000
   end;                                                        <<*8735>>06950000
IMPEDE(0);                                                              06955000
                                                                        06960000
<< CDT'COMPLETOR checks this list & removes any waitors >>              06965000
end;                                                                    06970000
                                                                        06975000
$page                                                                   06980000
subroutine MAKE'SEGS'PRESENT(LD'REQ);                                   06985000
value LD'REQ;                                                           06990000
integer LD'REQ;                                                         06995000
begin                                                                   07000000
                                                                        07005000
<< Attempt to make this LDR's CDT and DST present >>                    07010000
LDR'ENTRY'INDEX := LD'REQ;  << New index >>                             07015000
DST := LDR'BUF'DSTN;                                           <<07311>>07020000
WORK'CDT := BUILDOBJID(MAPPEDDOMAINOBJECT,LDR'CDT,0);                   07025000
                                                                        07030000
<< Loop until CACHE MOVE is done >>                                     07035000
DONE'FLAG := false;                                                     07040000
while (LDR'MOVE'DONE=0) and (not DONE'FLAG) do                          07045000
  begin <<force in the objects to allow the cache move>>                07050000
  if ISOBJECTABSENT(DOUBLE(DST))                               <<06855>>07055000
  then QUEUEONOBJECT(DOUBLE(DST))                              <<06855>>07060000
  else if ISOBJECTABSENT(WORK'CDT) and                         <<*8003>>07065000
          not IsObjectIMI(WORK'CDT)                            <<*8003>>07070000
  then QUEUEONOBJECT(WORK'CDT)                                          07075000
  else if CDT'GET'BIT(WRK'CDT(ObjIDnumField),CDT'IMO'BIT,0)    <<06855>>07080000
  then IMPEDE'ME(WRK'CDT(ObjIDnumField))                       <<06855>>07085000
  else DONE'FLAG := true;  << Both here, so leave >>                    07090000
  end;  << Of expediting cache move completion >>                       07095000
end;                                                                    07100000
$page                                                                   07105000
subroutine SCAN'DEFERRED'QUEUE;                                         07110000
begin                                                                   07115000
                                                                        07120000
<< This procedure scans the disabled disc request queue for >>          07125000
<< a matching CDT and attempts to force its completion.     >>          07130000
                                                                        07135000
<< Load deferred disc req pointer into LDR'ENTRY'INDEX      >>          07140000
                                                               <<07311>>07145000
LDR'INX   := DQH'DISAHEAD;              << deferred head    >> <<07311>>07150000
                                                                        07155000
<< If it's zero, we have a logic problem >>                             07160000
if = then                                                               07165000
  SUDDENDEATH(CDT'LOGIC'PROBLEM);                                       07170000
                                                                        07175000
while LDR'INX <> 0 do                                          <<07311>>07180000
  begin  << Scan queue >>                                               07185000
  LDR'ENTRY'INDEX := LDR'INX;                                  <<07311>>07190000
  if INTEGER(LDR'CDT) = CDT'ENTRY then                                  07195000
    begin << This is a MATCH, so force it to complete       >>          07200000
    MAKE'SEGS'PRESENT(LDR'ENTRY'INDEX);                                 07205000
    LDR'INX   := 0;        << To terminate looping          >> <<07311>>07210000
    end                                                                 07215000
  else                                                                  07220000
    begin                                                               07225000
    LDR'INX   := LDR'NEXTQ;       << Point to next in list  >> <<07311>>07230000
                                                                        07235000
    << If the list is exhausted, we have a logic problem    >>          07240000
    if = then                                                           07245000
      SUDDENDEATH(CDT'LOGIC'PROBLEM);                                   07250000
    end;                                                                07255000
  end;                                                                  07260000
                                                                        07265000
<< Restore LDR pointer (index) >>                                       07270000
LDR'ENTRY'INDEX := LDR'INDEX;                                           07275000
                                                                        07280000
end;                                                                    07285000
$page                                                                   07290000
subroutine PROCESS'CDT'QUEUE;                                           07295000
begin                                                                   07300000
                                                                        07305000
<< If this LDR is already on the CDT's active queue, >>                 07310000
<< just let it complete naturally.                   >>                 07315000
do                                                                      07320000
  begin  << We must get things out of the way >>                        07325000
  << Get first active LDR on CDT & force completion >>                  07330000
  WORK'LDR := CDT'GET'WORD(CDT'ENTRY,CDT'MD'LDR'HEAD,0);                07335000
  if WORK'LDR <> 0 then                                                 07340000
    begin   << Force completion >>                                      07345000
    MAKE'SEGS'PRESENT(WORK'LDR);                                        07350000
    end                                                                 07355000
  else                                                                  07360000
    begin  << We must scan deferred disc request queue >>               07365000
    if CDT'GET'BIT(CDT'ENTRY,CDT'WAIT'ON'NOPOST,0) = 0 then             07370000
      SCAN'DEFERRED'QUEUE                                               07375000
    else                                                                07380000
      << Wait for segment write to complete >>                          07385000
      IMPEDE'ME(CDT'ENTRY);                                             07390000
    end;                                                                07395000
  end until (LDR'CDTQUED = 1) or (LDR'MOVE'DONE = 1);                   07400000
end;                                                                    07405000
$page                                                                   07410000
$if x7=on                                                      <<06858>>07415000
subroutine PROCESS'FLUSH'QUEUE;                                         07420000
begin                                                                   07425000
                                                                        07430000
<< Get head CDT in ldev's FLUSH queue >>                                07435000
CDT'ENTRY := CDT'GET'WORD(LDEV'ENTRY,CDT'DE'FLUSH'HD,0);       <<06858>>07440000
if CDT'ENTRY = 0 then                                                   07445000
  SUDDENDEATH(CDT'LOGIC'PROBLEM)                                        07450000
else                                                                    07455000
  PROCESS'CDT'QUEUE;                                                    07460000
                                                                        07465000
end;                                                                    07470000
$if                                                            <<06858>>07475000
$page                                                                   07480000
                                                                        07485000
INHIBIT'PINSWITCH := false;                                    <<06858>>07490000
go to START;                                                   <<06858>>07495000
                                                               <<06858>>07500000
CDT'FORCE'CDT'COMPLETION:                                      <<06858>>07505000
INHIBIT'PINSWITCH := true;                                     <<06858>>07510000
                                                               <<06858>>07515000
START:                                                         <<06858>>07520000
                                                               <<06858>>07525000
<< We should be DISABLE'd prior to calling this routine >>              07530000
                                                                        07535000
LDR'ENTRY'INDEX := LDR'INDEX;                                           07540000
                                                                        07545000
<< If this process must stop for cache, count it >>            <<07308>>07550000
if not LDR'DONE then  << Not marked completed >>               <<07308>>07555000
  if not INHIBIT'PINSWITCH then << Not a FLUSH call >>         <<07308>>07560000
    begin                                                      <<*7724>>07565000
    CDT'ABS'ON'TOS;  << ABS CDT memory address >>              <<d7726>>07570000
    tos := tos + (integer(LDR'CDT) * CDT'ENTRY'SIZE) +         <<d7726>>07575000
           CDT'MD'DE;                                          <<d7726>>07580000
    ASMB(LSEA;DELB,DELB);    << Device entry index is on tos >><<d7726>>07585000
    LDEV'ENTRY := tos;                                         <<d7726>>07590000
$if x1=on                                                      <<*7724>>07595000
    CDT'ADD'DOUBLE(                                            <<07308>>07600000
      CDT'FIND'DE(LDR'LDEV),   << CDT# of LDEV entry >>        <<07308>>07605000
      CDT'DE'STOP,             << Inc STOP counter   >>        <<07308>>07610000
      1D);                                                     <<07308>>07615000
$if x1=off                                                     <<*7724>>07620000
    CDT'ABS'ON'TOS;                                            <<*7724>>07625000
    << Get LDEV offset in CDT >>                               <<*7724>>07630000
    tos := tos + (LDEV'ENTRY * CDT'ENTRY'SIZE);                <<*7724>>07635000
    tos := tos + CDT'DE'STOP; << STOP cell offset >>           <<*7724>>07640000
    << Increment STOP counter >>                               <<*7724>>07645000
    ASMB(LDEA);                                                <<*7724>>07650000
    tos := tos + 1D;                                           <<*7724>>07655000
    ASMB(SDEA;DDEL);                                           <<*7724>>07660000
$if                                                            <<*7724>>07665000
    end;                                                       <<*7724>>07670000
If (LDR'MOVE'DONE = 0) then                                             07675000
  begin  << Move not done on LDR >>                                     07680000
                                                                        07685000
  << Put DB to SYSDB for KERNEL calls >>                                07690000
  SAVE'DB := SETSYSDB;                                                  07695000
                                                                        07700000
  << If the caller's PIN is different than the PIN in >>                07705000
  << the logical disc request, we must fix-up locality>>                07710000
  CALLERS'PIN := CURPRC / PCBSIZE;                             <<06857>>07715000
  if CALLERS'PIN <> integer(LDR'PCB) and                       <<06858>>07720000
     not INHIBIT'PINSWITCH then                                <<06858>>07725000
    begin  << Adjust localities >>                                      07730000
    << Decrement initiator's prefetch count >>                          07735000
    tos := (integer(LDR'PCB)*PCBSIZE) ;                        <<06857>>07740000
    tos := WORK'CDT := BUILDOBJID(MAPPEDDOMAINOBJECT,                   07745000
                                  LDR'CDT,0);                           07750000
    tos := 0D;                                                          07755000
    tos.decprefetchcntflag := 1;                                        07760000
    ADJUSTLOCALITY(*,*,*,*);                                            07765000
                                                               <<*7724>>07770000
    << If LDR thinks its not in locality, SF >>                <<*7724>>07775000
    if not LDR'INLOC then                                      <<*7724>>07780000
      SUDDENDEATH(SFKERNCACHEINTBAD);                          <<*7724>>07785000
    LDR'PCB := CALLERS'PIN;                                    <<*7724>>07790000
                                                                        07795000
    << Now, add domain to caller's locality >>                          07800000
    tos := LPCB( CURPRC + SLLIXWORDNUM );                      <<06857>>07805000
    tos := WORK'CDT;                                                    07810000
    tos := 0;                                                           07815000
    tos.bumpprefetchcntflag := 1;                                       07820000
    ADDTOLOCALITY(*,*,*);                                               07825000
                                                                        07830000
    FLAGPROCABSENT(CALLERS'PIN,WORK'CDT,%100000);              <<*7859>>07835000
                                                               <<*7859>>07840000
    end;                                                                07845000
                                                                        07850000
  << If LDR is not on CDT's active queue, force it there>>              07855000
  if (not LDR'CDTQUED land not LDR'MOVE'DONE) or               <<*8216>>07860000
     INHIBIT'PINSWITCH then  << We must assume responsibility ><<06858>>07865000
                             << for forcing completion.  WAIT ><<06858>>07870000
                             << FORIO was NOT called.         ><<06858>>07875000
    begin                                                               07880000
    CDT'ENTRY := LDR'CDT;                                               07885000
    CDT'ABS'ON'TOS;  << ABS CDT memory address >>              <<d7726>>07890000
    tos := tos + (CDT'ENTRY * CDT'ENTRY'SIZE) + CDT'MD'DE;     <<d7726>>07895000
    ASMB(LSEA;DELB,DELB);    << Device entry index is on tos >><<d7726>>07900000
    LDEV'ENTRY := tos;                                         <<d7726>>07905000
                                                                        07910000
                                                               <<06858>>07915000
                                                               <<06858>>07920000
                                                               <<06858>>07925000
                                                               <<06858>>07930000
                                                               <<06858>>07935000
    PROCESS'CDT'QUEUE;                                         <<06858>>07940000
    end;                                                                07945000
                                                                        07950000
  RESETDB(SAVE'DB);                                                     07955000
                                                                        07960000
  end;                                                                  07965000
                                                                        07970000
end;  << of procedure CDT'FORCE'LDR'COMPLETION >>                       07975000
$page "CDT'LOCK'RANGE"                                                  07980000
<< Since LOCK code is extremely low-usage and would require >> <<06858>>07985000
<< exotic mechanisms to implement, it is currently NOT      >> <<06858>>07990000
<< implemented in disc caching.  Routines, such as FLUSH'   >> <<06858>>07995000
<< CACHE, CDT'ATTACHIO, and UNCACHE'LDEV would call this    >> <<06858>>08000000
<< mechanism.  Therefore, all code will disabled via a      >> <<06858>>08005000
<< compiler switch, S7.  The locking code in CDT'INITIATOR  >> <<06858>>08010000
<< will not be conditioned, and is an exception.            >> <<06858>>08015000
$if x7=on                                                      <<06858>>08020000
integer procedure CDT'LOCK'RANGE(LDEV'ENTRY,LDR'ADR,UPPER'LDR'ADR);     08025000
value LDEV'ENTRY,LDR'ADR,UPPER'LDR'ADR;                                 08030000
integer LDEV'ENTRY;                                                     08035000
double LDR'ADR,UPPER'LDR'ADR;                                           08040000
option privileged,uncallable;                                           08045000
begin                                                                   08050000
                                                                        08055000
<<********************************************************************>>08060000
<< This procedure scans the mapped domains for a cached LDEV and locks>>08065000
<< all overlapping and partially overlapping domains.  These domains  >>08070000
<< are marked to be in a "FLUSH" state, and a new mapped CDT is       >>08075000
<< obtained in the "LOCKED" state, which is linked-in the mapped      >>08080000
<< domain list to intercept any subsequent overlapping requests.      >>08085000
<< The lock count is set to 1 + the number of flushing CDTs that had  >>08090000
<< to be moved onto the ldev's flush queue.  The additional lock count>>08095000
<< is to allow the caller to gain control without giving up the lock. >>08100000
<<                                                                    >>08105000
<< The passed parameters are:                                         >>08110000
<<                                                                    >>08115000
<< LDEV'ENTRY   - This is the CDT disc entry for the LDEV whose         08120000
<<                mapped domains are to be locked.                    >>08125000
<< LDR'ADR      - This is the low sector address to lock.             >>08130000
<< UPPER'LDR'ADR- This is the upper sector address of the range to    >>08135000
<<                lock.  This is actually the sector number + 1 of    >>08140000
<<                the highest sector address to lock.                 >>08145000
<<                                                                    >>08150000
<< Returned parameter -                                               >>08155000
<<                                                                    >>08160000
<< CDT'LOCK'RANGE  - The mapped CDT entry of the domain owning the    >>08165000
<<                   lock.                                            >>08170000
<<********************************************************************>>08175000
                                                                        08180000
integer HLD'BEG,         << Ptr to mapd CDT prior to lock range >>      08185000
        HLD'END,         << Ptr to mapd CDT after lock range    >>      08190000
        NEXT'PTR,        << Ptr to last mapd CDT in lock range  >>      08195000
        PRIOR'PTR,       << Ptr to 1st mapd CDT in lock range   >>      08200000
        CDT'FLGS,        << Flags word in CDT entry.            >>      08205000
        CDT'ENTRY;       << New CDT entry obtained              >>      08210000
                                                                        08215000
double CDT'ADR,          << CDT base sector address             >>      08220000
       UPPER'CDT'ADR;    << CDT limit sector address            >>      08225000
                                                                        08230000
                                                               <<06858>>08235000
DEF'SET'WORD;                                                           08240000
DEF'GET'WORD;                                                           08245000
                                                               <<06858>>08250000
                                                               <<06858>>08255000
MMSTAT'(MMSTAT'LOCK'RANGE,LDEV'ENTRY,1,0,0,0,0);               <<06859>>08260000
                                                               <<06858>>08265000
                                                                        08270000
<< Get pointer to first mapped domain >>                                08275000
PDISABLE;                                                      <<06858>>08280000
NEXT'PTR := CDT'GET'WORD(LDEV'ENTRY,CDT'DE'MAPD'HEAD,0);                08285000
CDT'ENTRY := 0;   << Initialize in case no "hit" >>                     08290000
if NEXT'PTR = 0 then                                                    08295000
  begin  << There are no current mapped domains for this LDEV >>        08300000
  end                                                                   08305000
else                                                                    08310000
  begin  << Find the first overlapping domain >>                        08315000
  while NEXT'PTR <> 0 do                                                08320000
    begin                                                               08325000
    if CDT'GET'DOUBLE(NEXT'PTR,CDT'MD'END'SECTOR,0D) >                  08330000
       LDR'ADR then  << Possible overlap >>                             08335000
      begin                                                             08340000
      if CDT'GET'DOUBLE(NEXT'PTR,CDT'MD'SECTOR,0D) <                    08345000
         UPPER'LDR'ADR then << Definite overlap >>                      08350000
        begin                                                           08355000
        CDT'ENTRY := NEXT'PTR;  << Save CDT index >>                    08360000
        end                                                             08365000
      else                                                              08370000
        begin  << CDT is beyond requested lock range >>                 08375000
        end;                                                            08380000
      NEXT'PTR := 0;                                                    08385000
      end                                                               08390000
    else                                                                08395000
      begin  << We must step to next mapped CDT >>                      08400000
      NEXT'PTR := CDT'GET'WORD(NEXT'PTR,CDT'MD'NEXT,0);                 08405000
      end;                                                              08410000
    end;  << of WHILE looking for first domain in range >>              08415000
  end;  << of looking through mapped CDTs >>                            08420000
                                                                        08425000
<< Delink overlapping mapped domain strings >>                          08430000
<< The current CDT entry being pointed to is where we start >>          08435000
NEXT'PTR := PRIOR'PTR := CDT'ENTRY;                                     08440000
                                                                        08445000
<< Now, find the last overlapping mapped domain >>                      08450000
while CDT'ENTRY <> 0 do                                                 08455000
  begin                                                                 08460000
  << Save current CDT pointer >>                                        08465000
  NEXT'PTR := CDT'ENTRY;                                                08470000
  << Load next pointer >>                                               08475000
  CDT'ENTRY := CDT'GET'WORD(CDT'ENTRY,CDT'MD'NEXT,0);                   08480000
  if CDT'ENTRY = 0 then                                                 08485000
    begin  << This is the end of the scan >>                            08490000
    end  << The next pointer is set >>                                  08495000
  else                                                                  08500000
    begin  << See if this entry partially maps too >>                   08505000
    if CDT'GET'DOUBLE(CDT'ENTRY,CDT'MD'SECTOR,0D) <                     08510000
       UPPER'LDR'ADR  then                                              08515000
      begin  << Continue looping, still overlaps >>                     08520000
      end                                                               08525000
    else                                                                08530000
      begin  << No more overlap, so terminate loop >>                   08535000
      CDT'ENTRY := 0;                                                   08540000
      end;                                                              08545000
    end;                                                                08550000
  end;  << of WHILE looking for partially mapped CDT's >>               08555000
                                                                        08560000
<< Only perform the following if overlapping areas found >>             08565000
if PRIOR'PTR <> 0 then                                                  08570000
  begin                                                                 08575000
                                                                        08580000
  << Now, delink partially mapped domain(s) >>                          08585000
  << Hold pointer to MD prior to string being delinked >>               08590000
  HLD'BEG := CDT'GET'WORD(PRIOR'PTR,CDT'MD'PREV,0);                     08595000
  << Hold pointer to MD after string being delinked >>                  08600000
  HLD'END := CDT'GET'WORD(NEXT'PTR,CDT'MD'NEXT,0);                      08605000
                                                                        08610000
  << Link the MD, minus the string, together >>                         08615000
  if HLD'BEG = 0 then                                                   08620000
    begin  << The end will be the new head pointer >>                   08625000
    CDT'SET'WORD(LDEV'ENTRY,CDT'DE'MAPD'HEAD,HLD'END);                  08630000
    if HLD'END <> 0 then                                                08635000
      CDT'SET'WORD(HLD'END,CDT'MD'PREV,0);                              08640000
    end                                                                 08645000
  else                                                                  08650000
    begin  << There is a prior mapped domain >>                         08655000
    CDT'SET'WORD(HLD'BEG,CDT'MD'NEXT,HLD'END);                          08660000
    if HLD'END <> 0 then                                                08665000
      CDT'SET'WORD(HLD'END,CDT'MD'PREV,HLD'BEG);                        08670000
    end;                                                                08675000
                                                                        08680000
  if HLD'END = 0 then                                                   08685000
    begin  << There is a new tail entry >>                              08690000
    CDT'SET'WORD(LDEV'ENTRY,CDT'DE'MAPD'TAIL,HLD'BEG);                  08695000
    end                                                                 08700000
  else                                                                  08705000
    begin  << There is a "next" mapped domain >>                        08710000
    CDT'SET'WORD(HLD'END,CDT'MD'PREV,HLD'BEG);                          08715000
    end;                                                                08720000
  end;  << of processing string >>                                      08725000
                                                                        08730000
<< Now, get a new CDT entry to link-in >>                               08735000
<< Get lowest disc request address for cache >>                         08740000
CDT'ADR := if PRIOR'PTR = 0 then                                        08745000
             LDR'ADR                                                    08750000
           else                                                         08755000
             CDT'GET'DOUBLE(PRIOR'PTR,CDT'MD'SECTOR,0D);                08760000
<< Get highest disc request address for cache >>                        08765000
UPPER'CDT'ADR := if NEXT'PTR = 0 then                                   08770000
                   UPPER'LDR'ADR                                        08775000
                 else                                                   08780000
                   CDT'GET'DOUBLE(NEXT'PTR,CDT'MD'END'SECTOR,0D);       08785000
                                                                        08790000
<< Now we will get a CDT to cover the locked range >>                   08795000
CDT'ENTRY := CDT'GET'MD'ENTRY(LDEV'ENTRY,CDT'ADR,-2);                   08800000
                                                                        08805000
<< Initialize its fields >>                                             08810000
                                                                        08815000
                                                                        08820000
CDT'FLGS := CDT'GET'WORD(CDT'ENTRY,CDT'MD'FLAGS,0);                     08825000
CDT'FLGS.CDT'MD'STATE := CDT'LOCK'STATE;                                08830000
CDT'SET'WORD(CDT'ENTRY,CDT'MD'FLAGS,CDT'FLGS);                          08835000
                                                                        08840000
                                                                        08845000
CDT'SET'WORD(CDT'ENTRY,CDT'MD'LK'CNT,1); << Set lock = 1 >>             08850000
CDT'SET'DOUBLE(CDT'ENTRY,CDT'MD'SECTOR,CDT'ADR);                        08855000
CDT'SET'DOUBLE(CDT'ENTRY,CDT'MD'END'SECTOR,UPPER'CDT'ADR);              08860000
                                                                        08865000
<< If there is a string to "flush", we must now deal with it >>         08870000
if NEXT'PTR <> 0 then                                                   08875000
  begin  << We have to put these mapped CDT's on the "flush" string >>  08880000
                                                                        08885000
  << Force terminator in last mapped CDT >>                             08890000
  CDT'SET'WORD(NEXT'PTR,CDT'MD'NEXT,0);                                 08895000
                                                                        08900000
  << Mark all CDTs in this string "flushing" >>                         08905000
  HLD'BEG := PRIOR'PTR;                                                 08910000
  while HLD'BEG <> 0 do                                                 08915000
    begin                                                               08920000
                                                                        08925000
                                                                        08930000
                                                                        08935000
    CDT'FLGS := CDT'GET'WORD(HLD'BEG,CDT'MD'FLAGS,0);                   08940000
    CDT'FLGS.CDT'MD'STATE := CDT'FLUSH'STATE;                           08945000
    CDT'SET'WORD(HLD'BEG,CDT'MD'FLAGS,CDT'FLGS);                        08950000
                                                                        08955000
                                                                        08960000
    CDT'SET'WORD(HLD'BEG,CDT'MD'LKD'CDT,CDT'ENTRY);                     08965000
    CDT'ADD'WORD(CDT'ENTRY,CDT'MD'LK'CNT,1);                            08970000
                                                                        08975000
    << Get pointer to next CDT >>                                       08980000
    HLD'BEG := CDT'GET'WORD(HLD'BEG,CDT'MD'NEXT,0);                     08985000
    end;                                                                08990000
                                                                        08995000
  << Append string onto device's FLUSH list >>                          09000000
<<HLD'BEG := CDT'GET'WORD(LDEV'ENTRY,CDT'DE'FLUSH'HD,0);>>              09005000
  if HLD'BEG = 0 then                                                   09010000
    begin  << The flush list is currently empty >>                      09015000
  <<CDT'SET'WORD(LDEV'ENTRY,CDT'DE'FLUSH'HD,PRIOR'PTR);>>               09020000
                                                                        09025000
    CDT'SET'WORD(PRIOR'PTR,CDT'MD'PREV,0);                              09030000
    end                                                                 09035000
  else                                                                  09040000
    begin  << Append string on tail >>                                  09045000
    << Get OLD tail pointer >>                                          09050000
    while HLD'BEG <> 0 do                                               09055000
      begin                                                             09060000
      HLD'END := HLD'BEG;                                               09065000
      HLD'BEG := CDT'GET'WORD(HLD'END,CDT'MD'NEXT,0);                   09070000
      end;                                                              09075000
    << Link old end to new string >>                                    09080000
    CDT'SET'WORD(HLD'END,CDT'MD'NEXT,PRIOR'PTR);                        09085000
    CDT'SET'WORD(PRIOR'PTR,CDT'MD'PREV,HLD'END);                        09090000
    end;                                                                09095000
                                                                        09100000
                                                                        09105000
  end;  << of linking string to FLUSH list >>                           09110000
                                                                        09115000
PENABLE;                                                       <<06858>>09120000
end;  << of procedure CDT'LOCK'RANGE >>                                 09125000
$if                                                            <<06858>>09130000
$page "Procedure CDT'STRATEGY"                                          09135000
procedure CDT'STRATEGY(CDT'ENTRY,DISCREQ);                              09140000
value CDT'ENTRY,DISCREQ;                                                09145000
integer CDT'ENTRY,DISCREQ;                                              09150000
option privileged,uncallable,internal;                         <<06858>>09155000
begin                                                                   09160000
                                                                        09165000
<<********************************************************************>>09170000
<< This procedure examines a logical disc request and determines the  >>09175000
<< fetch strategy which is to be applied to a CDT.  The CDT is assumed>>09180000
<< to already be "linked" in the list of mapped-domain CDT's for this >>09185000
<< disc device.  The lower and upper CDT entries are consulted to     >>09190000
<< bound any round-up or round-down decision this procedure makes.    >>09195000
<< The lower and upper disc addresses calculated by this routine are  >>09200000
<< placed in the appropriate cells in the mapped CDT entry.           >>09205000
<<                                                                    >>09210000
<< The passed parameters are:                                         >>09215000
<<                                                                    >>09220000
<< CDT'ENTRY   - The index of the mapped domain CDT entry already     >>09225000
<<               linked into the appropriate position in the list of  >>09230000
<<               mapped CDT domains for this device.                  >>09235000
<< DISCREQ     - A disc request table relative index to the logical   >>09240000
<<               disc request.                                        >>09245000
<<                                                                    >>09250000
<< Returned parameters:                                               >>09255000
<<                                                                    >>09260000
<<               Only the calculated base and limit sector addresses, >>09265000
<<               which have been calculated by this routine, have been>>09270000
<<               placed in the mapped domain CDT entry.               >>09275000
<<                                                             <<*7724>>09280000
<<******** DB is assumed to be at the CDT ********** >>        <<*7724>>09285000
<<********************************************************************>>09290000
                                                                        09295000
<< Re-define DISCREQ to satisfy disc request INCL requirements >>       09300000
logical LDR'ENTRY'INDEX = DISCREQ;                                      09305000
                                                                        09310000
integer COUNT,       << Positive byte count in CDT entry >>             09315000
        CALLER,      << Strategy number to use           >>             09320000
        SECTORS,     << Number of sectors in transfer    >>             09325000
        CDT'PTR,     << Pointer to NEXT/PRIOR CDT entry  >>             09330000
        NEW'SECTORS; << CDT number of sectors to transfer>>             09335000
                                                                        09340000
double LDR'BASE'ADR,    << Base address specified in LDR entry        >>09345000
       LDR'UPPER'ADR,   << Upper address specified in LDR entry       >>09350000
       STRATEGY'BASE,   << Base address calculated by STRATEGY routine>>09355000
       STRATEGY'UPPER,  << Upper address calculated by STRATEGY       >>09360000
       PRIOR'CDT'UPPER, << Prior CDT's upper address                  >>09365000
       NEXT'CDT'BASE,   << Next CDT's base address                    >>09370000
       EXTENT'BASE,     << File system extent base address            >>09375000
       EXTENT'LIMIT;    << File system extent limit address           >>09380000
                                                                        09385000
logical IS'WRITE;   << TRUE if LDR is a write >>                        09390000
                                                                        09395000
<< Variables for fast CDT access >>                            <<*7724>>09400000
integer MAPD'OFFSET,                                           <<*7724>>09405000
        TEMP'MAPD'OFFSET;                                      <<*7724>>09410000
                                                               <<*7724>>09415000
<< Variable to access DST table via SST,LST >>                 <<*7724>>09420000
integer pointer DST   = %2;                                    <<*7724>>09425000
                                                               <<*7724>>09430000
<< Re-define LDR'BASE'ADR >>                                            09435000
integer LDR'P1  = LDR'BASE'ADR,                                         09440000
        LDR'P2  = LDR'P1 + 1;                                           09445000
                                                               <<*7724>>09450000
                                                               <<*7724>>09455000
                                                               <<*7724>>09460000
                                                               <<*7724>>09465000
                                                               <<*7724>>09470000
                                                               <<*7724>>09475000
                                                               <<*7724>>09480000
$page                                                                   09485000
<< Strategy subroutines >>                                              09490000
subroutine UNKNOWN;                                                     09495000
begin                                                                   09500000
                                                                        09505000
<< We can only use the bounds of the transfer >>                        09510000
STRATEGY'BASE := LDR'BASE'ADR;                                          09515000
STRATEGY'UPPER := LDR'UPPER'ADR;                                        09520000
                                                                        09525000
<< If this is a write, we will set the VIRGIN bit to >>                 09530000
<< eliminate a unrequired read prior to the write.   >>                 09535000
if IS'WRITE then << this is a write >>                                  09540000
  begin                                                        <<06858>>09545000
$if x1=on                                                      <<*7724>>09550000
  CDT'SET'BIT(CDT'ENTRY,CDT'VIRGIN'BIT,1);                              09555000
$if x1=off                                                     <<*7724>>09560000
  CDT'ARRAY(MAPD'OFFSET+CDT'MD'FLAGS).(CDT'VIRGIN'BIT:1):=1;   <<*7724>>09565000
$if                                                            <<*7724>>09570000
                                                               <<06858>>09575000
  << Force do-post if necessary >>                             <<06858>>09580000
  if CDT'ARRAY(CDT'FORCE'POST) <> 0 then                       <<*7724>>09585000
    LDR'DO'POST := 1;                                          <<06858>>09590000
  end;                                                         <<06858>>09595000
                                                                        09600000
end;                                                                    09605000
$page                                                                   09610000
subroutine GENMESSAGE;                                                  09615000
begin                                                                   09620000
                                                                        09625000
<< GENMESSAGE always reads one block (record) before the >>             09630000
<< requested address.  This means that a "center" strategy>>            09635000
<< should be used.                                       >>             09640000
                                                                        09645000
if IS'WRITE then                                               <<06858>>09650000
  UNKNOWN                                                      <<06858>>09655000
else                                                           <<06858>>09660000
  begin                                                        <<06858>>09665000
  STRATEGY'BASE := LDR'BASE'ADR - double(SECTORS);             <<06858>>09670000
  if STRATEGY'BASE < EXTENT'BASE then                          <<06858>>09675000
    STRATEGY'BASE := EXTENT'BASE;                              <<06858>>09680000
                                                                        09685000
  NEW'SECTORS:=(CDT'ARRAY(CDT'RND'MINFTCH)/SECTORS)            <<*7724>>09690000
                * SECTORS;                                     <<06858>>09695000
  STRATEGY'UPPER:=STRATEGY'BASE + double(NEW'SECTORS);         <<06858>>09700000
                                                                        09705000
  << Bounds check >>                                           <<06858>>09710000
  if STRATEGY'UPPER < LDR'UPPER'ADR then                       <<06858>>09715000
    begin  << We would have to exceed 32 sector limit >>       <<06858>>09720000
    STRATEGY'BASE := LDR'BASE'ADR;                             <<06858>>09725000
    STRATEGY'UPPER := LDR'UPPER'ADR;                           <<06858>>09730000
    end;                                                       <<06858>>09735000
                                                                        09740000
  if STRATEGY'UPPER > EXTENT'LIMIT then                        <<06858>>09745000
    STRATEGY'UPPER := EXTENT'LIMIT;                            <<06858>>09750000
  end;  << Of READ/GENMSG strategy >>                          <<06858>>09755000
                                                                        09760000
end;  << of subroutine GENMESSAGE >>                                    09765000
$page                                                                   09770000
subroutine FS'SEQUENTIAL;                                               09775000
begin                                                                   09780000
                                                                        09785000
if IS'WRITE then                                               <<06858>>09790000
  UNKNOWN                                                      <<06858>>09795000
else                                                           <<06858>>09800000
  begin                                                        <<06858>>09805000
  << Use base address of requested transfer >>                 <<06858>>09810000
  STRATEGY'BASE := LDR'BASE'ADR;                               <<06858>>09815000
                                                                        09820000
  <<Use upper address of a multiple of block size, <= 8KB>>    <<06858>>09825000
  NEW'SECTORS:=(CDT'ARRAY(CDT'SEQ'MINFTCH)/SECTORS)            <<*7724>>09830000
               *SECTORS;                                       <<06858>>09835000
  if NEW'SECTORS < SECTORS then <<Less than originally requeste<<06858>>09840000
    NEW'SECTORS := SECTORS;   << Round up to 1 block user reque<<06858>>09845000
                                                                        09850000
  << Figure new upper address >>                               <<06858>>09855000
  STRATEGY'UPPER := STRATEGY'BASE + double(NEW'SECTORS);       <<06858>>09860000
                                                                        09865000
  << If beyond end-of-extent, truncate >>                      <<06858>>09870000
  if STRATEGY'UPPER > EXTENT'LIMIT then                        <<06858>>09875000
    STRATEGY'UPPER := EXTENT'LIMIT;                            <<06858>>09880000
  end;  << of READ SEQ strategy >>                             <<06858>>09885000
                                                                        09890000
<< Turn-on flags bit to indicate sequential access >>          <<06858>>09895000
$if x1=on                                                      <<*7724>>09900000
CDT'SET'BIT(CDT'ENTRY,CDT'SEQ'BIT,1);                          <<06858>>09905000
$if x1=off                                                     <<*7724>>09910000
CDT'ARRAY(MAPD'OFFSET+CDT'MD'FLAGS).(CDT'SEQ'BIT:1):=1;        <<*7724>>09915000
$if                                                            <<*7724>>09920000
                                                               <<06858>>09925000
end;  << of FS'SEQUENTIAL strategy >>                                   09930000
$page                                                          <<06858>>09935000
subroutine FS'DIRECT;                                          <<06858>>09940000
begin                                                          <<06858>>09945000
                                                               <<06858>>09950000
if IS'WRITE then                                               <<06858>>09955000
  UNKNOWN                                                      <<06858>>09960000
else                                                           <<06858>>09965000
  begin                                                        <<06858>>09970000
  << Use base address of requested transfer >>                 <<06858>>09975000
  STRATEGY'BASE := LDR'BASE'ADR;                               <<06858>>09980000
                                                               <<06858>>09985000
  << Use upper address of a multiple of block size, <= 8KB >>  <<06858>>09990000
  NEW'SECTORS:=(CDT'ARRAY(CDT'RND'MINFTCH)/SECTORS)            <<*7724>>09995000
                *SECTORS;                                      <<06858>>10000000
  if NEW'SECTORS < SECTORS then<<Less than originally requested<<06858>>10005000
    NEW'SECTORS := SECTORS; << Round up to 1 block user request<<06858>>10010000
                                                               <<06858>>10015000
  << Figure new upper address >>                               <<06858>>10020000
  STRATEGY'UPPER := STRATEGY'BASE + double(NEW'SECTORS);       <<06858>>10025000
                                                               <<06858>>10030000
  << If beyond end-of-extent, truncate >>                      <<06858>>10035000
  if STRATEGY'UPPER > EXTENT'LIMIT then                        <<06858>>10040000
    STRATEGY'UPPER := EXTENT'LIMIT;                            <<06858>>10045000
                                                               <<06858>>10050000
  end; << of read/direct strategy >>                           <<06858>>10055000
end;  << of FS'DIRECT strategy >>                              <<06858>>10060000
$page                                                                   10065000
subroutine STRATEGY;                                                    10070000
begin                                                                   10075000
                                                               <<06858>>10080000
                                                               <<06858>>10085000
                                                               <<06858>>10090000
                                                               <<06858>>10095000
                                                               <<06858>>10100000
                                                               <<06858>>10105000
                                                               <<06858>>10110000
                                                               <<06858>>10115000
                                                               <<06858>>10120000
                                                               <<06858>>10125000
case CALLER of                                                 <<06858>>10130000
  begin                                                        <<06858>>10135000
                                                                        10140000
<<0>> UNKNOWN;            << Unknown caller >>                 <<06858>>10145000
<<1>> UNKNOWN;            << Unknown file system >>            <<06858>>10150000
<<2>> FS'SEQUENTIAL;      << spooler >>                        <<06858>>10155000
<<3>> UNKNOWN;            << Directory >>                      <<06858>>10160000
<<4>> UNKNOWN;                                                 <<06858>>10165000
<<5>> UNKNOWN;                                                 <<06858>>10170000
<<6>> UNKNOWN;                                                 <<06858>>10175000
<<7>> UNKNOWN;                                                 <<06858>>10180000
<<8>> GENMESSAGE;         << GENMSG >>                         <<06858>>10185000
<<9>> UNKNOWN;            << File system, QUIESCE I/O >>       <<06858>>10190000
<<10>> FS'SEQUENTIAL;     << FS, sequential, NOBUF >>          <<06858>>10195000
<<11>> FS'DIRECT;         << FS, direct, NOBUF >>              <<06858>>10200000
<<12>> FS'SEQUENTIAL;     << FS, sequential, BUF >>            <<06858>>10205000
<<13>> FS'DIRECT;         << FS, direct, BUF >>                <<06858>>10210000
<<14>> FS'DIRECT;         << FS, KSAM >>                       <<06858>>10215000
<<15>> FS'DIRECT;         << FS, IMAGE >>                      <<06858>>10220000
                                                                        10225000
  end;  << of case on CALLER >>                                <<06858>>10230000
                                                                        10235000
                                                               <<06858>>10240000
                                                               <<06858>>10245000
end;  << of subroutine STRATEGY >>                                      10250000
$page                                                                   10255000
<< Procedure mainline >>                                                10260000
                                                                        10265000
$if x1=on                                                               10270000
MMSTAT'(MMSTAT'STRATEGY,CDT'ENTRY,LDR'ENTRY'INDEX,LDR'STRATEGY,<<07311>>10275000
        0,0,0);                                                <<07311>>10280000
$if                                                                     10285000
                                                                        10290000
MAPD'OFFSET := CDT'ENTRY * CDT'ENTRY'SIZE;                     <<*7724>>10295000
                                                               <<*7724>>10300000
<< Put DB at LDR entry for fast access >>                      <<*7724>>10305000
tos := DST((LDR'DST & asl(2)) + 2);  << DST bank on tos >>     <<*7724>>10310000
tos := DST(CDT'X:=CDT'X+1);          << DST offset on tos >>   <<*7724>>10315000
tos := tos + LDR'ENTRY'INDEX;        << Point to entry >>      <<*7724>>10320000
EXCHDB;                                                        <<*7724>>10325000
                                                               <<*7724>>10330000
IS'WRITE := if LDR'DB'FUNC = WRITEREQ then true else false;    <<*7724>>10335000
                                                                        10340000
<< Load LDR constants locally >>                                        10345000
tos := LDR'DB'COUNT;                                           <<*7724>>10350000
if < then                                                               10355000
  COUNT := ((-tos)+1) & lsr(1)                                          10360000
else                                                                    10365000
  COUNT := tos;  << Make words >>                                       10370000
SECTORS := (COUNT + 127) & lsr(7); << Divide by 128 >>                  10375000
CALLER := LDR'DB'STRATEGY;  << Caller's code >>                <<*7724>>10380000
<< Load P1,P2 >>                                                        10385000
LDR'P1 := LDR'DB'PARM1;                                        <<*7724>>10390000
LDR'P2 := LDR'DB'PARM2;                                        <<*7724>>10395000
LDR'UPPER'ADR := LDR'BASE'ADR + double(SECTORS);                        10400000
                                                                        10405000
<< Load extent base from Disc Request >>                                10410000
tos := LDR'DB'B'HODA;                                          <<*7724>>10415000
tos := LDR'DB'B'LODA;                                          <<*7724>>10420000
if (EXTENT'BASE := tos) > LDR'BASE'ADR then                             10425000
  EXTENT'BASE := LDR'BASE'ADR;                                          10430000
                                                                        10435000
tos := LDR'L'HODA;                                                      10440000
tos := LDR'L'LODA;                                                      10445000
if (EXTENT'LIMIT := tos) < LDR'UPPER'ADR then                           10450000
  EXTENT'LIMIT := LDR'UPPER'ADR;                                        10455000
                                                                        10460000
<< Put DB back to caller's (pointing to CDT) DB >>             <<*7724>>10465000
EXCHDB;                                                        <<*7724>>10470000
ASMB(DDEL);                                                    <<*7724>>10475000
                                                               <<*7724>>10480000
<< Get prior CDT's UPPER disc address >>                                10485000
CDT'PTR := CDT'ARRAY(MAPD'OFFSET+CDT'MD'PREV);                 <<*7724>>10490000
if CDT'PTR = 0 then                                                     10495000
  begin  << There is no previous, so assume 0 >>                        10500000
  PRIOR'CDT'UPPER := 0D;                                                10505000
  end                                                                   10510000
else                                                                    10515000
  begin  << Get prior CDT's upper address >>                            10520000
  TEMP'MAPD'OFFSET := CDT'PTR * CDT'ENTRY'SIZE;                <<*7724>>10525000
$if x1=on                                                      <<*7724>>10530000
  PRIOR'CDT'UPPER := CDT'GET'DOUBLE(CDT'PTR,CDT'MD'END'SECTOR,0D);      10535000
$if x1=off                                                     <<*7724>>10540000
  PRIOR'CDT'UPPER := CDT'DARRAY((TEMP'MAPD'OFFSET +            <<*7724>>10545000
                              CDT'MD'END'SECTOR) & asr(1));    <<*7724>>10550000
$if                                                            <<*7724>>10555000
  end;                                                                  10560000
                                                                        10565000
<< Get next CDT's base disc address >>                                  10570000
CDT'PTR := CDT'ARRAY(MAPD'OFFSET+CDT'MD'NEXT);                 <<*7724>>10575000
if CDT'PTR = 0 then                                                     10580000
  begin << There is no next CDT, so assume highest disc address >>      10585000
  NEXT'CDT'BASE := %17777777777 D;  << Highest possible address >>      10590000
  end                                                                   10595000
else                                                                    10600000
  begin  << Get next CDT's base address >>                              10605000
$if x1=on                                                      <<*7724>>10610000
  NEXT'CDT'BASE := CDT'GET'DOUBLE(CDT'PTR,CDT'MD'SECTOR,0D);            10615000
$if x1=off                                                     <<*7724>>10620000
  NEXT'CDT'BASE := CDT'DARRAY(((CDT'PTR*CDT'ENTRY'SIZE) +      <<*7724>>10625000
                            CDT'MD'SECTOR) & asr(1));          <<*7724>>10630000
$if                                                            <<*7724>>10635000
  end;                                                                  10640000
                                                                        10645000
STRATEGY;                                                               10650000
                                                                        10655000
<< Bounds check strategy applied >>                                     10660000
if STRATEGY'BASE < PRIOR'CDT'UPPER then  << Must adjust >>              10665000
  STRATEGY'BASE := PRIOR'CDT'UPPER;                                     10670000
if STRATEGY'UPPER > NEXT'CDT'BASE then                                  10675000
  STRATEGY'UPPER := NEXT'CDT'BASE;                                      10680000
                                                                        10685000
<< Place disc domain in CDT entry >>                                    10690000
$if x1=on                                                      <<*7724>>10695000
CDT'SET'DOUBLE(CDT'ENTRY,CDT'MD'SECTOR,STRATEGY'BASE);                  10700000
CDT'SET'DOUBLE(CDT'ENTRY,CDT'MD'END'SECTOR,STRATEGY'UPPER);             10705000
$if x1=off                                                     <<*7724>>10710000
CDT'DARRAY((MAPD'OFFSET+CDT'MD'SECTOR)&asr(1)):=STRATEGY'BASE; <<*7724>>10715000
                                                               <<*7724>>10720000
CDT'DARRAY((MAPD'OFFSET+CDT'MD'END'SECTOR)&asr(1)):=           <<*7724>>10725000
   STRATEGY'UPPER;                                             <<*7724>>10730000
$if                                                            <<*7724>>10735000
                                                                        10740000
end;  << of procedure CDT'STRATEGY >>                                   10745000
$page "CDT'INITIATOR / CDT'COMPLETOR procedure"                         10750000
procedure CDT'INITIATOR(CDT'ENTRY,DISC'REQ);                            10755000
value CDT'ENTRY,DISC'REQ;                                               10760000
integer CDT'ENTRY,DISC'REQ;                                             10765000
option privileged,uncallable,internal;                         <<06858>>10770000
begin                                                                   10775000
                                                                        10780000
<<********************************************************************>>10785000
<< This procedure processes requests to "queue" disc requests to an   >>10790000
<< existing CDT entry for a new request, and to "dequeue" disc re-    >>10795000
<< quests when the 'move' has been satisfied by the cache completor   >>10800000
<< code.  On initiation, it is assumed that we are running in the     >>10805000
<< caller's process environment.  A call to "PREFETCH" is made which  >>10810000
<< might add this CDT entry to the processes locality.  On completion,>>10815000
<< this routine will perform housekeeping to determine if deferred    >>10820000
<< requests can be released for processing.                           >>10825000
<<                                                                    >>10830000
<< The parameters passed to this procedure are:                       >>10835000
<<                                                                    >>10840000
<< CDT'ENTRY    - This is the index of the CDT entry to be manipulated>>10845000
<< DISC'REQ     - This is the index of the disc request to be attached>>10850000
<<                or released from this procedure.  When the initiator>>10855000
<<                is called, this LDR entry is attached to either the >>10860000
<<                "active" or "deferred" queue on this CDT.  When the >>10865000
<<                "completor" is called, this entry MUST be the head  >>10870000
<<                entry on this CDT's active list.                    >>10875000
<<                                                                    >>10880000
<< It is assumed that we are already PDISABLEd when entering this     >>10885000
<< routine.  Also, there is no assumption made of where DB is sitting.>>10890000
<<********************************************************************>>10895000
                                                                        10900000
entry CDT'COMPLETOR;   << This is called to "complete" a LDR attached >>10905000
                       << to a CDT.                                   >>10910000
                                                                        10915000
<< Variable to satisfy the LDR's include file >>                        10920000
integer LDR'ENTRY'INDEX;                                                10925000
                                                                        10930000
integer NEXT'POINTER,  << Used to chase down linked LDR's >>            10935000
        SAVE'LDR,      << Cell to save passed DISC'REQ value >>         10940000
        STATE,         << CDT state (saved locally)       >>            10945000
        CDT'FLGS,      << FLAGS word in CDT entry         >>            10950000
        LKD'CDT,       << CDT entry of locked CDT         >>            10955000
        DEV'ENTRY,     << Device entry number             >>            10960000
        SENDMSGFLAGS,  << flags parameter to send msg     >>            10965000
        CURRENTPIN,    << pin of currently executing process>>          10970000
        IMPEDED'PIN,   << Head pin waiting on write compl'n >>          10975000
        NEXT'PIN,      << Next pin waiting on write compl'n >>          10980000
        FUNCTION;      << I/O function from disc request  >>            10985000
                                                                        10990000
logical CONTINUE'LOOP, << Loop control flag >>                          10995000
        FIRST'TIME;    << Loop control flag >>                          11000000
                                                                        11005000
double REGION'ADDRESS,   << CDT memory address >>              <<06858>>11010000
       OBJECT'ID;      << Object ID of cache domain         >> <<06858>>11015000
                                                               <<06858>>11020000
<< Variables for fast access to CDT >>                         <<*7724>>11025000
integer LDEV'OFFSET,       << LDEV entry offset in CDT   >>    <<*7724>>11030000
        MAPD'OFFSET;       << Mapd entry offset in CDT   >>    <<*7724>>11035000
                                                               <<*7724>>11040000
double  SAVE'DB;           << Value of caller's DB       >>    <<*7724>>11045000
                                                               <<*7724>>11050000
                                                               <<*7724>>11055000
                                                               <<*7724>>11060000
                                                               <<*7724>>11065000
                                                               <<*7724>>11070000
                                                               <<*7724>>11075000
                                                               <<*7724>>11080000
                                                               <<*7724>>11085000
$page                                                                   11090000
subroutine RELEASE'CDT;                                                 11095000
begin                                                                   11100000
                                                                        11105000
<< If in-motion out bit is set, we MUST hold on to the CDT entry >>     11110000
$if x1=on                                                      <<*7724>>11115000
tos := CDT'GET'WORD(CDT'ENTRY,CDT'MD'FLAGS,0);                 <<*7724>>11120000
$if x1=off                                                     <<*7724>>11125000
tos := CDT'ARRAY(MAPD'OFFSET+CDT'MD'FLAGS);                    <<*7724>>11130000
$if                                                            <<*7724>>11135000
if tos.(CDT'IMO'BIT:1) = 1 then                                <<*7724>>11140000
  begin     << Deferred posting is still in progress >>                 11145000
  end                                                                   11150000
                                                                        11155000
else                                                                    11160000
                                                                        11165000
  begin                                                                 11170000
                                                                        11175000
$if x7=on                                                      <<06858>>11180000
  << If there was a locked CDT, decrement its lock cnt >>               11185000
  LKD'CDT := CDT'GET'WORD(CDT'ENTRY,CDT'MD'LKD'CDT,0);                  11190000
  if LKD'CDT <> 0 then                                                  11195000
    begin                                                               11200000
    if CDT'ADD'WORD(LKD'CDT,CDT'MD'LK'CNT,-1) <= 1 then                 11205000
      CDT'COMPLETOR(LKD'CDT,0); << Awaken locked entry >>               11210000
    end;                                                                11215000
$if                                                            <<06858>>11220000
                                                                        11225000
  << Get LDEV CDT entry index >>                                        11230000
  DEV'ENTRY := CDT'ARRAY(MAPD'OFFSET+CDT'MD'DE);               <<d7726>>11235000
  LDEV'OFFSET := DEV'ENTRY * CDT'ENTRY'SIZE;                   <<*7724>>11240000
                                                                        11245000
  << If this was a sequential access and the last block >>     <<06858>>11250000
  << of the memory region was touched, delete the memory>>     <<06858>>11255000
  << region from main memory.                           >>     <<06858>>11260000
$if x1=on                                                      <<*7724>>11265000
  tos := CDT'GET'WORD(CDT'ENTRY,CDT'MD'FLAGS,0);               <<*7724>>11270000
$if x1=off                                                     <<*7724>>11275000
  tos := CDT'ARRAY(MAPD'OFFSET+CDT'MD'FLAGS);                  <<*7724>>11280000
$if                                                            <<*7724>>11285000
  if tos.(CDT'SEQ'BIT:1) = 1 then                              <<*7724>>11290000
    begin                                                      <<06858>>11295000
    LDR'ENTRY'INDEX := DISC'REQ;                               <<06858>>11300000
    if <> then                                                 <<06858>>11305000
      begin                                                    <<06858>>11310000
      << Place LDR logical disc address on tos >>              <<06858>>11315000
      tos := LDR'PARM1;                                        <<06858>>11320000
      tos := LDR(CDT'X:=CDT'X + 1);                            <<06858>>11325000
      tos := 0;   << Add sector offset to it >>                <<06858>>11330000
      tos := LDR'COUNT;                                        <<06858>>11335000
      if < then tos := ((-tos)+1) & lsr(1);  << Make words>>   <<06858>>11340000
      tos := (tos+127) & lsr(7); << Make sectors >>            <<06858>>11345000
      ASMB(DADD);   << Form end sector address >>              <<06858>>11350000
      << Get domain's ending disc address >>                   <<*7724>>11355000
$if x1=on                                                      <<*7724>>11360000
      tos := CDT'GET'DOUBLE(CDT'ENTRY,CDT'MD'END'SECTOR,0D);   <<*7724>>11365000
$if x1=off                                                     <<*7724>>11370000
      tos:=CDT'DARRAY((MAPD'OFFSET+CDT'MD'END'SECTOR)&asr(1)); <<*7724>>11375000
$if                                                            <<*7724>>11380000
                                                               <<*7724>>11385000
      << Now, see if they match >>                             <<*7724>>11390000
      ASMB(DCMP);                                              <<*7724>>11395000
      if = then   << They do, so plan to erode the domain >>   <<*7724>>11400000
         begin                                                 <<*7724>>11405000
$if x1=on                                                      <<*7724>>11410000
         REGION'ADDRESS:=CDT'GET'DOUBLE(CDT'ENTRY,             <<06858>>11415000
                         CDT'MD'MEM'ADDR,0D);                  <<*7724>>11420000
                                                               <<*7724>>11425000
                                                               <<*7724>>11430000
$if x1=off                                                     <<*7724>>11435000
         REGION'ADDRESS := CDT'DARRAY((MAPD'OFFSET +           <<*7724>>11440000
                                 CDT'MD'MEM'ADDR) & asr(1));   <<*7724>>11445000
         end                                                   <<*7724>>11450000
      else                                                     <<*7724>>11455000
         REGION'ADDRESS:=0D;                                   <<*7724>>11460000
      end                                                      <<06858>>11465000
    else                                                       <<06858>>11470000
      << If no LDR, this is NO'POST write >>                   <<06858>>11475000
      begin                                                    <<*7724>>11480000
$if x1=on                                                      <<*7724>>11485000
      REGION'ADDRESS:=CDT'GET'DOUBLE(CDT'ENTRY,CDT'MD'MEM'ADDR,<<06858>>11490000
                      0D);                                     <<06858>>11495000
$if x1=off                                                     <<*7724>>11500000
      REGION'ADDRESS := CDT'DARRAY((MAPD'OFFSET +              <<*7724>>11505000
                                  CDT'MD'MEM'ADDR) & asr(1));  <<*7724>>11510000
$if                                                            <<*7724>>11515000
      end;                                                     <<*7724>>11520000
    <<If non-zero REGION'ADDRESS, we must purge memory region>><<06858>>11525000
    if REGION'ADDRESS <> 0D then                               <<06858>>11530000
      begin                                                    <<06858>>11535000
      << Put DB at SYSDB for KERNEL >>                         <<*7724>>11540000
      tos := %1000 D;                                          <<*7724>>11545000
      EXCHDB;                                                  <<*7724>>11550000
                                                               <<*7724>>11555000
      << Convert to standard segment ID >>                     <<*7724>>11560000
      OBJECT'ID := BUILDOBJID(MAPPEDDOMAINOBJECT,              <<*7724>>11565000
                              CDT'ENTRY,0);                    <<*7724>>11570000
      << If not absent, make it an OC >>                       <<*7724>>11575000
      if not ISOBJECTABSENT(OBJECT'ID) then                    <<*7724>>11580000
        MakeOC(0,                                              <<*7724>>11585000
               OBJECT'ID,                                      <<*7724>>11590000
               0,  << Request size >>                          <<*7724>>11595000
               REGION'ADDRESS);                                <<*7724>>11600000
                                                               <<*7724>>11605000
      << Put DB back to CDT >>                                 <<*7724>>11610000
      EXCHDB;                                                  <<*7724>>11615000
      ASMB(DDEL);                                              <<*7724>>11620000
      end;                                                     <<*7724>>11625000
                                                               <<*7724>>11630000
                                                               <<*7724>>11635000
                                                               <<*7724>>11640000
                                                               <<*7724>>11645000
                                                               <<*7724>>11650000
                                                               <<*7724>>11655000
    end;  << of processing sequential I/O special case >>      <<06858>>11660000
                                                               <<06858>>11665000
  << Release CDT entry >>                                               11670000
  CDT'REL'MD'ENTRY(DEV'ENTRY,CDT'ENTRY);                                11675000
                                                               <<06858>>11680000
  end;                                                                  11685000
                                                                        11690000
end;                                                                    11695000
$page                                                                   11700000
subroutine UNIMPEDE'WAITORS;                                            11705000
begin                                                                   11710000
                                                                        11715000
<< Any processes waiting for writes to complete will be >>              11720000
<< awaked here.  Originally, they were impeded in proc. >>              11725000
<< CDT'FORCE'LDR'COMPLETION.                            >>              11730000
<<********** DB MUST BE AT SYSDB ***********************>>     <<*7724>>11735000
                                                                        11740000
<< Get pin of any waitor & unimpede them                >>              11745000
IMPEDED'PIN:=CDT'SET'WORD(CDT'ENTRY,CDT'MD'IMPEDED,0);         <<06858>>11750000
while IMPEDED'PIN <> 0 do                                               11755000
  begin                                                                 11760000
                                                                        11765000
  << Take off PCB list >>                                               11770000
  NEXT'PIN := UNSTRINGHEADPIN(IMPEDED'PIN);                             11775000
                                                                        11780000
  << AWAKEn process >>                                                  11785000
  UNIMPEDE(IMPEDED'PIN * PCBSIZE);                                      11790000
                                                                        11795000
  IMPEDED'PIN := NEXT'PIN;                                     <<06858>>11800000
                                                                        11805000
  end;                                                                  11810000
                                                                        11815000
end;  << of subroutine UNIMPEDE'WAITORS >>                              11820000
$page                                                                   11825000
subroutine MOVE'QUEUE;                                                  11830000
begin                                                                   11835000
                                                                        11840000
<< This subroutine moves disc requests from the 'impeded' to>>          11845000
<< the 'available' queue.  The first element is always moved>>          11850000
<< and afterwards will continue until the first 'write' is  >>          11855000
<< encountered.                                             >>          11860000
                                                                        11865000
CONTINUE'LOOP := FIRST'TIME := true;  << Loop control >>                11870000
                                                                        11875000
while CONTINUE'LOOP do                                                  11880000
  begin                                                                 11885000
$if x1=on                                                      <<*7724>>11890000
  LDR'ENTRY'INDEX := CDT'GET'WORD(CDT'ENTRY,CDT'MD'IMPED'HD,0);         11895000
$if x1=off                                                     <<*7724>>11900000
  LDR'ENTRY'INDEX := CDT'ARRAY(MAPD'OFFSET+CDT'MD'IMPED'HD);   <<*7724>>11905000
$if                                                            <<*7724>>11910000
  if LDR'ENTRY'INDEX = 0 then                                           11915000
    CONTINUE'LOOP := false                                              11920000
  else                                                                  11925000
    begin  << Try to move over to active list >>                        11930000
    << If this is a write, we must be careful >>                        11935000
    if LDR'FUNC = WRITEREQ then                                         11940000
      begin                                                             11945000
      if FIRST'TIME then                                                11950000
        begin  << we can move only this "write" >>                      11955000
        CDT'DEQUEUE'LDR(CDT'ENTRY,LDR'ENTRY'INDEX,CDT'MD'IMPED'HD);     11960000
        CDT'QUEUE'LDR(CDT'ENTRY,LDR'ENTRY'INDEX,CDT'MD'LDR'HEAD);       11965000
        FIRST'TIME := false;                                            11970000
        end                                                             11975000
      else                                                              11980000
        CONTINUE'LOOP := false;                                         11985000
      end                                                               11990000
    else                                                                11995000
      begin  << This is a read, so just move it >>                      12000000
      CDT'DEQUEUE'LDR(CDT'ENTRY,LDR'ENTRY'INDEX,CDT'MD'IMPED'HD);       12005000
      CDT'QUEUE'LDR(CDT'ENTRY,LDR'ENTRY'INDEX,CDT'MD'LDR'HEAD);         12010000
      end;                                                              12015000
    end;                                                                12020000
  end;  << of looping through WHILE stmt >>                             12025000
                                                                        12030000
<< Inform CDT processor routine that NEW requests exist >>              12035000
                                                                        12040000
$if x1=on                                                      <<*7724>>12045000
LDR'ENTRY'INDEX:=CDT'GET'WORD(CDT'ENTRY,CDT'MD'LDR'HEAD,0);             12050000
$if x1=off                                                     <<*7724>>12055000
LDR'ENTRY'INDEX := CDT'ARRAY(MAPD'OFFSET+CDT'MD'LDR'HEAD);     <<*7724>>12060000
$if                                                            <<*7724>>12065000
if LDR'ENTRY'INDEX <> 0 then                                   <<*7724>>12070000
   BEGIN                                                                12075000
   << Put DB to SYSDB >>                                       <<*7724>>12080000
   tos := %1000 D;                                             <<*7724>>12085000
   EXCHDB;                                                     <<*7724>>12090000
                                                               <<*7724>>12095000
   tos := CDT'ENTRY;                                                    12100000
   tos := IOSTATUSOK;                                                   12105000
   tos := CACHEMOVEREADYCODE;                                           12110000
   SENDMSGFLAGS:=0;                                                     12115000
   if (CURRENTPIN := (CURPRC/PCBSIZE)) <> 0                    <<06857>>12120000
   and PROCESSPRI(LDR'PCB) >= PROCESSPRI(CURRENTPIN)                    12125000
   then SENDMSGFLAGS.MSGDON'TPREEMPTFLAG := 1;                          12130000
   SENDMSG(SCHEDPIN,CACHEMOVEPORT,3,SENDMSGFLAGS);                      12135000
                                                                        12140000
  << Unimpede anybody waiting on write completions >>                   12145000
  UNIMPEDE'WAITORS;                                                     12150000
                                                                        12155000
  << Put DB back to CDT >>                                     <<*7724>>12160000
  EXCHDB;                                                      <<*7724>>12165000
  ASMB(ddel);                                                  <<*7724>>12170000
  end;                                                                  12175000
<< Restore current disc request pointer >>                              12180000
LDR'ENTRY'INDEX := DISC'REQ;                                            12185000
                                                                        12190000
end;                                                                    12195000
$page                                                                   12200000
subroutine WAKE'LDR;                                                    12205000
begin                                                                   12210000
                                                                        12215000
if  DISC'REQ <> 0 then                                                  12220000
  begin                                                                 12225000
  tos := %1000 D;                                              <<*7724>>12230000
  EXCHDB;                                                      <<*7724>>12235000
                                                                        12240000
  << tos := entry index >>                                     <<06856>>12245000
  LDR'ENTRY'INDEX := DISC'REQ;  << PEG LDR DEFS >>             <<*7727>>12250000
                                                               <<*7727>>12255000
                                                               <<*7727>>12260000
                                                               <<*7727>>12265000
<<       IN    LINE    SIODM'REQUEST'DONE      >>              <<*7727>>12270000
                                                               <<*7727>>12275000
                                                               <<*7727>>12280000
                                                               <<*7727>>12285000
  IF LDR'DONE  THEN  SUDDENDEATH(261);                         <<*7727>>12290000
  LDR'DONE := 1;                                               <<*7727>>12295000
  TOS := LDR'PCB;                                              <<*7727>>12300000
  IF  LDR'IOWAKE   THEN                                        <<*7727>>12305000
    BEGIN                                                      <<*7727>>12310000
    TOS := S0 * PCBSIZE;                                       <<*7727>>12315000
    TOS:=IF LDR'BLOCKED THEN BIOWAITCODE ELSE UIOWAITCODE;     <<*7727>>12320000
    TOS := NOWAIT;                                             <<*7727>>12325000
    AWAKE(*,*,*);                                              <<*7727>>12330000
    END;                                                       <<*7727>>12335000
                                                               <<*7727>>12340000
                                                               <<*7727>>12345000
  IF TOS = 0   THEN   <<  NO   PCB  >>                         <<*7727>>12350000
    BEGIN                                                      <<*7727>>12355000
    IF LDR'SBUF  THEN                                          <<*7727>>12360000
      IF LDR'BUFADR   <>  0 THEN                               <<*7727>>12365000
        RETURNSYSBUF(LDR'BUFADR);                              <<*7727>>12370000
    RETURNDISCREQ(LDR'ENTRY'INDEX);                            <<*7727>>12375000
    END;                                                       <<*7727>>12380000
                                                               <<*7727>>12385000
                                                               <<*7727>>12390000
                                                               <<*7727>>12395000
                                                               <<*7727>>12400000
                                                                        12405000
  EXCHDB;                                                      <<*7724>>12410000
  ASMB(ddel);                                                  <<*7724>>12415000
  end;                                                                  12420000
                                                                        12425000
end;                                                                    12430000
$page                                                                   12435000
subroutine SETSTATE(STATE'TYPE);                                        12440000
value STATE'TYPE;                                                       12445000
integer STATE'TYPE;                                                     12450000
begin                                                                   12455000
                                                                        12460000
DISABLE;                                                       <<06858>>12465000
$if x1=on                                                      <<*7724>>12470000
CDT'FLGS := CDT'GET'WORD(CDT'ENTRY,CDT'MD'FLAGS,0);                     12475000
CDT'FLGS.CDT'MD'STATE := STATE'TYPE;                                    12480000
CDT'SET'WORD(CDT'ENTRY,CDT'MD'FLAGS,CDT'FLGS);                          12485000
$if x1=off                                                     <<*7724>>12490000
CDT'X := MAPD'OFFSET+CDT'MD'FLAGS;                             <<*7724>>12495000
CDT'ARRAY(CDT'X).CDT'MD'STATE := STATE'TYPE;                   <<*7724>>12500000
$if                                                            <<*7724>>12505000
ENABLE;                                                        <<06858>>12510000
                                                                        12515000
end;                                                                    12520000
$page                                                                   12525000
subroutine DO'PREFETCH;                                                 12530000
begin                                                                   12535000
                                                                        12540000
tos := %1000 D;                                                <<*7724>>12545000
EXCHDB;                                                        <<*7724>>12550000
                                                               <<*7724>>12555000
<< Indicate that MD is now in prefetch locality of process >>  <<*7724>>12560000
tos := LDR'FLAGS;                                              <<*7724>>12565000
tos.(LDR'INLOC'BIT:1) := 1;                                    <<*7724>>12570000
if <> then   << Already set... problems >>                     <<*7724>>12575000
  SUDDENDEATH(SFKERNCACHEINTBAD);                              <<*7724>>12580000
LDR(CDT'X) := tos;                                             <<*7724>>12585000
PREFETCHOBJECT(LDR'PCB,    << PIN of requestor >>                       12590000
              BUILDOBJID(MAPPEDDOMAINOBJECT,                            12595000
                         CDT'ENTRY,                                     12600000
                         0 <<Pin>>)); << CDT object number >>           12605000
EXCHDB;                                                        <<*7724>>12610000
ASMB(ddel);                                                    <<*7724>>12615000
                                                                        12620000
end;                                                                    12625000
$page                                                                   12630000
subroutine INIT;                                                        12635000
begin                                                                   12640000
                                                                        12645000
<< This routine initializes variables for either entry point >>         12650000
                                                               <<*7724>>12655000
MAPD'OFFSET := CDT'ENTRY * CDT'ENTRY'SIZE;                     <<*7724>>12660000
                                                                        12665000
<< Put DB at CDT >>                                            <<*7724>>12670000
CDT'ABS'ON'TOS;                                                <<*7724>>12675000
EXCHDB;                                                        <<*7724>>12680000
SAVE'DB := tos;                                                <<*7724>>12685000
                                                               <<*7724>>12690000
<< If there is a disc request, place CDT# in it >>                      12695000
LDR'ENTRY'INDEX := DISC'REQ;  << Point to passed LDR >>        <<*7724>>12700000
if <> then                                                              12705000
  begin                                                                 12710000
  LDR'CDT := CDT'ENTRY;                                                 12715000
  FUNCTION := LDR'FUNC;                                                 12720000
  end                                                                   12725000
else                                                                    12730000
  FUNCTION := -1;                                                       12735000
                                                                        12740000
$if x1=on                                                      <<*7724>>12745000
STATE := CDT'GET'WORD(CDT'ENTRY,CDT'MD'FLAGS,0).CDT'MD'STATE;           12750000
$if x1=off                                                     <<*7724>>12755000
STATE := CDT'ARRAY(MAPD'OFFSET+CDT'MD'FLAGS).CDT'MD'STATE;     <<*7724>>12760000
$if                                                            <<*7724>>12765000
                                                                        12770000
end;                                                                    12775000
$page                                                                   12780000
<< This is the procedure INITIATOR point >>                             12785000
$if x1=on                                                               12790000
MMSTAT'(MMSTAT'INITIATOR,CDT'ENTRY,DISC'REQ,0,0,0,0);          <<06859>>12795000
$if                                                                     12800000
                                                                        12805000
INIT;                                                                   12810000
                                                                        12815000
case STATE of                                                           12820000
  begin                                                                 12825000
                                                                        12830000
  <<0>> << CDT is available, on FREE list >>                            12835000
  begin                                                                 12840000
  if FUNCTION = READREQ then                                            12845000
    begin << It's a read >>                                             12850000
    SETSTATE(CDT'READ'STATE);                                           12855000
    CDT'QUEUE'LDR(CDT'ENTRY,DISC'REQ,CDT'MD'LDR'HEAD);                  12860000
$if x1=on                                                      <<*7724>>12865000
    CDT'ADD'WORD(CDT'ENTRY,CDT'MD'READ'CNT,1);                          12870000
$if x1=off                                                     <<*7724>>12875000
    CDT'X := MAPD'OFFSET + CDT'MD'READ'CNT;                    <<*7724>>12880000
    CDT'ARRAY(CDT'X) := CDT'ARRAY(CDT'X) + 1;                  <<*7724>>12885000
$if                                                            <<*7724>>12890000
    DO'PREFETCH;                                                        12895000
    end                                                                 12900000
  else                                                                  12905000
    begin << It's a write >>                                            12910000
    SETSTATE(CDT'WRITE'STATE);                                          12915000
    CDT'QUEUE'LDR(CDT'ENTRY,DISC'REQ,CDT'MD'LDR'HEAD);                  12920000
$if x1=on                                                      <<*7724>>12925000
    CDT'ADD'WORD(CDT'ENTRY,CDT'MD'WRITE'CNT,1);                         12930000
$if x1=off                                                     <<*7724>>12935000
    CDT'X := MAPD'OFFSET + CDT'MD'WRITE'CNT;                   <<*7724>>12940000
    CDT'ARRAY(CDT'X) := CDT'ARRAY(CDT'X) + 1;                  <<*7724>>12945000
$if                                                            <<*7724>>12950000
    DO'PREFETCH;                                                        12955000
    end;                                                                12960000
  end;                                                                  12965000
                                                                        12970000
  <<1>> << CDT is in a read state >>                                    12975000
  begin                                                                 12980000
  if FUNCTION = READREQ then                                            12985000
    begin << It's a read >>                                             12990000
    CDT'QUEUE'LDR(CDT'ENTRY,DISC'REQ,CDT'MD'LDR'HEAD);                  12995000
$if x1=on                                                      <<*7724>>13000000
    CDT'ADD'WORD(CDT'ENTRY,CDT'MD'READ'CNT,1);                          13005000
$if x1=off                                                     <<*7724>>13010000
    CDT'X := MAPD'OFFSET + CDT'MD'READ'CNT;                    <<*7724>>13015000
    CDT'ARRAY(CDT'X) := CDT'ARRAY(CDT'X) + 1;                  <<*7724>>13020000
$if                                                            <<*7724>>13025000
    DO'PREFETCH;                                                        13030000
    end                                                                 13035000
  else                                                                  13040000
    begin << It's a write >>                                            13045000
    SETSTATE(CDT'WRITE'STATE);                                          13050000
    CDT'QUEUE'LDR(CDT'ENTRY,DISC'REQ,CDT'MD'IMPED'HD);                  13055000
$if x1=on                                                      <<*7724>>13060000
    CDT'ADD'WORD(CDT'ENTRY,CDT'MD'WRITE'CNT,1);                         13065000
$if x1=off                                                     <<*7724>>13070000
    CDT'X := MAPD'OFFSET + CDT'MD'WRITE'CNT;                   <<*7724>>13075000
    CDT'ARRAY(CDT'X) := CDT'ARRAY(CDT'X) + 1;                  <<*7724>>13080000
$if                                                            <<*7724>>13085000
    DO'PREFETCH;                                                        13090000
    end;                                                                13095000
  end;                                                                  13100000
                                                                        13105000
  <<2>> << CDT is in a write state >>                                   13110000
  begin                                                                 13115000
  if FUNCTION = READREQ then                                            13120000
    begin << It's a read >>                                             13125000
                                                                        13130000
    << If there is only one writer, we can allow other >>               13135000
    << readers to access domain.                       >>               13140000
    if CDT'ARRAY(MAPD'OFFSET+CDT'MD'WRITE'CNT) <= 1 then       <<*7724>>13145000
      CDT'QUEUE'LDR(CDT'ENTRY,DISC'REQ,CDT'MD'LDR'HEAD)                 13150000
    else                                                                13155000
      CDT'QUEUE'LDR(CDT'ENTRY,DISC'REQ,CDT'MD'IMPED'HD);                13160000
$if x1=on                                                      <<*7724>>13165000
    CDT'ADD'WORD(CDT'ENTRY,CDT'MD'READ'CNT,1);                          13170000
$if x1=off                                                     <<*7724>>13175000
    CDT'X := MAPD'OFFSET + CDT'MD'READ'CNT;                    <<*7724>>13180000
    CDT'ARRAY(CDT'X) := CDT'ARRAY(CDT'X) + 1;                  <<*7724>>13185000
$if                                                            <<*7724>>13190000
    DO'PREFETCH;                                                        13195000
    end                                                                 13200000
  else                                                                  13205000
    begin << It's a write >>                                            13210000
    CDT'QUEUE'LDR(CDT'ENTRY,DISC'REQ,CDT'MD'IMPED'HD);                  13215000
$if x1=on                                                      <<*7724>>13220000
    CDT'ADD'WORD(CDT'ENTRY,CDT'MD'WRITE'CNT,1);                         13225000
$if x1=off                                                     <<*7724>>13230000
    CDT'X := MAPD'OFFSET + CDT'MD'WRITE'CNT;                   <<*7724>>13235000
    CDT'ARRAY(CDT'X) := CDT'ARRAY(CDT'X) + 1;                  <<*7724>>13240000
$if                                                            <<*7724>>13245000
    DO'PREFETCH;                                                        13250000
    end;                                                                13255000
  end;                                                                  13260000
                                                                        13265000
  <<3>> << CDT is being flushed and should not receive requests >>      13270000
  SUDDENDEATH(CDT'INVALID'STATE);                                       13275000
                                                                        13280000
  <<4>> << CDT is LOCKED, awaiting other CDT's to "flush" >>            13285000
  begin                                                                 13290000
  CDT'QUEUE'LDR(CDT'ENTRY,DISC'REQ,CDT'MD'IMPED'HD);                    13295000
  end;                                                                  13300000
                                                                        13305000
  end;  << of case on STATE >>                                          13310000
                                                                        13315000
go to Leave'routine;  << Perform EXIT housekeeping >>                   13320000
$page                                                                   13325000
<< COMPLETOR entry point into procedure >>                              13330000
CDT'COMPLETOR:                                                          13335000
                                                                        13340000
$if x1=on                                                               13345000
MMSTAT'(MMSTAT'INITIATOR,CDT'ENTRY,DISC'REQ,1,0,0,0);          <<06859>>13350000
$if                                                                     13355000
                                                                        13360000
INIT;  << Initialize variables >>                                       13365000
                                                                        13370000
case STATE of                                                           13375000
  begin                                                                 13380000
                                                                        13385000
  <<0>> << The CDT should have no requests pending (AVAIL).  This case>>13390000
        << may be used by KERNEL to finish a WRITE which has been     >>13395000
        << already reported as "completed" to the user.               >>13400000
  begin                                                                 13405000
  RELEASE'CDT;                                                          13410000
  end;                                                                  13415000
                                                                        13420000
  <<1>> << Read state >>                                                13425000
  begin                                                                 13430000
  if FUNCTION = READREQ then                                            13435000
    begin << It's a read >>                                             13440000
    CDT'DEQUEUE'LDR(CDT'ENTRY,DISC'REQ,CDT'MD'LDR'HEAD);                13445000
$if x1=on                                                      <<*7724>>13450000
    tos := CDT'ADD'WORD(CDT'ENTRY,CDT'MD'READ'CNT,-1);         <<*7724>>13455000
$if x1=off                                                     <<*7724>>13460000
    CDT'X := MAPD'OFFSET + CDT'MD'READ'CNT;                    <<*7724>>13465000
    tos := CDT'ARRAY(CDT'X) := CDT'ARRAY(CDT'X) - 1;           <<*7724>>13470000
$if                                                            <<*7724>>13475000
    if tos = 0 then                                            <<*7724>>13480000
      begin << Read count is zero, remove this CDT entry >>             13485000
      SETSTATE(CDT'AVAIL'STATE);                                        13490000
      RELEASE'CDT;                                                      13495000
      end;                                                              13500000
    end                                                                 13505000
  else                                                                  13510000
    begin << It's a write >>                                            13515000
    SUDDENDEATH(CDT'INVALID'STATE);                                     13520000
    end;                                                                13525000
                                                                        13530000
  << Waken request >>                                                   13535000
  WAKE'LDR;                                                             13540000
  end;                                                                  13545000
                                                                        13550000
  <<2>> << Write state >>                                               13555000
  begin                                                                 13560000
  if FUNCTION = READREQ then                                            13565000
    begin << It's a read >>                                             13570000
    CDT'DEQUEUE'LDR(CDT'ENTRY,DISC'REQ,CDT'MD'LDR'HEAD);                13575000
$if x1=on                                                      <<*7724>>13580000
    CDT'ADD'WORD(CDT'ENTRY,CDT'MD'READ'CNT,-1);                         13585000
$if x1=off                                                     <<*7724>>13590000
    CDT'X := MAPD'OFFSET + CDT'MD'READ'CNT;                    <<*7724>>13595000
    CDT'ARRAY(CDT'X) := CDT'ARRAY(CDT'X) - 1;                  <<*7724>>13600000
$if                                                            <<*7724>>13605000
                                                                        13610000
    << If the CDT's active queue is empty, move requests >>             13615000
    << over from the pending queue.                      >>             13620000
    if CDT'ARRAY(MAPD'OFFSET+CDT'MD'LDR'HEAD) = 0 AND          <<s7729>>13625000
       CDT'ARRAY(MAPD'OFFSET+CDT'MD'FLAGS).CDT'NOPOST = 0 THEN <<s7729>>13630000
                                                               <<s7729>>13635000
       << Don't let any more writes onto the active queue    >><<s7729>>13640000
       << until any pending no-wait-on-posts have completed. >><<s7729>>13645000
                                                               <<s7729>>13650000
                                                               <<s7729>>13655000
      MOVE'QUEUE;                                                       13660000
    end                                                                 13665000
  else                                                                  13670000
    begin << It's a write >>                                            13675000
    if DISC'REQ = 0 then                                                13680000
      begin  << This must be a NOPOST I/O completion >>                 13685000
      CDT'ARRAY(MAPD'OFFSET+CDT'MD'FLAGS).                     <<*7724>>13690000
                (CDT'WAIT'ON'NOPOST:1) := 0;                   <<*7724>>13695000
      if = then                                                <<*7724>>13700000
        SUDDENDEATH(CDT'LOGIC'PROBLEM);<< We got problems...>>          13705000
      end                                                               13710000
    else                                                                13715000
      begin << See if this is a NOPOST move completion >>               13720000
      if not LDR'DO'POST then                                  <<06858>>13725000
        begin  << Yes, so don't decrement write count yet >>            13730000
        CDT'ARRAY(MAPD'OFFSET+CDT'MD'FLAGS).                   <<*7724>>13735000
                  (CDT'WAIT'ON'NOPOST:1) := 1;                 <<*7724>>13740000
        if <>                                                  <<*7724>>13745000
          then SUDDENDEATH(CDT'LOGIC'PROBLEM);                          13750000
        end;                                                            13755000
      CDT'DEQUEUE'LDR(CDT'ENTRY,DISC'REQ,CDT'MD'LDR'HEAD);              13760000
      end;                                                              13765000
                                                                        13770000
    << If we aren't waiting on a no-post completion, continue>>         13775000
    if CDT'ARRAY(MAPD'OFFSET+CDT'MD'FLAGS).                    <<*7724>>13780000
                 (CDT'WAIT'ON'NOPOST:1) = 0 then               <<*7724>>13785000
      begin                                                             13790000
      CDT'X := MAPD'OFFSET + CDT'MD'WRITE'CNT;                 <<*7724>>13795000
      tos := CDT'ARRAY(CDT'X) := CDT'ARRAY(CDT'X) - 1;         <<*7724>>13800000
      if tos = 0 then                                          <<*7724>>13805000
        begin  << All writes have completed >>                          13810000
        CDT'X := MAPD'OFFSET + CDT'MD'READ'CNT;                <<*7724>>13815000
        if CDT'ARRAY(CDT'X) = 0 then                           <<*7724>>13820000
          begin << All activity to this CDT has completed >>            13825000
          UNIMPEDE'WAITORS;                                    <<*8399>>13830000
          SETSTATE(CDT'AVAIL'STATE);                                    13835000
          RELEASE'CDT;                                                  13840000
          end                                                           13845000
        else                                                            13850000
          begin  << There is other pending "read" activity >>           13855000
          MOVE'QUEUE; << Move all deferred to active queue >>           13860000
          SETSTATE(CDT'READ'STATE);                                     13865000
          end;                                                          13870000
        end                                                             13875000
      else                                                              13880000
        begin  << There are still writes remaining. >>                  13885000
        CDT'X := MAPD'OFFSET + CDT'MD'LDR'HEAD;                <<*7724>>13890000
        if CDT'ARRAY(CDT'X) = 0 then                           <<*7724>>13895000
          MOVE'QUEUE; << Move up to the next WRITE >>                   13900000
        end;                                                            13905000
      end;                                                              13910000
    end;                                                                13915000
                                                                        13920000
  << Waken caller >>                                                    13925000
  WAKE'LDR;                                                             13930000
  end;                                                                  13935000
                                                                        13940000
  <<3>> << Flush requests >>                                            13945000
  begin                                                                 13950000
  if FUNCTION = READREQ then                                            13955000
    begin << It's a read >>                                             13960000
    CDT'DEQUEUE'LDR(CDT'ENTRY,DISC'REQ,CDT'MD'LDR'HEAD);                13965000
    CDT'X := MAPD'OFFSET + CDT'MD'READ'CNT;                    <<*7724>>13970000
    tos := CDT'ARRAY(CDT'X) := CDT'ARRAY(CDT'X) - 1;           <<*7724>>13975000
    if tos = 0 then                                            <<*7724>>13980000
      begin                                                             13985000
      if CDT'ARRAY(MAPD'OFFSET+CDT'MD'WRITE'CNT) = 0 then      <<*7724>>13990000
        begin << We're all done with this CDT >>                        13995000
        SETSTATE(CDT'AVAIL'STATE);                                      14000000
        RELEASE'CDT;                                                    14005000
        end                                                             14010000
      else                                                              14015000
        begin  << reads=0, writes>0 >>                                  14020000
        end;                                                            14025000
      end                                                               14030000
    else                                                                14035000
      begin  << reads>0, writes=? >>                                    14040000
      end;                                                              14045000
    end                                                                 14050000
  else                                                                  14055000
    begin << It's a write >>                                            14060000
    CDT'DEQUEUE'LDR(CDT'ENTRY,DISC'REQ,CDT'MD'LDR'HEAD);                14065000
    CDT'X := MAPD'OFFSET + CDT'MD'WRITE'CNT;                   <<*7724>>14070000
    tos := CDT'ARRAY(CDT'X) := CDT'ARRAY(CDT'X) - 1;           <<*7724>>14075000
    if tos = 0 then                                            <<*7724>>14080000
      begin                                                             14085000
      CDT'X := MAPD'OFFSET + CDT'MD'READ'CNT;                  <<*7724>>14090000
      if CDT'ARRAY(CDT'X) = 0 then                             <<*7724>>14095000
        begin  << We're all done with this CDT >>                       14100000
        STATE := CDT'AVAIL'STATE;                                       14105000
        RELEASE'CDT;                                                    14110000
        end                                                             14115000
      else                                                              14120000
        begin << writes=0, reads>0 >>                                   14125000
        MOVE'QUEUE;                                                     14130000
        end;                                                            14135000
      end                                                               14140000
    else                                                                14145000
      begin << writes>0, reads=? >>                                     14150000
      MOVE'QUEUE;                                                       14155000
      end;                                                              14160000
    end;                                                                14165000
                                                                        14170000
  << Waken caller >>                                                    14175000
  WAKE'LDR;                                                             14180000
  end;                                                                  14185000
                                                                        14190000
  <<4>> << LOCKED CDT entry >>                                          14195000
  begin                                                                 14200000
  << Lock code should NEVER execute completor >>                        14205000
  SUDDENDEATH(CDT'INVALID'STATE);                                       14210000
  end;                                                                  14215000
                                                                        14220000
  end;  << of case on STATE >>                                          14225000
                                                                        14230000
<< We will now leave this procedure >>                                  14235000
Leave'routine:                                                          14240000
                                                                        14245000
<< Put DB back to caller's DB >>                               <<*7724>>14250000
tos := SAVE'DB;                                                <<*7724>>14255000
EXCHDB;                                                        <<*7724>>14260000
end;  << of procedure CDT'INITIATOR and CDT'COMPLETOR >>                14265000
$page "Procedure REQUEST'CACHE"                                         14270000
logical procedure REQUEST'CACHE(DISCREQ);                               14275000
value DISCREQ;                                                          14280000
integer DISCREQ;                                                        14285000
option privileged,uncallable,internal;                         <<06858>>14290000
begin                                                                   14295000
                                                                        14300000
<<********************************************************************>>14305000
<< This procedure is called from ATTACHIO after determining that the  >>14310000
<< I/O to be performed is against DISC, and this DISC is currently    >>14315000
<< CACHED as specified by the FLAGS word of the disc's DIT.  If the   >>14320000
<< function requested against this disc is not of concern to CACHING, >>14325000
<< a return of FALSE to ATTACHIO indicates that ATTACHIO should issue >>14330000
<< the request through P'ATTACHIO.  If this is a data-transfer func-  >>14335000
<< tion, this procedure will return TRUE to ATTACHIO, indicating that >>14340000
<< CACHING will take responsibility for performing the I/O operation. >>14345000
<<                                                                    >>14350000
<< At this point, the CDT and memory regions for this disc are ex-    >>14355000
<< amined to determine if the requested data exists in main memory.   >>14360000
<< The cache service routines are then called to get everything going >>14365000
<< for this request.                                                  >>14370000
<<                                                                    >>14375000
<< The passed parameter to this procedure is:                         >>14380000
<<                                                                    >>14385000
<< DISCREQ- An LDR relative index to the logical disc req. asso<<07311>>14390000
<<          ciated with this request.  ATTACHIO is responsible for    >>14395000
<<          filling-in the request with the proper data.              >>14400000
<<                                                                    >>14405000
<< The returned parameter is:                                         >>14410000
<<                                                                    >>14415000
<< REQUEST'CACHE - TRUE indicates (to CDT'ATTACHIO) that     >><<07311>>14420000
<<                 caching has accepted the                  >><<07311>>14425000
<<                 request and takes the responsibility for  >><<07311>>14430000
<<                 processing it.                                     >>14435000
<<                 FALSE indicates that the request has been ignored  >>14440000
<<                 by caching, and must be handled by ATTACHIO.       >>14445000
<<                                                                    >>14450000
<< DB is assumed to be at SYSDB in this procedure.  It is guaranteed  >>14455000
<< that the caller will not be blocked if so specified in the FLAGS   >>14460000
<< word of the LDR.                                                   >>14465000
<<********************************************************************>>14470000
                                                                        14475000
integer LDEV'LINK'PTR,           << Pointer to next LDEV CDT entry    >>14480000
        LDEV,                    << The LDEV number of the current CDT>>14485000
        FUNCTN,                  << LDR's function                    >>14490000
        CDT'LINK'PTR,            << Pointer to next cache CDT entry   >>14495000
        RETURN'CODE,             << Return code from scan subroutine  >>14500000
        CDT'ENTRY,               << CDT'ENTRY found on scan           >>14505000
        MISS'ENTRY,              << CDT'ENTRY just past where CDT shd >>14510000
                                 << have been on MISS, or points to   >>14515000
                                 << first partially-mapped domain.    >>14520000
        COUNT;                   << Number of positive bytes in xfer  >>14525000
                                                                        14530000
<< it SHOULD be added to the measurement interface include  >> <<*8735>>14535000
<< file as soon as possible.  >>                               <<*8735>>14540000
EQUATE  C'IMPEDECACHE = 74 ;                                   <<*8735>>14545000
                                                               <<*8735>>14550000
logical LDR'ENTRY'INDEX=DISCREQ, << Satisfies LDR defines requi<<07308>>14555000
        IS'READ;                 << TRUE if I/O request was a r<<07308>>14560000
                                                                        14565000
double  LDR'ADR,                 << Base disc address in LDR entry    >>14570000
        CDT'ADR;                 << Base disc address in CDT entry    >>14575000
                                                                        14580000
integer LDR'P1    = LDR'ADR,                                            14585000
        LDR'P2    = LDR'P1 + 1;                                         14590000
                                                                        14595000
integer LDEV'LINK'OFFSET, << Word offset, LDEV entry in CDT >> <<*7724>>14600000
        CDT'LINK'OFFSET;  << Word offset, MAPD entry in CDT >> <<*7724>>14605000
                                                               <<*7724>>14610000
double  UPPER'CDT'ADR,             << High CDT disc address           >>14615000
        UPPER'LDR'ADR;             << High LDR disc address required  >>14620000
double STARTCACHETIME;                                                  14625000
                                                               <<*7724>>14630000
                                                               <<*7724>>14635000
                                                               <<*7724>>14640000
                                                               <<*7724>>14645000
                                                               <<*7724>>14650000
                                                               <<*7724>>14655000
$page                                                                   14660000
subroutine RESET'TOTALS;                                                14665000
begin                                                                   14670000
                                                                        14675000
<< This subroutine is called when an accumulator overflows >>           14680000
CDT'SET'DOUBLE(LDEV'LINK'PTR,CDT'DE'RHIT,0D);                  <<07308>>14685000
CDT'SET'DOUBLE(LDEV'LINK'PTR,CDT'DE'WHIT,0D);                  <<07308>>14690000
CDT'SET'DOUBLE(LDEV'LINK'PTR,CDT'DE'RMISS,0D);                 <<07308>>14695000
CDT'SET'DOUBLE(LDEV'LINK'PTR,CDT'DE'WMISS,0D);                 <<07308>>14700000
CDT'SET'DOUBLE(LDEV'LINK'PTR,CDT'DE'STOP,0D);                  <<07308>>14705000
                                                                        14710000
end;  << of subroutine RESET'TOTALS >>                                  14715000
$page                                                          <<*7724>>14720000
subroutine INC'HIT;                                            <<*7724>>14725000
begin                                                          <<*7724>>14730000
                                                               <<*7724>>14735000
$if x1=on                                                      <<*7724>>14740000
if CDT'ADD'DOUBLE(LDEV'LINK'PTR,if IS'READ then CDT'DE'RHIT    <<*7724>>14745000
                  else CDT'DE'WHIT,1D) <= 0D then              <<*7724>>14750000
  RESET'TOTALS;                                                <<*7724>>14755000
$if x1=off                                                     <<*7724>>14760000
if IS'READ then                                                <<*7724>>14765000
  tos := CDT'DARRAY((LDEV'LINK'OFFSET+CDT'DE'RHIT)&asr(1))     <<*7724>>14770000
else                                                           <<*7724>>14775000
  tos := CDT'DARRAY((LDEV'LINK'OFFSET+CDT'DE'WHIT)&asr(1));    <<*7724>>14780000
tos := tos + 1D;      << Increment counter >>                  <<*7724>>14785000
if overflow then                                               <<*7724>>14790000
  begin                                                        <<*7724>>14795000
  ASMB(DDEL);                                                  <<*7724>>14800000
  RESET'TOTALS;                                                <<*7724>>14805000
  end                                                          <<*7724>>14810000
else                                                           <<*7724>>14815000
  begin                                                        <<*7724>>14820000
  CDT'DARRAY(CDT'X) := tos; << Store back parameter(s)>>       <<*7724>>14825000
  end;                                                         <<*7724>>14830000
$if                                                            <<*7724>>14835000
                                                               <<*7724>>14840000
if CLASS0STATSENABLED then                                     <<*7724>>14845000
   if FUPDATESTATISTICS(MEASCLASS0,MEASSUBCLASS0,MEASENTRY1,   <<*7724>>14850000
                       if IS'READ then C'CACHEREADHITS         <<*7724>>14855000
                       else C'CACHEWRITEHITS,                  <<*7724>>14860000
                       NOTNEWVALUE,1D,NOTDOUBLE)               <<*7724>>14865000
   <> 0 then SUDDENDEATH(SFKERNCACHEINTBAD);                   <<*7724>>14870000
                                                               <<*7724>>14875000
end;                                                           <<*7724>>14880000
$page                                                          <<*7724>>14885000
subroutine INC'MISS;                                           <<*7724>>14890000
begin                                                          <<*7724>>14895000
                                                               <<*7724>>14900000
$if x1=on                                                      <<*7724>>14905000
if CDT'ADD'DOUBLE(LDEV'LINK'PTR,if IS'READ then CDT'DE'RMISS   <<*7724>>14910000
                  else CDT'DE'WMISS,1D) <= 0D then             <<*7724>>14915000
  RESET'TOTALS;                                                <<*7724>>14920000
$if x1=off                                                     <<*7724>>14925000
if IS'READ then                                                <<*7724>>14930000
  tos := CDT'DARRAY((LDEV'LINK'OFFSET+CDT'DE'RMISS)&asr(1))    <<*7724>>14935000
else                                                           <<*7724>>14940000
  tos := CDT'DARRAY((LDEV'LINK'OFFSET+CDT'DE'WMISS)&asr(1));   <<*7724>>14945000
tos := tos + 1D;      << Increment counter >>                  <<*7724>>14950000
if overflow then                                               <<*7724>>14955000
  begin                                                        <<*7724>>14960000
  ASMB(DDEL);                                                  <<*7724>>14965000
  RESET'TOTALS;                                                <<*7724>>14970000
  end                                                          <<*7724>>14975000
else                                                           <<*7724>>14980000
  begin                                                        <<*7724>>14985000
  CDT'DARRAY(CDT'X) := tos; << Store back parameter(s)>>       <<*7724>>14990000
  end;                                                         <<*7724>>14995000
$if                                                            <<*7724>>15000000
                                                               <<*7724>>15005000
end;                                                           <<*7724>>15010000
$page                                                                   15015000
logical subroutine CACHE'THIS'FUNCTION;                                 15020000
begin                                                                   15025000
                                                                        15030000
<< This subroutine examines the function specified in the LDR for this>>15035000
<< request and returns TRUE if this function is to be managed by the  >>15040000
<< cache routines.                                                    >>15045000
                                                                        15050000
if COUNT = 0 then                                                       15055000
  CACHE'THIS'FUNCTION := false                                          15060000
else                                                                    15065000
  begin                                                                 15070000
  if (LDEV'LINK'PTR := CDT'FIND'DE(LDR'LDEV)) = 0 then         <<06858>>15075000
    CACHE'THIS'FUNCTION := false << Caching shut-off >>        <<06858>>15080000
  ELSE                                                         <<06858>>15085000
    BEGIN                                                      <<06858>>15090000
    if (FUNCTN := LDR'FUNC) = READREQ then                     <<06858>>15095000
      begin                                                    <<07308>>15100000
      IS'READ := CACHE'THIS'FUNCTION := true;                  <<07308>>15105000
      end                                                      <<07308>>15110000
    else if FUNCTN = WRITEREQ then                             <<06858>>15115000
      begin                                                    <<06858>>15120000
      IS'READ := false;                                        <<07308>>15125000
                                                               <<07308>>15130000
      CACHE'THIS'FUNCTION := true;                             <<06858>>15135000
      end                                                      <<06858>>15140000
    else                                                       <<06858>>15145000
      CACHE'THIS'FUNCTION := false;                            <<06858>>15150000
    end;                                                       <<06858>>15155000
  LDEV'LINK'OFFSET := LDEV'LINK'PTR * CDT'ENTRY'SIZE;          <<*7724>>15160000
  end;                                                         <<06858>>15165000
end; << of  subroutine CACHE'THIS'FUNCTION >>                           15170000
$page                                                                   15175000
subroutine SCAN'CDTS'FOR'HIT;                                           15180000
begin                                                                   15185000
<<********************************************************************>>15190000
<< This subroutine scans the cached CDT entries for a "hit" on this   >>15195000
<< disc domain.                                                       >>15200000
<<                                                                    >>15205000
<< Input parameters:  not examined.                                   >>15210000
<<                                                                    >>15215000
<< Return parameters:                                                 >>15220000
<<                                                                    >>15225000
<<      CDT'ENTRY     - Cached CDT entry of 'hit' on disc address.    >>15230000
<<                      Valid only if RETURN'CODE is 0.               >>15235000
<<      MISS'ENTRY    - Mapped CDT following desired domain, or first >>15240000
<<                      domain that is partially mapped.  Valid if    >>15245000
<<                      RETURN'CODE is 1 or 2.  Set to 0 if beginning,>>15250000
<<                      or -1 if tail.                                >>15255000
<<      RETURN'CODE   - Indicates the results of the scan, which are: >>15260000
<<                      0 - CDT entry found that satisfies entire     >>15265000
<<                          requested disc domain.                    >>15270000
<<                      1 - CDT entry found that partially covers     >>15275000
<<                          requested disc domain.                    >>15280000
<<                      2 - No CDT entry found which corresponds to   >>15285000
<<                          this disc domain.                         >>15290000
<< DB is assumed to be at the CDT.                             <<*7724>>15295000
<<********************************************************************>>15300000
                                                                        15305000
<< Find actual cache CDT entry, if it exists >>                         15310000
<< Load low LDR address >>                                              15315000
LDR'P1 := LDR'PARM1;                                                    15320000
LDR'P2 := LDR(CDT'X:=CDT'X+1);   << LDR'ADR is now loaded >>            15325000
                                                                        15330000
<< Figure high LDR disc address >>                                      15335000
UPPER'LDR'ADR := double((COUNT+127)&lsr(7))+LDR'ADR;                    15340000
                                                                        15345000
<< Get pointer to first mapped domain >>                                15350000
$if x1=on                                                      <<*7724>>15355000
tos := CDT'LINK'PTR := CDT'GET'WORD(LDEV'LINK'PTR,             <<*7724>>15360000
                                    CDT'DE'MAPD'HEAD,0);       <<*7724>>15365000
$if x1=off                                                     <<*7724>>15370000
tos := CDT'LINK'PTR := CDT'ARRAY(LDEV'LINK'OFFSET +            <<*7724>>15375000
                                 CDT'DE'MAPD'HEAD);            <<*7724>>15380000
$if                                                            <<*7724>>15385000
if (tos = 0) then                                              <<*7724>>15390000
                                                               <<*7724>>15395000
  begin  << This is a miss, and CDT must be added to head >>            15400000
  RETURN'CODE := 2;                                                     15405000
  MISS'ENTRY := 0;                                                      15410000
  end                                                                   15415000
else                                                                    15420000
  << We must loop >>                                                    15425000
  begin                                                                 15430000
  << Wizz through mapped CDT domains >>                                 15435000
  while CDT'LINK'PTR <> 0 do                                            15440000
    begin                                                               15445000
    CDT'LINK'OFFSET := CDT'LINK'PTR * CDT'ENTRY'SIZE;          <<*7724>>15450000
$if x1=on                                                      <<*7724>>15455000
    tos:=UPPER'CDT'ADR:=CDT'GET'DOUBLE(CDT'LINK'PTR,           <<*7724>>15460000
                                       CDT'MD'END'SECTOR,0D);  <<*7724>>15465000
$if x1=off                                                     <<*7724>>15470000
    tos:=UPPER'CDT'ADR:=                                       <<*7724>>15475000
        CDT'DARRAY((CDT'LINK'OFFSET+CDT'MD'END'SECTOR)&asr(1));<<*7724>>15480000
$if                                                            <<*7724>>15485000
                                                                        15490000
    << if cache addr is higher than disc address, skip checking >>      15495000
    if tos <<UPPER'CDT'ADR>> > LDR'ADR then                    <<*7724>>15500000
      begin  << We have a hit, check if it's partial, full, or miss >>  15505000
                                                                        15510000
      << Get lower CDT address >>                                       15515000
$if x1=on                                                      <<*7724>>15520000
      tos := CDT'ADR :=                                        <<*7724>>15525000
             CDT'GET'DOUBLE(CDT'LINK'PTR,CDT'MD'SECTOR,0D);    <<*7724>>15530000
$if x1=off                                                     <<*7724>>15535000
      tos := CDT'ADR :=                                        <<*7724>>15540000
            CDT'DARRAY((CDT'LINK'OFFSET+CDT'MD'SECTOR)&asr(1));<<*7724>>15545000
$if                                                            <<*7724>>15550000
                                                                        15555000
      <<If low address is beyond high LDR address, then it's a miss>>   15560000
      if tos <<CDT'ADR>> >= UPPER'LDR'ADR then                 <<*7724>>15565000
        begin  << yep, it's a miss >>                                   15570000
        MISS'ENTRY := CDT'LINK'PTR;                                     15575000
        RETURN'CODE := 2;                                               15580000
        return;                                                         15585000
        end;                                                            15590000
                                                                        15595000
      <<We know we have at least a partial hit.  We will now range >>   15600000
      <<check to see if we can satisfy the LDR with this CDT.  >>       15605000
      if CDT'ADR <= LDR'ADR and                                         15610000
         UPPER'CDT'ADR >= UPPER'LDR'ADR then                            15615000
        begin  << WE HAVE A TOTAL HIT! >>                               15620000
        CDT'ENTRY := CDT'LINK'PTR;                                      15625000
        RETURN'CODE := 0;                                               15630000
        end                                                             15635000
      else                                                              15640000
        begin << We have a partial hit >>                               15645000
        MISS'ENTRY := CDT'LINK'PTR;                                     15650000
        RETURN'CODE := 1;                                               15655000
        end;                                                            15660000
      return;   << to caller >>                                         15665000
      end;  << of processing a 'hit' >>                                 15670000
                                                                        15675000
    << Increment to next CDT entry >>                                   15680000
$if x1=on                                                      <<*7724>>15685000
    CDT'LINK'PTR := CDT'GET'WORD(CDT'LINK'PTR,CDT'MD'NEXT,0);           15690000
$if x1=off                                                     <<*7724>>15695000
    CDT'LINK'PTR := CDT'ARRAY(CDT'LINK'OFFSET+CDT'MD'NEXT);    <<*7724>>15700000
$if                                                            <<*7724>>15705000
                                                                        15710000
    end; << of 'while' stmt wizzing through CDT entries >>              15715000
                                                                        15720000
  << At this point, we know that the disc address being      >>         15725000
  << requested is beyond any currently mapped domains.  Mark it >>      15730000
  << as a 'miss' at this point.                                       >>15735000
  MISS'ENTRY := -1;  << At end-of-chain >>                              15740000
  RETURN'CODE := 2;                                                     15745000
  end;                                                                  15750000
                                                                        15755000
end;  << of subroutine SCAN'CDTS'FOR'HIT >>                             15760000
$page                                                                   15765000
subroutine HIT'ON'CACHE;                                                15770000
begin                                                                   15775000
                                                                        15780000
INC'HIT;                                                       <<*7724>>15785000
                                                               <<*7724>>15790000
                                                               <<*7724>>15795000
                                                               <<*7724>>15800000
                                                               <<*7724>>15805000
                                                               <<*7724>>15810000
                                                               <<*7724>>15815000
                                                               <<*7724>>15820000
                                                               <<*7724>>15825000
                                                                        15830000
<< Go ahead and link this LDR to the CDT entry >>                       15835000
CDT'INITIATOR(CDT'ENTRY,DISCREQ);                                       15840000
                                                                        15845000
end;                                                                    15850000
$page                                                                   15855000
$if x7=on                                                      <<06858>>15860000
subroutine PARTIAL'HIT;                                                 15865000
begin                                                                   15870000
                                                                        15875000
<<******************************************************>>              15880000
<< Patial's are NOT supported yet...                    >>              15885000
assemble(halt 7);                                                       15890000
<<******************************************************>>              15895000
                                                                        15900000
<< Count this as a MISS >>                                              15905000
INC'MISS;                                                      <<*7724>>15910000
                                                               <<*7724>>15915000
                                                               <<*7724>>15920000
                                                                        15925000
<< Lock range >>                                                        15930000
CDT'ENTRY := CDT'LOCK'RANGE(LDEV'LINK'PTR,LDR'ADR,UPPER'LDR'ADR);       15935000
                                                                        15940000
<< Queue this request to the locked CDT entry >>                        15945000
CDT'INITIATOR(CDT'ENTRY,DISCREQ);                                       15950000
                                                                        15955000
end;                                                                    15960000
$if                                                            <<06858>>15965000
$page                                                                   15970000
subroutine MISS'ON'CDT;                                                 15975000
begin                                                                   15980000
                                                                        15985000
<< Get CDT entry and put in list >>                                     15990000
CDT'ENTRY:=CDT'GET'MD'ENTRY(LDEV'LINK'PTR,LDR'ADR,MISS'ENTRY);          15995000
CDT'LINK'OFFSET := CDT'ENTRY * CDT'ENTRY'SIZE;                 <<*7724>>16000000
                                                               <<07308>>16005000
                                                               <<07308>>16010000
                                                                        16015000
<< Now, we will see if unmapped region exists >>                        16020000
if CDT'MAP'CACHED'DOMAIN(LDEV'LINK'PTR,LDR'ADR,UPPER'LDR'ADR,           16025000
                         CDT'ENTRY,DISCREQ) THEN               <<07308>>16030000
  begin  << We found a HIT >>                                           16035000
  INC'HIT;                                                     <<*7724>>16040000
                                                               <<*7724>>16045000
                                                               <<*7724>>16050000
                                                               <<*7724>>16055000
                                                               <<*7724>>16060000
                                                               <<*7724>>16065000
                                                               <<*7724>>16070000
                                                               <<*7724>>16075000
                                                               <<*7724>>16080000
                                                               <<*7724>>16085000
                                                               <<*7724>>16090000
                                                               <<*7724>>16095000
  end                                                                   16100000
else                                                                    16105000
  begin  << We had a total miss, so get a CDT and fill it in >>         16110000
                                                                        16115000
  INC'MISS;                                                    <<*7724>>16120000
                                                               <<*7724>>16125000
                                                               <<*7724>>16130000
                                                                        16135000
  << Mark CDT entry as "MISS" >>                                        16140000
  CDT'ARRAY(CDT'LINK'OFFSET+CDT'MD'FLAGS).(CDT'MISS'BIT:1):=1; <<*7724>>16145000
                                                                        16150000
  << If MONITOR is enabled, report strategy applied >>                  16155000
  if MEASFLAG then                                             <<*7551>>16160000
    begin                                                               16165000
    MMSTAT'(-133,COUNT,LDR'P1,LDR'P2,0,0,0);                   <<06859>>16170000
    MMSTAT'(-134,CDT'GET'WORD(CDT'ENTRY,CDT'MD'SECTOR,0),      <<06859>>16175000
           CDT'GET'WORD(CDT'ENTRY,CDT'MD'SECTOR+1,0),                   16180000
           LDR'FLAGS,0,0,0);                                   <<06859>>16185000
    MMSTAT'(-135,CDT'GET'WORD(CDT'ENTRY,CDT'MD'END'SECTOR,0),  <<06859>>16190000
           CDT'GET'WORD(CDT'ENTRY,CDT'MD'END'SECTOR+1,0),               16195000
           LDR'FUNC,0,0,0);                                    <<06859>>16200000
    MMSTAT'(-136,LDR'B'HODA,LDR'B'LODA,LDR'L'LODA,0,0,0);      <<06859>>16205000
    end;                                                                16210000
  end;                                                                  16215000
                                                                        16220000
<< Link LDR to newly obtained CDT >>                                    16225000
CDT'INITIATOR(CDT'ENTRY,DISCREQ);                                       16230000
                                                                        16235000
end;                                                                    16240000
$page                                                                   16245000
<< Begin procedure mainline >>                                          16250000
                                                                        16255000
$if x1=on                                                               16260000
MMSTAT'(MMSTAT'REQ'CACHE,DISCREQ,0,0,0,0,0);                   <<06859>>16265000
$if                                                                     16270000
                                                                        16275000
<< Initialize return code >>                                            16280000
REQUEST'CACHE := false;                                                 16285000
                                                                        16290000
tos := LDR'COUNT;                                                       16295000
if < then                                                               16300000
  tos := ((-tos)+1) & lsr(1); << Make words >>                          16305000
COUNT := tos;                                                           16310000
                                                                        16315000
if CACHE'THIS'FUNCTION then                                             16320000
   BEGIN <<function is cachable>>                                       16325000
                                                                        16330000
   if CLASS0STATSENABLED then                                           16335000
      begin <<update meas instrumentation>>                             16340000
      startcachetime := TIMER;                                 <<06858>>16345000
      if FUPDATESTATISTICS(MEASCLASS0,MEASSUBCLASS0,MEASENTRY1,         16350000
                          IF IS'READ THEN C'CACHEREADS         <<07308>>16355000
                          ELSE C'CACHEWRITES,                           16360000
                          NOTNEWVALUE,1D,NOTDOUBLE)                     16365000
      <> 0 then SUDDENDEATH(SFKERNCACHEINTBAD);                         16370000
      end;                                                              16375000
                                                                        16380000
   << Place DB at CDT >>                                       <<*7724>>16385000
   CDT'ABS'ON'TOS;                                             <<*7724>>16390000
   EXCHDB;                                                     <<*7724>>16395000
   ASMB(DDEL);                                                 <<*7724>>16400000
                                                               <<*7724>>16405000
   <<Look thru CDT's for this dev for mapped domains>>                  16410000
Loopkludge:                                                             16415000
                                                               <<*8003>>16420000
   IF CACHE'DST = 0 THEN  GO OUT;                              <<*8003>>16425000
   SCAN'CDTS'FOR'HIT;                                                   16430000
                                                                        16435000
   case *RETURN'CODE of                                        <<*7724>>16440000
      begin                                                             16445000
                                                                        16450000
      <<0>> HIT'ON'CACHE;     << CDT fully satisfies request >>         16455000
                                                                        16460000
      <<1>> <<PARTIAL'HIT;>>  << CDT partially satisfies request >>     16465000
            << This code should be eliminated if the LOCK code <<06858>>16470000
            << is ever implemented.  Since the occurance of thi<<06858>>16475000
            << section of code is extremely low, it may never b<<06858>>16480000
            << done.  (AJK)                                    <<06858>>16485000
            begin  << Kludge until code is done >>                      16490000
                                                               <<07308>>16495000
            << Measure cache STOP event >>                     <<07308>>16500000
            if CDT'ADD'DOUBLE(LDEV'LINK'PTR,CDT'DE'STOP,1D)    <<07308>>16505000
              <= 0D then RESET'TOTALS;                         <<07308>>16510000
                                                               <<*7724>>16515000
            << Point back to SYSDB before PENABLE >>           <<*7724>>16520000
            tos := %1000 D;                                    <<*7724>>16525000
            EXCHDB;                                            <<*7724>>16530000
                                                               <<*8735>>16535000
         << we must save the accumulated time doing cache >>   <<*8735>>16540000
         << management on the process' stack.  this time  >>   <<*8735>>16545000
         << will start accumulating again when we return  >>   <<*8735>>16550000
         << from the delay.  >>                                <<*8735>>16555000
            STARTCACHETIME := TIMER - STARTCACHETIME;          <<*8735>>16560000
                                                               <<*8735>>16565000
<< Count impedes due to disc caching.  This is a double count>><<*8735>>16570000
                                                               <<*8735>>16575000
if CLASS0STATSENABLED then                                     <<*8735>>16580000
  if FUPDATESTATISTICS(MEASCLASS0,MEASSUBCLASS0,MEASENTRY1,    <<*8735>>16585000
           C'IMPEDECACHE,NOTNEWVALUE,1D,NOTDOUBLE)             <<*8735>>16590000
   <> 0 then SUDDENDEATH(SFKernCacheIntBad) ;                  <<*8735>>16595000
                                                               <<*8735>>16600000
<< this uses the old counter cp'segcontract to count impedes >><<*8735>>16605000
<< due to caching.  the old counters for cp'segcontract have >><<*8735>>16610000
<< been removed from KERNELD.  this counter should be renamed>><<*8735>>16615000
<< CP'IMPEDECACHE in the measurement include file ASAP!!!!!!!>><<*8735>>16620000
if GCLASSENABLEDMASK.CLASS15 then                              <<*8735>>16625000
   begin                                                       <<*8735>>16630000
   TOS:=MEASPROCXDSBANK;                                       <<*8735>>16635000
   TOS:=MEASPROCXDSBASE;                                       <<*8735>>16640000
   TOS:=TOS + CURPRC / PCBSIZE * CLASS15'SUB0SIZE +            <<*8735>>16645000
        CP'SEGCONTRACT ;                                       <<*8735>>16650000
   ASMB(LSEA);                                                 <<*8735>>16655000
   TOS:=TOS+1;                                                 <<*8735>>16660000
   ASMB(SSEA;DDEL);                                            <<*8735>>16665000
   end;                                                        <<*8735>>16670000
            tos := 100D;  << 100 ms >>                        <<*fast*>>16675000
            PENABLE;                                                    16680000
            DELAY(*);                                                   16685000
            PDISABLE;                                                   16690000
                                                               <<*8735>>16695000
         << restore the delta by subtracting the time >>       <<*8735>>16700000
         << accumulated before the delay. >>                   <<*8735>>16705000
            STARTCACHETIME := TIMER - STARTCACHETIME;          <<*8735>>16710000
                                                               <<*8735>>16715000
            << Point DB back to CDT >>                         <<*7724>>16720000
            EXCHDB;                                            <<*7724>>16725000
            ASMB(DDEL);                                        <<*7724>>16730000
            go to Loopkludge;                                           16735000
            end;                                                        16740000
                                                                        16745000
      <<2>> MISS'ON'CDT;      << No overlapping CDT entry found >>      16750000
                                                                        16755000
      end;                                                              16760000
                                                                        16765000
   <<Inform ATTACHIO that caching will be responsible for the I/O >>    16770000
                                                                        16775000
   REQUEST'CACHE := true;                                               16780000
                                                                        16785000
   if CLASS0STATSENABLED then                                           16790000
      begin                                                    <<*8735>>16795000
      if FUPDATESTATISTICS(MEASCLASS0,MEASSUBCLASS0,MEASENTRY1,         16800000
                          C'CACHEONPROCESS,NOTNEWVALUE,                 16805000
                          TIMER-STARTCACHETIME,DOUBLEVALUE)    <<06858>>16810000
      <> 0 then SUDDENDEATH(SFKERNCACHEINTBAD);                         16815000
                                                               <<*8735>>16820000
      <<we must subtract c'cacheonprocess from c'cpuprocess  >><<*8735>>16825000
      <<because cache mgt time is later added to c'cpuprocess>><<*8735>>16830000
      <<thus total time on the process' stack is c'cpuprocess>><<*8735>>16835000
      << + c'cacheonprocess.                                 >><<*8735>>16840000
                                                               <<*8735>>16845000
      if FUPDATESTATISTICS(MEASCLASS0,MEASSUBCLASS0,MEASENTRY1,<<*8735>>16850000
                           C'CPUPROCESS,NOTNEWVALUE,           <<*8735>>16855000
                           STARTCACHETIME-TIMER,DOUBLEVALUE)   <<*8735>>16860000
      <> 0 then SUDDENDEATH(SFKernCacheIntBad);                <<*8735>>16865000
      end ;                                                    <<*8735>>16870000
                                                                        16875000
                                                               <<*8003>>16880000
OUT:                                                           <<*8003>>16885000
                                                               <<*8003>>16890000
   << Put DB back to SYSDB >>                                  <<*7724>>16895000
   tos := %1000 D;                                             <<*7724>>16900000
   EXCHDB;                                                     <<*7724>>16905000
   ASMB(DDEL);                                                 <<*7724>>16910000
                                                               <<*7724>>16915000
   end;                                                                 16920000
end;  << of procedure REQUEST'CACHE >>                                  16925000
$page "Procedure FLUSH'CACHE"                                           16930000
<<**************************************************>>                  16935000
<< Change to perform attachio or LOCK'RANGE         >>                  16940000
<<**************************************************>>                  16945000
integer procedure FLUSH'CACHE(LDEV,START'ADDR,LIMIT'ADDR);     <<06858>>16950000
value LDEV,START'ADDR,LIMIT'ADDR;                              <<06858>>16955000
integer LDEV;                                                           16960000
double START'ADDR,LIMIT'ADDR;                                  <<06858>>16965000
option uncallable, privileged;                                          16970000
begin                                                                   16975000
                                                                        16980000
<<********************************************************************>>16985000
<< Upon return from this procedure, the caller is guaranteed of having>>16990000
<< the range of sectors specified posted to disc and removed   <<06858>>16995000
<< from main memory.                                                  >>17000000
<<                                                                    >>17005000
<< The passed arguments are:                                          >>17010000
<<                                                                    >>17015000
<< LDEV         - The MPE logical device number of the disc device.   >>17020000
<< START'ADDR   - The logical disc address from which the data <<06858>>17025000
<<                be flushed.                                         >>17030000
<< LIMIT'ADDR   - The logical disc address to which the data is<<06858>>17035000
<<                be flushed (up to, but not including sector  <<06858>>17040000
<<                LIMIT'ADDR).                                 <<06858>>17045000
<<                                                             <<06858>>17050000
<< The returned value is:                                             >>17055000
<<                                                                    >>17060000
<< FLUSH'CACHE  - Return parameter from the procedure.  The values are>>17065000
<<                0 - disc range successfully flushed.                >>17070000
<<                1 - LDEV specified is not a disc or not cached.     >>17075000
<<                                                                    >>17080000
<< DB can be pointing anywhere when calling this procedure.  The      >>17085000
<< must be able to be "blocked" when calling this procedure.          >>17090000
<<********************************************************************>>17095000
                                                                        17100000
double HOLD'ADDR;      << Hold logical disc address >>         <<06858>>17105000
                                                               <<06858>>17110000
logical LDR'ENTRY'INDEX;  << Logical disc req index >>         <<06858>>17115000
                                                               <<06858>>17120000
                                                               <<06858>>17125000
integer R'FLUSH'CACHE = FLUSH'CACHE, << Access return var >>   <<06858>>17130000
        LDEV'ENTRY,      << CDT index of LDEV's entry >>       <<06858>>17135000
        CDT'ENTRY,       << Mapped-domain CDT entry   >>       <<06858>>17140000
        OLDCRIT,         << Critical state before entering this proc >> 17145000
        OLD'SIR,         << Rerurn from GETSIR               >><<*7551>>17150000
        OLDDB;           << DB location prior to calling this p<<*7551>>17155000
$page                                                          <<*7551>>17160000
SUBROUTINE CHECK'FOR'DISABLED'LDR;                             <<*7551>>17165000
BEGIN                                                          <<*7551>>17170000
<<***********************************************************>><<*7551>>17175000
<<* This subroutine will force any disabled logical disc    *>><<*7551>>17180000
<<* request pending for the flushing CDT to complete.       *>><<*7551>>17185000
<<***********************************************************>><<*7551>>17190000
                                                               <<*7551>>17195000
LDR'ENTRY'INDEX := DQH'DISAHEAD;                               <<*7551>>17200000
WHILE LDR'ENTRY'INDEX <> 0 DO                                  <<*7551>>17205000
   BEGIN                                                       <<*7551>>17210000
   TOS := LDR'NEXTQ;      << Save the next one >>              <<*7551>>17215000
   IF LDR'LDREQ AND INTEGER(LDR'LDEV) = LDEV AND               <<*7551>>17220000
      INTEGER(LDR'CDT) = CDT'ENTRY  THEN                       <<*7551>>17225000
      CDT'FORCE'CDT'COMPLETION(LDR'ENTRY'INDEX);               <<*7551>>17230000
                                                               <<*7551>>17235000
   LDR'ENTRY'INDEX := TOS;     << Next guy in queue >>         <<*7551>>17240000
   END;                                                        <<*7551>>17245000
END;       << Subroutine CHECK'FOR'DISABLED'LDR >>             <<*7551>>17250000
$PAGE                                                          <<*7551>>17255000
subroutine CHECK'FOR'LAZY'LDR;                                 <<*7551>>17260000
begin                                                          <<06858>>17265000
<<****************************************************>>       <<06858>>17270000
<< This subroutine tries to force a LDR which is      >>       <<06858>>17275000
<< holding-up a FLUSH, to complete.                   >>       <<06858>>17280000
<<****************************************************>>       <<06858>>17285000
                                                               <<06858>>17290000
CDT'ENTRY := CDT'GET'WORD(LDEV'ENTRY,CDT'DE'MAPD'HEAD,0);      <<06858>>17295000
while CDT'ENTRY <> 0 do                                        <<06858>>17300000
   begin                                                       <<06858>>17305000
   HOLD'ADDR := CDT'GET'DOUBLE(CDT'ENTRY,CDT'MD'SECTOR,0D);    <<06858>>17310000
   if HOLD'ADDR >= START'ADDR and                              <<06858>>17315000
      HOLD'ADDR < LIMIT'ADDR then << They overlap >>           <<06858>>17320000
      begin                                                    <<06858>>17325000
                                                               <<06858>>17330000
      << See if there is a LDR we can get out of the way >>    <<06858>>17335000
      LDR'ENTRY'INDEX := CDT'GET'WORD(CDT'ENTRY,               <<06858>>17340000
                         CDT'MD'LDR'HEAD,0);                   <<06858>>17345000
      if LDR'ENTRY'INDEX <> 0 then                             <<06858>>17350000
         CDT'FORCE'CDT'COMPLETION(LDR'ENTRY'INDEX)             <<06858>>17355000
      else                                                     <<06858>>17360000
         begin                                                 <<06858>>17365000
         LDR'ENTRY'INDEX := CDT'GET'WORD(CDT'ENTRY,            <<06858>>17370000
                            CDT'MD'IMPED'HD,0);                <<06858>>17375000
         if LDR'ENTRY'INDEX <> 0 then                          <<06858>>17380000
            CDT'FORCE'CDT'COMPLETION(LDR'ENTRY'INDEX)          <<*7551>>17385000
         else                                                  <<*7551>>17390000
           if DQH'DISAHEAD <> 0 then CHECK'FOR'DISABLED'LDR;   <<*7551>>17395000
                                                               <<*7551>>17400000
         end;                                                  <<06858>>17405000
      << Terminate looping >>                                  <<06858>>17410000
      CDT'ENTRY := 0;                                          <<06858>>17415000
      end                                                      <<06858>>17420000
   else                                                        <<06858>>17425000
      begin                                                    <<06858>>17430000
      << If address is beyond, terminate looping >>            <<06858>>17435000
      if HOLD'ADDR >= LIMIT'ADDR then                          <<06858>>17440000
         CDT'ENTRY := 0                                        <<06858>>17445000
      else                                                     <<06858>>17450000
         CDT'ENTRY := CDT'GET'WORD(CDT'ENTRY,CDT'MD'NEXT,0);   <<06858>>17455000
      end;                                                     <<06858>>17460000
   end;                                                        <<06858>>17465000
end;  << of subroutine >>                                      <<06858>>17470000
$page                                                          <<06858>>17475000
<< First, set this process CRITICAL because we're getting system >>     17480000
<< resources.                                                    >>     17485000
TURNOFFTRAPS;                                                  <<06858>>17490000
OLDCRIT := SETCRITICAL;                                                 17495000
OLD'SIR := GETSIR(CACHE'CONTROL'SIR);                          <<*7551>>17500000
                                                                        17505000
<< Set DB to SYSDB to access I/O system tables. >>                      17510000
OLDDB := SETSYSDB;                                                      17515000
                                                                        17520000
                                                               <<06858>>17525000
PDISABLE;                                                      <<06858>>17530000
                                                               <<06858>>17535000
<< Loop until there are NO overlapping mapped domains >>       <<06858>>17540000
FLUSH'CACHE := -1;   << Loop control >>                        <<06858>>17545000
while R'FLUSH'CACHE = -1 do                                    <<06858>>17550000
   begin                                                       <<06858>>17555000
   if CACHE'DST = 0 then                                       <<06858>>17560000
      FLUSH'CACHE := 1                                         <<06858>>17565000
   else if (LDEV'ENTRY:=CDT'FIND'DE(LDEV)) = 0 then            <<06858>>17570000
      FLUSH'CACHE := 1                                         <<06858>>17575000
   else                                                        <<06858>>17580000
      begin                                                    <<06858>>17585000
      if CDT'FLUSH'CACHED'RANGE(                               <<06858>>17590000
         LDEV'ENTRY,   << LDEV entry in CDT >>                 <<06858>>17595000
         START'ADDR,   << Start sector address >>              <<06858>>17600000
         LIMIT'ADDR,   << Limit sector address >>              <<06858>>17605000
         0,0) then                                             <<07308>>17610000
         FLUSH'CACHE := 0                                      <<06858>>17615000
      else                                                     <<06858>>17620000
         begin  << We must wait for I/O to quiesce >>          <<06858>>17625000
         DISABLE;                                              <<06858>>17630000
         PENABLE;                                              <<06858>>17635000
         tos := 300D;   << 300 ms >>                           <<06858>>17640000
         DELAY(*);                                             <<06858>>17645000
         CHECK'FOR'LAZY'LDR;                                   <<06858>>17650000
         PDISABLE;                                             <<06858>>17655000
         ENABLE;                                               <<06858>>17660000
         end;                                                  <<06858>>17665000
      end;                                                     <<06858>>17670000
   end;                                                        <<06858>>17675000
PENABLE;                                                       <<06858>>17680000
RESETDB(OLDDB);                                                <<06858>>17685000
RELSIR(CACHE'CONTROL'SIR,OLD'SIR);                             <<*7551>>17690000
RESETCRITICAL(OLDCRIT);                                        <<06858>>17695000
                                                                        17700000
                                                               <<06858>>17705000
                                                               <<06858>>17710000
                                                               <<06858>>17715000
end;   << of procedure FLUSH'CACHE >>                                   17720000
$page "CDT'ATTACHIO"                                                    17725000
DOUBLE PROCEDURE CDT'ATTACHIO(LDEV,QMISC,DSTX,ADDR,FNCT,                17730000
                              CNT,P1,P2,FLAGS,                          17735000
                              EXTBASE,EXTSIZE);                         17740000
                                                                        17745000
VALUE                       LDEV, QMISC, DSTX, ADDR, FNCT,              17750000
                            EXTBASE, EXTSIZE,                           17755000
                            CNT, P1, P2, FLAGS;                         17760000
                                                                        17765000
INTEGER                     LDEV, QMISC, DSTX, ADDR, FNCT,              17770000
                            CNT, P1, P2, FLAGS;                         17775000
                                                                        17780000
DOUBLE                      EXTBASE;                                    17785000
                                                                        17790000
LOGICAL                     EXTSIZE;                                    17795000
                                                                        17800000
OPTION PRIVILEGED,UNCALLABLE;                                           17805000
  BEGIN                                                                 17810000
comment                                                                 17815000
<<*****************************************************>>               17820000
LDEV   - Logical device number                                          17825000
QMISC  - Misc parameter specified for device                            17830000
DSTX   - DST number of data segment.  If zero, then                     17835000
         specifies that ADDR is DB relative to the caller's             17840000
         stack.  Must be zero if system buffers is specified.           17845000
ADDR   - Depending on FLAGS.(14:1) and DSTX, this may be:               17850000
         1)Offset to data in DST.                                       17855000
         2)Offset to data from DB in callers stack.                     17860000
         3)Index to a system buffer.                                    17865000
FUNC   - Function code.  Device defined, but usually:                   17870000
         0 - Read.                                                      17875000
         1 - Write.                                                     17880000
         2 - Open file.                                                 17885000
         3 - Close file.                                                17890000
         4 - Close device.                                              17895000
CNT    - Data transfer count, + words or - bytes.                       17900000
P1     - Parameter 1.  High-order disc sector address (HODA).           17905000
P2     - Parameter 2.  Low-order disc sector address (LODA).            17910000
FLAGS  - Control and specification flags.                               17915000
         (0:4) - Caller is unknown(0), file system(1), or               17920000
                 spooler(2).                                            17925000
         (4:1) - Force posting of writes prior to              <<06858>>17930000
                 completion notification.                      <<06858>>17935000
         (5:1) - Serialize write request                       <<06858>>17940000
         (6:1) - Available                                     <<06858>>17945000
         (7:2) - Premption flags, soft(1) or hard(2).                   17950000
         (9:1) - 0.                                                     17955000
         (10:1)- Special request, device defined.  Usually              17960000
                 memory management.                                     17965000
         (11:1)- If set, this is a diagnostic request.                  17970000
         (12:1)- System buffer flag.  If set, ADDR is an index          17975000
                 relative to the SBUF table.  For devices               17980000
                 that support chaining, the data is trans-              17985000
                 ferred to and from a set of chained buffers,           17990000
                 up to a maximum of 1024 words.                         17995000
         (13:3)- Request type:                                          18000000
                 0)Unblocked, no wake.  Impede if no IOQ.               18005000
                 1)Blocked (caller is waited until done).               18010000
                 2)Unblocked, wake caller, impede if no IOQ.            18015000
                 3)Unblocked & no PIN is to be associated               18020000
                   with this I/O.  Impede if no IOQ.                    18025000
                 4)Unblocked, no wake, no impede if no IOQ.             18030000
                 5)Reserved.                                            18035000
                 6)Unblocked, wake, no impede if no IOQ.                18040000
                 7)Same as 3 but no impede & get secondary              18045000
                   IOQ if necessary.                                    18050000
                                                                        18055000
RETURN:                                                                 18060000
                                                                        18065000
Blocked-                                                                18070000
                                                                        18075000
S-1    - (0:8) - PCB number.                                            18080000
         (8:5) - Qualifying status.                                     18085000
         (13:3)- General status.                                        18090000
S-0    - Transmission log (+words or -bytes).                           18095000
                                                                        18100000
Unblocked-                                                              18105000
                                                                        18110000
S-1    - IOQ index of request  (1 if no PCB I/O)                        18115000
S-0    - 0                                                              18120000
                                                                        18125000
<<************************************************************>         18130000
;                                                                       18135000
    INTEGER PCBNUM=Q+1;                                                 18140000
    INTEGER DBSAVE = PCBNUM + 1;                                        18145000
    INTEGER ARRAY DITP(@) = DBSAVE + 1;                                 18150000
    LOGICAL POINTER DITPL = DITP;                                       18155000
    INTEGER SAVECRIT = DITP + 1;                                        18160000
<<>>                                                                    18165000
                                                               <<06858>>18170000
                                                                        18175000
equate DTYPE      = 5;     << Device type word in DLT    >>             18180000
                                                                        18185000
define DDTYPE     = (8:8)#;<< Device type field in DLT   >>             18190000
                                                                        18195000
    INTEGER ARRAY DLTP(@)=SAVECRIT + 1;                                 18200000
    INTEGER POINTER IOQP  = DLTP + 1;                                   18205000
    LOGICAL POINTER IOQPL = IOQP;                                       18210000
    DOUBLE  POINTER IOQPD = IOQP;                                       18215000
    logical LDR'ENTRY'INDEX = IOQP,  <<Satisfies equates>>              18220000
            LDSTX           = DSTX;  <<Redefine DSTX passed>>           18225000
                                                                        18230000
    integer HEAD'PIN = IOQP+1;<< Head pin of impeded queue >>  <<06858>>18235000
                                                                        18240000
    INTEGER STACKDST = HEAD'PIN+1; << Holds DST if a stack >>  <<06858>>18245000
                                                                        18250000
    LOGICAL LFLAGS = FLAGS;                                             18255000
                                                               <<07311>>18260000
    DEFINE                                                     <<07311>>18265000
       LPDT'INDEX = LDEV * SIZE'OF'LPDT'ENTRY#;                <<07311>>18270000
                                                               <<07311>>18275000
                                                                        18280000
<<**********************************************>>                      18285000
<< Defines and equates from HARDRES >>                                  18290000
                                                                        18295000
integer X = X;   << Index register >>                                   18300000
                                                                        18305000
equate DDLTP       = 4; << DLT entry offset in DIT >>          <<06857>>18310000
                                                                        18315000
<< Dbl offset to DST BANK & OFFSET of disc request table >>    <<*7724>>18320000
equate LDR'DSTD'BANK = (LDR'DST*2)+1;                          <<*7724>>18325000
                                                               <<*7724>>18330000
define NOTIMPEDABLE     = (13:1)#,                                      18335000
       RTYPE            = (14:2)#,                                      18340000
       SYSBUFRS         = (12:1)#, << Req uses sysbuffers >>            18345000
       STACKFLAG        = (0:1)#,  << Req is stack-relative >>          18350000
       BLOCKED          = (5:1)#,                                       18355000
       IOWAKE           = (4:1)#;                                       18360000
                                                                        18365000
integer array DST(*)    = DB + 2;                                       18370000
double pointer DSTD     = DST;                                          18375000
double START'ADDR       = P1;   << Double disc address >>      <<06858>>18380000
                                                                        18385000
                                                               <<*7724>>18390000
                                                               <<*7724>>18395000
                                                               <<*7724>>18400000
                                                                        18405000
$if x1=on                                                               18410000
MMSTAT'(MMSTAT'CDT'ATT,LDEV,FNCT,FLAGS,P1,P2,CNT);             <<07311>>18415000
<< If we are disabled prior to calling ATTACHIO, HALT >>       <<06858>>18420000
PUSH(STATUS);                                                  <<06858>>18425000
if tos.(1:1) = 0 then                                          <<06858>>18430000
   if absolute(%1355).(13:1) = 1 then                          <<06858>>18435000
      begin                                                    <<06858>>18440000
      ASMB(halt 3);                                            <<06858>>18445000
      HELP;                                                    <<06858>>18450000
      end;                                                     <<06858>>18455000
$if                                                                     18460000
                                                                        18465000
<< TRAPSOFF; >>                                                         18470000
<< FORCE STACK OVERFLOWS, LEAVE 2 WORDS OF LOCAL DATA >>                18475000
ASMB(adds 255);                                                <<06858>>18480000
ASMB(subs 253);                                                <<06858>>18485000
PUSH(DB);   IF TOS=%1000 D THEN ASMB(DEL,ZERO) ELSE                     18490000
ASMB( PCAL SETSYSDB );  << SET DBSAVE >>                                18495000
                                                               <<07311>>18500000
TOS := LPDT'DIT'PTR;     << Set up DIT, DITPL >>               <<07311>>18505000
TOS := 0;    << Set SAVECRIT >>                                         18510000
                                                                        18515000
X := DBSAVE;   << TEST IF I/O SYSTEM CALL >>                            18520000
IF <> THEN ASMB(PCAL SETCRITICAL);  << SET SAVECRIT >>                  18525000
                                                                        18530000
TOS := DITP(DDLTP);    <<SET UP DLT>>                                   18535000
TOS:=GETDISCREQ(FLAGS.NOTIMPEDABLE);                                    18540000
ASMB(TEST,DZRO);   << FOR STACKDST AND PFLAG >>                         18545000
IF = THEN GOTO OUT;   << NO IOQ'S AVAILABLE >>                          18550000
                                                                        18555000
                                                                        18560000
IF LFLAGS.SYSBUFRS THEN             << DST # OF SYS BUFS >>             18565000
  begin                                                                 18570000
  DSTX := 8;  << System buffers >>                                      18575000
  if CNT <> 0 then  << CACHING does not support chained sysbufs>>       18580000
    if > then                                                           18585000
      begin                                                             18590000
      if CNT > 128 then                                                 18595000
        SUDDENDEATH(SFKERNCACHEINTBAD);                                 18600000
      end                                                               18605000
    else                                                                18610000
      if CNT < -256 then                                                18615000
        SUDDENDEATH(SFKERNCACHEINTBAD);                                 18620000
  end;                                                                  18625000
                                                                        18630000
X := DSTX;                                                              18635000
IF = THEN   << A STACK RELATIVE ADDRESS >>                              18640000
  BEGIN                                                                 18645000
  STACKDST := INTEGER(LPCB(CURPRC+STKINFOWORDNUM).STKDSTFIELD);<<06857>>18650000
  TOS := STACKDST;  TOS.STACKFLAG := 1;  DSTX := TOS;                   18655000
  END;                                                                  18660000
                                                                        18665000
<< Put DB at LDR entry for fast access >>                      <<*7724>>18670000
tos := DSTD(LDR'DSTD'BANK);                                    <<*7724>>18675000
tos := tos + LDR'ENTRY'INDEX;   << Point to actual entry >>    <<*7724>>18680000
PDISABLE;                                                      <<*7724>>18685000
EXCHDB;                                                        <<*7724>>18690000
                                                               <<*7724>>18695000
<< Load parameters into LDR entry >>                                    18700000
LDR'DB'LDEV := LDEV;                                           <<*7724>>18705000
LDR'DB'CDT := 0;                                               <<*7724>>18710000
LDR'DB'BUFDST := DSTX;                                         <<*7724>>18715000
LDR'DB'BUFADR := ADDR;                                         <<*7724>>18720000
LDR'DB'FUNC := FNCT;                                           <<*7724>>18725000
LDR'DB'COUNT := CNT;                                           <<*7724>>18730000
LDR'DB'PARM1 :=P1;                                             <<*7724>>18735000
LDR'DB'PARM2 := P2;                                            <<*7724>>18740000
LDR'DB'STAT  := 0;                                             <<*7724>>18745000
tos := EXTBASE;                                                         18750000
LDR'DB'B'LODA := tos;                                          <<*7724>>18755000
LDR'DB'B'HODA := tos;                                          <<*7724>>18760000
tos := EXTBASE + double(EXTSIZE);                                       18765000
LDR'DB'L'LODA := tos;                                          <<*7724>>18770000
LDR'DB'L'HODA := tos;                                          <<*7724>>18775000
LDR'DB'STRATEGY := LFLAGS.(0:4);  << Save strategy >>          <<*7724>>18780000
                                                                        18785000
<<TOS := 0;   TOS.(1:3) := FLAGS.(10:3);>><<SPEC,DIAG,SYSBUF>>          18790000
TOS := (LFLAGS land %006000)&lsr(3); << DO'POST, SEQ'POST >>   <<06858>>18795000
TOS := TOS lor %2;  << Turn on logical disc request bit >>              18800000
                                                                        18805000
X := FLAGS.RTYPE;   << SWITCH ON REQUEST TYPE >>                        18810000
ASMB( BR *+1,X ;                                                        18815000
      br RT0;  br RT1;  br RT2;  br RT3 );                              18820000
                                                                        18825000
<< If this is NO PCB I/O, it cannot be sysbuf I/O >>                    18830000
RT3:  << No-PCB I/O >>                                                  18835000
if LFLAGS.SYSBUFRS and CNT <> 0 then                                    18840000
  SUDDENDEATH(SFKERNCACHEINTBAD);                                       18845000
go to RT0;    << We MUST cram a PCB number in here! >>                  18850000
                                                                        18855000
RT1:  << Blocked I/O - must clear WWS bit in PCB >>                     18860000
<<tos.BLOCKED := 1;>><< Turn on blocked bit in FLAGS >>                 18865000
DISABLE;                                                                18870000
CLEARWWS;                                                               18875000
                                                                        18880000
RT2:                                                                    18885000
<<TOS.IOWAKE := 1;>>                                                    18890000
                                                                        18895000
RT0:                                                                    18900000
LDR'DB'PCB := PCBNUM := CURPRC/PCBSIZE;                        <<*7724>>18905000
                                                                        18910000
LDR'DB'FLAGS := TOS; << Save FLAGS word  + LDR bit >>          <<*7724>>18915000
                                                               <<*7724>>18920000
<< Put DB back to SYSDB and allow to continue >>               <<*7724>>18925000
EXCHDB;                                                        <<*7724>>18930000
assemble(ddel);                                                <<*7724>>18935000
PENABLE;                                                       <<*7724>>18940000
                                                                        18945000
<< If caching is in the process of terminating, hold-off all >><<06858>>18950000
<< user disc requests.                                       >><<06858>>18955000
DISABLE;                                                       <<06858>>18960000
                                                               <<*7724>>18965000
<< Load abs addr of stop flag on tos >>                        <<*7724>>18970000
CDT'ABS'ON'TOS;                                                <<*7724>>18975000
tos := tos + CDT'STOP'PND;   << Abs addr of STOP flag >>       <<*7724>>18980000
ASMB(LSEA);                                                    <<*7724>>18985000
while (tos <> 0) and                                           <<*7724>>18990000
      (CACHE'DST <> 0) << Still enabled >> do                  <<*7724>>18995000
  begin  << Impede me, and wait for stopcache executor >>      <<06858>>19000000
  << Get in PIN list >>                                        <<06858>>19005000
  if (HEAD'PIN := CDT'GET'WORD(0,CDT'STOP'QUEUE,0))=0 then     <<06858>>19010000
    CDT'SET'WORD(0,CDT'STOP'QUEUE,PCBNUM);                     <<06858>>19015000
  STRINGPINATTAIL(HEAD'PIN,0);                                 <<06858>>19020000
                                                               <<06858>>19025000
  << Impede, waiting for stop cache to work >>                 <<06858>>19030000
  IMPEDE(0);                                                   <<06858>>19035000
                                                               <<*7724>>19040000
  << Re-load LOCK word on tos >>                               <<*7724>>19045000
  ASMB(LSEA);  << for WHILE stmt >>                            <<*7724>>19050000
  end;                                                         <<06858>>19055000
                                                               <<06858>>19060000
<< Remove abs pointer to lock word >>                          <<*7724>>19065000
ASMB(DDEL);                                                    <<*7724>>19070000
                                                               <<*7724>>19075000
<< Now, perform unblocked cache processing >>                           19080000
PDISABLE;                                                               19085000
ENABLE;                                                                 19090000
                                                                        19095000
tos := REQUEST'CACHE(@IOQP);                                            19100000
                                                                        19105000
PENABLE;                                                                19110000
                                                                        19115000
if not tos then                                                         19120000
  begin  << Cache did not accept, perform physical attachio >>          19125000
                                                                        19130000
  << Return disc request element >>                                     19135000
  TOS :=@IOQP;                                                 <<06856>>19140000
  RETURNDISCREQ(*);                                                     19145000
                                                                        19150000
  << If this is a STACK DST, zero DSTX word >>                          19155000
  if LDSTX.STACKFLAG then                                               19160000
    DSTX := 0;                                                          19165000
                                                                        19170000
  << If this is a data transfer function, we must force     >> <<06858>>19175000
  << any overlapping areas in memory OUT.                   >> <<06858>>19180000
  if FNCT > 4 and CNT <> 0 then <<not r/w/fopen/fclose/dclose>><<06858>>19185000
    if (5 <= FNCT <= 6) or  <<zero/blank fill>>                <<06858>>19190000
      FNCT = 11 then       << write sector zero >>             <<06858>>19195000
      FLUSH'CACHE(LDEV,                                        <<06858>>19200000
                                                               <<06858>>19205000
        START'ADDR,                                            <<06858>>19210000
                                                               <<06858>>19215000
        START'ADDR+(((if CNT < 0 then                          <<06858>>19220000
                                                               <<06858>>19225000
                        double((1-CNT)&asr(1))                 <<06858>>19230000
                                                               <<06858>>19235000
                      else                                     <<06858>>19240000
                                                               <<06858>>19245000
                        double(CNT)) + 127D)&dasr(7)));        <<06858>>19250000
                                                                        19255000
  CDT'ATTACHIO := P'ATTACHIO(LDEV,QMISC,DSTX,ADDR,FNCT,CNT,             19260000
                             P1,P2,FLAGS,EXTBASE,EXTSIZE);              19265000
  end                                                                   19270000
                                                                        19275000
else                                                                    19280000
                                                                        19285000
  begin  << Cache accepted responsibility, so proceed >>                19290000
  IF FLAGS.RTYPE=1 THEN   << BLOCKED I/O >>                             19295000
    BEGIN                                                               19300000
                                                                        19305000
    CDT'ATTACHIO := WAITFORIO(logical(@IOQP) lor %040000);              19310000
                                                                        19315000
    END                                                                 19320000
                                                                        19325000
  ELSE                                                                  19330000
                                                                        19335000
    BEGIN << UNBLOCKED REQUEST, RETURN IOQ INDEX >>                     19340000
    tos := logical(@IOQP) lor %040000;                                  19345000
                                                                        19350000
OUT:                                                                    19355000
                                                                        19360000
    TOS := 0;  << FOR P'ATTACHIO RETURN >>                              19365000
    CDT'ATTACHIO := TOS;                                                19370000
    END;                                                                19375000
                                                                        19380000
  END;                                                                  19385000
                                                                        19390000
TOS := DBSAVE;    IF = THEN RETURN;  << NOT SET HERE >>                 19395000
RESETCRITICAL(SAVECRIT);                                                19400000
RESETDB( * );                                                           19405000
                                                                        19410000
END;      <<  CDT'ATTACHIO >>                                           19415000
                                                                        19420000
$page "Cached Disc Domain List Management : Overview"                   19425000
                                                                        19430000
COMMENT                                                                 19435000
                                                                        19440000
All disc domains that have main memory allocated to them (ie cached     19445000
disc domains) are linked into cached disc domain lists.  A separate     19450000
cached disc domain list is maintained for the disc domains belonging    19455000
to common device.  The cached disc domains belonging to a common device 19460000
are linked together through the main memory region headers of  the      19465000
cached domains.  They are linked according to increasing sector offset  19470000
and the head and tail region addresses of the cached dommain lists      19475000
are kept in the CDT entry for the corresponding disc.  (the list is     19480000
ordered for fast searching using the LLSH instruction).                 19485000
                                                                        19490000
Cached regions are kept in the list even if the disc domain is not      19495000
mapped in and not present.  In particular, any cached disc domain that  19500000
is present, in motion in, or a recoverable overlay candidate is kept    19505000
in the appropraite list of cached disc domains.                         19510000
                                                                        19515000
The cached disc domain lists are managed by the procedures LinkCached   19520000
Domain and UnlinkCachedDomain. LinkCachedDomain is invoked by F<<07311>>19525000
Object when the main memory region is first allocated for the c<<07311>>19530000
disc domain.  UnlinkCachedDomain is invoked when the cached region is   19535000
being wiped out of main memory (from CleanRegion or FlushDiscRange).    19540000
                                                                        19545000
;                                                                       19550000
                                                                        19555000
$page "Cached Region Management Procedures : Link Cached Region"        19560000
                                                                        19565000
PROCEDURE LinkCachedRegion ( regionbase );                              19570000
VALUE regionbase;                                                       19575000
DOUBLE regionbase;                                                      19580000
OPTION PRIVILEGED,UNCALLABLE;                                           19585000
                                                                        19590000
COMMENT                                                                 19595000
                                                                        19600000
LinkCachedDomain places a main memory region into the list of           19605000
cached disc domains.                                                    19610000
                                                                        19615000
LinkCachedDomain is called from FetchObject when space is first         19620000
allocated for the object. (Also called from COLLECTGARBAGE).   <<07311>>19625000
                                                                        19630000
;                                                                       19635000
                                                                        19640000
BEGIN                                                                   19645000
                                                                        19650000
INTEGER ldev,                                                           19655000
        cdtentrynum,                                                    19660000
        pages,                                                          19665000
        cdcount,                                                        19670000
        remlinkcount,                                                   19675000
        devcdtentry;                                                    19680000
                                                                        19685000
DOUBLE sectoroffset,                                                    19690000
       cdhead,                                                          19695000
       prevlink,                                                        19700000
       nextlink;                                                        19705000
                                                                        19710000
INTEGER HODA=SECTOROFFSET,                                              19715000
        LODA=HODA+1;                                                    19720000
                                                                        19725000
DOUBLE OLDLISTHEAD,                                                     19730000
       nextlinktocheck,                                                 19735000
       scanpt,              << Index to last scan point >>              19740000
       targetda,                                                        19745000
       thisregndptraddr,                                                19750000
       OLDLISTTAIL;                                                     19755000
                                                                        19760000
<< Variables for fast CDT access >>                            <<*7724>>19765000
INTEGER LDEV'OFFSET,                                           <<*7724>>19770000
        MAPD'OFFSET;                                           <<*7724>>19775000
                                                               <<*7724>>19780000
DOUBLE  SAVE'DB;                << Caller's DB >>              <<*7724>>19785000
                                                               <<*7724>>19790000
LOGICAL not'smaller;                                                    19795000
$page                                                          <<*7724>>19800000
                                                               <<*7724>>19805000
                                                               <<*7724>>19810000
                                                               <<*7724>>19815000
                                                               <<*7724>>19820000
                                                               <<*7724>>19825000
subroutine FIX'DA(FIX'REGION,IS'TAIL);                                  19830000
value FIX'REGION,IS'TAIL;                                               19835000
double FIX'REGION;                                                      19840000
logical IS'TAIL;                                                        19845000
begin                                                                   19850000
                                                                        19855000
<< Fix disc address in region header >>                                 19860000
if IS'TAIL then                                                         19865000
   begin                                                                19870000
   TOS := FIX'REGION;                                                   19875000
   TOS := TOS + NDtoCACDAdisp;                                          19880000
   TOS := -1;   << Terminator >>                                        19885000
   ASMB(SSEA;DDEL);                                                     19890000
   end                                                                  19895000
else                                                                    19900000
   begin                                                                19905000
   TOS := FIX'REGION;                                                   19910000
   TOS := TOS + NDtoHODAdisp;                                           19915000
   ASMB(LDEA);                                                          19920000
   CDT'SHIFT'DA;                                                        19925000
   ASMB(DEL);  << Remove LODA >>                                        19930000
   S1 := S1 + HODAtoCACDAdisp;                                          19935000
   ASMB(SSEA;DDEL);                                                     19940000
   end;                                                                 19945000
                                                                        19950000
end;   << of subroutine FIX'DA >>                                       19955000
SUBROUTINE PLACEATHEAD;                                                 19960000
                                                                        19965000
BEGIN                                                                   19970000
oldlisthead := cdhead;                                                  19975000
TOS := regionbase;                                                      19980000
TOS := TOS + RBTONDDISP;                                                19985000
thisregndptraddr := TOS;                                                19990000
                                                                        19995000
<< Update scan point to this region >>                                  20000000
$if x1=on                                                      <<*7724>>20005000
CDT'SET'DOUBLE(devcdtentry,cdt'de'scanpt,thisregndptraddr);             20010000
$if x1=off                                                     <<*7724>>20015000
CDT'DARRAY((LDEV'OFFSET+CDT'DE'SCANPT)&asr(1)):=               <<*7724>>20020000
   thisregndptraddr;                                           <<*7724>>20025000
$if                                                            <<*7724>>20030000
                                                                        20035000
$if x1=on                                                      <<*7724>>20040000
CDT'SET'DOUBLE(devcdtentry,cdt'de'reg'hd,thisregndptraddr);             20045000
$if x1=off                                                     <<*7724>>20050000
CDT'DARRAY((LDEV'OFFSET+CDT'DE'REG'HD)&asr(1)):=               <<*7724>>20055000
   THISREGNDPTRADDR;                                           <<*7724>>20060000
$if                                                            <<*7724>>20065000
TOS := regionbase;                                                      20070000
TOS := TOS+RBTOPDDISP;                                                  20075000
TOS := 0D;                                                              20080000
ASMB(SDEA);      << zero out prev link >>                               20085000
TOS := TOS+PDTONDDISP;                                                  20090000
TOS := OLDLISTHEAD;                                                     20095000
ASMB(SDEA;DDEL);                                                        20100000
IF > THEN   << Load of old head was NOT zero >>                         20105000
   BEGIN       << must update prevlink of old head. >>                  20110000
   TOS := OLDLISTHEAD;                                                  20115000
   TOS := TOS+NDTOPDDISP;                                               20120000
   TOS := regionbase;                                                   20125000
   TOS := TOS + RBTOPDDISP;                                             20130000
   ASMB(SDEA;DDEL);                                                     20135000
   END;                                                                 20140000
FIX'DA(thisregndptraddr,FALSE);                                         20145000
END;     << subroutine PLACEATHEAD >>                                   20150000
                                                                        20155000
SUBROUTINE PLACEATTAIL;                                                 20160000
                                                                        20165000
BEGIN                                                                   20170000
                                                                        20175000
TOS := regionbase;                                                      20180000
TOS := TOS + RBTONDDISP;                                                20185000
TOS := 0D;                                                              20190000
ASMB(SDEA);    << Zero next region pointer >>                           20195000
thisregndptraddr:=TOS;                                                  20200000
$if x1=on                                                      <<*7724>>20205000
OLDLISTTAIL := CDT'SET'DOUBLE(devcdtentry,cdt'de'reg'tl,                20210000
                              thisregndptraddr);                        20215000
$if x1=off                                                     <<*7724>>20220000
OLDLISTTAIL := CDT'DARRAY((LDEV'OFFSET+CDT'DE'REG'TL)&asr(1)); <<*7724>>20225000
CDT'DARRAY(CDT'X) := THISREGNDPTRADDR;                         <<*7724>>20230000
$if                                                            <<*7724>>20235000
                                                                        20240000
<< Fill in prev and next links of this hole. >>                         20245000
                                                                        20250000
IF OLDLISTTAIL <> 0D THEN                                               20255000
   BEGIN                                                                20260000
   TOS := thisregndptraddr;                                             20265000
   TOS := TOS+NDTOPDDISP;                                               20270000
   TOS := OLDLISTTAIL;                                                  20275000
   TOS := TOS + NDTOPDDISP;                                             20280000
   ASMB(SDEA;DDEL);    << update Prev in list ptr >>                    20285000
                                                                        20290000
   << Update old tail's Next link >>                                    20295000
   TOS := OLDLISTTAIL;                                                  20300000
   TOS := thisregndptraddr;                                             20305000
   ASMB(SDEA;DDEL);                                                     20310000
                                                                        20315000
   << Update scan point >>                                              20320000
$if x1=on                                                      <<*7724>>20325000
   CDT'SET'DOUBLE(devcdtentry,cdt'de'scanpt,oldlisttail);               20330000
$if x1=off                                                     <<*7724>>20335000
   CDT'DARRAY((LDEV'OFFSET+CDT'DE'SCANPT)&asr(1)) :=           <<*7724>>20340000
      OLDLISTTAIL;                                             <<*7724>>20345000
$if                                                            <<*7724>>20350000
                                                                        20355000
   FIX'DA(oldlisttail,FALSE);                                           20360000
   END                                                                  20365000
ELSE                                                                    20370000
   begin                                                       <<*7724>>20375000
   << Update scan point >>                                              20380000
$if x1=on                                                      <<*7724>>20385000
   CDT'SET'DOUBLE(devcdtentry,cdt'de'scanpt,thisregndptraddr);          20390000
$if x1=off                                                     <<*7724>>20395000
   CDT'DARRAY((LDEV'OFFSET+CDT'DE'SCANPT)&asr(1)) :=           <<*7724>>20400000
      THISREGNDPTRADDR;                                        <<*7724>>20405000
$if                                                            <<*7724>>20410000
   end;                                                        <<*7724>>20415000
                                                                        20420000
FIX'DA(thisregndptraddr,TRUE);                                          20425000
END;      << subroutine PLACEATTHEAD >>                                 20430000
                                                                        20435000
$page                                                          <<*7724>>20440000
                                                               <<*7724>>20445000
<< Put DB at the CDT >>                                        <<*7724>>20450000
CDT'ABS'ON'TOS;                                                <<*7724>>20455000
EXCHDB;                                                        <<*7724>>20460000
SAVE'DB := tos;                                                <<*7724>>20465000
                                                               <<*7724>>20470000
<<look up device # and sector offset  of region , fill in               20475000
  corresponding local variables>>                                       20480000
TOS := regionbase;                                             <<d7726>>20485000
TOS := TOS + rbtohodadisp;                                     <<d7726>>20490000
ASMB(LDEA);                                                    <<d7726>>20495000
ASMB(DDUP);                                                    <<d7726>>20500000
targetda := TOS;                                               <<d7726>>20505000
loda := TOS;                                                   <<d7726>>20510000
ldev:=s0.regldevfield;                                         <<d7726>>20515000
hoda:=TOS.reghodafield;                                        <<d7726>>20520000
                                                               <<d7726>>20525000
                                                                        20530000
TOS:=regionbase;                                                        20535000
TOS := TOS + rbtoobjidentdisp;                                 <<06855>>20540000
ASMB(LDEA;DELB);        << Delete object descriptor word  >>   <<07311>>20545000
cdtentrynum := tos;                                            <<06855>>20550000
                                                                        20555000
<< If the CDT is mapped-in, get length from CDT >>                      20560000
IF cdtentrynum <> 0 then                                       <<07311>>20565000
   BEGIN                                                                20570000
   MAPD'OFFSET := CDTENTRYNUM * CDT'ENTRY'SIZE;                <<*7724>>20575000
$if x1=on                                                      <<*7724>>20580000
   DEVCDTENTRY := CDT'GET'WORD(CDTENTRYNUM,CDT'MD'DE,0);       <<d7726>>20585000
   pages := integer(                                                    20590000
     CDT'GET'DOUBLE(cdtentrynum,cdt'md'end'sector,0D) -                 20595000
     CDT'GET'DOUBLE(cdtentrynum,cdt'md'sector,0D)) +                    20600000
     1  << Overhead >>;                                                 20605000
$if x1=off                                                     <<*7724>>20610000
   tos := CDT'DARRAY((MAPD'OFFSET+CDT'MD'END'SECTOR)&asr(1));  <<*7724>>20615000
   tos := CDT'DARRAY((MAPD'OFFSET+CDT'MD'SECTOR)&asr(1));      <<*7724>>20620000
   ASMB(DSUB,DELB);                                            <<*7724>>20625000
   PAGES := tos+1;                                             <<*7724>>20630000
   DEVCDTENTRY := CDT'ARRAY(MAPD'OFFSET+CDT'MD'DE);            <<d7726>>20635000
$if                                                            <<d7726>>20640000
   END                                                                  20645000
ELSE                                                                    20650000
   BEGIN                                                                20655000
   TOS := TOS + objidenttossdisp;                                       20660000
   ASMB(LSEA);                                                          20665000
   pages := TOS;                                                        20670000
   if (DEVCDTENTRY := CDT'FIND'DE(LDEV)) = 0 then              <<d7726>>20675000
      SUDDENDEATH(SFKERNCACHEINTBAD);                          <<d7726>>20680000
   END;                                                                 20685000
                                                               <<07311>>20690000
$if x1=on                                                      <<07311>>20695000
TOS := MMSTAT'LINK'REGION;                                     <<07311>>20700000
TOS := 0;                   << 0 = link, 1 = unlink >>         <<07311>>20705000
TOS := REGIONBASE;                                             <<07311>>20710000
MMSTAT'(*,*,*,*,CDTENTRYNUM,PAGES,0);                          <<07311>>20715000
$if                                                            <<07311>>20720000
                                                               <<07311>>20725000
                                                                        20730000
<<find out head, tail, prev and next for the list of cached             20735000
  disc domains for this device>>                                        20740000
                                                                        20745000
LDEV'OFFSET := DEVCDTENTRY * CDT'ENTRY'SIZE;                   <<*7724>>20750000
                                                               <<*7724>>20755000
$if x1=on                                                      <<*7724>>20760000
                                                                        20765000
cdhead  := CDT'GET'DOUBLE(devcdtentry,                                  20770000
                          cdt'de'reg'hd,                                20775000
                          0d);                                          20780000
                                                                        20785000
cdcount := CDT'ADD'WORD(devcdtentry,                                    20790000
                        cdt'de'regions,                                 20795000
                        1)-1; <<bumps current by 1>>                    20800000
                                                                        20805000
                                                                        20810000
CDT'ADD'WORD(devcdtentry,cdt'de'mapd'pages,pages);                      20815000
$if x1=off                                                     <<*7724>>20820000
CDHEAD := CDT'DARRAY((LDEV'OFFSET+CDT'DE'REG'HD)&asr(1));      <<*7724>>20825000
                                                               <<*7724>>20830000
CDT'X := LDEV'OFFSET + CDT'DE'REGIONS;                         <<*7724>>20835000
tos := CDCOUNT := CDT'ARRAY(CDT'X);                            <<*7724>>20840000
CDT'ARRAY(CDT'X) := tos + 1;   << Bump region count >>         <<*7724>>20845000
                                                               <<*7724>>20850000
CDT'X := LDEV'OFFSET + CDT'DE'MAPD'PAGES;                      <<*7724>>20855000
CDT'ARRAY(CDT'X) := CDT'ARRAY(CDT'X) + PAGES;                  <<*7724>>20860000
$if                                                            <<*7724>>20865000
                                                                        20870000
IF cdhead = 0D THEN                                                     20875000
   BEGIN       << List of cached regions is empty >>                    20880000
   PlaceAtHead;                                                         20885000
   PlaceAtTail;                                                         20890000
   END                                                                  20895000
ELSE                                                                    20900000
   BEGIN     << Must merge into list >>                                 20905000
                                                                        20910000
   << Locate position in the hole list for this hole. >>                20915000
                                                                        20920000
   << Locate proper hoda position (since llsh only masks 1 word)>>      20925000
                                                                        20930000
   TOS := NDtoCACDAdisp;<< offset from Link to target for LLSH >>       20935000
   TOS := TARGETDA; <<test word>>                                       20940000
   CDT'SHIFT'DA;      << Put into search form >>                        20945000
   ASMB(DEL);         << Remove LODA          >>                        20950000
                                                                        20955000
   << Determine whether to use scan point or CDHEAD >>                  20960000
$if x1=on                                                      <<*7724>>20965000
   tos := SCANPT :=                                            <<*7724>>20970000
          CDT'GET'DOUBLE(DEVCDTENTRY,CDT'DE'SCANPT,0D);        <<*7724>>20975000
$if x1=off                                                     <<*7724>>20980000
   tos := SCANPT :=                                            <<*7724>>20985000
      CDT'DARRAY((LDEV'OFFSET+CDT'DE'SCANPT)&asr(1));          <<*7724>>20990000
$if                                                            <<*7724>>20995000
   IF (tos <<SCANPT>> <> 0D) then                              <<*7724>>21000000
                                                               <<*7724>>21005000
      BEGIN                                                             21010000
      TOS := SCANPT;                                                    21015000
      TOS := TOS + NDtoHODAdisp;                                        21020000
      ASMB(LDEA;DXCH,DDEL);                                             21025000
      IF TOS <= targetda THEN                                           21030000
         TOS := SCANPT                                                  21035000
      ELSE                                                              21040000
         TOS := CDHEAD;                                                 21045000
      END                                                               21050000
   ELSE                                                                 21055000
      TOS := CDHEAD;                                                    21060000
                                                                        21065000
   X := cdcount;                                                        21070000
   ASMB(LLSH);  << chase through the list to get to right place >>      21075000
   IF < THEN PLACEATTAIL  ELSE                                          21080000
      BEGIN    << got some regions with the same or larger hoda>>       21085000
      ASMB(DDUP);                                                       21090000
      nextlinktocheck:=TOS;                                             21095000
      remlinkcount := X;                                                21100000
      not'smaller := FALSE;                                             21105000
      do                                                                21110000
         BEGIN <<locate location within hoda>>                          21115000
         ASMB(DDUP);                                                    21120000
         TOS := TOS + NDtoHODAdisp;                                     21125000
         ASMB(LDEA;DXCH,DDEL);                                          21130000
         TOS := targetda;                                               21135000
         ASMB(DCMP);                                                    21140000
         IF < THEN                      <<GO TO NEXT>>                  21145000
            BEGIN                                                       21150000
            ASMB(LDEA);                                                 21155000
            IF <= THEN  << We are at end-of-list >>                     21160000
               X := 1; << Terminate scan >>                             21165000
            ASMB(DXCH,DDEL);                                            21170000
            END                                                         21175000
         ELSE IF > THEN NOT'SMALLER := TRUE                             21180000
         ELSE SuddenDeath(SFKernCacheIntBad);                           21185000
         END                                                            21190000
      UNTIL NOT'SMALLER OR DXBZ;                                        21195000
                                                                        21200000
      IF X = 0 THEN PlaceAtTail ELSE                                    21205000
         BEGIN    << stopped in middle of list >>                       21210000
                                                                        21215000
         << Put in front of link on TOS >>                              21220000
                                                                        21225000
         TOS := TOS+NDTOPDDISP;                                         21230000
         ASMB(LDEA);                                                    21235000
         PREVLINK := TOS;                                               21240000
                                                                        21245000
         << Now link in behind previous region base. >>                 21250000
                                                                        21255000
         TOS := PREVLINK;                                               21260000
         IF <= THEN PLACEATHEAD ELSE                                    21265000
            BEGIN                                                       21270000
            TOS := TOS+PDTONDDISP;                                      21275000
            ASMB(LDEA);                                                 21280000
            NEXTLINK := TOS;                                            21285000
                                                                        21290000
            TOS := regionbase;                                          21295000
            TOS := TOS+RBTONDDISP;                                      21300000
            ASMB(SDEA);  << put new next link in prev in list >>        21305000
                                                                        21310000
            ASMB(DDUP);                                                 21315000
            SCANPT := TOS;                                              21320000
            << Update scan point >>                                     21325000
$if x1=on                                                      <<*7724>>21330000
            CDT'SET'DOUBLE(devcdtentry,cdt'de'scanpt,scanpt);           21335000
$if x1=off                                                     <<*7724>>21340000
            CDT'DARRAY((LDEV'OFFSET+CDT'DE'SCANPT)&asr(1)) :=  <<*7724>>21345000
               SCANPT;                                         <<*7724>>21350000
$if                                                            <<*7724>>21355000
                                                                        21360000
            TOS := NEXTLINK;                                            21365000
            IF <= THEN SUDDENDEATH(SFKernCacheIntBad);                  21370000
            TOS := TOS+NDTOPDDISP;                                      21375000
            TOS := regionbase;                                          21380000
            TOS := TOS + RBTOPDDISP;                                    21385000
            ASMB(SDEA);  << put new prev ptr in next in list >>         21390000
                                                                        21395000
            TOS := regionbase;                                          21400000
            TOS := TOS+RBTONDDISP;                                      21405000
                                                                        21410000
            << Fix LLSH disc address >>                                 21415000
            ASMB(DDUP);                                                 21420000
            SCANPT := TOS;                                              21425000
            FIX'DA(scanpt,FALSE);                                       21430000
                                                                        21435000
            TOS := NEXTLINK;                                            21440000
            ASMB(SDEA);   << put next link into this region >>          21445000
            TOS := TOS+NDTOPDDISP;                                      21450000
            TOS := PREVLINK;                                            21455000
            ASMB(SDEA);   << put Prev region ptr into this region >>    21460000
            END;                                                        21465000
         END;                                                           21470000
      END;                                                              21475000
   END;                                                                 21480000
                                                                        21485000
<< Put DB back to caller's DB >>                               <<*7724>>21490000
tos := SAVE'DB;                                                <<*7724>>21495000
EXCHDB;                                                        <<*7724>>21500000
                                                               <<*7724>>21505000
END; <<LinkCachedDomain>>                                               21510000
                                                                        21515000
$page "Cached Region Management Procedures : Unlink Cached Region"      21520000
                                                                        21525000
PROCEDURE UnlinkCachedRegion ( regionbase );                            21530000
VALUE regionbase;                                                       21535000
DOUBLE regionbase;                                                      21540000
OPTION PRIVILEGED,UNCALLABLE;                                           21545000
                                                                        21550000
COMMENT                                                                 21555000
                                                                        21560000
UnlinkCachedDomain takes a main memory region off the list of           21565000
cached disc domains.                                                    21570000
                                                                        21575000
This routine is called form CleanRegion when a cached domain is         21580000
being wiped out of main memory and by ZapCachedDomain when releasing    21585000
cached regions form memory due to partial overlaps, dismounts, or       21590000
cache bypasses.  (Also called from COLLECTGARBAGE).            <<07311>>21595000
                                                                        21600000
;                                                                       21605000
                                                                        21610000
BEGIN                                                                   21615000
                                                                        21620000
INTEGER ldev,                                                           21625000
        regsize,                                                        21630000
        devcdtentry;                                                    21635000
                                                                        21640000
DOUBLE sectoroffset,                                                    21645000
       holdnextptr,                                                     21650000
       cdtail,                                                          21655000
       prevlink,                                                        21660000
       nextlink;                                                        21665000
                                                                        21670000
<< Variables for fast CDT access >>                            <<*7724>>21675000
INTEGER LDEV'OFFSET;                                           <<*7724>>21680000
                                                               <<*7724>>21685000
DOUBLE  SAVE'DB;       << Caller's setting of DB >>            <<*7724>>21690000
                                                                        21695000
INTEGER hoda=sectoroffset,                                              21700000
        loda=sectoroffset+1;                                            21705000
                                                                        21710000
                                                               <<*7724>>21715000
                                                               <<*7724>>21720000
                                                               <<*7724>>21725000
                                                               <<*7724>>21730000
                                                               <<*7724>>21735000
<< Set DB to CDT >>                                            <<*7724>>21740000
CDT'ABS'ON'TOS;                                                <<*7724>>21745000
EXCHDB;                                                        <<*7724>>21750000
SAVE'DB := tos;                                                <<*7724>>21755000
                                                               <<*7724>>21760000
<<look up device # and sector address of region , fill in               21765000
  corresponding local variables>>                                       21770000
                                                                        21775000
TOS:=regionbase;                                                        21780000
TOS:=TOS+rbtohodadisp;                                                  21785000
ASSEMBLE(ldea);                                                         21790000
loda := TOS;                                                            21795000
ldev:=s0.regldevfield;                                                  21800000
hoda:=TOS.reghodafield;                                                 21805000
                                                                        21810000
<<find out head, tail, prev and next for the list of cached             21815000
  disc domains for this device>>                                        21820000
                                                                        21825000
if (devcdtentry := CDT'FIND'DE(ldev)) = 0 then                 <<06858>>21830000
   SUDDENDEATH(SFKernCacheIntBad);                             <<06858>>21835000
LDEV'OFFSET := DEVCDTENTRY * CDT'ENTRY'SIZE;                   <<*7724>>21840000
                                                                        21845000
<< Decrement current region count by 1.  If < 0, SF >>                  21850000
$if x1=on                                                      <<*7724>>21855000
if CDT'ADD'WORD(devcdtentry,                                            21860000
                cdt'de'regions,                                         21865000
                -1) < 0 then                                            21870000
  SuddenDeath(sfkerncacheintbad);                                       21875000
$if x1=off                                                     <<*7724>>21880000
tos := CDT'ARRAY(LDEV'OFFSET+CDT'DE'REGIONS) - 1;              <<*7724>>21885000
if < then                                                      <<*7724>>21890000
   SUDDENDEATH(sfkerncacheintbad);                             <<*7724>>21895000
CDT'ARRAY(CDT'X) := tos;                                       <<*7724>>21900000
$if                                                            <<*7724>>21905000
                                                                        21910000
<< Decrement number of main memory pages consumed by device >>          21915000
TOS := regionbase;                                                      21920000
TOS := TOS + RBTOSSDISP;                                                21925000
ASMB(LSEA);                                                             21930000
REGSIZE := -TOS;                                                        21935000
$if x1=on                                                      <<*7724>>21940000
CDT'ADD'WORD(devcdtentry,cdt'de'mapd'pages,regsize);                    21945000
$if x1=off                                                     <<*7724>>21950000
CDT'X := LDEV'OFFSET + CDT'DE'MAPD'PAGES;                      <<*7724>>21955000
CDT'ARRAY(CDT'X) := CDT'ARRAY(CDT'X) + REGSIZE;                <<*7724>>21960000
$if                                                            <<*7724>>21965000
                                                                        21970000
                                                               <<07311>>21975000
$if x1=on                                                      <<07311>>21980000
TOS := MMSTAT'LINK'REGION;                                     <<07311>>21985000
TOS := 1;                   << 0 = link, 1 = unlink >>         <<07311>>21990000
TOS := REGIONBASE;                                             <<07311>>21995000
MMSTAT'(*,*,*,*,DEVCDTENTRY,REGSIZE,0);                        <<07311>>22000000
$if                                                            <<07311>>22005000
                                                               <<07311>>22010000
<< Look up addresses of prev hole and next link from header >>          22015000
                                                                        22020000
TOS := regionbase;                                                      22025000
TOS := TOS+RBTOPDDISP;                                                  22030000
ASMB(LDEA);                                                             22035000
if < then                                                               22040000
   SUDDENDEATH(SFKernCacheIntBad);  << Already unlinked >>              22045000
PREVLINK := TOS;                                                        22050000
TOS := -1D;                                                             22055000
ASMB(SDEA);                                                             22060000
TOS := TOS+PDTONDDISP;                                                  22065000
ASMB(LDEA);                                                             22070000
if < then                                                               22075000
   SUDDENDEATH(SFKernCacheIntBad);  << Already unlinked >>              22080000
NEXTLINK := TOS;                                                        22085000
TOS := -1D;                                                             22090000
ASMB(SDEA);                                                             22095000
ASMB(DDEL);                                                             22100000
                                                                        22105000
<< Take the region off the list >>                                      22110000
                                                                        22115000
IF PREVLINK <> 0D THEN                                                  22120000
   BEGIN   << Region is not the first in the list. >>                   22125000
                                                                        22130000
   << Place next link into previous cd's next link >>                   22135000
                                                                        22140000
   TOS := PREVLINK;                                                     22145000
   TOS := TOS+PDTONDDISP;                                               22150000
                                                                        22155000
   << Update scan point >>                                              22160000
   ASMB(DDUP);                                                          22165000
   holdnextptr := TOS;                                                  22170000
$if x1=on                                                      <<*7724>>22175000
   CDT'SET'DOUBLE(devcdtentry,cdt'de'scanpt,holdnextptr);               22180000
$if x1=off                                                     <<*7724>>22185000
   ASMB(DDUP);                                                 <<*7724>>22190000
   CDT'DARRAY((LDEV'OFFSET+CDT'DE'SCANPT)&asr(1)) := tos;      <<*7724>>22195000
$if                                                            <<*7724>>22200000
                                                                        22205000
   TOS := NEXTLINK;                                                     22210000
   ASMB(SDEA;DDEL);                                                     22215000
                                                                        22220000
   << Place Previnlist into next cd's Previous pointer >>               22225000
                                                                        22230000
   IF NEXTLINK=0D THEN                                                  22235000
      BEGIN   << That was the last cd in the list. >>                   22240000
                                                                        22245000
      << Update hole list tail and max avail region size >>             22250000
                                                                        22255000
      TOS := PREVLINK;                                                  22260000
      TOS := TOS + PDTONDDISP;                                          22265000
      ASMB(DDUP);                                                       22270000
      cdtail := TOS;                                                    22275000
                                                                        22280000
      << Put terminator (LLSH) in new last region >>                    22285000
      TOS := TOS + NDtoCACDAdisp;                                       22290000
      TOS := -1;                                                        22295000
      ASMB(SSEA;DDEL);                                                  22300000
                                                                        22305000
$if x1=on                                                      <<*7724>>22310000
      CDT'SET'DOUBLE(devcdtentry,cdt'de'reg'tl,cdtail);                 22315000
$if x1=off                                                     <<*7724>>22320000
      CDT'DARRAY((LDEV'OFFSET+CDT'DE'REG'TL)&asr(1)) :=        <<*7724>>22325000
         CDTAIL;                                               <<*7724>>22330000
$if                                                            <<*7724>>22335000
      END                                                               22340000
   ELSE                                                                 22345000
      BEGIN    << Not the last cd in the list >>                        22350000
      TOS := NEXTLINK;                                                  22355000
      TOS := TOS+NDTOPDDISP;                                            22360000
      TOS := PREVLINK;                                                  22365000
      ASMB(SDEA;DDEL);   << new Prev link for next in list >>           22370000
      END;                                                              22375000
   END                                                                  22380000
ELSE                                                                    22385000
   BEGIN        << Removing first in list >>                            22390000
                                                                        22395000
   << Update scan point.  Since there isn't a prior, point >>           22400000
   << to CDHEAD.                                           >>           22405000
$if x1=on                                                      <<*7724>>22410000
   CDT'SET'DOUBLE(devcdtentry,cdt'de'scanpt,0D);                        22415000
$if x1=off                                                     <<*7724>>22420000
   CDT'DARRAY((LDEV'OFFSET+CDT'DE'SCANPT)&asr(1)) := 0D;       <<*7724>>22425000
$if                                                            <<*7724>>22430000
                                                                        22435000
   IF NEXTLINK = 0D THEN                                                22440000
      BEGIN  <<last entry in list>>                                     22445000
$if x1=on                                                      <<*7724>>22450000
      CDT'SET'DOUBLE(devcdtentry,cdt'de'reg'hd,0d);                     22455000
      CDT'SET'DOUBLE(devcdtentry,cdt'de'reg'tl,0d);                     22460000
$if x1=off                                                     <<*7724>>22465000
      CDT'DARRAY((LDEV'OFFSET+CDT'DE'REG'HD)&asr(1)) := 0D;    <<*7724>>22470000
      CDT'DARRAY((LDEV'OFFSET+CDT'DE'REG'TL)&asr(1)) := 0D;    <<*7724>>22475000
$if                                                            <<*7724>>22480000
      END                                                               22485000
   ELSE                                                                 22490000
      BEGIN    << There's a cd after this one >>                        22495000
                                                                        22500000
      << Make next cd the new head. >>                                  22505000
                                                                        22510000
$if x1=on                                                      <<*7724>>22515000
      CDT'SET'DOUBLE(devcdtentry,cdt'de'reg'hd,nextlink);               22520000
$if x1=off                                                     <<*7724>>22525000
      CDT'DARRAY((LDEV'OFFSET+CDT'DE'REG'HD)&asr(1)) :=        <<*7724>>22530000
         NEXTLINK;                                             <<*7724>>22535000
$if                                                            <<*7724>>22540000
      TOS := NEXTLINK;                                                  22545000
      TOS := TOS+NDTOPDDISP;                                            22550000
      TOS := 0D;                                                        22555000
      ASMB(SDEA;DDEL);   << erase previous link >>                      22560000
      END;                                                              22565000
   END;                                                                 22570000
                                                               <<*7724>>22575000
<< Put DB back to caller's DB >>                               <<*7724>>22580000
tos := SAVE'DB;                                                <<*7724>>22585000
EXCHDB;                                                        <<*7724>>22590000
                                                               <<*7724>>22595000
END;  <<UnlinkCachedDomain>>                                            22600000
$page "Cache Management Utilities : Zap Cached Domain"                  22605000
                                                                        22610000
PROCEDURE ZapCachedDomain(regionbase);                                  22615000
VALUE regionbase;                                                       22620000
DOUBLE regionbase;                                                      22625000
OPTION PRIVILEGED,UNCALLABLE;                                           22630000
                                                                        22635000
COMMENT                                                                 22640000
                                                                        22645000
removes the cached disc domain pointed to by regionbase from the list   22650000
of cached domains attached to the device's CDT entry, wipes out the     22655000
indications in the region header that a cached domain was sitting       22660000
there, and releases the main memory region.                    <<06858>>22665000
                                                                        22670000
Assumes caller is pdisabled, and DB is placed at SYSDB.        <<06858>>22675000
                                                               <<06858>>22680000
                                                                        22685000
Returned condition codes are:                                  <<06858>>22690000
                                                               <<06858>>22695000
   CCE - Domain was successfully removed                       <<06858>>22700000
   CCG - Domain was NOT remove because it was still mapped     <<06858>>22705000
;                                                                       22710000
                                                                        22715000
BEGIN                                                                   22720000
                                                                        22725000
DOUBLE obj;                                                    <<06855>>22730000
LOGICAL ARRAY objid(*)=obj;                                    <<06855>>22735000
LOGICAL subregflags,                                           <<06858>>22740000
        rstat = q-1;     << Caller's status register >>        <<06858>>22745000
                                                               <<06858>>22750000
DEFINE rstatus = rstat.(6:2)#;                                 <<06858>>22755000
                                                                        22760000
TOS:=regionbase;                                                        22765000
TOS := TOS+rbtoobjidentdisp;                                            22770000
ASMB(LDEA);                                                    <<06855>>22775000
obj := TOS;                                                    <<06855>>22780000
IF (objid(ObjIDtypeField) <> ObjIDcdType) then                 <<06858>>22785000
   SUDDENDEATH(SFKernCacheIntBad);                             <<06858>>22790000
                                                               <<06858>>22795000
<< If it is still mapped into a CDT entry, we cannot release >><<06858>>22800000
<< it from main memory.                                      >><<06858>>22805000
if (objid(objidnumfield) <> 0 ) then                           <<06858>>22810000
   RSTATUS := CCG                                              <<06858>>22815000
else                                                           <<06858>>22820000
   begin                                                       <<06858>>22825000
   TOS:=0;                                                     <<06858>>22830000
   ASMB(SSEA);                                                 <<06858>>22835000
   UnlinkCachedRegion(regionbase);                             <<06858>>22840000
                                                                        22845000
   TOS := regionbase;                                          <<06858>>22850000
   TOS:=TOS+rbtosasdisp;                                       <<06858>>22855000
   ASMB(LSEA);                                                 <<06858>>22860000
   subregflags := TOS;                                         <<06858>>22865000
   IF NOT subregflags.regcachedflag THEN                       <<06858>>22870000
      SUDDENDEATH(SFKernCacheIntBad);                          <<06858>>22875000
   TOS:=subregflags;                                           <<06858>>22880000
   TOS.regcachedflag:=0;                                       <<06858>>22885000
   TOS.regrocflag:=0;                                          <<06858>>22890000
   ASMB(SSEA);                                                 <<06858>>22895000
                                                                        22900000
   <<if reg assigned, release it>>                             <<06858>>22905000
                                                                        22910000
   TOS:=TOS+sastorasdisp;                                      <<06858>>22915000
   ASMB(LSEA);                                                 <<06858>>22920000
   IF LS0.regreservedflag THEN SuddenDeath(SFKernCacheIntBad); <<06858>>22925000
   IF LS0.regassignedflag THEN                                 <<06858>>22930000
      BEGIN                                                    <<06858>>22935000
                                                               <<06858>>22940000
                                                               <<06858>>22945000
      ReleaseRegion(regionbase,0);                             <<06858>>22950000
                                                               <<06858>>22955000
      END;                                                     <<06858>>22960000
                                                               <<06858>>22965000
   << Return good status back to caller >>                     <<06858>>22970000
   RSTATUS := CCE;                                             <<06858>>22975000
   end;                                                        <<06858>>22980000
END;  <<ZapCachedDomain>>                                               22985000
                                                                        22990000
                                                                        22995000
$page "Cache Utilities : CDT'MAP'CACHED'DOMAIN"                         23000000
                                                                        23005000
LOGICAL PROCEDURE CDT'MAP'CACHED'DOMAIN(devcdtentry,start'addr,         23010000
                                        limit'addr,new'cdt,    <<07308>>23015000
                                        ldr'entry'index);      <<07308>>23020000
VALUE devcdtentry,start'addr,limit'addr,new'cdt,               <<07308>>23025000
      ldr'entry'index;                                                  23030000
INTEGER devcdtentry,new'cdt;                                            23035000
LOGICAL ldr'entry'index;                                       <<07308>>23040000
DOUBLE start'addr,limit'addr;                                           23045000
OPTION PRIVILEGED,UNCALLABLE,INTERNAL;                         <<06858>>23050000
                                                                        23055000
                                                                        23060000
COMMENT                                                                 23065000
                                                                        23070000
Input parameters are:                                                   23075000
                                                                        23080000
devcdtentry  - this is the CDT entry no. of the device.                 23085000
                                                                        23090000
start'addr   - this is the starting sector number of the                23095000
               requested domain(s) to flush, or the start               23100000
               address of logical disc request issued to                23105000
               satisfy a map request.                                   23110000
                                                                        23115000
limit'adr    - this is the limit sector number of the requested         23120000
               domain(s) to be flushed, or the end address of           23125000
               the logical disc request.                                23130000
                                                                        23135000
new'cdt      - only valid on a map request, this is the newly           23140000
               obtained mapped-domain CDT entry which has NOT h<<07308>>23145000
               strategy applied to it.  In case of a miss on the        23150000
               disc range specified by start'addr and limit'add<<07308>>23155000
               the disc address range specified in the CDT is           23160000
               flushed because it has a strategy applied to it          23165000
               which might be larger than the disc address range        23170000
               necessary to satisfy the actual logical disc req.        23175000
                                                                        23180000
ldr'entry'                                                     <<07308>>23185000
index        - only valid on a map request, this is the        <<07308>>23190000
               logical disc request which is trying to be      <<07308>>23195000
               statisfied.  Its only reason for being passed   <<07308>>23200000
               is to use it as a parameter to the STRATEGY     <<07308>>23205000
               routine on a MISS.                              <<07308>>23210000
                                                               <<07308>>23215000
Return parameter is:                                                    23220000
                                                                        23225000
cdt'map'cached'domain -                                        <<06858>>23230000
               On a map request, false is returned             <<06858>>23235000
               on a miss and true is returned if there is a             23240000
               hit.                                                     23245000
                                                                        23250000
cdt'flush'cached'range -                                       <<06858>>23255000
               On a flush request, TRUE is returned if the enti<<06858>>23260000
               range was successfully flushed, and FALSE is ret<<06858>>23265000
               if there was a MAPPED domain in the range specif<<06858>>23270000
               to be flushed.                                  <<06858>>23275000
                                                               <<06858>>23280000
This procedure scans the list of cached regions pointed to by the       23285000
devcdtentry passed as a parameter to locate the disc region             23290000
delimited by the start'addr and limit'addr parameters.  If a cached     23295000
region is found which completely contains the specified disc range,     23300000
a CDT entry is obtained and formatted to map the cached region and      23305000
the cdt entry number is returned.  Anyt partial overlaps are zapped     23310000
out from memory.  If the specified disc range is not on the list        23315000
of cached disc domains, a zero is returned.                             23320000
                                                                        23325000
caller expected to be pdisabled, DB must be at SYSDB.                   23330000
                                                                        23335000
                                                                        23340000
;                                                                       23345000
                                                                        23350000
BEGIN                                                                   23355000
                                                                        23360000
ENTRY CDT'Flush'Cached'Range;                                           23365000
                                                                        23370000
EQUATE hodatopddisp    = rbtopddisp - rbtohodadisp,            <<07308>>23375000
       hodatorbdisp    = -rbtohodadisp;                        <<07308>>23380000
                                                               <<07308>>23385000
INTEGER limithoda=limit'addr,                                           23390000
        limitloda=limithoda+1;                                          23395000
                                                                        23400000
DOUBLE cdhead,                                                          23405000
       cdtail,                                                          23410000
       targetda,                                                        23415000
       nextdiscaddr,                                                    23420000
       limitda,                                                         23425000
       da'less'ldev,                                                    23430000
       nextlinktocheck,                                                 23435000
       checkregionbase,                                                 23440000
       save'overlap'regbase,   << For flush on "miss" map req >>        23445000
       targetda'hit,           << DA for HIT on map request   >>        23450000
       limitda'hit,            << Limit DA for HIT on map req.>>        23455000
       scanpt,                 << Scan point (to save time)   >>        23460000
       checkregionsectors,                                              23465000
       checkregionlimit,                                                23470000
       checkregionstart;                                                23475000
                                                                        23480000
INTEGER domainsize,                                                     23485000
        cdcount,                                                        23490000
        remlinkcount,                                                   23495000
        ldev,                                                           23500000
        flags,                                                          23505000
        returned'cdt = cdt'map'cached'domain,                           23510000
        starthoda=start'addr,                                           23515000
        startloda=start'addr+1;                                         23520000
                                                                        23525000
<< Variables for fast CDT accessing >>                         <<*7724>>23530000
DOUBLE  SAVE'DB;             << Value of DB upon calling >>    <<*7724>>23535000
INTEGER LDEV'OFFSET,         << Offset of LDEV entry in CDT >> <<*7724>>23540000
        MAPD'OFFSET,         << Offset of MAPD entry in CDT >> <<*7724>>23545000
        TEMP'MAPD'OFFSET;    << Offset to temp MAPD entry   >> <<*7724>>23550000
                                                               <<*7724>>23555000
LOGICAL flush,                                                          23560000
        cdtfield,            << CDT# portion of objident    >> <<*7724>>23565000
        smaller,                                                        23570000
        roc,                                                            23575000
        zapfailed:=FALSE,<<T if zap of mapped domain attempted <<06858>>23580000
        gotahit := FALSE;                                               23585000
                                                                        23590000
DOUBLE obj;                                                    <<06855>>23595000
LOGICAL ARRAY objident(*)=obj;                                 <<06855>>23600000
$if x1=off                                                              23605000
DEF'SET'DOUBLE;                                                         23610000
DEF'SET'BIT;                                                            23615000
DEF'GET'DOUBLE;                                                         23620000
DEF'GET'WORD;                                                           23625000
$if                                                                     23630000
$page                                                          <<07308>>23635000
SUBROUTINE CheckCheckRegion;                                            23640000
                                                                        23645000
COMMENT                                                                 23650000
                                                                        23655000
checks the region pointed to by the checkregionbase variable to see     23660000
if this disc domain is contained in that region or overlaps that        23665000
region.  If contained, that region is mapped in.  If partial            23670000
overlapped, that region is zapped.                                      23675000
                                                                        23680000
The entry point CDT'Flush'CachedRange causes any overlapping domains    23685000
to be zapped even if they are complete hits.                            23690000
                                                                        23695000
;                                                                       23700000
                                                                        23705000
BEGIN                                                                   23710000
                                                                        23715000
<<check check reg for overlap>>                                         23720000
                                                                        23725000
TOS := checkregionbase;                                                 23730000
TOS := TOS + rbtohodadisp;                                              23735000
ASMB(LDEA);                                                             23740000
checkregionstart:=TOS;                                                  23745000
                                                                        23750000
<< If this domain is absent, but assigned a reserved region, >>         23755000
<< the SS is not correct yet.  We must figure length from    >>         23760000
<< mapped CDT entry.                                         >>         23765000
tos := tos + hodatoobjidentdisp;                                        23770000
ASMB(LDEA);                                                    <<06855>>23775000
obj:=tos;                                                      <<06855>>23780000
if (objident(ObjIDtypeField) = ObjIDcdType) then               <<06855>>23785000
   begin  << This is a cached domain, check if assigned >>              23790000
   if ( cdtfield := objident(ObjidNumField) ) <> 0 then        <<*7724>>23795000
     begin << Get length from CDT entry >>                              23800000
$if x1=on                                                      <<*7724>>23805000
     checkregionsectors:=                                               23810000
      CDT'GET'DOUBLE(cdtfield,cdt'md'end'sector,0D)            <<*7724>>23815000
       0D)                                                     <<06855>>23820000
     -CDT'GET'DOUBLE(cdtfield,cdt'md'sector,0D);               <<*7724>>23825000
$if x1=off                                                     <<*7724>>23830000
     TEMP'MAPD'OFFSET := CDTFIELD * CDT'ENTRY'SIZE;            <<*7724>>23835000
     CHECKREGIONSECTORS :=                                     <<*7724>>23840000
        CDT'DARRAY((TEMP'MAPD'OFFSET+CDT'MD'END'SECTOR)&asr(1))<<*7724>>23845000
      - CDT'DARRAY((TEMP'MAPD'OFFSET+CDT'MD'SECTOR)&asr(1));   <<*7724>>23850000
$if                                                            <<*7724>>23855000
     end                                                                23860000
   else                                                                 23865000
     begin  << normal path >>                                           23870000
     tos := tos + objidenttossdisp;                                     23875000
     ASMB(LSEA;DECA,ZERO;XCH);  << Put double pgs-1 on tos >>           23880000
     tos := tos * sectorspermainmempage;                                23885000
     checkregionsectors := tos;  << Save # of sectors >>                23890000
     end;                                                               23895000
   end                                                                  23900000
else                                                                    23905000
   SUDDENDEATH(SFKernCacheIntBad);  << Not a cached domain >>           23910000
                                                                        23915000
ASMB(DDEL); <<get rid of region address>>                               23920000
TOS:=checkregionlimit:=checkregionstart+checkregionsectors;    <<06858>>23925000
                                                                        23930000
IF TOS > TARGETDA'HIT THEN                                     <<07308>>23935000
   BEGIN <<checkregion is beyond>>                             <<06858>>23940000
   IF checkregionstart < limitda'hit THEN                      <<07308>>23945000
      BEGIN  <<check region not below ==> they overlap>>                23950000
      IF flush THEN                                            <<06858>>23955000
         BEGIN                                                 <<06858>>23960000
         << Point to SYSDB >>                                  <<*7724>>23965000
         tos := %1000 D;                                       <<*7724>>23970000
         EXCHDB;                                               <<*7724>>23975000
                                                               <<*7724>>23980000
         ZapCachedDomain(checkregionbase);                     <<06858>>23985000
         IF > THEN                                             <<06858>>23990000
            zapfailed := TRUE;                                 <<06858>>23995000
         << Point back to CDT >>                               <<*7724>>24000000
         EXCHDB;                                               <<*7724>>24005000
         ASMB(DDEL);                                           <<*7724>>24010000
         END                                                   <<06858>>24015000
      ELSE                                                     <<06858>>24020000
         BEGIN  <<not flush so check for hit>>                          24025000
                                                                        24030000
         << At this point, we have determined that an overlap >>        24035000
         << exists with, at least, the strategy determined on >>        24040000
         << this request.  Save the first region number over- >>        24045000
         << lapping in case we need to flush on an overlap.   >>        24050000
         IF save'overlap'regbase = 0D THEN                              24055000
            save'overlap'regbase := checkregionbase;                    24060000
                                                                        24065000
         << Now, use actual request disc address to determine >>        24070000
         << whether we have a total 'hit'.                    >>        24075000
         IF (checkregionstart <= targetda'hit)                          24080000
         AND (checkregionlimit >= limitda'hit) THEN                     24085000
            BEGIN  <<its contained entirely in the check region>>       24090000
            gotahit := TRUE;                                            24095000
                                                                        24100000
            <<if region not assigned, recover it>>                      24105000
                                                                        24110000
            TOS:=checkregionbase;                                       24115000
            TOS:=TOS+rbtosasdisp;                                       24120000
            ASMB(LSEA);                                                 24125000
            IF NOT LS0.regcachedflag                                    24130000
            THEN SuddenDeath(SFkernCacheIntBad);                        24135000
            IF LS0.regrocflag THEN                                      24140000
               BEGIN <<RECOVER IT>>                                     24145000
               << Point to SYSDB >>                            <<*7724>>24150000
               tos := %1000 D;                                 <<*7724>>24155000
               EXCHDB;                                         <<*7724>>24160000
                                                               <<*7724>>24165000
               RecoverOC(BuildObjId(mappeddomainobject,0,0),            24170000
                         0,checkregionbase);                            24175000
               << Point back to CDT >>                         <<*7724>>24180000
               EXCHDB;                                         <<*7724>>24185000
               ASMB(DDEL);                                     <<*7724>>24190000
               roc := TRUE;                                             24195000
               END                                                      24200000
            ELSE                                                        24205000
               roc := FALSE;                                            24210000
                                                                        24215000
            ASMB(DEL,DDEL);                                             24220000
                                                                        24225000
            <<map in check region>>                                     24230000
                                                                        24235000
            << Strip ldev >>                                            24240000
            tos := checkregionstart;                                    24245000
            s1.(0:8) := 0;                                              24250000
$if x1=on                                                      <<*7724>>24255000
            da'less'ldev := tos;                                        24260000
                                                                        24265000
            CDT'SET'DOUBLE(new'cdt,cdt'md'sector,                       24270000
                           da'less'ldev);                               24275000
$if x1=off                                                     <<*7724>>24280000
            CDT'DARRAY((MAPD'OFFSET+CDT'MD'SECTOR) & asr(1))   <<*7724>>24285000
               := tos;                                         <<*7724>>24290000
$if                                                            <<*7724>>24295000
            tos := checkregionlimit;                                    24300000
            s1.(0:8) := 0;                                              24305000
$if x1=on                                                      <<*7724>>24310000
            da'less'ldev := tos;                                        24315000
            CDT'SET'DOUBLE(new'cdt,cdt'md'end'sector,                   24320000
                           da'less'ldev);                               24325000
$if x1=off                                                     <<*7724>>24330000
            CDT'DARRAY((MAPD'OFFSET+CDT'MD'END'SECTOR)&asr(1)) <<*7724>>24335000
                := tos;                                        <<*7724>>24340000
$if                                                            <<*7724>>24345000
                                                               <<*7724>>24350000
$if x1=on                                                      <<*7724>>24355000
            CDT'SET'DOUBLE(new'cdt,cdt'md'mem'addr,checkregionbase);    24360000
                                                                        24365000
            << Update scan point >>                                     24370000
            CDT'SET'DOUBLE(devcdtentry,cdt'de'scanpt,                   24375000
                           checkregionbase+DOUBLE(RBtoNDdisp));         24380000
                                                                        24385000
            CDT'SET'BIT(new'cdt,CDT'ABS'BIT,0);<<mark pres>>            24390000
            CDT'SET'BIT(new'cdt,CDT'VIRGIN'BIT,0);<<Not virgin>>        24395000
                                                               <<*7724>>24400000
$if x1=off                                                     <<*7724>>24405000
            CDT'DARRAY((MAPD'OFFSET+CDT'MD'MEM'ADDR) & asr(1)) <<*7724>>24410000
                := CHECKREGIONBASE;                            <<*7724>>24415000
                                                               <<*7724>>24420000
            << Update scan point >>                            <<*7724>>24425000
            tos := CHECKREGIONBASE;                            <<*7724>>24430000
            tos := tos + RBtoNDdisp;                           <<*7724>>24435000
            CDT'DARRAY((LDEV'OFFSET+CDT'DE'SCANPT)&asr(1))     <<*7724>>24440000
               := tos;                                         <<*7724>>24445000
                                                               <<*7724>>24450000
            tos := CDT'ARRAY(MAPD'OFFSET+CDT'MD'FLAGS);        <<*7724>>24455000
            tos.(CDT'ABS'BIT:1) := 0;                          <<*7724>>24460000
            tos.(CDT'VIRGIN'BIT:1) := 0;                       <<*7724>>24465000
            CDT'ARRAY(CDT'X) := tos;                           <<*7724>>24470000
$if                                                            <<*7724>>24475000
                                                               <<*7724>>24480000
            <<fix up objident in region header>>                        24485000
            TOS:=checkregionbase;                                       24490000
            TOS:=TOS+rbtoobjidentdisp;                                  24495000
            TOS := obj;                                        <<07307>>24500000
                                                               <<*7724>>24505000
            << If already mapped, there is a logic problem >>  <<*7724>>24510000
            IF cdtfield <> 0 THEN                              <<*7724>>24515000
               SuddenDeath(SFKernCacheIntBad);                          24520000
            S0:=new'cdt;                                       <<06855>>24525000
            ASMB(SDEA;DDEL);                                   <<06855>>24530000
            END;                                                        24535000
         END;                                                           24540000
      END;                                                              24545000
   END;                                                                 24550000
END;  <<SUBROUTINE CheckCheckRegion>>                                   24555000
$page                                                          <<07308>>24560000
SUBROUTINE LOOP'THRU'LIST;                                              24565000
BEGIN                                                                   24570000
                                                                        24575000
<< Called when pointing to overlapping part of list >>                  24580000
TOS := nextlinktocheck;                                                 24585000
TOS := TOS + ndtohodadisp;                                              24590000
ASMB(LDEA;DXCH,DDEL);                                                   24595000
nextdiscaddr := TOS;                                                    24600000
WHILE (nextlinktocheck > 0D)                                            24605000
AND (limitda'hit > nextdiscaddr)                               <<07308>>24610000
AND NOT gotahit                                                         24615000
DO                                                                      24620000
   BEGIN <<check next link for overlap>>                                24625000
   TOS := nextlinktocheck;                                              24630000
   ASMB(LDEA);                                                          24635000
   nextlinktocheck := TOS;                                              24640000
   TOS := TOS + ndtorbdisp;                                             24645000
   checkregionbase := TOS;                                              24650000
   CheckCheckRegion;                                                    24655000
   TOS := nextlinktocheck;                                              24660000
   TOS := TOS + ndtohodadisp;                                           24665000
   ASMB(LDEA);                                                          24670000
   nextdiscaddr := TOS;                                                 24675000
   ASMB(DDEL);    << Clean up stack >>                                  24680000
   END;                                                                 24685000
END;                                                                    24690000
$page                                                          <<07308>>24695000
SUBROUTINE PROCESS'MISS;                                       <<07308>>24700000
BEGIN                                                          <<07308>>24705000
<< Process a MISS on a MAP request >>                          <<07308>>24710000
<< First, apply a STRATEGY to the request >>                   <<07308>>24715000
CDT'STRATEGY(NEW'CDT,LDR'ENTRY'INDEX);                         <<07308>>24720000
                                                               <<07308>>24725000
<< Obtain disc limits from strategy >>                         <<07308>>24730000
$if x1=on                                                      <<*7724>>24735000
TOS := CDT'GET'DOUBLE(NEW'CDT,CDT'MD'SECTOR,0D);               <<07308>>24740000
$if x1=off                                                     <<*7724>>24745000
tos := CDT'DARRAY((MAPD'OFFSET+CDT'MD'SECTOR)&asr(1));         <<*7724>>24750000
$if                                                            <<*7724>>24755000
S1.regldevfield := ldev;                                       <<07308>>24760000
targetda := TOS;                                               <<07308>>24765000
$if x1=on                                                      <<*7724>>24770000
TOS := CDT'GET'DOUBLE(NEW'CDT,CDT'MD'END'SECTOR,0D);           <<07308>>24775000
$if x1=off                                                     <<*7724>>24780000
tos := CDT'DARRAY((MAPD'OFFSET+CDT'MD'END'SECTOR)&asr(1));     <<*7724>>24785000
$if                                                            <<*7724>>24790000
S1.regldevfield := ldev;                                       <<07308>>24795000
limitda := TOS;                                                <<07308>>24800000
                                                               <<07308>>24805000
<< Determine region address to back-up to to start flush >>    <<07308>>24810000
if SAVE'OVERLAP'REGBASE = 0D then                              <<07308>>24815000
   if (SAVE'OVERLAP'REGBASE:=CHECKREGIONBASE) = 0D then        <<07308>>24820000
      if CDTAIL <> 0D then                                     <<07308>>24825000
         SAVE'OVERLAP'REGBASE:=CDTAIL+double(NDtoRBdisp);      <<07308>>24830000
                                                               <<07308>>24835000
tos := SAVE'OVERLAP'REGBASE;                                   <<07308>>24840000
if <> then                                                     <<07308>>24845000
   begin  << Start backing-up regions until no overlap >>      <<07308>>24850000
   SMALLER := false;                                           <<07308>>24855000
   do                                                          <<07308>>24860000
      begin                                                    <<07308>>24865000
      tos := tos + RBTOHODADISP;                               <<07308>>24870000
      ASMB(LDEA);                                              <<07308>>24875000
      if tos > TARGETDA then  << We must go-back a region >>   <<07308>>24880000
         begin                                                 <<07308>>24885000
         tos := tos + HODATOPDDISP;                            <<07308>>24890000
         ASMB(LDEA);                                           <<07308>>24895000
         if = then << We're at beginning-of-list >>            <<07308>>24900000
            begin << Terminate scan >>                         <<07308>>24905000
            ASMB(DDEL);  << Remove zeros >>                    <<07308>>24910000
            tos := tos + PDTORBDISP;  << Point back to RB >>   <<07308>>24915000
            SMALLER := true;                                   <<07308>>24920000
            end                                                <<07308>>24925000
         else                                                  <<07308>>24930000
            << Make TOS a RB to previous region >>             <<07308>>24935000
            begin                                              <<07308>>24940000
            tos := tos + PDTORBDISP;                           <<07308>>24945000
            ASMB(DXCH,DDEL);                                   <<07308>>24950000
            end;                                               <<07308>>24955000
         end                                                   <<07308>>24960000
      else                                                     <<07308>>24965000
         << We have backed-up far-enough >>                    <<07308>>24970000
         begin                                                 <<07308>>24975000
         tos := tos + HODATORBDISP;                            <<07308>>24980000
         SMALLER := true;                                      <<07308>>24985000
         end;                                                  <<07308>>24990000
      end until SMALLER;  << of DO backing-up regions >>       <<07308>>24995000
                                                               <<07308>>25000000
   << Region base should be on TOS here >>                     <<07308>>25005000
   tos := tos + RBTONDDISP;                                    <<07308>>25010000
   NEXTLINKTOCHECK := tos;                                     <<07308>>25015000
   FLUSH := true;                                              <<07308>>25020000
   LIMITDA'HIT := LIMITDA;                                     <<07308>>25025000
   TARGETDA'HIT := TARGETDA;                                   <<07308>>25030000
   LOOP'THRU'LIST;                                             <<07308>>25035000
   end                                                         <<07308>>25040000
else                                                           <<07308>>25045000
   ASMB(DDEL);  << Remove stacked regionbase of zeros >>       <<07308>>25050000
end;  << of subroutine PROCESS'MISS >>                         <<07308>>25055000
$page                                                          <<07308>>25060000
flush := FALSE;                                                         25065000
GO START;                                                               25070000
                                                                        25075000
CDT'FLUSH'CACHED'REGION : flush := TRUE;                                25080000
                                                                        25085000
START:                                                                  25090000
                                                                        25095000
<< Place DB at CDT >>                                          <<*7724>>25100000
CDT'ABS'ON'TOS;                                                <<*7724>>25105000
EXCHDB;                                                        <<*7724>>25110000
SAVE'DB := tos;                                                <<*7724>>25115000
LDEV'OFFSET := DEVCDTENTRY * CDT'ENTRY'SIZE;                   <<*7724>>25120000
MAPD'OFFSET := NEW'CDT * CDT'ENTRY'SIZE;                       <<*7724>>25125000
                                                               <<*7724>>25130000
$if x1=on                                                      <<*7724>>25135000
cdhead  := CDT'GET'DOUBLE(devcdtentry,                                  25140000
                          cdt'de'reg'hd,                                25145000
                          0d);                                          25150000
                                                                        25155000
cdtail := CDT'GET'DOUBLE(devcdtentry,                                   25160000
                         cdt'de'reg'tl,                                 25165000
                         0d);                                           25170000
                                                                        25175000
ldev := CDT'GET'WORD(devcdtentry,cdt'de'ldev,0);                        25180000
                                                                        25185000
$if x1=off                                                     <<*7724>>25190000
CDHEAD:=CDT'DARRAY((LDEV'OFFSET+CDT'DE'REG'HD)&asr(1));        <<*7724>>25195000
CDTAIL:=CDT'DARRAY((LDEV'OFFSET+CDT'DE'REG'TL)&asr(1));        <<*7724>>25200000
LDEV := CDT'ARRAY(LDEV'OFFSET+CDT'DE'LDEV);                    <<*7724>>25205000
$if                                                            <<*7724>>25210000
                                                               <<*7724>>25215000
checkregionbase :=                                             <<07308>>25220000
save'overlap'regbase := 0D;  << Init to no overlap >>                   25225000
                                                               <<*7551>>25230000
IF (CDCOUNT := CDT'ARRAY(LDEV'OFFSET+CDT'DE'REGIONS)) = 0      <<*7724>>25235000
   AND CDT'ARRAY(LDEV'OFFSET+CDT'DE'MAPD'CNT) <> 0             <<*7724>>25240000
  THEN ZAPFAILED := TRUE;                                      <<*7551>>25245000
                                                               <<*7551>>25250000
                                                                        25255000
$if x1=on                                                      <<*7724>>25260000
tos := CDCOUNT := CDT'GET'WORD(DEVCDTENTRY,CDT'DE'REGIONS,0);  <<*7724>>25265000
$if x1=off                                                     <<*7724>>25270000
tos := CDCOUNT := CDT'ARRAY(LDEV'OFFSET+CDT'DE'REGIONS);       <<*7724>>25275000
$if                                                            <<*7724>>25280000
                                                               <<*7724>>25285000
IF (tos <<CDCOUNT>> <> 0) then                                 <<*7724>>25290000
                                                               <<*7724>>25295000
   BEGIN     << Device has some cached domains >>                       25300000
                                                                        25305000
   << Use disc address from CDT if this is a map request >>             25310000
                                                               <<07308>>25315000
                                                               <<07308>>25320000
   TOS := limit'addr;                                          <<07308>>25325000
   S1.regldevfield := ldev;  << Overlay LDEV >>                <<07308>>25330000
   limitda'hit := TOS;                                         <<07308>>25335000
   TOS := start'addr;                                          <<07308>>25340000
   S1.regldevfield := ldev;  << Overlay LDEV >>                <<07308>>25345000
   targetda'hit := TOS;                                        <<07308>>25350000
                                                               <<07308>>25355000
   TOS := NDtoCACDAdisp;<< offset from Link to target for LLSH >>       25360000
   TOS := targetda'hit;  << Search double word >>              <<07308>>25365000
   CDT'SHIFT'DA;  << Shift disc address for search >>                   25370000
   ASMB(DEL);     << Remove LODA portion of DA     >>                   25375000
                                                                        25380000
   << Determine whether to use scan point or CDHEAD >>                  25385000
$if x1=on                                                      <<*7724>>25390000
   tos := SCANPT :=                                            <<*7724>>25395000
          CDT'GET'DOUBLE(DEVCDTENTRY,CDT'DE'SCANPT,0D);        <<*7724>>25400000
$if x1=off                                                     <<*7724>>25405000
   tos := SCANPT :=                                            <<*7724>>25410000
      CDT'DARRAY((LDEV'OFFSET+CDT'DE'SCANPT)&asr(1));          <<*7724>>25415000
$if                                                            <<*7724>>25420000
                                                               <<*7724>>25425000
   IF (tos <> 0D) then                                         <<*7724>>25430000
                                                               <<*7724>>25435000
      BEGIN                                                             25440000
      TOS := SCANPT;                                                    25445000
      TOS := TOS + NDtoHODAdisp;                                        25450000
      ASMB(LDEA;DXCH,DDEL);                                             25455000
      IF TOS <= targetda'hit THEN                              <<07308>>25460000
         TOS := SCANPT                                                  25465000
      ELSE                                                              25470000
         TOS := CDHEAD;                                                 25475000
      END                                                               25480000
   ELSE                                                                 25485000
      TOS := CDHEAD;                                                    25490000
                                                                        25495000
   X := cdcount;         << link count >>                               25500000
   ASMB(LLSH);  << chase through the list to get to right place >>      25505000
   IF < THEN                                                            25510000
      BEGIN <<hit end-check the tail of the list>>                      25515000
      checkregionbase := cdtail + double(ndtorbdisp);                   25520000
      CheckCheckRegion;                                                 25525000
      END                                                               25530000
   ELSE                                                                 25535000
      BEGIN    << got some regions with the same or larger hoda>>       25540000
      << Check prior REGION (if any) for overlap >>            <<07308>>25545000
      TOS := TOS + NDtoPDdisp;                                 <<07308>>25550000
      ASMB(LDEA);  << Load prior link pointer >>               <<07308>>25555000
      IF = THEN    << There was no prior link >>               <<07308>>25560000
         ASMB(DDEL)                                            <<07308>>25565000
      ELSE                                                     <<07308>>25570000
         BEGIN  << There was, so adjust count, etc >>          <<07308>>25575000
         X := X + 1;  << New count of remaining regions >>     <<07308>>25580000
         ASMB(DXCH,DDEL); << Remove old link pointer >>        <<07308>>25585000
         END;                                                  <<07308>>25590000
      TOS := TOS + PDtoNDdisp;  << Change ptr to next ptr >>   <<07308>>25595000
      << Save parameters for posterity >>                      <<07308>>25600000
      TOS := nextlinktocheck := TOS;                           <<07308>>25605000
      REMLINKCOUNT := X;                                       <<07308>>25610000
      << Start looking for overlapping domains >>              <<07308>>25615000
      smaller := TRUE;                                         <<07308>>25620000
                                                               <<07308>>25625000
      DO                                                       <<07308>>25630000
         BEGIN <<chase thru list for a ms or so>>              <<07308>>25635000
         ASMB(DDUP);                                           <<07308>>25640000
         TOS := TOS + NDtoHODAdisp;                            <<07308>>25645000
         ASMB(LDEA;DXCH,DDEL);                                 <<07308>>25650000
         TOS := targetda'hit;                                  <<07308>>25655000
         ASMB(DCMP);                                           <<07308>>25660000
         IF <= THEN                                            <<07308>>25665000
            BEGIN <<targetda > regionda so continue>>          <<07308>>25670000
            ASMB(LDEA);  <<addr of next region's link>>        <<07308>>25675000
            IF <= THEN                                         <<07308>>25680000
               X := 1;  << Terminate scan >>                   <<07308>>25685000
            ASMB(DXCH,DDEL);  << Remove address >>             <<07308>>25690000
            END                                                <<07308>>25695000
         ELSE                                                  <<07308>>25700000
            BEGIN                                              <<07308>>25705000
            smaller := FALSE;                                  <<07308>>25710000
            END                                                <<07308>>25715000
         END                                                   <<07308>>25720000
      UNTIL (NOT smaller) OR DXBZ;                             <<07308>>25725000
                                                                        25730000
      IF smaller THEN                                          <<07308>>25735000
         BEGIN <<got to end of list>>                          <<07308>>25740000
         checkregionbase := cdtail + double(ndtorbdisp);       <<07308>>25745000
         CheckCheckRegion;                                     <<07308>>25750000
         END                                                   <<07308>>25755000
      ELSE                                                     <<07308>>25760000
         BEGIN    << stopped in middle of list >>              <<07308>>25765000
                                                               <<07308>>25770000
         <<prev region may have overlapped so check it>>       <<07308>>25775000
         TOS := nextlinktocheck := TOS;                        <<07308>>25780000
         TOS := TOS +ndtopddisp;                               <<07308>>25785000
         ASMB(LDEA);                                           <<07308>>25790000
         IF > THEN                                             <<07308>>25795000
            BEGIN <<check prev region>>                        <<07308>>25800000
            TOS := TOS+pdtorbdisp;                             <<07308>>25805000
            checkregionbase := TOS;                            <<07308>>25810000
            CheckCheckRegion;                                  <<07308>>25815000
            END;                                               <<07308>>25820000
         IF NOT gotahit THEN                                   <<07308>>25825000
            LOOP'THRU'LIST;                                    <<07308>>25830000
                                                                        25835000
         END;                                                  <<07308>>25840000
      END;                                                     <<07308>>25845000
   END;                                                        <<07308>>25850000
                                                               <<07308>>25855000
                                                                        25860000
IF flush THEN                                                           25865000
   BEGIN                                                       <<06858>>25870000
   IF zapfailed THEN                                           <<06858>>25875000
      << There were mapped domains in the way >>               <<06858>>25880000
      CDT'MAP'CACHED'DOMAIN := FALSE                           <<06858>>25885000
   ELSE                                                        <<06858>>25890000
      CDT'MAP'CACHED'DOMAIN := TRUE; << Full range zapped >>   <<06858>>25895000
   END                                                         <<06858>>25900000
ELSE                                                                    25905000
  IF gotahit THEN                                                       25910000
     CDT'Map'Cached'Domain := TRUE                                      25915000
  ELSE                                                                  25920000
     BEGIN  << We must FLUSH any overlapping domains >>                 25925000
     << Process MISS on cache >>                               <<07308>>25930000
     PROCESS'MISS;                                             <<07308>>25935000
     CDT'Map'Cached'Domain := FALSE;  << MISS >>                        25940000
     END;                                                               25945000
                                                                        25950000
$if x1=on                                                               25955000
MMSTAT'(MMSTAT'MAP'DOMAIN,new'cdt,RETURNED'CDT,0,0,0,0);       <<06859>>25960000
$if                                                                     25965000
                                                                        25970000
<< Put DB back to caller's DB >>                               <<*7724>>25975000
tos := SAVE'DB;                                                <<*7724>>25980000
EXCHDB;                                                        <<*7724>>25985000
                                                               <<*7724>>25990000
END;  <<Map'Cached'Domain>>                                             25995000
$page "Cache Management Utilities : CDT'Unmap'Region"                   26000000
                                                                        26005000
                                                                        26010000
PROCEDURE CDT'Unmap'Region(devcdtentry,regcdtentry);                    26015000
VALUE devcdtentry,regcdtentry;                                          26020000
INTEGER devcdtentry,regcdtentry;                                        26025000
OPTION PRIVILEGED,UNCALLABLE,INTERNAL;                         <<06858>>26030000
                                                                        26035000
COMMENT                                                                 26040000
                                                                        26045000
invoked when the cdt entry for a mapped disc domain is released.  The   26050000
region is still to be cached, but not mapped, so any semblence to a     26055000
mapped disc domain must be eliminated.                                  26060000
                                                                        26065000
caller is assumed to be pdisabled.                                      26070000
                                                                        26075000
                                                                        26080000
;                                                                       26085000
                                                                        26090000
BEGIN                                                                   26095000
                                                                        26100000
DOUBLE REG'ADDR,    << Hold memory region address >>           <<d7726>>26105000
       MAPD'ABS'OFST; << Mapped domain entry abs address >>    <<d7726>>26110000
                                                               <<d7726>>26115000
LOGICAL flags;                                                 <<06855>>26120000
DOUBLE obj;                                                    <<06855>>26125000
LOGICAL ARRAY objident(*)=obj;                                 <<06855>>26130000
                                                                        26135000
                                                               <<d7726>>26140000
                                                               <<d7726>>26145000
                                                               <<d7726>>26150000
                                                               <<d7726>>26155000
                                                                        26160000
SUBROUTINE FixObjident;                                                 26165000
                                                                        26170000
BEGIN <<  mapped domain is present >>                                   26175000
$if x1=on                                                      <<d7726>>26180000
TOS := CDT'SET'DOUBLE(regcdtentry,cdt'md'mem'addr,0d);                  26185000
$if x1=off                                                     <<d7726>>26190000
tos := MAPD'ABS'OFST;                                          <<d7726>>26195000
tos := tos + CDT'MD'MEM'ADDR;                                  <<d7726>>26200000
ASMB(LDEA);                                                    <<d7726>>26205000
REG'ADDR := tos;                                               <<d7726>>26210000
tos := 0D;                                                     <<d7726>>26215000
ASMB(SDEA;DDEL);  << Store 0D back to mapped domain mem addr >><<d7726>>26220000
tos := REG'ADDR;                                               <<d7726>>26225000
$if                                                            <<d7726>>26230000
TOS := TOS+rbtoobjidentdisp;                                            26235000
ASMB(LDEA);                                                    <<06855>>26240000
obj := TOS;                                                    <<06855>>26245000
IF (objident(ObjIDtypeField) <> ObjIDcdType)                   <<06855>>26250000
OR (objident(ObjIDnumField) <> logical(regcdtentry))           <<06855>>26255000
THEN SuddenDeath(SFKernCacheIntBad);                                    26260000
TOS := obj;                                                    <<06855>>26265000
S0:= 0;                                                        <<07307>>26270000
ASMB(SDEA;DDEL);                                               <<07307>>26275000
END;                                                                    26280000
                                                                        26285000
                                                                        26290000
DISABLE;                                                                26295000
                                                                        26300000
$if x1=on                                                      <<d7726>>26305000
flags :=  CDT'GET'WORD(regcdtentry,cdt'md'flags,0);                     26310000
$if x1=off                                                     <<d7726>>26315000
CDT'ABS'ON'TOS;                                                <<d7726>>26320000
tos := tos + (REGCDTENTRY * CDT'ENTRY'SIZE);                   <<d7726>>26325000
tos := MAPD'ABS'OFST := tos;  << Save entry's address >>       <<d7726>>26330000
tos := tos + CDT'MD'FLAGS;                                     <<d7726>>26335000
ASMB(LSEA;DELB,DELB);  << Mapped FLAGS is on tos >>            <<d7726>>26340000
FLAGS := tos;                                                  <<d7726>>26345000
$if                                                            <<d7726>>26350000
                                                                        26355000
<< Create mask word for compare >>                             <<d7726>>26360000
tos := 0;                                                      <<d7726>>26365000
tos.CDT'IMI := 1;                                              <<d7726>>26370000
tos.CDT'FWIP := 1;                                             <<d7726>>26375000
tos.CDT'IMO := 1;                                              <<d7726>>26380000
IF ((tos land FLAGS) <> 0)                                     <<d7726>>26385000
THEN SuddenDeath(SFKernCacheSyncBad);                                   26390000
                                                                        26395000
IF (NOT flags.cdt'absent) OR (flags.cdt'roc) THEN                       26400000
   BEGIN <<mapped domain has a memory region corresponding>>            26405000
   FixObjident;                                                         26410000
$if x1=on                                                      <<d7726>>26415000
   flags.cdt'absent:=1;                                                 26420000
   flags.cdt'roc := 0;                                                  26425000
   CDT'Set'Word(regcdtentry,cdt'md'flags,flags);                        26430000
$if x1=off                                                     <<d7726>>26435000
   tos := MAPD'ABS'OFST;                                       <<d7726>>26440000
   tos := tos + CDT'MD'FLAGS;                                  <<d7726>>26445000
   tos := FLAGS;                                               <<d7726>>26450000
   tos.CDT'ABSENT := 1;                                        <<d7726>>26455000
   tos.CDT'ROC := 0;                                           <<d7726>>26460000
   ASMB(SSEA;DDEL);                                            <<d7726>>26465000
$if                                                            <<d7726>>26470000
   END;                                                                 26475000
                                                               <<07311>>26480000
$if x1=on                                                      <<07311>>26485000
MMSTAT'(MMSTAT'UNMAP'REGION,DEVCDTENTRY,REGCDTENTRY,0,0,0,0);  <<07311>>26490000
$if                                                            <<07311>>26495000
END;  <<PROCEDURE CDT'Unmap'Region>>                                    26500000
                                                                        26505000
$Page "Cache/Mem Mgr Interfaces : Cache Transfer Completor"             26510000
                                                                        26515000
PROCEDURE CacheXferComp(ldr'entry'index,iostatus);                      26520000
VALUE ldr'entry'index,iostatus;                                         26525000
INTEGER ldr'entry'index,iostatus;                                       26530000
OPTION PRIVILEGED, UNCALLABLE, INTERNAL;                       <<06858>>26535000
                                                                        26540000
COMMENT                                                                 26545000
                                                                        26550000
CachexferComp is called when a requested transfer against a mapped      26555000
domain is completed.  For a read, this occurs right after the move      26560000
from the mapped domain to the target segment completes.  For a write,   26565000
the completion occurs either after the move to cache has completed      26570000
(in case nowait for post was specified) or (if wait till post was spec  26575000
ified) the xfer completor is not invoked until the physical I/O backin  26580000
up the disc copy of the mapped domain completes. For reads and nowait-  26585000
for-post writes, the CacheXferComp routine is called by ProcessCDTQueu  26590000
when the cache move is performed.  For writes in which wait till post   26595000
was set, the logical transfer completor is called by the segment write  26600000
completor for the physical write updating the disc.  CacheXferComp      26605000
invokes the cache management completor to allow it to clean up the CDT  26610000
requesting the transfer if the wakeup bit has been set (ie if process   26615000
entry, get the next things going, awaken the process if wakeup set,     26620000
etc..                                                                   26625000
                                                                        26630000
;                                                                       26635000
                                                                        26640000
BEGIN                                                                   26645000
                                                                        26650000
<<record transfer status into logical request element>>                 26655000
                                                                        26660000
<< MPE V/E no longer needs to zero out the strategy field >>   <<*7727>>26665000
<< of the LDR'FUNC word.                                  >>   <<*7727>>26670000
                                                               <<*7727>>26675000
ldr'stat := iostatus;                                                   26680000
                                                                        26685000
<<If bad status, zap the xfer count>>                                   26690000
                                                                        26695000
IF iostatus <> iostatusok                                               26700000
THEN ldr'count := 0;                                                    26705000
                                                                        26710000
<<adjust locality if not db or stk, adj loc on cdt entry in sll         26715000
to offset add in attchio for blocked, waitforio for unbl>>              26720000
                                                                        26725000
IF (NOT ldr'dbrel) LAND ((ldr'blocked=1) LOR (ldr'iowake=1)) THEN       26730000
   BEGIN  <<must offset addtolocality of seg if not dbseg>>    <<07311>>26735000
<< IF LPCB(LDR'PCB*PCBSIZE + DBXDSTINFOWORDNUM).XDSDSTFIELD  >><<07311>>26740000
<<    <> LDR'BUF'DSTN  THEN                                  >><<07311>>26745000
      BEGIN  <<not his db seg so do it>>                                26750000
      TOS := ldr'pcb*pcbsize;                                  <<07311>>26755000
      TOS := DOUBLE(LDR'BUF'DSTN);                             <<07311>>26760000
      TOS:=0;<<reqsize>>                                                26765000
      TOS:=0;                                                           26770000
      TOS.cleardiscsegflag:=1;                                          26775000
      AdjustLocality(*,*,*,*);                                          26780000
      END;                                                              26785000
   END;                                                                 26790000
                                                                        26795000
<<invoke the cache management xfer completor>>                          26800000
                                                                        26805000
CDT'COMPLETOR(ldr'cdt,ldr'entry'index);                                 26810000
                                                                        26815000
END;  <<Procedure CacheXferComp>>                                       26820000
                                                                        26825000
$PAGE "Cache Write Completor"                                           26830000
                                                                        26835000
PROCEDURE CacheWriteComp(CDTEntryNumber,XferStatus);                    26840000
VALUE CDTEntryNumber,XferStatus;                                        26845000
INTEGER CDTENTRYNumber,XferStatus;                                      26850000
OPTION PRIVILEGED,UNCALLABLE;                                           26855000
                                                                        26860000
COMMENT                                                                 26865000
                                                                        26870000
The Cache Write Completor is invoked by the object write completor      26875000
from the ICS in response to the interrupt signalling the completion     26880000
of a physical write to the disc of a mapped disc domain.                26885000
                                                                        26890000
The CDT entry number of the mapped domain and the status of the disc    26895000
request transfer are sent as incoming parameters.                       26900000
                                                                        26905000
The cache write completor stuffs the status of the write update into    26910000
the CDT entry of the mapped domain and invokes the transfer completor   26915000
for the logical disc req which is related to this write update.         26920000
                                                                        26925000
;                                                                       26930000
                                                                        26935000
BEGIN                                                                   26940000
                                                                        26945000
INTEGER ldr'entry'index;                                                26950000
                                                                        26955000
$if x1=off                                                              26960000
DEF'GET'WORD;                                                           26965000
$if                                                                     26970000
ldr'entry'index:=CDT'Get'Word(cdtentrynumber,cdt'md'ldr'head,0);        26975000
IF ldr'entry'index <> 0 THEN                                            26980000
   BEGIN  <<somebody waiting>>                                          26985000
   if LDR'FUNC = WRITEREQ then  << This is a non-NOPOST >>              26990000
     CacheXferComp(ldr'entry'index,xferstatus)                          26995000
   else                                                                 27000000
     CDT'COMPLETOR(cdtentrynumber,0);                                   27005000
   END                                                                  27010000
ELSE CDT'COMPLETOR(cdtentrynumber,0);                                   27015000
                                                                        27020000
END;  <<CacheWriteComp>>                                                27025000
$PAGE "Process CDT Disc Request Queue"                                  27030000
PROCEDURE ProcessCDTLogReqQueue (cdtentrynum, iostatus, xfercnt);       27035000
VALUE cdtentrynum,iostatus,xfercnt;                                     27040000
INTEGER cdtentrynum, iostatus,xfercnt;                                  27045000
OPTION PRIVILEGED,UNCALLABLE;                                           27050000
                                                                        27055000
COMMENT                                                                 27060000
                                                                        27065000
ProcessCDTDiscQueue is invoked by the dispatcher when processing        27070000
a message related to the arrival of a mapped disc domain into           27075000
main memory, and by PrefecthObject,RecoverOC, and FetchObject when      27080000
a cached mapped disc domain is requested and found to be in memory.     27085000
                                                                        27090000
ProcessCDTDiscQueue chases through the queue of pending logical         27095000
disc requests attached to the CDT entry passed as parameter.  For       27100000
each logical disc request in the CDT entry's pending queue :            27105000
                                                                        27110000
   if the segment involved in the transfer request is absent,           27115000
   the process requesting the logical transfer is flagged absent        27120000
   and the disc request element is moved to the hung logical request    27125000
   queue.                                                               27130000
                                                                        27135000
   if the mapped domain is absent, the process requesting the transfer  27140000
   is flagged absent.                                                   27145000
                                                                        27150000
   if both the segment and the mapped domain are present, a             27155000
   move effecting the desired transfer is performed.  The prefetch      27160000
   count of the sll entry of the mapped domain is decremented, and      27165000
   the ongoingio flag of the sllentry of the segment is                 27170000
   cleared.  If the transfer involved a write, the virginflag of the    27175000
   CDT entry is cleared and a physical write update of the cached       27180000
   domain is initiated through attachio.  If the transfer is for a      27185000
   read, the transfer completor is invoked.                             27190000
                                                                        27195000
After a transfer is performed, the reference bit of the cached disc     27200000
domain is set, the prefetch count of the mapped domain is cleared       27205000
in the process' sll, and the ongoing disc io count of the related       27210000
buffer is decrementd in the process' sll if not a stack, db not         27215000
pointing at it, and blocked or the iowake bit set.                      27220000
                                                                        27225000
It is assumed that the caller is pdisabled, and that DB is set at       27230000
sysdb.                                                                  27235000
                                                                        27240000
;                                                                       27245000
                                                                        27250000
BEGIN                                                                   27255000
                                                                        27260000
LOGICAL domainabsent,                                                   27265000
        segabsent,                                                      27270000
        odd'byte,    << True if transfer is odd-byte >>                 27275000
        is'write,    << True if this is a write function >>             27280000
        dbrel;                                                          27285000
                                                                        27290000
INTEGER processid,                                                      27295000
        flagprocflags,                                                  27300000
        urgency,                                                        27305000
        ldr'entry'index,                                                27310000
        nextxferreqindex,                                               27315000
        xfercount,                                                      27320000
        residual,     << residual count >>                     <<06858>>27325000
        segoffset,                                                      27330000
        segsize,                                               <<h8580>>27335000
        mdoffset,                                                       27340000
        mdhoda,                                                         27345000
        mdloda,                                                         27350000
        xferhoda,                                                       27355000
        xferloda,                                                       27360000
        discreqoffset;                                         <<06855>>27365000
                                                                        27370000
DOUBLE mdregionbase,                                                    27375000
       mdobjident,                                             <<06855>>27380000
       segregionbase,                                                   27385000
       seg,                                                    <<06855>>27390000
       mddiscaddr=mdhoda,                                               27395000
       xferdiscaddr=xferhoda,                                           27400000
       segxferstartaddr,                                                27405000
       mdxferstartaddr,                                                 27410000
       startcachetime,                                                  27415000
       segaddress;                                                      27420000
                                                               <<*7724>>27425000
<< The following cell is used for ABS addressing of CDT >>     <<*7724>>27430000
DOUBLE MAPD'CDT'OFST;                                          <<*7724>>27435000
                                                                        27440000
LOGICAL ARRAY segid(*)=seg;                                    <<06855>>27445000
INTEGER discreqbase; <<ditto>>                                 <<07311>>27450000
                                                                        27455000
                                                               <<*7724>>27460000
                                                               <<*7724>>27465000
                                                               <<*7724>>27470000
                                                               <<*7724>>27475000
                                                               <<*7724>>27480000
                                                               <<*7724>>27485000
                                                               <<*7724>>27490000
                                                               <<*7724>>27495000
                                                                        27500000
<< Only process if this entry is currently assigned >>                  27505000
CDT'ABS'ON'TOS;        << Abs addr of CDT is on tos >>         <<*7724>>27510000
tos := tos + (CDTENTRYNUM * CDT'ENTRY'SIZE);                   <<*7724>>27515000
                                                               <<*7724>>27520000
<< Store absolute entry address >>                             <<*7724>>27525000
tos :=  MAPD'CDT'OFST := tos;                                  <<*7724>>27530000
                                                               <<*7724>>27535000
<< Load word 0 of entry - will be negative if unassigned >>    <<*7724>>27540000
ASMB(lsea;ddel,del);  << CC is set - remove stacked words >>   <<*7724>>27545000
                                                               <<*7724>>27550000
if >= THEN    << It is an allocated entry >>                   <<*7724>>27555000
BEGIN                                                                   27560000
                                                                        27565000
IF CLASS0STATSENABLED AND CURPRC = 0                           <<07311>>27570000
THEN STARTCACHETIME:=TIMER; <<FOR MEAS SUPPORT>>                        27575000
                                                                        27580000
mdobjident := BuildObjID(mappeddomainobject,cdtentrynum,0);             27585000
                                                                        27590000
<< Load first active LDR index to process >>                   <<*7724>>27595000
tos := MAPD'CDT'OFST;   << Entry abs address >>                <<*7724>>27600000
tos := tos + CDT'MD'LDR'HEAD;                                  <<*7724>>27605000
ASMB(lsea;delb,delb);   << Load LDR inx, remove abs addr >>    <<*7724>>27610000
NEXTXFERREQINDEX := tos;                                       <<*7724>>27615000
                                                                        27620000
WHILE nextxferreqindex <> 0 DO                                          27625000
   BEGIN  <<try to perform this move>>                                  27630000
   DISABLE;                                                             27635000
   ldr'entry'index := nextxferreqindex;                                 27640000
   nextxferreqindex := LDR'NEXTQ;                                       27645000
                                                               <<07311>>27650000
   IF NOT LDR'MOVE'DONE THEN                                            27655000
   BEGIN  << Cache move has NOT been performed yet >>                   27660000
                                                                        27665000
   IF LDR'DBREL THEN DBREL := TRUE  ELSE DBREL := FALSE;       <<07311>>27670000
   SEG := DOUBLE(LDR'BUF'DSTN);                                <<07311>>27675000
                                                                        27680000
   IF INTEGER(LDR'CDT) <> cdtentrynum                          <<07311>>27685000
   THEN SuddenDeath(SFKernCacheIntBad);                                 27690000
                                                                        27695000
   processid:=LDR'PCB;                                                  27700000
                                                                        27705000
   <<handle case of absent mapped domain>>                              27710000
                                                                        27715000
   IF IsObjectAbsent(mdobjident) THEN                                   27720000
      BEGIN  <<mapped domain is out, so flag process absent>>           27725000
      domainabsent:=TRUE;                                               27730000
      flagprocflags:=0;                                                 27735000
      flagprocflags.causefullswap:=1;                                   27740000
      FlagProcAbsent (processid,mdobjident,flagprocflags);     <<*8735>>27745000
$if x1=on                                                               27750000
      TOS := 139;                                              <<07311>>27755000
      TOS := 0;                                                <<07311>>27760000
      TOS := PROCESSID;                                        <<07311>>27765000
      TOS := MDOBJIDENT;                                       <<07311>>27770000
      MMSTAT'(*,*,*,*,*,0,0);                                  <<07311>>27775000
$if                                                                     27780000
      END                                                               27785000
   ELSE domainabsent := FALSE;                                          27790000
                                                                        27795000
   << handle case of absent data segment>>                              27800000
                                                                        27805000
   IF IsObjectAbsent(seg) THEN                                 <<06855>>27810000
      BEGIN                                                             27815000
      segabsent := TRUE;                                                27820000
      << Make sure desired XDS is already in locality >>       <<*7551>>27825000
      tos := 0;                                                <<*7551>>27830000
      tos.SETMEMREQPTRFLAG := 1;  << Fetch, but still launch>> <<*7551>>27835000
      FLAGPROCFLAGS := tos;                                    <<*7551>>27840000
      ADDTOLOCALITY(PCB((PROCESSID*PCBSIZE)+SLLIXWORDNUM),     <<*7551>>27845000
                    SEG,FLAGPROCFLAGS);                        <<*7551>>27850000
                                                               <<*7551>>27855000
      flagprocflags:=0;                                                 27860000
      flagprocflags.causefullswap:=1;                                   27865000
      FlagProcAbsent (processid,0D,flagprocflags);             <<06855>>27870000
$if x1=on                                                               27875000
      MMSTAT'(139,ldr'entry'index,processid,segid(0),segid(1), <<06859>>27880000
                                                       0,0);   <<06859>>27885000
$if                                                                     27890000
      discreqbase := ldr'entry'index;                          <<07311>>27895000
      DequeueDiscReq(discreqbase,cdtreqq,cdtentrynum);         <<07311>>27900000
      QueueDiscReq(discreqbase,deferredreqq,0);                <<07311>>27905000
      END                                                               27910000
   ELSE segabsent := FALSE;                                             27915000
                                                                        27920000
   <<handle case of seg and mapped domain present>>                     27925000
                                                                        27930000
   IF (NOT segabsent) AND (NOT domainabsent) THEN                       27935000
      BEGIN                                                             27940000
                                                                        27945000
      ENABLE;                                                           27950000
                                                                        27955000
      << lookup mdregionbase, seg region base>>                         27960000
                                                                        27965000
      tos := MAPD'CDT'OFST;  << Mapped domain abs address >>   <<*7724>>27970000
      tos := tos + CDT'MD'MEM'ADDR; << Cell offset added  >>   <<*7724>>27975000
      ASMB(LDEA;DXCH,DDEL);  << Only retrieved value on tos >> <<*7724>>27980000
      mdregionbase := tos;                                     <<*7724>>27985000
                                                               <<*7724>>27990000
      TOS:=0;                                                           27995000
      TOS := ABS(dstp)+segid(ObjIDnumField)&lsl(2)+2;          <<06855>>28000000
      ASMB(LDEA); <<base and bank from dst entry>>                      28005000
      segregionbase := TOS;                                             28010000
                                                                        28015000
      <<figure out transfer count>>                                     28020000
                                                                        28025000
      xfercount := ldr'count;                                           28030000
      IF < THEN                                                         28035000
         BEGIN  << Make count positive words >>                         28040000
         IF LOGICAL(xfercount) THEN  << Round count down 1 byte >>      28045000
            odd'byte := TRUE                                            28050000
         ELSE                                                           28055000
            odd'byte := FALSE;                                          28060000
         xfercount := (-xfercount) & ASR(1); << Make words >>           28065000
         END                                                            28070000
      ELSE                                                              28075000
         odd'byte := FALSE;                                             28080000
                                                                        28085000
      <<figure out offsets for transfer from base of seg, md>>          28090000
                                                                        28095000
      segoffset := ldr'bufadr;                                          28100000
      IF dbrel THEN                                                     28105000
         BEGIN <<must add db offset of stack to offset>>                28110000
         TOS := segregionbase;                                          28115000
         TOS := TOS+sbtostkreldbdisp;                                   28120000
         ASMB(LSEA);                                                    28125000
         segoffset := segoffset+TOS;                                    28130000
         DDEL;                                                 <<h8580>>28135000
         END;                                                           28140000
      TOS:=0;                                                           28145000
      TOS:=segoffset;                                                   28150000
      segxferstartaddr := TOS + segregionbase;                          28155000
                                                                        28160000
      << Make sure everything O.K. for the target segment.    ><<h8580>>28165000
      << Don't want to go beyond the region limit for the seg.><<h8580>>28170000
                                                               <<h8580>>28175000
      segsize := dst(LDR'BUF'DSTN&lsl(2)).datasizefield * 4;   <<h8580>>28180000
                                                               <<h8580>>28185000
      if (segxferstartaddr-segregionbase) + double(xfercount)  <<h8580>>28190000
         > double(segsize) then                                <<h8580>>28195000
         suddendeath(SFKernCacheIntBad);                       <<h8580>>28200000
                                                               <<h8580>>28205000
                                                                        28210000
      TOS:=mdregionbase;                                                28215000
      TOS:=TOS+rbtohodadisp;                                            28220000
      ASMB(LDEA);                                                       28225000
      mdloda:=TOS;                                                      28230000
      mdhoda:=TOS.reghodafield;                                         28235000
      xferhoda := ldr'parm1;                                            28240000
      xferloda := ldr(cdt'x:=cdt'x+1);                                  28245000
      TOS:=xferdiscaddr-mddiscaddr;                                     28250000
      mdoffset := TOS*sectorsizeinwords;                                28255000
      IF < THEN SuddenDeath(SFKernCacheIntBad);                         28260000
                                                                        28265000
      << Check transfer count >>                                        28270000
      TOS := mdregionbase;                                              28275000
      TOS := TOS + RBtoRSdisp;                                          28280000
      ASMB(LSEA;DELB,DELB);  << Region size on TOS >>                   28285000
      if (logical(tos * mmpagesize) <=                         <<*7551>>28290000
         logical(mdoffset + xfercount)) then                   <<*7551>>28295000
        Suddendeath(SFKernCacheIntBad);                                 28300000
                                                                        28305000
      TOS:=0;                                                           28310000
      TOS:=mdoffset;                                                    28315000
      mdxferstartaddr:=TOS + mdregionbase;                              28320000
                                                                        28325000
      IF ldr'func = readreq THEN                                        28330000
         BEGIN                                                          28335000
         is'write := false;                                             28340000
         TOS := segxferstartaddr;                                       28345000
         TOS := mdxferstartaddr;                                        28350000
         END                                                            28355000
      ELSE                                                              28360000
         BEGIN                                                          28365000
         is'write := true;                                              28370000
         TOS := mdxferstartaddr;                                        28375000
         TOS := segxferstartaddr;                                       28380000
         END;                                                           28385000
                                                                        28390000
      << At this point, absolute TARGET and SOURCE addresses >><<06858>>28395000
      << for MABS instruction are stacked.                   >><<06858>>28400000
      <<perform the move effecting the transfer>>                       28405000
                                                                        28410000
      IF iostatus = iostatusok THEN                                     28415000
         BEGIN  << Perform move of data >>                              28420000
         TOS:=xfercount;                                                28425000
         ASMB(MABS 1);                                                  28430000
         IF odd'byte THEN                                               28435000
            BEGIN  << Take care of residual data byte >>                28440000
            ASMB(LSEA;DELB,DELB); << Load next word of source >>        28445000
            CDT'X    := TOS;      << Save it >>                <<06858>>28450000
            ASMB(LSEA);           << Load next target word    >>        28455000
            TOS.(0:8) := CDT'X.(0:8); << Overlay byte      >>  <<06858>>28460000
            ASMB(SSEA);      << Store modified byte      >>    <<06858>>28465000
            END                                                         28470000
         ELSE                                                           28475000
            ASMB(DDEL);   << Remove stacked source addr  >>    <<06858>>28480000
         << At this point, move TARGET abs addr is on TOS >>   <<06858>>28485000
         if IS'WRITE then                                      <<06858>>28490000
         if (residual:=INTEGER((128-(LOGICAL(XFERCOUNT)        <<06858>>28495000
            land %177) ) land %177)) <> 0 or ODD'BYTE then     <<06858>>28500000
            begin if ODD'BYTE then                             <<06858>>28505000
               begin                                           <<06858>>28510000
               ASMB(LSEA); << Load word w/hobyte modified >>   <<06858>>28515000
               tos := tos & lsr(8); << Shift off unneeded byte><<06858>>28520000
               ASMB(DUP);  << Duplicate word >>                <<06858>>28525000
               tos := tos & lsl(8); << Put byte in upper half ><<06858>>28530000
               tos := tos lor tos;  << Make new word >>        <<06858>>28535000
               ASMB(SSEA);  << Store back in main memory >>    <<06858>>28540000
               << If residual is zero, 1 byte was moved >>     <<06858>>28545000
               if residual = 0 then                            <<06858>>28550000
                  residual := 128;   << Actually, 1 sector >>  <<06858>>28555000
               end                                             <<06858>>28560000
            else                                               <<06858>>28565000
               begin  << Copy last BYTE, like the CS80 controll<<06858>>28570000
               ASMB(DECA;LSEA);  << Load last valid word >>    <<06858>>28575000
               tos := tos & lsl(8); << Shift-off crap >>       <<06858>>28580000
               ASMB(DUP); << DUP word >>                       <<06858>>28585000
               tos := tos & lsr(8); << Put byte in low order >><<06858>>28590000
               tos := tos lor tos;  << Byte appears in both >> <<06858>>28595000
               ASMB(INCB);  << Increment destination address >><<06858>>28600000
               ASMB(SSEA);  << Store next word back >>         <<06858>>28605000
               end;                                            <<06858>>28610000
            << Perform overlapping move >>                     <<06858>>28615000
            ASMB(INCA,DDUP;DECA);<< Copy target to source, sub <<06858>>28620000
            tos := residual-1;                                 <<06858>>28625000
            ASMB(MABS 5);                                      <<06858>>28630000
            end                                                <<06858>>28635000
         else                                                  <<06858>>28640000
            ASMB(DDEL);  << Remove stacked target address >>   <<06858>>28645000
         end                                                   <<06858>>28650000
      ELSE                                                              28655000
         ASMB(DDEL,DDEL);  << Remove stacked parameters >>              28660000
                                                                        28665000
      <<set ref bit in region header of cached domain>>                 28670000
                                                                        28675000
      TOS := mdregionbase;                                              28680000
      TOS := TOS+rbtosasdisp;                                           28685000
      ASMB(LSEA);                                                       28690000
      IF NOT LS0.regcachedflag THEN SuddenDeath(SFKernCacheIntBad);     28695000
      TOS.regrefflag := 1;                                              28700000
      ASMB(SSEA;DDEL);                                                  28705000
                                                                        28710000
      <<update measurement instrumentation if statistics enabled>>      28715000
                                                                        28720000
      if CLASS0STATSENABLED then                                        28725000
         if FUPDATESTATISTICS(MEASCLASS0,MEASSUBCLASS0,MEASENTRY1,      28730000
                             C'CACHEDATAMOVES,NOTNEWVALUE,1D,NOTDOUBLE) 28735000
         <> 0 then SUDDENDEATH(SFKERNCACHEINTBAD);                      28740000
                                                                        28745000
      <<adjust locality to offset prefetch on mapped domain>>           28750000
                                                                        28755000
      TOS := processid*pcbsize;                                <<06858>>28760000
      TOS:=mdobjident;                                                  28765000
      TOS:=0;<<reqsize>>                                                28770000
      TOS:=0;                                                           28775000
      TOS.decprefetchcntflag := 1;                                      28780000
      AdjustLocality(*,*,*,*);                                          28785000
                                                                        28790000
      << Record fact that move has taken place >>                       28795000
      tos := LDR'FLAGS;                                        <<*7724>>28800000
      tos.(LDR'MOVE'DONE'BIT:1) := 1;                          <<*7724>>28805000
      tos.(LDR'INLOC'BIT:1):=0;<<MD no longer in locality list><<*7724>>28810000
      if = then            << Someone already removed it      ><<*7724>>28815000
        SUDDENDEATH(SFKERNCACHEINTBAD);                        <<*7724>>28820000
      LDR(CDT'X) := tos;   << Save back flags >>               <<*7724>>28825000
                                                                        28830000
      MMSTAT'(mmstatcachemove,segid(0),segid(1),cdtentrynum,   <<06859>>28835000
                                   xfercount,0,0);             <<06859>>28840000
                                                                        28845000
      DISABLE;                                                          28850000
                                                                        28855000
      <<nextxferreqindex := LDR'NEXTQ;>><<may have changed>>   <<06858>>28860000
                                                                        28865000
      <<start disc update for write requests>>                          28870000
                                                                        28875000
      IF is'write THEN                                                  28880000
         BEGIN                                                          28885000
                                                                        28890000
         << Clear mapped CDT VIRGIN bit, if set >>                      28895000
         tos := MAPD'CDT'OFST;  << Abs mapped entry address >> <<*7724>>28900000
         tos := tos + CDT'MD'FLAGS; << Add flags word offset>> <<*7724>>28905000
         ASMB(LSEA);            << Load flags word          >> <<*7724>>28910000
         tos.(CDT'VIRGIN'BIT:1) := 0;                          <<*7724>>28915000
         ASMB(SSEA;DDEL);<<Store back flags, remove abs addr>> <<*7724>>28920000
                                                                        28925000
         << Load physical disc request for KERNEL to use >>    <<*7724>>28930000
         tos := MAPD'CDT'OFST;  << Abs addr of mapped entry >> <<*7724>>28935000
         tos := tos + CDT'MD'DISCREQ; << Phys DRQ offset    >> <<*7724>>28940000
         ASMB(LSEA;DELB,DELB);  << Load DRQ, remove abs addr>> <<*7724>>28945000
         discreqoffset := tos;                                 <<*7724>>28950000
         urgency := if LDR'DO'POST or LDR'SERIAL'POST then     <<07310>>28955000
                       ProcessPri(processid)                   <<07310>>28960000
                    else                                       <<07310>>28965000
                       bkgrndpri;                              <<07310>>28970000
         StartObjWrite(mdobjident,urgency,mdregionbase,                 28975000
                       ldr'entry'index,discreqoffset);                  28980000
         END;                                                           28985000
                                                                        28990000
      <<finish off request for read, no-wait-for-post write requests>>  28995000
                                                                        29000000
      IF (not is'write) OR (not ldr'do'post) THEN              <<06858>>29005000
         BEGIN <<complete it now>>                                      29010000
         CacheXferComp(ldr'entry'index,iostatus);                       29015000
         END;                                                           29020000
                                                                        29025000
      END;                                                              29030000
                                                                        29035000
   END;  << of IF testing if move has been performed >>                 29040000
                                                                        29045000
   END;  <<While Loop>>                                                 29050000
                                                                        29055000
IF CLASS0STATSENABLED AND CURPRC = 0 THEN                      <<07311>>29060000
   IF FUPDATESTATISTICS(MEASCLASS0,MEASSUBCLASS0,MEASENTRY1,            29065000
                       C'CACHEONICS,NOTNEWVALUE,                        29070000
                       TIMER-STARTCACHETIME,DOUBLEVALUE)                29075000
   <> 0 THEN SUDDENDEATH(SFKERNCACHEINTBAD);                            29080000
                                                                        29085000
                                                                        29090000
END;  << of processing VALID cdt entry >>                               29095000
                                                                        29100000
END;  <<Procedure  ProcessCDTReqQ>>                                     29105000
                                                               <<06858>>29110000
                                                               <<06858>>29115000
                                                               <<06858>>29120000
                                                               <<06858>>29125000
                                                               <<06858>>29130000
$PAGE "DISC CACHE ENABLE / DISABLE CONTROL : CACHE'LDEV  "     <<06858>>29135000
procedure CACHE'LDEV(LDEV,STAT);                               <<06858>>29140000
value LDEV;                                                    <<06858>>29145000
integer LDEV,STAT  ;                                           <<06858>>29150000
option privileged,uncallable;                                  <<06858>>29155000
begin                                                          <<06858>>29160000
                                                               <<06858>>29165000
<< CACHE'LDEV is the executor for the STARTCACHE command.      <<06858>>29170000
                                                               <<06858>>29175000
<< This procedure accepts LDEV as input, and manipulates variou<<06858>>29180000
<< I/O and CACHE tables to enable global caching on that disc. <<06858>>29185000
<< If this is the first time a disc has been enabled, it will  <<06858>>29190000
<< obtain a CACHE DST, initialize it, and set up the environmen<<06858>>29195000
<< to allow any disc to have caching enabled.                  <<06858>>29200000
                                                               <<06858>>29205000
<<*************************************************************<<06858>>29210000
<< INPUT - LDEV.  This logical device number is assumed to be a<<06858>>29215000
<<         valid disc logical device configured into the system<<06858>>29220000
<<                                                             <<06858>>29225000
<< OUTPUT- STAT  . This integer is returned to the caller to   <<06858>>29230000
<<         indicate the status of the call.  The values returne<<06858>>29235000
<<         are:                                                <<06858>>29240000
<<         0 - call completed successfully.                    <<06858>>29245000
<<         1 - the cache DST could not be obtained.            <<06858>>29250000
<<         2 - an internal CACHE software error occurred.      <<06858>>29255000
<<         3 - the LDEV specified is already cached.           <<06858>>29260000
<<         4 - the CDT would be too large due to too many disc <<06858>>29265000
<<         5 - the device specified is not cachable            <<06858>>29270000
<<         6 - this system is not permitted to use disc caching<<06858>>29275000
<<*************************************************************<<06858>>29280000
                                                               <<06858>>29285000
<<******************* Caller environment **********************<<06858>>29290000
<< The caller of this procedure should have DB pointing to the <<06858>>29295000
<< stack and be able to be "BLOCKED", as an absence trap might <<06858>>29300000
<< occur during the CACHE DST initialization.                  <<06858>>29305000
<<                                                             <<06858>>29310000
<< This routine may PDISABLE/PENABLE at various times to handle<<06858>>29315000
<< syncronization problems.  It also needs to be privileged to <<06858>>29320000
<< access various system tables.                               <<06858>>29325000
<<*************************************************************<<06858>>29330000
                                                               <<06858>>29335000
<<**************** MPE Tables Accessed ************************<<06858>>29340000
<< CACHE'DST    - This SYSGLOB cell is read and modified.      <<06858>>29345000
<< LPDT         - This table is read only to obtain disc DIT in<<06858>>29350000
<<                and determine the highest LDEV configured.   <<06858>>29355000
<< DIT          - DIT word 0 (Flags) is accessed to set/reset b<<06858>>29360000
<<                which is the DIT'CACHE'ENABLED bit for this d<<06858>>29365000
<<*************************************************************<<06858>>29370000
$page                                                          <<06858>>29375000
integer HIGHEST'LDEV,          << Highest LDEV config'd in MPE><<06858>>29380000
        NUM'OF'DISCS,          << Number of DISCS config'd    ><<06858>>29385000
        CTR,                   << Indexing variable           ><<06858>>29390000
        NUM'OF'DISCREQ,        << Number of DISCREQ entries   ><<06858>>29395000
        NUM'OF'ENTRIES,        << Number of Entries in CDT    ><<06858>>29400000
        XDS'SIZE,              << CACHING DST size            ><<06858>>29405000
        OLD'CRITICAL,          << Return from SETCRITICAL     ><<06858>>29410000
        OLD'SIR,               << Return from GetSir          ><<06858>>29415000
        X = x,                 << Index register              ><<06858>>29420000
        LPDT'INDEX,            << Peg variable for INCLLPDT   ><<06858>>29425000
        DST'NUMBER;            << DST number obtained for CACH><<06858>>29430000
DOUBLE  OBJECT'IDENT;          << MPE standard object ident   ><<06858>>29435000
$page                                                          <<06858>>29440000
subroutine FORMAT'CDT;                                         <<06858>>29445000
begin                                                          <<06858>>29450000
                                                               <<06858>>29455000
<< This procedure formats the CACHE DST.  At this point, the DS<<06858>>29460000
<< is already LOCKED and FROZEN in memory.  We will move DB to <<06858>>29465000
<< the DST to facilitate ease of formatting.                   <<06858>>29470000
                                                               <<06858>>29475000
EXCHANGEDB(DST'NUMBER);                                        <<06858>>29480000
                                                               <<06858>>29485000
<< Zero out DST.  >>                                           <<06858>>29490000
CDT'ARRAY := 0;                                                <<06858>>29495000
move CDT'ARRAY(1) := CDT'ARRAY,(XDS'SIZE-1);                   <<06858>>29500000
                                                               <<06858>>29505000
<< Perform specific initialization >>                          <<06858>>29510000
                                                               <<06858>>29515000
<< Initialize table header >>                                  <<06858>>29520000
CDT'ARRAY(CDT'ENTRIES) := NUM'OF'ENTRIES;                      <<06858>>29525000
CDT'ARRAY(CDT'SIZE) := CDT'ENTRY'SIZE;                         <<06858>>29530000
CDT'ARRAY(CDT'FREE'COUNT) := NUM'OF'ENTRIES - 1;               <<06858>>29535000
<< CDT'FREE'HEAD already 0 >>                                  <<06858>>29540000
<< CDT'FREE'TAIL already 0 >>                                  <<06858>>29545000
CDT'ARRAY(CDT'MAX'USED) := 1;                                  <<06858>>29550000
<< CDT'NUM'LDEVS already 0 >>                                  <<06858>>29555000
<< CDT'DISC'HEAD already 0 >>                                  <<06858>>29560000
CDT'ARRAY(CDT'DST'WORDS) := XDS'SIZE;  << Words CDT is in lengt<<06858>>29565000
<< CDT'STOP'PND already false >>                               <<06858>>29570000
CDT'ARRAY(CDT'SEQ'MINFTCH) := CACHE'SEQUENTIAL;                <<06858>>29575000
CDT'ARRAY(CDT'RND'MINFTCH) := CACHE'RANDOM;                    <<06858>>29580000
<< CDT'FORCE'POST already false >>                             <<06858>>29585000
                                                               <<06858>>29590000
<< Initialize FREE entry list >>                               <<06858>>29595000
CDT'ARRAY(CDT'FREE'HEAD) := CDT'ENTRY'SIZE;                    <<06858>>29600000
CTR := CDT'ENTRY'SIZE;                                         <<06858>>29605000
while CTR < XDS'SIZE do                                        <<06858>>29610000
  begin                                                        <<06858>>29615000
  CDT'ARRAY(CTR) := -1;  << Mark as unassigned >>              <<06858>>29620000
  CDT'ARRAY(CTR+CDT'FREE'HEAD) := CTR + CDT'ENTRY'SIZE;        <<06858>>29625000
  CTR := CTR + CDT'ENTRY'SIZE;                                 <<06858>>29630000
  end;                                                         <<06858>>29635000
<< Back-up to last entry >>                                    <<06858>>29640000
CTR := CTR - CDT'ENTRY'SIZE;                                   <<06858>>29645000
CDT'ARRAY(CTR + CDT'FREE'HEAD) := 0;                           <<06858>>29650000
CDT'ARRAY(CDT'FREE'TAIL) := CTR;  << Fix tail pointer in header<<06858>>29655000
                                                               <<06858>>29660000
<< Put DB back to the caller's stack >>                        <<06858>>29665000
EXCHANGEDB(0);                                                 <<06858>>29670000
                                                               <<06858>>29675000
end; <<of subroutine FORMAT'CDT>>                              <<06858>>29680000
$page                                                          <<06858>>29685000
subroutine INIT'DITS;                                          <<06858>>29690000
begin                                                          <<06858>>29695000
                                                               <<06858>>29700000
<< This subroutine turns off the DIT'CACHE'ENABLED bit in all  <<06858>>29705000
<< DISC DITS "FLAGS" word.                                   >><<06858>>29710000
                                                               <<06858>>29715000
CTR := 0;     << Sweep through all the LDEV's >>               <<06858>>29720000
while (CTR:=CTR+1) <= HIGHEST'LDEV do                          <<06858>>29725000
  begin                                                        <<06858>>29730000
  IF IsDevCachable(CTR) THEN                                   <<06858>>29735000
    begin <<this dev is cachable>>                             <<06858>>29740000
    DISABLE;                                                   <<06858>>29745000
    LPDT'INDEX := CTR * SIZE'OF'LPDT'ENTRY;                    <<*7551>>29750000
    S'DITP(LPDT'DIT'PTR).DIT'CACHE'ENABLED := 0;  << Bit off >><<06858>>29755000
    ENABLE;                                                    <<06858>>29760000
    end;                                                       <<06858>>29765000
  end;                                                         <<06858>>29770000
                                                               <<06858>>29775000
end;  << of subroutine INIT'DITS >>                            <<06858>>29780000
$page                                                          <<06858>>29785000
subroutine BUILD'CDT;                                          <<06858>>29790000
begin                                                          <<06858>>29795000
                                                               <<06858>>29800000
<< This subroutine is called the first time a DISC is requested<<06858>>29805000
<< to have CACHING enabled.  The SYSGLOB cell containing the DS<<06858>>29810000
<< number will be zero until the first disc is requested to hav<<06858>>29815000
<< CACHING enabled against it.                                 <<06858>>29820000
                                                               <<06858>>29825000
<< Determine the number of discs configured on this system.    <<06858>>29830000
HIGHEST'LDEV := LPDT'MAX'ENTRIES;<< Max ldev configured on syst<<06858>>29835000
NUM'OF'DISCS := 0;                                             <<06858>>29840000
CTR := 0;   << LDEV index >>                                   <<06858>>29845000
                                                               <<06858>>29850000
<< Step through the LDEV's >>                                  <<06858>>29855000
while (CTR:=CTR+1) <= HIGHEST'LDEV do                          <<06858>>29860000
  begin                                                        <<06858>>29865000
  IF IsDevCachable(CTR) THEN NUM'OF'DISCS:=NUM'OF'DISCS+1;     <<06858>>29870000
  end;                                                         <<06858>>29875000
                                                               <<06858>>29880000
<< Determine the number of DISC REQUEST elements configured >> <<06858>>29885000
NUM'OF'DISCREQ := INTEGER(DQH'TOT'ENT);                        <<*7551>>29890000
                                                               <<06858>>29895000
<< Calculate the DST size and obtain CACHING DST >>            <<06858>>29900000
NUM'OF'ENTRIES := NUM'OF'DISCS +   << One entry for every disc <<06858>>29905000
                  NUM'OF'DISCREQ + << One for each Disc Request<<06858>>29910000
                  1;               << One entry for table head <<06858>>29915000
                                                               <<06858>>29920000
<< Over-configure table to handle table roundoff & init routine<<06858>>29925000
XDS'SIZE := CDT'ENTRY'SIZE * NUM'OF'ENTRIES;                   <<06858>>29930000
                                                               <<06858>>29935000
<< If overflow, its too big >>                                 <<06858>>29940000
if carry or overflow then                                      <<06858>>29945000
  begin  << System manager must make LDR table smaller >>      <<06858>>29950000
  STAT := stat'cdt'overflow;                                   <<06858>>29955000
  end                                                          <<06858>>29960000
else                                                           <<06858>>29965000
  begin <<can procede - get the xds for the CDT>>              <<06858>>29970000
  DST'NUMBER := GETDATASEG(XDS'SIZE,XDS'SIZE);                 <<06858>>29975000
  if DST'NUMBER <= 0 then                                      <<06858>>29980000
     begin  << Could not obtain DST >>                         <<06858>>29985000
     STAT   := stat'no'dst;                                    <<06858>>29990000
     end                                                       <<06858>>29995000
  else                                                         <<06858>>30000000
     begin <<got the xds for the cdt, now lock,freeze, format>><<06858>>30005000
     << Lock and freeze the DST in main memory >>              <<06858>>30010000
     OBJECT'IDENT := BUILDOBJID(DATAOBJECT,DST'NUMBER,0);      <<06858>>30015000
     LOCKSEG'(OBJECT'IDENT,true);  << Place it in a good locati<<06858>>30020000
     FREEZESEG'(OBJECT'IDENT,0);   << Don't allow it to move.  <<06858>>30025000
                                                               <<06858>>30030000
     << Format the data segment into the CDT >>                <<06858>>30035000
     FORMAT'CDT;                                               <<06858>>30040000
                                                               <<06858>>30045000
     << Build object identifier for the cacheseg>>             <<06858>>30050000
     OBJECT'IDENT := BUILDOBJID(SLOBJECT,                      <<06858>>30055000
                      logical(@CDT'GET'ENTRY) land %377,0);    <<06858>>30060000
                                                               <<06858>>30065000
     << Lock and freeze the cacheseg into main memory >>       <<06858>>30070000
     LOCKSEG'(OBJECT'IDENT,true);                              <<06858>>30075000
     FREEZESEG'(OBJECT'IDENT,0);                               <<06858>>30080000
                                                               <<06858>>30085000
     DISABLE;                                                  <<06858>>30090000
                                                               <<06858>>30095000
     << Turn off the CACHED bit in all disc DITS >>            <<06858>>30100000
     INIT'DITS;                                                <<06858>>30105000
                                                               <<06858>>30110000
     <<stuff away CDT dst num & address into sysglob>>         <<06858>>30115000
     CACHE'DST := DST'NUMBER;                                  <<06858>>30120000
     CACHE'DST'BANK := S'DST((DST'NUMBER*4)+2); << Bank >>     <<06858>>30125000
     CACHE'DST'OFST := S'DST((DST'NUMBER*4)+3); << Offset >>   <<06858>>30130000
                                                               <<06858>>30135000
     ENABLE;                                                   <<06858>>30140000
                                                               <<06858>>30145000
     end;                                                      <<06858>>30150000
  end;                                                         <<06858>>30155000
end;  << of subroutine BUILD'CDT>>                             <<06858>>30160000
$page                                                          <<06858>>30165000
subroutine ENABLE'CACHE;                                       <<06858>>30170000
begin                                                          <<06858>>30175000
                                                               <<06858>>30180000
<< This routine checks whether CACHING is already enabled again<<06858>>30185000
<< the specified LDEV, and if not, proceeds to enable CACHING o<<06858>>30190000
<< it.  The CACHE transition flag is set to block any further r<<06858>>30195000
<< uests until all the physical I/O's have completed on this LD<<06858>>30200000
                                                               <<06858>>30205000
DISABLE;     << Protect possible concurrent access >>          <<06858>>30210000
                                                               <<06858>>30215000
<< See if LDEV is already CACHED >>                            <<06858>>30220000
LPDT'INDEX := LDEV * SIZE'OF'LPDT'ENTRY;                       <<07311>>30225000
X := LPDT'DIT'PTR;       << DIT pointer is placed in INDEX regi<<06858>>30230000
if S'DITP(X).DIT'CACHE'ENABLED = 1 then                        <<06858>>30235000
  begin  << Cache is already enabled on this LDEV >>           <<06858>>30240000
  STAT := stat'ldev'cached;  << Return error code >>           <<06858>>30245000
  end                                                          <<06858>>30250000
else                                                           <<06858>>30255000
   begin <<caching not yet enabled - go ahead>>                <<06858>>30260000
   << Get a table entry for this new LDEV >>                   <<06858>>30265000
   CTR := CDT'GET'ENTRY;                                       <<06858>>30270000
   if CTR = 0 then                                             <<06858>>30275000
     begin  << We could not get an entry >>                    <<06858>>30280000
     STAT := stat'int'error;  << Indicate software error >>    <<06858>>30285000
     end                                                       <<06858>>30290000
   else                                                        <<06858>>30295000
     begin  <<got a cdt entry for this device>>                <<06858>>30300000
     << Increment number of LDEVs cached >>                    <<06858>>30305000
     CDT'ADD'WORD(0 << header >>,CDT'NUM'LDEVS,1);             <<06858>>30310000
                                                               <<06858>>30315000
     << Format this new entry >>                               <<06858>>30320000
     CDT'SET'WORD(CTR,CDT'DE'LDEV,LDEV);                       <<06858>>30325000
                                                               <<06858>>30330000
     << Fix pointers >>                                        <<06858>>30335000
     if CDT'GET'WORD(0,CDT'DISC'HEAD,0) = 0 then               <<06858>>30340000
        begin   << This is the first disc on the list >>       <<06858>>30345000
        CDT'SET'WORD(0,CDT'DISC'HEAD,CTR);                     <<06858>>30350000
        end                                                    <<06858>>30355000
                                                               <<06858>>30360000
     else                                                      <<06858>>30365000
                                                               <<06858>>30370000
        begin  << Someone else is on the list >>               <<06858>>30375000
        << Use DST'NUMBER as index >>                          <<06858>>30380000
        DST'NUMBER := CDT'GET'WORD(0,CDT'DISC'HEAD,0);         <<06858>>30385000
        while CDT'GET'WORD(DST'NUMBER,CDT'DE'NEXT'LDEV,0)      <<06858>>30390000
                                               <> 0            <<06858>>30395000
        do DST'NUMBER :=                                       <<06858>>30400000
           CDT'GET'WORD(DST'NUMBER,CDT'DE'NEXT'LDEV,0);        <<06858>>30405000
        << At this point, we should be at last entry in chain ><<06858>>30410000
        << Put new LDEV in this LDEV's NEXT pointer >>         <<06858>>30415000
        CDT'SET'WORD(DST'NUMBER,CDT'DE'NEXT'LDEV,CTR);         <<06858>>30420000
        << Point new LDEV entry back to prior LDEV entry >>    <<06858>>30425000
        CDT'SET'WORD(CTR,CDT'DE'PREV'LDEV,DST'NUMBER);         <<06858>>30430000
        end;                                                   <<06858>>30435000
                                                               <<06858>>30440000
      << Finally, turn on the DIT'CACHE'ENABLED bit in the DIT <<06858>>30445000
      LPDT'INDEX := LDEV * SIZE'OF'LPDT'ENTRY;                 <<*7551>>30450000
      X := LPDT'DIT'PTR;      << SYSDB DITP in index register ><<06858>>30455000
      S'DITP(X).DIT'CACHE'ENABLED := 1; << Turn on bit >>      <<06858>>30460000
                                                               <<06858>>30465000
      ENABLE;   << Let the system RIP >>                       <<06858>>30470000
                                                               <<06858>>30475000
      end;                                                     <<06858>>30480000
   end;                                                        <<06858>>30485000
end;  << of subroutine ENABLE'CACHE >>                         <<06858>>30490000
$page                                                          <<06858>>30495000
<<turn off arithmetic traps, set critical to prevent midway abo<<06858>>30500000
                                                               <<06858>>30505000
TurnOffTraps;                                                  <<06858>>30510000
old'critical := SetCritical;                                   <<06858>>30515000
                                                               <<06858>>30520000
<<serialize cache control thru sir acquisition>>               <<06858>>30525000
                                                               <<06858>>30530000
old'sir := GetSir(cache'control'sir);                          <<06858>>30535000
                                                               <<06858>>30540000
<<if caching is permitted on this system and on the >>         <<06858>>30545000
<<specified device, enable caching for the device>>            <<06858>>30550000
                                                               <<06858>>30555000
IF NOT IsSysCachable THEN stat := stat'sys'not'cachable ELSE   <<06858>>30560000
   BEGIN  <<system is allowed to have disc caching enabled>>   <<06858>>30565000
   IF NOT IsDevCachable(ldev)  THEN                            <<06858>>30570000
         stat := stat'dev'not'cachable ELSE                    <<06858>>30575000
      BEGIN  <<device is a cachable device>>                   <<06858>>30580000
      stat := stat'ok;  <<initialize to successful completion>><<06858>>30585000
      IF cache'dst = 0 THEN Build'CDT; << first enable-build CD<<06858>>30590000
      IF stat = stat'ok THEN Enable'Cache;                     <<06858>>30595000
      END;                                                     <<06858>>30600000
   END;                                                        <<06858>>30605000
                                                               <<06858>>30610000
<< release sir and reset critical state >>                     <<06858>>30615000
                                                               <<06858>>30620000
RelSir(cache'control'sir,old'sir);                             <<06858>>30625000
ResetCritical(old'critical);                                   <<06858>>30630000
                                                               <<06858>>30635000
END;  << of procedure CACHE'LDEV >>                            <<06858>>30640000
$PAGE "DISC CACHE ENABLE / DISABLE CONTROL : UNCACHE'LDEV  "   <<06858>>30645000
procedure UNCACHE'LDEV(LDEV,STATR);                            <<06858>>30650000
value LDEV;                                                    <<06858>>30655000
integer LDEV,STATR ;                                           <<06858>>30660000
option privileged,uncallable;                                  <<06858>>30665000
begin                                                          <<06858>>30670000
                                                               <<06858>>30675000
<< UNCACHE'LDEV is the executor for the STOPCACHE command.     <<06858>>30680000
                                                               <<06858>>30685000
<< This procedure accepts LDEV as input, and manipulates variou<<06858>>30690000
<< I/O and CACHE tables to disable global caching from that dis<<06858>>30695000
<< If this is the last disc to have caching disabled against it<<06858>>30700000
<< the cache data segment will be unfrozen, unlocked and releas<<06858>>30705000
<< and the cache segment CACHESEG will be unfrozen nad unlocked<<06858>>30710000
                                                               <<06858>>30715000
<<*************************************************************<<06858>>30720000
<< INPUT - LDEV.  This logical device number is assumed to be a<<06858>>30725000
<<         valid disc logical device configured into the system<<06858>>30730000
<<                                                             <<06858>>30735000
<< OUTPUT- STATR . This integer is returned to the caller to   <<06858>>30740000
<<         indicate the status of the call.  The values returne<<06858>>30745000
<<         are:                                                <<06858>>30750000
<<         0 - call completed successfully.                    <<06858>>30755000
<<         1 - caching was not enabled for any devices         <<06858>>30760000
<<         2 - an internal CACHE software error occurred.      <<06858>>30765000
<<         3 - the LDEV specified did not have caching enabled <<06858>>30770000
<<         5 - the device cannot support caching               <<06858>>30775000
<<         6 - this system is not permitted to use disc caching<<06858>>30780000
<<*************************************************************<<06858>>30785000
                                                               <<06858>>30790000
<<******************* Caller environment **********************<<06858>>30795000
<< The caller of this procedure should have DB pointing to the <<06858>>30800000
<< stack and be able to be "BLOCKED", as an absence trap might <<06858>>30805000
<< occur during the CACHE DST initialization.                  <<06858>>30810000
<<                                                             <<06858>>30815000
<< This routine may PDISABLE/PENABLE at various times to handle<<06858>>30820000
<< syncronization problems.  It also needs to be privileged to <<06858>>30825000
<< access various system tables.                               <<06858>>30830000
<<*************************************************************<<06858>>30835000
                                                               <<06858>>30840000
<<**************** MPE Tables Accessed ************************<<06858>>30845000
<< CACHE'DST    - This SYSGLOB cell is read and modified.      <<06858>>30850000
<< LPDT         - This table is read only to obtain disc DIT in<<06858>>30855000
<<                and determine the highest LDEV configured.   <<06858>>30860000
<< DIT          - DIT word 0 (Flags) is accessed to set/reset b<<06858>>30865000
<<                which is the DIT'CACHE'ENABLED bit for this d<<06858>>30870000
<<*************************************************************<<06858>>30875000
                                                               <<06858>>30880000
integer OLD'SIR,       << Return from GETSIR              >>   <<06858>>30885000
        OLD'CRITICAL,  << Return from SETCRITICAL         >>   <<06858>>30890000
        DBSAVE,        << Return from SETSYSDB            >>   <<06858>>30895000
        STAT,          << return status from procedure    >>   <<06858>>30900000
        LDEV'INDEX,    << CDT entry of LDEV to be uncached>>   <<06858>>30905000
        CDT'ENTRY,     << CDT entry of mapped domain      >>   <<06858>>30910000
        LPDT'INDEX,    << Peg for INCLLPDT                >>   <<06858>>30915000
        PRIOR'PTR,     << Prior mapped CDT entry          >>   <<06858>>30920000
        NEXT'PTR,      << Next mapped CDT entry           >>   <<06858>>30925000
        SAVE'DST,      << Temporarily save DST number     >>   <<*8003>>30930000
        IMPEDED'PIN,   << Head impeded pin                >>   <<06858>>30935000
        NEXT'PIN;      << Next pin to be unimpeded        >>   <<06858>>30940000
                                                               <<06858>>30945000
DOUBLE  OBJECT'IDENT;  << Object identifier               >>   <<06858>>30950000
$page                                                          <<06858>>30955000
subroutine DEALLOCATE'RESOURCES;                               <<06858>>30960000
begin                                                          <<06858>>30965000
                                                               <<06858>>30970000
<< This subroutine cleans-up all code and data structures >>   <<06858>>30975000
<< associated with disc caching.                          >>   <<06858>>30980000
                                                               <<06858>>30985000
<< Unlock/unfreeze cache DST >>                                <<06858>>30990000
OBJECT'IDENT := BUILDOBJID(SLOBJECT,logical(@CDT'GET'ENTRY)    <<06858>>30995000
                land %377,0);                                  <<06858>>31000000
UNFREEZESEG'(OBJECT'IDENT);                                    <<06858>>31005000
UNLOCKSEG'(OBJECT'IDENT);                                      <<06858>>31010000
                                                               <<06858>>31015000
OBJECT'IDENT := BUILDOBJID(DATAOBJECT,CACHE'DST,0);            <<06858>>31020000
UNFREEZESEG'(OBJECT'IDENT);                                    <<06858>>31025000
UNLOCKSEG'(OBJECT'IDENT);                                      <<06858>>31030000
                                                               <<06858>>31035000
<< Clean-up SysGlob cells >>                                   <<*8003>>31040000
                                                               <<*8003>>31045000
SAVE'DST := CACHE'DST;                                         <<*8003>>31050000
CACHE'DST := CACHE'DST'BANK := CACHE'DST'OFST := 0;            <<*8003>>31055000
                                                               <<*8003>>31060000
PENABLE;                                                       <<*8003>>31065000
                                                               <<*8003>>31070000
<< Release the cache XDS >>                                    <<06858>>31075000
RELDATASEG(SAVE'DST);                                          <<*8003>>31080000
                                                               <<06858>>31085000
                                                               <<06858>>31090000
end;                                                           <<06858>>31095000
$page                                                          <<06858>>31100000
TURNOFFTRAPS;                                                  <<06858>>31105000
DBSAVE := SETSYSDB;                                            <<06858>>31110000
OLD'CRITICAL := SETCRITICAL;                                   <<06858>>31115000
OLD'SIR := GETSIR(CACHE'CONTROL'SIR);                          <<06858>>31120000
                                                               <<06858>>31125000
<< Perform error checking >>                                   <<06858>>31130000
if not ISSYSCACHABLE then                                      <<06858>>31135000
   STAT := stat'sys'not'cachable  << Caching not permitted >>  <<*7553>>31140000
else if CACHE'DST = 0 then                                     <<06858>>31145000
   STAT := stat'no'dst    << Caching not enabled >>            <<*7553>>31150000
else if not ISDEVCACHABLE(LDEV) then                           <<06858>>31155000
   STAT := stat'dev'not'cachable   << Not a cachable device >> <<*7553>>31160000
else if (LDEV'INDEX:=CDT'FIND'DE(LDEV)) = 0 then               <<06858>>31165000
   STAT := stat'ldev'cached      << Device is NOT cached >>    <<*7553>>31170000
else                                                           <<06858>>31175000
   begin  << Turn it off... >>                                 <<06858>>31180000
   STAT := STAT'OK;                                            <<06858>>31185000
                                                               <<06858>>31190000
   << Lock the entire CDT >>                                   <<06858>>31195000
   CDT'SET'WORD(0,CDT'STOP'PND,-1);                            <<06858>>31200000
                                                               <<06858>>31205000
   << Flush all domains for this device >>                     <<06858>>31210000
   while (CDT'ENTRY:=CDT'GET'WORD(LDEV'INDEX,CDT'DE'MAPD'HEAD, <<06858>>31215000
          0)) <> 0 or                                          <<06858>>31220000
         (CDT'GET'WORD(LDEV'INDEX,CDT'DE'REGIONS,0) <> 0) do   <<06858>>31225000
      FLUSH'CACHE(LDEV,0D,%17777777777 D);                     <<06858>>31230000
                                                               <<06858>>31235000
   << Turn off CACHED flag in the DIT >>                       <<06858>>31240000
   PDISABLE;                                                   <<06858>>31245000
   DISABLE;                                                    <<06858>>31250000
   LPDT'INDEX := LDEV * SIZE'OF'LPDT'ENTRY;                    <<07311>>31255000
   S'DITP(LPDT'DIT'PTR).DIT'CACHE'ENABLED := 0;                <<06858>>31260000
   ENABLE;                                                     <<06858>>31265000
                                                               <<06858>>31270000
   << Delink the entry >>                                      <<06858>>31275000
   PRIOR'PTR := CDT'SET'WORD(LDEV'INDEX,CDT'DE'PREV'LDEV,0);   <<06858>>31280000
   NEXT'PTR  := CDT'SET'WORD(LDEV'INDEX,CDT'DE'NEXT'LDEV,0);   <<06858>>31285000
   if PRIOR'PTR <> 0 then                                      <<06858>>31290000
      CDT'SET'WORD(PRIOR'PTR,CDT'DE'NEXT'LDEV,NEXT'PTR)        <<06858>>31295000
   else                                                        <<06858>>31300000
      CDT'SET'WORD(0,CDT'DISC'HEAD,NEXT'PTR);                  <<06858>>31305000
                                                               <<06858>>31310000
   if NEXT'PTR <> 0 then                                       <<06858>>31315000
      CDT'SET'WORD(NEXT'PTR,CDT'DE'PREV'LDEV,PRIOR'PTR);       <<06858>>31320000
                                                               <<06858>>31325000
   << Release the entry >>                                     <<06858>>31330000
   CDT'FREE'ENTRY(LDEV'INDEX);                                 <<06858>>31335000
                                                               <<06858>>31340000
   << Decrement count of cached devices >>                     <<06858>>31345000
   CDT'ADD'WORD(0,CDT'NUM'LDEVS,-1);                           <<06858>>31350000
                                                               <<06858>>31355000
   << Unlock/unimpede waiting processes >>                     <<06858>>31360000
   CDT'SET'WORD(0,CDT'STOP'PND,0);                             <<06858>>31365000
   IMPEDED'PIN := CDT'SET'WORD(0,CDT'STOP'QUEUE,0);            <<06858>>31370000
   while IMPEDED'PIN <> 0 do                                   <<06858>>31375000
      begin                                                    <<06858>>31380000
      NEXT'PIN := UNSTRINGHEADPIN(IMPEDED'PIN);                <<06858>>31385000
      UNIMPEDE(IMPEDED'PIN * PCBSIZE);                         <<06858>>31390000
      IMPEDED'PIN := NEXT'PIN;                                 <<06858>>31395000
      end;                                                     <<06858>>31400000
                                                               <<06858>>31405000
   << If there are no more devices, deallocate resources >>    <<06858>>31410000
   if CDT'GET'WORD(0 <<header>>, CDT'DISC'HEAD,0) = 0 then     <<*8003>>31415000
      begin                                                    <<*8003>>31420000
      DEALLOCATE'RESOURCES;  << Returns Penabled >>            <<*8003>>31425000
      end                                                      <<*8003>>31430000
   else                                                        <<*8003>>31435000
      PENABLE;                                                 <<*8003>>31440000
                                                               <<*8003>>31445000
   end;                                                        <<06858>>31450000
                                                               <<06858>>31455000
<< Clean-up >>                                                 <<06858>>31460000
RELSIR(CACHE'CONTROL'SIR,OLD'SIR);                             <<06858>>31465000
RESETCRITICAL(OLD'CRITICAL);                                   <<06858>>31470000
RESETDB(DBSAVE);                                               <<06858>>31475000
STATR := STAT;                                                 <<06858>>31480000
end;   << of procedure UNCACHE'LDEV >>                         <<06858>>31485000
$page "CDT'DISPLAY'LDEVS"                                      <<06858>>31490000
$page "CDT'DISPLAY'LDEVS"                                      <<07308>>31495000
procedure CDT'DISPLAY'LDEVS(RESET'TTLS,RSTAT);                 <<07308>>31500000
value RESET'TTLS;                                              <<07308>>31505000
logical RESET'TTLS;                                            <<07308>>31510000
integer RSTAT;                                                 <<07308>>31515000
option privileged,uncallable;                                  <<07308>>31520000
begin                                                          <<07308>>31525000
                                                               <<07308>>31530000
<<CDT'DISPLAY'LDEVS IS THE EXECUTOR FOR THE SHOWCACHE CMD.  >> <<07308>>31535000
<< This procedure displays basic caching statistics for all >> <<07308>>31540000
<< cached discs on the system.  The returned value(s) are:  >> <<07308>>31545000
<<                                                          >> <<07308>>31550000
<< RSTAT    - Returned status, where:                       >> <<07308>>31555000
<<            0 - Successful                                >> <<07308>>31560000
<<            1 - Caching is not enabled on this system.    >> <<07308>>31565000
<<            2 - Could not obtain XDS to capture data.     >> <<*7553>>31570000
<<            6 - Caching not permitted.                    >> <<*7553>>31575000
<<                                                          >> <<07308>>31580000
<< Passed parameter is:                                     >> <<07308>>31585000
<< RESET'TTLS - Set to TRUE if caller wishes to reset       >> <<07308>>31590000
<<              cache HIT and REQUEST counters.             >> <<07308>>31595000
<< **** RESET IS NOT CURRENTLY SUPPORTED ****               >> <<*7553>>31600000
<< DB is assumed to be at the caller's stack.               >> <<07308>>31605000
<<**********************************************************>> <<07308>>31610000
                                                               <<07308>>31615000
array BUF(0:39);                                               <<07308>>31620000
byte array B'BUF(*) = BUF;                                     <<07308>>31625000
                                                               <<07308>>31630000
<< CDT entry save arrays >>                                    <<*7553>>31635000
integer array LD(0:CDT'ENTRY'SIZE-1),                          <<*7553>>31640000
              HD(0:CDT'ENTRY'SIZE-1);  << Table header >>      <<*7553>>31645000
                                                               <<*7553>>31650000
double array LDD(*) = LD;                                      <<*7553>>31655000
                                                               <<*7553>>31660000
integer XDS,           << Entry # of obtained XDS  >>          <<*7553>>31665000
        MAX'INDEX;     << Highest entry used in XDS>>          <<*7553>>31670000
                                                               <<*7553>>31675000
integer LENGTH,    << For printing >>                          <<07308>>31680000
        LDEV,      << Number of LDEV being displayed >>        <<07308>>31685000
        OLD'SIR,   << Return value from GETSIR >>              <<07308>>31690000
        OLD'CRIT,  << Old value from SETCRITICAL>>             <<07308>>31695000
        LDEV'LINK, << Pointer to device entry  >>              <<07308>>31700000
        WORK,      << Temp variable            >>              <<07308>>31705000
        OHEAD,     << Number of words in CDT   >>              <<07308>>31710000
        PCNT'MEM,  << Percent of main memory   >>              <<07308>>31715000
        PCNT'READ, << % of reads to all reqs.  >>              <<07308>>31720000
        RPERCENT,  << Read hit ratio on disc   >>              <<07308>>31725000
        WPERCENT;  << Write hit ratio on disc  >>              <<07308>>31730000
                                                               <<07308>>31735000
double RHIT,      << Number of read cache HITS >>              <<07308>>31740000
       WHIT,      << Number of write cache HITS>>              <<07308>>31745000
       RMISS,    << Number of cache read misses on this LDEV >><<07308>>31750000
       WMISS,    << Number of cache write misses on this LDEV>><<07308>>31755000
       WRITES,     << Number of cache write requests      >>   <<07308>>31760000
       TWRITES,    << Total # of cache write requests     >>   <<07308>>31765000
       TRHIT,     << Total # read hits for all ldev's         ><<07308>>31770000
       TWHIT,     << Total # write hits for all ldev's        ><<07308>>31775000
       TRMISS,   << Total # of read misses for all ldev's    >><<07308>>31780000
       TWMISS,   << Total # of write misses for all ldev's   >><<07308>>31785000
       STOPS,      << Number of process stops on this ldev     <<07308>>31790000
       TSTOPS,     << Total # of process stops on this ldev    <<07308>>31795000
       PAGES,      << Number of pages consumed by this dev>>   <<07308>>31800000
       TPAGES,     << Total # of pages by all devices     >>   <<07308>>31805000
       REGIONS,    << Number of cached domains for disc   >>   <<07308>>31810000
       TREGIONS,   << Total # of cached domains for all   >>   <<07308>>31815000
       TMEMORY,    << Total bytes of main memory          >>   <<07308>>31820000
       REQUESTS;   << Total number of cache requests on this LD<<07308>>31825000
                                                               <<07308>>31830000
logical OVRFLOW;           << An arithmetic overflow occurred ><<07308>>31835000
                                                               <<07308>>31840000
equate NBANKSINX = %1047;  << SYSGLOB cell indicating # banks>><<07308>>31845000
                                                               <<07308>>31850000
if not IsSysCachable then                                      <<*7553>>31855000
   begin                                                       <<*7553>>31860000
   RSTAT := stat'sys'not'cachable;                             <<*7553>>31865000
   RETURN;                                                     <<*7553>>31870000
   end;                                                        <<*7553>>31875000
                                                               <<*7553>>31880000
<< We can't abort here... >>                                   <<07308>>31885000
OLD'CRIT := SETCRITICAL;                                       <<07308>>31890000
                                                               <<07308>>31895000
<< Obtain SIR to protect integrity >>                          <<07308>>31900000
OLD'SIR := GETSIR(CACHE'CONTROL'SIR);                          <<07308>>31905000
                                                               <<07308>>31910000
<< Check if caching is enabled >>                              <<07308>>31915000
if CACHE'DST = 0 then                                          <<07308>>31920000
  begin  << Caching is NOT enabled >>                          <<07308>>31925000
  RSTAT := stat'no'dst;                                        <<*7553>>31930000
  RELSIR(CACHE'CONTROL'SIR,OLD'SIR);                           <<*7553>>31935000
  end                                                          <<07308>>31940000
else                                                           <<07308>>31945000
  begin                                                        <<07308>>31950000
                                                               <<07308>>31955000
  TURNOFFTRAPS;                                                <<07308>>31960000
                                                               <<07308>>31965000
  << Get XDS to copy data to >>                                <<*7553>>31970000
  LENGTH := CDT'ENTRY'SIZE *                                   <<*7553>>31975000
            integer(CDT'GET'WORD(0,CDT'NUM'LDEVS,0));          <<*7553>>31980000
  GETDSEG(XDS,LENGTH,0);                                       <<*7553>>31985000
  if XDS <= 0 then                                             <<*7553>>31990000
    begin                                                      <<*7553>>31995000
    RSTAT := stat'int'error;                                   <<*7553>>32000000
    RELSIR(CACHE'CONTROL'SIR,OLD'SIR);                         <<*7553>>32005000
    end                                                        <<*7553>>32010000
  else                                                         <<*7553>>32015000
                                                               <<*7553>>32020000
  begin                                                        <<*7553>>32025000
  << Couldn't indent here... >>                                <<*7553>>32030000
  << Copy CDT entries to XDS >>                                <<*7553>>32035000
  LDEV'LINK := CDT'GET'WORD(0<<hdr>>,CDT'DISC'HEAD,0);         <<*7553>>32040000
  MAX'INDEX := -1;                                             <<*7553>>32045000
  while (LDEV'LINK <> 0) do                                    <<*7553>>32050000
    begin                                                      <<*7553>>32055000
    MAX'INDEX := MAX'INDEX + 1;                                <<*7553>>32060000
    LENGTH := -1;                                              <<*7553>>32065000
    PDISABLE;                                                  <<*7553>>32070000
    while (LENGTH:=LENGTH+1) < CDT'ENTRY'SIZE do               <<*7553>>32075000
      LD(LENGTH) := CDT'GET'WORD(LDEV'LINK,LENGTH,0);          <<*7553>>32080000
    PENABLE;                                                   <<*7553>>32085000
    << Copy data to XDS >>                                     <<*7553>>32090000
    DMOVOUT(XDS,MAX'INDEX*CDT'ENTRY'SIZE,CDT'ENTRY'SIZE,LD);   <<*7553>>32095000
    LDEV'LINK  := LD(CDT'DE'NEXT'LDEV);                        <<*7553>>32100000
    end;   << While loop >>                                    <<*7553>>32105000
                                                               <<*7553>>32110000
  << Save CDT header >>                                        <<*7553>>32115000
  LENGTH := -1;                                                <<*7553>>32120000
  while (LENGTH:=LENGTH+1) < CDT'ENTRY'SIZE do                 <<*7553>>32125000
    HD(LENGTH) := CDT'GET'WORD(0,LENGTH,0);                    <<*7553>>32130000
                                                               <<*7553>>32135000
  << Release CDT SIR >>                                        <<*7553>>32140000
  RELSIR(CACHE'CONTROL'SIR,OLD'SIR);                           <<*7553>>32145000
                                                               <<*7553>>32150000
  << Loop through all cached discs >>                          <<07308>>32155000
  PRINT(BUF,0,0);   << One line space >>                       <<07308>>32160000
  TRHIT := TWHIT := TRMISS := TWMISS :=                        <<07308>>32165000
  TWRITES := TREGIONS := TPAGES := TSTOPS := 0D;               <<07308>>32170000
  OVRFLOW := false;                                            <<07308>>32175000
                                                               <<07308>>32180000
  move BUF :=                                                  <<07308>>32185000
"DISC   CACHE    READ WRITE        PROCESS               % OF    CACHE" 32190000
,2;                                                            <<07308>>32195000
  LENGTH := TOS - @BUF;                                        <<07308>>32200000
  PRINT(BUF,LENGTH,0);                                         <<07308>>32205000
                                                               <<07308>>32210000
  move BUF :=                                                  <<07308>>32215000
"LDEV  REQUESTS  HIT%  HIT%  READ%  STOPS      K-BYTES  MEMORY  DOMAINS"32220000
,2;                                                            <<07308>>32225000
  LENGTH := TOS - @BUF;                                        <<07308>>32230000
  PRINT(BUF,LENGTH,0);                                         <<07308>>32235000
                                                               <<07308>>32240000
  BUF := "--";                                                 <<07308>>32245000
  move BUF(1) := BUF,(LENGTH-1);                               <<07308>>32250000
  PRINT(BUF,LENGTH,0);                                         <<07308>>32255000
  PRINT(BUF,0,0);  << Space >>                                 <<07308>>32260000
                                                               <<07308>>32265000
  << Get main memory size in bytes >>                          <<07308>>32270000
  TMEMORY := double(absolute(NBANKSINX)) * 131072D;            <<07308>>32275000
                                                               <<07308>>32280000
  << Get cache data segment words >>                           <<07308>>32285000
  OHEAD := HD(CDT'DST'WORDS);                                  <<*7553>>32290000
                                                               <<07308>>32295000
  LDEV'LINK := 0;                                              <<*7553>>32300000
  while LDEV'LINK <= MAX'INDEX do                              <<*7553>>32305000
    begin                                                      <<07308>>32310000
    << Get statistics >>                                       <<07308>>32315000
    << Load entry from XDS >>                                  <<*7553>>32320000
    DMOVIN(XDS,LDEV'LINK * CDT'ENTRY'SIZE,CDT'ENTRY'SIZE,LD);  <<*7553>>32325000
                                                               <<*7553>>32330000
    RHIT := LDD(CDT'DE'RHIT/2);                                <<*7553>>32335000
    WHIT := LDD(CDT'DE'WHIT/2);                                <<*7553>>32340000
    RMISS := LDD(CDT'DE'RMISS/2);                              <<*7553>>32345000
    WMISS := LDD(CDT'DE'WMISS/2);                              <<*7553>>32350000
    STOPS := LDD(CDT'DE'STOP/2);                               <<*7553>>32355000
                                                               <<07308>>32360000
    WORK := LD(CDT'DE'MAPD'PAGES);                             <<*7553>>32365000
    PAGES := double(WORK);                                     <<07308>>32370000
    WORK := LD(CDT'DE'REGIONS);                                <<*7553>>32375000
    REGIONS := double(WORK);                                   <<07308>>32380000
                                                               <<07308>>32385000
    << Since there is 1 page overhead per mapped domain, >>    <<07308>>32390000
    << mask it off.                                      >>    <<07308>>32395000
    PAGES := PAGES - REGIONS;                                  <<07308>>32400000
                                                               <<07308>>32405000
    LDEV := LD(CDT'DE'LDEV);                                   <<*7553>>32410000
    REQUESTS := RHIT + RMISS + WHIT + WMISS;                   <<07308>>32415000
    if overflow then REQUESTS := 0D;                           <<07308>>32420000
    if REQUESTS = 0D then   << No hits/misses >>               <<07308>>32425000
      begin                                                    <<07308>>32430000
      PCNT'READ := 0;                                          <<07308>>32435000
      RPERCENT  := WPERCENT := 0;                              <<07308>>32440000
      end                                                      <<07308>>32445000
    else                                                       <<07308>>32450000
      begin                                                    <<07308>>32455000
      PCNT'READ:=integer(                                      <<07308>>32460000
                 (REQUESTS-WHIT-WMISS)*100D / REQUESTS         <<07308>>32465000
                 );                                            <<07308>>32470000
      RPERCENT := integer((RHIT*100D)/(RHIT+RMISS));           <<07308>>32475000
      WPERCENT := integer((WHIT*100D)/(WHIT+WMISS));           <<07308>>32480000
      end;                                                     <<07308>>32485000
                                                               <<07308>>32490000
    TRHIT := TRHIT + RHIT;                                     <<07308>>32495000
    if overflow then OVRFLOW := true;                          <<07308>>32500000
    TWHIT := TWHIT + WHIT;                                     <<07308>>32505000
    if overflow then OVRFLOW := true;                          <<07308>>32510000
    TRMISS := TRMISS + RMISS;                                  <<07308>>32515000
    if overflow then OVRFLOW := true;                          <<07308>>32520000
    TWMISS := TWMISS + WMISS;                                  <<07308>>32525000
    if overflow then OVRFLOW := true;                          <<07308>>32530000
    TPAGES := TPAGES + PAGES;                                  <<07308>>32535000
    if overflow then OVRFLOW := true;                          <<07308>>32540000
    TREGIONS := TREGIONS + REGIONS;                            <<07308>>32545000
    if overflow then OVRFLOW := true;                          <<07308>>32550000
    TSTOPS := TSTOPS + STOPS;                                  <<07308>>32555000
    if overflow then OVRFLOW := true;                          <<07308>>32560000
                                                               <<07308>>32565000
    << Perform interum calculations >>                         <<07308>>32570000
    PAGES := PAGES * 256D;   << Number of bytes >>             <<07308>>32575000
    PCNT'MEM := integer((PAGES*100D)/TMEMORY);                 <<07308>>32580000
    PAGES := (PAGES+512D)/1024D;  << Number of K-BYTES >>      <<07308>>32585000
                                                               <<07308>>32590000
    BUF := "  ";                                               <<07308>>32595000
    move BUF(1) := BUF,(39);                                   <<07308>>32600000
    ASCII(LDEV,10,B'BUF);                                      <<07308>>32605000
    DASCII(REQUESTS,10,B'BUF(6));                              <<07308>>32610000
    ASCII(RPERCENT,10,B'BUF(17));                              <<07308>>32615000
    ASCII(WPERCENT,10,B'BUF(23));                              <<07308>>32620000
    ASCII(PCNT'READ,10,B'BUF(29));                             <<07308>>32625000
    DASCII(STOPS,10,B'BUF(34));                                <<07308>>32630000
    DASCII(PAGES,10,B'BUF(46));                                <<07308>>32635000
    ASCII(PCNT'MEM,10,B'BUF(58));                              <<07308>>32640000
    LENGTH := DASCII(REGIONS,10,B'BUF(64));                    <<07308>>32645000
    LENGTH := LENGTH + 64;                                     <<07308>>32650000
    PRINT(BUF,-LENGTH,0);                                      <<07308>>32655000
                                                               <<07308>>32660000
    LDEV'LINK := LDEV'LINK + 1;                                <<*7553>>32665000
    end;  << of WHILE >>                                       <<07308>>32670000
                                                               <<07308>>32675000
  << Print final results >>                                    <<07308>>32680000
  PRINT(BUF,0,0);                                              <<07308>>32685000
  BUF := "  ";                                                 <<07308>>32690000
  move BUF(1) := BUF,(39);                                     <<07308>>32695000
                                                               <<07308>>32700000
  move BUF := "Total";                                         <<07308>>32705000
  if OVRFLOW then                                              <<07308>>32710000
    begin                                                      <<07308>>32715000
    move B'BUF(6) := "* * Arithmetic overflow * *",2;          <<07308>>32720000
    LENGTH := tos - @B'BUF;                                    <<07308>>32725000
    PRINT(BUF,-LENGTH,0);                                      <<07308>>32730000
    end                                                        <<07308>>32735000
  else                                                         <<07308>>32740000
    begin                                                      <<07308>>32745000
    REQUESTS := TRHIT + TRMISS + TWHIT + TWMISS;               <<07308>>32750000
    if overflow then REQUESTS := 0D;                           <<07308>>32755000
    if REQUESTS = 0D then                                      <<07308>>32760000
      begin                                                    <<07308>>32765000
      PCNT'READ := 0;                                          <<07308>>32770000
      RPERCENT := 0;                                           <<07308>>32775000
      WPERCENT := 0;                                           <<07308>>32780000
      end                                                      <<07308>>32785000
    else                                                       <<07308>>32790000
      begin                                                    <<07308>>32795000
      if ((TRHIT+TRMISS)=0D) then                              <<07308>>32800000
        begin                                                  <<07308>>32805000
        RPERCENT := 0;                                         <<07308>>32810000
        end                                                    <<07308>>32815000
      else                                                     <<07308>>32820000
        begin                                                  <<07308>>32825000
        RPERCENT := integer((TRHIT*100D)/(TRHIT + TRMISS));    <<07308>>32830000
        end;                                                   <<07308>>32835000
                                                               <<07308>>32840000
      PCNT'READ := integer((REQUESTS-TWHIT-TWMISS)             <<07308>>32845000
                   *100D/REQUESTS);                                     32850000
                                                               <<07308>>32855000
      if ((TWHIT+TWMISS)=0D) then                              <<07308>>32860000
        begin                                                  <<07308>>32865000
        WPERCENT := 0;                                         <<07308>>32870000
        end                                                    <<07308>>32875000
      else                                                     <<07308>>32880000
        begin                                                  <<07308>>32885000
        WPERCENT := integer((TWHIT*100D)/(TWHIT + TWMISS));    <<07308>>32890000
        end;                                                   <<07308>>32895000
      end;                                                     <<07308>>32900000
                                                               <<07308>>32905000
    DASCII(REQUESTS,10,B'BUF(6));                              <<07308>>32910000
    ASCII(RPERCENT,10,B'BUF(17));                              <<07308>>32915000
    ASCII(WPERCENT,10,B'BUF(23));                              <<07308>>32920000
    ASCII(PCNT'READ,10,B'BUF(29));                             <<07308>>32925000
    DASCII(TSTOPS,10,B'BUF(34));                               <<07308>>32930000
    TPAGES := TPAGES * 256D;                                   <<07308>>32935000
    if overflow then TPAGES := 0D;                             <<07308>>32940000
    PCNT'MEM := integer((TPAGES*100D)/TMEMORY);                <<07308>>32945000
    TPAGES := (TPAGES + 512D) / 1024D;                         <<07308>>32950000
    DASCII(TPAGES,10,B'BUF(46));                               <<07308>>32955000
    ASCII(PCNT'MEM,10,B'BUF(58));                              <<07308>>32960000
    LENGTH := DASCII(TREGIONS,10,B'BUF(64));                   <<07308>>32965000
    LENGTH := LENGTH + 64;                                     <<07308>>32970000
    PRINT(BUF,-LENGTH,0);                                      <<07308>>32975000
                                                               <<07308>>32980000
    PRINT(BUF,0,0);                                            <<*7553>>32985000
                                                               <<*7553>>32990000
    << Print percent of user I/O eliminated >>                 <<*7553>>32995000
                                                               <<*7553>>33000000
    LENGTH := DASCII(if REQUESTS=0D then 0D                    <<*7553>>33005000
              else ((TRHIT*100D)/REQUESTS),10,B'BUF(0));       <<*7553>>33010000
    move B'BUF(LENGTH) := "% of user I/Os eliminated.",2;      <<*7553>>33015000
    LENGTH := tos - @B'BUF;                                    <<*7553>>33020000
    PRINT(BUF,-LENGTH,0);                                      <<*7553>>33025000
                                                               <<*7553>>33030000
    << Print cache overhead number >>                          <<*7553>>33035000
                                                               <<*7553>>33040000
    move B'BUF := "Data overhead is ",2;                       <<07308>>33045000
    LENGTH := tos - @B'BUF;                                    <<07308>>33050000
    LENGTH := LENGTH + DASCII(((TREGIONS*256D)+                <<07308>>33055000
       double(OHEAD))/1024D,10,B'BUF(LENGTH));                 <<07308>>33060000
    move B'BUF(LENGTH) := "K bytes. ",2;                       <<*7553>>33065000
    LENGTH := tos - @B'BUF;                                    <<07308>>33070000
    PRINT(BUF,-LENGTH,0);                                      <<07308>>33075000
                                                               <<07308>>33080000
    move B'BUF:="Sequential fetch quantum is ",2;              <<07308>>33085000
    LENGTH := tos - @B'BUF;                                    <<07308>>33090000
    LENGTH := LENGTH + ASCII(HD(CDT'SEQ'MINFTCH),              <<*7553>>33095000
                             10,                               <<*7553>>33100000
                             B'BUF(LENGTH));                   <<*7553>>33105000
    move B'BUF(LENGTH):=" sectors.",2;                         <<07308>>33110000
    LENGTH := tos - @B'BUF;                                    <<07308>>33115000
    PRINT(BUF,-LENGTH,0);                                      <<07308>>33120000
                                                               <<07308>>33125000
    move B'BUF:="Random fetch quantum is ",2;                  <<07308>>33130000
    LENGTH := tos - @B'BUF;                                    <<07308>>33135000
    LENGTH := LENGTH + ASCII(HD(CDT'RND'MINFTCH),              <<*7553>>33140000
                             10,                               <<*7553>>33145000
                             B'BUF(LENGTH));                   <<*7553>>33150000
    move B'BUF(LENGTH):=" sectors.",2;                         <<07308>>33155000
    LENGTH := tos - @B'BUF;                                    <<07308>>33160000
    PRINT(BUF,-LENGTH,0);                                      <<07308>>33165000
    move B'BUF := "Block on Write = ", 2;                      <<*7551>>33170000
    LENGTH := tos - @B'BUF;                                    <<*7551>>33175000
    if HD(CDT'FORCE'POST) = 0                                  <<*7553>>33180000
      then move B'BUF(LENGTH) := "NO.", 2                      <<*7551>>33185000
    else move B'BUF(LENGTH) := "YES. ", 2;                     <<*7551>>33190000
    LENGTH := tos - @B'BUF;                                    <<*7551>>33195000
    PRINT(BUF,-LENGTH,0);                                      <<*7551>>33200000
    end;                                                       <<07308>>33205000
                                                               <<07308>>33210000
  PRINT(BUF,0,0);                                              <<07308>>33215000
  RSTAT := 0;                                                  <<07308>>33220000
  << Release XDS >>                                            <<*7553>>33225000
  FREEDSEG(XDS,0);                                             <<*7553>>33230000
  end;                                                         <<07308>>33235000
                                                               <<07308>>33240000
  end;                                                         <<*7553>>33245000
RESETCRITICAL(OLD'CRIT);                                       <<07308>>33250000
                                                               <<07308>>33255000
end;  << of procedure CDT'DISPLAY'DISCS >>                     <<07308>>33260000
$page "CDT'SET'SEQ / CDT'SET'RND / CDT'SET'POST procedure"     <<07308>>33265000
procedure CDT'SET'SEQ(PARM,RSTAT);                             <<07308>>33270000
value PARM;                                                    <<07308>>33275000
integer PARM,RSTAT;                                            <<07308>>33280000
option privileged,uncallable;                                  <<07308>>33285000
begin                                                          <<07308>>33290000
                                                               <<07308>>33295000
<<CDT'SET'SEQ is one of the executors for the CACHECONTROL cmd <<07308>>33300000
                                                               <<07308>>33305000
<< This procedure sets basic caching strategy and policy    >> <<07308>>33310000
<< parameters for all discs.    The returned value(s) are:  >> <<07308>>33315000
<<                                                          >> <<07308>>33320000
<< RSTAT    - Returned status, where:                       >> <<07308>>33325000
<<            0 - Successful                                >> <<07308>>33330000
<<            1 - Caching is not enabled on this system.    >> <<07308>>33335000
<<            6 - Caching not permitted.                    >> <<*7553>>33340000
<<                                                          >> <<07308>>33345000
<< Passed parameter is:                                     >> <<07308>>33350000
<< PARM       - Set to 1 to 96 to indicate the fetch        >> <<07308>>33355000
<<              quantum on CDT'SET'SEQ and CDT'SET'RND (in  >> <<07308>>33360000
<<              sectors).  In CDT'SET'POST, a non-zero value>> <<07308>>33365000
<<              indicates that caching should only notify   >> <<07308>>33370000
<<              the user of a write completion when the     >> <<07308>>33375000
<<              actual physical write has completed.        >> <<07308>>33380000
<<                                                          >> <<07308>>33385000
<< DB is assumed to be at the caller's stack.               >> <<07308>>33390000
<<**********************************************************>> <<07308>>33395000
                                                               <<07308>>33400000
integer OLD'SIR,   << Return value from GETSIR >>              <<07308>>33405000
        OLD'CRIT,  << Old value from SETCRITICAL>>             <<07308>>33410000
        ENTRY'INDEX; << Index to which entry point was called ><<07308>>33415000
                                                               <<07308>>33420000
entry CDT'SET'RND, CDT'SET'POST;                               <<07308>>33425000
                                                               <<07308>>33430000
ENTRY'INDEX := 0;    << SET'SEQ >>                             <<07308>>33435000
go to START;                                                   <<07308>>33440000
                                                               <<07308>>33445000
CDT'SET'RND:                                                   <<07308>>33450000
ENTRY'INDEX := 1;    << SET'RND >>                             <<07308>>33455000
go to START;                                                   <<07308>>33460000
                                                               <<07308>>33465000
CDT'SET'POST:                                                  <<07308>>33470000
ENTRY'INDEX := 2;                                              <<07308>>33475000
go to START;                                                   <<07308>>33480000
                                                               <<07308>>33485000
START:                                                         <<07308>>33490000
                                                               <<07308>>33495000
if not IsSysCachable then                                      <<*7553>>33500000
   begin                                                       <<*7553>>33505000
   RSTAT := stat'sys'not'cachable;                             <<*7553>>33510000
   RETURN;                                                     <<*7553>>33515000
   end;                                                        <<*7553>>33520000
                                                               <<*7553>>33525000
<< We can't abort here... >>                                   <<07308>>33530000
OLD'CRIT := SETCRITICAL;                                       <<07308>>33535000
                                                               <<07308>>33540000
<< Obtain SIR to protect integrity >>                          <<07308>>33545000
OLD'SIR := GETSIR(CACHE'CONTROL'SIR);                          <<07308>>33550000
                                                               <<07308>>33555000
<< See if caching is enabled >>                                <<07308>>33560000
if CACHE'DST = 0 then                                          <<07308>>33565000
  RSTAT := stat'no'dst                                         <<*7553>>33570000
else                                                           <<07308>>33575000
  begin                                                        <<07308>>33580000
                                                               <<07308>>33585000
  << Set the appropriate parameter >>                          <<07308>>33590000
  case ENTRY'INDEX of                                          <<07308>>33595000
    begin                                                      <<07308>>33600000
                                                               <<07308>>33605000
<<0 - SEQ >>                                                   <<07308>>33610000
    begin                                                      <<07308>>33615000
    if not (1 <= PARM <= 96) then                              <<07308>>33620000
      PARM := CACHE'SEQUENTIAL;                                <<07308>>33625000
    CDT'SET'WORD(0,CDT'SEQ'MINFTCH,PARM);                      <<07308>>33630000
    end;                                                       <<07308>>33635000
                                                               <<07308>>33640000
<<1 - RND >>                                                   <<07308>>33645000
    begin                                                      <<07308>>33650000
    if not (1 <= PARM <= 96) then                              <<07308>>33655000
      PARM := CACHE'RANDOM;                                    <<07308>>33660000
    CDT'SET'WORD(0,CDT'RND'MINFTCH,PARM);                      <<07308>>33665000
    end;                                                       <<07308>>33670000
                                                               <<07308>>33675000
<<2- Post notification >>                                      <<07308>>33680000
    begin                                                      <<07308>>33685000
    CDT'SET'WORD(0,CDT'FORCE'POST,if(PARM=0)then 0 else -1);            33690000
    end;                                                       <<07308>>33695000
                                                               <<07308>>33700000
    end;  << of CASE on ENTRY'INDEX >>                         <<07308>>33705000
                                                               <<07308>>33710000
  RSTAT := 0;   << Return a good status >>                     <<07308>>33715000
  end;                                                         <<07308>>33720000
                                                               <<07308>>33725000
RELSIR(CACHE'CONTROL'SIR,OLD'SIR);                             <<07308>>33730000
RESETCRITICAL(OLD'CRIT);                                       <<07308>>33735000
end;                                                           <<07308>>33740000
                                                               <<06858>>33745000
$page "ShutDownCaching"                                        <<*8596>>33750000
Procedure ShutDownCaching;                                     <<*8596>>33755000
   option privileged, uncallable;                              <<*8596>>33760000
BEGIN                                                          <<*8596>>33765000
                                                               <<*8596>>33770000
<< This procedure will stop caching on all discs currently >>  <<*8596>>33775000
<< cached. This is called by Progen on =SHUTDOWN.          >>  <<*8596>>33780000
                                                               <<*8596>>33785000
Integer                                                        <<*8596>>33790000
   dev'entry,                                                  <<*8596>>33795000
   dummy,                                                      <<*8596>>33800000
   ldev;                                                       <<*8596>>33805000
                                                               <<*8596>>33810000
Disable;                                                       <<*8596>>33815000
IF cache'dst <> 0 THEN                                         <<*8596>>33820000
   BEGIN                                                       <<*8596>>33825000
   dev'entry := Cdt'Get'Word(0 <<header>>,Cdt'Disc'Head,0);    <<*8596>>33830000
   WHILE dev'entry <> 0 DO                                     <<*8596>>33835000
      BEGIN                                                    <<*8596>>33840000
      ldev := Cdt'Get'Word(dev'entry,Cdt'DE'ldev,0);           <<*8596>>33845000
      dev'entry := Cdt'Get'Word(dev'entry,Cdt'DE'Next'ldev,0); <<*8596>>33850000
      Uncache'Ldev(ldev,dummy);                                <<*8596>>33855000
      END;                                                     <<*8596>>33860000
   END;                                                        <<*8596>>33865000
END;     << Procedure ShutDownCaching >>                       <<*8596>>33870000
$title " "                                                     <<*8596>>33875000
$CONTROL SEGMENT = MAIN                                        <<06858>>33880000
END.  <<CACHESEG>>                                             <<06858>>33885000
