;;; Copyright (c) 1999 Massachusetts Institute of Technology ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License as ;;; published by the Free Software Foundation; either version 3 of the ;;; License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;;; General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. IFE IMPP, IFE CH11P, .ERR NOT EVERYTHING IN CHAOS WILL WORK WITHOUT IMP IFNDEF FTRCHK, FTRCHK==0 ;PROBABLY FOUND ALL THE BUGS THIS WAS GOOD FOR ; LONG AGO IFN FTRCHK, .ERR REDUNDANT CHECKING ENABLED IN CHAOS ROUTINES ;NOTES: ; WINDOW SIZE ADJUSTMENT STUFF ; ROUND TRIP TIME MEASUREMENT & OTHER METERING ; BETTER METERING, SOME METERS ARE CURRENTLY MISSING SUBTTL CH-10 HARDWARE DEFINITIONS IFN CH10P,[ CHX==470 ;I/O DEVICE NUMBER ;CONI/CONO BITS ;1.1-1.3 PIA CHXTEN==10 ;1.4 TRANSMIT INTERRUPT ENABLE CHXREN==20 ;1.5 RECEIVE INTERRUPT ENABLE CHXSPY==40 ;1.6 MATCH ANY DESTINATION CHXLUP==100 ;1.7 LOOP BACK CHXSWB==200 ;1.8 SWAP BYTES CHXHLF==400 ;1.9 HALFWORD DATAO CHXXMT==1000 ;2.1 TRANSMIT DONE (CONI) ; TRANSMIT OR RETRANSMIT PACKET (CONO) CHXRCV==2000 ;2.2 RECEIVE DONE (CONI) ; ENABLE TO RECEIVE NEXT PACKET (CONO) CHXABT==4000 ;2.3 TRANSMIT ABORTED (CONI) ; RESET TRANSMITTER (CONO) $CHXLC==140400 ;2.4-2.7 LOST COUNT (CONI) CHXRST==10000 ;2.4 RESET (CONO) CHXCRC==200000 ;2.8 CRC ERROR (CONI) CHXWLE==400000 ;2.9 WORD LENGTH ERROR (CONI) CHXPLE==1,, ;3.1 PACKET LENGTH ERROR (CONI) CHXOVR==2,, ;3.2 OVERRUN (CONI) $CHXAD==242000 ;3.3-4.9 CHAOSNET ADDRESS (CONI) ];CH10P IFN CH11P,[ $INSRT KSNET ];CH11P SUBTTL CHAOS NET VARIABLES EBLK $CHXRI==001200 ;REAL INDEX PART (LOW TEN BITS) - IS IN LH(IOCHNM) $CHXUN==120600 ;UNIQUIZATION PART (TOP SIX BITS) CHXMUN==1_6-1 ;MAXIMUM VALUE OF UNIQUIZER MXWIND==100 ;MAXIMUM WINDOW SIZE (8K WORDS) .SEE MYCHAD ;SUBNET AND HOST OF MYSELF .SEE DLCP ;1 MEANS USE DL10 TO GET TO CHAOS NET .SEE T11CHP ;1 MEANS USE TEN-11 INTERFACE TO GET TO CHAOS NET .SEE CH10P ;1 MEANS USE CH10 HARDWARE TO GET TO CHAOS NET .SEE CH11P ;1 MEANS USE UNIBUS CHAOSNET HARDWARE ON KS10 ;Internet address of my Chaosnet Interface IMPUS4==<.BYTE 4 ? 0 ? .BYTE 8 ? 128. ? 31. ? .BYTE 16. ? MYCHAD> ;PER-INDEX VARIABLES CHSUSR: REPEAT NINDX,-1 ;-1 INDEX NOT IN USE ;OTHERWISE RH USER $CHSUO==220600 ;3.1-3.6 OUTPUT CHANNEL NUMBER (77=IOPUSHED) $CHSUI==300600 ;3.7-4.3 INPUT CHANNEL NUMBER (77=IOPUSHED) ;4.9 ZERO IF IN USE CHSSTA: REPEAT NINDX,-1 ;RH STATE, LH FLAGS %CF==525252(1) %CFOFF==400000 ;SIGN BIT MEANS TURNED OFF AT PI LEVEL, NO TALKING TO NETWORK %CFSTS==200000 ;SEND STS PACKET AS SOON AS POSSIBLE (1/2 SECOND CLOCK) %CFCLS==100000 ;HALF-CLOSED FLAG %CFSTY==040000 ;DIRECT-CONNECTED TO STTY FLAG $CFTTN==220600 ;TTY NUMBER OF STTY CONNECTED TO %CS==,,-1 .SEE %CSCLS ;FOR SYMBOLS FOR STATES CHSNBF: BLOCK NINDX ;LH LENGTH(CHSPBF), RH LENGTH(CHSIBF) CHSNOS: BLOCK NINDX ;NUMBER OF FREE OUTPUT SLOTS IN THE WINDOW CHSIBF: BLOCK NINDX ;RECEIVE BUFFER POINTERS FIRST,,LAST CHSPBF: BLOCK NINDX ;OUT OF ORDER RECEIVE BUFFER POINTERS FIRST,,LAST CHSOBF: BLOCK NINDX ;TRANSMIT BUFFER POINTERS FIRST,,LAST CHSITM: BLOCK NINDX ;TIME OF LAST INPUT FROM NET CHSWIN: BLOCK NINDX ;WINDOW SIZE RECEIVE,,TRANSMIT CHSPKN: BLOCK NINDX ;LAST PACKET# GIVEN TO USER,,LAST PACKET# SENT BY USER CHSACK: BLOCK NINDX ;LAST PACKET# ACKNOWLEDGED RECEIVE,,TRANSMIT (START OF WINDOW) CHSLCL: REPEAT NINDX,<.BYTE 16. ? MYCHAD ? 100000+.RPCNT> ;BYTE (16) LOCAL HOST, LOCAL INDEX (4) 0 ;NOTE THIS SAVES THE UNIQUIZER BITS FOR THIS INDEX CHSFRN: BLOCK NINDX ;BYTE (16) FOREIGN HOST, FOREIGN INDEX (4) 0 ;THESE FOUR ARE FOR BYTE-STREAM I/O CHSOBP: BLOCK NINDX ;BYTE PNTR TO OUTPUT BUFFER, 0 IF NONE CHSOBC: BLOCK NINDX ;BYTE COUNT, NUMBER OF BYTE SPACES LEFT IN OUTPUT BUFFER CHSIBP: BLOCK NINDX ;BYTE PNTR TO INPUT BUFFER, 0 IF NONE CHSIBC: BLOCK NINDX ;BYTE COUNT, NUMBER OF VALID BYTES REMAINING IN INPUT BUFFER CHAOSW: -1 ? 0 ;SWITCH FOR ALLOCATING INDICES CHALCP: 0 ;LAST INDEX ALLOCATED, USED TO CIRCULARIZE ALLOCATION CHIRFJ: SIXBIT/CHAOS/ ? 0 ;AGENT OF CHAOS .SEE NETUSW ;NON-ZERO ENABLES RFC'S FROM HOSTS OTHER THAN SELF. ;METERS CHNPI: 0 ;NUMBER OF PACKETS INPUT (REALLY TO 10) CHNPO: 0 ;NUMBER OF PACKETS OUTPUT (ALL CAUSES) CHNPF: 0 ;NUMBER OF PACKETS FORWARDED CHNSTS: 0 ;NUMBER OF STS PACKETS OUTPUT CHNSNS: 0 ;NUMBER OF SNS PACKETS OUTPUT CHNRTR: 0 ;NUMBER OF RETRANSMITTED PACKETS OUTPUT CHNPFL: 0 ;NUMBER OF PACKETS DISCARDED (FORWARDING LOOP) CHNPD: 0 ;NUMBER OF PACKETS DISCARDED (DUPLICATES) CHNIPI: 0 ;NUMBER OF INTERNET PACKETS IN FROM CHAOSNET CHNIPO: 0 ;NUMBER OF INTERNET FRAGMENTS OUT TO CHAOSNET ;BUFFER QUEUES. EACH HAS A ONE-WORD HEADER, WHICH IS ZERO ;IF IT IS EMPTY, OR CONTAINS FIRST,,LAST BUFFER ADDRESS. CHQFRE: 0 ;FREE LIST CHQRFC: 0 ;PENDING RFCS CHQLSN: 0 ;PENDING LISTENS CHCLNQ: 0 .SEE CHCLN CHFRBF: 0 ;NUMBER OF FREE BUFFERS CHTTBF: 0 ;TOTAL NUMBER OF BUFFERS IF2 CHMXBF==50.*<1024./<%CPMXW+2>> ;MAX CORE FOR CHAOS NET 50K CHMXTM: 0 ;TIME OF LAST COMPLAINT ABOUT USING TOO MUCH CORE IFN T11CHP,[ ;VARIABLES FOR TEN-11 INTERFACE CONNECTING TO CHAOS NET .SEE T11CHS ;EXEC ADDRESS OF PDP11 COMMUNICATION AREA T11VER=T11CHS ;VERSION NUMBER T11I10=T11CHS+1 ;INIT 10 T11I11=T11CHS+2 ;INIT 11 T11PRM=T11CHS+3 ;.WORD BUFFER SIZE, # BUFFERS ;THEN 4 SPARE DOUBLEWORDS T11IBB: T11CHS+8 ;BEGINNING OF INPUT BUFFERS T11IBE: 0 ;END OF INPUT BUFFERS T11IBP: 0 ;POINTER TO NEXT INPUT BUFFER T11OBB: 0 ;BEGINNING OF OUTPUT BUFFERS T11OBE: 0 ;END OF OUTPUT BUFFERS T11OBP: 0 ;POINTER TO NEXT OUTPUT BUFFER T11BSZ: 0 ;BUFFER SIZE IN PDP10 WORDS T11WIN: 0 ;1 WINNING, -1 HAVE TOLD 11 TO INIT, 0 NOT WINNING T11XMQ: 0 ;QUEUED TRANSMISSION QUEUE T11CKE: 0 ;COUNT OF CHECKSUM ERRORS ;THE FIRST 32-BIT WORD OF A BUFFER IS 0 IF IDLE, OR ;NON-ZERO IF BUFFER IS TO BE SENT TO OTHER MACHINE. ;THE SECOND 32-BIT WORD IS THE CHECKSUM, WHICH IS ;COMPUTED BY ADDING ALL THE 32-BIT WORDS, IGNORING OVERFLOW, ; AND LOGICALLY SHIFTING RIGHT ONE BIT AFTER EACH ADD; BITS SHIFTED ; OUT ON THE RIGHT ARE BROUGHT BACK IN ON THE LEFT. ;IF THE NUMBER OF 16-BIT WORDS IS ODD, THE LEFT-OVER ONE BETTER BE 0. ];T11CHP IFN DLCP,[ ;VARIABLES FOR INTERFACE TO CHAOS NET ON PDP11 ON DL10 ;.SEE INDICATES A VARIABLE SHARED BETWEEN 10 AND 11 ;NOTE THAT THE DL10 HARDWARE LIMITS PACKET LENGTH TO 256 WORDS (1K BYTES) .SEE DLCINI ;WHEN THE 11 SEES THIS NON-ZERO, IT KNOWS ITS HAS ; BEEN RELOADED AND RESETS ITS PACKET POINTER TO 0 ; AND CLEARS DLCINI. DLCSBF: 0 ;CURRENT BUFFER, 10 SEND SIDE (1 OR 0) DLCSA1: 0 ;ADDRESS OF PACKET BEING SENT DLCSA2: 0 ;DITTO, SECOND BUFFER .SEE DLCSP1 ;POINTER USED BY PDP11 TO COPY PACKET (16-BIT BYTES) .SEE DLCSP2 ;DITTO, SECOND BUFFER .SEE DLCSS1 ;STATE FOR BUFFER 1, 0 IDLE, 1 SENT TO 11, 2 11 DONE .SEE DLCSS2 ;STATE FOR BUFFER 2 DLCRA1: 0 ;ADDRESS OF PACKET BUFFER RECEIVING A PACKET DLCRA2: 0 ;DITTO, SECOND BUFFER .SEE DLCRP1 ;POINTER USED BY PDP11 TO COPY PACKET (16-BIT BYTES) .SEE DLCRP2 ;DITTO, SECOND BUFFER .SEE DLCRS1 ;STATE FOR BUFFER 1, 0 IDLE, 1 AWAITING 11, 2 CONTAINS A PACKET .SEE DLCRS2 ;STATE FOR BUFFER 2 DLCXMQ: 0 ;TRANSMIT BUFFER LIST FOR DL10 ;NOTE THAT THIS IS NOT A REGULAR BUFFER LIST SINCE ;IT IS THREADED THROUGH LH INSTEAD OF RH. WE DO MAINTAIN ;POINTERS TO FIRST,,LAST HOWEVER ];DLCP IFN CH10P,[ ;VARIABLES FOR CH10 INTERFACE ONLY CHXCNO: CHXREN+CHXTEN+CHXCHN ;CONO BITS CURRENTLY IN EFFECT ];CH10P IFN CH11P,[ ;VARIABLES FOR CH11 INTERFACE ONLY CHXCSR: %CAREN+%CATEN ;CURRENT BITS WANTED IN CSR ];CH11P IFN CH10P+CH11P,[ ;VARIABLES THAT WOULD OTHERWISE BE IN THE FRONT-END CHXXMQ: 0 ;HEAD,,TAIL OF TRANSMIT QUEUE CHOSTA: 0 ;OUTPUT STATUS: 0 IDLE, ELSE NUMBER OF TRANSMISSIONS NCHRTR==4 ;TRANSMIT UP TO 4 TIMES IN FACE OF COLLISIONS ;ROUTING STUFF NSUBNT==122. ;122 is maximum possible SBNRUT: REPEAT NSUBNT, 1000,,3040 ;COST,,GATEWAY ADDRESS ;EXTRA METERS CHNABT: 0 ;NUMBER OF TRANSMIT ABORTS CHNCRC: 0 ;NUMBER OF CRC ERRORS BEFORE READING PACKET CHNCR2: 0 ;NUMBER OF CRC ERRORS AFTER READING PACKET CHNWLE: 0 ;NUMBER OF WORD LENGTH ERRORS (NOT MULTIPLE OF 16 BITS) CHNPLE: 0 ;NUMBER OF PACKET LENGTH ERRORS (DISAGREES WITH LENGTH IN HEADER) CHNLOS: 0 ;NUMBER OF PACKETS LOST DUE TO RECEIVER BUSY ];CH10P+CH11P IFN CH11P,[ CHNSPZ: 0 ;NUMBER OF TIMERS BIT COUNTER SPAZZED ];CH11P BBLK ;Get definitions of packet format IF1,[ $INSRT CHSDEF PKTBSZ==%CPMXW+2 ;PACKET BUFFER IS 2 HEADER WORDS + MAX SIZE PACKET IFN >-PKTBSZ, .ERR PKTBSZ IS SUPPOSED TO BE A POWER OF 2 $CPKSX==$CHXRI+40000,,2 ;REAL PART OF SOURCE INDEX $CPKDX==$CHXRI+40000,,1 ;REAL PART OF DESTINATION INDEX ];IF1 ;;; Debugging Info ;;; This contains the last N headers received from the network NRECHD==20 EBLK RECHDP: RECHDR ;POINTER TO NEXT RECHDR: BLOCK NRECHD*%CPKDT BBLK SUBTTL CHAOS NET OPEN (.CALL CHAOSO) ;.CALL CHAOSO,RCVCHN,XMTCHN, CHASO: JRST OPNL12 ; Say "mode not avail" CHAOSO: HRRZS A HRRZS B CAIGE A,20 CAIL B,20 JRST OPNL14 ;BAD CHANNEL NUMBER ARGUMENT CAMN A,B JRST OPNL33 ;BOTH CHANNELS SAME IS ILLEGAL PUSH P,A ;SAVE ARGS, CLOSE THE SPECIFIED CHANNELS PUSH P,B PUSH P,C MOVE R,A ADDI R,IOCHNM(U) PUSHJ P,CCLOSE MOVE R,-1(P) ;B ADDI R,IOCHNM(U) PUSHJ P,CCLOSE POP P,C POP P,B POP P,A MOVE U,USER ;TO SAVE ULCERS HRRZM A,UUAC(U) ;REMEMBER INPUT CHNL # FOR ERRS PUSHJ P,SWTL ;LOCK CHAOS INDEX ASSIGNMENT SWITCH CHAOSW MOVE I,CHALCP ;ALLOCATE AN INDEX SOJL I,CHASO2 CHASO1: SKIPL CHSUSR(I) SOJGE I,CHASO1 JUMPGE I,CHASO3 CHASO2: MOVEI I,NINDX ;REACHED BEGINNING, WRAP AROUND TO END CAMN I,CHALCP JRST OPNL6 ;ALL INDICES IN USE MOVEM I,CHALCP SOJA I,CHASO1 CHASO3: MOVEM I,CHALCP ;SAVE SCAN POINTER FOR NEXT TIME PUSHJ P,CHASO4 ;INIT VARIOUS STUFF CAILE C,MXWIND ;SET UP WINDOW SIZE MOVEI C,MXWIND ;DON'T LET USER USE UP TOO MUCH WIRED CORE HRLZM C,CHSWIN(I) HRRZM U,CHSUSR(I) ;VARIABLES INITIALIZED, MAKE INDEX IN USE. DPB A,[$CHSUI,,CHSUSR(I)] DPB B,[$CHSUO,,CHSUSR(I)] HRLZ T,I ;SET UP USER'S IOCHNM WORDS HRRI T,CHAIDN ADDI A,IOCHNM(U) MOVEM T,(A) HRRI T,CHAODN ADDI B,IOCHNM(U) MOVEM T,(B) JRST LSWPJ1 ;SUCCESS RETURN ;INITIALIZE CONNECTION IN I CHASO4: SETZM CHSNBF(I) SETZM CHSNOS(I) SETZM CHSIBF(I) SETZM CHSPBF(I) SETZM CHSOBF(I) SETZM CHSACK(I) SETZM CHSPKN(I) ;START PACKET NUMBERING AT ONE SETZM CHSOBP(I) SETZM CHSOBC(I) SETZM CHSIBP(I) SETZM CHSIBC(I) MOVSI T,%CFOFF .SEE %CSCLS MOVEM T,CHSSTA(I) LDB TT,[$CHXUN+40000,,CHSLCL(I)] CAIE TT,CHXMUN ;INCREMENT THE UNIQUIZER AOSA TT MOVEI TT,1 ;BUT MAKE SURE IT ISN'T ZERO DPB TT,[$CHXUN+40000,,CHSLCL(I)] SETZM CHSFRN(I) POPJ P, SUBTTL CHAOS NET CLOSE, FINISH, WHYINT, NETBLK, CHAOSQ ;CLOSE A CHAOS CHANNEL. CHACLS: HLRZ I,(R) ;GET VARIABLES INDEX MOVSI A,%CFCLS TDNN A,CHSSTA(I) ;ONLY REALLY CLOSE WHEN BOTH CHANNELS CLOSED JRST CHACS7 PUSHJ P,CHACS1 ;FLUSH ALL BUFFERS OF THIS CONNECTION HRRZ T,CHSSTA(I) CAIN T,%CSOPN PUSHJ P,CHABGI ;SEND A CLS IF OPEN AND MEM AVAIL JRST CHACS4 MOVE T,CHSFRN(I) MOVEM T,%CPKS(A) MOVE T,CHSLCL(I) MOVEM T,%CPKD(A) MOVEI B,[ASCIZ/Channel closed/] PUSHJ P,CHIRF2 CHACS4: CONO PI,NETOFF SETZM (R) ;CLOSE THIS CHANNEL SETOM CHSUSR(I) ;RETURN INDEX MOVE W,CHQLSN ;FLUSH ANY PENDING LSN PACKET SETZM CHQLSN CHACS5: MOVEI Q,W ;GET NEXT PACKET OFF OLD LIST PUSHJ P,CHAQGF JUMPE A,NETONJ ;EXHAUSTED LDB B,[$CPKSX(A)] ;GET OWNER CAME B,I JRST [ MOVEI Q,CHQLSN ;NOT THIS INDEX, PUT BACK PUSHJ P,CHAQPL JRST CHACS5 ] PUSHJ P,CHABRT ;FREE JRST CHACS5 CHACS7: IORM A,CHSSTA(I) .SEE %CFCLS HRRZ B,(R) ;GET DIRECTION CAIN B,CHAIDN ;AS A BYTE POINTER TO CHANNEL NUMBER SKIPA B,[$CHSUI,,CHSUSR(I)] MOVE B,[$CHSUO,,CHSUSR(I)] MOVEI T,77 ;CLOSE THAT CHANNEL DPB T,B SETZM (R) POPJ P, ;THIS FLUSHES ALL BUFFERS FOR CONNECTION IN I CHACS1: MOVSI A,%CFOFF ;INHIBIT RETRANSMISSIONS IORB A,CHSSTA(I) LDB E,[$CFTTN,,CHSSTA(I)] EXCH E,I TLNE A,%CFSTY PUSHJ P,NSTYN0 ;DISCONNECT FROM STY JFCL EXCH E,I IFN DLCP,[ MOVEI Q,DLCXMQ ;REMOVE THIS INDEX'S BUFFERS FROM DL10 TRANSMIT LIST PUSHJ P,CFLXMQ ];DLCP IFN T11CHP,[ MOVEI Q,T11XMQ ;REMOVE THIS INDEX'S BUFFERS FROM TEN11 TRANSMIT LIST PUSHJ P,CFLXMQ ];T11CHP IFN CH10P+CH11P,[ MOVEI Q,CHXXMQ ;REMOVE THIS INDEX'S BUFFERS FROM CH10 TRANSMIT LIST PUSHJ P,CFLXMQ ];CH10P+CH11P MOVEI Q,CHSIBF(I) ;RETURN RECEIVE BUFFERS PUSHJ P,CHALFR MOVEI Q,CHSPBF(I) ;RETURN OUT OF ORDER RECEIVE BUFFERS PUSHJ P,CHALFR MOVEI Q,CHSOBF(I) ;RETURN TRANSMIT BUFFERS PUSHJ P,CHALFR IFE FTRCHK,[ SKIPE A,CHSOBP(I) ;RETURN STREAM I/O BUFFERS PUSHJ P,CHBPFR SKIPE A,CHSIBP(I) PUSHJ P,CHBPFR ];FTRCHK IFN FTRCHK,[ SKIPN A,CHSOBP(I) JRST .+3 SETZM CHSOBP(I) PUSHJ P,CHBPFR SKIPN A,CHSIBP(I) JRST .+3 SETZM CHSIBP(I) PUSHJ P,CHBPFR ];FTRCHK POPJ P, ;.CALL FORCE ON A CHAOS OUTPUT CHANNEL. CHAFRC: HLRZ I,(R) SKIPGE CHSSTA(I) .SEE %CFOFF JRST OPNL7 ;DEVICE NOT READY AOS (P) ;WILL TAKE SUCCESS RETURN CHAFC1: SKIPN A,CHSOBP(I) POPJ P, ;NO BUFFERED OUTPUT TO BE FORCED SUBI A,1 ;SIOKT LIKES TO POINT BP AT NEXT BUFFER ANDI A,-PKTBSZ ;GET PACKET POINTER ADDI A,2 MOVSI T,(SETZ) ;DATA OPCODE MOVEM T,(A) .SEE $CPKOP MOVEI T,%CPMXC ;SET BYTE COUNT SUB T,CHSOBC(I) DPB T,[$CPKNB(A)] PUSHJ P,[JUMPN T,CHODT1 ;IF THERE IS ANYTHING IN THE BUFFER, TRANSMIT IT JRST CHABRT ] ;OTHERWISE, JUST THROW IT AWAY SETZM CHSOBP(I) ;NOW THERE IS NO BUFFER SETZM CHSOBC(I) POPJ P, ;.CALL FINISH ON A CHAOS OUTPUT CHANNEL. WAIT FOR ALL BUFFERS ;ON SEND LIST TO GET SENT AND ACKNOWLEDGED. ;HANGS FOREVER IF SOCKET GETS INTO AN IMPROPER STATE, BUT YOU SHOULD GET AN INTERRUPT CHAFIN: HLRZ T,(R) PUSHJ P,[HRRZ A,CHSWIN(T) CAMG A,CHSNOS(T) AOS (P) POPJ P, ] PUSHJ P,UFLS JRST POPJ1 ;.CALL WHYINT ON A CHAOS CHANNEL. ;RESULTS ARE: A/ %WYCHA ; B/ STATE ; C/ LH NUMBER OF INPUT PACKETS AVAILABLE ; RH NUMBER OF OUTPUT SLOTS AVAILABLE ; D/ WINDOW SIZE (RECEIVE,,TRANSMIT) ; E/ INPUT CHNL#,,OUTPUT CHNL# CHAWHY: HLRZ I,(R) MOVEI A,%WYCHA HRRZ B,CHSSTA(I) HRLZ C,CHSNBF(I) ;NUMBER OF PACKETS AVAILABLE SKIPE CHSIBP(I) ADD C,[1,,] ;ADD 1 IF PARTIALLY-READ INPUT BUFFER EXISTS MOVSI D,%CFSTY TDNE D,CHSSTA(I) MOVEI C,0 ;NO INPUT AVAILABLE IF DIRECT-CONNECTED SKIPLE CHSNOS(I) HRR C,CHSNOS(I) MOVE D,CHSWIN(I) LDB E,[$CHSUO,,CHSUSR(I)] CAIN E,77 MOVEI E,-1 LDB T,[$CHSUI,,CHSUSR(I)] CAIN T,77 TLOA E,-1 HRL E,T JRST POPJ1 ;.CALL RFNAME on a CHAOS channel. A contains index. ;Returns results analogous to RFNAME on TCP: and (almost) RFNAME on NET:. ;"FN1" is local index, "FN2" is foreign index, "SNAME" is foreign host ;number in HOSTS3 format. CHARCH: LDB B,[042000,,CHSLCL(A)] LDB C,[042000,,CHSFRN(A)] LDB D,[242000,,CHSFRN(A)] TLO D,(NW%CHS) POPJ P, ;IOPDL ROUTINES. I IS 0 FOR IOPUSH, 1 FOR IOPOP. R POINTS AT IOCHNM WORD. ;C(R) IS SET UP TO THIS DEVICE IN EITHER CASE. CHAIOP: HRRZ T,R ;DISCOVER CHANNEL NUMBER SUBI T,IOCHNM(U) SKIPN I MOVEI T,77 ;IOPUSH, USE 77 HLRZ I,(R) ;GET CHAOS INDEX HRRZ B,(R) ;GET DIRECTION CAIN B,CHAIDN ;AS A BYTE POINTER TO CHANNEL NUMBER SKIPA B,[$CHSUI,,CHSUSR(I)] MOVE B,[$CHSUO,,CHSUSR(I)] DPB T,B ;ADJUST SAVED CHANNEL NUMBER POPJ P, ;.CALL NETBLK ON A CHAOS CHANNEL. ;ARG 1 - CHANNEL (COMES IN IN R) ;ARG 2 - UNDESIRED STATE ;ARG 3 - OPTIONAL TIMEOUT, WRITTEN BACK UNLESS IMMEDIATE ;VAL 1 - NEW STATE ;VAL 2 - TIME LEFT CHANBK: HRRZ T,(R) CAIL T,CHAIDN CAILE T,CHAODN IFN NCPP, JRST ANETBL ;NOT A CHAOS CHANNEL, TRY ARPANET IFE NCPP, JRST OPNL34 HLRZ I,(R) MOVE T,I ;SAVE INDEX IN T FOR FLSINS CAIGE W,3 JRST [ HRLOI D,377777 ;NO TIME GIVEN, USE INFINITY JRST CHANB4 ] TLNE C,1000 ;SKIP IF POINTER RATHER THAN IMMEDIATE JRST [ HRRZ D,C ;GET IMMEDIATE TIME ADD D,TIME JRST CHANB4 ] XCTR XRW,[MOVES D,(C)] ;GET TIME, CHECK WRITEABILITY JUMPGE D,[ MOVNS D ;RELATIVE TIME, MAKE NEGATIVE ABSOLUTE SUB D,TIME JRST .+1 ] UMOVEM D,(C) ;STORE BACK ABSOLUTE TIME MOVNS D ;MAKE POSITIVE CHANB4: MOVEM D,AC0S+D(U) ;SAVE ABSOLUTE TIME TO WAIT UNTIL MOVEM B,AC0S+B(U) ;SAVE UNDESIRED STATE PUSHJ P,CHANB2 ;SKIP IF STATE CHANGE OR TIMEOUT PUSHJ P,UFLS MOVE B,D SUB B,TIME ;HOW MUCH USED? HRRZ A,CHSSTA(I) ;NEW STATE JRST POPJ1 CHANB2: HRRZ A,CHSSTA(T) ;CURRENT STATE CAME A,AC0S+B(U) ;SKIP IF STILL MATCH JRST POPJ1 MOVE A,AC0S+D(U) ;TIMEOUT TIME CAMG A,TIME AOS (P) POPJ P, ;.CALL CHAOSQ ;ARG 1 - ADDRESS OF A %CPMXW-WORD PACKET BUFFER ;FINDS THE FIRST PACKET ON THE PENDING-RFC QUEUE, COPIES IT ;INTO THE USER'S BUFFER, AND RETURNS IT TO THE QUEUE. CHAOSQ: MOVE C,A ;SAVE POINTER TO USER'S BUFFER HRL A,A ;MAKE SURE USER'S BUFFER IS SWAPPED IN XCTR XBRW,[BLT A,%CPMXW-1(C)] ;AND NO MAR BREAK SET MOVEI Q,CHQRFC ;GET FIRST PACKET ON RFC QUEUE PUSHJ P,CHAQGF JUMPE A,OPNL4 ;QUEUE IS EMPTY PUSHJ P,CHAQPL ;PUT BACK AT END OF QUEUE HRL C,A ;COPY PACKET TO USER MOVE T,C XCTR XBW,[BLT T,%CPMXW-1(C)] JRST POPJ1 SUBTTL CHAOS NET IOT ROUTINES ;.CALL PKTIOT. ARG1 CHANNEL, ARG2 ADDRESS OF %CPMXW-WORD BUFFER PKTIOT: HRRZ A,(R) CAIN A,CHAODN JRST CHPKO CAIE A,CHAIDN JRST OPNL34 ;WRONG TYPE DEVICE ;CHAOSNET INPUT PKTIOT ;B POINTS TO %CPMXW-WORD PACKET BUFFER CHPKI: PUSHJ P,CHAIOS ;SET UP I, E HLRZ A,CHSIBF(I) ;GET FIRST RECEIVE BUFFER JUMPE A,[PUSHJ P,CHPKI0 ;LIST EMPTY JRST CHPKI ] HRL B,A ;COPY TO USER BEFORE REMOVING FROM LISTS LDB T,[$CPKNB(A)] ;GET SIZE OF PACKET ADDI T,4*%CPKDT+3 ;HEADER PLUS ROUND-UP TO NEXT WORD BOUNDARY LSH T,-2 ;CONVERT BYTES TO WORDS ADDI T,-1(B) ;ADDRESS OF LAST DESTINATION WORD XCTR XBW,[BLT B,(T)] LDB TT,[$CPKOP(A)] ;GET OPCODE CAIGE TT,%CODAT ;ACKNOWLEDGE IF DATA CAIN TT,%COEOF ;OR EOF MARK PUSHJ P,CHPKIA SOS CHSNBF(I) ;NOW REMOVE BUFFER FROM RECEIVE LIST MOVEI Q,CHSIBF(I) PUSHJ P,CHAQGF PUSHJ P,CHABRT ;AND RETURN TO FREE JRST POPJ1 ;SUCCESS ;INPUT WITH INPUT BUFFER EMPTY. MUSTN'T BASH B,C,E. CHPKI0: SKIPGE CHSSTA(I) .SEE %CFOFF JRST [ HRRZ T,CHSSTA(I) CAIE T,%CSFRN ;CHAOSNET OR FOREIGN PROTOCOL? JRST IOCR10 ;IOT WITH CHANNEL IN IMPROPER STATE JRST .+1 ] ;WAIT BUT DON'T TRY TO TOUCH WINDOW SIZE ;HERE CONSIDER INCREASING WINDOW SIZE SKIPN CHSIBF(I) ;AWAIT INPUT PUSHJ P,UFLS POPJ P, ;RETRY ;ACKNOWLEDGE DATA PACKET IN A. ITS OPCODE IN TT. CHPKIA: LDB T,[$CPKPN(A)] ;GET PACKET # HRLM T,CHSPKN(I) ;IT NOW NEEDS TO BE ACKNOWLEDGED CAIN TT,%COEOF ;ALWAYS ACKNOWLEDGE EOF RIGHT AWAY JRST CHASTO HLRZ TT,CHSACK(I) ;GET LAST ONE REALLY ACKNOWLEDGED SUB T,TT ;GET NUMBER OF PACKETS AWAITING ACK SKIPGE T ADDI T,200000 IMULI T,3 ;MORE THAN ONE THIRD THE WINDOW SIZE? IFN FTRCHK,[ MOVE TT,-1(A) CAMN TT,[ASCII/LUNCH/] BUG PAUSE,[CHAOS BUFFER ADDRESS TRASHED],OCT,A ];FTRCHK HLRZ TT,CHSWIN(I) CAML T,TT PUSHJ P,CHASTO ;YES, SEND ACK (CAN'T PCLSR) POPJ P, ;SET UP FOR CHAOS IOT CHAIOS: HLRZ I,(R) ;GET INDEX MOVE E,CHSSTA(I) TLNE E,%CFSTY+%CFCLS JRST IOCR10 ;CAN'T DO I/O WHILE DIRECT-CONNECTED OR HALF-CLOSED HRRZS E ;RETURN STATE IN E POPJ P, ;UNIT-MODE INPUT. ;1.4 IN CTLBTS IS DON'T-HANG MODE SKIPA T,[SIOKT] CHAUI: MOVEI T,CHRKT PUSHJ P,CHAIOS ;SET UP I, E MOVE E,[440800,,4] JSP B,(T) CHSIBP(I) CHSIBC(I) CHAIBG CHAIBD 0 TRNA ;CHAOS INPUT BUFFER DISCARD CHAIBD: SKIPN A,CHSIBP(I) POPJ P, SETZM CHSIBP(I) SETZM CHSIBC(I) JRST CHBPFR ;CHAOS INPUT BUFFER GET CHAIBG: HLRZ A,CHSIBF(I) ;GET FIRST RECEIVE BUFFER JUMPE A,CHAIB2 ;NONE LDB TT,[$CPKOP(A)] ;IS IT NORMAL DATA? CAIE TT,%CODAT JRST CHAIB1 ;NO PUSHJ P,CHAIB3 ;YES, ACKNOWLEDGE AND REMOVE FROM LIST LDB J,[$CPKNB(A)] ;SET UP FOR BYTE STREAM INPUT MOVEI TT,%CPKDT(A) JRST SIOBG1 CHAIB3: PUSH P,B PUSH P,C PUSH P,E PUSHJ P,CHPKIA ;SEND ACKNOWLEDGEMENT POP P,E POP P,C POP P,B SOS CHSNBF(I) ;REMOVE BUFFER FROM RECEIVE LIST MOVEI Q,CHSIBF(I) JRST CHAQGF CHAIB1: CAIE TT,%COEOF JRST CHAIB2 PUSHJ P,CHAIB3 ;EOF PACKET, ACKNOWLEDGE IT PUSHJ P,CHABRT ;RETURN IT TO FREE JRST POPJ2 ;AND SIGNAL EOF CHAIB2: MOVE TT,CTLBTS(U) ;CHECK DON'T-HANG MODE TRNE TT,10 JRST POPJ2 ;YES, EOF JUMPN A,IOCR10 ;NO, ABNORMAL PACKET, BARF PUSHJ P,CHPKI0 ;AWAIT INPUT JRST CHAIBG ;RETRY ;UNIT-MODE OUTPUT. ;1.4 IN CTLBTS IS DON'T-HANG MODE SKIPA T,[SIOKT] CHAUO: MOVEI T,CHRKT PUSHJ P,CHAIOS ;SET UP I, E CAIE E,%CSOPN JRST IOCR10 ;NOT OPEN, ERROR MOVE E,[440800,,4] JSP B,(T) SETZ CHSOBP(I) CHSOBC(I) CHAOBG CHAOBW 0 TRNA ;GET NEW OUTPUT BUFFER CHAOBG: SKIPG CHSNOS(I) ;WINDOW FULL PUSHJ P,[ MOVE TT,CTLBTS(U) TRNN TT,10 JRST UFLS SUB P,[1,,1] JRST POPJ2 ] ;DON'T HANG MODE, RETURN "EOF" PUSH P,B PUSHJ P,CHABGT ;SET UP AN OUTPUT BUFFER POP P,B MOVEI TT,%CPKDT(A) MOVEI J,%CPMXC JRST SIOBG1 ;WRITE OUTPUT BUFFER CHAOBW: PUSH P,B PUSH P,C PUSH P,E PUSHJ P,CHAFC1 POP P,E JRST POPCBJ ;CHAOSNET OUTPUT PKTIOT. ;B POINTS TO %CPMXW-WORD PACKET BUFFER CHPKO: PUSHJ P,CHAIOS ;SET UP I, E UMOVE H,(B) ;GET HEADER WORD OF USER'S PACKET BUFFER LDB D,[$CPKNB H] ;GET BYTE COUNT CAIG D,%CPMXC TLNE H,(.BM $CPKMV) ;WE DON'T SUPPORT MUPPETS ANY MORE JRST IOCER3 ;BYTE LENGTH OUT OF BOUNDS ADDI D,4*%CPKDT+3 ;CONVERT BYTES TO WORDS, INCLUDING HEADER WDS LSH D,-2 MOVSI J,1(B) ;SAVE ADDRESS+1 OF USER'S PACKET PUSHJ P,CHABGT ;GET A BUFFER PUSHJ P,LOSSET ;RETURN IT IF PCLSR CHPKO2 MOVEM H,(A) ;STORE PACKET HEADER, NOT STORED WITH BLT HRRI J,1(A) ; BECAUSE MIGHT HAVE CHANGED AFTER ERROR CHECK ADDI D,-1(A) XCTR XBR,[BLT J,(D)] ;COPY USER'S PACKET INTO SYSTEM AOS (P) ;GOING TO SUCCEED SKIPGE (A) ;SKIP IF CONTROL PACKET JRST CHODAT ;DATA LDB D,[$CPKOP(A)] ;GET OPCODE CAIGE D,%COMAX ;DISPATCH ON IT JRST @.+1(D) OFFSET -. JRST IOCER3 ;OPCODE OUT OF BOUNDS %CORFC::JRST CHORFC %COOPN::JRST CHOOPN %COCLS::JRST CHOCLS %COFWD::JRST CHOFWD %COANS::JRST CHOFWD %COSNS::JRST IOCER3 %COSTS::JRST IOCER3 %CORUT::JRST IOCER3 %COLOS::JRST IOCER3 %COLSN::JRST CHOLSN %COMNT::JRST IOCER3 %COEOF::JRST CHOEOF %COUNC::JRST CHOUNC %COBRD::JRST IOCER9 ;UNTIL I IMPLEMENT IT %COMAX::OFFSET 0 ;LOSSET ROUTINE TO RETURN BUFFER A POINTS TO. CHPKO2: MOVE A,AC0S+A(U) PUSH P,Q ;MAY CLOBBER ONLY A AND T PUSHJ P,CHABRT JRST POPQJ ;SENDING %COEOF (END-FILE MARK) CHOEOF: CAIE E,%CSOPN ;CONNECTION MUST BE OPEN JRST IOCR10 SKIPG CHSNOS(I) PUSHJ P,UFLS ;WINDOW FULL, WAIT JRST CHOOP1 ;SEND RETRANSMITTABLE CONTROL PACKET ;SENDING REQUEST FOR CONNECTION CHORFC: PUSHJ P,CHORF1 ;RE-INITIALIZE CONNECTION MOVSI B,777774 ;SAVE DESTINATION HOST, CLEAR OTHER BITS ANDB B,%CPKD(A) MOVEM B,CHSFRN(I) MOVEI E,%CSRFS ;PUT INTO RFC-SENT STATE JRST CHOOP1 ;GO SEND ;RE-INITIALIZE CONNECTION WHEN USER OUTPUTS RFC OR LSN ;FLUSHES ANY OLD PACKET BUFFERS, CHANGES UNIQUIZER IN INDEX# CHORF1: JUMPN E,IOCR10 .SEE %CSCLS ;CONNECTION MUST BE CLOSED PUSH P,A PUSH P,B PUSHJ P,CHACS1 ;FLUSH BUFFERS FROM CONNECTION PUSHJ P,CHASO4 ;REINITIALIZE VARIABLES JRST POPBAJ ;"SENDING" LISTEN CHOLSN: PUSHJ P,CHORF1 PUSHJ P,LSWDEL ;GOING TO USE PACKET MOVEI E,%CSLSN ;PUT INTO LISTENING STATE HRRM E,CHSSTA(I) MOVEI Q,CHQRFC ;NOW SEARCH PENDING-RFC QUEUE CONO PI,NETOFF PUSHJ P,CHAQSR JRST [ CONO PI,NETON ;NO MATCH, PUT ONTO LISTENING QUEUE MOVEI Q,CHQLSN MOVE T,CHSLCL(I) MOVEM T,%CPKS(A) JRST CHAQPL ] PUSHJ P,CHIRF0 ;MATCH, JOIN INTERRUPT LEVEL CODE JRST NETONJ ;SENDING OPEN CHOOPN: CAIE E,%CSRFC ;CONNECTION MUST BE RFC-RECEIVED JRST IOCR10 MOVEI TT,4 ;SET BYTE COUNT TO 4 DPB TT,[$CPKNB(A)] PUSHJ P,DPBRCP ;INCLUDE RECEIPT HLRZ B,CHSWIN(I) ;INCLUDE WINDOW SIZE DPB B,[042000,,%CPKDT(A)] MOVEI E,%CSOPN ;MAKE IT OPEN ;HERE TO SEND A RETRANSMITTABLE CONTROL PACKET (RFC OR OPN), NEW STATE IN E ;THIS PACKET WILL GET TAKEN OFF THE CHSOBF LIST BY RECEIPT IN THE NORMAL WAY ;THIS CODE COPIED FROM CHODAT WITH SOME MODIFICATIONS CHOOP1: MOVE T,TIME ;UPDATE CHSITM SO WON'T THINK HOST IS DOWN MOVEM T,CHSITM(I) MOVEM E,CHSSTA(I) ;AND CLEAR %CFOFF (NO OTHER LH FLAGS CAN BE ON) PUSHJ P,LSWDEL ;BUFFER WILL BE USED HRRZ B,CHSPKN(I) ;ASSIGN PACKET NUMBER CAIL B,177777 TDZA B,B ADDI B,1 HRRM B,CHSPKN(I) DPB B,[$CPKPN(A)] HLRZ B,CHSPKN(I) ;GET PACKET NUMBER TO ACKNOWLEDGE HRLM B,CHSACK(I) ;REMEMBER IT HAS BEEN DPB B,[$CPKAN(A)] ;PIGGY-BACK THIS ACKNOWLEDGE MOVE B,[<.BM $CPKOP>+<.BM $CPKNB>] ANDM B,(A) ;CLEAR FORWARDING COUNT AND UNUSED FIELD MOVE B,CHSLCL(I) ;SET UP SOURCE MOVEM B,%CPKS(A) MOVE D,CHSFRN(I) ;SET UP DESTINATION MOVEM D,%CPKD(A) SETOM -2(A) ;NOTE NOT ON TRANSMIT LIST YET CONI PI,E ;SUPER KLUDGERY REQUIRED HERE! FOREIGN HOST MIGHT RECEIPT CONO PI,NETOFF ;THIS PACKET JUST AS WE START TO TRANSMIT IT. THIS IS A ;VIOLATION OF PROTOCOL, BUT SHOULDN'T CRASH I.T.S. BECAUSE THE ;PACKET ABOUT TO BE GIVEN TO CHAXMT HAS BEEN FREED ALREADY. MOVEI Q,CHSOBF(I) ;PUT ON END OF SEND LIST PUSHJ P,CHAQPL JRST CHAXM0 ;GO TRANSMIT ;SENDING CLOSE CHOCLS: CAIE E,%CSOPN ;CONNECTION MUST BE OPEN ;SEND FWD OR ANS CHOFWD: CAIN E,%CSRFC ; OR RFC-RECEIVED TLOA E,%CFOFF ;PUT IT INTO THE CLOSED STATE JRST IOCR10 HLLZM E,CHSSTA(I) .SEE %CSCLS PUSHJ P,LSWDEL ;BUFFER WILL BE USED JRST CHODT2 ;GO TRANSMIT ;Here for transmitting an UNC packet. It could be part of a connection ;or it could be foreign-protocol mode. In any case transmit it without ;munging the header very much. CHOUNC: CAIN E,%CSFRN JRST CHOUN1 ;Okay to transmit UNC now CAIN E,%CSOPN JRST CHOUN2 JUMPN E,IOCR10 .SEE %CSCLS ;Bad state SKIPE CHSPBF(I) ;I guess out of order packets would JRST IOCR10 ; cause some confusion in the NCP. MOVE E,[%CFOFF,,%CSFRN] ;Put into foreign-protocol state MOVEM E,CHSSTA(I) MOVE D,%CPKD(A) ;Save destination MOVEM D,CHSFRN(I) CHOUN2: MOVE D,CHSFRN(I) ;Set up destination MOVEM D,%CPKD(A) CHOUN1: MOVE B,CHSLCL(I) ;Set up source MOVEM B,%CPKS(A) PUSHJ P,LSWDEL SETOM -2(A) JRST CHAXMT OVHMTR CHX ;SENDING REGULAR PACKET CHODAT: CAIE E,%CSOPN ;CONNECTION MUST BE OPEN JRST IOCR10 SKIPG CHSNOS(I) PUSHJ P,UFLS ;WINDOW FULL, WAIT PUSHJ P,LSWDEL ;BUFFER WILL BE USED CHODT1: HRRZ B,CHSPKN(I) ;ASSIGN PACKET NUMBER CAIL B,177777 TDZA B,B ADDI B,1 HRRM B,CHSPKN(I) DPB B,[$CPKPN(A)] CHODT2: HLRZ B,CHSPKN(I) ;GET PACKET NUMBER TO ACKNOWLEDGE HRLM B,CHSACK(I) ;REMEMBER IT HAS BEEN DPB B,[$CPKAN(A)] ;PIGGY-BACK THIS ACKNOWLEDGE MOVE B,[<.BM $CPKOP>+<.BM $CPKNB>] ANDM B,(A) ;CLEAR FORWARDING COUNT AND UNUSED FIELD MOVE B,CHSLCL(I) ;SET UP SOURCE MOVEM B,%CPKS(A) MOVE D,CHSFRN(I) ;SET UP DESTINATION MOVEM D,%CPKD(A) SETOM -2(A) ;NOTE NOT ON TRANSMIT LIST YET SKIPL (A) ;SKIP IF DATA PACKET JRST CHAXMT CONI PI,E ;SUPER KLUDGERY REQUIRED HERE! FOREIGN HOST MIGHT RECEIPT CONO PI,NETOFF ;THIS PACKET JUST AS WE START TO TRANSMIT IT. THIS IS A ;VIOLATION OF PROTOCOL, BUT SHOULDN'T CRASH I.T.S. BECAUSE THE ;PACKET ABOUT TO BE GIVEN TO CHAXMT HAS BEEN FREED ALREADY. MOVEI Q,CHSOBF(I) ;PUT ON END OF SEND LIST PUSHJ P,CHAQPL SOSA CHSNOS(I) ;USE UP WINDOW, SKIP ;SKIPS THROUGH INTO CHAXMT ;SKIPS IN SUBTTL CHAOS NET PACKET TRANSMIT ROUTINE ;CALL WITH PACKET IN A, SMASHES B, C, D, E, T, TT, Q, J ;USES E TO SAVE THE PI STATUS, NOTHING BETTER CLOBBER THIS, OR, BOY, WILL IT EVER LOSE! ;YOU BETTER SETOM -2(A) BEFORE CALLING THIS, AND IF YOU'RE ;PUTTING IT ON A SEND LIST, DO THAT FIRST ALSO. ;THIS CODE ASSUMES THERE IS ONLY ONE INTERFACE, AND IT IS ON A ;PDP11 WHICH WILL TAKE CARE OF THE ROUTING. ;;THIS ROUTINE IS SKIPPED INTO FROM THE PREVIOUS PAGE! CHAXMT: CONI PI,E ;SAVE PI STATUS BEFORE TURNING NETOFF; CALLED FROM MANY LEVELS CHAXM0: ANDI E,177 AOS CHNPO MOVE T,TIME MOVEM T,-1(A) ;SET TIME OF LAST TRANSMISSION CONO PI,NETOFF ;ONE PROCESS AT A TIME, TO PROTECT INTERFACE VARIABLES IFN FTRCHK,[ HLRZ J,-2(A) ;I TOLD YOU TO SETOM -2(A) CAIE J,-1 BUG PAUSE,[CHAOS BUFFER THREAD TRASHED],OCT,A,OCT,-2(A) ];FTRCHK IFN DLCP,[ ;FOR NOW, JUST ALWAYS SHIP IT OUT THE DL10 IFN FTRCHK,[ HLRZ J,DLCXMQ ;MAKE SURE NOT PUTTING ON LIST TWICE JUMPE J,.+7 CAMN J,A BUG PAUSE,[CHAOS BUFFER ALREADY ON DLCXMQ],OCT,A HLRZ J,-2(J) CAIN J,-1 BUG PAUSE,[DLCXMQ THREAD TRASHED] JUMPN J,.-5 MOVEI J,1 ;MAKE SURE NOT ACTIVE TO 11 HRRZ T,DLCSA1(J) CAMN T,A BUG PAUSE,[CHAOS BUFFER ALREADY ACTIVE TO 11],OCT,A SOJGE J,.-3 ];FTRCHK HRRZS -2(A) ;PUT END-LIST INDICATOR IN LH (FLAGS TRANSMIT ACTIVE) MOVE J,DLCSBF ;SEE IF SEND BUFFER IS FREE SKIPE DLCSS1(J) JRST CHXMD1 PUSHJ P,DLCXMT ;YES, SEND THE PACKET NOW JRST CHXMD2 CHXMD1: HRRZ B,DLCXMQ ;NO BUFFERS FREE RIGHT NOW, QUEUE JUMPE B,[ HRLZM A,DLCXMQ ? JRST .+2 ] HRLM A,-2(B) HRRM A,DLCXMQ CHXMD2: CONO PI,PICON(E) ;RESTORE PI POPJ P, ];DLCP IFN T11CHP,[ ;FOR NOW, JUST ALWAYS SHIP IT OUT THE TEN11 PUSHJ P,T11CHK ;SEE IF TEN-11 IS READY JRST CHXME3 ;NO SKIPE @T11OBP ;SEE IF HAVE AVAILABLE OUTPUT BUFFER JRST CHXME1 ;NO PUSHJ P,T11XMT ;SEND THE PACKET NOW JRST CHXME2 CHXME3: HRROS T,-2(A) ;TEN11 DOWN, DISCARD PACKET AOJN T,CHXME2 PUSHJ P,CHABRT JRST CHXME2 CHXME1: HRRZ B,T11XMQ ;NO BUFFERS FREE RIGHT NOW, QUEUE JUMPE B,[ HRLZM A,T11XMQ ? JRST .+2 ] HRLM A,-2(B) HRRM A,T11XMQ HRRZS -2(A) ;PUT END-LIST INDICATOR IN LH CHXME2: CONO PI,PICON(E) ;RESTORE PI POPJ P, ];T11CHP IFN CH10P,[ ;FOR NOW, JUST ALWAYS SHIP IT OUT THE CH10 HRRZ B,CHXXMQ ;ADD TO END OF TRANSMIT QUEUE JUMPE B,[ HRLZM A,CHXXMQ ? JRST .+2 ] HRLM A,-2(B) HRRM A,CHXXMQ HRRZS -2(A) ;PUT END-LIST INDICATOR IN LH MOVEI B,CHXTEN ;ENABLE TRANSMIT-DONE INTERRUPT IORM B,CHXCNO CONO CHX,@CHXCNO CONO PI,PICON(E) ;RESTORE PI POPJ P, ];CH10P IFN CH11P,[ ;FOR NOW, JUST ALWAYS SHIP IT OUT THE CH11 HRRZ B,CHXXMQ ;ADD TO END OF TRANSMIT QUEUE JUMPE B,[ HRLZM A,CHXXMQ ? JRST .+2 ] HRLM A,-2(B) HRRM A,CHXXMQ HRRZS -2(A) ;PUT END-LIST INDICATOR IN LH MOVEI B,%CATEN ;ENABLE TRANSMIT-DONE INTERRUPT IORB B,CHXCSR IOWRI B,CAICSR CONO PI,PICON(E) ;RESTORE PI POPJ P, ];CH11P SUBTTL CHAOS NET DIRECT CONNECT TO STY OVHMTR CHS ;CALLED AT CLOCK LEVEL FROM STYNTC WHEN A CHAOS STY IS ENCOUNTERED ;TTY NUMBER IN I & R STYCHA: MOVE I,STYNTI-NFSTTY(R) ;GET CHAOS INDEX MOVE TT,CHSSTA(I) TLNN TT,%CFSTY JRST 4,. ;CHAOS CONNECTION CLAIMS NOT BE CONNECTED? JUMPL TT,STYCH9 .SEE %CFOFF ;OK TO USE? IF NOT, DISCONNECT SKIPGE TTYOAC(R) ;ANY OUTPUT? JRST STYCH1 ;NO, CHECK FOR INPUT SKIPN D,CHSOBP(I) ;IF BUFFER ALLOCATED, USE IT JRST [ SKIPG CHSNOS(I) ;OTHERWISE ALLOCATE ONE JRST STYCH1 ;WINDOW FULL, WAIT UNTIL REACTIVATED PUSHJ P,CHABGI JRST STYCH3 ;NO CORE, WAIT ONE CLOCK TICK MOVEI D,%CPKDT(A) HRLI D,440800 MOVEM D,CHSOBP(I) MOVEI E,%CPMXC MOVEM E,CHSOBC(I) JRST .+3 ] SKIPG E,CHSOBC(I) JRST STYCH4 ;BUFFER FULL, FORCE IT EXCH R,I ;I GETS TTY, R GETS CHAOS CONO PI,TTYOFF MOVEM D,DBBBP ;SET UP BUFFER FOR TTY OUTPUT INTERRUPT LEVEL MOVEM E,DBBCC MOVEM E,DBBCC1 PUSH P,R SETOM TYPNTF PUSHJ P,TYP ;GENERATE OUTPUT SETZM TYPNTF POP P,R EXCH R,I ;I GETS CHAOS, R GETS TTY MOVE D,DBBBP ;ADVANCE POINTERS MOVEM D,CHSOBP(I) MOVE E,DBBCC SUB E,DBBCC1 ;MINUS # CHARS OUTPUT GENERATED CONO PI,TTYON ADDM E,CHSOBC(I) STYCH4: PUSHJ P,CHAFC1 ;FORCE THE BUFFER JRST STYCHA ;CHECK FOR MORE OUTPUT STYCH3: PUSHJ P,CHINTI ;REACTIVATE SO WILL COME BACK ON NEXT CLOCK TICK STYCH1: SOSGE CHSIBC(I) ;GET INPUT, IF ANY JRST [ PUSHJ P,CHAIBD ;DISCARD EXHAUSTED INPUT BUFFER, IF ANY HLRZ A,CHSIBF(I) JUMPE A,STYNT8 ;NONE, RETURN TO STYNTC LDB TT,[$CPKOP(A)] CAIE TT,%CODAT JRST STYCH9 ;RANDOM PACKET, DISCONNECT PUSHJ P,CHPKIA ;ACKNOWLEDGE GOBBLING OF THIS PACKET SOS CHSNBF(I) ;REMOVE BUFFER FROM RECEIVE LIST MOVEI Q,CHSIBF(I) PUSHJ P,CHAQGF LDB E,[$CPKNB(A)] ;SET UP FOR BYTE STREAM INPUT MOVEM E,CHSIBC(I) MOVEI D,%CPKDT(A) HRLI D,440800 MOVEM D,CHSIBP(I) JRST STYCH1 ] ILDB A,CHSIBP(I) ;GET CHARACTER OF INPUT TRNE A,200 JRST [ AOS CHSIBC(I) ;WOOPS, SPECIAL CHARACTER, NEEDS USER ATTENTION MOVSI A,8_14 ;SO PUT IT BACK AND DISCONNECT ADDM A,CHSIBP(I) JRST STYCH9 ] EXCH R,I ;I GETS TTY, R GETS CHAOS PUSH P,R PUSH P,I CONO PI,TTYOFF PUSHJ P,NTYI5 ;GIVE CHARACTER TO TTY INPUT INTERRUPT LEVEL CONO PI,TTYON POP P,R POP P,I ;I GETS CHAOS, R GETS TTY ((POP IN REVERSE ORDER)) JRST STYCH1 ;TRY FOR MORE INPUT STYCH9: PUSH P,I MOVE I,R ;I GETS TTY PUSHJ P,NSTYN0 ;DISCONNECT THE STY JRST 4,. POP P,I ;I GETS CHAOS PUSHJ P,CHINTI ;WAKE UP THE TELNET SERVER JRST STYNT8 ;GO HANDLE OTHER STYS SUBTTL CHAOS NET CLOCK LEVEL STUFF OVHMTR CHC ;HERE FROM 1/2 SECOND CLOCK. DO RETRANSMISSIONS AND DELAYED STS'S CHACLK: IFN DLCP,[ CONO PI,NETOFF PUSHJ P,DLCIBG ;GET MEMORY FOR INPUT BUFFERS IF NEEDED CONO PI,NETON ];DLCP MOVEI I,NINDX-1 ;SCAN ALL INDICES CHACL0: SKIPL CHSUSR(I) ;SKIP THIS ONE IF NOT IN USE SKIPGE CHSSTA(I) .SEE %CFOFF ;OR INHIBITED FROM PI LEVEL SOJGE I,CHACL0 JUMPL I,CPOPJ ;JUMP IF ALL INDICES DONE PUSHJ P,CHARTR ;RETRANSMIT IF NEEDED MOVSI B,%CFSTS TDNE B,CHSSTA(I) ;SEND STS IF NEEDED PUSHJ P,CHASTO SOJGE I,CHACL0 POPJ P, ;HERE EVERY 5 SECONDS, TO DO PROBES CHA5CL: MOVEI I,NINDX-1 ;SCAN ALL INDICES CHA5C0: SKIPL CHSUSR(I) ;SKIP IF THIS ONE NOT IN USE SKIPGE CHSSTA(I) .SEE %CFOFF ;OR INHIBITED FROM PI LEVEL CHA5C1: SOJGE I,CHA5C0 JUMPL I,CHA5C4 ;JUMP IF ALL INDICES DONE MOVE T,TIME SUB T,CHSITM(I) ;TIME SINCE LAST COMMUNICATION FROM OTHER END CAILE T,90.*30. JRST [ MOVEI W,%CSINC ;TOO LONG, CONNECTION BROKEN PUSHJ P,CHINT JRST CHA5C1 ] HRRZ B,CHSSTA(I) ;ONLY PROBE IF OPEN (COULD BE RFC-SENT) CAIE B,%CSOPN JRST CHA5C1 HRRZ B,CHSWIN(I) ;SEE IF NO TRANSMIT WINDOW (LOST STS DURING OPEN) JUMPE B,CHA5C2 HRRZ B,CHSACK(I) ;SEE IF AWAITING ACK (WINDOW NOT EMPTY) HRRZ C,CHSPKN(I) CAMN B,C CAIL T,60.*30. CHA5C2: PUSHJ P,CHABGI ;AWAITING ACK OR IDLE FOR 1 MINUTE, PROBE JRST CHA5C1 ;NO PROBE, OR NO BUFFER AVAILABLE MOVSI T,(.DPB %COSNS,($CPKOP),0) ;SENSE PACKET, BYTE-COUNT=0 MOVEM T,(A) AOS CHNSNS PUSHJ P,CHODT2 JRST CHA5C1 CHA5C4: MOVEI B,[ASCIZ/Timeout/] MOVEI Q,CHQRFC ;TIME-OUT FIRST RFC ON LIST PUSHJ P,CHAQGF JUMPE A,CHA5C5 MOVE T,-1(A) ADDI T,60.*30. ;TIME-OUT IS ONE MINUTE PUSHJ P,[ CAMG T,TIME JRST CHIRF2 JRST CHAQPF ] CHA5C5: IFN CH10P,[ MOVEI T,CHXREN+CHXTEN ;WAKE UP IN CASE OF TIMING ERROR IORM T,CHXCNO ;IN DEALING WITH CHXCNO CONO CHX,@CHXCNO MOVSI T,-NSUBNT ;DECAY ROUTING COSTS CONO PI,NETOFF ;PREVENT RUT PACKET FROM COMING IN CHA5C6: HLRZ TT,SBNRUT(T) ADDI TT,1 CAIG TT,1000 HRLM TT,SBNRUT(T) AOBJN T,CHA5C6 CONO PI,NETON ];CH10P IFN CH11P,[ MOVEI T,%CAREN+%CATEN ;WAKE UP IN CASE OF TIMING ERROR IORB T,CHXCSR ;IN DEALING WITH CHXCSR IOWRI T,CAICSR MOVSI T,-NSUBNT ;DECAY ROUTING COSTS CONO PI,NETOFF ;PREVENT RUT PACKET FROM COMING IN CHA5C6: HLRZ TT,SBNRUT(T) ADDI TT,1 CAIG TT,1000 HRLM TT,SBNRUT(T) AOBJN T,CHA5C6 CONO PI,NETON ];CH11P MOVEI T,5*60. MOVEI C,CHA5CK JRST CLQREE OVHMTR CHR ;RETRANSMIT FOR INDEX IN I CHARTR: CONI PI,W ;SAVE PI CHANNELS ACTIVE ANDI W,177 ;CHAXMT BETTER NOT CLOBBER W! CONO PI,NETOFF ;PI BETTER BE OFF THROUGHOUT THIS ZONE ; SO WE DON'T GET INTO CHIACK HLRZ A,CHSOBF(I) ;SCAN DOWN OUTPUT BUFFER LIST JUMPE A,CHART2 ;EMPTY CHART1: MOVE T,-1(A) ;DON'T RETRANSMIT IF DONE TOO RECENTLY HLRZ TT,-2(A) ;OR IF ALREADY ON ITS WAY OUT (DON'T LINK TWICE ON XMIT LIST) CAME T,TIME CAIE TT,-1 JRST CHART2 ;ANYTHING AFTER THIS IS LIKELY TO LOSE ALSO AOS CHNRTR PUSHJ P,CHAXMT ;RETRANSMIT THIS ; HRRZ A,-2(A) ;THREAD TO NEXT ; JUMPN A,CHART1 CHART2: CONO PI,PICON(W) POPJ P, ;THIS ROUTINE SENDS A STS PACKET, OR TRIES TO. FAILURE => SLOW CLOCK WILL TRY AGAIN. ;CANNOT PCLSR NOR WAIT, CALLABLE FROM INTERRUPT LEVEL. ;INDEX IN I, CLOBBERS A,B,C,D,E,T,TT,Q,J CHASTO: MOVSI D,%CFSTS IORM D,CHSSTA(I) PUSHJ P,CHABGI ;GET A BUFFER, WITHOUT WAITING POPJ P, ;CAN'T GET ONE, WILL RETRY AT CLOCK LEVEL ANDCAM D,CHSSTA(I) ;OK, A STS WILL BE SENT, CLEAR NEED-STS FLAG MOVE T,[.DPB %COSTS,($CPKOP),<.DPB 4,($CPKNB),0>] MOVEM T,(A) ;SEND A STS WITH 4 DATA BYTES PUSHJ P,DPBRCP ;FIRST PAIR IS RECEIPT HLRZ B,CHSWIN(I) ;SECOND PAIR IS WINDOW SIZE DPB B,[042000,,%CPKDT(A)] AOS CHNSTS JRST CHODT2 ;FIRE IT OFF DPBRCP: HLRZ B,CHSPKN(I) SKIPE T,CHSIBF(I) LDB B,[$CPKPN(T)] DPB B,[242000,,%CPKDT(A)] POPJ P, SUBTTL CHAOS NET INTERRUPT-LEVEL INPUT PROCESSING OVHMTR CHI ;PROCESS A PACKET RECEIVED AT INTERRUPT LEVEL. BY THE TIME WE GET HERE ; A BUFFER HAS BEEN ALLOCATED AND FILLED WITH THE DATA FROM THE DEVICE. ; ITS ADDRESS IS IN A. RETURN VIA POPJ P, WITH ALL REGISTERS CLOBBERED. CHAPII: MOVE B,RECHDP ;SAVE HEADER FOR DEBUGGING IN RING BUFFER MOVEI D,%CPKDT(B) HRL B,A BLT B,-1(D) CAIN D,RECHDR+ MOVEI D,RECHDR MOVEM D,RECHDP ;END OF DEBUGGING CODE LDB D,[$CPKMV(A)] ;MUPPET? JUMPN D,CHABRT ;FLUSH, NOT SUPPORTED LDB D,[$CPKOP(A)] ;GET OPCODE LDB B,[$CPKDA(A)] ;CHECK DESTINATION CAIE B,MYCHAD ;IF FOR ME, SKIPN B ;OR FOR ME BY VIRTUE OF BROADCAST AOSA CHNPI ;ACCEPT IT JRST CHAPFW ;NOT ME, FORWARD LDB C,[$CPKNB(A)] ;PASS LENGTH IN C TO OP ROUTINES MOVEI B,[ASCIZ/Illegal byte count/] CAILE C,%CPMXC JRST CHALOS SKIPGE (A) ;TEST OPCODE JRST CHIDAT ;DATA PACKET MOVEI B,[ASCIZ/Illegal opcode/] CAIGE D,%COMAX JRST @.+1(D) OFFSET -. JRST CHALOS ;ILLEGAL, FLUSH %CORFC::JRST CHIRFC %COOPN::JRST CHIOPN %COCLS::JRST CHICLS %COFWD::JRST CHIANS %COANS::JRST CHIANS %COSNS::JRST CHISNS %COSTS::JRST CHISTS %CORUT:: IFE CH10P+CH11P,JRST CHABRT ;IGNORE IFN CH10P+CH11P,JRST CHIRUT %COLOS::JRST CHILOS %COLSN::JRST CHALOS ;ILLEGAL, FLUSH %COMNT::JRST CHABRT ;IGNORE %COEOF::JRST CHIDAT %COUNC::JRST CHIUNC %COBRD::JRST CHIBRD %COMAX::OFFSET 0 ;FORWARDING CHAPFW: LDB B,[$CPKDA(A)] ;CHECK DESTINATION HOST TRNN B,377_8 ;SUBNET 0? JRST CHABRT ;FLUSH IT, XX-NETWORK-11 IS TRYING TO MAKE US CRASH LDB B,[$CPKFC(A)] ;INCREMENT FORWARDING COUNT ADDI B,1 CAIL B,20 JRST [ AOS CHNPFL ? JRST CHABRT ] ;LOOP, DISCARD DPB B,[$CPKFC(A)] SETOM -2(A) ;NOT ON SEND LIST AOS CHNPF JRST CHAXMT IFN CH10P+CH11P,[ ;INCOMING ROUTING INFO CHIRUT: LSH C,-2 ;NUMBER OF SUBNET ENTRIES JUMPE C,CHABRT ;COULD BE ZERO-LENGTH MOVEI D,%CPKDT(A) HRLI D,442000 LDB E,[$CPKSA(A)] ;SOURCE HOST IS GATEWAY CHIRU1: ILDB T,D ;SUBNET ILDB TT,D ;COST HLRZ B,SBNRUT(T) ;COST OF EXISTING ROUTE CAIGE T,NSUBNT CAMLE TT,B JRST CHIRU2 HRLM TT,SBNRUT(T) ;THIS IS BEST ROUTE NOW HRRM E,SBNRUT(T) CHIRU2: SOJG C,CHIRU1 JRST CHABRT ];CH10P+CH11P ;INTERRUPT-LEVEL PROCESSING OF SNS PACKET ;NOTE THAT WE DO NOT BARF AT SNS'S TO EXISTENT NON-OPEN CONNECTIONS. IF IT ;WAS AN RFC-SENT CONNECTION, THIS COULD BREAK IT PREMATURELY IF AN OPN WAS ;LOST AND THEN A SNS WAS NOT. CHISNS: MOVEI E,%CSOPN PUSHJ P,CHFNDX JRST [ CAIE E,%CSOPN JRST CHABRT ;CONNECTION EXISTS AND IS NOT OPEN, IGNORE PACKET JRST CHALOS ] ;CONNECTION DOES NOT EXIST, COMPLAIN PUSHJ P,CHABRT ;CONNECTION DOES EXIST CAIE E,%CSOPN POPJ P, ;NOT OPEN, IGNORE JRST CHASTO ;REPLY WITH STS ;INTERRUPT LEVEL PROCESSING OF RECEIVED FWD OR ANS CHIANS: PUSHJ P,CHFNDX ;FIND CONNECTION JRST CHABRT ;NOBODY AT OTHER END TO RECEIVE A LOS ANYWAY CAIE E,%CSRFS JRST CHABRT ;NOT IN RFC-SENT STATE, LOSS ; JRST CHICL1 ;CLOSE THE CONNECTION BUT GIVE TO USER AS INPUT ;DROPPING THROUGH WILL DO ;INTERRUPT LEVEL PROCESSING OF RECEIVED CLS PACKET CHICLS: PUSHJ P,CHFNDX ;FIND CONNECTION BEING CLOSED JRST CHALOS ;NONE, LOSS CHICL1: MOVEI W,%CSCLS ;CLOSE THE CONNECTION CHICL2: PUSHJ P,CHINT ;SET TO STATE IN W, INTERRUPT PUSH P,A MOVEI Q,CHSPBF(I) ;DISCARD OUT-OF-ORDER PACKETS PUSHJ P,CHALFR HRRZS CHSNBF(I) CHIC2A: MOVEI Q,CHSOBF(I) ;DISCARD TRANSMIT PACKETS, E.G. RFC WHICH RECEIVED PUSHJ P,CHAQGF ;AN ANS OR FWD, DON'T WANT TO TRANSMIT AGAIN JUMPE A,CHIC2B PUSHJ P,CHABR1 JRST CHIC2A CHIC2B: POP P,A JRST CHIDT1 ;GIVE PACKET TO USER AS DATA ;INTERRUPT LEVEL PROCESSING OF RFC PACKET CHIRFC: MOVE T,%CPKDT(A) ;CHECK FOR STATUS REQUEST CAMN T,[.BYTE 8 ? "S ? "T ? "A ? "T] CAIE C,6 JRST CHIRF7 MOVS TT,%CPKDT+1(A) XORI TT,(<.BYTE 8 ? "U ? "S>) TRNN TT,(<.BYTE 8 ? -1 ? -1>) JRST CHIRF3 CHIRF7: MOVEI Q,CHQLSN ;SEARCH LISTENING QUEUE PUSHJ P,CHAQSR JRST CHIRF1 ;NOT FOUND, LOAD SERVER EXCH A,B ;A LSN, B RFC LDB I,[$CPKSX(A)] ;GET CORRESPONDING INDEX HRRZ E,CHSSTA(I) CAIE E,%CSLSN JRST 4,. CHIRF0: PUSHJ P,CHABRT ;FOUND, DISCARD LISTEN PACKET MOVE A,B ;GET OTHER HOST'S RFC LDB B,[$CPKPN(A)] ;INITIALIZE RECEIVER'S PACKET NUMBER HRLM B,CHSPKN(I) MOVE B,%CPKS(A) MOVEM B,CHSFRN(I) ;HOOK 'EM UP MOVEI W,%CSRFC ;PUT INTO RFC-RECEIVED STATE MOVE T,TIME ;AND ENGAGE PI LEVEL MOVEM T,CHSITM(I) JRST CHICL2 ;RFC RECEIVED AND NOT IMMEDIATELY MATCHED TO A LSN. QUEUE AND LOAD SERVER JOB. ;BUT FIRST CHECK WHETHER THIS IS A DUPLICATE WHICH SHOULD BE DISCARDED. CHIRF1: MOVE C,%CPKS(A) ;SEARCH PENDING RFC QUEUE FOR RFC FROM HLRZ T,CHQRFC ;THE SAME SOURCE AS THIS. JUMPE T,CHIRD1 CHIRD0: CAMN C,%CPKS(T) JRST CHABRT ;THIS RFC IS A DUPLICATE, IGNORE IT HRRZ T,-2(T) JUMPN T,CHIRD0 CHIRD1: MOVSI T,-NINDX ;SEARCH OPEN AND RFC-RECEIVED CONNECTIONS CHIRD2: SKIPL CHSUSR(T) ;FOR ONE CONNECTED TO SAME GUY AS SENT RFC CAME C,CHSFRN(T) AOBJN T,CHIRD2 JUMPGE T,CHIRD3 ;NO DUPLICATE OF THIS RFC, QUEUE IT HRRZ TT,CHSSTA(T) CAIE TT,%CSOPN CAIN TT,%CSRFC JRST CHABRT ;REALLY A DUPLICATE, DISCARD AOBJN T,CHIRD2 CHIRD3: MOVEI B,[ASCIZ/System not up/] SKIPL SYSDBG ;REFUSE INCOMING CONNECTIONS IF LOGINS REFUSED SKIPE NETUSW ;ALLOWING INCOMING NET CONNECTIONS? JRST CHIRF2 ;NO, REFUSE (EVEN IF FROM OURSELVES) HRROI T,CHIRFJ ;LOAD JOB CONI PI,Q ;MUST TURN UTCOFF TO CALL NUJBST ANDI Q,177 ;SINCE THIS MAY RUN AT OTHER INT LEVELS CONO PI,NETOFF PUSHJ P,NUJBST JRST [ CONO PI,PICON(Q) JRST CHABRT ] ;RING BUFFER FULL, IGNORE, RETRY WILL CATCH CONO PI,PICON(Q) MOVE T,TIME ;REMEMBER WHEN THIS RFC WAS QUEUED MOVEM T,-1(A) MOVEI Q,CHQRFC JRST CHAQPF ;PUT ON FRONT OF QUEUE ;COME HERE TO SEND A LOS PACKET IN RESPONSE TO CRUFTY INPUT IN A ;B SHOULD POINT TO AN ASCIZ STRING FOR WHY. CHALOS: SKIPA T,[%COLOS] ;HERE TO REFUSE AN RFC. TURN IT INTO A CLS AND SEND IT BACK. ;B SHOULD POINT TO AN ASCIZ STRING FOR WHY. CHIRF2: MOVEI T,%COCLS HRLI B,440700 ;BP TO MESSAGE SETZB C,(A) .SEE $CPKFC DPB T,[$CPKOP(A)] MOVE T,%CPKS(A) ;EXCHANGE SOURCE AND DESTINATION EXCH T,%CPKD(A) MOVEM T,%CPKS(A) MOVE D,[440800,,%CPKDT(A)] CHIRF4: ILDB T,B JUMPE T,CHIRF5 IDPB T,D AOJA C,CHIRF4 CHIRF5: DPB C,[$CPKNB(A)] SETOM -2(A) ;NOT ON ANY SEND LIST JRST CHAXMT ;SEND IT ;HERE FOR RFC TO "STATUS" EXPUNGE FOO,BAR DEFINE FOO NAME BAR==0 .BYTE 8 IRPC CH,,NAME "CH BAR==BAR+1 TERMIN IFG BAR-4, .ERR NAME MORE THAN 4 CHARACTERS REPEAT 4-BAR, 0 .BYTE TERMIN CHIRF3: MOVE B,[MNAME FOO ,,] ;NAME OF MACHINE IN 8-BIT ASCII EXPUNGE FOO,BAR MOVEM B,%CPKDT(A) SETZM %CPKDT+1(A) MOVSI B,%CPKDT+1(A) HRRI B,%CPKDT+2(A) BLT B,%CPKDT+7(A) MOVE B,[.BYTE 8 ? MYCHAD/400 ? 1 ? 4+IFN CH10P+CH11P,[10.] ? 0 ] MOVEM B,%CPKDT+10(A) MOVEI B,%CPKDT+11(A) HRLI B,441000 MOVE T,CHNPI PUSHJ P,CHRF3A MOVE T,CHNPO PUSHJ P,CHRF3A IFN CH10P+CH11P,[ MOVE T,CHNABT PUSHJ P,CHRF3A MOVE T,CHNLOS PUSHJ P,CHRF3A MOVE T,CHNCRC PUSHJ P,CHRF3A MOVE T,CHNCR2 PUSHJ P,CHRF3A MOVE T,CHNPLE ADD T,CHNWLE PUSHJ P,CHRF3A ];CH10P+CH11P MOVEI T,%COANS SETZM (A) .SEE $CPKFC DPB T,[$CPKOP(A)] MOVE T,%CPKS(A) ;EXCHANGE SOURCE AND DESTINATION EXCH T,%CPKD(A) MOVEM T,%CPKS(A) MOVEI C,13*4+IFN CH10P+CH11P,[20.] ;BYTE COUNT JRST CHIRF5 ;SEND CHRF3A: MOVEI TT,4 IDPB T,B LSH T,-8 SOJG TT,.-2 POPJ P, ;HERE TO CONVERT A BRD INTO AN RFC CHIBRD: LDB T,[$CPKAN(A)] ;NUMBER OF BITMAP BYTES LDB TT,[$CPKNB(A)] ;NUMBER OF TOTAL DATA BYES (INCLUDES BITMAP) CAIG T,32. ;ACK NUMBER NO GREATER THAN 32. TRNE T,3 ; MUST BE MULTIPLE OF 4 JRST CHABRT ; FREE THE PACKET IF NO GOOD CAMG TT,T ;MUST BE SOME TEXTUAL RFC DATA AS WELL JRST CHABRT ; IF NOT, FREE PACKET MOVE C,TT ;GET NUMBER OF BYTES (CHIRFC WANTS COUNT IN C) SUB C,T ;WITHOUT BITMAP DPB C,[$CPKNB(A)] ;NEW BYTE COUNT LSH T,-2 ;CONVERT BITMAP BYTE COUNT TO WORD COUNT ADDI TT,3 ;CONVERT BYTE COUNT TO... LSH TT,-2 ;... WORD COUNT MOVEI D,%CPKDT(A) ;GET POINTER TO BEGINNING OF DATA HRL D,D ;IN UPPER AND LOWER HALVES (ALMOST BLT POINTER) HRLZ T,T ;BITMAP WORD COUNT,,0 ADD D,T ;RFC-STRING,,DATA-FIELD ADDI TT,%CPKDT-1(A) ;LAST LOCATION FOR BLT BLT D,(TT) SETZI TT, DPB TT,[$CPKAN(A)] ;ZERO THE ACK FIELD MOVE TT,MYCHAD DPB TT,[$CPKDA(A)] ;PRETEND IT WAS FOR ME JRST CHIRFC ;AND HANDLE IT AS AN RFC ;ROUTINE TO FIND INDEX PACKET CORRESPONDS TO, SKIP IF FOUND, INDEX IN I. ;ALSO RETURNS STATE IN E SINCE THAT'S OFTEN HANDY. ;ALSO SETS B FOR CHALOS CHFNDX: MOVEI B,[ASCIZ/Connection does not exist at this end/] LDB I,[$CPKDX(A)] ;GET REAL-INDEX PART OF DESTINATION INDEX CAIGE I,NINDX SKIPGE CHSUSR(I) POPJ P, ;NO MATCH SKIPGE CHSSTA(I) .SEE %CFOFF POPJ P, ;NOT TALKING TO NETWORK HRRZ E,CHSSTA(I) MOVE TT,%CPKD(A) MOVE T,%CPKS(A) CAIN E,%CSRFS ;IF IN RFC-SENT STATE, ONLY AND T,[.BYTE 16. ? -1 ? 0] ;THE SOURCE HOST HAS TO MATCH CAMN TT,CHSLCL(I) ;COMPARE LOCAL ADDRESS CAME T,CHSFRN(I) ; AND FOREIGN ADDRESS POPJ P, ;NO MATCH MOVE T,TIME MOVEM T,CHSITM(I) JRST POPJ1 ;SUCCEED, CALLER CHECKS THE STATE ;INTERRUPT LEVEL PROCESSING OF RECEIVED OPN PACKET CHIOPN: PUSHJ P,CHFNDX ;FIND CONNECTION TO BE OPENED JRST CHALOS CAIE E,%CSRFS ;NOT IN RFC-SENT STATE, JRST CHABRT ; MUST BE DUPLICATE, DISCARD. LDB B,[$CPKPN(A)] ;GET ITS PACKET NUMBER HRLM B,CHSPKN(I) ;INITIALIZE PACKET NUMBERING OF RECEIVED MESSAGES MOVE B,%CPKS(A) MOVEM B,CHSFRN(I) ;HOOK 'EM UP PUSHJ P,CHIST1 ;PROCESS AS A STS, DISCARD PUSHJ P,CHASTO ;RESPOND WITH A STS MOVEI W,%CSOPN ;DROP INTO CHINT ;COME HERE WITH INDEX IN I AND NEW STATE IN W, TO CHANGE STATE AND INTERRUPT CHINT: HRRM W,CHSSTA(I) MOVE T,TIME MOVEM T,CHSITM(I) ;IN CASE GOT HERE FROM CHOLSN MOVSI T,%CFOFF CAIE W,%CSOPN IORM T,CHSSTA(I) ;DISENGAGE PI LEVEL CAIN W,%CSOPN ANDCAM T,CHSSTA(I) ;NOW OPEN, ENGAGE PI LEVEL ;COME HERE TO INTERRUPT ON THE INPUT CHANNEL. SMASHES T,TT,W CHINTI: LDB T,[$CHSUI,,CHSUSR(I)] CHINT2: MOVE TT,CHSSTA(I) ;SIGNAL USER OR STY? TLNN TT,%CFSTY JRST CHINT4 ;USER LDB T,[$CFTTN,,TT] ;STY, GET TTY NUMBER CONO PI,PIOFF ;PROTECT LIST MODIFICATION SKIPL STYNTL-NFSTTY(T) ;DON'T PUT ON LIST TWICE JRST PIONJ MOVE TT,STYNTA ;ADD TO LIST MOVEM TT,STYNTL-NFSTTY(T) MOVEM T,STYNTA JRST PIONJ CHINT4: SKIPGE TT,CHSUSR(I) JRST 4,. MOVSI W,(SETZ) ;PCLSR THE JOB SO IT GETS AN IOC ERROR IF NEEDFUL IORM W,PIRQC(TT) ;EVEN IF NORMAL INTERRUPTS ARE NOT ENABLED CAIN T,77 POPJ P, ;IOPUSH'D, NO INTERRUPT MOVE T,CHNBIT(T) AND T,MSKST2(TT) IORM T,IFPIR(TT) POPJ P, OVHMTR CHD ;INTERRUPT LEVEL PROCESSING OF RECEIVED DATA PACKET CHIDAT: PUSHJ P,CHFNDX ;FIND ASSOCIATED CONNECTION JRST CHALOS ;NONE, LOSS CAIE E,%CSOPN ;STATE MUST BE OPEN JRST CHALOS ;BAD, LOSS PUSHJ P,CHIACK ;PROCESS ACKNOWLEDGEMENT FIELD ;NOW DECIDE WHETHER IT GOES ON CHSIBF(I), OR ON CHSPBF(I), OR GETS DISCARDED. HLRZ B,CHSPKN(I) ;LAST PACKET NUMBER GIVEN TO USER LDB C,[$CPKPN(A)] ;GET PACKET NUMBER OF THE NEW PACKET HLRZ T,CHSWIN(I) ;RECEIVE WINDOW SIZE ADDI T,(B) ;HIGHEST LEGAL PACKET NUMBER SUB T,C TRNE T,100000 ;SKIP IF T >= C JRST CHABRT ;FOO ON YOU, OVER WINDOW SIZE HRRZ T,CHSIBF(I) ;COMPUTE NEXT IN-ORDER PACKET EXPECTED JUMPE T,CHIDT6 ;BASED ON LAST IN-ORDER PACKET LDB TT,[$CPKOP(T)] CAIE TT,%COUNC JRST [ LDB B,[$CPKPN(T)] JRST CHIDT6 ] HLRZ T,CHSIBF(I) ;IF IT'S AN UNC, HAVE TO GO FIND CORRECT PACKET CHIDT5: LDB TT,[$CPKOP(T)] CAIE TT,%COUNC LDB B,[$CPKPN(T)] HRRZ T,-2(T) JUMPN T,CHIDT5 CHIDT6: ADDI B,1 ANDI B,177777 ;NEXT IN-ORDER PACKET EXPECTED CAMN B,C JRST CHIDT1 ;EQUAL, IT GOES ON THE END OF CHSIBF(I) LIST. SUB B,C ;NOT EQUAL, COMPARE THEM MODULO 2^16. TRNN B,100000 JRST CHIDTD ;B GREATER, THIS IS AN OLD PACKET, DISCARD IT ;PUT ON CHSPBF(I) IN PROPER ORDER ;A IS THIS PACKET, C IS HIS NUMBER, B IS PREDECESSOR, D IS NEXT, E IS HIS # MOVEI B,0 ;SIGNIFY AT FRONT OF LIST HLRZ D,CHSPBF(I) ;GET FIRST PACKET ON OUT-OF-ORDER LIST JUMPE D,CHIDT4 ;LIST IS EMPTY CHIDT3: LDB E,[$CPKPN(D)] SUB E,C ;COMPARE PACKET NUMBERS JUMPE E,CHIDTD ;DUPLICATE, DISCARD TRNE E,100000 JRST [ MOVE B,D ;E IS LESS, KEEP LOOPING HRRZ D,-2(B) JUMPN D,CHIDT3 JRST .+1 ] ;REACHED END PUT IT HERE SKIPE B HRRM A,-2(B) ;THREAD ONTO PREVIOUS PACKET SKIPN D CHIDT4: HRRM A,CHSPBF(I) ;THREAD ONTO BACK OF LIST SKIPN B HRLM A,CHSPBF(I) ;THREAD ONTO FRONT OF LIST HRRM D,-2(A) ;THREAD IN BEFORE PACKET IN D MOVSI B,1 ADDM B,CHSNBF(I) POPJ P, ;HERE IT GOES ON CHSIBF(I). A HAS PACKET, C HAS ITS PACKET NUMBER. ;IF GETTING HERE FROM CHICL1, C HAS GARBAGE BUT IT WILL NEVER BE USED. CHIDT1: SKIPN CHSIBF(I) PUSHJ P,CHINTI ;THERE WAS NO INPUT, BUT THERE IS NOW, COME AND GET IT AOS CHSNBF(I) MOVEI Q,CHSIBF(I) PUSHJ P,CHAQPL ;PUT ON END OF RECEIVE LIST HLRZ A,CHSPBF(I) ;GET FIRST OUT-OF-ORDER PACKET JUMPE A,CPOPJ ;NONE LDB B,[$CPKPN(A)] ;SEE IF THIS PACKET IS NOW IN-ORDER CAIL C,177777 ;BY COMPARING AGAINST C+1 MODULO 2^16. TDZA C,C ADDI C,1 CAME B,C POPJ P, ;NO MOVEI Q,CHSPBF(I) PUSHJ P,CHAQGF ;YES, PULL PACKET OF OUT-OF-ORDER LIST MOVSI B,-1 ADDM B,CHSNBF(I) JRST CHIDT1 ;AND GO PUT ONTO IN-ORDER LIST ;HERE IF PACKET IS A DUPLICATE AND IS TO BE DISCARDED. MUST SEND ;RECEIPT TO SHUT OFF EXCESS RETRANSMISSION. CHIDTD: PUSHJ P,CHABRT AOS CHNPD JRST CHASTO ;HERE FOR RECEIVING AN UNC PACKET CHIUNC: LDB I,[$CPKDI(A)] ;Destination index zero? JUMPE I,CHIUN2 LDB I,[$CPKDX(A)] ;GET REAL-INDEX PART OF DESTINATION INDEX CAIGE I,NINDX SKIPGE CHSUSR(I) JRST CHALOS ;NO MATCH MOVE TT,%CPKD(A) ;DESTINATION ADDRESS MATCHES? CAME TT,CHSLCL(I) JRST CHALOS HRRZ E,CHSSTA(I) ;IN FOREIGN PROTOCOL MODE? CAIN E,%CSFRN JRST CHIUN1 MOVE TT,%CPKS(A) ;NORMAL PROTOCOL, SOURCE ADDRESS MUST MATCH CAMN TT,CHSFRN(I) CAIE E,%CSOPN ;AND STATE MUST BE OPEN JRST CHALOS CHIUN1: MOVE TT,TIME MOVEM TT,CHSITM(I) SKIPE T,CHSIBF(I) ;DISCARD PACKET IF OVER WINDOW SIZE JRST [ LDB TT,[$CPKOP(T)] ; AND ALREADY HAVE AN UNC HRRZ T,CHSNBF(I) HLRZ Q,CHSWIN(I) CAML T,Q CAIE TT,%COUNC JRST .+2 JRST CHABRT ] PUSHJ P,CHINTI ;THERE WAS NO INPUT, BUT THERE IS NOW, COME AND GET IT AOS CHSNBF(I) ;PUT ON END OF RECEIVE LIST. MOVEI Q,CHSIBF(I) ;PACKET NUMBER IS RANDOM, NOTHING LOOKS AT IT JRST CHAQPL CHIUN2: IFE INETP,JRST CHALOS ;No comprendo internet IFN INETP,[ LDB I,[$CPKAN(A)] ;Protocol number CAIE I,8_8 ;DOD Internet #x0800 JRST CHALOS AOS CHNIPI ;Meter Internet packets in from Chaosnet MOVE J,A ;Save Chaosnet packet LDB A,[$CPKNB(A)] ;Compute size of Internet datagram in words ADDI A,3 LSH A,-2 MOVE C,A ;Save word count CALL IPGIPT ;Get buffer to copy datagram into JRST CHIUN3 ;No buffers available, discard packet MOVSI T,%CPKDT(J) ;Make BLT pointer HRRI T,1(B) ADDI B,(C) ;Address of last destination word BLT T,(B) EXCH A,J ;Free the Chaosnet packet CALL CHABRT MOVE A,J ;Datagram structure MOVE B,C ;Word count MOVEI C,0 ;Offset to start of IP header CALRET IPRDGM ;Dispose of datagram CHIUN3: MOVE A,J ;Discard Chaosnet packet CALRET CHABRT ];INETP OVHMTR CHJ ;INTERRUPT LEVEL PROCESSING OF LOS CHILOS: PUSHJ P,CHFNDX ;FIND CONNECTION TO BE BROKEN JRST CHABRT ;NONE, IGNORE MOVEI W,%CSLOS ;PUT INTO LOST STATE JRST CHICL2 ;GIVE PACKET TO USER AS DATA, DISENGAGE, AND INTERRUPT ;INTERRUPT LEVEL PROCESSING OF STS CHISTS: PUSHJ P,CHFNDX JRST CHALOS CAIE E,%CSOPN ;CONNECTION MUST BE OPEN JRST CHALOS CHIST1: LDB B,[042000,,%CPKDT(A)] ;GET NEW WINDOW SIZE CAILE B,MXWIND MOVEI B,MXWIND HRRM B,CHSWIN(I) LDB B,[242000,,%CPKDT(A)] ;PROCESS RECEIPT PUSHJ P,CHIAK0 PUSHJ P,CHABRT JRST CHARTR ;RETRANSMIT OVHMTR CHA ;INTERRUPT LEVEL PROCESSING OF RECEIVED ACKNOWLEDGEMENT. ;REMOVE THE ACKNOWLEDGED PACKETS FROM THE INDEX'S SEND LIST AND UPDATE CHSNOS(I). ;NOTE THAT THE LIST IS ASSUMED TO BE SORTED SO WE ONLY ;REMOVE PACKETS FROM THE FRONT. CLOBBERS B,C,D,T,TT,Q. CHIACK: LDB B,[$CPKAN(A)] ;PACKET NUMBER BEING RECEIPTED CHIAK0: LDB T,[$CPKAN(A)] ;ENTER HERE FROM CHISTS HRRZ D,CHSACK(I) ;GET MAX OF THIS ACKNOWLEDGE AND PREVIOUS SUB D,T TRNE D,100000 HRRM T,CHSACK(I) ;ACKNOWLEDGED PACKET NUMBER IS NEW START OF WINDOW PUSH P,A HLRZ A,CHSOBF(I) ;MAP DOWN SEND LIST JUMPE A,CHIAK2 ;LIST EMPTY CHIAK1: LDB D,[$CPKPN(A)] SUBM B,D TRNE D,100000 JRST CHIAK2 ;RCP# LESS THAN PKT# HRRZ C,-2(A) ;GET NEXT PACKET HLLOS D,-2(A) ;MARK NOT ON SEND LIST AOJE D,CHIAK3 ;AND JUMP IF NOT ON TRANSMIT LIST IFN DLCP,[ MOVEI Q,DLCXMQ ;ON TRANSMIT LIST, TRY TO TAKE OFF PUSHJ P,CHIAKF ];DLCP IFN T11CHP,[ MOVEI Q,T11XMQ PUSHJ P,CHIAKF ];T11CHP IFN CH10P+CH11P,[ MOVEI Q,CHXXMQ PUSHJ P,CHIAKF ];CH10P+CH11P CAIA ;AND DON'T FREE IT CHIAK3: PUSHJ P,CHABRT HRLM C,CHSOBF(I) SKIPE A,C JRST CHIAK1 SETZM CHSOBF(I) ;SEND LIST NOW EMPTY CHIAK2: MOVE D,CHSNOS(I) ;COMPUTE NEW VALUE OF CHSNOS HRRZ T,CHSACK(I) ;START OF WINDOW HRRZ C,CHSPKN(I) ;LAST PACKET SENT SUB T,C SKIPLE T SUBI T,200000 ;T GETS NEGATIVE AMOUNT OF WINDOW OCCUPIED ADD T,CHSWIN(I) ;RH(T) GETS AVAILABLE PORTION OF WINDOW HRREM T,CHSNOS(I) ;WHICH IS NUMBER OF OUTPUT SLOTS JUMPG D,POPAJ ;IF FORMERLY THERE WERE NO OUTPUT SLOTS, LDB T,[$CHSUO,,CHSUSR(I)] SKIPLE CHSNOS(I) ;AND NOW THERE ARE, PUSHJ P,CHINT2 ;INTERRUPT ON THE OUTPUT CHANNEL JRST POPAJ ;TRY TO TAKE PACKET IN A OFF OF TRANSMIT LIST IN Q. ;CLOBBER T,Q,D. CALLED WITH INTERRUPTS OFF. ;MAY RETURN WITH A POINTING TO FREE BUT THAT IS OK AT THIS TIME. CHIKF1: SKIPA D,T CHIAKF: MOVEI D,2(Q) ;LH[-2(D)] POINTS TO (T) HLRZ T,-2(D) JUMPE T,CPOPJ ;NOT FOUND CAIE T,(A) JRST CHIKF1 HLRZ T,-2(A) ;LINK OUT HRLM T,-2(D) JUMPN T,CHABRT ;JUMP IF DIDN'T DELETE LAST PACKET IN LIST HRRM D,(Q) ;NEW LAST PACKET IN LIST CAIN D,2(Q) SETZM (Q) ;FOO, TRANSMIT LIST NOW EMPTY JRST CHABRT SUBTTL CHAOS NET DL10 INTERRUPT ROUTINE OVHMTR CHH IFN DLCP,[ ;COME HERE FROM EACH DL10 INTERRUPT AT TTY LEVEL. SMASH ALL REGISTERS EXCEPT P AND 0. DLCWAK: CONI PI,E ;SAVE PI STATUS AND SWITCH TO NETWORK INTERRUPT LEVEL ANDI E,177 PUSH P,E CONO PI,NETOFF DLCWK1: MOVEI J,1 ;ALWAYS CHECK BOTH BUFFERS SO WE CAN'T GET OUT OF PHASE WITH 11 MOVEI R,2 ;CHECK FOR INPUT AVAILABLE CAME R,DLCRS1(J) SOJGE J,.-1 JUMPL J,DLCWK2 MOVE A,DLCRA1(J) ;GOT INPUT, PROCESS IT SETZM DLCRS1(J) ;BUFFER SLOT NOT OCCUPIED NOW IFN KS10P, CLRCSH IFN KL10P, PUSHJ P,DLCSWP ;SWEEP CACHE IN CASE ANYONE HAPPENED TO TOUCH BUFFER SKIPE A ;THIS CAN HAPPEN IF PDP11 WAS JUST STUFFED PUSHJ P,CHAPII ;PROCESS THE PACKET PUSHJ P,DLCIBG ;SUPPLY A NEW INPUT BUFFER TO 11 JRST DLCWK1 ;TRY FOR MORE INPUT DLCWK2: MOVEI J,1 ;SCAN CHANNELS FOR OUTPUT DONE CAME R,DLCSS1(J) DLCWK3: SOJGE J,.-1 JUMPL J,DLCWK4 MOVE A,DLCSA1(J) ;FOUND AN OUTPUT DONE BUFFER HRROS B,-2(A) ;MARK IT NOT ON TRANSMIT LIST AOJN B,.+2 ;AND UNLESS IT IS ON SEND LIST PUSHJ P,CHABRT ;RETURN IT TO FREE SETZM DLCSA1(J) ;IDLE THIS BUFFER SETZM DLCSS1(J) JRST DLCWK3 DLCWK4: MOVE J,DLCSBF ;TRY TO SEND SOME OUTPUT SKIPE DLCSS1(J) JRST DLCWK9 ;BUFFER BUSY HLRZ A,DLCXMQ ;GET ANOTHER OFF TRANSMIT QUEUE JUMPE A,DLCWK9 ;QUEUE EMPTY HLRZ T,-2(A) IFN FTRCHK,[ CAIN T,-1 BUG PAUSE,[CHAOS LIST THREAD TRASHED],OCT,A,OCT,-2(A) ];FTRCHK HRLM T,DLCXMQ IFN FTRCHK,[ JUMPN T,.+4 CAME A,DLCXMQ ;REACHED END OF LIST, END IN RIGHT PLACE? BUG PAUSE,[DCLXMQ THREAD TRASHED] SETZM DLCXMQ ];FTRCHK IFE FTRCHK,[ SKIPN T SETZM DLCXMQ ];FTRCHK PUSHJ P,DLCXMT ;SEND IT ON THIS BUFFER JRST DLCWK4 ;GO TRY TO SEND ON OTHER BUFFER DLCWK9: POP P,E CONO PI,PICON(E) ;RESTORE PI POPJ P, ;THIS ROUTINE SUPPLIES AN INPUT BUFFER TO THE 11 ON ALL BUFFERS THAT NEED IT ;CALL WITH INTERRUPTS OFF OR IN PROGRESS DLCIBG: MOVEI J,1 SKIPE DLCRS1(J) DLCIB1: SOJGE J,.-1 JUMPL J,CPOPJ PUSHJ P,CHABGI ;GET A BUFFER JRST [ SETZM DLCRA1(J) ;NO MEMORY, WILL TRY AGAIN AT CLOCK LEVEL SETZM DLCRS1(J) POPJ P, ] SETZM (A) ;CLEAR THE BUFFER SINCE THE DL10 DOESN'T TOUCH LOW 4 BITS HRLZ T,A HRRI T,1(A) BLT T,%CPMXW-1(A) MOVEM A,DLCRA1(J) ;MAKE AVAILABLE TO PDP11 HRLI A,120000 MOVEM A,DLCRP1(J) SOS DLCRP1(J) IFN KS10P, .ERR CLRCSH not needed here? IFN KL10P, PUSHJ P,DLCSWP ;SWEEP CACHE BEFORE SIGNALLING 11 MOVEI T,1 MOVEM T,DLCRS1(J) CONO DLC,100040+TTYCHN ;INTERRUPT 11 JRST DLCIB1 ;TRY FOR OTHER BUFFER ALSO ;THIS ROUTINE SENDS PACKET IN A TO DL10 (CALL WITH NETOFF OR IN PROGRESS) ;SWITCHES BUFFERS, LEAVES NEW ONE IN J DLCXMT: MOVE J,DLCSBF MOVEM A,DLCSA1(J) HRLI A,120000 MOVEM A,DLCSP1(J) ;GIVE 11 POINTER TO NEW PACKET SOS DLCSP1(J) IFN KS10P, .ERR CLRCSH not needed here? IFN KL10P, PUSHJ P,DLCSWP ;SWEEP CACHE, PUTTING PACKET INTO CORE MOVEI T,1 MOVEM T,DLCSS1(J) ;ACTIVATE PDP11 CONO DLC,100040+TTYCHN XORI J,1 ;NEXT BUFFER MOVEM J,DLCSBF POPJ P, IFN KL10P,[ ;THIS ROUTINE SWEEPS PACKET IN A OUT OF THE CACHE, ;CLOBBERING B, C, AND D. IFG PKTBSZ-1000, .ERR PKTBSZ BIGGER THAN HARDWARE PAGE SIZE, CACHE SWEEP LOSES DLCSWP: LDB D,[111100,,A] ;SWEEP ONE PAGE OF CACHE SWPUO (D) ;STORING PACKET INTO CORE MOVE B,[CONSZ 200000] ;AWAIT COMPLETION IN ACS MOVE C,[JRST B] ;TO MINIMIZE CACHE INTERFERENCE MOVSI D,(POPJ P,) JRST B ];KL10P ];DLCP SUBTTL CHAOS NET TEN-11 INTERFACE STUFF IFN T11CHP,[ ;THIS ROUTINE CHECKS FOR TEN-11 INITIALIZATION, SKIP-RETURNS IF OK TO USE ;CLOBBERS T,TT T11CHK: SKIPE TEN11F JRST T11LUZ ;NOT SUPPOSED TO USE TEN11 MOVE T,T11VER ;CHECK VERSION TO MAKE SURE RIGHT PROGRAM, ETC. CAME T,[.BYTE 8 ? "H ? "C ? 0 ? 1] JRST T11LUZ ;PROBABLY TURNED OFF OR WRONG PROGRAM SKIPE T11I10 ;SHOULD WE REINIT? JRST T11CK1 ;YES, GO DO SO SKIPLE T,T11WIN ;ARE WE WINNING? JRST POPJ1 ;YES, FINE JUMPE T,[SETOM T11WIN ;NOW THAT VERSION IS OK, TELL 11 TO INIT MOVSI T,-1 MOVEM T,T11I11 JRST T11CK1 ] ;AND INIT OURSELVES SKIPE T11I11 ;WAITING FOR 11 TO REINIT? POPJ P, ;YES, WAIT ;HERE TO REINIT. FIRST, PICK UP PARAMETERS. T11CK1: LDB TT,[242000,,T11PRM] ;BYTES PER PACKET BUFFER CAIGE TT,<%CPMXW+1>*4 ;BETTER BE RIGHT SIZE JRST T11LUZ ;TOO SMALL (ASSUME IF TOO BIG, PACKETS WON'T BE) LSH TT,-2 MOVEM TT,T11BSZ ;SAVE BUFFER SIZE IN PDP10 WORDS LDB T,[042000,,T11PRM] ;NUMBER OF BUFFERS IN EACH DIRECTION IMULB T,TT ;NUMBER OF PDP10 WORDS IN EACH DIRECTION ADD TT,T11IBB MOVEM TT,T11IBE ;INIT POINTERS MOVEM TT,T11OBB MOVEM TT,T11OBP ADD TT,T MOVEM TT,T11OBE HRREI T,-T11CHS-2000(TT) JUMPG T,T11LUZ ;COMMUNICATION AREA LONGER THAN 1K MOVE T,T11IBB MOVEM T,T11IBP T11CK2: SETZM (T) ;CLEAR BUFFER HEADERS ADD T,T11BSZ CAMGE T,TT JRST T11CK2 MOVEM T,T11WIN ;WE'RE WINNING (MAKE T11WIN POSITIVE NON-ZERO) SETZM T11I10 ;INIT DONE JRST POPJ1 ;HERE IF PDP11 PARAMETERS DON'T MATCH WHAT WE EXPECT T11LUZ: SETZM T11WIN ;NOT WINNING POPJ P, ;HERE FROM CLOCK LEVEL TO CHECK ON TEN-11 CHAOS NET CHANNEL T11WAK: PUSHJ P,T11CHK ;IS EVERYTHING OK? POPJ P, ;NO. T11WK0: MOVE C,T11IBP ;CHECK INPUT SKIPN (C) JRST T11WK1 ;NONE AVAILABLE MOVSI J,2(C) ;POINT TO PACKET LDB D,[$CPKNB+2(C)] ;GET SIZE OF PACKET ADDI D,4*%CPKDT+3 ;CONVERT BYTES TO WORDS INCLUDING HEADER LSH D,-2 CAILE D,%CPMXW ;DON'T GET FAKED OUT BY CLOBBERED COUNT MOVEI D,%CPMXW PUSHJ P,CHABGI ;GET PLACE TO PUT IT JRST T11WK1 ;NONE AVAILABLE HRLOI E,-1(D) EQVI E,(A) ;AOBJN POINTER TO PACKET BUFFER HRRI J,(A) ;BLT POINTER TO COPY PACKET ADDI D,-1(A) ;LAST WORD BLT J,(D) ;COPY PACKET FROM 11 TO 10 MOVEI H,0 ;COMPUTE CHECKSUM T11WK4: ADD H,(E) LSH H,-1 TRZE H,10 TLO H,(SETZ) AOBJN E,T11WK4 MOVE TT,1(C) ;GET PDP11'S CHECKSUM SETZM (C) ;GIVE THE 11 BACK THE BUFFER ADD C,T11BSZ ;ADVANCE THE POINTER CAML C,T11IBE MOVE C,T11IBB MOVEM C,T11IBP CAME H,TT JRST [ AOS T11CKE ;COUNT CHECKSUM ERRORS PUSHJ P,CHABRT ;AND DISCARD PACKET JRST T11WK0 ] CONO PI,NETOFF PUSHJ P,CHAPII ;PROCESS THE INPUT CONO PI,NETON JRST T11WK0 T11WK1: CONO PI,NETOFF SKIPE T11XMQ ;ANY OUTPUT? SKIPE @T11OBP ;AND OUTPUT BUFFER SPACE AVAILABLE? JRST NETONJ ;NO, RETURN FROM T11WAK HLRZ A,T11XMQ ;GET PACKET OFF TRANSMIT QUEUE HLRZ B,-2(A) ;GET NEXT AFTER THAT HRLM B,T11XMQ ;BECOMES NEW HEAD OF QUEUE SKIPN B SETZM T11XMQ PUSHJ P,T11XMT ;COPY PACKET INTO 11 CONO PI,NETON JRST T11WK1 ;LOOK FOR MORE OUTPUT ;SEND PACKET A-> TO 11. SMASHES B,C,T,TT,Q. CALL WITH NETOFF. T11XMT: LDB C,[$CPKNB(A)] ;GET BYTE COUNT MOVE Q,C ;MUST CLEAR UNUSED BYTES AT END OF LAST WORD ANDI Q,3 ;TO MAKE THE CHECKSUM COME OUT RIGHT ADDI C,4*%CPKDT+3 LSH C,-2 ;CONVERT TO WORD COUNT MOVE Q,(Q)[ -1 ;MASK FOR BYTES TO RETAIN IN LAST WORD <.BYTE 8 ? -1> <.BYTE 8 ? -1 ? -1> <.BYTE 8 ? -1 ? -1 ? -1> ] MOVEI TT,-1(C) ADD TT,A ANDM Q,(TT) ;MASK OFF LAST WORD HRLOI C,-1(C) EQVI C,(A) ;AOBJN PTR MOVEI TT,0 ;COMPUTE XOR CHECKSUM IN TT SKIPA B,T11OBP ;-> CURRENT OUTPUT BUFFER IN 11 T11XM1: ADDI B,1 MOVE T,(C) TRZ T,17 ;CLEAR BITS 10-11 TREATS SPECIALLY ADD TT,T ;COMPUTE CHECKSUM LSH TT,-1 TRZE TT,10 TLO TT,(SETZ) MOVEM T,2(B) AOBJN C,T11XM1 MOVE B,T11OBP MOVEM TT,1(B) ;GIVE CHECKSUM TO 11 MOVSI TT,-1 MOVEM TT,0(B) ;GIVE PACKET TO 11 ADD B,T11BSZ ;ADVANCE BUFFER POINTER CAML B,T11OBE MOVE B,T11OBB MOVEM B,T11OBP HRROS T,-2(A) ;TAKE PACKET OFF TRANSMIT LIST AOJN T,.+2 PUSHJ P,CHABRT ;NOT ON SEND LIST, FREE IT POPJ P, ];T11CHP SUBTTL CH-10 INTERRUPT ROUTINES ;THE GENERAL IDEA IS THAT WE INTERRUPT ON A LOW-PRIORITY INTERRUPT LEVEL, ;AND DO THE TIME-INTENSIVE PACKET COPYING AT THAT LEVEL. THE GENERAL ;CHAOS ROUTINES ARE THEN CALLED WITH NETOFF. IFN CH10P,[ EBLK CHXACS: BLOCK 20 CHXPDL: -60,,. BLOCK 60 CHXBRK: 0 BBLK MOVEM 17,CHXACS+17 MOVEI 17,CHXACS BLT 17,CHXACS+16 MOVE P,CHXPDL CONSO CHX,CHXRCV ;PACKET RECEIVED? JRST CHXBK5 PUSHJ P,CHABGI ;GET PLACE TO PUT PACKET JRST [ MOVEI T,CHXREN ;NONE AVAILABLE, DISABLE INTR ANDCAM T,CHXCNO CONO CHX,@CHXCNO JRST CHXBK5 ] CONSZ CHX,CHXCRC+CHXWLE ;CHECK FOR ERRORS JRST [ CONSZ CHX,CHXCRC AOSA CHNCRC AOS CHNWLE JRST CHXBK4 ] ;IGNORE PACKET DATAI CHX,T ;FIRST DATAI YIELDS GARBAGE MOVEI T,CHXSWB ;DISABLE BYTE SWAPPING ANDCAM T,CHXCNO CONO CHX,@CHXCNO HRLI A,-%CPKDT ;READ HEADER DATAI CHX,(A) AOBJN A,.-1 HRRZI A,-%CPKDT(A) PUSHJ P,CHSWAB ;ENABLE BYTE SWAPPING IF NEEDED LDB T,[$CPKNB(A)] ;GET SIZE OF PACKET CAILE T,%CPMXC ;DON'T RUN OFF END OF BUFFER JRST CHXBK4 ADDI T,3 ;ROUND UP TO NEXT WORD BOUNDARY LSHC T,-2 ;CONVERT BYTES TO WORDS, TT GETS REMAINDER HRLOI D,-1(T) ;MAKE AOBJN POINTER EQVI D,%CPKDT(A) JUMPGE D,.+3 ;EMPTY PACKET BOUNDARY CASE DATAI CHX,(D) AOBJN D,.-1 DATAI CHX,T ;NOW READ AND IGNORE HARDWARE HEADER TLNE T+1,400000 DATAI CHX,T ;THIRD HALFWORD CONI CHX,T ;CHECK FOR ERRORS TDNE T,[CHXPLE+CHXCRC+CHXOVR] JRST [ TLNE T,(CHXOVR) JRST CHXBKZ ;OVERRRUN CAN'T HAPPEN UNLESS HARDWARE BROKEN TLNE T,(CHXPLE) AOSA CHNPLE TRNN T,CHXCRC JRST CHXBK4 AOS CHNCR2 JRST CHXBK4 ] CONO PI,NETOFF-1 PUSHJ P,CHAPII ;PROCESS THE INPUT CONO PI,NETON-1 CAIA CHXBK4: PUSHJ P,CHABRT ;DIDN'T USE BUFFER AFTER ALL CONI CHX,T ;COUNT LOST PACKETS LDB T,[$CHXLC,,T] ADDM T,CHNLOS MOVEI T,CHXREN ;ENABLE RECEIVER FOR NEXT PACKET IORB T,CHXCNO CONO CHX,CHXRCV(T) CHXBK5: CONSO CHX,CHXXMT ;TRANSMIT DONE? JRST CHXBK9 SKIPE T,CHOSTA ;TRANSMIT IN PROGRESS? CONSO CHX,CHXABT ;AND WAS ABORTED? JRST CHXBK7 ;NO TO EITHER, LOOK FOR MORE WORK AOS CHNABT ;METER TRANSMIT ABORTS CAIL T,NCHRTR ;ABORTED TOO MANY TIMES? JRST CHXBK7 ;DONE WITH PACKET AOS CHOSTA ;COUNT RETRANSMISSIONS MOVEI T,CHXTEN IORB T,CHXCNO CONO CHX,CHXXMT(T) ;RETRANSMIT PACKET JRST CHXBK9 CHXBK7: SETZM CHOSTA ;TRANSMITTER IDLE, LOOK FOR NEXT PACKET CONO PI,PIOFF HLRZ A,CHXXMQ ;ANYTHING QUEUED FOR TRANSMISSION? JUMPE A,[ MOVEI T,CHXTEN ;DISABLE INTERRUPTS ANDCAM T,CHXCNO CONO CHX,@CHXCNO CONO PI,PION JRST CHXBK9 ] HLRZ B,-2(A) ;CDR TRANSMIT QUEUE HRLM B,CHXXMQ SKIPN B SETZM CHXXMQ ;QUEUE EMPTY NOW CONO PI,PION AOS CHOSTA ;NOW SEND THIS PACKET MOVEI T,CHXHLF+CHXSWB ;CLEAR HALFWORD, BYTE-SWAP MODES ANDCAM T,CHXCNO CONO CHX,@CHXCNO HRLI A,-%CPKDT ;TRANSMIT HEADER DATAO CHX,(A) AOBJN A,.-1 HRRZI A,-%CPKDT(A) PUSHJ P,CHSWAB ;ENABLE BYTE SWAPPING IF NEEDED LDB T,[$CPKNB(A)] ;GET SIZE OF PACKET ADDI T,1 ;ROUND UP TO NEXT HALF WORD BOUNDARY LSHC T,-2 ;CONVERT BYTES TO WORDS, T+1 GETS REMAINDER HRLOI D,-1(T) ;MAKE AOBJN POINTER EQVI D,%CPKDT(A) JUMPGE D,.+3 ;EMPTY PACKET BOUNDARY CASE DATAO CHX,(D) AOBJN D,.-1 MOVEI T,CHXHLF+CHXTEN ;SWITCH TO HALFWORD MODE, ENABLE DONE INTR IORM T,CHXCNO CONO CHX,@CHXCNO TLNE T+1,400000 ;SEND EXTRA HALFWORD IF NEEDED DATAO CHX,(D) MOVEI T,CHXSWB ;DISABLE SWAP BYTES MODE ANDCAM T,CHXCNO CONO CHX,@CHXCNO LDB T,[$CPKDN(A)] ;GET DESTINATION SUBNET HRRZ D,SBNRUT(T) ;GATEWAY TO THAT SUBNET CAIGE T,NSUBNT CAIN T,MYCHAD_-8 ;IF ON LOCAL CABLE LDB D,[$CPKDA(A)] ;GO DIRECT LSH D,16.+4 DATAO CHX,D ;STORE HARDWARE DESTINATION ADDRESS MOVE T,CHXCNO ;TRANSMIT PACKET CONO CHX,CHXXMT(T) CONI CHX,T TLNE T,(CHXOVR) ;CAN'T HAPPEN UNLESS HARDWARE BROKEN CHXBKZ: BUG HALT,[CHAOS: I/O BUS OVERRUN] HRROS B,-2(A) ;MARK IT NOT ON TRANSMIT LIST AOJN B,.+2 ;AND UNLESS IT IS ON SEND LIST PUSHJ P,CHABRT ;RETURN IT TO FREE CHXBK9: MOVSI 17,CHXACS ;DISMISS INTERRUPT BLT 17,17 JRST 12,@CHXBRK CHSWAB: LDB T,[$CPKOP(A)] ;DOES THIS PACKET NEED BYTE SWAPPING? TRNE T,200 JRST [ TRNE T,100 POPJ P, ;BINARY DATA JRST CHSWB1 ] ;CHARACTER DATA IDIVI T,40 MOVE T,CHSWBT(T) LSH T,(T+1) JUMPL T,CPOPJ ;BINARY CONTROL PACKET CHSWB1: MOVEI T,CHXSWB ;CHARACTER, SWAP DEM BYTES IORM T,CHXCNO CONO CHX,@CHXCNO POPJ P, CHSWBT: 1_<35.-%COOPN>+1_<35.-%COSTS>+1_<35.-%CORUT> 0 ? 0 ? 0 ];CH10P SUBTTL CH-11 INTERRUPT ROUTINES ;The Unibus Chaosnet board interrupts on the same level as TTYs, ;and comes to CHXBKH via vectored interrupt. We use a programmed ;interrupt request to drop down to a lower interrupt level for the ;slow packet-copying operation, so as not to interfere with the TTYs, ;then turn NETOFF when we call into the Chaosnet NCP. ;(We actually use NETOFF-1 and NETON-1 so as not to interfere with ;CLKOFF. This assumes that interrupt levels between CLKCHN and ;CHXCHN are never turned off.) IFN CH11P,[ ;;; Macros that will eventually be instructions DEFINE PACK16 AC,E ;AC,AC+1 right-aligned and zero-filled LSH AC,16. IOR AC,AC+1 LSH AC,4 MOVEM AC,E TERMIN DEFINE PACK8 AC,E ;AC: ...B2B1 AC+1: ...B4B3 zero-filled!! ROTC AC,-8 ;B3...B2 B1...B4 ROT AC,-16. ;B1,B2,B3 in position, B4 right-aligned ADDI AC+1,(AC+1) ;Shift RH(AC+1) left 4 bits ADDI AC+1,(AC+1) ADDI AC+1,(AC+1) ADDI AC+1,(AC+1) ;B1,B4 in position in AC+1 IOR AC,AC+1 MOVEM AC,E TERMIN DEFINE UNPK16 AC,E ;Doesn't bother masking off garbage bits MOVE AC,E MOVE AC+1,AC ROT AC,16. ;First halfword right-aligned LSH AC+1,-4 ;Second halfword right-aligned TERMIN DEFINE UNPK8 AC,E MOVE AC,E ;B1B2B3B4... ROT AC,8 ;B2B3B4...B1 MOVE AC+1,AC AND AC,[377_2,,377] ;...B3...B1 zero-filled ROT AC+1,16. ;B4...B1B2B3 AND AC+1,[377_12,,377_8];B4...B2... zero-filled IORB AC,AC+1 ;B4B3...B2B1 ROT AC+1,16. ;...B4B3, garbage in high bits TERMIN EBLK CHXACS: BLOCK 20 CHXSVH: 0 CHXPDL: -60,,. BLOCK 60 CHXBKH: 0 ;Hardware interrupt on TTYCHN comes here BBLK CONO PI,CHXRQ ;Redirect to lower interrupt level MOVEM T,CHXSVH ;Clear hardware interrupt enable MOVEI T,%CAREN+%CATEN ; so the Chaos board will stop interrupting ANDCAB T,CHXCSR IOWRI T,CAICSR MOVE T,CHXSVH JRST 12,@CHXBKH EBLK CHXBRK: 0 ;Software interrupt on CHXCHN comes here BBLK CONO PI,020000+200_<-CHXCHN> ;BAG-BITING DEC LOSERS MOVEM 17,CHXACS+17 MOVEI 17,CHXACS BLT 17,CHXACS+16 MOVE P,CHXPDL IORDI T,CAICSR ;Check for received packet TRNN T,%CARDN JRST CHXBK3 ;No incoming packet yet TRNE T,%CAERR ;Check for error in received packet JRST [ AOS CHNCRC JRST CHXBK1 ] ;Ignore packet IORDI R,CAIRBC ;Number of bits in packet - 1 SUBI R,31. ;Exclude the three extra hardware words TRNE R,17 JRST [ AOS CHNWLE ;Length not a multiple of 16 JRST CHXBK1 ] ASH R,-5 ;32-bit word count, rounded up PUSHJ P,CHABGI ;Get place to put packet JRST [ AOS CHNLOS ;No buffers, lose this packet JRST CHXBK1 ] HRLI A,-%CPKDT ;Copy out the packet header CHSRC1: IORDI B,CAIRBF IORDI C,CAIRBF PACK16 B,(A) AOBJN A,CHSRC1 PUSHJ P,CHSHDR ;Decode the header JRST CHSRC4 ;No byte swapping JUMPGE D,CHSRC3 CHSRC2: IORDI B,CAIRBF ;Read out the data, byte-swapped IORDI C,CAIRBF PACK8 B,(D) AOBJN D,CHSRC2 CHSRC3: JUMPGE H,CHSRC7 ;Jump if even packet length IORDI B,CAIRBF ;Residual halfword SETZ C, ;Somebody depends on zero here PACK8 B,(D) AOJA D,CHSRC7 CHSRC4: JUMPGE D,CHSRC6 CHSRC5: IORDI B,CAIRBF ;Read out the data, halfwords IORDI C,CAIRBF PACK16 B,(D) AOBJN D,CHSRC5 CHSRC6: JUMPL H,[ IORDI B,CAIRBF ;Residual halfword SETZ C, ;Somebody depends on zero here PACK16 B,(D) AOJA D,CHSRC7 ] CHSRC7: SUB D,R ;AOBJN pointer minus number of words in packet CAIE A,(D) JRST [ AOS CHNPLE ;Packet length disagrees with hardware length JRST CHXBK2 ] IORDI T,CAIRBF ;Read the three hardware header words IORDI T,CAIRBF IORDI T,CAIRBF IORDI T,CAICSR TRNE T,%CAERR ;Make sure packet came out of RAM okay JRST [ AOS CHNCR2 ;Garbage, try again JRST CHXBK2 ] IORDI T,CAIRBC ;Make sure counter didn't spazz CAIE T,7777 JRST [ AOS CHNSPZ JRST CHXBK2 ] CONO PI,NETOFF-1 ;Get to network interrupt level PUSHJ P,CHAPII ;Process the input CONO PI,NETON-1 CHXBK1: IORDI T,CAICSR ;Count lost packets LDB TT,[$CALOS,,T] ADDM TT,CHNLOS MOVE TT,CHXCSR IORI TT,%CARCL ;Enable receiver for next packet IOWRI TT,CAICSR CHXBK3: TRNN T,%CATDN ;Transmit done? JRST CHXBK8 ;No, dismiss SKIPN TT,CHOSTA ;Transmit in progress? JRST CHXBK7 ;No, look for something to transmit TRNN T,%CATAB ;Yes, was it aborted? JRST CHXBK5 ;No, we're done with that packet AOS CHNABT ;Meter transmit aborts CAIGE TT,NCHRTR ;Aborted too many times? JRST CHXBK7 ;No, retransmit it CHXBK5: CONO PI,PIOFF ;Lock transmit list HLRZ A,CHXXMQ ;Get packet probably being transmitted now JUMPE A,[ CONO PI,PION ;It vanished? JRST CHXBK6 ] HLRZ B,-2(A) ;CDR transmit queue HRLM B,CHXXMQ SKIPN B SETZM CHXXMQ ;Queue empty now CONO PI,PION HRROS B,-2(A) ;Mark it not on transmit list AOJN B,CHXBK6 ;And unless it is on send list PUSHJ P,CHABRT ;Return it to free CHXBK6: SETZM CHOSTA ;Transmitter idle, look for next packet CHXBK7: HLRZ A,CHXXMQ ;Anything queued for transmission? JUMPE A,CHXBK9 ;No, leave interrupts disabled AOS CHOSTA ;Count retransmissions MOVE T,CHXCSR ;Reset transmitter IORI T,%CATDN IOWRI T,CAICSR HRLI A,-%CPKDT ;Transmit header CHXXM1: UNPK16 B,(A) IOWRI B,CAIWBF IOWRI C,CAIWBF AOBJN A,CHXXM1 PUSHJ P,CHSHDR ;Decode the header JRST CHXXM4 ;No byte swapping JUMPGE D,CHXXM3 CHXXM2: UNPK8 B,(D) ;Transmit data with byte swapping IOWRI B,CAIWBF IOWRI C,CAIWBF AOBJN D,CHXXM2 CHXXM3: JUMPGE H,CHXXM7 ;Jump if even packet length UNPK8 B,(D) ;Transmit residual bytes IOWRI B,CAIWBF JRST CHXXM7 CHXXM4: JUMPGE D,CHXXM6 CHXXM5: UNPK16 B,(D) ;Transmit data with byte swapping IOWRI B,CAIWBF IOWRI C,CAIWBF AOBJN D,CHXXM5 CHXXM6: JUMPGE H,CHXXM7 ;Jump if even packet length UNPK16 B,(D) ;Transmit residual bytes IOWRI B,CAIWBF CHXXM7: LDB T,[$CPKDN(A)] ;Get destination subnet HRRZ D,SBNRUT(T) ;Gateway to that subnet CAIGE T,NSUBNT CAIN T,MYCHAD_-8 ;If on local cable, LDB D,[$CPKDA(A)] ; go direct IOWRI D,CAIWBF ;Store hardware destination address IORDI T,CAIXMT ;Transmit packet CHXBK8: MOVEI A,%CATEN ;Enable transmit-done interrupt if xmitting CHXBK9: IORI A,%CAREN ;Enable receive-done interrupt always IORB A,CHXCSR IOWRI A,CAICSR MOVSI 17,CHXACS ;Dismiss software interrupt BLT 17,17 JRST 12,@CHXBRK CHXBK2: PUSHJ P,CHABRT ;Packet no good, discard it JRST CHXBK1 ;Examine packet in A, return AOBJN pointer to data in D, ; H is negative if there is an extra halfword after that. ; W gets number of full words of data (same as LH D). ; T,U get clobbered ; Returns: ; +1 16-bit data ; +2 8-bit data CHSHDR: HRRZI A,-%CPKDT(A) ;Restore packet address LDB W,[$CPKNB(A)] ;Get size of packet in bytes CAILE W,%CPMXC MOVEI W,%CPMXC ;Self-defense ADDI W,1 ;Round up to next word boundary LSHC W,-2 ;Convert bytes to words, H gets remainder HRLOI D,-1(W) ;Make AOBJN pointer EQVI D,%CPKDT(A) LDB T,[$CPKOP(A)] ;Does this packet need byte swapping? TRNE T,200 JRST [ TRNN T,100 AOS (P) ;Character data POPJ P, ] ;Binary data IDIVI T,40 MOVE T,CHSWBT(T) LSH T,(T+1) JUMPL T,CPOPJ ;Binary control packet JRST POPJ1 ;Characters CHSWBT: 1_<35.-%COOPN>+1_<35.-%COSTS>+1_<35.-%CORUT> 0 ? 0 ? 0 ];CH11P SUBTTL CHAOS NET BUFFER LIST STUFF OVHMTR CHL ;BUFFERS ARE PKTBSZ WORDS LONG; 2 HEADER WORDS AND %CPMXW PACKET WORDS. ;PKTBSZ IS A POWER OF 2 AND LESS THAN 1K (MEMORY PAGE SIZE). ;NOTE THAT A BUFFER ADDRESS POINTS AT THE FIRST PACKET WORD ;AND THE HEADER WORDS ARE AT NEGATIVE ADDRESSES. ;FIRST HEADER WORD: -2(A) ; RH LIST THREAD FOR MOST LISTS, 0=END, -1=NOT ON LIST ; LH LIST THREAD FOR TRANSMIT LIST ;SECOND HEADER WORD: -1(A) ; TIME RECEIVED OR TIME PUT ON TRANSMIT LIST ; OR VALUE OF I FOR A PACKET ON THE LSN QUEUE ; ASCII/LUNCH/ FOR A PACKET ON THE FREE LIST ;I DO IT THIS WAY (PIOFF) TO AVOID HAVING TO PUSH AND POP PI STATUS, ;CONO PI,NETOFF CAN LOSE AT INTERRUPT LEVEL (MAINLY THE NETON LOSES) ;THESE ROUTINES TURN OFF INTERRUPTS MOMENTARILY SO THAT ;LISTS MAY BE SAFELY MANIPULATED. ;Q POINTS TO THE HEADER WORD OF A QUEUE, REMOVE THE FIRST ;THING AND RETURN IN A. (ZERO IF NONE) CLOBBERS T CHAQGF: CONO PI,PIOFF HLRZ A,(Q) ;GET FIRST JUMPE A,PIONJ ;EMPTY HRRZ T,-2(A) ;GET SECOND HRLM T,(Q) ;MAKE FIRST IFN FTRCHK,[ JUMPN T,PIONJ HRRZ T,(Q) CAIE T,(A) BUG PAUSE,[CHAOS LIST TRASHED],OCT,Q SETZM (Q) ;IS NOW EMPTY ];FTRCHK IFE FTRCHK,[ SKIPN T SETZM (Q) ;IS NOW EMPTY ];FTRCHK CONO PI,PION POPJ P, ;RETURN BUFFER INTO WHICH THE BYTE POINTER IN A POINTS. CLOBBERS A,T,Q CHBPFR: SUBI A,1 ;SIOKT LIKES TO MAKE BP POINT AT NEXT BUFFER ANDI A,-PKTBSZ ADDI A,2 JRST CHABRT ;RETURN BUFFER POINTED TO BY A TO FREE UNLESS ON TRANSMIT LIST. CHABR1: HLLOS T,-2(A) ;RH GETS -1, NO LONGER ON REGULAR LIST AOJN T,CPOPJ ;EXIT IF STILL ON TRANSMIT LIST ;DROPS THROUGH ;RETURN BUFFER POINTED BY A TO FREE STORAGE. CLOBBERS T, Q. CHABRT: MOVEI Q,CHQFRE IFN FTRCHK,[ SKIPN A BUG PAUSE,[FREEING 0] ];FTRCHK MOVE T,[ASCII/LUNCH/] ;TANSTAAFL MOVEM T,-1(A) SETOM -2(A) ;NOT ON TRANSMIT LIST NOW (THIS IS WHAT INITS AOS CHFRBF ; LH[-2(A)] WHEN BUFFER FIRST CREATED) ;JRST CHAQPL ;DROPS THROUGH ;A POINTS TO A BUFFER, Q TO A QUEUE. PUT IT ON AS THE LAST THING. BASHES T. CHAQPL: HLLZS -2(A) ;PUT ENDLIST IN RH CONO PI,PIOFF HRRZ T,(Q) ;GET LAST HRRM A,(Q) ;MAKE NEW LAST JUMPN T,[HRRM A,-2(T) ;MAKE A COME AFTER IT JRST PIONJ ] HRLM A,(Q) ;WAS EMPTY, ALSO IS NEW FIRST CONO PI,PION POPJ P, ;A POINTS TO A BUFFER, Q TO A QUEUE. PUT IT ON AS THE FIRST THING. SMASHES T. CHAQPF: CONO PI,PIOFF HLRZ T,(Q) ;GET FIRST HRRM T,-2(A) ;MAKE SECOND HRLM A,(Q) ;MAKE NEW FIRST SKIPN T HRRM A,(Q) ;WAS EMPTY, ALSO MAKE NEW LAST CONO PI,PION POPJ P, ;ALLOCATE A BUFFER AT MAIN PROGRAM LEVEL, TO A, MASHES T, TT, Q, B. CHABG0: PUSHJ P,UDELAY ;WAIT FOR MEMORY CHABGT: PUSHJ P,CHABGI JRST CHABG0 POPJ P, ;WIN ;ALLOCATE A BUFFER, RETURN POINTER TO IT IN A, SKIP. BLOWS AWAY T, TT, Q. ;NON-SKIP IF NO BUFFERS AVAILABLE. (DOESN'T MAKE NEW ONES IF FREE LIST EMPTY) CHABAL: MOVEI Q,CHQFRE PUSHJ P,CHAQGF JUMPE A,CPOPJ SETZM -1(A) ;NO LUNCH SOS CHFRBF JRST POPJ1 ;ALLOCATE A BUFFER TO A, MAKE NEW IF NONE FREE. OBLITERATES T,Q,B. ;NON-SKIP IF CAN'T GET MEMORY. (SUITABLE FOR CALLING FROM INT LEVEL) CHABGI: PUSHJ P,CHABAL ;TRY TO ALLOCATE A BUFFER FROM FREE LIST CAIA JRST POPJ1 ;WON, RETURN CONI PI,Q ;SAVE PI CHANNELS ON STATUS ANDI Q,177 CONO PI,UTCOFF ;MAKE THE WORLD SAFE FOR IOMQ MOVE B,CHTTBF CAIL B,CHMXBF ;MAKE SURE NOT TO USE UP ALL CORE JRST CHABG4 PUSHJ P,IOMQ ;GET 1K OF MEMORY JRST CHABG3 ;MEM NOT AVAILABLE, FAIL CONO PI,PICON(Q) ;WON, RESTORE PI STATUS MOVEI B,MUCHA DPB B,[MUR,,MEMBLT(A)] LSH A,10. ;ADDRESS OF 1K OF ALLOCATED MEMORY ADD A,[-<2000/PKTBSZ>,,2] ;-BUFFERS PER 1K,,OFFSET TO HEADER CHABG2: PUSHJ P,CHABRT ;PUT THEM ALL ON FREE LIST ADDI A,PKTBSZ-1 AOBJN A,CHABG2 MOVEI B,<2000/PKTBSZ> ;THIS MANY MORE BUFFERS HAVE BEEN CREATED ADDM B,CHTTBF JRST CHABGI ;NOW GO ALLOCATE ONE ;HERE IF CHAOS NET TRYING TO USE UP TOO MUCH CORE CHABG4: MOVE B,CHMXTM ;DON'T COMPLAIN TOO OFTEN ADDI B,60.*30. ;JUST ONCE A MINUTE CAMLE B,TIME JRST CHABG3 IFE CH10P, BUG CHECK,[CHAOS NET ATTEMPTING TO USE TOO MUCH CORE] IFN CH10P,[ CONI CHX,B BUG CHECK,[CHAOS NET ATTEMPTING TO USE TOO MUCH CORE, CONI=],OCT,B,[CONO=],OCT,CHXCNO,[CHOSTA=],OCT,CHOSTA ];CH10P MOVE B,TIME MOVEM B,CHMXTM CHABG3: CONO PI,PICON(Q) ;LOST, RESTORE PI STATUS POPJ P, ;AND TAKE ERROR RETURN ;FREE A WHOLE LIST OF BUFFERS, Q-> HEAD. DESTROYS A,T CHALFR: PUSHJ P,CHAQGF JUMPE A,CPOPJ PUSH P,Q PUSHJ P,CHABR1 ;FREE UNLESS STILL ON TRANSMIT LIST POP P,Q JRST CHALFR ;Q -> A TRANSMIT QUEUE, FLUSH ALL BUFFERS BELONGING TO INDEX I. ;CLOBBERS A,B,C,T CFLXMQ: PUSH P,Q CONO PI,NETOFF ;DON'T LET TRANSMIT LIST CHANGE (AT ALL) HLRZ A,(Q) ;HEAD OF TRANSMIT LIST JUMPE A,CFLXM3 MOVEI B,2(Q) ;B PREVIOUS PACKET, A CURRENT, C NEXT CFLXM1: HLRZ C,-2(A) ;GET THREAD TO NEXT IFN FTRCHK,[ CAIN C,-1 JRST 4,. ;CLAIMS NOT TO BE ON LIST? ];FTRCHK LDB T,[$CPKSX(A)] ;GET THIS PACKET'S INDEX CAME T,I JRST CFLXM2 HRLM C,-2(B) ;THREAD PREVIOUS TO NEXT HRROS T,-2(A) ;IF THIS BUFFER IS NOT ALSO ON SEND LIST, AOJN T,.+2 PUSHJ P,CHABRT ;RETURN IT SKIPA Q,(P) CFLXM2: MOVE B,A SKIPE A,C JRST CFLXM1 HRRM B,(Q) ;LAST PACKET ON LIST MAY HAVE CHANGED CAIN B,2(Q) SETZM (Q) ;TRANSMIT QUEUE IS NOW EMPTY CFLXM3: POP P,Q JRST NETONJ ;SEARCH LIST IN Q FOR PACKET WHOSE CONTACT NAME MATCHES THAT ;OF PACKET IN A, RETURN IT IN B, SKIPPING IF WINNING. CLOBBERS T,TT,C,D,E,H,J. ;THE PACKET RETURNED IN B IS DE-LINKED FROM THE SEARCHED QUEUE. ;HAS TO BE CALLED WITH NETOFF OR IN PROGRESS, SO LIST CAN'T GET MUNGED. ;I HOPE IT'S NOT TOO BLETCHEROUSLY SLOW. CHAQSR: HLRZ B,(Q) ;GET START OF LIST TO SEARCH JUMPE B,CPOPJ ;EMPTY, LOSE MOVEI J,0 ;PACKET PREVIOUS TO B CHAQS1: LDB C,[$CPKNB(A)] ;SET UP STRING COMPARE LOOP LDB H,[$CPKNB(B)] ;THIS ASSUMES NO ZERO-LENGTH STRINGS MOVEI D,%CPKDT(A) HRLI D,440800 MOVEI E,%CPKDT(B) HRLI E,440800 CHAQS2: ILDB T,D ILDB TT,E ;DON'T IGNORE CASE, THAT WOULD JUST SLOW THIS CAME T,TT ;BAG-BITER DOWN EVEN MORE. EVERYONE SHOULD JRST CHAQS4 ;PUT THEIR CONTACT NAMES IN UPPER-CASE. CAIN T,40 ;TERMINATE ON SPACE JRST CHAQS5 SOJLE C,CHAQS3 SOJG H,CHAQS2 ILDB T,D CAIE T,40 JRST CHAQS4 CHAQS5: HRRZ C,-2(B) ;WON, DELINK PACKET FROM LIST JUMPE J,[ HRLM C,(Q) JUMPN C,POPJ1 IFN FTRCHK,[ HRRZ C,(Q) ;CHECK LIST ENDING IN RIGHT PLACE CAIE C,(B) JRST 4,. ];FTRCHK SETZM (Q) JRST POPJ1 ] HRRM C,-2(J) JUMPN C,POPJ1 HRRM J,(Q) ;TOOK LAST PACKET, STORE NEW LAST JRST POPJ1 CHAQS3: SOJLE H,CHAQS5 ILDB TT,E CAIN TT,40 JRST CHAQS5 CHAQS4: MOVE J,B ;THIS ONE DOESN'T MATCH, TRY NEXT HRRZ B,-2(B) JUMPN B,CHAQS1 POPJ P, ;NO MATCHES ;THIS ROUTINE RUNS IN THE CORE JOB AND CLEANS UP MEMORY USED BY CHAOS BUFFERS ;SMASHES ALL ACS CHCLN: SKIPE A,CHTTBF ;SEE IF 2/3 OR MORE OF BUFFERS FREE SKIPN B,CHFRBF POPJ P, ;NO BUFFERS OR NONE FREE, NOTHING TO DO SUBM A,B IDIV A,B ;GET RATIO OF TOTAL TO USED CAIGE A,3 ;NOTE IF B IS ZERO A IS UNCHANGED POPJ P, ; AND AT LEAST 32. IFL TSYSM-256., MOVEI D,TSYSM-1 ;SCAN MEMORY FOR CHAOS BUFFER PAGES .ELSE MOVEI D,255. CHCLN0: LDB A,[MUR,,MEMBLT(D)] CAIE A,MUCHA CHCLN4: SOJGE D,CHCLN0 JUMPL D,CPOPJ MOVE A,D ;QUICKLY DETERMINE IF ANY NON-FREE BUFFERS LSH A,10. ; ON THIS PAGE HRLI A,-<2000/PKTBSZ> MOVE T,[ASCII/LUNCH/] CHCLN5: CAME T,1(A) JRST CHCLN4 ;NOT FREE, DON'T BOTHER WITH SLOW STUFF ADDI A,PKTBSZ-1 AOBJN A,CHCLN5 SETZB C,CHCLNQ ;COLLECT ALL FREE BUFFERS THAT ARE ON THIS PAGE MOVE E,CHFRBF ;LOOP ABOUT AS MANY TIMES AS THERE ARE FREE BUFFERS CHCLN1: PUSHJ P,CHABAL ;GET NEXT FREE BUFFER JUMPE A,CHCLN2 LDB B,[121000,,A] CAMN B,D JRST [ MOVEI Q,CHCLNQ ;THIS ONE'S ON THE PAGE, SAVE IT PUSHJ P,CHAQPL AOJA C,.+2 ] ;COUNT THEM PUSHJ P,CHABRT ;NOT ON THE PAGE, PUT BACK SOJG E,CHCLN1 CHCLN2: CAIE C,<2000/PKTBSZ> ;DID WE GET THE WHOLE PAGE? JRST [ MOVEI Q,CHCLNQ ? PUSHJ P,CHALFR ? JRST CHCLN4 ] MOVNS C ;YES, GET RID OF THESE BUFFERS ADDM C,CHTTBF MOVE A,D PUSHJ P,MEMR JRST CHCLN OVHMTR CHZ