*DECK     CSTRND
USETEXT TEXTCS
USETEXT TXTCTCS 
PROC CSTRND (SWTESS); 
# TITLE CSTRND - RECEIVE NCF DATA.                                     #
  
      BEGIN  # CSTRND # 
# 
**    CSTRND - RECEIVE NCF DATA.
* 
*     D. G. DEPEW.           81/09/24.
* 
*     THIS PROCEDURE DEBLOCKS LINE RECORDS FROM THE NCF CIO BUFFER AND
*     COMBINES THEM WITH THE CORRESPONDING NCF READ REQUESTS QUEUE
*     ENTRIES TO CREATE NCF DATA QUEUE ENTRIES. 
* 
*     PROC CSTRND (SWTESS)
* 
*     ENTRY   THE NCF DATA QUEUE MAY CONTAIN EITHER OF THE FOLLOWING: 
*               - ZERO (I.E., IT MAY BE EMPTY) OR MORE COMPLETE ENTRIES.
*               - ZERO OR MORE COMPLETE ENTRIES FOLLOWED BY A PARTIALLY 
*                 COMPLETED ENTRY.  A PARTIALLY COMPLETED ENTRY IS ONE
*                 WHICH AS YET CONTAINS ONLY A PROTION OR ITS LINE
*                 RECORD. 
*             THE NCF READ REQUESTS QUEUE CONTAINS ENTRIES CORRESPONDING
*               TO THOSE LINE RECORDS FOR WHICH DEBLOCKING HAS NOT YET
*               BEGUN.
*             ITEM *RLCOUNT* (IN TXTCTCS) CONTAINS THE NUMBER OF LINE 
*               RECORDS BEING READ BY THE CURRENT READLS FUNCTION (AND
*               THENCE THE NUMBER OF RESULTING NCF DATA QUEUE ENTRIES). 
*             ITEM *RLIORD* (IN TXTCTCS) POINTS TO THE READ LIST INDEX
*               ENTRY CORRESPONDING TO ONE OF THE FOLLOWING:  
*               - THE LINE RECORD CURRENTLY BEING DEBLOCKED IF THE LAST 
*                 ENTRY IN THE NCF DATA QUEUE IS INCOMPLETE.
*               - THE LINE RECORD FOR WHICH DEBLOCKING WILL BEGIN IF THE
*                 LAST ENTRY IN THE NCF DATA QUEUE IS COMPLETE OR THE 
*                 QUEUE IS EMPTY. 
*             DATA IS AVAILABLE IN THE NCF CIO BUFFER.
* 
*     EXIT    LINE RECORD DATA AND/OR NEW ENTRIES HAVE BEEN ADDED TO THE
*               NCF DATA QUEUE AS DESCRIBED BELOW UNDER *METHOD*. 
*             NCF READ REQUESTS QUEUE ENTRIES, CORRESPONDING TO THOSE 
*               NEW ENTRIES (EITHER COMPLETE OR INCOMPLETE) THAT HAVE 
*               BEEN ADDED TO THE NCF DATA QUEUE THIS TIME (IF ANY),
*               HAVE BEEN DELETED.
*             FORMAL RETURN PARAMETER ARRAY SWTESS IS SET AS FOLLOWS: 
*               - IF ALL LINE RECORDS SPECIFIED IN THE CURRENT READLS 
*                 OPERATION HAVE BEEN COMPLETELY PROCESSED, SWTESS IS 
*                 SET SO THAT PROC CSTSNR IS CALLED WHEN AN ENTRY IS
*                 MADE IN THE CONFIGURE TERMINAL REQUEST QUEUE. 
*               - IF ALL LINE RECORDS SPECIFIED IN THE CURRENT READLS 
*                 OPERATION HAVE NOT BEEN PROCESSED AND THE NCF CIO 
*                 BUFFER IS EMPTY, SWTESS IS SET SUCH THAT THIS ROUTINE 
*                 WILL AGAIN BE CALLED WHEN THE FET COMPLETE BIT IS SET 
*                 OR THE IN POINTER DOES NOT EQUAL THE OUT POINTER. 
*             IF WE ARE WAITING FOR DATA TO BE PLACED IN THE BUFFER AND 
*               THE I/O HAS STOPPED, THE READLS FUNCTION IS REISSUED. 
* 
*     METHOD  THIS ROUTINE CONSISTS PRIMARILY OF A LARGE LOOP.  EACH
*             TIME THROUGH THE LOOP ONE OF THE FOLLOWING OCCURS:  
*               - A NEW, SKELETON ENTRY IS ADDED TO THE NCF DATA QUEUE. 
*                 THIS ENTRY CONSISTS OF THE CNF/TE/R SM (FROM THE NCF
*                 READ REQUESTS QUEUE) PLUS THE FIRST TWO WORDS OF THE
*                 LINE RECORD.  (WORD TWO OF A LINE RECORD CONTAINS ITS 
*                 LENGTH, WHICH IS USED TO DETERMINE THE SIZE OF THE
*                 NCF DATA QUEUE ENTRY.)  THE NCF READ REQUESTS QUEUE 
*                 ENTRY IS DELETED. 
*               - LINE RECORD DATA IS ADDED TO AN INCOMPLETE NCF DATA 
*                 QUEUE ENTRY, BUT BECAUSE OF INSUFFICIENT DATA 
*                 AVAILABILITY, THE ENTRY CANNOT BE COMPLETED.
*               - LINE RECORD DATA IS ADDED TO AN INCOMPLETE NCF DATA 
*                 QUEUE ENTRY, COMPLETING IT EXACTLY. 
*             THE LOOP TERMINATES WHEN ALL LINE RECORDS SPECIFIED IN THE
*             READLS FUNCTION HAVE BEEN PROCESSED OR WHEN THE CIO BUFFER
*             IS EMPTY.  THIS ROUTINE CAN STOP AN INDEFINITE NUMBER OF
*             TIMES TO WAIT FOR I/O.
# 
  
