*M*  RA            ROUTINES TO IMPLEMENT READ-AHEAD AND AIR
         PCC      0
UTSPROC  SET      1
S69PROC  SET      1
MONPROC  SET      1
DISCBPROC SET     1
BITS     SET      1                 GET TABLE BITS
         SYSTEM   UTS
         SPACE    6
         SPACE    6
RA:      EQU      %
     TITLE         '****  PREAMBLE  ****'
     SPACE         3
*P*  NAME:         RA
*P*
*P*  PURPOSE:      PROVIDE ALL ROUTINES SPECIFIC TO READ-AHEAD AND
*P*                AIR (ASSOCIATIVE I/O REDUCTION).
*P*
*P*  DESCRIPTION:  THIS MODULE IS OPTIONALLY INCLUDED IN THE MONITOR
*P*                ROOT BY THE APPEARANCE OF THE KEYWORD 'RASIZE' ON
*P*                THE IMC CARD OF PASS2.  THEREFORE, ALL EXTERNAL
*P*                CALLS TO ROUTINES IN THIS MODULE MUST BE CONDITIONAL
*P*                ON THE PRESENCE OF THE MODULE.
*P*
*P*                ALL CODE IS EXECUTED MAPPED WITH THE EXCEPTION OF
*P*                RAENDAC, THE I/O END-ACTION ROUTINE.
*P*
*P*  READ-AHEAD:   WHENEVER A USER FINISHES AN M:READ CAL ON A
*P*                DISC FILE OPENED IN WITH SEQUENTIAL ACCESS,
*P*                THE NEXT DISC ADDRESS WHICH WILL HAVE TO BE READ
*P*                IS LOCATED.  IF A MONITOR FREE PAGE AND A READ-
*P*                AHEAD TABLE ENTRY CAN BE OBTAINED, A READ IS ISSUED
*P*                FOR THAT GRANULE.
*P*                WHENEVER IT IS NECESSARY TO READ A BLOCKED DATA
*P*                GRANULE OR A CONTROL GRANULE, T:RACHK IS CALLED
*P*                TO SEE IF IT HAS ALREADY BEEN READ.
*P*
*P*  AIR:          WHENEVER FILE MANAGEMENT IS FINISHED WITH AN
*P*                FPOOL BUFFER CONTAINING A FILE DIRECTORY GRANULE,
*P*                T:RADD IS CALLED TO ATTEMPT TO LEAVE THE GRANULE
*P*                IN CORE.
*P*                WHENEVER A FILE DIRECTORY GRANULE MUST BE READ,
*P*                T:RACHK IS CALLED TO SEE IF IT IS ALREADY IN CORE.
         TITLE    '****  EXTERNAL DEFINITIONS  ****'
         SPACE    2
         DEF      RA:               MODULE NAME FOR PATCHING
         DEF      RAPURGE           PURGE ONE TIMED-OUT ENTRY
         DEF      T:RACHK           CHECK FOR GRANULE IN TABLES
         DEF      T:RAPURGD         PURGE ANY READ-AHEAD FOR THIS DCB
         DEF      T:RAMISRCH        START NEXT KEYED FILE READ-AHEAD
         DEF      T:RACONSEC        START NEXT CONSEC FILE READ-AHEAD
         DEF      T:RADD            ADD FILE DIR GRANULE TO TABLES
         DEF      T:RAREL           RELEASE AN ENTRY
         TITLE    '****  EXTERNAL REFERENCES  ****'
         SPACE    2
         REF      ACNCFU            CFU FOR ACCOUNT DIRECTORY
         REF      C:CTUN
         REF      C:TIC
         REF      C:TINC
         REF      DUALEA            END-ACTION FOR DUAL I/O'S
         REF      FILCFU            CFU FOR FILE DIRECTORY
         REF      FMCHKDA           VALIDATE DISC ADDRESS
         REF      GETORG            GET ORGANIZATION FROM DCB
         REF      GETTBL            GET DUAL I/O END-ACTION TABLE ENTRY
         REF      GETVDCTX          GET DCB:VDCTX
         REF      GETVNO            GET DCB:VNO
         REF      NEWQNW            QUEUE AN I/O NO WAIT
         REF      PULLFOUR          GET NEXT FOUR BYTES FROM BUFFER
         REF      REGIPSD           ENTRY TO REG FOR I/O WAIT
         REF      S:PNO             CPU NUMBER
         REF      S:STLC            < 0 IS SWAPPER NEEDS STOLEN PAGES
         REF      SETPVI            POINT DCB TO GIVEN PRIV VOL
         REF      SETVNO            STORE NEW VOL # IN DCB
         REF      T:RSPP            RELEASE STOLEN PAGE
         REF      T:STLPP           STEAL A PAGE
         REF      T:XBUF            EXCHANGE WINDOW PAGES
         REF      UB:MF             # OUTSTANDING I/O'S
         SPACE    1
         REF      RAB:FLINK         LINK TO NEXT NEWEST ENTRY
         REF      RAB:BLINK         LINK TO NEXT OLDEST ENTRY
         REF      RAB:USER          USER ASSOCIATED WITH ENTRY
         REF      RAH:DCB           MOST SIG 16 BITS OF DCB
         REF      RAH:TIME          TIME ENTRY WAS INITIALIZED
         REF      RA:DA             DISC ADDRESS AND FLAGS
         REF      RAX:PAGE          PAGE # OF BUFFER
         SPACE    1
         REF      S:CUN             CURRENT USER
         REF      S:CUP             CURRENT USER'S PRIORITY
         SPACE    1
         REF      RA:CURA           CURRENT # AIR ENTRIES ACTIVE
         REF      RA:CURF           CURRENT # IN FREE POOL
         REF      RA:CURR           CURRENT # READ-AHEADS
         REF      RA:ABNTB          # NOT STARTED - NO TABLE ENTRIES
         REF      RA:ABNCO          # NOT STARTED - NO CORE PAGE
         REF      RA:AINIT          # READ-AHEAD TRIED TO START
         REF      RA:ABNTR          # READ-AHEADS TIMED OUT
         REF      RA:ABNTA          # AIR ENTRIES TIMED OUT
         REF      RA:ABNWP          # WRONG PAGES READ AHEAD
         REF      RA:ABNNN          # READ-AHEAD BUFFERS NOT USED
         REF      RA:ASTOR          # ATTEMPTS TO ADD FILE DIR GRANULE
         REF      RA:SSTOR          # FILE DIR GRANULES ADDED
         REF      RA:AGET           # ATTEMPTS TO RETRIEVE FILE DIR
         REF      RA:SGET           # FILE DIR GRANULES GOTTEN
         REF      RA:SINIT          # READ-AHEADS STARTED
         REF      RA:SCHK           # READ-AHEADS RETRIEVED
         REF      RA:IOW            # I/O WAIT EVENTS ON RETRIEVES
         REF      RA:IOWA           # AIR I/O WAIT EVENTS
         REF      RA:PUTF           # ENTRIES PUT ON FREE POOL
         REF      RA:GETF           # ENTRIES GOTTEN FROM FREE POOL
         REF      SL:RAMR           MAX # READ-AHEADS ALLOWED
         REF      SL:RAMF           MAX # PAGES ALLOWED IN FREE POOL
         REF      SL:AIRM           MAX # AIR ENTRIES ALLOWED
         REF      SL:RATOR          READ AHEAD TIME OUT
         REF      SL:AIRTO          AIR TIME OUT
         SPACE    1
         REF      NB31TO0           MASKS
         SPACE    1
         TITLE    '****  REGISTERS AND CONSTANTS  ****'
         SPACE    2
