*DECK     NVFVDCD 
USETEXT  TEXTNVF
USETEXT  TXVCBNV
  
PROC NVFVDCD(SWTESS); 
# TITLE NVFVDCD - DISPATCH CIO DATA.   #
  
      BEGIN    # NVFVDCD #
# 
**    NVFVDCD - DISPATCH VCB DATA FROM CIO BUFFER.
* 
*     A. LIM.    81/11/20.
* 
*     THIS PROCEDURE DISPATCHES VCB DATA FROM CIO BUFFER TO THE 
*     APPROPRIATE QUEUE, OR CALL THE APPROPRIATE ROUTINE TO 
*     PROCESS IT. 
* 
*     PROC NVFVDCD(SWTESS)
* 
*     ENTRY   *AVRT* (ACTIVE-VCB-REQUEST-TABLE) CONTAINS THE ACTIVE 
*               VCB READ REQUESTS READ BY THE CURRENT READLS FUNCTION.
*               *AVCOUNT* CONTAINS THE NUMBER OF ENTRIES IN AVRT. 
*             *READLIST* IS THE ACTUAL READ LIST USED BY THE CIO
*               READLS FUNCTION.  *RLCOUNT* CONTAINS THE NUMBER OF
*               ENTRIES IN READLIST.
*             *AVRT*, *AVCOUNT*, *READLIST*, *RLCOUNT* ARE IN 
*               COMMON BLOCK *VCBIO* IN *TXVCBNV*.
*             *VWT* (IN TEXTNVF) CONTAINS THE VCB WRITE REQUESTS. 
*             DATA IS AVAILABLE IN THE VCB CIO BUFFER.
* 
*     EXIT    VCB DATA FROM THE VCB CIO BUFFER ARE DISPATCHED TO
*               THE APPROPRIATE QUEUE, OR THE APPROPRIATE ROUTINE 
*               IS CALLED TO PROCESS THE DATA.
*             FORMAL RETURN PARAMETER ARRAY SWTESS IS SET AS FOLLOWS: 
*               - IF ALL VCB RECORDS SPECIFIED IN THE CURRENT READLS
*                 OPERATION HAVE BEEN PROCESSED, AND
*                 *VWBT* (VCB-WRITE-BLOCK-TABLE) NOT EMPTY, SWTESS IS 
*                 SET SO THAT PROC NVFVWVF IS CALLED TO WRITE THE 
*                 RECORD BACK TO DISK.  ELSE IF *VWBT* EMPTY, SET 
*                 SWTESS TO GO BACK TO THE INITIAL STATE, I.E.
*                 CALL PROC NVFVRVF TO READ THE VCB FILE AGAIN. 
*               - IF CIO READLS NOT COMPLETE, AND CIO IDLE, REISSUE 
*                 READLS FUNCTION.
*                 EITHER CIO READLS NOT COMPLETE AND CIO IDLE, OR 
*                 JUST CIO READLS NOT COMPLETE, SET SWTESS SUCH 
*                 THAT THIS ROUTINE WILL AGAIN BE CALLED WHEN THE 
*                 FET COMPLET BIT IS SET OR THE IN POINTER
*                 DOES NOT EQUAL TO THE OUT POINTER.
* 
*     METHOD  THIS ROUTINE CONSISTS PRIMARILY OF A LARGE LOOP.  EACH
*               TIME THROUGH THE LOOP, A REQUEST IN THE AVRT WILL BE
*               PROCESSED.
*             THE LOOP TERMINATES WHEN ALL ENTRIES IN THE AVRT HAVE 
*               BEEN PROCESSED OR WHEN THE CIO BUFFER IS EMPTY. 
# 
  
  
  
  
  
*CALL SWTESS
  
