;<134-TENEX>IMPDV.MAC;361 2-DEC-75 10:31:23 EDIT BY TOMLINSON ;<134-TENEX>IMPDV.MAC;360 2-DEC-75 10:22:37 EDIT BY TOMLINSON ;<134-TENEX>IMPDV.MAC;359 10-NOV-75 13:44:21 EDIT BY ALLEN ; INCREASE IMPNLK TO ^D200 ;<134-TENEX>IMPDV.MAC;358 26-OCT-75 11:48:06 EDIT BY TOMLINSON ;<134-TENEX>IMPDV.MAC;357 21-OCT-75 12:38:48 EDIT BY TOMLINSON ; MORE RCTE FIXUPS ;<134-TENEX>IMPDV.MAC;355 9-OCT-75 13:15:48 EDIT BY ALLEN ; MAKE SURE IMIB NOT ON FREELIST IN IMPEIN ;<134-TENEX>IMPDV.MAC;353 24-SEP-75 09:46:23 EDIT BY TOMLINSON ; DEFER OKINT IN NVTCOB 'TIL AFTER SENDING DATA MARK ;<134-TENEX>IMPDV.MAC;352 22-SEP-75 11:46:31 EDIT BY CLEMENTS ; On startup, (IMPRC1), only send RST's to hosts in name table. ;<134-TENEX>IMPDV.MAC;351 19-SEP-75 12:28:44 EDIT BY TOMLINSON ; MORE RCTE BUG FIXES ;<134-TENEX>IMPDV.MAC;350 17-SEP-75 14:55:18 EDIT BY TOMLINSON ;<134-TENEX>IMPDV.MAC;348 17-SEP-75 14:41:56 EDIT BY TOMLINSON ; RCTE BUG FIXES ;<134-TENEX>IMPDV.MAC;344 15-SEP-75 17:12:18 EDIT BY ALLEN ;<134-TENEX>IMPDV.MAC;343 15-SEP-75 16:39:45 EDIT BY ALLEN ; TEMPORARILY NOP'ED NVTCIB ;<134-TENEX>IMPDV.MAC;342 12-SEP-75 15:31:45 EDIT BY ALLEN ; ADD CHECKS TO BE SURE THAT WE NEVER LOCK OR UNLOCK A BUFFER ON THE ; FREELIST ;IMPDV.MAC;1 10-SEP-75 08:34:36 EDIT BY TOMLINSON ; RCTE FIXES ;<134-TENEX>IMPDV.MAC;336 5-SEP-75 15:48:23 EDIT BY ALLEN ; RESTORE ORIGINAL ACTIVATION CRITERIA ;<134-TENEX>IMPDV.MAC;335 5-SEP-75 15:38:54 EDIT BY ALLEN ;<134-TENEX>IMPDV.MAC;334 3-SEP-75 22:01:33 EDIT BY ALLEN ; NEW ACTIVATION LOGIC AND FIX INPUT BUFFER FETCH LOGIC ;<134-TENEX>IMPDV.MAC;333 28-AUG-75 16:32:26 EDIT BY ALLEN ; SLIGHT MOD DUE TO CHANGE IN LOCK-UNLOCK MACROS ;<134-TENEX>IMPDV.MAC;332 19-AUG-75 15:40:48 EDIT BY ALLEN ; REPAIR TO PKQOB TO STORE ACTUAL WORDS IN USE IN HEADER SO ; OUTPUT ROUTINES DON'T TRY TO SEND THE WHOLE BUFFER ;<134-TENEX>IMPDV.MAC;331 14-AUG-75 15:18:49 EDIT BY ALLEN ; ELIMINATE LOCKUP DUE TO RUNNING OUT OF BUFFERS ;<134-TENEX>IMPDV.MAC;330 12-AUG-75 17:07:12 EDIT BY ALLEN ; FIX AT PKMS5 TO KEEP PKMSG FROM GOING NUTS WHEN ASNTBF FAILS ;<134-TENEX>DCAIMP.MAC;9 6-AUG-75 11:19:35 EDIT BY ALLEN ; END INPUT ROUTINE RECORDS ACTUAL COUNT IN BUFFER HEADER ;<134-TENEX>DCAIMP.MAC;8 5-AUG-75 13:57:29 EDIT BY ALLEN ; Various bug fixes to new buffer management ;<134-TENEX>DCAIMP.MAC;7 4-AUG-75 10:46:05 EDIT BY ALLEN ; VARIOUS CHANGES FOR NEW BUFFER MANAGEMENT ;<134-TENEX>IMPDV.MAC;328 11-JUL-75 17:17:33 EDIT BY ALLEN ; MINOR FIX ;<134-TENEX>IMPDV.MAC;327 11-JUL-75 16:12:43 EDIT BY ALLEN ; DELETE CALL IMPKO1 AT PKMSD 4 ;<134-TENEX>DCAIMP.MAC;3 11-JUL-75 09:59:54 EDIT BY ALLEN ; PKMSG USES REMAINING SPACE IN CURRENT OUTPUT BUFFER UNLESS ; THIS WOULD CAUSE A CONTROL MESSAGE TO CROSS A NET MESSAGE BOUNDARY. ; PKMSG1 ADDED -- SAME AS PKMSG BUT DOESN'T ATTEMPT TO SEND THE ; CURRENT MESSAGE. CALLED BY NETTCS SO THAT SIZE OF NET MESSAGE ; IS NOW LIMITED ONLY BY AVAILABLE CHARACTERS IN TTY BUFFERS, ; BY ALLOCATION, OR BY SIZE OF OUTPUT BUFFER, NOT BY SIZE ; OF NETTCS' STACK BUFFER. ;<134-TENEX>IMPDV.MAC;326 15-MAY-75 07:51:23 EDIT BY TOMLINSON ; CHANGE REFERENCES TO NLINES TO NVTHI ;<134-TENEX>IMPDV.MAC;325 21-APR-75 11:34:59 EDIT BY TOMLINSON ; Limit special queues on message basis rather than buffer space ;<134-TENEX>IMPDV.MAC;324 14-APR-75 17:08:59 EDIT BY OPERATOR ; CORRECT INITIALIZATION OF IDVLCK ;<134-TENEX>IMPDV.MAC;323 14-APR-75 15:37:09 EDIT BY ALLEN ; AVOID SMASHING AC1 IN PIE-SLICE VERSION OF LCKID1 ;<134-TENEX>IMPDV.MAC;322 11-APR-75 17:08:19 EDIT BY ALLEN ; REPAIRS TO NEW LOCKING STUFF ;<134-TENEX>IMPDV.MAC;319 10-APR-75 22:18:40 EDIT BY ALLEN ; MAKE USE OF NEW SCHEDULING FOR LCKERS ;<134-TENEX>IMPDV.MAC;318 4-APR-75 18:00:19 EDIT BY CLEMENTS ; FIX TO PREVENT UNKNOWN LINK IMPBUGS IF REMOTE CLOSES A ; SEND SOCKET WHICH HAS AN OUTSTANDING RFNM ;<134-TENEX>IMPDV.MAC;317 12-MAR-75 14:08:45 EDIT BY PLUMMER ; CHANGE SIQCHK TO FLUSH ENTIRE Q IF NOT ACTIVE ;<134-TENEX>IMPDV.MAC;316 27-FEB-75 15:50:47 EDIT BY CLEMENTS ; INCREASE NUMBER OF CHARACTERS PROCESSED IN NETTCS FROM 32 TO 64 ; INCREASE SIZE OF PI-LEVEL STACK, DUE TO DEBUG ROUTINES ;<134-TENEX>IMPDV.MAC;315 10-JAN-75 10:32:56 EDIT BY ALLEN ; REPLENISH INPUT BUFFERS IF IMPNFI .LT. 8 ;<133-TENEX>IMPDV.MAC;314 24-DEC-74 08:32:56 EDIT BY TOMLINSON ; DISABLE RCTE UNTIL DEBUGGED THOROUGHLY ;<133-TENEX>IMPDV.MAC;313 18-DEC-74 15:40:48 EDIT BY TOMLINSON ;<133-TENEX>IMPDV.MAC;312 17-DEC-74 16:17:00 EDIT BY TOMLINSON ; CAUSE INITIAL SB STRING FOR RCTE ;MISC BUG FIXES TO RCTE ;<133-TENEX>IMPDV.MAC;311 16-DEC-74 15:50:14 EDIT BY TOMLINSON ; TAKE OUT CODE TO TURN ON RCTE IN ASNNVT. CAN'T DO IT BECAUSE NCPLCK IS SET. ;<133-TENEX>IMPDV.MAC;309 13-DEC-74 12:41:16 EDIT BY TOMLINSON ; INITITATE TURN ON OF RCTE AND SUPPRESS GA ;<133-TENEX>IMPDV.MAC;308 13-DEC-74 12:32:18 EDIT BY TOMLINSON ; BUG FIXES TO RCTE ; PKBY1: MOVE SOS IMPLT4 TO AFTER ASNTBF CALL ; UPBRB: CHANGE BUG MSG ; IM8RAS: ACCOUNT FOR BUFFERS IN CONNECTION QUEUE WHEN RESETTING ALLOC ;<133-TENEX>IMPDV.MAC;306 8-DEC-74 18:28:13 EDIT BY CLEMENTS ; FIX MISSING EXTERN ON SKPRET ;<133-TENEX>IMPDV.MAC;303 3-DEC-74 10:25:14 EDIT BY TOMLINSON ; Added RCTE code ;<133-TENEX>IMPDV.MAC;300 29-OCT-74 08:22:03 EDIT BY TOMLINSON ; SET UP STACK FOR BUG(IMP) AT IMIMTL ;<133-TENEX>IMPDV.MAC;299 1-OCT-74 13:16:36 EDIT BY TOMLINSON ; REMOVE SUPERFLUOUS INSTRINCTION AT IMPRAP+2 ;<133-TENEX>IMPDV.MAC;298 25-SEP-74 12:47:56 EDIT BY TOMLINSON ; (1) MARK HOST USING NEW PROTOCOL AS UNDERSTANDING SAME. ; (2) RELEASE BOTH HALVES OF AN NVT WHEN RECEIVING NXS/R ; (3) FIX BUGIMH ARG IN BADLKS/R ; (4) BUGCHK IF IMPLT4 IS OVERDECREMENTED IN UPBRB ;<133-TENEX>IMPDV.MAC;297 22-AUG-74 16:28:54 EDIT BY CLEMENTS ;IMPDV.MAC;296 22-JUN-74 13:07:40 EDIT BY TOMLINSON ; NOP IMPCHK IF IMPRDY = 0 SEARCH PROLOG IFDEF IMPCHN,< ; This whole file is included only if imp exists TITLE IMPDV SEARCH STENEX ; Accumulators IMPUN==5 ; Ac for 'unit' ; Parameters IMPNLK==^D200 ; Size of link table IMP8XS==40 ; Size of irreg mes buffer NSQ==8 ; Size of special q tables SIQMAX==6 ; Maximum messages allowed on siq NIMSTK==20 ; Pi level stack IMPLBT==400/^D36+1 ; Size of bit tables for host states CLINK==0 ; Control link FLINK==2 ; First link to use LLINK==^D72 ; Last link to use RFNTMO==^D20000 ; Rfnm time-out interval (three of these) UPROBI==^D300000 ; Interval at which to probe every up host UPROBT==^D60000 ; Time to spend probing every down host SIQTM0==^D30000 ; Special queue time-out interval NEGTM0==^D30000 ; Negotiation time-out (between 1 & 2 of these) ; NVT special characters IACCH==377 ; Initiate command DNTCH==376 ; DON'T DOCH==375 ; DO WNTCH==374 ; WON'T WILCH==373 ; WILL SBCH==372 ; SB beginning of sub negotiation GACH==371 ; GA go ahead ELCH==370 ; EL erase line ECCH==367 ; EC erase character AYTCH==366 ; AYT are you there? AOCH==365 ; AO abort output IPCH==364 ; IP interrupt process BRKCH==363 ; BREAK DMCH==362 ; DM data mark NOPCH==361 ; NOP SECH==360 ; SE end of subnegotiation ; Nvt option definitions BINOPT==0 ; Binary ECHOPT==1 ; Echo RCNOPT==2 ; Reconnection SGAOPT==3 ; Suppress ga NAMOPT==4 ; Negotiate message size STSOPT==5 ; Status TMKOPT==6 ; Timing mark option RCTOPT==7 ; RCTE option WILOPT==10 ; Offset for requests MAXOPT==^D18 ; Only 1 half word of option bits ; Bits in ttnetw NVTCRP==1 ; Bit in ttnetw -- last char out was cr IMPTB2==2 ; Bit in ttnetw, last char in was cr NVTGAB==4 ; Bit in ttnetw -- suppress go-ahead ; Bits 12-14 used for nvtstp NEGTMO==100 ; Negotiation time-out started NEWNVB==200 ; New style nvt NVTRCS==1000 ; RCTE CHAAGE IN STATE NVTWKS==2000 ; RCTE WAKEUP SEEN ; The following nvt states are stored in ttnetw bits 12-14 (nvtstp) DFRWIL==1 ; Deferred will DFRWNT==2 ; Deferred wont DFRDO==3 ; Deferred do DFRDNT==4 ; Deferred dont DFRIAC==5 ; Deferred iac ; Imp message leader bits IMPHIP==1B0 ; Hi priority imp msg leader bit FRMIMP==1B1 ; From imp ; Bits in implt2 RFNMC=3B1 ; Rfnm outstanding (2 bit count) LTDF=1B2 ; 'done' flag HIPFLG=1B3 ; High priority connection ILCKB==1B4 ; Connection locked (no transmissions) RXMTF==1B5 ; Retransmission after time-out RARF==1B6 ; Rar expected RARRF==1B7 ; Send ras whe no rfnm's out ; Cono-coni bits IMP=550 IMPINB==1B32 ; Input word ready IMPOUB==1B28 ; Ready for next output word IMPEIB==1B24 ; End of input IMPGEB==1B23 ; Clear eib IMPEOB==1B22 ; End of output IMPSTO==1B21 ; Stop output IMPIOF==10B27+10 ; E of cono to clear input pi asmt IMPION==<10+IMPCHN>B27+<10+IMPCHN> ; E of cono to set input pi asmt IMPOOF==10B31 ; E of cono to clear output assmnt IMPOON==<10+IMPCHN>B31 ; E of cono to set output pi asmt ; Pointers to various fields PTNETI: POINT 9,TTNETW(2),35 ; Input unit PTNETO: POINT 9,TTNETW(2),26 ; Output unit PTINTC: POINT 3,TTNETW(2),5 ; Count, sync-ins NVTSTP: POINT 3,TTNETW(2),14 ; Current nvt state PBRCNT: POINT 9,TTBRKC(2),8 ; OUTSTANDING BREAKS COUNT MAXBRC==777 IMPLBS: POINT 8,IMPLT2(1),17 ; Connection byte size LTHOST: POINT 8,IMPLT1(1),27 ; Foreign host LTLINK: POINT 8,IMPLT1(1),35 ; Link MAXWPM: 400 ; Max wds/input msg = (8000/32) + ovhd + slop = ; 250 + 3 + 3 = 256 = 400(8) ; Following two are a getab table - don't separate NLHOST: LHOSTN ; All references to lhostn should be to this cell, ; So it can be patched if needed. NVTPTR: XWD -NNVTLN,NVTLO ; -number of nvt's,,first nvt ; End of getab group ; Linkage into impdv INTERN IMPBEG,IMPNLK,IMPLBT,CHKNET,NVTDOB,NVTCOB,NVTPAR,NTTCSO,NETCAP INTERN IMPHLT,NVTRCC INTERN NVTCHO,NVTXCR,NVTXGA,NVTMOD INTERN IMPSV,IMPCHK,IMPOPL,IMPCLL,IMPABL,IMPSYN,IMPRTS,IMPSTR,IMPCLS,IMPALL INTERN ASNNVT,NVTDET,TTNETW INTERN .ASNSQ,.RELSQ,.SNDIM,.RCVIM INTERN IMPRST,IMPRRP,IMSRST,IMPERR,IMPINR,IMPINS INTERN HSTDED,IMPBG0,NTTRC3 INTERN IMPSDB,PKBYT,PKCHK,PKULCK,PKMSG,UPBYT,UPMSG,MAXWPM,NLHOST,NVTPTR INTERN PTNETI,PTNETO ; Linkage to swpmon EXTERN CHKBG1,CHKH1 ; Linkage to forks EXTERN CAPENB,LSTERR ; Linkage to pisrv EXTERN MENTR,CHNSON,BUGCHK,BUGNTE,BUGHLT,MRETN,SKMRTN ; Linkage to ttysrv EXTERN TTOCT,TTECT,TTICT,TTCHI,TTYLMD,TTFORK,NVTCOF,TTPSI,TTCOBI,TTCIBF EXTERN TTRLOB,TTOOUT,TTEOUT,WRPMSK,TTIMAX,TTOMAX,TCOB,TCOBQ,TTFLGS EXTERN TCOTST ; Linkage to scheduler EXTERN EDISMS,FORKX,JB0FLG,DISNT,ITRAP,IMPTM2 ; Miscellaneous EXTERN BHC,BITS,R,RSKP EXTERN BYTBLT EXTERN NETBUF EXTERN MAXBPM EXTERN RECRTS,RECSTR,RECCLS,DISG,PFHST,PLINK,EOTF,DEDF,NVTCLZ EXTERN NETSTS,RLNTBF,ASNTBF,MULKMP,RCFRFN,MLKMA EXTERN SK2DWN EXTERN ERRB,NETDWN,NETHDN,NETCHK,HOSTN,NHOSTS,DISGT EXTERN RECRST,NETBAL,NETRAL,RECINR,RECINS,PLIDX,DISL,SVCINT,SVCRST EXTERN LCKNCP,ULKNCP EXTERN JOBRTT,TODCLK ; Macros ; Lock imp device lock DEFINE ILOCK (A) < CALL LCKIDV IFB ,<0> IFNB, > ; Unlock imp device lock DEFINE IUNLK < CALL ULKIDV> ; Call clock switch code DEFINE IMSCLK(CLOCK)< MOVEI 1,CLOCK CALL IMUCLK> ; Storage ; First impgtn are a getab table - don't separate LS IMPRDY,1 ; 0=down, .gtr. 0 =going down, -1=up LS NETON,1 ; 0=network off LS NETENT,1 ; Flags to drive netser. e.g., don't allow login LS NCPUPT,1 ; Gtad of last time ncp cycled up. LS IGDMSG,1 ; Most recent imp-going-down msg LS IMPDNT,1 ; Time of last imp ready line drop LS IMPUPT,1 ; Time of last imp ready line up LS IGDTIM,1 ; Time of above imp-going-down msg IMPGTN==:8 ;LENGTH OF THIS GETAB TABLE ; End of getab group LS IMPORD,1 ; Output ready. non-zero permits outgoing msgs LS IMPRDL,1 ; Ready line noticed off LS IMPRDT,1 ; Todclk when ready line first went off LS IMPFLG,1 ; Service needed by async process LS NCPFRK,1 ; Forkx of ncp fork LS TTNOF,1 ; Scan of net tty lines requested if non-0 LS IMPNOS,1 ; Output scan request flag LS IDVLCK,1 ; Local lock LS IDVLLK,1 ; Last idvlck locker LS IMPDRQ,1 ; Reset cycle requested in non-0 LS NETTCH,1 ; State of net has changed if non-0 LS IMPFRI,1 ; List of free input buffers LS IMPNFI,1 ; Count of free input buffers LS IMPNIB,1 ; NUMBER OF INPUT BUFFERS TO KEEP ON TAP LS SIQIBI,NSQ ; Special queue LS SIQIBO,NSQ LS SIQTIM,NSQ ; Time of first message on special queue LS SIQSPC,NSQ ; Space occupied by special input q LS SQJOB,NSQ ; Job to which special q is assigned LS SQVAL,NSQ ; Value to compare against for mux special q LS SQMSK,NSQ ; Mask to use in compare LS SQLCK,1 ; Interlock for assigning special q LS IMPIBI,1 ; In buffers in ptr LS IMPIBO,1 ; In buffers out ptr LS IMPOBI,1 ; Output buffers in pointer LS IMPOBO,1 ; Output buffers out pointer LS IMPHBI,1 ; Hi priority output buffers in pointer LS IMPHBO,1 ; Hi priority output buffers out pointer LS IMIB,1 ; Current in bfr, pi level LS IMPOB,1 ; Buffer now being emptied by pi routine LS IMPINP,1 ; Blki pointer on input LS IMPOUP,1 ; Blko pointer LS IMIDSP,1 ; Input pi dispatch LS IMODSP,1 ; Output pi dispatch LS IMINFB,1 ; Buffers made free by pi routines ; Storage continued LS IMPNCL,1 ; Number of control input conns LS IMPNOL,1 ; Number of control output conns LS LNKNDL,1 ; Number of deletes in link table LS IMIS32,1 ; Input repacking state word LS IMOS32,1 ; Output repacking state word LS IMPSVX,1 ; Pi service return LS IMPTIM,1 ; Time of next clock run down LS IBPTIM,1 ; Time of next impibp run LS NETTIM,1 ; Time of next check of fsm for hangs LS RFNTIM,1 ; Time of next check for lost rfnm's LS NEGTIM,1 ; Negotiation time-out clock LS IMPCHU,1 ; 0 if current control mess host not up LS IMPCHO,1 ; Host number of control msg, must precede i8cal LS I8CAL,5 ; Args of control operation, must follow impcho LS IMPFLS,1 ; Count (neg) of messages to flush LS NOPCNT,1 ; Count of nops left to send LS IMPGDM,1 ; Last imp going down msg LS HSTGDM,1 ; Current host going down message LS IMPCCH,1 ; Index to host number for periodic check LS IMP8XI,1 ; Irreg mes buffer in ptr LS IMP8XO,1 ; .. .. out LS IMP8XC,1 ; .. .. count LS IMP8XB,IMP8XS ; Irreg mes buffer LS IMPHRT,IMPLBT ; Host ready bits LS HSTSTS,200 ; Dead host status table (18 bits per host) LS IMPHCT,IMPLBT ; Recent message sent IFDEF POLLF, ; Hosts which have gone down IFDEF POLLF, ; State of hrt at last log tty report LS IMPBGC,1 ; Impbug count LS IMPBGH,1 ; Host involved in last impbug LS BADHMS,1 ; Message associated with header below LS BADHDR,2 ; Header of last funny message received LS BUGIMP,1 ; Impbug w/o host LS IMPBHT,IMPLBT ; 'bad' host table LS NWPBT,IMPLBT ; BIT TABLE OF HOSTS USING RAR/RAS ETC. LS IMPIAC,5 ; Pi level ac storage LS IMSTK,NIMSTK ; Pi level stack LS IMINP,1 LS TTNETX,NNVTLN ; Stuff for nvt's LS TTBRKX,NNVTLN ; BREAK CLASSES FOR NVT'S TTNETW= ; Relative to 0 TTBRKC= ; RELATIVE TO 0 ; BITS 0-8: OUTSTANDING BREAK COUNT ; BITS 9-17: LAST RCTE COMMAND SENT ; BITS 18-35: LAST BREAK CLASSES SENT LS NVTOPX,NNVTLN ; Lh -- bit for each option in progress ; Rh -- bit for result of each option NVTOPF= ; Relative to 0 ; Time accumulators LS IMCCLK,1 ; Run time of last check LS IMCLST,1 ; Pointer to current clock LS IMCIDL,1 ; Time spent idling LS IMCNRB,1 ; Time spent releasing spent buffers LS IMCGC,1 ; Time spent garbage collecting link tables LS IMCGIB,1 ; Time spent assigning input buffers LS IMCCNP,1 ; Time spent processing control messages LS IMCP1,1 ; Time spent dispatching input messages LS IMC8XM,1 ; Time spent processing irregular messages LS IMCTS,1 ; Time spent scanning for nvt output LS IMCNVI,1 ; Time spent unpacking nvt input LS IMCOS,1 ; Time spent scanning for output to do LS IMCNCK,1 ; Time spent probing network LS IMCRFN,1 ; Time spent checking overdue rfnm's LS IMCNCC,1 ; Time spent in ncp checks LS IMNIDL,1 ; Count of idling LS IMNNRB,1 ; Count of releasing spent buffers LS IMNGC,1 ; Count of garbage collecting link tables LS IMNGIB,1 ; Count of assigning input buffers LS IMNCNP,1 ; Count of processing control messages LS IMNP1,1 ; Count of dispatching input messages LS IMN8XM,1 ; Count of processing irregular messages LS IMNTS,1 ; Count of scanning for nvt output LS IMNNVI,1 ; Count of unpacking nvt input LS IMNOS,1 ; Count of scanning for output to do LS IMNNCK,1 ; Count of probing network LS IMNRFN,1 ; Count of checking overdue rfnm's LS IMNNCC,1 ; Count of ncp checks ; Link tables LS IMPLT1,IMPNLK ; Lh -- UNIT (INDEX TO NCP TABLES) ; OR -1 IF CONTROL LINK ; B18-19/00 -- receive ; 10 -- SEND ; 11 -- FREE ; 01 -- DELETED ; B20-27 -- host ; B28-35 -- link LS IMPLT2,IMPNLK ; B0-b5 -- flags ; B5-9 -- unused ; B10-17 -- byte size ; Rh -- in bfr ptr LS IMPLT3,IMPNLK ; Lh -- out bfr ptr ; Rh -- save message for retransmission LS IMPLT4,IMPNLK ; Lh -- CURRENT BUFFER ; Rh -- MSG ALLOCATION ; Pi dispatch IMPSV: XWD IMPSVX,.+1 CONSO IMP,7 ; Input turned off? JRST IMPSV1 ; Yes CONSZ IMP,IMPINB JRST @IMIDSP ; Word in CONSZ IMP,IMPEIB JRST [ CONSO IMP,IMPINB; It can happen that last input came in JRST IMPEIN ; Within the last few instructions JRST @IMIDSP] ; If so, handle it first IMPSV1: CONSZ IMP,7B31 ; Do nothing if no channel assigned CONSO IMP,IMPOUB JRST @IMPSVX ; N.o.t.a SKIPE IMPOB JRST @IMODSP ; Word out CONO IMP,IMPSTO JRST @IMPSVX IMPCHK: MOVEI 2,^D1000 MOVEM 2,IMPTM2 ; Call this every second SKIPN IMPRDY ; Net on? RET ; NO. CONSZ IMP,1B19 ; Power not on CONSZ IMP,1B21!1B20 ; Or error flop on, or host not ready? SKIPL IMPRDT ; And not already noticed? RET CALL IMIERR ; Be sure it's noticed AOS IMPFLG ; No, cause running of ncp fork RET ; Called by periodic check routine SWAPCD CHKNET: IFDEF POLLF,< ; Do this printout only if pollf is dfnd MOVSI 5,-IMPLBT ; Setup to scan host bit tables CHKN2: MOVE 3,IMPHL1(5) ; Bit set if host has gone down since lst JFFO 3,[MOVE 3,BITS(4) ; Found one ANDCAM 3,IMPHL1(5) ; Reset bits ANDCAM 3,IMPHL2(5) HRROI 1,[ASCIZ /HOST /] PSOUT ; Report downage MOVEI 1,101 MOVEI 2,0(5) ; Compute host number IMULI 2,^D36 ADDI 2,0(4) MOVEI 3,^D8 ; Octal for nout CVHST ; Type host name if any, NOUT ; But if that fails, type number JFCL HRROI 1,[ASCIZ / DOWN /] PSOUT JRST CHKN2] MOVE 3,IMPHL2(5) ; State of hosts as reported XOR 3,IMPHRT(5) ; Compare with state from ncp JFFO 3,[MOVE 3,BITS(4) ; Found a difference XORM 3,IMPHL2(5) ; Update logged table HRROI 1,[ASCIZ /HOST /] PSOUT ; Report change on log tty MOVEI 1,101 MOVEI 2,0(5) ; Compute host number IMULI 2,^D36 ADDI 2,0(4) MOVEI 3,^D8 ; Octal for nout CVHST ; Type host name NOUT ; Or host number JFCL MOVE 3,BITS(4) HRROI 1,[ASCIZ / UP /] TDNN 3,IMPHL2(5) HRROI 1,[ASCIZ / DOWN /] PSOUT JRST CHKN2] AOBJN 5,CHKN2 ; Scan tables > ; End of ifdef pollf at chknet SKIPE BUGIMP CALL CHKN1 ; Yes SKIPE NETTCH ; Change of state? CALL CHKN5 ; Yes SKIPE IMPGDM ; Any "imp going down" messages? CALL CHKN7 ; Yes, go print it RET ; Log network change of state CHKN5: HRROI 1,[ASCIZ / ***** NETWORK /] PSOUT HRROI 1,[ASCIZ /ON/] SKIPN NETON HRROI 1,[ASCIZ /OFF/] PSOUT HRROI 1,[ASCIZ /, IMP /] PSOUT HRROI 1,[ASCIZ /ON/] SKIPN IMPRDY HRROI 1,[ASCIZ /OFF/] PSOUT MOVEI 1," " PBOUT CONI IMP,2 SETZM NETTCH CALL CHKH1 ; Go print coni word and tod RET ; Log impbug/imhbug CHKN1: HRROI 1,[ASCIZ / ***IMPBUG /] PSOUT MOVEI 1,101 MOVEI 3,^D10 MOVE 2,IMPBGC NOUT JFCL HRRZ 2,IMPBGH ; Host number if any JUMPE 2,CHKN4 ; None HRROI 1,[ASCIZ / HOST /] PSOUT MOVEI 1,101 MOVEI 3,^D8 CVHST ; Type host name or number NOUT JFCL CHKN4: HLRZ 2,IMPBGH ; Status if any JUMPE 2,CHKN3 ; None HRROI 1,[ASCIZ \ STS/LINK \] PSOUT MOVEI 1,101 MOVEI 3,10 NOUT ; Print status in octal JFCL CHKN3: SKIPN 4,BADHMS ; Any header to print JRST CHKN8 ; No HRROI 1,[ASCIZ / HEADER: /] PSOUT MOVE 5,[POINT 4,BADHDR] MOVEI 1,101 MOVEI 3,10 CHKN8L: ILDB 2,5 ROT 2,4 ILDB 6,5 IOR 2,6 NOUT JFCL CHKN8: MOVEI 2," " BOUT SOJG 4,CHKN8L HRROI 1,[ASCIZ /AT /] PSOUT SOS 2,BUGIMP ; Back pc up to point at jsr SETZM BADHMS SETZM BUGIMP SETZM IMPBGH CALL CHKBG1 ; Print address and message RET ; Broadcast imp going down message CHKN7: HRROI 1,1(P) ; Buffer on pdl ADD P,[20,,20] HRROI 2,[ASCIZ /IMP GOING DOWN FOR /] SETZ 3, SOUT LDB 2,[POINT 10,IMPGDM,31] IMULI 2,5 MOVEI 3,^D10 NOUT JFCL HRROI 2,[ASCIZ / MIN IN /] SETZ 3, SOUT LDB 2,[POINT 4,IMPGDM,21] MOVEI 3,^D10 IMULI 2,5 NOUT JFCL HRROI 2,[ASCIZ / MIN DUE TO /] SETZ 3, SOUT LDB 2,[POINT 2,IMPGDM,17] HRRO 2,[[ASCIZ /PANIC /] [ASCIZ /SCHED HDWRE PM /] [ASCIZ /SOFTWRE RELOAD /] [ASCIZ /EMRGNCY RESTRT /]](2) SOUT HRROI 2,-17(P) SETO 1, TTMSG SUB P,[20,,20] SETZM IMPGDM RET RESCD ; Routines to make footprints for debugging ; Take imp footprints jsys ; Call: 1 ; Jfn of output file ; 2 ; Word count (stops at first opportunity past this) ; 3 ; Re-init flag (non-zero to reset pointers) .DBGIM::JSYS MENTR HRRZS 1 ; Don't allow byte pointers MOVEI 4,WHEEL!NETWIZ TDNN 4,CAPENB JRST MRETN JUMPE 3,DBGIM0 ; Skip init stuff NOSKED SETZM DBGNWD SETZM DBGSP SETZM DBGFAC OKSKED SETZM DBGRP AOS DBGRP ; Point at first word DBGIM0: PUSH P,2 ; Save count on stack PUSH P,1 DBGDBL: SKIPG 3,DBGNWD JRST DBGDBW MOVEI 4,DBGNBF SUB 4,DBGRP ; Space to end of buffer CAMGE 3,4 MOVEM 3,4 ; Keep min MOVN 3,4 MOVE 2,DBGRP ADD 2,[POINT 36,DBGBUF] SOUT MOVN 3,4 ADDM 3,DBGNWD ADDB 4,DBGRP CAIL 4,DBGNBF SETZB 4,DBGRP ADDB 3,-1(P) ; Count words written JUMPG 3,DBGDBL ; Continue if still .gr. 0 UMOVEM 3,3 ; Else return updated count SUB P,BHC+2 JRST SKMRTN DBGDBW: MOVEI 1,DBGNWD PUSHJ P,DISG MOVE 1,0(P) JRST DBGDBL ; Variables DBGNBF==2000 LS(DBGFAC,1) ; Failure counter LS(DBGSP,1) ; Store pointer LS(DBGRP,1) ; Read pointer LS(DBGNWD,1) ; Number of words in buffer NGS(DBGBUF,DBGNBF) ; Buffer ; Stash input irregular msg DBGIIM: PUSH P,2 MOVEI 2,1 DBGSIM: PUSHJ P,DBGCKS ; Check for space JRST DBGXIT PUSHJ P,DBGS2B MOVE 2,1 PUSHJ P,DBGS1B DBGXIT: OKSKED POP P,2 POPJ P, DBGIM: PUSH P,2 MOVE 2,1(1) TDNE 2,[377B23] SKIPA 2,[3] HRRZ 2,0(1) DBGSM: SOS 2 PUSHJ P,DBGCKS JRST DBGXIT PUSH P,1 PUSHJ P,DBGS2B MOVNI 1,0(2) HRLZS 1 HRR 1,0(P) DBGSLP: MOVE 2,1(1) PUSHJ P,DBGS1B AOBJN 1,DBGSLP POP P,1 JRST DBGXIT DBGOM: PUSH P,2 MOVE 2,1(1) TLNE 2,(17B7) JRST [ HRROI 2,2 JRST DBGSM] TDNE 2,[377B23] SKIPA 2,[-1,,3] HRRO 2,0(1) JRST DBGSM ; Record impbug DBGBG1: PUSH P,2 MOVEI 2,1 CALL DBGCKS JRST DBGXIT MOVE 2,1 HRLI 2,3 CALL DBGS2B MOVE 2,0(P) CALL DBGS1B JRST DBGXIT ; Store header word and time stamp DBGS2B: PUSHJ P,DBGS1B PUSH P,2 EXCH 1,2 GTAD EXCH 1,2 PUSHJ P,DBGS1B POP P,2 POPJ P, ; Store 1 word in debug buffer DBGS1B: PUSH P,1 AOS 1,DBGSP CAIL 1,DBGNBF SETZB 1,DBGSP MOVEM 2,DBGBUF(1) AOS DBGNWD POP P,1 POPJ P, ; Check for sufficient space to make new entry DBGCKS: SKIPE DBGFAC ; Any intervening failures? AOJA 2,DBGCK2 ; Yes DBGCK1: PUSH P,1 NOSKED MOVE 1,DBGNWD ADDI 1,2(2) CAIG 1,DBGNBF AOSA -1(P) AOS DBGFAC POP P,1 DBGCK3: POPJ P, DBGCK2: PUSHJ P,DBGCK1 SOJA 2,DBGCK3 EXCH 2,DBGFAC HRLI 2,1 PUSHJ P,DBGS1B SOS 2,DBGFAC SETZM DBGFAC POPJ P, ; Imp asynchronous process ; Started once, call from rundd IMPBEG: MOVSI 1,(1B1) ; Create fork of job 0 CFORK BUG(HLT,) MOVEI 2,IMPBP0 MSFRK ; Start fork in monitor RET ; Init IMPBP0: MOVSI 1,UMODF ; Establish usual jsys context MOVEM 1,FPC JSYS MENTR MOVE 1,FORKX MOVEM 1,NCPFRK MOVE 1,[XWD ITFPC,IMPUXI] MOVEM 1,MONBK ; Trap any interrupts MOVE 1,CHNSON MOVEM 1,MONCHN MOVEI 1,NINBFS MOVEM 1,IMPNIB ;INIT NUMBER OF BUFFERS TO KEEP ON TAP IFE PIESLC,< MOVEI 1,202 MOVEM 1,JOBBIT > IFN PIESLC, ;NCPFRK GETS SPECIAL QUEUE CALL IMPINI MOVEI 1,2 MOVEM 1,IMCLST ; Make last clock be dummy (ac 2) IMPBP1: IMSCLK(IMCIDL) ; Start charging time to imcidl PUSH P,[IMPBP1] ; Return for following dispatches SETZM IMPFLG ; Clear request flag CALL IMPSTT ; Check state of net and imp JRST IMPBP3 ; Down SKIPE IMINFB ; Garbage buffers to release? JRST IMINRB ; Yes MOVE 1,LNKNDL ; Deletes in link table CAIL 1,IMPNLK/2 ; Time for gc? JRST IMPGC ; Yes SKIPE IMPNCL ; Control msgs for processing? JRST IMPCN0 ; Yes SKIPE IMPIBO ; Input buffers ready? JRST IMIP1 ; Yes SKIPE IMP8XC ; Irreg msgs for processing? JRST IMP8XM ; Yes SKIPE TTNOF ; Scan of net ttys requested? JRST IMPTS ; Yes MOVE 1,IMPNFI CAMGE 1,IMPNIB ; NEED INPUT BUFFERS? CALL IMPGIB ; Yes SKIPE IMPNOS ; Need output scan? CALL IMPOS ; Yes IMSCLK(IMCIDL) ; Back to imcidl for charging IMPBP2: MOVE 1,TODCLK CAML 1,IMPTIM ; Time for local checks? JRST NETCH0 ; Yes CAML 1,RFNTIM ; Time for overdue rfnm check? JRST RFNCHK ; Yes CAML 1,NETTIM ; Time for netwrk checks? JRST [ IMSCLK(IMCNCC) JRST NETCHK] ; Yes CAML 1,NEGTIM JRST NEGCHK ; Check incomplete negotiations PUSHJ P,SIQCHK CAMLE 1,IMPTIM MOVE 1,IMPTIM ; Compute min clocks as CAMLE 1,NETTIM ; Next time to wakeup MOVE 1,NETTIM CAMLE 1,RFNTIM MOVE 1,RFNTIM CAMLE 1,NEGTIM MOVE 1,NEGTIM MOVEM 1,IBPTIM MOVEI 1,IMPBPT JSYS EDISMS ; Dismiss until something to do RET IMPBPT: SKIPE IMPFLG ; Flag set? JRST 1(4) ; Yes, wakeup MOVE 1,TODCLK ; Check alarm clock CAML 1,IBPTIM JRST 1(4) SKIPGE IDVLCK ; Lock clear and out scan needed? SKIPG IMPNOS JRST 0(4) JRST 1(4) ; Yes, wakeup IMPBP3: MOVE 1,TODCLK CAML 1,NETTIM CALL NETCHK ; Continue calling netchk if net down MOVEI 1,^D10000 DISMS ; Wait 10 sec RET ; Then try again ; Unexpected interrupt IMPUXI: BUG(CHK,) MOVSI 1,UMODF ; Reset stack MOVEM 1,FPC JSYS MENTR JRST IMPBP1 ; Special raw message routines ; Assign a special message queue .ASNSQ: JSYS MENTR PUSHJ P,CKNTWZ JRST ERMRTN NOINT AOSE SQLCK PUSHJ P,SQLWAT MOVSI 3,-NSQ SETZ 4, ASNSQL: SKIPGE SQJOB(3) ; Assigned? JRST [ JUMPL 4,ASNSQN MOVE 4,3 JRST ASNSQN] UMOVE 1,1 ; Get mask AND 1,SQMSK(3) ; Joint mask UMOVE 2,2 XOR 2,SQVAL(3) ; Difference TDNN 1,2 ; Must be different in joint mask bits JRST ASNSQF ; Else fail ASNSQN: AOBJN 3,ASNSQL ; Test all possibilities MOVEI 1,ASNSX1 JUMPGE 4,ASNSF1 UMOVE 1,1 ; Mask MOVEM 1,SQMSK(4) ; Store mask in table XCTUU [ AND 1,2] ; Mask good bits of value MOVEM 1,SQVAL(4) MOVE 1,JOBNO MOVEM 1,SQJOB(4) SETOM SQLCK XCTUU [HRRZM 4,1] JRST SKMRTN ASNSQF: MOVEI 1,ASNSX2 ASNSF1: UMOVEM 1,1 SETOM SQLCK JRST MRETN ; Release special q .RELSQ: JSYS MENTR NOINT AOSE SQLCK PUSHJ P,SQLWAT CAMN 1,[-1] JRST RELASQ CAIL 1,0 CAIL 1,NSQ JRST RELSQ1 PUSHJ P,REL1SQ RELSQ1: SETOM SQLCK JRST MRETN RELASQ: MOVSI 4,-NSQ RELAS1: HRRZ 1,4 PUSHJ P,REL1SQ AOBJN 4,RELAS1 JRST RELSQ1 REL1SQ: MOVE 2,JOBNO CAME 2,SQJOB(1) POPJ P, SETOM SQJOB(1) REL1S1: PUSHJ P,SIQGET POPJ P, PUSH P,1 PUSHJ P,RLNTBF POP P,1 JRST REL1S1 ; .rcvim receive raw messages .RCVIM: JSYS MENTR RCVIM1: NOINT UMOVE 1,1 CALL CHKSQ ; Check for accessibility to special q JRST ERMRTN ; No access PUSHJ P,SIQGET ; Get the message JRST [ OKINT ; None there JSYS EDISMS ; Wait JRST RCVIM1] ; Try again UMOVE 1,2 ; Get user's buffer HRL 1,2 ; Message location MOVE 3,1 ; Copy of user's buffer location ADD 3,0(2) ; Plus size -- end XCTMU [BLT 1,-1(3)] ; Transfer to user PUSHJ P,RLNTBF ; Release the buffer JRST SKMRTN ; Return ERMRTN: UMOVEM 1,1 JRST MRETN SIQGET: MOVE 2,TODCLK ADDI 2,SIQTM0 MOVEM 2,SIQTIM(1) ; Reset time NOSKED HLRZ 2,SIQIBO(1) JUMPE 2,SIQEMT HLLZ 3,0(2) MOVEM 3,SIQIBO(1) JUMPN 3,.+3 MOVEI 3,SIQIBO(1) MOVEM 3,SIQIBI(1) SOS SIQSPC(1) ; Credit space used OKSKED AOS 0(P) RET SIQEMT: OKSKED HRLZI 1,SIQIBO(1) HRRI 1,DISNT POPJ P, ; .sndim: send special message .SNDIM: JSYS MENTR CALL CHKSQ ; Check access to special q JRST ERMRTN UMOVE 1,2 UMOVE 2,0(1) ; Get size CAIL 2,2 CAML 2,MAXWPM JRST [ MOVEI 1,SNDIX1 JRST ERMRTN] ; Bad size NOINT PUSHJ P,ASNTBF ; Get a buffer JRST [ MOVEI 1,SNDIX2 JRST ERMRTN] ; No room PUSH P,1 ; Save it XCTUU [HRL 1,2] ; Make blt pointer MOVE 2,0(1) ; Size ADD 2,1 ; End of buffer ADD 1,BHC+1 ; Don't transfer first word XCTUM [BLT 1,-1(2)] ; Transfer message to monitor space POP P,2 ; The buffer MOVE 1,1(2) ; Get header word AND 1,[FRMIMP+377B23] CAMG 1,[LLINK*1B23] JRST [ PUSHJ P,RLNTBF ; Don't allow messages with ncp links MOVEI 1,SNDIX3 JRST ERMRTN] UMOVE 1,1 ; Get sq index MOVE 3,1(2) ; And header XOR 3,SQVAL(1) ; Difference with value TDNE 3,SQMSK(1) ; Must be equal in masked bits JRST [ PUSHJ P,RLNTBF MOVEI 1,SNDIX4 JRST ERMRTN] NOSKED SKIPL IMPRDY ; Last minute check if imp is up JRST [ OKSKED PUSHJ P,RLNTBF MOVEI 1,SNDIX5 JRST ERMRTN] PUSHJ P,IMPQOA ; Put onto output q OKSKED JRST SKMRTN ; Check for access to specific special q CHKSQ: CAIL 1,0 CAIL 1,NSQ JRST [ MOVEI 1,SQX1 POPJ P,] MOVE 2,JOBNO CAMN 2,SQJOB(1) JRST RSKP MOVEI 1,SQX2 POPJ P, ; Check for net wizardry CKNTWZ: MOVEI 2,NETWIZ TDNE 2,CAPENB JRST RSKP MOVEI 1,NTWZX1 POPJ P, SQLWAT: PUSH P,1 MOVEI 1,SQLTST JSYS EDISMS POP P,1 POPJ P, SQLTST: AOSE SQLCK JRST 0(4) JRST 1(4) ; Siqchk: check for unclaimed messages SIQCHK: HRLOI 3,377777 MOVSI 2,-NSQ SIQCKL: SKIPGE SQJOB(2) JRST SIQCKE CAMG 1,SIQTIM(2) JRST SIQCKX PUSH P,1 PUSH P,2 PUSH P,3 HRRZ 1,2 REPEAT 0,< ;CODE TO DELETE JUST ONE BUFFER PUSHJ P,SIQGET SKIPA PUSHJ P,RLNTBF> REPEAT 1,< ;CODE TO FLUSH THE WHOLE QUEUE PUSHJ P,REL1S1> POP P,3 POP P,2 POP P,1 SIQCKX: CAML 3,SIQTIM(2) MOVE 3,SIQTIM(2) SIQCKE: AOBJN 2,SIQCKL MOVE 1,3 POPJ P, USE RESPC ; Update imp clocks IMUCLK: PUSH P,1 SUBI 1,IMCIDL AOS IMNIDL(1) ; Count entries MOVE 1,JOBRTT ; Time since last update of fkrt ADD 1,FKRT ; Fork cpu to now SUB 1,IMCCLK ; Time since last measurement ADDM 1,IMCCLK ; Update to be time of this clock measurement ADDM 1,@IMCLST ; Charge to current clock POP P,IMCLST ; Set to new clock RET ; Set idvlck IFE PIESLC,< ; Version for non-pie slice scheduler LCKIDV: PUSH P,1 MOVEI 1,1 CALL STMINQ## ; Prevent dropping below q1 while locked LOCK IDVLCK,,SPQ LCKID0: POP P,1 PUSH P,FORKX POP P,IDVLLK AOS 0(P) RET LCKID1: SKIPE @-1(P) ; Wait wanted? JRST ULKID0 ;NO ,RETURN MOVEI 1,IDVTST JSYS EDISMS JRST LCKID0 > ;END NON-PIE-SLICE CONDITIONAL IFN PIESLC,< ; Version for pie-slice scheduler LCKIDV: LOCK IDVLCK,,SPQ LCKID0: PUSH P,FORKX POP P,IDVLLK AOS 0(P) RET LCKID1: SKIPE @0(P) ; Wait wanted? JRST RELSPQ## ;RETURN VIA RELSPQ, NORMAL SCHEDULING PUSH P,1 MOVEI 1,IDVTST JSYS EDISMS POP P,1 JRST LCKID0 > ; END OF IFN PIESLC CONDITIONAL ; Unlock idvlck ULKIDV: UNLOCK IDVLCK,RESIDENT,SPQ IFE PIESLC,< PUSH P,1 ULKID0: SETZ 1, CALL STMINQ POP P,1 > RET IDVTST: AOSE IDVLCK JRST 0(4) JRST 1(4) ; Release buffers left by pi routines IMINRB: IMSCLK(IMCNRB) ; Charge time to releasing buffers SETZ 4, EXCH 4,IMINFB ; Get all garbage buffers IMINR1: JUMPE 4,R ; Quit when all released MOVEI 2,0(4) HLRZ 4,0(4) CALL RLNTBF ; Release one JRST IMINR1 ; Get one buffer for input and lock it in core IMPGIB: IMSCLK(IMCGIB) ; Charge to imcgib IMPGI1: MOVE 2,MAXWPM ; For max input msg CALL ASNTBF ; Assign from pool JRST IMPB03 MOVEI 2,0(1) CALL IMPLKB ; Lock buffer PIOFF EXCH 2,IMPFRI ; Put bfr on input free list HRLM 2,@IMPFRI AOS 2,IMPNFI ; Count number free, if was 0, then PION SKIPN IMIB ; Input is off? SKIPG IMPNFI ; YES, BUFFERS AVAILABLE? CAIA ; NO PUSHJ P,IMISRT ; Yes, restart MOVE 2,IMPNFI ; GOT ENOUGH BUFFERS? CAMGE 2,IMPNIB JRST IMPGI1 ; NO RET ; Scan net tty lines IMPTS: IMSCLK(IMCTS) ; Charge to imcts SETZM TTNOF MOVSI 10,-NNVTLN ; Count thru nvt lines IMPTS1: MOVEI 2,NVTLO(10) SKIPN TTOCT(2) ; Output ready? SKIPE TTECT(2) CALL NETTCS ; Yes AOBJN 10,IMPTS1 RET ; Scan all connections for output possible ; Called by asynch process IMPOS: IMSCLK(IMCOS) ; Charge to imcos MOVSI 6,-IMPNLK SETZM IMPNOS ; Cancel request IMPOS2: HRRZ 2,IMPLT1(6) TRNE 2,1B18 ; Output connection has bit 18 on TRNE 2,1B19 ; And bit 19 off IMPOS1: AOBJN 6,IMPOS2 JUMPGE 6,[SUB P,BHC+1 ; Flush .+1 return, go back to top RET] ILOCK() ; Return if can't set lock MOVEI 1,0(6) CALL IMPKO1 ; Check and send if possible JRST IMPOS1 ; Asynch process to put buffers on proper connection queues IMIP1: IMSCLK(IMCP1) ; Charge to imcp1 HLRZ 2,IMPIBO ; Try to get next buffer JUMPE 2,R ; None left PIOFF HLLZ 3,0(2) JUMPN 3,.+3 MOVEI 4,IMPIBO MOVEM 4,IMPIBI MOVEM 3,IMPIBO PION PUSH P,2 ; Save bfr address MOVEI 1,0(2) IFDEF DBGBUF,< CALL DBGIM> NOSKED HRRZ 2,0(2) ; GET SIZE FIELD CAMLE 2,MAXWPM ; MAKE SURE ITS NOT ON FREELIST BUG (HLT,) MOVE 2,0(P) ; RESTORE 2 CALL MULKMP ; Unlock head, tail unlocked at pi lev HRRZS 0(2) ; Clear fwd pointer MOVE 1,1(2) ; Get header AND 1,[FRMIMP+377B23] ; Extract link + frmimp CAML 1,[B23] ; Normal link? JRST IMIPSQ ; No, dispatch to special q OKSKED LDB 1,[POINT 16,1(2),23] ; Get host-link ILOCK CALL LNKLUK ; See if connection exists JRST [ TRNE 1,377 ; Doesn't, control link? JRST IMIBB ; Link non-existant MOVEI 3,^D8 ; Create connection, byte size is 8 CALL IMPOP1 HRROS IMPLT1(1) ; Make unit -1 MOVEI 3,377777 HRRM 3,IMPLT4(1) ; Set infinite msg alloc AOS IMPNCL ; Count control connections JRST .+1] POP P,2 MOVE 3,IMPLT2(1) HRLM 2,0(3) ; Put msg on queue for conn HRRM 2,IMPLT2(1) HLRE IMPUN,IMPLT1(1) IUNLK JUMPL IMPUN,R ; See if nvt connection LDB 2,PNVT CAIL 2,NVTLO CAILE 2,NVTHI RET ; Isn't CALL NVTUPI ; Unpack nvt input RET IMIPSQ: MOVSI 3,-NSQ IMIPS1: MOVE 1,1(2) ; Get header XOR 1,SQVAL(3) ; Compare to value SKIPL SQJOB(3) ; In use? TDNE 1,SQMSK(3) ; Yes, equal? AOBJN 3,IMIPS1 ; No or no JUMPGE 3,IMIPS2 ; Found nobody, go throw away MOVE 1,SIQSPC(3) ; How much space in use? CAIL 1,SIQMAX ; Less than max? JRST IMIPS2 ; No, too much, go throw away MOVE 1,TODCLK ADDI 1,SIQTM0 SKIPN SIQIBO(3) ; First one (queue empty?) MOVEM 1,SIQTIM(3) ; Record time of arrival AOS SIQSPC(3) ; Count messages on queue HRLM 2,@SIQIBI(3) HRRZM 2,SIQIBI(3) OKSKED JRST IMIPS3 IMIPS2: OKSKED PUSHJ P,RLNTBF ; Throw message away IMIPS3: SUB P,BHC+1 RET ; Cause bad msg to be printed IMIBB: IUNLK LSHC 1,-8 ; Host in 1 ROT 2,8 ; Link in 2 ANDI 1,377 ANDI 2,377 CALL IMPNXR ; Send nxr JRST IMIPB1 IMIPB: IUNLK IMIPB1: HRLI 2,9 BUG(IML,,X) IMIPB2: POP P,2 JRST RLNTBF ; Send RST to all named hosts on startup NETCH0: IMSCLK(IMCNCK) ; Charge to imcnck SKIPGE 7,IMPCCH ; Sending rst's? JRST IMPET ; No. IMPRC1: CALL IMPRCC ; Check for space in link table JRST [ MOVEI 1,^D50 JRST IMPET1] HRRZ 1,7 CAMN 1,NLHOST ; Local host? JRST IMPRC2 ; Never send reset to local host MOVEI 1,377777 ; NIL designator for CVHST HRRZ 2,7 ; Host number CVHST ; See if the host has a name JRST IMPRC2 ; It doesn't. Don't swamp net with ; resets to nonexistent hosts. HRRZ 2,7 ; Host exists. See if it's up already IDIVI 2,^D36 MOVE 3,BITS(3) TDNN 3,IMPHRT(2) ; No reset if already up CALL IMSRST IMPRC2: CAIGE 7,377 AOJA 7,IMPRC1 IMPEET: SETZM IMPHCT MOVE 1,[IMPHCT,,IMPHCT+1] BLT 1,IMPHCT+IMPLBT-1 MOVSI 7,-IMPNLK MOVE 1,[UPROBI-UPROBT] JRST IMPET1 IMPRCC: MOVE 1,IMPNOL ; Number of links in use CAIG 1,IMPNLK/4-10 AOS 0(P) RET ; Echo tester IMPET: MOVEI 1,^D120000 SKIPL IMPRDY JRST IMPCC6 ; Don't probe if ncp not fully up PUSHJ P,IMPRCC ; Check space in link table JRST [ MOVEI 1,^D5000 ; Try again in 5 seconds JRST IMPCC6] IMPET3: MOVE 1,IMPLT1(7) TRNE 1,200000 ; Active? JRST IMPET4 ; No, get next LSH 1,-8 ANDI 1,377 ; The host MOVE 2,1 IDIVI 2,^D36 ; Compute bit table index MOVE 3,BITS(3) TDNE 3,IMPHCT(2) ; Recently sent a message JRST [ ANDCAM 3,IMPHCT(2) JRST IMPET4] ; Send next time not this IORM 3,IMPHCT(2) ; Remember we have sent one MOVE 2,1 ; If up, data=host CALL IMPNOP ; And send nop (echo might be better) IMPET4: AOBJP 7,IMPEET IMPET0: TRNE 7,7 ; Wait every eighth entry JRST IMPET MOVEI 1,UPROBT*8/IMPNLK ; Delay for correct interval IMPET1: MOVEM 7,IMPCCH ; Save current state IMPCC6: ADD 1,TODCLK ; Compute when to do it again MOVEM 1,IMPTIM RET ; Check for overdue rfnm's ; Count down rfnmc field if non-zero. ; If it reaches 0, then generate impbug cause rfnm seems lost RFNCHK: IMSCLK(IMCRFN) ; Charge imcrfn MOVSI 10,-IMPNLK ; Set to scan conn table RFNCK0: MOVSI 6,(RFNMC) MOVEI 5,1B19 RFNCK2: TDNN 5,IMPLT1(10) ; Connection in use? TDNN 6,IMPLT2(10) ; Rfnm set here? RFNCK1: AOBJN 10,RFNCK2 ; No JUMPGE 10,RFNCK4 LDB 7,[POINT 2,IMPLT2(10),1] SOJE 7,RFNCK5 ; Decrement count, jump if exhausted DPB 7,[POINT 2,IMPLT2(10),1] JRST RFNCK1 RFNCK5: PIOFF ; Prevent confusion if pi stores buffer HRRZ 2,IMPLT3(10) ; While we get message to retransmit HLLZS IMPLT3(10) ; And clear the pointer PION JUMPE 2,RFNCK3 ; Apparently hasn't made it thru q yet HRRZ 3,IMPLT1(10) ; Get host/link ROT 3,-8 ANDI 3,377 ; Retain only host MOVSI 5,(RXMTF) CAME 3,NLHOST ; If local host TDNE 5,IMPLT2(10) ; Or retransmission wanted? JRST RFNCK7 ; Then retransmit CALL RLNTBF ; Else release the buffer DPB 7,[POINT 2,IMPLT2(10),1] HRRZ 2,IMPLT1(10) ; Yes, rfnm lost. get host-link CALL IMP8X1 ; Reformat for bug msg BUG(IMH,,X) AOS IMPNOS ; Cause output scan to restart output RFNCK6: AOBJN 10,RFNCK0 ; Reset ac5 and 6 RFNCK4: MOVEI 1,RFNTMO ADD 1,TODCLK ; Set next check for rfntmo msec. MOVEM 1,RFNTIM RET RFNCK7: IORM 6,IMPLT2(10) ; Set rfnmc again CALL IMPQOA ; Put message back on output queue JRST RFNCK6 ; Go to next item RFNCK3: IORM 6,IMPLT2(10) ; Set rfnmc again HRRZ 2,IMPLT1(10) ; Get host/link CALL IMP8X1 ; Format for bug msg BUG(IMH,,X) JRST RFNCK6 ; Go on to next item ; Queue irreg msg IMP8XQ: AOS 3,IMP8XI ; Increment input index CAIL 3,IMP8XS SETZB 3,IMP8XI ; Wraparound CAMN 3,IMP8XO ; Overflow? BUG(NTE,) MOVEM 2,IMP8XB(3) AOS IMP8XC RET IMP8XM: IMSCLK(IMC8XM) ; Charge to imc8xm AOS 3,IMP8XO ; Retrieve stuff from queue CAIL 3,IMP8XS SETZB 3,IMP8XO ; Wraparound MOVE 1,IMP8XB(3) SOS IMP8XC IFDEF DBGBUF,< CALL DBGIIM> LDB 3,[POINT 4,1,7] ; Message type code LDB 2,[POINT 16,1,23] ; Host-link XCT IMPMTT(3) ; Dispatch to appropriate routine RET XX==JRST IMP8XX ; Unimplemented code IMPMTT: BUG(HLT,) JRST IMPEC1 ; Error JRST IMPDN2 ; Imp going down XX ; Formerly blocked link JFCL ; Nop JRST IMRFNM ; Rfnm JRST IMPEC6 ; Dead host status JRST IMPEC7 ; Destination dead JRST IMPEC8 ; Error JRST IMPEC9 ; Incomplete transmission JRST IMPE10 ; Imp dropped ready line XX ; Cease timeout XX ; Cease sent XX ; Unassigned XX ; " XX ; " ; Irregular message processors ; Error in leader (type 1) IMPEC1: TRNN 1,377B31 ; Sub-type 0? JRST IMPEC8 ; Yes, retransmit JRST BADIRM ; Go cause it to be printed ; Imp going down (type 2) IMPDN2: MOVEM 1,IMPGDM ; Save it for printing AOS JB0FLG MOVEM 1,IGDMSG GTAD MOVEM 1,IGDTIM RET ; Rfnm (type 5) IMRFNM: MOVEI 1,1B18(2) ; Host and link, denote send connection ILOCK CALL LNKLUK ; Lookup in link table JSP 2,BADIRY ; Not found PUSH P,1 MOVSI 2,(RFNMC) PIOFF ; if rfnm returns before msg out done ANDCAM 2,IMPLT2(1) ; Clear rfnm and check flags HRRZ 2,IMPLT3(1) ; Get retransmit buffer HLLZS IMPLT3(1) PION SKIPE 2 CALL RLNTBF POP P,1 HLRE IMPUN,IMPLT1(1) ; Get impun MOVSI 2,(RXMTF) TDNN 2,IMPLT2(1) ; Have we been retransmitting? JRST IMPKO1 ; No. just send next message ANDCAM 2,IMPLT2(1) ; Yes. stop retransmitting CALL IMPKO1 ; Send next message JUMPGE IMPUN,SVCRST ; If not ctrl generate service restored RET ; Dead host status (type 6) IMPEC6: TLNE 1,(1B1) ; Usual type? RET ; No. ignore it ROT 2,-9 ; Get host number/2 low bit in b0 LSH 1,-4 ; Get msg id -- subtype ANDI 1,177777 ; Keep 16 bits IORI 1,1B18+1B19 ; Mark info valid and dead JUMPL 2,[ ; Odd host? HRRM 1,HSTSTS(2); Yes, store in rh JRST .+2] HRLM 1,HSTSTS(2) ; No, store in lh ANDI 1,17 ; Extract sub-type CAIE 1,2 ; Is it simply tardy? CAIN 1,^D10 ; Or at a bpt RET ; Yes, no further action ROT 2,9 ; No. get back host/link JRST IMPDD1 ; And declare it dead ; Destination dead (type 7) IMPEC7: PUSH P,2 LDB 1,[POINT 8,2,27] ; Extract host IDIVI 1,^D36 MOVE 1,IMPHRT(1) ; Get host up bits AND 1,BITS(2) ; Mask in the correct one POP P,2 JUMPE 1,IMPDD1 ; If already down, call it down MOVE 1,2 ; Host/link IORI 1,1B18 ; Send ILOCK CALL LNKLUK ; Find the link JSP 2,BADIRY IMPECC: MOVSI 2,(RXMTF) IORM 2,IMPLT2(1) ; Cause retransmission HLRE IMPUN,IMPLT1(1) ; Get "unit" IUNLK JUMPL IMPUN,R ; Done if control connection CALL SVCINT ; Else perform service interruption RET IMPDD1: LDB 1,[POINT 8,2,27] ; Host number HSTDED: MOVEI 3,0(1) IDIVI 3,^D36 MOVE 5,BITS(4) TDNE 5,IMPHRT(3) ; Did we already know he was down? IFDEF POLLF,< IORM 5,IMPHL1(3)> ; Request obituary ANDCAM 5,IMPHRT(3) ; Mark him down CALL IMPXLT ; Clear link table for dead host CALL NETHDN ; Clean up any connections to host RET ; Error in data & incomplete transmission (types 8 & 9) IMPEC8: IMPEC9: MOVEI 1,1B18(2) ; Send connection ILOCK CALL LNKLUK ; Get lt index for this one JSP 2,BADIRY ; Not there, can't retransmit PIOFF ; Prevent pi from storing in implt3 HRRZ 2,IMPLT3(1) ; Get buffer for retransmission HLLZS IMPLT3(1) PION JUMPE 2,IMPECC ; None there now. retransmit later IUNLK CALL IMPQOA ; Put it back on output queue RET ; Interface reset (type 10) IMPE10: MOVSI 1,-IMPNLK IMPRSY: PUSH P,1 ILOCK MOVE 2,IMPLT1(1) TRNE 2,1B19 ; In use? JRST IMPZSY ; No TRNN 2,377 JRST IMPZSY ; Control TRNE 2,1B18 ; Send? JRST IMPSSY ; Yes LDB 2,LTLINK LDB 1,LTHOST IUNLK CALL IMPRAP JRST IMPXSY IMPSSY: CALL IMPSYN IMPZSY: IUNLK IMPXSY: POP P,1 AOBJN 1,IMPRSY MOVSI 4,-400 IMPOSY: HRRZ 1,4 CALL CHKNWP ; DOES THIS HOST UNDERSTAND? JRST [ PUSH P,4 ; NO CALL HSTDED POP P,4 JRST .+1] AOBJN 4,IMPOSY AOS IMPNOS ; Scan for output to pick up rarrf's RET ; Check if host for control message knows about new protocol stuff CHKNWP: PUSH P,2 PUSH P,1 IDIVI 1,^D36 MOVE 2,BITS(2) TDNE 2,NWPBT(1) AOS -2(P) POP P,1 POP P,2 RET ; MARK NEW PROTOCOL BIT FOR HOST MRKNWP: PUSH P,1 PUSH P,2 IDIVI 1,^D36 MOVE 2,BITS(2) IORM 2,NWPBT(1) POP P,2 POP P,1 RET ; Error tail ends for irregular msg processors BADIRY: IUNLK BADIRM: IMP8XX: MOVE 2,IMP8XO ADD 2,[4,,IMP8XB-1] ; Make pointer to one before message BUG(IML,,X) RET IMP8X1: DPB 2,[POINT 8,2,9] ; Unpack host-link in b20-35 into LSH 2,-^D8 ; Xwd link,host TRZ 2,777400 RET ; Scan for input ready on control link connection IMPCN0: IMSCLK(IMCCNP) ; Charge to imccnp MOVEI 5,1B18+1B19+377 ; Connection must be receive, link 0 PUSH P,BHC ; Put a zero on stack MOVSI 6,-IMPNLK IMPCN4: TDNE 5,IMPLT1(6) ; Desired connection? AOBJN 6,.-1 ; No JUMPGE 6,IMPCN5 ; Done AOS 0(P) ; Count number of msgs seen MOVEI 1,0(6) ; Conn index PUSH P,5 ; Save these ac's PUSH P,6 CALL IMPCNP ; Go process this host's control msgs POP P,6 ; Restore ac's POP P,5 MOVEI 1,0(6) CALL IMPCLL ; Close "connection" JRST IMPCN4 IMPCN5: POP P,1 ; Done. get count of processed msgs JUMPN 1,R ; If any, done. BUG(IMP,,X) SOS IMPNCL ; Count it down so don't loop. RET ; Control table for control opcodes DEFINE CTOP (A,C) < XWD IM8'A,C> I8CCM: CTOP NOP,0 CTOP RTS,441000 CTOP STR,441000 CTOP CLS,440000 CTOP ALL,124000 CTOP GVB,111000 CTOP RET,124000 CTOP INR,100000 CTOP INS,100000 CTOP ECO,100000 CTOP ERP,100000 CTOP ERR,144200 CTOP RST,0 CTOP RRP,0 CTOP RAR,100000 CTOP RAS,100000 CTOP RAP,100000 CTOP NXR,100000 CTOP NXS,100000 I8NCCM==.-I8CCM ; Process control message IMPCNP: LDB 2,LTHOST ; Get host MOVEM 2,IMPCHO ; And leave it for following commands IDIVI 2,^D36 ; Compute index to bit tables MOVE 3,BITS(3) TDNE 3,IMPBHT(2) ; Bad host? RET ; Yes. let impcll flush it SETZM IMPCHU ; Say host not ready (no rst/rrp) TDNE 3,IMPHRT(2) ; Unless it is up SETOM IMPCHU ; Then say it's up IMP8T6: CALL UPBYT ; Get next op code RET ; None left...done CAIL 3,I8NCCM ; Legal code? JRST IMP8T4 ; No, flush whole message MOVEI 6,I8CCM(3) ; Address of table entry for this code HRLI 6,220300 ; Pntr for 3-bit bytes specifying fields HLRZ 7,I8CCM(3) ; Get routine dispatch address MOVEI 4,I8CAL ; Args buffer IMP8T1: ILDB 5,6 ; Number of (8-bit) bytes in next arg SETZ 2, ; Clear word to construct arg JUMPN 5,IMP8T2 ; 0 means no more args CAIN 7,IM8NOP ; Check for NOP's at this level JRST IMP8T6 CAIE 7,IM8RST ; Is rst? CAIN 7,IM8RRP ; Or rrp? SETOM IMPCHU ; Yes, consider him up SKIPN IMPCHU ; Is he up? MOVEI 7,IMSRST ; No. force call to send rst PUSH P,1 ; Preserve ac1 MOVE 6,[XWD IMPCHO,1] ; Move args to acs 1-6 BLT 6,6 ; Ac1 (impcho) always gets host number CALL 0(7) ; Do function POP P,1 ; Restore 1 (lt index) JRST IMP8T6 ; See if another IMP8T2: PUSH P,2 ; Preserve ac2 CALL UPBYT ; Get a byte of argument JRST IMP8T5 ; Whoops, short message POP P,2 ROT 3,-8 ; And shift it LSHC 2,8 ; Into the arg being accumulated SOJG 5,IMP8T2 ; All bytes packed? MOVEM 2,0(4) ; Yes, store arg in buffer AOJA 4,IMP8T1 ; And see if more args IMP8T5: SUB P,BHC+1 IMP8T4: MOVE 2,IMPCHO ; Screwed up control msg BUG(IMH,,X) RET ; Let impcll flush rest of message(s) ; Control routines ; Nop (type 0) IM8NOP: RET ; Receiver to sender request for connection (type 1) IM8RTS=RECRTS ; Code in netwrk ; Sender to receiver request for connection (type 2) IM8STR=RECSTR ; Code in netwrk ; Close connection (type 3) IM8CLS=RECCLS ; Code in netwrk ; Allocate (type 4) IM8ALL: LSH 1,^D8 ; Concat host and link IORI 1,1B18(2) ; Bit for send connection ILOCK CALL LNKLUK ; Lookup in connect table JSP 2,BADLKS ; Not found HLRE IMPUN,IMPLT1(1) ; Get unit JUMPL IMPUN,ULKIDV ; Control connection, shouldn't happen MOVSI 2,(RARF) ; Waiting for rar? TDNE 2,IMPLT2(1) JRST ULKIDV ; Yes, ignore all allocates HRRZ 2,IMPLT4(1) ; Get current msg alloc ADD 2,3 CAILE 2,777777 ; Bigger than max? JRST IMPB06 ; Yes HRRM 2,IMPLT4(1) ADDB 4,NETBAL(IMPUN) ; Update bit allocation CAML 4,[1B3] ; Excessive? JRST IMPB06 LDB 2,PNVT CAIL 2,NVTLO ; Nvt attached? CAILE 2,NVTHI JRST IMPKO1 ; No, test more output for reg. connet'n IUNLK CALL NETTCS ; Yes, pack up more characters JRST IMPCKO ; And try to send ; Give back (code 5) IM8GVB: LSH 1,^D8 ; Give back requested IORI 1,1B18(2) ; Construct host-link for send socket ILOCK CALL LNKLUK JSP 2,BADLKS ; Not found HLRE IMPUN,IMPLT1(1) ; Get unit JUMPL IMPUN,ULKIDV ; Control conn, shouldn't happen HRRZ 2,IMPLT4(1) ; Msg alloc CAIL 3,200 ; All? JRST .+3 ; Yes IMUL 2,3 ; No, calc how much IDIVI 2,200 HRRZ 3,IMPLT4(1) SUB 3,2 ; Reduce current msg alloc HRRM 3,IMPLT4(1) PUSH P,2 MOVE 2,NETBAL(IMPUN) ; Bit allocation CAIL 4,200 ; Return all? JRST .+3 ; Yes MUL 2,4 ; No, calc how much DIVI 2,200 MOVN 3,2 ADDM 3,NETBAL(IMPUN) ; Reduce bit alloc MOVE 4,2 ; Setup call for ret POP P,3 LDB 2,LTLINK LDB 1,LTHOST IUNLK CALL IMPRET ; Send the ret RET ; Return (code 6) IM8RET: RET ; Never send gvb/ nver get ret ; Interrupt from receiver (code 7) IM8INR: MOVE 3,1 LSH 1,^D8 IORI 1,1B18(2) ; We must be a send connection ILOCK CALL LNKLUK JSP 2,BADLKS ; No such connection HLRE IMPUN,IMPLT1(1) ; Unit IUNLK JUMPL IMPUN,R ; Control connection, shouldn't happen MOVE 1,3 ; Host JRST RECINR ; Not specified for nvt ; Interrupt from sender (code 8) IM8INS: MOVE 3,1 LSH 1,^D8 IORI 1,0(2) ; Combine host-link ILOCK CALL LNKLUK JSP 2,BADLKR HLRE IMPUN,IMPLT1(1) IUNLK JUMPL IMPUN,R MOVE 1,3 LDB 3,PNVT ; Get nvt number CAIL 3,NVTLO CAILE 3,NVTHI JRST RECINS ; Isn't nvt, go do regular connection MOVE 2,3 LDB 1,PTINTC SUBI 1,1 ; Ins counts -1, sync char counts 1 DPB 1,PTINTC LDB IMPUN,PTNETI SKIPN NETBAL(IMPUN) CALL NVTRAL ; Send more allocation RET ; Echo and echo reply (code 9 & 10) IM8ECO: CALL IMPERP ; Send reply RET IM8ERP: CAME 1,2 ; We send echo with data = host JFCL ; Not equal ... oh well RET ; Error (code 11) IM8ERR: MOVSI 2,0(2) ; Arg HRRI 2,0(1) ; Host BUG(IMH,,X) RET ; Reset and reset-reply ctrl msg (codes 12 & 13) IM8RST: PUSH P,1 CALL RECRST ; Notify fsm POP P,1 IM8RRP: ROT 1,-1 ; Halve MOVEI 2,1B18 ; Valid info, host up JUMPL 1,[ ; If od host number HRRM 2,HSTSTS(1); Put into rh JRST .+2] HRLM 2,HSTSTS(1) ROT 1,1 ; Restore host number IDIVI 1,^D36 ; Get bit for host tables MOVE 5,BITS(2) IORM 5,IMPHRT(1) ; Mark host alive RET ; Reset allocate by receiver (code 14) IM8RAR: CALL MRKNWP ; MARK THIS HOST AS USING NEW PROTOCOL LSH 1,^D8 IORI 1,1B18(2) ILOCK CALL LNKLUK JSP 2,BADLKS HLRE IMPUN,IMPLT1(1) JUMPL IMPUN,ULKIDV MOVSI 2,(RARF) ANDCAM 2,IMPLT2(1) ; Clear resync in progress flag JRST ULKIDV ; Reset allocate by sender (code 15) IM8RAS: CALL MRKNWP ; MARK THIS HOST AS USING NEW PROTOCOL LSH 1,8 IORI 1,0(2) ILOCK CALL LNKLUK JSP 2,BADLKR HLRE IMPUN,IMPLT1(1) JUMPL IMPUN,ULKIDV HLLZS IMPLT4(1) HLRZ 4,IMPLT4(1) ; ANY CURRENT BUFFER? JUMPE 4,IM8RA1 ; NO MOVE 4,2(4) ; ACCUMULATE BYTES IM8RA1: HLRZ 2,IMPLT3(1) ; GET BUFFER JUMPE 2,IM8RA3 ; NONE IM8RA2: LDB 3,[POINT 16,2(2),27]; NUMBER OF BYTES ADD 4,3 AOS IMPLT4(1) ; COUNT MSGS HLRZ 2,0(2) ; NEXT BUFFER JUMPN 2,IM8RA2 IM8RA3: LDB 3,IMPLBS ; BYTE SIZE IMUL 3,4 MOVEM 3,NETBAL(IMPUN) IUNLK LDB 2,LTLINK LDB 1,LTHOST CALL IMPRAR LDB 2,PNVT CAIL 2,NVTLO CAILE 2,NVTHI JRST NETRAL JRST NVTRAL ; Reset allocate please (code 16) IM8RAP: CALL MRKNWP ; MARK THIS HOST AS USING NEW PROTOCOL LSH 1,8 IORI 1,1B18(2) ILOCK CALL LNKLUK JSP 2,BADLKS HLRE IMPUN,IMPLT1(1) JUMPL IMPUN,ULKIDV MOVSI 2,(RARF!RARRF) IORM 2,IMPLT2(1) JRST IMPKO1 ; Non-existent link from receiver and sender (codes 17 & 18) IM8NXR: IORI 2,1B18 IM8NXS: CALL MRKNWP ; MARK THIS HOST AS USING NEW PROTOCOL LSH 1,8 IOR 1,2 ILOCK CALL LNKLUK JRST ULKIDV HLRE IMPUN,IMPLT1(1) ; Get impun JUMPL IMPUN,ULKIDV ; Ignore if control conn IUNLK CALL SK2DWN RET ; Link lookup failure for receivers and senders BADLKR: SKIPA 3,[IMPNXR] BADLKS: MOVEI 3,IMPNXS IUNLK PUSH P,2 ; SAVE PC FOR INSPECTION MOVE 2,1 LSH 1,-8 ANDI 1,377 ANDI 2,377 PUSH P,1 HRLM 2,0(P) CALL 0(3) POP P,2 BUG(IMH,,X) SUB P,BHC+1 ; FLUSH SAVED PC RET ; Calls from ncp ; Open link, i.e. associate host-link and unit ; 1/ host ; 2/ link ; 3/ byte size IMPOPL: ILOCK LSH 1,^D8 IORI 1,0(2) ; Concat host and link CALL LNKLUK ; Now in table? JRST IMPOP0 ; No, slot to use returned in 2 IUNLK BUG(IMP,,X) RET IMPOP0: CALL IMPOP1 IUNLK RET IMPOP1: EXCH 1,2 MOVEM 2,IMPLT1(1) HRLM IMPUN,IMPLT1(1) MOVEI 2,IMPLT3(1) ; Init bfr queue MOVEM 2,IMPLT2(1) ; Make in point to out SETZM IMPLT3(1) SETZM IMPLT4(1) DPB 3,IMPLBS ; Set byte size RET ; Close link, inverse of above ; 1/ LT INDEX IMPCLL: ILOCK CALL IMPLL0 IUNLK RET IMPLL0: MOVEI 2,1B19 TDNE 2,IMPLT1(1) ; Was in use? RET ; No, do nothing else EXCH 2,IMPLT1(1) ; Set entry to deleted TRNE 2,377 ; Control link? JRST IMPLL9 ; No, skip this TRNE 2,1B18 ; Send? SOSA IMPNOL ; Yes, decrease count of send cl's SOS IMPNCL ; Else decrease count of recv cl's IMPLL9: AOS LNKNDL ; Count deletes CALL IMPLL1 ; Flush messages RET ; Set done flag for connection ; 1/ conn index IMPSDB: MOVSI 2,(LTDF) IORM 2,IMPLT2(1) AOS IMPNOS ; Make output be looked at RET ; Abort link (called by ncp if transmission aborted) IMPABL: ILOCK CALL IMPLL3 ;CLEAR QUEUES, DON'T CLEAR RFNMC IUNLK RET ; Clear link table for particular host IMPXLT: PUSH P,1 ILOCK MOVSI 1,-IMPNLK ; Set to scan conn table IMPXLL: LDB 2,LTHOST ; Get host CAIE 2,@0(P) ; Specified one? JRST IMPXLN LDB 2,LTLINK ; Get link JUMPE 2,[CALL IMPLL0 ; If control link, flush all JRST IMPXLN] CALL IMPLL1 ; Else flush queued messages IMPXLN: AOBJN 1,IMPXLL IUNLK POP P,1 RET ; Resync allocation IMPSYN: PUSH P,1 LDB 1,LTHOST CALL CHKNWP ; NEW PROTOCOL? JRST [ POP P,1 RET] POP P,1 MOVSI 2,(RARF!RARRF) IORM 2,IMPLT2(1) AOS IMPNOS RET ; Flush all messages for a connection IMPLL3: TDZA 2,2 ;DON'T CLEAR RFNMC IMPLL1: MOVSI 2,(RFNMC) ;CLEAR RFNMC PUSH P,2 ;A BIT LATER ON HLRZ 2,IMPLT4(1) HRRZS IMPLT4(1) PUSH P,1 CAIE 2,0 ; Is current bfr? PUSHJ P,RLNTBF MOVE 1,0(P) ; Get back lt index MOVEI 2,IMPLT3(1) HRRM 2,IMPLT2(1) ; Fix tail pointer PIOFF MOVE 2,-1(P) ;GET BITS TO CLEAR, EITHER 0 OR RFNMC ANDCAM 2,IMPLT2(1) ; Cancel outstanding rfnm HRRZ 2,IMPLT3(1) ; Get retransmit buffer HLLZS IMPLT3(1) PION SKIPE 2 IMPLL2: CALL RLNTBF ; Yes, release it POP P,1 HLRZ 2,IMPLT3(1) ; Release any buffers on queue JUMPE 2,[POP P,(P) POPJ P,0] HLLZ 3,0(2) HLLM 3,IMPLT3(1) PUSH P,1 JRST IMPLL2 ; Control message senders ; Nop, rts, str, cls, all, gvb, ret, inr, ins, eco, erp IMPNOP: PUSH P,[XWD 0,0] ; Nop, no args JRST IMPSCM IMPRTS: PUSH P,[XWD 441000,1] ; Arg descriptor,,opcode JRST IMPSCM ; Construct message and output IMPSTR: PUSH P,[XWD 441000,2] JRST IMPSCM IMPCLS: PUSH P,[XWD 440000,3] JRST IMPSCM IMPALL: CAIGE 3,0 ; Don't send neg allocs SETZ 3, CAIGE 4,0 SETZ 4, PUSH P,1 LDB 1,PLIDX ; Get conn index PUSH P,2 MOVSI 2,(RARF) ; Waiting for ras? TDNE 2,IMPLT2(1) JRST [ POP P,2 ; Yes. do nothing POP P,1 RET] POP P,2 ; No, get back ac2 ADDM 3,IMPLT4(1) ; Update msg alloc POP P,1 ADDM 4,NETBAL(IMPUN) ; Bits PUSH P,[XWD 124000,4] JRST IMPSCM IMPGVB: PUSH P,[XWD 111000,5] JRST IMPSCM IMPRET: PUSH P,[XWD 124000,6] JRST IMPSCM IMPINR: PUSH P,[XWD 100000,^D7] JRST IMPSCM IMPINS: PUSH P,[XWD 100000,^D8] JRST IMPSCM IMPECO: PUSH P,[XWD 100000,^D9] JRST IMPSCM IMPERP: PUSH P,[XWD 100000,^D10] JRST IMPSCM ; Control message senders (continued) ; Err, rst, rrp, rar, ras, rap, nxr, nxs IMPERR: PUSH P,[XWD 144200,^D11] JRST IMPSCM IMSRST: PUSH P,[XWD 0,^D12] JRST IMPSCM IMPRRP: PUSH P,[XWD 0,^D13] JRST IMPSCM IMPRAR: CALL CHKNWP RET PUSH P,[100000,,^D14] JRST IMPSCM IMPRAS: CALL CHKNWP JRST IM8RAR ; Resync not implemented -- sim rar PUSH P,[100000,,^D15] JRST IMPSCM IMPRAP: CALL CHKNWP RET ; DOES NOT UNDERSTAND NEW PROTOCOL PUSH P,[100000,,^D16] JRST IMPSCM IMPNXR: CALL CHKNWP RET PUSH P,[100000,,^D17] JRST IMPSCM IMPNXS: CALL CHKNWP RET PUSH P,[100000,,^D18] JRST IMPSCM ; Send control message ; 1/ dest host ; 0(p) arg descriptor,,opcode IMPSCM: EXCH 13,0(P) PUSH P,6 PUSH P,7 PUSH P,10 PUSH P,11 PUSH P,12 PUSH P,14 MOVEI 10,0(P) ; Use 3 words on stack as buffer ADD P,BHC+3 HRLI 10,1000 ; Construct byte pointer, 8-bits PUSH P,10 ; Save it for later use IDPB 13,10 ; Store opcode as first byte of message MOVEI 11,1 ; Init message byte count MOVEI 14,2 ; Index to args IMPSC4: SETZ 12, LSHC 12,3 ; Next arg descriptor byte JUMPN 12,IMPSC3 ; 0 means done LSH 1,^D8 IORI 1,1B18 ILOCK CALL LNKLUK ; See if connection now exists JRST [ MOVEI 3,^D8 ; Doesn't, create it CALL IMPOP1 AOS IMPNOL ; Count open output links HRROS IMPLT1(1) ; Set unit neg MOVEI 3,377777 ; Set infinite msg alloc HRRM 3,IMPLT4(1) MOVSI 3,(HIPFLG) IORM 3,IMPLT2(1) ; Set high priority flag JRST .+1] POP P,3 ; Byte ptr MOVEI 4,0(11) ; Count CALL PKMSG0 ; Does iunlk SUB P,BHC+3 POP P,14 POP P,12 POP P,11 POP P,10 POP P,7 POP P,6 POP P,13 RET IMPSC3: ADDI 11,0(12) ; Accumulate byte count of message MOVNI 6,0(12) ; Compute number of bits to left of arg IMULI 6,^D8 ; Number bytes times bits per byte ADDI 6,^D36 ; Subtracted from size of word MOVE 7,0(14) ; Get next arg LSH 7,0(6) ; Shift out unused bits ROT 7,^D8 ; Shift next byte into place IDPB 7,10 ; Store it in message buffer SOJG 12,.-2 ; For all bytes AOJA 14,IMPSC4 ; Index arg pointer ; Network tty logic ; For connection driven via the tty service routines ; Assign a pseudo (network) tty ; 1/ receive unit ; 2/ send unit ; Returns 1/ line number ASNNVT: MOVEI 3,NVTLO ; Nvt's start after scanner ttys NOSKED ASNPT1: SKIPGE TTNETW(3) ; Free? JRST ASNPT3 ; Yes ASNPT2: CAIGE 3,NVTHI ; Looked at all nvt's? AOJA 3,ASNPT1 ; No OKSKED ; Yes, RET ; Return bad ASNPT3: SKIPL TTFORK(3) ; Tty already attached? JRST ASNPT2 ; Yes, don't use TLNN 1,(1B2) ; New nvt protocol request? TLZA 3,-1 ; No, make zeroes HRLI 3,NEWNVB ; Yes, make new nvb bit HLLZM 3,TTNETW(3) ; Clear ttnetw except for newnvb SETZM NVTOPF(3) ; Clear option status OKSKED EXCH 2,3 DPB 1,PTNETI ; Remeber units DPB 3,PTNETO CALL TTCOBI CALL TTCIBF ; Clear buffers MOVEI 1,3 DPB 1,[POINT 2,TTFLGS(2),33] MOVEI 1,1 DPB 1,[POINT 2,TTFLGS(2),29] MOVEI 1,0(2) ; Return line number AOS 0(P) ; Return good RET ; Close a full duplex net tty connection NVTDET: PUSH P,2 SKIPL TTFORK(2) ; Line attached? CALL NVTCOF ; Yes, initiate carrier off psi MOVE 2,0(P) SKIPG TTNETW(2) ; Reasonable units? JRST NVTDT1 ; No LDB IMPUN,PTNETI ; Input unit CALL NVTCLZ ; Close it MOVE 2,0(P) LDB IMPUN,PTNETO ; Output unit CALL NVTCLZ ; Close it NVTDT1: POP P,2 SETZM NVTOPF(2) SETOM TTNETW(2) SETZM TTPSI(2) CALL TTCOBI CALL TTCIBF RET PNVT: POINT 18,NETBUF(IMPUN),35 ; Used to get nvt line number ; Called from tci NVTCAP: ; Alternate name NETCAP: SKIPGE TTNETW(2) ; Still connected? RET ; No PUSH P,IMPUN PUSH P,2 NOINT ; Protect any possible ilocks CALL CKNNVT ; If not new nvt JRST NETCA1 ; Skip sending ga CALL NVTXGA ; SEND GA IF NEEDED NETCA1: LDB IMPUN,PTNETI SKIPN NETBAL(IMPUN) CALL NVTRAL ; Probably only 1st time, or after cfibf OKINT POP P,2 POP P,IMPUN RET ; Check if this nvt is using new protocol CKNNVT: PUSH P,1 MOVSI 1,NEWNVB TDNE 1,TTNETW(2) AOS -1(P) POP P,1 RET ; Check for special nvt output processing ; Called from tcoutx for nvt's NVTCHO: PUSHJ P,CKNNVT ; Check if new nvt RET ; Not. no special processing PUSH P,1 ; Save character MOVSI 3,NVTCRP TDNE 3,TTNETW(2) ; Was previous char cr? JRST [ ANDCAM 3,TTNETW(2) ; Yes, clear it CAIE 1,12 ; Must be followed by lf CAIN 1,0 ; Or null JRST .+1 SETZ 1, ; If not follow it with null PUSHJ P,TCOBQ MOVE 1,0(P) JRST .+1] CAIN 1,IACCH ; Iac? PUSHJ P,TCOBQ ; Yes. double the special character POP P,1 RET ; Set NVTCRP called from TTYSRV NVTXCR: CALL CKNNVT RET MOVSI 3,NVTCRP IORM 3,TTNETW(2) RET ; Called from tcout NTTCSO: AOS TTNOF ; Request tty scan AOS IMPFLG RET ; CHECK FOR ECHOS DONE BY RCTE ; RETURNS ; +1 ; NO RCTE ACTION ; +2 ; CHARACTER NOT A BREAK CHARACTER ; +3 ; CHARACTER IS A RCTE BREAK ; THE 400 BIT IS SET IN THE CHARACTER IN AC1 IF RCTE DID THE ECHO. NVTRCC::CAIL 2,NVTLO CAILE 2,NVTHI JRST RSKP PUSH P,3 ; STASH AC3 MOVEI 3,(1B) TDNN 3,NVTOPF(2) JRST NVTRC1 ; RCTE NOT ON MOVEI 3,0(1) ; THE CHARACTER ANDI 3,177 ; RETAIN LOW BITS LSH 3,-2 ; DIVIDE BY 4 BYTES PER WORD TRNE 1,2 ; IF SECOND TWO BYTES WANTED SKIPA 3,CHWTB(3) ; GET THEM MOVS 3,CHWTB(3) ; ELSE GET FIRST TWO BYTES TRNN 1,1 ; IF BYTE 0 OR 2 LSH 3,-9 ; SHIFT OVER HRROS 3 AND 3,TTBRKC(2) ; RETAIN BITS SPECIFIED AS BREAKS TRNN 3,777 ; IS THIS CHAR ONE OF THEM? LSH 3,-1 ; YES, SHIFT BIT 15 INTO BIT 16 TLNE 3,2 ; WAS ECHO SUPPRESSED? NVTRC1: AOSA -1(P) ; YES, INDICATE RCTE HAS DONE NOUGHT IORI 1,400 ; ELSE INDICATE ECHO GENERATED POP P,3 ; RESTORE AC3 RET ; Send ga NVTXGA: CAIL 2,NVTLO CAILE 2,NVTHI RET MOVSI 1,NVTGAB TDNN 1,TTNETW(2) ; GA SUPPRESSED CALL CKNNVT ; OR NOT NEW PROTOCOL? JRST NVTXG1 MOVEI 1,GACH CALL NVTSSP NVTXG1: MOVEI 3,(1B) TDNN 3,NVTOPF(2) ; IS RCTE TURNED ON? RET ; NO. RETURN LDB 1,PBRCNT ADDI 1,1 CAILE 1,MAXBRC BUG(CHK, ) DPB 1,PBRCNT MOVSI 3,NVTWKS ANDCAM 3,TTNETW(2) ; CANCEL WAKEUP SEEN NVTRRR: PUSH P,BHC+0 ; ASSUME ZERO COMMAND MOVSI 3,NVTRCS TDNN 3,TTNETW(2) ; UNLESS ANY CHANGE IN STATE? JRST NVTRR1 ; NO, BYPASS THIS NONSENSE. CALL GTBRKC ; GET BREAK CLASSES MOVEM 1,0(P) ; SAVE THAT CALL GTSPCC IORM 1,0(P) ; MUST BREAK ON ALL OF THEM SKIPE 1 ; ANY SPECIAL BREAKS? MOVEI 1,2 ; YES, SUPPRESS ECHO OF BREAKS MOVE 3,TTFLGS(2) TRNN 3,3B25 ; NO ECHO WANTED? IORI 1,6 ; SUPPRESS ALL ECHOES TRC 3,3B25 TRCN 3,3B25 ; SUPPRESS ECHOES OF BREAKS? IORI 1,2 ; YES, ... IORI 1,11 ; CAUSE BREAK CLASS TO CHANGE HRLM 1,(P) ; SAVE THE COMMAND SKIPA 1,[^D10] ; NEED 4 CHARS FOR BREAK CLASSES NVTRR1: MOVEI 1,6 ; NEED 6 FOR SB ETC CALL NVTRSV ; RESERVE SPACE JRST [ SUB P,BHC+1 RET] MOVEI 1,SBCH CALL NVTSSP ; SEND IAC-SB MOVEI 1,RCTOPT CALL TCOBQ ; SAY WHICH OPTION WE ARE CHANGING HLRZ 1,0(P) ; GET COMMAND CALL TCOB ; SEND THE COMMAND JUMPE 1,NVTRR3 ; NO CHANGE, SKIP THE FOLLOWING HRRZ 1,0(P) ; GET NEW BREAK CLASSES LSH 1,-8 ; GET HIGH ORDER BYTE CALL TCOB ; SEND IT HRRZ 1,0(P) ; AND LOW ORDER TOO. ANDI 1,377 CALL TCOB ; SEND LOW ORDER BYTE NVTRR3: MOVEI 1,SECH CALL NVTSSP ; SEND SE LDB 1,PBRCNT ; GET OUTSTANDING BREAKS POP P,3 SKIPE 3 MOVEM 3,TTBRKC(2) ; SET NEW CURRENT BREAK CLASSES SOS 1 ; DECREMENT OUTSTANDING BRKS DPB 1,PBRCNT ; STORE BACK MOVSI 3,NVTRCS ANDCAM 3,TTNETW(2) ; CANCEL STATE CHANGE OKSKED JUMPN 1,NVTRRR ; REPEAT IF BREAKS STILL OUTSTANDING RET ; TABLE OF BREAK CLASS FOR EACH CHARACTER U==1 L==2 N==4 FC==10 CC==20 P6==40 P7==100 P8==200 P9==400 CHWTB: BYTE(9)CC,CC,CC,CC,CC,CC,CC,CC ; ^@ - ^G BYTE(9)FC,FC,FC,FC,FC,FC,CC,CC ; ^H - ^O BYTE(9)CC,CC,CC,CC,CC,CC,CC,CC ; ^P - ^W BYTE(9)CC,CC,CC,CC,CC,CC,CC,FC ; ^X - EOL BYTE(9)P9,P6,P8,P8,P8,P8,P8,P8 ; SPACE - ' BYTE(9)P7,P7,P8,P8,P6,P8,P6,P8 ; ( - / BYTE(9)N,N,N,N,N,N,N,N ; DIGITS BYTE(9)N,N,P6,P6,P7,P8,P7,P6 ; 8, 9 - ? BYTE(9)P8,U,U,U,U,U,U,U ; @ - G BYTE(9)U,U,U,U,U,U,U,U ; H - O BYTE(9)U,U,U,U,U,U,U,U ; P - W BYTE(9)U,U,U,P7,P8,P7,P8,P8 ; X - _ BYTE(9)P8,L,L,L,L,L,L,L ; ' - g BYTE(9)L,L,L,L,L,L,L,L ; h - o BYTE(9)L,L,L,L,L,L,L,L ; p - w BYTE(9)L,L,L,P7,P7,P7,P8,CC ; x - RUBOUT ; GET TERMINAL BREAK CLASSES GTBRKC: SETZ 1, MOVE 3,TTFLGS(2) TRNE 3,1B23 ; BREAK ON ALPHANUMERICS TRO 1,7 ; UPPER AND LOWER CASE AND NUMBERS TRNE 3,1B22 ; PUNCTUATION TRO 1,740 TRNE 3,1B21 ; NON-FORMATTING CONTROLS TRO 1,20 TRNE 3,1B20 ; FORMATTERS TRO 1,10 RET ; GET BREAK CLASS FOR CHARACTERS NEEDING SPECIAL ECHOES GTSPCC: CALL TTYGPI## ; GET PI CHARACTERS AS COCFORMAT PUSH P,1 ; SAVE PUSH P,3 CALL TTRCOC## ; GET CONTROL CHAR OUTPUT MODES ANDCMI 3,377 ; ONLY CONTROL CHARACTERS IORI 3,2B<40*2-^D36+1> ; FAKE A NORMAL ECHO FOR SPACE ANDCM 3,0(P) ; FORCE ZEROES FOR INT CHARS ANDCM 1,-1(P) XOR 1,NVTNMD ; COMPARE TO ASSUMED ECHO MODE XOR 3,NVTNMD+1 PUSH P,[FC] ; ASSUME NEED FORMATTERS TDZN 1,[BYTE (2)0,0,0,0,0,0,0,0,3,3,3,3,3,3] TDNE 3,[BYTE (2)0,0,0,0,0,0,0,0,0,0,0,0,0,3] SKIPA SETZM 0(P) ; NOT NEEDED AFTER ALL TDZN 1,[BYTE (2)3,3,3,3,3,3,3,3,0,0,0,0,0,0,3,3,3,3] TDNE 3,[BYTE (2)3,3,3,3,3,3,3,3,3,3,3,3,3,0,0,3] MOVEI 1,CC ; NEED SPECIAL ECHO FOR NON-FORMATTERS IOR 1,0(P) TRNE 3, ; SPACE? IORI 1,P9 ; NEED SPECIAL ECHO FOR SPACE SUB P,BHC+3 RET ; NORMAL MODES FOR ECHO (MUST AGREE WITH THAT IN USER TELNET) NVTNMD: BYTE (2)0,0,0,0,0,0,0,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2 ; RCTE SET NVTWKS NVTXWW::CAIL 2,NVTLO CAILE 2,NVTHI RET PUSH P,3 MOVSI 3,NVTWKS IORM 3,TTNETW(2) POP P,3 RET ; RCTE CHECK FOR READING BREAK CHARACTERS AND SEND RCTRST IF NEEDED NVTXWK::CAIL 2,NVTLO ; IS THIS AN NVT? CAILE 2,NVTHI RET ; NO SKIPL TTNETW(2) ; THAT IS STILL CONNECTED CALL CKNNVT ; AND USING NEW PROTOCOL RET ; NO, RETURN PUSH P,3 ; PRESERVE AC3 MOVEI 3,(1B) TDNN 3,NVTOPF(2) ; RCTE OPTION TURNED ON? JRST NVTXWX ; NO, GET OUT MOVSI 3,NVTWKS TDNN 3,TTNETW(2) ; JUST SAW WAKEUP? JRST NVTXW1 ; SEND A RCTE RESET PUSH P,1 CALL NVTXGA ; NOW SEND THIS ONE POP P,1 ; RESTORE AC1 NVTXW1: CALL WAKCHK## ; IS THIS A WAKEUP CHAR? JRST NVTXWX ; NO MOVSI 3,NVTWKS ; YES IORM 3,TTNETW(2) ; REMEMBER WE SAW IT NVTXWX: POP P,3 RET ; NVT CLEAR INPUT BUFFER ; NEEDS NEW PROTOCOL FEATURE TO WORK PROPERLY NVTCIB::CAIL 2,NVTLO CAILE 2,NVTHI RET SKIPL TTNETW(2) ; STILL CONNECTED TO NETWORK? CALL CKNNVT ; AND NEW STYLE NVT? RET ; NO. DONE MOVEI 1,RCTOPT ; USE RCTE OPTION IN REVERSE SKIPN NSKED CALL NVTNGT ; TO CLEAR INPUT BUFFER SETZ 1, DPB 1,PBRCNT RET ; NOTE CHANGE IN PSI SET NVTXPI::CAIL 2,NVTLO CAILE 2,NVTHI RET CALL CKNNVT RET PUSH P,3 MOVE 3,NVTOPF(2) ; GET CURRENTLY ON OPTIONS TRNN 3,(1B) JRST NVTXP1 MOVSI 3,NVTRCS IORM 3,TTNETW(2) ; NOTE STATE CHANGE NVTXP1: POP P,3 RET ; Called from ttcobf NVTCOB: SKIPG TTNETW(2) RET NOINT ; Protect possible ilocks PUSH P,IMPUN PUSH P,2 LDB IMPUN,PTNETO LDB 1,PLIDX LDB 2,LTLINK LDB 1,LTHOST CALL IMPINS POP P,2 POP P,IMPUN CALL CKNNVT ; New style nvt? JRST NVTCO1 ; Old style MOVEI 1,DMCH CALL NVTSSP ; Send new dm OKINT RET NVTCO1: MOVEI 1,200 CALL TCOB OKINT RET ; Perform dobe sequence called from ttdobe NVTDOB: CALL CKNNVT ; New nvt? RET ; No. just return MOVEI 1,TMKOPT ; Timing mark option PUSHJ P,NVTNGT ; Go negotiate option JFCL ; Ignore failure RET ; Check stpar argument and negotiate any needed options NVTPAR: CAIL 2,NVTLO CAILE 2,NVTHI RET ; Return if not nvt CALL CKNNVT ; New nvt? JRST [ PUSH P,1 XOR 1,TTFLGS(2) TRNN 1,14 JRST NVTPAX MOVE 1,0(P) TRNE 1,14 ; Is new full? SKIPA 1,[204] ; No. send "you echo" MOVEI 1,203 ; Yes. send "i echo" CALL TCOB JRST NVTPAX] MOVE 3,1 ; Copy new state PUSH P,1 ; Save XOR 1,TTFLGS(2) ; Get difference TRNN 1,14 ; Change in echo? JRST NVTPA1 ; No, try next PUSH P,1 ; Save difference TRNN 3,14 ; Negotiate on? SKIPA 3,[NVTNGT] ; Yes MOVEI 3,NVTNGF ; No MOVEI 1,ECHOPT+WILOPT CALL @3 JRST [ MOVEI 1,14 IORM 1,-1(P) JRST .+1] POP P,1 NVTPA1: ; Other checks go here if any NVTPAX: POP P,1 RET ; Check sfmod argument and negotiate any options needed NVTMOD: CAIL 2,NVTLO CAILE 2,NVTHI RET ; Return if not nvt CALL CKNNVT ; New nvt? RET ; No. do nothing MOVE 3,1 ; Copy of argument PUSH P,1 ; Save it XOR 1,TTFLGS(2) ; Get bit difference PUSH P,1 TRNN 1,100 ; Change in binary? JRST NVTMO1 MOVE 3,0(P) TRNN 3,100 SKIPA 3,[NVTNGT] MOVEI 3,NVTNGF PUSH P,3 MOVEI 1,BINOPT CALL @3 JRST [ MOVEI 1,100 IORM 1,-1(P) SUB P,BHC+1 JRST NVTMO1] MOVEI 1,BINOPT+WILOPT POP P,3 CALL @3 JRST [ MOVEI 1,BINOPT CALL NVTNGF JFCL MOVEI 1,100 IORM 1,0(P) JRST NVTMO1] NVTMO1: MOVE 3,0(P) ; GET BIT DIFFERENCE MOVEI 1,(1B) TDNE 1,NVTOPF(2) ; NO RCTE ON? TRNN 3,77B23+3B25 ; OR NO CHANGE IN WAKEUP SET JRST NVTMO2 ; NO,, SKIP FOLLOWING MOVSI 3,NVTRCS IORM 3,TTNETW(2) ; NOTE CHANGE IN RCTE SETTINGS NVTMO2: POP P,1 ; GET BACK DIFFERENCE POP P,1 ; AND ARGUMENT RET ; Negotiate an option NVTNGT: MOVE 3,[NVTXWL,,NVTXDO] CALL NVTNGC AOS 0(P) RET NVTNGF: MOVE 3,[NVTXWN,,NVTXDN] NVTNGC: CAIL 1,MAXOPT RET PUSH P,1 PUSH P,3 MOVE 3,BITS(1) IORM 3,NVTOPF(2) ; Set option negotiation in progress bit TRZE 1,WILOPT MOVSS 0(P) POP P,3 CALL 0(3) ; Say "do, wil, dont, wont" MOVE 1,0(P) ROT 1,-9 ; Into top 9 bits TLO 1,(2) ; Line number in 9-17 HRRI 1,NVTNTT ; Activation test JSYS EDISMS MOVSI 1,NEGTMO ANDCAM 1,TTNETW(2) ; Cancel any time-out in progress POP P,1 MOVS 3,BITS(1) TDNN 3,NVTOPF(2) AOS 0(P) ; Skip if successful RET NVTNTT: LDB 3,[POINT 9,1,26] ; Get option number MOVE 3,BITS(3) ANDI 1,777 ; Line number SKIPL TTNETW(1) ; Satisfied if disconnected TDNN 3,NVTOPF(1) JRST 1(4) ; Negotiation complete JRST 0(4) ; Check overdue negotiations NEGCHK: MOVE 2,NVTPTR ; Pointer to nvts NEGCKL: SKIPGE TTNETW(2) ; Attached? JRST NEGCKE ; No, skip it MOVSI 3,NEGTMO HLLZ 1,NVTOPF(2) ; Get outstanding options JUMPE 1,[ANDCAM 3,TTNETW(2) ; None, cancel time-out if any JRST NEGCKE] XORB 3,TTNETW(2) ; Yes, count counter TLNN 3,NEGTMO ; Count from 1 to 0? HRRZS NVTOPF(2) ; Yes, cancel outstanding option NEGCKE: AOBJN 2,NEGCKL MOVE 1,TODCLK ADDI 1,NEGTM0 MOVEM 1,NEGTIM RET ; Move tty output to net buffers NETTCS: MOVEI 3,(1B) TDNE 3,NVTOPF(2) CALL CKNNVT JRST NETTC8 ; NO RCTE LDB 3,PBRCNT ; NEED TO SEND RESET? SKIPE 3 CALL NVTRRR ; YES, TRY TO SEND NETTC8: SKIPGE TTNETW(2) ; Still connected? JRST NETTCF ; No, just clear buffer SETZ 4, ; Init char count MOVEI 6,0(P) ; Use stack as local buffer HRLI 6,1000 ; Construct 8-bit byte ptr LDB IMPUN,PTNETO ; Get unit index MOVE 7,NETSTS(IMPUN) TLNN 7,EOTF TLNE 7,DEDF JRST NETTCF ; Yes, don't send any more PUSH P,2 ; Preserve line number LDB 1,PLIDX ; Get link index PUSHJ P,PKCHK ; Check how many bits can be sent now MOVE 7,2 POP P,2 JUMPLE 7,PKULCK ; If none, give up CAILE 7,100 ; But limit to 100 (20 wds on stack) MOVEI 7,100 ADD P,[20,,20] ; Reserve space on stack MOVE 3,6 ; Save byte ptr NETTC2: SOJL 7,NETTC4 ; Count down limit NOSKED SKIPE TTECT(2) ; Chars from echo buffer? JRST [ CALL NETTEO ; Yes, get one JRST NETTC1] SKIPE TTOCT(2) ; Chars from output buffer? JRST [ CALL NETTOO ; Yes, get one JRST NETTC1] PUSH P,3 ; Preserve ac3 CALL TTRLOB ; Buffers empty, release them POP P,3 OKSKED NETTC4: JUMPE 4,[SUB P,[20,,20] ; No chars to send, clear stack JRST PKULCK] MOVNI 1,^D8 IMUL 1,4 ; Adjust allocation ADDM 1,NETBAL(IMPUN) LDB 1,PLIDX ; Get conn index PUSH P,2 CALL PKMSG1 POP P,2 SUB P,[20,,20] ; Clear stack JRST NETTC8 ; See if any more NETTCF: CALL TTCOBI ; FLUSH OUTPUT BUFFER LDB 1,PLIDX RET NETTC1: OKSKED IDPB 1,6 ; Put char on stack buffer AOJA 4,NETTC2 ; Get chars for output from echo buffer NETTOO: SKIPN 1,TTOOUT(2) RET ; Stuff vanished, return 0 TDNN 1,WRPMSK HRR 1,1-TTSIZ(1) MOVEM 1,TTOOUT(2) ILDB 1,TTOOUT(2) SOS TTOCT(2) RET ; Get chars for output from echo buffer NETTEO: SKIPN 1,TTEOUT(2) RET ; Stuff vanished, return 0 TDNN 1,WRPMSK HRR 1,1-TTSIZ(1) MOVEM 1,TTEOUT(2) ILDB 1,TTEOUT(2) SOS TTECT(2) RET ; Unpack message into tty buffers ; Impun/socket table index (unit) ; 1/ LT INDEX NVTUPI: PUSH P,1 ; Preserve ac1 IMSCLK(IMCNVI) ; Charge to imcnvi PUSH P,[0] ; Count bytes unpacked NVTUPL: MOVE 1,-1(P) ; Get link table index CALL UPBYT ; Get byte JRST NVTUPD AOS 0(P) ; Count bytes LDB 2,PNVT ; Get line number MOVE 1,3 LDB 3,NVTSTP ; Get the current command state of this SETZ 4, DPB 4,NVTSTP CALL @NVTSTD(3) ; Dispatch on it JRST NVTUPL NVTSTD: NVTNRM ; Nothing deferred NVTWIL ; Deferred will NVTWNT ; Deferred wont NVTDO ; Deferred do NVTDNT ; Deferred dont NVTIAC ; Deferred iac NVTNRM ; Not used NVTNRM ; Not used NVTNRM: CAIL 1,200 JRST NVTCTL ; Process possible nvt control character NVTDCH: LDB 3,TTYLMD JUMPE 3,NVTUPB ; Binary, skip special checks MOVSI 3,IMPTB2 TDNN 3,TTNETW(2) ; Was last ch cr? JRST [ CAIE 1,15 ; NO. IS THIS ONE? JRST NVTUPB ; NO, PROCEED NORMALLY IORM 3,TTNETW(2) ; YES, REMEMBER IT RET] ; AND IGNORE FOR NOW ANDCAM 3,TTNETW(2) ; YES, FORGET THAT MOVEI 1,15 ; AND PROCESS AS CR NOW NVTUPB: SETZ 6, ; No special flags PUSH P,IMPUN NOSKED ; Ttchi expects to be called nosked CALL TTCHI ; Stuff it in tty buffer OKSKED POP P,IMPUN RET NVTUPD: POP P,4 ; Bytes unpacked POP P,1 ; Restore lt index IMUL 4,[-8] ADDB 4,NETBAL(IMPUN) JUMPGE 4,NVTRAL ; Reallocate LDB 2,LTHOST ; Get host BUG(IMH,,X) SETZM NETBAL(IMPUN) JRST NVTRAL ; Telnet control codes received ; 1/ code ; 2/ line NVTCTL: SKIPGE TTNETW(2) ; If no sockets attached, JRST NVTDCH ; Ignore char PUSHJ P,CKNNVT ; New style nvt? JRST NVTCT0 ; No, look for old style commands CAIE 1,IACCH ; Yes, is iac JRST NVTDCH ; No, continue processing JRST NVTCL4 ; Yes. take care of it NVTCT0: CAIN 1,202 ; Nop RET CAIN 1,200 ; Sync char? JRST NVTCL1 CAIN 1,203 ; Echo off? JRST NVTCL2 CAIN 1,204 ; Echo on? JRST NVTCL3 JRST NVTDCH NVTCL1: LDB 1,PTINTC ADDI 1,1 ; Sync counts 1, ins counts -1 DPB 1,PTINTC RET NVTCL3: TDZA 1,1 ; Zero ac and skip NVTCL2: MOVEI 1,3 DPB 1,[POINT 2,TTFLGS(2),33] ; Set duplex mode full/half RET ; Process iac NVTCL4: MOVEI 3,DFRIAC DPB 3,NVTSTP RET ; Process byte after iac NVTIAC: CAIGE 1,SECH RET ; Not a valid command MOVSI 3,NEWNVB IORM 3,TTNETW(2) ; Mark this new protocol SETZ 3, ; Next state if any XCT NVTDTB-SECH(1) ; Dispatch on the character JRST NVTDCH ; Special function character DPB 3,NVTSTP ; Next state RET NVTDTB: RET ; (360) end of subnegotiation RET ; (361) nop -- ignore JRST NVTCL1 ; (362) new data mark RET ; (363) break -- ignore MOVEI 1,3 ; (364) ip -- convert to ^c MOVEI 1,"O"-100 ; (365) ao -- convert to ^o MOVEI 1,"T"-100 ; (366) ayt -- convert to ^t MOVEI 1,"A"-100 ; (367) ec -- convert to ^a MOVEI 1,"Q"-100 ; (370) el -- convert to ^q RET ; (371) ga -- ignore RET ; (372) sb -- shouldn't get this TROA 3,DFRWIL ; (373) defer will TROA 3,DFRWNT ; (374) defer wont TROA 3,DFRDO ; (375) defer do TROA 3,DFRDNT ; (376) defer dont JFCL ; (377) iac iac -- iac ; Send special character NVTSSP: PUSH P,1 MOVEI 1,2 PUSHJ P,NVTRSV ; Reserve space in buffer (nosked) JRST [ POP P,1 RET] HRROI 1,IACCH ; SAME AS 377, BUT PREVENT ITS DOUBLING CALL TCOB ; CALL TCOB TO GET CR-NULL IF NEEDED POP P,1 CALL TCOBQ OKSKED RET ; Reserve space in buffer for characters specified in 1 NVTRSV: NOSKED ; Make sure space doesn't disappear LDB 3,TTOMAX SUB 3,TTOCT(2) ; Space in output buffers CAML 3,1 JRST RSKP ; Enough room, return skip OKSKED MOVE 3,FORKX CAMN 3,NCPFRK ; Is this the ncp fork? JRST NVTRV1 ; Yes, attempt to send the buffer PUSH P,1 ; No. wait for space MOVEI 1,TCOTST HRL 1,2 JSYS EDISMS ; Wait for space POP P,1 JRST NVTRSV NVTRV1: LDB IMPUN,PTNETO ;@GET UNIT NUMBER PUSH P,1 LDB 1,PLIDX ; Get lt index HRRZ 3,IMPLT4(1) ; Get msg alloc SKIPE 3 MOVE 3,NETBAL(IMPUN) ; Get bit alloc if non-zero msg alloc LSH 3,-3 ; Convert to bytes CAMGE 3,0(P) ; At least what we need? JRST [ POP P,1 ; No. give up RET] PUSH P,2 ; P@PRESERVE LINE NUMBER CALL NETTC8 ; s, send as much as possible POP P,2 ; RESTORE LINE NUMBER POP P,1 JRST NVTRSV ; And try again ; Send wont (refuse) NVTRFU: MOVEI 1,WNTCH ; Send reply in 1 for option on stack NVTSRP: PUSH P,1 MOVEI 1,3 CALL NVTRSV ; Reserve space for three characters JRST [ SUB P,BHC+2 RET] HRROI 1,IACCH ; SAME AS 377 BUT PREVENT DOUBLING PUSHJ P,TCOB ; USE TCOB TO GET CR-NULL IF NEEDED POP P,1 PUSHJ P,TCOBQ POP P,1 PUSHJ P,TCOBQ OKSKED RET ; Send will NVTXWL: PUSH P,1 ; Save option NVTSWL: MOVEI 1,WILCH ; Enter here when option is on stack JRST NVTSRP ; Send reply ; Send no reply NVTSNR: SUB P,BHC+1 ; No reply necessary or possible RET ; Send wont NVTXWN: PUSH P,1 ; Save option NVTSWN: MOVEI 1,WNTCH ; Enter here when option already pushed JRST NVTSRP ; Send "do" NVTXDO: PUSH P,1 ; Save option NVTSDO: MOVEI 1,DOCH ; Enter here when option already pushed JRST NVTSRP ; Send "dont" NVTXDN: PUSH P,1 ; Save option NVTSDN: MOVEI 1,DNTCH ; Enter here when option already pushed JRST NVTSRP ; Process "do" NVTDO: CAIL A,WILOPT JRST NVTDO1 MOVE 3,BITS+WILOPT(1) TDNE 3,NVTOPF(2) JRST NVTWI2 NVTDO1: PUSH P,1 ; Remember the option MOVSS 3 ; Put bit in "options on" half TDNE 3,NVTOPF(2) ; Is the option on? JRST NVTSNR ; Yes, send no reply CAIGE 1,NVTLOP ; Do we know about this option CALL @NVTDOD(1) ; Yes. attempt execution JRST NVTRFU ; Can't do it -- refuse IORM 3,NVTOPF(2) ; Set option on JRST NVTSWL ; And send "will" NVTDOD: R ; Binary xmit -- refuse for now NVTECN ; Turn echos on R ; Reconnect -- refuse for now NVTSGA ; Suppress ga -- wonderful news R ; Message size -- refuse R ; Status -- refuse NVTDTM ; Timing mark -- try to do it NVTDRC ; Remote controlled trans & echo NVTLOP=.-NVTDOD ; Action routines for "do" ; Turn echoes on NVTECN: MOVEI 1,3B33 ANDCAM 1,TTFLGS(2) ; Set to full duplex JRST RSKP ; Set suppress ga bit NVTSGA: MOVSI 1,NVTGAB IORM 1,TTNETW(2) JRST RSKP ; Do timing mark protocol NVTDTM: JRST RSKP ; TURN ON RCTE NVTDRC: MOVSI 1,NVTRCS ; SEND CURRENT STATE INFO WITH FIRST CMD IORM 1,TTNETW(2) SETZM TTBRKC(2) ; CLEAR BREAK STATUS INFO MOVEI 1,1 DPB 1,PBRCNT ; SEND ONE RCTE COMMAND TO START JRST RSKP ; We are happy to do RCTE ; Process "dont" NVTDNT: CAIL A,WILOPT JRST NVTDN1 MOVE 3,BITS+WILOPT(1) TDNE 3,NVTOPF(2) JRST NVTWN2 NVTDN1: PUSH P,1 MOVSS 3 ; Put bit in "option on" half TDNN 3,NVTOPF(2) ; Option already off? JRST NVTSNR ; Yes. send no reply CAIGE 1,NVTLOP ; Do we know about this option? CALL @NVTDND(1) ; Yes. perform action ANDCAM 3,NVTOPF(2) ; Clear the option JRST NVTSWN ; And send "won't" NVTDND: R ; Dilemma -- he wants off, but we can't NVTECF ; Echo off R ; Option not on, no reply NVTAGA ; He wont suppress ga -- nuts R ; Message size option R ; Status option R ; Timing mark -- huh? R ; Turn off RCTE ; "dont" action routines ; Turn echos off NVTECF: MOVEI 1,3B32 IORM 1,TTFLGS(2) RET ; Turn off suppress ga bit NVTAGA: MOVSI 1,NVTGAB ANDCAM 1,TTNETW(2) RET ; Process "will" NVTWIL: CAIL A,WILOPT ; Only wilopt options JRST NVTWI1 ; Others cannot be outstanding MOVE 3,BITS(1) ; Get the bit for the option TDNN 3,NVTOPF(2) ; Is this option outstanding? JRST NVTWI1 ; No. NVTWI2: MOVS 1,3 IORM 1,NVTOPF(2) ; Set will bit ANDCAM 3,NVTOPF(2) ; And clear outstanding bit RET NVTWI1: PUSH P,1 ; save the option MOVSS 3 ; Put bit in "optons on" half TDNE 3,NVTOPF(2) ; Is option already on? JRST NVTSNR ; Yes. send no reply CAIGE 1,NVTLOP CALL @NVTWID(1) ; Call action routine JRST NVTSDN ; Unimplemented option or can't comply IORM 3,NVTOPF(2) ; Done. set option "on" JRST NVTSDO ; And send "do" NVTWID: R ; Will binary -- dont R ; Will echo -- dont R ; Reconnect -- dont RSKP ; Suppress ga -- do, do, do , do! R ; Message size -- dont R ; Status -- dont R ; Timing mark -- huh? R ; What's he trying to do? ; Process "wont" NVTWNT: CAIL 1,MAXOPT JRST NVTWN1 ; Option not handled MOVE 3,BITS(1) ; Get bit for option TDNN 3,NVTOPF(2) ; Is this option outstanding JRST NVTWN1 ; No. request NVTWN2: HLR 3,3 ; Yes. neg acknowledge ANDCAM 3,NVTOPF(2) ; Clear both outstand and will flags RET NVTWN1: PUSH P,1 MOVSS 3 ; Put bit in "options on" half TDNN 3,NVTOPF(2) ; Option already off? JRST NVTSNR ; Yes. send no rply ANDCAM 3,NVTOPF(2) ; Strangely enough, the user end JRST NVTSDN ; Never has any options to turn off ; Re-allocate if needed to bring allocation up to operating level ; Impun/socket table index (unit) NTTRC3: ; Known to ncp by this tag NVTRAL: CALL LCKNCP ; Prevent ncp changes MOVSI 1,DEDF TLO 1,EOTF TDNE 1,NETSTS(IMPUN) JRST ULKNCP ; Connection dead or done LDB 2,PNVT ; Pick up line number LDB 3,TTIMAX ; Capacity of line SUB 3,TTICT(2) ; Gives space now in line buffer JUMPE 3,[LDB 1,PTINTC ; If full, check for ins received TRNE 1,4 ; Count is sync-ins, 3 bit field MOVEI 3,1 ; Ins requested, allocate 1 byte JRST .+1] LSH 3,3 ; Imuli 3,8 (byte size) SUB 3,NETBAL(IMPUN) ; Desired all less all now out MOVE 4,3 LDB 1,PLIDX ; Get conn index HRRZ 3,IMPLT4(1) ; Current msg alloc MOVN 3,3 ADDI 3,^D6 ; Raise it to 6 LDB 1,TTIMAX ; Max space in buffer ASH 1,-1 ; One-half CAMGE 4,1 ; Re-allocate if more than half a buffer CAIL 3,4 ; Or if more than 3 msgs SKIPA JRST ULKNCP LDB 1,PFHST LDB 2,PLINK CALL IMPALL JRST ULKNCP ; Lookup host-link ; 1/ b20-27, host; b28-35, link; b18, direction (1=send) LNKLUK: PUSH P,3 MOVSI 3,(1B1) ; Bit says no deleted entry found LNKL6: PUSH P,4 PUSH P,1 ; Save arg IMUL 1,[5654123] ; Compute hash LSH 1,-^D9 IDIVI 1,IMPNLK ; Remainder gives initial index POP P,1 PUSH P,2 HRLI 2,-IMPNLK(2) ; Setup ptr for remainder of table LNKL2: HRRZ 4,IMPLT1(2) CAIN 4,0(1) ; Desired entry? JRST [ AOS -3(P) ; Yes, return good MOVEI 1,0(2) JRST LNKL1] ; With table index in 1 TRNE 4,1B19 ; Special? i.e. free or deleted? JRST [ TLNE 3,(1B2) ; Yes, called by rehash or pi level? JRST LNKL4 ; Yes TRNE 4,1B18 ; This a free entry? JRST LNKL3 ; Yes, search done, not found TLZE 3,(1B1) ; This first deleted entry encountered? HRRI 3,0(2) ; Yes, save its position JRST .+1] LNKL5: AOBJN 2,LNKL2 JUMPL 3,[TLNN 3,(1B1) ; Table full, was delete seen? JRST LNKL3 ; Yes, use it JRST IMPB01] ; No, lossage MOVN 2,0(P) ; Wraparound ptr, setup count MOVSI 2,0(2) ; To look up to initial index TLO 3,(1B0) ; Remember wraparound JRST LNKL2 LNKL3: TLNN 3,(1B1) ; Not found, delete encountered? MOVEI 2,0(3) ; Yes, use that for new entry LNKL1: SUB P,BHC+1 ; Flush temp POP P,4 POP P,3 RET LNKL4: TLNE 3,(1B3) ; Pi level call? JRST LNKL5 ; Yes. ignore deleted/free entries MOVEI 4,1B19 ; Make deleted MOVEM 4,IMPLT1(2) JRST LNKL5 ; Special entry used only by rehash routine ; It assumes item will be found, and it sets any 'free' entries ; Encountered to be 'deleted' IMPHFL: PUSH P,3 MOVSI 3,(1B2) ; Controls action on special entries JRST LNKL6 ; Special entry from imodn2 to find entry to store retransmit buffer ; Searches entire table for entry regardless of deletes and frees IMPPIL: PUSH P,3 MOVSI 3,(1B2+1B3) JRST LNKL6 ; Routine to garbage collect hash table. ; Sets all deleted entries to free then calls lookup ; routine to mark all needed entris deleted to enable all entries ; to be found. ; Lookup routine will change any 'free' entries passed over during ; a search to 'deleted'. thus all 'deleted' entries not currently ; Necessary will be flushed. IMPGC: IMSCLK(IMCGC) ; Charge time to imcgc ILOCK SETZM LNKNDL ; Clear delete count MOVSI 7,-IMPNLK ; Prepare to scan link table MOVEI 1,1B19 MOVEI 2,1B19!1B18 IMPGC1: TDNE 1,IMPLT1(7) ; Free or deleted? MOVEM 2,IMPLT1(7) ; Yes, set it to free AOBJN 7,IMPGC1 MOVSI 7,-IMPNLK ; Prepare to scan again IMPGC2: HRRZ 1,IMPLT1(7) ; For every entry TRNE 1,1B19 ; That is not JRST IMPGC3 ; Deleted or free CALL IMPHFL ; Marked necessary deleted entries BUG(CHK,) IMPGC3: AOBJN 7,IMPGC2 IUNLK RET ; Unpack byte from current msg for a connection ; 1/ connection index ; Returns byte in 3 UPBYT: ILOCK HLRZ 2,IMPLT4(1) ; Get current buffer JUMPN 2,UPBYT1 CALL UPBGNB ; No buffer, try to get one RET ; Failed, return noskip UPBYT1: ILDB 3,1(2) ; Get byte, byte ptr in bfr header SOSG 2(2) ; Count down bytes in bfr CALL UPBRB ; Now empty, release bfr IUNLK AOS 0(P) RET ; Unpack message ; 1/ LT INDEX ; 3/ STORE BYTE POINTER ; 4/ MAX BYTE COUNT UPMSG: ILOCK PUSH P,3 ; Save store pointer HLRZ 2,IMPLT4(1) ; Get current buffer JUMPN 2,.+3 CALL UPBGNB ; None, try to get one JRST UPMSG5 ; Failed, return bad MOVE 3,2(2) ; Get buffer count CAML 3,4 MOVE 3,4 ; Use minimum count SUB 4,3 ; Update count PUSH P,4 ; Save updated count MOVN 4,3 ADDM 4,2(2) ; Update buffer count PUSH P,1 ; Save lt index MOVE 1,1(2) ; Get buffer pointer EXCH 2,-2(P) ; Save buffer location, get tgt MOVEI 4,0 ; Transfer monitor to monitor PUSHJ P,BYTBLT ; Transfer the bytes EXCH 2,-2(P) ; Save updated tgt, get buffer loc MOVEM 1,1(2) ; Store update buffer pointer POP P,1 ; Restore lt index UPMSG4: POP P,4 SKIPG 2(2) ; Imp bfr now exhausted? CALL UPBRB ; Yes, release it UPMSG2: AOS -1(P) IUNLK UPMSG5: POP P,3 RET ; Try to get next input bfr UPBGNB: HLRZ 2,IMPLT3(1) ; Check queue of in bfrs JUMPE 2,UPBG1 ; None PUSH P,4 HLLZ 3,0(2) ; Unqueue this buffer JUMPN 3,.+3 MOVEI 4,IMPLT3(1) HRRM 4,IMPLT2(1) ; Make input buffer list empty HLLM 3,IMPLT3(1) ; Output buffer pointer HRLM 2,IMPLT4(1) ; Save current bfr adr PUSH P,1(2) ; Save header in case of error PUSH P,2(2) HRRZ 4,0(2) ; Number words in buffer CAIGE 4,3 ; At least overhead words present? JRST UPBGNE ; No, msg too short LDB 3,[POINT 16,2(2),27] ; Byte count for this buffer JUMPE 3,UPBGNE ; 0 is illegal, but in case... LDB 4,[POINT 8,2(2),11] ; Get byte size MOVEM 3,2(2) ; Leave byte count in full word LDB 3,IMPLBS ; Byte size for connection CAME 3,4 ; Same? JRST UPBGNE ; No LSH 3,^D24 ; Shift to s field of byte ptr HRRI 3,2(2) MOVEM 3,1(2) MOVEI 3,^D36 ; Compute max bytes which could be IDIV 3,4 ; As words*(bytes/wd) HRRZ 4,0(2) ; Number of words IMULI 3,-3(4) ; But not counting overhead CAMGE 3,2(2) ; Actual greater than max? JRST UPBGNE ; Yes, lossage SUB P,BHC+2 POP P,4 AOS 0(P) RET UPBGNE: CALL UPBRB PUSH P,2 MOVEI 2,-3(P) ; Pntr to 1 before saved hdr on stack HRLI 2,9 BUG(IML,,X) POP P,2 SUB P,BHC+2 POP P,4 JRST UPBGNB UPBGNX: SUB P,BHC+2 POP P,4 JRST UPBGNB ; No input ready, return activation test UPBG1: MOVSI 1,0(1) ; Connection index HRRI 1,UPBGT ; Wait for input or closed conn IUNLK RET ; Activation test UPBGT: MOVSI 3,777777 MOVSI 2,(LTDF) ; Check done flag TDNN 2,IMPLT2(1) ; If set, or TDNE 3,IMPLT3(1) ; If bfr(s) appeared JRST 1(4) ; Wakeup JRST 0(4) ; Release input buffer UPBRB: HLRZ 2,IMPLT4(1) ; Get current buffer HRRZS IMPLT4(1) ; Clear field PUSH P,1 CALL RLNTBF ; Release bfr back to pool POP P,1 SOSL IMPLT4(1) ; Count msgs processed RET BUG(CHK,) SETZM IMPLT4(1) RET ; Check connection for output possible ; Called on receipt of rfnm, allocation, etc. ; 1/ connection index ; Do output if rfnm clear, msg alloc non-0, and output exists IMPCKO: ILOCK (JRST IMPROS) ; If can't check now, set request flag IMPKO1: MOVSI 3,(RFNMC!ILCKB) TDNE 3,IMPLT2(1) ; Rfnm out or connection locked? JRST IMPKO2 ; Yes, will try again later HLRZ 2,IMPLT3(1) JUMPN 2,[ CALL IMPQO1 ; If completed bfrs on output queue, JRST IMPKO1] ; Give one to imp to send HLRZ 2,IMPLT4(1) ; See if partial bfr exists JUMPN 2,[ CALL PKQOB ; Complete it and send JRST IMPKO1] LDB 2,LTLINK ; Nothing to do here JUMPE 2,[CALL IMPLL0 JRST IMPKO2] ; Flush conn if ctl link MOVSI 2,(RARRF) TDNN 2,IMPLT2(1) ; Ras requested? JRST IMPKO4 ; No PUSH P,1 ; Yes ANDCAM 2,IMPLT2(1) HLRZ IMPUN,IMPLT1(1) SETZM NETBAL(IMPUN) HLLZS IMPLT4(1) IUNLK LDB 2,LTLINK LDB 1,LTHOST CALL IMPRAS POP P,1 JRST IMPKO3 IMPKO4: IUNLK IMPKO3: HLRZ IMPUN,IMPLT1(1) ; Pick up pseudo-unit MOVSI 2,(LTDF) TDNN 2,IMPLT2(1) ; Done flag set? RET ; No. done ANDCAM 2,IMPLT2(1) ; Only see it once PUSH P,6 ; Preserve ac6 CALL RCFRFN ; Yes, notify ncp POP P,6 RET IMPKO2: IUNLK ; Always returns with lock clear RET IMPROS: AOS IMPNOS RET ; Pack byte for output ; 1/ CONNECTION INDEX ; 3/ BYTE PKBYT: ILOCK HLRZ 2,IMPLT4(1) JUMPN 2,PKBY2 CALL PKBY1 ; No current buffer, get a new one JRST PKBY5 ; No buffers PKBY2: IDPB 3,1(2) MOVSI 3,(ILCKB) ANDCAM 3,IMPLT2(1) ; Clear lock SOSG 2(2) ; Or if bfr now full CALL PKQOB ; Put bfr on output queue CALL IMPKO1 ; Send if possible (does iunlk) AOS 0(P) RET PKBY5: IUNLK CALL IMPB03 JRST PKBYT ; Check maximum bytes that can be sent due to msg alloc restriction ; and partial msg already constructed. Leave connection locked. PKCHK: ILOCK PKCHK0: PUSH P,3 SETZ 2, MOVSI 3,(ILCKB) TDNE 3,IMPLT2(1) ; There should only be one fork trying JRST PKCHK2 ; at a time since files are interlocked ; by fillck, nvt transmission is done by ; Ncp fork and control links have no ; flow control. IORM 3,IMPLT2(1) ; Lock connection so state can't change LDB 3,IMPLBS ; Get byte size HLRZ 2,IMPLT4(1) ; get current buffer JUMPE 2,PKCHK1 ; If none, contribution is zero MOVE 2,2(2) ; Get bytes left IMUL 2,3 ; Times byte size is bits PKCHK1: PUSH P,3 HRRZ 3,IMPLT4(1) ; GET MSG ALLOCATION JUMPG 3,[IMUL 3,MAXBPM ; TIMES BITS PER MESSAGE ADD 2,3 ; ADD TO CURRENT BUFFER RESIDUE JRST .+1] ; AND CHECK AGAINST BIT ALLOCATION POP P,3 ; NO MSG ALLOC., JUST RESTORE 3 CAMLE 2,NETBAL(IMPUN) ; More than bit allocation MOVE 2,NETBAL(IMPUN) ; Yes. limit is that IDIV 2,3 ; Convert to bytes PKCHK2: POP P,3 IUNLK RET ; Unlock connection PKULCK: MOVSI 2,(ILCKB) ANDCAM 2,IMPLT2(1) MOVE 2,IMPLT3(1) ; Any buffers to be sent IOR 2,IMPLT4(1) TLNE 2,-1 JRST IMPCKO ; Yes RET ; No ; Pack msg ; 1/ connection index ; 3/ byte ptr ; 4/ byte count PKMSG: ILOCK PKMSG0: CALL PKMSG2 ; GET THE MESSAGE PACKED UP PUSH P,3 CALL IMPKO1 ; SEND IF POSSIBLE (DOES IUNLK) POP P,3 RET ; SAME AS PKMSG, BUT DOESN'T ATTEMPT TO SEND THE MSG PKMSG1: ILOCK CALL PKMSG2 ; PACK IT UP IUNLK RET ; ROUTINE TO MOVE BYTES FROM SOURCE BUFFER TO NETWORK OUTPUT BUFFER ; 1/ CONNECTION INDEX ; 2/ SOURCE BYTE PTR ; 4/ BYTE COUNT PKMSG2: MOVSI 2,(ILCKB) ; LOCK CONNECTION IORM 2,IMPLT2(1) PUSH P,4 ; SAVE BYTE COUNT HLRZ 2,IMPLT4(1) ; Get current bfr JUMPN 2,PKMS2 PUSH P,4 ; Wasn't one, get a new one PKMS4: CALL PKBY1 JRST PKMS5 POP P,4 CAMLE 4,2(2) ; New buffer big enough? JRST PKMSL ; Message too long PKMS3: PUSH P,1 ; Save connection index MOVE 1,3 ; Source pointer MOVE 3,4 ; Count to 3 MOVNS 4 ADDM 4,2(2) ; Update buffer count ADDM 4,-1(P) ; MAINTAIN RESIDUAL COUNT PUSH P,2 ; Save buffer loc MOVE 2,1(2) ; Target to 2 MOVEI 4,0 ; Mode is monitor to monitor PUSHJ P,BYTBLT ; Transfer bytes EXCH 2,0(P) ; Get buffer location, save updated ptr POP P,1(2) ; Store updated pointer MOVEM 3,4 ; Updated count EXCH 1,0(P) ; Save update source and get lt index PKMSD: MOVSI 3,(ILCKB) ANDCAM 3,IMPLT2(1) SKIPG 2(2) ; Bfr now full? CALL PKQOB ; Yes POP P,3 POP P,4 ; GET BACK RESIDUAL COUNT JUMPG 4,PKMSG2 ; GO BACK IF ANYTHING LEFT SKIPE 4 ; MAKE SURE WE HAVEN'T SCREWED UP BUG (HLT,) RET PKMSL: BUG(CHK,) MOVE 4,2(2) JRST PKMS3 PKMS2: CAMG 4,2(2) ; Enough room in current bfr? JRST PKMS3 ; Yes PUSH P,4 HLRZ 4,IMPLT1(1) CAIN 4,-1 ; CONTROL LINK? JRST PKMS6 ; YES, CONTROL MESSAGE CAN'T CROSS ; NET MESSAGE BOUNDARY SUB P,BHC+1 ; USE REST OF CURRENT BUFFER MOVE 4,2(2) ; GET RESIDUAL BYTE COUNT OF BUFFER JRST PKMS3 ; GO DO IT PKMS6: PUSH P,3 CALL PKQOB ; No, finish current bfr POP P,3 JRST PKMS4 ; Start a new one PKMS5: IUNLK SUB P,BHC+1 POP P,4 CALL IMPB03 ILOCK JRST PKMSG2 ; Assign and init a bfr for output use PKBY1: PUSH P,3 HRRZ 3,IMPLT4(1) ; Get msg allocation JUMPG 3,PKBY4 ; Ok BUG(CHK,) AOS IMPLT4(1) PKBY4: MOVEI 2,^D36 ; Compute number of bits per output wd LDB 4,IMPLBS ; As (36/bs)*bs IDIVI 2,0(4) IMULI 2,0(4) MOVEI 4,0(2) MOVE 2,IMPLT1(1) ; Get proper size for output msg TRNE 2,377 ; For link 0? SKIPA 2,MAXBPM ; No, usual regular max MOVEI 2,^D<120*8> ; For ctrl link, max is 120 bytes IDIVI 2,0(4) ; Wds = bits / (bits/wd) ADDI 2,3 ; Plus overhead PUSH P,1 CALL ASNTBF ; Assign bfr JRST [ POP P,1 POP P,3 RET] MOVEI 2,0(1) POP P,1 HRLM 2,IMPLT4(1) ; Set as current buffer SOS IMPLT4(1) ; Consume allocate MOVEI 3,^D36 ; Compute number of bytes LDB 4,IMPLBS ; Which will fit in buffer. IDIVI 3,0(4) ; I.e. words*(36/bytesize) HRRZ 4,0(2) ; Number of words in bfr IMULI 3,-3(4) ; Less header overhead MOVEM 3,2(2) ; Setup counter HRLM 3,0(2) ; Remember original count LDB 3,IMPLBS ; Byte size LSH 3,^D24 ; Construct byte ptr HRRI 3,2(2) MOVEM 3,1(2) POP P,3 AOS 0(P) RET ; Put output buffer on queue PKQOB: HLRZ 2,IMPLT4(1) ; Get current buffer HRRZS IMPLT4(1) ; Clear ptr HRRZ 4,1(2) ; ADDRESS OF LAST WORD CONTAINING DATA SUBI 4,-1(2) ; LESS ADDRESS-1 OF BUFFER HRRM 4,0(2) ; GIVES ACTUAL WORDS IN USE HLRZ 3,0(2) ; Get original byte count SUB 3,2(2) ; Minus current count gives bytes in bfr LSH 3,^D8 ; Shift to proper position for header MOVEM 3,2(2) LDB 3,IMPLBS ; Byte size DPB 3,[POINT 8,2(2),11] ; Put in header SETZM 1(2) ; Clear imp header MOVE 3,IMPLT1(1) ; Get host-link DPB 3,[POINT 16,1(2),23] ; Put in imp header MOVE 3,IMPLT2(1) MOVSI 4,(IMPHIP) TLNE 3,(HIPFLG) ; If high priority connection, IORM 4,1(2) ; Set priority bit in leader HRRZS 0(2) ; Put bfr on queue HRLM 2,0(3) HRRM 2,IMPLT2(1) ; Fall into output check ; Put bfr on imp output queue if no rfnm outstanding IMPQOB: MOVSI 3,(RFNMC!ILCKB) TDNE 3,IMPLT2(1) ; Rfnm now out? RET ; Yes, don't send HLRZ 2,IMPLT3(1) JUMPE 2,R ; Return if no bfrs to go IMPQO1: MOVSI 3,(RFNMC) IORM 3,IMPLT2(1) ; Set rfnm flag HLLZ 3,0(2) ; Get bfr off queue JUMPN 3,.+3 MOVEI 4,IMPLT3(1) HRRM 4,IMPLT2(1) HLLM 3,IMPLT3(1) CALL IMPQOA ; Actually put it on output queue RET ; Entry here for queueing host-imp messages IMPQOA: SKIPN IMPORD ; is output on? JRST RLNTBF ; No. don't queue it up PUSH P,1 ; Save ac1 CALL IMPLKB ; Lock bfr for pi service routine IFDEF DBGBUF,< MOVE 1,2 CALL DBGOM> MOVSI 1,(IMPHIP) PIOFF HRRZS 0(2) ; Put bfr on imp out queue TDNN 1, 1(2) ; Is priority bit set in message JRST IMPQOL ; No, lo priority queue HRLM 2,@IMPHBI HRRZM 2,IMPHBI JRST IMPQOC IMPQOL: HRLM 2,@IMPOBI HRRZM 2,IMPOBI IMPQOC: PION SKIPN IMPOB ; Output now in progress? JSP 4,IMPXOU ; No, start it POP P,1 RET ; Lock imp bfr. must lock beginning and end in case crosses page bndry IMPLKB: PUSH P,1 ; Save 1 and 2 PUSH P,2 HRRZ 1,0(2) ; GET SIZE FIELD CAMLE 1,MAXWPM ; MAKE SURE NOT ON FREELIST BUG (HLT,) MOVEI 1,0(2) CALL MLKMA ; Lock beginning MOVE 1,0(P) ADD 1,0(1) ; Compute end MOVEI 1,-1(1) CALL MLKMA ; LOCK END POP P,2 POP P,1 RET ; Clear imp queues IMPCLQ: NOSKED ; Prevent confusion SKIPLE 1,IMPOB ; Anything here? CALL IMPCQ5 ; Unlock and release SETZB 2,IMPOB EXCH 2,IMPHBO MOVEI 1,IMPHBO MOVEM 1,IMPHBI CALL IMPCQ2 ; Dequeue everything SETZ 2, EXCH 2,IMPOBO MOVEI 1,IMPOBO MOVEM 1,IMPOBI CALL IMPCQ2 SKIPE 1,IMIB ; Anything here? CALL IMPCQ5 ; Yes, clear it SETZB 2,IMIB EXCH 2,IMPIBO ; Get things on input queue MOVEI 1,IMPIBO MOVEM 1,IMPIBI CALL IMPCQ3 ; Clear 1 locked things SETZB 2,IMPIBO EXCH 2,IMPFRI ; Clear input free list HRLZS 2 CALL IMPCQ2 ; Clear 2 locked things SETZB 2,IMPNFI EXCH 2,IMINFB ; Get release queue HRLZS 2 CALL IMPCQ4 ; Release 0 locked things OKSKED RET ; Unlock buffers on a queue twice IMPCQ2: MOVEI 3,2 JRST IMPCQ0 ; Unlock buffers on a queue 0 or 1 times IMPCQ4: TDZA 3,3 ; Zero times IMPCQ3: MOVEI 3,1 ; Once IMPCQ0: JUMPE 2,R ; Common code. 0 -- no buffers left HLRZ 1,2 HLLZ 2,0(1) CALL IMPCQ1 ; Unlock and release JRST IMPCQ0 ; Continue with next in chain ; Release individual buffer IMPCQ5: MOVEI 3,2 ; Entry for twice locked buffer IMPCQ1: PUSH P,3 ; Common routine PUSH P,2 ; Transparent to 2 PUSH P,1 HRRZ 1,0(1) ; GET COUNT FIELD CAMLE 1,MAXWPM ; MAKE SURE NOT ON FREELIST BUG (HLT,) MOVE 1,0(P) ;RESTORE AC1 CALL @[ R MULKMP IMULKB](3) ; Call appropriate routine POP P,2 CALL RLNTBF ; And release POP P,2 POP P,3 RET ; Unlock imp buffer at pi level IMULKB: PUSH P,1 HRRZ 1,0(1) ; GET SIZE FIELD CAMLE 1,MAXWPM ; MAKE SURE NOT ON FREELIST BUG (HLT,) MOVE 1,0(P) CALL MULKMP ; Unlock first adr in bfr POP P,1 ADD 1,0(1) ; COMPUTE END OF BFR MOVEI 1,-1(1) CALL MULKMP ;UNLOCK END OF BFR IN CASE PAGE BDRY RET ; Start input ; called from process level when buffers made available and input is off ; and from endin processor if more buffers are available IMISRT: CONSZ IMP,1B19 ; Power on CONSZ IMP,1B22 ; And imp up? RET ; No do nothing SOSL IMPNFI SKIPN 1,IMPFRI BUG(HLT,) HLRZ 2,0(1) ; Get next free MOVEM 2,IMPFRI MOVEM 1,IMIB MOVN 2,0(1) ; Get count HRLI 1,2(2) ; Blki ptr MOVEM 1,IMPINP MOVEI 1,IMIN0 MOVEM 1,IMIDSP CONSZ IMP,1B21 ; If error flop is set CALL IMIERR ; Be sure it gets noticed CONO IMP,IMPION+1B19 ; Clear error and start input POPJ P, ; Pi service for input ; Dispatched at impsv to one of the following: ; Imin1: first word of msg ; Imis1: second word of msg ; Imi36: 36-bit msg in ; Imi32: 32-bit msg in ; Imin00: flush rest of msg in ; Impein - handles 'end input' signal IMIN0: BLKI IMP,IMPINP ; Read in first word BUG(HLT,) MOVEM 1,IMIDSP MOVEI 1,IMIS1 EXCH 1,IMIDSP UNBRK IMP ; Second word in IMIS1: BLKI IMP,IMPINP BUG(HLT,) MOVEM 1,IMIDSP ; Save an ac MOVSI 1,-^D8 ; Init 36-32 bit state word MOVEM 1,IMIS32 MOVE 1,IMIB ; Get buffer location MOVE 1,1(1) ; Header AND 1,[FRMIMP + 17B7 + 377B23] CAMLE 1,[B23] JRST IMIS1A ; Special link/irreg msg do in 36 bit MOVE 1,IMIB LDB 1,[POINT 8,2(1),11] CAIE 1,^D36 ; 36-bit? SKIPA 1,[IMI32] ; No, assume 32 (or 8) IMIS1A: MOVEI 1,IMI36 ; Yes EXCH 1,IMIDSP ; Setup dispatch for rest of msg UNBRK IMP ; 36-bit input IMI36: BLKI IMP,IMPINP JRST .+2 ; Overflowed buffer UNBRK IMP MOVEM 4,IMPIAC+4 MOVEI 4,IMPIAC BLT 4,IMPIAC+3 IMIMTL: MOVEM P,IMINP MOVE P,PIMSTK BUG(IMP,,X) MOVE P,IMINP MOVEI 1,IMIN00 MOVEM 1,IMIDSP IMPUB: MOVSI 4,IMPIAC ; Restore ac's BLT 4,4 UNBRK IMP IMIN00: DATAI IMP,IMIS32 UNBRK IMP PIMSTK: IOWD NIMSTK,IMSTK ; 32-bit input IMI32: MOVEM 4,IMPIAC+4 MOVEI 4,IMPIAC BLT 4,IMPIAC+3 ; Save ac's DATAI IMP,1 SKIPL 4,IMPINP ; Get ptr to input buffer JRST IMIMTL ; Bfr full, msg too long MOVE 3,IMIS32 ; Get unpacking state word AOBJP 4,IMIMTL ; Seq bfr ptr TRNN 3,777777 ; Is this the zero'th state? AOBJP 4,IMIMTL ; Yes point to partial word LSHC 1,@IMISHT(3) ; Align input bytes with destination DPB 1,IMIPT1(3) ; High order byte for n-1st word MOVEM 2,0(4) ; Low order byte for nth word AOBJN 3,IMI32A ; Step state MOVSI 3,-^D8 ; Reinit state word IMI32A: MOVEM 3,IMIS32 ; Save state MOVEM 4,IMPINP ; Save bfr ptr JRST IMPUB ; Tables for 36-32 bit conversion, indexed by state word IMISHT: XX==4 REPEAT ^D8, IMIPT1: XX==^D32 REPEAT ^D8, ; Here when end msg recd from imp IMPEIN: MOVEM 4,IMPIAC+4 MOVEI 4,IMPIAC BLT 4,IMPIAC+3 ; Save ac's MOVEM P,IMINP MOVE P,PIMSTK ; Setup local stack CONSZ IMP,1B21 ; Error ff set? PUSHJ P,IMIERR ; Take care of it CONO IMP,IMPGEB!IMPIOF SKIPG 1,IMIB ; Bfr address JRST IMPEI2 ; Wasn't one AOSG IMPFLS ; Flushing msgs? JRST IMPEI3 ; Yes, return to free list HRRZ 2,IMIDSP CAIE 2,IMIN0 ; No msg started? or CAIN 2,IMIN00 ; Were flushing msg? JRST IMPEI2 ; Yes, skip usual finish up stuff MOVE 2,1(1) ; Get header LDB 3,[POINT 4,2,7] ; And msg type AND 2,[FRMIMP + 377B23] CAIN 3,6 ; Dead host status JRST IMPEI4 ; Yes. has no message id CAIE 3,2 ; Going down? CAMG 2,[B23] JUMPN 3,IMPEI4 ; Irregular msg not special link HRRZS 0(1) ; Clear fwd ptr of this bfr HRLM 1,@IMPIBI ; Add bfr to in queue HRRZM 1,IMPIBI HRRZ 3,0(1) ; GET SIZE FIELD CAMLE 3,MAXWPM ; MAKE SURE NOT RELEASED BUG (HLT,) ADD 1,0(1) ; Compute tail of bfr MOVEI 1,-1(1) CALL MULKMP ; Unlock it HRRZ 3,IMPINP ; GET LAST LOC WITH DATA HRRZ 4,IMIB ; START ADDRESS OF BUFFER SUBI 3,-1(4) ; 3=END-(START-1)=ACTUAL COUNT HRRM 3,@IMIB ; RECORD ACTUAL COUNT IN BUFFER HEADER AOS IMPFLG ; Request job 0 service IMPEI2: SETZM IMIB SKIPLE IMPNFI ; More buffers available? PUSHJ P,IMISRT ; Yes, start new input IMPUB1: MOVE P,IMINP JRST IMPUB IMPEI4: MOVE 2,1(1) ; Get header CALL IMP8XQ ; Put on irreg msg q AOS IMPFLG IMPEI3: EXCH 1,IMPFRI HRLM 1,@IMPFRI AOS IMPNFI JRST IMPEI2 IMIERR: PUSH P,1 SETOM IMPRDL ; Be sure this flap gets noticed MOVNI 1,2 MOVEM 1,IMPFLS MOVNM 1,NOPCNT ; Send some nops CONO IMP,1B19 ; Clear error flop POP P,1 POPJ P, ; Pi service for output ; Dispatched from impsv to one of the following: ; Imo36: doing 36 bit output ; Imo32: doing 32 bit output (second word only) ; Imo321: doing 32 bit output (rest of msg) ; Impdn2: final phase of end-of-msg cleanup IMODN0: MOVEM 4,IMPIAC+4 MOVEI 4,IMPIAC BLT 4,IMPIAC+3 ; Save ac's IMODN1: MOVEM P,IMINP MOVE P,PIMSTK CONO IMP,IMPEOB ; Sent last word, now send end bit MOVE 1,IMPOB ; Get buffer location MOVE 2,1(1) ; Get header AND 2,[FRMIMP+377B23] CAMLE 2,[B23] ; Regular link? JRST IMODN4 ; No. just flush the message LDB 1,[POINT 16,1(1),23]; Extract host-link IORI 1,1B18 CALL IMPPIL ; Get lt index for this JRST IMODN6 ; Not there MOVSI 2,(RFNMC) ; Be sure rfnm has not returned already TDNN 2,IMPLT2(1) JRST IMODN4 ; Well what do you know! HRRZ 2,IMPLT3(1) ; Be sure nothing is there JUMPN 2,IMODN6 ; Anomalous, but what can you do? MOVE 2,IMPOB HRRM 2,IMPLT3(1) JRST IMODN5 IMODN6: BUG(NTE,) IMODN4: MOVE 1,IMPOB EXCH 1,IMINFB ; Put bfr back on free list HRLM 1,@IMINFB AOS IMPFLG ; Request job 0 service IMODN5: MOVE 1,IMPOB CALL IMULKB ; Unlock bfr MOVEI 1,IMODN2 ; Setup dispatch for final step MOVEM 1,IMODSP JRST IMPUB1 IMOIRG: CONO IMP,IMPEOB MOVEM 1,IMODSP MOVEI 1,IMODN2 EXCH 1,IMODSP UNBRK(IMP) IMODN2: MOVEM 4,IMPIAC+4 MOVEI 4,IMPIAC BLT 4,IMPIAC+3 ; Save ac's JSP 4,IMPIOU ; Start next msg if any JRST IMPUB ; Routine to start msg going out. called at pi level, and at ; Main level if no output in progress IMPXOU: PIOFF SKIPN IMPOB ; ANY OUTPUT IN PROGRESS? JRST IMPXO1 ; NO PION ; YES, TURN PI BACK ON JRST (4) ; AND RETURN IMPXO1: HRROS IMPOB ; MARK OUTPUT IN PROGRESS PION ; NO IT'S OK TO TURN PI BACK ON IMPIOU: SKIPLE NOPCNT ; Any nop's to send? JRST IOUNOP ; Yes, go send them HLRZ 1,IMPHBO ; Hi priority msg waiting? JUMPE 1,IMPIOL ; No, check lo priority HLLZ 2,0(1) ; Get buffer JUMPN 2,.+3 MOVEI 3,IMPHBO MOVEM 3,IMPHBI MOVEM 2,IMPHBO JRST IMPIOC IMPIOL: HLRZ 1,IMPOBO ; Msg waiting to go out? JUMPE 1,[SKIPE 2,HSTGDM JRST IOUIRG ; Send the host going down msg CONO IMP,IMPSTO ; No, turn of imp pi req SETZM IMPOB JRST 0(4)] HLLZ 2,0(1) ; Get bfr JUMPN 2,.+3 MOVEI 3,IMPOBO MOVEM 3,IMPOBI MOVEM 2,IMPOBO IMPIOC: MOVEM 1,IMPOB MOVN 2,0(1) ; Count of data words HRLI 1,1(2) ; Construct blko ptr MOVEM 1,IMPOUP MOVE 2,1(1) ; Get header AND 2,[FRMIMP + 377B23] CAMLE 2,[LLINK*1B23] ; Special message? SKIPA 2,[^D36] ; Yes, assume 36-bit mode LDB 2,[POINT 8,2(1),11] ; Byte size MOVEI 1,IMO36 CAIE 2,^D36 ; 36-bit connection? MOVEI 1,IMO32 ; No, transmit in 32-bit MOVEM 1,IMODSP ; Setup dispatch BLKO IMP,IMPOUP ; Send first word (always 36-bit) JFCL JRST 0(4) IOUNOP: SOS NOPCNT MOVE 2,[BYTE (8)4,0,0,0] IOUIRG: HRROS IMPOB ; Make non-zero so checks work MOVEI 1,IMOIRG MOVEM 1,IMODSP DATAO IMP,2 JRST (4) ; 36-bit output IMO36: SKIPL IMPOUP ; Data left? JRST IMODN0 ; No BLKO IMP,IMPOUP JFCL UNBRK IMP ; 32-bit output (second word) IMO32: BLKO IMP,IMPOUP ; Send second word (extended hdr) JFCL MOVEM 1,IMODSP ; Save an ac MOVSI 1,-^D8 ; Init 36-32 bit translation state word MOVEM 1,IMOS32 MOVEI 1,IMO321 ; Setup dispatch for rest of msg EXCH 1,IMODSP UNBRK IMP ; 32-bit output (rest of msg) IMO321: MOVEM 4,IMPIAC+4 MOVEI 4,IMPIAC BLT 4,IMPIAC+3 ; Save ac's SKIPL 4,IMPOUP ; Data left? JRST IMODN1 ; No MOVE 3,IMOS32 ; Get state word AOBJP 4,.+2 ; Inc bfr ptr MOVE 2,1(4) ; Get n+1th word MOVE 1,0(4) ; Get nth word LSH 1,-4 ; Align high-order byte LSHC 1,@IMOSHT(3) ; Shift bytes into output word DATAO IMP,1 AOBJN 3,IMO32A ; Step state AOBJN 4,.+1 ; Extra inc of bfr each cycle MOVSI 3,-^D8 ; Reinit state word IMO32A: MOVEM 3,IMOS32 ; Save state word MOVEM 4,IMPOUP ; Save bfr ptr JRST IMPUB ; Table for 32-36 bit conversion, indexed by state word IMOSHT: XX==4 REPEAT ^D8, ; Various impbug's from above IMPB01: BUG(IMP,,X) JRST LNKL1 IMPB03: SKIPN IMINFB ; ANY BUFFERS RELEASE BY PI ROUTINES? JRST IMPB04 ; NO PUSH P,1 PUSH P,2 PUSH P,4 CALL IMINRB POP P,4 POP P,2 POP P,1 RET IMPB04: PUSH P,1 BUG(IMP,,X) MOVEI 1,^D5000 DISMS ; Wait for 5 sec, then try again POP P,1 RET IMPB06: IUNLK MOVE 2,1 CALL IMP8X1 BUG(IMH,,X) RET ; Bug or untreated net error BGRIML: PUSH P,1 PUSH P,2 MOVE 1,2 SETZ 2, JRST BGRIM0 IMPBG0: BGRIMH: PUSH P,1 PUSH P,2 SETZ 1, ; No header JRST BGRIM0 BGRIMP: PUSH P,1 PUSH P,2 SETZB 1,2 BGRIM0: IFDEF DBGBUF,< EXCH 1,-2(P) CALL DBGBG1 ; Store bug info EXCH 1,-2(P)> AOS IMPBGC ; Count bugs SKIPE BUGIMP JRST BGRIM1 MOVEM 2,IMPBGH ; Save host/link HLRZM 1,BADHMS MOVE 2,1(1) ; First word ofheader MOVEM 2,BADHDR MOVE 2,2(1) MOVEM 2,BADHDR+1 HRRZ 2,-2(P) ; Pc of the bug MOVEM 2,BUGIMP BGRIM1: POP P,2 POP P,1 AOS JB0FLG ; Get job 0 started RET ; Imp and ncp status check IMPSTT: AOSE IMPRDL ; Was error flop noticed set? CONSZ IMP,1B22 ; Or is ready line off? JRST IMPSTA ; Yes, mark down SKIPGE IMPRDT ; Was it down? JRST IMPSTB ; No, continue SETOM IMPRDT ; Yes, reset flag GTAD MOVEM 1,IMPUPT ; Record time back up JRST IMPSTB ; Continue ; Imp is or was down. record time thereof IMPSTA: SKIPN IMPRDY JRST IMPSTB ; Don't record imp down if ncp is off SKIPL 1,IMPRDT ; Was it down? JRST IMPSTC ; Yes, check how long MOVE 1,TODCLK MOVEM 1,IMPRDT ; No, record when in went off GTAD MOVEM 1,IMPDNT JRST IMPSTB IMPSTC: ADDI 1,^D10000 CAMG 1,TODCLK ; Down for more than 10 sec? SETOM IMPDRQ ; Yes, declare imp down & recycle ncp JRST IMPSTB ; Bring state of ncp into agreement with state of imp and neton/impdrq IMPSTB: SKIPLE 1,IMPRDY ; Down cycle in progress? JRST IMPNO1 ; Yes. complete it. JUMPL 1,IMPSTU ; No. jump if we think imp is up SKIPE NETON ; Ncp is shut off. do we want it off? SKIPLE NETTCH ; No. but if state change unreported, RET ; then wait. do nothing if all agrees. JRST IMPRSS ; Else bring ncp back up. IMPSTU: SKIPLE NOPCNT ; ARE ANY NOPS NEEDED JSP 4,IMPXOU ; YES, BE SURE OUTPUT IS GOING SKIPN IMPDRQ ; We think it's up, want it down SKIPN NETON JRST IMPNOF ; Yes, take it down SETZM HSTGDM ; Else it's up. be sure to cancel JRST RSKP ; host going down msg and skip ; Shut down ncp IMPNOF: SKIPLE NETTCH JRST RSKP ; But not until state change reported IMPNF1: MOVEI 1,^D30000 ; Begin down sequence ADD 1,TODCLK MOVEM 1,IMPRDY ; When to give up and turn ncp off. CALL NETDWN ; Start clear of ncp CALL CLRHRT ; Clear host ready table SETZM IMPCCH ; Send rst's to everyone SETZM IMPTIM ; Now. AOS NETTCH AOS JB0FLG JRST IMPSTT ; Down sequence in progress IMPNO1: CONSO IMP,1B22 ; If imp is dead CAMG 1,TODCLK ; or time has run out? JRST IMPNF3 ; Yes. just pull the plug. SKIPG NETTCH ; Else if change unreported SKIPL IMPCCH ; or rst's not all sent JRST RSKP ; then wait. SETZM IMPORD ; Shut off output SKIPN IMPOBO ; Check if both output queues are empty. SKIPE IMPHBO JRST RSKP ; If not, then wait. SKIPLE IMPOB ; If last message not completely sent JRST RSKP ; then wait. SETZM HSTGDM ; Now stop sending host going down. SKIPE IMPOB ; Are all messages sent? JRST RSKP ; No. wait. IMPNF3: SETZM IMPRDY ; Now say totally down CONO IMP,IMPSTO!IMPIOF!IMPOOF!1B20 ; Stop output, in&out off, drop rdy AOS NETTCH ; Report final state change AOS JB0FLG MOVEI 2,NVTLO ; Finish clean up IMPNO2: SKIPGE TTFORK(2) ; Nvt in use SKIPL TTNETW(2) CALL TTCOBI ; Yes, flush output CAIGE 2,NVTHI ; Check all net nvt lines AOJA 2,IMPNO2 MOVSI 1,-IMPNLK CALL IMPCLL ; Clear all entries from link table AOBJN 1,.-1 CALL IMPCLQ ; Clear queues RET ; Not up - nonskip return ; Initialization IMPINI: MOVEI 1,IMPIBO ; Init buffer lists MOVEM 1,IMPIBI MOVEI 1,IMPOBO MOVEM 1,IMPOBI MOVEI 1,IMPHBO MOVEM 1,IMPHBI MOVSI 2,-NSQ MOVEI 1,SIQIBO(2) MOVEM 1,SIQIBI(2) SETOM SQJOB(2) AOBJN 2,.-3 SETOM SQLCK MOVEI 2,1B18+1B19 ; Free entry for implt1 MOVSI 1,-IMPNLK MOVEM 2,IMPLT1(1) ; Make all links unused AOBJN 1,.-1 MOVSI 1,-NNVTLN ; Count through nvt lines SETOM TTNETX(1) ; Init all net lines to free AOBJN 1,.-1 SETOM IDVLCK ; INIT IDVLCK IMPRSN: SETZM IMPNCL ; Clear irreg msg q variables SETZM IMP8XI SETZM IMP8XO SETZM IMP8XC MOVEI 1,IMIN00 ; Setup pi dispatches MOVEM 1,IMIDSP MOVEI 1,IMODN2 MOVEM 1,IMODSP MOVEI 1,^D120000 ; Start timers ADD 1,TODCLK ; In two minutes MOVEM 1,NETTIM ; Set alarm clocks to infinity MOVEM 1,RFNTIM SETZM IMPTIM SETZM IGDTIM ; Clear time of last imp-going-down msg SETZM HSTGDM ; Cancel any residual host going down SETZM IMPCCH ; Cause send of rst to all hosts CLRHRT: SETZM IMPHRT ; Clear ready table MOVE 1,[XWD IMPHRT,IMPHRT+1] BLT 1,IMPHRT+IMPLBT-1 RET ; Bring up ncp IMPRSS: CONSZ IMP,1B19 ; Power on CONSZ IMP,1B22 ; And ready line on RET ; No, stop here CALL IMPRSN ; Reset variables CONO IMP,1B19 ; Set host ready line, clear imp error SETZM IMPRDL ; And notices of b21 SETZM IMPDRQ ; Forget any intervening down requests MOVNI 1,2 MOVEM 1,IMPFLS ; Init flush count MOVEI 1,3 MOVEM 1,NOPCNT MOVEI 1,^D1000 DISMS ; Allow time for ready line to settle AOS NETTCH ; Cause change in state to be noted AOS JB0FLG GTAD ; Yes MOVEM 1,NCPUPT ; Save time whe it came up DATAI IMP,1 ; Helps to clear interface CONO IMP,IMPSTO+IMPGEB CONO IMP,IMPOON ; Give output pi asmt SKIPLE IMPNFI ; If input bfrs available, CALL IMISRT ; Start input SETOM IMPRDY SETOM IMPORD ; Allow output MOVE 1,NLHOST ; Local host CALL IMPRRP ; Send ourselves an rrp RET ; Take network down ; Accepts in ; 1 ; Reason for going down (a la 1822) ; 2 ; Time when back up (TENEX standard) IMPHLT: SKIPN NETON ; IS IT ON? RET ; NO. DO NOTHING PUSH P,1 GTAD ; GET NOW CAMG 2,1 ; IS SHUTDOWN LATER THAN NOW? JRST [ MOVEI 1,177776 JRST IMPHL1] ; TIME BACK UP NOT KNOWN ADD 1,[6,,0] CAMG 1,2 ; MORE THAN 6 DAYS AWAY? JRST [ MOVEI 1,177777 JRST IMPHL1] MOVSI 4,(1B0+1B2+0B17) ; USE GMT STANDARD TIME ODCNV ; SEPARATE INTO DAY, SECOND ETC HRRZ 1,3 ; DAY OF WEEK HRRZ 2,4 IDIVI 2,^D300 ; CONVERT SECONDS TO 5 MIN IDIVI 2,^D12 ; SEPARATE INTO HOUR AN 5 MIN LSH 1,5 IOR 1,2 ; INSERT HOUR OF DAY LSH 1,4 IOR 1,3 ; AND 5 MIN PART OF HOUR IMPHL1: LSH 1,4 IOR 1,0(P) LSH 1,4 TLO 1,(2B7) PIOFF SETZM NETON ; START NET DOWN MOVEM 1,HSTGDM PION JSP 4,IMPXOU SUB P,BHC+1 RET ; Restart code. called by sysrst IMPRST: SETOM IMPDRQ ; Request down cycle MOVEI 1,1 SKIPLE IMPRDY ; Going down already? MOVEM 1,IMPRDY ; Shorten delay RET > ; End of idfef impchn on page 1 END