R0       EQU      0
R1       EQU      1
R2       EQU      2
R3       EQU      3
R4       EQU      4
R5       EQU      5
R6       EQU      6
R7       EQU      7
R8       EQU      8
R9       EQU      9
R10      EQU      10
R11      EQU      11
R12      EQU      12
R13      EQU      13
R14      EQU      14
R15      EQU      15
         SPACE    2
Y5       DATA     X'50000000'
         SPACE    3
FL:ACT   EQU      Y8                ENTRY IS ACTIVE
FL:IOP   EQU      Y4                I/O IN PROGRESS
MSK:IOP  EQU      NB31TO0+31
FL:AIR   EQU      Y2                AIR ENTRY
FL:WAIT  EQU      Y1                USER IS WAITING FOR I/O COMPLETE
MSK:WAIT EQU      NB31TO0+29
FL:REL   EQU      Y08               ENTRY IS TO BE RELEASED
FL:IW    EQU      Y5                IOP AND WAIT
         SPACE    2
DCDAM    EQU      ACNCFU+4          DUAL DISC ADDRESS
         TITLE    '****  INITIATE A READ AHEAD OPERATION  ****'
         SPACE    2
*  PURPOSE:  INITIATE A READ AHEAD IF POSSIBLE
*
*  INPUT:  R6 = DCB ADDRESS
*          R12 = DISC ADDRESS TO BE READ
*
*  CALL:  BAL,R0  T:RAINIT
*
*  VOLATILE:  R7,R8,R11
*
         SPACE    1
T:RAINIT EQU      %
         PUSH     9,R12
         MTW,1    RA:AINIT          INCR # ATTEMPTED TO INITIATE
*
         LW,R8    R12               DISC ADDRESS TO BE READ
         BAL,R11  FMCHKDA           VALIDATE IT
         BCR,15   CHKXIT            BAD DISC ADDRESS
*
         BAL,R11  PRIVDA            CONVERT PRIVATE FORM OF DISC ADDR
*
         DISABLE
*
         OR,R12   FL:IOP            I/O IN PROGRESS FLAG
         BAL,R11  GETENTRY          GET TABLE ENTRY
         BNEZ     RAINXIT6          DIDN'T GET AN ENTRY
         MTW,1    RA:CURR           COUNT AN ACTIVE READ-AHEAD ENTRY
*
         LW,R13   R6
         SLS,R13  -1
         STH,R13  RAH:DCB,R7        PUT DCB IN TABLE
*
         LI,R2    BARAX
         STB,R7   *R6,R2            SAVE TABLE INDEX IN DCB
*
         MTW,1    RA:SINIT          INCR # SUCCESSFULLY INITIATED
*
         LI,R2    0                 FUNCTION CODE (READ)
*
RAIO     LW,R1    R7                MOVE END-ACTION INFO
RAIO1    AND,R12  M24
         LW,R15   R12               DISC ADDRESS
         LI,R14   512*4             BYTE COUNT
         CI,R15   1
         BAZ      %+2
         LI,R14   256*4             HALF GRANULE
         LOAD,R13 RAX:PAGE,R7       PAGE # OF BUFFER
         SLS,R13  9+2               BYTE ADDRESS
         LDCTX,R12  R15             DCT INDEX
         LW,R11   S:CUP             CURRENT USER'S PRIORITY
         STH,R11  R12               PRIORITY
         STB,R2   R12               FUNCTION CODE
         AI,R12   X'0A00'           NRT=10
         LI,R0    RAENDAC           END ACTION ADDRESS
         BAL,R11  NEWQNW            QUEUE THE I/O
         NOP
         LB,R11   R7
         BEZ      CHKXIT            NO DUAL
         LW,R12   DCDAM             DISC ADDRESS OF DUAL
         LI,R2    1                 FUNCTION CODE = WRITE
         LW,R1    R7                MOVE END-ACTION INFO
         AND,R7   M24               MASK OFF DUAL FLAG
         B        RAIO1             WRITE THE DUAL
         SPACE    3
RAINXIT6 EQU      %
         MTW,1    0,R4              INCR BUCKET TO SAY WHY IT DIDN'T WORK
         BAL,R0   RAPURGE           PURGE TIMED-OUT ENTRIES
         B        RACHKCC1
         SPACE    2
GETIME   LW,R1    C:CTUN
         SW,R1    C:TINC
         AW,R1    C:TIC
         SLS,R1   -4                MSEC/32
         AND,R1   M16
         B        *R0
         TITLE    '****  END ACTION ROUTINE  ****'
         SPACE    2
RAENDAC  EQU      %
         LB,R3    R14               DUAL FLAG
         BEZ      RAENDAC1          NOT DUAL WRITE
         BAL,R0   DUALEA            CHECK IF LAST WRITE
         AND,R14  M24
