*DECK NVFCTRM 
USETEXT TEXTNVF 
USETEXT TEXTSS
USETEXT TXSMNVF 
USETEXT TXTANVF 
USETEXT TXTAPSS 
PROC NVFCTRM(NORMTRM, SENT);
      BEGIN # NVFCTRM # 
# 
**    NVFCTRM - PROCESS CR/TRM SUPERVISORY MESSAGE (FROM NVF TO NIP)
* 
*     P. A. MURRAY       84/09/24 
* 
*     THIS PROCEDURE PERFORMS ALL THE CONNECTION (C) LAYER PROCESSING 
*     REQUIRED FOR THE CR/TRM SUPERVISORY MESSAGE.
* 
*     PROC NVFCTRM (NORMTRM, SENT)
* 
*     ENTRY 
*       NORMTRM = TRUE IF THIS IS A NORMAL CR/TRM (FROM THE C-LAYER), 
*               = FALSE IF THIS IS A SPECIAL CR/TRM (FROM INNER LAYER). 
*       THE CR/TRM SM IS IN MSGBUF[0] AND THE WORD COUNT AND BLOCK
*       HEADER WORDS ARE IN WCBUF[0] AND ABHBUF[0] RESPECTIVELY.
* 
*     EXIT
*       SENT = TRUE IF THE CR/TRM WAS SENT TO THE <OTQ> OR <WBQ>, 
*       SENT = FALSE IF THE CR/TRM COULD NOT BE SENT BECAUSE THE ACN
*              ENTRY DOES NOT EXIST OR BECAUSE THE CR/SWH HAS ALREADY 
*              BEEN SENT.  (THIS PARAMETER IS OF INTEREST ONLY TO THE 
*              INNER LAYER -- SEE THE "NOTES" SECTION BELOW.) 
* 
*       ALSO, ANY OF THE FOLLOWING IN VARIOUS COMBINATIONS ACCORDING
*       TO THE STATE OF THE ACN ENTRY FOR THE USER IN QUESTION: 
*       - THE STATE OF THE ACN ENTRY HAS BEEN UPDATED.
*       - AN ENTRY FOR THE CR/TRM SM HAS BEEN PLACED IN THE OUTGOING
*         TRAFFIC QUEUE (*OTQ*).
*       - IF THE CONNECTION HAS NOT YET BEEN INITIALIZED (NO FC/INIT
*         RECEIVED) OR UNACKNOWLEDGED SYNCHRONOUS BLOCKS ARE OUTSTANDING
*         FOR THE CONNECTION, AN ENTRY FOR THE SM HAS BEEN MADE IN THE
*         WAITING BLOCK QUEUE (*WBQ*).  (THE SM WILL BE ISSUED WHEN THE 
*         CONNECTION HAS BEEN INITIALIZED AND ALL BLOCKS ARE
*         ACKNOWLEDGED.)
* 
*     NOTES 
*       1.  THIS ROUTINE MAY BE CALLED BY THE C-LAYER OR BY THE INNER 
*           LAYER.  IT IS CALLED BY THE C-LAYER IF THE CR/TRM IS A
*           RESULT OF A CR/RCN OR CR/CB (NORMAL CR/TRM).  IT IS CALLED
*           BY THE INNER LAYER IF THE CR/TRM IS THE RESULT OF A 
*           NET/OFF OR FAI/APP (SPECIAL CR/TRM).  THE REASON FOR THIS IS
*           TO PREVENT A (SPECIAL) CR/TRM FROM BEING ISSUED FROM THE
*           INNER LAYER AFTER A CR/SWH HAS BEEN SENT TO NIP BY THE
*           C-LAYER (SINCE AFTER THE CR/SWH HAS BEEN SENT, NVF DOES NOT 
*           REALLY HAVE THE CONNECTION ANY MORE). 
*           NOW, WHEN THE INNER LAYER NEEDS TO ISSUE A "SPECIAL" CR/TRM,
*           IT CAN SEND IT TO NIP AND DELETE THE PAAC ENTRY AT THE SAME 
*           TIME, INSTEAD OF DELETING THE PAAC ENTRY AND HOPING THE 
*           CR/TRM GETS SENT TO NIP BEFORE A CR/SWH GETS SENT.
*       2.  THE PROCESSING FOR THE CR/TRM IS DEFINED BY THE NVF 
*           C-LAYER STATE DIAGRAMS. 
# 
  
  
# 
****  PROC NVFCTRM - XREF LIST. 
# 
      XREF
        BEGIN 
        PROC NVFCFCE;        # FIND CONNECTION ENTRY                   #
        PROC SSCATR;         # ACCEPT TIMER REQUEST                    #
        PROC SSTAQE;         # ACCEPT QUEUE ENTRY                      #
        PROC SSTRTS;         # REMOVE TABLE SPACE                      #
        END 
  