*CALL SWTESS
  
# 
****  PROC CSTRND - XREF LIST BEGIN.
# 
      XREF
        BEGIN 
        PROC CSTSNR;         #START NCF READ REQUESTS                  #
        PROC MOVE;           #MOVE STORAGE DIRECT ADDRESSING (MACREL)  #
        PROC READLS;         #ISSUE CIO READLS FUNCTION (MACREL)       #
        PROC READW;          #READ WORDS FROM CIO BUFFER (MACREL)      #
        PROC SSFCBS;         #DETERMINE AVAIL DATA AND SPACE IN BUFFER #
        PROC SSSAWR;         #ACCEPT WORKLIST REQUEST                  #
        PROC SSTATS;         #ALLOCATE STORAGE AT END OF TABLE         #
        PROC SSTRTS;         #REMOVE STORAGE ANYWHERE IN TABLE         #
        END 
# 
****
# 
  
  
      ITEM I;                #LOOP INDUCTION VARIABLE                  #
      ITEM QORD;             #CALCULATED ORD LAST ENTRY OF NCF DATA Q  #
      ITEM RORD;             #NDQ ORD TO RD INTO OR CORRES NRQ NTRY ORD#
      ITEM NEED;             #AMT OF DATA NEEDED TO COMPLETE NDQ ENTRY #
      ITEM AVAIL;            #AMT OF DATA AVAILABLE IN NCF CIO BUFFER  #
      ITEM WC;               #SIZ NEW NDQ NTRY OR AMT FILLED IN SO FAR #
      ITEM SIZ;              #SIZ OF CORRESPONDING NCF READ Q ENTRY    #
      ITEM TEMP;             #FOR UNNEEDED GARBAGE                     #
  
      ARRAY LINEHDR [00:00] S(LRHDRL$);  #LINE RECORD HEADER WSA       #
        ITEM LH$LRLEN   U(01,48,12);  #LINE REC LENGTH EXCLUDING ID WD #
  
  
  
  
  
      IF NDQL NQ 0
      THEN                   # AT LEAST ONE ENTRY IN NDQ (MAY BE INC)  #
        FOR QORD=0  STEP NDQ$ESIZE[QORD]
          WHILE (QORD + NDQ$ESIZE[QORD]) LS NDQL
        DO                   # FIND FIRST WD OF LAST NCF DATA Q ENTRY  #
          BEGIN  END
  
      FOR I=0  WHILE NF$IN[0] NQ NF$OUT[0]
        AND RLIORD LS RLCOUNT 
      DO                     # LOOP UNTIL BUF EMPTY OR ALL LINRECS READ#
        IF NDQL NQ 0
          AND NOT NDQ$CFLAG[QORD] 
  
        THEN                 # NDQ NOT EMPTY AND LAST ENTRY INCOMPLETE #
          BEGIN              # CONTINUE ENTRY IN PROGRESS              #
          WC = NDQ$TCSIZE[QORD] + NDQ$LRSIZE[QORD];  # TOT DATA SO FAR #
          NEED = NDQ$ESIZE[QORD] - WC;
          SSFCBS (NCFFET, TEMP, AVAIL);  # FIND OUT WHAT'S AVAILABLE   #
          IF AVAIL GQ NEED
          THEN               # THE LAST ENTRY CAN BE COMPLETED NOW     #
            BEGIN 
            AVAIL = NEED;    # WILL ADD EXACT AMOUNT TO COMPLETE ENTRY #
            NDQ$CFLAG[QORD] = TRUE;  # SET ENTRY COMPLETE              #
            SSSAWR(CSWDF"CTDNQ") ;       # CONFIGUE OR RE-CONFIGUE TERM#
            RLIORD = RLIORD + 1;  # NEXT READLIST INDEX ENTRY          #
            END 
          RORD = QORD + WC;  # ORD TO WHICH DATA WILL BE READ          #
          READW (NCFFET, NDQ[RORD], AVAIL, TEMP);  # XFER DATA TO NTRY #
          NDQ$LRSIZE[QORD] = NDQ$LRSIZE[QORD] + AVAIL;  # AMT RD SO FAR#
          END 
  
        ELSE                 # NDQ EMPTY OR LAST ENTRY COMPLETE        #
          BEGIN              # CREATE A NEW SKELETON NCF DATA Q ENTRY  #
          QORD = NDQL;       # WHERE NEW NDQ ENTRY WILL BE             #
          FOR RORD=0  STEP NRQ$ESIZE[RORD]
            WHILE NRQ$LRIORD[RORD] NQ RLI$LRIORD [RLIORD] 
          DO                 # FND NRQ NTRY CORRESPONDING TO NXT LINREC#
            BEGIN  END
          READW (NCFFET, LINEHDR, LRHDRL$, TEMP);  # GET NXT LINREC HDR#
          SIZ = NRQ$ESIZE[RORD];
          WC = SIZ + LH$LRLEN[0] + 1;  # TOTAL SIZE NEW NCF DATA Q NTRY#
          SSTATS (P<NDQ>, WC);  # ADD NEW ENTRY SPACE TO NCF DATA Q    #
          MOVE (SIZ, NRQ[RORD], NDQ[QORD]);  # START NEW NDQ ENTRY     #
          SSTRTS (P<NRQ>, RORD, SIZ);  # DELETE NCF READ QUEUE ENTRY   #
          NDQ$CFLAG[QORD] = FALSE;
          NDQ$LRSIZE[QORD] = LRHDRL$;  # AMT OF LINREC IN NTRY SO FAR  #
          NDQ$TCSIZE[QORD] = SIZ;  # CNF/TE/R SIZ SAME AS NRQ NTRY SIZ #
          NDQ$ESIZE[QORD] = WC;  # INITIALIZE WITH FINAL ENTRY SIZE    #
          RORD = QORD + SIZ;  # BEGINNING ORDINAL OF LINE RECORD       #
          MOVE (LRHDRL$, LINEHDR, NDQ[RORD]);  # SKELETON NDQ NTRY DONE#
          END 
  