# 
****  PROC NVFVDCD - XREF LIST BEGIN. 
# 
      XREF
        BEGIN 
        PROC ABORT;          # MACREL- ABORT TASK                      #
        PROC MESSAGE;        # MACREL- DAYFILE MESSAGE                 #
        PROC MOVE;           # MACREL - MOVE CM WORDS                  #
        PROC NVFUMVD;        # NVF - MARK VCB DATA VALID/INVALID       #
        PROC NVFVFSD;        # NVF - FILTER SS DATA BLOCK              #
        PROC NVFVRVF;        # NVF - READ VCB FILE                     #
        PROC NVFVWVF;        # NVF - WRITE VCB FILE                    #
        PROC READLS;         # MACREL - CIO READLS FUNCTION CALL       #
        PROC READW;          # MACREL - CIO READW FUNCTION CALL        #
        PROC SSTAQE;         # SS - ACCEPT QUEUE ENTRY                 #
        PROC SSTATS;         # SS - ALLOCATE STORAGE AT END OF TABLE   #
        PROC SSTRTS;         # SS - REMOVE TABLE SPACE                 #
        END 
# 
****
# 
  
#     ITEM      # 
  
      ITEM AINDX I = 0;      # AVRT INDEX, PRESET TO 0                 #
      ITEM CURBLK I = -1;              # CURRENT DATA BLOCK            #
      ITEM I,II,J,L   I;     # INDUCTION VARIABLES                     #
      ITEM K          I;     # INDEX                                   #
      ITEM MATCHE     B;     # FLAG FOR MATCH ON ENTRY                 #
      ITEM P          I;     # ACTUAL PARAMETER FOR SSTRTS             #
      ITEM TEMP       I;     # FOR UNNEEDED GARBAGE                    #
      ITEM VWTFLAG    B;     # FLAG FOR TERMINATING VWT SEARCH LOOP    #
      ITEM WRSAMBLK   B;     # FLAG FOR WRITTING ON SAME BLOCK         #
  
  
# 
**    DUMMY - DUMMY BASED ARRAY.
* 
*     DUMMY IS A BASED ARRAY USED TO STORE AN ADDRESS INTO THE
*     PARAMETER LIST. 
# 
  
      BASED ARRAY DUMMY[00:00] S(1);; 
  
  
# 
**    WCWD - WORD COUNT ARRAY.
* 
*     WCWD ARRAY IS THE FIRST PORTION OF A MANAGED QUEUE ENTRY.  IT 
*     CONTAINS THE WORD COUNT OF QUEUE ENTRY SIZE + 2 WORDS.
*     (ITSELF AND HEADER WORD). 
# 
      ARRAY WCWD[00:00] S(1); 
        BEGIN 
        ITEM WC$WORD    U(00,00,60);   # FULL WORD REFERENCE           #
        ITEM WC$WC      U(00,48,12);   # ENTRY SIZE                    #
        END 
  
  
# 
**    HDR - HEADER ARRAY. 
* 
*     HDR ARRAY IS THE SECOND PORTION OF A MANAGED QUEUE ENTRY.  IT 
*     CONTAINS THE HEADER INFORMATION OF THE ENTRY. 
# 
      ARRAY HDR[00:00] S(1);
        BEGIN 
        ITEM HDR$WORD   U(00,00,60);   # FULL WORD REFERENCE           #
        END 
  
# 
*     TEMPB- THIS IS A TEMPBORARY BUFFER TO GET THE CONTENT OF
*           AN ADDRESS. 
# 
  
      BASED ARRAY TEMPB[00:00] S(1);
        BEGIN 
        ITEM TEM$LA     U(00,42,18);   # LIST ADDRESS FOR CIO READLS   #
        END 
  
  
