! FILE 'PARR5S' !********************* !* PARR5S/PARR5Y * !* DATE: 27.JAN.82 * !********************* ! NODE 6 VERSION !STACK = 140 %CONSTINTEGER SECAD = 9 %RECORDFORMAT XXF(%INTEGER DUMMY) %CONSTRECORD (XXF) %NAME NULL = 0 %CONTROL X'100001'; ! TRUSTED PROGRAM AND QUICK ! ROUTINE ENTRY AND EIS %CONSTSTRING (7) VSN = 'VSN003K' %BEGIN %SYSTEMROUTINESPEC ALARM(%INTEGER TICKS) %SYSTEMROUTINESPEC LINKIN(%INTEGER SER) %SYSTEMINTEGERFNSPEC MAP ABS(%INTEGER ADR, LEN, REQ ID) %SYSTEMROUTINESPEC MAPHWR(%INTEGER SEG) %PERMROUTINESPEC SVC(%INTEGER EP, R0, R1) %RECORDFORMAT PARRF(%INTEGER RCSR, RBC, RBA, RVEC, %C TCSR, TBC, TBA, TVEC) %OWNRECORD (PARRF) %NAME PA = 1 %CONSTBYTEINTEGERNAME ID = K'160030' %CONSTINTEGER KERNEL SER = 29 %OWNINTEGER LINE TYPE = 0; ! 0=DQS11, 1=DUP11E %OWNINTEGER LINE = 0; !LOGICAL LINE %OWNINTEGER PRIO = 0; ! LINE PRIORITY %OWNINTEGER MISSING TX INT %CONSTINTEGERNAME NO OF BUFF = K'060112'; ! NO OF BUFFERS %OWNINTEGER CRITICAL = 10; ! MIN GLOBAL POOL SIZE %OWNINTEGER MAX READS = 3; ! MAX IT IS ALLOWED TO HOLD %CONSTINTEGER INPUT REQ = 1; ! INTERFACE TO HIGHER LEVEL %CONSTINTEGER OUTPUT REQ = 2 %CONSTINTEGER BOUNCE = 3 %CONSTINTEGER PUT DOWN = 4 %CONSTINTEGER PUT UP = 5 %CONSTINTEGER MONIT = 6 %CONSTINTEGER VARBS ADDRESS = 7 %CONSTINTEGER BUFFER MANAGER = 17 %OWNINTEGER RX INT = -7, TX INT = -6 %RECORDFORMAT MEF(%BYTEINTEGER HLEN, HTYPE, LEN, TYPE, %C %BYTEINTEGERARRAY A(0:240)) %RECORDFORMAT HDLCF(%BYTEINTEGER ADD, TYPE, %BYTEINTEGERARRAY A(0:239)) %RECORDFORMAT MEF2(%BYTEINTEGER HLEN, HTYPE, %RECORD (HDLCF) HDLC) %RECORDFORMAT PE(%BYTEINTEGER SER, REPLY, %INTEGER A1, A2, A3) %RECORDFORMAT P2F(%BYTEINTEGER SER, REPLY, FN, LINE, %C %RECORD (MEF) %NAME M, %BYTEINTEGER LEN, S1) %OWNRECORD (PE)P %OWNRECORD (P2F) %NAME P2 %OWNINTEGER TSTATE %OWNINTEGER ISTATE, RSTATE, INPUT EXP, W PEND, Q MAX %OWNINTEGER IRD, ITR, NO READ, CLOCK0, RER, READ OFF %OWNINTEGER MON = 0 %INTEGER I %RECORDFORMAT WDSE(%RECORD (MEF2) %NAME M, %INTEGER LEN) %RECORDFORMAT BPF(%RECORD (MEF2) %NAME M) %RECORDFORMAT QF(%RECORD (MEF) %NAME E) %RECORDFORMAT R1F(%RECORD (MEF) %NAME M) %RECORDFORMAT R2F(%INTEGER X) %OWNRECORD (QF) MQ %OWNRECORD (MEF2) %NAME ICURR, OCURR %OWNRECORD (WDSE) %NAME IPOOL %OWNRECORD (BPF) %NAME ME2 %OWNRECORD (R1F) R1 %OWNRECORD (R2F) %NAME R2 %OWNINTEGERARRAY RADDR(0:7); ! HOLDS PAGE NO OF EACH SEGMENT %RECORDFORMAT R3F(%INTEGERNAME N) %RECORDFORMAT R4F(%INTEGER X) %RECORD (R3F) %NAME R3; %RECORD (R4F) R4 %CONSTBYTEINTEGERNAME CHANGE OUT ZERO = K'160310' %CONSTINTEGER T3 SER = 21 %CONSTBYTEINTEGERNAME INT = K'160060' %ROUTINESPEC ASK FOR BUFFER(%INTEGER TYPE) %SWITCH SW(INPUT REQ:VARBS ADDRESS) ! %ROUTINE OCTAL(%INTEGER N) ! %INTEGER I ! PRINTSYMBOL((N>>I)&7+'0') %FOR I=15,-3,0 ! SPACE ! %END %ROUTINE TELL PRINTSTRING("PAR"); WRITE(LINE, 1); PRINTSYMBOL(':') %END %ROUTINE INITIALISE %INTEGER F, I LINKIN(RX INT); LINKIN(TX INT) SVC(18, 2, 0); ! SET PRIORITY = 2 %CYCLE I = 1, 1, 7; ! FIND ABSOLUTE ADDRESSES RADDR(I) = MAP ABS(I<<13, 256, ID); ! MY ADDRESSES F = MAP ABS(I<<13, 0, ID); ! AND OFF AGAIN %REPEAT MAPHWR(0) PA_RCSR = PA_RCSR&(\K'100') PA_RCSR = PA_RCSR!K'100'; ! GENERATE AN EXTRA INT I STATE = 2 %IF INPUT EXP = 0 %THEN ASK FOR BUFFER(0) ASK FOR BUFFER(X'0100'); ! SEND A SARM OUT %END %ROUTINE START INPUT %INTEGER PAD, PAR, CAD, EXT BITS R1_M == ICURR; ! NEED THE ADDRESS AS AN INTEGER PAD = R2_X+2 ! PAR = MAP ABS(PAD, P_LEN, RXREPLY) PAR = RADDR(PAD>>13) %IF PAR = 0 %START TELL; PRINTSTRING("** BAD R ADDR *** ") *K'104001'; ! EMT WAIT %FINISH PAR = PAR+(PAD&K'17700')>>6; ! ENSURE ACTUAL BLOCK EXT BITS = (PAR&K'176000')>>6 CAD = PAR << 6+PAD&K'77' PA_RBC = -252 PA_RCSR = EXT BITS PA_RBA = CAD; ! EXT BITS ******************** PA_RCSR = PA_RCSR!K'100' R STATE = 1 %END %ROUTINE START OUTPUT(%RECORD (MEF2) %NAME M) %INTEGER OSEG, PAR, EXT BITS, I !! NB: THE HDLC HEADER MUST BE SWAPPED M_HTYPE = M_HDLC_TYPE M_HLEN = 0 PA_TBC = -(M_HDLC_ADD+2); ! LENGTH M_HDLC_ADD = SECAD; M_HDLC_TYPE = 0 %IF ISTATE = 2 %THEN M_HDLC_TYPE = 15; ! SARM ON 1ST GO R1_M == M; ! NEED ADDRESS AS INTEGER OSEG = R2_X+2 ! PAR = MAP ABS(OSEG, P_LEN, ID) PAR = RADDR(OSEG>>13) %IF PAR = 0 %START TELL; PRINTSTRING("** BAD W ADDR *** ") *K'104001'; ! EMT WAIT %FINISH PAR = PAR+(OSEG&K'17700')>>6; ! ON ACTUAL BLOCK EXT BITS = (PAR&K'176000')>>6 PA_TCSR = EXT BITS PA_TBA = PAR << 6+OSEG&K'77' !! NB: EXT BITS *************************************** PA_TCSR = PA_TCSR!K'100' TSTATE = 1 %END %ROUTINE WREPLY(%INTEGER FLAG, BLOCK) P_SER = KERNEL SER; P_REPLY = ID P2_FN = OUTPUT REQ; P_A2 = BLOCK; P_A3 = FLAG P2_LINE = LINE !! MONITOR(P) PON(P) %END %ROUTINE RETURN BUFF(%RECORD (MEF2) %NAME M) %RECORD (WDSE) %NAME ME2 P_SER=BUFFER MANAGER; P_REPLY=ID P_A1=1; P2_M == M P2_M_TYPE = M_HTYPE %IF P2_M_TYPE # 0 %OR INPUT EXP >= MAX READS %OR NO OF BUFF %C < CRITICAL %OR ISTATE # 0 %START PON(P) %ELSE ME2 == P2_M ME2_M == IPOOL IPOOL == ME2 INPUT EXP = INPUT EXP+1 %FINISH %END %ROUTINE ASK FOR BUFFER(%INTEGER TYPE) P_SER = BUFFER MANAGER; P_REPLY = ID P_A1 = 0; P_A3 = TYPE; ! ASK FOR BIG BUFFER PON(P) %END %ROUTINE ABORT(%INTEGER TYPE) ! REASONS FOR ABORT: %RETURNIF ISTATE # 0; !ALREADY DOWN TELL; PRINTSTRING("DEAD ") PRINTSYMBOL(TYPE+'0') NEWLINE WREPLY(1, 0); !TELL GATE DOWN %WHILE %NOT MQ_E == NULL %CYCLE ME2 == POP(MQ) P_SER = BUFFER MANAGER; P_REPLY = ID P_A1 = 1; P2_M == ME2; ! RETURN BUFFER PON(P); ! CANT USE RETURN BUFF (TYPE BYTE!) %REPEAT ISTATE = 2; W PEND = 0 %END %ROUTINE HANDLE INPUT(%RECORD (MEF2) %NAME M) %RECORD (HDLCF) %NAME HDLC %RECORD (WDSE) %NAME IMESS %INTEGER TYPE, LEN, I %IF M == NULL %START; ! I FRAME IN %IF ISTATE = 10 %START; ! HELD DOWN RETURN BUFF(ICURR) %UNLESS ICURR == NULL %RETURN %FINISH %IF ICURR == NULL %THEN -> NOISE TYPE = ICURR_HDLC_TYPE %IF TYPE = 15 %START; ! SARM, IE RESET ABORT(6); ! OTHER END RESET %FINISH M == ICURR LEN = PA_RBC+252 %IF PA_RCSR < 0 %OR LEN = 0 %START RER = RER+1 ABORT(3) START INPUT; ! START INPUT ON SAME BUFFER %RETURN %FINISH %IF ISTATE # 0 %START; ! WAS DOWN TELL; PRINTSTRING("UP ") WREPLY(0!ICURR_HDLC_ADD<<8, 0) ISTATE = 0 ! ASK FOR BUFFER(X'0100'); ! 'SARM' TYPE %IF LEN = 2 %START; ! JUST 'SARM' FROM OTHER END START INPUT; %RETURN; ! PUT READ ON AGAIN %FINISH %FINISH P_SER = KERNEL SER; P_REPLY = ID P2_FN = INPUT REQ; P2_LINE = LINE P2_M == M P2_M_TYPE = M_HTYPE P2_M_LEN = LEN-2 PON(P) IRD = IRD+1 %FINISH NOISE: CLOCK0 = 0 %IF INPUT EXP > 0 %START ICURR == IPOOL IPOOL == IPOOL_M; INPUT EXP = INPUT EXP-1 ICURR_HTYPE = ICURR_HDLC_TYPE %IF INPUT EXP <= 1 %START %IF NO OF BUFF > CRITICAL %THEN ASK FOR BUFFER(0) %C %ELSE READ OFF = 1 %FINISH START INPUT %FINISH %END %ROUTINE CLOCK INT %INTEGER FLAG ALARM(25); !RESTART CLOCK %IF TSTATE # 0 %START %IF PA_TCSR&K'300' = K'300' %START; ! INT PENDING? MISSING TX INT = MISSING TX INT+1 %IF MISSING TX INT&3 = 3 %START TELL; PRINTSTRING(" Missing TX Int **********") PRINTSTRING("********** !!!!!!!!!!!! *************** ") PA_TCSR = PA_TCSR&(\K'100') PA_TCSR = PA_TCSR!K'100' %FINISH %ELSE MISSING TX INT = 0 CLOCK0 = CLOCK0+1 %IF CLOCK0 = 80 %START; ! 40 SEC OUTPUT TIMEOUT ABORT(2); ! FAILED TO TRANSMIT %RETURN %FINISH %FINISH NO READ = NO READ+1 %IF INPUT EXP = 0 %IF READ OFF # 0 %AND NO OF BUFF>CRITICAL %START READ OFF = 0; ASK FOR BUFFER(0) %FINISH %END !! MAP VIRT(BUFFER MANAGER, 4, 3) MAP VIRT(BUFFER MANAGER,5,4) MAP VIRT(BUFFER MANAGER, 6, 5) CHANGE OUT ZERO = T3 SER P2 == P; R2 == R1 P2_SER = 0; POFF(P2); ! WAIT FOR INSTRUCTIONS LINE = P2_FN; LINE TYPE = P2_LINE&X'F' ! PRIO = P2_LINE>>4 %IF P2_LINE&X'F0' # 0 %THEN CRITICAL = 3 %ELSE MAX READS = 2 P_A2 = P_A2&K'17777'; ! ENSURE P2_M IS IN SEGMENT ZERO PA == P2_M RXINT = P2_LEN!X'FF00'; TXINT = P2_S1!X'FF00' INITIALISE WREPLY(2, 0); ! HERE I AM ( LINE NUMBER! = 0!) ALARM(25) %CYCLE P_SER = 0 POFF(P) %IF P_SER&X'80' # 0 %START; ! INTERRUPT %IF P_SER = TX INT&X'FF' %START; ! OP DONE MISSING TX INT = 0 %UNLESS OCURR == NULL %START RETURN BUFF(OCURR); OCURR == NULL %FINISH %IF PA_TCSR < 0 %START; ! ERROR TELL; PRINTSTRING("TX ERROR ") %CONTINUE %IF TSTATE = 0 %FINISH TSTATE = 0 CLOCK0 = 0 %IF %NOT MQ_E == NULL %START OCURR == POP(MQ) START OUTPUT(OCURR) WPEND = WPEND-1; ITR = ITR+1 %FINISH %ELSE; ! INPUT INTERRUPT RSTATE = 0; ! NOW INACTIBE HANDLE INPUT(NULL) %FINISH %CONTINUE %FINISH %IF P_REPLY = 0 %START CLOCK INT; ! CLOCK INTERRUPT %IF INT = '?' %START INT = 0 TELL; WRITE(ISTATE, 4); WRITE(RSTATE, 4) WRITE(INPUT EXP, 5); WRITE(W PEND, 4); WRITE(Q MAX, 4) NEWLINE TELL; WRITE(IRD, 4) WRITE(ITR,4) WRITE(NO READ, 8); WRITE(CLOCK0, 4); WRITE(RER, 4) WRITE(READ OFF, 4) NEWLINE %FINISH %CONTINUE %FINISH %IF P_REPLY = BUFFER MANAGER %START; ! BUFFER HAS ARRIVED %IF P_A3 # 0 %AND TSTATE = 0 %START; ! 'SARM' BUFFER P2_M_LEN = 0; ! NO 'REAL' DATA OCURR == P2_M START OUTPUT(OCURR); ! SEND THE SARM %CONTINUE %FINISH ME2 == P2_M ME2_M == IPOOL IPOOL == ME2 INPUT EXP = INPUT EXP+1 %IF RSTATE = 0 %START; ! NO READ ON HANDLE INPUT(ME2); ! PUT A READ ON %FINISH %CONTINUE %FINISH !! USER REQUEST !! MONITOR(P) -> SW(P2_FN) SW(OUTPUT REQ): %IF ISTATE = 0 %START; ! ITS UP %IF TSTATE = 0 %START I TR = I TR+1 OCURR == P2_M START OUTPUT(OCURR) %ELSE PUSH(MQ, P2_M) W PEND = W PEND+1 %IF W PEND > Q MAX %THEN Q MAX = W PEND %FINISH %CONTINUE %FINISH; ! ITS DOWN, SO CHUCK THE BUFFER SW(INPUT REQ): ! BEING PHASED OUT P_SER = BUFFER MANAGER; P_REPLY = ID P_A1 = 1 PON(P) %CONTINUE SW(BOUNCE):; ! FORCE LINE BOUNCE ABORT(4) %CONTINUE SW(PUT DOWN): ABORT(4); ISTATE = 10 %IF RSTATE # 0 %START; ! READ ON RETURN BUFF(ICURR) %UNLESS ICURR == NULL ! FREE THE BUFFER ICURR == NULL PA_RCSR = PA_RCSR&(\K'100'); ! AND STOP INTERRUPTS %FINISH %CONTINUE SW(PUT UP): INITIALISE; ! GRAB INTERRUPTS AGAIN %CONTINUE SW(MONIT): INT = '?' %CONTINUE SW(VARBS ADDRESS): R3 == R4 R3_N == ISTATE P_SER = P_REPLY; P_REPLY = ID P_A1 = 2; ! TYPE IS PARR LINK HANDLER P_A2 = R4_X; ! PLANT ADDRESS PON(P) %REPEAT %ENDOFPROGRAM !! MONITOR(P) /