*DECK CSCUFS
USETEXT TEXTCS
USETEXT TEXTSS
USETEXT TXTAPSS
PROC CSCUFS;
# TITLE CSCUFS - UPDATE FLOW STATUS. #
BEGIN # CSCUFS #
#
** CSCUFS - UPDATE FLOW STATUS.
*
* D. G. DEPEW. 82/06/04.
*
* THIS PROCEDURE PERFORMS ALL THE CONNECTION(C) LAYER PROCESSING
* REQUIRED FOR ALL INBOUND, FLOW CONTROL SUPERVISORY MESSAGES.
*
* PROC CSCUFS
*
* ENTRY WCBUF[0] = WORD COUNT WORD FROM ORIGINAL CONNECTION
* TRAFFIC QUEUE (*CNQ*) 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, 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 NOP IN QUESTION.
* - THE STATE OF THE ACN LIST ENTRY HAS BEEN UPDATED.
* - AN FC/INIT/N OR AN FC/RST SM HAS BEEN PLACED IN THE
* OUTGOING TRAFFIC QUEUE (*OTQ*).
* - AN FC/INACT ENTRY HAS BEEN PLACED IN THE PROTOCOL EVENT
* QUEUE (*PEQ*).
* - ONE OR MORE ENTRIES IN THE WAITING BLOCK QUEUE (*WBQ*)
* FOR THE NOP IN QUESTION HAVE BEEN TRANSFERRED TO THE
* OUTGOING TRAFFIC QUEUE (*OTQ*)
* - ALL OUTPUT ENQUEUED (IN THE *WBQ*) FOR THE NOP IN
* QUESTION HAS BEEN DISCARDED.
* - A TERMINAL TEXT ENTRY HAS BEEN PLACED IN THE CONNECTION
* TRAFFIC QUEUE (*CNQ*).
* - AN FC/BRK ENTRY HAS BEEN PLACED IN THE OPERATOR TYPEIN
* QUEUE (*OPTQ*).
*
* NOTE THE PROCESSING IS DEFINED BY THE CS/NOP C-LAYER STATE
* DIAGRAM.
#
#
**** PROC CSCUFS - XREF LIST.
#
XREF
BEGIN
PROC CSCPNQ; # PURGE NOP QUEUE #
PROC MOVE; # MOVE STORAGE DIRECT ADDRESSING #
PROC SSSAWR; # ACCEPT WORKLIST REQUEST #
PROC SSTAQE; # ACCEPT QUEUE ENTRY #
PROC SSTATS; # ALLOCATE TABLE SPACE #
PROC SSTRTS; # REMOVE TABLE SPACE #
END
#
****
#
DEF ODTLW$ #2#; # *OUTPUT DISCARDED..* TEXT LEN IN WORDS #
ITEM NACN; # NOP ACN = ORDINAL OF ACN LIST ENTRY #
ITEM MSGBLOC B; # TRUE IF *MSG* BLOCK IN *WBQ* #
ARRAY DISCARD [00:00] S(ODTLW$);
BEGIN
ITEM D$TEXT C(00,00,18) = ["OUTPUT DISCARDED.."];
ITEM D$ZERO U(01,48,12) = [0];
END
CONTROL EJECT;
PROC XMITNQ;
BEGIN # XMITNQ #
#
* XMITNQ - TRANSMIT NOP QUEUE.
*
* THIS EMBEDDED PROC FINDS BLOCKS QUEUED FOR THE NOP IN QUESTION IN
* THE WAITING BLOCK QUEUE (*WBQ*) AND MOVES THEM TO THE OUTGOING
* TRAFFIC QUEUE (*OTQ*) UNTIL THE NUMBER OF UNACKNOWLEDGED BLOCKS
* IS EQUAL TO THE APPLICATION BLOCK LIMIT, OR THE *WBQ* ENTRIES ARE
* EXHAUSTED FOR THIS NOP.
*
* PROC XMITNQ
*
* ENTRY 1. THE *WBQ* CONTAINS ZERO OR MORE ENTRIES FOR THE NOP
* IN QUESTION.
* 2. THE ACN LIST ENTRY FOR THE NOP CONTAINS ALL REQUIRED
* INFORMATION - NAMELY, THE COUNT OF *WBQ* ENTRIES, THE
* COUNT OF OUTSTANDING BLOCKS AND THE APPLICATION BLOCK
* LIMIT FOR THE CONNECTION.
*
* EXIT 1. ZERO OR MORE ENTRIES, FOR THE NOP IN QUESTION, HAVE
* BEEN REMOVED FROM THE *WBQ* AND PLACED IN THE *OTQ*.
* 2. THE COUNTS OF WAITING BLOCKS AND UNACKNOWLEDGED BLOCKS
* HAVE BEEN UPDATED APPROPRIATELY.
*
* NOTE NOP ENTRIES IN THE *WBQ* ARE ALREADY IN CORRECT NETWORK
* BLOCK FORMAT, AND MAY BE MOVED TO THE *OTQ* UNCHANGED.
#
ITEM I; # LOOP INDUCTION VARIABLE #
ITEM SIZ; # ENTRY SIZE #
ITEM OORD; # OUTGOING TRAFFIC QUEUE ORDINAL #
ITEM WORD; # WAITING BLOCK QUEUE ORDINAL #
WORD = 0;
FOR I=0 WHILE ACN$WBCNT[NACN] NQ 0
AND ACN$BLCNT[NACN] LS ACN$ABL[NACN]
DO # MOVE BLOCKS #
BEGIN
FOR WORD = WORD STEP WBQ$ESIZE[WORD]
WHILE WBQ$ABHACN[WORD] NQ NACN
DO # FIND NOP'S ENTRY #
BEGIN END
OORD = OTQL; # WHERE *OTQ* ENTRY WILL BE #
SIZ = WBQ$ESIZE[WORD]; # SIZE OF ENTRY TO BE MOVED #
SSTATS (P<OTQ>, SIZ); # MAKE ROOM #
MOVE (SIZ, WBQ[WORD], OTQ[OORD]);
SSTRTS (P<WBQ>, WORD, SIZ); # DELETE WAITING BLOCK #
IF OORD EQ 0
THEN # FIRST ENTRY IN *OTQ* #
SSSAWR(CSWDF"SACNI");
ACN$BLCNT[NACN] = ACN$BLCNT[NACN] + 1; # OUTSTANDING BLOCKS #
ACN$WBCNT[NACN] = ACN$WBCNT[NACN] - 1; # WAITING BLOCKS #
END
END # XMITNQ #
CONTROL EJECT;
#
* MAIN ROUTINE BEGINS HERE.
*
* SAVE THE ACN NUMBER AND EXECUTE A CASE CONSTRUCT TO PROCESS THE
* FIVE TYPES OF INCOMING SM'S. REFORMAT THE ABH FOR THE I-LAYER.
#
ABHWORD[1] = 0;
IF WCB$SMID[0] EQ SMID"BIMARK"
THEN
BEGIN
NACN = ABHADR[0];
ABHADR[1] = NACN;
END
ELSE
BEGIN
ABHADR[1] = FCACN[0];
NACN = FCACN[0];
END
IF WCB$SMID[0] EQ SMID"FCINIT"
THEN # CONNECTION INITIALIZED #
BEGIN
#
* MARK THE CONNECTION AS INITIALIZED, ISSUE THE FC/INIT/N SM, AND
* OUTPUT ANY BLOCKS QUEUED (IN THE *WBQ*) FOR THIS NOP.
#
ACN$INIT[NACN] = TRUE;
PFCSFC[0] = FCINITN;
SSTAQE (P<OTQ>, WCBUF[0], ABHBUF[0], MSGBUF[0]);
XMITNQ;
END # FC/INIT #
ELSE IF WCB$SMID[0] EQ SMID"FCACK"
OR WCB$SMID[0] EQ SMID"FCNAK"
THEN # A BLOCK HAS BEEN ACKNOWLEDGED #
BEGIN
#
* NOTE THAT WE TREAT A BLOCK NOT DELIVERED MESSAGE THE SAME AS A
* BLOCK DELIVERED. THAT IS, CS DOES NOT ATTEMPT ANY RECOVERY OF
* LOST BLOCKS. THIS IS BECAUSE LOST BLOCKS ARE, IN PRACTICE,
* EXTREMELY RARE. IF THE CONNECTION IS ACTIVE OR A COMMAND IS IN
* PROGRESS, DECREMENT THE OUTSTANDING BLOCK COUNT AND OUTPUT THE
* NEXT QUEUED (IN THE *WBQ*) BLOCK (IF THERE IS ONE). OTHERWISE,
* IGNORE THE SM.
#
IF ACN$NOPST[NACN] EQ S"ACTIVE"
OR ACN$NOPST[NACN] EQ S"COMMAND"
OR ACN$NOPST[NACN] EQ S"BREAK"
OR ACN$NOPST[NACN] EQ S"CLEARI"
THEN # CONNECTION IS OK FOR OUTPUT #
BEGIN
ACN$BLCNT[NACN] = ACN$BLCNT[NACN] - 1;
XMITNQ;
END
END # FC/ACK, FC/NAK #
ELSE IF WCB$SMID[0] EQ SMID"INTRUSR"
THEN # NOP ENTERED A USER BREAK #
BEGIN
#
* IF THIS IS JUST A USER INTERUPT AND NOT A USER BREAK, THEN SEND
* A INTR/RSP SM IN RESPONSE.
#
IF INTRCHR[0] GR RIR"UB2"
THEN
BEGIN
WCB$WORD[1] = LINTR + 2;
ABHWORD[1] = LINTR;
ABHABT[1] = APPCMD;
ABHACT[1] = CT60TRANS;
SPMSG0[1] = 0;
PFCSFC[1] = INTRRSP;
INTRACN[1] = INTRACN[0];
SSTAQE(P<OTQ>,WCBUF[1],ABH[1],APSM[1]);
END
#
* RELEASE ALL OUTPUT QUEUED (IN THE *WBQ*) FOR THIS NOP (IF ANY).
* CLEAR THE OUTSTANDING BLOCK COUNT.
* SEND A RO/MARK SM ON THE CONNECTION TO ALLOW OUT TO RESUME.
* IF THE CONNECTION IS ACTIVE AND THERE WAS NO *MSG* BLOCK QUEUED
* ENQUEUE A TERMINAL TEXT ENTRY (*CNQ*) CONTAINING THE MESSAGE
* *OUTPUT DISCARDED..* WITHOUT INPUT ALLOWED. IF THERE WAS AN
* *MSG* BLOCK QUEUED, THE *OUTPUT DISCARDED* MESSAGE MUST BE OF
* TYPE *MSG* TO TURN AROUND THE HALF-DUPLEX MODE AND TO STAY IN
* SYNCH WITH NIP. TO ACCOMPLISH THIS WE ENQUEUE (IN THE *CNQ*)
* A TERMINAL TEXT ENTRY WITH INPUT ALLOWED AND CHANGE THE STATE
* TO BREAK IN PROGRESS. THIS WILL CAUSE THE OUTBOUND TEXT
* PROCESSOR (*CSCPNT*) TO GENERATE THE FC/RST FOLLOWED BY THE
* CORRECT MESSAGES. IF A COMMAND IS IN PROGRESS, SEND THE BREAK
* TO THE I-LAYER AS AN OPERATOR TYPEIN (*OPTQ*).
#
ELSE
BEGIN
CSCPNQ (NACN, MSGBLOC); # DELETE NOP'S OUTPUT (IF ANY) #
IF ACN$NOPST[NACN] EQ S"ACTIVE" OR
ACN$NOPST[NACN] EQ S"COMMAND"
THEN
BEGIN # SEND RO/MARK SM #
WCB$WORD[1] = 3;
ABHWORD[1] = LROMARK;
ABHABT[1] = APPCMD;
ABHADR[1] = INTRACN[0];
ABHACT[1] = CT8ASCII;
SPMSG0[1] = 0;
PFCSFC[1] = ROMARK;
IF ACN$BLCNT[NACN] LS ACN$ABL[NACN]
THEN
BEGIN
ABHABN[1] = ACN$ABN[NACN];
ACN$ABN[NACN] = ACN$ABN[NACN] + 1;
ACN$BLCNT[NACN] = ACN$BLCNT[NACN] + 1;
SSTAQE(P<OTQ>,WCBUF[1],ABH[1],APSM[1]);
END
ELSE
BEGIN
ABHABN[1] = ACN$ABN[NACN];
ACN$ABN[NACN] = ACN$ABN[NACN] + 1;
ACN$WBCNT[NACN] = ACN$WBCNT[NACN] + 1;
SSTAQE(P<WBQ>,WCBUF[1],ABH[1],APSM[1]);
END
END
IF ACN$NOPST[NACN] EQ S"ACTIVE"
THEN # BREAK UNSOLICITED STATUS RPTS #
BEGIN
WCB$WORD[1] = ODTLW$ + 2; # TERM TEXT NTRY SIZ, IAF=FALSE #
WCB$SMID[1] = SMID"TTEXT";
IF MSGBLOC
THEN # MUST TURN AROUND HALF DUPLEX #
BEGIN
WCB$IAF[1] = TRUE;
ACN$NOPST[NACN] = S"BREAK";
END
ELSE # SET BREAK FLAG TO INDICATE A #
BEGIN # BREAK OCCURRED WHILE IN THE #
ABHBRK[1] = 1; # ACTIVE STATE. #
ACN$NOPST[NACN] = S"CLEARI";
END
SSTAQE (P<CNQ>, WCBUF[1], ABHBUF[1], DISCARD);
END
ELSE # BREAK COMMAND IN PROGRESS #
BEGIN
WCB$WORD[1] = 2; # MINIMUN QUEUE ENTRY SIZE #
ABHBRK[1] = 1;
SSTAQE(P<OPTQ>, WCBUF[1], ABHBUF[1], MSGBUF[0]);
ACN$NOPST[NACN] = S"BREAK";
END
END
END # FC/BRK #
#
* IF THIS MESSAGE IS A BREAK MARKER, THEN SEND A INTR/RSP FOR THE
* CONNECTION TO ALLOW ANOTHER BREAK AND SET THE STATE OF THE CONNEC-
* TION TO ACTIVE.
#
ELSE IF WCB$SMID[0] EQ SMID"BIMARK"
THEN
BEGIN
IF ACN$NOPST[NACN] EQ S"BREAK" OR
ACN$NOPST[NACN] EQ S"CLEARI"
THEN
BEGIN
WCB$WORD[1] = LINTR + 2;
ABHWORD[1] = LINTR;
ABHABT[1] = APPCMD;
ABHACT[1] = CT60TRANS;
SPMSG0[1] = 0;
PFCSFC[1] = INTRRSP;
INTRACN[1] = NACN;
SSTAQE(P<OTQ>,WCBUF[1],ABH[1],APSM[1]);
ACN$NOPST[NACN] = S"ACTIVE";
END
END
ELSE # MUST BE CONNECTION INACTIVE #
BEGIN
#
* RELEASE ALL OUTPUT QUEUED FOR THIS NOP AND FORWARD THE FC/INACT
* TO THE I-LAYER (AS PROTOCOL EVENT).
#
CSCPNQ (NACN, MSGBLOC); # DELETE NOP'S OUTPUT (IF ANY) #
IF ACN$NOPST[NACN] EQ S"ACTIVE"
OR ACN$NOPST[NACN] EQ S"COMMAND"
THEN
SSTAQE (P<PEQ>, WCBUF[0], ABHBUF[1], MSGBUF[0]);
END # FC/INACT #
END # CSCUFS #
TERM