RAENDAC1 PUSH     R11
         LW,R7    R14               READ-AHEAD TABLE INDEX
         LW,R2    RA:DA,R7
         AND,R2   MSK:IOP           RESET FL:IOP
         STW,R2   RA:DA,R7
         CW,R2    FL:REL
         BAZ      CHKERR            ENTRRY IS NOT TO BE RELEASED
         B        CHKREL
*
*  RELEASE THE ENTRY
*
RAENDREL PULL     R10
         B        T:RAREL
         SPACE    2
*
*  CHECK COMPLETION CODE
*
CHKERR   EQU      %
         MTB,-1   R12
         BEZ      CHKWAIT           OK IF TYC = 1
*
*  I/O ERROR
*
CHKREL   CW,R2    FL:WAIT
         BAZ      RAENDREL          USER IS NOT WAITING
         OR,R2    FL:REL            SET RELEASE FLAG
         SPACE    2
*
*  REPORT I/O COMPLETE FOR WAITING USER
*
REPIOC   STW,R2   RA:DA,R7          STORE FLAGS
         ENABLE
         PULL     R11               GET RETURN ADDRESS
         LB,R2    RAB:USER,R7       GET USER NUMBER
         STW,R2   *TSTACK           IOQ WILL REPORT I/O COMPLETE
         B        *R11
         SPACE    2
CHKWAIT  CW,R2    FL:WAIT
         BANZ     REPIOC            USER IS WAITING
         ENABLE
         PULL     R11
         B        *R11
         SPACE    2
PRIVDA   EQU      %
         LI,R15   DCBPRIVBIT
         CW,R15   PRIV,R6
         BAZ      *R11              NOT PRIVATE
         PUSH     6,R7
         BAL,R0   GETVNO            R3 = CURRENT VOL #
         LDCTX,R0 R12               VOL # OF DESIRED DA
         CW,R3    R0
         BE       PRIV2             SAME - ALL OK
         BAL,R0   GETORG            NOT SAME - BETTER NOT BE CONSEC
         BL       PRIV8             CONSEC - ONLY ONE VOL OPEN
         BAL,R0   SETVNO            PUT IN DESIRED VOL #
         BAL,R15  SETPVI            FIND THE HGP, PUT IN DCTX
*
PRIV2    BAL,R0   GETVDCTX          GET DCTX OF CURRENT VOL
         LW,R12   *TSTACK
         STDCTX,R3  R12             PUT IN DCT INDEX
         STW,R12  *TSTACK
         PULL     6,R7
         B        *R11
*
PRIV8    PULL     6,R7              CAN'T DO READ-AHEAD
         B        CHKXIT
         TITLE    '****  CHECK FOR BLOCK READ AHEAD  ****'
         SPACE    2
*F*  NAME:         T:RACHK
*F*
*F*  PURPOSE:      CHECK IF DESIRED GRANULE WAS READ AHEAD.
*F*
*F*  DESCRIPTION:  THE READ-AHEAD TABLES ARE SEARCHED FOR THE DESIRED
*F*                DISC ADDRESS.  IF IT IS FOUND, THE USER IS PUT INTO
*F*                STATE I/O WAIT (SIOW) IF THE I/O HAS NOT COMPLETED.
*F*                THE READ-AHEAD BUFFER PAGE AND THE USER'S BUFFER
*F*                PAGE ARE SWITCHED IN THE USER'S CMAP, AND HIS
*F*                MAP RELOADED.  THE USER'S OLD BUFFER PAGE # IS
*F*                PLACED IN THE READ-AHEAD TABLE ENTRY, AND THE ENTRY
*F*                IS RELEASED.
         SPACE    1
*D*  NAME:        T:RACHK
*D*
*D*  REGISTERS:   R5,R7,R8,R10,R11,R13 VOLATILE
*D*
*D*  CALL:        R0 IS LINK
*D*
*D*  INPUT:       R6 = DCB ADDRESS
*D*               R12 = DISC ADDRESS
*D*               R14 = BUFFER ADDRESS
*D*
*D*  OUTPUT:      CC=0  BLOCK FOUND AND MAPPED IN
*D*                 =1  NO BLOCK OR WRONG BLOCK FOUND
*D*
*D*  DESCRIPTION: RAX FIELD IN DCB IS EXAMINED.  IF NOT 0 OR X'FF',
*D*               THE INDICATED ENTRY IS CHECKED TO SEE THAT
*D*               USER #, DCB ADDRESS AND DISC ADDRESS ARE CORRECT.
*D*               IF SO, USER IS PUT INTO I/O WAIT STATE (SIOW)
*D*               IF I/O HAS NOT COMPLETED, THEN READ-AHEAD BUFFER
*D*               IS SWITCHED WITH USER'S PHYSICAL BUFFER PAGE.
*D*               USER'S OLD PHYSICAL BUFFER PAGE IS PUT IN READ-AHEAD
*D*               ENTRY AND ENTRY IS RELEASED BY T:RAREL.
*
         SPACE    2
T:RACHK  EQU      %
         LI,R15   X'1FFFF'
         AND,R15  CFU,R6            CFU ADDRESS
         CI,R15   FILCFU            IS THIS A FILE DIRECTORY READ
         BE       RACHKAIR          MAYBE
         BL       CHKXIT1           ACCOUNT DIRECTORY - IGNORE
         LI,R5    BARAX
         LB,R7    *R6,R5            CURRENT READ-AHEAD INDEX
         BEZ      CHKXIT1           NO READ-AHEAD IN PROGRESS
         CI,R7    X'FF'
         BE       CHKXIT1           READ-AHEAD NOT ALLOWED
         LI,R4    0
         STB,R4   *R6,R5            CLEAR RAX IN DCB
*
         PUSH     9,R12
****************************************
         BLOCK                      GO TO MASTER CPU
****************************************
         BAL,R11  PRIVDA            CONVERT PRIVATE DISC ADDRESS
         LW,R13   M24
         DISABLE
         LB,R4    RAB:USER,R7
         CW,R4    S:CUN
         BNE      RACHKCC1          DOESN'T BELONG TO THIS USER
         LW,R4    FL:ACT
         CW,R4    RA:DA,R7
         BAZ      RACHKCC1          ENTRY NOT ACTIVE
