Trailing-Edge
-
PDP-10 Archives
-
BB-F493Z-DD_1986
-
10,7/703mon/netdev.mac
Click 10,7/703mon/netdev.mac to
see without markup as text/plain
There are 8 other files named netdev.mac in the archive. Click here to see a list.
TITLE NETDEV - NETWORK DEVICE SERVICE ROUTINES - V176
SUBTTL NETDEV -- WEM/ 14 JAN 86
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.
;
.CPYRT<1978,1986>
;COPYRIGHT (C) 1978,1979,1980,1982,1984,1986
; BY DIGITAL EQUIPMENT CORP., MAYNARD, MASS.
;ALL RIGHTS RESERVED.
XP VNETDV,176 ;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 CPOPJ## ;(-4) SPECIAL ERROR STATUS
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 CPOPJ## ;(-4) SPECIAL ERROR STATUS
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?
PJRST TPOPJ## ;NO, DON'T TOUCH IT
PUSH P,T2 ;SAVE THE OTHER TEMPS
PUSH P,T3
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
ADDI T1,'0'(T3) ;INCLUDE THE UNIT NUMBER
HRLI T1,'DDA' ;FORCE KONTROLLER NUMBER
DDBSRL ;LOCK THE DDB DATA BASE
HLRZ T2,NETDDB##+DEVSER ;GET ADDRESS OF FIRST DDB IN CHAIN
DDPSR1: CAMN T1,DEVNAM(T2) ;IS THIS THE ONE
JRST DDPSR2 ;YES, WE FOUND IT
HLRZ T2,DEVSER(T2) ;NO, STEP TO NEXT DDB
JUMPN T2,DDPSR1 ;LOOP IF ONE THERE
DDPSR2: DDBSRU ;DONE FOOLING WITH DDBS
SKIPN T2 ;NO SKIP IF NO DDB
JRST DDPSR3 ;WE DIDN'T FIND ON
AOS -3(P) ;WE FOUND ONE, SKIP RETURN
MOVEM T2,-1(P) ;STORE DDB ADDRESS
DDPSR3: POP P,T3 ;RESTORE AC'S
POP P,T2
POP P,T1
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 FUNNY 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:
;
; MOVE AC,[LEN,,ADR]
; DDP. AC,
; ERROR RETURN
; NORMAL RETURN
;
;ADR: FUNCTION
; DDP DEVICE ID
; ARGUMENT (AS NEEDED)
;
;FUNCTION IS ONE OF
;
; (00) .DPFAS ASSIGN (CREATING IF NEEDED) DDP DEVICE
; (01) .DPFZP ZAP ("RELEASE") DDP DEVICE/KONTROLLER
; (02) .DPFDV SET DDP TO "DEVICE" MODE (IN/OUT/ETC. UUOS)
; (03) .DPFKN SET DDP TO "KONTROLLER" MODE
; (04) .DPFUS SET DDP "KONTROLLER" USER TYPE
; (10) .DPFHL HALT THE DDP KONTROLLER
; (11) .DPFIN INITIALIZE DDP KONTROLLER
; (12) .DPFMA SET TO MAINTENANCE MODE (FOR BOOTSTRAPING)
;
;ON ERROR, AC CONTAINS ERROR CODE:
;
; (01) DPEIF% ILLEGAL DDP. FUNCTION CODE
; (02) DPESH% ARGUMENT LIST TOO SHORT
; (03) DPEID% ILLEGAL DDP. DEVICE (NOT DDP, ETC.)
; (04) DPEPR% USER NOT PRIVILEGED
; (05) DPEIM% ILLEGAL OPERATION MODE (DDP NOT IN KONTROLLER MODE)
; (06) DPEIU% ILLEGAL USER NAME
; (07) DPEOU% DDP IS IN USE BY OTHER USER/JOB
;DEFINE ERROR RETURNS
DDE%IF==ECOD1## ;ILLEGAL FUNCTION
DDE%SH==ECOD2## ;ARG LIST TOO SHORT
DDE%ID==ECOD3## ;ILLEGAL DEVICE
DDE%PR==ECOD4## ;USER NOT PRIVILEGED
DDE%IM==ECOD5## ;ILLEGAL OPERATION MODE
DDE%IU==ECOD6## ;ILLEGAL USER NAME
DDE%OU==ECOD7## ;OTHER USER HAS THE DDP
DDPUUO::HLRZ P2,T1 ;SAVE LENGTH OF ARG LIST
HRR M,T1 ;POSITION ADDRESS OF ARG LIST
SOJL P2,DDE%SH ;ERROR IF TOO SHORT
PUSHJ P,GETWDU## ;GET THE FUNCTION CODE
HRRZ P1,T1 ;POSITION JUST FUNCTION CODE (ALLOW FOR FUTURE)
CAILE P1,DDPCMX ;RANGE-CHECK THE FUNCTION CODE
JRST DDE%IF ;ILLEGAL FUNCTION CODE
SOJL P2,DDE%SH ;ERROR IF ARG LIST TOO SHORT
PUSHJ P,NTDPRV## ;IS THIS USER PRIVILEGED?
JRST DDE%PR ;NO, HE LOSES
PUSHJ P,GETWD1## ;GET THE DEVICE NAME/ID
PUSHJ P,DVCNSG## ;TRY TO DECIPHER THE DEVICE NAME
JRST DDE%ID ;ILLEGAL DEVICE
LDB T1,PDVTYP## ;GET DEVICE TYPE
CAIE T1,.TYDDP/.TYEST;IS IT A REAL DDP DEVICE?
JRST DDE%ID ;NO, ILLEGAL DEVICE
MOVE S,DEVIOS(F) ;PRE-LOAD S
PJRST @DDPCMT(P1) ;DISPATCH ON FUNCTION
DDPCMT: 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 DDE%IF ;(05) RESERVED/ILLEGAL
IFIW DDE%IF ;(06) RESERVED/ILLEGAL
IFIW DDE%IF ;(07) RESERVED/ILLEGAL
IFIW DDPCHA ;(10) HALT KONTROLLER PROTOCOL
IFIW DDPCIN ;(11) INITIALIZE KONTROLLER PROTOCOL
IFIW DDPCMA ;(12) SET TO MAINTENANCE MODE PROTOCOL
DDPCMX==.-DDPCMT ;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 DDE%OU ;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 DDE%OU ;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,DDE%SH ;ERROR IF TOO SHORT
PUSHJ P,GETWD1## ;GET THE USER NAME (INTO T1)
DDPCU1: PUSHJ P,KONUSN## ;TRANSLATE USER NAME INTO TYPE (IN T2)
JRST DDE%IU ;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 DDE%IU ;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 DDE%IU ;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,FTDN60,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 DDE%IM ;ILLEGAL OPERATING MODE
JRST DDE%IF ;*** ILLEGAL FUNCTION . . .
;DDPCIN - INITIALIZE DDP KONTROLLER
DDPCIN: TLNN S,IOSDDK ;IS DDP IN KONTROLLER MODE?
JRST DDE%IM ;NO, ERROR
JRST DDE%IF ;*** ILLEGAL FUNCTION . . .
;DDPCMA - SET DDP KONTROLLER TO MAINTENANCE MODE
DDPCMA: TLNN S,IOSDDK ;IS DDP IN KONTROLLER MODE?
JRST DDE%IM ;NO, ERROR
JRST DDE%IF ;*** 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
;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
TRN ;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
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:
XMOVEI T2,. ;*** JUST CHECKING
TLNN T2,1 ;*** TO MAKE SURE
STOPCD .,STOP,DDPSE0, ;++ NOT IN SECTION 1
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,FTDN60,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 CPOPJ## ;(-4) SPECIAL ERROR STATUS
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 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 ;LOWERCASE?
TLO T2,(HC.LCP) ;YES
LDB T1,NETDVU## ;RETRIEVE "UNIT" TYPE
DPB T1,[POINT 3,T2,14] ;AND STUFF INTO HCW WORD
LDB T1,NETDVV## ;RETRIEVE "CONTROLLER" TYPE
DPB T1,[POINT 3,T2,11] ;AND STUFF INTO HCW WORD
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 D85ELE ;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: PJRST SETCHP## ;LET SCNSER DO THE WORK
;HERE TO REQUEST A LINE PARM CHANGE.
D85LPC: CAIE T3,<LPCUKB>B27 ;UNLOCK KEYBOARD OR TERMINAL INPUT WAIT?
POPJ P, ;??
PJRST D85CHP ;REQUEST THE CHANGE OF PARMS
;HERE TO CHANGE THE ELEMENT ON A 2741
D85ELE: PUSHJ P,ELEINX## ;CONVERT TO AN INDEX
POPJ P, ;ILLEGAL
DPB T2,LDPELE## ;STORE THE NEW ELEMENT NUMBER,
AOS (P) ;GIVE A GOOD SKIP RETURN
PJRST D85CHP ; AND SIGNAL THE CHANGE IN PARAMETERS
;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 "OUT" 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)
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)
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 WITH 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,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,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
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
IFN FTPI,<
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##
> ;END IFN FTPI
IFE FTPI,<
DSCSG: POPJ P, ;NO PSISER
> ;END IFE FTPI
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
;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE
LDB T2,LDPRSP## ;GET THE RECEIVE SPEED BACK
MOVEI T1,LDR274## ;GET 2741 BIT
CAIN T2,(P2) ;RECEIVE AND TRANSMIT THE SAME
CAIE T2,LS0134## ;IS IT AN IBM 2741
SKIPA T2,[ANDCAM T1,LDBDCH##(U)] ;CLEAR THE BIT
MOVE T2,[IORM T1,LDBDCH##(U)] ;SET THE BIT
XCT T2 ;DO IT
PUSHJ P,EBI2BI ;WIDTH OF TERMINAL'S CHARRIAGE
SKIPE T1
DPB T1,LDPWID## ;STORE
PUSHJ P,EBI2BI ;GET THE AUTO CRLF
SKIPE T1
DPB T1,LDPACR## ;STORE
PUSHJ P,EBI2BI ;READ THE ELEMENT #
MOVE T3,T1 ;COPY TO T3
PUSHJ P,ELEINX## ;GET THE INDEX
SETZ T2, ;ILLEGAL
DPB T2,LDPELE## ;STORE THE ELEMENT NUMBER
PUSHJ P,EBI2BI ;GET THE 2741 BITS
MOVE T2,LDBISB##(U) ;GET THE FLAGS
TRNE T1,CDT.PL ;APL
TLOA T2,LILAPL## ;YES, SET
TLZ T2,LILAPL## ;NO, CLEAR
TRNE T1,CDT.CB ;DEBREAK
TLOA T2,LILDBK## ;YES, SET
TLZ T2,LILDBK## ;NO, CLEAR
TRNE T1,CDT.TD ;TIDY MODE?
TLOA T2,LILTDY## ;YES, SET
TLZ T2,LILTDY## ;NO, CLEAR
HLLM T2,LDBISB##(U) ;STORE THE RESULT
PJRST 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 STANAM## ; 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!DTY.27 ;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
;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
CAILE T2,M.RMCR## ;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## ;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 CLEAR DE IF WE 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
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
TRC T1,LRRSHC## ;CHANGE "CAN SET HOST" INTO "DC72" BIT
TDNN T1,[XWD LRLCHR##,LRRSHC##] ;IF DC72 OR WE HAVE RECEIVED CHARACTERSISTICS, OK TO SEND
JRST SCNCH4 ;OTHERWISE, DON'T SEND ONE (***SEE FOOTNOTE)
PUSHJ P,GETCR ;TRANSLATE SPEED ETC TO CHARACTERISTICS WORD
CAMN T1,LDBCCH##(U) ;ANY CHANGE?
JRST SCNCH4 ;NO CHANGE. GIVE GOOD RETURN
PUSHJ P,TRXTCR ;SEND THE CHARACTERISTICS. (WILL PUT T1 IN LDBCCH)
POPJ P, ;NO CORE. GIVE ERROR RETURN
SCNCH4: 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" IN TO A SINGLE WORD
GETCR:: MOVSI T1,400000 ;BUILD ENCODED CHARASTICS
LDB T2,LDPFLC## ;GET FILL CLASS
DPB T2,[POINT 4,T1,35] ;BITS 35-32
LDB T2,LDPRSP## ;GET RECEIVE SPEED
DPB T2,[POINT 4,T1,31] ;BITS 31-28
LDB T2,LDPTSP## ;GET TRANSMIT SPEED
DPB T2,[POINT 4,T1,27] ;BITS 27-24
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,LDPELE## ;GET THE ELEMNET NUMBER
DPB T2,[POINT 4,T1,7] ;BITS 4-7
MOVE T2,LDBISB##(U) ;GET THE CONTROL BITS
TLNE T2,LILAPL## ;APL MODE
TLO T1,(1B3) ;YES
TLNE T2,LILDBK## ;DEBREAK
TLO T1,(1B2) ;YES
TLNE T2,LILTDY## ;TIDY?
TLO T1,(1B1) ;YES
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
MOVEI T1,DC.STS ;GET STATUS MESSAGE CODE
PUSHJ P,BI2EBI ;WRITE
;STC
MOVE T1,-1(P) ;GET THE STC
PUSHJ P,BI2EBI ;WRITE
;STD
MOVE T1,-2(P) ;GET THE STD
PUSHJ P,BI2EBI ;WRITE
;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
MOVEI T1,DC.CTL ;CONTROL MESSAGE
PUSHJ P,BI2EBI## ;SEND
;DCT
MOVEI T1,DCT.EP ;PIPE LINE MARKER FLAG
PUSHJ P,BI2EBI ;SEND
;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
MOVEI T1,DC.CTL ;TELETYPE CONTROL MESSAGE
PUSHJ P,BI2EBI ;SEND
;DCT
MOVEI T1,DCT.CG ;CHARACTER GOBLER CODE
PUSHJ P,BI2EBI ;SEND
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,27 ;REQUEST A LARGE SUBMESSAGE
PUSHJ P,TRQPCB ; AND SET UP P3 AND STACK
POPJ P, ;NO CORE. GIVE AN ERROR RETURN
;TYP
MOVEI T1,DC.CTL ;SET UP CONTROL MESSAGE
PUSHJ P,BI2EBI ;WRITE
;DCT
MOVEI T1,DCT.TC ;TELETYPE CHARASTICS
PUSHJ P,BI2EBI ;WRITE
;CDT
PUSH P,P1 ;SAVE "P1" OVER THIS LOOP
LDB T1,[POINT 2,P1,35] ;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),27] ;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.
PUSHJ P,BI2EBI ;WRITE
SOJG T4,MCRTC1 ;DO FOR ALL SIX TIMES
POP P,P1 ;GET OUR CHARACTERISTICS BACK
LDB T1,[POINT 4,P1,31]
MOVE T1,LSPTAB##(T1) ;GET RECEIVE SPEED
PUSHJ P,BI2EBI ;WRITE
LDB T1,[POINT 4,P1,27]
MOVE T1,LSPTAB##(T1) ;GET TRANSMIT SPEED
PUSHJ P,BI2EBI ;WRITE
LDB T1,[POINT 8,P1,23]
PUSHJ P,BI2EBI ;WRITE
LDB T1,[POINT 8,P1,15]
PUSHJ P,BI2EBI ;WRITE
;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE
LDB T1,LDPELE## ;ELEMENT NUMBER NOT IMPLEMENTED
MOVE T1,ELETAB##(T1) ;GET THE VALUE FROM THE TABLE
PUSHJ P,BI2EBI ;WRITE
MOVEI T1,0 ;IBM 2741 BITS
MOVE T2,P1 ;GET THE 2741 BITS
TLNE T2,(1B3) ;APL MODE
TRO T1,CDT.PL ;YES, SET THE BIT
TLNE T2,(1B2) ;DEBREAK FEATURE
TRO T1,CDT.CB ;YES, SET THE BIT
TLNE T2,(1B1) ;TIDY?
TRO T1,CDT.TD ;YES
PUSHJ P,BI2EBI ;WRITE
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
MOVEI T1,DC.CTL ;CONTROL MESSAGE
PUSHJ P,BI2EBI ;SEND
;DCT
MOVEI T1,DCT.AD ;AUTO DIAL CODE
PUSHJ P,BI2EBI ;SEND
;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
MOVEI T1,DC.CTL ;TERMINAL CONTROL MSG
PUSHJ P,BI2EBI ;SEND THAT TOO
;DCT
MOVEI T1,DCT.XF ;XOFF REQUEST
PUSHJ P,BI2EBI ;SEND THAT
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.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##!LRLATO##!LRLDSR##,LRRSHC##]
ANDCAM T2,LDBREM##(U) ;CLEAR ALL "ATTRIBUTE" TYPE BITS
MOVEI T2,LDRDSD##!LDR274## ;DATASET, 2741 LINE FLAGS
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
TRNE T1,DTY.27 ;IBM 2741?
TRO T2,LDR274## ;YES, SET THE BIT
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.AB ;AUTO BAUD LINE
TLO T2,LRLATO## ;YES, SET THE BIT
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
;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,APCHWD## ;YES--ASSUME A HARD WIRED LINE
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
;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
CAIG T2,M.RMCR## ;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## ;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
SKIPL LDBATR##(U) ;IF 8-BIT
SKIPGE LDBCHM##(U) ;OR FANCY MAPPING
POPJ P, ;CAN'T DO IT
EXTERN LAL8BT,LMLNDS ;FLAG BITS REFERENCED
SKIPE LDBIST##(U) ;IF DOING FANCY TWO-CHARACTER INPUT,
POPJ P, ;CAN'T DO IT
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
JRST CPOPJ1## ;YES--WE CAN DO IT
;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
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
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 .,STO