! COMPILE THIS MODULE WITH 15000 STACK & 0 STREAMS ! RINGRS/RXR ALI AUG 1979 ! CAMBRIDGE RING RECEIVE HANDLER ! USES BSP PROTOCOL. PASSES TX TASKS TO RINGTS/TXR ! SEE RPTS/RPT FOR OPERATOR INTERFACE ! %CONTROL K'100001' %BEGIN %INTEGERARRAY TXBUFFER(0:153) ! %CONSTBYTEINTEGERNAME MY ID = K'160030', INT = K'160060' %CONSTINTEGER ATBLIM=31, PTBLIM=127; ! TRACE BUFFER LIMITS %CONSTINTEGER RINGSER=29,TXRSER=28,TXRDUMPSER=27,TRACESER=26; ! SERVICE NRS %CONSTINTEGER LASTTIMERMAX=7, HLRILIM=2099 ! ! SETTINGS FOR SET TIMER REQUESTS ! %CONSTINTEGER TSTATE E ALARM = 0, RSTATE E ALARM = 1, RBALARM = 2 %CONSTINTEGER ONE SECOND = 50, TENTH SEC = 5, TOLIM=5 ! ! SETTINGS FOR TSTATE & RSTATE ! %CONSTINTEGER TSTATE E = 0, RSTATE E = 0 %CONSTINTEGER TSTATE N = 1, RSTATE N = 1 %CONSTINTEGER TSTATE I = 2, RSTATE I = 2 ! ! RTP HEADERS ! %CONSTINTEGER HEADERA=K'170000',STANDARDA=K'110000',HEADERC=K'1777' %CONSTINTEGER STANDARD PORT = 500 ;! ALWAYS ALLOCATED IF OPENED %CONSTINTEGER STANDARDAB = STANDARDA ;! LONG BLOCK, WITH C/S ! ! SETTINGS FOR PTRAN_ACTION ! %CONSTINTEGER NULL=0,SETADDRESS=1,INPT=2,OUTPT=3,RESET=4 %CONSTINTEGER OPEN=5,CLOSE=6,KILL=7,DIAG=8,REOUTPT=9 ! ! SETTINGS FOR HLERROR ! %CONSTBYTEINTEGER HLOPEN=1, HLIR=2, HLOD=4, HLBUFL=8, %C RIBEENCLOSED=K'20',RIOPENERROR=K'40',RIBEENRESET=K'100' ,%C RITIMEOUT=K'200',RICHECKSUM=K'200',RIUNEXPECTEDCOMMAND=K'200' ! ! EXTRA SETTINGS FOR HLSTATUS ! %CONSTBYTEINTEGER HLSTOP = K'200' ,HLADRSET=K'10';! & HLOPEN,HLIR,HLOD ! ! SETTINGS FOR STATE ! %CONSTINTEGER SNOTSTARTED=-1, SRUN=0, SWAIT4OPEN=1,%C SWAIT4OPENACK=2, SWAIT4RESET=3, SWAIT4CLOSE=4 ! ! BSP COMMANDS ! %CONSTINTEGER BSPDATA=K'120000', BSPNODATA=K'140000', %C BSPRDY=K'30000', BSPNOTRDY=K'50000',%C BSPRESET=K'61400', BSPCLOSE=K'63000' ! %INTEGER ATBPTR,PTBPTR,HLINPUTCOUNT,HLINPUTSPACE,HLTASKNR,TEMP %INTEGER HLSTATUS,HLERROR %INTEGER LASTTIMERENTRY,STATE,TSTATE,RSTATE,TSEQ,RSEQ,%C TALARMS,RALARMS,RBTIMEOUT,HLRIFILL,HLRIEMPTY,DEVADD,%C ALARMSET,INTERNALTXSEQ,HISPORT,I,OUTPTCOUNT,DATALEN ! ! PARAMETERS FOR PON/POFF ! %RECORDFORMAT PF(%BYTEINTEGER SERVICE,REPLY,%INTEGER A1,A2,A3) %RECORDFORMAT PRF(%BYTEINTEGER SERVICE,REPLY,%C ERROR,STATUS,%INTEGER LEN,A3) %RECORDFORMAT PTF(%BYTEINTEGER SERVICE,REPLY, %INTEGER ACTION,%C LEN, %BYTEINTEGERARRAYNAME BUF) %RECORD (PF) P %RECORD (PTF) %NAME PTRAN; ! ==P %RECORD (PRF) %NAME PREPLY; ! == P ! %SWITCH ACTION(NULL:REOUTPT) ! %RECORDFORMAT ATF(%STRINGNAME S,%INTEGER FLAG,A,B) %RECORD (ATF) %ARRAY ACTIONTRACEBUFFER(0:ATBLIM) %INTEGERARRAY PACKETTRACEBUFFER(0:PTBLIM) ! %RECORDFORMAT TQF(%INTEGER COUNT,RTN) %RECORD (TQF) %ARRAY TIMEQ(0:LASTTIMERMAX) ! %INTEGERARRAY DUMMY(0:1) %BYTEINTEGERARRAY HLRINGINPUTBUFFER(0:HLRILIM) %INTEGERARRAYNAME DATABUF ! ! SINGLE SHOT RTP BLOCKS ! %CONSTINTEGER OABLEN=6,OBLEN=6 %OWNINTEGERARRAY OPENBLOCK(0:5) = K'112002',1,K'65000',%C STANDARD PORT,0,0 %OWNINTEGERARRAY OPENACKBLOCK(0:5)=K'112002',0,K'62400',0,0,0 ! ! MDB INTERFACE TO RING. ASSUMED TO BE AT ADDR 764040 ! %RECORDFORMAT HDWRF(%INTEGER RBUFF,SOURCE,SELECTOR,STATUS,TBUFF,%C DEST,SPARE,INTSTATUS) %CONSTRECORD (HDWRF) %NAME HDWR = K'104040' ;! IN SEG 4 ! %RECORDFORMAT PBUFFIF(%BYTEINTEGER S,R,%INTEGER A1,A2,%INTEGERARRAYNAME BUF) %RECORD (PBUFFIF) %NAME PBUFFI ! ! PARAMS TO ACTION TRACE ! %CONSTINTEGER AVALID=2, BVALID=4, ABVALID=6 %CONSTSTRING(23) ATM TSEALARM="T/O AWAITING DATA- " %CONSTSTRING(23) ATM RSEALARM="T/O AWAITING RDY-" %CONSTSTRING(27) ATM SEND="QUEUE TRANSFER OUT. R,T= " %CONSTSTRING(11) ATM DORESET="RESETTING" %CONSTSTRING(31) ATM RDY="RX RDY. MY SEQ,HIS SEQ=" %CONSTSTRING(35) ATM NOTRDY="RX NOTRDY. MY SEQ,HIS SEQ= " %CONSTSTRING(33) ATM DATA1="RX DATA. MY SEQ,HIS SEQ= " %CONSTSTRING(23) ATM DATA2="NON-BSP PACKET COUNT=" %CONSTSTRING(17) ATM DATA3="CLOSE REQUESTED" %CONSTSTRING(35) ATM NODATA="RX NODATA. MY SEQ,HIS SEQ= " %CONSTSTRING(33) ATM OPEN="RX OPEN. HIS PORT,MY ACK=" %CONSTSTRING(37) ATMOPENACK="RX OPENACK. HIS PORT,HIS ACK=" %CONSTSTRING(15) ATM RESET="RX RESET " %CONSTSTRING(15) ATM CLOSE="RX CLOSE " %CONSTSTRING(21) ATM RBALARM="RTP RX TIMEOUT" %CONSTSTRING(27) ATM WTF1="TX COMPLETED OK. INT SEQ=" %CONSTSTRING(23) ATM WTF2="TX TIMEOUT ON INT SEQ" %CONSTSTRING(35) ATM RI="VALID RTP BLOCK. NR DATA PACKETS=" %CONSTSTRING(21) ATM RISTART=" RTP HEADER RECEIVED=" %CONSTSTRING(19) ATM HLACTION="OPERATOR COMMAND:" %CONSTSTRING(13) ATM HLSA="SET ADDRESS" %CONSTSTRING(23) ATM HLIN1="INPUT. MAX BYTECOUNT=" %CONSTSTRING(39) ATM HLIN2="BYTES HANDED ON, BYTES STILL BUFFERED =" %CONSTSTRING(19) ATM HLOUT="OUTPUT. BYTE COUNT=" %CONSTSTRING(5) ATM HLRESET="RESET" %CONSTSTRING(21) ATM HLOPEN="OPEN. FUNCTION CODE =" %CONSTSTRING(5) ATM HLCLOSE="CLOSE" %CONSTSTRING(35) ATM HLREPLY="REPLY TO OPERATOR. STATUS,ERROR= " %CONSTSTRING(31) ATM TRANSMIT="TXFR QUEUED. PACKETS,INT SEQ=" ! %ROUTINESPEC TSEALARM %ROUTINESPEC RSEALARM %ROUTINESPEC RBALRM %ROUTINESPEC MAP BUFFER %BYTEINTEGERFNSPEC HLGETINPUT %ROUTINESPEC SEND(%INTEGER R,T,%INTEGERARRAYNAME D,%INTEGER L) %ROUTINESPEC CANCELTIMER(%INTEGER RTN) %SYSTEMROUTINESPEC ALARM(%INTEGER TICKS) %SYSTEMROUTINESPEC LINKIN(%INTEGER TASK) %SYSTEMROUTINESPEC MAP VIRT(%INTEGER TASK,SEG,MYSEG) %SYSTEMROUTINESPEC MAP HWR(%INTEGER SEG) ! ! ! ! FN DOES DIRTY EMT 20 ! ! %INTEGERFN TOFF(%INTEGER TEMP) *K'010046' ;! STACK R0 *K'104024' *K'010065'; *K'000004'; ! MOV R0,TEMP *K'012600' ;! UNSTACK R0 %RESULT = TEMP %END ! ! ! %ROUTINE WRITEHEX(%INTEGER X) %INTEGER J,K %CYCLE J=12,-4,0 K = (X>>J) & 15 %IF K>9 %THEN PRINTSYMBOL(K-10+'A') %C %ELSE PRINTSYMBOL(K+'0') %REPEAT %END ! ! ! ! RTN FOR KEEPING HISTORY OF MOST RECENT ACTIONS. ! HISTORY IS PRINTED ON FATAL ERROR. EACH ENTRY ! CONTAINS A STRING & POSSIBLY 2 INTEGERS ! %ROUTINE ACTION TRACE (%STRINGNAME S,%INTEGER FLAG,A,B) %RECORD (ATF) %NAME T T == ACTION TRACE BUFFER(ATBPTR) T_S == S T_FLAG = FLAG ! 1 ;! BIT MAP. 1=S VALID, 2=A VALID, 4=B VALID T_A = A T_B = B ATBPTR = ATBPTR + 1 %IF ATBPTR > ATBLIM %THEN ATBPTR = 0 %END ! ! RTN PRINTS UP ACTION TRACEBACK ON FATAL ERROR ! %ROUTINE ACTION BACKTRACE %RECORD (ATF) %NAME T %INTEGER I PRINTSTRING("MOST RECENT ACTIONS:-"); NEWLINE %CYCLE I=0,1,ATBLIM T == ACTION TRACE BUFFER(ATBPTR) %IF (T_FLAG&1) # 0 %START ;! NON-EMPTY ENTRY? PRINTSTRING(T_S); SPACE %IF (T_FLAG&2) # 0 %THEN WRITEHEX(T_A) %AND SPACE %IF (T_FLAG&4) # 0 %THEN WRITEHEX(T_B) NEWLINE %FINISH ATBPTR = ATBPTR + 1 %IF ATBPTR > ATBLIM %THEN ATBPTR = 0 %REPEAT NEWLINE %END ! ! ! RTN PRINTS UP RECEIVED PACKET BACKTRACE ! %ROUTINE PACKET BACKTRACE %INTEGER I,L,P L = 0 PRINTSTRING(" MOST RECENTLY RECEIVED PACKETS:-"); NEWLINE %CYCLE I=0,1,PTBLIM L = (L+1) & 15 P = PACKET TRACE BUFFER(PTBPTR) ;! SEE FN GETRINGDATA WRITEHEX(P) SPACE PTBPTR = PTBPTR + 1 %IF PTBPTR > PTBLIM %THEN PTBPTR = 0 %IF L=0 %THEN NEWLINE %REPEAT NEWLINE %END ! ! ! ! RTN CALLED ON FATAL ERROR TO PASS ANY BUFFERED RING INPUT ! TO HIGHER LEVEL. ! %ROUTINE EMPTY HLINPUT BUFFER %INTEGER I %WHILE HLINPUTCOUNT > 0 %CYCLE P_SERVICE = 0; POFF(P) %IF P_SERVICE # RING SER %THENCONTINUE %IF PTRAN_ACTION = INPT %START MAP BUFFER %IF PTRAN_LEN > HLINPUTCOUNT %THEN PTRAN_LEN=HLINPUTCOUNT %CYCLE I=0,1,PTRAN_LEN - 1 PTRAN_BUF(I) = HL GET INPUT ;! UPDATES HLINPUTCOUNT %REPEAT %FINISH P_SERVICE = P_REPLY P_REPLY = RING SER PREPLY_ERROR = 0 PREPLY_STATUS = HLIR PON(P) %REPEAT %END ! ! ! ! RTN CALLED ON FATAL ERROR. GENERATES DIAGNOSTIC BACKTRACES ! OF RECENT TX/RX PACKETS & ACTIONS. ! %ROUTINE FATAL(%STRING(255) S) %RECORD(PF) P PRINTSTRING("RXR: FATAL ERROR - ") PRINTSTRING(S); NEWLINE; NEWLINE EMPTY HL INPUT BUFFER ACTION BACKTRACE PACKET BACKTRACE ;! RX P_SERVICE = TXR DUMP SER P_REPLY = MY ID P_A1 = 1 PON(P) ;! REQUEST TRANSMIT PACKET BACKTRACE & STOP P_SERVICE = MY ID P_REPLY = TXR DUMP SER POFF(P) ;! WAIT FOR PRINTUP TO COMPLETE %IF HLTASKNR # 0 %START ;! CONTROLLING S/W PREPLY == P ;! LOCAL ONE P_SERVICE = HLTASKNR P_REPLY = RING SER PREPLY_STATUS = HL STOP PREPLY_LEN = 0 PREPLY_ERROR = 0 PON(P) ; PON(P);! TELL HIM TO STOP %FINISH %STOP ;! ALL GONE!! %END ! ! ! ! RTNS FOR IMPLEMENTING TIMEOUTS. ! SINCE I'M ONLY ALLOWED 1 PENDING CALL TO ALARM ! MULTIPLE TIMEOUTS ARE IMPLEMENTED VIA A QUEUE ! OF PENDING EVENTS, ORDERED ON TIME-TO-NEXT-EVENT ! EACH QUEUE ENTRY CONSISTS OF A ROUTINE NR TO BE CALLED ! AND A TIME FIELD. TIMES ARE MEASURED IN 100MILLISEC ! JIFFIES. ! ! SET TIMER SLOTS THE ROUTINE NR 'R' INTO THE TIME QUEUE ! & SETS THE TIME FIELDS IN THE CURRENT & NEXT QUEUE ! ENTRIES TO THE CORRECT ELAPSED TIME BETWEEN THE ! EVENTS (IN 1/10THS OF A SECOND). STARTS ! THE CLOCK IF NECESSARY ! %ROUTINE SET TIMER(%INTEGER R, TIME) %INTEGER I,J,T %IF LAST TIMER ENTRY = LAST TIMER MAX %THEN FATAL(" TIMEQ OFLO") TIME = (TIME+4)//5; ! CONVERT 20->100MSEC & ROUND UP ! %IF LAST TIMER ENTRY >= 0 %START; ! QUEUE NOT EMPTY %CYCLE I=0,1,LASTTIMERENTRY %IF TIMEQ(I)_RTN = R %THEN FATAL("MULTIPLE SET TIMER CALL") %REPEAT T = 0 ;! TIME TO CURRENT EVENT %CYCLE I=0,1,LASTTIMERENTRY T = T + TIMEQ(I)_COUNT %IF TIME < T %START T = T-TIMEQ(I)_COUNT ;! ELAPSED TIME TO THIS ENTRY %CYCLE J=LASTTIMERENTRY,-1,I TIMEQ(J+1) = TIMEQ(J) ;! RECORD COPY TO CREATE HOLE %REPEAT TIMEQ(I)_RTN = R TIMEQ(I)_COUNT = TIME-T; ! TIME BETWEEN PREVIOUS EVENT & THIS ONE TIMEQ(I+1)_COUNT = TIMEQ(I+1)_COUNT - TIMEQ(I)_COUNT LAST TIMER ENTRY = LAST TIMER ENTRY + 1 %RETURN %FINISH %REPEAT TIMEQ(LASTTIMERENTRY+1)_RTN = R; ! ADD TO END OF QUEUE TIMEQ(LASTTIMERENTRY+1)_COUNT = TIME - T ! %ELSE ;! QUEUE EMPTY TIMEQ(0)_RTN = R TIMEQ(0)_COUNT = TIME %IF ALARM SET = 0 %THEN ALARM(TENTH SEC) %AND ALARM SET = 1 %FINISH ! LAST TIMER ENTRY = LAST TIMER ENTRY + 1 ;! RECORD OFFSET %END ! ! ! ! RTN LOOKS UP R ON TIMEQ & IF FOUND DELETES ENTRY ! %ROUTINE CANCEL TIMER (%INTEGER R) %INTEGER I,J ! %IF LAST TIMER ENTRY >= 0 %START %CYCLE I=0,1,LASTTIMERENTRY %IF TIMEQ(I)_RTN = R %START %IF I # LAST TIMER ENTRY %START TIMEQ(I+1)_COUNT = TIMEQ(I+1)_COUNT + TIMEQ(I)_COUNT %CYCLE J=I+1,1,LASTTIMERENTRY TIMEQ(J-1) = TIMEQ(J); ! RECORD COPY %REPEAT %FINISH LAST TIMER ENTRY = LAST TIMER ENTRY - 1 %RETURN %FINISH %REPEAT %FINISH %END ! ! ! ! RTN CALLED ON CLOCK INTERRUPT (100 MILLISECONDS) ! %ROUTINE CLOCK INTERRUPT %INTEGER I,RTN %SWITCH CALL(0:2) ! ALARM SET = 0; ! GLOBAL FLAGS CLOCKINT PENDING %IF LAST TIMER ENTRY < 0 %THENRETURN ;! CASE OF CANCELLING LAST ENTRY ! TIMEQ(0)_COUNT = TIMEQ(0)_COUNT - 1 ! %IF TIMEQ(0)_COUNT <= 0 %START RTN = TIMEQ(0)_RTN %IF LAST TIMER ENTRY > 0 %START %CYCLE I=1,1,LAST TIMER ENTRY TIMEQ(I-1) = TIMEQ(I) ;! COLLAPSE QUEUE %REPEAT %FINISH LAST TIMER ENTRY = LAST TIMER ENTRY - 1 -> CALL(RTN) CALL(TSTATE E ALARM): TSE ALARM -> CI1 CALL(RSTATE E ALARM): RSE ALARM -> CI1 CALL(RB ALARM): RB ALRM %FINISH ! CI1: %IF ALARMSET = 0 %THEN ALARM(TENTH SEC) %AND ALARMSET=1 %END ! ! ! ! RTNS MAPPED ON P1 TO SET TIMER ! %ROUTINE TSE ALARM TALARMS = TALARMS + 1 %IF TALARMS > TO LIM %THEN FATAL("NO REPLY TO MY DATA") ACTION TRACE(ATM TSEALARM, AVALID, TSEQ, 0) SEND(0,(BSPDATA+(TSEQ<<8))!(DATALEN&1),DATABUF,(DATALEN+1)//2); !RETRANSMIT DATA-N SET TIMER(TSTATE E ALARM, ONE SECOND) %END ! ! %ROUTINE RSE ALARM RALARMS = RALARMS + 1 %IF RALARMS > TO LIM %THEN FATAL(" NO REPLY TO MY READY") ACTION TRACE(ATM RSE ALARM, AVALID, RSEQ, 0) SEND(BSPRDY+(RSEQ<<8),0,DUMMY,0) SET TIMER(RSTATE E ALARM,ONE SECOND) %END ! ! %ROUTINE RB ALRM ACTION TRACE(ATM RBALARM, 0, 0, 0) RBTIMEOUT = 1 %END ! ! ! ! RTN PASSES COUNT PACKETS IN BUF TO TASK TXR/RINGTS ! TXR WILL PON A REPLY BACK TO ME ON TRACE SER TO ! INDICATE SUCCESS, TIMEOUT, OR FATAL ERROR. NOTE THAT ! TX TIMEOUTS ARE ONLY LOGGED, AS NORMAL 1 SEC TIMEOUT ! IN BSP PROTOCOL AT EACH END OF THE RING CONNECTION ! WILL GENERATE RETRANSMITS. ! %ROUTINE TRANSMIT(%INTEGERARRAYNAME BUF,%INTEGER COUNT) %RECORDFORMAT PT(%BYTEINTEGER S,R,%INTEGERARRAYNAME B,%INTEGER C,A) %RECORD (PT) P %OWNINTEGER FIRST=1 P_S = TXR SER P_R = MY ID %IF FIRST # 0 %START ;! SEND DEST STN ADDR P_A = DEV ADD FIRST = 0 %ELSE INTERNAL TX SEQ = INTERNAL TX SEQ + 1 P_A = INTERNAL TX SEQ %FINISH P_B == BUF P_C = COUNT PON(P) P_S = MY ID P_R = TXR SER POFF(P) ACTION TRACE(ATM TRANSMIT, ABVALID, COUNT, INTERNALTXSEQ) %END ! ! ! ! DIRTY M/C RTN FOR DOING AN ADC ! %INTEGERFN SUM WITH CARRY(%INTEGER A,B) A = A + B *K'005565'; *K'000006'; ! ADC 6(R5) %RESULT = A %END ! ! ! ! RTN ADDS HEADER & CHECKSUM TO BSP TXFR & PASSES BLOCK ON TO ! TRANSMIT. ! %ROUTINE SEND(%INTEGER R,T,%INTEGERARRAYNAME DATABUF,%INTEGER COUNT) %INTEGER I,PACKETS,CHECK ! ACTION TRACE(ATM SEND, ABVALID, R, T) TXBUFFER(0) = STANDARDAB ! ((COUNT+1)&K'1777') TXBUFFER(1) = HIS PORT TXBUFFER(2) = R TXBUFFER(3) = T %IF COUNT > 150 %THEN FATAL("TX COUNT TOO BIG ") %IF COUNT > 0 %START %CYCLE I=0,1,COUNT-1 TXBUFFER(I+4) = DATABUF(I) %REPEAT PACKETS = COUNT + 5 %ELSE PACKETS = 5 %FINISH CHECK = 0 %CYCLE I=0,1,PACKETS-2 CHECK = SUM WITH CARRY(TXBUFFER(I),CHECK) %REPEAT TXBUFFER(PACKETS-1) = CHECK TRANSMIT(TXBUFFER,PACKETS) %END ! ! ! ! RTN CALLED WHEN BSP RESET RECEIVED & ON OPEN ! %ROUTINE DO RESET ACTION TRACE(ATM DORESET, 0, 0, 0) STATE = SRUN ;! FLAG NOW RUNNING BSP HLSTATUS = HLOPEN + HLADRSET ;! FOR HIGHER LEVEL S/W LAST TIMER ENTRY = -1 ;! CANCEL ALL TIMEOUTS TSTATE = TSTATE I ;! BSP TX STATE VARIABLE TSEQ = 15 ;! TX SEQUENCE COUNT (= -1) OUTPT COUNT = 0 TALARMS = 0 ;! COUNTER FOR TSTATE E TIMEOUTS HLRIEMPTY=0; HLINPUTCOUNT=0 HLRIFILL=0 ; HLINPUTSPACE=HLRILIM+1 ;! DROP ALL BUFFERED RING INPUT RSTATE = RSTATE E ;! BSP RX STATE VARIABLE RSEQ = 0 ;! RX SEQUENCE COUNT RALARMS = 0; ! COUNTER FOR RSTATE E TIMEOUTS SEND(BSPRDY,0,DUMMY,0) ;! TELL OTHER END I'M READY FOR DATA-0 SET TIMER(RSTATE E ALARM, ONE SECOND) %END ! ! ! ! RTN BUFFERS 1 BYTE READY FOR PASSING ON TO HIGHER LEVEL, ! SINCE HL MAY BE A SLOW PRINTING RTN E.G. ! %ROUTINE HL SAVE INPUT(%BYTEINTEGER B) HLRINGINPUT BUFFER(HLRIFILL) = B HLRIFILL = HLRIFILL + 1 %IF HLRIFILL > HLRILIM %THEN HLRIFILL = 0 HL INPUTCOUNT = HL INPUTCOUNT + 1 HL INPUTSPACE = HL INPUTSPACE -1 %END ! ! ! FN RETURNS NEXT BYTE OF BUFFERED RING INPUT DATA ! FOR PASSING TO HIGHER LEVEL S/W ! %BYTEINTEGERFN HL GET INPUT %INTEGER B B = HL RING INPUT BUFFER(HLRIEMPTY) HLRIEMPTY = HLRIEMPTY + 1 %IF HLRIEMPTY > HLRILIM %THEN HLRIEMPTY = 0 HLINPUTCOUNT = HLINPUTCOUNT - 1 HLINPUTSPACE = HLINPUTSPACE + 1 %RESULT = B %END ! ! ! ! THE NEXT 4 ROUTINES EACH ACTION 1 OF THE BSP COMMANDS ! THEY USE THE STATE VARIABLES TSTATE/RSTATE & THE ! SEQUENCE NUMBERS TSEQ/RSEQ TO IMPLEMENT THE FINITE STATE ! MACHINE DESCRIBED IN BSP DOCUMENTATION ! %INTEGERFN DECODE RDY(%INTEGER RC) ;!RC=RX COMMAND FIELD %INTEGER HIS RSEQ %SWITCH RDY(0:2) ! HIS RSEQ = (RC>>8) & 15 ACTION TRACE(ATM RDY, ABVALID, TSEQ, HISRSEQ) TALARMS = 0; ! NR TIMEOUTS AWAITING RDY (SEE TSTATE E ALARM) -> RDY(TSTATE) ! RDY(TSTATE E): ;! AWAITING ESSENTIAL ELEMENT CANCEL TIMER(TSTATE E ALARM) %IF TSEQ = HIS RSEQ %START; ! REQUEST TO TX LAST BLOCK AGAIN SEND(0,(BSPDATA+(TSEQ<<8))!(DATALEN&1),DATABUF,(DATALEN+1)//2) SET TIMER(TSTATE E ALARM, ONE SECOND) %ELSE; ! HE NOW WANTS DATA N+1 RN1: TSEQ = (TSEQ+1) & 15 ;! ADVANCE SEQUENCE COUNT %IF TSEQ # HIS RSEQ %THEN FATAL("RDY SEQ ERROR") %IF OUTPT COUNT <= 0 %START SEND(0,BSPNODATA+(TSEQ<<8),DUMMY,0) TSTATE = TSTATE N ;! I'VE SENT NON-ESSENTIAL ELEMENT HLSTATUS = HLSTATUS ! HL OD ;! OUTPUT DONE TO HIGHER LEVEL %ELSE ;! HAD ACTION = REOUTPT DATABUF OUTPT COUNT TIMES SEND(0,(BSPDATA+(TSEQ<<8))!(DATALEN&1),DATABUF,(DATALEN+1)//2) TALARMS = 0 SET TIMER(TSTATE E ALARM,ONE SECOND) TSTATE = TSTATE E OUTPT COUNT = OUTPT COUNT - 1 %FINISH %FINISH %RESULT = 0 ! RDY(TSTATE N): ;! MUST BE RETRANSMIT REQUEST %IF TSEQ # HIS RSEQ %THEN FATAL(" REC RDY IN STATE N") SEND(0,BSPNODATA+(TSEQ<<8),DUMMY,0) %RESULT = 0 ! RDY(TSTATE I): ;! I-STATE ENTERED VIA DECODENOTRDY %IF TSEQ = HIS RSEQ %THEN FATAL(" REC RDY N IN STATE I") -> RN1 ;! HE'S NOW RDY 4 DATA N+1 %END ! ! %INTEGERFN DECODE NOTRDY(%INTEGER RC) %INTEGER HIS RSEQ HIS RSEQ = (RC>>8) & 15 ACTION TRACE(ATM NOTRDY, ABVALID, TSEQ, HISRSEQ) CANCEL TIMER(TSTATE E ALARM) %IF TSTATE = TSTATE N %THEN FATAL("REC NOTRDY IN STATE N") %IF ((TSEQ+1)&15) # HIS RSEQ %THEN FATAL(" NOTRDY SEQ ERROR") TSTATE = TSTATE I; !& WAIT 4 RDY N+1 %RESULT = 0 %END ! ! %INTEGERFN DECODE DATA(%INTEGER TC,RBMAX,%INTEGERARRAYNAME RB) %INTEGER HIS TSEQ,I %SWITCH DATA(0:2) ! HIS TSEQ = (TC>>8) & 15 ACTION TRACE(ATM DATA1, ABVALID, RSEQ, HISTSEQ) RALARMS = 0 ;! TIMEOUT COUNTER %IF HIS TSEQ # RSEQ %AND ((HIS TSEQ+1)&15) # RSEQ %THENC FATAL(" DATA SEQ ERROR") -> DATA(RSTATE) ! DATA(RSTATE E): CANCEL TIMER(RSTATE E ALARM) %IF HIS TSEQ = RSEQ %THEN -> NDN %ELSESTART SEND(BSPRDY+(RSEQ<<8),0,DUMMY,0); !REPEAT MY RDY COMMAND SET TIMER(RSTATE E ALARM, ONE SECOND) %RESULT = 0 %FINISH ! DATA(RSTATE N): %IF HIS TSEQ = RSEQ %THEN FATAL("REC DATA N IN STATE N") SEND(BSPNOTRDY+(RSEQ<<8),0,DUMMY,0) %RESULT = 0 ! DATA(RSTATE I): %IF HIS TSEQ # RSEQ %THEN FATAL("REC DATA N-1 IN STATE I") NDN: ;! NEW DATA-N ACTION TRACE(ATM DATA2, AVALID, RBMAX-3, 0) %IF RBMAX > 3 %START ;! SAVE ANY NON-BSP DATA FOR HIGHER LEVEL %CYCLE I=4,1,RBMAX HLSAVEINPUT(RB(I)>>8) %UNLESS I=RBMAX %AND (TC&1)#0 %THEN HLSAVEINPUT(RB(I)) %REPEAT HLSTATUS = HLSTATUS ! HL IR ;! FLAG INPUT READY %FINISH ! RSEQ = (RSEQ+1) & 15; ! ADVANCE SEQUENCE COUNT %IF HLINPUTSPACE > 2043 %START ;! BUFFER SPACE 4 ANOTHER TXFR? SEND(BSPRDY+(RSEQ<<8),0,DUMMY,0) ;! ESSENTIAL ELEMENT SET TIMER(RSTATE E ALARM, ONE SECOND) RSTATE = RSTATE E %ELSE SEND(BSPNOTRDY+(RSEQ<<8),0,DUMMY,0) RSTATE = RSTATE N ;! I SEND RDY WHEN HIGHER LEVEL EMPTIES MY BUFFER %FINISH ! %IF (TC & 4) # 0 %START ;! CLOSE REQUEST ACTION TRACE(ATM DATA3, 0,0,0) HLSTATUS = HLSTATUS & (\(HLOPEN + HLOD)) SEND(BSPCLOSE,0,DUMMY,0) STATE = SWAIT 4 CLOSE %RESULT = RI BEEN CLOSED %FINISH %RESULT = 0 %END ! ! %INTEGERFN DECODE NODATA(%INTEGER TC) %INTEGER HIS TSEQ %SWITCH NODATA(0:2) ! HIS TSEQ = (TC>>8) & 15 ACTION TRACE(ATM NODATA, ABVALID, RSEQ, HISTSEQ) %IF HIS TSEQ # RSEQ %THEN FATAL(" NODATA SEQ ERROR") -> NODATA(RSTATE) ! NODATA(RSTATE N): FATAL("REC NODATA IN STATE N") NODATA(RSTATE E): CANCEL TIMER(RSTATE E ALARM) RSTATE = RSTATE I NODATA(RSTATE I): %RESULT = 0 %END ! ! ! ! RTN ACTIONS SPECIAL R COMMANDS (TYPE=6). ! OPEN/OPENACK/RESET/CLOSE ! %INTEGERFN DECODE SPECIAL RC(%INTEGER RC,RBMAX,%INTEGERARRAYNAME RB) %INTEGER RES,TYPE,OPENERR,I ! TYPE = (RC>>8) & 15 ;! WHAT SORT OF SPECIAL COMMAND IS IT? %IF TYPE = 10 %START ;! OPEN RB(0)=RB(0) ! K'2000' ;! ADD C/S/BIT OPENERR = 0 %IF STATE # SWAIT 4 OPEN %THEN OPENERR = RI OPENERROR %CYCLE I=0,1,2 %IF RB(I) # OPENBLOCK(I) %THEN OPENERR = RI OPENERROR %REPEAT HIS PORT = RB(3) ACTION TRACE(ATM OPEN, ABVALID, HISPORT, OPENERR) %IF RB(1) # 1 %THEN FATAL(" OPEN NOT ON PORT 1") OPEN ACK BLOCK(1) = HIS PORT OPEN ACK BLOCK(3) = STANDARD PORT OPEN ACK BLOCK(4) = OPENERR ;! =0 IF OK TRANSMIT(OPENACKBLOCK, OABLEN) %IF OPENERR=0 %THEN DO RESET ;! & ENTER SRUN STATE %RESULT = OPENERR %FINISH; ! OPEN ! %IF RB(1) # STANDARD PORT %THEN FATAL("INPUT ON WRONG PORT") ! %IF TYPE = 5 %START ;! OPEN ACK %IF STATE # SWAIT 4 OPENACK %THENC FATAL("UNEXPECTED OPENACK RECEIVED") HIS PORT = RB(3) ACTION TRACE(ATM OPENACK, ABVALID, HISPORT, RB(4)) %IF RB(4) # 0 %THEN FATAL("OPENACK DUD RETURN CODE") DO RESET %RESULT = 0 %FINISH; ! OPENACK ! %IF TYPE = 3 %START; ! RESET ACTION TRACE(ATM RESET, 0,0,0) %IF STATE = SWAIT 4 RESET %START ;! REPLY TO MY RESET DO RESET %RESULT = 0 %FINISH %IF STATE # SRUN %THEN FATAL("UNEXPECTED RESET RECEIVED") SEND(BSPRESET,0,DUMMY,0) DO RESET %RESULT = RI BEENRESET %FINISH; ! RESET ! %IF TYPE = 6 %START ;! CLOSE LAST TIMER ENTRY = -1 ;! CANCEL ALL TIMEOUTS ACTION TRACE(ATM CLOSE, 0,0,0) %IF STATE # SWAIT 4 CLOSE %START; ! INITIATED BY OTHER END SEND(BSPCLOSE,0,DUMMY,0) %FINISH STATE = SWAIT 4 OPEN HLSTATUS = HLSTATUS & (\(HLOPEN+HLOD)) ;! FOR HIGHER LEVEL %RESULT = RI BEEN CLOSED %FINISH; ! CLOSE ! FATAL(" UNKNOWN R FIELD RECEIVED") %RESULT = 0 ;! JUST TO SHUT COMPILER UP! %END ! ! ! ! FN TAKES A PACKET FROM RING HARDWARE ( CHECK RDY B4 CALL) ! %INTEGERFN GET RING DATA %INTEGER D D = HDWR_RBUFF HDWR_INTSTATUS = HDWR_INTSTATUS ! 1 ;! READY PACKET TRACE BUFFER (PTBPTR) = D ;! 4 DEBUG ON FATAL PTBPTR = PTBPTR + 1 %IF PTBPTR > PTBLIM %THEN PTBPTR = 0 %RESULT = D %END ! ! ! ! FN CHECKS TO SEE IF RING HARDWARE HAS DATA READY. IF NOT, OR IF ! DATA ISN'T A STANDARD RTP HEADER, RETURNS ! IF HEADER OK, READS WHOLE RTP BLOCK INTO RECBUF (OR DISCARDS ! IF TIMEOUT/CHECKSUM ERROR) ! CALLS RTNS TO PERFORM BSP DECODE ! RESULT IS A BIT MAP OF ERRORS & WARNINGS ! %INTEGERFN RING INPUT %INTEGER I,R,HEADER,FIELDB,FIELDC,DOCHECKSUM,CHECKSUM,%C RC,RCTYPE,TC,TCTYPE,RECDATAEND %INTEGERARRAY RECBUF(0:1026) %SWITCH BSWI(0:3) ! R = 0; ! FOR RESULT WAIT HDR: %IF HDWR_INTSTATUS >= 0 %THENRESULT = R ;! NOT READY HEADER = GET RING DATA ACTION TRACE(ATM RISTART, AVALID, HEADER, 0) -> WAIT HDR %IF (HEADER & HEADER A) # STANDARD A ;! SKIP TO STD HDR ! ! STORE & DECODE THE HEADER PACKET ! RECBUF(0) = HEADER FIELD B = (HEADER>>10) & 3 FIELD C = HEADER & HEADERC -> BSWI(FIELD B) ! BSWI(2): BSWI(3): FATAL("RECEIVED ILLEGAL RTP HEADER FIELD B") BSWI(0): DO CHECKSUM = 1 ;! LONG BLOCK, C/S = 0 -> REC BLOCK BSWI(1): DO CHECKSUM = 0 ;! LONG BLOCK, WITH C/S ! ! READ WHOLE RTP BLOCK INTO RECBUF, OPERATING A 1 SEC TIMEOUT ! REC BLOCK: RBTIMEOUT = 0 ;! SEE RTN RBALARM SET TIMER(RB ALARM, ONE SECOND) %CYCLE I=1,1,FIELDC + 3 ;! INCL ROUTE & CHECKSUM PACKETS RBWAIT: %IF HDWR_INTSTATUS < 0 %THEN RECBUF(I) = GET RING DATA %C %ELSESTART -> RBWAIT %IF TOFF(TEMP) = 0 ;! MESSAGES WAITING? P_SERVICE = 0; POFF(P) %IF P_SERVICE # MYID %OR P_REPLY # 0 %START PON(P) ;! ACTION IT LATER IN MAIN PROG -> RBWAIT %FINISH CLOCK INTERRUPT ;! ONLY TAKING CLOCK MESSAGES %IF RBTIMEOUT # 0 %THENRESULT = RITIMEOUT ! R -> RBWAIT %FINISH %REPEAT CANCEL TIMER(RB ALARM) ;! GOT WHOLE BLOCK ! ! LOOK AT CHECKSUM ! %IF DOCHECKSUM = 0 %START %IF RECBUF(FIELDC+3) # 0 %THENRESULT = R ! RI CHECKSUM %ELSE CHECKSUM = 0 %CYCLE I=0,1,FIELDC + 2 CHECKSUM = SUM WITH CARRY(CHECKSUM,RECBUF(I)) %REPEAT %IF CHECKSUM # RECBUF(FIELDC + 3) %THENRESULT = R!RI CHECKSUM %FINISH ! ! RECBUF CONTAINS A VALID RTP BLOCK (HEADER,ROUTE,C+1 DATA,C/S) ! THE DATA FRAME IS EITHER A SPECIAL (OPEN ETC) OR ITS NORMAL ! BSP WITH 1ST 2 WORDS BEING RX & TX COMMANDS ! ACTION TRACE(ATM RI, AVALID, FIELDC+1, 0) RECDATAEND = FIELD C + 2 RC = RECBUF(2) RCTYPE = RC >> 12 %IF RCTYPE=6 %THENRESULT = R ! DECODE SPECIAL RC(RC,RECDATAEND,RECBUF) %IF RECBUF(1) # STANDARD PORT %THEN FATAL("INPUT ON WRONG PORT") %IF STATE # SRUN %THENRESULT = R ! RI UNEXPECTED COMMAND %IF RCTYPE=3 %THEN R = R ! DECODE RDY(RC) %AND -> DO T %IF RCTYPE=5 %THEN R = R ! DECODE NOTRDY(RC) %AND -> DO T %UNLESS RC=0 %THEN FATAL(" UNKNOWN R FIELD RECEIVED") ! DO T: TC = RECBUF(3) TCTYPE = TC >> 12 %IF TCTYPE=10 %THENRESULT = R ! DECODE DATA(TC,RECDATAEND,RECBUF) %IF TCTYPE=12 %THENRESULT = R ! DECODE NODATA(TC) %UNLESS TC=0 %THEN FATAL(" UNKNOWN T FIELD RECEIVED") ! ! BEWARE - ALL SORTS OF SIDE EFFECTS OCCUR IN ABOVE FN CALLS ! %RESULT = R %END ! ! ! ! RTN MAPS BUFFER PASSED BY HIGHER LEVEL S/W INTO MY VM ! %ROUTINE MAP BUFFER %INTEGER SEG %CONSTINTEGER MYSEG=3, MYSEGA=K'60000' SEG = P_A3 >> 13 MAP VIRT(P_REPLY,SEG,MYSEG) P_A3 = MYSEGA + (P_A3&K'17776') ;! COBBLE PTRAN_BUF %END ! ! ! ! RTN REVERSES BYTES IN A DATA-N FRAME B4 TRANSMISSION ! COS BSP DEMANDS HI BYTE IS 1ST ! %ROUTINE SWAB(%INTEGERARRAYNAME B, %INTEGER BYTECOUNT) %INTEGER I %CYCLE I=0,1,(BYTECOUNT-1)//2 B(I) = (B(I)<<8)!(B(I)>>8) %REPEAT %END ! ! ! ! RTN SETS UP PRIVATE VARIABLES ! %ROUTINE INITIALISE %INTEGER I PTRAN == P; PREPLY == P; PBUFFI == P ATBPTR=0; PTBPTR=0 HLINPUTCOUNT=0; HLTASKNR=0; HLSTATUS=0; HLERROR=0 DATALEN = 0 LAST TIMER ENTRY = -1 INTERNAL TX SEQ = 0 STATE = S NOT STARTED HDWR_SELECTOR = 0 ;! UNABLE TO RX ANYTHING 'TIL ADRESS SET I = HDWR_RBUFF ;! CLEAR ANY JUNK %CYCLE I=0,1,PTBLIM PACKET TRACE BUFFER(I) = 0 %REPEAT %CYCLE I=0,1,ATBLIM ACTION TRACE BUFFER(I)_FLAG = 0 %REPEAT OUTPT COUNT = 0 ALARM SET = 0 INT = 0 %END ! ! ! ! !*********************** MAIN PROGRAM CODE ********************* ! ! LINKIN(RING SER) LINKIN(TRACE SER) MAP HWR(4) INITIALISE ! ! ! MAIN LOOP ! %CYCLE; ! UNTIL FATAL ERROR OR KILL ACTION %WHILE TOFF(TEMP) = 0 %CYCLE HL ERROR = HLERROR ! RING INPUT %IF INT # 0 %THEN FATAL("INT DIAG!") %REPEAT P_SERVICE=0; POFF(P) ! %IF P_SERVICE=MYID %AND P_REPLY=0 %THENC CLOCK INTERRUPT %ANDCONTINUE %IF P_SERVICE=TRACE SER %START ;! RINGTY TX TASK WANTS ACTION TRACE %IF P_A2=0 %THEN ACTIONTRACE(ATMWTF1,AVALID,P_A3,0) %C %ELSE ACTIONTRACE(ATMWTF2,AVALID,P_A3,0) %IF P_A1#0 %OR (STATE#SRUN %AND P_A2#0) %THENC FATAL("TX FAIL") %CONTINUE %FINISH ! ! GOT AN ACTION FROM HIGHER LEVEL S/W ON RING SER ! %IF PTRAN_ACTION # NULL %THENC ACTION TRACE(ATM HLACTION, 0, 0, 0) %UNLESS REOUTPT >= PTRAN_ACTION >= NULL %THENC FATAL(" DUD OP ACTION CODE") ! -> ACTION(PTRAN_ACTION) ! ACTION(SET ADDRESS): ACTION TRACE(ATM HLSA, AVALID, P_A2, 0) %IF (HLSTATUS & HLOPEN) # 0 %THEN HLERROR=HLERROR!HLOPEN %C %ELSESTART HLTASKNR = P_REPLY ;! FOR USE ON FATAL ERROR DEVADD = P_A2 ;! DEST STATION ON RING HDWR_SELECTOR = DEVADD HDWR_INTSTATUS = HDWR_INTSTATUS ! 1 ;! READY HLSTATUS = HL ADR SET HLERROR = 0 STATE = SWAIT 4 OPEN %FINISH -> REPLY ! ACTION(INPT): ACTION TRACE(ATM HLIN1, AVALID, PTRAN_LEN, 0) %IF (HLSTATUS & HLIR) # 0 %START MAP BUFFER %IF PTRAN_LEN > HLINPUTCOUNT %THEN PTRAN_LEN=HLINPUTCOUNT %IF PTRAN_LEN <= 0 %THEN HLERROR=HLERROR!HLBUFL %AND ->REPLY %CYCLE I=0,1,PTRAN_LEN-1 PTRAN_BUF(I) = HL GET INPUT %REPEAT ACTION TRACE(ATM HLIN2, ABVALID, PTRAN_LEN, HLINPUTCOUNT) %IF HL INPUT COUNT = 0 %THEN HLSTATUS = HLSTATUS & (\HLIR) %IF RSTATE=RSTATEN %AND STATE=SRUN %AND HLINPUTSPACE > 2043 %START SEND(BSPRDY+(RSEQ<<8),0,DUMMY,0) RALARMS = 0 SET TIMER(RSTATE E ALARM, ONE SECOND) RSTATE = RSTATE E %FINISH %FINISHELSE HLERROR=HLERROR ! HLIR %AND PTRAN_LEN=0 -> REPLY ! ACTION(OUTPT): ACTION TRACE(ATM HLOUT, AVALID, PTRAN_LEN, 0) %IF (HLSTATUS & HLOD) = 0 %THEN HLERROR=HLERROR!HLOD %AND ->REPLY %UNLESS 300>=PTRAN_LEN>0 %THEN HLERROR=HLERROR!HLBUFL %AND -> REPLY MAP BUFFER DATABUF == PBUFFI_BUF ;! SAVE 4 RETRANSMISSION (AS INT ARRAY NAME) DATALEN = PTRAN_LEN SWAB(DATABUF,DATALEN) ;! BSP DEFINES HI BYTE 1ST! OUTPTCOUNT = 1 TXAGAIN: SEND(0,(BSPDATA+(TSEQ<<8))!(DATALEN&1),DATABUF,(DATALEN+1)//2) TALARMS = 0 SET TIMER(TSTATE E ALARM, ONE SECOND) TSTATE = TSTATE E HLSTATUS = HLSTATUS & (\HLOD) ;! DROP O/P DONE OUTPTCOUNT = OUTPTCOUNT - 1 -> REPLY ! ACTION(RESET): ACTION TRACE(ATM HLRESET, 0,0,0) %IF STATE # SRUN %START HLERROR = HLERROR ! HLOPEN %ELSE SEND(BSPRESET,0,DUMMY,0) STATE = SWAIT 4 RESET HLSTATUS = HLSTATUS & (\HLOD) ;! PREVENT O/P ACTIONS TIL HANDSHAKE %FINISH -> REPLY ! ACTION(OPEN): ACTION TRACE(ATM HLOPEN, AVALID, P_A2, 0) %IF STATE # SWAIT 4 OPEN %START HLERROR = HLERROR ! HLOPEN %ELSE OPENBLOCK(4) = P_A2 ;! FUNCTION CODE TRANSMIT(OPENBLOCK,OBLEN) STATE = SWAIT 4 OPENACK %FINISH -> REPLY ! ACTION(CLOSE): ACTION TRACE(ATM HLCLOSE, 0,0,0) %IF STATE # SRUN %START HLERROR = HLERROR ! HLOPEN %ELSE SEND(BSPCLOSE,0,DUMMY,0) STATE = SWAIT 4 CLOSE HLSTATUS = HLSTATUS & (\HLOD) %FINISH -> REPLY ! ACTION(KILL): P_SERVICE = TXR DUMP SER P_REPLY = 0 P_A1 = 0 ;! NO DUMP, JUST STOP PON(P) %STOP ! ACTION(DIAG): FATAL("DIAGNOSTICS REQUESTED BY HIGHER LEVEL") ! ACTION(REOUTPT): OUTPTCOUNT = P_A2 %IF (HLSTATUS & HLOD) # 0 %THEN -> TX AGAIN ! REPLY: ACTION TRACE(ATM HLREPLY, ABVALID, HLSTATUS, HLERROR) ACTION(NULL): ;! AVOID FILLING TRACE BUFFER WITH NULLS P_SERVICE = P_REPLY P_REPLY = RING SER PREPLY_STATUS = HLSTATUS PREPLY_ERROR = HLERROR HLERROR = 0 PON(P) %REPEAT %ENDOFPROGRAM