*
         LH,R4    RAH:DCB,R7
         LW,R5    M16
         SLD,R4   1
         CS,R4    R6
         BNE      RACHKCC1          NOT FOR THIS DCB
*
         CS,R12   RA:DA,R7
         BE       CHKIOC            DISC ADDRESS CORRECT
*
*  WRONG DISC ADDRESS READ
*
         MTW,1    RA:ABNWP          INCR # WRONG PAGES READ
RACHKREL BAL,R10  T:RAREL           RELEASE THE ENTRY
*
RACHKCC1 ENABLE
         PULL     9,R12
         LCI      1
         B        *R0
*
CHKXIT   PULL     9,R12
         LCI      0
         B        *R0
*
CHKXIT1  ENABLE
         LCI      1
         B        *R0
         SPACE    3
*
*  CHECK FOR FILE DIRECTORY GRANULE
*
RACHKAIR   EQU    %
         LI,R7    DCBPRIVBIT
         CW,R7    PRIV,R6
         BANZ     CHKXIT1           NO AIR FOR PRIVATE
         LW,R13   M24
*
****************************************
         BLOCK                      GO TO MASTER CPU
****************************************
         MTW,1    RA:AGET           INCR # ATTEMPTED GETS
         LW,R8    FL:AIR
         LI,R7    0
         DISABLE
AIR10    LB,R7    RAB:FLINK,R7      GET NEXT ENTRY
         BEZ      CHKXIT1           NO MORE
         CW,R8    RA:DA,R7          IS THIS AN AIR ENTRY
         BAZ      AIR10             NO
         CS,R12   RA:DA,R7          IS IT RIGHT DISC ADDRESS
         BNE      AIR10             NO
*
         MTW,1    RA:SGET           INCR # SUCCESSFUL GETS
         PUSH     9,R12
         B        CHKIOC2
         SPACE    3
*
*  THE CORRECT GRANULE WAS READ AHEAD
*
CHKIOC   EQU      %
         MTW,1    RA:SCHK           INCR # SUCCESSFUL CHECKS
CHKIOC2  EQU      %
         LW,R4    RA:DA,R7
         AND,R4   MSK:WAIT          RESET FL:WAIT
         STW,R4   RA:DA,R7
         CW,R4    FL:IOP            IS I/O IN PROGRESS
         BAZ      IOC               NO
*
IOWAIT   OR,R4    FL:WAIT           SET USER WAITING FLAG
         STW,R4   RA:DA,R7
         CW,R4    FL:AIR
         BAZ      %+2
         MTW,1    RA:IOWA           COUNT AIR REGS SEPARATELY
         MTW,1    RA:IOW            INCR # I/O WAIT REGS
*
         LW,R4    S:CUN
         STB,R4   RAB:USER,R7       STORE USER # (NEEDED FOR AIR)
         MTB,1    UB:MF,R4          INCR MASTER FUNCTON COUNT
         PUSH     R6
         LI,R6    0                 SPECIAL DCB ADDRESS
         XPSD,0   REGIPSD           WAIT FOR I/O TO COMPLETE
         PULL     R6
         B        CHKIOC2
*
*  I/O COMPLETE
*
IOC      CW,R4    FL:REL
         BANZ     RACHKREL          BR TO RELEASE ENTRY
         ENABLE
         LW,R5    R7                T:XBUF DESTROYS R7
         LOAD,R3  RAX:PAGE,R7
         BEZ      SC2E01            BAD PAGE #
         SLS,R3   9                 ADDRESS OF READ AHEAD BUFFER
         BAL,R2   T:XBUF            EXCHANGE BUFFERS
         LW,R7    R5
         SLS,R10  -9                USER'S BUFFER PAGE
         STORE,R10  RAX:PAGE,R7
         BAL,R10  T:RAREL           RELEASE ENTRY AND PAGE
         B        CHKXIT            NORMAL EXIT
         TITLE    '****  PURGE READ AHEAD FOR A GIVEN DCB  ****'
         SPACE    2
*F*  NAME:         T:RAPURGD
*F*
*F*  PURPOSE:      RELEASE ANY READ-AHEAD ENTRY FOR A GIVEN DCB.
*F*
*F*  DESCRIPTION:  READ-AHEAD TABLES ARE SEARCHED FOR AN ACTIVE
*F*                ENTRY THAT HAS THIS USER # AND DCB ADDRESS.  IF
*F*                ONE IS FOUND, IT IS RELEASED VIA T:RAREL.
         SPACE    1
*D*  NAME:        T:RAPURGD
*D*
*D*  REGISTERS:   R0,R2,R4,R5,R10,R15 VOLATILE
*D*
*D*  CALL:        R11 IS LINK
*D*
*D*  DESCRIPTION: RAX FIELD IN DCB IS EXAMINED.  IF NOT 0 OR X'FF',
*D*               THE INDICATED ENTRY IS CHECKED TO SEE THAT
*D*               USER # AND DCB ADDRESS ARE CORRECT.  IF SO,
*D*               T:RAREL IS CALLED TO RELEASE THE ENTRY AND
*D*               RA:ABNNN IS INCREMENTED.
*
         SPACE    2
T:RAPURGD  EQU    %
         LW,R15   R7                SAVE R7 - CLS USES IT
         LI,R2    BARAX
         LB,R7    *R6,R2            INDEX OF CURRENT READ AHEAD
         BEZ      RAPURGD7          NONE ACIVE
         CI,R7    X'FF'
         BE       RAPURGD7          NONE POSSIBLE
*
***********************************************************
         BLOCK                      BLOCK SLAVE CPU
***********************************************************
         DISABLE
         LW,R4    RA:DA,R7
         CW,R4    FL:ACT
         BAZ      RAPURGD5          ENTRY INACTIVE
*
         LB,R5    RAB:USER,R7
         CW,R5    S:CUN
         BNE      RAPURGD5          DOESN'T BELONG TO THIS USER
*
         LH,R4    RAH:DCB,R7
         LW,R5    M16
         SLD,R4   1
         CS,R4    R6
         BNE      RAPURGD5          DOESN'T BELONG TO THIS DCB
*
         PUSH     R11
         BAL,R10  T:RAREL           RELEASE IT
         PULL     R11
         MTW,1    RA:ABNNN          INCR # READS UNUSED
