*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, SIZ); # MAKE ROOM # MOVE (SIZ, WBQ[WORD], OTQ[OORD]); SSTRTS (P, 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, 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,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,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,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, 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, 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,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, WCBUF[0], ABHBUF[1], MSGBUF[0]); END # FC/INACT # END # CSCUFS # TERM