Trailing-Edge
-
PDP-10 Archives
-
BB-JR93K-BB_1990
-
10,7/mon/netdev.mac
There are 9 other files named netdev.mac in the archive. Click here to see a list.
TITLE NETDEV - NETWORK DEVICE SERVICE ROUTINES - V220
SUBTTL NETDEV -- WEM/ 11-APR-89
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,220 ;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 <IDPB T1,DEVAXI(F)> ;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 <IDPB T1,DEVAXI(F)> ;STORE THE BYTE IN THE USERS BUFFER.
SOJG P2,C.ASC1 ;LOOP FOR ALL 80 CHARACTERS.
SOSGE DEVAXI+1(F) ;COUNT OFF THE <CR>
JRST C.BKTL ;BUFFER TOO SMALL
MOVEI T1,15 ;<CR>
EXCTUU <IDPB T1,DEVAXI(F)> ;STORE THE <CR>
SOSGE DEVAXI+1(F) ;COUNT OFF THE <LF>
JRST C.BKTL ;BUFFER TOO SMALL
MOVEI T1,12 ;<LF>
EXCTUU <IDPB T1,DEVAXI(F)> ;STORE THE <LF>
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 <IDPB T1,DEVAXI(F)> ;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 T1,2(T2)> ;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>),<NAM==:<%%%OFF==%%%OFF+SIZ>-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,<LINE-ID>
; PUSHJ P,DDPSRC
; <ERROR>
; <GOOD>
;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,<DDB>
; 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,<IFIW CPOPJ##>
IFN CON,<IFIW DSP>
> ;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-<DD.MAX+1>,<
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 <IDPB T1,T3> ;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,<FNC>
; MOVX T2,<DDP>
; MOVX T3,<ARG>
; MOVX T4,<USR>
; PUSHJ P,DDPDSP
; ERROR RETURN
; NORMAL RETURN
;
;WHERE <FNC> IS THE KONTROLLER FUNCTION (DD.???) TO BE PERFORMED, SUCH
;AS START OR STOP THE DEVICE, ETC.; <DDP> IS THE DDP DATA BLOCK ADDRESS
;(I.E., THE DDB, THE SAME AS IN UUO-LEVEL PROCESSING). <ARG> IS ANY
;ARGUMENT APPROPRIATE TO THE PARTICULAR FUNCTION REQUESTED (E.G., BUFFER
;ADDRESS FOR OUTPUT DATA) AND <USR> 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>,<PRINTX ? Table DDPDST is incorrect>
;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,<FNC>
; MOVX T3,<ARG>
; PUSHJ P,DDPDVR
; RETURN
;
;WHERE <FNC> IS THE DRIVER FUNCTION (DI.???) TO PERFORM; AND <ARG> 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*<DD.MAX+1>>,<
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 <CR><FF>)
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 <CR><FF>
JRST L.FRS3 ; IF NOT, THEN SKIP MOST OF THIS
PUSHJ P,L.XFF ;SEND THE INITIAL <CR><FF> 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 <CR><FF>?
JRST L.CLO4 ; IF NOT, THEN SKIP MOST OF THIS
PUSHJ P,L.XFF ;SEND THE TRAILING <CR><FF> SEQUENCE
POPJ P, ;FORGET IT
L.CLO4: POPJ P, ;RETURN FROM NETWORK CLOSE PROCESSING
;SEND A <CR><FF> 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,(<NCT.IT>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 <SKIPN M,5(P1)> ;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 <SKIPN M,6(P1)>;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 <PEN UP>)
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 <PEN UP>)
; 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<IOSDRP>>+^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 <ILDB T3,DEVAXO(F)> ;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 <ILDB T1,DEVAXO(F)> ;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 <IDPB T2,DEVAXI(F)> ;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 <IDPB T2,DEVAXI(F)> ;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 <HLRZ P2,1(T1)> ; 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 <IDPB T1,DEVAXI(F)> ;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 <IDPB T1,DEVAXI(F)> ;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 <IDPB T1,DEVAXI(F)> ;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 <HRLM P2,1(T1)> ;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 <SKIPL T1,1(T1)>;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 <BLT T1,(T2)> ;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,<MAXODR*NTTPLN##*4>+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 RELIES ON THE FACT THAT ONE CAN DETERMINE 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
PUSH P,T1 ;SAVE THE FILL CLASS FOR LATER
;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
TRNA ;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
TRNA ;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
PUSH P,T1 ;SAVE NEW WIDTH FOR LATER
PUSHJ P,EBI2BI## ;READ THE AUTO-CRLF POSITION
PUSH P,T1 ;SAVE IT FOR LATER
PUSHJ P,XSKIP## ;SKIP 2741 ELEMENT NUMBER (NOT IMPLEMENTED)
PUSHJ P,EBI2BI## ;GET FORMERLY-2741 BITS
PUSH P,T1 ;SAVE THE BITS
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
POP P,T1 ;RESTORE "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
POP P,T1 ;RESTORE AUTO-CRLF POSITION
DPB T1,LDPACR## ; AND STORE THAT (ZERO IS OK)
POP P,T1 ;RESTORE NEW WIDTH
SKIPE T1 ;DON'T SET WIDTH TO ZERO
DPB T1,LDPWID## ;STORE THE NEW WIDTH
POP P,T1 ;RESTORE THE FILL CLASS
DPB T1,LDPFLC## ;TELL SCNSER
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,<LPCABR>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
; <SCANNER INTERRUPTS OFF>
;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
; <SCANNER INTERRUPTS OFF>
;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