*
RAPURGD5 ENABLE
RAPURGD7 LW,R7    R15
         LI,R2    BARAX
         LI,R4    X'FF'             SET NO MORE READ-AHEADS ALLOWED
         STB,R4   *R6,R2
         B        *R11
         TITLE    '****  PURGE ALL TIMED OUT READ AHEADS  ****'
         SPACE    2
*F*  NAME:         RAPURGE
*F*
*F*  PURPOSE:      RELEASE ONE TIMED-OUT READ-AHEAD TABLE ENTRY.
*F*
*F*  DESCRIPTION:  READ-AHEAD TABLES ARE SEARCHED FOR THE OLDEST
*F*                ENTRY THAT HAS TIMED OUT.  IF ONE IS FOUND, IT
*F*                IS RELEASED.
         SPACE    1
*D*  NAME:        RAPUURGE
*D*
*D*  REGISTERS:   R8-R15 VOLATILE
*D*
*D*  CALL:        R0 IS THE LINK
*D*
*D*  DESCRIPTION: THE ACTIVE CHAIN IS SEARCHED STARTING WITH
*D*               RAB:FLINK (OLDEST ENTRY).  IF A TIMED-
*D*               OUT ENTRY IS FOUND, IT IS RELEASED VIA T:RAREL
*D*               AND RAPURGE EXITS.
*
RAPURGE  EQU      %
         PUSH     8,R0
         BAL,R0   GETIME            R1 = CURRENT TIME
*
         LI,R7    0
         DISABLE
RPURG10  LB,R7    RAB:FLINK,R7      GET OLDEST ENTRY
         BEZ      RPURGEXIT         DONE IF NO MORE
         LW,R2    R1                CURRENT TIME
         LH,R4    RAH:TIME,R7       TIME READ AHEAD STARTED
         AND,R4   M16
         SW,R2    R4
         BGEZ     %+2
         AI,R2    X'FFFF'           WRAP AROUND
         SLS,R2   5
         LW,R4    FL:AIR
         AND,R4   RA:DA,R7
         BNEZ     RPURG14           BR IF AIR
         LI,R4    RA:ABNTR          READ-AHEAD TIME-OUT BUCKET
         CW,R2    SL:RATOR          COMPARE AGAINST READ-AHEAD
         B        RPURG15
RPURG14  LI,R4    RA:ABNTA          AIR TIME-OUT BUCKET
         CW,R2    SL:AIRTO          COMPARE AGAINST AIR
RPURG15  BL       RPURG10           NOT TIMED OUT
         LW,R2    RA:DA,R7
         BEZ      %+2               IF FREE POOL ENTRY, DON'T COUNT IT
         MTW,1    0,R4              INCR APPROPRIATE BUCKET
*
*  RELEASE TIMED OUT ENTRY
*
         BAL,R10  T:RAREL           RELEASE IT
         SPACE    2
RPURGEXIT EQU     %
         ENABLE
         PULL     8,R0
         B        *R0
         TITLE    '****  SEARCH MI BLOCK  ****'
         SPACE    2
*F*  NAME:         T:RAMISRCH
*F*
*F*  PURPOSE:      START NEXT READ-AHEAD FOR KEYED FILE.
*F*
*F*  DESCRIPTION:  EXIT IF THERE IS ALREADY A READ-AHEAD IN PROGRESS.
*F*                THE CURRENT MASTER INDEX BLOCK IS SEARCHED FOR
*F*                THE NEXT BLOCKED DATA DISC ADDRESS THAT IS DIFFERENT
*F*                FROM THE ONE CURRENTLY IN CORE.  IF ONE IS FOUND,
*F*                AN ATTEMPT IS MADE TO READ IT.  IF ONE IS NOT
*F*                FOUND, AN ATTEMPT IS MADE TO READ THE NEXT MASTER
*F*                INDEX GRANULE.
         SPACE    1
*D*  NAME:        T:RAMISRCH
*D*
*D*  REGISTERS:   R7,R8,R9,R11 VOLATILE
*D*
*D*  CALL:        R0 IS LINK
*D*
*D*  DESCRIPTION: IF A READ-AHEAD IS ALREADY ACTIVE FOR THIS
*D*               DCB, EXIT.  OTHERWISE, SEARCH BUFF2 STARTING
*D*               AT THE CURRENT KEY.  IF A KEY IS FOUND THAT
*D*               HAS A BLOCKED DATA DISC ADDRESS DIFFERENT FROM
*D*               THE DATA DoGRANULE CURRENTLY IN BUFF1, TRY
*D*               TO START A READ-AHEAD FOR IT.  IF NO
*D*               SUCH DATA DISC ADDRESS CAN BE FOUND, TRY TO START
*D*               A READ-AHEAD OF THE FLINK OF THE BUFF2 GRANULE.
*
         SPACE    2
T:RAMISRCH EQU    %
         BAL,R9   RACHK
         PUSH     9,R12
         LI,R14   BUFF2             BUFFER ADDRESS FOR PULLFOUR
         LI,R4    BASCR
         LB,R4    *R6,R4            LENGTH OF KEY
         B        %+2
*
INCRKEY  AI,R3    5                 POSITION TO NEXT KEY
         CH,R3    BUFF2+NAVX
         BGE      CHKFLINK          AT END OF BLOCK
         AW,R3    R4                POINT PAST KEY
         BAL,R0   PULLFOUR          GET DISPL AND SIZE
         INT,R9   R12               SAVE SIZE
         BAL,R0   PULLFOUR          GET DISC ADDRESS
         AI,R12   0
         BEZ      INCRKEY           NOTHING - CHECK NEXT
         CW,R12   BCDA,R6
         BE       INCRKEY           SAME AS CURRENT GRANULE
         CI,R9    BUFSIZ-15
         BGE      INCRKEY           IGNORE UNBLOCKED SEGMENTS
*
MIEXIT   BAL,R0   T:RAINIT          START A READ AHEAD
MIEXIT5  PULL     9,R12
         B        *R0
         SPACE    3
*
*  NO DATA GRANULE TO READ - TRY NEXT MI GRANULE
*
CHKFLINK LW,R12   BUFF2+FLINK
         BEZ      MIEXIT5           NO FLINK
         B        MIEXIT            START READ AHEAD OF FLINK
         TITLE    '****  START READ AHEAD FOR CONSECUTIVE  ****'
         SPACE    2
