%CONTROL 1 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! ! INFO MARK 2--ITP CONSOLE HANDLER ! ! FILE=ITPS ! ! 27TH AUG 1980 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! ! THIS MODULE TAKES CONNECTIONS TO FACILITY 18 FROM GATE AND HANDLES ! CONSEQUENT ITP LOGONS FROM CONSOLES. IT ASSOCIATES THE CONSOLE WITH THE USER TASK ! AND WILL LOAD OTHER TASKS TO GIVE THE REQUIRED SERVICE. ! IT THEN HANDLES THE FLOW OF DATA FROM THE TASK TO THE CONSOLE AND VICE-VERSA. ! LOGGING OFF THE CONSOLE IS ALSO CONTROLLED FROM HERE. ! ! SEE INFO NOTES 2 AND 3 FOR INTERFACE DETAILS. ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! ! SYSTEM DECLARATIONS ! %RECORDFORMAT NSIF((%BYTEINTEGERARRAY X(0:245) %OR %BYTEINTEGER FN,SUFL,ST,SS, %C FLAG,UFL,CONSN,HB1,HB2,(%BYTEINTEGER LENG, %C %BYTEINTEGERARRAY DATA(0:234) %OR %STRING(235) S))) %INCLUDE "ERCM08.INC_RECORDS" %INCLUDE "ERCM08.INC_DEIMOSPERM" %CONSTRECORD(*)%NAME NULL==0 %BEGIN ! ! ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! ! CONNECTION HANDLING ! %CONSTINTEGER NCONS=15; !NUMBER OF CONNECTIONS %RECORDFORMAT CONF(%BYTEINTEGER STATE,PORT,NODE,TERM, %C %RECORD(QF) OUTPUT Q) %OWNRECORD(CONF)%ARRAY CONNS(0:NCONS) %OWNRECORD(CONF)%NAME CONN ! ! CONNECTION STATES ! %CONSTINTEGER UNALLOC=0 %CONSTINTEGER DATA GONE=1; !DATA SENT TO GATE %CONSTINTEGER TX ENABLED=2; !OK TO SEND TO GATE ! ! ITP CONSOLE HANDLING ! %CONSTINTEGER NITPS=31; !NUMBER OF CONSOLES %RECORDFORMAT ITPF(%BYTEINTEGER STATE,TASK SER,LENGO,GAHS, %C CLK,CONSNO,ITPNO,%RECORD(CONF)%NAME CONN) %OWNRECORD(ITPF)%ARRAY ITPS(0:NITPS) %OWNRECORD(ITPF)%NAME ITP ! ! ITP STATE-UNALLOC AS ABOVE ! %CONSTINTEGER TASK PROMPT=1; !PROMPT FROM TASK SENT %CONSTINTEGER DATA ASKED FOR=2 %CONSTINTEGER BLOCKED=3; !WAITING FOR GOAHEADS %CONSTINTEGER TIMEDOUT=4 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! %INCLUDE "ERCM08.INC_ITPINT" %INCLUDE "ERCM08.INC_GATEINT" %INCLUDE "ERCM08.INC_SERVICES" ! ! ITP HEADER BYTES ! %CONSTINTEGER CONTROL=1 %CONSTINTEGER GAHBIT=2 %CONSTINTEGER DISC=4 %CONSTINTEGER HELLOBIT=8 !HB2 %CONSTINTEGER BREAKBIT=1 %CONSTINTEGER SETBIT=2 %CONSTINTEGER PROMPTBIT=4 %CONSTINTEGER TERMBIT=2 ! GENERAL VARIABLES ! %OWNRECORD(PEF) P %OWNRECORD(NSIF) %NAME NSL %OWNINTEGER MONIT,CLOCK,I ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! ! ROUTINES START HERE ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! ! ! ROUTINES TO INTERFACE TO THE BUFFER MANAGER ! ! ! RELEASE BLOCK ! %ROUTINE RELEASE BLOCK(%RECORD(MEF)%NAME MES) P_SER=BUFFER MANAGER; P_REPLY=OWN ID P_FN=RELEASE BUFFER; P_MES==MES PON(P) %END ! ! ASK FOR BLOCK ! %ROUTINE ASK FOR BLOCK P_SER=BUFFER MANAGER; P_REPLY=OWN ID P_FN=REQUEST BUFFER; P_S0=1 PONOFF(P) %END ! ! PUSH AND POP ROUTINES TO REPLACE DEIMOS PERM ONES ! %ROUTINE PUSH(%RECORD (QF) %NAME Q,NEW) %IF Q_LINK == NULL %THENSTART Q_LINK == NEW NEW_LINK == NEW %FINISHELSESTART NEW_LINK == Q_LINK_LINK Q_LINK_LINK == NEW Q_LINK == NEW %FINISH %END %RECORD (QF) %MAP POP(%RECORD (QF) %NAME Q) %RECORD (QF) %NAME OLD %IF Q_LINK == NULL %THEN OLD == NULL %ELSESTART %IF Q_LINK_LINK == Q_LINK %THENSTART ;!One element only on Q OLD == Q_LINK Q_LINK == NULL %FINISHELSESTART OLD == Q_LINK_LINK Q_LINK_LINK == OLD_LINK %FINISH %FINISH %RESULT == OLD %END ! SEND MESSAGE TO GATE ! %ROUTINE TO GATE(%INTEGER FN) %INTEGER I P_SER=GATE SER; P_REPLY=OWN ID P_FN=FN; P_PORT=CONN_PORT PON(P) %IF MONIT&1#0 %START PRINTSTRING("TO GATE:") WRITE(FN,3); WRITE(P_PORT,3) %IF P_MES##NULL %START %FOR I=0,1,14 %CYCLE WRITE(P_MES_NSL_X(I),1) %REPEAT %FINISH NEWLINE %FINISH %END ! ! SEND MESSAGE TO OTHER TASK ! %ROUTINE TO TASK(%INTEGER FN) P_SER=ITP_TASK SER; P_REPLY=ITP SER P_FN=FN; P_PORT=ITP_ITPNO PON(P) %END ! ! RESET ITP.......RECORDS EVENT 31 (LOGOFF) ! %ROUTINE RESET ITP ! WRITE(31,2);! WRITE(ITP_ITPNO,2) ! NEWLINE ITP_STATE=UNALLOC; ITP_TASK SER=0 ITP_GAHS=0; ITP_CONSNO=0 ITP_CONN==NULL %END ! ! ! HANDLE CONNECTION FROM GATE ! ! ROUTINE FINDS A FREE CONN PORT ! %ROUTINE HANDLE CONNECTION %INTEGER I %FOR I=0,1,NCONS %CYCLE %IF CONNS(I)_STATE=UNALLOC %START; !GOT FREE ONE CONN==CONNS(I) CONN_PORT=P_PORT CONN_NODE=P_MES_NSL_FLAG CONN_TERM=P_MES_NSL_ST P_S1=P_S0; !ACCEPT FLAG TO GATE(CALL REPLY) CONN_STATE=TX ENABLED %IF MONIT&1#0 %START PRINTSTRING("CONN "); WRITE(CONN_PORT,2) WRITE(I,2); NEWLINE %FINISH %EXIT %FINISHELSEIF I=NCONS %START; !NONE LEFT P_S1=0 TO GATE(CALL REPLY) PRINTSTRING("*** OUT OF PORTS !!!!!"); NEWLINE %FINISH %REPEAT %END ! ! HANDLE CALL CLOSED/ABORTED FROM GATE ! ! MUST CLEAR DOWN QUEUES AND THROW OFF USERS ! %ROUTINE CLOSEDOWN %INTEGER I %WHILE CONN_OUTPUT Q_LINK##NULL %CYCLE RELEASE BLOCK(POP(CONN_OUTPUT Q)) %REPEAT CONN_STATE=UNALLOC %IF MONIT&1#0 %START PRINTSTRING("CABT "); WRITE(P_PORT,2); WRITE(I,2) %FINISH %FOR I=0,1,NITPS %CYCLE %IF ITPS(I)_CONN==CONN %START ITP==ITPS(I) TO TASK(LOGOFF) %IF ITP_TASK SER#0 RESET ITP; !RESET ITP RECORD %IF MONIT&1#0 %THEN WRITE(I,2) %FINISH %REPEAT %IF MONIT&1#0 %THEN NEWLINE %END ! ! SEND ITP MESSAGE ! ! PUTS ITP HEADER ON AND PUTS IT ON NSI Q. ! SENDS MESSAGE TO GATE IF TX ENABLED ! %ROUTINE SEND ITP MESSAGE(%INTEGER HB1,HB2) NSL_CONSN=ITP_CONSNO NSL_HB1=HB1; NSL_HB2=HB2 P_S0=0 CONN==ITP_CONN PUSH(CONN_OUTPUT Q,P_MES); !TO BE CHANGED...TESTING PUSH/POP %IF CONN_STATE=TX ENABLED %START P_MES==POP(CONN_OUTPUT Q) TO GATE(PUT OUTPUT) CONN_STATE=DATA GONE %FINISH %END ! ! RECEIVE MESSAGE FROM TASK ! %ROUTINE FROM TASK %SWITCH FN(DATA OUT:CHANGE TASK) %IF MONIT&2#0 %START PRINTSTRING("FT "); WRITE(P_PORT,2) WRITE(P_FN,2); WRITE(P_REPLY,2); WRITE(P_S0,3) NEWLINE %FINISH ->ILLEG %IF P_PORT<0 %OR P_PORT>NITPS ITP==ITPS(P_PORT) ->ILLEG %IF ITP_TASK SER#P_REPLY ->ILLEG %IF P_FNCHANGE TASK ->ILLEG %IF ITP_STATE#DATA ASKED FOR %AND ITP_STATE#TIMEDOUT NSL==P_MES_NSL %UNLESS P_FN=CHANGE TASK ->FN(P_FN) !* !** DATA OUT !* FN(DATA OUT): SEND ITP MESSAGE(0,TERMBIT) GAHL: ITP_GAHS=ITP_GAHS-1 %IF ITP_GAHS>0 %START; !CAN SEND MORE TO TASK(SEND DATA) ITP_STATE=DATA ASKED FOR %FINISHELSE ITP_STATE=BLOCKED ITP_CLK=24 %RETURN !* !** SEND PROMPT !* FN(SEND PROMPT): SEND ITP MESSAGE(GAHBIT,PROMPTBIT) ITP_STATE=TASK PROMPT ITP_CLK=24 %RETURN !* !** LOGOFF !* FN(LOGOFF): SEND ITP MESSAGE(CONTROL!DISC,0) RESET ITP; !RESET ITP RECORD %RETURN !* !** SETMODE !* FN(SETMODE): SEND ITP MESSAGE(CONTROL,SETBIT) ->GAHL !* !** CHANGE TASK !* FN(CHANGE TASK): ->ILLEG; !NOT YET IMPLEMENTED ILLEG: P_S1=P_FN TO TASK(ILLEGAL MESSAGE) %IF MONIT&2#0 %START PRINTSTRING("ILLEG"); NEWLINE %FINISH %END ! ! DUMP ITP RECORD TO TTY ! %ROUTINE DUMP ITP WRITE(ITP_ITPNO,3) WRITE(ITP_STATE,3); WRITE(ITP_TASK SER,3); WRITE(ITP_LENGO,3) WRITE(ITP_GAHS,3); WRITE(ITP_CLK,3); WRITE(ITP_CONSNO,3) NEWLINE %END ! ! ITP DATA IN ! ! GETS ITP MESSAGE SENT IN, IDENTIFIES THE TYPE AND ! TAKES APPROPRIATE ACTION. CONN SET UP BEFORE ENTRY ! %ROUTINE ITP DATA IN %CONSTINTEGER ITPLIM=28 %INTEGER I NSL==P_MES_NSL %IF MONIT&4#0 %START PRINTSTRING("IN "); WRITE(NSL_CONSN,2) WRITE(NSL_HB1,3); WRITE(NSL_HB2,3) NEWLINE %FINISH %IF NSL_HB1&HELLOBIT#0 %START; !LOGON %FOR I=1,1,NITPS %CYCLE %IF ITPS(I)_STATE=UNALLOC %START ITP==ITPS(I) ITP_CONSNO=NSL_CONSN ITP_CONN==CONN ITP_GAHS=0 ITP_TASK SER=USER SER; !ALWAYS START WITH USER ITP_STATE=BLOCKED RELEASE BLOCK(P_MES) P_B1=CONN_NODE; !TELL USER TASK DETAILS P_B2=CONN_TERM P_C1=ITP_CONSNO TO TASK(LOGON) ! %RETURN %FINISH %REPEAT %FINISHELSESTART %FOR I=0,1,NITPS %CYCLE; !FIND ENTRY %IF ITPS(I)_CONN==CONN %AND %C ITPS(I)_CONSNO=NSL_CONSN %START ITP==ITPS(I) %IF MONIT&4#0 %THEN DUMP ITP %EXITIF ITP_STATE#TIMEDOUT %FINISH %IF I=NITPS %START; !CONSOLE CLOSED DOWN RELEASE BLOCK(P_MES) %RETURN %FINISH %REPEAT %IF NSL_HB1&GAHBIT#0 %THEN ITP_GAHS=(ITP_GAHS+1)&3 %IF NSL_HB1&DISC#0 %START; !LOGOFF(SETMODE EOT!) RELEASE BLOCK(P_MES) %IF ITP_TASK SER#0 %START; !TELL TASK TO TASK(LOGOFF) %FINISH RESET ITP; !RESET ITP RECORD %RETURN %FINISH %IF NSL_HB1&CONTROL#0 %START; !CONTROL MESSAGE RELEASE BLOCK(P_MES) %IF NSL_HB2&BREAKBIT#0 %START; !INT %IF ITP_TASK SER#0 %AND NSL_LENG>0 %THEN TO TASK(INT IN) %FINISH %FINISHELSESTART ! MUST BE DATA MESSAGE %IF ITP_STATE=TASK PROMPT %START TO TASK(DATA IN) ITP_STATE=BLOCKED %FINISHELSESTART; !SPECIAL TASKS TO BE DONE HERE!!!! RELEASE BLOCK(P_MES) PRINTSTRING("DATA SEQUENCE ERROR!") WRITE(ITP_STATE,3); NEWLINE %FINISH %FINISH %IF ITP_STATE=BLOCKED %AND ITP_GAHS>0 %START TO TASK(SEND DATA) ITP_STATE=DATA ASKED FOR %FINISH %FINISH %END ! ! FROM GATE ! ! HANDLES MESSAGES FROM GATE--SEE DIEMOS NOTE 2 ! %ROUTINE FROM GATE %SWITCH S(INCOMMING CALL:CALL ABORTED) %ROUTINE FIND CONNECTION %INTEGER I CONN==NULL %FOR I=0,1,NCONS %CYCLE %IF CONNS(I)_PORT=P_PORT %THEN CONN==CONNS(I) %ANDEXIT %REPEAT %END ! %IF MONIT&1#0 %START PRINTSTRING("FG "); WRITE(P_FN,2); WRITE(P_PORT,2); NEWLINE %FINISH %IF P_FN#INCOMMING CALL %THEN FIND CONNECTION ->S(P_FN) S(INCOMMING CALL): HANDLE CONNECTION; %RETURN S(INPUT RECD): %IF P_MES_NSL_FLAG&128#0 %START RELEASE BLOCK(P_MES); P_MES==NULL TO GATE(CLOSE CALL); ->CL %FINISH ITP DATA IN P_MES==NULL; TO GATE(ENABLE INPUT) %RETURN S(OUTPUT TXD): %IF CONN##NULL %START %IF CONN_OUTPUT Q_LINK##NULL %START P_MES==POP(CONN_OUTPUT Q) TO GATE(PUT OUTPUT) CONN_STATE=DATA GONE %FINISHELSESTART CONN_STATE=TX ENABLED %FINISH %FINISH %RETURN S(CALL CLOSED): %RETURN S(CALL ABORTED): TO GATE(ABORT CALL) CL: CLOSEDOWN %END ! ! HANDLE INT ! %ROUTINE HANDLE INT %INTEGER I %IF INT='G' %THEN MONIT=1; !GATE MONITOR ! %IF INT='T' %THEN MONIT=2; !TASK MONITOR ! %IF INT='P' %THEN MONIT=4; !ITP MONITOR %IF INT='A' %THEN MONIT=7; !ALL MONITORING %IF INT='O' %THEN MONIT=0; !MONITOR OFF ! %IF INT='C'% %OR INT='?' %START ! %FOR I=0,1,NCONS %CYCLE ! %IF CONNS(I)_STATE#UNALLOC %START ! WRITE(CONNS(I)_STATE,3) ! WRITE(CONNS(I)_PORT,3) ! WRITE(I,3) ! NEWLINE ! %FINISH ! %REPEAT ! %FINISH ! %IF INT='I' %OR INT='?' %START ! %FOR I=0,1,NITPS %CYCLE ! ITP==ITPS(I) ! DUMP ITP %IF ITP_STATE#UNALLOC ! %REPEAT ! %FINISH %IF INT = 'S' %START; ! STOP IT P_S1=18; ! FACILITY = ITP TO GATE(DISABLE FACILITY) %FOR I = 0, 1, NCONS %CYCLE CONN == CONNS(I) %IF CONN_STATE # UNALLOC %START CLOSEDOWN TO GATE(ABORT CALL) %FINISH %REPEAT %STOP; ! WAIT FOR GATE REPLIES ??????? %FINISH INT=0 %END !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! ! PROGRAM STARTS HERE ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! ! INITIALISATION ! I=MAPVIRT(BUFFER MANAGER, 4, 3) I=MAPVIRT(BUFFER MANAGER,5,4) I=MAPVIRT(BUFFER MANAGER,6,5) LINKIN(ITP SER) ALARM(250); !FOR TIMEOUTS %FOR I=0,1,NCONS %CYCLE CONNS(I)=0 %REPEAT CONN==CONNS(0) %FOR I=0,1,NITPS %CYCLE ITPS(I)=0 ITPS(I)_ITPNO=I %REPEAT ! ! MAIN PROGRAM LOOP ! ->HORRIBLE %CYCLE P_SER=0; POFF(P) %IF INT#0 %THEN HANDLE INT %IF P_REPLY=0 %START; !CLOCK ALARM(250) ! %FOR I=0,1,NITPS %CYCLE; !CHECK FOR TIMEOUTS ! %IF ITPS(I)_STATE=TASK PROMPT %START ! ITPS(I)_CLK=ITPS(I)_CLK-1 ! %IF ITPS(I)_CLK=0 %START ! ITP==ITPS(I) ! ITP_STATE=TIMEDOUT ! TO TASK(TIMEOUT) ! %FINISH ! %FINISH ! %REPEAT %FINISHELSEIF P_REPLY=GATE SER %START FROM GATE %FINISHELSEIF P_REPLY=USER SER %START FROM TASK %FINISHELSEIF P_REPLY=POLL SER %START HORRIBLE: P_S1=18 TO GATE(ENABLE FACILITY) %FINISHELSEIF P_REPLY=LOAD SER %START !TO BE IMPLEMENTED %FINISHELSESTART PRINTSTRING("** MESSAGE ?? ") WRITE(P_FN,3); WRITE(P_REPLY,3); NEWLINE %FINISH ! %REPEAT ! %ENDOFPROGRAM