!******************************** !* EMAS-2900 RING INTERFACE * !* HANDLER * !* FILE: RING4S * !* 27:3:80 * !********************************* !! STK = 300, STRM = 1 ! COMPILE OPTIONS ! --------------- ! TRACE OPTION #T ON ! ERROR OPTION #E ON ! STATS OPTION #S OFF ! !NB LOCATION K'140016 IS USED TO HOLD THE CHECKSUM SO THAT IT MAY !BE ACCESSED FROM CODE %SYSTEMROUTINESPEC LINKIN(%INTEGER SER) %SYSTEMROUTINESPEC MAP HWR(%INTEGER SEG) %SYSTEMROUTINESPEC ALARM(%INTEGER TICKS) %RECORDFORMAT DMF(%INTEGER I) %CONSTRECORD (DMF) %NAME NIL = 0 %CONTROL K'100001' %BEGIN %CONSTSTRING (7)VSN = 'VSN004A' %RECORDFORMAT MEF(%RECORD (MEF) %NAME LINK, %BYTEINTEGER LEN, %C TYPE, %INTEGER ADDRESS, %INTEGERARRAY A(0:100) ) ! THINK ABOUT THE POSITION OF ! 'LEN' %RECORDFORMAT PE(%BYTEINTEGER SER, REPLY, FN, PORT, %C %RECORD (MEF) %NAME MES, %BYTEINTEGER LEN, S1) %RECORDFORMAT PE2(%BYTEINTEGER SER, REPLY, FN, PORT, %C %INTEGER LPORT, HPORT) %RECORDFORMAT QF(%RECORD (MEF) %NAME E) %RECORDFORMAT R1F(%INTEGER X) %RECORDFORMAT R2F(%RECORD (MEF) %NAME MES) %RECORDFORMAT R3F(%BYTEINTEGERNAME B) %RECORDFORMAT R4F(%STRINGNAME S) !! RING INTERFACE REGISTERS !----------------------------- %RECORDFORMAT RINGF(%INTEGER RDATA,SOURCE,SOURCESELECT,STATUS, %C TDATA,DEST,SPARE,INTSTAT) %CONSTRECORD (RINGF) %NAME RING=K'64040' ! RING COMMAND/STATUS REGISTER BITS %CONSTINTEGER BUSY=1 %CONSTINTEGER UNSELECTED=2 %CONSTINTEGER ACCEPTED=4 %CONSTINTEGER IGNORED=8 %CONSTINTEGER BADPACKET=16 %CONSTINTEGER PACKET REJECTED=64 !RING INTERFACE STATUS BITS %CONSTINTEGER RECEIVE=1 %CONSTINTEGER TRANSMIT=2 %CONSTINTEGER ONOFF=16 %CONSTINTEGER RINTOFF=K'40' %CONSTINTEGER RINTON=K'100' %CONSTINTEGER TREADY=K'200' %CONSTINTEGER TINTOFF=K'400' %CONSTINTEGER TINTON=K'1000' %CONSTINTEGER IPROFF=K'2000' %CONSTINTEGER IPRON=K'4000' %CONSTINTEGER IPTOFF=K'10000' %CONSTINTEGER IPTON=K'20000' %CONSTINTEGER REPA=K'100000' !BYTE STREAM COMMAND CODES %CONSTINTEGER RDY=X'3000' %CONSTINTEGER NOTRDY=X'5000' %CONSTINTEGER RESET=X'6300' %CONSTINTEGER CLOSE=X'6600' %CONSTINTEGER DATA=X'A000' %CONSTINTEGER NODATA=X'C000' %CONSTINTEGER CLOSEREQ=4 !TRANSPORT SERVICE COMMAND CODES %CONSTINTEGER OPEN=X'6A00' %CONSTINTEGER OPENACK=X'6500' %CONSTINTEGER LONGBLOCK=X'9000' %CONSTINTEGER LONGBLOCKCH=X'9000' %CONSTINTEGER LONGBLOCKCS0=X'9400' %CONSTINTEGER SINGLESHOT=X'9800' ! INCOMING FUNCTION CODES ! ------------------------- !HE FOLLOWING VALUES MAY BE ADDED TO THE OUTPUT CODES %CONSTINTEGER RELEASE FLAG=X'80'; !RELEASE BUFFER AT END OF OUTPUT %CONSTINTEGER TELL FLAG=X'40'; !NOTIFY AT END OF TRANSFER %CONSTINTEGER CS0FLAG=X'20' %CONSTINTEGER COMMAND MASK=X'1F'; !TO GET COMMAND CODE %CONSTINTEGER ENABLE PORT=0 %CONSTINTEGER XDATA=1 %CONSTINTEGER SSOUT=2; !SINGLE SHOT OUTPUT %CONSTINTEGER XRDY=3 %CONSTINTEGER XNOTRDY=4 %CONSTINTEGER XNODATA=5 %CONSTINTEGER XCLOSE=6 %CONSTINTEGER XRESET=7 %CONSTINTEGER XCLOSEREQ=8 %CONSTINTEGER DISABLE PORT=15 %CONSTINTEGER OUTPUT TRACE=16; !FORCE OUTPUT OF TRACE BUFFER ! OUTGOING FUNCTION CODES ! ----------------------- %CONSTINTEGER OUTPUT DONE=0 %CONSTINTEGER TRANSFER ERROR=1 %CONSTINTEGER R INPUT DONE=2 %CONSTINTEGER INPUT ERROR=3 %CONSTINTEGER RING DOWN=4 %CONSTINTEGER TIMEOUT=2; !NUMBER OF ALARM CALLS !TIME IS INCREMENTED ON EVERY ALARM CALL, ON OVERFLOW TO !ZERO IT IS SET TO 1 AS TIME 0 IMPLIES TIME-NOT-SET %OWNINTEGER NTIMES=0 %OWNINTEGER TIME %OWNINTEGER ME; !RING ADDRESS %INTEGER T,I !************************************************************** !* BUFFER MANAGER CALLS (FROM AND TO) * !************************************************************** %CONSTINTEGER BUFFER HERE = 0 !********** TO BUFFER MANAGER *********** %CONSTINTEGER REQUEST BUFFER = 0 %CONSTINTEGER RELEASE BUFFER = 1 !**************************************************************** !********** VARIOUS SERVICE NUMBERS ************* %CONSTBYTEINTEGERNAME INT = K'160060' %CONSTBYTEINTEGERNAME OWN ID = K'160030' %CONSTINTEGER RING SER = 10 %CONSTINTEGER BUFFER MANAGER = 17 %CONSTINTEGER TIME INT = 0 %CONSTBYTEINTEGER TX INT = -6; %CONSTBYTEINTEGER RX INT = -7; %CONSTBYTEINTEGERNAME CHANGE OUT ZERO = K'160310' %CONSTINTEGER T3 SER = 21 !************************************************************ %RECORD (PE)P; !INPUT PON RECORD %RECORD (PE2) %NAME P1; !POINTS TO P %RECORD (PE) OP; !OUTPUT PON RECORD %OWNINTEGER X !!#SRETRY STATISTICS VARIABLES !%OWNINTEGERARRAY RHIST(0:6); !#S !%OWNINTEGER RCOUNT; !#S ! !#S COUNTS OF I/O PKTS AND INTERRUPTS; !%OWNINTEGER IP,OPKTS,INTS; !#S !#E IF # 0 THEN A TRANSMISSION ERROR IS %OWNINTEGER EFLAG = 0; !#E !#E GENERATED ON EVERY 100'TH PACKET !#E EFAG IS TOGGLED WIUTH INT(E) %OWNINTEGER ECOUNT = 0; !#E %OWNINTEGER MON = 0 %OWNINTEGER INTLOOP = 10 %CONSTINTEGER TRACELIM = 1023; !#T KEEP TO A POWER OF 2 -1 !#T %RECORDFORMAT TRACEF(%BYTEINTEGER TYPE,%INTEGER DATA); %OWNRECORD (TRACEF) %ARRAY TRACE(0:TRACELIM); !#T %OWNINTEGER TRACEP = 0; !#T %OWNINTEGER TSENT=0; !#T !%OWNRECORD (PE) %ARRAY PTRACE(0:300) !%OWNINTEGER PTP=0 %OWNINTEGER STATE=0 !VALUES OF STATE %CONSTINTEGER CLOSED=0; !BEFORE FIRST ENTRY %CONSTINTEGER ON=1; !NORMAL STATE %CONSTINTEGER OFF=2; !RING OFFLINE %OWNINTEGER DSTATE=0; !DYNAMIC STATE (ONE OF THE VALUES BELOW) !VALUES FOR DSTATE %CONSTINTEGER IDLE=0 %CONSTINTEGER INPUTTING=1 %CONSTINTEGER OUTPUTTING=2 !DATA USED DURING AN INPUT TRANSFER !---------------------------------- %OWNRECORD (MEF) %NAME INBUF %OWNINTEGER PORT,CSFLAG %OWNRECORD (MEF) %NAME INBUFQ %CONSTINTEGER MAXLEN=125; !250 BYTES OF DATA MAX %CONSTINTEGER NIBUFREQD=8; !NUMBER OF INPUT BUFFERS IN POOL !DATA ACCESSED IN CODE THEREFORE IN FIXED LOCATION THE GLA %CONSTINTEGERNAME CS=K'140016'; !CHECKSUM !DATA USED DURING OUTPUT TRANSFER !--------------------------------- %OWNRECORD (PE) OUTP %OWNRECORD (PE2) %NAME OUTPP; !POINTS TO OUTP %OWNINTEGERARRAYNAME BUF %OWNINTEGER DEST, PKTCOUNT, PKTLEN, TOUT, %C OUTCS, D, ORETRY, FUNC; !OUTCS#0 => CHECKSUM REQD %CONSTINTEGER MAXRETRIES=500; !MAX NUMBER OF RETRIES OF !A SINGLE PACKET !DATA USED FOR PORT-PAIRS LIST !----------------------------- !EACH RECORD CONTAINS A PORT RANGE (LOW, HIGH) AND THE ID !OF THE TASK THAT WILL HANDLE INPUT ON A PORT IN THIS RANGE %RECORDFORMAT PPF(%INTEGER LPORT, HPORT, %BYTEINTEGER REPLY) %CONSTINTEGER NPPMAX=8 %OWNRECORD (PPF) %ARRAY PPA(1:NPPMAX) %OWNINTEGER NPP=0 %OWNRECORD (PPF) %NAME PP !DATA USED FOR OUTPUT PON QUEUE !------------------------------ !ALL THE PQ RECORDS ARE ON A CYCLIC LIST, PQFIRST AND PQLAST POINT !TO THE HEAD AND TAIL OF THE Q, NPQ TELLS HOW MANY ITEMS ARE ON THE Q. %RECORDFORMAT PQF( %RECORD (PQF) %NAME LINK, %RECORD (PE) P) %CONSTINTEGER MAXNPQ=32 %OWNRECORD (PQF) %ARRAY PQ(1:MAXNPQ) %OWNRECORD (PQF) %NAME PQFIRST, PQLAST %OWNINTEGER NPQ=0 !DATA DEFINING CANNED COMMANDS (RDY, NODATA ETC.) !DATA DEFINING 'CANNED' BYTE STREAM COMMANDS RDY ETC. THE COMMAND IS !PUT INTO THE ARRAY CCBUF, CCBUF(0) IS THE PORT NUMBER, CCBUF(1) IS !THE RECEIVER COMMAND SET FROM THE RECCOM ARRAY, AND CCBUF(2) IS THE !TRANSMITTER COMMAND SET FROM TRANCOM ARRAY. THE ARRAY SINDEX GIVES THE POSITION !IN CCBUF OF THE SEQUENCE NUMBER IF REQD. %OWNINTEGERARRAY CCBUF(0:2) %CONSTINTEGERARRAY RECCOM(XRDY:XCLOSEREQ)=RDY, %C NOTRDY, 0, CLOSE, RESET, 0 %CONSTINTEGERARRAY TRANCOM(XRDY:XCLOSEREQ)=0, %C 0, NODATA, 0, 0, X'A004'; !DATA+CLOSEREQ %CONSTBYTEINTEGERARRAY SINDEX(XRDY:XCLOSEREQ)=1,1,2,0,0,2 %RECORD (R1F)R1; %RECORD (R2F) %NAME R2; %RECORD (R3F) %NAME R3 %RECORD (R4F) %NAME R4 !%ROUTINESPEC PONT(%RECORD (PE) %NAME P) %ROUTINESPEC DO TIMEOUT %ROUTINESPEC FREEBUFFER(%RECORD (MEF) %NAME MES) %ROUTINESPEC GETBUFFER %ROUTINESPEC INITIALIZE %ROUTINESPEC INPUT DONE(%INTEGER FUNCTION) %ROUTINESPEC DISPORTS %ROUTINESPEC PUTTRACE; !#T %ROUTINESPEC PUTHEX(%INTEGER D); !#T !! %PERMRECORD (MEF) %MAPSPEC POP(%RECORD (QF) %NAME Q) !! %PERMROUTINESPEC PUSH(%RECORD (QF) %NAME Q, %RECORD (MEF) %NAME E) !********************************************** !* INITIALISATION * !********************************************** MAP HWR(3); ! MAP TOP SEG TO SEG 3 MAP VIRT(BUFFER MANAGER, 5, 4); ! MAP TO MY SEG 4 MAP VIRT(BUFFER MANAGER, 6, 5) R2 == R1; R3 == R2; R4 == R3 LINKIN(RING SER) LINKIN(TX INT);; LINKIN(RX INT) CHANGE OUT ZERO = T3 SER INITIALIZE; !INITIALISE DATA STRUCTURES !GET INPUT BUFFERS %CYCLE I=1,1,NIBUFREQD GETBUFFER %REPEAT ALARM(20) %CYCLE P_SER = 0; POFF(P) %IF P_SER = OWN ID %START; %IF P_REPLY=0 %START; !CLOCK CALL ALARM(20) TIME=TIME+1 %IF TIME=0 %THEN TIME=1; !TIME=0 => TIME NOT SET !IF RING DOWN ABORT ALL THE BYTE STREAMS %IF RING_INTSTAT & ONOFF = 0 %START DO TIMEOUT; !ABORT CURRENT TRANSFER (IF ANY) %IF STATE=ON %START %CYCLE I=1,1,5 PRINTSTRING("****************** RING SWITCHED OFF") NEWLINE %REPEAT !SEND MESSAGE THAT RING DOWN %CYCLE I=1,1,NPP OP_SER=PPA(I)_REPLY OP_REPLY=RING SER OP_FN=RING DOWN ! PONT(OP) PON(OP) %REPEAT STATE=OFF %FINISH %ELSE %IF STATE=OFF %START PRINTSTRING("RING ONLINE") !CALCULATE MY RING ADDRESS ME=0 %CYCLE I=1,1,254 RING_SOURCESELECT=I RING_INTSTAT=RING_INTSTAT ! RECEIVE RING_DEST=I RING_TDATA=X'F0F0' %WHILE RING_INTSTAT & TREADY=0 %CYCLE %REPEAT %IF RING_INTSTAT#0 %AND RING_RDATA= %C X'F0F0' %THEN ME=I %ANDEXIT %REPEAT WRITE(ME, 3) NEWLINE STATE=ON !INITIALIZE RING INTERFACE RING_INTSTAT=RING_INTSTAT ! %C ( RECEIVE+IPROFF+IPTOFF+RINTON) RING_SOURCESELECT=-1 %FINISH %FINISH %IF 'M' <= INT <= 'P' %START MON = INT-'O'; INT = 0 %FINISH ! X = X+1; !#S ! %IF X >= 150 %START; !#S %IF MON>0 %START; !#S ! PRINTSTRING("RING:"); !#S ! WRITE(RCOUNT, 5); !#S ! %CYCLE I=0,1,6; !#S ! WRITE(RHIST(I),4); !#S ! %REPEAT; !#S ! WRITE(IP,4); !#S ! WRITE(OPKTS, 4); !#S ! WRITE(INTS, 4); !#S ! NEWLINE; !#S %FINISH; !#S ! RCOUNT=0; !#S ! X=0; !#S ! IP=0; !#S ! OPKTS=0; !#S ! INTS=0; !#S ! %CYCLE I=0,1,6; !#S ! RHIST(I)=0; !#S ! %REPEAT; !#S ! %FINISH; !#S %IF INT = 'E' %START; !#E EFLAG = (EFLAG + 1) & 1; !#E PRINTSTRING("EFLAG="); !#E WRITE(EFLAG,1); !#E NEWLINE; !#E INT=0; !#E %FINISH; !#E %IF INT='T' %START; !#T PUTTRACE; !#T INT = 0; !#T %FINISH; !#T ! TRACE(TRACEP)_TYPE='S'; !#T ! TRACE(TRACEP)_DATA=TIME; !#T ! TRACEP=(TRACEP+1) & TRACELIM; !#T %IF TOUT#0 %AND TIME-TOUT>TIMEOUT %THEN DO TIMEOUT %ELSE; !FROM BUFFER MANAGER ! PONT(P) !LINK BUFFER ONTO INPUT Q P_MES_LINK==INBUFQ INBUFQ==P_MES %FINISH %ELSE %IF P_SER=RING SER %START ! PONT(P) !DECODE 'NORMAL' PON MESSAGE %IF P_FN=ENABLE PORT %START %IF NPP >= NPPMAX %START PRINTSTRING("RING:TOO MANY PORTS") NEWLINE %ELSE !ADD PORT PAIR TO LIST NPP=NPP+1 PP==PPA(NPP) PP_LPORT=P1_LPORT PP_HPORT=P1_HPORT PP_REPLY=P1_REPLY %IF STATE=CLOSED %START !IF THIS IS THE FIRST ENTRY, SETUP !STATE ACCORDING TO THE INVERSE OF ONOFF !SO THAT THE STATE CHANGE IS RECOGNISED %IF RING_INTSTAT & ONOFF=0 %THENC STATE=ON %C %ELSEC STATE=OFF %ELSE %IF STATE=OFF %START OP_SER=P_REPLY OP_REPLY=RING SER OP_FN=RING DOWN ! PONT(OP) PON(OP) %FINISH %FINISH %FINISH %ELSE %IF P_FN=DISABLE PORT %THEN DIS PORTS %AND %CONTINUE %IF P_FN=OUTPUT TRACE %START %IF TSENT=0 %THEN PUTTRACE; !#T TSENT=1; !#T %ELSE !ASSUME OUTPUT REQUEST %IF NPQMAXRETRIES %START DO TIMEOUT %CONTINUE %FINISH RING_INTSTAT=RING_INTSTAT ! TRANSMIT;!SEND IT AGAIN ORETRY=ORETRY+1 I=0 %ELSE ! %IF ORETRY<6 %START; !#S ! RHIST(ORETRY)=RHIST(ORETRY)+1 ; !#S ! %ELSE; !#S ! RHIST(6)=RHIST(6)+1; !#S ! %FINISH; !#S ! RCOUNT=RCOUNT+ORETRY; !#S %IF PKTCOUNT1000 %START; !#E D=D+1; !#E CORRUPT THE DATA ECOUNT=0; !#E TRACE(TRACEP)_TYPE='E'; !#E TRACE(TRACEP)_DATA=0; !#E TRACEP=(TRACEP+1)&TRACELIM; !#E %FINISH; !#E %FINISH; !#E RING_TDATA=D I=0 ORETRY=0 PKTCOUNT=PKTCOUNT+1 %ELSE %IF PKTCOUNT=PKTLEN %AND OUTCS#0 %START D=CS %IF OUTP_FN&CS0FLAG#0 %THEN D=0 -> PUTOUT %FINISH !END OF OUTPUT TRANSFER !---------------------- END OUTPUT: DSTATE=IDLE TOUT=0 %IF OUTP_FN & RELEASE FLAG # 0 %THEN %C FREEBUFFER(OUTP_MES) %IF OUTP_FN & TELL FLAG # 0 %START OP_SER=OUTP_REPLY OP_REPLY=RING SER OP_FN=OUTPUT DONE PON(OP) %FINISH %FINISH %FINISH %FINISH %ELSE %IF DSTATE=INPUTTING %START %IF RING_INTSTAT & REPA=0 %THEN %CONTINUE D=RING_RDATA TRACE(TRACEP)_TYPE='I'; !#T TRACE(TRACEP)_DATA=D; !#T TRACEP=(TRACEP+1) & TRACELIM; !#T ! IP=IP+1; !#S !LOOK TO SEE IF PORT FIELD LOOKS LIKE A HEADER AND IF SO START TRANSFER !FROM HERE %IF PKTCOUNT=0 %START %IF D&X'F800'=LONGBLOCK %THEN ->START INP %FINISH %IF EFLAG # 0 %START; !#E ECOUNT=ECOUNT+1; !#E %IF ECOUNT>1000 %START; !#E ECOUNT=0; !#E D=D+1; !#E TRACE(TRACEP)_TYPE='F'; !#E TRACEP=(TRACEP+1)&TRACELIM; !#E %FINISH; !#E %FINISH; !#E I=0 %IF PKTCOUNTMAXLEN %THEN -> SKIP PKTCOUNT=0 %IF INBUFQ==NIL %START PRINTSTRING("RING:NO BUFFERS") NEWLINE SKIP: RING_INTSTAT=RING_INTSTAT ! RECEIVE %CONTINUE %FINISH INBUF==INBUFQ INBUFQ==INBUFQ_LINK INBUF_LEN=PKTLEN-2 BUF==INBUF_A INBUF_ADDRESS=RING_SOURCE RING_SOURCESELECT=RING_SOURCE RING_INTSTAT=RING_INTSTAT ! RECEIVE DSTATE=INPUTTING CS=D TOUT=TIME I=0 %CONTINUE %FINISH -> SKIP %ELSE %IF (RING_INTSTAT & TREADY#0) %OR (RING_INTSTAT %C & ONOFF = 0) %START !START UP OUTPUT TRANSFER (IF ANY) !---------------------------------- %IF NPQ=0 %THEN %CONTINUE; !NO OUTPUT TO DO OUTP=PQFIRST_P PQFIRST==PQFIRST_LINK; !REMOVE RECORD NPQ=NPQ-1; !FROM OUTPUT Q FUNC=OUTP_FN & COMMAND MASK %IF FUNC=SSOUT %START; !SINGLE SHOT BLOCK DEST=OUTP_MES_ADDRESS PKTCOUNT=1 BUF==OUTP_MES_A PKTLEN=OUTP_MES_LEN %IF PKTLEN=0 %THEN ->END OUTPUT CS=BUF(0); !FIRST PACKET OUTCS=0; !NO CHECKSUM %ELSE %IF FUNCEND OUTPUT %FINISH INBUF==INBUFQ INBUFQ==INBUFQ_LINK INBUF_ADDRESS=ME INBUF_LEN=PKTLEN-2 %CYCLE I=0,1,PKTLEN-1 INBUF_A(I)=BUF(I) %REPEAT BUF==INBUF_A INPUT DONE(R INPUT DONE) ->END OUTPUT %FINISH %FINISH RING_DEST=DEST RING_TDATA=CS TRACE(TRACEP)_TYPE='O'; !#T TRACE(TRACEP)_DATA=CS; !#T TRACEP=(TRACEP+1)&TRACELIM; !#T ORETRY=0 TOUT=TIME DSTATE=OUTPUTTING I=0 %FINISH %FINISH %FINISH %FINISH %REPEAT !NEED TO SWITCH INTERRUPTS BACK ON RING_INTSTAT=RING_INTSTAT ! RINTON %IF DSTATE=OUTPUTTING %THEN RING_INTSTAT=RING_INTSTAT ! TINTON %REPEAT %ROUTINE INPUT DONE( %INTEGER FUNCTION) !------------------- !FIND OUT WHO WANTS INPUT TO THIS PORT %INTEGER PORT,I %RECORD (PPF) %NAME PP PORT=BUF(0) %CYCLE I=NPP,-1,1 PP==PPA(I) %IF PP_LPORT<=PORT<=PP_HPORT %START OP_SER=PP_REPLY OP_REPLY=RING SER OP_FN=FUNCTION %IF FUNCTION=R INPUT DONE %START OP_MES==INBUF ! PONT(OP) PON(OP) GETBUFFER %ELSE ! PONT(OP) PON(OP) %FINISH %RETURN %FINISH %REPEAT !NOBODY WANTS THE INPUT PRINTSTRING("RING:INPUT REJECTED ") WRITE(PORT, 3); WRITE(INBUF_ADDRESS, 3) NEWLINE !RETURN THE INPUT BUFFER TO THE QUEUE INBUF_LINK==INBUFQ INBUFQ==INBUF %END %ROUTINE DO TIMEOUT !---------------- TOUT=0 %IF DSTATE=OUTPUTTING %START PRINTSTRING("RING:OUTPUT TIMEOUT TO") WRITE(DEST,3); NEWLINE OP_SER=OUTP_REPLY OP_REPLY=RING SER OP_FN=TRANSFER ERROR OP_PORT=OUTP_PORT ! PONT(OP) PON(OP) %IF OUTP_FN& RELEASE FLAG # 0 %THEN FREEBUFFER(OUTP_MES) %ELSE %IF DSTATE=INPUTTING %START !SEND MESSAGE IF PORT NUMBER HAS BEEN INPUT %IF PKTCOUNT>0 %THEN INPUTDONE(INPUT ERROR) !RETURN THE INPUT BUFFER INBUF_LINK==INBUFQ INBUFQ==INBUF PRINTSTRING("RING:INPUT TIMEOUT FROM") WRITE(INBUF_ADDRESS,3); NEWLINE RING_INTSTAT=RING_INTSTAT ! RECEIVE RING_SOURCESELECT=-1 %FINISH %FINISH TRACE(TRACEP)_TYPE='X'; !#T TRACE(TRACEP)_DATA=0; !#T TRACEP=(TRACEP+1)&TRACELIM; !#T DSTATE=IDLE %END %ROUTINE INITIALIZE !------------------ %INTEGER I OUTPP==OUTP P1==P; !INITIALISE POINTERS SO CAN ACCESS PON !PON RECORDS IN PE2 FORMAT !INITIALISE PON Q AS CYCLIC LIST PQFIRST==PQ(1) PQLAST==PQ(MAXNPQ) %CYCLE I=1,1,MAXNPQ-1 PQ(I)_LINK==PQ(I+1) %REPEAT PQ(MAXNPQ)_LINK==PQ(1) NPQ=0 %END %ROUTINE FREEBUFFER( %RECORD (MEF) %NAME MES) !----------------------------------------------- OP_SER=BUFFER MANAGER; OP_REPLY=OWN ID OP_FN=RELEASE BUFFER; OP_MES==MES ! PONT(OP) PON(OP) %END %ROUTINE GETBUFFER !----------------- OP_SER=BUFFER MANAGER; OP_REPLY=OWN ID OP_FN=REQUEST BUFFER; OP_LEN=0; !LONG BUFFER !PONT(OP) PON(OP) %END %ROUTINE DISPORTS; !DISABLE PORT BY REMOVING !----------------- !FROM PORT PAIRS LIST %INTEGER I,J %CYCLE I=1,1,NPP PP==PPA(I) %IF PP_LPORT=P1_LPORT %AND PP_HPORT=P1_HPORT %ANDC PP_REPLY=P1_REPLY %START %CYCLE J=I,1,NPP-1 PPA(J)=PPA(J+1) %REPEAT NPP=NPP-1 %RETURN %FINISH %REPEAT %END %ROUTINE PUTHEX(%INTEGER D); !#T !--------------------------; !#T %INTEGER I; !#T %BYTEINTEGER S; !#T PRINTSYMBOL(' '); !#T %CYCLE I=12,-4,0; !#T S=(D>>I)&X'F'; !#T %IF S>9 %THEN S=S-'0'+'A'-10; !#T PRINTSYMBOL(S+'0'); !#T %REPEAT; !#T %END; !#T %ROUTINE PUTTRACE; !#T !----------------; !#T %INTEGER TPLAST,TP,TC; !#T %INTEGER TY,TYPE; !#T TC=0; !#T TP=(TRACEP+1)&TRACELIM; !#T SELECTOUTPUT(1); !#T TYPE=0; !#T %UNTIL TP=TRACEP %CYCLE; !#T TY=TRACE(TP)_TYPE; !#T %IF TY#0 %START; !#T TRACE(TP)_TYPE=0; !#T %IF TY#TYPE %START; !#T NEWLINE; !#T PRINTSTRING("******** "); !#T PRINTSYMBOL(TY); !#T TC=2; !#T TYPE=TY; !#T %FINISH; !#T %IF TC>=16 %THEN NEWLINE %AND TC=0; !#T PUTHEX(TRACE(TP)_DATA); !#T TC=TC+1; !#T %FINISH; !#T TP=(TP+1)&X'3FF'; !#T %REPEAT; !#T NEWLINE; !#T PRINTSTRING("END OF TRACE"); !#T NEWLINE; !#T %CYCLE TC=1,1,40; !#T PRINTSTRING("************"); !#T NEWLINE; !#T %REPEAT; !#T SELECTOUTPUT(0); !#T PRINTSTRING("DONE"); !#T NEWLINE; !#T %END; !#T !%ROUTINE PONT(%RECORD (PE) %NAME P) ! PTRACE(PTP)=P ! PTP=PTP+1 ! %IF PTP>300 %THEN PTP=0 !%END %ENDOFPROGRAM