# 
****
# 
      ITEM ACNN       I;     # ACN FROM ENTRY WE ARE LOOKING FOR       #
      ITEM AE         I;     # ORD OF NEW ACN ENTRY                    #
      ITEM I          I;     # LOOP INDUCTION VARIABLE                 #
      ITEM NEWACN     B;     # TRUE IF ACN NOT FOUND IN ACN LIST       #
      ITEM NORMTRM    B;     # TRUE IF SM FROM C-LAYER, NOT INNER LAYER#
      ITEM RORD       I;     # ORDINAL OF WBQ ENTRY                    #
      ITEM SENT       B;     # TRUE IF CR/TRM CAN BE SENT TO NIP       #
      ITEM SIZ        I;     # WBQ ENTRY SIZE                          #
  
# 
**    TRBBUF - TIMER REQUEST BUFFER.
* 
*     BUFFER CONTAINING TIMER INFORMATION.  BUFFER IS SET UP TO CONTAIN 
*     FC/INACT SM WHICH IS TO BE RETURNED TO THE *CTQ* QUEUE SHOULD THE 
*     TIMER EXPIRE. 
# 
      DEF TRBSIZ$ # 4 #;     # WORD SIZE OF TIMER REQUEST BUFFER       #
      ARRAY TRBBUF [00:00] S(TRBSIZ$);
        BEGIN 
        ITEM TRB$SMID   S:CTQSTAT(00,00,12) = [S"SINA"];  # INTERNAL ID#
        ITEM TRB$WC     U(00,48,12) = [TRBSIZ$]; # ENTRY SIZE          #
        ITEM TRB$ABT    U(01,00,06) = [APPCMD];  # APPL BLOCK TYPE     #
        ITEM TRB$CNUM   U(01,18,18);   # CANCELLATION NUMBER           #
        ITEM TRB$PFCSFC U(02,00,16) = [FCINA];   # FC/INACT PFCSFC     #
        ITEM TRB$ACN    U(02,24,12);   # APPLICATION CONNECTION NUMBER #
        ITEM TRB$DELAY  U(03,24,18) = [90];      # DELAY TIME IN SEC   #
        ITEM TRB$QNUM   U(03,42,18);   # Q NUM FOR TIMER EXPIRED MSG   #
        END 
  
      CONTROL EJECT;
# 
*     **** PROC NVFCTRM ENTRY START *** 
# 
  
# 
*     INITIALIZE "SENT" TO TRUE.  GET THE ACN FROM THE CR/TRM SM. 
# 
      SENT = TRUE;
      ACNN = CRACN[0];
# 
*     LOCATE THE ACN LIST ENTRY FOR THE ACN SPECIFIED IN THE CR/TRM.
*     IF NO ACN ENTRY WAS FOUND, SET THE "SENT" FLAG TO FALSE, AS THE 
*     CR/TRM CANNOT BE SENT, AND RETURN.
# 
      IF ACNN NQ 0
      THEN
        BEGIN 
        NVFCFCE (ACNN, AE, NEWACN); 
        IF NEWACN 
        THEN
          BEGIN 
          SENT = FALSE; 
          GOTO ENDTAS;
          END 
        END 