*F*  NAME:         T:RACONSEC
*F*
*F*  PURPOSE:      START NEXT READ-AHEAD FOR CONSECUTIVE FILE.
*F*
*F*  DESCRIPTION:  EXIT IF THERE IS ALREADY A READ-AHEAD IN PROGRESS.
*F*                IF THERE IS A FLINK TO THE CURRENT GRANULE,
*F*                AN ATTEMPT IS MADE TO READ IT.
         SPACE    1
*D*  NAME:        T:RACONSEC
*D*
*D*  REGISTERS:   R7,R9,R11,R13 VOLATILE
*D*
*D*  CALL:        R0 IS THE LINK
*D*
*D*  DESCRIPTION: EXIT IF THERE IS ALREADY A READ-AHEAD IN PROGRESS
*D*               FOR THIS DCB.  IF THE FLINK IF NON-ZERO, TRY
*D*               TO START A READ-AHEAD OF IT.
*
         SPACE    2
T:RACONSEC EQU    %
         BAL,R9   RACHK
*
         LW,R13   R8
         PUSH     5,R12
         LW,R12   BUFF1+FLINK       PICK UP FLINK
         BEZ      %+2
         BAL,R0   T:RAINIT          INITIATE READ AHEAD
         PULL     5,R12
         LW,R8    R13
         B        *R0
         TITLE    '****  CHECK LEGALITY OF STARTING READ-AHEAD  ****'
         SPACE    2
*  PURPOSE:  CHECK IF IT IS LEGAL TO START A READ AHEAD
*
*  CALL:  BAL,R9  RACHK
*
*  RETURNS *R9 IS LEGAL
*  RETURNS *R0 IF ILLEGAL
*
         SPACE    2
RACHK    LW,R7    S:PNO
         BNEZ     *R0               DO NOTHING IF ON SLAVE
         LW,R7    SL:RAMR
         CW,R7    RA:CURR           CHECK LIMIT AGAINST CURRENT
         BLE      *R0               TOO MANY ALREADY IN PROGRESS
         LI,R7    BARAX
         LB,R7    *R6,R7
         BNEZ     *R0               ONE ALREADY IN PROGRESS
         LI,R11   X'400'
         CW,R11   DIR,R6
         BAZ      *R9               NOT READ REVERSE
         B        *R0               NONE FOR READ REVERSE
         TITLE    '****  RELEASE ENTRY FROM READ AHEAD TABLES  ****'
         SPACE    2
*F*  NAME:         T:RAREL
*F*
*F*  PURPOSE:      RELEASE ENTRY IN READ-AHEAD TABLES.
*F*
*F*  DESCRIPTION:  IF THERE IS I/O OUTSTANDING OR A USER IS WAITING,
*F*                SET THE RELEASE FLAG AND EXIT.  OTHERWISE, DECHAIN
*F*                FROM ACTIVE CHAIN AND EITHER PUT INTO FREE POOL
*F*                (KEEPING THE PHYSICAL BUFFER PAGE), OR RELEASE
*F*                THE BUFFER PAGE TO MONITOR FREE PAGE CHAIN AND
*F*                CHAIN ENTRY ON FREE ENTRY CHAIN.
         SPACE    1
*D*  NAME:        T:RAREL
*D*
*D*  REGISTERS:   R0,R2,R4,R5,R11 VOLATILE
*D*
*D*  CALL:        R10 IS THE LINK
*D*
*D*  INPUT:       R7 = TABLE INDEX
*D*
*D*  DESCRIPTION: IF THERE IS I/O IN PROGRESS OR A USER IS WAITING,
*D*               SET THE REL FLAG TO CAUSE RELEASE LATER.
*D*               OTHERWISE, DECHAIN ENTRY FROM ACTIVE CHAIN.
*D*               ZERO RAB:USER, RAH:TIME AND RA:DA.  IF THE PREVIOUS
*D*               CONTENTS OF RA:DA WAS ZERO, THIS IS A FREE POOL
*D*               ENTRY WITH A PHYSICAL PAGE - CHAIN IT ON TO
*D*               FREE ENTRY CHAIN AND RELEASE THE PAGE.
*D*               IF NON-ZERO, EITHER PLACE ENTRY ON FREE ENTRY
*D*               CHAIN AND RELEASE BUFFER PAGE IF TOO MANY ENTRIES
*D*               ARE ON THE FREE POOL CHAIN, OR KEEP THE PHYSICAL
*D*               PAGE AND PUT ENTRY ON ACTIVE CHAIN WITH CURRENT
*D*               TIME IN RAH:TIME.
*
         SPACE    2
T:RAREL  EQU      %
         DISABLE
         LW,R4    RA:DA,R7          FLAGS
         CW,R4    FL:IW             I/O IN PROGRESS OR USER WAITING
         BAZ      RAREL10           NO - RELEASE IT NOW
         OR,R4    FL:REL            SET RELEASE AT END ACTION FLAG
         STW,R4   RA:DA,R7
         ENABLE
         B        *R10
         SPACE    2
RAREL10  EQU      %
         BAL,R0   RADCHAIN          REMOVE FROM BLINK/FLINK CHAINS
         LI,R0    0
         STB,R0   RAB:USER,R7       CLEAR SOME TABLE ENTRIES
         STH,R0   RAH:TIME,R7
         STH,R0   RAH:DCB,R7
         XW,R0    RA:DA,R7
         BEZ      RAREL15           RELEASING FREE POOL ENTRY
         LI,R4    RA:CURA
         CW,R0    FL:AIR
         BANZ     %+2
         LI,R4    RA:CURR
         MTW,-1   0,R4              DECR # ACTIVE ENTRIES
