.TITLE DSP - DISPATCH PROCESS FOR SPP AND TRANSPARENT CONNECTIONS .INSERT MOSCNF-1.SML .INSERT MOSMAC.SML .INSERT MOSTBL.SML .INSERT DSPTBL.SML .INSERT DSPMAC.SML .LIST ME $CNFIG ; SYSTEM CONFIGURATION .PAGE $DFHDR ; PACKET HEADER $DFPKD ; PACKET DESCRIPTOR $DFDEV ; DEFINE DEVICE NUMBERS $DFDCN ; DISPATCH CONTANTS .PAGE $DFCCB ; CONNECTION CONTROL BLOCK .PAGE $DFDOP ; DISPATCH OP-CODES $DFDSC ; DISPATCH STATUS CODES $DFDOF ; DISPATCH OPTION FLAGS $DFDST ; DISPATCH STATES .NLIST ME .LIST MEB .ENABLE ISD .PAGE ; ; GLOBALS ; .GLOBL $DSP,$ETEBL,$ETEDF,$NOCNN .GLOBL $CVTBL,$GSTBL,$NSCON,$DSPID,$NTSTS,$DEQ .GLOBL $PROPN,$PRRCV,$PRSND,$PRCLS,$HRDY .GLOBL PKTLCL,PKTFGN,PKTCTL,FRMHDR,SNDPKT,PKTSTS .GLOBL DEQPKT,RTNACK,HNDOFF,RCVCLN,RLSCCB,ALCPKT .GLOBL $DSPTP,$DSPBT,ALSPKT .GLOBL $TIUID ; ; ; .MACRO $VRCCB ?A,?B ; VERIFY CCB ADDRESS CMP R5,@CVTPTR(R5) ;R5 = VALUE IN VECTOR TABLE? BEQ B ; NO ==> SKIP ERROR $ERROR ; INDICATE ERROR B: .ENDM $VRCCB .SBTTL $DSP - INITIALIZATION AND WAIT LOOP $DSPTP: $DSP: MOV #$CVTBL,R3 ; R3 = A(CONN VECTOR TABLE) MOV (R3)+,R2 ; R2 = MAX NO. OF ENTRIES 1$: CLR (R3)+ ; CLEAR ENTRY $LOOP R2,1$ MOV #CSLEN/2,R2 ; R2 = LENGTH( A STATISTICS TABLE) MOV #$GSTBL,R3 ; R3 = A(GLOBAL STATISTICS) 2$: CLR (R3)+ ; CLEAR ENTRY $LOOP R2,2$ MOV #$ETEDF,R1 ; R1 = A(ETE DEFAULT BUCKET LIMITS) MOV #$ETEBL,R2 ; R2 = A(ETE CURRENT BUCKET LIMITS) MOV #NETEBK-1,R3 ; R3 = NO. OF BUCKET LIMIT DEFINITIONS 3$: MOV (R1)+,(R2)+ ; COPY DEFAULTS INTO CURRENT LIMIT DEF. $LOOP R3,3$ ; LOOP CLR $NOCNN ; INIT "DROP PKT NO CONNECTION" COUNT CLR $NSCON ; CLEAR "NO. OF CONNECTIONS" COUNT $GAPID ; R0= OUR PID MOVB R0,$DSPID ; SAVE IT FOR SIGNALS $SEMTX #20,#$PROPN ; SET OPEN EXIT $SEMTX #21,#$PRRCV ; SET RECEIVE EXIT $SEMTX #22,#$PRSND ; SET SEND EXIT $SEMTX #23,#$PRCLS ; SET CLOSE EXIT JSR PC,INPUT ; START 2 INPUTS FROM PRU JSR PC,INPUT DSPLP: $WAIT ; WAIT FOR WORK ; RETURN LSB R0 = OP-CODE, R1 = DATA MOV R1,R5 ; R5 = DATA WORD BIC #^C17,R0 ; CLEAR ALL EXCEPT LOW 4 BITS ASL R0 ; CONVERT TO WORD INDEX JSR PC,@DSPOPC(R0) ; CALL APPROPRIATE ROUTINE ; NOTE THAT THE SIGNAL ROUTINES MAY ; NOT SAVE REGISTERS BR DSPLP ; GET NEXT SIGNAL DSPOPC: .WORD PKTRCV ; PACKET JUST RECEIVED FROM PRU .WORD SPPOPN ; SEND OPEN PACKET .WORD SPPSND ; SEND PACKET THATS ON SEND QUEUE .WORD PKTSNT ; PACKET JUST SENT TO PRU .WORD SPPACK ; SEND ACK PACKET .WORD SPPCLS ; SEND CLOSE PACKET .WORD RTXTIM ; RETRANSMIT TIMER EXPIRED .WORD ORTTIM ; ONE ROUND TRIP TIME EXPIRED .WORD RFLACK ; REFLECTED OR ACK PACKET JUST SENT .PAGE .SBTTL PKTRCV - PACKET RECEIVED ; ; CALLED WITH: R1 = R5 = A(PKT) ; PKTRCV: MOV R1,R0 ; R0 = A(PKT) TST PDSTAT(R0) ; IS THE PKT OK AND PR UP BMI REUSPK ; NO ==> REUSE PKT FOR INPUT CLR PKTSTS ; INIT PKT STATUS JSR PC,INPUT ; ELSE REISSUE AN INPUT, C=1 NO STORAGE BCC 1$ ; C = 0 ==> CONTINUE MOV #1,PKTSTS ; INDICATE PKT TO BE RLSD AFTER DSPTCH 1$: CLRB $NTSTS ; INDICATE IMP/PR READY AGAIN ; ELIMINATE CKSUM IF PRESENT, VERIFY ; PKT LEN WITH AMT RECEIVED. MOV PDADDR(R0),R1 ; R1 = A(PKT) MOVB 1(R1),R1 ; R1 = PKT LEN(WORDS) FROM HDR ASL R1 ; R1 = PKT LEN(BYTES) FROM HDR CMP R1,PDBX(R0) ; DOES THE PKT LEN AGREE W REC CNT BHI REUSPK ; THROW PKT AWAY IF TOO SHORT MOV R1,PDBX(R0) ; SAVE LEN FROM HDR, DEL CKSUM MOV PDADDR(R0),R1 ; R1 = A(HDR) BIT #HC.ACK,HCNTL(R1) ; ACK? BEQ 2$ ; NO ==> SKIP MOV HSRC(R1),PKTLCL ; IF ACK, PKT SOURCE IS LOCAL MATCH ID MOV HDSTN(R1),PKTFGN ; IF ACK, PKT DEST. IS FGN MATCH ID BR 3$ 2$: MOV HDSTN(R1),PKTLCL ; IF REG PKT, PKT DSTN IS LOCAL ID MOV HSRC(R1),PKTFGN ; AND SRC IS FGN ID 3$: MOV HCNTL(R1),PKTCTL ; GET PKT FUNCTION FIELD MOV #$CVTBL,R4 ; R4 = A(CONN VECTOR TABLE) MOV (R4)+,R3 ; R3 = NO. OF ENTRIES FNDLP: MOV (R4)+,R2 ; R2 = PNTR TO A CCB MOV R2,R5 ; R5 = A( A CCB) BEQ 4$ ; IF ZERO ==> SKIP MOV PKTLCL,R1 ; GET LOCAL ID BIC (R2)+,R1 ; APPLY MSK CMP R1,(R2)+ ; COMPARE TO LCL ID BNE 4$ ; NOT EQUAL TRY NEXT CCB MOV PKTFGN,R1 ; R1 = FGN ID BIC (R2)+,R1 ; APPLY MSK CMP (R2)+,R1 ; COMPARE BNE 4$ ; NOT EQUAL ==> TRY NEXT CCB MOV PKTCTL,R1 ; R1 = FUNCTION MOV 2(R2),-(SP) ; SAVE ON STACK COMPARE WORD BIC (R2),(SP) ; APPLY MASK BIC (R2),R1 ; APPLY MASK TO PKT CONTROL WORD CMP (SP)+,R1 ; COMPARE BNE 4$ ; NOT EQUAL ==> TRY NEXT CCB MOV PDADDR(R0),R1 ; RESTORE R1 = A(HDR) JSR PC,PRCPKT ; PROCESS PACKET RTS PC 4$: $LOOP R3,FNDLP ; LOOP NEXT CCB INC $NOCNN ; BUMP "NO CONNECTION" COUNT TST PKTSTS ; WAS "INPUT" SUCCESSFUL? BNE REUSPK ; NO REUSE PACKET FOR INPUT JSR PC,RLSPKT ; RELEASE PKT RTS PC REUSPK: $SIO R0 ; REISSUE INPUT RTS PC .PAGE .SBTTL PRCPKT - PROCESS PACKET ; IN WITH: R0 = A(PKT DESC) ; R1 = A(HDR) ; R5 = A(CCB) ; PRCPKT: BIT #HC.ACK,HCNTL(R1) ; ACK? BEQ 1$ ; NO ==> CONTINUE JSR PC,FNDCON ; PROCESS ACK TST PKTSTS ; WAS INPUT SUCCESSFUL? BEQ PRCRTN ; YES ==> RETURN JSR PC,INPUT ; INPUT AGAIN BR PRCRTN 1$: BIT #HC.ARQ,HCNTL(R1) ; ACK PKT REQUIRED? BEQ 2$ ; NO ==> SEE IF PKT CAN BE PROCESSED $PUSH R0 $SCK #PDLEN+PKTLEN ; STORAGE CHECK FOR ANOTHER PKT TST R0 ; ZERO? BEQ 3$ ; YES ==> DROP PKT $POP R0 ; RESTORE R0 2$: TST PKTSTS ; CAN WE PROCESS PKT? BNE 4$ ; NO ==> DROP PKT JSR PC,FNDCON ; PROCESS PKT BR PRCRTN 3$: $POP R0 4$: INC CSDRPB(R5) ; BUMP DROP PKT COUNT $SIO R0 ; REISSUE INPUT PRCRTN: RTS PC .PAGE .SBTTL FNDCON - FOUND CONNECTION THAT MATCHES PKT ; ; CALLED WITH: R0 = A(PKT) ; R1 = A(HDR) ; R5 = A(CCB) ; FNDCON: INC CSPKRC(R5) ; BUMP PKTS RECEIVED COUNT JSR PC,RTNBYT ; RETURN R2 = BYTES IN PKT ADD R2,CSBYTR+2(R5) ; UPDATE BYTES RECEIVED ADC CSBYTR(R5) ; MOVB COPFLG(R5),R4 ; R4 = FLAGS BITB #DF.TRN,R4 ; TRANSPARENT? BEQ SPPRCV ; NO ==> SPP PACKET RECEIVED BITB #DF.LSN,R4 ; LISTENING CONNECTION BEQ 1$ ; NO ==> NOT LISTENING BICB #DF.LSN,COPFLG(R5) ; CLEAR LISTENING FLAG MOV PKTFGN,CFGNID(R5) ; SET FGN ID CLR CFGNMK(R5) ; SET BIC MASK 1$: BITB #DF.SNK,R4 ; SINK PKT? BEQ 3$ ; NO ==> REGULAR TRANSPARENT PKT BR 4$ 3$: CMP CRCVCT(R5),#- ; HAS MAX NO. OF PKTS QUEUED BEEN REACHECD? BEQ 4$ ; YES ==> RELEASE PKT DEC CRCVCT(R5) ; DEC COUNT BMI 5$ ; NO RCV'S OUTSTATNDING ==> QUEUE PKT JSR PC,RTNACK ; RETURN ACK IF REQUESTED MOV R0,R1 ; R1 = A(PKT) $SGNLI CURPID(R5),CRCVOP(R5),R1; SIGNL USER WITH NEW PKT RTS PC 5$: CLR (R0) ; CLEAR LINK MOV R0,@CRCVQT(R5) ; LINK TO TAIL PKT MOV R0,CRCVQT(R5) ; RESET TAIL PNTR RTS PC 4$: JSR PC,RLSPKT ; RELEASE PACKET RTS PC .PAGE .SBTTL SPPRCV - SPP PACKET RECEIVE ; ; ENTERED WITH: R0 = A(PKT) ; R1 = A(HDR) ; R4 = FLAGS ; R5 = A(CCB) ; SPPRCV: MOV CSTATE(R5),R3 ; R3 = STATE BIC #HS.RCF*400,HSEQ(R1) ; CLEAR OUT THE RETRANSMIT COUNT BIT #HC.ACK,HCNTL(R1) ; IS THIS AN ACK? BNE ACKPKT ; YES ==> ACK PKT BIT #HF.SYN!HF.FIN,HCNTL(R1); OPEN OR CLOSE PKT? BNE OPNCLS ; YES ==> OPN OR CLS BIT #ST.ROP,R3 ; IS RCV OPEN? BEQ 1$ ; NO ==> DISCARD PKT JSR PC,WINDOW ; WINDOW THE PACKET JSR PC,HNDOFF ; HAND OFF PKT TO USER RTS PC 1$: JSR PC,RLSPKT ; DISCARD PACKET RTS PC .PAGE .SBTTL OPNCLS - OPEN OR CLOSE PACKET RECEIVED ; ; ENTERED WITH: R0 = A(PKT) ; R1 = A(HDR) ; R3 = STATE ; R4 = FLAGS ; R5 = A(CCB) ; OPNCLS: BIT #HF.SYN,HCNTL(R1) ; OPEN PACKET? BEQ CLSPKT ; NO ==> CLOSE PACKET BITB #DF.LSN,R4 ; WAS CONNECTION LISTENING? BEQ 1$ ; NO ==> CONTINUE MOV PKTFGN,CFGNID(R5) ; SET FOREIGN COMPARE WORD CLR CFGNMK(R5) ; SET FOREIGN BIC WORD JSR PC,SPPOPN ; SEND OPEN PKT BICB #DF.LSN,COPFLG(R5) ; CLEAR LISTEN FLAG 1$: BIT #ST.ROP,R3 ; RCV SIDE OPEN? BNE 2$ ; YES ==> CONTINUE BIS #ST.ROP,CSTATE(R5) ; CONNECTION NOW OPEN MOV HSEQ(R1),CRSQNO(R5) ; INIT SEQ. NO. SWAB CRSQNO(R5) ; UNSWAP BYTES $PUSH R0,R1 $STIME #SG.ORT,R5,#ORTDLY ; START ORT TIMER FOR THIS CONNECTION $POP R1,R0 2$: BIT #ST.ORT,R3 ; ORT EXPIRED? BNE 4$ ; YES ==> CLOSE UP CONNECTION JSR PC,WINDOW ; WINDOW PKT ON RCV QUEUE JSR PC,HNDOFF ; AND HAND OFF ANY PKTS TO USER RTS PC 4$: BIS #ST.DEL,CSTATE(R5) ; PUT INTO DELETE STATE JSR PC,CLSUP ; TRY CLOSING UP. RTS PC .PAGE .SBTTL CLSPKT - CLOSE PACKET RECEIVED ; ; ENTERED WITH: R0 = A(PKT) ; R1 = A(HDR) ; R4 = FLAGS ; R5 = A(CCB) ; CLSPKT: MOV CSTATE(R5),R3 ; R3 = REFRESHED STATE BIT #ST.ROP,R3 ; RCV OPEN? BEQ 1$ ; NO ==> DISCARD PKT JSR PC,WINDOW ; WINDOW PACKET ON RCV QUEUE JSR PC,HNDOFF ; AND HANDOFF PKT TO USER. RTS PC 1$: JSR PC,RLSPKT ; RELEASE PKT RTS PC .PAGE .SBTTL ACKPKT - ACK PACKET RECEIVED ; ; ENTERED WITH: R0 = A(PKT) ; R1 = A(HDR) ; R3 = STATE ; R4 = FLAGS ; R5 = ACCB) ; ACKPKT: INC CSACKR(R5) ; BUMP ACKS RECEIVED COUNT MOV HSEQ(R1),R2 ; R2 = SWAPPED PKT SEQ. NO. SWAB R2 ; UNSWAP IT BIC #HS.RCF,R2 ; CLEAR RETRANSMIT COUNT MOV PKTTMH(R1),CSACKT(R5) ; GET HIGH WORD OF TIME STAMP MOV PKTTML(R1),CSACKT+2(R5) ; GET LOW WORD JSR PC,RLSPKT ; RELEASE ACK PKT MOV R2,R3 ; R3 = SEND LEFT WINDOW EDGE (LWE) SUB CSDLWE(R5),R3 ; R3 = ACK SEQ NO. (A) MINUS LWE BMI 1$ ; IF (A-LWE) < 0 ==> DUPLICATE ACK MOV R2,R3 ; R3 = SEND LWE SUB CSEQNO(R5),R3 ; R3 = (A) MINUS RIGHT MOST PKT SEQ. NO BEQ 2$ ; IF EQUAL THEN ACK IS WITHIN SEND WINDOW BMI 2$ ; IF MINUS THEN ACK IS BEFORE RIGHT WINDOW EDGE RTS PC ; ELSE ACK IS OUTSIDE SEND WINDOW; IGNORE IT 1$: INC CSDUPA(R5) ; BUMP DUPLICATE ACK COUNT RTS PC 2$: TST CSSNDC(R5) ; OUTPUT IN PROGRESS? BEQ 3$ ; NO ==> PROCESS ACK BIS #ST.ACK,CSTATE(R5) ; INDICATE ACK PROCESSING NEEDED MOV R2,CACKSQ(R5) ; SAVE ACK SEQ NO. RTS PC 3$: JSR PC,ACKPRS ; PROCESS ACK RTS PC .PAGE .SBTTL WINDOW - WINDOW PACKET ON RECEIVE QUEUE ; ; CALLED WITH: R0 = A(PKT) ; R5 = A(CCB) ; WINDOW: $PUSH R1,R2,R3,R4 MOV PDLEN+HSEQ(R0),R1 ; R1 = SWAPPED SEQ NO. SWAB R1 ; UNSWAP IT MOV R1,R2 ; R2 = PKT SEQ NO. (P) SUB CRSQNO(R5),R2 ; R2 = P - LWE BMI 1$ ; IF MINUS ==> DUPLICATE SO ACK & RLS ASH #-RCFWID,R2 ; SHIFT OVER RETRANSMIT FIELD CMP R2,CRCVCT(R5) ; COMPARE (P - LWE) TO WINDOW SIZE BGT 7$ ; IF GREATER THAN ==> OUTSIDE WINDOW DISCAD MOV R5,R4 ; R4 = A(CCB) ADD #CRCVQH,R4 ; R4 = A(HEAD OF RCV QUEUE) 3$: MOV R4,R3 ; R3 = A(PREVIOUS PKT) MOV (R3),R4 ; R4 = A(CURRENT PKT) BEQ 4$ ; ZERO ==> LINK PKT IN; UPDATE TAIL MOV PDLEN+HSEQ(R4),R2 ; R2 = SWAPPED SEQ. NO. OF RCV Q PKT (R) SWAB R2 ; UNSWAP IT SUB R1,R2 ; R2 = R - P BEQ 8$ ; IF EQUAL ITS A DUPLICATE SO DON'T SEND ACK BMI 3$ ; IF (R-P)< 0 THEN COMPARE TO NEXT PKT BR 5$ ; CONTINUE 4$: MOV R0,CRCVQT(R5) ; UPDATE TAIL PNTR 5$: MOV R4,(R0) ; LINK NEW PKT TO POINT TO CURRENT PKT MOV R0,(R3) ; BR 6$ 7$: INC CSBYDW(R5) ; BUMP "BEYOND WINDOW" COUNT BR 2$ 8$: INC CSDUPP(R5) ; BUMP "DUPLICATE WITHIN WINDOW" COUNT BR 2$ 1$: INC CSBFRW(R5) ; BUMP "BEFORE WINDOW" COUNT JSR PC,RTNACK ; RETURN ACK IF REQUESTED 2$: JSR PC,RLSPKT ; AND RELEASE 6$: $POP R4,R3,R2,R1 RTS PC .PAGE .SBTTL HNDOFF - HANDOFF PACKET TO USER ; ; CALLED WITH: R5 = A(CCB) ; HNDOFF: $PUSH R0,R1,R2,R3,R4 CLR R0 ; CLEAR PREVIOUS PKT PNTR HNDLOP: MOV CRCVQH(R5),R3 ; R3 = A(CURRENT PKT) BEQ HNDACK ; NO PKTS LEFT ==> EXIT PROCEDURE MOV PDADDR(R3),R4 ; R4 = A(CURRENT HDR) TST CRCVCT(R5) ; TEST RCV COUNT FOR ZERO BEQ HNDCLC ; ZERO ==> CHECK FOR CLOSE PKT MOV HSEQ(R4),R2 ; R2 = SEQ NO. OF CURRENT PKT SWAB R2 ; SWAP TO CORRECT POSITION CMP R2,CRSQNO(R5) ; COMPARE SEQ NO. TO LWE BNE HNDACK ; NOT EQUAL ==> EXIT PROCEDURE JSR PC,HNDPRC ; PROCESS PREVIOUS PACKET MOV #CRCVQH,R2 ; R2 = OFFSET TO RCV Q HEAD JSR PC,DEQPKT ; R0 = CURRENT PKT ADDRESS MOV PDADDR(R0),R1 ; R1 = A(CURRENT HDR) DEC CRCVCT(R5) ; UPDATE RCV COUNT ADD #HS.RCF+1,CRSQNO(R5) ; UPDATE LWE BIT #HF.FIN,HCNTL(R1) ; CLOSE PKT? BEQ HNDLOP ; NO ==> HANDOFF LOOP BIS #ST.RCR,CSTATE(R5) ; MARK CLOSE PKT RECEIVED BIC #ST.ROP,CSTATE(R5) ; MARK RCV CLOSED BIS #SC.CLR*400,PDSTAT(R0) ; MARK PKT STATUS AS CLOSED REMOTELY MOV R0,R1 ; R1 = A(PKT) $SGNLI CURPID(R5),CRCVOP(R5),R1; SIGNAL USER WITH PKT MOV R1,R0 ; R0 = A(PKT) JSR PC,RTNACK ; RETURN ACK IF REQUESTED BR HNDRTN HNDCLC: CMPB HPKTL(R4),#SPPHDL/2 ; CHECK FOR DATA IN PKT BHI HNDRTN ; HIGH; PKT HAS DATA ==> RETURN BIT #HF.FIN,HCNTL(R4) ; CLOSE PKT? BEQ HNDRAK ; NO ==> HANDOFF AND ACK BIS #ST.RCR,CSTATE(R5) ; CLOSE RCVD BIC #ST.ROP,CSTATE(R5) ; RCV CLOSED HNDRAK: JSR PC,HNDPRC ; PROCESS PREVIOUS PKT MOV #CRCVQH,R2 ; R2 = OFFSET TO RCV Q HEAD JSR PC,DEQPKT ; R0 = R0 = A(CURRENT) ADD #HS.RCF+1,CRSQNO(R5) ; BUMP SEQNO HNDACK: TST R0 ; PREVIOUS PKT? BEQ HNDRTN ; NO ==> RETURN JSR PC,RTNACK ; RETURN ACK IF REQUESTED JSR PC,HNDPRC ; PROCESS PREVIOUS PKT HNDRTN: $POP R4,R3,R2,R1,R0 RTS PC HNDPRC: TST R0 ; PKT EXIST? BEQ 1$ ; NO ==> SKIP CMPB PDLEN+HPKTL(R0),#SPPHDL/2; ANY DATA? BHI 2$ ; YES ==> SIGNAL USER WITH PKT JSR PC,RLSPKT ; NO, RELEASE PKT BR 1$ 2$: MOV R0,R1 ; R1 = A(PKT) $SGNLI CURPID(R5),CRCVOP(R5),R1; SIGNAL USER WITH PKT MOV R1,R0 ; RESTORE R0 = A(PKT) 1$: RTS PC .PAGE .SBTTL SPPOPN - SPP OPEN CONNECTION SIGNAL ; ; CALLED WITH: R5 = A(CCB) ; SPPOPN: $PUSH R3 $VRCCB MOV #HF.SPP!HF.SYN!HT.IP!HC.ARQ,R3 ; R3 = OPEN FUNCTION WORD JSR PC,SNDOPC ; SEND OPEN PKT BCC 1$ ; NO ERRORS ==> CONTINUE $PUSH R0,R1 $SGNLI $DSPID,#SG.OPN,R5 ; SIGNAL SELF AND TRY AGAIN $POP R1,R0 BR 2$ 1$: BIS #ST.OPS,CSTATE(R5) ; INDICATE CONNECTION BEING OPENED 2$: $POP R3 RTS PC .SBTTL SPPSND - SPP SEND PACKET SIGNAL ; ; CALLED WITH: R5 = A(CCB) ; SPPSND: $PUSH R0,R2,R3 $VRCCB MOV #CSNDQH,R2 ; R2 = OFFSET TO SEND Q HEAD JSR PC,DEQPKT ; R0 = A(PKT) MOVB PDOP(R0),CSNDOP(R5) ; SAVE OP-CODE TO SIGNAL SENDS WITH BIT #ST.DEL,CSTATE(R5) ; CONNECTON READY FOR DELETION BNE 1$ ; YES ==> JUST PUT PKT ON RTX QUEUE MOVB #SG.SNT,PDOP(R0) ; SET OP-CODE TO BE SIGNALED WITH MOV CCTLWD(R5),R3 ; R3 = CONTROL WORD BIS #HF.SPP!HC.ARQ,R3 ; FORCE SPP AND ARQ BITS ON MOV PDADDR(R0),R2 ; R2 = A(HDR) JSR PC,FRMHDR ; FORMAT HEADER JSR PC,SNDRLB ; SEND OUT PKT RELIABLY BR 2$ 1$: CLR PDRTX(R0) ; CLEAR LINK MOV CRTXQT(R5),R3 ; R3 = A(TAIL PKT) MOV R0,PDRTX(R3) ; LINK PKT TO TAIL MOV R0,CRTXQT(R5) ; SET TAIL PNTR JSR PC,CLSUP ; TRY CLOSING UP CONNECTION 2$: $POP R3,R2,R0 RTS PC .PAGE .SBTTL PKTSNT - PACKET SENT SIGNAL ; ; CALLED WITH: R1 = A(PKT) ; PKTSNT: MOV PDCON(R1),R5 ; R5 = A(CCB) $VRCCB DEC CWRKCT(R5) ; DECREMENT WORK COUNT DEC CSSNDC(R5) ; DECREMENT SEND PKT COUNT BNE 2$ BIT #ST.ACK,CSTATE(R5) ; ANY ACK PROCESSING PENDING? BEQ 2$ ; NO ==> SKIP MOV CACKSQ(R5),R2 ; R2 = ACK SEQ. NO. JSR PC,ACKPRS ; PROCESS ACK ; RETURN R5 = 0 IF CONN. CLOSED TST R5 ; CONNECTION CLOSED BEQ 1$ ; YES ==> RETURN 2$: BIT #ST.DEL,CSTATE(R5) ; CONNECTION READY FOR DELETION? BEQ 1$ ; NO ==> RETURN JSR PC,CLSUP ; ELSE TRY CLOSING UP CONNECTION 1$: RTS PC .SBTTL SPPACK - SPP SEND ACK PKT ; ; CALLED WITH: R5 = A(CCB) ; SPPACK: $PUSH R0 $VRCCB MOV #CSNDQH,R2 ; R2 = OFFSET TO SEND Q HEAD JSR PC,DEQPKT ; R0 = A(PKT TO BE SENT) DEC CWRKCT(R5) ; DECREMENT WORK COUNT BIT #ST.DEL,CSTATE(R5) ; DELETION STATE? BNE 1$ ; YES ==> RELEASE PKT MOVB #SG.RFA,PDOP(R0) ; SET OP-CODE AS ACK BEEN SENT MOV #SPPHDL,PDPKLN(R0) ; SET PKT LENGTH INC CSACKS(R5) ; BUMP ACKS SENT COUNT JSR PC,SNDPKT ; SEND PKT OUT TO PRU BR 2$ ; RETURN 1$: JSR PC,RLSPKT ; RELEASE PACKET JSR PC,CLSUP ; TRY CLOSING UP CONN 2$: $POP R0 RTS PC .PAGE .SBTTL SPPCLS - SPP SEND CLOSE PACKET SIGNAL ; ; CALLED WITH: R5 = A(CCB) ; SPPCLS: $PUSH R3 $VRCCB MOV #HF.SPP!HF.FIN!HT.IP!HC.ARQ,R3 ; R3 = CLOSE FUNCTION JSR PC,SNDOPC ; SEND CLOSE PKT BCC 1$ ; NO ERRORS ==> RETURN $SGNLI $DSPID,#SG.CLS,R5 ; SIGNAL SELF AND TRY AGAIN 1$: $POP R3 RTS PC .SBTTL RTXTIM - RETRANSMIT TIMER EXPIRED ; ; CALLED WITH: R5 = A(CCB) ; RTXTIM: $VRCCB CMP #MAXRTX,CRTXCT(R5) ; HAS MAX. NO. OF RTX BEEN REACHED BEQ 1$ ; YES ==> RTX CLEAN UP MOV CRTXQH(R5),R0 ; R0 = A(FIRST PKT IN RTX QUEUE) BEQ 2$ ; NO PKT ==> KILL TIMER INC CRTXCT(R5) ; BUMP RTX COUNT TSTB PDSTAT(R0) ; IS I/O DONE ON THIS PKT? BPL 3$ ; NO DON'T SEND PKT JUST KEEP THE ; RTX COUNT BEING BUMPED IN CASE ; THE 1822 GET CLOGGED. THIS WILL ; EVENTUALLY CAUSE THE CONNECTION TO ; TO CLOSE. INC CSSNDC(R5) ; BUMP SEND COUNT IN CASE ACK RCVD INC CSRTXP(R5) ; BUMP RETRANSMITTED PKT COUNT JSR PC,RTNBYT ; RETURN R2 = NO. BYTES IN PKT ADD R2,CSRTXB+2(R5) ; UPDATE RETRANSMITTED BYTE COUNT ADC CSRTXB(R5) ; INC CWRKCT(R5) ; INDICATE WORK IN PROGRESS MOV PDADDR(R0),R2 ; R2 = A(PKT HDR) MOVB HSEQ+1(R2),R1 ; R1 = LSB SEQ. NO. AND RTX COUNT INC R1 ; BUMP HS.RCF BIC #^CHS.RCF,R1 ; CLEAR ALL BUT HS.RCF BICB #HS.RCF,HSEQ+1(R2) ; CLEAR HS.RCF IN SEQ. NO. BISB R1,HSEQ+1(R2) ; SET NEW HS.RCF FIELD $SIO R0 ; RETRANSMIT HEAD PKT 3$: $STIME #SG.RTX,R5,#RTXDLY ; SET RETRANSMIT TIMER BR 2$ 1$: $STIME #SG.RTX,R5,#0 ; KILL TIMER BIS #ST.DEL,CSTATE(R5) ; SET INTO DELETE STATE JSR PC,CLSUP ; TRY CLOSING UP CONN 2$: RTS PC .PAGE .SBTTL ORTTIM - ONE ROUND TRIP TIME DELAY EXPIRED ; ; CALLED WITH: R5 = A(CCB) ; ORTTIM: $VRCCB BIS #ST.ORT,CSTATE(R5) ; SET ORT STATE BIT RTS PC .SBTTL RFLACK - REFLECT OR ACK PACKET SENT OUT ; ; CALLED WITH: R1 = A(PKT) ; RFLACK: $PUSH R0,R2,R5 MOV PDCON(R1),R5 ; R5 = A(CCB) $VRCCB $FVS #PDLEN+PKTLEN,R1 ; FREE PACKET DEC CWRKCT(R5) ; ONE ITEM OF WORK DONE BIT #ST.DEL,CSTATE(R5) ; SHOULD CONNECTION BE DELETED BEQ 1$ ; NO == SKIP JSR PC,CLSUP ; TRY CLOSING CONNECTION 1$: $POP R5,R2,R0 RTS PC .PAGE .SBTTL INPUT - INPUT PKT FROM PRU INPUT: $PUSH R0,R2 JSR PC,ALSPKT ; R0 = A(PKT), R2 = A(HDR) BCS 1$ ; NO PKT ==> RETURN WITH CARRY SET MOV #PKTLEN,PDPKLN(R0) ; SET PACKET LENGTH (HDR+TEXT+CHKSUMS) MOV #IMPIN,PDDEV(R0) ; SET DEVICE NUMBER AS PR INPUT MOVB #SG.RCV,PDOP(R0) ; SET RECEIVE OP-CODE $SIO R0 ; START INPUT CLC 1$: $POP R2,R0 RTS PC .SBTTL FRMHDR - FORMAT HEADER ; ; CALLED WITH: R0 = A(PACKET DESCRIPTOR) ; R2 = A(HEADER) ; R3 = FUNCTION WORD FOR HEADER ; R5 = A(CCB) ; FRMHDR: $PUSH R2,R4 MOVB #SPPHDL/2,(R2)+ ; SET HDR LENGTH IN WORDS MOV PDPKLN(R0),R4 ; R4 = PKT LENGTH, BYTES CLC ROR R4 ; CONVERT TO WORD LENGTH ADC R4 ; ROUND UP MOVB R4,(R2)+ ; SET PKT LENGTH, WORDS MOV CLCLID(R5),(R2)+ ; SET SOURCE ID MOV CFGNID(R5),(R2)+ ; SET DESTINATION ID ADD #HS.RCF+1,CSEQNO(R5) ; BUMP SEQ NO. MOV CSEQNO(R5),(R2) ; SET SEQ NO. SWAB (R2)+ ; SWAB BACKWARDS FORMAT MOV R3,(R2)+ ; SET FUNCTION WORD CLR (R2)+ ; CLEAR MEASUREMENT WORD CLR (R2)+ ; CLEAR FIRST ID BITB #DF.FWD,COPFLG(R5) ; SHOULD PKT BE FORCED THROUGH STATION? BNE 1$ ; YES ==> SET NEXT SEL. TO FF CLR (R2) ; CLEAR FOR INDEX MOVB CONNID(R5),(R2) ; OTHERWISE INSERT CONNID AS AN INDEX SUB #1,(R2) ; ADJUST INDEX TO RANGE FROM ZERO SWAB (R2) ; SWAP FOR THE PR'S SAKE BR 2$ 1$: MOV #^HFFFF,(R2) ; SET ID TO FORCE ROUTE TO STATION BIS #4,-4(R2) ; SET ROUTE SUPP. BIT IN MEAS WORD ; SWAPED FOR PR'S SAKE 2$: $POP R4,R2 RTS PC .PAGE .SBTTL ACKPRC - ACK PROCESSOR ; ; CALLED WITH: R2 = UNSWAPPED ACK SEQ. NO. ; R5 = A(CCB) ; ; RETURN WITH: R5 = 0 IF CONNECTION CLOSED ; ACKPRS: $PUSH R0,R1,R3,R4 BIC #ST.ACK,CSTATE(R5) ; CLEAR ACK PROCESSING BIT SWAB R2 ; SWAB ACK SEQ NO. TO BACKWARD FORMAT 7$: JSR PC,DEQRTX ; DEQUEUE PKT FROM RTX Q ; R0 = A(PKT), R1 = A(HDR) TST R0 ; ANY BUFFERS? BNE 9$ ; YES ==> CONTINUE BUGHLT ; NO PKT FOUND SO MUST BE BAD ACK SEQ. 9$: $PUSH PKTTML(R1),PKTTMH(R1) ; SAVE TIME STAMP FOR THIS PKT MOV HSEQ(R1),R3 ; R3 = RTX PKT SEQ NO. BIC #HS.RCF_8.,R3 ; CLEAR RETRANSMIT COUNT MOV HCNTL(R1),R4 ; R4 = FUNCTION WORD OF RTX PKT ADD #HS.RCF+1,CSDLWE(R5) ; BUMP SEND LWE BIT #HF.SYN!HF.FIN,R4 ; IS THIS AN OPEN OR CLOSE PKT? BNE 4$ ; YES ==> CONTINUE MOV R0,R1 ; R1 = A(PKT) $SGNLI CURPID(R5),CSNDOP(R5),R1; SIGNAL USER THAT PACKET WAS SENT. BR 5$ 4$: JSR PC,RLSPKT ; RELEASE PKT CLR R1 ; R1 = DATA WORD = SUCESS STATUS CODE MOV CURPID(R5),R0 ; R0 = USER OP-CODE, PID $SGNLI R0,R0,R1 ; SIGNAL CALLER THAT CONNECTION HAS ; OPEN OR CLOSED BIT #HF.SYN,R4 ; WAS IT AN OPEN PKT? BNE 6$ ; YES ==> OPEN PKT $POP R0,R1 ; GET PKT TIME STAMP JSR PC,STETES ; SET E-T-E DELAY SPECTRUM BIS #ST.DEL,CSTATE(R5) ; INDICATE CONNECTION SHOULD BE DELETED JSR PC,CLSUP ; TRY CLOSING UP CONN BR 8$ 6$: BIS #ST.OPA,CSTATE(R5) ; INDICATE OPEN HAS BEEN ACKED 5$: $POP R0,R1 ; GET TIME STAMP CMP R2,R3 ; COMPARE ACK SEQ NO. TO DEQD PKT SEQNO BNE 7$ ; NOT EQUAL GET NEXT PKT IN RTX QUEUE JSR PC,STETES ; SET E-T-E DELAY SPECTRUM JSR PC,STRTFS ; SET RETRANSMISSION FREQ. SPECTRUM CLR CRTXCT(R5) ; INIT RTX COUNT BACK TO ZERO. TST CRTXQH(R5) ; IS RTX Q EMPTY? BNE 8$ ; NO ==> SKIP TIMER KILL $STIME #SG.RTX,R5,#0 ; KILL RTX TIMER FOR THIS CONNECTION 8$: $POP R4,R3,R1,R0 RTS PC .PAGE .SBTTL SNDOPC - SEND OPEN/CLOSE PACKET ; ; CALLED WITH: R3 = FUNCTION WORD ; R5 = A(CCB) ; SNDOPC: $PUSH R0,R2 JSR PC,ALSPKT ; ALLOCATE PKT R0 = A(PD), R2 = A(HDR) BCS 1$ ; NO STORAGE ==> RETURN WITH ERROR MOV #SPPHDL,PDPKLN(R0) ; SET PACKET LENGTH IN PD MOVB #SG.SNT,PDOP(R0) ; SET EVENT OP-CODE FOR PKT SENT JSR PC,FRMHDR ; FORMAT PKT HEADER JSR PC,SNDRLB ; SEND PACKET RELIABLY CLC ; I.E PUT ON RTX Q 1$: $POP R2,R0 RTS PC .SBTTL SNDRLB - SEND PACKET RELIABLY ; ; CALLED WITH: R0 = A(PACKET DESCRIPTOR) ; R5 = A(CCB) ; SNDRLB: $PUSH R1 TST CRTXQH(R5) ; ANY PACKETS ON RTX Q? BNE 1$ ; YES ==> DON'T BOTHER TO START TIMER CLR CRTXCT(R5) ; CLEAR COUNT $PUSH R0,R1,R2 ; $STIME #SG.RTX,R5,#RTXDLY ; START TIMER FOR RTX $POP R2,R1,R0 ; 1$: CLR PDRTX(R0) ; CLEAR LINK MOV CRTXQT(R5),R1 ; R1 = A(TAIL PKT) MOV R0,PDRTX(R1) ; LINK TAIL PKT TO THIS ONE MOV R0,CRTXQT(R5) ; UPDATE TAIL PNTR INC CSSNDC(R5) ; BUMP OUTPUT IN PROGRESS COUNT ; IN CASE AN ACK RCVD INC CSARQS(R5) ; BUMP "PKT SENT WITH ARQ" COUNT JSR PC,SNDPKT ; SEND PACKET TO PRU $POP R1 RTS PC .PAGE .SBTTL RTNACK - RETURN ACK PACKET IF REQUESTED ; ; CALLED WITH: R0 = A(PKT TO BE ACKED) ; R5 = A(CCB) ; RTNACK: $PUSH R0,R1,R2,R3 MOV PDADDR(R0),R1 ; R1 = A(HDR) BIT #HC.ARQ,HCNTL(R1) ; ACK REQUESTED? BEQ 1$ ; NO ==> SKIP JSR PC,ALCPKT ; R0 = A(ACK PKT), R2 = A(ACK HDR) $PUSH R2 ; SAVE A(ACK HDR) MOV #SPPHDL/2,R3 ; R3 = TALLY 2$: MOV (R1)+,(R2)+ ; COPY WORD $LOOP R3,2$ ; LOOP $POP R2 ; R2 = A(ACK HDR) MOVB #SPPHDL/2,HPKTL(R2) ; SET PKT LENGTH TO HDR ONLY BIC #HC.ARQ,HCNTL(R2) ; CLEAR ARQ BIS #HC.ACK,HCNTL(R2) ; SET ACK BIT MOV #HC.DIR,R3 ; R3 = DIRECTION MASK XOR R3,HCNTL(R2) ; COMPLEMENT DIRECTION BIT CLR (R0) ; PUT ACK ON SEND Q MOV R0,@CSNDQT(R5) ; LINK TO TAIL PKT MOV R0,CSNDQT(R5) ; UPDATE TAIL PNTR INC CWRKCT(R5) ; ONE MORE WORK ITEM $SGNLI $DSPID,#SG.ACK,R5 ; SIGNAL DSP TO SEND ACK 1$: $POP R3,R2,R1,R0 RTS PC .PAGE .SBTTL SNDPKT - SEND PACKET TO PRU ; ; CALLED WITH: R0 = A(PKT) ; R5 = A(CCB) SNDPKT: $PUSH R2 INC CWRKCT(R5) ; INDICATE WORK IN PROGRESS MOV #IMPOT,PDDEV(R0) ; SET DEVICE NUMBER MOV R5,PDCON(R0) ; SET PNTR BACK TO CCB INC CSPKTX(R5) ; BUMP "PKTS SENT" COUNT JSR PC,RTNBYT ; RETURN R2 = NO. OF BYTES IN PKT ADD R2,CSBYTS+2(R5) ; UPDATE BYTES SENT ADC CSBYTS(R5) ; $SIO R0 $POP R2 RTS PC .SBTTL DEQPKT - DEQUEUE A PACKET ; CALLED WITH: R2 = OFFSET IN CCB TO DESIRED Q HEAD ; R5 = A(CCB) ; ; RETURNS WITH: R0 = A(PKT FROM Q) ; DEQPKT: $PUSH R2 ADD R5,R2 ; R2 = A(Q HEAD) JSR PC,$DEQ ; R0 = A(PKT) $POP R2 RTS PC .PAGE .SBTTL DEQRTX - DEQUEUE PACKET FROM RETRANSMIT QUEUE ; ; RETURN WITH: R0 = A(PKT) ; R1 = A(HDR) ; DEQRTX: MOV CRTXQH(R5),R0 ; R0 = A(HEAD PKT) BEQ 2$ ; IF ZERO RETURN WITH NULL PKT MOV PDRTX(R0),CRTXQH(R5) ; UPDATE HEAD PNTR BNE 1$ ; IF MORE PKTS, DON'T UPDATE TAIL PNTR MOV R5,CRTXQT(R5) ; SET TAIL PNTR TO POINT CRTXQH MINUS ADD #CRTXQH-PDRTX,CRTXQT(R5); PDRTX . 1$: MOV PDADDR(R0),R1 ; R1 = A(HDR) 2$: RTS PC .SBTTL RLSPKT - RELEASE PACKET ; ; CALLED WITH: R0 = A(PKT) ; RLSPKT: $PUSH R2 MOV R0,R2 ; R2 = A(PKT) $FVS #PDLEN+PKTLEN,R2 ; RELEASE PKT $POP R2 RTS PC .SBTTL CLSUP - CLOSE UP CONNECTION ; ; CALLED WITH: R5 = A(CCB) ; CLSUP: TST CWRKCT(R5) ; ANY WORK LEFT TO DO? BNE 1$ ; YESS ==> SKIP FOR NOW $STIME #SG.ORT,R5,#0 ; CANCEL ORT TIMER IF STILL RUNNING JSR PC,STRTFS ; SET RETRANSMISSION FREQ. SPECTRUM JSR PC,RTXCLN ; CLEAN RTX Q JSR PC,RCVCLN ; CLEAN RCV Q JSR PC,RLSCCB ; RELEASE CCB 1$: RTS PC .PAGE .SBTTL RTXCLN - RETRANSMIT QUEUE CLEAN UP ; ; CALLED WITH: R5 = A(CCB) ; RTXCLN: $PUSH R0,R1,R2 RTCLNL: JSR PC,DEQRTX ; DEQUEUE PKT FROM RTX Q ; R0 = A(PKT), R1 = A(HDR) TST R0 ; ANY PKTS? BEQ RTXRTN ; NO ==> SKIP BIT #HF.SYN!HF.FIN,HCNTL(R1); IS THIS A SYN OR FIN PKT BEQ RTXNRM ; NO ==> NORMAL PKT JSR PC,RLSPKT ; ELSE RELEASE PKT MOV CURPID(R5),R0 ; SET OP-CODE AND PID $SGNLI R0,R0,#SC.RTT ; SIGNAL USER THAT RTX TIMEOUT OCCURRED BR RTCLNL ; GET NEXT PKT RTXNRM: BISB #SC.RTT*400,PDSTAT(R1) ; INDICATE RTX TIMEOUT OCCURRED MOV R0,R1 ; R1 = A(PKT) $SGNLI CURPID(R5),CSNDOP(R5),R1; SIGNAL CALLER WITH A(PKT) BR RTCLNL RTXRTN: $STIME #SG.RTX,R5,#0 ; KILL TIMER $POP R2,R1,R0 RTS PC .PAGE .SBTTL RCVCLN - RECEIVE QUEUE CLEAN UP ; ; CALLED WITH: R5 = A(CCB) ; RCVCLN: $PUSH R0,R1,R2 2$: MOV #CRCVQH,R2 ; R2 = OFFSET TO RCV Q HEAD JSR PC,DEQPKT ; RETURN R0 = A(PKT) TST R0 ; ANY PACKET LEFT BEQ 1$ ; NO ==> NO MORE PACKETS JSR PC,RLSPKT ; RELEASE PKT BR 2$ ; LOOP FOR NEXT PKT 1$: $POP R2,R1,R0 RTS PC .PAGE .SBTTL RLSCCB - RELEASE CCB AND UPDATE GLOBAL STATISTICS ; ; CALLED WITH: R5 = A(CCB) ; ; RETURN WITH: R5 = 0 ; RLSCCB: $PUSH R0,R1,R2 MOV #$GSTBL,R0 ; R0 = A(GLOBL STATISTICS TABLE) MOV R5,R1 ; R1 = A(CCB) ADD #CSTBL,R1 ; ADD OFFSET TO STATISTICS TABLE MOV #/4,R2 ; R2 = NO. OF DOUBLE WRD ENTRIES 1$: ADD (R1)+,(R0)+ ; UPDATE MSW OF ENTRY ADD (R1)+,(R0)+ ; UPDATE LSW OF ENTRY ADC -4(R0) ; ADD CARRY TO MSW $LOOP R2,1$ MOV #/2,R2 ; R2 = NO. OF REMAINING ONE WORD ENTRIES 2$: ADD (R1)+,(R0)+ ; UPDATE ENTRY $LOOP R2,2$ DEC $NSCON ; DEC NO. OF CONNECTIONS CLR @CVTPTR(R5) ; CLEAR ENTRY IN CONN VECTOR TABLE $FVS #CCBLEN,R5 ; RELEASE CCB CLR R5 ; INDICATE CCB RELEASED $POP R2,R1,R0 RTS PC .PAGE .SBTTL RTNBYT - RETURN LENGTH OF PACKETS IN BYTES ; ; CALLED WITH: R0 = A(PKT) ; ; RETURN WITH: R2 = LENGTH IN BYTES ; RTNBYT: MOV PDADDR(R0),R2 ; R2 = A(HDR) MOVB HPKTL(R2),R2 ; R2 = NO. OF WORDS IN PKT BIC #377*400,R2 ; CLEAR HIGH BYTE ASL R2 ; CONVERT TO BYTES RTS PC .SBTTL STRTFS - SET DISCRETE RETRANSMISSION FREQ. SPECTRUM ; ; CALLED WITH: R5 = A(CCB) ; STRTFS: $PUSH R0,R1 MOV CRTXCT(R5),R1 ; R1 = NO. OF RETRANSMISSION BEQ 1$ ; SKIP IF NO RETRANSMISSION CLR R0 ; MSB TO ZERO DEC R1 ; ADJUST FOR CALCULATION DIV #RTXBKS,R0 ; COMPUTE BUCKET NO. ASL R0 ; CONVERT TO BYTE OFFSET ADD R5,R0 ; DISPLACE WITHIN CCB INC CSRTFS(R0) ; UPDATE BUCKET 1$: $POP R1,R0 RTS PC .SBTTL STETES - SET E-T-E DELAY TIME SPECTRUM ; ; CALLED WITH: R0 = MSW (SENT TIME) ; R1 = LSW (SENT TIME) ; R5 = A(CCB) ; STETES: $PUSH R0,R1,R2,R3,R4 MOV CSACKT(R5),R2 ; R2 = MSW(ACK TIME STAMP) MOV CSACKT+2(R5),R3 ; R3 = LSW SUB R1,R3 ; COMPUTE TIME DIFFERENCE SBC R2 SUB R0,R2 ADD R3,CSCUMD+2(R5) ; ACCUMLATE E-T-E TIME ADC CSCUMD(R5) ; ADD R2,CSCUMD(R5) ; TST R2 ; IS MSW OF DELAY ZERO? BEQ 1$ ; YES ==>SKIP DEFAULT MOV #-1,R3 ; SET TO LARGEST NO. POSSIBLE 1$: MOV R3,CLSTDT(R5) ; SET LAST PACKET DELAY MOV #NETEBK-1,R4 ; R4 = NO. OF BUCKETS MOV R5,R0 ; R0 = A(CCB) ADD #CSETES,R0 ; R0 = A(E-T-E SPECTRUM TABLE) MOV #$ETEBL,R1 ; R1 = A(BUCKET LIMITS TABLE) 2$: CMP R3,(R1)+ ; IS DELAY <= THIS BUCKET BHI 3$ ; NO ==> NEXT BUCKET INC (R0) ; BUMP BUCKET COUNT BR 4$ 3$: TST (R0)+ ; BUMP BUCKET ADDRESS BY 2 SOB R4,2$ ; LOOP INC (R0) ; BUMP LAST BUCKET 4$: $POP R4,R3,R2,R1,R0 RTS PC $DSPBT: .END