*DECK NVFCUFS
USETEXT TEXTSS
USETEXT TXTSUSS
USETEXT TXTAPSS
USETEXT TXTANVF
USETEXT TEXTNVF
USETEXT TXINNVF
PROC NVFCUFS;
# TITLE NVFCUFS - UPDATE FLOW STATUS. #
BEGIN # NVFCUFS #
#
** NVFCUFS - UPDATE FLOW STATUS.
*
* S. H. FISCHER. 81/11/06.
* D. G. DEPEW. 81/12/22.
*
* THIS PROCEDURE PERFORMS ALL THE CONNECTION(C) LAYER PROCESSING
* REQUIRED FOR ALL INBOUND, FLOW CONTROL SUPERVISORY MESSAGES.
*
* PROC NVFCUFS
*
* ENTRY WCBUF[0] = WORD COUNT WORD FROM ORIGINAL CONNECTION
* TRAFFIC QUEUE (*CTQ*) ENTRY.
* ABHBUF[0] = APPLICATION BLOCK HEADER FOR THE SM (BASED
* ARRAY *ABH* IN *TXTAPSS* POINTS HERE).
* MSGBUF[0] = BODY OF THE SM (BASED ARRAY *APSM* IN
* *TXTAPSS* POINTS HERE). THE POSSIBLE PFC/SFC
* VALUES ARE: FC/INIT/R, FC/ACK, FC/NAK,
* FC/BRK, INTR/USR, AND FC/INACT.
*
* EXIT ANY OF THE FOLLOWING IN VARIOUS COMBINATIONS ACCORDING TO
* THE SM RECEIVED AND THE STATE OF THE ACN LIST ENTRY FOR
* THE USER IN QUESTION.
* - THE STATE OF THE ACN LIST ENTRY HAS BEEN UPDATED.
* - AN FC/INIT/N SM HAS BEEN PLACED IN THE OUTGOING TRAFFIC
* QUEUE (*OTQ*).
* - AN FS/RST SM HAS BEEN PLACED IN THE OUTGOING TRAFFIC
* QUEUE (*OTQ*).
* - ONE OR MORE ENTRIES IN THE WAITING BLOCK QUEUE (*WBQ*)
* FOR THE USER IN QUESTION HAVE BEEN TRANSFERRED TO THE
* OUTGOING TRAFFIC QUEUE (*OTQ*)
* - A CR/SWH/R OR CR/TRM/R SM ENQUEUED (IN THE *WBQ*) FOR
* THE USER IN QUESTION HAS BEEN TRANSFERRED TO THE
* OUTGOING TRAFFIC QUEUE (*OTQ*).
* - ALL OUTPUT ENQUEUED (IN THE *WBQ*) FOR THE USER IN
* QUESTION HAS BEEN DISCARDED.
* - AN INTR/USR ENTRY HAS BEEN PLACED IN THE TERMINAL-TO-
* APPLICATION CONNECTION INPUT QUEUE (*TAINPQ*).
* - THE SM HAS BEEN DISCARDED.
*
* NOTE THE PROCESSING IS DEFINED BY THE NVF/USER C-LAYER STATE
* DIAGRAM.
#
#
**** PROC NVFCUFS - XREF LIST.
#
XREF
BEGIN
PROC ABORT; # ABORT PROGRAM #
PROC NVFCFCE; # FIND CONNECTION ENTRY #
PROC MOVE; # MOVE BLOCK OF MEMORY #
PROC SSCCTR; # CANCEL TIMER REQUEST #
PROC SSSAWR; # ACCEPT WORKLIST REQUEST #
PROC SSTAQE; # ACCEPT QUEUE ENTRY #
PROC SSTATS; # ALLOCATE TABLE SPACE #
PROC SSTRTS; # REMOVE TABLE SPACE #
END
#
****
#
ITEM I I; # LOOP VARIABLE AND SCRATCH #
ITEM NEWACN B; # TRUE IF ACN NOT FOUND IN ACN LIST #
ITEM AE I; # ORD OF MATCHED (OR NEW) ACN LIST ENTRY #
ITEM ACNN I; # ACN FROM ENTRY WE ARE LOOKING FOR #
ITEM RORD I; # ORDINAL OF ENTRY LOCATED IN *WBQ*/*IWBQ*#
ITEM OORD I; # ORDINAL OF ENTRY POSITION IN *OTQ* #
ITEM SIZ I; # SIZE OF ENTRY BEING MOVED TO *OTQ* #
ITEM SMID I; # INTERNAL SM IDENTIFIER #
SWITCH FSSWT:CTQSTAT
LLFCACK: SACK, # FC/ACK #
LLFCBRK: SBRK, # FC/BRK #
LLIUSR: SIUSR, # INTR/USR #
LLFCINA: SINA, # FC/INACT #
LLFCINI: SINIT, # FC/INIT #
LLFCNAK: SNAK, # FC/NAK #
LLBIMRK: SBMRK; # BI/MARK #
PROC DELDAT;
BEGIN # DELDAT #
#
* DELDAT - DELETE SYNCHRONOUS BLOCKS.
*
* THIS EMBEDDED PROC FINDS BLOCKS QUEUED FOR THE ACN IN QUESTION IN
* THE WAITING BLOCK QUEUE AND DELETES THEM FROM THE QUEUE.
*
* PROC DELDAT
#
FOR I = 0 WHILE ACN$WBCNT[AE] NQ 0
DO
BEGIN
FOR RORD = RORD STEP WBQ$ESIZE[RORD]
WHILE WBQ$ABHACN[RORD] NQ ACNN
DO
BEGIN
END
SIZ = WBQ$ESIZE[RORD]; # SIZE OF ENTRY TO DELETE #
SSTRTS( P<WBQ>, RORD, SIZ ); # DELETE ENTRY #
ACN$WBCNT[AE] = ACN$WBCNT[AE] - 1;
END
END # DELDAT #
PROC XMITDAT;
BEGIN # XMITDAT #
#
* XMITDAT - TRANSMIT SYNCHRONOUS BLOCKS.
*
* THIS EMBEDDED PROC FINDS BLOCKS QUEUED FOR THE ACN IN QUESTION IN
* THE WAITING BLOCK QUEUE AND MOVES THEM TO THE OUTGOING TRAFFIC
* QUEUE UNTIL THE NUMBER OF UNACKNOWLEDGED SYNCHRONOUS BLOCKS IS
* EQUAL TO THE APPLICATION BLOCK LIMIT.
*
* PROC XMITDAT
#
FOR I=0 WHILE ACN$WBCNT[AE] NQ 0
AND ACN$BLCNT[AE] LS ACN$ABL[AE]
DO
BEGIN
FOR RORD = RORD STEP WBQ$ESIZE[RORD]
WHILE WBQ$ABHACN[RORD] NQ ACNN
DO
BEGIN END
OORD = OTQLNGTH;
SIZ = WBQ$ESIZE[RORD]; # SIZE OF ENTRY TO BE MOVED #
WBQ$ABN[RORD] = ACN$ABN[AE]; # TRANSFER NEXT ABN #
SSTATS( P<OTQ>, SIZ );
MOVE( SIZ, WBQ[RORD], OTQ[OORD] );
SSTRTS( P<WBQ>, RORD, SIZ );
IF OORD EQ 0
THEN
SSSAWR( WWDF"SACNI");
ACN$ABN[AE] = ACN$ABN[AE] + 1;
ACN$BLCNT[AE] = ACN$BLCNT[AE] + 1;
ACN$WBCNT[AE] = ACN$WBCNT[AE] - 1;
END
END # XMITDAT #
PROC XMITSM;
BEGIN # XMITSM #
#
* XMITSM - TRANSMIT ASYNCHRONOUS SUPERVISORY MESSAGE.
*
* THIS EMBEDDED PROC FINDS AN ASYNCHRONOUS SM (EITHER CR/SWH/R OR
* CR/TRM/R) QUEUED FOR THE ACN IN QUESTION IN THE WAITING BLOCK
* QUEUE AND MOVES IT TO THE OUTGOING TRAFFIC QUEUE.
*
* PROC XMITSM
#
IF (ACN$STATE[AE] EQ ACNST"SWTPEND"
OR ACN$STATE[AE] EQ ACNST"TRMPEND")
AND ACN$BLCNT[AE] EQ 0
THEN
BEGIN
FOR RORD = RORD STEP WBQ$ESIZE[RORD]
WHILE WBQ$ABHACN[RORD] NQ 0
OR WBQ$CRSACN[RORD] NQ ACNN
DO
BEGIN END
OORD = OTQLNGTH;
SIZ = WBQ$ESIZE[RORD]; # SIZE OF ENTRY TO BE MOVED #
SSTATS( P<OTQ>, SIZ );
MOVE( SIZ, WBQ[RORD], OTQ[OORD] );
SSTRTS( P<WBQ>, RORD, SIZ );
IF OORD EQ 0
THEN
SSSAWR( WWDF"SACNI" );
IF ACN$STATE[AE] EQ ACNST"SWTPEND"
THEN
ACN$STATE[AE] = ACNST"SWSTART";
ELSE
ACN$STATE[AE] = ACNST"ENDED";
END
END # XMITSM #
# MAIN PROCEDURE CODE BEGINS HERE #
IF WCB$SMID[0] EQ CTQSTAT"SBMRK"
THEN
BEGIN
ACNN = ABHADR[0];
END
ELSE
BEGIN
ACNN = FCACN[0];
END
NVFCFCE( ACNN, AE, NEWACN );
SMID = WCB$SMID[0]; # GET INTERNAL SM IDENTIFIER #
IF NEWACN
THEN
BEGIN
IF SMID NQ CTQSTAT"SINA"
THEN
ABORT;
ELSE
GOTO ENDTAS;
END
RORD = 0;
GOTO FSSWT[SMID];
LLFCINI:
IF ACN$STATE[AE] NQ ACNST"ENDED"
THEN
BEGIN
ACN$INIT[AE] = TRUE;
PFCSFC[0] = FCINITN;
SSTAQE( P<OTQ>, WCBUF, ABHBUF, MSGBUF );
XMITDAT; # SEND DATA IF ANY #
XMITSM; # SEND SM IF ALL BLOCKS ACKED #
END
GOTO ENDTAS;
LLFCINA:
#
* IF THE CURRENT STATE OF THE CONNECTION IS TERMINATE PENDING, THEN
* THE CONNECTION IS HUNG. GO AHEAD AND TERMINATE IT.
#
IF ACN$STATE[AE] EQ ACNST"TRMPEND" AND
ACN$CNUM[AE] EQ ABHABN[0]
THEN
BEGIN
ACN$BLCNT[AE] = 0; # CLEAR OUTSTANDING BLOCK COUNT #
DELDAT; # DELETE SYNCHRONOUS DATA #
XMITSM; # SEND CR/TRM/R #
END
GOTO ENDTAS;
LLIUSR:
IF INTRCHR[0] GR RIR"UB2"
THEN # IF THIS IS A USER INTERRUPT #
BEGIN
IF ACN$STATE[AE] NQ ACNST"SWSTART" AND
ACN$STATE[AE] NQ ACNST"ENDED"
THEN # IF A SWITCH OR TERM IS NOT IN PROGRESS, #
BEGIN # SEND AN INTR/RSP SM #
WCB$WORD[1] = LINTR + 2;
ABHWORD[1] = LINTR;
ABHABT[1] = APPCMD;
ABHACT[1] = ACINTR;
SPMSG0[1] = 0;
PFCSFC[1] = INTRRSP;
INTRACN[1] = ACNN;
SSTAQE(P<OTQ>,WCBUF[1],ABH[1],APSM[1]);
END
END
ELSE # MUST BE A USER BREAK #
BEGIN
ACN$BKCNT[AE] = 1;
DELDAT; # DELETE SYNCHRONOUS DATA #
IF ACN$STATE[AE] EQ ACNST"ACTIVE" OR
ACN$STATE[AE] EQ ACNST"BRKCMD"
THEN
BEGIN
ACN$STATE[AE] = ACNST"BRKOUT";
SSTAQE( P<TAINPQ>, WCBUF, ABHBUF, MSGBUF );
IF ACN$BLKF[AE]
THEN
BEGIN
ACN$BLKF[AE] = FALSE;
FOR RORD=0 STEP IWQ$WC[RORD] WHILE ACNN NQ IWQ$ACN[RORD+1]
DO
BEGIN
END
SSTRTS(P<IWBQ>,RORD,IWQ$WC[RORD]);
END
END
ELSE
XMITSM; # SEND SM IF ONE #
END
GOTO ENDTAS;
LLBIMRK:
IF ACN$STATE[AE] EQ ACNST"CLEARI"
THEN # IF THE CURRENT ACN STATE IS CLEAR INPUT #
BEGIN
WCB$WORD[1] = LINTR + 2;
ABHWORD[1] = LINTR;
ABHABT[1] = APPCMD;
ABHACT[1] = ACINTR;
SPMSG0[1] = 0;
PFCSFC[1] = INTRRSP;
INTRACN[1] = ACNN;
SSTAQE(P<OTQ>,WCBUF[1],ABH[1],APSM[1]);
# SET CURRENT ACN STATE BACK TO ACTIVE #
ACN$STATE[AE] = ACNST"ACTIVE";
ACN$BKCNT[AE] = 0;
END
ELSE IF ACN$STATE[AE] EQ ACNST"BRKOUT"
THEN
BEGIN
ACN$BKCNT[AE] = 0;
END
GOTO ENDTAS;
LLFCACK:
LLFCNAK:
IF ACN$STATE[AE] EQ ACNST"ENDED" OR
ACN$STATE[AE] EQ ACNST"SWSTART"
THEN
GOTO ENDTAS;
ACN$BLCNT[AE] = ACN$BLCNT[AE] - 1;
XMITDAT; # SEND DATA IF ANY #
#
* IF TERMINATION IS PENDING AND THE CR/TRM/R WILL NOW BE SENT OUT
* THEN CANCEL THE TIMER REQUEST THAT WAS STARTED UP BECAUSE OF BEING
* IN THE PENDING STATE.
#
IF ACN$STATE[AE] EQ ACNST"TRMPEND" AND
ACN$BLCNT[AE] EQ 0
THEN
SSCCTR(ACN$CNUM[AE],I);
XMITSM; # SEND SM IF ALL BLOCKS ACKED #
GOTO ENDTAS;
LLFCBRK:
IF ACN$STATE[AE] NQ ACNST"SWSTART" AND
ACN$STATE[AE] NQ ACNST"ENDED"
THEN # IF A SWITCH OR TERM IS NOT IN PROGRESS #
BEGIN # SEND AN FC/RST SM #
WCB$WORD[1] = LFCRST + 2;
ABHWORD[1] = LFCRST;
ABHABT[1] = APPCMD;
ABHACT[1] = ACFC;
SPMSG0[1] = 0;
PFCSFC[1] = FCRST;
FCACN[1] = ACNN;
SSTAQE(P<OTQ>,WCBUF[1],ABH[1],APSM[1]);
END
GOTO ENDTAS;
ENDTAS:
END # NVFCUFS #
TERM