! FILE 'NODE_PRT11NS' !********************* !* PRT1S/PRT1Y * !* DATE: 26.MAR.81 * !*VERSION FOR NODE * !*HISTORY UNCERTAIN * !!!!!!!!!!!!!!!!!!!!!! !STACK = 140 %CONTROL X'100001'; ! TRUSTED PROGRAM AND QUICK ! ROUTINE ENTRY AND EIS %CONSTINTEGER KERNEL SER = 29 %OWNINTEGER SECONDARY = 0; !PRIM = 0, SEC = 1 %OWNINTEGER SECAD = 9; !SECONDARY ADDRESS %CONSTINTEGER WMAX = 56; ! MAX NO OF WRITES %CONSTINTEGER SFMASK = 63; ! CIRC BUFFER SIZE FOR WRITES %CONSTSTRING (7) VSN = 'VSN011C' %PERMINTEGERFNSPEC SVC(%INTEGER EP, B, C) %BEGIN %RECORDFORMAT XXF(%INTEGER DUMMY) %CONSTRECORD (XXF) %NAME NULL = 0 %SYSTEMROUTINESPEC ALARM(%INTEGER TICKS) %SYSTEMROUTINESPEC LINKIN(%INTEGER SER) %RECORDFORMAT PARF(%INTEGER TYPE, %RECORD (XXF) %NAME B, %C %INTEGER LEN) %EXTERNALROUTINESPEC DQS11E(%RECORD (PARF) %NAME L) %EXTERNALROUTINESPEC DUP11E(%RECORD (PARF) %NAME B) %CONSTBYTEINTEGERNAME ID = K'160030' %CONSTINTEGER KERNEL SER = 29 %OWNINTEGER LINE TYPE = 0; ! 0=DQS11, 1=DUP11E %OWNINTEGER LINE = 0; !LOGICAL LINE %OWNRECORD (XXF) %NAME HANDLER ADDRESS = 1; ! SET BY INITIATING PROG %OWNINTEGER SECONDARY = 0; !PRIM = 0, SEC = 1 %CONSTINTEGERNAME NO OF BUFF = K'060112'; ! NO OF BUFFERS (BUFF3) %OWNINTEGER BIG LIMIT = 7; ! TRY AT 5 FOR NOW %OWNINTEGER CRITICAL = 8; ! NO TO RETURN BUFFERS AT %OWNINTEGER MAX READS = 4; ! MAX IT IS ALLOWED TO HOLD %OWNINTEGER RR TIME = 2; ! TIME IN 1/2 SEC TO SEND RR %CONSTINTEGER INITIALISE = 0; ! CALLS & REPLIES TO LINE HANDLER ROUTINES %CONSTINTEGER LINE INPUT = 1 %CONSTINTEGER LINE OUTPUT = 2 %CONSTINTEGER INPUT HERE = 3 %CONSTINTEGER OUTPUT DONE = 4 %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) %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 (PARF) PAR %OWNRECORD (PE)P %OWNRECORD (P2F) %NAME P2 %INTEGER I %OWNINTEGER ACTIVE, TSTATE %OWNINTEGER AAA, EEE, FFF, TTT !A..LAST MESSAGE ACKNOWLEDGED ! BY OTHER END !E..NUMBER OF NEXT MESSAGE ! EXPECTED !F..LAST OUTPUT MESSAGE HELD+1 !T..LAST MESSAGE SENT %OWNINTEGER DATA MISSED, ABORT REQ, ITRH, LOST INT %OWNINTEGER CLOCK0, CLOCK1, CLOCK2, CLOCK3, CLOCK4, CLOCK5, CLOCK6 !CLOCK1. CLEARED WHEN ACK ! RECEIVED, AND WHEN RETRY STARTS ! TIMED WHEN ACK ! OUTSTANDING !CLOCK2. TIME SINCE VALID ! MESSAGE FROM OTHER END !CLOCK3. NO OF TRANSMIT ! RETRIES. CLEARED WHEN ACK ! RECEIVED !CLOCK. TIME SINCE RR OR SARM !CLOCK6. Q TOO LONG TIME !******************************************************* !! DO NOT CHANGE THE ORDER OR POSITION OF THE FOLLOWING VARBS %OWNINTEGER ISTATE, RSTATE,INPUT EXP, WPEND, Q MAX %OWNINTEGER DCOU, DSYM %OWNINTEGER IRD, RRRD, RNR RD, REJ RD, I TR, RR TR, RNR TR, REJ TR %OWNINTEGER BADACK, BAD FR, SILOFULL, DM, I RE TR !************************************************************** %RECORDFORMAT WDSE(%RECORD (MEF2) %NAME M, %INTEGER LEN) %RECORDFORMAT BPF(%RECORD (MEF2) %NAME M) %OWNRECORD (WDSE) %NAME WDESC %OWNRECORD (WDSE) %ARRAY WSPACE(0:SFMASK) %OWNRECORD (WDSE) %NAME IDESC %OWNRECORD (WDSE) ICURR %OWNRECORD (WDSE) %NAME IPOOL %OWNRECORD (WDSE) OM %OWNRECORD (BPF) %NAME IM %OWNRECORD (BPF) %NAME ME2 %CONSTBYTEINTEGERNAME CHANGE OUT ZERO = K'160310' %CONSTINTEGER T3 SER = 21 %CONSTBYTEINTEGERNAME INT = K'160060' %CONSTBYTEINTEGERARRAY INIT(0:1) = 4, 2; ! INITIAL STATE OF ISTATE %RECORDFORMAT M1F(%INTEGER A, B, C, D, E, F) %RECORD (M1F) M1, M2 %RECORDFORMAT R1F(%INTEGERNAME N) %RECORDFORMAT R2F(%INTEGER X) %RECORD (R1F) %NAME R1; %RECORD (R2F) R2 %SWITCH SW(INPUT REQ: VARBS ADDRESS) %ROUTINESPEC REINITIALISE %ROUTINE START INPUT PAR_TYPE = LINE INPUT; PAR_B == ICURR_M_HDLC; PAR_LEN = ICURR_LEN %IF LINE TYPE = 0 %START DQS11E(PAR) %ELSE %IF LINE TYPE = 1 %START DUP11E(PAR) %FINISH %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 (WDSE) %NAME ME2 P_SER=BUFFER MANAGER; P_REPLY=ID P_A1=1; P2_M == WDESC_M P2_M_TYPE = WDESC_M_HTYPE %IF P2_M_TYPE # 0 %OR INPUT EXP >= MAX READS %OR NO OF BUFF %C < CRITICAL %START P2_M_A(4) = K'123' PON(P) %ELSE ME2 == P2_M ME2_M == IPOOL IPOOL == ME2 INPUT EXP = INPUT EXP+1 %FINISH %END %ROUTINE ASK FOR BUFFER P_SER = BUFFER MANAGER; P_REPLY = ID P_A1 = 0; P_A3 = 0; ! ASK FOR BIG BUFFER PON(P) %END %ROUTINE TELL PRINTSTRING("PROT"); WRITE(LINE, 1); PRINTSYMBOL(':') %END %ROUTINE DELETE READS %WHILE %NOT IPOOL == NULL %CYCLE ME2 == IPOOL; IPOOL == ME2_M P2_M == ME2 P_SER = BUFFER MANAGER; P_REPLY = ID; P_A1 = 1 PON(P) %REPEAT INPUT EXP = 0 %END %ROUTINE ABORT(%INTEGER TYPE) ! REASONS FOR ABORT: !1..NOTHING VALID RECEIVED IN ! 40 TICKS !2..10 RETRIES TO RE-TRANSMIT !3..DEVICE HANDLER FAULT !4..RESET FROM BRIAN !6..SARM RECEIVED FROM PRIMARY !7..NO READS ONFOR 24 TRIES !8..TOO MANY WRITES (IE FULL UP) %INTEGER X, I %RETURNIF ISTATE # 0; !ALREADY DOWN %IF ABORTREQ = 0 %START TELL; PRINTSTRING("DEAD ") PRINTSYMBOL(TYPE+'0') WRITE(DATA MISSED, 3); DATA MISSED = 0 NEWLINE WREPLY(1, 0); !TELL GATE DOWN !SET RESTRICTIVE CONDITION %FINISH %IF ACTIVE = 2 %START ABORTREQ = 1 %ELSE ABORTREQ = 0 !TIDY UP REQUESTS X = 0 %WHILE AAA # FFF %CYCLE; !TIDY UP REQUESTS WDESC == WSPACE(AAA) RETURN BUFF X = X+1 %IF X&7=7 %THEN I = SVC(18, 2, 0) WDESC_M == NULL AAA = (AAA+1)&SFMASK %REPEAT WPEND = 0 ISTATE = INIT(SECONDARY) DELETE READS %FINISH %END %ROUTINE HANDLE OUTPUT %RECORD (HDLCF) %NAME HDLC %RECORD (MEF2) %NAME M %INTEGER TYPE, LEN %RETURNIF ACTIVE # 0; !ABORT IF TRANSMITTER BUSY %IF ABORT REQ # 0 %THEN ABORT(0) %IF ISTATE # 0 %START; ! IN INITIAL SEQUENCE %IF ISTATE = 4 %START; ! SEND SARM ISTATE = 3; ! GOES BACK TO 4 AFTER CLOCK TICK TYPE = X'0F'; !SARM -> SEND1 %FINISH %IF ISTATE = 1 %START; ! READY TO SEND UA ISTATE = 0 TYPE = X'63'; !UA -> SEND1 %FINISH %RETURN; ! ISTATE#ABOVE VALUES %FINISH %IF RSTATE = 3 %START RSTATE = 2 REJ TR = REJ TR+1 TYPE = 9; !REJ -> SEND %FINISH %IF RSTATE = 6 %START; ! SEND RNR TYPE = 5 RNR TR = RNR TR+1 RSTATE = 5; ! GET IT TO SEND RR IF POSSIBLE -> SEND %FINISH %IF TTT # FFF %AND TSTATE = 0 %C %AND (TTT-AAA)&7#5 %START WDESC == WSPACE(TTT) M == WDESC_M; HDLC == M_HDLC LEN = WDESC_LEN TYPE = EEE << 5+(TTT&7) << 1 TTT = (TTT+1)&SFMASK ACTIVE = 2; !BIG BLOCK BEING TRANSMITTED CLOCK1 = 0; !SET TIMER I RE TR = I RE TR+1; ! TOTAL NO OF I FRAMES TR -> PUT %FINISH %IF RSTATE = 1 %OR (RSTATE = 2 %AND CLOCK0 >= 5) %START RSTATE = 0 %IF RSTATE = 1 TYPE = 1; !RR RR TR = RR TR+1 %ELSE %RETURN !! SEND: TYPE = EEE << 5+TYPE SEND1: HDLC == OM_M LEN = 2 ACTIVE = 1; !SHORT BLOCK BEING TRANSMITTED PUT: CLOCK0 = 0 HDLC_ADD = SECAD; HDLC_TYPE = TYPE PAR_TYPE = LINE OUTPUT; PAR_B == HDLC; PAR_LEN = LEN %IF LINE TYPE = 0 %START DQS11E(PAR) %ELSE %IF LINE TYPE = 1 %START DUP11E(PAR) %FINISH LOST INT = 0; ! NO MISSING INT %END !! %ROUTINE HANDLE INPUT %RECORD (HDLCF) %NAME HDLC %RECORD (WDSE) %NAME IMESS %RECORD (MEF2) %NAME M %INTEGER R, S, X, TYPE M == ICURR_M HDLC == PAR_B; ! NB: HDLC AND M ARE PICKED UP SEPERATELY !!!!!! %UNLESS HDLC == M_HDLC %START PRINTSTRING("PROT:BAD ADDRESS ") *K'104001'; ! EMT WAIT %FINISH ! PAR_LEN<0 BUFFER TOO SMALL %IF PAR_LEN < 0 %START %IF PAR_LEN = -1 %START DM = DM+1 CLOCK4 = CLOCK4+1 %IF CLOCK4>24 %THEN ABORT(7) %ELSE %IF PAR_LEN = -2 %START BAD FR = BAD FR+1 %ELSE %IF PAR_LEN = -3 %START SILO FULL = SILO FULL+1 %FINISH -> NOISE %FINISH TYPE = HDLC_TYPE&X'EF'; ! IGNORE POLL -> NOISE %IF ABORT REQ # 0 %IF ISTATE # 0 %START -> NOISE %IF ISTATE = 10 ! KEEP DOWN IF NO READS OR LINE MEANT TO BE DOWN DCOU = DCOU+1; DSYM = TYPE; ! RETAIN FOR MONITORING %IF TYPE = X'0F' %START; ! SARM SEEN %IF SECONDARY = 1 %OR SECAD > HDLC_ADD %START ISTATE = 1; ! SEND UA %ELSE -> NOISE; ! IGNORE IT %ELSE -> NOISE %UNLESS SECONDARY = 0 %AND TYPE = X'63' ISTATE = 0; ! ALL DONE %FINISH RSTATE = 1; ! SEND RR TSTATE = 0 AAA = 0; EEE = 0; FFF = 0; TTT = 0 CLOCK1 = 0; CLOCK2 = 0; !RESET CLOCKS CLOCK3 = 0 WREPLY(0!(HDLC_ADD<<8), 0); !TELL NOEL UP WPEND = 0 -> END3 %FINISH %IF TYPE = X'0F' %START %IF CLOCK2 >= 15 %START !SARM RECEIVED & THIS IS ! SECONDARY ABORT(6); !SARM RECEIVED %FINISH -> NOISE %FINISH R = (TYPE >> 5)&7 TYPE = TYPE&15 %IF TYPE&1 = 0 %START; !INFORMATION BLOCK S = TYPE >> 1 %IF S # EEE %START RSTATE = 3 %UNLESS RSTATE = 2 !REJECT IF NOT ALREADY SET -> END1 %FINISH !PASS MESSAGE UP 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 = PAR_LEN-2 %IF 0 # P2_M_TYPE # 64 %START PRINTSTRING("PROT: GROTTED ") %FINISH PON(P) I RD = I RD+1 HDLC == NULL; !NO CURRENT BUFFER EEE = (EEE+1)&7 %IF RSTATE = 5 %THEN RSTATE = 1 %ELSE RSTATE = 5 !! SEND RR IF 2 OUTSTANDING, ELSE WAIT AND SEE %IF NO OF BUFF < BIG LIMIT %THEN RSTATE = 6; ! SEND RNR %ELSE %IF TYPE = 1 %START; !RR TSTATE = 0 RR RD = RR RD+1 %ELSE %IF TYPE = 5 %START; !RNR TSTATE = 1 RNR RD = RNR RD+1 %ELSE %IF TYPE = 9 %START ! 9=REJ REJ RD = REJ RD+1 %ELSE TELL; PRINTSTRING("NOISE"); WRITE(TYPE, 1); WRITE(R, 1) NEWLINE -> NOISE %FINISH; %FINISH; %FINISH %FINISH !! END1: !CHECK ACKNOWLEDGEMENT X = AAA %WHILE X&7 # R %CYCLE %IF X = TTT %START; !NO ACK EXPECTED BAD ACK = BAD ACK+1 -> END3 %FINISH X = (X+1)&SFMASK %REPEAT %UNLESS ACTIVE = 2 %AND X = TTT %START !IGNORE ACK FOR BLOCK !CURRENTLY BEING TRANSMITTED !UPDATE A COUNTER %WHILE AAA # X %CYCLE WDESC == WSPACE(AAA) RETURN BUFF I TR = I TR+1 WDESC_M == NULL WPEND = WPEND-1; !COUNT DOWN TRANSMIT REQUESTS AAA = (AAA+1)&SFMASK CLOCK1 = 0; CLOCK3 = 0 %REPEAT %IF TYPE = 9 %THEN TTT = AAA; !REJ..RESET TRANSMIT COUNT %FINISH END3: !VALID MESSAGE CLOCK2 = 0; !RESET VALIDITY TIMER NOISE: %IF %NOT HDLC == NULL %AND %NOT ICURR_M==IM %START %IF ISTATE = 10 %START WDESC == ICURR; ! MAP TO IT FOR RETURN BUFF RETURN BUFF DELETE READS ICURR_M == NULL %RETURN %FINISH !! USE THE SAME ONE AGAIN %ELSE %RETURN %IF ISTATE = 10; ! HOLD IT DOWN %IF INPUT EXP > 0 %START CLOCK5 = 0 ICURR_M == IPOOL IPOOL == IPOOL_M; INPUT EXP = INPUT EXP-1 ICURR_M_HTYPE = ICURR_M_HDLC_TYPE %IF ICURR_M_HTYPE=0 %THEN ICURR_LEN =252 %C %ELSE ICURR_LEN = 60 %ELSE ICURR_M == IM; ICURR_LEN = 6 %FINISH %FINISH %IF INPUT EXP<2 %THEN ASK FOR BUFFER START INPUT HANDLE OUTPUT %END %ROUTINE FREE INPUT BUFF %RECORD (MEF2) %NAME M M == ICURR_M; ! PICKUP INPUT BUFF %IF %NOT M == NULL %OR ICURR_M == IM %START ! 'FULL LENGTH' INPUT BUFFER WDESC == ICURR; ! PICK IT UP RETURN BUFF ICURR_M == NULL %FINISH %END %ROUTINE CLOCK INT %INTEGER FLAG ALARM(25); !RESTART CLOCK CLOCK0 = CLOCK0+1 %IF ISTATE # 0 %START %RETURN %IF CLOCK0 < 5 %OR ISTATE = 10 ISTATE = INIT(SECONDARY); !SEND ANOTHER SARM %ELSE CLOCK4 = 0 %IF INPUT EXP > 0 CLOCK2 = CLOCK2+1 %IF CLOCK2 >= 80 %START !NOTHING FROM OTHER END IN 80 ! TICKS %IF CLOCK4>10 %THEN FLAG = 7 %ELSE FLAG = 1 -> LABORT %FINISH %IF NO OF BUFF = 0 %START CLOCK5 = CLOCK5+1 %IF CLOCK5 > 60 %THEN FLAG=7 %AND ->LABORT %FINISH %IF WPEND > 10 %START %IF CLOCK6 = 0 %THEN ITRH = ITR; ! CHECK THRUPUT CLOCK6 = CLOCK6+1 %IF CLOCK6 > 75 %START; ! JUST OVER HALF MIN %IF ITRH = ITR %START TELL; PRINTSTRING("*** NO THRUPUT ") FLAG = 8; ->LABORT; ! DO ABORT 8 %ELSE CLOCK6 = 0 %FINISH %ELSE CLOCK6 = 0; ! NO Q, SO RESET CLOCK6 %IF ACTIVE # 0 %START; ! OUTPUT IN PROGRESS LOST INT = LOST INT+1; ! TEST FOR LOST INTERRUPTS %IF LOST INT = 20 %START; ! GIVE IT 5 SECS TO TRANSMIT THE BLOCK TELL; PRINTSTRING("******** MISSING INTERRUPT ********** ") FREE INPUT BUFF REINITIALISE %FINISH %FINISH %IF AAA # TTT %THEN CLOCK1 = CLOCK1+1 %IF CLOCK1 > RR TIME %AND AAA # TTT %AND TSTATE = 0 %START CLOCK3 = CLOCK3+1; !COUNT RETRIES %IF CLOCK3 > 30 %START FLAG = 2 -> LABORT %FINISH CLOCK1 = 0 TTT = AAA; !RESET TRANSMIT COUNT %ELSE %IF CLOCK0 >= RR TIME %START; !SEND ANOTHER RR RSTATE = 6 %IF NO OF BUFF < BIG LIMIT RSTATE = 1 %IF RSTATE = 0 %OR RSTATE = 5 %ELSE %RETURN !! LABORT: ABORT(FLAG); !1..NOTHING VALID IN 40 ! TICKS..2..10 RETRIES TO ! RETRANSMIT %FINISH; %FINISH; %FINISH HANDLE OUTPUT %END !! %ROUTINE REINITIALISE !! GRABS THE INTERRUPT SERVICE NOS AND SETS/RESETS THE DEVICE LINKIN(RXINT); LINKIN(TXINT) PAR_TYPE = INITIALISE PAR_B ==HANDLER ADDRESS %IF LINE TYPE = 0 %START DQS11E(PAR) %ELSE %IF LINE TYPE = 1 %START DUP11E(PAR) %FINISH ICURR_M == IM; ICURR_LEN = 6 ACTIVE = 0; ABORT REQ = 0; LOST INT = 0 START INPUT %END !* S T A R T O F M A I N C O D E !* =================================== MAP VIRT(BUFFER MANAGER, 4, 3) MAP VIRT(BUFFER MANAGER,5,4) MAP VIRT(BUFFER MANAGER, 6, 5) I = SVC(18, 2, 0) IM == M1; OM_M == M2 CHANGE OUT ZERO = T3 SER P2 == P P2_SER = 0; POFF(P2); ! WAIT FOR INSTRUCTIONS LINE = P2_FN; LINE TYPE = P2_LINE&7 HANDLER ADDRESS == P2_M RXINT = P2_LEN!X'FF00'; TXINT = P2_S1!X'FF00' %IF P2_LINE&K'70' # 0 %THEN %C ISTATE = 10 %ELSE ISTATE = INIT(SECONDARY) !! IF ANY OF BITS 3-5 IS SET, LINE IS HELD DOWN REINITIALISE; ! GRAB INTERRUPTS AND RESET DEVICE WREPLY(2, 0); ! HERE I AM (HELLO TO KERNEL) ALARM(25) HANDLE OUTPUT ASK FOR BUFFER %CYCLE P_SER = 0 POFF(P) %IF P_SER&X'80' # 0 %START; ! INTERRUPT %IF P_SER = TX INT&X'FF' %THEN I = OUTPUT DONE %ELSE %C I = INPUT HERE PAR_TYPE = I %IF LINE TYPE = 0 %START DQS11E(PAR) %ELSE %IF LINE TYPE = 1 %START DUP11E(PAR) %FINISH %IF PAR_TYPE = LINE OUTPUT %START ACTIVE = 0; HANDLE OUTPUT %ELSE HANDLE INPUT %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); QMAX = 0; SPACES(4) WRITE(DCOU, 4); WRITE(DSYM, 4) NEWLINE TELL; WRITE(IRD, 4);WRITE(RRRD, 4);WRITE(RNRRD, 4);WRITE(REJRD, 4) WRITE(ITR,6);WRITE(RRTR, 4); WRITE(RNR TR, 4) WRITE(REJTR, 4); NEWLINE TELL; WRITE(BADACK, 4);WRITE(BADFR, 4);WRITE(SILOFULL, 4);WRITE(DM, 4) WRITE(I RE TR-ITR, 5) NEWLINE %FINISH %IF INT = 'A' %START; ! ABORT THE LINE INT = 0 ABORT(4); ! REQUEST TO PUT DOWN %FINISH %IF INT = 'L' %START; ! LOWER PRIORITY MAX READS = 2; BIG LIMIT = 10; RR TIME = 3; CRITICAL = 12 INT = 0 %FINISH %IF INT = 'H' %START; ! HIGHER PRIORITY MAX READS = 5; BIG LIMIT = 4 INT = 0 %FINISH %CONTINUE %FINISH %IF P_REPLY = BUFFER MANAGER %START; ! BUFFER HAS ARRIVED ME2 == P2_M ME2_M == IPOOL IPOOL == ME2 INPUT EXP = INPUT EXP+1 %CONTINUE %FINISH !! USER REQUEST -> SW(P2_FN) SW(OUTPUT REQ): !WRITE REQ %IF ISTATE = 0 %START WPEND = WPEND+1; ! COUNT PENDING WRITES %IF WPEND > Q MAX %THEN Q MAX = W PEND %IF WPEND = WMAX %START TELL; PRINTSTRING("FULL!") ABORT(8); ! FULL UP ->RELEASE %FINISH WDESC == WSPACE(FFF) WDESC_M == P2_M WDESC_M_HTYPE = P2_M_TYPE WDESC_LEN = P2_LEN+2 FFF = (FFF+1)&SFMASK HANDLE OUTPUT; !KICK TRANSMIT %ELSE; ! NOT UP, SO DISCARD SW(INPUT REQ): ! BEING PHASED OUT RELEASE: P_SER = BUFFER MANAGER; P_REPLY = ID P_A1 = 1 PON(P) %FINISH %CONTINUE SW(BOUNCE): ! FORCE LINE BOUNCE ABORT(4) %CONTINUE SW(PUT DOWN): ! FORCE AND HOLD DOWN ABORT(4); ISTATE = 10 %CONTINUE SW(PUT UP): ! ALLOW IT UP AGAIN FREE INPUT BUFF ! RECOVER READ BUFFER IF NOT ALREADY DONE %IF INPUT EXP = 0 %THEN ASK FOR BUFFER ISTATE = INIT(SECONDARY) REINITIALISE; ! GRAB INTERRUPTS AND RESET DEVICE ! MAY HAVE BEEN DOWN LINE LOADED %CONTINUE SW(MONIT): INT = '?' %CONTINUE SW(VARBS ADDRESS): R1 == R2 R1_N == ISTATE P_SER = P_REPLY; P_REPLY = ID P_A1 = 0; ! TYPE IS PROTOCOL HANDLER P_A2 = R2_X; ! PLANT ADDRESS PON(P) %REPEAT %ENDOFPROGRAM