# 
*     RDLSMSG- DAYFILE MESSAGE. 
# 
  
      ARRAY RDLSMSG[00:00] S(4);
        BEGIN 
        ITEM RDL$MSG     C(00,00,31) =
                         [" NVFVDCD- ERRONEOUS READLS CALL"]; 
        ITEM RDL$ZERO    U(03,06,54) = [0]; 
        END 
  
  
      CONTROL EJECT;
  
      P<TEMPB> = VB$LA[0];
      FOR I = AINDX STEP 1 WHILE     ((VB$IN[0] NQ VB$OUT[0]) OR
                                       (AVR$RPA[I] EQ CURBLK))
                                  AND (I LS AVCOUNT)
      DO                     # LOOP AS LONG AS BUFFER HAS DATA OR READ #
        BEGIN                # ON CURRENT BLOCK AND AVRT NOT EXHAUSTED #
        IF AVR$RPA[I] NQ CURBLK 
        THEN
          BEGIN              # TIME TO TRFR A NEW BLK OF DATA INTO WSA #
          READW(VCBFET,VCBWSA,VBRECD$,TEMP);
          CURBLK = VBW$RPA[1];         # SAVE THE CURRENT BLK NUMBER   #
          END 
        IF AVR$RPA[I] EQ VBW$RPA[1] 
        THEN
          BEGIN              # AVRT RPA MATCH VCBWSA RPA               #
          IF AVR$TYPE[I] NQ MARKED$ 
          THEN
            BEGIN            # A REQUEST THAT HAS NOT BEEN PROCESSED   #
            IF AVR$TYPE[I] EQ RDWRITE$
            THEN
              BEGIN             # READ FOR A WRITE                     #
              WRSAMBLK = TRUE;  # MIGHT BE OTHER WRITE ON SAME BLK     #
              FOR II = I STEP 1 WHILE II LS AVCOUNT 
                AND WRSAMBLK
              DO               # LOOP UNTIL AVRT EXHSTD OR NOT SAME BLK#
                BEGIN 
                IF AVR$TYPE[II] EQ RDWRITE$ 
                THEN
                  BEGIN 
                  IF AVR$RPA[II] EQ VBW$RPA[1]
                  THEN
                    BEGIN  # WRITE ON SAME BLK MERGE DATA FR VWT TO WSA#
                    IF VWTLNGTH NQ 0
                    THEN
                      BEGIN 
                      VWTFLAG = FALSE;
                      FOR J = 0 STEP 1 WHILE J LS VWTLNGTH/VBESIZ$
                        AND NOT VWTFLAG 
                      DO
                        BEGIN 
                        IF AVR$ORD[II] EQ VWT$ORD[J]
                        THEN
                          BEGIN                 # MATCH ON VCB ORD     #
                          MOVE(VBESIZ$,VWT[J],VCBWSA[AVR$ENTRY[II]]); 
                          P = J * VBESIZ$;
                          SSTRTS(P<VWT>,P,VBESIZ$); # REMOVE SPS FR VWT#
                          NVFUMVD(AVR$ORD[II],VALID$); # MRK DATA VALID#
                          AVR$TYPE[II] = MARKED$;  # MARK NTRY AS PROCD#
                          VWTFLAG = TRUE;          # TERMINATE LOOP    #
                          END 
                        END 
                      $BEGIN
                      IF NOT VWTFLAG THEN ABORT;
                      $END
                      END 
                    ELSE
                      BEGIN 
                      $BEGIN       # VWT EMPTY                         #
                      ABORT;
                      $END
                      END 
                    END 
                  ELSE
                    BEGIN 
                    WRSAMBLK = FALSE; 
                    END 
                  END 
                END 
              SSTATS(P<VWBT>,VBRECD$);       # ALLOC SPS AT END OF VWBT#
              K = VWBLNGTH/VBRECD$ - 1;      # CALCULATE INDEX         #
              MOVE(VBRECD$,VCBWSA,VWBT[K]);     #MOV BLK FR WSA TO VWBT#
              END                               # READ FOR A WRITE     #
            ELSE IF AVR$TYPE[I] EQ RDSS$
            THEN
              BEGIN                    # READ FOR SERIAL SEARCH        #
              NVFVFSD;                 # CALL PROC TO PROCESS THE BLK  #
              END 
            ELSE IF AVR$TYPE[I] EQ RDREAD$
            THEN
              BEGIN                    # READ FOR READING OF AN ENTRY  #
              MATCHE = FALSE;          # INIT FLAG                     #
              FOR L = 1 STEP 1 WHILE L LQ VBMXENTRY$
                AND NOT MATCHE
              DO
                BEGIN                  # SEARCH WSA FOR THE ENTRY      #
                IF AVR$ENTRY[I] EQ VBW$ENTRY[L] 
                THEN
                  BEGIN                # FOUND                         #
                  WC$WC[0] = VBESIZ$ + 2; 
                  HDR$WORD[0] = AVR$WORD[I];  # PUT AVRT ENTRY IN HDR  #
                  P<DUMMY>  = AVR$QADDR[I];   # GET DESTINATION Q ADDR #
                  SSTAQE(DUMMY,WCWD,HDR,VCBWSA[L]);  # TRFR ENTRY TO Q #
                  NVFUMVD(AVR$ORD[I],INVALID$); # MARK DATA INVALID    #
                  MATCHE = TRUE;
                  END 
                END 
              $BEGIN         # CANNOT FIND THE ENTRY, IMPOSSIBLE...    #
              IF NOT MATCHE THEN ABORT; 
              $END
              END            # READ FOR READING OF AN ENTRY            #
            END              # AVRT READ TYPE NOT MARKED               #
          END                # AVRT RPA MATCH VCBWSA RPA               #
        END                  # FOR I LOOP                              #
      AINDX = I;             # SET AVRT INDEX                          #
  