*
         LW,R4    RA:CURF           # CURRENTLY IN FREE POOL
         BLZ      RAREL20           SOMETHING WRONG
         CW,R4    SL:RAMF           MAX ALLOWED
         BGE      RAREL20           TOO MANY - RELEASE PAGE
         LW,R0    S:STLC
         BLEZ     RAREL20           DON'T ADD IF SWAPPER NEEDS PAGES
         MTW,1    RA:CURF
         MTW,1    RA:PUTF           COUNT # ADDED TO FREE POOL
         BAL,R0   GETIME            GET CURRENT TIME IN R1
         LB,R4    RAB:FLINK         CHAIN ENTRY
         BEZ      %+2               BR IF CHAIN EMPTY
         LH,R1    RAH:TIME,R4       USE TIME OF OLDEST ENTRY
         STB,R4   RAB:FLINK,R7        ONTO OLDEST
         STB,R7   RAB:FLINK           END OF
         STB,R7   RAB:BLINK,R4        BLINK/FLINK
         LI,R4    0                   CHAIN
         STB,R4   RAB:BLINK,R7
         STH,R1   RAH:TIME,R7       CURRENT TIME
         ENABLE
         B        *R10
         SPACE    2
*
*  RELEASE PAGE TO FREE POOL
*
RAREL15  MTW,-1   RA:CURF           DECR # IN FREE POOL
RAREL20  EQU      %
         LB,R4    RAB:USER          CHAIN ENTRY
         STB,R4   RAB:USER,R7         ONTO FREE
         STB,R7   RAB:USER              ENTRY CHAIN
         ENABLE
         PUSH     8,R12
         LOAD,R3  RAX:PAGE,R7       PAGE #
         BEZ      RAREL25           ERROR - NO PAGE
         SLS,R3   9                 WORD ADDRESS
         LI,R2    0
         STORE,R2 RAX:PAGE,R7
         BAL,R11  T:RSPP            RELEASE STOLEN PAGE
RAREL25  PULL     8,R12
         B        *R10
         TITLE    '****  DECHAIN ENTRY FROM ACTIVE CHAIN  ****'
         SPACE    2
*  PURPOSE:  DECHAIN AN ENTRY FROM THE ACTIVE CHAIN
*
*  INPUT:  R7 = TABLE INDEX OF ENTRY TO BE DE-CHAINED
*
*  CALL:  BAL,R0  RADCHAIN
*
*  VOLATILE:  R4,R5
*
         SPACE    2
RADCHAIN EQU      %
         LB,R4    RAB:FLINK,R7
         LB,R5    RAB:BLINK,R7
         STB,R5   RAB:BLINK,R4
         STB,R4   RAB:FLINK,R5
         B        *R0
         TITLE    '****  ADD AIR ENTRY  ****'
         SPACE    2
*F*  NAME:         T:RADD
*F*
*F*  PURPOSE:      ADD A FILE DIRECTORY BUFFER TO READ-AHEAD TABLES.
*F*
*F*  DESCRIPTION:  IF THE FD BUFFER IS UPDATED, A WRITE IS ISSUED.
*F*                A MONITOR FREE PAGE IS OBTAINED, IT IS SWITCHED
*F*                WITH THE USER'S BUFFER PAGE IN HIS CMAP, AND
*F*                A READ-AHEAD TABLE ENTRY IS OBTAINED TO
*F*                POINT TO THE FD BUFFER PAGE.
         SPACE    1
*D*  NAME:        T:RADD
*D*
*D*  REGISTERS:   R12-R14,R2-R4 SAVED
*D*
*D*  CALL:        R0 IS THE LINK
*D*
*D*  INPUT:       R12 = DISC ADDRESS
*D*
*D*  OUTPUT:      CC=0  GRANULE WAS ADDED TO TABLES
*D*                 =1  COULD NOT ADD GRANULE
*D*
*D*  DESCRIPTION: EXIT IF CFU NOT FILCFU OR IF BUFFER DOES NOT CONTAIN
*D*               A VALID DISK GRANULE (WD 0 NOT ZERO OR DISK ADDR).
*D*               SEARCH READ-AHEAD TABLES REMEMBERING OLDEST AIR
*D*               ENTRY.  SCREECH IF FIND THE DISC ADDRESS BEING
*D*               ADDED ALREADY IN THE TABLES.  TRY TO GET A NEW
*D*               TABLE ENTRY, OR IF NONE AVAILABLE TRY TO USE
*D*               THE OLDEST AIR ENTRY CURRENTLY ACTIVE.  IF
*D*               ABLE TO FIND AN ENTRY, INITIALIZE IT FOR THIS
*D*               DISC ADDRESS.  IF BUFFER NOT UPDATED, EXIT.
*D*               OTHERWISE WRITE THE BUFFER TO DISC, SETTING
*D*               I/O IN PROGRESS FLAG FOR THE ENTRY.
*
         SPACE    2
T:RADD   EQU      %
         LI,R1    X'1FFFF'
         AND,R1   CFU,R6
         CI,R1    FILCFU
         BNE      CHKXIT1           CAN'T BE FILE DIRECTORY
         LI,R15   DCBPRIVBIT
         CW,R15   PRIV,R6
         BANZ     CHKXIT1           NO AIR FOR PRIVATE
*
         LW,R15   SL:AIRM           MAX # ALLOWED
         BLEZ     CHKXIT1           NONE - GET OUT NOW
         PUSH     9,R12
         AND,R12  M24
         LW,R8    R12
         BAL,R11  FMCHKDA           VALIDATE DISC ADDRESS
         BCR,15   RACHKCC1          BAD - IGNORE
         LW,R8    BUFF2
         BEZ      %+3
         BAL,R11  FMCHKDA           VALIDATE BUFFER CONTENTS
         BCR,15   RACHKCC1          BAD - BUFFER NEVER READ INTO
****************************************
         BLOCK                      GO TO MASTER CPU
****************************************
         MTW,1    RA:ASTOR          INCR # ATTEMPTED STORES
         LI,R7    0
         LW,R2    FL:AIR
         LI,R5    0
         LW,R13   M24
         OR,R12   FL:AIR
         DISABLE                    **** DISABLE ****
RADD10   LB,R7    RAB:BLINK,R7      GET NEXT ENTRY
         BEZ      RADD20            NO MORE
         LW,R2    RA:DA,R7          GET FLAGS AND DISC ADDR
         CW,R2    FL:AIR            IS THIS ONE AN AIR
         BAZ      RADD10            NO
         CW,R2    FL:IOP            IGNORE ONES WITH I/O
         BANZ     RADD15
         LW,R5    R7
