TITLE NETDEV - NETWORK DEVICE SERVICE ROUTINES - V217 SUBTTL NETDEV -- WEM/ 31-MAY-88 SEARCH F,S,NETPRM $RELOC $HIGH ;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED ; OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE. ; ;COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION 1978,1979,1980,1982,1984,1986,1988. ;ALL RIGHTS RESERVED. .CPYRT<1978,1988> XP VNETDV,217 ;PUT VERSION NUMBER IN GLOB AND LOADER MAP XLIST $LIT LIST PRGEND TITLE NETCDR - NETWORK CARD READER ROUTINES - V001 SUBTTL NETCDR -- WEM/ 4-JUN-78 SEARCH F,S,NETPRM $RELOC $HIGH ;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED ; OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE. ; ; COPYRIGHT (C) 1978,1984 BY DIGITAL EQUIPMENT CORP., MAYNARD, MASS. XP VNETCD,001 ;PUT VERSION NUMBER IN GLOB AND LOADER MAP ENTRY NETCDR NETCDR:: SUBTTL 1.0 CDR SPECIFIC SYMBOL DEFINITIONS ;SPECIAL CHARACTERS C%EOF==7417 ;END OF FILE CHARACTER C%026==4242 ;CHANGE MODE TO 026 CHARACTER C%029==5252 ;CHANGE MODE TO 029 CHARACTER ;BITS IN LH OF DEVIOS(F) IOS029==IOSFFB ;IF SET THEN DO TRANSLATION IN 029 MODE ;BIT INDICATING SUPER-IMAGE-MODE INPUT IO.SIM==1B29 ;BIT THAT SAYS SUPER-IMAGE-INPUT SUBTTL 2.0 INTERFACE TO UUOCON (DEVSER DISPATCH VECTOR) JRST NTDONL## ;(-5) CHECK IF DEVICE IS ON LINE JRST ECOD2## ;(-4) DEVOP UUO JRST C.BFSZ ;(-3) BUFFER SIZE JRST CPOPJ## ;(-2) INITIALIZATION JRST CPOPJ1## ;(-1) HUNG DEVICE NDEVCD::JRST NTDREL## ;RELEASE JRST CPOPJ## ;CLOSE OUTPUT JRST NTDILO## ;ILLEGAL OUTPUT (RETURN INTERLOCK) JRST C.IN ;INPUT SUBTTL 2.1 INPUT UUO PROCESSING C.IN: ;HERE FROM UUOCON ON IN UUO PUSHJ P,SAVE4## ;WE CLOBBER ALL THE P'S MOVSI S,IOSUSI ;CLEAR THE "UUOCON STOPED INPUT" BIT SINCE ANDCAB S,DEVIOS(F) ; IT HAS JUST TRIED TO START IT AGAIN. C.LOOP: PUSHJ P,NTDSET## ;SET UP W, S ETC. MOVE S,DEVIOS(F) ;FAMOUS STYLE OF LOOP DRIVEN CODE. TLNN S,IOSCON ;STILL THERE? PJRST NTDGON## ;NODE WENT AWAY TLNE S,IOBEG ;IS THIS THE FIRST TIME THROUGH? JRST C.FRST ; IF IT IS, DO SOME SPECIAL CHECKING MOVSI S,IO ;WE ARE AN INPUT DEVICE ANDCAB S,DEVIOS(F) ;MAKE SURE THAT UUOCON NOTICES PUSHJ P,NTDIBA## ;CHECK TO MAKE SURE THAT NTDSIB WON'T FAIL POPJ P, ;IF NO INPUT BUFFER, RETURN TO UUOCON HRRZ T1,DEVPCB(F) ;IS THERE ANY INPUT TO PROCESS?? JUMPE T1,C.WAIT ;IF NO DATA, GO WAIT FOR SOME PUSHJ P,NTDDID## ;PROCESS THE NEXT NCL SUB-MESSAGE JRST C.LOOP ;MAKE SURE EVERYTHING'S STILL OK. C.WAIT: PUSHJ P,NTDONL## ;SEE IF THERE'S ANY BAD REASON FOR NO DATA JRST C.HUNG ; IF ERROR BIT IS SET. GO FIND OUT WHY. PUSHJ P,NTDXDQ## ;SEE IF WE ARE BEHIND ON OUR DRQ'S PUSHJ P,C.CLRS ;MAKE SURE THE CDR IS RUNNING PUSHJ P,NTDWTI## ;WAIT FOR INPUT (EW STATE) POPJ P, ;IF NONBLOCKING, RETURN TO UUOCON NOW. JRST C.LOOP ;SOMETHING WOKE US UP. GO SEE WHAT SUBTTL 2.2 INPUT UUO EXCEPTION PROCESSING C.FRST: ;HERE ON THE FIRST IN MOVSI S,IO!IOBEG!IOSREL ;CLEAR THESE BITS ANDCAB S,DEVIOS(F) ;SINCE WE ARE APPARENTLY RUNNING NOW MOVSI S,IOS029 ;INITIALIZE THE TRANSLATION MODE IORB S,DEVIOS(F) ;MODEL 029. SETZM DEVAXI(F) ;CLEAR ANY PARTIAL BUFFER THAT MAY BE LEFT PUSHJ P,C.CLRS ;CLEAR THE "STOP" BITS JRST C.LOOP C.HUNG: ;HERE FROM C.LOOP WHEN IOSERR IS SET. TLNN S,IOSCON ;ARE WE STILL CONNECTED PJRST NTDGON## ; NO. TELL USER THE DEVICE IS GONE PUSHJ P,C.CLRS ;CLEAR THE STOP BITS TLNE S,IOSERR ;IS THE CDR ONLINE YET?? PUSHJ P,NTDHNG## ;SET OFF-LINE AND TELL THE OPERATOR JRST C.LOOP ;BACK TO LOOP TO TRY AGAIN. C.CLRS: ;HERE TO CLEAR THE "EOF" AND "STOP" BITS MOVEI T1,SCD.SR!SCD.HZ!SCD.CZ ;"STOP READ", "HARD EOF", "EOF CARD" PUSHJ P,NTDCST## ;SEND THE "CLEAR BITS" MESSAGE JRST C.CLR1 ;COULDN'T SEND MSG. SLEEP AND TRY AGAIN LATER. POPJ P, ;ALL DONE. RETURN C.CLR1: PUSHJ P,NETSLP## ;SLEEP FOR 2 SECONDS PUSHJ P,NTDSET## ;SET UP "W" AND "S" AGAIN TLNE S,IOSCON ;MAKE SURE NODE DIDN'T GO AWAY JRST C.CLRS ;IF STILL THERE, TRY SENDING STATUS AGAIN POPJ P, ;IF NODE GONE, JUST PRETEND MSG WENT OUT. ;ROUTINE TO RETURN BUFFER SIZE C.BFSZ: MOVEI T1,^D81 ;ASSUME THAT WE ARE IN SUPER IMAGE MODE TRNE M,IO.SIM ;IF WE ARE IN SUPER IMAGE MODE POPJ P, ; THEN THE BUFFER SIZE IS 80. WORDS JRST REGSIZ## ;IF NOT IN SUPERIMAGE MODE, LOOK IN THE DDB SUBTTL 3.0 INTERFACE TO NETSER (NETWORK DISPATCH VECTOR) IFIW NTDNWD## ;USE DEFAULT "NODE WENT DOWN" HANDLER IFIW NTDDSC## ;USE DEFAULT DISCONNECT HANDLER IFIW NTDCNC## ;USE STANDARD CONNECT CONFIRM CODE IFIW NTDSTP## ;++ SHOULD NEVER GET HERE IFIW CPOPJ## ;WE SHOULDN'T GET DATA REQUESTS CDRNDP::IFIW NTDQIP## ;QUEUE INCOMING MESSAGE TO UUO LEVEL IFIW C.DATA ;DATA IFIW C.DATA ;DATA WITH E-O-R IFIW C.STAT ;STATUS IFIW CPOPJ## ;WE DONT GET CONTROL IFIW CPOPJ## ;OR UID IFIW CPOPJ## ;OR FILE-SPEC'S ;DUMMY CONNECT INIT PROCESSOR NCDRCI==:NJNKCI## ;A JUNK CI SUBTTL 3.1 INPUT DATA MESSAGE PROCESSING ;REGISTER USAGE IS AS FOLLOWS. ; P1 SET UP AT ENTRY BY NTDISP. POINTS TO FIRST DATA BYTE IN MESSAGE ; P4 SET UP AT ENTRY BY NTDISP. CONTAINS NUMBER OF DATA BYTES LEFT. ; P2 USED AS A COLUMN COUNTER. (STARTS AT 80. COUNTS DOWN) ; P3 USED BY C.NEXT WHEN DE-COMPRESSING CDR DATA. C.DATA: ;HERE TO PROCESS CDR DATA SETZ P3, ;CLEAR REPEAT COUNT FOR C.NEXT MOVEI P2,^D80 ;INITIALIZE THE COLUMN COUNTER. TRNE S,IO.SIM ;IS IT SUPER IMAGE MODE? JRST C.SIMG ; YES. GO TO SUPER IMAGE MODE PROCESSOR. LDB T1,PIOMOD## ;GET THE MODE. CAIG T1,AL ;IS IT ONE OF THE ASCII MODES JRST C.ASCI ; YES. GO TO SPECIAL PROCESSOR CAIN T1,I ;IMAGE? JRST C.IMAG ; YES. CAIL T1,IB ;IS IT ONE OF THE SCREWY CAILE T1,B ; BINARY MODES? JRST C.IMPM ;NO. BAD MODE. GIVE ERROR JRST C.BIN ;BINARY MODE. GO READ SCREWY CARDS. SUBTTL 3.1.1 IMAGE MODE INPUT PROCESSING C.SIMG: ;CDR SUPER-IMAGE MODE. SKIPA T4,[EXP ^D36] ;SUPER-IMAGE MODE USES 36 BIT BYTES C.IMAG: ;IMAGE MODE MOVEI T4,^D12 ;IMAGE MODE USES 12 BIT BYTES. PUSHJ P,NTDSIB## ;SET UP THE INPUT BUFFER STOPCD .,STOP,CDRIMG, ;++ NTDSIB FAILED IN C.IMAG C.IMG1: PUSHJ P,C.NEXT ;GET THE NEXT 12 BIT CHARACTER JRST C.DERR ;IF NONE, THEN REMOTE SENT BAD MESSAGE. SOSGE DEVAXI+1(F) ;COUNT DOWN THE BYTE COUNT JRST C.BKTL ; IF EMPTY, THEN USER'S BUFFER IS TOO SMALL EXCTUU ;STORE THE BYTE SOJG P2,C.IMG1 ;LOOP OVER ALL COLUMNS PJRST NTDA1B## ;ADVANCE THE INPUT BUFFER AND SKIP RETURN SUBTTL 3.1.2 ASCII MODE INPUT PROCESSING C.ASCI: ;ASCII MODE CARDS (UGH) MOVEI T4,^D7 ;SEVEN BIT BYTES FOR ASCII MODES PUSHJ P,NTDSIB## ;SET UP THE INPUT BUFFER STOPCD .,STOP,CDRASC, ;++ NTDSIB FAILED IN C.ASCI ; CAN'T HAPPEN. WE CHECKED AT C.LOOP PUSHJ P,C.NEXT ;GET COLUMN 1 JRST C.DERR ;?? NO FIRST COLUMN ?? CAIN T1,C%EOF ;IS IT AN E-O-F CARD JRST C.DEND ; IF SO, GO TELL THE USER CAIN T1,C%029 ;IS IT A CHANGE TO 029 STYLE TRANSLATION JRST [MOVSI S,IOS029 ;IF SO, FIRST SET THE "029 MODE" IORB S,DEVIOS(F) ; BIT FOR C.CONV TO SEE, AND PJRST CPOPJ1##] ; GIVE GOOD RETURN (BUT DON'T ADVANCE BUFFER) CAIN T1,C%026 ;IS IT A CHANGE TO 026 STYLE TRANSLATION JRST [MOVSI S,IOS029 ;IF SO, FIRST CLEAR THE "029 MODE" ANDCAB S,DEVIOS(F) ; FOR C.COMV PJRST CPOPJ1##] ;GIVE GOOD RETURN. JRST C.ASC2 ;NORMAL CARD. SKIP INTO COPY LOOP. C.ASC1: PUSHJ P,C.NEXT ;GET THE NEXT BYTE JRST C.DERR ;REMOTE SENT BAD DATA C.ASC2: PUSHJ P,C.CONV ;DO THE DATA CONVERSION SOSGE DEVAXI+1(F) ;COUNT DOWN THE BYTE COUNT JRST C.BKTL ;USER DIDN'T GIVE BIG ENOUGH BUFFER. EXCTUU ;STORE THE BYTE IN THE USERS BUFFER. SOJG P2,C.ASC1 ;LOOP FOR ALL 80 CHARACTERS. SOSGE DEVAXI+1(F) ;COUNT OFF THE JRST C.BKTL ;BUFFER TOO SMALL MOVEI T1,15 ; EXCTUU ;STORE THE SOSGE DEVAXI+1(F) ;COUNT OFF THE JRST C.BKTL ;BUFFER TOO SMALL MOVEI T1,12 ; EXCTUU ;STORE THE PJRST NTDA1B## ;ADVANCE BUFFER AND NCL MESSAGE SUBTTL 3.1.3 BINARY MODE INPUT PROCESSING C.BIN: ;BINARY MODE MOVEI T4,^D12 ;12 BIT BYTES IN BINARY MODE PUSHJ P,NTDSIB## ;SET UP THE INPUT BUFFER STOPCD .,STOP,CDRBIN, ;++ NTDSIB FAILED IN C.BIN PUSHJ P,C.NEXT ;GET THE FIRST COLUMN JRST C.DERR ;?? NO FIRST BYTE ?? CAIN T1,C%EOF ;WAS THIS AN EOF CARD JRST C.DEND ;IF SO, GO SET E-O-F AND RETURN MOVEI T2,-5(T1) ;TAKE OUT THE 7-9 BITS TRNE T2,17 ;MAKE SURE THAT'S ALL THAT WAS THERE JRST C.IMPB ;IMPROPER BINARY CARD. ABORT. LSH T1,-6 ;SHIFT TO GET JUST WORD COUNT. JUMPE T1,CPOPJ1## ;IF NO WORDS. JUST RETURN HRLM T1,DEVAXO(F) ;STORE WORD COUNT IN OUTPUT WORD FOR A BIT IMUL T1,3 ;CONVERT WORD COUNT INTO A COLUMN COUNT MOVEI T2,(T1) ;INITIALIZE "GLOBAL" COLUMN COUNT. PUSHJ P,C.NEXT ;GET THE CHECKSUM BYTE JRST C.DERR ;?? STRANGE MESSAGE ?? HRRM T1,DEVAXO(F) ;SAVE THE CHECKSUM TILL LATER TOO! C.BIN1: ;COPY LOOP. PUSHJ P,C.NEXT ;GET THE NEXT BYTE JRST C.DERR ;CARD ENDED TOO SOON! SOSGE DEVAXI+1(F) ;COUNT DOWN THE BYTE JRST C.BKTL ;USER DIDN'T MAKE BUFFER BIG ENOUGH. EXCTUU ;STORE THE BYTE IN THE USERS BUFFER. SOJG P2,C.BIN1 ;COMPLETE THE REST OF THE CARD. ;NOW WE MUST COMPUTE THE "FOLDED 12 BIT" CHECKSUM HRRZ T2,DEVIAD(F) ;GET A POINTER TO THE BUFFER HEADER HLRZ T3,DEVAXO(F) ;RECOVER THE WORD COUNT MOVNS T3 ;NEGATIVE WORD COUNT HRL T2,T3 ;MAKE INTO -COUNT,,ADDRESS-2 SETZ T1, ;INITIALIZE THE CHECKSUM EXCTUX ;ADD THE NEXT WORD AOBJN T2,.-1 ;LOOP UNTIL ALL WORDS ARE COLLECTED LSHC T1,-^D24 ;SHIFT SO AS TO GET TOP AND LSH T2,-^D12 ; BOTTOM THIRD ADDED ADD T1,T2 ; TOGETHER IN T1 LSHC T1,-^D12 ;SHIFT SO AS TO GET MIDDLE LSH T2,-^D24 ; THIRD ADDED IN ADD T1,T2 ; THERE TOO TRZE T1,770000 ;CLEAR EXTRA BITS, BUT CHECK ADDI T1,1 ; AND CORRECT FOR CARRY (CIRCULAR CHECKSUM) HRRZ T2,DEVAXO(F) ;GET THE ORIGIONAL CHECKSUM CAIE T1,(T2) ;SEE IF THEY AGREE. JRST C.DTER ;IF NOT, GIVE IODTER PJRST NTDA1B## ;IF THEY DO, THEN ADVANCE BUFFERS SUBTTL 3.2 INPUT STATUS MESSAGE PROCESSING C.STAT: ;HERE UPON RECEIPT OF A STATUS MESSAGE ;STC PUSHJ P,EBI2BI## ;READ THE CODE (STATUS, SET, OR CLEAR) JUMPN T1,CPOPJ## ;WE ONLY ACCEPT THE ZERO KIND. ;STD PUSHJ P,EBI2BI## ;READ THE STATUS BITS XOR T1,DEVSTS(F) ;GET A MASK OF THE BITS THAT CHANGED TRNN T1,-1 ;DID ANY CHANGE? JRST CPOPJ1## ;IF NOT, DON'T GO ANY FARTHER XORB T1,DEVSTS(F) ;REMEMBER THE NEW STATUS MOVSI S,IOSERR ;GET ERROR BIT TO SET/CLEAR MOVE T2,[0 S,DEVIOS(F)] ;GET SKELETON INSTRUCTION TO SET/CLEAR BITS TRNE T1,SCD.ME ;IS THE ERROR BIT LIT? TLOA T2,(IORB) ;YES. SET ERROR BITS TLO T2,(ANDCAB) ;NO. CLEAR ERROR BITS XCT T2 ;SET/CLEAR THE BITS PUSHJ P,NTDIAV## ;TELL LOWLEVEL THAT SOMETHING HAPPENED JRST CPOPJ1## ;NO NEED TO DO MORE. C.LOOP & C.HUNG WILL ; NOTICE THESE BITS SOON ENOUGH. SUBTTL 4.0 UTILITY ROUTINES SUBTTL 4.1 ERROR HANDLING ROUTINES COMMENT \ Possible CDR error codes and their causes are as follows. IOEND Ascii and binary modes. Indicates an "EOF" card IOBKTL All modes. A user specified buffer was too small to hold an entire card. IODTER Binary mode only. Indicates that the checksum was wrong. IODERR Device error (usually a bad message from the remote) IOIMPM Improper mode. Cdr was not opened in a legal mode, or while in binary mode a non-binary card was read. \ C.SER0==.+1 ;KONSTANT TO NORMALIZE "T1" C.DEND: JSP T1,C.SERR ;END-OF-FILE C.BKTL: JSP T1,C.SERR ;BLOCK TO LARGE C.DTER: JSP T1,C.SERR ;CHECKSUM ERROR C.DERR: JSP T1,C.SERR ;DEVICE ERROR (OR REMOTE ERROR) C.IMPM: JSP T1,C.SERR ;IMPROPER MODE (OPEN) C.IMPB: JSP T1,C.SERR ;IMPROPER MODE (BINARY MODE AND NOT BINARY CARD) ;THE FORMAT OF ENTRIES IN THIS NEXT TABLE ARE "XWD FLAGS,BIT" ; WHERE BIT IS THE "DEVIOS" ERROR BIT TO SET, AND ; WHERE FLAGS ARE BITS THAT SAY: ; 1 - ADVANCE THE USERS BUFFER ; 2 - SKIP RETURN (ADVANCE THE NCL MESSAGE) C.SERR: MOVE T1,[XWD 7,IOEND ;E-O-F XWD 3,IOBKTL ;BLOCK-TOO-LARGE XWD 3,IODTER ;DATA-ERROR XWD 3,IODERR ;DEVICE ERROR XWD 1,IOIMPM ;IMPROPER MODE (OPEN) XWD 3,IOIMPM ;IMPROPER MODE (BINARY CARD) ]-C.SER0(T1) ;GET XWD FLAGS,BIT MOVEI S,(T1) ;GET OUR BIT TO SET TLNE T1,4 ;IF THIS BIT IS SET, HRLZ S,S ;THEN PUT THE BIT IN THE LH IORB S,DEVIOS(F) ;AND SET IT TLNE T1,2 ;SKIP RETURN? AOS (P) ;YES. MAKE SURE IT HAPPENS TLNE T1,1 ;ADVANCE INPUT BUFFER? PUSHJ P,NTDAIB## ;YES. GO DO IT. POPJ P, ;ALL DONE SUBTTL 4.2 DATA DECOMPRESSION ROUTINE COMMENT \ DATA SENT TO DECSYSTEM-10 IS ESSENTIALY IMAGE MODE REPRESENTATION MEANING 1CCCCCCC CCCCCCC = SEVEN BIT ENCODED CHARACTER PUNCH 12=B6; PUNCH 11=B5; PUNCH 0=B4 CODE PUNCHES IN ROWS 1-9 0 NONE 1 1 2 2 3 3 4 4 5 5 6 6 7 7 10 8 11 9 12 8-2 13 8-3 14 8-4 15 8-5 16 8-6 17 8-7 01XXXXXX XXXXXX =COUNT OF BLANKS 001XXXXX XXXXX = COUNT OF REPETITIONS, 0-31 0000CCCC CCCCCCCC CCCCCCCCCCCC = TWELVE BIT ENCODED CHARACTER DB.DCS - DEVICE CONTROL STATUS BITS CS.ERR=0001 ;CARD READER ERROR(MASTER ERROR) CS.HEM=0002 ;HOPPER EMPTY CS.RER=0004 ;REGISTRATION ERROR 0010 ;INVALID PUNCH CS.FUL=0020 ;STACKER FULL CS.JAM=0040 ;JAM WHILE FEEDING CS.PCK=0100 ;PICK FAILURE CS.EOF=0200 ;END OF FILE CARD 0400 ;HDW EOF 1000 ;CDR OVERRAN THE PROCESSOR CS.OFL=2000 ;CDR HAS GONE OFF LINE CS.STP=4000 ;CDR STOPPED (CLEARED BY 10 WITH CLEAR STATUS MSG) \ ;SUBROUTINE C.NEXT RETURN THE NEXT CHAR FROM THE DAP MESSAGE POINTED ; TO BY P1 (WITH SUB-MESSAGE LENGTH IN P4) ; ;CALL MOVE P1,BYTE POINTER TO FIRST CHAR OF DATA IN MESSAGE (AFTER TYP) ; MOVE P4,COUNT OF DAP DATA BYTES ; SETZ P3, ;CLEAR THE REPEAT COUNT ; PUSHJ P,C.NEXT ;RETURN CPOPJ ;NO CHAR AVAILABLE (MESSAGE COUNTED OUT, OR ; ; SOMETHING WAS WRONG WITH THE MESSAGE) ; CPOPJ1 ;T1 := THE NEXT 12 BIT CHAR FROM THE STREAM ; ;NOTE. WHEN THIS ROUTINE IS DECOMPRESSING CHARACTERS IT USES P3 AS ; A REPEAT COUNT. IF YOU CLOBBER P3 BETWEEN CALLS TO C.NEXT, YOU ; WILL GET GARBAGE. C.NEXT: ;MAIN ENTRY TO GET NEXT 12 BYTE CHAR. JUMPN P3,C.RPT ;IF WE ARE IN A REPEAT, GO USE LH OF P3 C.NXT0: ;RECURSIVE ENTRY POINT WHEN PICKING ; A REPEATED CHARACTER SOJL P4,C.IERR ;COUNT OFF NEXT BYTE (ERROR IF MESSAGE IS DONE) ILDB T1,P1 ;FETCH THE NEXT CHARACTER TRZE T1,1_7 ;IS THIS A "COMPRESSED" CHAR JRST C.NXT1 ; IF SO, EXPAND IT AND RETURN TRZE T1,1_6 ;IS THIS A REPEATED BLANK? JRST C.NXT2 ; IF SO, SET COUNT AND LET C.RPT LOOSE ON IT. TRZE T1,1_5 ;IS THIS A REPEAT COUNT? JRST C.NXT3 ; IF SO, THEN GET NEXT CHAR AND REPEAT IT. TRZE T1,1_4 ;IS IT AN "UNUSED" FORM... JRST C.IERR ; IF SO, THEN SOMETHING IS WRONG. MOVEI T2,(T1) ;IT MUST BE THE FIRST 4 BITS OF A TWO BYTE CHAR LSH T2,^D8 ;SHIFT UP THE MOST SIGNIFICANT 4 BITS SOJL P4,C.IERR ;COUNT DOWN THE NEXT BYTE ILDB T1,P1 ;GET THE NEXT CHAR IORI T1,(T2) ;OR IN THE HIGH FOUR BITS JRST CPOPJ1## ;GIVE A GOOD RETURN C.NXT1: ;HERE IF THIS IS A "COMPRESSED" CHAR IDIVI T1,20 ;SEPARATE THE ZONES (CLEVER DON'T YOU THINK...) LSHC T2,-2 ;NOW T2 := WORD INDEX, T3(B0, B1) HAS BYTE INDEX MOVE T2,[BYTE (9)000,400,200,100 ;NOW LOAD T2 WITH A WORD THAT BYTE (9)040,020,010,004 ; HAS FOUR DIFFERENT LOW ORDER BYTE (9)002,001,202,102 ; BYTES. WE WILL THEN CLEVERLY BYTE (9)042,022,012,006](T2) ; POSITION IT AT THE TOP OF T2 TLZE T3,(1B0) ;SKIP IF TOP HALF-WORD IS RIGHT. HRLZI T2,(T2) ;MAKE UPPER HALF CONTAIN THE DESIRED BYTE TLZE T3,(1B1) ;SKIP IF THE TOP BYTE IS RIGHT. LSH T2,^D9 ;MOVE THE SECOND BYTE UP TO WHERE IT BELONGS LSHC T1,^D9 ;(REMEMBER THAT T1 HAS TOP 4 BITS ALREADY) JRST CPOPJ1## ;ALL DONE. THE CHAR IS THE LOW 12 BITS IN T1! C.NXT2: ;HERE IF WE HAVE REPEATED BLANKS JUMPN P3,C.IERR ;NESTED REPEATS ARE ILLEGAL! MOVEI P3,(T1) ;COPY THE REPEAT COUNT JUMPE P3,C.NEXT ;IGNORE ZERO LENGTH REPEATS PJRST C.RPT ;PASS THE BUCK TO C.RPT. C.NXT3: ;HERE TO REPEAT AN ARBITRARY CHAR. JUMPN P3,C.IERR ;NEXTED REPEATS ARE NOT ALLOWED. MOVEI P3,(T1) ;COPY THE REPEAT COUNT PUSHJ P,C.NXT0 ;CALL OURSELF RECURSIVLY FOR THE REPEATED CHAR. PJRST C.IERR ;?? THIS IS WRONG. WE SHOULD HAVE ANOTHER CHAR. JUMPE P3,C.NEXT ;LET ZERO LENTGH REPEATS WORK. (WONT HAPPEN) HRLI P3,(T1) ;COPY THE CHAR TO REPEAT SO C.RPT WILL SEE IT. ; PJRST C.RPT ;LET C.RPT DO THE REST. C.RPT: HLRZ T1,P3 ;GET THE CHAR THAT'S BEING REPEATED SUBI P3,1 ;DECREMENT THE COUNT TRNN P3,77 ;SEE IF WE HAVE COUNTED DOWN ALL CHARS. SETZ P3, ; IF WE HAVE, CLEAR THE REPEAT CHAR JRST CPOPJ1## ;GIVE A GOOD RETURN C.IERR: POPJ P, ;GIVE ERROR RETURN (WHAT ELSE CAN I DO??) SUBTTL 4.3 CARD CODE TO ASCII CONVERSION ROUTINE ;C.CONV THIS ROUTINE TRANSLATES A 12 BIT CARD CODE INTO A 7 BIT ; ASCII CHAR (GOD KNOWS HOW...) ;CALL MOVEI T1,"THE 12 BIT CHAR" ; PUSHJ P,C.CONV ;RETURN CPOPJ ;CONVERTED CHAR IN T1 C.CONV: MOVEI T3,(T1) ;PUT THE CHAR IN T3 FOR EXAMINATION SETZB T1,T2 ;CLEAR T1 AND T2 JUMPE T3,C.CNV1 ;BLANKS ARE VERY SIMPLE CAIN T3,5000 ;12-0? MOVEI T3,4242 ;YES, TREAT AS 12-8-2 ([) CAIN T3,3000 ;NO, 11-0? MOVEI T3,2202 ;YES, TREAT AS 11-8-2 (!) LDB T2,[POINT 3,T3,26] TRNE T3,3 ;DIDDLE T1 AND T2 TO FORM TRC T2,7 ;INDEXES INTO CHAR TABLE TRNE T3,74 TRO T2,10 TRNE T3,314 TRO T1,2 TRNE T3,525 TRO T1,1 TLNE S,IOS029 ;IN 026 CHAR SET MODE? TRO T2,20 ;NO, USE SECOND TABLE C.CNV1: LDB T1,CRCVPT##(T1) ;GET 7-BIT TRANSLATION POPJ P, XLIST ;DON'T LIST THE LITERALS $LIT LIST NTCDRX::PRGEND TITLE NETDDP - NETWORK "DDCMP" DEVICE SERVICE ROUTINES - V001 SUBTTL NETDDP -- RDH/ 21-APR-82 SEARCH F,S,NETPRM,D36PAR,MACSYM $RELOC $HIGH ;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE SUED ; OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE. ; ; COPYRIGHT (C) 1982,1984 BY DIGITAL EQUIPMENT CORP., MAYNARD, MASS. XP VNETDP,001 ;PUT VERSION NUMBER IN GLOB AND LOADER MAP NETDDP::ENTRY NETDDP SUBTTL GENERAL DEFINTIONS PECULIAR TO THE DDP DEVICE/KONTROLLER ;DEVIOUS BITS XP IOSDDK,IOSFFB_0 ;DDP IS IN USE AS A KONTROLLER ; IF 0 THEN USER I/O (IN, OUT UUOS) OK ; IF 1 THEN USER GETS IO.IMP XP IOSDDH,IOSFFB_1 ;DDP KONTROLLER IS "HALTED" (BY DRIVER REQUEST) ; IF 0 THEN DDP RUNNING, PASS DATA ; IF 1 THEN DDP DOWN, DISCARD DATA XP IOSDDD,IOSFFB_2 ;DDP'S DDCMP PROTOCOL IS DOWN ; IF 0 THEN DDCMP IS RUNNING ; IF 1 THEN DDCMP IS DOWN ;DDP DDB WORDS ABOVE AND BEYOND STANDARD NETWORK DEVICE DEFINE X(NAM,SIZ<1>),-SIZ> %%%OFF==NETLEN X DDPUSR ;LINE USER OF DDP KONTROLLER (E.G., DECNET) X DDPLBK ;DRIVER'S LINE BLOCK ADDRESS X DDPQOB ;POINTER TO QUEUE OF OUTPUT MESSAGES X DDPMBP ;POINTER TO RECEIVE MESSAGE BUFFER X DDPDLN,0 ;LENGTH OF DDP DDB SUBTTL UUO INTERFACE - DEVSER UUO DISPATCH VECTOR JRST NTDONL## ;(-5) CHECK IF DEVICE IS ONLINE JRST ECOD2## ;(-4) DEVOP UUO JRST REGSIZ## ;(-3) BUFFER SIZE JRST CPOPJ## ;(-2) INITIALIZATION JRST CPOPJ1## ;(-1) HUNG DEVICE CHECK (REMOTE DOES IT) NDEVDP::JRST NTDREL## ;(00) RELEASE JRST NTDCLO## ;(01) CLOSE JRST DDPUOU ;(02) BUFFERED OUT JRST DDPUIN ;(03) BUFFERED IN SUBTTL UUO INTERFACE - DDB CREATION ;TSTDDP - TEST FOR DDP DEVICE, CREATE DDB IF NEEDED ;CALL MOVEI P1,FLAGS ;(ONLY MATCH IF LOOKING FOR PHYSICAL DEVICE) ; MOVE T1,[SIXBIT /DD?NNX/] ;DEVICE NAME ; PUSHJ P,TSTDDP ;RETURN CPOPJ ;NOT A DDP DEVICE ; CPOPJ1 ;IS A DDP DEVICE; F := DDP DDB. TSTDDP::TRNE P1,DD%LOG## ;LOOKING AT LOGICAL NAMES? POPJ P, ;GIVE UP NOW IF NOT PHYSICAL SEARCH HLRZ T2,T1 ;GET JUST THE NAME CAIL T2,'DDA' ;SEE IF WITHIN RANGE OF ALLOWABLE CAILE T2,'DDH' ; "CONTROLLER"S POPJ P, ;NOT A DDP-CLASS DEVICE PUSHJ P,NTDPRV## ;DDP'S ARE PRIVILEGED GADGETS POPJ P, ;AND THE USER ISN'T PUSHJ P,SAVJW## ;WE CLOBBER W RIGHT AWAY, AND J IF WE CONNECT. PUSHJ P,SAVE4## ;NETSER CLOBBERS MOST OF THESE NETDBJ ;BETTER INTERLOCK FROM HERE ON OUT. PUSH P,T1 ;SAVE THE DEVICE NAME PUSHJ P,DVSCVT## ;GET THE NODE NUMBER FROM THE NAME PJRST TPOPJ## ;NOT A NETWORK NAME. MOVEI T1,(T2) ;COPY THE NODE NUMBER PUSHJ P,SRCNDB## ;GET A NDB POINTER PJRST TPOPJ## ;NO NODE MEANS NO DDP MOVEI P1,(W) ;COPY THE NDB POINTER FOR MAKDDB MOVEI T1,'DDP' ;GET GENERIC DEVICE NAME IN RH(T1) PUSHJ P,SRCNDT## ;SEE IF THE NODE SUPPORTS DDP'S PJRST TPOPJ## ;IF NOT, THEN DEVICE DOESN'T EXIST LDB T1,[POINT 6,(P),17] ;POINT TO "CONTROLLER" CHARACTER SUBI T1,'A' ;CONVERT TO A CONTROLLER NUMBER LDB T2,[POINT 3,(P),35] ;GET THE UNIT DIGIT (NUMERIC) CAIL T2,0 ;MAKE SURE THAT IT'S IN THE CAILE T2,7 ; RANGE 0-7 PJRST TPOPJ## ;NOT A VALID DIGIT. LSH T1,3 ;CONTROLLER BECOMES TOP HALF OF "PUNIT" IORI T1,(T2) ;T1 := FULL UNIT SPECIFICATION PUSH P,T1 ;SAVE "PUNIT" VALUE UNTIL WE SEND THE CONNECT. MOVE P2,-1(P) ;GET THE FULL NAME BACK PUSHJ P,MAKDDP ;MAKE A DDP DDB JRST TTPOPJ## ;NO CORE. GIVE ERROR RETURN POP P,T1 ;GET THE UNIT NUMBER BACK DPB T1,PUNIT## ;STORE THE UNIT NUMBER IN THE DDB MOVEI W,(P1) ;SET UP THE NDB POINTER AGAIN PUSHJ P,NTDCNT## ;ATTEMPT TO CONNECT THE DEVICE JRST [PUSHJ P,UNLDDB## ;CONNECT FAILED. FREE THE DDB JRST TPOPJ##] ;AND GIVE UUOCON THE ERROR RETURN PJRST TPOPJ1## ;ALL DONE. GOOD RETURN, F := DDB POINTER. SUBTTL UUO INTERFACE - CONVERT LINE-ID TO DDB ;DDPSRC - CONVERT LINE-ID TO DDB ;CALL MOVE T2, ; PUSHJ P,DDPSRC ; ; ;RETURN CPOPJ IF NOT A DDP LINE ID ;RETURN CPOPJ1 WITH DDB ADDRESS IN T2 DDPSRC: PUSH P,T1 ;SAVE WORK AC'S LOAD T1,LIDEV,+T2 ;GET LINE ID CAIE T1,LD.DDP ;IS IT ONE OF OURS? JRST TPOPJ## ;NO, DON'T TOUCH IT PUSH P,T2 ;SAVE THE OTHER TEMPS PUSH P,T3 PUSH P,T4 MOVE T4,PDVTYP## ;GET DEVTYP POINTER TLC T4,F^!T2 ;CONVERT INDEX REGISTER FOR OUR LOOP BELOW LOAD T1,LIKON,+T2 ;GET KONTROLLER NUMBER(REALLY NODE) LOAD T3,LIUNI,+T2 ;GET THE UNIT NUMBER IDIVI T1,10 ;GET THE HIGH ORDER DIGIT OF NODE NUMBER ADDI T1,'0' ;MAKE IT SIXBIT LSH T1,6 ;SHIFT FOR NEXT DIGIT ADDI T1,'0'(T2) ;SIXBIT ALSO LSH T1,6 ;SHIFT ONE LAST TIME MOVEI T2,(T3) ;COPY UNIT NUMBER IDIVI T2,10 ;SPLIT INTO 'KONTROLLER' AND 'UNIT' ADDI T1,'0'(T3) ;INCLUDE THE UNIT NUMBER HRLI T1,'DDA'(T2) ;FORCE KONTROLLER NUMBER DDBSRL ;LOCK THE DDB DATA BASE HLRZ T2,DDBTAB##+.TYDDP ;GET ADDRESS OF FIRST DDB IN CHAIN JUMPE T2,DDPSR2 ;SKIP LOOP IF NO DDP DDB DDPSR1: CAMN T1,DEVNAM(T2) ;IS THIS THE ONE JRST DDPSR2 ;YES, WE FOUND IT HLRZ T2,DEVSER(T2) ;NO, STEP TO NEXT DDB JUMPE T2,DDPSR2 ;EXIT LOOP IF NONE THERE LDB T3,T4 ;GET DEVICE TYPE CAIN T3,.TYDDP ;IS IT STILL A DDP? JRST DDPSR1 ;LOOP IF SO DDPSR2: DDBSRU ;DONE FOOLING WITH DDBS SKIPN T2 ;NO SKIP IF NO DDB JRST DDPSR3 ;WE DIDN'T FIND ON AOS -4(P) ;WE FOUND ONE, SKIP RETURN MOVEM T2,-2(P) ;STORE DDB ADDRESS DDPSR3: DMOVE T1,-3(P) ;RESTORE T1 & T2 DMOVE T3,-1(P) ;RESTORE T3 & T4 ADJSP P,-4 ;BALANCE STACK POPJ P, ;RETURN TO CALLER SUBTTL UUO INTERFACE - DDB DESTRUCTION ;ZAPDDP - SEE IF OK TO DESTROY DDP DDB ;CALL MOVE F, ; PUSHJ P,ZAPNET ;RETURN CPOPJ ;ALWAYS ; ;IF DDP IS IN USE AS KONTROLLER (AND THUS CANNOT BE ZAPPED) THEN THIS ;ROUTINE (CALLED BY ZAPNET) RETURNS, AND ZAPNET DOES NOTHING. IF THE ;DDP IS IDLE (I.E., IS NOT A KONTROLLER), THEN ZAPNET IS ALLOWED TO ;GO AHEAD AND DESTROY THE DDB, RELEASING THE DDP DEVICE BACK TO THE ;REMOTE NODE. ZAPDDP::MOVE S,DEVIOS(F) ;GET THE I/O STATUS BITS TLNN S,IOSDDK ;IN USE AS A KONTROLLER? PJRST ZAPNE1## ;NO, OFF TO ZAPNET TO ZAP THE DEVICE POPJ P, ;YES, RETURN HAVING DONE NOTHING SUBTTL UUO INTERFACE - IN UUO ;HERE FROM UUOCON ON USER IN UUO DDPUIN: TLNE S,IOSDDK ;IS DDP IN USE AS A KONTROLLER PJRST DDPIMP ;YES, NAUGHTY BOY, HE GETS AN ERROR RETURN ;DDP IS AVAILABLE AS AN I/O DEVICE TO THE USER PUSHJ P,SAVE4## ;WE NEED LOTS OF P'S MOVSI S,IOSUSI ;CLEAR THE UUOCON-STOPPED-INPUT BIT ANDCAB S,DEVIOS(F) ; SINCE WE ARE DOING AN IN NOW DDPUI1: PUSHJ P,NTDSET## ;SETUP NETWORK CONTEXT (W, S, ETC) TLNE S,IOSERR ;ANYTHING SERIOUSLY WRONG? JRST DDPIER ;YES, NODE DOWN, ETC. TLNE S,IOBEG ;HAVE WE BEEN HERE BEFORE? PUSHJ P,DDPFIR ;NO, FIRST IN, SPECIAL MOVSI S,IO ;THE IN VERSUS OUT BIT ANDCAB S,DEVIOS(F) ;WE ARE DOING "IN" TYPE STUFF ;NOW TRY TO FILL A USER BUFFER FROM INCOMING DATA MESSAGE(S) DDPUI3: PUSHJ P,NTDIBA## ;VERIFY BUFFERS ETC POPJ P, ;NO BUFFER, RETURN TO UUOCON HRRZ T1,DEVPCB(F) ;ADDRESS OF PENDING PCB CHOCK FULL OF DATA JUMPE T1,DDPUI8 ;NO DATA, GO WAIT FOR INPUT PUSHJ P,NTDDID## ;PROCESS THIS NCL SUBMESSAGE JRST DDPUI1 ;LOOP ON INPUT ;HERE WHEN NO INPUT DDPUI8: PUSHJ P,NTDONL## ;CHECK THE DEVICE JRST DDPIER ;ERROR? PUSHJ P,NTDXDQ## ;SEND ANY DATA REQUESTS NEEDED PUSHJ P,NTDWTI## ;WAIT FOR INPUT POPJ P, ;NON-BLOCKING, BACK TO UUOCON JRST DDPUI1 ;LOOP BACK FOR INPUT PROCESSING ;HERE ON INPUT ERROR FROM NTDONL DDPIER: MOVE S,DEVIOS(F) ;ENSURE FRESH COPY TLNN S,IOSCON ;IS DEVICE STILL CONNECTED? PJRST NTDGON## ;NO - NETWORK CONNECTION GONE TLNE S,IOSERR ;IS THE DDP "OFFLINE" PUSHJ P,NTDHNG## ;YES, COMPLAIN JRST DDPUI1 ;BACK TO TRY INPUT PROCESSING SUBTTL UUO INTERFACE - OUT UUO ;HERE FROM UUOCON ON OUT UUO DDPUOU: TLNE S,IOSDDK ;IS DDP IN USE AS A KONTROLLER? PJRST DDPIMP ;YES, DISALLOW UUO-LEVEL DIDDLING ;DDP IS AVAILABLE AS AN I/O DEVICE PUSHJ P,SAVE4## ;USE LOTS OF P'S MOVSI S,IOSUSO ;CLEAR THE UUOCON-STOPPED-OUTPUT BIT ANDCAB S,DEVIOS(F) ; SINCE ITS DOING ANOTHER OUT ;LOOP OUTPUTTING DATA FROM USER'S I/O BUFFER(S) DDPUO1: PUSHJ P,NTDSET## ;SETUP NETWORK ACS (W, S, ETC) TLNE S,IOSERR ;ANYTHING SERIOUSLY WRONG? JRST DDPOER ;YES, SEE IF STILL THERE TLNE S,IOBEG ;FIRST TIME HERE? PUSHJ P,DDPFIR ;YEAH, DO SOME CLEANUP FIRST MOVSI S,IO ;THE IN VERSUS OUT BIT IORB S,DEVIOS(F) ;WE ARE DOING "OUT" TYPE STUFF ;TRY TO SEND ONE BUFFER'S WORTH OF DATA DDPUO3: PUSHJ P,NTDCDQ## ;CHECK TO SEE IF ANY DATA REQUESTS AVAILABLE JRST DDPUO8 ;NONE AVAILABLE, WAIT MOVEI T1,^D08 ;DDP DATA IS BY DEFINITION 8 BITS PUSHJ P,NTDSOB## ;SET UP AN OUTPUT BUFFER POPJ P, ;TIME TO RETURN TO UUOCON (NO MORE DATA, ETC) MOVEI T1,PCV.NC ;NO BIT DIDDLING, JUST STRAIGHT IMAGE DATA MOVEI T2,DC.DAR ;NCL DATA WITH EOR PUSHJ P,NTDXMT## ;SEND A BUFFER JRST DDPUO7 ;NO FREE CORE FOR PCB PUSHJ P,NTDDDQ## ;WE JUST USED UP ONE DATA REQUEST SKIPE DEVAXO+1(F) ;DID NTDXMT EMPTY THE BUFFER? JRST DDPBTL ;NO - BLOCK TOO LARGE ERROR PUSHJ P,NTDAOB## ;ADVANCE USER'S BUFFER JRST DDPUO1 ;TRY FOR ANOTHER BUFFER ;HERE WHEN NO FREE CORE FOR OUTPUT PCBS DDPUO7: CAIE T1,0 ;0 MEANS NO FREE CORE STOPCD .,STOP,DDPXMT, ;++ NTDXMT FAILED, NOT RUNNING OUT OF FREECORE PUSHJ P,NETSLP## ;WAIT FOR FREE CORE JRST DDPUO1 ;LOOP BACK AND TRY AGAIN ;HERE TO WAIT FOR OUTPUTABILITY DDPUO8: PUSHJ P,NTDONL## ;ENSURE NICE JUICY DEVICE JRST DDPOER ;CHECK OUT BADNESS PUSHJ P,NTDWTO## ;WAIT FOR OUTPUT (DATA REQUESTS) POPJ P, ;NON-BLOCKING, BACK TO UUOCON NOW JRST DDPUO1 ;TRY OUTPUT AGAIN ;HERE ON OUTPUT ERROR FROM NTDONL DDPOER: MOVE S,DEVIOS(F) ;ENSURE FRESH COPY TLNN S,IOSCON ;IS DDP DEVICE STILL CONNECTED? PJRST NTDGON## ;NO, NETWORK CONNECTION GONE TLNE S,IOSERR ;IS THE DDP "OFFLINE" PUSHJ P,NTDHNG## ;YEAH, COMPLAIN JRST DDPUO1 ;LOOP BACK AND TRY OUTPUT AGAIN SUBTTL UUO INTERFACE - DDP SERVICE INITIALIZATION DDPFIR: MOVSI S,IOBEG!IOSREL ;KRUFTY BITS ANDCAB S,DEVIOS(F) ;CLEAR OLD BITS IN DDB SETZM DEVAXI(F) ;CLEAR DANGLING INPUT SETZM DEVAXO(F) ;AND ANY DANGLING OUTPUT POPJ P, ;NOW SET FOR CLEAN I/O SUBTTL UUO INTERFACE - DDP DEVICE ERRORS ;HERE WHEN USER TRIED TO PLAY WITH A DDP IN KONTROLLER MODE DDPIMP: MOVEI S,IOIMPM ;IMPROPER MODE JRST DDPERS ;SET ERROR AND RETURN ;HERE WHEN OUTPUT BUFFER OVERFLOWED NETWORK PCB DDPBTL: MOVEI S,IOBKTL ;BLOCK-TOO-LARGE FOR NETWORK BUFFER DDPERS: IORB S,DEVIOS(F) ;SET ERROR BITS IN DDB POPJ P, ;ERROR RETURN TO UUOCON SUBTTL UUO INTERFACE - DDP. UUO - CONTROL OF DDP KONTROLLER ;THE DDP. UUO ALLOWS UUO-LEVEL CONTROL OF DDP DEVICES/KONTROLLERS. ;CALL IS: ; ; XMOVEI AC,ADDRESS ; DDP. AC, ; ERROR RETURN ; NORMAL RETURN ; ;ADR: LENGTH,,FUNCTION ; DDP DEVICE ID ; ARGUMENT (AS NEEDED) ;DEFINE ERROR RETURNS DPIFC%==ECOD1## ;ILLEGAL DDP. FUNCTION CODE DPLTS%==ECOD2## ;ARGUMENT LIST TOO SHORT DPIDV%==ECOD3## ;ILLEGAL DDP. DEVICE (NOT DDP, ETC.) DPNPR%==ECOD4## ;USER NOT PRIVILEGED DPIOM%==ECOD5## ;ILLEGAL OPERATION MODE (DDP NOT IN KONTROLLER MODE) DPIUN%==ECOD6## ;ILLEGAL USER NAME DPIOJ%==ECOD7## ;DDP IS IN USE BY ANOTHER USER/JOB DPADC%==ECOD10## ;ADDRESS CHECK DDPUUO::MOVE M,T1 ;COPY ARGUMENT BLOCK ADDRESS PUSHJ P,SXPCS## ;SET PCS JRST DPADC% ;ADDRESS CHECK PUSHJ P,GETEWD## ;GET BLOCK LENGTH AND FUNCTION JRST DPADC% ;ADDRESS CHECK HLRZ P2,T1 ;SAVE LENGTH OF ARG LIST TRZ P2,777000 ;CLEAR OUR RESERVED BITS HRRE P1,T1 ;ISOLATE FUNCTION CODE SOJL P2,DPLTS% ;ERROR IF TOO SHORT CAML P1,[DDPCST-DDPDMT] ;RANGE CHECK BOTH THE CUSTOMER CAILE P1,DDPDMX ;AND DEC DEFINED FUNCTION CODES JRST DPIFC% ;ILLEGAL FUNCTION CODE SOJL P2,DPLTS% ;ERROR IF ARG LIST TOO SHORT PUSHJ P,NTDPRV## ;IS THIS USER PRIVILEGED? JRST DPNPR% ;NO, HE LOSES PUSHJ P,GETEW1## ;GET THE DEVICE NAME/ID JRST DPADC% ;ADDRESS CHECK PUSHJ P,DVCNSG## ;TRY TO DECIPHER THE DEVICE NAME JRST DPIDV% ;ILLEGAL DEVICE LDB T1,PDVTYP## ;GET DEVICE TYPE CAIE T1,.TYDDP ;IS IT A REAL DDP DEVICE? JRST DPIDV% ;NO, ILLEGAL DEVICE MOVE S,DEVIOS(F) ;PRE-LOAD S PJRST @DDPDMT(P1) ;DISPATCH ON FUNCTION DDPCST==. ;END OF CUSTOMER DISPATCH TABLE IFIW CPOPJ## ;(-1) FIRST CUSTOMER FUNCTION GOES HERE DDPDMT: IFIW DDPCAS ;(00) ASSIGN (CREATE) DDP DEVICE IFIW DDPCZP ;(01) ZAP (DESTROY/RELEASE) DDP DEVICE IFIW DDPCDV ;(02) SET TO DEVICE MODE IFIW DDPCKN ;(03) SET TO KONTROLLER MODE IFIW DDPCUS ;(04) SET KONTROLLER USER IFIW DPIFC% ;(05) RESERVED/ILLEGAL IFIW DPIFC% ;(06) RESERVED/ILLEGAL IFIW DPIFC% ;(07) RESERVED/ILLEGAL IFIW DDPCHA ;(10) HALT KONTROLLER PROTOCOL IFIW DDPCIN ;(11) INITIALIZE KONTROLLER PROTOCOL IFIW DDPCMA ;(12) SET TO MAINTENANCE MODE PROTOCOL DDPDMX==.-DDPDMT ;MAX DDP COMMAND FUNCTION ;DDPCAS - ASSIGN (CREATE IF NEEDED) DDP DEVICE ;NOTE THAT THE DDP WILL HAVE BEEN CREATED IF NECESSARY BY THE DVCNSG ;PRIOR TO MAIN FUNCTION DISPATCH . . . DDPCAS: PUSHJ P,DDPCAZ ;SEE IF WE CAN MUNCH ON THE DDP JRST DPIOJ% ;OTHER USER HAS THE DDP MOVEI T1,ASSCON ;THE "IN USE BY ASSIGN COMMAND" FLAG IORM T1,DEVMOD(F) ;WE NOW OWN THE DDP DPB J,PJOBN## ;MAKE SURE "WE" IS US JRST CPOPJ1## ;SUCCESSFUL RETURN ;DDPCZP - ZAP (DESTROY) THE DDP DEVICE DDPCZP: PUSHJ P,DDPCAZ ;SEE IF WE CAN MUNCH ON THE DDP JRST DPIOJ% ;OTHER USER HAS THE DDP TLNE S,IOSDDK ;IS THE DDP IN USE AS A KONTROLLER? PUSHJ P,DDPKZP ;YES, ZAP THE KONTROLLER USER FIRST MOVEI T1,ASSCON ;THE "IN USE" BY ASSIGNMENT FLAG ANDCAM T1,DEVMOD(F) ;ALLOW UUOCON TO KRUMP ON THE DDB NOW PUSHJ P,URELEA## ;NOW DO UUO-LEVEL DDB ZAPPING ; (EVENTUALLY WINDING UP IN ZAPNET/ZAPDDP) JRST CPOPJ1## ;SUCCESSFUL RETURN ;HELPER FOR DDPCAS/DDPCZP ; ;RETURNS CPOPJ IF THE DDP DDB IS NOT AVAILABLE TO THIS JOB (I.E., SOME OTHER ;JOB HAS THE DDB "IN USE"); RETURNS CPOPJ1 IF THE DDB CAN BE ASSIGNED TO ;THIS JOB. DDPCAZ: MOVEI T1,ASSCON!ASSPRG;THE "IN USE" FLAGS LDB T2,PJOBN## ;THE JOB NUMBER (IF ANY) USING THE DDP TDNE T1,DEVMOD(F) ;IS THE DDB IN USE BY A JOB? CAMN T2,J ;YES, IS THAT JOB THIS JOB? AOS (P) ;EITHER AVAILABLE, OR ALREADY IN USE BY US POPJ P, ;RETURN AS APPROPRIATE ;DDPCDV - SET DDP TO "DEVICE" MODE DDPCDV: TLNN S,IOSDDK ;IN KONTROLLER MODE? JRST CPOPJ1## ;NO, ALL DONE HERE PUSHJ P,DDPKZP ;YES, ZAP THE KONTROLLER'S USER FIRST ; (ALSO FLUSHES ANY QUEUED DATA) MOVSI S,IOSDDK ;THE KONTROLLER-MODE FLAG ANDCAB S,DEVIOS(F) ;SWITCH THE DDP INTO DEVICE MODE JRST CPOPJ1## ;SUCCESSFUL RETURN ;DDPCKN - SET DDP TO "KONTROLLER" MODE DDPCKN: MOVSI S,IOSDDK ;THE KONTROLLER MODE FLAG IORB S,DEVIOS(F) ;SWITCH TO KONTROLLER MODE JRST CPOPJ1## ;ALL DONE HERE ;DDPCUS - SET THE KONTROLLER'S USER DDPCUS: SOJL P2,DPLTS% ;ERROR IF TOO SHORT PUSHJ P,GETEW1## ;GET THE USER NAME (INTO T1) JRST DPADC% ;ADDRESS CHECK DDPCU1: PUSHJ P,KONUSN## ;TRANSLATE USER NAME INTO TYPE (IN T2) JRST DPIUN% ;ILLEGAL USER NAME DDPCU2: CAMN T2,DDPUSR(F) ;IS USER TYPE CHANGING? JRST CPOPJ1## ;NO, THIS IS A NO-OP THEN ;*** KROCK FOR NOW CAIE T2,DD.NOB ;ALLOW NOBODY CAIN T2,DD.DEC ;AND DECNET, THAT'S IT CAIA ;HAPPY JRST DPIUN% ;UNHAPPY ;CHANGING DRIVER ("USER") TYPE, QUIESCE THE KONTROLLER FIRST TLNN S,IOSDDK ;BUT IS THE DDP A KONTROLLER? JRST DDPCU9 ;NO, NOT TO WORRY, JUST SET NEW USER PUSH P,T2 ;SAVE TENTATIVE NEW USER PUSHJ P,DDPKZP ;"ZAP" THE KONTROLLER MOVSI S,IOSDDK ;RESET THE "KONTROLLER" STATUS IORB S,DEVIOS(F) ; 'CUZ DDPKZP CLEARS THE KONTROLLER STATUS POP P,T2 ;RETRIEVE NEW USER DDPCU9: HRRZM T2,DDPUSR(F) ;SET NEW USER TYPE PUSHJ P,@DDPCUT(T2) ;DO ANY HACKERY REQUIRED BY NEW USER JRST DPIUN% ;SOMETHING IS ILLEGAL JRST CPOPJ1## ;SUCCESSFUL RETURN DEFINE X(USR,CON,DSP),< IFN .-DDPCUT-DD.'USR,< PRINTX ? DDPCUT "USR" initialization dispatch out of order> IFE CON, IFN CON, > ;END X MACRO DDPCUT: X (NOBODY,1,CPOPJ1##) X (ANF,FTNET,NTDSTP##) X (DECNET,FTDECN,DDPC2T) X (PROGRA,1,CPOPJ##) X (IBMCOM,1,CPOPJ##) IFN .-DDPCUT-,< PRINTX ? DDPCUT initialization dispatch missing> ;DDPC2T - INITIALIZE FOR DECNET USER IFN FTDECN,< DDPC2T: SKIPE DDPLBK(F) ;ALREADY HAVE LINE BLOCK? PJRST CPOPJ1## ;YES, SKIP THIS SETZ T3, ;START OFF WITH A CLEAN LINE ID MOVEI T1,LD.DDP ;GET THE DEVICE TYPE STOR T1,LIDEV,+T3 ;SAVE IN LINE ID HRRZ T1,DEVNET(F) ;NODE NUMBER OWNING THE DDP DEVICE STOR T1,LIKON,+T3 ;SAVE AS KONTROLLER NUMBER LDB T1,PUNIT## ;GET THE DDP UNIT NUMBER AT SAID NODE STOR T1,LIUNI,+T3 ;SAVE AS THE UNIT NUMBER MOVEI T1,DI.ICB ;OPEN THIS CIRCUIT PUSHJ P,DDPDVR ;TELL DLL OF NEW KONTROLLER POPJ P, ;GIVE ERROR RETURN MOVEM T1,DDPLBK(F) ;REMEMBER THE DLL'S DATA BLOCK ADDRESS JRST CPOPJ1## ;GIVE A GOOD RETURN > ;END IFN FTDECN ;DDPCHA - HALT THE DDP KONTROLLER DDPCHA: TLNN S,IOSDDK ;IS DDP IN KONTROLLER MODE? JRST DPIOM% ;ILLEGAL OPERATING MODE JRST DPIFC% ;*** ILLEGAL FUNCTION . . . ;DDPCIN - INITIALIZE DDP KONTROLLER DDPCIN: TLNN S,IOSDDK ;IS DDP IN KONTROLLER MODE? JRST DPIOM% ;NO, ERROR JRST DPIFC% ;*** ILLEGAL FUNCTION . . . ;DDPCMA - SET DDP KONTROLLER TO MAINTENANCE MODE DDPCMA: TLNN S,IOSDDK ;IS DDP IN KONTROLLER MODE? JRST DPIOM% ;NO, ERROR JRST DPIFC% ;*** ILLEGAL FUNCTION . . . SUBTTL NETSER INTERFACE IFIW DDPNND ;(-5) NODE WENT DOWN IFIW DDPNRL ;(-4) DISCONNECT ("RELEASE") INIT RECEIVED IFIW NTDCNC## ;(-3) STANDARD CONNECT CONFIRM PROCESSOR IFIW NTDSTP## ;(-2) ERROR - WE DON'T POST DDBS IFIW DDPNIQ ;(-1) DATA REQUEST PROCESSOR DDPNDP::IFIW DDPNIL ;(00) INCOMING NCL TO PROCESS IFIW CPOPJ## ;(01) SHOULD NEVER RECEIVE DATA SANS EOR IFIW DDPNIN ;(02) RECEIVE DATA WITH EOR IFIW DDPNST ;(03) DEVICE STATUS IFIW DDPNCT ;(04) DEVICE CONTROL IFIW CPOPJ## ;(05) UID (?) IFIW CPOPJ## ;(06) FILE SPECIFICATION (?) SUBTTL NETSER INTERFACE - INCOMING NCL PROCESSORS ;HERE FOR CONNECT INITIATE NDDPCI::PUSH P,U ;PROTECT THE INPUT PCB PUSHJ P,DPCIDD ;ALLOCATE US A NETWORK DDP DEVICE DDB JRST DPCIE3 ;NO FREE CORE FOR EVEN A DDB??? JEEEZZ HRRZ T1,F ;ADDRESS OF NEWLY-ACQUIRED DDB MOVEI T2,LAT.OK ;INITIAL LAT STATE PUSHJ P,GETSLA## ;GET A LAT SLOT FOR THE DDB JRST DPCIE2 ;NO FREE LAT SLOTS, BOMB THE CONNECT INIT DPB T1,NETSLA## ;REMEMBER THE LAT SLOT HLRZ T1,P3 ;GET THE REMOTE'S "LAT" SLOT DPB T1,NETDLA## ;AND REMEMBER THAT TOO ;DPN(,PID) PUSHJ P,XSKIP## ;SKIP THE REMOTE'S REQUEST ;SPN(OBJ,) PUSHJ P,EBI2BI## ;GET REMOTE'S OBJECT TYPE CAIE T1,OBJ.DP ;MAKE SURE IT IS CONSISTENT JRST DPCIE4 ;WHOA! WHAT NONSENSE IS THIS? ;SPN(,PID) PUSHJ P,EBI2BI## ;GET REMOTE "UNIT" NUMBER CAIL T1,0 ;CAN'T BE NEGATIVE (TEXT???) CAILE T1,77 ;AND CAN'T EXCEED DDH7 JRST DPCIE4 ;MORE NONSENSE DPB T1,PUNIT## ;STORE DEVICE UNIT NUMBER LSHC T1,-3 ;SEPARATE "CONTROLLER" AND "UNIT" LSH T1,^D18-3 ;PARTIALLY POSITION LSHC T1,3 ;MAKE XWD CONTROLLER,UNIT IOR T1,['DDA 0'] ;SIXBITDEVICEIFY THE VALUE IORM T1,DEVNAM(F) ;MAKE FULL-FLEDGED DEVICE NAME ;(MAKDDC LEFT THE NODE NUMBER FIELD SETUP) ;CONTINUED ON NEXT PAGE ;CONTINUED FROM PREVIOUS PAGE ;PROCESS THE MML AND FEA FIELDS PUSHJ P,NTDCNF## ;SLURP UP MML AND RLN JFCL ;NOT USED ;WE LIKE THE DEVICE, ACCEPT THE CONNECT (SEND A CONNECT CONFIRM) MOVE T1,[NTDXMN##,,NTDXPN##] ;SPN AND DPN ROUTINES PUSHJ P,NCSCNC## ;SEND CONNECT CONFIRM JRST DPCIE1 ;AFTER ALL THAT WORK, CAN'T BUILD A MESSAGE! ;THE DEVICE IS NOW READY AND RARING TO GO. FOR LACK OF ANYTHING BETTER ;TO DO (AND BECAUSE IT WAS THE REASON FOR CREATING DDP'S IN THE FIRST ;PLACE) MAKE THE DDP INTO A DECNET KONTROLLER PUSHJ P,DDPCKN ;MAKE A KONTROLLER OUT OF IT STOPCD .,STOP,DDPKON, ;++ CAN'T MAKE A KONTROLLER OUT OF DDP MOVEI T2,DD.DEC ;USER: DECNET PUSHJ P,DDPCU2 ;ANNOUNCE NEW KONTROLLER TO DECNET JRST [PUSHJ P,DDPCDV ;WELL! UNMAKE IT A KONTROLLER STOPCD .,STOP,DDPBAU, ;++ BEING AWFULLY UNCOOPERATIVE! JRST UPOPJ1##] ;AND LEAVE DEVICE LYING AROUND ;IF DDCMP ALREADY RUNNING, MAKE SURE DECNET PAYS ATTENTION MOVE S,DEVIOS(F) ;FRESH COPY OF DEVIOUS BITS TLNN S,IOSDDD ;DDCMP UP AND RUNNING? PUSHJ P,DDPKUP ;YES, CONJURE UP ON ONLINE INTERRUPT ;ALL DONE JRST UPOPJ1## ;SUCCESSFUL RETURN ;HELPER TO CREATE DDB (NETSER INTERRUPT LEVEL) DPCIDD: PUSHJ P,SAVE4## ;PROTECT INPUT POINTER/ET AL PUSHJ P,SAVJW## ;ALSO J AND W MOVE P1,W ;POSITION NDB POINTER FOR MAKDDC SETZB P2,J ;FRESH SLATE FOR THE NAME ;ENTRY FROM TSTDDP (UUO LEVEL) MAKDDP: SKIPN W,NDTTAB##+OBJ.DP ;POSITION NDT POINTER FOR MAKDDC STOPCD .,STOP,DDPNDT, ;++ NO NDT ENTRY SETZ P3, ;NO LOGICAL NAME (YET, ANYWAY) MOVEI T2,DDPDLN ;LENGTH OF A DDP DDB PUSHJ P,MAKDDC## ;MAKE GENERAL NETWORK DEVICE DDB POPJ P, ;NO CORE, ERROR RETURN MOVSI T1,DEPRAS ;THE RESTRICTED-DEVICE FLAG IORM T1,DEVSTA(F) ;REQUIRE PRIVILEGES TO PLAY WITH DDPS PUSHJ P,LNKDDB## ;MAKE THE DDB "REAL" JRST CPOPJ1## ;SUCCESS RETURN WITH NICE SHINY NEW DDB ;ERRORS FOR DDP CONNECT INIT DPCIE1: LDB T1,NETSLA## ;GET LAT SLOT INDEX PUSHJ P,GIVSLA## ;FREE UP THE LAT DPCIE2: PUSHJ P,UNLDDB## ;FREE UP THE DDB DPCIE3: MOVEI T1,RSN.XN ;REASON: NO RESOURCES JRST UPOPJ## ;RESTORE U AND ERROR EXIT DPCIE4: LDB T1,NETSLA## ;GET LAT SLOT INDEX PUSHJ P,GIVSLA## ;FREE UP THE LAT PUSHJ P,UNLDDB## ;FREE UP THE DDB MOVEI T1,RSN.OT ;REASON: JUNK JRST UPOPJ## ;RESTORE U AND ERROR EXIT ;HERE FOR DISCONNECT INITIATE DDPNRL: MOVE S,DEVIOS(F) ;GET THE DDP I/O STATUS FLAGS TLNE S,IOSDDK ;IN USE AS A KONTROLLER? PUSHJ P,DDPKZP ;YES, ZAP THE KONTROLLER FIRST PJRST NTDDSC## ;NOW ALLOW NETSER TO ZAP THE DEVICE/DDB ;HERE FOR NODE DOWN DDPNND: HRRZ T1,DEVNET(F) ;GET OWNING NODE MOVE S,DEVIOS(F) ;GET THE DDP I/O STATUS FLAGS TLNE S,IOSDDK ;IN USE AS A KONTROLLER? PUSHJ P,DDPKZP ;YES, ZAP THE KONTROLLER FIRST PJRST NTDNWD## ;NOW ALLOW NETSER TO CLEAN UP THE DDB ;HERE FOR AN NCL DATA REQUEST RECEIVED (AT NETWORK INTERRUPT LEVEL) DDPNIQ: MOVE S,DEVIOS(F) ;DEVICE STATUS FLAGS TLNE S,IOSDDK ;IS DDP A DEVICE OR A KONTROLLER? PJRST DDPKIQ ;A KONTROLLER, NUDGE OUTPUT, ETC. PJRST NTDRDQ## ;A DEVICE, USE STANDARD NETSER ROUTINE ;HERE FOR AN NCL MESSAGE RECEIVED (AT NETWORK INTERRUPT LEVEL) DDPNIL: MOVE S,DEVIOS(F) ;DEVICE STATUS FLAGS TLNE S,IOSDDK ;IS DDP A DEVICE OR A KONTROLLER? PJRST DDPKIL ;A KONTROLLER, IT RUNS AT INTERRUPT LEVEL PJRST NTDQIP## ;A DEVICE, IT RUNS AT UUO LEVEL, SO TELL ; NETSER TO "QUEUE" THE NCL TO BE PROCESSED ; LATER AT USER/UUO LEVEL. ;HERE FOR INCOMING DATA (WITH EOR) DDPNIN: MOVE S,DEVIOS(F) ;GET DEVIOUS BITS TLNE S,IOSDDK ;IS DDP IN USE AS A KONTROLLER? PJRST DDPKIN ;YES, INTERRUPT LEVEL BEHAVES DIFFERENTLY ;DDP IS NOT A KONTROLLER, THEREFORE DATA IS DESTINED FOR USER I/O BUFFER MOVEI T4,^D08 ;DDCMP DATA IS *ALWAYS* 8 BITS PUSHJ P,NTDSIB## ;SETUP USER'S INPUT BUFFER POINTER/COUNTER STOPCD .,STOP,DDPSIB, ;++ NTDSIB FAILED AFTER NTDIBA SUCCEEDED DMOVE T3,DEVAXI(F) ;GET BYTE POINTER AND COUNTER FOR SPEED JRST DDPNI5 ;ENTER DATA COPY LOOP ;LOOP COPYING DATA FROM NCL INTO USER BUFFER DDPNI3: ILDB T1,P1 ;NEXT NCL DATA BYTE SOJL T4,DDPNI9 ;COUNT DOWN ROOM LEFT, IOBKTL IF OVERFLOW EXCTUU ;STORE BYTE INTO USER'S BUFFER DDPNI5: SOJGE P4,DDPNI3 ;COPY ENTIRE NCL DATA MESSAGE DMOVEM T3,DEVAXI(F) ;RESTORE BYTE COUNTER/POINTER FOR USER PJRST NTDA1B## ;ADVANCE USER'S BUFFER, RETURN TO DDPUIN ;HERE IF NCL DATA OVERFLOWED USER'S BUFFER DDPNI9: PUSHJ P,DDPBTL ;SET IOBKTL ERROR PJRST NTDAIB## ;AND RETURN USER HIS STUFFED BUFFER ;HERE FOR STATUS MESSAGE DDPNST: ;HERE ON RECEIPT OF DEVICE STATUS MESSAGE ;STC PUSHJ P,EBI2BI## ;READ THE CODE (STATUS, SET, OR CLEAR) JUMPN T1,CPOPJ## ;MUST BE BASIC STATUS ;STS PUSHJ P,EBI2BI## ;READ IN STATUS BITS XOR T1,DEVSTS(F) ;GET CHANGE FROM PREVIOUS STATUS XORM T1,DEVSTS(F) ;AND UPDATE TO NEW STATUS HRL T1,DEVSTS(F) ;CARRY CURRENT STATUS IN LH, DELTA IN RH TRNN T1,-1 ;ANYTHING OF CONSEQUENCE CHANGE? JRST CPOPJ1## ;SUCCESSFUL RETURN ;SOMETHING HAPPENED TO THE DDP, TELL SOMEONE ABOUT IT, IF ANYONE CARES MOVE S,DEVIOS(F) ;S PROBABLY TRASHED BY NOW TLNE S,IOSDDK ;IS DDP IN USE AS A KONTROLLER? PJRST DDPKST ;YES, PROCESS KONTROLLER STATUS CHANGE ; (WE ARE AT INTERRUPT LEVEL) ;DDP IN USE AS AN I/O DEVICE, GIVE USER PSI/ETC. PUSHJ P,NTDIAV## ;NUDGE LOW LEVEL ROUTINES JRST CPOPJ1## ;SUCCESSFUL RETURN ;HERE FOR DEVICE CONTROL DDPNCT: POPJ P, ;HO HUM. SUBTTL KONTROLLER SERVICE - VECTORED DRIVER INTERFACE ;REMEMBER, KONTROLLERS RUN AT INTERRUPT LEVEL, GOTTA BE CAREFUL NOT TO ;OFFEND ANYONE! ;DDPDSP -- ENTRY INTO KONTROLLER LAYER FROM DRIVER LAYER ;CALL IS: ; ; MOVX T1, ; MOVX T2, ; MOVX T3, ; MOVX T4, ; PUSHJ P,DDPDSP ; ERROR RETURN ; NORMAL RETURN ; ;WHERE IS THE KONTROLLER FUNCTION (DD.???) TO BE PERFORMED, SUCH ;AS START OR STOP THE DEVICE, ETC.; IS THE DDP DATA BLOCK ADDRESS ;(I.E., THE DDB, THE SAME AS IN UUO-LEVEL PROCESSING). IS ANY ;ARGUMENT APPROPRIATE TO THE PARTICULAR FUNCTION REQUESTED (E.G., BUFFER ;ADDRESS FOR OUTPUT DATA) AND IS THE "LINE USER" - ANF, DECNET, ;ETC. ; ;ON ERROR RETURN SOMETHING AWFUL HAPPENED, SUCH AS ILLEGAL USER. ; ;ON NORMAL RETURN THE REQUESTED FUNCTION HAS BEEN SUCCESSFULLY PERFORMED ;(WHICH IS NOT TO SAY IT CAN'T FAIL LATER - SUCH AS THE DDP GOING DOWN ;WHILE OUTPUT DATA IS STILL QUEUED). DDPDSP::CAIL T1,0 ;RANGE-CHECK THE FUNCTION CODE CAILE T1,DD.MAX ; TO MAKE SURE WE UNDERSTAND IT STOPCD CPOPJ##,DEBUG,DDPFNC, ;++ ILLEGAL KONTROLLER FUNCTION CALL CAIE T4,DD.DEC ;IS IT A LINE-ID FROM DECNET JRST DDPDS1 ;NO, DON'T CONVERT IT TLNN T2,-1 ;IS IT A LINE-ID JRST DDPDS1 ;NO, ITS A DDB USE IT PUSHJ P,DDPSRC ;GET THE DDB POPJ P, ;COULDN'T DO IT DDPDS1: CAME T4,DDPUSR(T2) ;CALLED BY LEGIT USER? POPJ P, ;NO, ERROR RETURN PUSH P,F ;SAVE F PUSH P,S ; AND S PUSH P,U ;ALSO SAVE U PUSH P,W ;AND DOUBLE-U MOVE F,T2 ;PUT DDB ADDRESS IN F MOVE S,DEVIOS(F) ;LOAD S ON G.P.S TLNE S,IOSDDK ;HAD BETTER BE IN KONTROLLER MODE! PUSHJ P,@DDPDST(T1) ;DISPATCH BASED ON FUNCTION TRNA ;HO HUM AOS -4(P) ;PROPIGATE SKIP POP P,W ;RANDOM ACS POP P,U ;TRASHED BY NETSER POP P,S ;RESTORE S POP P,F ;AND F POPJ P, ;RETURN TO DRIVER DDPDST: IFIW DDPOPN ;0 = OPEN CIRCUIT (INITIALIZE PROTOCOL) IFIW DDPCLS ;1 = CLOSE CIRCUIT (HALT PROTOCOL) IFIW DDPQUE ;2 = QUEUE OUTPUT BUFFER IFIW DDPPRB ;3 = POST RECEIVE BUFFER IFIW CPOPJ## ;4 = CHECK FOR EXISTANCE IFN <.-DDPDST-DD.MAX-1>, ;KONTROLLER FUNCTION: OPEN CIRCUIT (INITIALIZE PROTOCOL) DDPOPN: SKIPE DDPMBP(F) ;JUST CAUTIOUS STOPCD .+1,DEBUG,DDPRBA, ;++ RECIEVE BUFFER ALLREADY ALLOCATED SETZM DDPMBP(F) ;CLEAR IT (OR STOPCD LATER) TLNN S,IOSDDH ;WERE WE HALTED BEFORE? JRST DDPOP2 ;NO, SEE IF DDCMP IS RUNNING MOVSI S,IOSDDH ;THE "HALTED BY REQUEST" BIT ANDCAB S,DEVIOS(F) ;TURN THE DDP BACK ON DDPOP2: TLNE S,IOSDDD ;WAS THE DDCMP PROTOCOL RUNNING? PUSHJ P,DDPKUP ;DDCMP IS NOW RUNNING HRRZ T1,F ;RETURN DDB ADDRESS TO USER JRST CPOPJ1## ;SUCCESSFUL (I HOPE) ;KONTROLLER FUNCTION: CLOSE CIRCUIT (HALT PROTOCOL) DDPCLS: TLNE S,IOSDDH ;ALREADY HALTED? JRST DDPCL1 ;YES MOVSI S,IOSDDH ;THE "HALTED BY REQUEST" BIT IORB S,DEVIOS(F) ;STOP FURTHER USAGE TLNN S,IOSDDD ;WAS THE PROTOCOL UP BEFORE? PUSHJ P,DDPKDN ;YES, TAKE IT DOWN FORCIBLY ; IOSDDH WILL HOLD IT DOWN EVEN THOUGH ; DDCMP IS REALLY STILL RUNNING DDPCL1: MOVE T1,DDPMBP(F) ;GET ANY MESSAGE POINTER SETZM DDPMBP(F) ;CLEAR KNOWLEDGE JRST CPOPJ1## ;SUCCESSFUL (MORE OR LESS) ;KONTROLLER FUNCTION: QUEUE OUTPUT DATA DDPQUE: TLNN S,IOSDDD ;MAKE SURE THE PROTOCOL IS "UP" SKIPN DDPUSR(F) ; AND IS IN USE BY SOMEBODY POPJ P, ;IT ISN'T, DON'T QUEUE IT SETZM MB.NXT(T3) ;CLEAR GARBAGE IN MESSAGE BLOCK ; (I PERSONALLY THINK THIS, AH, IS JUNK! ; HOWEVER, THAT'S THE WAY IT IS) XMOVEI T1,DDPQOB-MB.NXT(F) ;PRIME THE PUMP, SO TO SPEAK SETZ T4, ;*** FOR KICKS NETOFF ;TIME TO PLAY WITH THE OUTPUT QUEUE DDPDM3: MOVE T2,T1 ;SAVE CURRENT MESSAGE SKIPE T1,MB.NXT(T2) ;STEP TO NEXT MESSAGE AOJA T4,DDPDM3 ;*** FOR KICKS MOVEM T3,MB.NXT(T2) ;STASH THIS MESSAGE AT THE TAIL OF THE QUEUE NETON ;ALLOW INTS AGAIN AOS (P) ;WHATEVER ELSE HAPPENS, THIS FUNCTION WORKED PJRST DDPKOU ;NOW TRY TO OUTPUT WHAT WE CAN ;KONTROLLER FUNCTION: POST RECEIVE BUFFER DDPPRB: TLNN S,IOSDDD ;MAKE SURE THE PROTOCOL IS "UP" SKIPN DDPUSR(F) ; AND IS IN USE BY SOMEBODY POPJ P, ;NO, REFUSE RECEIVE BUFFER SKIPE DDPMBP(F) ;ALREADY HAVE RECEIVE BUFFER POINTER? STOPCD CPOPJ##,DEBUG,DDPAHB ;++ALREADY HAVE RECEIVE BUFFER MOVEM T3,DDPMBP(F) ;SAVE RECEIVE BUFFER ADDRESS PJRST CPOPJ1## ;AND RETURN ;CONTINUED FROM PREVIOUS PAGE ;TRY TO PROCESS ANY QUEUED DATA AWAITING TRANSMISSION DDPKOU: SKIPN DDPQOB(F) ;ANY DATA QUEUED FOR OUTPUT? POPJ P, ;NO, NOTHING TO DO ;TIS NOW TIME TO ARRANGE NETSER'S INTERLOCK. WISH ME LUCK. SKIPL NTLOCK## ;IS NETSER INTERLOCK TAKEN? JRST [PUSHJ P,NTCHCK## ;YES, CHECK NETSER INTERLOCK POPJ P, ;IT'S OWNED BY SOMEONE ELSE, PUNT PJRST DDPKO1] ;WE ALREADY OWN IT, ALL SET PUSHJ P,INTLVL## ;ARE WE AT INTERRUPT LEVEL? JRST [NETDBL ;GET NETSER INTERLOCK AT UUO LEVEL PUSHJ P,DDPKO1 ;DO IT NETDBU ;FREE NETSER INTERLOCK POPJ P,] ;ALL DONE NTDBLI ;GET NETSER INTERLOCK AT INTERRUPT LEVEL POPJ P, ;CAN'T DO IT NOW PUSHJ P,DDPKO1 ;DO IT NTDBUI ;FREE NETSER INTERLOCK POPJ P, ;ALL DONE ;NOW SETUP NDB POINTER FOR NETSER. DDPKO0: SE1ENT ;HERE FROM NETSER, GET TO SECTION 1 DDPKO1: PUSHJ P,SAVE4## ;NETSER TRASHES THE P'S HRRZ T1,DEVNET(F) ;GET THE NODE NUMBER PUSHJ P,SRCNDB## ;FIND THE DDP'S NDB STOPCD .,STOP,DDPFIX, ;++ THIS NEEDS TO BE FIXED ;LOOP BUILDING NCL OUTPUT MESSAGES FOR NETSER DDPKO2: NETOFF ;TIME TO DIDDLE THE QUEUE SKIPE P1,DDPQOB(F) ;GET ADDRESS OF NEXT OUTPUT MESSAGE PUSHJ P,NTDCDQ## ;GOT OUTPUT PENDING, ANY DATA REQUESTS FOR IT? JRST DDPKP2 ;OOPS - NO MORE LEFT, PUNT MOVE T1,MB.NXT(P1) ;NEXT QUEUED DATA MESSAGE MOVEM T1,DDPQOB(F) ;BECOMES NEW FIRST QUEUED MESSAGE NETON ;SAFE AGAIN ;START UP A NETSER DATA MESSAGE SKIPN T2,MB.FMS(P1) ;ADDRESS OF FIRST MESSAGE SEGMENT DESCRIPTOR STOPCD .,STOP,DDPBBM, ;++ BUTTS BAD MESSAGE SKIPA T1,MD.BYT(T2) ;START WITH FIRST BYTE COUNT ADD T1,MD.BYT(T2) ;ACCUMULATE TOTAL MESSAGE BYTE COUNT SKIPE T2,MD.NXT(T2) ;ADVANCE TO NEXT SEGMENT JRST .-2 ;WALK THE ENTIRE CHAIN PUSH P,T1 ;SAVE DATA BYTE COUNT ADDI T1,17 ;ALLOW FOR NCL HEADER (AND ROUND UP) LSH T1,-2 ;CONVERT TO WORD ALLOCATION ;THIS WOULD BE A CLEVER PLACE TO TRY TO PIGGYBACK OUTGOING DATA REQUESTS ;WITH RELATIVELY NON-HUGE OUTGOING DATA MESSAGES S0PSHJ NTDHDR## ;FIRE UP NCL DATA MESSAGE JRST DDPKPU ;NO NETSER FREE CORE, PUNT FOR NOW MOVE T1,0(P) ;RETRIEVE THE DATA BYTE COUNT ADDI T1,1 ;ALLOW FOR "TYP" NCL FIELD PUSHJ P,BI2EBI## ;OUTPUT "CNT" (COUNT OF DATA) FIELD MOVEI T1,DC.DAR ;DATA WITH END OF RECORD PUSHJ P,DPBBIN## ;OUTPUT "TYP" FIELD ADDM P3,PCBCTR(U) ;ACCOUNT FOR ADDITIONAL NCL BYTES ;CONTINUED ON NEXT PAGE ;CONTINUED FROM PREVIOUS PAGE ;LOOP COPYING DATA FROM MESSAGE BLOCK INTO PCB MOVEM P1,0(P) ;SAVE ORIGINAL MESSAGE BLOCK ADDRESS MOVE P1,MB.FMS(P1) ;ADDRESS OF FIRST MESSAGE SEGMENT DESCRIPTOR PUSH P,T5 ;SAVE PROTECTED TEMPORARY PUSH P,T6 ;AND THE OTHER ONE TOO ;AT THIS POINT, P1 IS THE FIRST LINK OF A CHAIN OF "MESSAGE SEGMENT DESCRIPTOR" ;BLOCKS (ANY ONE OF WHICH CAN BE "NULL") CONTAINING THE DATA TO BE SENT. THE ;MD.AUX WORD IDENTIFIES THE FIRST BYTE WITHIN THE FIRST WORD CONTAINING VALID ;DATA, AND THE MD.ALA WORD IDENTIFIES THE FIRST WORD. WE CONSTRUCT OUR OWN ;BYTE POINTER SINCE THE DRIVER MAY HAVE INDEXED MD.AUX WITH SOME BIZARRE ;REGISTER. DDPKO4: SKIPG T1,MD.BYT(P1) ;COUNT OF BYTES IN THIS SEGMENT JRST DDPKO6 ;NULL SEGMENT, PITCH AND ADVANCE TO NEXT ONE HLLZ T2,MD.AUX(P1) ;GET FIRST-WORD BYTE POSITION TLZ T2,77 ;ENSURE ONE-WORD LOCAL SANS @(XX) TLO T2,T3 ;GLOBALLY INDEX TO DATA SKIPN T3,MD.ALA(P1) ;ADDRESS OF DATA STOPCD .,STOP,DDPNDA, ;++ NO ALLOCATED DATA ADDRESS MOVE T4,T1 ;SET "DESTINATION" BYTE COUNT = "SOURCE" ADDM T4,PCBCTR(U) ;UPDATE PCB'S BYTE COUNT MOVE T5,P2 ;SETUP "DESTINATION" BYTE POINTER TLO T5,T6 ;GLOBALLY INDEX TO DATA MOVSI T6,(MCSEC1) ;WHICH IS IN SECTION 0/1 ;*** USING A GLOBAL INDEX IS REQUIRED DUE TO ;*** A UCODE BUG WHEREIN THE EXTEND/MOVSLJ ;*** GETS CONFUSED OVER WHICH SECTION TO USE ;*** AS THE DEFAULT SECTION, LEADING TO AN ;*** IME (IF YOU'RE LUCKY) EXTEND T1,[MOVSLJ] ;COPY DRIVER DATA INTO PCB STOPCD .,STOP,DDPSLJ, ;++ COULDN'T MOVE THE SLUDGE TLZ T5,77 MOVEM T5,P2 ;UPDATE NETSER'S COPY OF THE BYTE POINTER DDPKO6: SKIPE P1,MD.NXT(P1) ;GET ADDRESS OF NEXT MESSAGE SEGMENT JRST DDPKO4 ;COPY NEXT SEGMENT OF DATA INTO ANF PCB POP P,T6 ;RESTORE FUNNY T-REG POP P,T5 ;AND THE OTHER ONE TOO MOVEI T1,PCV.NC ;"NO COMPRESSION" S0PSHJ NTDWRT## ;GIVE THIS BUFFER TO NETSER TO TRANSMIT PUSHJ P,NTDDDQ## ;COUNT DOWN AVAILABLE DATA REQUESTS POP P,T3 ;ADDRESS OF USED-UP MESSAGE BLOCK MOVEI T1,DI.ODN ;"OUTPUT DONE" INTERRUPT PUSHJ P,DDPDV1 ;CALL OUR DRIVER JFCL ;HO HUM JRST DDPKO2 ;CHECK FOR MORE OUTPUT ;HERE WHEN NETSER IS OUT OF MEMORY - TRY TO REQUEUE THE MESSAGE BLOCK DDPKPU: POP P,T1 ;PITCH THE UNUSEABLE BYTE COUNT NETOFF ;BACK TO DIDDLING THE QUEUE MOVE T1,MB.NXT(P1) ;MB THAT WE LEFT AS THE NEXT IN THE QUEUE CAME T1,DDPQOB(F) ;STILL THERE? JUMPN T1,DDPKP5 ;QUEUE HAS CHANGED (UNLESS NEW ENTRY APPEARED) MOVE T1,DDPQOB(F) ;GET PENDING HEAD OF QUEUE MOVEM T1,MB.NXT(P1) ;PRE-PEND THE DE-QUEUED MESSAGE BLOCK ; (THIS IS NEEDED FOR THE CASE WHERE ; THE DE-QUEUED MB WAS THE ONLY ENTRY IN ; THE QUEUE, THEN A NEW ENTRY WAS ADDED ; AFTER THIS ONE GOT DE-QUEUED) MOVEM P1,DDPQOB(F) ;RE-QUEUE THE DE-QUEUED MESSAGE BLOCK DDPKP2: NETON ;SAFE AGAIN PJRST DDPKK7 ;TRY TO OUTPUT DATA REQUESTS (IF NEEDED) ;HERE WHEN WE CAN'T RE-QUEUE THE MESSAGE 'CUZ THE QUEUE CHANGED. PROBABLY ;KONTROLLER GOT HALTED OR SOMETHING LIKE THAT. PITCH THE MESSAGE AND LET ;THE DRIVER WORRY ABOUT IT. THIS SHOULD NOT HAPPEN OFTEN. DDPKP5: NETON ;HO HUM MOVE T3,P1 ;ADDRESS OF MESSAGE BLOCK DDPKP7: MOVEI T1,DI.ODN ;FUNCTION: LIE AND SAY "OUTPUT DONE" PUSHJ P,DDPDV1 ;TELL DRIVER OUR WOES JFCL ;IGNORE ERROR POPJ P, ;HERE WHEN RECEIVE DATA REQUESTS FROM REMOTE ; ;ENTERED WITH NETSER INTERLOCK . . . DDPKIQ: PUSHJ P,NTDRDQ## ;ACCUMULATE DATA REQUESTS FOR OUTPUT STOPCD .,STOP,DDPRDQ, ;++ NTDRDQ FAILED PUSHJ P,DDPKKO ;KICK THE OUTPUT STUFF JRST CPOPJ1## ;SKIP RETURN (FOR NCTDSP) ;HERE WHEN WE'VE RECEIVED AN NCL MESSAGE FOR THIS DDP, MAY BE DATA, STATUS, ;ETC. LET NETSER DO THE BRUNT OF THE PARSING AND DISPATCHING (BACK TO DDPSER ;VIA NDEVDP DISPATCH - AND NO, THIS IS NOT RECURSIVE, EVEN THOUGH WE GOT ;HERE VIA SAID NDEVDP DISPATCH). ; ;ENTERED WITH NETSER INTERLOCK . . . ;*** AT THIS POINT, WE REALLY SHOULD CHECK FOR ANY DATA LEFT OVER FROM ;*** "UUO" DAYS (READ, "DEVPCB") SINCE IT IS POSSIBLE THAT BETWEEN THE ;*** CREATION OF THE DDP AS A DEVICE (DDB) AND THE SWITCHING OF THE ;*** DDP INTO KONTROLLER MODE ONE OR MORE DATA MESSAGES IN THE PIPE ;*** ARRIVED AND GOT QUEUED FOR "IN" UUOS . . . DDPKIL: PUSHJ P,NTDILD## ;GO PROCESS NCL INPUT ; PJRST DDPKKO ;GO KICK THE OUTPUT ROUTINES ;CHECK FOR OUTPUTTABILITY DDPKKO: PUSHJ P,SAVJW ;SAVE REGISTERS J AND W PUSHJ P,SAVE4## ;SAVE REGISTERS P1 - P4 PUSH P,U ;FINALLY SAVE THE INPUT'S PCB ADDRESS SETZ U, ;TAKE NO CHANCES PUSHJ P,DDPKK0 ;DO IT! POP P,U ;RESTORE INPUT'S PCB ADDRESS POPJ P, ;AND LOTS OF REGISTERS TOO! ;SEE IF THERE IS ANY QUEUED OUTPUT WE CAN SHIP TO THE REMOTE DDPKK0: NTDBUG YES, EITHER ;MUST HAVE NETSER INTERLOCK HERE! PUSHJ P,DDPKO0 ;TRY TO FORCE OUT ANY PENDING OUTPUT ;TRY TO OUTPUT ANY DATA REQUESTS DDPKK7: HRLOI T1,6 ;AIM AT 6 OUTSTANDING DATA REQUESTS SUB T1,DEVDRQ(F) ;LH(T1) IS SHORT-COUNT HLRZ T1,T1 ;T1 IS COUNT OF DATAREQUESTS NEEDED CAIGE T1,2 ;WAIT FOR AT LEAST 2 POPJ P, ;DON'T BOTHER WITH JUST 1 PUSH P,T1 ;SAVE DATA REQUEST INCREMENT S0PSHJ NCSDRQ## ;SEND DATA REQUEST(S) JRST TPOPJ## ;NO CORE, TRY LATER POP P,T1 ;DATA REQUESTS SENT HRLZ T1,T1 ;POSITION IN LH ADDM T1,DEVDRQ(F) ;AND ACCOUNT FOR OUTSTANDING DATA REQUESTS POPJ P, ;ALL DONE ;HERE FOR DATA INPUT (VIA DDPKIL), PASS TO THE DRIVER (OR "TRANSPORT") LAYER DDPKIN: SE1ENT ;NEED TO RUN IN EXTENDED ADDRESS SPACE TLNN S,IOSDDH ;IS THE PROTOCOL "RUNNING" SKIPN DDPUSR(F) ;YES, AND DO WE HAVE SOMEBODY TO RECEIVE DATA? JRST DDPKI9 ;NO, JUST EAT INCOMING DATA ;GET A BUFFER FROM OUR DRIVER INTO WHICH TO COPY DATA SKIPN T3,DDPMBP(F) ;DO WE HAVE A RECEIVE MESSAGE BUFFER JRST DDPKI9 ;NO, PITCH DATA, MUST BE SHUTTING DOWN SETZM DDPMBP(F) ;CLEAR PREVIOUS MESSAGE BUFFER POINTER PUSH P,T5 ;SAVE EXTEND TEMPS PUSH P,T6 ;THE OTHER ONE ;COPY DATA INTO MESSAGE BLOCK MOVE P2,T3 ;ADDRESS OF MESSAGE BLOCK MOVE P3,MB.FMS(P2) ;POINTER TO FIRST (AND ONLY) MESSAGE SEGMENT MOVEM P4,T1 ;SET "SOURCE" BYTE COUNT MOVEM P4,MD.BYT(P3) ;ALSO TELL THE DRIVER MOVE T2,P1 ;"SOURCE" BYTE POINTER TLO T2,T3 ;GLOBALLY INDEX TO DATA MOVSI T3,(MCSEC1) ;WHICH IS IN SECTION 0/1 ;*** UCODE BUG, SEE DDPKO4 HRRZ T4,MD.ALL(P3) ;GET MAXIMUM MESSAGE SIZE CAMLE P4,T4 ;WILL IT FIT? STOPCD .,STOP,DDPMTB ;++ DDP MESSAGE IS TOO BIG MOVEM P4,T4 ;SET "DESTINATION" BYTE COUNT MOVSI T5,(POINT 8,(T6)) ;"DESTINATION" BYTE POINTER (PROTOTYPE) SKIPN T6,MD.ALA(P3) ;ADDRESS OF "DESTINATION" DATA SEGMENT STOPCD .,STOP,DDPALA, ;++ DESTINATION ALLOCATED ADDRESS IS ZERO EXTEND T1,[MOVSLJ] ;BLT THE BYTES INTO THE DRIVER BUFFER STOPCD .,STOP,DDPBCD, ;++ BYTE COPY DIDN'T TLZ T2,77 MOVEM T2,P1 ;UPDATE NETSER'S BYTE POINTER SETZ P4, ;AND SUBMESSAGE BYTE COUNTER POP P,T6 ;DONE WITH EXTEND INSTRUCTION POP P,T5 ;THE OTHER ONE ;GIVE THE DATA TO OUR DRIVER MOVE T3,P2 ;POSITION MESSAGE BLOCK ADDRESS MOVEI T1,DI.INC ;FUNCTION "INPUT COMPLETE" PUSHJ P,DDPDV1 ;GIVE DATA TO OUR DRIVER JFCL ;IGNORE ERROR JRST CPOPJ1## ;SUCCESSFUL RETURN TO NETSER ;HERE TO EAT THE NCL INPUT DATA DDPKI9: ADJBP P4,P1 ;SKIP PAST THIS NCL SUB-MESSAGE MOVEM P4,P1 ;PUT INCREMENTED POINTER BACK IN P1 SETZ P4, ;PUT DECREMENTED COUNTER BACK IN P4 JRST CPOPJ1## ;AND TAKE THE SUCCESSFUL RETURN ;HERE FOR STATUS CHANGE, PASS PROTOCOL UP/DOWN/ETC TO THE DRIVER DDPKST: SE1ENT ;THIS NEEDS TO BE IN SECTION 1 PUSH P,T1 ;SAVE A COPY OF THE STATUS ;BASICALLY, THE SDP.AV STATUS IS IGNORED (IF SDP.AV CLEARS, IT WILL DRAG ;SDP.RN WITH IT), ONLY SDP.RN IS CHECKED TO SEE IF THE DDP IS "VIABLE" TRNN T1,SDP.RN ;DID PROTOCOL GO UP/DOWN? JRST TPOPJ## ;NO, (Should check for errors) XMOVEI T3,DDPKUP ;YES, ASSUME IT WENT UP TLNN T1,SDP.RN ;IS DDCMP PROTOCOL NOW RUNNING? XMOVEI T3,DDPKDN ;NO, THEN THE PROTOCOL WENT DOWN TLNN S,IOSDDH ;IGNORE IF HALTED BY DRIVER PUSHJ P,0(T3) ;HANDLE PROTOCOL STATUS CHANGE JRST TPOPJ## ;RESTORE STATUS THEN RETURN ;PROCESS DDP PROTOCOL UP CONDITION DDPKUP: MOVSI S,IOSDDD ;THE "PROTOCOL DOWN" FLAG ANDCAB S,DEVIOS(F) ;PROTOCOL IS NOT DOWN MOVEI T1,DI.LSC ;LINE STATE CHANGE MOVEI T3,LS.ON ;PROTOCOL IS UP PUSHJ P,DDPDV1 ;TELL OUR DRIVER THE GOOD NEWS JFCL ;HO HUM POPJ P, ;PROCESS DDP PROTOCOL DOWN CONDITION DDPKDN: MOVSI S,IOSDDD ;THE "PROTOCOL DOWN" FLAG IORB S,DEVIOS(F) ;FLAG THE EVENT ;CLEAN UP STALE OUTPUT AND DECLARE THE KONTROLLER "PROTOCOL DOWN" DDPKD3: NETOFF ;NO INTERRUPTS WHILST DIDDLING QUEUES SKIPN T3,DDPQOB(F) ;GET START OF OUTPUT QUEUE JRST DDPKD7 ;NONE, ALL CLEAR MOVE T1,MD.NXT(T3) ;GET ADDRESS OF NEXT MESSAGE IN THE QUEUE MOVEM T1,DDPQOB(F) ;DELINK THE FIRST MESSAGE NETON ;SAFE AGAIN MOVEI T1,DI.ODN ;LIE AND SAY OUTPUT DONE PUSHJ P,DDPDV1 ;TELL DRIVER THE BAD NEWS JFCL ;IGNORE ERRORS JRST DDPKD3 ;FREE THE REST OF THE OUTPUT QUEUE DDPKD7: NETON ;SAFE AGAIN ;CLEAN UP STALE INPUT BUFFER TOO SKIPN T3,DDPMBP(F) ;HAVE A DECNET INPUT BUFFER POSTED? JRST DDPKD8 ;NO SETZM DDPMBP(F) ;YES, MARK IT DE-POSTED MOVE T2,DDPLBK(F) ;POSITION ADDRESS OF DATA LINK BLOCK ; MOVEI T1,DI.INE ;FUNCTION: INPUT ERROR RETURN OF BUFFER ; PUSHJ P,DDPDV1 ;TELL DRIVER WE ARE RETURNING HIS BUFFER ; JFCL ;OH, WELL, WE TRIED PUSHJ P,DDIINE## ;TELL DRIVER WE ARE RETURNING HIS BUFFER DDPKD8: MOVEI T1,DI.LSC ;LINE STATE CHANGE MOVEI T3,LS.OFF ;PROTOCOL IS DOWN PUSHJ P,DDPDV1 ;TELL THE DRIVER WE ARE NOW "HALTED" JFCL POPJ P, ;ZAP (DESTROY) A DDP KONTROLLER DDPKZP: SE1ENT ;NEED SECTION 1 . . . PUSHJ P,DDPKDN ;FIRST SHUT DOWN THE DDP PROTOCOL/DRIVER MOVSI S,IOSDDK!IOSDDD ;VARIOUS KONTROLLER FLAGS ANDCAB S,DEVIOS(F) ;DDP IS NO LONGER A KONTROLLER! SETZM DDPUSR(F) ; . . . SETZM DDPLBK(F) ; . . . POPJ P, ;AND THAT IS THE END OF THAT SUBTTL SUBSIDIARY ROUTINES ;DDPDVR ROUTINE TO CALL THIS LINE'S DRIVER ;CALL: ; ; MOVX T1, ; MOVX T3, ; PUSHJ P,DDPDVR ; RETURN ; ;WHERE IS THE DRIVER FUNCTION (DI.???) TO PERFORM; AND IS ;ANY ARGUMENT AS NEEDED BY THE DRIVER. ; ;F MUST BE POINTING TO THE DDP DDB ; ;DDPDVR WILL DISPATCH INTO THE APPROPRIATE DRIVER BASED ON THE LINE ;USER IN DDPUSR, WITH T2 CONTAINING THE APPROPRIATE DATA BLOCK ADDRESS DEFINE X(TYP,CON,DAT,ADR),< IFN .-DDPDX0-<2*DD.'TYP>,< PRINTX ? DDPDVR vector dispatch phase error for TYP user> IFE CON,< PUSHJ P,NTDSTP## ;;DIE IF NO DRIVER SUPPORTED HALT .> ;;FILLER FOR TWO-WORD VECTOR IFN CON,< MOVE T2,DAT(F) ;;GET "DRIVER" DATA BLOCK ADDRESS PJRST ADR> ;;AND GO TO APPROPRIATE DRIVER > ;END DEFINE X DDPDVR: SE1ENT ;RUN IN EXTENDED ADDRESS SPACE DDPDV1: PUSHJ P,SAVR## ;DECnet USES R AS A TRASH AC. HRRZ T2,DDPUSR(F) ;GET THE USER CODE CAILE T2,DD.MAX ; AND RANGE CHECK IT STOPCD .,STOP,DDPIDV, ;++ ILLEGAL DRIVER NUMBER LSH T2,1 ;TRANSLATE INTO TWO-WORD BLOCK OFFSET PJRST .+1(T2) ;DISPATCH BASED ON "USER" TYPE DDPDX0: X (NOBODY,1,0,CPOPJ1##) ;ALWAYS SAY GOODNESS FOR "NOBODY" DDPDX1: X (ANF10,FTNET,0,DDPDXE) DDPDX2: X (DECNET,FTDECN,DDPLBK,DDIPPI##) DDPDX3: X (PROGRAM,1,0,DDPDXE) DDPDX4: X (IBMCOMM,1,0,DDPDXE) IFN .-DDPDX0-<2*>,< PRINTX ? DDPDVR vector dispatch entry missing> DDPDXE: STOPCD CPOPJ##,DEBUG,DDPIOT ;++ UNUSED DISPATCH (Illegal Owner Type) XLIST ;THE LITERALS LIT LIST PRGEND TITLE NETLPT - NETWORK LINE PRINTER ROUTINES - V001 SUBTTL NETLPT -- WEM/ 18 OCT 83 SEARCH F,S,NETPRM $RELOC $HIGH ;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED ; OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE. ; ; COPYRIGHT (C) 1977, 1984 BY DIGITAL EQUIPMENT CORP., MAYNARD, MASS. ;XP VNETLP,001 ;PUT VERSION NUMBER IN GLOB AND LOADER MAP NETLPT::ENTRY NETLPT SUBTTL 1.0 LPT SPECIFIC SYMBOL DEFINITIONS ;BITS IN LPT IOS STATUS REGISTER LPTNFF==100 ;SUPPRESSS FORM FEED AT START/END LPTSVF==2000 ;SUPPRESS VFU CONTROL ("GRAPHICS DATA") SUBTTL 2.0 INTERFACE TO UUOCON. (DEVSER DISPATCH VECTOR) JRST NTDONL## ;(-5) CHECK IF DEVICE IS ON LINE JRST L.DVOP ;(-4) DEVOP UUO JRST REGSIZ## ;(-3) BUFFER SIZE JRST CPOPJ## ;(-2) INITIALIZATION JRST CPOPJ1## ;(-1) HUNG DEVICE (IGNORE. REMOTE WORRYS) NDEVLP::JRST NTDREL## ;RELEASE JRST L.CLO ;CLOSE OUTPUT JRST L.OUT ;OUTPUT JRST NTDILI## ;ILLEGAL INPUT (RETURN INTERLOCK) SUBTTL 2.1 OUT UUO. L.OUT: ;HERE FROM UUOCON TO OUTPUT A BUFFER PUSHJ P,SAVE3## ;WE USE P1, NETSER USES P2, P3 FOR PCB'S MOVSI S,IOSUSO ;CLEAR THE "UUOCON STOPED OUTPUT" ANDCAB S,DEVIOS(F) ; SINCE IT JUST TRIED TO START IT AGAIN L.LOOP: PUSHJ P,NTDSET## ;SET UP W, S AND CHECK IOSCON MOVSI S,IO ;GET AND SET 'OUTPUT" IORB S,DEVIOS(F) ; JUST TO KEEP WSYNC HAPPY. PUSHJ P,NTDONL## ;CHECK IOSERR TO SEE IF STILL ONLINE JRST L.HUNG ;IF LPT IS OFFLINE, GO PLAY DEAD. TLNE S,IOBEG ;IS THIS THE FIRST OUT?? JRST L.FRST ; IF SO, GO DO SPECIAL CODE. ;ENSURE THAT THE REMOTE LPT IS SETUP ACCORDING TO DESIRED OPERATION ;(E.G., NORMAL 7-BIT COMPRESSED, LN01 EIGHT-BIT GRAPHICS, ETC.) ; ;*** REALLY SHOULD TRY TO PIGGYBACK THE POTENTIAL STATUS MESSAGES BELOW L.LOO0: MOVEI T1,SLP.SV ;THE "GRAPHICS" OUTPUT (SUPPRESS VFU) FLAG TRNN S,LPTSVF ;USER WANT VFU SUPPRESSION (E.G., GRAPHICS)? JRST L.LOO1 ;NO, MAKE SURE IT IS CLEAR TDNE T1,DEVSTS(F) ;YES, IS IT ALREADY SET? JRST L.LOO2 ;OK IORM T1,DEVSTS(F) ;WE WILL/HAVE SET IT PUSHJ P,NTDSST## ;SEND STATUS TO REMOTE TO SET IT JRST L.LOO2 ;GRAPHICS/VFU ALL SET L.LOO1: TDNN T1,DEVSTS(F) ;IS SUPPRESSION SET? JRST L.LOO2 ;NO, OK ANDCAM T1,DEVSTS(F) ;WE WILL/HAVE CLEARED IT PUSHJ P,NTDCST## ;SEND STATUS TO REMOTE TO CLEAR IT L.LOO2: MOVEI T1,SLP.8B ;THE EIGHT-BIT-DATA-NO-COMPRESSION FLAG LDB T2,PIOMOD## ;GET LPT DATA MODE CAIE T2,A8 ;IS LPT IN EIGHT-BIT-ASCII MODE? JRST L.LOO3 ;NO TDNE T1,DEVSTS(F) ;MORE TO THE POINT, IS IT IN 8-BIT MODE NOW? JRST L.LOO5 ;YES, ALL SET LDB T2,NETDVT## ;GET REMOTE'S LPT ATTRIBUTES TRNN T2,DLP.8B ;DOES THE REMOTE LPT SUPPORT 8-BIT? JRST L.8IMP ;NO, RETURN I/O ERROR IORM T1,DEVSTS(F) ;WE WILL/HAVE SET IT PUSHJ P,NTDSST## ;SEND STATUS TO REMOTE JRST L.LOO5 ;KEEP ON PLUGGIN' L.LOO3: TDNN T1,DEVSTS(F) ;IS THE LPT IN 8-BIT MODE NOW? JRST L.LOO5 ;NO, ALL SET ANDCAM T1,DEVSTS(F) ;YES, WE MUST CLEAR IT PUSHJ P,NTDCST## ;CLEAR IT IN THE REMOTE TOO L.LOO5: MOVEI T1,^D07 ;LPT'S ARE USUALLY IN 7-BIT DATA MODE MOVEI T2,SLP.8B ;THE EIGHT-BIT FLAG TDNE T2,DEVSTS(F) ;IS THE LPT IN 8-BIT MODE? MOVEI T1,^D08 ;YES, SELECT 8-BIT DATA BYTES PUSHJ P,NTDSOB## ;SET UP THE OUTPUT BUFFER JRST L.DONE ;NO MORE DATA. RETURN TO UUOCON. SKIPN DEVAXO+1(F) ;FOR LPT'S MAKE SURE THAT WE DON'T JRST L.LOO9 ; SEND ZERO LENGTH BUFFERS PUSHJ P,NTDCDQ## ;SEE IF ANY DATA REQUESTS PENDING JRST L.WAIT ;NONE AVAILABLE. WE MUST WAIT. MOVEI T1,PCV.LC ;WE WANT LINE-PRINTER COMPRESSION MOVEI T2,SLP.8B ;THE EIGHT-BIT FLAG TDNE T2,DEVSTS(F) ;IS THE LPT IN 8-BIT MODE? MOVEI T1,PCV.NC ;YES, THEN NO DATA COMPRESSION MOVEI T2,DC.DAR ; NOT-INTERRUPT, DATA WITH E-O-R PUSHJ P,NTDXMT## ;SEND ANOTHER PCB'S WORTH OF DATA PUSHJ P,[JUMPN T1,NTDSTP## ;WE SHOULD NEVER GET AN IO-ERROR POP P,(P) ;CLEAN OFF THE RETURN ADDRESS (UGLY) JRST L.SLP] ;A QUICK NAP AND TRY AGAIN PUSHJ P,NTDDDQ## ;UPDATE THE DATA REQUEST COUNT SKIPN DEVAXO+1(F) ;ARE THERE ZERO BYTES LEFT?? L.LOO9: PUSHJ P,NTDAOB## ;IF SO, THEN GIVE USER BACK THE BUFFER JRST L.LOOP ;LOOP UNTIL ALL DATA IS OUT SUBTTL 2.2 FIRST TIME ONLY CODE (OUTPUT ) L.FRST: ;HERE ON FIRST OUT FROM UUOCON SETZM DEVAXO(F) ;CLEAR ANY DATA NOT OUTPUT LAST TIME TRNE S,LPTNFF ;SHOULD WE OUTPUT THE FIRST JRST L.FRS3 ; IF NOT, THEN SKIP MOST OF THIS PUSHJ P,L.XFF ;SEND THE INITIAL SEQUENCE POPJ P, ;FORGET IT L.FRS3: ;HERE WHEN ALL "FIRST TIME" STUFF DONE. MOVSI S,IOBEG!IOSREL ;GET AND CLEAR "RELEASED" ANDCAB S,DEVIOS(F) ; AND "FIRST TIME" BIT JRST L.LOOP ;GO BACK AND TRY TO SEND USER DATA. ;HERE ON "CLOSE" UUO - 'LAST' TIME ONLY PROCESSING L.CLO: PUSHJ P,NTDCLO## ;FLUSH OUT ANY DANGLING LPT DATA MOVE S,DEVIOS(F) ;DEVICE STATUS FLAGS TRNE S,LPTNFF ;SHOULD WE OUTPUT A TRAILING ? JRST L.CLO4 ; IF NOT, THEN SKIP MOST OF THIS PUSHJ P,L.XFF ;SEND THE TRAILING SEQUENCE POPJ P, ;FORGET IT L.CLO4: POPJ P, ;RETURN FROM NETWORK CLOSE PROCESSING ;SEND A SEQUENCE TO REMOTE LINE PRINTER L.XFF: PUSHJ P,NTDSET## ;SET UP REGS, IOSCON, ETC. PUSHJ P,NTDONL## ;MAKE SURE LPT IS STILL VIABLE JRST [TLNN S,IOSCON ;ARE WE STILL CONNECTED? PJRST NTDGON## ; NO. TELL USER DEVICE IS GONE TLNE S,IOSERR ;IS THE LPT ON LINE YET?? PUSHJ P,NTDHNG## ;SET OFF-LINE AND TELL THE OPERATOR JRST L.XFF] ;TRY AGAIN PUSHJ P,NTDCDQ## ;DO WE HAVE A DATA REQUEST FOR THIS? JRST [PUSHJ P,NTDWTO## ;WAIT FOR DRQ. POPJ P, ;RETURN TO UUOCON IF NON-BLOCKING. JRST L.XFF] ;TRY AGAIN MOVEI T1,^D16 ;WE WANT A 16 WORD DATA MESSAGE PUSHJ P,NTDHDR## ; SET UP P2 := POINTER, P3 := COUNT JRST [PUSHJ P,NETSLP## ;WAIT A BIT JRST L.XFF] ;AND TRY AGAIN MOVEI T3,SLP.8B ;THE 8-BIT MODE FLAG TDNN T3,DEVSTS(F) ;IS THE NET LPT IN 7-BIT OR 8-BIT MODE? SKIPA T3,[POINT 8,[BYTE (8)3,DC.DAR,215,214]] ;7-BIT, COMPRESSED MOVE T3,[POINT 8,[BYTE (8)3,DC.DAR,15,14]] ;8-BIT, UNCOMPRESSED ;LENGTH & MESSAGE TO SEND MOVEI T4,4 ;WE WILL SEND 4 BYTES (INCLUDING LENGTH) L.XFF2: ILDB T1,T3 ;GET THE NEXT BYTE PUSHJ P,DPBBIN## ; AND PUT IT IN THE MESSAGE SOJG T4,L.XFF2 ;LOOP TILL ALL BYTES IN MESSAGE. ADDB P3,PCBCTR(U) ;UPDATE THE COUNT IN FIRST SEGMENT. SETZB P3,PCBCT2(U) ;INDICATE THAT THERE IS NO SECOND SEG. MOVEI T1,PCV.NC ;NO DATA COMPRESSION (ALREADY HANDLED ABOVE) PUSHJ P,NTDWRT## ;SEND THE MESSAGE. PUSHJ P,NTDDDQ## ;DECREMENT THE DATA REQUEST COUNT JRST CPOPJ1## ;SUCCESSFUL RETURN SUBTTL 2.3 EXCEPTION HANDLING. L.DONE: ;HERE IF ALL USERS BUFFERS SENT POPJ P, ;I THINK UUOCON WILL DO THE REST L.SLP: PUSHJ P,NETSLP## ;WAIT A BIT JRST L.LOOP ;AND TRY AGAIN L.WAIT: ;HERE WHEN NO DATA REQUESTS. PUSHJ P,NTDWTO## ;WAIT FOR DRQ. POPJ P, ;RETURN TO UUOCON IF NON-BLOCKING. JRST L.LOOP ;TRY FOR MORE DATA-OUT. ;L.LOOP WILL RELOAD "S" AND "W" L.HUNG: ;HERE WHEN IOSERR IS SET. TLNN S,IOSCON ;ARE WE STILL CONNECTED PJRST NTDGON## ; NO. TELL USER DEVICE IS GONE TLNE S,IOSERR ;IS THE LPT ON LINE YET?? PUSHJ P,NTDHNG## ;SET OFF-LINE AND TELL THE OPERATOR JRST L.LOOP ;TRY TO SEND SOME MORE DATA. L.8IMP: MOVEI S,IOIMPM ;SET "IMPROPER MODE" IORB S,DEVIOS(F) ;IN THE DDB POPJ P, ;AND LET UUOCON GIVE USER THE ERROR SUBTTL 2.4 DEVOP UUO ;HERE ON DISPATCH FROM UUOCON ; F=DDB ; T1=FUNCTION L.DVOP: MOVSI T2,-DEVOPL ;SETUP AOBJN POINTER TO TABLE DEVOP1: HLRZ T3,DEVOPT(T2) ;GET THE FUNCTION CODE HRRZ T4,DEVOPT(T2) ;GET THE DISPATCH ADDRESS CAMN T1,T3 ;DO THE CODES MATCH? JRST (T4) ;YES, DISPATCH AOBJN T2,DEVOP1 ;NOT YET, KEEP LOOKING JRST ECOD2## ;NOT APPLICABLE TO THIS DEVICE (ERROR 2) DEVOPT: XWD 12,LODVFU ;LOAD VFU ; XWD 1004,ECOD2## ;READ DEVICE STATUS XWD 1005,GETDFT ;READ FORMS TYPE XWD 2005,SETDFT ;SET FORMS TYPE DEVOPL==.-DEVOPT ;LENGTH OF TABLE ;HERE FROM UUOCON TO READ/SET FORMS TYPE GETDFT: MOVE T1,DEVDFT(F) ;FETCH FROM THE DDB JRST STOTC1## ;RETURN GOODNESS TO USER SETDFT: PUSHJ P,GETWR1## ;READ USER'S ARGUMENT JRST RTM1## ;ADDRESS CHECK ERROR MOVEM T1,DEVDFT(F) ;SAVE FOR POSTERITY PUSHJ P,SAVE4## ;PRESERVE AGAINST NETSER PUSHJ P,SAVJW## ;SUPERSTITION SETDF1: PUSHJ P,NTDSET## ;SETUP ACS TLNN S,IOSCON ;ARE WE STILL CONNECTED? JRST ECOD7## ;NO--PUNT BACK TO THE USER HRRZ T1,NDBNVR(W) ;YES--GET REMOTE'S NCL VERSION NUMBER JUMPE T1,CPOPJ1## ;TOO OLD FOR US--PRETEND ALL WENT WELL MOVEI T1,^D9 ;OK--SIZE FOR CNT+DC.CTL+DCT.LF+6 CHARACTERS PUSHJ P,NTDHDI## ;GET A PCB IGNORING DRQ'S JRST SETDF2 ;WAIT FOR SOME CORE IBP P2 ;SKIP OVER COUNT FIELD MOVE P1,P2 ;SAVE POINTER TO COUNT XMTI DC.CTL ;CONTROL MESSAGE XMTI DCT.LF ;FORMS TYPE XMTS DEVDFT(F) ;SEND FORMS TYPE NAME DPB P3,P1 ;SAVE COUNT AOJ P3, ;ADJUST FOR COUNT BYTE ADDM P3,PCBCTR(U) ;UPDATE IN PCB PUSHJ P,NETWRT## ;SEND THE PCB JRST CPOPJ1## ;SUCCESS RETURN SETDF2: PUSHJ P,NETSLP## ;WAIT A WHILE (PRESERVING THE NT) JRST SETDF1 ;TRY IT AGAIN ;HERE FROM UUOCON TO LOAD A VFU. LODVFU==ECOD2## ;NOT YET IMPLEMENTED SUBTTL 3.0 INTERFACE TO NETSER (NETWORK DISPATCH VECTOR) IFIW NTDNWD## ;USE DEFAULT "NODE WENT DOWN" HANDLER IFIW NTDDSC## ;USE DEFAULT DISCONNECT HANDLER IFIW L.CNC ;CONNECT CONFIRM HANDLER IFIW NTDSTP## ;++ SHOULD NEVER GET CONNECT INITIATE ENTRY IFIW NTDRDQ## ;USE STANDARD DATA-REQUEST HANDLER LPTNDP::IFIW NTDILD## ;USE CANNED INTERRUPT LEVEL DISPATCH IFIW CPOPJ## ;WE DON'T GET ANY DATA IFIW CPOPJ## ; ESPECIALY DATA WITH E-O-R... IFIW L.STAT ;WE DO GET STATUS MESSAGES IFIW CPOPJ## ;WE DONT GET CONTROL IFIW CPOPJ## ;OR UID IFIW CPOPJ## ;OR FILE-SPEC'S ;DUMMY CONNECT INIT PROCESSOR NLPTCI==:NJNKCI## ;A JUNK CI SUBTTL CONNECT CONFIRM HANDLER L.CNC: PUSHJ P,NTDCNC## ;STANDARD CONNECT CONFIRM PROCESSING POPJ P, ;ERROR, PROPAGATE BACK TO NETSER LDB T1,NETDVT## ;RETRIEVE "DVT" ATTRIBUTES FIELD SETZ T2, ;INITIAL "HCW" HARDWARE CHARACTERISTICS TRNE T1,DLP.LL!DLP.FC ;LOWERCASE? TLO T2,(HC.LCP) ;YES LDB T3,NETDVU## ;RETRIEVE "UNIT" TYPE DPB T3,[POINT 3,T2,14] ;AND STUFF INTO HCW WORD LDB T3,NETDVV## ;RETRIEVE "CONTROLLER" TYPE DPB T3,[POINT 3,T2,11] ;AND STUFF INTO HCW WORD TLO T2,(<.HCVTO>B5) ;SET OPTICAL VFU (CLOSE ENOUGH) SETZ T3, ;ASSUME UPPERCASE PRINTER TLNE T2,(HC.LCP) ;TRUE? AOS T3 ;NO--BUMP TO 96-CHAR TRNE T1,DLP.FC ;IF FCS PRINTER, AOS T3 ;BUMP TO 128-CHAR DPB T3,[POINT 3,T2,8] ;AND STUFF INTO HC.CST FIELD MOVEM T2,DEVHCW(F) ;SET LINEPRINTER HARDWARE CHARACTERISTICS JRST CPOPJ1## ;SUCCESSFUL RETURN BACK TO NETSER SUBTTL 3.1 INPUT STATUS MESSAGE PROCESSING L.STAT: ;HERE FROM NETSER WITH A STATUS MESSAGE. ;STC PUSHJ P,EBI2BI## ;GET TYPE OF STATUS MESSAGE JUMPN T1,CPOPJ## ; (WE ONLY RESPECT TYPE 0) ;STD PUSHJ P,EBI2BI## ;GET THE DEVICE BITS. HRRM T1,DEVSTS(F) ;STORE THE STATUS FOR UUOLEVEL TO WATCH AOS (P) ;WE ARE NOW SATISFIED THAT MSG IS GOOD. MOVE T2,[IORB S,DEVIOS(F)] ;ASSUME THAT WE ARE OFFLINE. TRNN T1,SLP.OL ; BUT CHANGE OUR MINDS IF WE MOVE T2,[ANDCAB S,DEVIOS(F)] ; WE ARE ONLINE MOVE T3,DEVIOS(F) ;COPY OLD STATUS MOVSI S,IOSERR ;AND SET/CLEAR XCT T2 ; THE ERROR BIT "IOSERR" IN DEVIOS CAME S,T3 ;DID THE STATUS CHANGE?? PUSHJ P,NTDOAV## ; IF IT DID, THEN WAKE UP UUOLEVEL POPJ P, ;GIVE GOOD RETURN TO NETSER XLIST ;DON'T LIST LITERALS $LIT LIST PRGEND TITLE NETMCR - NETWORK MONITOR CONTROL ROUTINES VERSION 001 SUBTTL NETMCR -- WEM/ 4-JUN-78 SEARCH F,S,NETPRM $RELOC $HIGH ;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED ; OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE. ; ; COPYRIGHT (C) 1978,1984 BY DIGITAL EQUIPMENT CORP., MAYNARD, MASS. XP VNEMCR,001 ;PUT VERSION NUMBER IN GLOB AND LOADER MAP NETMCR::ENTRY NETMCR NDEVMC==:777740 ;DUMMY DEVSER DISPATCH FOR NDT MACRO SUBTTL 1.0 INTERFACE TO SCNSER SUBTTL 1.1 SCNSER DISPATCH TABLE MCRDSP::JRST D85TYP ;ILLEGAL NOW. DON'T USE!! JRST CPOPJ## ;MODEM CONTROL JRST CPOPJ## ;ONCE A SECOND STUFF JRST CPOPJ## ;INITIALIZE JRST D85CHP ;CHANGE HARDWARE PARMS JRST D85LPC ;LINE PARM CONTROL JRST CPOPJ## ;SET TERMINAL ELEMENT JRST D85REM ;STUFF FOR REMOTE TERMINALS JRST D85OFL ;IS THE LINE DEFINED ON THE STATION ;FUNCTION CODE 0 IS ILLEGAL D85TYP: STOPCD .,STOP,CU0, ;++ CAN'T USE ZERO DISPATCH POPJ P, ;HERE TO REQUEST A CHANGE OF PARAMETERS D85CHP==SETCHP## ;LET SCNSER DO THE WORK ;HERE TO REQUEST A LINE PARM CHANGE. D85LPC: MOVE T1,T3 ;COPY LPC CODE LSH T1,-8 ;ISOLATE IT CAIE T1,LPCABR ;AUTOBAUD REGOCNITION? POPJ P, ;THAT'S THE ONLY ONE WE HANDLE MOVSI T1,LRLABR## ;AUTOBAUD REQUEST FLAG IORM T1,LDBREM##(U) ;SET IT PJRST SETCHP## ;MAKE SURE SCNCHP SENDS THE REQUEST ;SEE IF THE TERMINAL IS ON-LINE D85OFL: MOVE T1,LDBREM##(U) ;GET THE STATUS BITS TLNE T1,LRLCON## ;IF THIS IS SET WE ARE PROBABLY AOS (P) ; STILL CONNECTED, IF IT IS ZERO, WE POPJ P, ; ARE MOST CERTAINLY NOT. ;COME HERE ON SPECIAL CALLS FROM SCNSER ;CODE IN T3: ;1 = BUFFER LOW ;2 = CHARACTER NOT STORED ;3 = CONTROL O PROCESSING. D85REM: CAILE T3,IRRINV ;VALIDATE RANGE CAILE T3,IRRTMO ; ... POPJ P, ;IGNORE IF NOT IN RANGE JRST @.(T3) ;OTHERWISE DISPATCH IFIW MCRBFL ;BUFFER LOW IFIW MCRCNS ;CHARACTER NOT STORED IFIW MCRCTO ;CONTROL O IFIW MCRCSA ;CHUNK SPACE AVAILABLE IFIW MCRDIS ;DISCONNECT IFIW MCRCIB ;CLEAR INPUT BUFFER IFIW MCRTMO ;AUTO-DISCONNECT TIMEOUT ;THESE ARE NO-OPS FOR NOW. MCRCNS==CPOPJ## MCRCSA==CPOPJ## MCRCIB==CPOPJ## ;COME HERE ON CONTROL O ACTION. THE CONTROL O MAY HAVE BEEN ; SET EITHER ON OR OFF. CHECK THE LDB TO DETERMINE WHICH AND ; SEND A CHARACTER GOBBLER IF IT HAS BEEN SET ON. MCRCTO: MOVSI T2,LRLSCG## ;GET AND SET THE BIT IORM T2,LDBREM##(U) ; SAYING WE WANT A CHAR GOBBLER SENT PJRST D85CHP ;NOW QUEUE THE LDB FOR SERVICE ;COME HERE IF INPUT BUFFER IS FULL ;THIS TELLS THE FRONT END THAT AN XOFF IS NEEDED ; SKIP RETURNS IF MESSAGE GETS SENT MCRBFL: MOVSI T2,LRLXOF## ;GET THE XOFF FLAG IORM T2,LDBREM##(U) ;SET IT SO SCNMC7 WILL SEE IT AOS (P) ;GIVE A GOOD SKIP RETURN PJRST D85CHP ;AND QUEUE THE LDB ;COME HERE ON AUTO-DISCONNECT TIMEOUT FROM SCNSEC. ; THIS WILL TRY TO DISCONNECT THE TERMINAL IF AT ALL REASONABLE. MCRTMO: MOVEI T2,LDRDSD## ;DATASET BIT TDNN T2,LDBDCH##(U) ;IS IT ONE? PJRST MCRDIS ;NO, TRY IT THIS WAY PUSHJ P,MCRCHK ;SEE IF A LEGAL TERMINAL POPJ P, ;RETURN FAILURE IF NOT PJRST D85OFF ;JUST DO THE DISCONNECT IF SO ;COME HERE ON USER DISCONNECT REQUEST (E.G., FROM TRMOP. .TODNT). ; THIS WILL SEND THE DISCONNECT IF REASONABLE. MCRDIS: PUSHJ P,MCRCHK ;SEE IF A LEGAL TERMINAL POPJ P, ;RETURN IF NOT MOVE T2,LDBREM##(U) ;NO, GET ITS REMOTE STATUS BITS TRNN T2,LRRSHC## ;CAN THIS LINE HANDLE A DISCONNECT? POPJ P, ;NO, DON'T DISCONNECT IT MOVSI T2,LRLTMO## ;YES, GET TIME-OUT BIT IORM T2,LDBREM##(U) ;LIGHT IT JRST CPOPJ1## ;NMCSEC WILL DISCONNECT THE LINE SUBTTL 1.2 SCNSER MODEM CONTROL. ;HERE FOR MODEM CONTROL FROM SCNSER D85DSC::PUSHJ P,MCRCHK ;SEE IF A LEGAL TERMINAL JRST ECOD4## ;NOT A TERMINAL MOVE T2,LDBDCH##(U) ;GET THE STATUS BITS TRNN T2,LDRDSD## ;IS THIS A DATA SET LINE JRST ECOD4## ;NO CAIN T3,DSTSTS## ;STATUS? JRST D85STS ;YES CAIN T3,DSTOFF## ;MODEM OFF JRST D85OFF ;YES, CAIN T3,DSTON## ;MODEM ON JRST D85ON ;YES CAIN T3,DSTCRQ## ;REQUEST DIAL OUT JRST D85CRQ ;YES JRST ECOD3## ;NONE OF ABOVE D85STS: MOVSI T2,LRLDSR## ;CARRIER ON BIT TDNN T2,LDBREM##(U) ;IS IT? TDZA T1,T1 ;NO MOVSI T1,DSCHWC## ;YES JRST STOTC1## ;STORE ANSWER FOR USER D85OFF: MOVSI T2,LRLHUR## ;HANG-UP BIT IORM T2,LDBREM##(U) ;REQUEST REMOTE TO HANG UP THE PHONE PUSHJ P,D85CHP ;GO KICK THE REMOTE JRST CPOPJ1## ;WE'VE DONE OUR PART D85ON: JRST CPOPJ1## ;JUST PRETEND ALL IS WELL ;HERE FOR CALL REQUEST (DIALOUT) D85CRQ: MOVSI T2,LRLADL## ;GET AUTO DIAL LINE BIT TDNN T2,LDBREM##(U) ;IS THIS A AUTO DIAL LINE PJRST ECOD4## ;NOPE FAIL D85CR1: SKIPN DIALDB## ;IS THE DIALER AVAILABLE JRST D85CR2 ;YES, CONTINUE MOVEI T1,5 ;NO PUSHJ P,[NTSAVE ;RETURN THE 'NT RESOURCE S0PSHJ SLEEP## ;AND NOW SLEEP. POPJ P,] ;RETURN IN CORRECT SECTION JRST D85CR1 ;TRY AGAIN D85CR2: MOVEM U,DIALDB## ;STORE THE LDB OF THE REQUESTER MOVEM J,DIALJB## ;STORE THE JOB NUMBER FOR NETCTC SETZM DIALFL## ;INITIALIZE DIALOUT "STATE" PUSHJ P,GETWRD## ;GET PART ONE OF THE NUMBER PJRST ECOD3## ;BAD ADDRESS MOVEM T1,DIALNM## ;STORE PART ONE PUSHJ P,GETWR1## ;GET SECOND PART PJRST ECOD3## ;ADDRESS CHECK TRO T1,17 ;FORCE AN END CHARACTER MOVEM T1,DIALNM+1 ;STORE PART TWO MOVSI T2,LRLADR## ;GET AUTO DIAL REQUEST BIT IORM T2,LDBREM##(U) ;SET IT PUSHJ P,D85CHP ;REQUEST SERVICE D85CR3: MOVEI T1,^D3 ;WAIT FOR THREE SECONDS PUSHJ P,[NTSAVE ;SAVE THE 'NT' S0PSHJ SLEEP## ;AND GO SLEEP POPJ P,] ;AND RETURN IN THE CORRECT SECTION SKIPL T1,DIALFL## ;CHECK FOR A COMPLETED CALL JRST D85CR3 ;NO, WAIT AGAIN SETZM DIALDB## ;YES, MAKE THE DIALER AVAILABLE SETZM DIALJB## ;DON'T CONFUSE NETCTC TLNN T1,LRLDSR ;DID THE DIALOUT SUCCEED? JRST ECOD5## ;NO, GIVE AN ERROR RETURN JRST CPOPJ1## ;YES, GOOD RETURN SUBTTL 2.0 INTERFACE TO NETSER FOR INCOMING DATA SUBTTL 2.1 NETWORK DISPATCH TABLE FOR TERMINALS (NDP) IFIW MCRNWD ;(-5)NODE WENT DOWN IFIW MCRDSC ;(-4)DISCONNECT MESSAGE IFIW MCRCNC ;(-3)CONNECT CONFIRM IFIW NTDSTP## ;(-2)CONNECT INITIATE (WE DON'T POST DDB'S) IFIW MCRDRQ ;(-1)DATA REQUESTS MCRNDP::IFIW MCRDAP ;(0) DISPATCH ON INCOMING DAP MESSAGE IFIW MCRDAT ;(1) DATA WITHOUT END OF RECORD IFIW MCRDAR ;(2) DATA WITH END OF RECORD (MTA'S) IFIW MCRSTS ;(3) STATUS IFIW MCRCTL ;(4) CONTROL MESSAGE IFIW CPOPJ## ;(5) USER ID IFIW CPOPJ## ;(6) FILE SPEC SUBTTL 2.2 NETWORK CONTROL MESSAGE PROCESSING SUBTTL 2.2.1 NODE WENT DOWN ;MCRNWD ROUTINE TO HANDLE THE "NODE WENT DOWN" NETWORK DISPATCH ENTRY ;CALL MOVEI F,LAT-ENTRY ;RH CONTAINS LDB POINTER ; MOVEI P1,NODE NUMBER OF THE DEAD NODE ; PUSHJ P,MCRNWD ;RETURN CPOPJ ;ALWAYS MCRNWD: PUSH P,U ;SAVE U MOVE U,F ;THE LDB ADDRESS IS CARRIED IN "U" LDB T1,LDPRNN## ;GET THE REMOTE NODE NUMBER CAIE T1,(P1) ;IS IT THE SAME AS THE ONE WE ARE LOOKING AT? STOPCD .,STOP,MCRBRN, ;++ BAD REMOTE NODE NUMBER PUSHJ P,NMCWAK ;WAKE ANYONE WHO MIGHT BE WAITING PUSHJ P,MCRDET ;THEN DETACH THE TERMINAL PUSHJ P,MCRFRE ; AND FREE THE LDB PJRST UPOPJ## ;RESTORE U AND WE ARE DONE SUBTTL 2.2.2 DISCONNECT MESSAGES (BOTH INIT AND CONFIRM) ;MCRDSC ROUTINE TO HANDLE INCOMING DISCONNECTS FOR MCR'S ;CALL MOVEI F,LDB ;(CAUSE THAT'S HOW ICMDSC DOES IT) ; P1, P4 := POINT TO "SLA" OF THE DISCONNECT MESSAGE. (BUT WE DON'T CARE) ; MOVEI W,NDB ; PUSHJ P,MCRDSC ;RETURN CPOPJ ;WE SHOULDN'T HAVE GOTTEN A DISCONNECT. BAD MSG. ; CPOPJ1 ;MESSAGE ACCEPTED. MCRDSC: PUSH P,U ;SAVE THE INCOMING PCB MOVE U,F ;THE LDB ADDRESS IS CARRIED IN "U" LDB T1,LDPSLA## ;GET OUR LAT ADDRESS LDB T2,LATSTA## ;GET THE STATE OF THE CONNECTION CAIL T2,LAT.CC ;THE ONLY TIMES DISCONNECT IS LEGAL IS CAILE T2,LAT.DC ; ARE LAT.CC, LAT.OK, AND LAT.DC JRST UPOPJ## ;IF IT'S NOT ONE OF THEM, WE CAN'T PROCESS IT. CAIE T2,LAT.OK ;DO WE NEED TO SEND A DISCONNECT CONFIRM? JRST MCRDS1 ; IF NOT. SKIP THE CODE THAT DOES MOVEI T1,RSN.OK ;GET THE REASON FOR THE DISCONNECT CONFIRM EMRGCY ;USE "EMERGENCY" MEMORY IF NECESSARY PUSHJ P,TRMXDC ;SEND THE DISCONNECT. STOPCD .,STOP,MCRDSF, ;++ DISCONNECT FAILED. EMRGCY HACK F.U. MCRDS1: PUSHJ P,NMCWAK ;WAKE ANY JOB THAT MAY BE WAITING ON A CONNECT. PUSHJ P,MCRDET ;ATTEMPT TO "DETACH" THE USER (IF THERE IS ONE) PUSHJ P,MCRFRE ;FREE THE LAT AND THE LDB PJRST UPOPJ1## ;RETURN PCB AND GIVE A GOOD RETURN SUBTTL 2.2.3 CONNECT CONFIRM ;MCRCNC ROUTINE TO PROCESS A MCR CONNECT CONFIRM MESSAGE. ;CALL MOVEI W,NDB ; MOVEI F,LDB ; P1, P4 := POINTER TO THE "SLA" SECTION OF THE CONNECT CONFIRM ;RETURN CPOPJ1 ;ALWAYS MCRCNC: PUSH P,U ;SAVE THE PCB POINTER MOVE U,F ;THE LDB ADDRESS IS CARRIED IN "U" ;SLA PUSHJ P,EBI2BI## ;GET THE LINK ADDRESS AT THE OTHER END DPB T1,LDPDLA## ;REMEMBER IT SO WE CAN SEND HIM STUFF ;DPN(OBJ) PUSHJ P,XSKIP## ;IGNORE "OUR" OBJECT TYPE ;DPN(,PID) PUSHJ P,XSKIP## ;IGNORE "OUR" PROCESS NAME (OR UNIT #) ;SPN(OBJ,PID) PUSHJ P,TTYRPN ;READ HIS LINE NUMBER AND CHECK FOR OPR. ;MML,FEA(DCM,RLN,DVT,DVU,DVV,DFT) PUSHJ P,TTYRAT ;READ THE "ATTRIBUTES" PUSHJ P,TRM.UP ;MARK TERMINAL ONLINE (MCRCHK WILL NOW SKIP) MOVSI T1,LRLGRT## ;AS THIS IS A TERMINAL ASSIGNMENT REQUEST, IORM T1,LDBREM##(U) ;LET THE OWNER "GREET" IT IF NECESSARY PUSHJ P,NMCWAK ;WAKE ANY JOB THAT MAY BE WAITING FOR CONNECT JRST UPOPJ1## ;RESTORE THE PCB AND SKIP RETURN SUBTTL 2.2.4 CONNECT INITIATE ;NMCRCI ROUTINE TO HANDLE THE CONNECT INITIATE MESSAGE FOR A MCR. ;CALLED BY THE NDTCNI DISPATCH IN ICMCNT. ; P1, P4 POINT TO THE "DPN" OF THE CONNECT MESSAGE ; P3 := XWD DLA,OBJ ;AS READ FROM THE CONNECT ; W := POINTER TO THE NDB ;RETURN CPOPJ ;CONNECT REJECT. REASON IN "T1" ; CPOPJ1 ;CONNECT ACCEPTED. CONNECT CONFIRM SENT. NMCRCI::MOVE T1,STATES## ;GET THE SCHEDULE BITS TRNE T1,ST.NRT ;ANY REASON NOT TO CONNECT? JRST [MOVEI T1,RSN.OT ;IF SO, GIVE A "NOT AVAILABLE" CODE POPJ P,] ; AND GIVE AN ERROR RETURN PUSH P,U ;SAVE THE INPUT PCB PUSHJ P,MCRGET ;GET AN ANF/MCR LDB JRST NMCRC9 ;CAPACITY EXCEEDED ERROR MOVEI T1,M.AIDL## ;GET MAXIMUM IDLE TIME BEFORE AUTO-DISCONNECT PUSHJ P,SCNADT## ;START THE TIMER GOING MOVE T1,U ;ADDRESS OF LDB FOR GETSLA TLO T1,LAT.TY ;THIS WILL BE A LDB-TYPE OF ADDRESS MOVEI T2,LAT.OK ;AND ITS INITIAL STATE IS "OK" PUSHJ P,GETSLA## ;ALLOCATE A LAT ENTRY JRST NMCRC8 ;IF NONE LEFT, THEN CAPACITY EXCEEDED. DPB T1,LDPSLA## ;STORE THE LAT ADDRESS IN THE SLA FIELD HLRZ T1,P3 ;GET AND DPB T1,LDPDLA## ; SAVE THE DLA PUSHJ P,TRM.UP ;ANTICIPATE SUCCESS, AND DECLARE THE LDB ONLINE ; (IF WE FAIL LATER, ALL WILL BE CLEARED UP) ;DPN(,PID) PUSHJ P,XSKIP## ;THE REMOTE CAN'T SELECT PARTICULAR MCR'S ;SPN(OBJ,PID) PUSHJ P,TTYRPN ;READ THE REMOTE LINE NUMBER. ;MML,FEA(DCM,RLN,DVT,DVU,DVV,DFT) PUSHJ P,TTYRAT ;READ THE REMOTE MCR'S ATTRIBUTES. PUSHJ P,MCRXCN ;TRY TO SEND A CONNECT-CONFIRM. JRST NMCRC8 ;FAILED, CLEAR LAT AND FREE LDB MOVSI T1,LRLGRT## ;SINCE THIS IS AN UNSOLICITED TTY CONNECT ANDCAM T1,LDBREM(U) ;FLAG THE TERMINAL TO BE "GREETED" ASAP JRST UPOPJ1## ;CONNECT COMPLETED SUCCESSFULLY ;CAN'T ACCEPT INCOMING CONNECT, RETURN "CAPACITY EXCEEDED" ERROR NMCRC8: PUSHJ P,MCRFRE ;GIVE UP LAT SLOT, FREE LDB NMCRC9: MOVEI T1,RSN.XN ;GET CAPACITY EXCEEDED ERROR CODE PJRST UPOPJ## ;RESTORE "U" AND GIVE ERROR RETURN SUBTTL 2.2.5 DATA REQUEST ;MCRDRQ ROUTINE TO PROCESS A DATA REQUEST FOR A MCR. ;CALL MOVEI T4,"DRQ" FIELD OF THE MESSAGE (READ IN ICMDRQ) ; MOVEI F,LDB ; PUSHJ P,MCRDRQ ;(ACTUALLY MCRNDP+NDPDRQ) ;RETURN CPOPJ ;MESSAGE BAD. ; CPOPJ1 ;DATA REQUEST ACCEPTED MCRDRQ: NTDBUG ;VERIFY THE INTERLOCK PUSH P,U ;SAVE THE PCB MOVE U,F ;THE LDB ADDRESS IS CARRIED IN "U" LDB T2,LDPDRQ## ;GET THE CURRRENT DATA REQUEST COUNT ADD T2,T4 ;FORM NEW SUM CAILE T2,^D256 ;UNREASONABLE? PJRST UPOPJ## ;YES, IGNORE THE REQUEST DPB T2,LDPDRQ## ;STORE THE NEW COUNT MOVSI T1,LRLTTW## ;GET AND CLEAR THE ANDCAM T1,LDBREM##(U) ; WAITING BIT PUSHJ P,TOREQ## ;REQUEST SERVICE ON THE LINE PJRST UPOPJ1 ;GIVE GOOD RETURN SUBTTL 2.3 DAP MESSAGE PROCESSING SUBTTL 2.3.1 DAP DISPATCH ROUTINE ;MCRDAP ROUTINE TO SEPARATE THE NCL SUB-MESSAGES ;CALL MOVEI F,LDB ; MOVE P1,BYTE POINTER TO THE FIRST "CNT" FIELD IN THE MESSAGE ; PUSHJ P,MCRDAP ;DO DAP DISPATCHING ;RETURN CPOPJ MCRDAP: PUSH P,U ;SAVE THE PCB MOVE U,F ;THE LDB ADDRESS IS CARRIED IN "U" ;LOOP DISPATCHING FOR EACH SUB-MESSAGE MCRDP1: JUMPLE P4,UPOPJ## ;EXIT IF ALL SUB-MESSAGES HAVE BEEN DONE ;CNT PUSHJ P,EBI2BI## ;GET THE LENGTH OF NEXT SUB-MESSAGE SUB P4,T1 ;UPDATE TOTAL MESSAGE LEFT LENGTH SKIPGE P4 ;MAKE SURE SUB-MSG IS A REASONABLE LENGTH JSP T1,MCRDP3 ;++ SUB-MSG EXTENDS PAST TOTAL MESSAGE'S END PUSH P,P4 ;SAVE LENGTH OF REST OF TOTAL MESSAGE MOVEI P4,(T1) ;COPY THE LENGTH OF THE SUB-MESSAGE ;TYP PUSHJ P,EBI2BI## ;GET THE IDC TYPE FIELD CAIL T1,DC.DAT ;RANGE CHECK CAILE T1,DC.MAX ; THE TYPE FEILD PJSP T1,MCRDP2 ;BAD MESSAGE. ILLEGAL TYPE. PUSHJ P,@MCRNDP(T1) ;DO THE DISPATCH PJSP T1,MCRDP2 ;THE DRIVER DIDN'T LIKE THE MESSAGE? SOJG P4,[IBP P1 ;MAKE SURE P1 POINTS AT THE NEXT "CNT" BYTE JRST .] POP P,P4 ;GET LENGTH OF "REST" OF MESSAGE BACK JRST MCRDP1 ;LOOP OVER ALL SUB-MESSAGES MCRDP2: POP P,T2 ;POP TOTAL MESSAGE LENGTH OFF STACK MCRDP3: POP P,U ;HERE IF BAD MSG, RESTORE PCB POINTER PJRST INCTBD## ; CALL INCTBD WITH T1 = ADDR OF ERROR SUBTTL 2.3.2 DAP DATA MESSAGE (WITH AND WITHOUT E-O-R) ;MCRDAR/MCRDAT ROUTINES TO PROCESS TERMINAL INPUT DATA. ;CALL MOVEI U,LDB ; P1, P4 := POINTER TO THE FIRST BYTE OF DATA. ;RETURN CPOPJ1 ;ALWAYS (IT DOESN'T DETECT ANY ERRORS) MCRDAR: ;DATA WITH END OF RECORD MCRDAT: PUSH P,F ;RECINT CLOBBERS F MCRDA1: SOJL P4,FPOPJ1## ;ALL DONE ILDB T3,P1 ;GET NEXT CHARACTER MOVEI T1,STY.DE ;DEFERRED ECHO BIT TDNN T1,LDBREM##(U) ;IS FRONT-END DOING THE ECHO? TRO T3,CK.FDE ;YES, NOTE THAT PUSHJ P,RECPTY## ;PROCESS CHARACTER JRST MCRDA1 ;AND PROCESS NEXT CHAR, IF ANY. SUBTTL 2.3.3 DAP STATUS MESSAGE ;MCRSTS ROUTINE TO PROCESS DAP TERMINAL STATUS MESSAGES ;CALL MOVEI U,LDB ; P1, P4 := POINTER TO THE "STC" BYTE OF A DAP STATUS MESSAGE ;RETURN CPOPJ ;MESSAGE'S "STC" WAS BAD ; CPOPJ1 ;MESSAGE PROCESSED OK MCRSTS: ;STC PUSHJ P,EBI2BI ;GET THE STATUS CODE JUMPN T1,CPOPJ## ;WE ONLY ACCEPT THE "STC=0" TYPE STATUS MESSAGES ;STY PUSHJ P,EBI2BI ;GET THE STATUS BITS DPB T1,LDPSTS## ;STORE THE NEW STATUS BITS MOVSI T2,LRLCHR## ;INITIAL CHARACTERISTICS SEEN? TDNE T2,LDBREM##(U) ;TEST JRST MCRST1 ;YES--SKIP REMOTE'S IDEA OF TS.ESC FLAGS MOVSI T2,LDLTAB## ;HARDWARE-TABS FLAG TRNE T1,STY.HT ;DOES REMOTE HAVE TTY TAB SET? IORM T2,LDBDCH##(U) ;YES, SET TTY TAB TRNN T1,STY.HT ;DOES REMOTE HAVE TTY TAB SET? ANDCAM T2,LDBDCH##(U) ;NO, SET TTY NO TAB MOVSI T2,LDLFRM## ;HARDWARE-FORMS FLAG TRNE T1,STY.FF ;DOES REMOTE HAVE TTY FORM SET? IORM T2,LDBDCH##(U) ;YES, SET TTY FORM TRNN T1,STY.FF ;DOES REMOTE HAVE TTY FORM SET? ANDCAM T2,LDBDCH##(U) ;NO, SET TTY NO FORM MOVSI T2,LDLNFC## ;NO-FREE-CRLF FLAG TRNN T1,STY.CR ;DOES REMOTE HAVE TTY CRLF SET? ANDCAM T2,LDBDCH##(U) ;YES, SET TTY CRLF TRNE T1,STY.CR ;DOES REMOTE HAVE TTY CRLF SET? IORM T2,LDBDCH##(U) ;NO, SET TTY NO CRLF MCRST1: MOVSI T2,LDLLCT## ;LOWER-CASE CONVERSION FLAG TRNN T1,STY.CV ;DOES REMOTE HAVE TTY LC SET? ANDCAM T2,LDBDCH##(U) ;YES, SET TTY LC (CLEAR CASE CONVERSION) TRNE T1,STY.CV ;DOES REMOTE HAVE TTY LC SET? IORM T2,LDBDCH##(U) ;NO, SET TTY UC (SET CASE CONVERSION) MOVSI T2,LPLXNF## ;XON-XOFF FLAG TRNE T1,STY.TP ;DOES REMOTE HAVE TTY XONXOF SET? IORM T2,LDBPAG##(U) ;YES, SET TTY XONXOF TRNN T1,STY.TP ;DOES REMOTE HAVE TTY XONXOF SET? ANDCAM T2,LDBPAG##(U) ;NO, CLEAR TTY XONXOF TRNN T1,STY.DE ;IF THE REMOTE IS LOCAL ECHOING JRST [PUSHJ P,MCROKE ;SEE IF WE THINK THAT'S OK PUSHJ P,D85CHP ;IF NOT, QUEUE A STATUS CHECK LDB T1,LDPSTS## ;GET STATUS BITS BACK JRST .+1] ;BACK TO MAIN FLOW. ;FALL THROUGH TO PLAY WITH THE MODEM-CONTROL BITS SUBTTL 2.3.3.1 INCOMING MODEM CONTROL MCRTIW: MOVE T2,LDBDCH##(U) ;THE UBIQUITOUS DCH BITS TRNN T2,LDRDSD## ;SEE IF THIS IS A DATA SET JRST CPOPJ1## ;NOT A DATA SET LINE MOVE T2,LDBREM##(U) ;GET THE DATA SET BITS SETZ T3, ;START OUR STATE VARIABLE WITH A ZERO TRNE T1,STY.RG ;MAP REMOTE CARRIER/RING INTO IORI T3,1 ; BIT 35 TRNE T1,STY.DT ;MAP REMOTE DATA TERMINAL READY INTO IORI T3,2 ; BIT 34 CAMN U,DIALDB## ;IS THIS THE DIALOUT LINE? IORI T3,4 ;YES, DTR/CARRIER HAS DIFFERENT MEANING THEN PUSHJ P,@MCRSTD(T3) ;DISPATCH ON STATE VAR PJRST CPOPJ1 ;AND WE ARE DONE! ;MODEM STATUS DISPATCH TABLE MCRSTD: IFIW D85LST ;(I00) MAYBE NOTHING, MAYBE LOST CARRIER IFIW D85RNG ;(I01) THE PHONE IS RINGING. IFIW D85MLC ;(I10) MOMENTARY LOSS OF CARRIER? IFIW D85RUN ;(I11) DTR AND CARRIER - DATASET UP AND RUNNING IFIW D85DL0 ;(O00) POSSIBLE SYNCHRONIZATION IFIW D85DLR ;(O01) RING - ACKNOWLEDGEMENT OF DIALOUT REQ IFIW D85DLX ;(O10) DTR - DIALOUT SUCCEEDED (BUT NO CARRIER) IFIW D85DLW ;(O11) DTR - DIALOUT SUCCEEDED, LINE IS UP ;HERE TO SEE IF LOST THE PHONE D85LST: TLNN T2,LRLDSR ;DID WE USED TO HAVE CARRIER? POPJ P, ;NO, IGNORE MOVEI T3,DSTOFF## ;GET PSISER'S MODEM OFFLINE FLAG PUSHJ P,DSCSG ;SIGNAL LOST CARRIER PUSHJ P,MCRDET ;DETACH THE JOB (OR WHATEVER) MOVSI T1,LRLDSR## ;NOW CLEAR DSR SO WE KNOW THAT HE HAS ANDCAM T1,LDBREM##(U) ; GONE. (KEEPS D85LST FROM RUNNING) POPJ P, ;THAT'S THE END OF THAT PHONE CONVERSATION ;HERE IF THE PHONE IS RINGING D85RNG: HRRZ T1,LDBDDB(U) ;HERE SEE IF THE TERMINAL HAS BEEN OPENED. JUMPE T1,CPOPJ## ; NOT, WAIT FOR THE REMOTE MOVEI T3,DSTRNG## ;OTHERWISE JUST SIGNAL THE FACT PJRST DSCSG ;THAT A DATASET LINE IS RINGING ;HERE IF MOMENTARY LOSS OF CARRIER D85MLC: TLNN T2,LRLDSR## ;DID WE HAVE CARRIER BEFORE? POPJ P, ;NO, NOT TO WORRY THEN HRRZ T1,LDBDDB##(U) ;ADDRESS OF ASSOCIATED DDB JUMPE T1,CPOPJ## ;IGNORE IF NO TTY DDB MOVE T2,DEVMOD(T1) ;GET DEVICE CHARACTERISTICS TRNN T2,ASSPRG ;IN USE AS I/O DEVICE? POPJ P, ;NO, NOBODY CARES MOVEI T2,IODERR ;YES, SET THE DEVICE-ERROR FLAG IORM T2,DEVIOS(T1) ;TO TELL USER THAT HIS I/O DEVICE HICCUPPED POPJ P, ;OTHERWISE IGNORE MOMENTARY LOSS OF CARRIER ;DTR AND CARRIER - DATASET IS UP AND RUNNING D85RUN: TLNE T2,LRLDSR## ;WAS CARRIER UP BEFORE?? POPJ P, ; IF IT WAS, THEN EVERYTHING'S OK PUSH P,W ;THIS LINE JUST CAME UP. SAVE W, PUSHJ P,TSETBI## ; AND CLEAR THE INPUT BUFFER. POP P,W ; ... MOVSI T1,LRLGRT## ;THE NEED-TO-BE-GREETED FLAG TDNE T1,LDBREM(U) ;IS THIS GUY LONELY? JRST D85RU4 ;NO, HE'S HAPPY IORM T1,LDBREM(U) ;YES, SO TAKE NOTICE OF HIM PUSHJ P,TTFGRT## ;"WELL HELLO THERE" D85RU4: MOVSI T1,LRLDSR## ;NOW SET A BIT TO REMEMBER THAT THIS IORM T1,LDBREM##(U) ;LINE THINK'S THAT IT'S UP. PUSHJ P,D85CHP ;KICK THE REMOTE TO LET IT KNOW WE CARE MOVEI T3,DSTON## ;AND FINALLY TELL PSISER PJRST DSCSG ; THAT IT'S UP. ;HERE FOR NO DTR/CARRIER ON DIALOUT, MAY BE DIALOUT FAILURE D85DL0: MOVSI T2,LRLCHR## ;A TIMESHARED FLAG NAME HERE TDNN T2,DIALFL## ;HAS REMOTE ACKNOWLEDGED THE DIALOUT REQ? POPJ P, ;NO, JUST IGNORE MOVSI T2,400000 ;YES, THE LACK OF DTR IS DIALOUT FAILED IORM T2,DIALFL## ;SET DIALOUT COMPLETION SANS SUCCESS POPJ P, ;THAT'S THE END OF THAT ;DIALOUT "RING" IS ACKNOWLEDGEMENT D85DLR: MOVSI T2,LRLCHR## ;A TIMESHARED FLAG NAME IORM T2,DIALFL## ;WHICH IN THIS CASE MEANS REMOTE ACK OF DIALOUT POPJ P, ;WHICH IS ALWAYS NICE TO KNOW ;DIALOUT DTR AND CARRIER = HAPPINESS D85DLW: MOVSI T2,LRLDSR## ;OUR COPY OF CARRIER IORM T2,LDBREM##(U) ;WE HAVE AN UP AND RUNNING DATASET LINE ;DIALOUT DTR SANS CARRIER = PUZZLEMENT D85DLX: MOVSI T2,LRLDSR##!400000 ;THE DIALOUT HAS SUCCEEDED IORM T2,DIALFL## ;SET COMPLETION AVEC SUCCESS POPJ P, ;LET D85CRQ WAKE UP AND FIND THE GOOD NEWS DSCSG: PUSH P,T1 PUSH P,F LDB T2,LDPLNO## ;PSISER WANT'S ITS ARG AS A LINE NUMBER PUSHJ P,SIGDSC## ;SIGNAL DATA SET STATUS CHANGE POP P,F JRST TPOPJ## SUBTTL 2.3.4 DAP CONTROL ;MCRCTL ROUTINE TO PROCESS DAP TERMINAL CONTROL MESSAGES ;CALL MOVEI U,PCB ; MOVEI F,LDB ; P1, P4 := POINTER TO THE "DCT" FIELD OF A DAP CONTROL MESSAGE ;RETURN CPOPJ ;CONTROL TYPE NOT RECOGNIZED ; CPOPJ1 ;MESSAGE ACCEPTED MCRCTL: ;SET LDB FIELDS AS FROM "SET TERMINAL" COMMAND. ;DCT PUSHJ P,EBI2BI ;READ THE TYPE OF CONTROL CAIN T1,DCT.EP ;ECHO PIPLINE JRST MCREPM ;YES CAIN T1,DCT.TC ;TERMINAL CHARACTERISTICS JRST MCRCHR ;YES, POPJ P, ;NONE OF THE ABOVE, ERROR RETURN MCREPM: ;HERE TO PROCESS AN ECHO PIPELINE MARKER ;CDT ILDB T1,P1 ;GET THE SERIAL NUMBER SUBI P4,1 ;REDUCE THE COUNT DPB T1,LDPEPM## ;STORE THE PIPELINE MARKER MOVSI T1,LRLEPW## ;RETURN MARKER AT ONCE IORM T1,LDBREM##(U) PUSHJ P,MCROKE ;OK TO ECHO (TEST THE LDB)? PJRST CPOPJ1## ;EXIT. CAN'T SEND IT NOW PUSHJ P,D85CHP ;QUEUE THE REQUEST SO IT GOES QUICK PJRST CPOPJ1## ;EXIT MCRCHR: MOVSI T1,LRLCHR## ;THE CHARACTERISTICS-SEEN FLAG TDNE T1,LDBREM(U) ;BEEN HERE BEFORE? JRST MCRCH4 ;YEAH, JUST PROCESS THE NEW CHARACTERISTICS ;HERE WHEN A NEWLY-CONNECTED TERMINAL HAS SENT THE INITIAL CHARACTERISTICS IORB T1,LDBREM##(U) ;MARK WE HAVE NOW RECEIVED CHARACTERISTICS MOVE T2,LDBDCH##(U) ;GET GENERAL DEVICE CHARACTERISTICS TLNN T1,LRLGRT## ;IF TERMINAL NEEDS TO BE GREETED TRNE T2,LDRDSD## ;AND ISN'T A DATASET (D85RUN HANDLES THIS CASE) JRST MCRCH4 ;ALREADY GREETED, OR A DATASET MOVSI T1,LRLGRT## ;THE GREETED FLAG IORM T1,LDBREM##(U) ;WE ARE NOW GREETING IT PUSHJ P,TTFGRT## ;"WELL HELLO THERE" MCRCH4: PUSHJ P,XSKIP## ;READ PUSHJ P,XSKIP## ; AND PUSHJ P,XSKIP## ; IGNORE PUSHJ P,XSKIP## ; THE PUSHJ P,XSKIP## ; FILL PUSHJ P,XSKIP## ; TIME(S) PUSHJ P,EBI2BI ;GET THE RECEIVE SPEED MOVEI T2,(T1) ;COPY TO T2 PUSHJ P,TTCSP1## ;GET THE SPEED INDEX CAIA ;DON'T SAVE INVALID SPEED DPB P2,LDPRSP## ;STORE PUSHJ P,EBI2BI ;GET THE TRANSMIT SPEED MOVEI T2,(T1) ;COPY THE SPEED PUSHJ P,TTCSP1## ;GET THE SPEED INDEX CAIA ;DON'T SAVE INVALID SPEED DPB P2,LDPTSP## ;STORE MOVSI T1,LRLATO## ;AUTOBAUD REQUEST BIT ANDCAM T1,LDBREM##(U) ;DONE WAITING ;CONTINUED ON NEXT PAGE ;CONTINUED FROM PREVIOUS PAGE PUSHJ P,EBI2BI ;WIDTH OF TERMINAL'S CHARRIAGE SKIPE T1 DPB T1,LDPWID## ;STORE PUSHJ P,EBI2BI ;GET THE AUTO CRLF DPB T1,LDPACR## ;STORE PUSHJ P,XSKIP## ;READ AND IGNORE THE ELEMENT # PUSHJ P,EBI2BI ;READ THE FORMER-2741 BITS TRNN T1,CDT.8B ;8-BIT TERMINAL? TDZA T2,T2 ;NO MOVEI T2,1 ;YES DPB T2,LDP8BT## ;ASSIGN APPROPRIATELY TRNN T1,CDT.PL ;APL MODE? TDZA T2,T2 ;NO MOVEI T2,1 ;YES DPB T2,LDPAPL## ;PROPAGATE TO THE LDB TRNE T1,CDT.FT ;NEW FORMS-TYPE PRESENT? PUSHJ P,XSKIP## ;YES--IGNORE IT. DON'T LET REMOTE CHANGE THIS JRST CPOPJ1 ;RESTORE PCB AND GIVE GOOD RETURN SUBTTL 3.0 INTERFACE TO NETSER FOR OUTPUT OF DATA SUBTTL 3.1 NETWORK CONTROL MESSAGE OUTPUT (NCL) SUBTTL 3.1.1 OUTPUT A CONNECT MESSAGE ;MCRXCN ROUTINE TO SEND A MCR CONNECT MESSAGE. ;CALL MOVEI W,NDB ;NODE THAT OWNS THE TERMINAL ; MOVEI U,LDB ;LDB OF MCR TO CONNECT. ; ; SLA MUST BE SET UP. DLA = 0 IMPLIES INITIATE. ;RETURN CPOPJ ;COULDN'T SEND. NO CORE ; CPOPJ1 ;MESSAGES GIVEN TO NCL MCRXCN: PUSH P,U ;SAVE THE LDB FOR A BIT PUSHJ P,NCMHDR## ;U := PCB, (P)+ := "CNT" BYTE POINTER JRST UPOPJ## ;NO CORE? GIVE ERROR RETURN EXCH U,-1(P) ;GET THE LDB BACK FOR A WHILE. ;TYP XMTI NC.CNT ;THIS IS A CONNECT MESSAGE ;DLA XMTB LDPDLA## ;SEND DLA (OR 0 IF CONNECT INITIATE) ;SLA LDB T1,LDPSLA## ;WE MUST HAVE A LAT ASSIGNED. SO SKIPN T1 ; MAKE SURE THAT THE SLA IS NON-ZERO STOPCD .,STOP,MCRSLZ, ;++ SLA IS ZERO XMT T1 ;WRITE THE SLA ;DPN(OBJ) XMTI OBJ.TY ;WE ARE CONNECTING TO A TERMINAL ;DPN(,PID) XMTB LDPRLN## ; AND THIS IS HIS LINE NUMBER ;SPN(OBJ) XMTI OBJ.TT ;WE ARE THE MONITOR CONTROL ROUTINE (MCR) ;SPN(,PID) XMTS NDBSN2+NETNDB## ; AND THIS IS OUR NAME ;MML XMTI ^D512 ;SEND THE MAX-MESSAGE-LENGTH (BUT NO-ONE CARES) ;FEA(DCM) XMTI DCM.AS ;ASCII MODE ;FEA(,RLN) XMTI 0 ;VARIABLE RECORD LENGTH ;FEA(,,DTY) XMTI DTY.MC!DTY.AB!DTY.SB ;OUR ATTRIBUTES EXCH U,-1(P) ;GET THE PCB BACK JSP T1,NETWRC## ;GIVE THE MESSAGE TO NCL PJRST UPOPJ1## ;GIVE A GOOD RETURN SUBTTL 3.1.2 OUTPUT A DISCONNECT MESSAGE ;TRMXDC ROUTINE TO SEND A DISCONNECT TO A REMOTE TERMINAL. ;CALL MOVE T1,XWD NODE,RSN ;NODE IS NODE TO RE-CONNECT TO IF REASON ; ; IS RSN.RC (IE A SET-HOST STYLE DISCONNECT) ; MOVEI U,LDB ; MOVEI W,NDB ; PUSHJ P,TRMXDC ;RETURN CPOPJ ;NO CORE. ; CPOPJ1 ;MESSAGE SENT ; TRMXDC:: ;HERE TO SEND A REMOTE TERMINAL A DISCONNECT. PUSH P,T1 ;SAVE THE "XWD NODE,RSN" FOR A BIT PUSH P,U ;SAVE THE LDB PUSHJ P,NCMHDR## ;GET A PCB, PUSH "CNT" POINTER ON STACK JRST [POP P,U ;IF NO CORE, REPLACE THE LDB, JRST TPOPJ##] ; AND GIVE A BAD RETURN EXCH U,-1(P) ;GET THE LDB ADDRESS BACK PUSHJ P,TTYOPR## ;RESET DEVOPR IF NECESSARY ;TYP XMTI NC.DSC ;THIS IS A DISCONNECT MESSAGE ;DLA XMTB LDPDLA## ;INSERT THE REMOTE'S LINK ADDRESS ;SLA XMTB LDPSLA## ;INSERT OUR LINK ADDRESS ;RSN HRRZ T1,-2(P) ;GET THE REASON XMT T1 ;SEND IT ;NNM HRRZ T1,-2(P) ;GET THE REASON AGAIN CAIE T1,RSN.RC ;IS THIS A "SET HOST" STYLE DISCONNECT? JRST MCRXD1 ;NO. DON'T SEND THE "NNM" BYTE HLRZ T1,-2(P) ;GET THE "NNM" XMT T1 ; AND SEND THAT TOO MCRXD1: EXCH U,-1(P) ;GET THE PCB BACK JSP T1,NETWRC## ;GIVE THE MESSAGE TO NCL TO SEND POP P,U ;RESTORE THE LDB LDB T1,LDPSLA## ;NOW GET THE LAT ADDRESS, AND MOVEI T2,LAT.DC ; CHANGE THE STATE TO BE DPB T2,LATSTA## ; DISCONNECT CONFIRM WAIT. MOVSI T1,LRLCON## ;GET THE "CONNECTED BIT" ANDCAB T1,LDBREM##(U) ;AND CLEAR IT SO SCNMCR WON'T RUN JRST TPOPJ1## ;GIVE GOOD RETURN SUBTTL 3.2 TERMINAL OUTPUT SERVICE (SCNMCR) COMMENT @ There are three basic phases to the SCNMCR routine. They are: 1) Save and set up registers, and ensure that the terminal is connected. 2) Do a priority based scan looking for messages to send. In decreasing priority these messages are: a) XOFF (DAP control) b) Character Gobbler (DAP control) c) Terminal Status (DAP status) (From SCNCHP routine) d) Terminal Characteristics (DAP control) (From SCNCHP routine) e) Terminal Data (DAP data) f) Auto Dial (DAP control) g) Terminal Echo Pipeline Marker (DAP control) 3) Send the message. (Give it to NCL to send) @ ;SCNMCR ROUTINE TO CONSTRUCT MCR MESSAGES. (CALLED FROM NETSCN) ;CALL MOVEI U,LDB ;LDB WANTING SERVICE ;RETURN CPOPJ ;NO CORE ; CPOPJ1 ;LDB PROCESSED OK ;CLOBBERS W SCNMCR::NTDBUG ;VERIFY THE INTERLOCK PUSHJ P,SAVE4## ;SAVE THE P'S CAUSE SCNSER CALLS US. LDB T2,LDPLNO## ;MAKE SURE A NETWORK LINE SUBI T2,NETOFS## ;(THIS IS ONLY PART OF MCRCHK) JUMPL T2,CPOPJ1## ;IF NOT, OK RETURN SO WON'T REQUEUE CAIL T2,M.RTTY## ;OFF END? JRST CPOPJ1## ;GLAD WE CHECKED MOVE T1,LDBREM##(U) ;STILL CONNECTED? TLNE T1,LRLCON## ;?? JRST SCNMC0 ;YES, CONTINUE SKIPLE LDBTOC##(U) ;NO - OUTPUT LEFT? PUSHJ P,TSETBO## ;YES, FLUSH IT PUSH P,F ;SAVE F A BIT HRRZ F,LDBDDB##(U) ;GET DDB JUMPE F,FPOPJ1## ;IF NONE, GIVE OK RETURN MOVE S,DEVIOS(F) ;GET STATUS BITS TLNE S,IOW ;I/O WAIT? PUSHJ P,TTWAKE## ;YES, WAKE IT JRST FPOPJ1## ;GIVE GOOD RETURN SCNMC0: LDB T1,LDPRNN## ;GET THE NODE NUMBER, AND USE IT PUSHJ P,SRCNDB## ; TO SET UP W (POINTER TO THE NDB) JRST CPOPJ1## ; IF NO NDB GIVE GOOD RETURN. ;CONTINUED ON NEXT PAGE ;CONTINUED FROM PREVIOUS PAGE ;COME HERE WITH U := LDB ADDRESS ;HERE IS WHERE WE SEE WHAT SORT OF SERVICE A MCR NEED'S SCNMC1: MOVE T1,LDBREM##(U) ;GET THE REMOTE STATION BITS TLNN T1,LRLXOF!LRLSCG ;NEED AN XOFF OR A GOBBLER? JRST SCNMC2 ; IF NOT, THEN CHECK THE PARMS TLNE T1,LRLXOF## ;WAS IT AN XOFF WE NEEDED? JRST [PUSHJ P,MCXXOF ; IF SO, THEN SEND THE XOFF, AND JRST SCNMC6 ; IF NO CORE, RE-QUEUE THE LINE JRST SCNMC1] ; SEE IF THE MCR NEEDS OTHER SERVICE PUSHJ P,MCXGBL ;IF IT WAS A GOBBLER, THEN SEND THAT, JRST SCNMC6 ;IF NO CORE, RE-QUEUE THE LINE JRST SCNMC1 ; AND PERFORM OTHER SERVICES. SCNMC2: MOVE T2,LDBBYT##(U) ;GET SCNSER'S FLAGS. TRNE T2,L1RCHP## ;DOES SCNSER WANT A PARM CHANGE? JRST [PUSHJ P,SCNCHP ; IF SO, THEN SEND THE CHANGE, JRST SCNMC6 ; IF NO CORE, REQUEUE THE LINE JRST SCNMC1] ; AND PERFORM OTHER SERVICES. TLNE T1,LRLTTW##!LRLATO## ;ARE WE WAITING FOR A DATA-REQUEST? JRST SCNMC4 ; IF SO, THEN SKIP OUTPUT CHECK TLNE T1,LRLTTO## ;DO WE ALREADY HAVE A CHAR IN LDPCHR? JRST SCNMC3 ;IF WE HAVE THE CHAR, DON'T CALL XMTCHR PUSHJ P,XMTCHR## ;SEE IF SCNSER WILL GIVE US A CHAR JRST SCNMC4 ;NO OUTPUT. GO LOOK FOR OTHER WORK DPB T3,LDPCHR## ;SAVE THE CHAR WHERE MCXDAT WILL LOOK MOVSI T1,LRLTTO## ;GET THE "CHAR IN LDPCHR" BIT IORB T1,LDBREM##(U) ; AND SET IT SO WE DON'T LOSE THE CHAR SCNMC3: PUSHJ P,MCXDAT ; SEND THE DATA, AND JRST SCNMC6 ; IF NO CORE, GET OUT NOW, OTHERWISE JRST SCNMC1 ; FINISH THE SERVICE SCNMC4: MOVE T1,LDBREM(U) ;RELOAD T1 TLNE T1,LRLADR ;IS THERE AN AUTO DIAL REQUEST? JRST [PUSHJ P,MCX801 ; IF SO, THEN SEND THE NUMBER, AND JRST SCNMC6 ; IF NO CORE, RE-QUEUE THE LINE JRST SCNMC1] ; CONTINUE PROCESSING TLNE T1,LRLEPW ;IS ECHO PIPELINE MARKER WAITING? PUSHJ P,MCROKE ;LOCAL ECHO OK NOW? JRST SCNMC5 ; IF NOT, DON'T SEND EPM PUSHJ P,TRXEPM ;OTHERWISE SEND THE EPM JRST SCNMC6 ;NO CORE. REQUEUE THE LINE SCNMC5: AOS (P) ;GIVE SKIP RETURN (WON'T REQUE THE LINE) SCNMC6: PUSHJ P,TSDPCB ;FINALLY SEND THE MULTIPART MESSAGE POPJ P, ; AND RETURN ;SCNCHP ROUTINE TO DETERMINE IF TERMINAL STATUS, OR TERMINAL CHARACTERISTICS ; MESSAGE NEEDS TO BE SENT. ROUTINE IS CALLED FROM "SCNMCR" WHENEVER ; SCNSER LITES THE "L1RCHP" BIT. (THIS IS DONE BY THE "SETCHP" ROUTINE.) ; THIS ROUTINE PERFORMS THE NECESSARY TRANSLATION FROM SCNSER'S BIT'S ; TO NETMCR'S. ;CALL MOVEI U,LDB ;RETURN CPOPJ ;NO CORE ; CPOPJ1 ;WITH "L1RCHP" OFF. SCNCHP: PUSHJ P,SAVE1## ;SAVE THE P'S SETZ P1, ;LH = BITS TO SET, RH = CLEAR PUSHJ P,MCROKE ;CHECK ON ECHOING MODE TLO P1,STY.DE ; AND SET DE IF REMOTE CAN'T ECHO NOW MOVE T4,LDBDCH##(U) ;CARRY THE UBIQITOUS DCH IN T4 TLNN T4,LDLLCT## ;"TTY LC" SET? TROA P1,STY.CV ;DONT TRANSLATE TLO P1,STY.CV ;TRANSLATE TLNN T4,LDL8BI## ;8-BIT I/O MODE SET? TROA T1,STY.8B ;DON'T ALLOW 8-BIT ECHO TLO T1,STY.8B ;ALLOW 8-BIT ECHO MOVEI T2,LRRXFF## ;GET SEND-XOFF STATUS BIT TDNN T2,LDBREM##(U) ;SET FOR REMOTE? JRST SCNCH0 ;NO, SKIP IT ANDCAM T2,LDBREM##(U) ;CLEAR THE BIT MOVSI T2,LOLSTP## ;GET OUTPUT STOPPED BIT TDNN T2,LDBOST##(U) ;IS IT SET IN THE STATES WORD? TROA P1,STY.XS ;NO. TLO P1,STY.XS ;YES. SCNCH0: TLNE T4,LDLIMI## ;IF IMAGE MODE IS SET IN LDBDCH, TLOA P1,STY.II ; TELL REMOTE TO SEND EVERYTHING TRO P1,STY.II ;IF NOT, USE ASCII MODE MOVSI T1,LRLIMO## ;IMAGE OUTPUT BIT TDNN T1,LDBREM##(U) ;IMAGE OUTPUT? TROA P1,STY.IO ;NO TLO P1,STY.IO ;YES MOVE T2,LDBOST##(U) ;GET SPECIAL STATES BITS TLNE T2,LOLPIM## ;IF WE ARE IN PIM MODE, THEN OVER-RIDE JRST [TRZ P1,STY.II!STY.IO ; ANY OTHER IMAGE MODE DECISIONS, AND TLO P1,STY.II!STY.IO ; SINCE PIM DOESN'T ALWAYS GET THE JRST .+1] ; BITS RIGHT CONTINUE. ;FALL INTO NEXT PAGE ;FROM ABOVE MOVE T1,LDBPAG##(U) ;GET PAGING CONTROL MOVE T2,LDBBY2##(U) ;AND CLOSELY RELATED BITS TLNE T1,LPLXNF## ;IS XON/XOFF PROCESSING ENABLED? TLNE T2,L2LTAP## ;YES, BUT "TTY TAPE" OVERRIDES IT TROA P1,STY.TP ;NO - CLEAR XONXOFF PROCESSING IN REMOTE. TLO P1,STY.TP ;YES - SET XONXOFF PROCESSING IN REMOTE. TRNN T2,L2RXON## ;CHECK "TAPE IS XON'ED" BIT TROA P1,STY.TT ;NOT IN TAPE MODE TLO P1,STY.TT ;IN TAPE MODE TLNN T4,LDLTAB## ;IS "TTY TAB" SET IN LDBDCH? TROA P1,STY.HT ;NO. TLO P1,STY.HT ;YES. TLNN T4,LDLFRM## ;IS "TTY FORM" SET IN LDBDCH? TROA P1,STY.FF ;NO. TLO P1,STY.FF ;YES. TLNN T4,LDLNFC## ;IS "TTY CRLF" SET IN LDBDCH? TROA P1,STY.CR ;NO. TLO P1,STY.CR ;YES. MOVSI T2,LRLHUR## ;THE HANG-UP PHONE BIT TRNE T4,LDRDSD## ;IS THIS A DATA-SET-LINE, TDNN T2,LDBREM##(U) ; WITH A HANG-UP REQUEST PENDING? JRST SCNCH1 ;NO CONTINUE TRO P1,STY.DT+STY.RG;TELL REMOTE TO CLEAR DTR AND CARRIER SCNCH1: ANDCAB T2,LDBREM##(U) ;AND NOTE REQUEST HONORED HLRZ T1,P1 ;GET THE BITS TO "SET" TRNE T1,STY.XS ;ARE WE SETTING XOFF? JRST SCNC1A ;YES, ALWAYS SEND XOFF STATUS LDB T2,LDPSTS## ;GET THE CURRENT STATUS ANDCM T1,T2 ;WILL ANY REALLY GET SET? JUMPE T1,SCNCH2 ;IF NOT, DON'T SEND A "SET BITS" MESSAGE SCNC1A: PUSHJ P,MCXSST ;SET THE BITS (IN REMOTE AND LDPSTS) POPJ P, ;GIVE ERROR RETURN IF NO CORE SCNCH2: HRRZ T1,P1 ;GET THE BITS TO "CLEAR" TRNE T1,STY.XS ;ARE WE CLEARING XOFF? JRST SCNC2A ;YES, ALWAYS SEND XOFF STATUS LDB T2,LDPSTS## ;GET THE CURRENT STATUS IORI T2,STY.DT!STY.RG;ALWAYS SEND REQUEST TO CLEAR DTR/CARRIER AND T1,T2 ;WILL ANY BITS REALLY BE CLEARED JUMPE T1,SCNCH3 ;IF NOT, DON'T TRY TO CLEAR THEM SCNC2A: PUSHJ P,MCXCST ;CLEAR THE BITS IN REMOTE AND LDPSTS POPJ P, ;GIVE ERROR RETURN IF NO CORE ;DROP THROUGH ;FROM ABOVE ;NOW CHECK TO SEE IF WE MUST SEND TERMINAL CHARACTERISTICS. SCNCH3: MOVE T1,LDBREM##(U) ;GET REMOTE TERMINAL BITS TLNN T1,LRLABR## ;NEED TO INITIATE AUTOBAUD? JRST SCNCH4 ;NO--DON'T PUSHJ P,MCXABR ;YES--SEND THE REQUEST POPJ P, ;NO CORE RETURN JRST SCNCH5 ;WAIT FOR SPEED FROM -11 BEFORE CONTINUING SCNCH4: TRC T1,LRRSHC## ;CHANGE "CAN SET HOST" INTO "DC72" BIT TLNN T1,LRLATO## ;SEND NONE IF WAITING FOR SPEED FROM REMOTE TDNN T1,[XWD LRLCHR##,LRRSHC##] ;IF DC72 OR WE HAVE RECEIVED CHARACTERSISTICS, OK TO SEND JRST SCNCH5 ;OTHERWISE, DON'T SEND ONE (***SEE FOOTNOTE) PUSHJ P,GETCR ;TRANSLATE SPEED ETC TO CHARACTERISTICS WORD CAMN T1,LDBCCH##(U) ;ANY CHANGE? JRST SCNCH5 ;NO CHANGE. GIVE GOOD RETURN PUSHJ P,TRXTCR ;SEND THE CHARACTERISTICS. (WILL PUT T1 IN LDBCCH) POPJ P, ;NO CORE. GIVE ERROR RETURN SCNCH5: MOVEI T1,L1RCHP## ;WE'VE SUCCESSFULY SCANED THE PARAMETERS ANDCAB T1,LDBBYT##(U) ;SO CLEAR REQUEST SO WE DON'T DO IT AGAIN JRST CPOPJ1## ;GOOD RETURN ;GETCR ROUTINE TO TRANSLATE THE VARIOUS "CHARACTERISTICS" INTO A SINGLE WORD GETCR:: LDB T1,LDPLTT## ;GET LAST TTY TYPE WE SENT LDB T2,LDPTTT## ;AND CURRENT TTY TYPE INDEX SKIPL LDBREM##(U) ;IF A VTM, FORGET ABOUT LTT FIELD CAMN T1,T2 ;IF THE SAME, TDZA T1,T1 ;START OFF WITHOUT THE CHANGE BIT MOVSI T1,(1B1) ;LIGHT CHANGE BIT IF DIFFERENT LDB T2,LDPSPD## ;GET SPEEDS DPB T2,[POINT 8,T1,35] ;BITS 28-35 LDB T2,LDPFLC## ;GET FILL CLASS DPB T2,[POINT 4,T1,27] ;BITS 24-27 LDB T2,LDPWID## ;GET WIDTH DPB T2,[POINT 8,T1,23] ;BITS 23-16 LDB T2,LDPACR## ;GET AUTO CRLF POINT DPB T2,[POINT 8,T1,15] ;BITS 15-8 LDB T2,LDP8BT## ;GET 8-BIT MODE DPB T2,[POINT 1,T1,0] ;BIT 0 LDB T2,LDPAPL## ;APL MODE BIT DPB T2,[POINT 1,T1,2] ;PROPAGATE TO OUR BIT POPJ P, ;*** FOOTNOTE *** COMMENT @ The terminal characteristics "protocol" is laden with races. If both the remote and the host decide to change the characteristics at the same time, there is no telling what may happen. This "hack" of the LRLCHR bit is a lame effort to minimize the effects of this race. It avoids the case of the host sending a characteristics message with a speed of zero baud before the remote has had a chance to tell the host what it's speed really is. @ ;MCXDAT ROUTINE TO PACKAGE CHARACTERS INTO A DATA MESSAGE. ;CALL PUSHJ P,MCXDAT ;RETURN CPOPJ ;NO CORE ; CPOPJ1 ;SENT DATA MCXDAT: NTDBUG ;VERIFY THE INTERLOCK LDB T1,LDPDRQ## ;GET THE NUMBER OF OUTSTANDING DATA-REQUESTS JUMPE T1,[MOVSI T1,LRLTTW## ;IF WE DON'T HAVE ANY, IORB T1,LDBREM##(U) ; THEN LITE LRLTTW SO WE WON'T JRST CPOPJ1##] ; CALLED UNTIL SOME COME IN. LDB T3,LDPCHR## ;GET THE STORED CHAR (FOR IT'S IMAGE BIT) PUSHJ P,MCXDAM ;SEE IF IT'S BIT AGREES WITH LAST STATUS MSG JRST CPOPJ1## ;NEED TO SEND STATUS MSG. RETURN TO SCNMCR MOVEI T1,2 ;REQUEST A 2 BYTE MESSAGE (MINIMUM...) PUSHJ P,TRQPCB ;TRY TO GET THE PCB PJRST TOPOKE## ;NO CORE. REQUEUE THE LINE AND LEAVE. PUSH P,W ;RUMOR HAS IT THAT SCNSER WILL CLOBBER THIS. ;TYP XMTI DC.DAT ;WE ARE SENDING A DATA MESSAGE MOVSI T1,LRLTTO## ;GET THE "OUTPUT CHAR IN LDPCHR" BIT IFN PARANOID&P$MCR,< ;IF WE'RE PARANOID, TDNN T1,LDBREM##(U) ;MAKE SURE IT'S ON STOPCD .+1,DEBUG,MCRNCO, ;++NO CHARACTER FOR OUTPUT > ;END PARANOIA ANDCAB T1,LDBREM##(U) ;CLEAR THE "CHARACTER WAITING" BIT LDB T3,LDPCHR## ;GET THE WAITING CHARACTER JRST MCXD.2 ;JUMP INTO THE MIDDLE OF THE COPY LOOP. MCXD.1: MOVEI T1,L1RCHP## ;GET SCNSER'S "PARM CHANGE NEEDED" BIT TDNN T1,LDBBYT##(U) ;AND SEE IF WE SHOULD SEND A STATUS MSG FIRST CAIL P3,(P4) ;SEE IF WE HAVE FILLED UP THE ENTIRE MSG JRST MCXD.4 ;FILLED ENTIRE MESSAGE, OR PARM CHANGE NEEDED PUSHJ P,XMTCHR## ;GET THE NEXT CHAR TO GO JRST MCXD.4 ;NO OUTPUT READY. CLOSE OFF MSG AND EXIT MCXD.2: PUSHJ P,MCXDAM ;MAKE SURE THE IMAGE MODE BITS AGREE JRST MCXD.3 ; IF NOT, STASH THE CHAR AWAY & SEND STATUS IDPB T3,P2 ;SEND THE CHAR AOJA P3,MCXD.1 ;COUNT THE CHAR AND TRY TO GET ANOTHER. MCXD.3: MOVSI T1,LRLTTO## ;HERE TO GET OUT WHILE HOLDING A CHAR. IORB T1,LDBREM##(U) ;SIGNIFY WE HAVE A CHAR IN LDPCLR DPB T3,LDPCHR## ;STORE THE CHAR FOR NEXT TIME MCXD.4: POP P,W ;GET OUR NDB POINTER BACK PUSHJ P,TWRPCB ;SEND THE SUB MESSAGE HRRZ T1,NTRPCB ;GET A POINTER TO OUR PCB MOVSI T2,(B7) ;GET THE "INTERRUPT MESSAGE" BIT TDNN T2,@PCBPTR(T1) ;SEE IF WE'VE ALREADY COUNTED THIS DRQ JRST CPOPJ1## ;IF WE'VE COUNTED THE DRQ, THEN JUST LEAVE ANDCAB T2,@PCBPTR(T1) ;CLEAR THE INT BIT (SO MESSAGE WILL COUNT) LDB T2,LDPDRQ## ;GET THE DATA-REQUEST COUNT SOSGE T2 ;AND DECREMENT IT STOPCD .+1,STOP,DRQNEG,;++ DATA REQUEST WENT NEGATIVE DPB T2,LDPDRQ## ;SAVE THE UPDATED DRQ COUNT JRST CPOPJ1## ;GIVE A GOOD RETURN ;MCXDAM ROUTINE TO CHECK THE STATE OF THE IMAGE-OUTPUT BITS ; USED ONLY BY MCXDAT ;CALL T3 := CHAR (WITH CK.IMG BIT ON/OFF) ; J := LDB ;RETURN NONSKIP ;MODES ARE DIFFERENT ; SKIP ;MODES ARE THE SAME ;PRESERVES T3 MCXDAM: SETZ T1, ;START WITH A ZERO TRNE T3,CK.IMG## ;IS THE "IMAGE MODE CHAR" BIT SET? TRC T1,1 ;IF AN IMAGE MODE CHAR, THEN T1 := 1 MOVSI T2,LRLIMO## ;GET THE IMAGE MODE OUTPUT BIT TDNE T2,LDBREM##(U) ;SEE IF WE ARE IN IMAGE OUTPUT MODE TRC T1,1 ;IF WE ARE IN IMAGE MODE OUTPUT, COMPLEMENT T1 JUMPE T1,CPOPJ1## ;GIVE GOOD RETURN IF MODES ARE OK XORM T2,LDBREM##(U) ;FLIP THE STATE OF THE LRLIMO PUSH P,T3 ;PRESERVE THE CHAR FOR A BIT PUSHJ P,SETCHP## ;TELL SCNMCR TO SEND A STATUS MSG POP P,T3 ;GET THE CHAR BACK POPJ P, ; AND GIVE AN ERROR RETURN SUBTTL 3.2.2 OUTPUT DAP STATUS MESSAGE ;MCXSST/MCXCST ROUTINES TO SET AND CLEAR STATUS BITS ;CALL MOVEI T1,BITS ;TO BE CLEARED OR SET ; PUSHJ P,MCXSST/MCXCST ; CPOPJ ;NO CORE ; CPOPJ1 ;MESSAGE SENT, BITS SET/CLEARED IN LDPSTS MCXSTA::MOVEI T2,0 ;SEND STATUS JRST MCXST1 ;GO TO COMMON CODE MCXSST: SKIPA T2,[1] ;SET STATUS MCXCST: MOVEI T2,2 ;CLEAR STATUS MCXST1: PUSH P,T1 ;SAVE STD PUSH P,T2 ;SAVE STC MOVEI T1,4 ;WE WANT A 4 BYTE SUBMESSAGE PUSHJ P,TRQPCB ; SET UP P3 & MUNG THE STACK JRST [POP P,(P) ;NO CORE. GIVE ERROR RETURN JRST TPOPJ##] ; AND HOPE WE GET IT OUT LATER XMTI DC.STS ;WRITE STATUS MESSAGE CODE ;STC XMT -1(P) ;WRITE THE STC ;STD XMT -2(P) ;WRITE THE STD ;CNT PUSHJ P,TWRPCB ;STORE BACK P3 & FIXUP THE STACK POP P,T3 ;GET THE STC BACK (1 = SET, 2 = CLEAR) POP P,T2 ;GET THE STD BACK (BITS TO SET/CLEAR) JUMPE T3,CPOPJ1## ;IF SEND STATUS, DONT UPDATE STATUS LDB T1,LDPSTS ;GET THE UN-UPDATED STATUS CAIN T3,1 ;WAS CODE SET OR CLEAR? TROA T1,(T2) ;IS WAS SET. SET THE BITS TRZ T1,(T2) ;IT WAS CLEAR. CLEAR THE BITS DPB T1,LDPSTS ;STORE THE UPDATED STATUS JRST CPOPJ1## ;GOOD RETURN SUBTTL 3.2.3 OUTPUT DAP CONTROL MESSAGE SUBTTL 3.2.3.1 ECHO PIPELINE MARKER MESSAGE ;TRXEPM ROUTINE TO SEND AN ECHO PIPE LINE MARKER ;CALL MOVEI U,LDB ; PUSHJ P,TRXEPM ;RETURN CPOPJ ;NO CORE ; CPOPJ1 ;MESSAGE SENT TRXEPM::MOVEI T1,4 ;REQUEST A 4 BYTE SUBMESSAGE PUSHJ P,TRQPCB ; AND SET UP P3 AND STACK POPJ P, ;NO CORE, ERROR RETURN ;TYP XMTI DC.CTL ;CONTROL MESSAGE ;DCT XMTI DCT.EP ;PIPE-LINE MARKER ;CDT LDB T1,LDPEPM## ;GET THE PIPE LINE MARKER PUSHJ P,DPBBIN## ;SEND ;CNT MOVSI T1,LRLEPW## ;EPM NO LONGER WAITING ANDCAM T1,LDBREM##(U) ;CLEAR PUSHJ P,TWRPCB ;STORE BACK P3 AND FIXUP STACK JRST CPOPJ1## ;GOOD RETURN SUBTTL 3.2.3.2 CHARACTER GOBBLER MESSAGE ;MCXGBL ROUTINE TO SEND A CHARACTER GOBBLER ;CALL MOVEI U,LDB ; PUSHJ P,MCXGBL ;RETURN CPOPJ ;MESSAGE SENT MCXGBL: MOVEI T1,2 ;REQUEST A 2 BYTE SUBMESSAGE PUSHJ P,TRQPCB ; SET UP P3 AND STACK POPJ P, ;NO CORE, GIVE ERROR RETURN ;TYP XMTI DC.CTL ;CONTROL MESSAGE ;DCT XMTI DCT.CG ;CHARACTER GOBBLER CODE MOVSI T1,LRLSCG##!LRLTTO## ;CHARACTER GOBBLER AND LDPCHR BITS ANDCAM T1,LDBREM##(U) ;CLEAR THEM ;CNT PUSHJ P,TWRPCB ;WRITE BACK P3 AND FIXUP STACK JRST CPOPJ1## ;GIVE GOOD RETURN SUBTTL 3.2.3.3 TERMINAL CHARACTERISTICS MESSAGE ;TRXTCR ROUTINE TO SEND TERMINAL CHARACTERISTICS MESSAGE. ;CALL MOVEI U,LDB ; MOVE T1,NEW-CHARACTERISTICS (WILL BE PUT IN LDBCCH IF SUCCESSFUL) ; PUSHJ P,TRXTCR ;RETURN CPOPJ ;NO CORE ; CPOPJ1 ;CHARACTERISTICS SENT TRXTCR::PUSHJ P,SAVE1## ;WE WANT TO USE P1 FOR A TEMP MOVE P1,T1 ;SAVE CHARACTERISTICS TO SEND MOVEI T1,36 ;REQUEST A LARGE SUBMESSAGE PUSHJ P,TRQPCB ; AND SET UP P3 AND STACK POPJ P, ;NO CORE. GIVE AN ERROR RETURN ;TYP XMTI DC.CTL ;CONTROL MESSAGE ;DCT XMTI DCT.TC ;TTY CHARACTERISTICS ;CDT PUSH P,P1 ;SAVE "P1" OVER THIS LOOP LDB T1,[POINT 2,P1,27] ;FILL CLASS MOVE P1,FILTAB(T1) ;GET POINTER TO CONSTANTS MOVEI T4,6 ;COUNTER MCRTC1: ILDB T1,P1 ;GET FILL VALUE LDB T2,[POINT 4,(P),31] ;XMIT SPEED MOVE T2,LSPTAB##(T2) ;GET SPEED VALUE SKIPN T2 ;PRESENT? MOVEI T2,^D110 ;NO, ASSUME 110 BAUD. MOVEI T3,^D10000 ;COMPUTE BAUD RATE FACTOR CAIN T2,^D110 ;110 BAUD? MOVEI T3,^D11000 ;YES, ASSUME 11-UNIT CODE IMUL T1,T3 ;MULTIPLY BY FACTOR IDIV T1,T2 ;COMPUTE WAIT TIME IN MS. XMT T1 ;WRITE SOJG T4,MCRTC1 ;DO FOR ALL SIX TIMES POP P,P1 ;GET OUR CHARACTERISTICS BACK LDB T1,[POINT 4,P1,35] XMT LSPTAB##(T1) ;WRITE RECEIVE SPEED LDB T1,[POINT 4,P1,31] XMT LSPTAB##(T1) ;WRITE TRANSMIT SPEED LDB T1,[POINT 8,P1,23] ;GET WIDTH XMT T1 ;WRITE LDB T1,[POINT 8,P1,15] ;GET ACR XMT T1 ;WRITE ;CONTINUED ON NEXT PAGE ;CONTINUED FROM PREVIOUS PAGE XMTI 0 ;ELEMENT NUMBER NOT IMPLEMENTED TLNN P1,(1B2) ;TEST APL MODE TDZA T1,T1 ;NO MOVEI T1,CDT.PL ;OR YES HRRZ T2,NDBNVR(W) ;GET REMOTE'S NCL VERSION JUMPE T2,MCRTC2 ;SEND NO MORE CDT IF OLD NODE TRO T1,CDT.FT ;NEW "FORMS TYPE" PRESENT SKIPGE P1 ;IF 8-BIT SET, TRO T1,CDT.8B ;LIGHT THAT AS WELL XMT T1 ;WRITE TLZ P1,(1B1) ;CHANGE BIT NO LONGER VALID LDB T1,LDPTTT## ;GET NEW TTY TYPE SKIPL LDBREM##(U) ;UNLESS A VTM, DPB T1,LDPLTT## ;SAVE AS CHANGED VALUE XMTS CTTWDT##(T1) ;SEND TYPE NAME IN EXTENSIBLE ASCII TRNA ;SKIP OVER OLD-NODE CASE MCRTC2: XMT T1 ;SEND "2741" BITS FOR OLD NODE PUSHJ P,TWRPCB ;WRITE BACK P3 MOVEM P1,LDBCCH(U) ;STORE THE NEW CHARACTERISTICS JRST CPOPJ1## ;GIVE A GOOD RETURN SUBTTL 3.2.3.4 AUTO DIAL MESSAGE ;MCX801 ROUTINE TO SEND A AUTO DIAL MESSAGE TO THE REMOTE DN80 ;CALL MOVEI U,LDB ; PUSHJ P,MCX801 ;RETURN CPOPJ ;NO CORE ; CPOPJ1 ;ALWAYS (WE CHECKED FOR CORE) MCX801: MOVEI T1,30 ;REQUEST A 24 BYTE SUBMESSAGE PUSHJ P,TRQPCB ; AND SET UP P3 AND STACK POPJ P, ;GIVE ERROR RETURN IF NO CORE ;TYP XMTI DC.CTL ;CONTROL MESSAGE ;DCT XMTI DCT.AD ;AUTO DIAL REQUEST ;CDT MOVE T4,[POINT 4,DIALNM##] ;GET THE POINTER TO THE PHONE NUMBER MCX802: ILDB T1,T4 ;GET A DIGIT ADDI T1,"0"+200 ;MAKE EXTENSIBLE ASCII IDPB T1,P2 ;STORE IN THE MESSAGE CAIE T1,17+"0"+200 ;IS IT THE END AOJA P3,MCX802 ;COUNT THE CHARACTER ADDI P3,1 ;COUNT THE LAST BYTE TRZ T1,200 ;CLEAR THE CONTINUE BIT DPB T1,P2 ;RESTORE IT MOVE U,DIALDB## ;GET THE LDB FOR THE DIAL MOVSI T1,LRLADR## ;GET THE AUTO DIAL BIT ANDCAM T1,LDBREM##(U) ;CLEAR THE REQUEST MOVEM T1,DIALFL## ;NOTE DIALOUT REQUEST PROCESSED ; WAITING FOR REMOTE TO ACKNOWLEDGE ; RING = ACKNOWLEDGEMENT OF DIALOUT REQ, THEN ; DTR ASSERTED = SUCCESS, OR ; DTR CLEARED = FAILURE ;CNT PUSHJ P,TWRPCB ;WRITE BACK P3 AND FIXUP STACK JRST CPOPJ1## ;GIVE SUCCESSFUL RETURN SUBTTL 3.2.3.5 XOFF MESSAGE ;MCXXOF ROUTINE TO ASK THE REMOTE TO XOFF A USER ;CALL MOVEI U,LDB ; PUSHJ P,MCXXOF ;RETURN CPOPJ ;NO CORE ; CPOPJ1 ;XOFF MESSAGE SENT SUCCESSFULY MCXXOF: MOVEI T1,2 ;GET A 2 BYTE SUBMESSAGE PUSHJ P,TRQPCB ; AND SET UP P3 AND STACK POPJ P, ;GIVE ERROR RETURN IF NO CORE ;TYP XMTI DC.CTL ;TERMINAL CONTROL MSG ;DCT XMTI DCT.XF ;XOFF REQUEST MOVSI T1,LRLXOF## ;GET AND CLEAR THE BIT ANDCAM T1,LDBREM##(U) ; SO WE DON'T DO IT AGAIN ;CNT PUSHJ P,TWRPCB ;WRITE BACK P3 AND FIXUP STACK JRST CPOPJ1## ; AND GIVE A GOOD RETURN SUBTTL 3.2.3.6 AUTOBAUD MESSAGE ;MCXABR ROUTINE TO ASK THE REMOTE TO INITIATE AUTOBAUD ON A LINE ;CALL MOVEI U,LDB ; PUSHJ P,MCXABR ;RETURN CPOPJ ;NO CORE ; CPOPJ1 ;ABR MESSAGE SENT SUCCESSFULY MCXABR: MOVEI T1,2 ;GET A 2 BYTE SUBMESSAGE PUSHJ P,TRQPCB ; AND SET UP P3 AND STACK POPJ P, ;GIVE ERROR RETURN IF NO CORE ;TYP XMTI DC.CTL ;TERMINAL CONTROL MSG ;DCT XMTI DCT.AB ;AUTOBAUD REQUEST MOVSI T1,LRLABR## ;GET AND CLEAR THE BIT ANDCAM T1,LDBREM##(U) ; SO WE DON'T DO IT AGAIN MOVSI T1,LRLATO## ;BUT SET THE PENDING BIT IORM T1,LDBREM##(U) ;SO WE WAIT FOR THE RESULTS ;CNT PUSHJ P,TWRPCB ;WRITE BACK P3 AND FIXUP STACK JRST CPOPJ1## ; AND GIVE A GOOD RETURN SUBTTL 3.3 OUTPUT PCB MANIPULATION ;THE FOLLOWING FOUR ROUTINES ARE USED FOR HANDLING TERMINAL PCB'S. THE ; REASON THAT THEY ARE SO COMPLEX IS TO MAKE IT EASY TO SEND ; MULTI-PART MESSAGES. ; ;TRQPCB REQUEST A TERMINAL PCB. ;CALL PUSHJ P,TRQPCB ;ARGS T1 := MINIMUM NUMBER OF BYTES REQUIRED (LESS COUNT FIELD) ;RET CPOPJ ;COULD NOT GET THE PCB. "U" NOT SET UP. ; CPOPJ1 ;DID GET THE PCB. THE FOLLOWING HAS BEEN DONE: ; ; A) P2 := BYTE POINTER (TO IDPB WITH) ; ; B) P3 := ZERO (USE TO COUNT BYTES) ; ; C) P4 := MAX NUMBER OF BYTES LEFT IN THIS ; ; SUB MESSAGE. (IE. TO END OF PCB) ; ; D) A "PUSH P,P2" HAS BEEN DONE. (IE THIS ; ; ROUTINE HAS LEFT A COPY OF P2 ON THE STACK) ; ; THIS IS TO MAKE IT EASY TO FILL IN THE ; ; COUNT FIELD LATER. TWRPCB MUST BE CALLED ; ; TO PERFORM THIS ACTION. (CANNOT BE CALLED WITH ; ; A ZERO COUNT) ; ;TWRPCB WRITE BACK THE PCBPTR AND PCBCTR FIELDS AND POP OLD BYTE ; POINTER OFF OF THE STACK ;CALL PUSHJ P,TSRPCB ;RET CPOPJ ; ;TSDPCB SEND THE CURRENT PCB. (QUEUE IT FOR OUTPUT) ;CALL PUSHJ P,TSDPCB ;RET CPOPJ ;NTRPCB WILL BE CLEARED TO INDICATE PCB WAS SENT. SUBTTL 3.3.1 REQUEST AN OUTPUT PCB ;TRQPCB GET A TERINAL PCB ; T1 := MINIMUM NUMBER OF BYTES ;RETURN CPOPJ ;NO CORE ; CPOPJ1 ;PCB ACQUIRED SUCCESSFULY TRQPCB::SKIPLE T1 ;WE DON'T ALLOW NEGATIVE REQUESTS CAIL T1,NTTPLN##*4-7 ;HERE MAKE SURE HE ASKED FOR A REASONABLE AMT. STOPCD .,STOP,RTM, ;++REQUESTED TOO MUCH. PUSH P,T1 ;REMEMBER THIS FOR LATER PUSH P,U ;SAVE THE LDB (WILL SWAP FOR PCB LATER) HRRZ U,NTRPCB ;NOW GET CURRENT PCB (IF ANY) SKIPE U ; IF THERE WAS ONE, THEN JRST [MOVE P3,PCBCTR(U) ; SET UP THE COUNT AND SKIP THE CODE THAT JRST TRQP.2] ; TRIES TO ALLOCATE A NEW PCB TRQP.1: MOVEI T1,NTTPLN## ;GET LENGTH OF A TERMINAL PCB SETZ F, ;MAKE SURE MAKPCB DOESN'T HACK ANY DDB PUSHJ P,MKNPCB## ; AND GO GET A NEW PCB. JRST [POP P,U ;NO CORE. RESTORE THE LDB JRST TPOPJ##] ; AND GIVE AN ERROR RETURN HRRM U,NTRPCB ;NOW STORE THE FACT WE HAVE A PCB. MOVE P2,PCBPTR(U) ; AND SET UP THE INITIAL BYTE POINTER MOVEI T1,NCT.IT ;GET THE NCT BITS PUSHJ P,NCSWHD## ;WRITE THE NCL HEADER. SETZ P3, ;NOW WRITE OUR DLA. TO DO THIS WE MUST EXCH U,(P) ; GET BACK OUR LDB, LDB T1,LDPDLA## ; USE IT TO EXTRACT OUR DESTINATION LINK, PUSHJ P,BI2EBI ; AND THIS WILL WRITE IT OUT. EXCH U,(P) ;NOW GET BACK THE PCB POINTER, ADDB P3,PCBCTR(U) ; UPDATE THE POINTERS, AND DROP INTO MAIN FLOW TRQP.2: MOVEI P4,NTTPLN##*4 ;HERE WE MUST CALCULATE TO SEE IF THE CURRENT SUBI P4,1(P3) ; PCB WILL HOLD AS MUCH AS OUR CALLER CAMGE P4,-1(P) ; REQUESTED IT SHOULD. IF IT CAN'T, THEN JRST [PUSHJ P,TSDPCB ; SEND THIS PCB OUT, AND JRST TRQP.1] ; START ON A NEW ONE. POP P,U ;RESTORE THE LDB POP P,T1 ; THE REQUEST (WHICH WE CAN NOW IGNORE) POP P,T1 ; AND POP OFF OUR RETURN ADDRESS. PUSH P,P2 ;NOW SAVE A BYTE POINTER TO COUNT FIELD IBP P2 ; AND MAKE POINTER POINT TO THE TYP FIELD SETZ P3, ;SET THE INITIAL COUNT TO ZERO. JRST 1(T1) ;ALL DONE. RETURN TO CALLER. ; (WITH UNESTHETIC GARBAGE ON THE STACK ...) SUBTTL 3.3.2 CLOSE OFF A DAP SUB-MESSAGE ;TWRCPB THIS ROUTINE WRITES BACK THE COUNT FIELD AND UPDATES THE POINTER ; IN THE PCB. IT ALSO REMOVES UNESTHETIC GARBAGE FROM THE STACK ;CALL PUSHJ P,TWRPCB ;RETURN CPOPJ ;WITH ONE LESS WORD ON THE STACK TWRPCB::SKIPG P3 ;IF NO-ONE WROTE ANYTHING, THEN COMPLAIN STOPCD .,STOP,NWA, ;++NO-ONE WROTE ANYTHING? PUSH P,U ;SAVE THE LDB, AND HRRZ U,NTRPCB ; GET BACK A POINTER TO THE PCB SKIPE U ;HERE JUST MAKE A LITTLE CHECK ON U'S VALIDITY CAILE P3,(P4) ; AND MAKE SURE NO ONE WROTE TOO FAR STOPCD .,STOP,SNS, ;++NTRPCB NOT SETUP?? ADDM P3,PCBCTR(U) ;NOW UPDATE THE COUNT AND AOS PCBCTR(U) ; DON'T FORGET ABOUT THE 'COUNT' BYTE POP P,U ;RESTORE THE LDB, POP P,T1 ; GET OUR RETURN ADDRESS, POP P,T2 ; AND GET BACK THE POINTER TO THE COUNT FIELD. IDPB P3,T2 ;STORE THE COUNT, JRST (T1) ; AND RETURN SUBTTL 3.3.3 SEND A COMPLETED NCL MESSAGE ;TSDPCB SEND A PCB OUT. THIS NUMBERS AND SENDS THE CURRENT PCB. ;CALL PUSHJ P,TSDPCB ;RETURN CPOPJ ;ALWAYS TSDPCB::PUSH P,U ;SAVE THE LDB (OR WHATEVER) HRRZ U,NTRPCB ;GET THE PCB POINTER JUMPE U,UPOPJ ; BUT RETURN QUICK IF THERE ISN'T ONE PUSHJ P,NETWRT## ;ASSIGN MESSAGE NUMBERS AND SEND THE MESSAGE HLLZS NTRPCB ;CLEAR POINTER TO PCB JRST UPOPJ ; AND RETURN SUBTTL 4.0 UTILITY ROUTINES AND INTERFACE TO UUOCON SUBTTL 4.1 PARSE THE NCL CONNECT MESSAGE FOR A TERMINAL ;TTYRPN ROUTINE TO READ THE "SPN" FIELD OF A CONNECT AND LOOK FOR OPR TERMINALS. ;CALL MOVEI U,LDB ;OF TTY BEING CONNECTED ; P1, P4 POINT TO THE "SPN" FIELD OF THE CONNECT (OBJ AND PID) ;RETURN CPOPJ ;WITH NDBOPR SET IF THIS WAS TERMINAL #0 TTYRPN: ;HERE TO READ THE "SPN" ON A MCR CONNECT ;SPN(OBJ) PUSHJ P,EBI2BI## ;GET THE OBJECT TYPE CAIE T1,OBJ.TY ;SEE IF IT'S A TERMINAL. PJRST XSKIP## ;DON'T LET TASKS BECOME "OPR'S" ;SPN(PID) PUSHJ P,EBI2BI## ;READ THE LINE NUMBER DPB T1,LDPRLN## ;SAVE IT FOR POSTERITY CAIN T1,0 ;IS IT THE OPR'S LINE HRRM U,NDBOPR(W) ;IF SO, REMEMBER THIS LDB POPJ P, ;TTYRAT ROUTINE TO READ THE "ATTRIBUTES" FROM A TERMINAL'S CONNECT MESSAGE ;CALL MOVEI U,LDB ;TERMINAL TO READ ATTRIBUTES FOR ; P1, P4 POINT TO THE "MML" BYTE OF THE CONNECT MESSAGE (AFTER DPN) ;RETURN CPOPJ ;AFTER SETTING/CLEARING THE PROPER BITS IN LDB ; ; AND FORCING A "GREETING" ; TTYRAT: ;HERE TO READ ATTRIBUTES OF A CONNECT ;MML PUSHJ P,XSKIP## ;SO FAR WE IGNORE MAX-MESSAGE-LENGTH... ;FEA(DCM) PUSHJ P,XSKIP## ;WE KNOW MORE ABOUT THE MODES THAN THE REMOTE... ;FEA(RLN) PUSHJ P,XSKIP## ;WE ASSUME A VARIABLE RECORD LENGTH ;FEA(DVT)=DTY PUSHJ P,EBI2BI## ;READ THE ATTRIBUTES MOVE T2,[XWD LRLADL##!LRLDSR##,LRRSHC##] ANDCAM T2,LDBREM##(U) ;CLEAR ALL "ATTRIBUTE" TYPE BITS MOVEI T2,LDRDSD## ;DATASET LINE FLAG ANDCAM T2,LDBDCH##(U) ;CLEAR OTHER "ATTRIBUTE" TYPE BITS MOVEI T3,APCHWD## ;ASSUME A HARDWIRED LINE ;FIRST, THE DCH ATTRIBUTES TRNE T1,DTY.MC ;MODEM CONTROL ON THIS LINE SKIPA T3,[APCDSD##] ;YES--GET DATASET APC CODE TDZA T2,T2 ;NOT A DATASET MOVEI T2,LDRDSD## ;MARK TTY AS A DATASET TTY IORM T2,LDBDCH##(U) ;SET APPROPRIATE DCH ATTRIBUTES/CHARACTERISTICS ;SECOND, THE REM ATTIBUTES TRNE T1,DTY.AD ;AUTO DIAL LINE (BELL 801) SKIPA T3,[APCADL##] ;YES--GET DIALOUT APC CODE TDZA T2,T2 ;NOT AUTO DIAL MOVSI T2,LRLADL## ;FLAG AS DIALOUT CAPABLE TRNE T1,DTY.SH ;CAN THIS LINE DO "SET HOST" TRO T2,LRRSHC## ;IF SO, THEN ENABLE THE COMMAND IORB T2,LDBREM##(U) ;SET APPROPRIATE REM ATTRIBUTES DPB T3,LDPAPC## ;SET ASYNC PORT CHARACTERISTIC MOVSI T2,LILCFE## ;ASSUME NOT CAPABLE OF AUTOBAUD ANDCAM T2,LDBISB##(U) ;BY DEFAULT TRNE T1,DTY.RA ;CORRECT? IORM T2,LDBISB##(U) ;NO--SET BIT FOR TOPABR ;CONTINUED ON NEXT PAGE ;CONTINUED FROM PREVIOUS PAGE ;FEA(DVU) PUSHJ P,EBI2BI ;GET THE "UNIT" TYPE CAILE T1,APCMAX## ;APC CODE OUT OF RANGE MOVEI T1,APCUNK## ;YES--ASSUME A HARD WIRED LINE REPEAT 0,< CAIE T1,APCNRT## ;CHECK FOR CONFUSING APC VALUES CAIN T1,APCCTM## ;DECNET LINE? MOVEI T1,APCUNK## ;YES--IGNORE DVU FIELD CAIN T1,APCLAT## ;CONFUSING LAT LINE? MOVEI T1,APCUNK## ;YES--IGNORE DVU FIELD FOR THIS, TOO > ;END REPEAT 0 CAIE T1,APCUNK## ;UNKNOWN? DPB T1,LDPAPC## ;NO--STORE APC FOR CURIOUS PROGRAMS ;FEA(DVV) PUSHJ P,EBI2BI ;GET THE "CONTROLLER" TYPE ; AND PITCH IT TOO ;FEA(DFT) PUSHJ P,EAS2SX## ;GET THE TTY TYPE NAME SKIPE T2,T1 ;MOVE FOR COMCON PUSHJ P,TTUTYP## ;SET FOR CURIOUS EYES JFCL ;DON'T CARE IF IT FAILS ;ALL DONE WITH TTY "ATTRIBUTES" PJRST SETCHP## ;MAKE SURE WE SEND STATUS SOON SUBTTL 4.2 MANIPULATE LDB'S ;MCRCHK ROUTINE TO ENSURE THAT A LDB IS USABLE ;CALL MOVEI U,LDB ; PUSHJ P,MCRCHK ;RETURN CPOPJ ;LDB NOT CONNECTED, (OR WORSE...) ; CPOPJ1 ;LOOKS OK AS FAR AS I CAN TELL ... MCRCHK::MOVE T1,LDBREM##(U) ;GET THE REMOTE BITS TLNN T1,LRLCON## ;IS THIS LDB "CONNECTED" POPJ P, ;IF NOT, DON'T USE IT (ERROR RETURN) LDB T2,LDPLNO## ;YES, GET PHYSICAL LINE NO. SUBI T2,NETOFS## ;RELOCATE TO A REMOTE LINE JUMPL T2,CPOPJ## ;NOR IN RANGE CAIGE T2,M.RTTY## ;CHECK LENGTH AOS (P) ;OK POPJ P, ;NO ERROR ;MCROKE ROUTINE TO TEST THE LDB AND SKIP RETURN IF LOCAL ; ECHOING SHOULD BE ALLOWED. ;LDB ADDRESS IN U. MCROKE: MOVE T1,LDBREM##(U) ;GET REMOTE STATION BITS TLNE T1,LRLTTW##!LRLTTO##!LRLATO## ;THIS TERMINAL WAITING? POPJ P, ; THEN DONT SEND EPM. MOVE T1,LDBBY2##(U) ;NO, GET MISC. TERMINAL BITS SKIPL LDBBKB##(U) ;IN USER DEFINED BREAK SET MODE TLNE T1,L2LDEL## ;NO, ARE WE IN RUBOUT SEQUENCE? POPJ P, ;YES, DONT RETURN EPM. SKIPGE T1,LDBDCH##(U) ;GET STATUS BITS, SKIP IF OUTPUT ACTIVE TLNE T1,LDLNEC##!LDLLCP##!LDLCNE##!LDLBKA##!LDLIMI## ;PROGRAM CONTROL? POPJ P, ;YES SKIPN LDBIST##(U) ;IF DOING FANCY TWO-CHARACTER INPUT, SKIPGE LDBCHM##(U) ;OR IF FANCY MAPPING POPJ P, ;CAN'T DO IT EXTERN LMLNDS ;FLAG BIT REFERENCED MOVE T1,LDBBYT##(U) ;GET THE DEFERRED ECHO BITS TRNE T1,L1RDEM## ;IF NOT DEFERRED ECHO, TRNE T1,L1RDEL## ; OR IF WAITING FOR A LINE TLNE T1,L1LUNR## ;AND NOT DOING UNREAD POPJ P, ;NO--FAIL IF NOT WAITING FOR A LINE SKIPL LDBATR##(U) ;GO WITH SUCCESS IF 7-BIT EXTERN LAL8BT ;(NOTE THE BIT WE TESTED) JRST CPOPJ1## ;YES--WE CAN DO IT LDB T1,LDPNVR## ;GET REMOTE'S VERSION JUMPE T1,CPOPJ## ;DON'T DO IT IF OLD 87 MOVSI T1,LDL8BI## ;8-BIT TTY, ARE WE IN 8-BIT I/O MODE? TDNE T1,LDBDCH##(U) ;TEST AOS (P) ;IF YES, WE CAN LET THE FE DO THE ECHO POPJ P, ;RETURN APPROPRIATELY ;TRM.UP ROUTINE TO DECLARE AN LDB AS "ON LINE". ;CALL MOVEI U,LDB ;WITH DLA, SLA SET UP ; PUSHJ P,TRM.UP ;RETURN CPOPJ ;WITH LDB READY TO MASH BITS TRM.UP::LDB T1,LDPSLA## ;GET OUR LAT ADDRESS MOVEI T2,LAT.OK ; AND SET OUR STATE DPB T2,LATSTA## ; TO BE "OK" MOVSI T1,LRLCON## ;GET THE "CONNECTED" BIT IORB T1,LDBREM##(U) ; AND SET IT. LDB IS OFFICIALLY "ON LINE" MOVSI T1,L1LOFL## ;SCNSER OFF-LINE BIT ANDCAM T1,LDBOFL##(U) ;CLEAR NOW, IRMA WON'T BE AROUND FOR AWHILE POPJ P, ;NMCWAK ROUTINE TO TRY TO WAKE A JOB WAITING FOR A TERMINAL CONNECT. ;CALL MOVEI U,LDB ; PUSHJ P,NMCWAK ;RETURN CPOPJ ;ALWAYS. NMCWAK: LDB T1,LDPJOB## ;GET THE NUMBER OF JOB WAITING JUMPE T1,CPOPJ## ;IF NONE, DON'T WAKE JOB ZERO PUSHJ P,EWAKE## ;WAKE THE JOB SETZ T1, ;GET A ZERO, DPB T1,LDPJOB## ; AND CLEAR THE JOB NUMBER FIELD POPJ P, ;ALL DONE ;MCRGET ROUTINE TO GET AN ANF TERMINAL LDB ;CALL PUSHJ P,MCRGET ;RETURN CPOPJ IF FAILURE ; CPOPJ1 WITH U/LDB ADDRESS MCRGET: MOVSI T1,LTLANF## ;FLAG NEW ANF-10 TERMINAL MOVEI T3,MCRDSP ;ANF MCR ISR DISPATCH VECTOR PUSHJ P,GETLDB## ;GET A FREE LDB POPJ P, ;CAN'T, FAILURE RETURN HLRZ T1,NDBNNM(W) ;GET THE NODE NUMBER DPB T1,LDPRNN## ;ASSIGN THE LDB TO THE REMOTE NODE HRRZ T1,NDBNVR(W) ;GET REMOTE'S NCL VERSION DPB T1,LDPNVR## ;SAVE IT FOR LATER MOVSI T3,LIL7BT## ;DUMB FE BIT SKIPN T1 ;IF OLD NCL VERSION, IORM T3,LDBISB##(U) ;RESTRICT TO 7-BIT MOVEI T1,MCRRTQ ;ANF MCR QUEUE HEADER HRLZM T1,LDBQUH##(U) ;STORE FOR SCNSER'S TOPOKE/TOTAKE JRST CPOPJ1## ;SUCCESS RETURN ;MCRDET ROUTINE TO DETACH A TERMINAL FROM THE JOB ;CALL MOVEI U,LDB ; PUSHJ P,MCRDET ;RETURN CPOPJ MCRDET: PUSHJ P,SAVJW ;SAVE J,W MOVEI T1,IONND% ;"NODE DOWN" I/O ERROR STATUS PJRST DETLDB## ;DETACH THE LDB/DDB ;MCRFRE ROUTINE TO FREE AN ANF TERMINAL'S ASSOCIATED LAT & LDB ;CALL MOVEI U,LDB ; PUSHJ P,MCRFRE ;RETURN CPOPJ MCRFRE::NTDBUG LDB T1,LDPSLA## ;DOES THIS LDB HAVE A LAT SLOT ASSIGNED? JUMPE T1,MCRFR1 ;NO, DON'T TOUCH NDBOPR OR NETLAT SETZB T1,NETLAT##(T1) ;FREE THE LAT SLOT DPB T1,LDPSLA## ;FREE THE LAT POINTER LDB T2,LDPRLN## ;GET THE REMOTE LINE NUMBER JUMPN T2,MCRFR1 ;JUMP IF THIS IS NOT AN OPR LINE LDB T1,LDPRNN## ;GET THE NUMBER OF THE NODE PUSHJ P,SRCNDB## ;GET "W" POINTING TO THE NDB CAIA ;IF NODE GONE, THEN DON'T BLAST MEMORY HLLZS NDBOPR(W) ;CLEAR THE OPR POINTER MCRFR1: SETZM LDBREM##(U) ;CLEAR LRLCON (ET AL) PJRST FRELDB## ;RETURN LDB TO SCNSER'S FREE POOL ;NETOP. UUO ;NETDIA - NETOP. function to return node and port ID for a TTY ; ;Call: (in section 1 already) ; ; U/ LDB of terminal ; M/ Address of user's NETOP. arg list ;Return: ; ECDX? depending on error ; RETSKP node name stored in string block pointed to by user's arg list ; ;Uses P1,P2 (already saved by higher routine), T1-T4, M NETDIA::MOVE P1,M ;SAVE ARG LIST POINTER PUSHJ P,GTNTS1## ;GET NODE#,,LINE# IN T1 JRST NOPDNC## ;NOT CONNECTED MOVE P2,T1 ;SAVE IT EXCTUX ;DOES HE WANT NODE NAME? JRST NTDIA2 ;NO HLRZ T1,P2 ;GET NODE NUMBER NETDBL ;NEXT STUFF IS INTERLOCKED PUSHJ P,SRCNDB## ;FIND NDB TDZA T1,T1 ;CLEAR THE NAME IF CAN'T FIND IT MOVE T1,NDBSN2(W) ;GET THE REMOTE'S NODE NAME NETDBU ;GIVE BACK THE INTERLOCK JUMPN T1,NTDIA1 ;IF THERE IS A NAME WE'RE OK HLRZ T1,P2 ;ELSE, GET NUMBER AGAIN PUSHJ P,CVTSBT## ;AND USE SIXBIT VERSION OF THAT NTDIA1: PUSHJ P,PU6STB## ;PUT SIXBIT INTO STRING BLOCK JRST NOPADC## ;CAN'T NTDIA2: EXCTUX ;DOES THE GUY WANT PORT NAME? JRST CPOPJ1## ;NO, DONE HRRZ T1,P2 ;ISOLATE LINE NUMBER PUSHJ P,CVTSBT## ;CONVERT TO SIXBIT HRRI T1,'TTY' ;STUFF DEVICE NAME MOVSS T1 ;MAKE 'TTYNNN' PUSHJ P,PU6STB## ;STORE SIXBIT NAME INTO STRING BLOCK JRST NOPADC## ;NO LUCK JRST CPOPJ1## ;DONE SUBTTL 4.3 CONNECT TO REMOTE TERMINALS ;MCRCNT ROUTINE TO SEND A CONNECT TO A REMOTE TERMINAL. ;CALL MOVE T1,[XWD NODE#,LINE#] ; PUSHJ P,MCRCNT ;RETURN CPOPJ ;CONNECT REJECTED, NO CORE, NO LDB'S, ... ; CPOPJ1 ;CONNECTED. U := LDB THAT WAS USED. ;NOTE! THIS ROUTINE WILL SEND A CONNECT EVEN IF THE TERMINAL IS ALREADY ; CONNECTED. USE ASGTTY IF YOU JUST WANT THE LINE. MCRCNT::PUSHJ P,SAVE3## ;WE CLOBBER THESE WHEN SENDING THE MESSAGE PUSHJ P,SAVJW## ;THESE WHEN WE LOOK AT THE NDB PUSH P,T1 ;SAVE THE ARGUMENT FOR LATER. HLRZ T1,T1 ;GET THE NODE NUMBER PUSHJ P,SRCNDB## ; AND TRY TO FIND THE NDB. JRST TPOPJ## ; GIVE ERROR RETURN IF NO NDB PUSHJ P,MCRGET ;GET A NEW ANF/MCR LDB JRST TPOPJ## ; GIVE ERROR RETURN IF NONE AVAILABLE SETZ T1, ;NO TIMING UNTIL CONNECT CONFIRM PUSHJ P,SCNADT## ;TELL SCNSER MOVE T1,U ;LDB ADDRESS FOR GETSLA TLO T1,LAT.TY ;FLAG THAT THIS IS AN LDB-STYLE ADDRESS MOVEI T2,LAT.CC ;WHOSE INITIAL STATE IS CONNECT-CONFIRM PUSHJ P,GETSLA## ;TRY TO ASSIGN AN SLA JRST MCRCN8 ; NO LUCK. CLEAN UP AND FAIL DPB T1,LDPSLA## ;REMEMBER THE LAT ADDRESS HRRZ T1,(P) ;GET THE NUMBER OF THE LINE TO CONNECT TO DPB T1,LDPRLN## ; AND SAVE IT SO THAT MCRXCN CAN SEND IT SKIPN J,.CPJOB## ;LOAD OUR JOB NUMBER STOPCD .,STOP,MCRJIZ ;++ JOBNUMBER IS ZERO DPB J,LDPJOB## ;STORE OUR JOB NUMBER (FOR NMCWAK) PUSHJ P,MCRXCN ;ATTEMPT TO SEND A CONNECT. JRST MCRCN8 ;NO CORE. CLEAN UP AND RETURN ;CONTINUED ON NEXT PAGE ;CONTINUED FROM PREVIOUS PAGE ;HERE TO WAIT FOR A CONNECT CONFIRM/REJECT. MCRCN2: MOVE J,.CPJOB## ;GET OUR JOB NUMBER BACK MOVEI T1,EV.NTC ;GET THE TERMINAL CONNECT EVENT WAIT CODE PUSHJ P,[NTSAVE ;RETURN THE "NT" RESOURCE, AND SLEEP S0PSHJ ESLEEP## ; TILL REJECT/CONFIRM COMES POPJ P,] ;AND CONTINUE IN THE PROPER SECTION ;RDH LDB J,LDPJOB## ;WE WOKE UP. GET LDB'S JOB NUMBER ;RDH CAME J,.CPJOB## ;DOES THE LDB STILL BELONG TO US? ;RDH JRST TPOPJ## ;NO, THEN MUST HAVE RECYCLED! LDB T1,LDPSLA## ;SEE IF LAT STILL ASSIGNED JUMPE T1,TPOPJ## ;IF LAT HAS BEEN CLEARED, CONNECT WAS REJECTED. LDB T2,LATSTA## ;SEE WHAT STATE WE'RE IN CAIN T2,LAT.OK ;IF WE'RE "OK" THEN CONNECT SUCCEEDED JRST MCRCN4 ; AND THEN WE CAN GIVE GOOD RETURN CAIN T2,LAT.DC ;IT IS POSSIBLE FOR SOMEONE TO DISCONNECT JRST TPOPJ## ; THE TERMINAL WE JUST CONNECTED BEFORE WE ; WAKE UP. IF SOME ONE DID SNEAK IN, ; JUST GIVE UP GRACEFULLY. IFN PARANOID&P$LAT,< CAIE T2,LAT.CC ;THE ONLY OTHER LEGAL STATE IS CONFIRM WAIT STOPCD .,STOP,MCRILS, ;++ ILLEGAL STATE > JRST MCRCN2 ;LOOP UNTIL CONNECT/DISCONNECT COMES IN MCRCN4: MOVEI T1,M.AIDL## ;GET MAXIMUM IDLE TIME BEFORE AUTO-DISCONNECT PUSHJ P,SCNADT## ;START THE TIMER GOING JRST TPOPJ1## ;GIVE SUCCESS RETURN ;CAN'T CONNECT, NO CORE. MCRCN8: PUSHJ P,MCRFRE ;FREE UP THE LAT SLOT AND THE LDB JRST TPOPJ## ;FAIL RETURN TO CALLER SUBTTL 4.4 INTERFACE TO ASSIGN COMMAND ;ASGTTY ROUTINE TO HELP THE ASSIGN FUNCTION OF THE NETWORK ASSIGN COMMNADS ;CALL MOVE T1,[XWD NODE#,LINE#] ; PUSHJ P,ASGTTY ;RETURN CPOPJ ;TERMINAL NOT AVAILABLE ; CPOPJ1 ;T1 := SIXBIT /TTYNNN/ ;NOTE: THIS ROUTINE SENDS A CONNECT IF NECESSARY. ; THIS ROUTINE ALSO PRESERVS M & U ASGTTY::SE1ENT ;ENTER SECTION 1 PUSH P,U ;SAVE THE LDB IN CASE COMCON CALLED PUSH P,T1 ;SAVE THE "XWD NODE,LINE" PUSH P,M ;SAVE M OVER CALL TO SCREWY GTXTN TLO M,FLMCOM ;SET SIGN BIT TO PROPERLY CONFUSE GTXTN PUSHJ P,GTXTN## ;SEE IF LINE IS ALREADY CONNECTED. JRST ASGTT1 ;IF NOT. THEN GO TRY TO CONNECT IT POP P,M ;IT IS CONNECTED. T1 := 'TTYNNN' POP P,(P) ;CLEAN UP THE STACK JRST UPOPJ1## ;AND GIVE A GOOD RETURN ASGTT1: POP P,M ;WE WON'T CLOBBER M NOW POP P,T1 ;GET OUR ARGUMENTS BACK PUSHJ P,MCRCNT ;TRY TO CONNECT THE TERMINAL JRST UPOPJ## ;FAILURE... GIVE BAD RETURN LDB T1,LDPLNO## ;GET THE LINE NUMBER S0PSHJ CVTSBT## ;CONVERT IT TO SIXBIT HLRZ T1,T1 ;PUT IT IN THE RIGHT HALV HRLI T1,'TTY' ;PUT IN THE GENERIC "TTY" JRST UPOPJ1## ;GIVE A GOOD RETURN SUBTTL 4.5 DISCONNECT/RECONNECT TERMINALS (SET HOST) HOST.U::SE1ENT ;ENTER SECTION 1 PUSHJ P,TTYFNU## ;SET UP U & F JUMPE U,ECOD0## ;0 IN U IS AN ERROR TO US MOVE T1,LDBDCH##(U) ;GET THE CHARACTERISTICS TRNE T1,LDRPTY## ;PTY'S CAN'T SET HOST JRST ECOD0## ; WITHOUT CONFUSING THE HELL OUT OF BATCON HRR M,T2 ;GET THE LOCATION OF THE ARGUMENT PUSHJ P,GETWDU## ;GET THE NODE NUMBER PUSHJ P,SAVE4## ;SAVE THE P'S NETDBJ ;INTERLOCK THE REST OF THIS PUSHJ P,SRCNDB## ;GO FIND THE NODE JRST ECOD0## ;IF NO NODE, GIVE THE ERROR RETURN CAIN W,NETNDB## ;SEE IF HE'S TRYING TO SET HOST HERE RETSKP ; IF SO, JUST GIVE A GOOD RETURN LDB T1,NETCNF## ;SEE IF THE NODE HAS A MCR JUMPE T1,ECOD0## ; IF NO MCR, DON'T LET HIM SET HOST SKIPL LDBTTW##(U) ;IF THIS IS A NON-ANF TERMINAL PJRST VTMHST## ; CALL NETVTM TO DO THE WORK MOVE T1,LDBREM##(U) ;GET THE REMOTE BITS, AND TRNN T1,LRRSHC## ; MAKE SURE THIS STATION ISN'T A 72 JRST ECOD0## ;GIVE ERROR IF STATION DOESN'T ALLOW SET HOST PJRST HOSTDT ;GO DETACH THE GUY AND DO THE SET HOST HOST.A::SE1ENT ;DO THIS IN SECTION 1 MOVE T2,LDBDCH##(U) ;GET THE CHARACTERISTICS TRNE T2,LDRPTY## ;IF THIS IS A PTY, GIVE HIM AN ERROR JRST [MOVEI T1,[ASCIZ /PTYs cannot be switched by SET HOST./] S0JRST ERRMES##] ;SINCE JOBSTS WON'T WORK OVER THE NET MOVE S,T1 ;SAVE NAME JSP T2,SAVCTX## ;RUN THE REST OF THIS AS A JOB MOVE T1,S ;RESTORE NAME NETDBJ ;GET THE NETSER INTERLOCK PUSHJ P,SRCNDB## ;LOOKUP UP THE NDB JRST [MOVE T1,NRTUNN## ;GET THE "NO SUCH NODE" ERROR MSG S0JRST ERRMES##] ; AND GO PRINT IT CAIN W,NETNDB## ;SEE IF IT'S SET HOST SELF JRST [MOVEI T1,[ASCIZ /% Already at node /] S0PSHJ CONMES## ;PRINT THE FIRST PART S0PSHJ TYPNOD## ;PRINT THE NODE NAME S0JRST PCRLF##] ;FINISH OFF THE MESSAGE AND EXIT LDB T1,NETCNF## ;SEE IF THE NODE HAS A MCR JUMPE T1,[MOVEI T1,[ASCIZ /Node does not support remote terminals./] S0JRST ERRMES##] ;PRINT THE ERROR SKIPL LDBTTW##(U) ;IF THIS IS A NON-ANF TERMINAL PJRST VTMHST## ; CALL NETVTM TO DO THE WORK MOVE T1,LDBREM##(U) ;GET THE REMOTE BITS, AND TRNN T1,LRRSHC## ; SEE IF THIS STATION HAS SET HOST CAPABILITY MCRCSH::JRST [JUMPGE M,ECOD0## ;SETUUO ERROR MOVEI T1,[ASCIZ /Your station does not support SET HOST./] S0JRST ERRMES##] ;PRINT THE MESSAGE AND EXIT HOSTDT: PUSHJ P,TSETBI## ;CLEAR OUT THE INPUT BUFFER PUSHJ P,TSETBO## ; AND THE OUTPUT BUFFER MOVE T1,LDBREM##(U) ;NOW, SINCE I CAN'T SEEM TO FATHOM THE TLNN T1,LRLCON ; OBSCURITIES OF SAVCTX, MAKE SURE WE ARE JRST ECOD0## ; STILL "CONNECTED". (SHOULDN'T HAPPEN BUT) MOVEI P4,RSN.RC ;BUILD THE ARGUMENTS FOR TRMXDC HLL P4,NDBNNM(W) ;ARG IS "XWD NODE,REASON" REASON = RECONNECT LDB T1,LDPRNN## ;GET THE NODE NUMBER OF THIS TERMINALS STATION PUSHJ P,SRCNDB## ;FIND HIS NDB SO WE CAN SEND HIM A DISCONNECT STOPCD .,STOP,MCRNSN, ;++ NO SOURCE NODE FOR TERMINAL MOVE T1,P4 ;GET THE ARGUMENT WE JUST CONSTRUCTED PJRST TRMXDC ; AND GO SEND THE DISCONNECT/RECONNECT SUBTTL 4.6 TIMING LOGIC RELATED TO THE AUTO-DISCONNECT FEATURE ;NMCSEC ROUTINE TO DO DISCONNECT FOR NETWORK DATASETS. ; THIS ROUTINE DISCONNECTS (AND HANGS UP) ANY LINE THAT HAS LOST ; ITS CARRIER AND IS A NETWORK DATASET. ;CALLED FROM NETSER ONCE/SECOND NMCSEC::SE1ENT ;ENTER SECTION 1 PUSH P,P4 ;WE USE P4 FOR AN AOBJN POINTER TO THE LDB'S MOVE P4,NETRTY## ;GET AOBJN POINTER TO NETWORK TERMINALS'S NMCSE1: MOVE U,LINTAB##(P4) ;GET ADDRESS OF NEXT LDB TO CHECK. SKIPL LDBTTW##(U) ;IF THIS IS A NON-ANF TERMINAL JRST NMCSE8 ;THEN NO ANF ONCE/SECOND STUFF SKIPE T2,LDBREM##(U) ;GET THE REMOTE'S ATTRIBUTES/ET AL TLNN T2,LRLCON## ;STILL CONNECTED? JRST NMCSE8 ;DUD TTY, SKIP IT CAMN U,DIALDB## ;IS THIS LDB TRYING TO DIAL OUT? JRST NMCSE8 ;YES, LEAVE IT ALONE TLNE T2,LRLTMO## ;DID MCRDIS REQUEST A DISCONNECT? JRST NMCSE2 ;YES, GIVE IT A TRY MOVE T1,LDBDCH##(U) ;GET BITS WE CARE ABOUT TRNE T1,LDRDSD## ;NO, IS IT A DATASET? TLNE T2,LRLDSR## ;OR IS DATASET STILL RUNNING (DTR/CARRIER)? JRST NMCSE8 ;YES, DON'T DISCONNECT IT NMCSE2: PUSHJ P,NMCXDC ;NO, TRY TO DISCONNECT IT JFCL ;WE'LL TRY AGAIN LATER NMCSE8: AOBJN P4,NMCSE1 ;LOOP OVER ALL REMOTE TERMINALS POP P,P4 ;RESTORE P4 POPJ P, ;ALL DONE. BACK TO NETSCN NMCXDC: LDB T1,LDPRNN## ;GET NUMBER OF NODE THAT OWNS THIS TERMINAL PUSHJ P,SRCNDB## ;USE IT TO SET UP W AS A POINTER TO THE NDB STOPCD .,STOP,MCRNWA, ;++ MCRNWD SHOULD HAVE DISCONNECTED US MOVEI T1,RSN.OK ;NO PARTICULAR REASON FOR THE DISCONNECT. PJRST TRMXDC ;SEND THE DISCONNECT MESSAGE & RETURN SUBTTL 4.7 ONCE/JIFFY PROCESSING ;MCRJIF ROUTINE TO START NETWORK TERMINALS ;CALL PUSHJ P,MCRJIF ;RET CPOPJ MCRJIF::MOVEI T1,MCRRTQ## ;GET THE QUEUE HEADER PUSHJ P,TOTAKE## ;GET U := TERMINAL NEEDING SERVICE POPJ P, ;IF NONE, THEN ALL DONE PUSHJ P,SCNMCR ;SEE WHAT MESSAGES NEED BE SENT PJRST TOPOKE## ;IF NO CORE, RE-QUEUE THIS LDB AND EXIT JRST MCRJIF ;GO SEE IF ANY MORE TERMINALS TO START SUBTTL 4.8 TABLES ;TABLES FOR FILL. THE TABLE ENTRIES ARE FOR BS, TAB, LF, VT, ; FF AND CR FROM LEFT TO RIGHT, AND FILL 0-3 FROM TOP ; TO BOTTOM. THE VALUE OF THE ENTRY IS THE NUMBER OF FILL ; CHARACTERS. THIS IS CONVERTED TO MILLISECONDS BY DIVIDING ; BY THE TRANSMIT SPEED OVER 1000. SOMEDAY MAYBE THE USER ; WILL BE ABLE TO SET THE TIMES DIRECTLY, BUT THIS METHOD ; IS USED NOW FOR COMPATABLILTY WITH LOCAL FILLING, WHICH SENDS ; RUBOUTS INSTEAD OF USING TIMEING. FILTAB: POINT 6,[BYTE (6) 0,0,0,0,00,0] ;CLASS 0 POINT 6,[BYTE (6) 2,2,2,2,14,2] ;CLASS 1 POINT 6,[BYTE (6) 6,0,6,6,25,4] ;CLASS 2 POINT 6,[BYTE (6) 6,2,6,6,25,4] ;CLASS 3 SUBTTL 4.8 VARIABLES $LOW NTRPCB: EXP 0 ;CELL THAT CONTAINS A POINTER TO THE CURRENT ; PCB IN USE WHEN CONSTRUCTING A "MCR" MSG. ; BECAUSE ALL THIS CODE RUNS UNDER THE NETSER ; INTERLOCK WE CAN USE A GLOBAL CELL WITH OUT ; FEAR OF RACES. $HIGH XLIST ;DON'T LIST THE LITERALS $LIT LIST NMCEND::PRGEND TITLE NETPLT - NETWORK PLOTTER ROUTINES - V001 SUBTTL JAC/ 21 SEP 81 SEARCH F,S,NETPRM $RELOC $HIGH XP VNETPL,001 ;PUT VERSION NUMBER IN GLOB AND LOADER MAP COMMENT \ Digital no longer supports ANF remote plotters. The NETPLT module is included only as a convenience for those customers who might wish to try it. \ NETPLT::ENTRY NETPLT REPEAT 0,< CCS Edit History ---------------- Edit Date Who Comment ---- ---- --- ------- The following updates were made to keep NETPLT in line with NETLPT. They are not actual CCS edits, but have been assigned nominal CCS edit numbers for convenience. 001) 840808 AGM Define global symbol NPLTCI, used by COMNET. 002) 840808 AGM Clean up code and comments. No functional changes. 003) 840808 AGM Updates to error recovery. 004) 840808 AGM Decrement data request count at end of first time code. ------------------------> SUBTTL 1.0 PLT SPECIFIC SYMBOL DEFINITIONS SUBTTL 2.0 INTERFACE TO UUOCON. (DEVSER DISPATCH VECTOR) JRST NTDONL## ;(-5) CHECK IF DEVICE IS ON LINE JRST ECOD2## ;(-4) DEVOP UUO JRST REGSIZ## ;(-3) BUFFER SIZE JRST CPOPJ## ;(-2) INITIALIZATION JRST CPOPJ1## ;(-1) HUNG DEVICE (IGNORE. REMOTE WORRYS) NDEVPL::JRST NTDREL## ;RELEASE JRST P.CLOS ;CLOSE OUTPUT JRST P.OUT ;OUTPUT JRST NTDILI## ;ILLEGAL INPUT (RETURN INTERLOCK) SUBTTL 2.1 OUT UUO. P.OUT: ;HERE FROM UUOCON TO OUTPUT A BUFFER PUSHJ P,SAVE3## ;WE USE P1, NETSER USER P2, P3 FOR PCB'S MOVSI S,IOSUSO ;CLEAR THE "UUOCON STOPED OUTPUT" ANDCAB S,DEVIOS(F) ; SINCE IT JUST TRIED TO START IT AGAIN P.LOOP: PUSHJ P,NTDSET## ;SET UP W, S AND CHECK IOSCON MOVSI S,IO ;GET AND SET 'OUTPUT" IORB S,DEVIOS(F) ; JUST TO KEEP WSYNC HAPPY. PUSHJ P,NTDONL## ;CHECK IOSERR TO SEE IF STILL ONLINE JRST P.HUNG ;IF PLT IS OFFLINE, GO PLAY DEAD. TLNE S,IOBEG ;IS THIS THE FIRST OUT?? JRST P.FRST ; IF SO, GO DO SPECIAL CODE. MOVEI T1,6 ;TRY FOR SIXBIT DATA TRNN S,16 ; IS IT SIX OR SEVEN BIT ? MOVEI T1,7 ;THIS TIME IT IS SEVEN PUSHJ P,NTDSOB## ;SET UP THE OUTPUT BUFFER JRST P.DONE ;NO MORE DATA. RETURN TO UUOCON. SKIPN DEVAXO+1(F) ;FOR PLT'S MAKE SURE THAT WE DON'T JRST P.LOO1 ; SEND ZERO LENGTH BUFFERS PUSHJ P,NTDCDQ## ;SEE IF ANY DATA REQUESTS PENDING JRST P.WAIT ;NONE AVAILABLE. WE MUST WAIT. MOVEI T1,PCV.NC ;WE DON'T WANT LINE-PRINTER COMPRESSION MOVEI T2,DC.DAR ; NOT-INTERRUPT, DATA WITH E-O-R PUSHJ P,NTDXMT## ;SEND ANOTHER PCB'S WORTH OF DATA PUSHJ P,[JUMPN T1,NTDSTP## ;WE SHOULD NEVER GET AN IO-ERROR POP P,(P) ;CLEAN OFF THE RETURN ADDRESS (UGLY) PUSHJ P,NETSLP## ;PAUSE FOR FREECORE JRST P.LOOP] ; AND TRY AGAIN PUSHJ P,NTDDDQ## ;UPDATE THE DATA REQUEST COUNT SKIPN DEVAXO+1(F) ;ARE THERE ZERO BYTES LEFT?? P.LOO1: PUSHJ P,NTDAOB## ;IF SO, THEN GIVE USER BACK THE BUFFER JRST P.LOOP ;LOOP UNTIL ALL DATA IS OUT SUBTTL 2.2 FIRST TIME ONLY CODE (OUTPUT ) P.FRST: ;HERE ON FIRST OUT FROM UUOCON SETZM DEVAXO(F) ;CLEAR ANY DATA NOT OUTPUT LAST TIME PUSHJ P,NTDCDQ## ;DO WE HAVE A DATA REQUEST FOR THIS? JRST P.WAIT ; IF NOT, WE MUST WAIT FOR ONE MOVEI T1,^D16 ;WE WANT A 16 WORD DATA MESSAGE PUSHJ P,NTDHDR## ; SET UP P2 := POINTER, P3 := COUNT JRST [PUSHJ P,NETSLP## ;IF WE CAN'T GET THE MEMORY, SLEEP JRST P.LOOP] ;NOW GO TRY AGAIN MOVE T3,[POINT 8,[BYTE (8)3,DC.DAR,40,40]] ;LENGTH & MESSAGE TO SEND (REMEMBER ; COMPRESSION) MOVEI T4,4 ;WE WILL SEND 4 BYTES (INCLUDING LENGTH) P.FRS2: ILDB T1,T3 ;GET THE NEXT BYTE PUSHJ P,DPBBIN## ; AND PUT IT IN THE MESSAGE SOJG T4,P.FRS2 ;LOOP TILL ALL BYTES IN MESSAGE. ADDB P3,PCBCTR(U) ;UPDATE THE COUNT IN FIRST SEGMENT. SETZB P3,PCBCT2(U) ;INDICATE THAT THERE IS NO SECOND SEG. MOVEI T1,PCV.NC ;NO LPT COMPRESSION PUSHJ P,NTDWRT## ;SEND THE MESSAGE. PUSHJ P,NTDDDQ## ;DECREMENT THE DATA REQUEST COUNT P.FRS3: ;HERE WHEN ALL "FIRST TIME" STUFF DONE. MOVSI S,IOBEG!IOSREL ;GET AND CLEAR "RELEASED" ANDCAB S,DEVIOS(F) ; AND "FIRST TIME" BIT JRST P.LOOP ;GO BACK AND TRY TO SEND USER DATA. SUBTTL 2.3 EXCEPTION HANDLING. P.DONE: ;HERE IF ALL USERS BUFFERS SENT POPJ P, ;I THINK UUOCON WILL DO THE REST P.WAIT: ;HERE WHEN NO DATA REQUESTS. PUSHJ P,NTDWTO## ;WAIT FOR DRQ. POPJ P, ;RETURN TO UUOCON IF NON-BLOCKING. JRST P.LOOP ;TRY FOR MORE DATA-OUT. ;P.LOOP WILL RELOAD "S" AND "W" P.HUNG: ;HERE WHEN IOSERR IS SET. TLNN S,IOSCON ;ARE WE STILL CONNECTED JRST P.GONE ; NO. TELL USER DEVICE IS GONE TLNE S,IOSERR ;IS THE PLT ON LINE YET?? PUSHJ P,NTDHNG## ;SET OFF-LINE AND TELL THE OPERATOR JRST P.LOOP ;TRY TO SEND SOME MORE DATA. P.GONE: ;HERE WHEN PLT IS DISCONNECTED. MOVEI S,IODERR!IODTER ;TWO BITS FOR UUOCON TO CONTEMPLATE IORB S,DEVIOS(F) ;SET THEM IN DEVIOS MOVEI T1,IONND% ;?????? DPB T1,PDVESE## ;?????? POPJ P, ;BACK TO UUOCON SUBTTL 2.4 CLOSE UUO AND LAST TIME ONLY CODE (OUTPUT ) ; MAY HAVE TO ADD SOME FLAGS ETC HERE IO IN PROCESS OF CLOSE P.CLOS: PUSHJ P,SAVE3## ;GET SOME P'S PUSHJ P,OUT## ;FINNISH OFF BUFFERS P.LAST: ;HERE FROM CLOSE UUO P.LAS1: MOVEI T1,^D16 ;WE WANT A 16 WORD DATA MESSAGE PUSHJ P,NTDHDR## ; SET UP P2 := POINTER, P3 := COUNT JRST [PUSHJ P,NETSLP## ;IF WE CAN'T GET THE MEMORY, SLEEP PUSHJ P,NTDSET## ;RELOAD W AND S (THEY MAY HAVE CHANGED) TLNN S,IOSCON ;ARE WE STILL CONNECTED ?? JRST P.LAS3 ; IF NOT, JUST PRETEND WE SEND THE MSG JRST P.LAS1] ;IF NODE STILL THERE, TRY AGAIN MOVE T3,[POINT 8,[BYTE (8)3,DC.DAR,40,40]] ;LENGTH & MESSAGE TO SEND (REMEMBER ; COMPRESSION) MOVEI T4,4 ;WE WILL SEND 4 BYTES (INCLUDING LENGTH) P.LAS2: ILDB T1,T3 ;GET THE NEXT BYTE PUSHJ P,DPBBIN## ; AND PUT IT IN THE MESSAGE SOJG T4,P.LAS2 ;LOOP TILL ALL BYTES IN MESSAGE. ADDB P3,PCBCTR(U) ;UPDATE THE COUNT IN FIRST SEGMENT. SETZB P3,PCBCT2(U) ;INDICATE THAT THERE IS NO SECOND SEG. MOVEI T1,PCV.NC ;NO LPT COMPRESSION PUSHJ P,NTDWRT## ;SEND THE MESSAGE. P.LAS3: ;HERE WHEN ALL "LAST TIME" STUFF DONE JRST NTDCLO## ;CLOSE OUTPUT SUBTTL 3.0 INTERFACE TO NETSER (NETWORK DISPATCH VECTOR) JRST NTDNWD## ;USE DEFAULT "NODE WENT DOWN" HANDLER JRST NTDDSC## ;USE DEFAULT DISCONNECT HANDLER JRST NTDCNC## ;USE DEFAULT CONNECT CONFIRM HANDLER JRST NTDSTP## ;++ SHOULD NEVER GET CONNECT INITIATE ENTRY JRST NTDRDQ## ;USE STANDARD DATA-REQUEST HANDLER PLTNDP::JRST NTDILD## ;USE CANNED INTERRUPT LEVEL DISPATCH JRST CPOPJ## ;WE DON'T GET ANY DATA JRST CPOPJ## ; ESPECIALY DATA WITH E-O-R... JRST P.STAT ;WE DO GET STATUS MESSAGES JRST CPOPJ## ;WE DONT GET CONTROL JRST CPOPJ## ;OR UID JRST CPOPJ## ;OR FILE-SPEC'S ;DUMMY CONNECT INIT PROCESSOR NPLTCI==:NJNKCI## ;A JUNK CI SUBTTL 3.1 INPUT STATUS MESSAGE PROCESSING P.STAT: ;HERE FROM NETSER WITH A STATUS MESSAGE. ;STC PUSHJ P,EBI2BI## ;GET TYPE OF STATUS MESSAGE JUMPN T1,CPOPJ## ; (WE ONLY RESPECT TYPE 0) ;STD PUSHJ P,EBI2BI## ;GET THE DEVICE BITS. HRRM T1,DEVSTS(F) ;STORE THE STATUS FOR UUOLEVEL TO WATCH AOS (P) ;WE ARE NOW SATISFIED THAT MSG IS GOOD. MOVE T2,[IORB S,DEVIOS(F)] ;ASSUME THAT WE ARE OFFLINE. TRNN T1,SLP.OL ; BUT CHANGE OUR MINDS IF WE MOVE T2,[ANDCAB S,DEVIOS(F)] ; WE ARE ONLINE MOVE T3,DEVIOS(F) ;COPY OLD STATUS MOVSI S,IOSERR ;AND SET/CLEAR XCT T2 ; THE ERROR BIT "IOSERR" IN DEVIOS CAME S,T3 ;DID THE STATUS CHANGE?? PUSHJ P,NTDOAV## ; IF IT DID, THEN WAKE UP UUOLEVEL POPJ P, ;GIVE GOOD RETURN TO NETSER ; XLIST ;DON'T LIST LITERALS $LIT LIST PRGEND TITLE NETRDX - REMOTE DATA ENTRY SERVICE ROUTINE TO SUPPORT MCS10 - V001 SUBTTL D. TODD/WEM 26 JUL 83 SEARCH F,S,NETPRM $RELOC $HIGH ;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED ; OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE. ; ; COPYRIGHT (C) 1978,1984 BY DIGITAL EQUIPMENT CORP., MAYNARD, MASS. ;XP VRDXSER,052 ;PUT VERSION NUMBER IN GLOB AND LOADER MAP NETRDX::ENTRY NETRDX ;RDX ONLY DEVICE STATUS BITS IOSDRP==IOSFFB ;INDICATES THAT THIS IS A MULTIDROP RDX SUBTTL 1.0 UUOCON INTERFACE. JRST NTDONL## ;(-5) ONLINE CHECK JRST ECOD2## ;(-4) DEVOP UUO JRST REGSIZ## ;(-3) LENGTH CAN BE GOTTEN FROM DDB JRST CPOPJ## ;(-2) INITIALIZE JRST CPOPJ## ;(-1) HUNG DEVICE NDEVRD::JRST NTDREL## ;(0) RELEASE JRST NTDCLO## ;(1) CLOSE OUTPUT JRST R.OUT ;(2) OUTPUT JRST R.IN ;(3) INPUT JRST CPOPJ## ;(4) ENTER JRST CPOPJ## ;(5) LOOKUP JRST NTDILI## ;(6) DUMP MODE INPUT JRST NTDILO## ;(7) DUMP MODE OUTPUT JRST CPOPJ## ;(10) USETO JRST CPOPJ## ;(11) USETI JRST CPOPJ## ;(12) GETF UUO JRST CPOPJ## ;(13) RENAME UUO JRST CPOPJ## ;(14) CLOSE INPUT JRST CPOPJ## ;(15) UTPCLR JRST CPOPJ## ;(16) MTAPE UUO SUBTTL 1.1 DDB SEARCH LOGIC INTERFACE (TSTRDX) ;TSTRDX ROUTINE TO SEE IF A RDX DDB SHOULD BE CREATED. CALLED FROM ; UUOCON'S DDB SEARCH LOGIC ROUTINE. ;CALL MOVEI P1,FLAGS ;(ONLY MATCH IF LOOKING FOR PHYSICAL DEVICE) ; MOVE T1,[SIXBIT /RD?NNX/] ;DEVICE NAME ; PUSHJ P,TSTRDX ;RETURN CPOPJ ;NOT AN RDX DEVICE ; CPOPJ1 ;IS AN RDX DEVICE. F := RDX DDB. TSTRDX::HLRZ T2,T1 ;GET JUST THE NAME XORI T2,'RDA' ;"COMPARE" IT WITH SIXBIT /RDA/ TRNN T2,777700 ;MAKE SURE IT'S OF THE FORM RD? TRNE P1,DD%LOG## ;MAKE SURE IT'S A PHYSICAL DEVICE SEARCH POPJ P, ;EITHER NOT RD?, OR LOGICAL DEVICE NETDBJ ;BETTER INTERLOCK FROM HERE ON OUT. PUSHJ P,SAVJW## ;WE CLOBBER W RIGHT AWAY, AND J IF WE CONNECT. PUSHJ P,SAVE4## ;NETSER CLOBBERS MOST OF THESE PUSH P,T1 ;SAVE THE DEVICE NAME PUSHJ P,DVSCVT## ;GET THE NODE NUMBER FROM THE NAME PJRST TPOPJ## ;NOT A NETWORK NAME. MOVEI T1,(T2) ;COPY THE NODE NUMBER PUSHJ P,SRCNDB## ;GET A NDB POINTER PJRST TPOPJ## ;NO NODE MEANS NO RDX MOVEI P1,(W) ;COPY THE NDB POINTER FOR MAKDDB MOVEI T1,'RDA' ;GET GENERIC DEVICE NAME IN RH(T1) PUSHJ P,SRCNDT## ;SEE IF THE NODE SUPPORTS RDA'S PJRST TPOPJ## ;IF NOT, THEN DEVICE DOESN'T EXIST LDB T1,[POINT 6,(P),17] ;POINT TO "CONTROLLER" CHARACTER CAIL T1,'A' ;MAKE SURE THAT IT'S IN THE CAILE T1,'H' ; RANGE A-H (= 0-7) PJRST TPOPJ## ;NOT AN RDX DEVICE IF NOT IN RANGE SUBI T1,'A' ;CONVERT TO A CONTROLLER NUMBER LDB T2,[POINT 6,(P),35] ;GET THE UNIT DIGIT (NUMERIC) CAIL T2,'0' ;MAKE SURE THAT IT'S IN THE CAILE T2,'7' ; RANGE 0-7 PJRST TPOPJ## ;NOT A VALID DIGIT. SUBI T2,'0' ;CONVERT NUMERIC TO NUMBER LSH T1,3 ;CONTROLLER BECOMES TOP HALF OF "PUNIT" IORI T1,(T2) ;T1 := FULL UNIT SPECIFICATION PUSH P,T1 ;SAVE "PUNIT" VALUE UNTIL WE SEND THE CONNECT. ;CONTINUED ON NEXT PAGE ;CONTINUED FROM PREVIOUS PAGE MOVE P2,-1(P) ;GET THE FULL NAME BACK SETZ P3, ;THERE IS NO LOGICAL NAME PUSHJ P,MAKDDB## ;MAKE A DDB (NDB POINTER IN P1) JRST [POP P,T1 ;NO CORE. FLUSH THE UNIT NUMBER JRST TPOPJ##] ;AND GIVE THE ERROR RETURN POP P,T1 ;GET THE UNIT NUMBER BACK DPB T1,PUNIT## ;STORE THE UNIT NUMBER IN THE DDB MOVEI W,(P1) ;SET UP THE NDB POINTER AGAIN PUSHJ P,NTDCNT## ;ATTEMPT TO CONNECT THE DEVICE JRST [PUSHJ P,UNLDDB## ;CONNECT FAILED. FREE THE DDB JRST TPOPJ##] ;AND GIVE UUOCON THE ERROR RETURN PUSHJ P,LNKDDB## ;IT CONNECTED. PUT THE DDB IN THE CHAIN LDB T1,NETDVT## ;GET THE ATTRIBUTES TRNN T1,DRX.MD ;IS THIS A MULTIDROP LINE? TDZA T2,T2 ;NO, LEAVE DEVSTS 0 MOVEI T2,1 ;YES, LEAVE A 1 IN DEVSTS MOVEM T2,DEVSTS(F) ;SET DEVSTS FOR USERS TO LOOK AT LSH T2,<^D35-^L>+^D18 ;POSITION IOSDRP IORB T2,DEVIOS(F) ;AND SET INTERNAL MULTI-DROP LINE FLAG PJRST TPOPJ1## ;ALL DONE. GOOD RETURN, F := DDB POINTER. SUBTTL 1.2 OUTPUT UUO. R.OUT: PUSHJ P,SAVE4## ;NETSER LIKES ITS P'S. MOVSI S,IOSUSO ;CLEAR "UUOCON STOPPED OUTPUT" SINCE ANDCAB S,DEVIOS(F) ; IT'S TRYING TO START IT NOW ROLOOP: PUSHJ P,NTDSET## ;SET UP "W" ETC. TLNE S,IOBEG ;FIRST TIME THROUGH? PUSHJ P,RDXFIR ;YES, DO SOME CLEANUP BEFORE REAL I/O MOVSI S,IO ;MARK DIRECTION AS OUTPUT IORB S,DEVIOS(F) ;SO THAT "WAIT" WORKS RIGHT PUSHJ P,NTDONL## ;MAKE SURE WE ARE STILL CONNECTED PJRST R.HUNG ;NOT THERE?? RETURN IODERR ROLOO0: LDB T2,PIOMOD## ;GET THE DEVICE MODE MOVEI T1,7 ;ASSUME THAT IT'S ASCII (7 BIT BYTES) CAIE T2,A8 ;BUT IF IT'S EIGHT-BIT ASCII CAIN T2,BYTMOD ;OR IF IT'S BYTE MODE MOVEI T1,^D8 ;THEN SELECT 8-BIT-BYTE DATA PUSHJ P,NTDSOB## ;SET UP THE OUTPUT BUFFER POPJ P, ;NO MORE OUTPUT DATA. RETURN TO UUOCON. SKIPN DEVAXO+1(F) ;MAKE SURE WE DON'T TRY TO SEND JRST ROLOO6 ; A ZERO LENGTH BUFFER PUSHJ P,NTDCDQ## ;CHECK FOR AVAILABLE DATA REQUESTS JRST ROWAIT ;IF NONE, THEN WE MUST WAIT TLNE S,IOSDRP ;IS THIS A MULTIDROP LINE? JRST R.MXMT ;IF MULTIDROP, THEN USE SPECIAL ROUTINE MOVEI T1,PCV.NC ;NO CONVERSION AT FEK TIME MOVEI T2,DC.DAR ;DATA WITH END OF RECORD PUSHJ P,NTDXMT## ;SEND A PCB'S WORTH OF DATA PUSHJ P,[JUMPN T1,NTDSTP## ;WE SHOULD NEVER GET AN IO-ERROR POP P,(P) ;CLEAN OFF THE RETURN ADDRESS (UGLY) PUSHJ P,NETSLP## ;PAUSE FOR FREECORE JRST ROLOOP] ; AND TRY AGAIN PUSHJ P,NTDDDQ## ;UPDATE THE DATA REQUEST COUNT ROLOO5: SKIPE DEVAXO+1(F) ;DID THAT FINISH OFF THE BUFFER? JRST ROLOOP ;IF NOT, THEN GO TRY TO SEND SOME MORE ROLOO6: SETZM DEVAXO+1(F) ;INDICATE THAT THE BUFFER IS ALL GONE PUSHJ P,NTDAOB## ;ADVANCE THE OUTPUT BUFFER JRST ROLOOP ;GO TRY TO SEND MORE ROWAIT: PUSHJ P,NTDWTO## ;WAIT FOR A DATA REQUEST POPJ P, ; IF NON-BLOCKING, RETURN TO UUOCON. JRST ROLOOP ;GO TRY TO SEND MORE NOW. ;MULTIDROP RDX OUTPUT CODE. R.MXMT: SETZ T1, ;WE WILL ACCUMULATE THE DROP NUMBER HERE MOVEI T2,5 ;THERE ARE 5 CHARACTERS IN THE DROP NUMBER R.MXM1: SOSGE DEVAXO+1(F) ;COUNT OFF ONE MORE BYTE JRST R.IMPM ;BUFFER DIDN'T CONTAIN A DROP NUMBER?? EXCTUX ;GET THE NEXT CHARACTER FROM THE BUFFER CAIN T3," " ;IF IT'S A SPACE, MOVEI T3,"0" ; THEN TREAT IT AS A ZERO CAIL T3,"0" ;MAKE SURE THAT IT'S IN THE RANGE CAILE T3,"9" ; 0-9 (DECIMAL) JRST R.IMPM ;BAD DROP NUMBER. SET IOIMPM SUBI T3,"0" ;CONVERT NUMERIC TO A NUMBER IMULI T1,^D10 ;MULTIPLY THE PARTIAL NUMBER BY THE RADIX ADDI T1,(T3) ;ADD IN THE NEXT DIGIT SOJG T2,R.MXM1 ;LOOP OVER ALL FIVE DIGITS. TRNE T1,740000 ;ABSURD DROP NUMBER? JRST R.IMPM ;YEAH, FLAG IO.IMP ERROR PUSH P,T1 ;SAVE THE DROP NUMBER ;START UP AN NCL MESSAGE (CAN'T USE NTDXMT DUE TO MULTIPOINT'S UNIQUE ;"DROP" NUMBER SANDWICHED BETWEEN "TYP" AND "DATA" FIELDS . . .) MOVE T1,DEVAXO+1(F) ;COUNT OF ACTUAL DATA BYTES TO BE SENT LDB T2,NETMML## ;GET RDM'S MAX MESSAGE LENGTH CAMLE T1,T2 ;WILL USER'S BUFFER FIT IN ONE MESSAGE? JRST R.MXME ;NO, BLOCK-TOO-LARGE ERROR ADDI T1,20+3 ;ALLOW FOR NCL OVERHEAD, ROUND UP LSH T1,-2 ;AND CONVERT TO WORD SIZE CAILE T1,MSGMAW## ;CAN WE GET A PCB THAT LARGE? JRST R.MXME ;NO, BLOCK-TOO-LARGE ERROR PUSHJ P,NTDHDR## ;FILL IN THE HEADER UP TO THE "DLA" JRST [POP P,T1 ;NO PCB MEMORY, BACK OUT OF TRANSMIT MOVNI T1,5 ;NUMBER OF BYTES IN "DROP" ADJBP T1,DEVAXO(F) ;ADJUST BUFFER POINTER BACKWARDS MOVEM T1,DEVAXO(F) ;TO START OF DROP FOR NEXT ROLOOP CYCLE MOVEI T1,5 ;NUMBER OF BYTES IN "DROP" ADDM T1,DEVAXO+1(F) ;ADJUST BUFFER COUNTER TOO MOVEI T1,DEPAIO ;THE "NON-BLOCKING-I/O" BIT TDNE T1,DEVAIO(F) ;IS JOB DOING ASYNC I/O? POPJ P, ;YES, "NON-BLOCKING" RETURN TO UUOCON PUSHJ P,NETSLP## ;NO, WAIT A BIT FOR SOME FREE CORE JRST ROLOOP] ;AND TRY AGAIN ;CONTINUED ON NEXT PAGE ;CONTINUED FROM PREVIOUS PAGE POP P,T4 ;RETRIEVE THE DROP NUMBER MOVEI T1,2 ;COUNT "TYP" BYTE, ASSUME ONE BYTE FOR DROP TRNE T4,777600 ;SMALL OR LARGE DROP NUMBER? ADDI T1,1 ;TWO BYTE'S WORTH OF DROP NUMBER ADD T1,DEVAXO+1(F) ;ADD COUNT OF DATA BYTES LEFT ;CNT XMT T1 ;SEND THE "COUNT" FIELD ;TYP XMTI DC.DAR ;SEND THE "TYP" = DATA WITH EOR ;DROP XMT T4 ;AND SEND THE DROP NUMBER ;DATA SETZ T4, ;COUNT OF BYTES THAT WILL BE LEFT OVER EXCH T4,DEVAXO+1(F) ;GET COUNT OF USER DATA BYTES IN BUFFER JRST R.MXM3 ;ENTER OUTPUT LOOP R.MXM2: EXCTUX ;GET ANOTHER BYTE FROM THE USER'S BUFFER XMT1 T1 ;SEND THE BYTE R.MXM3: SOJGE T4,R.MXM2 ;LOOP UNTIL WE'VE SENT IT ALL ADDB P3,PCBCTR(U) ;UPDATE THE PCB'S LENGTH MOVEI T1,PCV.NC ;THIS IS TO BE SENT UN-ADULTERATED PUSHJ P,NTDWRT## ;SEND THE MESSAGE ON IT'S CONTORTED WAY PUSHJ P,NTDDDQ## ;ACCOUNT FOR DATA REQUEST THAT JUST GOT USED JRST ROLOO5 ;GO SEE IF THE USER'S BUFFER WANTS ADVANCING ;HERE ON OUTPUT BLOCK TOO LARGE (RETURN IO.BKT ERROR) R.MXME: POP P,T1 ;PITCH DROP NUMBER JRST R.OBTL ;GO SET IO.BKT ERROR FOR USER SUBTTL 1.3 INPUT UUO. R.IN: PUSHJ P,SAVE4## ;WE CLOBBER MOST EVERYTHING MOVSI S,IOSUSI ;CLEAR "UUOCON STOPED INPUT" SINCE IT'S ANDCAB S,DEVIOS(F) ; TRYING TO START IT NOW. RILOOP: PUSHJ P,NTDSET## ;SET UP "W" ETC. TLNE S,IOBEG ;FIRST TIME THROUGH SERVICE ROUTINE? PUSHJ P,RDXFIR ;YES, CLEAN UP SOME OLDE KRUFTE MOVSI S,IO ;THE I/O DIRECTION BIT ANDCAB S,DEVIOS(F) ;TELL "WAITX" THAT WE'RE DOING INPUT PUSHJ P,NTDIBA## ;IS THERE AN INPUT BUFFER AVAILABLE TO FILL? POPJ P, ; IF NOT, THEN GO BACK TO UUOCON HRRZ T1,DEVPCB(F) ;IS THERE A PCB AVAILABLE? JUMPE T1,RIWAIT ;IF NOT, WE MUST WAIT FOR ONE PUSHJ P,NTDDID## ;IF THERE IS A PCB, THEN DECODE IT. JRST RILOOP ;KEEP IT UP TILL SOME ONE GETS BORED. RIWAIT: PUSHJ P,NTDONL## ;ARE WE STILL ONLINE? JRST R.HUNG ;IF NOT, THEN SET IODERR AND RETURN PUSHJ P,NTDXDQ## ;MAKE SURE WE'VE SENT ENOUGH DATA REQUESTS PUSHJ P,NTDWTI## ;WAIT FOR DATA. POPJ P, ;NO DATA, BUT NON-BLOCKING. RETURN TO UUOCON JRST RILOOP ;GO SEE IF IT WAS DATA THAT WOKE US UP. ;FIRST-TIME SERVICE ROUTINE INITIALIZATION RDXFIR: MOVSI S,IOBEG!IOSREL ;OBNOXIOUS FLAGS ANDCAB S,DEVIOS(F) ;CLEAR DEVICE I/O FLAGS SETZM DEVAXI(F) ;CLEAR ANY DANGLING INPUT SETZM DEVAXO(F) ;AND/OR DANGLING OUTPUT POPJ P, ;DDB CLEANED UP, READY FOR I/O SUBTTL 2.0 NETSER INTERFACE. ;RDXSER'S NDP DISPATCH VECTOR (HERE ON MESSAGES FROM NETSER) IFIW NTDNWD## ;NODE WENT DOWN IFIW NTDDSC## ;DISCONNECT MESSAGE (INIT/CONFIRM) IFIW NTDCNC## ;CONNECT CONFIRM MESSAGE IFIW NTDSTP## ;CONNECT INITIATE MESSAGE (CAN'T HAPPEN) IFIW NTDRDQ## ;RECIEVED DATA REQUEST RDANDP::IFIW NTDQIP## ;QUEUE INCOMING PCB'S TO UUO LEVEL IFIW R.DATA ;DATA WITH OUT E-O-R IFIW R.DATA ;DATA WITH E-O-R IFIW CPOPJ## ;STATUS ?? IFIW CPOPJ## ;CONTROL ?? IFIW CPOPJ## ;UNIT ID ?? IFIW CPOPJ## ;FILE SPEC ?? ;DUMMY CONNECT INIT PROCESSOR NRDACI==:NJNKCI## ;JUNK CI PROCESSOR SUBTTL 2.1 DAP INPUT DATA MESSAGE. R.DATA: LDB T2,PIOMOD## ;GET THE DATA MODE MOVEI T4,7 ;ASSUME THAT IT'S ASCII (7 BIT BYTES) CAIE T2,A8 ;CHANGE OUR MIND FOR 8-BIT ASCII CAIN T2,BYTMOD ;BUT IF IT'S BYTE MODE, CHANGE OUT MIND MOVEI T4,^D8 ; (8 BIT BYTES) PUSHJ P,NTDSIB## ;SET UP THE INPUT BUFFER STOPCD .,STOP,RDXDAT, ;++ NTDSIB FAILED IN R.DATA TLNN S,IOSDRP ;IS THIS IS MULTI DRIP LINE? JRST R.DAT1 ;IF NOT, SKIP READING THE DROP NUMBER PUSHJ P,EBI2BI## ;GET THE DROP NUMBER SETZB T2,T3 ;CLEAR THESE (WE ACCUMULATE THE NUMBER HERE) MOVEI T4,5 ;WE WANT A 5 DIGIT NUMBER R.RDR1: IDIVI T1,^D10 ;GET THE REMAINDER (NEXT DIGIT) ADDI T2,"0" ;ASCIIZ IT LSHC T2,-7 ;SAVE IT IN T3 (DON'T USE THE STACK) SOJG T4,R.RDR1 ;LOOP OVER ALL 5 CHARS MOVEI T4,5 ;NOW STORE ALL 5 CHARS R.RDR2: SOSGE DEVAXI+1(F) ;COUNT DOWN ANOTHER BYTE JRST R.BKTL ;?? USER GAVE US AN AWFULLY TINY BUFFER LSHC T2,7 ;GET THE NEXT BYTE BACK EXCTUU ;STORE THE DIGIT SOJG T4,R.RDR2 ;LOOP OVER ALL 5 DIGITS R.DAT1: SOJL P4,NTDA1B## ;COUNT OFF THE NEXT DATA CHARACTER ILDB T2,P1 ;GET THE NEXT DATA CHARACTER SOSGE DEVAXI+1(F) ;COUNT DOWN THE USERS FREE BUF CNT JRST R.BKTL ;IOBKTL IF HE DIDN'T GIVE A BIG BUFFER EXCTUU ;STORE THE BYTE JRST R.DAT1 ;LOOP OVER ALL THE DATA SUBTTL 3.0 UTILITY SUBROUTINES. ;R.BKTL ROUTINE TO SET IOBKTL IF THE USER GAVE US AN INPUT BUFFER THAT ; WAS TOO SMALL. IT ALSO ADVANCES THE INPUT BUFFER WHEN DONE. ; R.BKTL: MOVEI S,IOBKTL ;GET THE ERROR BIT IORB S,DEVIOS(F) ;SET IT WHERE UUOCON WILL NOTICE PJRST NTDA1B## ;ADVANCE THE USERS BUFFER AND SKIP RETURN ;R.OBTL ROUTINE TO SET IOBKTL IF THE USER GAVE US AN OUTPUT BUFFER THAT ; WAS TOO LARGE. IT ALSO SETS THE OUTPUT BUFFER AS "DONE" SO THAT THE ; NEXT "OUT" CALL WILL AUTOMATICALLY ADVANCE PAST THE OFFENDING BUFFER. R.OBTL: SETZM DEVAXO+1 ;MARK THE OUTPUT BUFFER AS "DONE" (EMPTY) MOVEI S,IOBKTL ;GET THE ERROR BIT JRST R.ERRS ;SET ERROR BIT, TAKE NON-SKIP RETURN ;R.HUNG RDA IS "OFFLINE" (NTDONL), CHECK IT OUT R.HUNG: TLNN S,IOSCON ;STILL CONNECTED? PJRST NTDGON## ;NO, DEVICE WENT AWAY ;YES, FALL INTO R.DERR ;R.DERR, R.IMPM ROUTINES TO SET IODERR AND IOIMPM R.DERR: MOVE S,[XWD IOSERR,IODERR] ;TWO ERROR BITS TO SET CAIA R.IMPM: MOVEI S,IOIMPM ;ERROR BIT TO SET R.ERRS: IORB S,DEVIOS(F) ;SET THE BIT(S) POPJ P, ;AND RETURN XLIST ;DON'T LIST LITERALS $LIT LIST RDXEND::PRGEND TITLE NETTSK - TASK TO TASK COMMUNICATION SERVICE ROUTINE - V001 SUBTTL W. E. MATSON/WEM 20 SEP 83 SEARCH F,S,NETPRM $RELOC $HIGH ;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED ; OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE. ; ; COPYRIGHT (C) 1978,1979,1980,1984 BY DIGITAL EQUIPMENT CORP., MAYNARD, MASS. ;XP VTSKSER,001 ;PUT VERSION NUMBER IN GLOB AND LOADER MAP NETTSK::ENTRY NETTSK ;LOADING IF IN LIBRARY SEARCH MODE ;TSK. ERROR CODES TK%TNL==ECOD1## ; 1 = TSKSER NOT LOADED. TK%ATS==ECOD2## ; 2 = ARG LIST TOO SHORT TK%UNP==ECOD3## ; 3 = USER NOT PRIVLEDGED TK%ILF==ECOD4## ; 4 = ILLEGAL FUNCTION TK%ILC==ECOD5## ; 5 = ILLEGAL CHANNEL (OR NOT TASK) TK%ILN==ECOD6## ; 6 = ILLEGAL NPD TK%NTS==ECOD7## ; 7 = NPD TOO SHORT TK%ILS==ECOD10## ; 10 = ILLEGAL FUNCTION WHILE IN THIS STATE TK%NFC==ECOD11## ; 11 = NO MONITOR FREE CORE TK%NFL==ECOD12## ; 12 = NO FREE LINKS TK%NXN==ECOD13## ; 13 = ATTEMPT TO CONNECT TO A NONEXISTANT NODE TK%UDW==ECOD14## ; 14 = UUO (IN OR OUT) DIDN'T SKIP ;TSK. FUNCTION CODES .TKFRS==1 ; 1 = RETURN STATUS, NPD'S .TKFEP==2 ; 2 = ENTER PASSIVE STATE .TKFEA==3 ; 3 = ENTER ACTIVE STATE .TKFEI==4 ; 4 = ENTER IDLE STATE .TKFWT==5 ; 5 = WAIT .TKFOT==6 ; 6 = OUTPUT WITH CONTROL OF TYPE/E-O-R .TKFIN==7 ; 7 = INPUT WITH NOTIFICATION OF TYPE/E-O-R .TKFRX==10 ;10 = RETURN STATUS, MESSAGE SIZE ;TSK. STATE VALUES .TKSID==0 ; 0 = LINE IS IDLE .TKSCI==1 ; 1 = WAITING FOR CONNECT INITIATE .TKSCC==2 ; 2 = WAITING FOR CONNECT CONFIRM .TKSOK==3 ; 3 = LINK IS OPERATIONAL .TKSDC==4 ; 4 = WAITING FOR A DISCONNECT CONFIRM COMMENT @ The first NPD in the UUO argument list is the Right-hand one (RH(DEVNPD)) The second NPD is the Left-hand one (LH(DEVNPD)) For the passive task. 1) The enter passive state uuo - NPD1 := Name we wish to be identified as (our process name) - NPD2 := The "pattern" we wish to match 2) After a successful connection, - NPD1 := The "actual" that the pattern successfully matched - NPD2 := The name of the remote process that sent the connect. For the active task. 1) The enter active state uuo - NPD1 := The name we want to return as "ours" on the confirm - NPD2 := The the "actual" we try to connect to. 2) After a successful connection, - NPD1 := The name the remote thinks we are. - NPD2 := The name he gave us as "his" @ UTSK:: PUSHJ P,SAVE4## ;WE USE A LOT OF P'S HLRZ P4,T1 ;P4 := LENGTH OF ARG LIST HRRZ P3,T1 ;P3 := ADDRESS OF ARG LIST CAIGE P4,2 ;MAKE SURE AT LEAST FCN & CHAN ARE THERE PJRST TK%ATS ;ERROR: ARG LIST TOO SHORT HRRI M,(P3) ;SET "M" UP TO READ FUNCTION CODE PUSHJ P,GETWDU## ;READ FUNCTION SKIPG P2,T1 ;P2 := FUNCTION CODE PJRST TK%ILF ;ILLEGAL FUNCTION CODE PUSHJ P,GETWD1## ;GET THE CHANNEL NUMBER MOVE P1,T1 ;P1 := CHANNEL NUMBER PUSHJ P,SETUF## ;SET UP F WITH ADDRESS OF DDB PJRST TK%ILC ;ERROR: ILLEGAL CHANNEL HRLM P1,.USCTA ;SET UP THE EXTENDED CHANNEL NUMBER LDB T1,PDVTYP## ;GET THE DEVICE TYPE CAIE T1,.TYTSK ;MAKE SURE THAT THIS IS A TASK DEVICE PJRST TK%ILC ;ERROR: ILLEGAL CHANNEL CAILE P2,TSKMX ;IS THIS A LEGAL FUNCTION CODE PJRST TK%ILF ;ILLEGAL FUNCTION JRST @.(P2) ;DISPATCH TO SUBFUNCTION JRST TSKRS ; 1 = RETURN TASK STATUS JRST TSKEP ; 2 = ENTER PASSIVE TASK STATE JRST TSKEA ; 3 = ENTER ACTIVE TASK STATE JRST TSKEI ; 4 = ENTER IDLE TASK STATE JRST TSKWT ; 5 = WAIT FOR CONNECT INITIATE/CONFIRM/REJECT JRST TSKOU ; 6 = OUT WITH CONTROL OF E-O-R. JRST TSKIN ; 7 = IN WITH NOTIFICATION OF E-O-R. JRST TSKRX ;10 = RETURN STATUS, MESSAGE SIZE MAXIMA TSKMX=10 ;10 = MAXIMUM LEGAL FUNCTION. ;SUB-FUNCTION #1 = RETURN STATUS, NPD'S TSKRS: PUSHJ P,GETSTA ;GET THE CONNECTION STATE CAIGE P4,3 ;IF WE CAN'T STORE THE STATUS JRST TK%ATS ;ERROR: ARG LIST TOO SHORT HRRI M,2(P3) ;GET THE ADDRESS OF THE RETURN VALUE AREA PUSHJ P,PUTWDU## ;RETURN THE STATE CAIN T1,LAT.ID ;SKIP IF WE HAVE TO RETURN NPD'S JRST [LDB T1,NETRSN## ;GET REASON FOR LAST DISCONNECT CAIL P4,4 ;ONLY RETURN IT IF HE ASKED FOR IT PUSHJ P,PUTWD1## ;RETURN THAT AS SECOND ARG RETSKP] ;GIVE GOOD RETURN CAIGE P4,4 ;IF THE LIST IS ONLY 3 WDS LONG JRST CPOPJ1 ; THEN WE'RE DONE HRRI M,3(P3) ;GET ADDRESS OF THE FIRST NPD POINTER HRRZ J,DEVNPD(F) ;GET THE POINTER TO THE LOCAL NPD PUSHJ P,WRTNPD ;STORE THE NPD IN THE USER'S AREA POPJ P, ;PROPAGATE THE ERROR RETURN CAIGE P4,5 ;IF THE LIST ISN'T LONG ENOUGH JRST CPOPJ1 ; THEN RETURN HRRI M,4(P3) ;GET THE ADDRESS OF THE SECOND NPD POINTER HLRZ J,DEVNPD(F) ;GET THE POINTER TO THE REMOTE NPD PUSHJ P,WRTNPD ;STORE THE NPD POPJ P, ;PROPAGATE THE ERROR RETURN RETSKP ;ALL DONE, GOOD RETURN ;SUB-FUNCTION #10 = RETURN STATUS, MESSAGE ("SEGMENT") SIZE TSKRX: PUSHJ P,GETSTA ;GET THE CONNECTION STATE CAIGE P4,3 ;IF WE CAN'T STORE THE STATUS JRST TK%ATS ;ERROR: ARG LIST TOO SHORT HRRI M,2(P3) ;GET THE ADDRESS OF THE RETURN VALUE AREA PUSHJ P,PUTWDU## ;RETURN THE STATE CAIGE P4,4 ;WANT MESSAGE SIZE TOO? JRST CPOPJ1## ;NO, THEN ALL DONE LDB T1,NETMML## ;YES, GET "MAX MESSAGE LENGTH" (OF USER DATA) LDB T2,NETRLN## ;AND RECORD LENGTH TOO (FOR WHAT IT'S WORTH) HRL T1,T2 ;RETURN AS RECORD,,MESSAGE LENGTH PUSHJ P,PUTWD1## ;RETURN SECOND VALUE JRST CPOPJ1## ;SUCCESSFUL RETURN ;SUB-FUNCTION #2 = ENTER PASSIVE STATE. (WAITING FOR CONNECT INITIATE) TSKEP: PUSHJ P,GETSTA ;GET AND RANGE CHECK THE STATE CAIE T1,LAT.ID ;THIS FUNCTION IS ONLY LEGAL IN IDLE STATE PJRST TK%ILS ;ERROR: ILLEGAL STATE PUSHJ P,RD2NPD ;READ THE TWO NPD'S (ARG'S 1 & 2) POPJ P, ;NPD WAS BAD, PROPAGATE THE ERROR RETURN NETDBJ ;GET THE NETSER INTERLOCK PUSHJ P,T.PSIV ;ENTER PASSIVE STATE. JRST [PUSHJ P,GV2NPD## ;NO FREE LAT'S, FIRST RETURN THE NPD'S PJRST TK%NFL] ;GIVE "NO FREE LINK ADDRESSES" ERROR RETSKP ;GIVE GOOD RETURN. STATE = LAT.CI ;SUB;SUB-FUNCTION #3 = ENTER ACTIVE STATE. (SEND CONNECT INITIATE) TSKEA: PUSHJ P,GETSTA ;GET AND RANGE CHECK THE STATE CAIE T1,LAT.ID ;THIS FUNCTION IS ONLY LEGAL IN IDLE STATE PJRST TK%ILS ;ERROR: ILLEGAL STATE PUSHJ P,RD2NPD ;READ THE TWO NPD'S (ARG'S 1 & 2) POPJ P, ;NPD WAS BAD, PROPAGATE THE ERROR RETURN HLRZ J,DEVNPD(F) ;GET THE ADDRESS OF THE REMOTE NPD SKIPG T1,NPDNOD(J) ;T1 := THE NODE NUMBER TO SEND CONNECT TO JRST [PUSHJ P,GV2NPD## ;IF IT'S NEGATIVE, RETURN NPD'S JRST TK%NXN] ;GIVE ILLEGAL NODE ERROR. NETDBJ ;GET THE NETSER INTERLOCK PUSHJ P,SRCNDB## ;W := NDB ADDRESS (IF NODE IS UP) JRST [PUSHJ P,GV2NPD## ;RETURN THE NPD'S PJRST TK%NXN] ; AND GIVE AN ILLEGAL NODE ERROR HRRM T1,DEVNET(F) ;MAKE THIS TASK'S NODE BE .T1 (FOR NCSCNT) PUSHJ P,T.ACTV ;ENTER ACTIVE STATE. SEND CONNECT INITIATE JRST [PUSHJ P,GV2NPD## ;NO FREE CORE. FIRST RETURN THE NPD'S PJRST TK%NFC] ; THEN GIVE "NO FREE CORE" ERROR RETSKP ;GIVE GOOD RETURN. STATE = LAT.CC ;SUB-FUNCTION #4 = ENTER IDLE STATE. SEND DISCONNECT IF NECESSARY. TSKEI: NETDBJ ;GET THE NETSER INTERLOCK TLZE F,LOOKB!ENTRB ;NO LONGER LOOKUP'ED OR ENTER'ED PUSHJ P,T.STOF ; (SORTA LIKE HAVING DONE A "CLOSE" UUO) PUSHJ P,GETSTA ;GET AND RANGE CHECK THE CONNECTION STATE JRST @.+1(T1) ;DISPATCH IFIW CPOPJ1## IFIW TSKEI1 IFIW TK%ILS IFIW TSKEI3 IFIW TK%ILS ;LAT.CI - WAITING FOR A CONNECT INITIATE TSKEI1: PUSHJ P,GV2NPD## ;RETURN THE TWO NPD'S PUSHJ P,GIVSLA## ;RETURN THE SLA, ENTER STATE LAT.ID RETSKP ;GIVE GOOD RETURN ;LAT.OK - LINK IS UP AND RUNNING TSKEI3: CAIL P4,3 ;USER SPECIFY DISCONNECT REASON? JRST [PUSHJ P,GETWD1 ;YES, GET "ARG1" JRST .+2] ;AND USE IT MOVEI T1,RSN.OK ;GET THE "NORMAL" REASON FOR DISCONNECT PUSHJ P,NTDXDS ;SEND THE DISCONNECT, ENTER LAT.DC STATE PJRST TK%NFC ;ERROR: NO MONITOR FREE CORE RETSKP ;GIVE GOOD RETURN ;SUB-FUNCTION #5 = WAIT FOR CONNECT INITIATE/CONFIRM/REJECT TSKWT: PUSHJ P,T.WAIT ;WAIT FOR TASK TO ENTER "ID" OR "OK" STATE RETSKP ;GIVE GOOD RETURN ;SUB-FUNCTION #6 = OUTPUT WITH CONTROL OF INTERRUPT/DAP MESSAGE TYPE TSKOU: PUSHJ P,GETSTA ;GET THE STATE OF THE CONNECTION, CAIE T1,LAT.OK ; AND IF WE AREN'T CONNECTED, THEN PJRST TK%ILS ; GIVE "ILLEGAL STATE" ERROR CODE HRRI M,2(P3) ;GET THE ADDRESS OF TSKOP.'S ARG #1 PUSHJ P,GETWDU## ;READ THE DAP TYPE PUSH P,T1 ;SAVE THE TYPE FOR A BIT HLR M,DEVBUF(F) ;GET THE ADDRESS OF THE BUFFER CONTROL BLOCK PUSHJ P,GETWDU## ;GET THE ADDRESS OF THE BUFFER HEADER JUMPL T1,TSKOU1 ;RING NOT SET UP. CALL "TOUT" TO SET UP RING HRRI M,(T1) ;GET THE USE BIT PUSHJ P,GETWDU## ; TO SEE IF THIS BUFFER HAS HAD AN "OUT" JUMPL T1,TSKOU1 ; DONE. IF SO, DON'T CHANGE THE DAP TYPE PUSHJ P,GETWD1## ;GET "XWD 0,WORD-COUNT" HRL T1,(P) ;T1 := "XWD DAP-TYPE,WORD-COUNT" PUSHJ P,PUTWDU## ;STORE TYPE AND COUNT IN THE BUFFER HEADER TSKOU1: POP P,T2 ;CLEAN UP THE STACK HLLZS M,M ;CLEAR "BUFFER POINTER" BEFORE DOING AN OUT PUSHJ P,TOUT## ;DO THE OUT. (NTDXMT WILL NOTICE THE DAP TYPE) CAIA ;OUT SUCCEEDED JRST TSKIOE ;IF THE UUO DIDN'T WORK, TELL THE USER TLON F,ENTRB ;EFFECT AN "ENTER" FOR CLOSE UUO PUSHJ P,T.STOF ;UPDATE "F" BITS RETSKP ;PROPAGATE SUCCESS RETURN ;SUB-FUNCTION #7 = INPUT WITH NOTIFICATION OR INTERRUPT/MESSAGE TYPE TSKIN: HLLZS M,M ;CLEAR THE "BUFFER POINTER" PUSHJ P,TIN## ;DO THE "IN" UUO CAIA ;IN SUCCEEDED JRST TSKIOE ;IF UUO DIDN'T GIVE A BUFFER, GO SEE WHY TLON F,LOOKB ;EFFECT A "LOOKUP" FOR CLOSE UUO PUSHJ P,T.STOF ;UPDATE "F" BITS HRR M,DEVBUF(F) ;TO RETURN E-O-R NOTIFICATION, GET BUFFER PUSHJ P,GETWDU## ; HEADER, AND FROM THAT TRACK DOWN THE HRRI M,1(T1) ; ".BTCNT" WORD OF THE BUFFER JUST PUSHJ P,GETWDU## ; RETURNED. HLRZ T1,T1 ;TSKSER PUTS THE DAP TYPE IN LH(.BFCNT) HRRI M,2(P3) ;GET THE ADDRESS OF ARG#1 OF THE TSKOP. PUSHJ P,PUTWDU## ; BLOCK AND RETURN THE DAP TYPE CODE RETSKP ;GIVE A GOOD RETURN TO THE ENTIRE UUO. TSKIOE: HRRZ T1,DEVIOS(F) ;IF UUO FAILS, GET THE DEVICE STATUS HRRI M,2(P3) ; AND RETURN IT IN ARG #1 OF THE PUSHJ P,PUTWDU## ; TSK. ARGUMENT BLOCK. PUSHJ P,GETSTA ;GET OUR STATE AND MAKE SURE CAIE T1,LAT.OK ; THAT WE ARE CONNECTED. PJRST TK%ILS ;IF NOT CONNECTED, "ILLEGAL STATE" PJRST TK%UDW ;ELSE TELL THE USER "UUO DIDN'T WORK" ;T.WAIT ROUTINE TO WAIT FOR A TASK TO ENTER EITHER "LAT.ID" OR "LAT.OK" STATE ;CALL F := DDB POINTER ;RETURN CPOPJ ;ALWAYS T.WAIT: PUSHJ P,GETSTA ;GET THE CONNECTION STATE CAIE T1,LAT.ID ;IF IT'S IDLE, OR CAIN T1,LAT.OK ; IF IT'S "RUNNING" POPJ P, ; THEN RETURN PUSHJ P,NETHIB## ;OTHERWISE SLEEP TILL SOMEONE WAKES US. JRST T.WAIT ;UPON AWAKING, SEE IF THE STATE CHANGED. ;T.PSIV ROUTINE TO PUT A TASK IN THE PASSIVE (LAT.CI) STATE. ;CALL F := DDB POINTER ;RETURN CPOPJ ;IF NO FREE LINK ADDRESSES (LAT FULL) ; CPOPJ1 ;LINK ADDRESS ASSIGNED. WAITING FOR CI T.PSIV: IFN PARANOID&P$TSK,< ;IF WE'RE BEING CAUTIOUS, PUSHJ P,T.CHKC ;MAKE SURE WE'RE NOT CONNECTED > HRRZ T1,F ;DDB ADDRESS FOR GETSLA MOVEI T2,LAT.CI ;INITIAL LAT STATE IS CONNECT-INIT PUSHJ P,GETSLA## ;ASSIGN A SLA, SET NEW STATE POPJ P, ;NO FREE LINK ADDRESSES DPB T1,NETSLA## ;REMEMBER THE LINK ADDRESS RETSKP ;GIVE GOOD RETURN ;T.ACTV ROUTINE TO PUT A TASK IN THE ACTIVE (LAT.CC) STATE. SENDS CONNECT ;CALL F := DDB POINTER (WITH RH(DEVNET) := NODE NUMBER) ;RETURN CPOPJ ;NO CORE, OR NO FREE LINKS, OR NO NODE ; CPOPJ1 ;CONNECT INITIATE SENT. STATE := LAT.CC T.ACTV: IFN PARANOID&P$TSK,< ;IF WE'RE BEING CAUTIOUS, PUSHJ P,T.CHKC ;MAKE SURE WE'RE NOT CONNECTED > HRRZ T1,F ;DDB ADDRESS FOR GETSLA MOVEI T2,LAT.CC ;INITIAL LAT STATE IS CONNECT-SENT (CFM WAIT) PUSHJ P,GETSLA## ;ASSIGN A LINK ADDRESS POPJ P, ;ERROR: NO FREE LINK ADDRESSES DPB T1,NETSLA## ;REMEMBER OUR LINK ADDRESS MOVEI T1,MSGMAD## ;GET OUR DATA MAXIMUM DPB T1,NETMML## ;SET FOR REMOTE TO SEE MOVE T1,[XWD T.XSPN,T.XDPN] ;GET ADDRESS OF ROUTINE TO SEND "DPN" PUSHJ P,NCSCNT## ;CALL ROUTINE TO ACTUALLY SEND THE CONNECT PJRST GIVSLA ;ERROR: NO CORE. FREE THE SLA AND RETURN RETSKP ;GIVE GOOD RETURN IFN PARANOID&P$TSK,< ;IF CHECKING, STOP IF DDB IS CONNECTED T.CHKC: PUSHJ P,GETSTA ;GET THE STATE (BETTER BE ZERO) MOVE S,DEVIOS(F) ;GET THE "CONNECTED" BIT (AND OTHERS...) CAIN T1,LAT.ID ;DIE IF STATE /= "IDLE" TLNE S,IOSCON ;DIE IF DEVIOS THINKS WERE CONNECTED STOPCD .,STOP,TSKIOS, ;++ IOSCON IS ON POPJ P, ;RETURN IF EVERYTHING'S OK > ;T.STOF - STORE "F" BITS BACK INTO JDAADR ; ;USES T1, T2 T.STOF: PUSHJ P,JDAADR## ;FIND "F" STORAGE MOVEM F,(T1) ;STORE UPDATED "F" POPJ P, ;RETURN SUBTTL 1.0 UUOCON INTERFACE. ;DISPATCH TABLE (FROM UUOCON) JRST CPOPJ## ;(-5) DEVICE OFF LINE JRST ECOD2## ;(-4) DEVOP UUO JRST REGSIZ## ;(-3) LENGTH CAN BE GOTTEN FROM DDB JRST CPOPJ## ;(-2) INITIALIZE JRST CPOPJ## ;(-1) HUNG DEVICE NDEVTK::JRST NTDREL## ;(0) RELEASE JRST T.CLSO ;(1) CLOSE OUTPUT JRST T.OUT ;(2) OUTPUT JRST T.IN ;(3) INPUT JRST T.ENTR ;(4) ENTER JRST T.LOOK ;(5) LOOKUP JRST NTDILI## ;(6) DUMP MODE INPUT JRST NTDILO## ;(7) DUMP MODE OUTPUT JRST CPOPJ## ;(10) USETO JRST CPOPJ## ;(11) USETI JRST CPOPJ## ;(12) GETF UUO JRST CPOPJ## ;(13) RENAME UUO JRST T.CLSI ;(14) CLOSE INPUT JRST CPOPJ## ;(15) UTPCLR JRST CPOPJ## ;(16) MTAPE UUO SUBTTL 1.1 DDB SEARCH LOGIC INTERFACE. ;TSTTSK ROUTINE TO SEE IF A TASK DDB SHOULD BE CREATED. ;CALL MOVEI P1,FLAGS ;DD%LOG ETC ; MOVE T1,[SIXBIT /DEVICE/] ; PUSHJ P,TSTTSK ;RETURN CPOPJ ;NOT A TSK ; CPOPJ1 ;WAS A TSK, F := DDB POINTER TSTTSK::TRNE P1,DD%LOG## ;IS THIS A LOGICAL SEARCH? POPJ P, ;IF SO, THEN DON'T MATCH PHYSICAL TASKS TLC T1,(SIXBIT /TSK/) ;IF T1 := "TSKNNM" THEN THE LH(T1) TLNE T1,-1 ; IS NOW ZERO. JRST [TLC T1,(SIXBIT /TSK/) ;IF IT'S NOT, FIXUP T1 AGAIN POPJ P,] ; AND FAIL RETURN TLC T1,(SIXBIT /TSK/) ;FIX UP T1 AGAIN... TRNE P1,DD%DEA## JRST [TRZ P1,DD%DEA## JRST CPOPJ##] NETDBJ ;INTERLOCK THIS CODE PUSHJ P,SAVE4## ;SAVE THE P'S PUSHJ P,SAVT## ;UUOCON LIKES ITS TEAS MOVE P2,T1 ;COPY DEVICE NAME TO A REASONABLE REGISTER PUSHJ P,DVSCVT## ;CONVERT THE NETWORK DEVICE NAME, GET NODE # POPJ P, ;ILLEGAL DEVICE NAME MOVEI T1,(T2) ;COPY THE NODE NUMBER FOR SRCNDB PUSHJ P,SRCNDB## ;DOES THE NODE EXIST POPJ P, ;IF NOT, WE CAN'T CONNECT TO IT'S DEVICES MOVEI P1,(W) ;COPY THE NDB FOR SRCNDT SETZ P3, ;CLEAR THE LOGICAL NAME WORK HLRZ T1,P2 ;GET THE GENERIC DEVICE NAME PUSHJ P,SRCNDT## ;DOES THIS NODE SUPPORT THIS DEVICE? POPJ P, ;IF NOT. THEN SEARCH FAILS PUSHJ P,MAKDDB## ;IF NODE DOES SUPPORT THEM, THEN MAKE A DDB POPJ P, ;IF NO CORE. JUST MAKE SEARCH FAIL PUSHJ P,LNKDDB## ;LINK IN THIS DDB (EVEN THOUGH NOT CONNECTED) RETSKP ;RETURN WITH NEWLY CONSTRUCTED DDB. SUBTTL 1.2 OUTPUT UUO. ;T.OUT ROUTINE TO HANDLE THE OUT UUO FOR THE TSK DEVICE. T.OUT: PUSHJ P,SAVE4## ;THEY GET CLOBBERED NTDXMT AND FRIENDS MOVSI S,IOSUSO ;CLEAR "UUOCON STOPED OUTPUT" SINCE IT ANDCAB S,DEVIOS(F) ; APPEARS TO BE TRYING TO START IT AGAIN TOLOOP: PUSHJ P,NTDSET## ;SET UP S, W ETC MOVSI S,IO ;SET DIRECTION TO "OUTPUT" IORB S,DEVIOS(F) ; SO THAT UUOCON WILL BE HAPPY (WAIT1 ETC) PUSHJ P,NTDONL## ;SEE IF THIS DEVICE IS STILL CONNECTED. PJRST T.HUNG ;NOT CONNECTED. SET IOSERR ; AS AN ECONOMY OF CODE, SET P1 := XWD CONVERSION-CODE, BYTE-SIZE. P1 ; SHOULD CONTAIN THESE VALUES UNTIL NTDISP IS CALLED. LDB T1,PIOMOD## ;GET THE CURRENT MODE MOVE P1,[XWD PCV.NC,^D07] ;ASSMUE ASCII MODE. (NO CONVERSION, 7 BIT) CAILE T1,AL ;IF IT'S NOT [7-BIT] ASCII, IT'S IMAGE/BINARY MOVE P1,[XWD PCV.BN,^D12] ; (BINARY CONVERSION, 12 BITS) CAIE T1,A8 ;UNLESS IT'S 8-BIT ASCII, CAIN T1,BYTMOD ; OR 8-BIT BYTE MODE. MOVE P1,[XWD PCV.NC,^D08] ; (NO CONVERSION, 8 BIT BYTES) MOVEI T1,(P1) ;GET THE BYTE SIZE PUSHJ P,NTDSOB## ;SET UP THE OUTPUT BUFFER JRST TODONE ;IF NO BUFFER, OUTPUT UUO IS DONE. ; NOTE: THIS CODE ALLOWS ZERO LENGTH DATA BUFFERS HRRZ T1,DEVOAD(F) ;GET A POINTER TO THE BUFFER HEADER EXCTUX ; AND USE IT TO GET THE TYPE/INTERRUPT BIT PUSHJ P,NTDCDQ## ;SEE IF WE HAVE ANY DRQ'S JRST TOWAIT ;IF NO DRQ'S, THEN GO WAIT FOR SOME HLRZ T1,P1 ;GET THE CONVERSION CODE SKIPN T2,P2 ;GET THE IDC TYPE FIELD MOVEI T2,DC.DAR ;IF THE USER DIDN'T SPECIFY ONE. USE THE DEFAULT PUSHJ P,NTDXMT## ;SEND A PCB'S WORTH OF DATA JRST [JUMPN T1,T.SET ;IF WE GOT AN ERROR, GO TELL THE USER PUSHJ P,NETSLP ;IF NO CORE, SLEEP FOR A WHILE JRST TOLOOP] ; AND TRY AGAIN PUSHJ P,NTDDDQ## ;DECREMENT THE DATA REQUEST COUNT SKIPN DEVAXO+1(F) ;IS THE BUFFER FINALLY EMPTY PUSHJ P,NTDAOB## ;IF SO, ADVANCE THE OUTPUT BUFFER JRST TOLOOP ;CONTINUE TILL SOMEONE GETS BORED. ;TOWAIT ROUTINE TO WAIT FOR TASK OUTPUT DATA REQUESTS TOWAIT: PUSHJ P,NTDWTO## ;LET NETSER DO THE WORK. POPJ P, ;NON-BLOCKING. RETURN TO UUOCON JRST TOLOOP ;WHEN WE WAKE UP. TRY TO DO MORE OUTPUT ;TODONE HERE WHEN WE HAVE OUTPUT ALL THE USERS BUFFERS TODONE: POPJ P, SUBTTL 1.3 INPUT UUO. ;T.IN ROUTINE TO HANDLE THE "IN" UUO ENTRY TO THE TSK DEVICE T.IN: PUSHJ P,SAVE4## ;WE CLOBBER MOST OF THEM MOVSI S,IOSUSI ;CLEAR "UUOCON STOPED INPUT" SINCE ITS ANDCAB S,DEVIOS(F) ; OBVIOUSLY TRYING TO START IT AGAIN TILOOP: PUSHJ P,NTDSET## ;USE COMMON SETUP ROUTINE (S, W, ETC) MOVE S,DEVIOS(F) ;GET STATUS BITS BACK AFTER A POSSIBLE SLEEP TLNE S,IOBEG ;IS THIS THE FIRST TIME THROUGH JRST TIFRST ;IF SO, LOOK FOR PSEUDO NON-BLOCKING CONNECT MOVSI S,IO ;CLEAR THE DIRECTION BIT SO THAT ANDCAB S,DEVIOS(F) ; UUOCON WON'T GET CONFUSED. PUSHJ P,NTDIBA## ;IS THERE AN INPUT BUFFER AVAILABLE? POPJ P, ;IF NOT, WE ARE DONE. HRRZ T1,DEVPCB(F) ;GET A POINTER TO THE LIST OF INPUT PCB'S JUMPE T1,TIWAIT ;IF NO DATA, WE MUST WAIT PUSHJ P,NTDDID## ;DO THE DELAYED INPUT DISPATCH JRST TILOOP ;KEEP IT UP TILL WE RUN OUT OF DATA. ;TIFRST HERE WE CHECK TO SEE IF WE ARE CONNECTED. IF NOT, AND THIS IS NON- ; BLOCKING STYLE I/O. THEN WE DO A DEVERR RETURN TO UUOCON. OTHERWISE WE JUST ; WAIT. WHEN WE FINNALY GET CONNECTED. WE MUST REMEMBER TO TURN OFF "IOSERR" ; WHICH GOT SET BY NTDSET. TIFRST: TLNE S,IOSCON ;ARE WE CONNECTED YET JRST [MOVSI S,IOBEG!IOSERR!IOSREL ;IF WE ARE CONNECTED, CLEAR ANDCAB S,DEVIOS(F) ; THESE BITS, JRST TILOOP] ; AND TRY ONCE AGAIN TO PROCESS DATA. PUSHJ P,NTDWTI## ;IF NON CONNECTED, THEN WAIT FOR CONNECT/DATA POPJ P, ;IF NONBLOCKING, RETURN TO UUOCON JRST TILOOP ;TRY ONCE MORE TO DO INPUT ;TIWAIT HERE IF WE HAVE NO INPUT PCB'S TO PROCESS. FIRST MAKE SURE WE HAVEN'T ; BEEN DISCONNECTED. IF SO, SET EOF. OTHERWISE SEND DATA REQUESTS, AND ; WAIT IT OUT. TIWAIT: PUSHJ P,NTDONL## ;IS THERE ANY PARTICULAR PROBLEM?? JRST T.EOF ; IF SO, GO SEE WHAT IT IS PUSHJ P,NTDXDQ## ;SEE IF WE ARE BEHIND ON OUR DATA-REQUESTS PUSHJ P,NTDWTI## ;WAIT FOR DATA POPJ P, ;RETURN TO UUOCON IF NON-BLOCKING JRST TILOOP ;AND GO MUNCH IT ;T.EOF ROUTINE TO RETURN END-OF-FILE ON FIRST "IN" AFTER DISCONNECT. T.EOF: TLNE S,IOEND ;SEE IF END-OF-FILE ALREADY SET JRST T.HUNG ;YUP, GET SERIOUS ABOUT ERROR STATUS MOVSI S,IOEND ;NO, SET EOF NOW JRST T.SET ;AND LET UUOCON WORRY ABOUT IT ;T.HUNG DEVICE IS OFFLINE (NTDONL), SEE IF STILL CONNECTED T.HUNG: TLNN S,IOSCON ;STILL CONNECTED? PJRST NTDGON## ;NO, GIVE ERROR ;YES, FALL INTO T.SERR ;T.IMPM, T.SERR ROUTINES TO SET ERROR BITS AND RETURN T.SERR: MOVE S,[XWD IOSERR,IODERR] ;THE TWO DEVICE ERROR BITS JRST T.SET ; AND SET THEM IN DEVIOUS T.IMPM: MOVEI S,IOIMPM ;IMPROPER MODE (NOT LOOKED UP/ENTERED) T.SET: IORB S,DEVIOS(F) ;SET THE BITS POPJ P, ;RETURN TO UUOCON. SUBTTL 1.4 ENTER UUO. ;T.ENTR ROUTINE TO HANDLE THE ENTER VECTORED ENTRY FROM UUOCON ;CALL F := XWD FLAGS,DDB ; M := UUO ;POINTE TO LOOKUP/ENTER BLOCK (LEB) ;RETURN CPOPJ ;NOT ENTERED. ERROR STORED IN LEB ; CPOPJ1 ;ENTERED. TASK IS CONNECTED. T.ENTR: PUSHJ P,GETSTA ;GET OUR STATE. MOVEI T2,1 ;GET A "1" LSH T2,(T1) ;MAKE IT A 1 BIT MASK TRNN T2,1_LAT.ID!1_LAT.CI!1_LAT.OK ;LEGAL STATES FOR ENTER'ING PJRST RTNISU ;OTHERWISE RETURN "ILLEGAL SEQUENCE OF UUO'S" PUSHJ P,SAVJW## ;WE CLOBBER THEM WITH NPD'S AND NDB'S PUSHJ P,SAVE4## ;SAVE THE P'S PUSHJ P,GETLEA ;GET THE LOOKUP ENTER ARG'S IN THE P'S PJRST RTNLEE ; IF LEB ARGS BAD, STORE ERROR IN LEB & RETURN PUSHJ P,GETSTA ;GET THE STATE AGAIN CAIN T1,LAT.ID ;IF WE ARE IDLE, THEN JRST T.ENT1 ; GO STORE ARGS & CONTINUE ;HERE IF TASK HAS BEEN LOOKED-UP (PUT IN PASSIVE STATE, POSSIBLY CONNECTED) PUSHJ P,CHKLEA ;MAKE SURE THAT THE LEB'S ARE IN AGREEMENT PJRST RTNAEF ; IF LEB BAD, GIVE AN "AEF" ERROR PUSHJ P,GETSTA ;GET THE CONNECTION STATE CAIN T1,LAT.OK ;IF WE'RE ALREADY CONNECTED, THEN RETSKP ; GIVE A GOOD RETURN TO THE ENTER. IFN PARANOID&P$TSK,< ;IF WE'RE BEING PARANOID, MAKE SURE CAIE T1,LAT.CI ; WE'RE IN THE "PASSIVE" STATE STOPCD .,STOP,TSKNIP, ;++ NOT IN PASSIVE STATE > PUSHJ P,GV2NPD ;RETURN THE LOOKUP'S NPDS PUSHJ P,GIVSLA## ;RETURN THE LAT (T.ACTV ASSIGNS A NEW ONE) JRST T.ENT2 ;GO SEND THE CONNECT INITIATE AND RETURN ;HERE IF WE HAVEN'T BEEN LOOKED UP YET. (STATE IS "IDLE") T.ENT1: PUSHJ P,STOLEA ;STORE THE LOOKUP/ENTER ARGS ;HERE WE SET UP "W", BUILD TWO NPD'S, SEND THE CONNECT & WAIT FOR A REPLY T.ENT2: HRRZ T1,DEVNET(F) ;GET THIS DEVICE'S NODE NUMBER PUSHJ P,SRCNDB## ;SET W := NDB POINTER. PJRST RTNUNN ; ERROR. RETURN "UNKNOWN NETWORK NODE" PUSHJ P,LE2NPD ;MAKE 2 NPD'S, REMOTE & LOCAL FOR T.ACTV PJRST RTNENC ; IF NO CORE "EXCEEDED NETWORK CAPACITY" HLRZ T1,NDBNNM(W) ;GET THE NODE NUMBER WE'RE TRYING TO CONNECT TO HLRZ J,DEVNPD(F) ;GET THE "REMOTE" NPD MOVEM T1,NPDNOD(J) ;SET THE NPD'S NODE NUMBER PUSHJ P,T.ACTV ;SEND THE CONNECT INITIATE JRST [PUSHJ P,GV2NPD ;IF NO CORE, OR NO LATS, FREE NPD'S PJRST RTNENC] ;RETURN EXCEEDED NETWORK CAPACITY ;IF NONBLOCKING, WE MIGHT WANT TO RETURN HERE PUSHJ P,T.WAIT ;WAIT FOR CONNECT CONFIRM/REJECT PUSHJ P,GETSTA ;GET OUR STATE (TO SEE IF CONFIRM/REJECT) CAIE T1,LAT.OK ;IF WE'RE NOT CONNECTED, THEN JRST [PUSHJ P,GV2NPD ; RETURN BOTH THE NPD'S, AND PJRST RTNTNA] ; GIVE A "TASK NOT AVAILABLE" ERROR RETSKP ; OTHERWISE, GIVE A GOOD RETURN SUBTTL 1.5 LOOKUP UUO. ;T.LOOK ROUTINE TO HANDLE THE LOOKUP VECTORED ENTRY FROM UUOCON ;CALL F := XWD FLAGS,DDB ; M := UUO ;POINTS TO THE USERS LOOKUP/ENTER BLOCK (LEB) ;RETURN CPOPJ ;IF ERROR, CODE RETURNED IN LEB ; CPOPJ1 ;TASK LOOKED-UP. NOW IN "PASSIVE" STATE T.LOOK: PUSHJ P,GETSTA ;GET OUR CONNECTION STATE MOVEI T2,1 ;GET A "1" LSH T2,(T1) ;MAKE IT A 1 BIT MASK TRNN T2,1_LAT.ID!1_LAT.OK ;LEGAL STATES FOR LOOKING UP PJRST RTNISU ;OTHERWISE RETURN "ILLEGAL SEQUENCE OF UUO'S" PUSHJ P,SAVJW## ;J := NPD'S, W := NDB'S PUSHJ P,SAVE4## ;WE PUT THE LOOKUP/ENTER ARGS HERE PUSHJ P,GETLEA ;GET THE LEB'S DATA PJRST RTNLEE ;LEB BAD, RETURN ERROR CODE IN "T1" PUSHJ P,GETSTA ;GET THE STATE AGAIN CAIN T1,LAT.ID ;IF NOT IDLE, JUST CHECK THE ARGUMENTS JRST T.LOO1 ;IF IDLE, GO TO "PASSIVE" STATE ;HERE IF WE'VE BEEN ENTERED, CHECK THE LEB'S ARGS AND RETURN PUSHJ P,CHKLEA ;MAKE SURE THE LOOKUP AGREES WITH THE ENTER PJRST RTNAEF ; IF LEB IS BAD, RETURN "AEF" RETSKP ;GIVE GOOD RETURN TO THE LOOKUP ;HERE IF WE'VE NOT BEEN ENTERED, MAKE 2 NPD'S AND ENTER PASSIVE STATE T.LOO1: PUSHJ P,STOLEA ;STORE DEVFIL AND FRIENDS FOR LE2NPD. IFN PARANOID&P$TSK,< ;IF WERE CAUTIOUS, MAKE SURE NOT CONNECTED SKIPE DEVNPD(F) ;DIE IF WE'VE ALREADY GOT 1 OR MORE NPD'S STOPCD .,STOP,TSKAND, ;++ ALREADY GOT AN NPD > HRRZ T1,DEVNET(F) ;GET THE NUMBER OF THIS TASK'S NODE PUSHJ P,SRCNDB## ;SET W := NDB POINTER. PJRST RTNUNN ; ERROR. RETURN "UNKNOWN NETWORK NODE" PUSHJ P,LE2NPD ;MAKE NPD'S BASED ON DEVFIL & FRIENDS PJRST RTNENC ; NO CORE. RETURN "EXCEEDED NET CAP" CAIE W,NETNDB## ;IF HE SPECIFIED "ANY" NODE, DON'T SET NPDNOD JRST [HLRZ J,DEVNPD(F) ;GET ADDRESS OF "REMOTE" NPD. HLRZ T1,NDBNNM(W) ;GET OUR NODE NUMBER MOVEM T1,NPDNOD(J) ;SET THE NODE NUMBER JRST .+1] ;CONTINUE WITH MAIN CODE PUSHJ P,T.PSIV ;ENTER "PASSIVE" STATE JRST [PUSHJ P,GV2NPD ;IF NO CORE, OR NO LATS, FREE NPD'S PJRST RTNENC] ;RETURN EXCEEDED NETWORK CAPACITY RETSKP ;GIVE GOOD RETURN TO THE LOOKUP SUBTTL 1.6 CLOSE UUO. ;T.CLS ROUTINE TO HANDLE THE CLOSE ENTRY FROM UUOCON ;CALL MOVEI F,DDB ; PUSHJ P,T.CLS ;FROM CLOSE1 CODE IN UUOCON ;RETURN CPOPJ ; ;THE CLOSE UUO CODE DOES NOTHING IF THE TSK HAS NOT BEEN CLOSED ON BOTH INPUT ; AND OUTPUT. IF IT HAS, IT DOES THE FINAL "OUT" TO FLUSH THE BUFFERS, AND ; SENDS A DISCONNECT INITIATE WAITING FOR THE DISCONNECT CONFIRM. T.CLSO: TLNE F,ENTRB ;DON'T FORCE OUTPUT IF NOT ENTERED PUSHJ P,NTDCLO## ;FORCE OUT THE LAST BUFFER (AND WAIT) TLZA F,ENTRB ;SIGNIFY THAT WE ARE NO LONGER "ENTERED" T.CLSI: TLZ F,LOOKB ;SIGNIFY THAT WE ARE NO LONGER "LOOKED UP" T.CLS: TLNE F,ICLOSB ;IF WE HAVEN'T CLOSED BOTH INPUT AND TLNN F,OCLOSB ; OUTPUT, THEN POPJ P, ; DON'T ATTEMPT TO DISCONNECT THIS TASK PUSHJ P,T.WAIT ;WAIT FOR CONNECTS/DISCONNECTS TO FINISH MOVE S,DEVIOS(F) ;NOW SEE IF WE ARE CONNECTED TLNN S,IOSCON JRST T.CLS4 ;DON'T SEND DISCONNECT IF NOT CONNECTED T.CLS2: MOVEI T1,RSN.OK ;STANDARD REASON PUSHJ P,NTDXDS## ;SEND THE DISCONNECT JRST [PUSHJ P,NETSLP## ;IF WE CAN'T SEND THE DISCONNECT, THEN JRST T.CLS2] ; THEN WAIT FOR A BIT AND TRY AGAIN T.CLS3: PUSHJ P,NETHIB## ;WAIT FOR THE CONFIRM LDB T1,NETSLA## ;GET OUR LAT ADDRESS JUMPE T1,T.CLS5 ;THE DISCONNECT CONFIRM CODE WILL ZERO IT IFN PARANOID&P$LAT,< ;MAKE SURE LAT ENTRY IS RIGHT LDB T1,LATSTA## ;GET THE STATE CAIE T1,LAT.DC ;SHOULD STILL BE DISCONNECT CONFIRM STOPCD .,STOP,TSKNID, ;++ NOT IN DISCONNECT CONFIRM > JRST T.CLS3 ;MUST HAVE BEEN A SPURIOUS WAKE T.CLS4: LDB T1,NETSLA## ;FIRST CHECK TO SEE IF WE HAVE JUMPE T1,T.CLS5 ;LAT ASSIGNED. IF NOT, DON'T FREE IT. IFN PARANOID&P$LAT,< LDB T2,LATSTA## ;GET THE STATE CAIE T2,LAT.CI ;THE ONLY LEGAL STATE AT THIS POINT IS "CI" STOPCD .,STOP,TSKNIC, ;++ NOT IN "CI" STATE > PUSHJ P,GIVSLA## ;FREE THE SLA T.CLS5: PUSH P,J ;NOW FREE THE NPD'S. FIRST SAVE J PUSHJ P,GV2NPD## ;FREE THE NPD'S POP P,J SETZM DEVFIL(F) ;CLEAR THE FILE NAME HRRZS DEVEXT(F) ; THE EXTENSION SETZM DEVPPN(F) ; THE PPN POPJ P, ;ALL DONE. SUBTTL 2.0 NETSER INTERFACE. ;TSKSER'S NDP DISPATCH VECTOR (HERE ON MESSAGES FROM NETSER) IFIW NTDNWD## ;COMMON CODE FOR CRASHED NODE IFIW NTDDSC## ;COMMON CODE FOR DISCONNECT IFIW T.CONC ;SPECIAL CODE FOR CONNECT CONFIRM IFIW T.CONI ;SPECIAL CODE FOR CONNECT INITIATE IFIW NTDRDQ## ;COMMON CODE FOR DATA-REQUESTS TSKNDP::IFIW NTDQIP## ;QUEUE INCOMING PCB'S TO UUO LEVEL IFIW T.DAPI ;DATA WITH OUT EOR IFIW T.DAPI ;DATA WITH EOR IFIW T.DAPI ;STATUS IFIW T.DAPI ;CONTROL IFIW T.DAPI ;UNIT ID IFIW T.DAPI ;FILE SPEC ;DUMMY CONNECT INIT PROCESSOR (SHOULD HAVE MATCHED IN ICMCN1) NTSKCI==:NJNKCI## ;JUNK CI PROCESSOR IN NETSER SUBTTL 2.1 CONNECT CONFIRM NCL MESSAGE. ;T.CONC ROUTINE TO PROCESS THE CONNECT CONFIRM FOR A TASK ;CALL MOVEI F,DDB ; P1, P4 := POINT TO THE "SLA" FIELD OF THE CONNECT ;RETURN CPOPJ1 ;ALWAYS T.CONC: PUSHJ P,SAVJW## ;WE USE J FOR THE NPD ;SLA PUSHJ P,EBI2BI## ;READ OUR REMOTE LAT ADDRESS DPB T1,NETDLA## ;SAVE IT SO WE CAN TALK TO HIM PUSHJ P,GV2NPD ;RETURN THE TWO STALE NPD'S. ;DPN(OBJ) PUSHJ P,XSKIP## ;WE'RE NOT INTERESTED ;DPN(,PID) PUSHJ P,GETSPN ;GET WHAT HE THINKS WE ARE SETZ J, ; IF NO CORE, DON'T WORRY... HRRM J,DEVNPD(F) ;STORE NEW LOCAL NPD ;SPN(OBJ) PUSHJ P,XSKIP## ;WE'RE NOT INTERESTED ;SPN(PID) PUSHJ P,GETSPN ;GET HIS ID SETZ J, ; IF NO CORE, JUST RETURN ZERO HRLM J,DEVNPD(F) ;STORE THE NEW REMOTE NPD ;MML,FEA(DCM,RLN,DVT,DVU,DVV) PUSHJ P,GETFEA ;READ THE "FEATURES" PUSHJ P,T.OK ;SET BITS SAYING WE ARE CONNECTED RETSKP ;GIVE GOOD RETURN SUBTTL 2.2 CONNECT INITIATE NCL MESSAGE. ;T.CONI ROUTINE TO HANDLE THE CONNECT INITIATE ENTRY FOR THE TSK DEVICE. ;CALL MOVEI F,DDB ; MOVE P3,[XWD SLA,OBJ] ; P1, P4 := POINT TO THE "DPN(PID)" FIELD OF THE CONNECT MESSAGE ;RETURN CPOPJ ;DIDN'T LIKE THE CONNECT ; CPOPJ1 ;OK. CONNECT CONFIRM SENT. LINK IN "OK" STATE T.CONI: HRRZ T1,P3 ;GET THE OBJECT TYPE CAIE T1,OBJ.TK ; AND MAKE SURE IT'S FOR TYPE "TSK" POPJ P, ; IF NOT FOR US, EXIT NOW PUSHJ P,SAVJW## ;WE CLOBBER J PUSHJ P,SAVE4## ; AND MASSACRE THE P'S MOVS J,DEVNPD(F) ;GET THE "PATTERN" NPD POINTER TLNE J,-1 ;MAKE SURE THAT BOTH NPD'S TRNN J,-1 ; EXIST POPJ P, ;IF EITHER NPD MISSING, DON'T MATCH HLRZ T1,NDBNNM(W) ;GET THIS NODE'S NUMBER SKIPL T2,NPDNOD(J) ;GET THE PATTERN'S NODE NUMBER CAIN T1,(T2) ;SKIP IF THEY DON'T MATCH SKIPA ;EITHER WILD CARD, OR MATCH, SUCCEED. POPJ P, ;NO MATCH. EXIT NOW. PUSHJ P,T.CON1 ;CALL ROUTINE TO DO PATTERN MATCH POPJ P, ; IF NO MATCH, GIVE "REJECT" RETURN HLRZ T1,P3 ;GET THE SLA DPB T1,NETDLA## ; AND REMEMBER IT. HLRZ T1,NDBNNM(W) ;GET THE NODE NUMBER HRRM T1,DEVNET(F) ; AND REMEMBER THAT TO. ;READ NCD'S ;DPN(,PID) PUSHJ P,GETSPN ;SET J := NPD DESCRIBING WHAT WE MATCHED POPJ P, ; NO CORE, GIVE ERROR RETURN FROM T.CONI HLRZ T1,NDBNNM+NETNDB## ;GET OUR NODE NUMBER MOVEM T1,NPDNOD(J) ;AND USE THAT INSTEAD OF HIS. PUSH P,J ;SAVE NPD FOR A BIT ;SPN(OBJ) PUSHJ P,XSKIP## ;WE'RE NOT INTERESTED ;SPN(,PID) PUSHJ P,GETSPN ;READ THE SOURCE PID JRST [POP P,J ;IF NO CORE, GET LAST NPD READ PJRST GIVNPD] ; RETURN IT, AND ERROR RETURN FROM T.CONI HRLM J,0(P) ;SAVE THE NEW "REMOTE" NPD ;MML,FEA(DCM,RLN,DVT,DVU,DVV) PUSHJ P,GETFEA ;READ THE "FEATURES" ;SEND CONFIRM HLRZ J,DEVNPD(F) ;GET OLD "REMOTE" NPD AND FREE IT. PUSHJ P,GIVNPD## ; (THERE MUST BE ONE TO GET THIS FAR...) HLRZ J,0(P) ;GET THE NEW "REMOTE" NPD HRLM J,DEVNPD(F) ; AND PUT IT WHERE T.XDPN CAN FIND IT. MOVE T1,[XWD T.XSPN,T.XDPN] ;ROUTINES TO SEND SPN AND DPN EMRGCY ;USE EMERGENCY MEMORY IF NECESSARY PUSHJ P,NCSCNT## ;SEND THE CONNECT CONFIRM STOPCD .,STOP,TSKSCC, ;++ SEND CONNECT CONFIRM FAILED HRRZ J,DEVNPD(F) ;GET OLD "LOCAL" NPD AND FREE IT PUSHJ P,GIVNPD## ; (THERE MUST BE ONE IF WE GOT THIS FAR) POP P,J ;GET NEW "LOCAL" NPD HRRM J,DEVNPD(F) ;AND PUT IT WHERE A ".TKFRS" CAN FIND IT PUSHJ P,T.OK ;DECLARE THE TSK UP, WAKE ANY WAITING JOBS RETSKP ;GIVE GOOD RETURN ;T.CON1 SUB-ROUTINE TO SET THINGS UP FOR THE "MATCH" ROUTINE. ; THE ONLY REASON THAT THIS IS A SUBROUTINE IS TO MAKE IT EASY ; TO SKIP/NON-SKIP RETURN. ;CALL J := POINTER TO THE "PATTERN" NPD ; P1, P4 := MESSAGE POINTER,COUNT TO PID (AS USUAL) ;RETURN CPOPJ ;PATTERN DIDN'T MATCH PID ; CPOPJ1 ;PATTERN DID MATCH, P1, P4 UPDATED TO AFTER ; ; PID T.CON1: PUSH P,P3 ;SAVE THE "XWD SLA,OBJ" INFORMATION PUSH P,P1 ;SAVE THE BYTE POINTER TO THE MESSAGE PUSH P,P4 ;SAVE THE LENGTH OF THE MESSAGE MOVE P3,P4 ;COPY THE LENGTH FOR MATCH PUSHJ P,XSKIP## ;ADVANCE PAST PID SO WE CAN CALCULATE LENGTH SUB P3,P4 ;SET P3 := LENGTH(PID) MOVE P4,-1(P) ;SET P4 := BYTE-POINTER TO PID MOVE P1,NPDNLN(J) ;SET P1 := LENGTH OF THE "PATTERN" MOVEI P2,NPDNAM(J) ;GET THE ADDRESS OF THE "PATTERN" HRLI P2,(POINT 7) ;SET P2 := BYTE-POINTER TO "PATTERN" SETZ T4, ;GET A ZERO EXCH T4,TKMTCH ;SEE IF THERE IS ALREADY A PSUEDO-STACK JUMPE T4,[MOVEI T2,100 ;GET LENGTH OF PSUEDO-STACK PUSHJ P,GETZWD## ;TRY TO ALLOCATE A NEW PSUEDO-STACK JRST T.CON3 ;IF NO CORE, CLEAN UP AND ERROR RETURN MOVEI T4,(T1) ;COPY ADDRESS OF NEW STACK HRLI T4,-100 ;MAKE IT AN AOBJN POINTER JRST .+1] ;RETURN TO MAIN CODE WITH T4 := STACK POINTER PUSHJ P,MATCH ;SEE IF THE PID MATCHES THE PATTERN JRST T.CON2 ; IF NO MATCH, CLEAN UP AND ERROR RETURN AOS -3(P) ;IF IT MATCHES. GIVE SKIP RETURN (UGH...) T.CON2: EXCH T4,TKMTCH ;PUT STACK IN THE PSUEDO-STACK CACHE JUMPN T4,[MOVEI T1,(T4) ;IF THERE IS ALREADY A P-STACK, HRLI T2,(T4) ; THEN WE MUST FREE THE EXTRA MOVN T2,T2 ; ONE. PUSHJ P,GIVZWD## ;CALL NETSER TO FREE THE CORE. JRST .+1] ;RETURN TO MAIN LINE CODE. T.CON3: POP P,P4 ;SET P4 := LENGTH(MESSAGE-PID) POP P,P1 ;SET P1 := BYTE-POINTER TO PID POP P,P3 ;SET P3 := "XWD SLA,OBJ" POPJ P, ;GIVE (POSSIBLY SKIP) RETURN SUBTTL 2.3 DAP MESSAGES. ;T.DAPI HERE TO PROCESS ALL OF THE INCOMING DAP MESSAGES ;CALL MOVEI T1,IDC MESSAGE TYPE ; MOVEI F,DDB OF DEVICE GETTING MESSAGES ;RETURN CPOPJ ;MESSAGE BAD ; CPOPJ1 ;MESSAGE OK T.DAPI: HRRZ T2,DEVPCB(F) ;GET A POINTER TO THE PCB WE'RE READING MOVE T2,PCBPTR(T2) ;GET A BYTE POINTER TO THE NCT FIELD OF THE MSG ILDB T2,T2 ;GET THE NCT BYTE TLNE T2,NCT.IT ;IF THIS IS AN INTERRUPT MESSAGE, IORI T1,(1B0) ; REMEMBER, SET "INTERRUPT" BIT IN BUFFER HEAD MOVE P2,T1 ;COPY THE HALFWORD INTO A SAFER REGISTER. LDB T1,PIOMOD## ;GET THE MODE IN WHICH WE ARE READING. CAIG T1,AL ;7-BIT ASCII OR ASCII LINE? JRST T.ASCI ;IF SO, GO TO ASCII CODE CAIE T1,A8 ;8-BIT ASCII MODE? CAIN T1,BYTMOD ; OR BYTE MODE? JRST T.BYTE ;IF SO, SPECIAL CODE JRST T.IMAG ;ALL THE REST IS IMAGE. T.ASCI: SKIPA T4,[7] ;SEVEN BIT BYTES IN ASCII T.BYTE: MOVEI T4,8 ;EIGHT BIT BYTES IN BYTE MODE PUSHJ P,T.SIB ;USE COMMON SET-UP ROUTINE T.BYT1: SOJL P4,T.ADVB ;IF DONE. ADVANCE PCB & USER'S BUFFERS ILDB T1,P1 ;GET THE NEXT DATA BYTE SOSGE DEVAXI+1(F) ;COUNT OFF NEXT BYTE IN THE BUFFER JRST T.BKTL ;IF NO ROOM, SET IOBKTL EXCTUU ;STORE THE BYTE JRST T.BYT1 ;LOOP UNTIL INPUT MESSAGE IS USED UP. T.IMAG: MOVEI T4,^D12 ;12 BIT BYTES PUSHJ P,T.SIB ;USE COMMON SETUP ROUTINE T.IMG1: SOJL P4,T.ADVB ;IF NO MORE, ADVANCE PCB'S AND USER'S BUFFERS ILDB T1,P1 ;GET THE TOP 8 BITS OF THE FIRST BYTE LSH T1,4 ;POSITION THEM IN THE 12 BIT FIELD SOJL P4,T.IMG2 ;IF NO MORE, STORE THIS WITH ZERO FILL ILDB T2,P1 ;GET LOW 4 BITS THIS BYTE, HIGH 4 OF THE NEXT ROT T2,-4 ;POSITION THE LOW 4 BITS IORI T1,(T2) ;COMBINE BOTH HALVES FOR A 12 BIT BYTE SOSGE DEVAXI+1(F) ;COUNT OFF THIS BYTE JRST T.BKTL ;GIVE AN ERROR IF IT WON'T FIT EXCTUU ;STORE THIS FIRST 12 BIT BYTE SOJL P4,T.ADVB ;IF NO MORE, LAST 4 BITS ARE GARBAGE. ILDB T1,P1 ;GET THE LAST 8 BITS OF THE SECOND 12 BIT BYTE ROT T2,^D12 ;ISOLATE THE LOW 4 BITS AS THE HIGH 4 IORI T1,(T2) ;BUILD THE SECOND 12 BIT BYTE T.IMG2: SOSGE DEVAXI+1(F) ;COUNT OFF THIS BYTE JRST T.BKTL ;GIVE AN ERROR IF IT WON'T FIT EXCTUU ;STORE THE SECOND 12 BIT BYTE JRST T.IMG1 ;LOOP UNTIL ALL INPUT IS PROCESSED. ;T.SIB ROUTINE TO SET UP AN INPUT BUFFER FOR TSK INPUT ; CALLS NTDSIB, AND STORES THE MESSAGE TYPE AND INTERRUPT BIT IN THE ; USER'S BUFFER HEADER. T.SIB: PUSHJ P,NTDSIB## ;SET UP THE INPUT BUFFER STOPCD .,STOP,TSKSIB, ;++ NO INPUT BUFFER (BUT WE CHECKED IN T.IN) HRRZ T1,DEVIAD(F) ;GET THE ADDRESS OF THE BUFFER HEADER EXCTUU ;STORE THE MESSAGE TYPE AND INTERRUPT BIT POPJ P, ;RETURN TO MAIN-LINE CODE. ;T.ADVB TASK ADVANCE BUFFER AND PCB ROUTINE. THIS ROUTINE ADVANCES ; THE BUFFER IFF THE MESSAGE RECEIVED WAS NOT DATA-WITHOUT-EOR, OR ; IF THE "DISABLE MESSAGE RE-ASSEMBLY" (IOSDMR) BIT WAS SET. ;CALL P2 := IDC TYPE ;LEFT OVER FROM EARLIER ;RETURN CPOPJ1 ;ALWAYS. T.ADVB: TRZ P2,(1B0) ;MAKE SURE THE "INTERRUPT" BIT IS OFF CAIN P2,DC.DAT ;IF IT'S NOT DATA-WITHOUT-EOR, TLNE S,IOSDMR ; OR WE'RE NOT RE-ASSEMBLING BUFFERS PJRST NTDA1B## ; THEN ADVANCE THE BUFFER RETSKP ;IF DATA WITHOUT-EOR, THEN DON'T ADVANCE ; THE BUFFER ;T.BKTL ROUTINE TO SET THE "IOBKTL" ERROR BIT IF A USERS BUFFER IS TOO SMALL ; IT ADVANCES THE USERS BUFFER, AND SKIP RETURNS (ADVANCING THE DAP MESSAGE) ; T.BKTL: MOVEI S,IOBKTL ;GET THE BLOCK TOO LARGE BIT IORB S,DEVIOS(F) ;SET IT PJRST NTDA1B## ;ADVANCE THE USERS BUFFER AND THE DAP MESSAGE SUBTTL X.X ONCE/SECOND TASK CODE ;FREE THE TEMPORARY "PSUEDO-STACK" USED BY TSKSER TSKSEC::SETZ T2, ;GET A ZERO TO INDICATE NO BLOCK EXCH T2,TKMTCH ;GET "XWD LENG,ADDR" OF BLOCK JUMPE T2,CPOPJ## ;IF NONE, RETURN NOW HLRE T1,T2 ;COPY (MINUS) THE LENGTH MOVN T1,T1 ;MAKE THE LENGTH POSITIVE PJRST GIVZWD## ;RETURN THE STORAGE SUBTTL 3.0 SUBROUTINES. SUBTTL 3.1 LOOKUP/ENTER BLOCK MANIPULATION ;GETLEA ROUTINE TO GET THE LOOKUP/ENTER ARGUMENTS FOR THE TSK DEVICE. ;CALL MOVE M,THE UUO ; PUSHJ P,GETLEA ;RETURN CPOPJ ;ERROR CODE IN T1 ; CPOPJ1 ;P1 := DEVNAM ; ;P2 := DEVEXT ; ;P3 := DEVPPN (THE USERS IF NOT PRVJ) GETLEA: PUSH P,U ;USE U AS A TEMP TO MOVE U,M ; THE ADDRESS OF THE ARGUMENT LIST PUSHJ P,GETWDU## ;GET THE FIRST (DEVNAM OR COUNT) MOVE P1,T1 ;RETURN FIRST WORD AS DEVNAM TLNN T1,-1 ;IS IT AN EXTENDED BLOCK JRST GETLEE ; IF SO. GO TO SPECIAL CODE TO READ IT HRRI M,UUNEXT(U) ;GET THE EXTENSION PUSHJ P,GETWDU## ; FROM THE USERS MEMORY, AND MOVE P2,T1 ; RETURN THAT AS DEVEXT HRRI M,UUNPPN(U) ;GET THE PPN FROM THE USERS MEMORY JRST GETLE1 ; AND GO TO COMMON CODE. GETLEE: MOVEI T1,FNFERR ;IN CASE TOO SHORT CAIGE P1,UUXEXT ;IS THIS BLOCK LONG ENOUGH JRST UPOPJ## ; IF TOO SHORT, GIVE AN ERROR RETURN HRRI M,UUXNAM(U) ;GET THE FILE NAME PUSHJ P,GETWDU## ; FROM THE USERS MEMORY, MOVE P1,T1 ; AND RETURN AS DEVNAM HRRI M,UUXEXT(U) ;GET THE EXTENSION PUSHJ P,GETWDU## ; FROM THE USER MOVE P2,T1 ; AND RETURN AS DEVEXT HRRI M,UUXPPN(U) ;GET THE PPN GETLE1: PUSHJ P,GETWDU## ;GET THE PPN JUMPE T1,GETL1A ;DEFAULT PPN? TLNE T1,-1 ;IS IT A PATH BLOCK? JRST GETL1A ;NO,CONTINUE ONWARD HRRI M,2(T1) ;YES, POINT TO PPN IN PATH BLOCK PUSHJ P,GETWDU## ;GET THE REAL PPN GETL1A: MOVE T2,.CPJOB## ;GET THIS GUY'S JOB NUMBER SKIPN P3,T1 ;GET USER-SPECIFIED PPN MOVE P3,JBTPPN##(T2) ;HE DIDN'T SPECIFY ONE, USE JOB'S PPN. CAME P3,JBTPPN##(T2) ;SPECIFYING A PPN OTHER THAN HIS? CAMN P3,[-1] ;(OR [777777,777777]?) JRST GETLE2 ;NO, IT IS OK MOVEI T1,PRTERR ;IN CASE NOT PRIVILEGED PUSHJ P,NTDPRV## ; HE MUST BE PRIVILEGED JRST GETLE9 ; AND HE IS NOT, PROTECTION ERROR GETLE2: MOVE T1,P3 ;GET THE PPN THAT WE WILL USE PUSHJ P,PUTWDU## ;TELL THE USER WHAT PPN WE REALLY ARE USING AOS -1(P) ;GIVE A GOOD RETURN GETLE9: MOVE M,U ;RESTORE THE UUO PJRST UPOPJ## ;CHKLEA ROUTINE TO CHECK TO MAKE SURE THAT THE DDB'S DEVNAM, DEVEXT, AND ; DEVPPN AGREE WITH THE LOOKUP/ENTER BLOCK'S ;CALL MOVEI F,DDB ;WITH DEVNAM ... SET UP ; P1, P2, P3 := THE LOOKUP/ENTER ARGS ;RETURN CPOPJ ;THEY DON'T AGREE (AEF ERROR RETURNED) ; CPOPJ1 ;THEY AGREE CHKLEA: CAMN P1,DEVFIL(F) ;COMPARE THE FILE NAMES CAME P3,DEVPPN(F) ;COMPARE THE PPN'S JRST RTNAEF ;GIVE THE "AEF" ERROR (ALREADY EXISTING FILE) XOR P2,DEVEXT(F) ;COMPARE THE EXTENSIONS TLNE P2,-1 ; AND ONLY THE EXTENSIONS JRST RTNAEF ;DIFFERENT. GIVE ERROR RETSKP ;ALL THE SAME. GIVE GOOD RETURN ;STOLEA ROUTINE TO STORE THE LOOKUP/ENTER ARGS IN P1, P2, P3 INTO A DDB ;CALL MOVEI F,DDB ; P1, P2, P3 := FILE NAME, EXTENSION, PPN ; PUSHJ P,STOLEA ;RETURN CPOPJ ;ALWAYS STOLEA: MOVEM P1,DEVFIL(F) ;STORE THE FILE NAME HLLM P2,DEVEXT(F) ;STORE JUST THE EXTENSION MOVEM P3,DEVPPN(F) ;STORE THE PPN POPJ P, ;ALL DONE ;ERRORS ROUTINES TO RETURN VARIOUS LOOKUP/ENTER ERRORS ; ; RTNFNF ;(00) FILE NOT FOUND ; RTNPRT ;(02) PROTECTION ERROR ; RTNAEF ;(04) ALREADY EXISTING FILE ; RTNENC ;(37) EXCEEDED NETWORK CAPACITY ; RTNTNA ;(40) TASK NOT AVAILABLE ; RTNUNN ;(41) UNKNOWN NETWORK NODE DEFINE X(CODE),< ;;SIMPLE MACRO TO MAKE DEFINING THESE EASY RTN'CODE: MOVEI T1,CODE'ERR ;;S.MAC HAS ALL THESE SYMBOLS DEFINED PJRST RTNLEE ;;COMMON CODE TO RETURN THE ERROR > X FNF ;FILE NOT FOUND X PRT ;PROTECTION FAILURE (USER NOT PRIVILEGED) X AEF ;ALREADY EXISTING FILE X ISU ;ILLEGAL SEQUENCE OF UUO'S X ENC ;EXCEEDED NTEWORK CAPACITY X TNA ;TASK NOT AVAILABLE X UNN ;UNKNOWN NETWORK NODE ;RTNLEE ROUTINE TO RETURN A LOOKUP/ENTER ERROR CODE. ;CALL MOVE U,UUO ; MOVEI T1,ERROR NUMBER ; PUSHJ P,RTNLEE ;RETURN CPOPJ ;ALWAYS RTNLEE: PUSH P,T1 ;STORE THE ERROR CODE FOR LATER PUSHJ P,GETWDU## ;GET THE FIRST WORD (TO SEE IF EXTENDED L/E) ADDI M,UUNEXT ;ASSUME THAT THIS IS THE OLD NON-EXTENDED FORM TLNN T1,-1 ; BUT IF IT IS EXTENDED, ADDI M,UUXEXT-UUNEXT ; THEN CHANGE OUT MIND PUSHJ P,GETWDU## ;GET THE "EXTENSION" FIELD HRR T1,(P) ;PUT THE ERROR CODE IN THE RH PUSHJ P,PUTWDU## ;STORE THE ERROR CODE IN THE USERS MEMORY POP P,T1 ;RESTORE THE ERROR CODE POPJ P, ;ALL DONE SUBTTL 3.2 NPD MANIPULATION SUBTTL 3.2.1 USER NPD MANIPULATION ;ADCNPD ROUTINE TO ADDRESS CHECK AN NPD ;CALL M := USER ADDRESS OF NPD POINTER (XWD LENGTH,ADDR) ;RETURN NOT AT ALL -- PAGE FAULT, OR ADDRESS ERROR ; CPOPJ NPD TOO SHORT ; CPOPJ1 ALL'S OK ADCNPD: PUSHJ P,GETWDU## ;GET XWD LENGTH,ADDRESS HLRZ T2,T1 ;COPY THE LENGTH CAIGE T2,3 ;IS IT LONG ENOUGH TO HOLD A VALID NPD JRST TK%ILN ;IF NOT, SAY "ILLEGAL NPD" HRLI T1,(IFIW) ;MAKE SECTION LOCAL REFERENCE PUSHJ P,ARNGE## ;MAKE SURE THAT THE NPD IS INCORE JRST ADRERR## ;ADDRESS CHECK JRST UADERR## ;ILLEGAL FOR I/O RETSKP ;IF IT IS, GIVE GOOD RETURN ;REDNPD ROUTINE TO READ AN NPD. NPD MUST BE ADDRESSABLE (FAULT = "IME") ;CALL M := USER ADDRESS OF NPD POINTER (XWD LENGTH,ADDR) ;RETURN CPOPJ SOME SORT OF ERROR, ERROR CODE STORED ; CPOPJ1 J := NPD REDNPD: PUSHJ P,SAVE1## ;USE P1 FOR A TEMP PUSHJ P,GETWDU## ;GET "XWD LENGTH,ADDRESS" OF NPD MOVE P1,T1 ;SAVE XWD LENGTH,ADDR HRRZS T1 ;PREVENT ILLEGAL-SECTION IMES EXCTUX ;GET THE LENGTH OF THE NAME-STRING CAILE T1,^D100 ;ALLOW THIS MANY CHARS FOR THE NPD PJRST TK%ILN ;GIVE ILLEGAL NPD ERROR IF BAD LENGTH ADDI T1,<2*5>+4 ;ADD 3 WORDS, ROUND UP IDIVI T1,5 ;CALCULATE NUMBER OF WORDS TO HOLD NPD HLRZ T2,P1 ;GET "DECLARED" LENGTH CAILE T1,(T2) ;MAKE SURE NPD FITS IN RANGE-CHECKED REGION PJRST TK%ILN ;GIVE ILLEGAL NPD ERROR IF IT DOESN'T FIT ADDI T1,1 ;ACCOUNT FOR MONITOR'S "NPDBLK" WORD PUSHJ P,GETNPD## ;ALLOCATE AN NPD, J := ADDRESS PJRST TK%NFC ;ERROR: NO MONITOR FREE CORE IFE FTXMON,< HRLZ T1,P1 ;MAKE BLT POINTER: FROM = USER ADDRESS HRRI T1,NPDNOD(J) ; TO = MONITOR NPD ADDRESS HLRZ T2,NPDBLK(J) ;T2 := LENGTH OF THE NPD ADDI T2,-1(J) ;T2 := ADDRESS OF LAST WORD IN THE NPD EXCTUX ;COPY THE NPD > IFN FTXMON,< XSFM T2 ;GET PCS HRLZS T2 ;IN LH WHERE IT BELONGS HRR T2,P1 ;FORM USER SOURCE ADDRESS HRRZI T3,NPDNOD(J) ;FORM MONITOR DESTINATION ADDRESS HLRZ T1,NPDBLK(J) ;GET LENGTH IN WORDS OF TRANSFER SUBI T1,NPDNOD ;OFFSET SINCE WE DON'T START AT BEGINNING XBLTUX T1 ;COPY THE NPD > RETSKP ;GIVE GOOD RETURN ;RD2NPD ROUTINE TO READ BOTH NPD'S FOR .TKFEA OR .TKFEP SUB FUNCTIONS ; FREE'S OLD NPD'S FIRST, THEN READS NEW ONES. ;CALL P1, P2, P3, P4 := CHANNEL, SUB=FUNCTION, ADDRESS, LENGTH ;RETURN CPOPJ SOMETHING'S WRONG, ERROR CODE STORED ; CPOPJ1 NPD'S READ. DEVNPD(F) HAS POINTERS TO BOTH RD2NPD: SKIPE DEVNPD(F) ;MAKE SURE THAT THERE AREN'T ANY NPD'S ASSIGNED STOPCD .,STOP,TSKNPD, ;++ NPD ALREADY ASSIGNED HRRI M,2(P3) ;GET THE ADDRESS OF THE FIRST NPD POINTER PUSHJ P,ADCNPD ;ADDRESS CHECK IT POPJ P, ;ERROR? PASS IT BACK HRRI M,3(P3) ;GET THE ADDRESS OF THE SECOND NPD POINTER PUSHJ P,ADCNPD ;ADDRESS CHECK THIS ONE TOO POPJ P, ;ERROR. PASS IT BACK HRRI M,2(P3) ;GET THE ADDRESS OF THE FIRST NPD POINTER AGAIN PUSHJ P,REDNPD ;GET J := ADDRESS OF NPD IN MONITOR FREE CORE POPJ P, ;SOME RANDOM ERROR. CODE ALREADY STORED HRRM J,DEVNPD(F) ;STORE "LOCAL" NPD HRRI M,3(P3) ;GET ADDRESS OF SECOND NPD POINTER PUSHJ P,REDNPD ;GET J := ADDRESS OF COPY JRST [SETZ J, ;ERROR. FIRST FREE "LOCAL" NPD EXCH J,DEVNPD(F) ;AND CLEAR DEVNPD PJRST GIVNPD##];THEN RETURN. (ERROR CODE ALREADY STORED) HRLM J,DEVNPD(F) ;STORE THE "REMOTE" NPD RETSKP ;WRTNPD ROUTINE TO COPY A MONITOR NPD BACK INTO USER SPACE. ;CALL M := ADDRESS OF USER'S NPD POINTER (XWD LENGTH,ADDR) ; J := ADDRESS OF MONITOR NPD. ;RETURN CPOPJ ;USER'S NPD DESCRIPTOR IS BAD ; CPOPJ1 ;ALL'S OK. NPD RETURNED. WRTNPD: JUMPE J,[SETZ T1, ;IF NO NPD, (PROBABLY SHORT OF CORE) PJRST PUTWDU##] ;WRITE ZERO'S OVER THE USERS NPD POINTER PUSHJ P,SAVE1## ;WE USE P1 AS A TEMP PUSH P,J ;SAVE NPD POINTER (???WDU## CLOBBERS J) PUSHJ P,GETWDU## ;GET THE NPD POINTER (XWD LENGTH,ADDRESS) POP P,J ;GET NPD POINTER BACK HLRZ T2,NPDBLK(J) ;GET THE LENGTH OF THE MONITOR NPD SUBI T2,1 ; LESS ONE (MONITOR'S LENGTH INCLUDES NPDBLK) HLRZ T3,T1 ;GET THE LENGTH OF THE USER'S AREA CAIGE T3,(T2) ;SEE IF THE NPD WILL FIT. PJRST TK%NTS ;ERROR: USER'S NPD IS TOO SHORT MOVNI T2,1(T2) ;GET NEGATIVE COUNT (+1 FOR AOBJP) HRLZ P1,T2 ;SET UP THE LH OF THE AOBJN POINTER HRRI P1,(J) ;SET UP THE RH. HRRI M,(T1) ;GET THE ADDRESS OF THE USER'S NPD AREA PUSH P,J ;SAVE NPD POINTER AGAIN. (PUTWRD...) WRTNP1: AOBJP P1,JPOPJ1## ;COUNT OFF THE NEXT ITEM, EXIT IF DONE MOVE T1,(P1) ;FETCH THE NEXT WORD OF THE NPD PUSHJ P,PUTWDU## ;STORE THE WORD AOJA M,WRTNP1 ;INCREMENT USER'S ADDRESS AND DO NEXT WORD. SUBTTL 3.2.2 MONITOR NPD MANIPULATION ;GETSPN ROUTINE TO BUILD A REMOTE NPD BASED ON CONNECT MSG DATA ;CALL P1, P4 := POINTER TO THE "PID" ; W := POINTER TO NDB OF REMOTE NODE ; PUSHJ P,GETPID ;RETURN CPOPJ ;NO CORE ; CPOPJ1 ;J := POINTER TO A NEWLY CONS-ED NPD ; ; P1, P4 POINT AFTER THE PID GETSPN: MOVE T2,P1 ;COPY THE BYTE POINTER HRREI T1,-1(P4) ;GET THE COUNT -1 GETSP1: ILDB T4,T2 ;GET THE NEXT CHAR FROM THE MESSAGE TRNE T4,200 ;SKIP OUT OF THE LOOP IF NOT EXTENSIBLE SOJGE T1,GETSP1 ;LOOP COUNTING ALL CHARS IN THE PID SUBM P4,T1 ;CALCULATE THE NUMBER OF CHARS IN THE PID PUSH P,T1 ;SAVE THE PID'S LENGTH (IN CHARACTERS) ADDI T1,3*5+4 ;ACCOUNT FOR NPDNOD AND NPDNLN, ROUND UP IDIVI T1,5 ;DIVIDE TO GET WORDS NEEDED TO HOLD PID PUSHJ P,GETNPD## ;ALLOCATE A NEW NPD JRST [PUSHJ P,XSKIP##;SKIP OVER THE PID JRST TPOPJ##] ; FIXUP STACK, RETURN WITH PID NOT COPIED HLRZ T1,NDBNNM(W) ;GET THE NODE NUMBER OF THE REMOTE MOVEM T1,NPDNOD(J) ; AND SAVE IT IN THE NPD POP P,T4 ;GET THE CHARACTER COUNT BACK MOVEM T4,NPDNLN(J) ; AND SAVE THAT TOO MOVE T3,[POINT 7,NPDNAM(J)] ;GET A POINTER TO THE "NAME" PART SUBI P4,(T4) ;MAKE T4 REFLECT THE CHARS WE ARE ABOUT TO READ GETSP2: ILDB T1,P1 ;READ A CHAR FROM THE MESSAGE IDPB T1,T3 ;STORE IT IN THE NEW PID STRING SOJG T4,GETSP2 ;LOOP OVER ALL CHARACTERS RETSKP ;ALL DONE. GIVE GOOD RETURN ;GETFEA ROUTINE TO COPY THE "FEA" FIELDS FROM A MESSAGE TO A DDB ;CALL P1, P4 := MESSAGE POINTERS ; F := DDB POINTER ; PUSHJ P,GETFEA ;RETURN CPOPJ ;ALWAYS GETFEA: PUSHJ P,NTDCNF## ;READ IN MML AND FEA FIELDS JFCL ;NOT SUPPOSED TO HAPPEN LDB T1,NETMML## ;GET MAX MESSAGE LENGTH CAILE T1,MSGMAD## ;IS HE RESTRICTING US? MOVEI T1,MSGMAD## ;NO, WE MUST RESTRICT HIM DPB T1,NETMML## ;SET FOR CONNECT CONFIRM POPJ P, ;ALL DONE ;GETSTA ROUTINE TO RETURN THE CONNECTION STATE OF A TASK ;CALL F := DDB ADDRESS ;RETURN T1 := CONNECTION STATE GETSTA: LDB T1,NETSLA## ;GET THE SOURCE LINK ADDRESS SKIPE T1 ;IF NONE, THEN ZERO IS THE STATE LDB T1,LATSTA## ;GET THE STATE CAIG T1,LAT.MX ;MAKE SURE THAT IT'S A LEGAL STATE SKIPGE T1 ; AND NOT NEGATIVE STOPCD .,STOP,TSKSOR, ;STATE IS OUT OF RANGE POPJ P, ;RETURN ;LE2NPD ROUTINE TO DUMMY UP THE NPD'S FOR TASKS OPENED VIA THE ; LOOKUP/ENTER MECHANISM. THIS ROUTINE CREATES 2 NPD'S ; (ONE REMOTE AND ONE LOCAL) BASED ON THE TASK'S FILE-NAME ; AND THE JOB'S NAME ;CALL F := DDB POINTER ;RETURN CPOPJ ;IF NO CORE ; CPOPJ1 ;DEVNPD(F) := XWD RMT,LOCAL NPD'S LE2NPD: SKIPE DEVNPD(F) ;MAKE SURE THAT THERE AREN'T ANY NPD'S STOPCD .,STOP,TSKLE2, ;++ NPD ALREADY ASSIGNED IN LOOKUP/ENTER ;FIRST BUILD THE "LOCAL" NPD MOVEI T1,3+5 ;5 WORDS HOLDS ANY "NAME[P,PN]" PUSHJ P,GETNPD## ;GET STORAGE FOR A "LOCAL" NPD POPJ P, ;IF NO CORE, JUST GIVE ERROR RETURN HLRZ T1,NDBNNM+NETNDB## ;GET OUR NODE NUMBER MOVEM T1,NPDNOD(J) ;STORE IT IN THE NPD MOVE P2,[POINT 7,NPDNAM(J)] ;P2 := BYTE POINTER TO STRING AREA SETZ P3, ;COUNT STARTS AT ZERO MOVE T1,.CPJOB## ;GET OUR JOB NUMBER MOVE T1,JBTNAM##(T1) ;GET OUR JOB NAME PUSHJ P,SX2EAS## ;WRITE THE NAME MOVE T1,.CPJOB## ;GET OUR JOB NUMBER AGAIN... MOVE T1,JBTPPN##(T1) ;GET OUR P,PN PUSHJ P,PP2EAS## ;WRITE THE "[P,PN]" MOVEM P3,NPDNLN(J) ;STORE THE STRING'S LENGTH HRRM J,DEVNPD(F) ;STORE THE NPD POINTER IN THE DDB ;CONTINUED ON NEXT PAGE ;CONTINUED FROM PREVIOUS PAGE ;NOW BUILD THE "REMOTE" NPD MOVEI T1,3+5 ;GET THE LENGTH OF THE NPD PUSHJ P,GETNPD## ;TRY TO ALLOCATE ONE PJRST GV2NPD ;IF NO CORE, RETURN THE "LOCAL" NPD AND ERR SETOM NPDNOD(J) ;DEFAULT TO A WILD-CARD NODE. MOVE P2,[POINT 7,NPDNAM(J)] ;P2 := BYTE POINTER TO STRING AREA SETZ P3, ;COUNT STARTS AT ZERO MOVE T1,DEVFIL(F) ;GET THE FILE NAME PUSHJ P,SX2EAS## ; AND "OUTPUT" THAT XMTI "[" ;OUTPUT THE OPEN BRACKET SKIPGE T1,DEVPPN(F) ;GET THE PPN, AND AOJE T1,[XMTI "*" ;IF IT'S -1 THEN OUTPUT A WILDCARD (*) JRST LE2NP1] ; AND WE'RE DONE WITH THE PPN HLRZ T1,DEVPPN(F) ;GET THE PROJECT NUMBER PUSHJ P,OC2EAS## ;OUTPUT THE NUMBER XMTI "," ;OUTPUT THE COMMA HRRZ T1,DEVPPN(F) ;GET THE PROGRAMMER NUMBER PUSHJ P,OC2EAS## ;OUTPUT THAT TOO LE2NP1: XMTI "]" ;CLOSE OFF THE PPN MOVEM P3,NPDNLN(J) ;REMEMBER THE LENGTH HRLM J,DEVNPD(F) ;SAVE THE "REMOTE" NPD RETSKP ;GIVE A GOOD RETURN ;T.X?PN ROUTINE CALLED BY NCSCNT TO SEND THE "?PN" PART OF A CONNECT MESSAGE ;CALL P2, P3 := POINTERS TO CONNECT MESSAGE SO FAR ; F := POINTER TO TASK DDB ;RETURN CPOPJ ;ALWAYS T.XSPN: HRRZ J,DEVNPD(F) ;GET NPD FOR LOCAL TASK NAME PJRST T.XPN ;GO TO COMMON ROUTINE TO SEND "SPN" T.XDPN: HLRZ J,DEVNPD(F) ;GET NPD FOR REMOTE TASK NAME ; PJRST T.XPN ;GO TO COMMON ROUTINE TO SEND "DPN" T.XPN: ;ROUTINE TO SEND A "DPN/SPN" J := NPD. ;?PN(OBJ) XMTI OBJ.TK ;SEND THE TASK OBJECT TYPE ;?PC(PID) SKIPE J ;IF NO NPD, SKIPN T3,NPDNLN(J) ; OR IF NAME IS OF LENGTH "ZERO" JRST [XMTI 0 ; SEND A "ZERO" NAME POPJ P,] ; AND RETURN MOVE T4,[POINT 7,NPDNAM(J)] ;GET A POINTER TO THE NAME T.XPN1: ILDB T1,T4 ;GET THE NEXT CHARACTER IORI T1,200 ;SET THE EXTENSIBLE BIT. XMT1 T1 ;SEND THE CHAR SOJG T3,T.XPN1 ;LOOP OVER ALL CHARACTERS PJRST CLRBT8## ;CLEAR THE BIT ON LAST CHAR & RETURN ;T.OK ROUTINE CALLED WHEN A TASK CONNECTION COMPLETED. SETS THE TASK ; AS ONLINE (CONNECTED, LAT-STATE OK) T.OK: LDB T1,NETSLA## ;GET THE LAT ADDRESS MOVEI T2,LAT.OK ;THE "OK" STATE DPB T2,LATSTA## ;SET THE STATE OF THE LAT MOVSI S,IOSCON IORB S,DEVIOS(F) ;SET THE "WE ARE CONNECTED" BIT MOVE S,[XWD IOSERR+IOEND,IODERR] ANDCAB S,DEVIOS(F) ;CLEAR THESE ERROR BITS. PUSHJ P,PSIONL## ;GIVE THE USER AN ON-LINE INTERRUPT PUSHJ P,NTDIAV## ;SAY INPUT IS NOW AVAILABLE PJRST NETWAK## ; AND WAKE HIM IF SLEEPING OR HIBERING ;MATCH Routine to perform a pattern match. ;Call P1, P2 := Length, Byte pointer to the "Pattern" ; P3, P4 := Length, Byte pointer to the "Source" ; T4 := Aobjn pointer to block of "free" storage. This ; is used as a Psuedo-stack. This routine uses no ; "real" stack. ;Return CPOPJ ;Source did not match Pattern ; CPOPJ1 ;Source did match Pattern ; ;Note Only T1, T2 and T3 are modified. T4, and P1 - P4 are returned ; unchanged. ; ; The algorithm works in the obvious way. Special "pattern" ; characters are: ; ; ? Match any next source character. ; * Match zero or more next source characters. ; ^V (Control "V") Treat the next "pattern" char as a normal ; char even if it is a "?" or a "*". MATCH: MOVE T3,T4 ;COPY THE PSUEDO-STACK POINTER HLRE T1,T3 ;GET MINUS(LENGTH) OF STACK LEFT CAMLE T1,[EXP -4] ;MAKE SURE WE HAVE AT LEAST 4 WORDS LEFT POPJ P, ;GIVE ERROR RETURN IF NOT ENOUGH STORAGE ;BIG LOOP. ONCE PER STRING MATCH1: DMOVEM P1,0(T3) ;SAVE THE PATTERN DESCRIPTORS DMOVEM P3,2(T3) ;SAVE THE SOURCE DESCRIPTORS ;LOOP. ONCE PER CHARACTER MATCH2: SOJL P1,[SOJL P3,MATCHS ;IF BOTH ARE NULL, RETURN SUCCESS JRST MATCH3];IF SOURCE STRING TOO LONG, BACK-UP ILDB T1,P2 ;GET THE NEXT PATTERN CHARACTER CAIN T1,"*" ;SEE IF IT'S A STAR JRST MATCH4 ; IF IT'S A STAR, GO RECURSE ON REST. CAIN T1,"?" ;SEE IF IT'S A WILD CHARACTER JRST [SOJL P3,MATCHF ; IF SO, COUNT ONE SOURCE CHAR (FAIL IF NONE) IBP P4 ; SKIP OVER NEXT SOURCE CHAR JRST MATCH2] ; AND CONTINUE THE MATCH WITH NEXT CHAR CAIN T1,"V"-100 ;IS IT A ^V? JRST [SOJL P1,MATCHF ; IF IT'S A ^V, COUNT OFF ON PATTERN CHAR ILDB T1,P2 ; GET THE NEXT "QUOTED" CHAR JRST .+1] ; AND CONTINUE WITH THE MATCH SOJL P3,MATCHF ;COUNT OFF SOURCE CHAR. COMPLETE FAIL IF NONE. ILDB T2,P4 ;GET THE NEXT SOURCE CHARACTER XORI T1,(T2) ;COMPARE THE CHARACTERS TRNN T1,177 ; BUT ONLY LOOK AT LOW 7 BITS JRST MATCH2 ;IF THEY MATCH, GO COMPARE NEXT CHARS. ;BACKUP. HERE IF CHARS DON'T MATCH MATCH3: CAMN T3,T4 ;ARE WE AT "LEVEL 0" JRST MATCHF ;IF AT LEVEL 0 THEN THE MATCH FAILED DMOVE P1,0(T3) ;GET BACK ORIGIONAL PATTERH DMOVE P3,2(T3) ;GET BACK SOURCE SOJL P3,MATCHF ;WE ARE PROCESSING A "*". EAT ONE MORE SOURCE IBP P4 ; CHARACTER. DMOVEM P3,2(T3) ;REMEMBER THE UPDATED SOURCE JRST MATCH2 ;NOW TRY THE COMPARE AGAIN ON SHORTER SOURCE ;STAR. RECURSE MATCH4: ADD T3,[XWD 4,4] ;BUMP OUR "PSUEDO-STACK" POINTER HLRE T1,T3 ;GET THE NUMBER OF WORDS LEFT CAMLE T1,[EXP -4] ;MAKE SURE THERE ARE AT LEAST 4 LEFT. JRST MATCHF ;IF NO "STACK", RETURN FAILURE JRST MATCH1 ;GO "RECURSE" MATCHS: AOS (P) ;IF WE SUCCEED, GIVE SKIP RETURN MATCHF: DMOVE P1,0(T4) ;LOAD ORIGIONAL P1 & P2 DMOVE P3,2(T4) ; OLD P3 & P4 POPJ P, ;RETURN SUBTTL 4.0 TSKSER IMPURE STORAGE. $LOW TKMTCH: EXP 0 ;THIS TEMP CONTAINS THE "PATTERN" MATCH ; TEMPORARY PSUEDO-STACK. XLIST ;DON'T LIST LITERALS $LIT LIST TSKEND::PRGEND TITLE NETVTM - VIRTUAL TERMINAL ROUTINES VERSION 001 SUBTTL NETVTM -- MAT/ 21-FEB-79 SEARCH F,S,NETPRM $RELOC $HIGH ;This software is furnished under a license and may only be used ; or copied in accordance with the terms of such license. ; ; Copyright (C) 1979,1984 By Digital Equipment Corp., Maynard, Ma. xp vnetvtm,002 ;version number in Glob and Loader Map NETVTM::ENTRY NETVTM NDEVTY==:777740 ;DUMMY DEVSER DISPATCH FOR NDT MACRO EXTERN LTLANF ;SINCE ".CREF LTLANF##" DOESN'T WORK... ;AND I WANT SOME FLAG FOR THE "SKIPL LDBTTW" ;VTMREC ROUTINE TO PROCESS LOCALLY INPUT CHARS THAT ARE DESTINED FOR ; A REMOTE MCR. ;CALL U := POINTER TO THE LDB OF THE "VTM" LINE ; T3 := THE CHAR ;RETURN CPOPJ ;ALWAYS VTMREC::MOVE T2,LDBREM##(U) ;GET THE REMOTE STATUS BITS TLNN T2,LRLCON## ;MAKE SURE WE'RE CONNECTED JRST [PUSHJ P,PCRLF##;GIVE THE USER A HINT AS TO HOW HE'S SCREWED MOVEI T1,[ASCIZ /Waiting for connect confirm./] PJRST CONMES##]; IF THE CONNECT IS NOT COMPLETE TLNE T2,LRLDIP## ;IF A DISCONNECT IS IN PROGRESS, JRST [PUSHJ P,PCRLF##;TELL THE TYPIST THAT HIS CHARACTER IS LOST MOVEI T1,[ASCIZ /Waiting for disconnect confirm./] PJRST CONMES##]; AND WAIT TILL THE CONFIRM FINALLY COMES IN ;MAKE SURE WE HAVE THE RESOURCES (CHUNKS) TO HANDLE THIS CHARACTER. MOVE T2,LDBTIC##(U) ;GET THE NUMBER OF CHARS IN THE INPUT BUFFER. ; (DON'T BOTHER WITH COUNT IN LDBECC) CAIG T2,^D150 ;IF MORE THAN THIS ARBITRARY NUMBER, SKIPG TTFREN## ; OR THERE ARE NO MORE CHUNKS, PJRST RCHLT1## ;THEN DING USER'S BELL AS OUR ECHO CAIL T2,^D100 ;IF MORE THAN THIS ARBITRARY NUMBER, PUSHJ P,SNDXOF## ; THEN TELL THE USER'S MACHINE TO STOP ;CHECK FOR ^S MOVE T2,LDBREM##(U) ;GET THE DAP STATUS BITS MOVEI T1,(T3) ;GET A COPY OF THE CHARACTER SKIPL LDBATR##(U) ;IF 7-BIT EXTERN LAL8BT ;CREF BIT TESTED TRZ T1,CK.PAR ;CLEAR PARITY JUNK ANDI T1,CK.CHR ;KEEP ONLY CHARACTER IN ANY CASE TRNN T2,STY.TP ;IF WE'RE NOT IN "TERMINAL PAGE" MODE JRST VTMRE1 ; DON'T STOP OUTPUT. CAIE T1,"S"-100 ;IF IT'S NOT A ^S, JRST VTMRE0 ; THEN CHECK FOR ^Q MOVSI T1,LOLSTP## ;GET SCNSER'S BIT MEANING THE SAME THING, IORM T1,LDBOST##(U) ; AND SET IT SO OUTPUT WILL STOP. JRST VTMRE3 ;GO SHIP THE ^S TO THE REMOTE MCR. ;CHECK FOR ^Q VTMRE0: CAIE T1,"Q"-100 ;IF IT'S NOT A ^Q, JRST VTMRE1 ; THEN KEEP GOING MOVSI T1,LOLSTP## ;GET SCNSER'S BIT MEANING THE SAME THING ANDCAM T1,LDBOST##(U) ; AND CLEAR IT SO OUTPUT WILL START. PUSHJ P,SETCHP## ; AND START OUTPUT JRST VTMRE3 ;GO SHIP THE ^Q TO THE REMOTE MCR ;SEE IF IMAGE INPUT MODE. IF NOT, DO AUTO-CRLF, ^S AND CASE CONVERSION VTMRE1: TRNE T2,STY.II ; AND SEE IF WE'RE IN IMAGE INPUT. JRST VTMRE3 ; IF IMAGE INPUT, SKIP THE NEXT FEW CHECKS. SKIPL LDBATR##(U) ;IF 7-BIT EXTERN LAL8BT ;(NOTE TEST) TRZ T3,CK.PAR ;THEN JUNK PARITY BIT ANDI T3,CK.CHR ;MAKE SURE JUST HAVE A CHARACTER ;CHECK FOR CASE CONVERSION TRNN T2,STY.CV ;SEE IF CASE CONVERSION IS ENABLED JRST VTMRE2 ;IF NOT ENABLED, DON'T DO IT. CAIL T3,140 ;RANGE CHECK THE CHARACTER CAIL T3,175 ; TO SEE IF IT SHOULD BE CONVERTED CAIL T3,340 ; CHECK IN 8-BIT RANGE CAIL T3,377 ; AS WELL JRST VTMRE2 ;IF NOT A LOWER CASE CHAR, DON'T CONVERT IT TRZ T3,40 ;MAKE UPPER CASE LOWER CASE JRST VTMRE3 ;SKIP NEXT CHECK SINCE CHAR ISN'T A SPACE ;NOW DO AUTO-CRLF CHECK. VTMRE2: CAIE T3,40 ;IS THE CHAR A SPACE? JRST VTMRE3 ; IF NOT, DON'T CONVERT IT TO A CR. LDB T4,LDPACR## ;GET THE "AUTO-CRLF" POSITION JUMPE T4,VTMRE3 ; IF AUTO-CRLF NOT ENABLED, CHECK NO FARTHER PUSHJ P,HPOS## ;GET OUR CURRENT HORIZONTAL POSITION. CAIL T2,(T4) ; AND IF WE'RE PAST THE "AUTO-CRLF" LOCATION MOVEI T3,15 ; THEN PRETEND THE USER TYPE "CR" NOT SPACE. ;ALL LOCAL CHARACTER PROCESSING IS DONE (EXCEPT POSSIBLY ECHO). NOW ; IT'S TIME TO SHIP THE CHARACTER TO THE REMOTE MCR. VTMRE3: SCNOFF ;IN PREPARATION FOR TICKLING CHUNK CHAINS MOVE T2,LDBREM##(U) ;GET THE DAP STATUS ONCE AGAIN TRNE T2,STY.DE ; AND SEE IF WE'RE IN DEFERED (MCR) ECHO JRST [PUSHJ P,VTMSTI ; IF DEFERED ECHO, FIRST STORE THE CHARACTER LDB T1,LDPEPM##;GET THE OLD ECHO PIPELINE SERIAL AOS T1 ; AND MAKE A NEW ONE DPB T1,LDPEPM##;STORE NEW ONE SO MARKER FROM HOST WON'T MATCH SCNON ;INTERRUPTS OK NOW. PJRST VTMENQ] ;QUEUE THE LINE SO THE DATA GETS SENT TO MCR. ;HERE IF WE'RE IN LOCAL ECHO. NOW CHECK TO SEE IF THERE IS ANY REASON ; FOR GOING INTO DEFERED ECHO. MOVSI T1,LPLALT## ;BIT TO TEST TDNE T1,LDBPAG##(U) ;DOING ALTMODE CONVERSION? SKIPA T1,[174] ;YES MOVEI T1,176 ;... CAIG T3,(T1) ;SEE IF THIS CHARACTER IS CAIGE T3,40 ; IN THE RANGE OF BREAK CHARACTERS JRST [CAIE T3,11 ; OR IF IT IS THE "NON BREAK" TAB JRST VTMRE4 ;IF IT'S A BREAK GO ENTER DEFERED ECHO JRST .+1] ;NON-BREAK TAB. STAY IN LOCAL ECHO VTMRE7: PUSHJ P,VTMSTE ;GO STORE THE CHARACTER AS "ECHOED" PUSHJ P,VTMSTO ;ECHO THE CHARACTER BY PUTTING IN OUTPUT STREAM SCNON ;INTERRUPTS OK NOW. PUSHJ P,TOPOKE## ;START THE OUTPUT GOING. MOVE T1,LDBECC##(U) ;GET THE COUNT OF ECHOED CHARACTERS CAIL T1,^D72 ; AND IF MORE THAN 30 WAITING TO GO, PUSHJ P,VTMENQ ; THEN QUEUE THE LINE FOR SERVICE. POPJ P, ;RETURN. CHAR HAS BEEN STORED AND ECHOED. ;HERE WHEN WE RECEIVE A BREAK CHARACTER WHILE WE ARE IN LOCAL ECHO MODE. ; WE MUST STORE THE CHARACTER, ENTER DEFERED ECHO MODE, AND QUEUE ; THE LINE SO THE DATA GETS SHIPPED TO THE MCR. NOTE THAT "CR" IS ; SPECIAL IN THAT IT IS THE ONLY BREAK CHARACTER THAT IS ECHOED LOCALLY. ; THIS IMPROVES THE "FEEL" OF THE NETWORK AND GIVES AN ILLUSION OF ; GREAT SPEED. VTMRE4: CAIGE T3,240 ;IS THIS AN 8-BIT DATA CHARACTER? JRST VTMRE6 ;NO, WE'RE DEFINITELY GOING INTO MCR ECHO MOVE T2,LDBREM##(U) ;GET OUR CHARACTERISTICS TRNE T2,STY.8B ;ARE WE IN 8-BIT I/O MODE? JRST VTMRE7 ;YES, JUST PASS THE CHARACTER VTMRE6: CAIE T3,15 ;WAS THIS A "CR" JRST VTMRE5 ; IF NOT, DON'T DO THE FANCY LOCAL ECHO PUSHJ P,VTMSTE ;STORE THE CHAR AS AN "ECHOED" CHAR PUSHJ P,VTMSTO ; AND ECHO A "CR" TO THE OUTPUT STRING MOVEI T3,12 ;GET A "LF" PUSHJ P,VTMSTO ; AND PUT THAT IN THE OUTPUT STRING TOO. SCNON ;ALL CHARS STORED. INTERRUPTS OK NOW. PUSHJ P,TOPOKE## ;START UP OUTPUT TO GET THE ECHO OUT. PJRST VTMEDM ;ENTER DEFERED ECHO MODE (QUEUE LINE) & EXIT VTMRE5: PUSHJ P,VTMSTI ;STORE THE CHAR AS A NORMAL NON-ECHOED CHAR SCNON ;INTERRUPTS OK NOW... PJRST VTMEDM ;QUEUE THE LINE SO MCR GETS DATA & EXIT. ;VTMDSO ROUTINE CALLED BY SCNSER WHEN A DATA-SET LINE COMES UP ;CALL U := POINTER TO THE LDB ;RETURN CPOPJ ;ALWAYS VTMDSO::MOVEI T1,STY.RG ;GET THE RING/CARRIER BIT IORM T1,LDBREM##(U) ; AND SET IT IN THE STATUS PJRST VTMSSS ;GO "SET SEND STATUS" AND QUEUE THE LINE ;VTMDSF ROUTINE CALLED BY SCNSER WHEN A DATA-SET LINE HANGS UP ;CALL U := POINTER TO THE LDB ;RETURN CPOPJ ;ALWAYS VTMDSF::MOVEI T1,STY.RG ;GET THE RING/CARRIER BIT ANDCAM T1,LDBREM##(U) ; AND CLEAR IT IN THE STATUS WORD MOVSI T1,LRLDIP## ;GET THE "WE WANT TO DISCONNECT" BIT IORM T1,LDBREM##(U) ; AND SET IT PJRST VTMENQ ;QUEUE THE LINE SO THAT IT GETS SENT ;VTMSSS ROUTINE TO "SET SEND STATUS" AND QUEUE A LINE ;CALL U := POINTER TO THE LDB ;RETURN CPOPJ ;ALWAYS VTMSSS: MOVSI T1,LRLSTS## ;GET THE "PLEASE SEND STATUS BIT" IORM T1,LDBREM##(U) ; AND SET IT SO STATUS GOES SOON PJRST VTMENQ ;QUEUE THE LINE SO IT GETS SCANNED ;NETWORK DISPATCH VECTOR. IFIW VTMNWD ;(-5) NODE DOWN IFIW VTMDCC ;(-4) DISCONNECT MESSAGE IFIW VTMCNC ;(-3) CONNECT CONFIRM IFIW NTDSTP## ;(-2) CONNECT INITIATE IFIW CPOPJ## ;(-1) DATA REQUESTS (DON'T GET ANY ON THIS SIDE) TTYNDP::IFIW VTMDAP ;( 0) INCOMING DAP MESSAGES. IFIW VTMDAT ;( 1) DATA WITH-OUT END OF RECORD IFIW VTMDAT ;( 2) DATA WITH END OF RECORD IFIW VTMSTS ;( 3) DAP STATUS MESSAGE IFIW VTMCTL ;( 4) DAP CONTROL MESSAGE IFIW CPOPJ## ;( 5) USER ID IFIW CPOPJ## ;( 6) FILE SPEC ;FIELD A CONNECT-INIT ON A LOCAL TERMINAL ;CALLED BY THE NDTCNI DISPATCH IN ICMCNT. ; P1, P4 POINT TO THE "DPN" OF THE CONNECT MESSAGE ; P3 := XWD DLA,OBJ ;AS READ FROM THE CONNECT ; W := POINTER TO THE NDB ;RETURN CPOPJ ;CONNECT REJECT. REASON IN "T1" ; CPOPJ1 ;CONNECT ACCEPTED. CONNECT CONFIRM SENT. NTTYCI::PUSH P,U ;PROTECT THE INPUT PCB MOVE T1,STATES## ;GET THE SCHEDULE FLAGS TRNE T1,ST.NRT ;IF SYSTEM IS S/A JRST VTMCE3 ;THEN DISALLOW REMOTE CONNECTS ;DPN(,PID) PUSHJ P,EBI2BI## ;READ IN REMOTE'S REQUESTED "UNIT" NUMBER CAIN T1,FRCLIN## ;IS THIS FORCE-LINE? JRST VTMCE4 ;YES, YOU CAN'T HAVE IT! MOVE U,LINTAB##(T1) ;GET ADDRESSED LDB HRRZ F,LDBDDB##(U) ;GET LDB'S DDB (IF ANY) JUMPN F,VTMCE4 ;IF DDB THEN IN USE, ERROR SKIPL T1,LDBCOM##(U) ;GET LDB 'COMMAND' WORD TLNE T1,LDBCMF## ;CHECK FOR FORCED COMMAND PENDING JRST VTMCE4 ;COMMAND PENDING, CAN'T HAVE THE TERMINAL MOVE T1,LDBTTW##(U) ;GET LDB 'TYPE' WORD TLNE T1,LTLUSE## ;IF THE LDB IS 'NOT-IN-USE' TLNE T1,LTLANF## ;OR IF THE LDB IS AN ANF TERMINAL JRST VTMCE4 ;THEN ALSO CAN'T ASSIGN IT MOVE T1,LDBDCH##(U) ;GET LDB DEVICE CHARACTERISTICS TRNN T1,LDRPTY##!LDRCTY## ;REMOTE CAN'T HAVE PTYS OR OUR CTY SKIPE LDBREM##(U) ;IF ALREADY 'HOSTED' AWAY JRST VTMCE4 ;THEN ALSO CAN'T ASSIGN IT ;THE REQUESTED TERMINAL IS AVAILABLE PUSHJ P,VTMLOC ;MAKE SURE LDB IS PRESENTABLE PUSHJ P,FRELDB## ;LDB DEFUNCT??? SHOULDN'T EVER HAPPEN! JRST VTMCE3 ;LDB ZAPPED? TELL REMOTE HE CAN'T HAVE THIS ONE MOVE T1,U ;ADDRESS OF LDB FOR GETSLA TLO T1,LAT.TY!LAT.VT;FLAG THIS IS A VTM/LDB ADDRESS MOVEI T2,LAT.CC ;WHOSE INITIAL STATE WILL BE "CC" PUSHJ P,GETSLA## ;GET A LINK ADDRESS JRST VTMCE3 ;NO LAT SLOTS, NO RESOURCES DPB T1,LDPSLA## ;MARK OUR LINK ADDRESS HLRZ T1,P3 ;GET REMOTE'S LINK ADDRESS DPB T1,LDPDLA## ;AND SAVE THE DLA TOO HLRZ T1,NDBNNM(W) ;REMOTE'S NODE NUMBER DPB T1,LDPRNN## ;SET LDB'S REMOTE OWNER MOVSI T1,LRLVTM##!LRLSCH##!LRLSTS## ;IMPORTANT VTM FLAGS IORM T1,LDBREM##(U) ;TO MAKE ALL SORTS OF 'RIGHT' THINGS HAPPEN ;CONTINUED ON NEXT PAGE ;CONTINUED FROM PREVIOUS PAGE ;SPN(OBJ) PUSHJ P,EBI2BI## ;READ IN REMOTE'S OBJECT TYPE CAIE T1,OBJ.TT ;MUST BE A TERMINAL HANDLER (MCR) JRST VTMCE2 ;NOT - SOMEONE IS CONFUSED ;SPN(,PID) PUSHJ P,XSKIP## ;IGNORE REMOTE'S 'PID' ;MML PUSHJ P,XSKIP## ;IGNORE REMOTE'S MAX MESSAGE SIZE ;FEA PUSHJ P,XSKIP## ;IGNORE DATA CODES (WE *KNOW* WHAT IS LEGAL) PUSHJ P,XSKIP## ;IGNORE RECORD LENGTH PUSHJ P,XSKIP## ;IGNORE DEVICE ATTRIBUTES PUSHJ P,XSKIP## ;IGNORE DEVICE 'UNIT TYPE' PUSHJ P,XSKIP## ;IGNORE DEVICE 'CONTROLLER TYPE' PUSHJ P,XSKIP## ;IGNORE DEVICE 'FORMS TYPE' ;ALL IS HAPPY, SEND CONNECT CONFIRM TO REMOTE PUSHJ P,VTMXCN ;SEND A CONNECT CONFIRM JRST VTMCE2 ;OOPS, CAN'T, ABORT AND RETURN LAT SLOT PUSHJ P,VTMENQ ;GET THE BALL ROLLING PUSHJ P,TRM.UP## ;FLAG THE TERMINAL "UP" JRST UPOPJ1## ;THE VTM IS NOW CONNECTED ;VTM CONNECT INIT ERRORS VTMCE2: PUSHJ P,VTMLOC ;RESTORE THE TERMINAL TO [LOCAL] GOODNESS PUSHJ P,FRELDB## ;LDB DEFUNCT??? SHOULDN'T EVER HAPPEN! JFCL ;LDB ZAPPED? VTMCE3: MOVEI T1,RSN.OT ;CAN'T DO THE CONNECT JRST UPOPJ## ;ABORT AND RETURN BAD NEWS VTMCE4: MOVEI T1,RSN.XP ;THIS TERMINAL IS UNAVAILABLE JRST UPOPJ## ;ABORT AND RETURN BAD NEWS ;VTMNWD THE "NODE WENT DOWN" NDP ENTRY ;CALL F := LAT ENTRY ; P1 := NODE NUMBER OF NODE THAT HAS JUST GONE OFFLINE ;RETURN CPOPJ ;WITH TTY "LOCAL" IF LINE WAS "SET HOSTED" ; ; TO THE JUST CRASHED NODE. VTMNWD: PUSH P,U ;SAVE U MOVE U,F ;THE LDB ADDRESS IS CARRIED IN "U" LDB T1,LDPRNN## ;GET THE NODE NUMBER CAIE T1,(P1) ;COMPARE OUR NUMBER WITH THAT OF CRASHED NODE STOPCD .,STOP,VTMNDA, ;++ NODE NUMBER DOESN'T AGREE MOVEI T1,[ASCIZ \Path to host system was lost.\] PUSHJ P,VTMLOP ;MAKE LINE LOCAL AND TELL USER WHAT HAPPENED. PUSHJ P,FRELDB## ;DEFUNCT LDB, RETURN IT TO THE FREE POOL PJRST UPOPJ## ;IDLE PTY (OR THE LIKE), DON'T "GREET" IT PUSHJ P,TTFGRT## ;USEABLE LOCAL TERMINAL, "GREET" IT PJRST UPOPJ## ;RESTORE "U" AND WE'RE DONE. LINE IS NOW ; USABLE LOCALLY. ;VTMDCC ROUTINE TO HANDLE DISCONNECT MESSAGES FOR A VTM. ;CALL F := LDB ADDRESS (REALLY THE LAT ENTRY) ; W := NODE WHO SENT THE DISCONNECT ; P1 & P4 := POINTERS TO THE DISCONNECT MESSAGE ;RETURN CPOPJ ;BAD MESSAGE (CAN'T HAPPEN) ; CPOPJ1 ;DISCONNECT PROCESSED. ;THIS ROUTINE CHECKS THE REASON FOR THE DISCONNECT. IF IT IS ; "RSN.RC" (REASON -- RECONNECT) AN IMPLICIT "SET HOST" IS DONE VTMDCC: PUSHJ P,SAVJW## ;WE MAY CLOBBER THESE IF IT'S A "SET HOST" PUSH P,U ;SAVE INCOMING PCB POINTER MOVE U,F ;THE LDB ADDRESS IS CARRIED IN "U" LDB T1,LDPSLA## ;GET OUR LOCAL LAT ADDRESS LDB T2,LATSTA## ; AND GET OUR CONNECTION STATE. CAIN T2,LAT.CC ;SEE IF THIS IS A CONNECT REJECT. JRST [MOVEI T1,[ASCIZ \Host rejected connection.\] PJRST VTMDC7] ;RESTORE "U" AND RETURN CAIN T2,LAT.DC ;IS THIS A DISCONNECT CONFIRM JRST VTMDC6 ; IF D-CONFIRM, PRINT GREETING AND MAKE LOCAL IFN PARANOID&P$VTM,< ;IF WE'RE BEING CAUTIOUS, CAIE T2,LAT.OK ; MAKE SURE WE'RE IN A REASONABLE STATE STOPCD .,STOP,VTMILS, ;++ ILLEGAL STATE > ;FALL THROUGH TO PROCESS DISCONNECT INITIATE ;CONTINUED FROM PREVIOUS PAGE ;HERE WHEN WE RECEIVE A DISCONNECT INITIATE. SEND THE DISCONNECT ; CONFIRM, AND SEE IF WE MUST PERFORM AN IMPLICIT "SET HOST" MOVEI T1,RSN.OK ;GIVE AN "OK" REASON FOR THE CONFIRM EMRGCY ;USE THE EMERGENCY FREE-POOL IF NECESSARY PUSHJ P,TRMXDC## ;SEND THE DISCONNECT CONFIRM STOPCD .,STOP,VTMSDF, ;++ SEND DISCONNECT FAILED ;SLA PUSHJ P,XSKIP## ;SKIP OVER THE SLA (USELESS) ;RSN PUSHJ P,EBI2BI## ;GET THE REASON FOR THE DISCONNECT. CAIE T1,RSN.RC ;IF ITS NOT RECONNECT (SET HOST) JRST [MOVEI T1,[ASCIZ \Host sent disconnect.\] JRST VTMDC7] ;LOCAL'IZE LINE AND PRINT MESSAGE ;HERE TO DO THE IMPLICIT SET HOST. ;NNM PUSHJ P,EBI2BI## ;GET THE NUMBER OF THE NODE TO RECONNECT TO. HLRZ T2,NETNDB##+NDBNNM ;GET OUR LOCAL NODE NUMBER CAIN T1,(T2) ;IF THEY ARE THE SAME, THEN JRST VTMDC6 ; PRINT A GREETING AND LET HIM RUN HERE AGAIN PUSHJ P,SRCNDB## ;GET NDB OF HOST TO RECONNECT TO JRST [MOVEI T1,[ASCIZ \? Unable to complete SET HOST command.\] JRST VTMDC7] ;LOCAL'IZE LINE AND PRINT MESSAGE PUSHJ P,VTMCNT ;[RE]CONNECT TO REMOTE MCR SERVICE PJRST UPOPJ1## ;RESTORE PCB POINTER AND EXIT ;HERE TO MAKE A LINE LOCAL AND FORCE A GREETING VTMDC6: PUSHJ P,VTMLOC ;MAKE LINE LOCAL PUSHJ P,FRELDB## ;DEFUNCT LDB, RETURN IT TO SCNSER'S FREE POOL PJRST UPOPJ1## ;IDLE PTY (OR THE LIKE), DON'T GREET IT JRST VTMDC8 ;USEABLE LOCAL TERMINAL, GREET IT VTMDC7: PUSHJ P,VTMLOP ;MAKE LINE LOCAL AND PRINT MESSAGE PUSHJ P,FRELDB## ;DEFUNCT LDB, RETURN IT TO SCNSER'S FREE POOL PJRST UPOPJ1## ;IDLE PTY (OR THE LIKE), DON'T GREET IT VTMDC8: PUSHJ P,TTFGRT## ;GREET THE NEWFOUND TERMINAL PJRST UPOPJ1## ;RESTORE PCB AND RETURN ;VTMCNC ROUTINE TO PROCESS AN INCOMING CONNECT CONFIRM MESSAGE ;CALL W := NDB OF NODE WE'VE SENT A CONNECT TO ; F := LDB OF TERMINAL ; P1 & P4 := POINTER TO THE CONNECT CONFIRM MESSAGE ;RETURN CPOPJ ;ILLEGAL CONNECT CONFIRM MESSAGE ; CPOPJ1 ;LINK SET UP. TERMINAL NOW "SET HOSTED" TO ; ; OTHER SYSTEM. VTMCNC: PUSH P,U ;SAVE THE INCOMING PCB ADDRESS MOVE U,F ;THE LDB ADDRESS IS CARRIED IN "U" LDB T1,LDPSLA## ;GET OUR LOCAL LAT ADDRESS LDB T2,LATSTA## ; AND FROM THAT OUR LOCAL CONNECT STATE CAIE T2,LAT.CC ;IF WE'RE NOT IN CONNECT CONFIRM WAIT, JRST UPOPJ## ; THEN THIS IS AN ILLEGAL MESSAGE. ;DLA PUSHJ P,EBI2BI## ;GET THE LAT ADDR ASSIGNED TO US BY THE MCR JUMPE T1,UPOPJ## ;DON'T EVER USE A ZERO DLA... DPB T1,LDPDLA## ;STORE THE REMOTE LINE ADDRESS PUSHJ P,TRM.UP## ;INITIALIZE THE LINE, SET LRLCON. MOVE T1,LDBDCH##(U) ;GET THE CHARACTERISTICS FOR THIS LINE TRNN T1,LDRDSD## ; ARE WE A DATA-SET LINE? JRST VTMCN1 ;NOT A DATA SET, NEVER MIND LDB T1,LDPDSC## ;GET DATASET TABLE INDEX MOVE T1,DSCTAB##(T1) ;GET DATASET DATA TLNE T1,DSCSWC## ;IS THE CARRIER THERE? SKIPA T1,[XWD LRLSTS##+LRLSCH##,STY.DE+STY.DT+STY.RG] VTMCN1: MOVE T1,[XWD LRLSTS##+LRLSCH##,STY.DE] IORM T1,LDBREM##(U) ;SAY WE NEED TO SEND STATUS, GO TO DEFERED ECHO PUSHJ P,VTMENQ ;QUEUE THE VTM SO WE SEND THESE MESSAGES JRST UPOPJ1## ;DONE PROCESSING THE CONNECT-CONFIRM ;VTMDAP ROUTINE TO DIS-ASSEMBLE AN INCOMING DAP MESSAGE AND DISPATCH ; ON THE VARIOUS DAP SUB-MESSAGES. ;CALL F := LAT ENTRY (RH(F) = LDB POINTER) ; W := NDB THAT THE LINE IS CONNECTED TO ; P1 & P4 := BYTE POINTER & COUNT TO THE INCOMING MESSAGE ;RETURN CPOPJ ;MESSAGE WAS "BAD" IN ONE WAY OR ANOTHER ; CPOPJ1 ;MESSAGE HAS BEEN PROCESSED. VTMDAP: MOVE T1,PCBPTR(U) ;GET MESSAGE POINTER (SO WE CAN GET NCT LATER) PUSH P,U ;PRESERVE THE PCB ADDRESS MOVE U,F ;THE LDB ADDRESS IS CARRIED IN "U" ;NOW LOOK AT THE NCT BYTE TO SEE IF THIS MESSAGE IS INTERRUPT OR NORMAL ILDB T1,T1 ;GET THE NCT BYTE TRNE T1,NCT.IT ; AND SEE IF IT HAS THE INTERRUPT BIT SET JRST VTMDP1 ;IT'S AN INTERRUPT MSG. LEAVE DRQ ALONE. LDB T1,LDPDRQ## ;IT'S NORMAL DATA. GET THE DRQ COUNT SOSGE T1 ; AND COUNT OFF ONE LESS OUTSTANDING DRQ PJSP T1,VTMDP3 ;IF DRQ WENT NEGATIVE, REMEMBER OUR PC ; FIXUP THE STACK AND MARK THE MSG AS BAD. DPB T1,LDPDRQ## ;STORE THE UPDATED DRQ ;DROP THROUGH TO DISSECT THE INCOMING MESSAGE. VTMDP1: JUMPLE P4,UPOPJ## ;IF AT END OF MESSAGE, GIVE GOOD RETURN ;CNT PUSHJ P,EBI2BI## ;GET THE LENGTH OF THIS SUB-MESSAGE SUB P4,T1 ; CALCULATE LENGTH OF REMAINDER OF MSG. SKIPGE P4 ;MAKE SURE MSG LENGTH DOESN'T GO NEGATIVE PJSP T1,VTMDP3 ;IF SUB MSG LONGER THAN MSG, TOSS MSG AS BAD PUSH P,P4 ;REMEMBER HOW MUCH IS LEFT IN THE MESSAGE MOVEI P4,(T1) ; AND SET UP THE LENGTH FOR THIS SUB-MSG ;TYPE PUSHJ P,EBI2BI## ;GET THE IDC TYPE FIELD CAIL T1,DC.DAT ;RANGE CHECK IT CAILE T1,DC.CTL ; SO WE DON'T JUMP OFF INTO THE WEEDS PJSP T1,VTMDP2 ;IF OUT OF RANGE TYPE, REPORT BAD MESSAGE PUSHJ P,@TTYNDP(T1) ;CALL THE APPROPRIATE SUB-MSG PROCESSOR PJSP T1,VTMDP2 ; AND IF HE THINKS THE MSG IS BAD, TOSS IT. SOJG P4,[IBP P1 ;SKIP TO THE END OF THE SUB-MSG JRST .] ; SO WE'RE READY TO READ THE NEXT "CNT" FIELD POP P,P4 ;RECOVER THE LENGTH OF THE UNPROCESSED PART JRST VTMDP1 ; AND GO DO THE NEXT SUB-MESSAGE ;HERE IF FOR SOME REASON WE THINK THE MESSAGE IS BAD. ;CALL T1 := ADDRESS OF CODE THAT DECIDED IT DIDN'T LIKE THE MSG VTMDP2: POP P,P4 ;FIXUP THE STACK IF WE HAVE THE LENGTH ON IT VTMDP3: POP P,U ;GET THE PCB POINTER BACK FOR INCTBD JRST INCTBD## ;MARK THE MESSAGE AS BAD & RETURN ;VTMDAT ROUTINE TO PROCESS INCOMING DAP-DATA MESSAGES ;CALL U := POINTER TO LDB ; P1 & P4 := POINTER AND LENGTH OF DATA TO STORE. ;RETURN CPOPJ ;ONLY IF WE GOT A ZERO LENGTH MSG ; CPOPJ1 ;DATA COPIED INTO OUTPUT BUFFER AND ; ; OUTPUT HAS BEEN STARTED. VTMDAT: JUMPLE P4,CPOPJ## ;WE DON'T LIKE ZERO LENGTH MSGS ;FIRST MAKE SURE WE HAVE ENOUGH CHUNKS TO ACCOMODATE THIS DATA MOVE T1,TTFREN## ;GET NUMBER OF FREE CHUNKS IMULI T1,CK.CPC## ;CONVERT THAT NUMBER INTO CHARACTERS CAIG T1,10(P4) ; AND SEE IF MSG (PLUS A FUDGE) WILL FIT POPJ P, ;SAY THAT MESSAGE IS BAD IF IT WON'T FIT MOVE T1,LDBTOC##(U) ;GET THE NUMBER OF CHARS TO OUTPUT CAIL T1,+100 ;SEE IF IT'S MORE THAN "MAXODR" POPJ P, ; DRQ'S WORTH OF DATA. IF SO, TOSS IT. ; SOME-ONE IS SENDING US DATA WE DIDN'T ASK ; FOR. (CALCULATION IS BASED ON "NTTPLN" WORD ; MESSAGES OF 4 CHARS PER WORD) MOVE T4,LDBREM##(U) ;GET THE DAP-STATUS WORD TRNN T4,STY.IO ; AND IF WE'RE NOT DOING IMAGE OUTPUT TDZA T4,T4 ; MAKE OUR "IOR" MASK ZERO. MOVEI T4,CK.IMG## ; IF IMAGE-OUT, GET MASK TO SET "IMAGE" BIT SCNOFF ;GET A LITTLE PROTECTION WHILE WE HACK CHUNKS ADDM P4,LDBTOC##(U) ;COUNT THE CHARS WE'RE ABOUT TO STUFF VTMDA1: ILDB T3,P1 ;GET THE NEXT CHAR IOR T3,T4 ;SET THE IMAGE BIT IF WE'RE IN IMAGE MODE TRNN T3,CK.IMG## ;ARE WE? SKIPGE LDBATR##(U) ;OR ARE WE IN 8-BIT MODE? EXTERN LAL8BT ;FLAG BIT REFERENCED TRNA ;YES, SKIP ON TRZ T3,CK.PAR## ;NO, CLEAR THAT OBNOXIOUS PARITY BIT STCHK T3,LDBTOP##(U),VTMDA5 ;STORE THE CHAR IN THE OUTPUT CHAIN SOJG P4,VTMDA1 ;LOOP OVER ALL CHARS. SCNON ;ALL'S CONSISTANT AGAIN. TURN ON INTS. PUSHJ P,TOPOKE## ;START THE LINE TYPING RETSKP ; AND GIVE A GOOD RETURN ;EAT REST OF DATA SUB-MESSAGE (NO ROOM IN CHUNKS) ILDB T3,P1 ;ADVANCE P1 VTMDA5: SOJG P4,.-1 ;LOOP SCNON ;RELEASE INTERLOCK POPJ P, ;ERROR ;VTMSTS ROUTINE TO PROCESS INCOMING DAP-STATUS MESSAGES ;CALL U := POINTER TO THE LDB ; P1 & P4 := POINTER TO, AND LENGTH OF THE MESSAGE ;RETURN CPOPJ ;IF IT'S A GARBAGE MESSAGE ; CPOPJ1 ;STATUS MESSAGE PROCESSED. VTMSTS: ;PROCESS VTM STATUS ;STC PUSHJ P,EBI2BI## ;READ THE STATUS CODE CAIL T1,STC.SB ;RANGE CHECK THE CODE (1 = SET BITS) CAILE T1,STC.CB ; (2 = CLEAR BITS) POPJ P, ;STATUS CODE NOT SET/CLEAR. SOS T4,T1 ;COPY THE STATUS CODE (MINUS ONE) ;STY PUSHJ P,EBI2BI## ;READ THE STATUS BITS TO SET/CLEAR IFN FTKL10,< TRNN T1,STY.XS ;DO WE WANT OUTPUT STOPPED OR STARTED? JRST VTMST3 ;NO HRRZ T2,LDBISR##(U) ;GET ISR DISPATCH CAIE T2,TTDDSP## ;IS THIS A -20F LINE JRST VTMST3 ;NO MOVSI T2,LTLXFF## ;YES, SET BIT TO INFORM -20F IORM T2,LDBTTD##(U) ; > ;END IFN FTKL10 VTMST3: MOVE T2,LDBREM##(U) ;SAVE THE PREVIOUS STATUS FOR A BIT XCT [IORB T1,LDBREM##(U) ;SET OR ANDCAB T1,LDBREM##(U)](T4) ;CLEAR THE BITS AS DIRECTED TRNN T2,STY.DE ;IF WE WERE IN LOCAL ECHO TRNN T1,STY.DE ; AND WE ARE NOW IN REMOTE CAIA ; (IE DEFERRED ECHO) PUSHJ P,VTMEDM ; THEN SEND THE HOST A STATUS MSG ;CONTINUED ON NEXT PAGE ;CONTINUED FROM PREVIOUS PAGE ;MAKE LDBDCH AGREE WITH LDPSTS (LH(T2) = BITS TO SET, RH(T2) = CLEAR) MOVE T1,LDBREM##(U) ;RESTORE BITS SETZ T2, ;START WITH NO BITS TO CHANGE TRNE T1,STY.XS ;IF WE WANT OUTPUT STOPPED, TLOA T2,LOLSTP## ; THEN SET THIS BIT TRO T2,LOLSTP##!LOLSSO## ;OTHERWISE CLEAR THESE BITS HLLZ T3,T2 ;COPY BIT TO SET IORM T3,LDBOST##(U) ;SET IN APPROPRIATE WORD HRLZ T3,T2 ;GET BITS TO CLEAR ANDCAM T3,LDBOST##(U) ;DO SO SETZ T2, ;CLEAR FOR LDBDCH BITS TRNE T1,STY.HT ;IF WE HAVE HARDWARE TABS TLOA T2,LDLTAB## ; THEN TELL SCNSER TRO T2,LDLTAB## ; CLEAR BIT IF NO TABS TRNE T1,STY.FF ;IF WE HAVE TTY FORM TLOA T2,LDLFRM## ; SET THE BIT TRO T2,LDLFRM## ; OTHERWISE CLEAR IT TRNN T1,STY.CR ;IF WE'RE DOING FREE CRLF TROA T2,LDLNFC## ; THEN CLEAR THE "NO FREE CRLF" BIT TLO T2,LDLNFC## ; OTHERWISE SET IT. HRLZ T3,T2 ;GET THE BITS TO CLEAR ANDCAM T3,LDBDCH##(U) ; AND CLEAR THEM HLLZ T3,T2 ;GET THE BITS TO SET, IORM T3,LDBDCH##(U) ; AND SET THEM. ;NOW MAKE LDBBY2 AGREE WITH LDPSTS MOVEI T2,L2RXON## ;THE "SET TTY TAPE" BIT TRNE T1,STY.TT ;IF WE'RE IN TERMINAL TAPE MODE SKIPA T3,[IORM T2,LDBBY2##(U)] ;THEN SET THE BIT MOVE T3,[ANDCAM T2,LDBBY2##(U)] ;OTHERWISE CLEAR IT XCT T3 ;SET/CLEAR THE BIT ;NOW MAKE THE MODEM CONTROL BITS AGREE WITH THE MODEM STATUS PUSHJ P,SETCHP## ;KICK THE LINE INCASE WE JUST STARTED OUTPUT RETSKP ;ALL DONE WITH STATUS MESSAGE ;VTMCTL ROUTINE TO DISPATCH ON INCOMING DAP-CONTROL MESSAGES ;CALL U := POINTER TO THE LDB ; P1 & P4 := POINTER TO, AND LENGTH OF THE CONTROL MESSAGE ;RETURN CPOPJ ;IF MESSAGE IS BAD ; CPOPJ1 ;IF MESSAGE IS PROCESSED. VTMCTL: PUSHJ P,EBI2BI## ;GET THE CONTROL-MESSAGE TYPE SKIPL T1 ;RANGE CHECK THE TYPE CAILE T1,DCT.AB ; SO WE DON'T JUMP OFF INTO THE WEEDS POPJ P, ;BAD CONTROL TYPE. GIVE "BAD-MSG" RETURN JRST @.+1(T1) ;DISPATCH ON THE CONTROL CODE IFIW VTMEPM ; (0) = ECHO PIPELINE MARKER IFIW VTMCGB ; (1) = CHARACTER GOBBLER (^O) IFIW VTMCHR ; (2) = "CHARACTERISTICS" (SPEED ETC.) IFIW VTMADL ; (3) = AUTO DIAL-OUT IFIW VTMXOF ; (4) = SEND "XOFF" IMMEDIATLY IFIW VTMABR ; (5) = AUTOBAUD REQUESTED ;VTMEPM ROUTINE TO PROCESS AN INCOMING ECHO-PIPELINE-MARKER. ;CALL U := POINTER TO THE LDB ; P1 & P4 := POINTER TO AND LENGTH OF SUB MESSAGE ;RETURN CPOPJ ;NEVER ; CPOPJ1 ;EPM PROCESSED. ;FCN IF THE EPM SERIAL NUMBER MATCHES THE LAST ONE SENT, THEN ; THERE ARE NO MORE CHARS IN THE "PIPELINE". IN THIS CASE ; WE CAN GO INTO LOCAL ECHO ONLY IF WE HAVE NO INPUT CHARS ; QUEUED FOR THE REMOTE HOST. VTMEPM: PUSHJ P,BYT2BI## ;GET THE 8 BIT EPM SERIAL NUMBER LDB T2,LDPEPM## ;GET THE SERIAL NUMBER OF THE LAST EPM SENT CAIE T1,(T2) ;IF WE HAVEN'T GOTTEN OUR LAST EPM BACK RETSKP ; THEN THERE ARE STILL CHARS IN THE PIPE MOVEI T1,STY.DE ;GET THE "REMOTE IS ECHOING" BIT TDNN T1,LDBREM##(U) ;SEE IF WE ARE ALREADY IN LOCAL ECHO RETSKP ; IF IN LOCAL ECHO, IGNORE EXTRA EPM SCNOFF ;MAKE SURE WE DON'T ECHO A CHAR FOR A WHILE SKIPN LDBTIC##(U) ;MAKE SURE THAT NO CHARS HAVE SKIPE LDBECC##(U) ; SNUCK IN WHILE WE WEREN'T LOOKING JRST SONPJ1## ;IF CHARS QUEUED, DON'T ENTER LOCAL ECHO MODE ANDCAB T1,LDBREM##(U) ;CLEAR REMOTE ECHO (ENABLE LOCAL ECHO) DPB T1,LDPDST## ;SAVE THE STATUS MESSAGE MOVSI T1,LRLDST## ;GET THE BIT SAYING A STATUS MSG IS "SAVED" IORM T1,LDBREM##(U) ; SO THAT NEXT TIME WE START A MESSAGE ; FOR THE REMOTE WE WILL SEND A STATUS ; MESSAGE TELLING HIM WE'RE LOCAL ECHOING SCNON ;INTERRUPTS OK NOW. AOS (P) ;GIVE GOOD RETURN PJRST VTMENQ ;NOW QUEUE THE LINE TO SEND THE STATUS ; *** NOTE *** WHILE IT WOULD BE NICE ; TO BE ABLE TO DELAY SENDING THIS STATUS ; MESSAGE, UNTIL NETMCR GETS SMARTER ABOUT ; TELLING US IF WE SHOULD ECHO OR NOT, WE ; MUST INFORM IT IMMEDIATLY UPON ENTERING ; LOCAL ECHO MODE. IF WE DON'T, PASSWORDS ; WILL ECHO... ;VTMCGB ROUTINE TO PROCESS A "CHARACTER GOBBLER" (^O) REQUEST ;CALL U := POINTER TO THE LDB ; P1 & P4 := POINTER TO, AND LENGTH OF SUB MSG (WE IGNORE IT) ;RETURN CPOPJ ;NEVER ; CPOPJ1 ;OUTPUT STREAM "GOBBLED" VTMCGB: PUSHJ P,TSETBO## ;SCNSER DOES ALL THE WORK RETSKP ;GIVE GOOD RETURN ;VTMCHR ROUTINE TO PROCESS AN INCOMING CHARACTERISTICS MESSAGE ;CALL U := POINTER TO THE LDB ; P1 & P4 := POINTER TO, AND LENGTH OF THIS SUB-MESSAGE ;RETURN CPOPJ ;SOMETHING WAS WRONG WITH THE MESSAGE ; CPOPJ1 ;MESSAGE PROCESSED VTMCHR: PUSHJ P,EBI2BI## ;GET BACK-SPACE FILL TIME PUSH P,T1 ; AND SAVE FOR JUST A BIT PUSHJ P,EBI2BI## ;GET H-TAB FILL TIME HRLM T1,(P) ; AND SAVE THAT TOO. PUSHJ P,EBI2BI## ;GET LF FILL TIME (IGNORE) PUSHJ P,EBI2BI## ;GET V-TAB FILL TIME (IGNORE) PUSHJ P,EBI2BI## ;GET FORM FEED FILL TIME (IGNORE) PUSHJ P,EBI2BI## ;GET CR FILL TIME (IGNORE) ;NOW WE MUST GUESS WHAT FILL CLASS WE WANT GIVEN THE TIMES. ; RATHER THAN TRY TO INVERT THE ALGORITHM IN NETMCR(TTXTCR), ; THIS CODE RELYS ON THE FACT THAT ONE CAN DETERMINT THE ; CLASS FROM THE FIRST TWO ENTRIES IN FILTAB. ;EG. BSP H-TAB CLASS ; 0 0 0 ; 2 2 1 ; 6 0 2 ; 6 2 3 POP P,T2 ;GET XWD H-TAB,BSP FILL TIMES BACK MOVEI T1,3 ;INITIALIZE "T1" FOR THE SOS'ES COMING UP JUMPE T2,VTMCH1+0 ;IF BOTH ARE "0" THEN FILL CLASS MUST BE TOO. TLNN T2,-1 ;IF "H-TAB" IS ZERO, THEN JRST VTMCH1+2 ; WE HAVE FILL CLASS "2" TSC T2,T2 ;COMPARE THE TWO TIMES JUMPE T2,VTMCH1+1 ;IF EQUAL, THEN FILL CLASS = 1 JRST VTMCH1+3 ;IF NOT EQUAL, THEN CLASS = 3 VTMCH1: SOS T1 ;HERE FOR FILL CLASS 0 SOS T1 ;HERE FOR FILL CLASS 1 SOS T1 ;HERE FOR FILL CLASS 2 ; JFCL ;HERE FOR FILL CLASS 3 DPB T1,LDPFLC## ;REMEMBER THE FILL CLASS ;DROP THROUGH TO PROCESS THE REST OF THE MSG (SPEEDS ETC...) ;NOW PROCESS THE SPEEDS ETC. PUSH P,P2 ;PROTECT P2 FROM RAVAGES OF COMCON PUSHJ P,EBI2BI## ;GET THE RECEIVE SPEED MOVEI T2,(T1) ;COPY IT FOR COMCON PUSHJ P,TTCSP1## ;TRANSLATE SPEED INTO AN INDEX LDB P2,LDPRSP## ;IF ILLEGAL SPEED, THEN DON'T CHANGE IT DPB P2,LDPRSP## ;STORE THE NEW SPEED PUSHJ P,EBI2BI## ;GET THE TRANSMIT SPEED MOVEI T2,(T1) ;COPY IT FOR COMCON PUSHJ P,TTCSP1## ;TRANSLATE SPEED INTO INDEX LDB P2,LDPTSP## ;DON'T CHANGE SPEED IF IT'S ILLEGAL DPB P2,LDPTSP## ;STORE THE NEW TRANSMIT SPEED POP P,P2 ;RESTORE P2 PUSHJ P,EBI2BI## ;READ THE WIDTH SKIPE T1 ;DON'T SET WIDTH TO ZERO DPB T1,LDPWID## ;STORE THE NEW WIDTH PUSHJ P,EBI2BI## ;READ THE AUTO-CRLF POSITION DPB T1,LDPACR## ; AND STORE THAT (ZERO IS OK) PUSHJ P,XSKIP## ;SKIP 2741 ELEMENT NUMBER (NOT IMPLEMENTED) PUSHJ P,EBI2BI## ;GET FORMERLY-2741 BITS TRNN T1,CDT.8B ;CHECK FOR 8-BIT TDZA T2,T2 ;NO, MOVEI T2,1 ;OR YES DPB T2,LDP8BT## ;TELL SCNSER TRNN T1,CDT.PL ;TEST APL MODE TDZA T2,T2 ;NO, MOVEI T2,1 ;OR YES DPB T2,LDPAPL## ;TELL SCNSER TRNN T1,CDT.FT ;CHECK FOR "FORMS TYPE" TDZA T1,T1 ;NOT PRESENT PUSHJ P,EAS2SX## ;YES, FETCH IT SKIPE T2,T1 ;MOVE FOR COMCON PUSHJ P,TTUTYP## ;SET TTY TYPE JFCL ;IGNORE FAILURE PUSHJ P,SETCHP## ;QUEUE A KICK TO THE LINE DRIVER'S HARDWARE RETSKP ;GIVE GOOD RETURN ;VTMADL ROUTINE TO PROCESS AN AUTO-DIAL MESSAGE ;CALL U := POINTER TO THE LDB ; P1 & P4 := POINTER TO, AND LENGTH OF THE SUB MSG ;RETURN CPOPJ ;IF MESSAGE IS BAD ; CPOPJ1 ;WITH AUTO-DIAL MESSAGE PROCESSED VTMADL: POPJ P, ;WE DON'T HANDLE THIS MESSAGE ;VTMXOF ROUTINE TO PROCESS THE "SEND XOFF IMMEDIATELY" REQUEST ;CALL U := POINTER TO THE LDB ; P1 & P4 := POINTER TO, AND LENGTH OF THE SUB MSG (NULL) ;RETURN CPOPJ ;NEVER ; CPOPJ1 ;XOFF FILLER POINTER SET. VTMXOF: MOVE T2,FLPPXF## ;GET THE XOFF FILLER POINTER PUSHJ P,SETXNP## ;CALL SCNSER TO SET THE "XON CLASS" FILL PTR PUSHJ P,TOPOKE## ;KICK THE LINE (PROBABLY NOT NECESSARY...) RETSKP ;GIVE GOOD RETURN, XOFF FILLER QUEUED TO GO. ;VTMABR ROUTINE TO PROCESS AN AUTOBAUD REQUEST ;CALL U := POINTER TO THE LDB ; P1 & P4 := POINTER TO, AND LENGTH OF SUB MSG (WE IGNORE IT) ;RETURN CPOPJ ;FUNCTION NOT AVAILABLE ; CPOPJ1 ;AUTOBAUD SEQUENCE INITIATED VTMABR: SKIPL LDBISB##(U) ;CLEVER FE? POPJ P, ;NO--INVALID REQUEST MOVSI T1,LRLATO## ;IN AUTOBAUD SEQUENCE IORM T1,LDBREM##(U) ;FLAG THE LINE DPB T1,LDPSPD## ;CLEAR CURRENT SPEED IDEAS DPB T1,[POINT 8,LDBCCH##(U),35] ;EVERYWHERE WE CAN MOVEI T1,ISRLPC ;LINE PARAMETER CHANGE MOVEI T3,B27 ;AUTOBAUD REQUEST PUSHJ P,@LDBISR##(U) ;KICK THE FE RETSKP ;GOOD RETURN FOR THIS MESSAGE ;HERE WHEN THE FE HAS SET THE SPEED VTMSPD::PUSHJ P,SAVT## ;SAVE A REGISTER MOVSI T1,LRLATO## ;NO MORE AUTOBAUD ANDCAM T1,LDBREM##(U) ;CLEAR THE BIT MOVSI T1,LRLSCH## ;SEND CHARACTERSITICS IORM T1,LDBREM##(U) ;SET THAT BIT PJRST VTMENQ ;MAKE SURE WE GET QUEUED ;VTMSCN ROUTINE TO SCAN THE STAUS OF A VTM AND SEND MESSAGES NEEDED. ;CALL U := LDB OF VTM ;RETURN CPOPJ ;NO CORE. REQUEUE THE LINE ; CPOPJ1 ;PROCESSING COMPLETED. ;FUNCTION ; VTMSCN CHECKS FOR MESSAGES TO SEND IN THE FOLLOWING PRIORITY: ; . CHARACTERISTICS (NEEDED IMMEDIATLY AFTER A CONNECT) ; . DELAYED STATUS (STATUS SAVED JUST AS LINE GOES INTO LOCAL ECHO) ; . CHARACTERS IN THE "LOCAL ECHOED" CHAIN. ; . NORMAL STATUS ; . CHARACTERS IN THE "REMOTE ECHO" CHAIN ; . ECHO PIPELINE MARKERS. VTMSCN: MOVE T1,LDBREM##(U) ;GET THE REMOTE STATUS BITS TLNE T1,LRLSCH## ;SEE IF WE NEED TO SEND CHARACTERISTICS JRST [PUSHJ P,VTMXCH ;SEND THE CHARACTERISTICS JRST VTMSC1 ;REQUEUE THE LINE IF NO CORE JRST VTMSCN] ;SEE WHAT ELSE THERE IS TO DO. TLNE T1,LRLATO## ;WAITING FOR FE TO AUTOBAUD? JRST VTMSC2 ;YES--WAIT FOR SPEED TLNE T1,LRLDST## ;DO WE HAVE A "DELAYED STATUS" MESSAGE TO SEND JRST [PUSHJ P,VTMXDS ;SEND THE DELAYED STATUS JRST VTMSC1 ;REQUEUE THE LINE IF NO CORE JRST VTMSCN] ;SEE WHAT ELSE THERE IS TO DO SKIPE LDBECC##(U) ;ANY "LOCALLY ECHOED" CHARS TO GO JRST [PUSHJ P,VTMXEC ;SEND THE "ECHOED" CHARS JRST VTMSC1 ;NO CORE. REQUEUE LINE JRST VTMSCN] ;GO LOOK AT THE LINE AGAIN TLNE T1,LRLSTS## ;DO WE NEED TO SEND "NORMAL" STATUS JRST [PUSHJ P,VTMXST ;SEND THE STATUS JRST VTMSC1 ;NO CORE JRST VTMSCN] SKIPE LDBTIC##(U) ;ANY "REMOTE ECHO" CHARS TO GO JRST [PUSHJ P,VTMXUC ;SEND THE "UN-ECHOED CHARS" JRST VTMSC1 ;NO CORE JRST VTMSCN] ;RELOAD T1 AND HAVE ANOTHER GO AT IT... PUSHJ P,CHKXON## ;SEND AN XON (IF WE OWE ONE) NOW THAT ; WE'VE EMPTIED THE CHUNKS. PUSHJ P,VTMXEP ;TRY TO SEND AN ECHO-PIPELINE MARKER JRST VTMSC1 ;NO CORE. REQUEUE VTMSC2: AOS (P) ;SCAN IS COMPLETE. GIVE GOOD RETURN VTMSC1: PUSHJ P,TSDPCB## ;FORCE ANY PARTIAL MESSAGES OUT. POPJ P, ;ALL DONE. RETURN ;VTMXCH ROUTINE TO SEND THE "CHARACTERISTICS" MESSAGE FOR A VTM ;CALL U := POINTER TO THE LDB ;RETURN CPOPJ ;NO CORE ; CPOPJ1 ;MESSAGE SENT VTMXCH: PUSHJ P,GETCR## ;GET THE "CONDENSED CHARACTERISTICS" IN T1 TRNE T1,377 ;NO SPEED? JRST VTMXC1 ;NO--SEND THE MESSAGE MOVE T2,LDBREM##(U) ;YES--GET BITS TLNE T2,LRLATO## ;IF WAITING FOR AUTOBAUD FROM FE, RETSKP ;JUST PRETEND VTMXC1: PUSHJ P,TRXTCR## ;CALL ROUTINE IN NETMCR TO SEND THEM POPJ P, ;NO CORE. GIVE ERROR ROUTINE MOVSI T1,LRLSCH##!LRLATO## ;GET THE "CHARACTERISTICS REQUEST" BIT ANDCAB T1,LDBREM##(U) ; AND CLEAR THE REQUEST. RETSKP ;GIVE GOOD RETURN ;VTMXDS ROUTINE TO SEND THE "DELAYED" STATUS MESSAGE FOR A VTM. ;CALL U := POINTER TO THE LDB ;RETURN CPOPJ ;NO CORE ; CPOPJ1 ;DELAYED STATUS SENT, LRLDST CLEARED VTMXDS: LDB T1,LDPDST## ;GET THE DELAYED STATUS MOVEI T2,0 ;GET THE DAP STATUS CODE (FULL STATUS) PUSHJ P,MCXSTA## ;CALL NETMCR TO SEND THE MSG POPJ P, ;GIVE ERROR RETURN IF NO CORE MOVSI T1,LRLDST## ;GET THE "DELAYED STATUS" QUEUED BIT ANDCAB T1,LDBREM##(U) ; AND CLEAR IT SO WE DON'T SEND IT AGAIN RETSKP ;GIVE GOOD RETURN WITH MSG SENT ;VTMXST ROUTINE TO SEND THE "NORMAL" STATUS MESSAGE FOR A VTM. ;CALL U := POINTER TO THE LDB ;RETURN CPOPJ ;IF NO CORE ; CPOPJ1 ;STATUS SENT VTMXST: LDB T1,LDPSTS## ;GET THE DAP STATUS BITS PUSHJ P,MCXSTA## ;CALL NETMCR TO SEND THE STATSU POPJ P, ;GIVE AN ERROR RETURN IF NO CORE MOVSI T1,LRLSTS## ;GET THE "PLEASE SEND STATUS" REQUEST ANDCAB T1,LDBREM##(U) ; BIT, AND CLEAR IT SO WE DON'T SEND IT AGAIN RETSKP ;GIVE GOOD RETURN NOW THAT MSG HAS GONE. ;VTMXEC ROUTINE TO SEND THE "LOCALLY ECHOED" CHARACTERS ;CALL U := POINTER TO THE LDB ;RETURN CPOPJ ;NO CORE. ; CPOPJ1 ;ALL CHARACTERS SENT. VTMXEC: MOVEI T1,2 ;MINIMUM ACCEPTABLE LENGTH PUSHJ P,TRQPCB## ;REQUEST A PCB POPJ P, ;GIVE ERROR RETURN IF NO CORE ;TYP XMTI DC.DAT ;SEND "DATA WITHOUT EOR" SCNOFF ;NO INTERRUPTS WHILE WE LOOK AT CHUNKS. PUSH P,P4 ;SAVE NETMCR'S "P4" SOS P4 ;ACCOUNT FOR THE DAP MSG TYPE JUST WRITTEN CAMLE P4,LDBECC##(U) ;IF ALL THE CHARS WILL FIT IN THE MESSAGE MOVE P4,LDBECC##(U) ; THEN USE THE SMALLER VALUE. MOVN P4,P4 ;GET "MINUS" THE NUMBER ADDM P4,LDBECC##(U) ;ACCOUNT FOR THE NUMBER WE'RE ABOUT TO SEND IFN PARANOID&P$VTM,< SKIPGE P4 ;MAKE SURE THIS COUNT IS NEGATIVE, SKIPGE LDBECC##(U) ; AND THIS ONE ISN'T STOPCD .,STOP,VTMECC, ;++ ECHO COUNTS MESSED UP > VTMXE1: LDCHKR T1,LDBTIT##(U),VTMXE3 ;GET THE NEXT CHARACTER XMT1 T1 ;WRITE THE CHAR AOJL P4,VTMXE1 ;LOOP OVER ALL THE CHARS VTMXE3: POP P,P4 ;GET THE MESSAGE LENGTH BACK FOR NETMCR SCNON ;CHUNKS ARE CONSISTANT AGAIN PUSHJ P,TWRPCB## ;SEND THE DATA SKIPE LDBECC##(U) ;IF THERE ARE MORE CHARS, JRST VTMXEC ; THEN GO SEND THEM RETSKP ;ALL DONE. GIVE GOOD RETURN ;VTMXUC ROUTINE TO SEND THE "NOT LOCALLY ECHOED" CHARACTERS ;CALL U := POINTER TO THE LDB ;RETURN CPOPJ ;NO CORE. ; CPOPJ1 ;ALL CHARACTERS SENT. VTMXUC: MOVEI T1,2 ;MINIMUM ACCEPTABLE LENGTH PUSHJ P,TRQPCB## ;TRY TO GET A PCB (AND SCREW UP THE STACK) POPJ P, ;NO CORE. GIVE ERROR RETURN ;TYP XMTI DC.DAT ;SEND "DATA WITHOUT EOR" PUSH P,P1 ;SAVE "P1" AND KEEP THE CONTENTS OF MOVE P1,LDBREM##(U) ; LDBREM IN IT FOR THE ENTIRE LOOP SCNOFF ;NO INTERRUPTS WHILE WE LOOK AT CHUNKS. PUSH P,P4 ;SAVE NETMCR'S "P4" SOS P4 ;ACCOUNT FOR THE DAP MSG TYPE JUST WRITTEN VTMXU1: SOSGE LDBTIC##(U) ;COUNT OUT ONE MORE CHAR FROM CHUNKS JRST [AOS LDBTIC##(U); IF NO MORE, FIX UP THE COUNT JRST VTMXU2] ; AND SEND THE MESSAGE. LDCHKR T1,LDBTIT##(U),VTMXU2 ;GET THE NEXT CHARACTER XMT1 T1 ;WRITE THE CHAR ANDI T1,177 ;MASK OFF PARITY CAIN T1,"S"-100 ;IF THE CHAR IS A CONTROL "S" JRST VTMXU2 ;EXIT THE LOOP TO LET XOFF BE SENT SOJG P4,VTMXU1 ;LOOP OVER ALL THE CHARS VTMXU2: POP P,P4 ;GET THE MESSAGE LENGTH BACK FOR NETMCR SCNON ;CHUNKS ARE CONSISTANT AGAIN POP P,P1 ;RECOVER "P1" PUSHJ P,TWRPCB## ;SEND THE DATA SKIPE LDBTIC##(U) ;IF THERE ARE MORE CHARS, JRST VTMXUC ; THEN GO SEND THEM RETSKP ;ALL DONE. GIVE GOOD RETURN ;VTMXEP ROUTINE TO SEND AN ECHO-PIPELINE-MARKER (IF NECESSARY) ;CALL U := LDB POINTER ;RETURN CPOPJ ;NO CORE ; CPOPJ1 ;EITHER NO REASON SEND AN EPM, OR EPM SENT. VTMXEP: MOVE T1,LDBREM##(U) ;GET THE REMOTE STATUS BITS TRNE T1,STY.DE ;IF WE'RE ALREADY IN LOCAL ECHO, TRNE T1,STY.II ; OR WE'RE DOING IMAGE MODE INPUT, RETSKP ;THEN THERE'S NO REASON TO SEND AN EPM. PJRST TRXEPM## ;LET NETMCR DO ALL THE WORK... ;VTMXDQ ROUTINE TO SEND ANY DATA-REQUESTS THAT ARE NECESSARY. ;CALL U := POINTER TO THE LDB ;RETURN CPOPJ ;NO CORE ; CPOPJ1 ;ALL CAUGHT UP W.R.T. DRQ'S VTMXDQ: MOVE T1,LDBTOC##(U) ;GET THE COUNT OF CHARS TO OUTPUT CAILE T1,^D100 ;IF THERE ARE MORE THAN THIS MANY, RETSKP ; THEN DON'T SEND ANY MORE DRQ'S MOVE T1,TTFREN## ;GET THE COUNT OF FREE CHUNKS CAIG T1,^D25 ; AND REQUIRE THAT THERE BE AT LEAST RETSKP ; THIS MANY FREE. LDB T1,LDPDRQ## ;GET THE NUMBER OF OUTSTANDING DRQ'S MOVN T1,T1 ;GET MINUS THE NUMBER OF DRQ ADDI T1,MAXODR## ;T1 = (MAXODR - NUMBER OF DRQ'S) SKIPG T1 ;SKIP IF WE NEED TO SEND SOME. RETSKP ;RETURN IF WE'VE ALREADY SENT THE DRQ'S PUSH P,T1 ;SAVE THE NUMBER OF MESSAGES WE WILL REQUEST PUSH P,U ;SAVE OUR LDB POINTER PUSHJ P,NCMHDR## ;CALL NETSER TO GET A CONTROL MESSAGE HEADER. JRST [POP P,U ;IF NO CORE, FIXUP THE STACK JRST TPOPJ##] ; AND GIVE THE "NO CORE" RETURN. EXCH U,-1(P) ;GET OUR LDB ADDRESS BACK ;TYP XMTI NC.DQR ;THE "TYPE" IS DATA-REQUEST ;DLA XMTB LDPDLA## ;SEND OUR FRIENDS REMOTE LINK ADDRESS ;DRQ XMT -2(P) ;WRITE THE DATA-REQUEST COUNT EXCH U,-1(P) ;GET THE PCB BACK, SAVE LDB ADDRESS JSP T1,NETWRC## ;FINISH OFF AND SEND THE CONTROL MSG POP P,U ;CLEAN UP THE STACK LDB T1,LDPDRQ## ;GET THE OLD DATA-REQUEST COUNT POP P,T2 ;GET THE VALUE OF THIS DRQ ADD T1,T2 ;GET THE TOTAL OUTSTANDING DRQ DPB T1,LDPDRQ## ; AND SAVE THAT RETSKP ;ALL DONE. RETURN SUCCESSFULLY ;VTMSTE & VTMSTI -- ROUTINES TO STORE CHARACTERS IN THE LDB'S INPUT STRING. ;CALL T3 := CHAR TO STORE ; U := POINTER TO THE LDB ; ;RETURN CPOPJ ;WITH T3 STORED AND EITHER ; ; LDBECC (VTMSTE) OR LDBTIC (VTMSTI) ; ; INCREMENTED VTMSTE: AOSA LDBECC##(U) ;COUNT UP ONE MORE "ECHOED" CHAR VTMSTI: AOS LDBTIC##(U) ;COUNT UP ONE MORE "UN-ECHOED" CHAR VTMST1: STCHK T3,LDBTIP##(U),VTMST2 ;STORE THE CHARACTER VTMST2: POPJ P, ; AND RETURN ;VTMSTO ROUTINE TO STORE A CHARACTER IN THE LDB'S OUTPUT BUFFER ;CALL T3 := CHAR TO STORE ; U := POINTER TO THE LDB ; ;RETURN CPOPJ ;WITH T3 STORED AND LDBTOC INCREMENTED VTMSTO: AOS LDBTOC##(U) ;COUNT THE CHAR, STCHK T3,LDBTOP##(U),VTMST2 ; STORE IT IN THE OUTPUT BUFFER, POPJ P, ; AND RETURN. ;VTMEDM ROUTINE TO "ENTER DEFERED ECHO MODE" FROM LOCAL ECHO MODE. ;CALL U := LDB. ;RETURN CPOPJ ;WITH EPM SERIAL# INCREMENTED AND ; ; ALL (HOPEFULLY) RELEVANT BITS SET/CLEARED. VTMEDM: LDB T1,LDPEPM## ;GET THE SERIAL OF THE LAST EPM SEND AOS T1 ; INCREMENT THE NUMBER AND STORE SO WE DON'T DPB T1,LDPEPM## ; HAVE TO WORRY ABOUT AN EPM RACE. MOVE T1,[XWD LRLSTS##,STY.DE] ;SAY SEND STATUS, NOW DEFERED ECHO IORM T1,LDBREM##(U) ; AND SET THESE IN THE DAP STATUS WORD PJRST VTMENQ ;QUEUE THE LINE AND EXIT ;VTMLOP ROUTINE TO MAKE LINE LOCAL (ALA VTMLOC) AND THEN PRINT A MESSAGE. ;CALL T1 := ADDRESS OF ASCIZ STRING TO PRINT ; U := ADDRESS OF LDB ;RETURN CPOPJ ;DEFUNCT LDB, NEED TO CALL FRELDB ;RETURN CPOPJ1 ;INERT LDB (IDLE PTY, ETC), DON'T TYPE ON IT ;RETURN CPOPJ2 ;SUCCESSFUL WITH USEABLE LOCAL TERMINAL VTMLOP: PUSH P,T1 ;SAVE THE MESSAGE ADDRESS PUSHJ P,VTMLOC ;MAKE THE LINE LOCAL JRST TPOPJ## ;DEFUNCT LDB, NEED TO CALL FRELDB JRST TPOPJ1## ;INERT LDB, JUST DON'T TYPE ON IT PUSHJ P,PCRLF## ;PRINT INITIAL "CRLF" TO GET MSG ON NEW LINE POP P,T1 ;GET THE MESSAGE POINTER BACK PUSHJ P,CONMES## ;PRINT THAT. PUSHJ P,PCRLF## ; AND PRINT A LAST "CRLF" TO END THE MSG. JRST CPOPJ2## ;SUCCESSFUL RETURN ;VTMLOC ROUTINE TO CLEAN UP A LINE THAT HAS BEEN "SET HOSTED" AWAY. ;CALL U := LDB TO "MAKE LOCAL" ;RETURN CPOPJ ;DEFUNCT LDB, NEED TO CALL FRELDB ;RETURN CPOPJ1 ;INERT LDB (IDLE PTY, ETC), DON'T TYPE ON IT ;RETURN CPOPJ2 ;SUCCESSFUL WITH USEABLE LOCAL TERMINAL VTMLOC: PUSH P,W ;PROTECT "W" PUSH P,LDBREM##(U) ;NEED A COPY OF LRLVTZ!LRLVTF PUSHJ P,VTMDEQ ;MAKE SURE THE LINE IS NOT QUEUED. PUSHJ P,VTMCLR ;CLEAR LDBREM WORDS (IN PARTICULAR LRLVTM) PUSHJ P,LDBVRS## ;RESET PARAMETERS ETC. (DOES A TSETBE ; WHICH FIXES UP THE INPUT CHUNK CHAIN) PUSHJ P,CLRPCT## ;CLEAR THE PAGE COUNTERS. POP P,T1 ;COPY OF LRLVTZ!LRLVTF TLNE T1,LRLVTF## ;IS THIS LDB TOTALLY DEFUNCT? PJRST WPOPJ## ;YES, LINE IS NOW A USELESS LOCAL LINE. AOS -1(P) ;LDB IS VALID, SKIP CALL TO FRELDB TLNE T1,LRLVTZ## ;IS THE LDB ZAPPED OR GOOD? PJRST WPOPJ## ;ZAPPED, SHOULDN'T GREET IT OR TYPE ON IT PJRST WPOPJ1## ;GOOD, LINE IS NOW A USEABLE LOCAL LINE ;VTMHST ROUTINE TO PERFORM THE "SET HOST" FUNCTION FOR A LOCAL TERMINAL ;CALL W := ADDRESS OF THE NODE TO "SET HOST" THIS TERMINAL TO ; U := ADDRESS OF THE LDB TO THAT IS DOING THE "SET HOST" ;RETURN CPOPJ ;WITH EITHER THE CONNECT DONE, OR AN ; ; ERROR MESSAGE PRINTED VTMHST::HRRZ F,LDBDDB##(U) ;GET THE ADDRESS OF THIS GUY'S TTY DDB SKIPE F ;DON'T DO THE DETACH IF NO DDB PUSHJ P,TTYDET## ;DETACH THIS GUY ; PJRST VTMCNT ;LET VTMCNT DO THE REST OF THE WORK ;VTMCNT ROUTINE TO PERFORM THE CONNECT FUNCTION FOR A TERMINAL. ;CALL W := ADDRESS OF NDB OF NODE TO CONNECT TO ; U := ADDRESS OF LDB TO CONNECT ;RETURN CPOPJ ;WITH EITHER THE CONNECT SENT, OR ; ; AN ERROR MESSAGE PRINTED. VTMCNT: PUSHJ P,VTMLOC ;CLEAN UP THE LDBREM WORDS. PJRST FRELDB## ;AWKWARD TIME FOR LAT/NRT/ETC TO DIE. FREE LDB POPJ P, ;RETURN WITH NO MORE ADO MOVE T1,U ;LDB ADDRESS FOR GETSLA TLO T1,LAT.TY!LAT.VT;REMEMBER THAT THIS IS VTM/LDB-STYLE MOVEI T2,LAT.CC ;INITIAL STATE IS CONNECT-CONFIRM PUSHJ P,GETSLA## ;ATTEMPT TO ASSIGN AN SLA JRST [MOVEI T1,[ASCIZ \No free LAT entries.\] JRST VTMCN8] ;MAKE LINE LOCAL AND PRINT ERROR DPB T1,LDPSLA## ;SAVE THE SOURCE LINK ADDRESS HLRZ T1,NDBNNM(W) ;GET THE NUMBER OF THE NODE TO CONNECT TO DPB T1,LDPRNN## ; AND SAVE THAT AS THE VTMS REMOTE NODE # PUSHJ P,VTMXCN ;SEND THE CONNECT. JRST [MOVE T1,NRTNCE## ;"NETWORK CAPACITY EXCEEDED ERROR JRST VTMCN8] ;MAKE LINE LOCAL AND PRINT ERROR ;AT THIS POINT WE HAVE SENT THE CONNECT. NOW MAKE THE LINE "REMOTE" MOVSI T1,LRLVTM## ;GET THE "THIS IS A VTM" BIT IORM T1,LDBREM##(U) ; AND SET IT SO TYPEIN COMES TO US AND ; DOESN'T GO TO SCNSER POPJ P, ;EXIT WITH LINE WAITING FOR CONNECT CONFIRM. ;HERE ON ERROR TRYING TO DO THE CONNECT, ERROR MESSAGE IN T1 VTMCN8: PUSHJ P,VTMLOP ;MAKE LINE LOCAL AND PRINT ERROR MESSAGE PJRST FRELDB## ;AWKWARD TIME FOR LAT/NRT/ETC TO DIE. FREE LDB POPJ P, ;RETURN WITH NO MORE ADO POPJ P, ;RETURN WITH LINE LOCAL AND USEABLE ;VTMXCN ROUTINE TO SEND A CONNECT MESSAGE FOR A VTM. (EITHER CONFIRM -- ; DLA SET UP, OR INITIATE -- DLA = 0) ;CALL W := NDB OF THE NODE TO SEND THE CONNECT TO. ; U := POINTER TO THE LDB TO SEND CONNECT FOR ;RETURN CPOPJ ;NOT ENOUGH CORE TO BUILD A MSG ; CPOPJ1 ;CONNECT SENT VTMXCN: PUSH P,U ;SAVE THE LDB WHILE WE GO GET A PCB PUSHJ P,NCMHDR## ;GO GET A NUMBERED PCB WITH THE NCL HEADER JRST UPOPJ## ;GIVE ERROR RETURN IF NO CORE. EXCH U,-1(P) ;REMEMBER PCB ADDRESS, RECOVER LDB ADDRESS ;TYP XMTI NC.CNT ;CONNECT MESSAGE TYPE ;DLA XMTB LDPDLA## ;SEND DLA (IF = 0, THEN CONNECT INIT) ;SLA LDB T1,LDPSLA## ;GET OUR LOCAL LAT ADDRESS SKIPN T1 ;MAKE SURE THERE IS ONE STOPCD .,STOP,VTMLAT ;++ LAT ADDRESS NOT SET UP (CALL GETSLA FIRST) XMT T1 ;WRITE THE SOURCE LINK ADDRESS FIELD ;DPN(OBJ) XMTI OBJ.TT ;WE WANT A TERMINAL HANDLER (MCR) ;DPN(,PID) XMTI 0 ;(DUMMY PROCESS NAME) ;SPN(OBJ) XMTI OBJ.TY ;WE ARE A TERMINAL (TTY) ;SPN(,PID) XMTB LDPLNO## ;THIS IS OUR LOCAL LINE NUMBER ;MML XMTI ^D512 ;RECORD LENGTH (IGNORED EVERYWHERE) ;FEA(DCM) XMTI DCM.AS ;ASCII DEVICE MODE ;FEA(,RLN) XMTI 0 ;VARIABLE RECORD LENGTH ;FEA(,,DTY) MOVEI T1,DTY.SB!DTY.SH;WE CAN SET HOST AND CHANGE SPEEDS, MOVE T2,LDBDCH##(U) ; AND, IF WE TRNE T2,LDRDSD## ; ARE A DATA-SET LINE IORI T1,DTY.MC ; WE CAN PERFORM MODEM CONTROL. SKIPGE LDBISB##(U) ;IF CLEVER FRONT-END, TRO T1,DTY.RA ;WE CAN HANDLE .TOEAB XMT T1 ;WRITE THE "ATTRIBUTES" ;FEA(,,,DVU) XMTB LDPAPC## ;SEND OUR IDEA OF APC VALUE ;FEA(,,,,DVV) XMTI 0 ;NO CONTROLLER TYPE ;FEA(,,,,,DFT) LDB T1,LDPTTT## ;GET TTY TYPE INDEX MOVE T1,CTTWDT##(T1) ;THEN SIXBIT TTY NAME CAME T1,DEFTTT## ;IF NOT DULL & BORING, XMTS T1 ;SEND IT EXCH U,-1(P) ;GET PCB BACK, PRESERVE LDB ADDRESS JSP T1,NETWRC## ;GO SEND THE MESSAGE JRST UPOPJ1## ;GIVE GOOD RETURN NOW THAT MESSAGE HAS GONE ;VTMENQ ROUTINE TO QUEUE A VTM FOR PROCESSING. ;CALL U := ADDR OF THE LDB TO QUEUE ;RETURN CPOPJ ;WITH THE LINE QUEUED VTMENQ:: IFN PARANOID&P$VTM,< ;IF WE'RE BEING CAREFUL, TRNN U,-1 ;MAKE SURE THAT WE'VE GOT A LDB POINTER STOPCD .,STOP,VTMLDB, ;++ NO LDB IN VTMENQ > SCNOFF ;NO JOSTLING IN THE WAITING ROOM PLEASE. MOVSI T1,LRLQED## ;GET THE "LDB ALREADY QUEUED BIT" TDNE T1,LDBREM##(U) ; AND SEE IF WEVE ALREADY BEEN QUEUED JRST SONPPJ## ;IF ALREADY QUEUED, WE'RE DONE. IORM T1,LDBREM##(U) ;MARK THIS LDB AS QUEUED. MOVE T1,VTMQUE## ;GET THE FIRST QUEUE ENTRY HRRM T1,LDBVTQ##(U) ;MAKE OUR LDB POINT TO IT. HRRZM U,VTMQUE## ;MAKE OUR LDB THE HEAD OF THE LIST. JRST SONPPJ## ;RE-ENABLE INTERRUPTS AND RETURN ;VTMDEQ ROUTINE TO REMOVE A LINE FROM THE VTMQUE. ;CALL U := POINTER TO THE LDB TO DE-QUEUE (CALLED BY VTMLOC ONLY) ;RETURN CPOPJ ;WITH THE LINE DEQUEUED, BUT THE "QUEUED BIT" ; ; STILL ON (SO LINE WON'T GET RE-QUEUED BY ; ; AN INTERRUPT) VTMDEQ: SCNOFF ;NO INTERRUPTS WHILE THIS IS GOING ON. MOVSI T1,LRLQED## ;GET THE "THIS VTM IS QUEUED BIT" TDNN T1,LDBREM##(U) ; AND SEE IF WE THINK IT IS QUEUED JRST [IORM T1,LDBREM##(U) ;IF NOT, SET BIT TO PREVENT RE-QUEUE JRST SONPPJ##] ; AND WE'RE DONE HRRZ T1,VTMQUE## ;GET ADDR OF FIRST LDB IN THE QUEUE SSX T1,MS.SCN ; USING SCNSER SECTION CAMN T1,U ; AND SEE IF WE'RE FIRST JRST [HRRZ T1,LDBVTQ##(U) ;GET POINTER TO THE "NEXT" LDB HRRZM T1,VTMQUE## ; AND MAKE THAT THE "FIRST" JRST SONPPJ##] ;EXIT WITH LINE DE-QUEUED. JRST VTMDE2 ;FIRST DIDN'T MATCH, CHECK FOR EMPTY QUEUE VTMDE1: MOVE T2,T1 ;REMEMBER THE ADDRESS OF THE "LAST" LDB HRRZ T1,LDBVTQ##(T1) ;STEP TO THE "NEXT" LDB SSX T1,MS.SCN ;SCNSER SECTION CAMN T1,U ;IF THIS LDB IS THE ONE WE WANT, JRST [HRRZ T1,LDBVTQ##(T1) ;GET THE ADDR OF THE ONE AFTER THAT HRRM T1,LDBVTQ##(T2) ; AND PUT IT IN OUR PLACE JRST SONPPJ##] ;EXIT WITH THE LINE DE-QUEUED. VTMDE2: TRNE T1,-1 ;IF WE'RE NOT AT THE END YET, JRST VTMDE1 ;KEEP LOOKING STOPCD .,STOP,VTMQED, ;++ LINE NOT QUEUED THOUGH LRLQED IS SET ;VTMFRE - "FREE" A VTM'ED LDB (E.G., IF A LAT/ETC TERMINAL VTM'S OUT) ;CALL WITH U/LDB ADDRESS ; ;ON RETURN, THE VTM IS IN THE PROCESS OF BEING DISCONNECTED, NETVTM WILL ;EVENTUALLY RETURN THE LDB TO FRELDB WHEN THE DISCONNECT IS COMPLETE. ;RETURN CPOPJ ;ALWAYS ;VTMPRL ROUTINE CALLED WHEN A PTY IS RELEASED. IF SET-HOSTED, ; A DISCONNECT IS QUEUED ;CALL U := LDB ; PUSHJ P,VTMPRL ;RETURN POPJ P, ;ALWAYS. VTMFRE::SKIPA T1,[LRLDIP##!LRLVTF##,,0] ;FLAG NEED TO FRELDB LATER VTMPRL::MOVSI T1,LRLDIP##!LRLVTZ## ;FLAG THIS LDB IS ZAPPED SKIPL LDBREM##(U) ;IF NOT A "SET HOSTED" LINE, POPJ P, ; THEN RETURN NOW IORM T1,LDBREM##(U) ;SET THE DISCONNECT PROCESSING FLAGS PJRST VTMENQ ;QUEUE THE LINE AND RETURN ;VTMCLR ROUTINE TO CLEAN UP FOR A VTM CONNECT ;CALL PUSHJ P,VTMCLR ;RETURN CPOPJ VTMCLR: LDB T1,LDPSLA## ;GET OUR ("SOURCE") LAT ADDRESS JUMPE T1,VTMCL1 ;NONE (?), NOT MUCH TO DO HERE THEN LDB T2,LATPTR## ;GET NETLAT'S LDB ADDRESS CAME T2,U ;IS THE CIRCLE COMPLETE? STOPCD .,STOP,VTMLAL ;++LAT AND LDB DON'T AGREE SETZM NETLAT##(T1) ;FREE UP THIS NETLAT ENTRY VTMCL1: SETZM LDBREM##(U) ;CLEAR THE VTM/ANF WORDS SETZM LDBREM##+1(U) ;.. SETZM LDBREM##+2(U) ;.. SETZM LDBREM##+3(U) ;.. SETZM LDBREM##+4(U) ;.. POPJ P, ;VTMJIF ONCE/JIFFY PROCESSING FOR VTMS. ;CALL PUSHJ P,VTMJIF ;FROM JIFFY CODE IN NETSER ;RETURN CPOPJ ;ALWAYS (WITH VTMQUE PROCESSED) VTMJIF::SKIPN VTMQUE## ;JUST A QUICKY CHECK (SINCE WE GET HERE A LOT) POPJ P, ;VTMQUE IS EMPTY. SCNOFF ;GET THE SCNSER INTERLOCK. HRRZ U,VTMQUE## ;GET THE NEXT ENTRY JUMPE U,SONPPJ## ;?? SOME ONE SNUCK IN. SSX U,MS.SCN ;SCNSER SECTION HRRZ T1,LDBVTQ##(U) ;GET THE ADDRESS OF THE NEXT ENTRY HRRZM T1,VTMQUE## ; AND MAKE THAT LDB BE THE NEW "FIRST" MOVSI T1,LRLQED## ;GET THE "THIS LDB IS QUEUED" BIT ANDCAB T1,LDBREM##(U) ; AND CLEAR IT SO WE CAN RE-QUEUE LATER. SCNON ;RE-ENABLE INTERRUPTS TLNN T1,LRLCON## ;MAKE SURE WE'RE CONNECTED JRST VTMJIF ;IF NOT CONNECTED YET, DON'T PROCESS ; (THIS HAPPENS WHEN WE RUN OUT OF CHARS ; AND "ZAPBUF" IN SCNSER RE-QUEUES THE ; LINE BEFORE THE CONNECT FINISHES) TLNE T1,LRLDIP## ;IF WE WANT TO SEND A DISCONNECT-INIT JRST VTMJI1 ; THEN SEE IF WE ALREADY HAVE LDB T1,LDPRNN## ;GET THE NUMBER OF THE NODE WE'RE TALKING TO PUSHJ P,SRCNDB## ;SET W := A POINER TO THE NODES NDB STOPCD .,STOP,VTMNDB, ;++ NO NDB FOR LDB'S NODE. PUSHJ P,VTMSCN ;GO DO WHATEVER IS NECESSARY FOR THE VTM PJRST VTMENQ ; IF NO CORE. REQUEUE LINE, AND WAIT TILL ; NEXT JIFFY. PUSHJ P,VTMXDQ ;TRY TO SEND DATA-REQUESTS PJRST VTMENQ ;REQUEUE IF NO CORE JRST VTMJIF ;LOOP OVER ALL LINES IN VTMQUE. ;HERE SEE IF WE NEED TO SEND A DISCONNECT FOR THIS TERMINAL VTMJI1: LDB T1,LDPSLA## ;GET THE SOURCE LAT ADDRESS SKIPN T1 ;MAKE SURE WE HAVE ONE STOPCD .,STOP,VTMNLA, ;++ NO LAT ADDRESS FOR VIRTUAL TERMINAL? LDB T2,LATSTA## ;GET OUR CONNECTION STATE CAIE T2,LAT.OK ;IF WE'RE NOT IN "OK" STATE JRST VTMJIF ; THEN WE'VE SENT THE DISCONNECT. NEXT TERMINAL LDB T1,LDPRNN## ;GET THE REMOTE NODE NUMBER PUSHJ P,SRCNDB## ;SET UP "W" WITH THE NDB ADDRESS STOPCD .,STOP,VTMNNN, ;++ BUT VTMNWD SHOULD HAVE CAUGHT THIS MOVEI T1,RSN.OK ;REASON = GOODNIGHT PUSHJ P,TRMXDC## ;SEND THE DISCONNECT PJRST VTMENQ ;REQUEUE THE LINE IF NO CORE JRST VTMJIF ;OTHERWISE GO DO THE NEXT LINE XLIST $LIT LIST VTMEND::END ;END OF NETWORK VIRTUAL TERMINAL SERVICE