# 
*     SET UP FORMAL RETURN PARAMETER ARRAY SWTESS.
# 
  
      IF AINDX EQ AVCOUNT 
      THEN
        BEGIN                # AVRT EXHAUSTED, IMPLIES CIO READLS COMPL#
        AINDX = 0;           # RESET AVRT INDEX                        #
        CURBLK = -1;                   # RESET CURRENT BLOCK           #
        IF VWBLNGTH NQ 0
        THEN
          BEGIN                         # VWBT NOT EMPTY               #
          STE$ADDR1[0] = LOC(VCBFET);  # WATCH FET COMPLETE BIT        #
          STE$ADDR2[0] = 0;             #   AND WATCH ONE LOCATION ONLY#
          STE$RTN[0] = LOC(NVFVWVF);    # WAKE UP PROC *NVFVWVF*       #
          STE$INIT1[0] = VB$WORD[0];
          STE$CBIT1[0] = FALSE; 
          STE$INIT2[0] = 0; 
          END 
        ELSE
          #GO BACK TO INITIAL STATE: READ VCB FILE WHEN VRQ NON-EMPTY  #
          BEGIN 
          STE$ADDR1[0] = LOC(INVVRVF);  # WATCH INTERRUPT CELL FOR VRQ #
          STE$ADDR2[0] = 0; 
          STE$RTN[0] = LOC(NVFVRVF);
          STE$INIT1[0] = 0; 
          STE$INIT2[0] = 0; 
          IF NOT VB$CBIT[0] 
          THEN
            BEGIN 
            STE$ADDR1[0] = LOC(VCBFET); 
            STE$ADDR2[0] = 0; 
            STE$RTN[0] = LOC(NVFVRVF);
            STE$INIT1[0] = VB$WORD[0];
            STE$CBIT1[0] = FALSE; 
            STE$INIT2[0] = 0; 
            END 
          END 
        END 
      ELSE
        BEGIN                # CIO READLS INCOMPLETE                   #
        IF VB$CBIT[0] 
        THEN
          BEGIN              # CIO IDLE                                #
          IF TEM$LA[0] EQ 0 
          THEN
            BEGIN            # READLS LA IS SET TO TERMINATOR WORD     #
            MESSAGE(RDLSMSG[0], 0); 
            ABORT;
            END 
          ELSE
            BEGIN 
            READLS(VCBFET);            # REISSUE READLS REQUEST        #
            END 
          END 
        STE$ADDR1[0] = LOC(VCBFET);    # WATCH COMPLETE BIT IN FET+0   #
        STE$ADDR2[0] = LOC(VB$IN[0]);  #   AND WATCH FET *IN* POINTER  #
        STE$RTN[0] = LOC(NVFVDCD);     # WAKE UP *NVFVDCD* WHEN ONE CHG#
        STE$INIT1[0] = VB$WORD[0];     # SET UP INIT VALUE OF FET + 0  #
        STE$CBIT1[0] = FALSE;        # WAKE SELF UP AGAIN WHEN CBIT ST# 
        STE$INIT2[0] = VB$OUT[0]; 
        END 
  
      END  # NVFVDCD #
 TERM 