# 
*     IF THIS IS A SPECIAL CR/TRM (FROM THE INNER LAYER), AND IF THE
*     CR/SWH FOR THIS CONNECTION HAS ALREADY BEEN SENT OUT, NIP MAY HAVE
*     ALREADY CLEANED UP ITS CONNECTION AND SENT A CR/SWH/N.  SET THE 
*     "SENT" FLAG TO FALSE, AS THE CR/TRM CANNOT BE SENT, AND RETURN. 
# 
      IF NOT NORMTRM
        AND ACN$STATE[AE] EQ ACNST"SWSTART" 
      THEN
        BEGIN 
        SENT = FALSE; 
        GOTO ENDTAS;
        END 
# 
*     WE HAVE A VALID ACN, SO THE CR/TRM CAN BE SENT TO NIP.  DETERMINE 
*     WHETHER IT GOES DIRECTLY TO THE *OTQ* OR GETS QUEUED IN THE *WBQ*.
# 
      IF ACN$STATE[AE] EQ ACNST"ACTIVE" 
        OR ACN$STATE[AE] EQ ACNST"CLEARI" 
        OR ACN$STATE[AE] EQ ACNST"BRKCMD" 
      THEN
        BEGIN 
        IF ACN$INIT[AE] 
          AND ACN$BLCNT[AE] EQ 0
        THEN
          BEGIN 
          SSTAQE( P<OTQ>, WCBUF, ABHBUF, MSGBUF );
          ACN$STATE[AE] = ACNST"ENDED"; 
          END 
        ELSE
          BEGIN 
# 
*         THE CR/TRM MUST BE QUEUED.  START TIMER FOR THE CONNECTION. 
*         SET STATE TO TERMINATION PENDING. 
# 
          SSTAQE(P<WBQ>, WCBUF, ABHBUF, MSGBUF);
          TRB$ACN = ACNN; 
          TRB$QNUM = LOC(P<CTQ>); 
          SSCATR(TRBBUF); 
          ACN$CNUM[AE] = TRB$CNUM;
          ACN$STATE[AE] = ACNST"TRMPEND"; 
          END 
        END 
      ELSE
        BEGIN 
# 
*       SEND CR/TRM IF ONE IS NOT PENDING OR HAS NOT ALREADY BEEN SENT. 
# 
        IF ACN$STATE[AE] NQ ACNST"TRMPEND"
          AND ACN$STATE[AE] NQ ACNST"ENDED" 
        THEN
          BEGIN 
          SSTAQE(P<OTQ>, WCBUF, ABHBUF, MSGBUF);
          IF ACN$STATE[AE] EQ ACNST"SWTPEND"
          THEN
            BEGIN 
# 
*           FIND AND DELETE CR/SWH SM.
# 
            FOR RORD = 0 STEP WBQ$ESIZE[RORD] WHILE 
             (WBQ$ABHACN[RORD] NQ 0 OR WBQ$CRSACN[RORD] NQ ACNN)
              AND (RORD LS WBQLNGTH)
            DO
              BEGIN 
              END 
            IF RORD LS WBQLNGTH         # CR/SWH FOUND IN WBQ          #
            THEN
              BEGIN 
              SIZ = WBQ$ESIZE[RORD];
              SSTRTS(P<WBQ>, RORD, SIZ);
              ACN$WBCNT[AE] = 0;
              END 
            END 
          ACN$STATE[AE] = ACNST"ENDED"; 
          END 
        END 
# 
*     IF A BLK BLOCK IS WAITING IN THE <IWBQ>, DELETE IT. 
# 
      IF ACN$BLKF[AE] 
      THEN
        BEGIN 
        ACN$BLKF[AE] = FALSE; 
        FOR RORD = 0 STEP IWQ$WC[RORD] WHILE
          IWQ$ACN[RORD+1] NQ ACNN 
        DO
          BEGIN 
          END 
  
        SSTRTS(P<IWBQ>, RORD, IWQ$WC[RORD]);
        END 
  
 ENDTAS:  
  
      END # NVFCTRM # 
      TERM