RADD15   CS,R12   RA:DA,R7
         BE       SC2E01            CAN'T ALREADY BE THERE
         B        RADD10
*
RADD20   EQU      %
         ENABLE                     ****  ENABLE  ****
         LW,R2    RA:CURA           CURRENT # INITIATED
         CW,R2    SL:AIRM           MAX # ALLOWED
         BG       RACHKCC1          TOO MANY ALREADY
         BE       RADD30            TRY TO STEAL EXISTING ENTRY
         PUSH     R5                SAVE TABLE ENTRY
         BAL,R11  GETENTRY          GET TABLE ENTRY
         PULL     R5
         AI,R4    0
         BEZ      RADD50            GOT ONE
*
*  NO TABLE ENTRY AVAIL - TRY TO USE EXISTING ONE
*
RADD30   EQU      %
         LW,R7    R5                SAVED ENTRY INDEX
         BEZ      RACHKCC1          NONE - CAN'T DO ANYTHING
         MTW,1    RA:DA             COUNT # AIR ENTRIES OVERWRITTEN
*
         DISABLE                    ****  DISABLE  ****
         BAL,R0   RADCHAIN          DE-CHAIN ENTRY
         BAL,R11  GETEXIT           CHAIN ON AND FILL IN
         B        RADD60
*
RADD50   MTW,1    RA:CURA           INCR # IN PROGRESS
RADD60   MTW,1    RA:SSTOR          INCR # SUCCESSFULLY STORED
         LW,R5    R7                SAVE TABLE INDEX
         LOAD,R3  RAX:PAGE,R7       PAGE #
         SLS,R3   9                 WORD ADDRESS
         BAL,R2   T:XBUF            EXCHANGE USER PAGE
         LW,R7    R5
         SLS,R10  -9
         STORE,R10 RAX:PAGE,R7      USER'S OLD PHYS PAGE ADDR
*
         LW,R3    Y002
         LI,R2    1                 FUNCTION CODE FOR WRITE
         CW,R3    MIUD,R6           IS BUFFER UPDATED
         BAZ      CHKXIT            NO
         STS,R2   MIUD,R6           YES - RESET MIUD
         LW,R12   RA:DA,R7          DISC ADDRESS
         LW,R5    FL:IOP
         STS,R5   RA:DA,R7          SET I/O IN PROGRESS
         LW,R8    DCDAM             DUAL DISC ADDRESS
         BAL,R11  FMCHKDA
         BCR,15   RAIO              BAD
         BAL,R10  GETTBL            GET END-ACTION TABLE
         STB,R3   R7                SAVE ITS INDEX
         B        RAIO
         TITLE    '****  GET TABLE ENTRY  ****'
         SPACE    2
*  PURPOSE:  OBTAIN A TABLE ENTRY
*
*  CALL:  BAL,R11  GETENTRY
*
*  OUTPUT:  R4 = 0  GOT ONE
*              = 1  NO ENTRY AVAILABLE
*              = 2  NO PAGE AVAILABLE
*
         SPACE    2
GETENTRY EQU      %
         DISABLE                    ****  DISABLE  ****
         LW,R2    RA:CURF           # ENTRIES WITH PAGES IN FREE POOL
         BLEZ     GET10             NONE
         MTW,-1   RA:CURF           DECR # IN POOL
         MTW,1    RA:GETF           COUNT # FREE POOL ENTRIES USED
         LI,R7    0
GET05    LB,R7    RAB:FLINK,R7      GET NEXT ENTRY
         BEZ      GET10             DONE - DIDN'T FIND
         LW,R2    RA:DA,R7
         BNEZ     GET05             NOT FREE POOL ENTRY
         BAL,R0   RADCHAIN          DE-CHAIN FROM ACTIVE CHAIN
*
*  FILL IN THIS ENTRY
*
GETEXIT  EQU      %
*
         OR,R12   FL:ACT            SET ACIVE BIT
         STW,R12  RA:DA,R7
*
         LB,R2    RAB:BLINK         CHAIN
         STB,R2   RAB:BLINK,R7        ONTO
         STB,R7   RAB:BLINK           BLINK/FLINK
         LB,R4    RAB:FLINK,R2        CHAIN
         STB,R4   RAB:FLINK,R7
         STB,R7   RAB:FLINK,R2
*
         ENABLE                     ****  ENABLE  ****
*
         LW,R2    S:CUN
         STB,R2   RAB:USER,R7       USER #
*
         BAL,R0   GETIME
         STH,R1   RAH:TIME,R7       CURRENT TIME
*
         LI,R4    0
         B        *R11
         SPACE    2
GET10    EQU      %
         ENABLE                     ****  ENABLE
         PUSH     2,R11
         BAL,R11  T:STLPP           STEAL A PHYSICAL PAGE
         PULL     2,R11
         AI,R3    0
         BGZ      GET15             GOT A PAGE
         LI,R4    RA:ABNCO          NO PAGE AVAILABLE BUCKET
         B        *R11
GET15    DISABLE                    ****  DISABLE  ****
         LB,R7    RAB:USER          LOOK FOR AVAILABLE ENTRIES
         BNEZ     GET20             THERE ARE SOME
         ENABLE                     ****  ENABLE  ****
         PUSH     2,R11
         BAL,R11  T:RSPP            GIVE THE PAGE BACK
         PULL     2,R11
         LI,R4    RA:ABNTB          NO TABLE ENTRIES AVAILABLE
         B        *R11
*
GET20    EQU      %
         SLS,R3   -9
         LB,R2    RAB:USER,R7       DE-CHAIN FROM FREE CHAIN
         STB,R2   RAB:USER
         STORE,R3 RAX:PAGE,R7       PUT IN PAGE
         B        GETEXIT
         SPACE    4
*S*  SCREECH CODE:  2E-01
*S*  MESSAGE:      INCONSISTENCY IN READ-AHEAD TABLES
*S*  REGISTERS:    R12 = DISC ADDRESS
*S*  REMARKS:      AN ATTEMPT WAS MADE TO ADD AN AIR BLOCK TO
*S*                THE TABLES WHEN AN ENTRY FOR THAT BLOCK WAS
*S*                ALREADY PRESENT.
SC2E01   SCREECH  X'2E',X'01'
         END