#     SET UP FORMAL RETURN PARAMETER ARRAY SWTESS.                     #
  
      IF RLIORD EQ RLCOUNT
        AND NF$CBIT[0]
      THEN                   # ALL LINE RECORDS HAVE BEEN DEBLOCKED    #
        BEGIN 
  
#     WE WANT PROC CSTSNR TO BE CALLED WHENEVER AN ENTRY IS PLACED IN  #
#     THE CONFIGURE TERMINAL REQUEST QUEUE (CTQ) AND IF THERE IS       #
#     ALREADY AN ENTRY IN THE CTQ, WE WANT CSTSNR CALLED IMMEDIATELY.  #
#     AT THIS POINT, HOWEVER, THE INTERRUPT CELL FOR PROC CSTSNR (ITEM #
#     *ICSTSNR* - WATCHED BY THE STATUS WORKLIST ENTRY PROCESSOR AND   #
#     INCREMENTED WHENEVER AN ENTRY IS PLACED IN THE CTQ) HAS SOME NON-#
#     ZERO VALUE THAT MAY OR MAY NOT ACCURATELY REFLECT THE PRESENSE   #
#     OF AN ENTRY IN THE CTQ (*ICSTSNR* MAY BE NON-ZERO SOLELY AS A    #
#     RESULT OF PREVIOUS ENTRIES THAT HAVE ALL BEEN PROCESSED).  IF WE #
#     SIMPLY CLEAR *ICSTSNR*, RECOLLECTION OF ANY ENTRIES THAT MIGHT   #
#     ALREADY BE IN THE CTQ WILL BE LOST AND THEY WONT GET PROCESSED   #
#     UNTIL ANOTHER ENTRY IS PLACED IN THE CTQ (COULD BE A LONG TIME). #
#     WHAT WE WANT TO DO IS SET *ICSTSNR* TO ZERO IF THE CTQ IS EMPTY, #
#     OR SET IT NON-ZERO (ACTUAL VALUE OF NO CONSEQUENCE) IF THERE IS  #
#     AT LEAST ONE ENTRY IN THE CTQ.  HENCE, THE FOLLOWING CODE LINE.  #
  
        ICSTSNR = CTQL;      # REFLECTS PRESENSE OF CNF/TE/R Q ENTRIES #
        STE$ADDR1[0] = LOC (ICSTSNR);  # WATCH INTERRUPT CELL          #
        STE$ADDR2[0] = 0;    # WATCH ONE CELL ONLY                     #
        STE$RTN[0] = LOC (CSTSNR);  # PROCESSOR OF CNF/TE/R QUEUE      #
        STE$INIT1[0] = 0;    # CALL WHEN NONZERO ENTRIES IN CNF/TE/R Q #
        STE$INIT2[0] = 0; 
        END 
      ELSE                   # WE MUST WAIT FOR I/O                    #
        BEGIN 
        STE$ADDR1[0] = LOC (NCFFET);  # WATCH FIRST WORD OF NCF FET    #
        STE$ADDR2[0] = LOC (NF$IN[0]);  # WATCH FET IN POINTER         #
        STE$RTN[0] = LOC (CSTRND);  # RECALL THIS ROUTINE              #
        STE$INIT1[0] = NF$WORD[0];  # SET UP INIT VALUE OF FET 1ST WD  #
        STE$CBIT1[0] = FALSE;  # RECALL WHEN FET COMP BIT IS SET       #
        STE$INIT2[0] = NF$OUT[0];  # RECALL WHEN *IN* NQ *OUT*         #
        IF NF$CBIT[0] 
        THEN                 # I/O HAS STOPPED                         #
          READLS (NCFFET);   # RESTART CURRENT READLS OPERATION        #
        END 
  
      END  # CSTRND # 
  
      TERM
