Google
 

Trailing-Edge - PDP-10 Archives - tops10_704_monitoranf_bb-x140c-sb - 10,7/mon/nrtser.mac
There are 3 other files named nrtser.mac in the archive. Click here to see a list.
	TITLE	NRTSER - DECnet Network Remote Terminal Service V066
	SUBTTL	W. G. Nichols/WGN/RCB, 7 JUL 87

	SALL
	SEARCH	D36PAR,SCPAR,NETPRM,F,S,MACSYM
	D36SYM			;Fix problems with MACSYM in DECnet-36
	$RELOC
	$HIGH

;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED
;  OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION 1982,1984,1986,1988.
;ALL RIGHTS RESERVED.

.CPYRT<1982,1988>


VNRTSER==:066


	NRTOBJ==^D23		;NRTSRV OBJECT TYPE
	CTHOBJ==^D42		;CTERM HOST OBJECT
	CTSOBJ==^D24		;CTERM SERVER OBJECT
	NRTINT==3		;JIFFIES BETWEEN NRT SERVICE CHECKS


; The length of the record and the max record we will send are separately
; defined so that the compiled-in record buffer can be larger than the
; actual record we send so that we can poke the max to a larger value for
; performance tests to systems we know can handle the size.

	NRTROL==^D500		;BYTES IN OUTPUT NRT RECORD
	NRTMXC==^D500		;MAX LENGTH OF RECORD WE WILL SEND
	NRTRIL==^D90		;BYTES IN INPUT NRT RECORD
	CTHMSZ==^D139		;MINIMUM ACCEPTABLE SEGMENT SIZE ON CTERM LINK

IFG NRTMXC-NRTROL,NRTMXC==NRTROL ;ASSURE WE DON'T GET CARRIED AWAY
	SUBTTL	Table of contents

;               TABLE OF CONTENTS FOR NRTSER
;
;
;                        SECTION                                   PAGE
;    1. Table of contents.........................................   3
;    2. Definitions
;         2.1   External References...............................   4
;    3. Register & Macro Definitions..............................   5
;    4. CTERM Protocol Definitions................................   6
;    5. NRT Data Base Definitions.................................  21
;    6. Impure Storage............................................  22
;    7. LDBISR Dispatch Table.....................................  23
;    8. NRTINI - Initialization...................................  24
;    9. NRTSTO - Called every Jiffy via .CPSTO....................  25
;   10. NRTSEC - Called every second via .CPSTO...................  26
;   11. NJFRxx - Routines to handle each DECnet link state........  27
;   12. Subroutines
;        12.1   NRTNSF - Call SCLINK's SCTNSF.....................  83
;        12.2   NRTREL - Release a Link...........................  84
;        12.3   NGTLDB - Get an LDB for NRTSER....................  85
;        12.4   NGVLDB - Give an LDB back to ANF..................  86
;        12.5   NRTWAK - Subroutine to do the WAKEs...............  87
;        12.6   NRTHBR - Subroutine to do the HIBERs..............  88
;   13. Subroutine
;        13.1   NRTLFC - Get a NRT Line number from channel.......  89
;   14. NRTGWD - Get Some Words...................................  90
;   15. NRTFWD - Free Some Words..................................  91
;   16. End of Program............................................  92
COMMENT @

                         Theory of Operation

Except for NRTINI, called by SYSINI, NRTSER runs only at clock level,
and then only on one CPU, so it needs little more interlocking.

Every jiffy, NRTSTO gets called along with all the other queued
drivers in the system via a call in CLOCK1 through .CPSTO.  NRTSTO
checks that it is on the boot CPU and then counts down an interval
timer.  The timer is reinitialized to some small number, say 3, every
time it expires.

NRTSTO only runs after its interval counter expires for two reasons:
it imposes less overhead if it runs less often, and it lets more input
& output build up and thus fills the DECnet messages better than it
would if it ran more frequently.  It is important that it run often
enough that the user not see any delay, the optimum setting seems to
be around 3 to 5 jiffies.

When the interval timer expires, NRTSTO checks two queues for service
requests:

1)	NRTSTO calls TOTAKE to dequeue any LDBs which may have output
	pending.  NRTSTO loops over these LDBs, calling NRTLKS
	(NRT Link Service) on each.  If an LDB has output available
	and the associated DECnet link cannot take any output, NRTLKS
	just forgets about it:  it will get a DECnet 'interrupt' from
	that link when output is again OK.

2)	NRTSTO then calls SCTPSQ to see if there has been any DECnet
	activity.  This activity could be: a) input available, b)
	output newly OK on this link, or c) the link has changed
	state.

@
	SUBTTL	Definitions -- External References

;ENTRY declarations for LINK

	ENTRY	NRTSTO		;CALLED VIA .CPSTO EVERY JIFFY

;These are the external references to the D36COM library of routines.

	EXT	DNSWDS		;SMEAR SOME WORDS

;Here are the references to SCLINK.

	EXT	SCTNSF		;NSP. FUNCTION PROCESSING (Section 1)
	EXT	MAKSJB		;MAKE AN SJB
	EXT	SCTWKQ		;ENQUEUE THIS SLB FOR SCTPSQ CALL
	EXT	SCTPSQ		;DEQUEUE NEXT SLB FOR PSI INTERRUPT

;Here are some external references to TOPS-10 things.

	EXT	CPOPJ		;RETURN
	EXT	CPOPJ1		;SKIP RETURN
	SUBTTL	Register & Macro Definitions

;NRTSER uses standard TOPS-10 register definitions with the exception
;that R is redefined as CX, the super-temp for macros.
;
;The register defintions from D36PAR are ignored herein.

	CX==R		;SUPER-TEMP AC FOR MACROS
	.SAC==CX	;SOME USE THIS NAME INSTEAD


;Register Conventions in NRTSER
;
;	M	usually points to an SAB, SCLINK arg block
;	W	usually points to a NRB, NRT data block
	SUBTTL	CTERM Protocol Definitions

;Define a helper macro for making masks out of network bits

DEFINE	NETBIT(FIRST,LAST),<<B'LAST!<B'LAST-B'FIRST>>>

;The values B0-B15 are defined in NETPRM, and are the 16-bit network
; bit and byte-order equivalents of our <n>Bm notation's "m" offsets.

BYTMSK==NETBIT(0,7)		;A NETWORK BYTE
WRDMSK==NETBIT(0,15)		;A NETWORK WORD
SGNBIT==B15			;THE SIGN BIT OF A NETWORK WORD
;Define the Foundation message types

.FMILL==0			;ILLEGAL MESSAGE TYPE
.FMBND==1			;BIND-REQUEST
.FMUNB==2			;UNBIND
.FMREB==3			;RE-BIND (*ILLEGAL*)
.FMBAC==4			;BIND-ACCEPT
.FMENM==5			;ENTER-MODE
.FMEXM==6			;EXIT-MODE
.FMCFM==7			;CONFIRM-MODE
.FMNOM==10			;NO-MODE
.FMCMD==11			;COMMON DATA (CTERM MESSAGES)
.FMMDD==12			;MODE DATA
;Define the O/S types for a Bind message

O.UNSP==0			;UNSPECIFIED
O.RT11==1			;RT-11
O.RSTS==2			;RSTS/E
O.RSXS==3			;RSX-11S
O.RSXM==4			;RSX-11M
O.RSXD==5			;RSX-11D
O.IAS==6			;IAS
O.VMS==7			;VAX/VMS
O.T20==10			;TOPS-20
O.T10==11			;TOPS-10
O.OS8==12			;OS-8
O.RTS8==13			;RTS-8
O.RSXP==14			;RSX-11M+

;Define the valid Protocol types for a Bind-Request message

PT%RST==B0			;RSTS/E HOMOGENEOUS NETWORK TERMINALS
PT%RSX==B1			;RSX-11 HOMOGENEOUS NETWORK TERMINALS
PT%VMS==B2			;VMS HOMOGENEOUS NETWORK TERMINALS
PT%PIM==B3			;PIM (TOPS-10/TOPS-20) HOMOGENEOUS TERMINALS
PT%CTM==B4			;CTERM HETEROGENEOUS TERMINALS

;Define the valid Options flags for a Bind-Request message

OP%HIA==B0			;HIGH-AVAILABILITY SYSTEM

;Define the valid parameters for a CTERM Protocol Initiate message

.PIILL==0			;ILLEGAL PROTOCOL PARAMETER
.PIMMS==1			;MAXIMUM ACCEPTABLE MESSAGE SIZE
.PIIBS==2			;MAXIMUM ACCEPTABLE INPUT BUFFER SIZE
.PISUP==3			;PROTOCOL MESSAGES SUPPORTED BIT MASK

;Define the various minimum acceptable parameter values

MT.SUP==NETBIT(1,14)		;MUST SUPPORT MESSAGES ^D1-^D14
HSTMMS==^D90			;HOSTS MUST BE ABLE TO ACCEPT 90-BYTE MESSAGES
SRVMMS==^D139			;REQUIRED MESSAGE SIZE ACCEPTABLE BY SERVERS
MINIBS==^D80			;SERVERS MUST ALLOW AN 80-CHAR INPUT BUFFER
IFL NRTRIL-HSTMMS,<NRTRIL==HSTMMS
PRINXT % NRTRIL EXPANDED TO HSTMMS>
;Define the Unbind reasons

.UBILL==0			;ILLEGAL UNBIND REASON
.UBICV==1			;INCOMPATIBLE VERSIONS OF THE PROTOCOL(S)
.UBNPA==2			;NO PORTAL AVAILABLE
.UBUUR==3			;USER UNBIND REQUEST
.UBDSC==4			;TERMINAL DISCONNECTED
.UBTIU==5			;REQUESTED LOGICAL TERMINAL IN USE
.UBNST==6			;NO SUCH TERMINAL
.UBPED==7			;PROTOCOL ERROR DETECTED
;Define the CTERM message types

.CMILL==0			;ILLEGAL MESSAGE TYPE
.CMPIN==1			;CTERM PROTOCOL INITIATE
.CMSRD==2			;START-READ
.CMRDD==3			;READ DATA
.CMOOB==4			;OUT-OF-BAND CHARACTER
.CMUNR==5			;UNREAD
.CMCTA==6			;CLEAR ALL TYPEAHEAD
.CMWRT==7			;WRITE
.CMWRC==10			;WRITE COMPLETE
.CMDOS==11			;DISCARD-OUTPUT STATE
.CMRCH==12			;READ CHARACTERISTICS
.CMCHR==13			;CHARACTERISTICS (WRITE/RESPOND)
.CMCHK==14			;CHECK INPUT COUNT
.CMICT==15			;INPUT COUNT
.CMIST==16			;INPUT STATE
;Define the CTERM characteristics that can be set and read via the
;CHARACTERISTICS messages.

;First, the types of characteristics:

.CTCFP==0			;FOUNDATION PHYSICAL
.CTCFL==1			;FOUNDATION LOGICAL
.CTCMH==2			;CTERM MODE HANDLER

;Also define the various format types used for the characteristics

.FTASD==0			;ASCIC FORMAT
.FTBYT==1			;SINGLE-BYTE CHARACTERISTIC
.FTINT==2			;DOUBLE-BYTE CHARACTERISTIC
.FTCCA==3			;COMPOUND: CHARACTER ATTRIBUTES
 SYN .FTBYT,.FTBOL		;BOOLEANS ARE BYTES
 SYN .FTINT,.FT2BY		;2-BYTE MASKS ARE DOUBLE-BYTES

;Define a macro to make it easy to define characteristics and their associated
;formats.  Defines .CCnam and FT.nam for each invocation.

DEFINE	X(NAM,FMT),<
	IF1,<IFDEF .CC'NAM,<PRINTX ? DUPLICATE CHARACTERISTIC .CC'NAM>>
	FT.'NAM==.FT'FMT
	.CC'NAM==<XX==XX+1>>

;Note that characteristic zero is illegal for each of the three types

XX==.CTCFP_8			;START DEFINING THE PHYSICAL CHARACTERISTICS
	X	RSP,INT		;RECEIVE SPEED
	X	TSP,INT		;TRANSMIT SPEED
	X	CSZ,INT		;CHARACTER SIZE
	X	CPE,BOL		;CHARACTER PARITY ENABLED
	X	CPT,INT		;CHARACTER PARITY TYPE
		PAR.EV==1	;EVEN PARITY
		PAR.OD==2	;ODD PARITY
		PAR.SP==3	;SPACE PARITY
		PAR.MK==4	;MARK PARITY
	X	MSP,BOL		;MODEM SIGNALS PRESENT (DATASET)
	X	ABR,BOL		;AUTO-BAUD RECOGNITION
	X	EMG,BOL		;ENTER-MANAGEMENT GUARANTEED
	X	SW1,ASD		;SWITCH-CHARACTER 1
	X	SW2,ASD		;SWITCH-CHARACTER 2
	X	8BC,BOL		;8-BIT CHARACTER-SET TERMINAL
	X	EME,BOL		;ENTER-MANAGEMENT ENABLED
.CMXFP==XX			;MAXIMUM FOR FOUNDATION PHYSICAL

XX==.CTCFL_8			;START DEFINING THE LOGICAL CHARACTERISTICS
	X	MWA,BOL		;MODE WRITING ALLOWED
	X	TAM,2BY		;TERMINAL ATTRIBUTES MASK
		TA%KNO==B0	;TYPE IS KNOWN TO SENDER'S SYSTEM
		TA%DIS==B1	;DISPLAY TERMINAL
	X	TTN,ASD		;TERMINAL TYPE NAME
	X	OFC,BOL		;OUTPUT FLOW CONTROL (TTY XONOFF)
	X	OPS,BOL		;OUTPUT PAGE STOP (TTY STOP)
	X	FCP,BOL		;FLOW-CHARACTER PASSTHROUGH
	X	IFC,BOL		;INPUT FLOW CONTROL
	X	LNE,BOL		;LOSS NOTIFICATION ENABLED
	X	WID,INT		;CARRIAGE WIDTH
	X	LEN,INT		;FORMS LENGTH
	X	SSZ,INT		;STOP SIZE
	X	CRF,INT		;C-R FILL
	X	LFF,INT		;L-F FILL
	X	WRP,INT		;WRAP HANDLING
		WP.NON==1	;NO WRAPPING AT ALL
		WP.TRC==2	;TRUNCATE AT RIGHT MARGIN
		WP.PHY==3	;HARDWARE IS WRAPPING AND WE'RE TRACKING IT
		WP.SFT==4	;FULL SOFTWARE WRAPPING
	X	HTM,INT		;HORIZONTAL TAB MODELING
		HT.PHY==1	;PHYSICAL TABS
		HT.SIM==2	;SOFTWARE-SIMULATED TABS
	X	VTM,INT		;VERTICAL TAB MODELING
		VT.PHY==1	;HARDWARE VT
		VT.SIM==2	;SOFTWARE SIMULATION OF VT
		VT.MAP==3	;TURN INTO FF AND HANDLE AS PER .CCFFM
	X	FFM,INT		;FORM FEED MODELING
		FF.PHY==1	;HARDWARE FF
		FF.SIM==2	;SOFTWARE-SIMULATED FF
.CMXFL==XX			;MAXIMUM FOR FOUNDATION LOGICAL

XX==.CTCMH_8			;BEGIN MODE-HANDLER CHARACTERISTICS
	X	IGN,BOL		;IGNORE INPUT
	X	CAT,CCA		;CHARACTER ATTRIBUTES
	X	COP,BOL		;CONTROL-O PASSTHROUGH
	X	RAI,BOL		;RAISE INPUT
	X	ECH,BOL		;NORMAL ECHO
	X	IER,BOL		;INPUT ESCAPE-SEQUENCE RECOGNITION
	X	OER,BOL		;OUTPUT ESCAPE-SEQUENCE RECOGNITION
	X	CNT,INT		;INPUT-COUNT MESSAGE STATE
		CN.NON==1	;NEVER SEND INPUT-STATE MESSAGES
		CN.NRD==2	;SEND INPUT-STATE ONLY IF NO READ OUTSTANDING
		CN.ALL==3	;ALWAYS SEND INPUT-STATE MESSAGES
	X	APE,BOL		;AUTO-PROMPT ENABLED
	X	EPM,BYT		;ERROR-PROCESSING MASK
		EP%LBK==B0	;LINE BREAK PROCESSING
		EP%FRM==B1	;FRAMING ERROR PROCESSING
		EP%PAR==B2	;PARITY ERROR PROCESSING
		EP%OVR==B3	;RECEIVER OVERRUN PROCESSING
.CMXMH==XX			;MAXIMUM FOR CTERM MODE HANDLER
;Define the flag bits that form the MASK and BITS fields of .CCCAT

CA.OOB==B0!B1			;OUT-OF-BAND TYPE
	.OBNOT==0		;NOT O-O-B AT ALL
	.OBCLR==1		;IMMEDIATE CLEAR
	.OBDFR==2		;DEFERRED CLEAR
	.OBHEL==3		;IMMEDIATE HELLO
CA.INC==B2			;INCLUDE FLAG FOR .OBHEL
CA.SDO==B3			;SETS DISCARD-OUTPUT IF ON & OOB
CA.ECH==B4!B5			;ECHO FORM (FOR CONTROL CHARACTERS)
  CA.SLF==B4			;ECHO AS SELF
  CA.STD==B5			;ECHO IN STANDARD FORM
				;(CA.STD HAPPENS BEFORE CA.SLF)
CA.ENB==B6			;ENABLE ANY SPECIAL FUNCTIONS IT MIGHT HAVE

CA.MSK==CA.ENB!CA.ECH!CA.SDO!CA.INC!CA.OOB	;SETTABLE BITS
;Define the flags field for a start-read message

SR.UND==B0!B1			;UNDERFLOW HANDLING
	.SRIGN==0		;IGNORE UNDERFLOW
	.SRBEL==1		;RING BELL ON UNDERFLOW
	.SRTRM==2		;TERMINATE ON UNDERFLOW
SR.CTA==B2			;CLEAR-TYPEAHEAD IF ON
SR.FMT==B3			;DO FANCY CR/LF FORMATTING IF ON
SR.VPT==B4			;TERMINATE ON VERTICAL POSITION CHANGE
SR.CON==B5			;THIS IS A CONTINUATION READ
SR.RAI==B6!B7			;RAISE-INPUT HANDLING
	.SRUNS==0		;UNSPECIFIED, USE CHARACTERISTIC
	.SRSLC==1		;SINGLE-READ ALLOW LOWER CASE
	.SRSUC==2		;SINGLE-READ FORCE UPPER CASE
SR.CCD==B8!B9!B10		;CONTROL-CHARACTER DISABLE FIELD
	.SRNON==0		;NONE ARE DISABLED
	.SRLIN==1		;THE LINE CHARACTERS (^R & ^U) ARE DISABLED
	.SREDI==2		;THE EDITING CHARACTERS ARE DISABLED
	.SRALL==3		;ALL BUT XON/XOFF ARE DISABLED
SR.NEC==B11			;NO-ECHO FOR THIS READ DESPITE CHARACTERISTIC
SR.ECT==B12			;ECHO TERMINATORS
SR.TMR==B13			;TIMER FIELD IS SPECIFIED
SR.TRM==B14!B15			;TERMINATOR MASK SPECIFICATION
	.SRUPT==0		;USE PREVIOUSLY SPECIFIED MASK
	.SRUNT==1		;USE NEW TERMINATOR MASK (SUPPLIED)
	.SRUUT==2		;USE THE 'UNIVERSAL' TERMINATOR MASK
;(SECOND WORD--REALLY ONLY THIRD BYTE)
S2.IER==B0!B1			;INPUT ESCAPE-SEQUENCE RECOGNITION
	.SRUNS==0		;UNSPECIFIED, USE CHARACTERISTIC
	.SRSIE==1		;SINGLE-READ IGNORE ESCAPES
	.SRSRE==2		;SINGLE-READ RECOGNIZE ESCAPES
;Define the flags that come with a Read-Data message

RD.TRM==NETBIT(0,3)		;TERMINATION REASON CODE
	.RDTRM==0		;TERMINATOR CHARACTER SEEN
	.RDVES==1		;VALID ESCAPE SEQUENCE
	.RDIES==2		;INVALID ESCAPE SEQUENCE
	.RDOOB==3		;OUT-OF-BAND CHARACTER
	.RDIBF==4		;INPUT BUFFER FULL
	.RDTMO==5		;TIMED-OUT
	.RDUNR==6		;UNREAD RECEIVED
	.RDUND==7		;DELETION UNDERFLOW
	.RDTOK==10		;ABSENTEE TOKEN
	.RDVPC==11		;VERTICAL POSITION CHANGE
	.RDLBK==12		;LINE BREAK ERROR
	.RDFRM==13		;FRAMING ERROR
	.RDPAR==14		;PARITY ERROR
	.RDOVR==15		;RECEIVER OVERRUN
RD.IIP==B4			;INPUT IS PRESENT (INPUT-STATE PIGGYBACK)
;Define the bits that can be sent with a Write message

WR.LOK==B0!B1			;THE LOCK/UNLOCK FIELD
	.WRULK==0		;UNLOCK AT START
	.WRLOK==1		;LOCK & LEAVE LOCKED
	.WRLTU==2		;LOCK AT START THEN UNLOCK AT END
	.WRLUR==3		;.WRLTU FOLLOWED BY REDISPLAY OF INPUT
WR.FMT==B2			;DO FANCY CR/LF FORMATTING IF ON
WR.CDS==B3			;CLEAR DISCARD STATE
WR.BOM==B4			;THIS IS FIRST PART OF WRITE MESSAGE
WR.EOM==B5			;THIS IS LOGICAL END OF WRITE MESSAGE
WR.PRE==B6!B7			;PREFIX CHARACTER HANDLING
	.WRIGN==0		;IGNORE THE FIELD
	.WRNLC==1		;FIELD IS NEW-LINE COUNT
	.WRCHR==2		;FIELD IS A CHARACTER
WR.PST==B8!B9			;POSTFIX CHARACTER HANDLING
	;USES SAME VALUES AS WR.PRE
WR.VFY==B10			;VERIFY BY SENDING A WRITE-COMPLETE WHEN DONE
WR.BIN==B11			;BINARY (TRANSPARENT) WRITE OF CHARACTERS
;Define the flags that come with a Discard-State message

DS.CDS==B0			;CLEAR DISCARD STATE IF ON, SET IF OFF


;Define the flags that come with an input state message

IS.IIP==B0			;INPUT IS NEWLY PRESENT IF ON, ABSENT IF OFF


;Define the flags that come with an Out-of-Band message

OB.DIS==B0			;SET DISCARD-OUTPUT STATE TRUE


;Define the flag bits that can be sent with an Unread message

UR.OIE==B0			;WHEN LIT, ONLY CANCEL THE READ IF THERE ARE NO
				; CHARACTERS AVAILABLE (AT ALL)
;Helper macro to build byte strings to send over the network

DEFINE	BYTSTR (PFX,BYTES),<
IFNB<BYTES>,<
	IFDEF PFX'S,<CONCAT PFX'S,<,>>
	IFNDEF PFX'S,<
		CCLEAR PFX'S
		CONCAT PFX'S,<BYTE (8)>
		PFX'LEN==0
		>
	CONCAT	PFX'S,<BYTES>
	IRP BYTES,<PFX'LEN==PFX'LEN+1>
>
IFB<BYTES>,<
	PFX'S
	PURGE	PFX'S
>>;END DEFINE BYTSTR
;Define macros to build the Characteristics messages

FORX. <CSC,PIM,IMI>,PFX,<
	DEFINE	PFX(NAM,VAL),<
		BYTSTR(PFX,<.CC'NAM,.CC'NAM/B8>)
	IFE FT.'NAM-.FTBYT,< BYTSTR(PFX,<VAL>) >
	IFE FT.'NAM-.FTINT,< BYTSTR(PFX,<<VAL>,<VAL>/B8>) >
	IFE FT.'NAM-.FTCCA,< BYTSTR(PFX,<<VAL>/B8,CA.MSK,<VAL>>) >
	IFE FT.'NAM-.FTASD,<
			..'PFX==0
			IRPC VAL,<..'PFX==..'PFX+1>
			BYTSTR (PFX,\..'PFX)
			IRPC VAL,<	IFIDN<VAL><">,< BYTSTR(PFX,"""") >
					IFDIF<VAL><">,< BYTSTR(PFX,"VAL") >
				>
			>
	> ;END DEFINE PFX
> ;END OF FORX.
;Define macro to build the Parameters portion of our Protocol Initiate message

DEFINE	CPI(NAM,VAL),<
	BYTSTR(CPI,.PI'NAM)
	...CPI==<VAL>
	..CPI==0
	REPEAT 5,<;;VALUE MUST FIT IN A WORD, AFTER ALL
		IFN ...CPI,<
			..CPI==..CPI+1
			...CPI==...CPI_-8>
		>
	BYTSTR(CPI,\..CPI)
	...CPI==<VAL>
	REPEAT ..CPI,<
		BYTSTR(CPI,\...CPI)
		...CPI==...CPI_-8
		>
> ;END DEFINE CPI
;Define macro to send selector sequence for our Read Characteristics message

DEFINE	RSC(NAM,CHR),<
	BYTSTR(RSC,<.CC'NAM,.CC'NAM/B8>)
IFE FT.'NAM-.FTCCA,< BYTSTR(RSC,CHR) >
> ;END DEFINE RSC
	SUBTTL	NRT Data Base Definitions

;The NRB is the NRT Data Block.  One is allocated for each active
;link to hold data associating the DECnet link with an LDB.

DEFINE CMNBLK<
	WORD	LDB		;PTR TO ASSOCIATED LDB
	HWORD	CHN		;DECnet CHANNEL NUMBER
	HWORD	STS		;CURRENT STATUS OF DECnet LINK
	HWORD	SIZ		;MAX CHARS IN A SEGMENT ON THIS LINK
	FIELD	FLG,18		;FLAGS
	  BIT	CFG		;SET IF CONFIG MSG HAS BEEN SENT
	  BIT	REL		;THIS NRB IS BEING RELEASED
	  BIT	CTM		;SET IF THIS IS A CTB, NOT A NRB
	  BIT	RLS		;WANT UNBIND SENT (DISCONNECTING)
	  BIT	XOF		;SCNSER REQUESTED NO DRQ'S FOR A WHILE
>

BEGSTR NR			;USUALLY INDEXED BY W
	CMNBLK			;STANDARD PART OF BLOCK ONLY
	;FIELD	FLG,18		;WHERE WE ARE (5 BITS IN)
;NRT-SPECIFIC ITEMS FROM HERE ON
	  BIT	TMO		;CONNECT TIMED OUT BY SCNSER
ENDSTR


BEGSTR CT
	CMNBLK			;INCLUDE STANDARD PORTION OF BLOCK
	;FIELD	FLG,18		;WHERE WE ARE (5 BITS IN)
;CTERM-SPECIFIC ITEMS FROM HERE ON
	  BIT	BND		;BIND-ACCEPT RECEIVED (FOUNDATION RUNNING)
	  BIT	SPI		;SENT PROTOCOL INIT (CTERM LEVEL)
	  BIT	RPI		;RECEIVED PROTOCOL INIT (CTERM RUNNING)
	  BIT	RCS		;READ CHARACTERISTICS SENT
	  BIT	CHP		;NEED TO SEND CHARACTERISTICS MSG
	  BIT	CSD		;CHARACTERISTICS SEQUENCE DONE (LINK IS READY)
	  BIT	DRQ		;DATA REQUEST OUTSTANDING (START-READ MSG)
	  BIT	ECH		;THIS DRQ IS ECHOING
	  BIT	OBC		;OUT-OF-BAND CHANGE (RE-CALC BREAK MASK)
	  BIT	BMC		;BREAK MASK CHANGE
	  BIT	CTG		;CHARACTER TO GO (CTCHO IS VALID)
	  BIT	URA		;UNREAD ACTIVE (FOR CTHDRQ)
	  BIT	DRZ		;LAST DATA REQUEST WAS OF ZERO EFFECT
	WORD	IFM,4		;16. BYTES OF INPUT FOUNDATION MESSAGE STORAGE
	WORD	MW1		;A WORD FOR MESSAGE PROCESSORS
	WORD	IML		;LENGTH OF COMMON DATA STRING IN PROGRESS
	WORD	IFL		;BUFFER COUNTDOWN FOR RE-READING CTIFM
	FIELD	FLM,18		;CTERM MODE FLAGS
	  BIT	RUN		;CTERM IS RUNNING ON THIS LINK
	  BIT	MI0		;THE MODE PROCESSOR HAS ALREADY BEEN INITIALIZED
	  BIT	MI1		;THE MESSAGE HANDLER HAS SKIPPED ITS FILLER
	  BIT	CIB		;NEED TO CLEAR THE INPUT BUFFER
	  BIT	DRI		;DATA REQUEST INVALID (CAME AFTER IRRCIB)
	  BIT	BAD		;KNOWN BAD PROTOCOL (VMS)
	FIELD	CHO,9		;CHARACTER TO OUTPUT (WHEN CHANGING IMAGE STATE)
	FIELD	IFT,8		;INPUT FOUNDATION TYPE (MESSAGE IN PROGRESS)
	FIELD	IMT,8		;INPUT CTERM MODE TYPE (MESSAGE IN PROGRESS)
	FIELD	MIJ,8		;'JUNK' MESSAGE BYTES THAT NEED TO BE SKIPPED
	FIELD	MB1,8		;FIRST RANDOM BYTE FOR SUB-MESSAGE PROCESSING
	FIELD	IBS,8		;MAXIMUM INPUT BUFFER SIZE REMOTE CAN HANDLE
	FIELD	UBR,4		;UNBIND REASON
	FIELD	RLN,18		;REMOTE'S LINE NUMBER
	FIELD	ROS,18		;REMOTE'S O/S TYPE
ENDSTR

BEGSTR	CH,CT.LST		;LAST CHARACTERISTICS SENT TO REMOTE
	WORD	BKM,8		;LAST BREAK MASK SENT
	FIELD	WID,8		;TTY WIDTH
	FIELD	LNB,8		;TTY LENGTH
	FIELD	TTT,8		;TTY TYPE INDEX
	FIELD	FLG,12		;SINGLE-BIT VALUES
	  BIT	LCT		;RAISE INPUT
	  BIT	ECH		;NO ECHO
	  BIT	DIS		;DISPLAY
	  BIT	XNF		;XON/XOFF
	  BIT	8BT		;EIGHT-BIT TERMINAL
	  BIT	IMI		;IMAGE I/O MODE
	  BIT	PIM		;PACKED IMAGE MODE
ENDSTR

CT.LEN==CH.LST		;EACH CTB NEEDS TO INCLUDE A CH BLOCK
	SUBTTL	Impure Storage

	$LOW			;IMPURE STUFF

NRTDFT::EXP	<FLD(^D9,PDGOL) ! FLD(^D16,PDDQT) ! FLD(^D50,PDIPR)>
NRTINL:	EXP	NRTINT		;NUMBER OF JIFFIES BETWEEN NRT SERVICES
NRTINC:	BLOCK	1		;NRT INTERVAL COUNTER, SEE NRTSTO
NRTINA:	EXP	M.NIDL##	;AUTO-DISCONNECT TIMER VALUE (POKABLE)
NRTMAX::EXP	NRTMXC		;MAX SIZED RECORD WE'LL SEND (POKABLE)
NRTRTQ:	BLOCK	2		;QUEUE HEADER FOR LDBQUE
NRTPSQ:	BLOCK	1		;NON-ZERO IF DECnet NEEDS SERVICE
NRTCWL::BLOCK	1		;NUMBER OF NRT LINKS IN CW STATE
CTHCWL::BLOCK	1		;NUMBER OF CTERM LINKS IN CW STATE
NRTCHP::BLOCK	1		;POINTER TO NRT CHANNEL TABLE
NRTCHL:	BLOCK	1		; AND ITS LENGTH (WORDS)
NRTSJP::BLOCK	1		;PTR TO NRT'S SJB (ACCESS FROM SEC 1)
NRTSAP:	BLOCK	1		;PTR TO NRT'S SAB (SEC 0/1 ADDR)
NRTBLW:	BLOCK	1		;SAVED NRB PTR FOR BLOCKED LINK
NRTBLP:	BLOCK	2		;SAVED BYTE PTR "    "      "
NRTBLC:	BLOCK	1		;SAVED BYTE COUNT "  "      "
NRTRCO:	BLOCK	<<NRTROL+3>/4>	;PLACE TO BUILD OUTPUT RECORD
NRTRCI:	BLOCK	<<NRTRIL+3>/4>	;PLACE TO BUILD INPUT RECORD
CTHIFP:	BLOCK	1		;INPUT POINTER FOR FOUNDATION BUFFERS
CTHCDP:	BLOCK	1		;OUTPUT POINTER FOR COMMON DATA MESSAGES
CTHCDL:	BLOCK	1		;WORD USED TO FIND LENGTH OF CTERM OUTPUT DATA
CTH6BW:	BLOCK	1		;WORD USED TO ACCUMULATE SIXBIT
CTHBUL:	BLOCK	1		;WORD USED TO BYPASS USELESS MESSAGES

	$HIGH
	SUBTTL	LDBISR Dispatch Table

NRTDSP::JRST	CPOPJ##		;( 0)ILLEGAL NOW.  DON'T USE!!
	JRST	CPOPJ##		;( 1)MODEM CONTROL
	JRST	NRTSEC		;( 2)ONCE A SECOND CALL (NOT PER TTY)
	JRST	CPOPJ##		;( 3)INITIALIZE
	JRST	CTHCHP		;( 4)CHANGE HARDWARE PARMS
	JRST	CPOPJ##		;( 5)LINE PARM CONTROL
	JRST	CPOPJ##		;( 6)SET TERMINAL ELEMENT
	JRST	NRTREM		;( 7)STUFF FOR REMOTE TERMINALS
	JRST	CPOPJ1##	;(10)IS LINE DEFINED ON STATION (YES)


CTHCHP==SETCHP##		;LET SCNSER DO IT

NRTREM:	SKIPN	T1,LDBNRT##(U)	;IS THIS LINE CONTROLLED BY NRTSER?
	RET			;NO, FORGET IT
	CAILE	T3,IRRINV	;MAKE SURE THE ISRREM SUB-CODE IS IN RANGE
	CAILE	T3,IRROOB	;DO WE UNDERSTAND IT?
	RET			;NO, IGNORE IT
	PUSHJ	P,SAVR##	;PRESERVE FOR TOP-LEVEL CALLERS
	TMNE	NRCTM,(T1)	;YES, BUT IS IT RUNNING CTERM PROTOCOL?
	JRST	CTHREM		;YES, CTERM HANDLES MORE OF THESE REQUESTS
	PJRST	@.(T3)		;NO, NRT, DISPATCH FOR IT
	IFIW	CTHCSL		;(1) CHUNK SPACE LOW
	IFIW	CPOPJ		;(2) CHARACTER NOT STORED (RECHLT)
	IFIW	CPOPJ		;(3) OUTPUT SUPPRESSION CHANGE (DON'T CARE)
	IFIW	CTHCSA		;(4) CHUNK SPACE AVAILABLE
	IFIW	NRTRM1		;(5) DISCONNECT (TRMOP. .TODNT)
	IFIW	CPOPJ		;(6) CLEAR INPUT BUFFER (CLRBFI) (CAN'T DO)
	IFIW	NRTRM1		;(7) DISCONNECT TIMEOUT
	IFIW	CPOPJ		;(10) BREAK MASK CHANGED
	IFIW	CPOPJ		;(11) OOB SET CHANGED

NRTRM1:	MOVX	R,NRRLS		;GET RELEASE BIT
	CAIN	T3,IRRTMO	;WAS THIS A TIMEOUT?
	TXO	R,NRTMO		;YES, FLAG THAT ALSO
	IORM	R,NR.FLG(T1)	;SET OUR FLAGS FOR NRTLKS
	PJRST	TOPOK1		;QUEUE & SUCCEED

CTHREM:	PJRST	@.(T3)		;DISPATCH FOR CTERM
	IFIW	CTHCSL		;(1) CHUNK SPACE LOW
	IFIW	CTHCNS		;(2) CHARACTER NOT STORED
	IFIW	CTHOSU		;(3) OUTPUT SUPPRESSION CHANGE
	IFIW	CTHCSA		;(4) CHUNK SPACE AVAILABLE
	IFIW	CTHDSC		;(5) DISCONNECT (TRMOP. .TODSF)
	IFIW	CTHCIB		;(6) CLEAR INPUT BUFFER (CLRBFI)
	IFIW	CTHTMO		;(7) DISCONNECT TIMEOUT
	IFIW	CTHBMC		;(10) BREAK MASK CHANGED
	IFIW	CTHBMC		;(11) OOB SET CHANGED

CTHCSL:	SETONE	CTXOF,(T1)	;REMEMBER SCNSER ASKED FOR AN XOFF
	RETSKP			;TELL IT NOT TO SEND ONE

CTHCNS==CPOPJ##			;DON'T HANDLE UNTIL WE CAN MANAGE INPUT BLOCKING

CTHOSU:	MOVX	T2,CTCTG	;CHARACTER-TO-GO BIT
	MOVX	T3,CTCSD	;CHARACTERISTICS-SEQUENCE-DONE BIT
	TDNE	T3,CT.CSD(T1)	;IF CTCTG IS FOR NORMAL DATA,
	ANDCAM	T2,CT.CTG(T1)	;THEN DON'T SEND THE DEFERRED CHARACTER
	RET			;AND DEFER TO CLOCK LEVEL SERVICE

CTHCSA:	SETZRO	CTXOF,(T1)	;OK TO SEND DRQ'S AGAIN (ACCORDING TO SCNSER)
	PJRST	TOPOK1		;QUEUE FOR SERVICE AND SKIP THE CONTROL-Q

CTHDSC:	SKIPA	T2,[.UBUUR]	;USER UNBIND REQUEST
CTHTMO:	MOVEI	T2,.UBDSC	;TERMINAL DISCONNECTED
	TMNE	CTBAD,(T1)	;IF SUB-STANDARD PROTOCOL,
	MOVEI	T2,.UBUUR	;BE NICE AND DON'T MAKE VMS HANG UP ON THE USER
	STOR	T2,CTUBR,(T1)	;SAVE UNBIND REASON
	PJRST	TOPOK1		;QUEUE & SUCCEED

CTHCIB:	SETONE	CTCIB,(T1)	;LIGHT BIT FOR NRTLKS
	PJRST	TOPOKE##	;RETURN TO SCNSER, QUEUEING FOR SERVICE

CTHBMC:	SETONE	CTOBC,(T1)	;RE-CALCULATE THE BREAK TABLE
TOPOK1:	AOS	(P)		;RETURN SUCCESS
	PJRST	TOPOKE##	;BUT ALSO QUEUE FOR SERVICE
	SUBTTL	NRTINI - Initialization

;Here to set up NRT host object for DECnet
;
;Call:
;	RET			;ALWAYS
;
;Here to initialize the NRT data base

NRTINI::SAVEAC	<M,W>		;CALLED FROM SYSINI
	SEC1			;NRTSER RUNS IN SECTION 1
	HLRE	T1,NETRTY##	;GET LENGTH OF AOBJN PTR TO NET LDBS
	MOVMS	T1		;MAKE POSITIVE
	AOJ	T1,		;LEAVE ROOM FOR RELEASE TIMING
	MOVEM	T1,NRTCHL	;SAVE CHANNEL TABLE LENGTH
	CALL	NRTGWD		;GET WORDS FOR OUR CHANNEL TABLE
	  BUG. HLT,NRTSJM,NRTSER,SOFT,<No memory for NRT's SJB>,,<

Cause:	This BUG is not documented yet.

>,NRTINI
	MOVEM	T1,NRTCHP	;STORE POINTER TO CHANNEL TABLE

	MOVX	T1,SA.LEN	;LENGTH OF AN SAB
	CALL	NRTGWD		;GET WORDS FOR OUR SA BLOCK
	  BUG. HLT,NRTSAB,NRTSER,SOFT,<No memory for NRT's SAB>,,<

Cause:	This BUG is not documented yet.

>,NRTINI
	MOVEM	T1,NRTSAP	;STORE POINTER TO SCLINK ARG BLK
	MOVEM	T1,M		;NORMALLY USE M TO POINT TO SAB

;We will elect No Flow Control on incoming links.
;		Default Goal		Quota		Input %
	MOVE	T1,NRTDFT	;GET DEFAULT GOAL,QUOTAS
	SETZM	NRTSJP		;IN CASE WE FAIL, SIGNAL TO OTHERS
	SNCALL	(MAKSJB##,MS.HGH) ;GO MAKE AN SJB
	  BUG. HLT,NRTSJB,NRTSER,SOFT,<No memory for NRT's SJB>,,<

Cause:	This BUG is not documented yet.

>,NRTINI
	SETONE	SJPRV,(T1)	;TURN ON PRIVED BIT IN SJB
	MOVEM	T1,NRTSJP	;SAVE POINTER TO OUR SJB

	STOR	M,SJSAB,(T1)	;SAVE SAB PTR FOR SCLINK
	RET			;RETURN
	SUBTTL	NRTSTO - Called every Jiffy via .CPSTO

;Called every jiffy to handle DECnet Network Remote Terminals
;
;Call:
;	RET			;ALWAYS
;
;Changes M,W,U and T1 through T4

NRTSTO::
IFN FTMP,<XCT	.CPSK0##	;SKIP IF WE'RE ON POLICY CPU
	  RET			;NO, ONLY RUN ONCE A JIFFY!
	 >
	SOSG	NRTINC		;HAS INTERVAL COUNTER EXPIRED YET?
	SKIPN	NRTSJP		;YES, HAS NRTINI BEEN CALLED?
	RET			;NO
	MOVE	T1,NRTINL	;YES, GET INTERVAL LENGTH
	MOVEM	T1,NRTINC	;REINITIALIZE THE INTERVAL COUNTER
	SEC1			;NRTSER RUNS IN SECTION 1
IFE FTXMON,<
	DNCALL	(NRTSTX)	;CALL REST IN DECNET CONTEXT
	RET			;DONE
>

NRTSTX:	SKIPE	NRTBLW		;IS THERE A BLOCKED LINK?
	JRST	[CALL	NRTUNB	;  YES, UNBLOCK IT
		  JRST	NRTST3	;  STILL BLK'D, SEE IF WE CAN FREE ANY
		 JRST	.+1]	;ALL CLEAR NOW, TRY FOR MORE OUTPUT
	SKIPN	NRTCWL		;ANY CONNECT WAITERS?
	CALL	NRTNEP		;NO, MAKE ANOTHER IF WE CAN
	SKIPN	CTHCWL		;ANY CONNECT WAITERS?
	CALL	CTHNEP		;NO, MAKE ANOTHER IF WE CAN

;We know that we can safely take at least one link with TOTAKE, since
;there is now no other blocked link, so the worst that can happen
;is that this link will become blocked and we'll have to try it again.

NRTST1:	MOVEI	T1,NRTRTQ	;GET THE QUEUE HEADER
	CALL	TOTAKE##	;GET U := TERMINAL NEEDING SERVICE
	  JRST	NRTST2		;IF NONE, THEN ALL DONE
	SKIPE	W,LDBNRT##(U)	;GET POINTER TO ITS NRB
	CALL	NRTLKS		;SERVICE THE LINK, IF ITS STILL THERE
	JRST	NRTST1		;GO SEE IF ANY MORE TERMINALS TO START

;Loop over lines DECnet wants to service

NRTST2:	SETZ	T1,		;LOAD UP A ZERO
	EXCH	T1,NRTPSQ	;CLEAR FLAG SAYING DECnet WANTS US
	JUMPE	T1,NRTST4	;LEAVE IF DECnet DIDN'T WANT SERVICE

NRTST3:	MOVE	T1,NRTSJP	;POINTER TO NRT'S SJB (EXTENDED ADDR)
	SNCALL	(SCTPSQ##,MS.HGH) ;ANY SERVICE NEEDED? (EXTENDED CALL)
NRTST4:	  RET			;NO, ALL DONE FOR THIS INTERVAL
	HRRZ	T1,T2		;YES, GET CHANNEL NUMBER
	MOVE	T3,T1		;COPY CHANNEL NUMBER
	ADD	T3,NRTCHP	;ADD IN BASE ADDR OF CHANNEL TABLE
	SKIPG	W,(T3)		;GET PTR TO NRB, ANYTHING THERE?
	JRST	NRTST3		;NO, NO LONGER INTERESTED
	OPSTR	<CAME T1,>,NRCHN,(W) ;CHECK CHANNEL NUMBER
	  BUG. CHK,NRTSET,NRTSER,SOFT,<SCTPSQ returned wrong channel info>,,<

Cause:	This BUG is not documented yet.

>,NRTST3
	CALL	NRTLKS		;SERVICE THE LINK
	JRST	NRTST3		;LOOP OVER LINKS NEEDING SERVICE
	SUBTTL	NRTSEC - Called every second via .CPSTO

;Called every second to handle DECnet Network Remote Terminals
;
;Call:
;	U/ Pointer to LDB
;	RET			;ALWAYS
;
;Changes M,W,U and T1 through T4
;
;This routine is called at clock level (as are all NRTSER routines
;except NRTWAK) so it does not need an interlock from NRTSTO.

NRTSEC::
IFN FTMP,<
	XCT	.CPSK0##	;SKIP IF WE'RE ON POLICY CPU
	RET			;NO, ONLY RUN ONCE A SECOND!
>
	SAVEAC <W,U,P1,P2>
	SEC1			;NRTSER RUNS IN SECTION 1
	SKIPN	NRTBLW		;ANY BLOCKED LINK?
	JRST	NRTSE1		;NO
IFE FTXMON,<
	DNCALL	(NRTSCX)	;NEED DECNET CONTEXT
	RET
>

NRTSCX:	CALL	NRTUNB		;YES, TRY TO UNBLOCK IT
	  RET			;CAN'T, DECnet IS BLOCKED
NRTSE1:
	RET
	SUBTTL	NJFRxx - Routines to handle each DECnet link state

;Routine to service a link according to its DECnet state
;Call
;	W/ Pointer to NRB
;	U/ Pointer to LDB
;
;Return:
;	RET			;ONLY RETURN

NRTLKS:	TMNE	NRREL,(W)	;IS THIS NRB BEING RELEASED?
	PJRST	NRTREL		;YES, COMPLETE THE PROCESS

	MOVE	M,NRTSAP	;POINT TO NRT'S SAB
	MOVX	T1,.NSFRS	;READ STATUS FUNCTION CODE
	MOVEI	T2,3		;NUMBER OF ARGS PASSED
	CALL	NRTNSF		;READ LINK STATUS, STORE IT IN NRB
	  PJRST NRTREL		;ERROR, CLEAN UP
	LOAD	T1,NRSTS,(W)	;GET LINK'S STATUS WORD
	LOAD	T1,NSSTA,+T1	;GET THE STATE FIELD FROM STATUS
	CAILE	T1,NJFTLN	;A STATE WE UNDERSTAND?
	SETZ	T1,		;NO, CALL ILLEGAL STATE BUG.
	PJRST	@NJFTBL(T1)	;CALL ROUTINE APPROPRIATE TO LINK STATE


DEFINE LNKSTA(code),<
	IFN	.-NJFTBL-.NSS'code,<PRINTX NJFTBL is in wrong order>
	IFIW	NJFR'code	;;ADDRESS OF NJF ROUTINE
>

NJFTBL:	IFIW	NJFRIL		;ILLEGAL STATE
	LNKSTA	CW		;CONNECT WAIT
	LNKSTA	CR		;CONNECT RECEIVED
	LNKSTA	CS		;CONNECT SENT
	LNKSTA	RJ		;REMOTE REJECTED CONNECT INIT
	LNKSTA	RN		;LINK IS UP AND RUNNING
	LNKSTA	DR		;DISCONNECT RECEIVED
	LNKSTA	DS		;DISCONNECT SENT
	LNKSTA	DC		;DISCONNECT CONFIRMED
	LNKSTA	CF		;NO CONFIDENCE
	LNKSTA	LK		;NO LINK
	LNKSTA	CM		;NO COMMUNICATION
	LNKSTA	NR		;NO RESOURCES
NJFTLN==.-1-NJFTBL		;LENGTH	OF TABLE

	PURGE	LNKSTA

NJFRCS:				;CONNECT SENT
NJFRIL:	BUG. CHK,NRTILS,NRTSER,SOFT,<NRT link in unexpected state>,,<

Cause:	This BUG is not documented yet.

>,NRTREL

NJFRRJ:				;REJECTED, WAITING FOR DC
NJFRDS:				;DISCONNECT SENT, WAITING FOR DC
NJFRCW:	RET			;CONNECT WAIT, WAITING FOR A CONNECT
;NJFRCR - Jiffy Service Routine for a link in CONNECT RECEIVED state
;
;Call:
;	W/ Pointer to Link's NRB
;	RET			;ALWAYS
;
;Now we	have someone interested in this link, try to get a LDB for
;it.  If that succeeds, accept the link.

NJFRCR:				;CONNECT RECEIVED STATE PROCESSOR
	TMNE	NRCTM,(W)	;IS THIS A CTERM CONNECT?
	SOSA	CTHCWL		;YES, ONE LESS CTERM WAITER
	SOS	NRTCWL		;NO, ONE LESS NRT LINK IN CW STATE
	MOVX	T1,RSNRNS	;REMOTE NODE SHUT DOWN REASON CODE
	MOVE	T2,STATES##	;GET THE SCHEDULE BITS
	TRNE	T2,ST.NRT	;NO REMOTE TERMINALS?
	JRST	NJRCRF		;YES, GO ANNOUNCE THE FAILURE

;Get a TTY for this link

	CALL	NGTLDB		;GET A NRT LDB
	  JRST	NJRCRF		;FAILED, REASON CODE IN T1

;Accept the Connect

	MOVE	M,NRTSAP	;POINT TO NRT'S SAB
	SETZRO	SAAA1,(M)	;NO USER DATA
	MOVEI	T1,NRTROL	;GET MAX BYTES IN OUR RECORD
	STOR	T1,SAAA2,(M)	;USE A MSG SEGMENT NO BIGGER THAN THAT
	MOVX	T1,NSF.C0	;ELECT NO FLOW CONTROL FOR INPUT
	STOR	T1,SAAA3,(M)	;ARG #3
	MOVX	T1,.NSFAC	;ACCEPT FUNCTION CODE
	MOVEI	T2,5		;NUMBER OF ARGS PASSED
	CALL	NRTNSF		;ACCEPT THE CONNECT
	  PJRST NRTREL		;ERROR, CLEAN UP

;Read link status to find out segment size

	MOVE	M,NRTSAP	;POINT TO NRT'S SAB
	MOVX	T1,.NSFRS	;READ STATUS FUNCTION CODE
	MOVEI	T2,3		;NUMBER OF ARGS PASSED
	CALL	NRTNSF		;READ LINK STATUS
	  PJRST NRTREL		;ERROR, CLEAN UP
	LOAD	T1,SAAA1,(M)	;GET LINK'S SEGMENT SIZE
	CAMLE	T1,NRTMAX	;IS THAT TOO BIG FOR US?
	MOVE	T1,NRTMAX	;YES, LOAD UP OUR MAX
	CAILE	T1,NRTROL	;HAS SOMEONE POKED THAT TOO BIG?
	MOVEI	T1,NRTROL	;YES, LIMIT TO SIZE OF RECORD
	STOR	T1,NRSIZ,(W)	;STORE FOR NRTOUT
	MOVE	T1,NRTINA	;GET INACTIVITY TIMER
	CALL	SCNADT##	;START THE TIMER GOING

	TMNN	NRCTM,(W)	;CTERM LINK?
	PJRST	NRTNEP		;NO, HANG OUT A NEW NRT CONNECT WAIT LINK
	LOAD	T1,NRSIZ,(W)	;YES, GET SIZE AGAIN
	CAIGE	T1,CTHMSZ	;IS THE BUFFER SIZE ACCEPTABLE?
	CALL	NRTREL		;NO, PUNT THE LINK
	PJRST	CTHNEP		;HANG OUT A NEW CTERM LINK

;We'll send a configuration message when we get a data request.
;Here on failure in Connect Received state processing

NJRCRF:	MOVE	M,NRTSAP	;POINT TO NRT'S SAB
	STOR	T1,SAAA2,(M)	;SET DISCONNECT REASON
	SETZRO	SAAA1,(M)	;NO STRING BLOCK
	MOVX	T1,.NSFRJ	;REJECT FUNCTION CODE
	MOVEI	T2,4		;NUMBER OF ARGS PASSED
	CALL	NRTNSF		;REJECT THE CONNECT
	  PJRST NRTREL		;RELEASE THE LINK
	RET			;WE'LL RELEASE LINK WHEN DC COMES IN


;The configuration message sent out when we accept a connect

CFGLEN==10			;BYTES	IN CONFIG MESSAGE
CFGMSG:	BYTE(8) 1,1,0,0,11,0,10,0
;	Config--' ^ ^ ^  ^ ^  ^ ^
;		  ? ? ?  | ?  | ?
;	System=TOPS10----'    |
;	Protocol=TOPS20-------'

;The Bind message sent out when CTERM accepts a connect

OSTYPE==O.T10			;OUR O/S TYPE
PTTYPE==PT%CTM			;PROTOCOLS WE SUPPORT

BNDMSG:	BYTE	(8) .FMBND,2,0,0,OSTYPE,OSTYPE/B8,PTTYPE,PTTYPE/B8
;REMAINING BYTES	ARE VARIABLE, AND FILLED IN BY SNDCFG

BNDLEN==23			;TOTAL BYTES IN BIND-REQUEST MESSAGE

;BIND/CONFIG FIELDS:
; (0) MESSAGE TYPE (CONFIG/BIND-REQUEST)
; (1-3) PROTOCOL VERSION:
;   (1) MAJOR
;   (2) ECO (MINOR)
;   (3) MOD (CUSTOMER) LEVEL
; (4-5) SYSTEM TYPE CODE (NETWORK BYTE ORDER) 11=TOPS10
; (6-7) MASK OF PROTOCOLS SUPPORTED (NETWORK BYTE ORDER)
;    10=PIM (NRT)
;    20=CTERM
; (10-17) SYSTEM REVISION STRING (ASCII)
; (20-21) LDPLNO
; (22) OPTIONS (1=HIGH-AVAILABILITY)
;NJFRRN - Jiffy Service Routine for a link in RUN state
;
;Call:
;	W/ Pointer to Link's NRB
;	RET			;ALWAYS
;
;The link is running, see if any traffic needs to be transferred.

NJFRRN:				;LINK IS UP AND RUNNING
	LOAD	U,NRLDB,(W)	;GET PTR TO LDB

;First, try some input, may free up some DECnet buffers for output

	LOAD	T1,NRSTS,(W)	;GET DECnet STATUS LAST TIME WE HEARD
NJFRR1:	TXNN	T1,NSNDA	;NORMAL DATA AVAILABLE?
	JRST	NJFRR2		;NO, TRY OUTPUT
	CALL	NRTIN		;YES, TRY TO READ SOME
	  JFCL			;IGNORE ERROR HERE

;See if there is any output requested and allowed now

NJFRR2:	LOAD	T1,NRSTS,(W)	;GET DECnet STATUS LAST TIME WE HEARD
	TXNN	T1,NSNDR	;NORMAL DATA REQUESTED?
	RET			;NO, ALL DONE WITH THIS LINK
	CALL	NRTOUT		;YES, TRY TO SEND SOME
	  JFCL			;BLOCKED, CAN'T DO ANY OUTPUT
	RET			;RETURN
;NRTOUT - Try to do some output from SCNSER to DECnet
;
;Call, when DECnet is ready to receive from us:
;	W/ Pointer to Link's NRB
;	U/ Points to LDB
;Return:
;	RET			;IF FATAL ERROR
;	RETSKP			;SUCCESS

NRTOUT:	SAVEAC	<P1,P2>
NRTOT1:	LOAD	P1,NRSIZ,(W)	;GET MAX BYTES IN A SEGMENT ON LINK
	MOVE	P2,[POINT 8,NRTRCO] ;BYTE POINTER TO RECORD WE'LL SEND
	MOVE	R,NR.FLG(W)	;GET THE FLAGS
	TXNN	R,NRCFG		;HAVE WE SENT OUR CONFIG MESSAGE YET?
	PJRST	SNDCFG		;NO, DO SO
	TXNE	R,NRCTM		;YES, IS THIS A CTERM LINK?
	JRST	CTHOUT		;YES, USE OTHER PROTOCOL
NRTOT2:	CALL	XMTCHR##	;GET A CHAR IN T3
	  JRST	NRTOT6		;NO MORE, SEND WHAT WE COLLECTED
	IDPB	T3,P2		;STORE BYTE
	SOJG	P1,NRTOT2	;GET MORE WHILE THERE'S ROOM

NRTOT3:	LOAD	P2,NRSIZ,(W)	;GET MAX AGAIN
NRTOT4:	CALL	NRTOT7		;SEND THAT MUCH
	  RET			;BLOCKED, TRY AGAIN LATER
	LOAD	T1,NRSTS,(W)	;GET DECnet STATUS AFTER LAST SEND
	TXNN	T1,NSNDR	;NORMAL DATA STILL REQUESTED?
	RETSKP			;NO, SUCCESS RETURN NOW
	JRST	NRTOT1		;SUCCESS, TRY FOR MORE

;CTERM messages come here to be sent out

NRTOT5:	LOAD	P2,NRSIZ,(W)	;GET MAX AGAIN
	SUB	P2,P1		;FIND HOW MANY WE COPIED
	JUMPG	P2,NRTOT4	;SEND & LOOP IF WE DID SOMETHING
	RETSKP			;SUCCESS RETURN IF NONE

;Completed messages come here for a final send-off

NRTOT6:	LOAD	P2,NRSIZ,(W)	;GET MAX AGAIN
	SUB	P2,P1		;CALC NUMBER WE COPIED
	JUMPLE	P2,NRTOT9	;CHECK FOR END OF SESSION IF NONE
				;FALL THROUGH TO NRTOT7 TO SEND

;Subroutine to send data for NRTOUT & CTHOUT

NRTOT7:	MOVE	M,NRTSAP	;POINT TO NRT'S SAB
	STOR	P2,SAAA1,(M)	;STORE LENGTH OF DATA TO SEND
	MOVX	T1,<<POINT 8,>!1B12> ;MAKE A 2-WORD BYTE POINTER
	STOR	T1,SAAA2,(M)	;STORE AS FIRST WORD OF BYTE POINTER
	XMOVEI	T1,NRTRCO	;GET EXTENDED ADDR OF RECORD
	STOR	T1,SAAA3,(M)	;STORE AS 2ND WORD OF BYTE POINTER
	SETONE	SAEOM,(M)	;SET THE END-OF-MESSAGE FLAG

	MOVX	T1,.NSFDS	;DATA SEND FUNCTION
	MOVEI	T2,5		;NUMBER ARGS WE'RE PASSING
	CALL	NRTNSF		;SEND THE DATA TO DECnet
	  JRST	NRTOT8		;ERROR, GO DEAL WITH IT
	LOAD	T1,SAAA1,(M)	;GET COUNT OF BYTES LEFT TO SEND
	JUMPE	T1,CPOPJ1	;SUCCESS RETURN NOW IF ALL SENT

;Here when the link is blocked (DECnet is out of buffers)

	MOVEM	W,NRTBLW	;SAVE PTR TO BLOCKED LINK
	MOVEM	T1,NRTBLC	;SAVE COUNT OF BYTES STILL TO SEND
	LOAD	T1,SAAA2,(M)	;GET BYTE POINTER
	LOAD	T2,SAAA3,(M)	;GET SECOND WORD OF BYTE POINTER
	DMOVEM	T1,NRTBLP	;SAVE BYTE PNTR FROM WHICH TO SEND
	RET			;FAIL RETURN

NRTOT8:	LOAD	T1,SAAST,(M)	;GET NEW STATUS
	LOAD	T1,NSSTA,+T1	;GET THE STATE FIELD FROM STATUS
	CAIN	T1,.NSSRN	;IN RUN STATE?
	BUG. CHK,NRTOUD,NRTSER,SOFT,<NRT output to DECnet failed>,,<

Cause:	This BUG is not documented yet.

>,NRTREL
	RETSKP			;DON'T COMPLAIN NOW, ITS CLOSING

NRTOT9:	TMNE	NRCTM,(W)	;CTERM WILL DISCONNECT IN ITS OWN WAY
	RETSKP			;SO DON'T DO IT HERE
	TMNE	NRRLS,(W)	;SEE IF IT WANTS TO BE RELEASED
	PJRST	NRTRLS		;CLOSE OFF THE LINK
	RETSKP			;SUCCESS RETURN IF NOT TO BE CLOSED
;SNDCFG - Send a configuration message
;
;Call:
;	W/ Pointer to Link's NRB
;	U/ Pointer to LDB
;
;Return:
;	RET			;ERROR
;	RETSKP			;SUCCESS
;
;Send a configuration message

SNDCFG:	SETONE	NRCFG,(W)	;WE'RE SENDING THE CONFIG MESSAGE NOW
	TMNN	NRCTM,(W)	;IS THIS A CTERM LINK?
	JRST	SNDCFN		;NO, JUST SEND NRT MESSAGE
	MOVE	T2,[POINT 8,BNDMSG]	;POINT TO PROLOGUE OF BIND MESSAGE
	MOVEI	T3,8		;PROLOGUE LENGTH
	CALL	CFOSTR		;STUFF BYTES
	MOVE	T2,[POINT 8,CTHREV##]	;POINT TO REVISION STRING IN COMMON
	MOVEI	T3,8		;IT'S EIGHT BYTES LONG
	CALL	CFOSTR		;TRANSFER TO OUTPUT RECORD
	LDB	T1,LDPLNO##	;GET LINE NUMBER FROM LDB
	CALL	CFOINT		;STUFF INTO MESSAGE
	MOVEI	T1,CTHOPT##	;GET OPTIONS BYTE FROM COMMON
	CALL	CFOBYT		;INSERT INTO MESSAGE
	PJRST	NRTOT5		;SEND IT OFF

;Here to send the config message for NRT links

SNDCFN:	MOVEI	T3,CFGLEN	;LENGTH OF MESSAGE TO SEND
	MOVE	T2,[POINT 8,CFGMSG] ;BYTE POINTER TO CONFIG MSG
	CALL	CFOSTR		;STUFF INTO OUTPUT RECORD
	PJRST	NRTOT5		;SEND IT OFF AND LOOP FOR MORE
;NRTUNB - Unblock a link which is blocked trying to output
;
;Call:	NRTBLW/ Pointer to NRB of blocked link
;	NRTBLC/ Count of bytes still to send
;	NRTBLP/ Two-word byte pointer from which to send
;
;Return:
;	RET		;If link still blocked, NRTBLx updated
;	RETSKP		;If link is now free, NRTBLW zeroed
;
;Uses T1-T4, M and the SAB

NRTUNB:	SAVEAC	W
	MOVE	M,NRTSAP	;POINT TO NRT'S SAB
	SKIPN	W,NRTBLW	;GET POINTER TO BLOCKED NRB
	RETSKP			;NONE?  LEAVE SUCCESSFULLY
	MOVE	T1,NRTBLC	;GET COUNT OF BYTES TO SEND
	STOR	T1,SAAA1,(M)	;STORE IN SAB
	DMOVE	T1,NRTBLP	;GET DOUBLE-WORD BYTE PTR
	STOR	T1,SAAA2,(M)	;PASS IN SAB
	STOR	T2,SAAA3,(M)	;PASS SECOND WORD OF BYTE PTR
	SETONE	SAEOM,(M)	;SET THE END-OF-MESSAGE FLAG

	MOVX	T1,.NSFDS	;DATA SEND FUNCTION
	MOVEI	T2,5		;NUMBER ARGS WE'RE PASSING
	CALL	NRTNSF		;SEND THE DATA TO DECnet
	  JRST	NRTOT8		;ERROR, GO DEAL WITH IT
	LOAD	T1,SAAA1,(M)	;GET COUNT OF BYTES LEFT TO SEND
	JUMPE	T1,NRTUN1	;SUCCESS RETURN NOW IF ALL SENT

;Here when the link is still blocked (DECnet is out of buffers)

	MOVEM	T1,NRTBLC	;SAVE NEW COUNT OF BYTES STILL TO SEND
	LOAD	T1,SAAA2,(M)	;GET NEW BYTE POINTER
	LOAD	T2,SAAA3,(M)	;GET NEW BYTE POINTER (2ND WORD)
	DMOVEM	T1,NRTBLP	;SAVE BYTE PNTR FROM WHICH TO SEND
	RET			;FAIL RETURN

;Here when the link is unblocked

NRTUN1:	SETZM	NRTBLW		;NO LINK IS NOW BLOCKED
	RETSKP			;SUCCESS RETURN
;NRTRLS - Release an idle link
;
;Call, when DECnet is willing to accept data:
;	W/ Pointer to Link's CTB
;	U/ Points to LDB
;	P1/ Maximum byte count for storing via P2
;	P2/ Byte pointer (8-bit) to NRTRCO
;Return:
;	RET			;IF FATAL ERROR
;	RETSKP			;SUCCESS

NRTRLS:	MOVE	R,NR.FLG(W)	;GET THE FLAGS WORD
	TXNE	R,NRCTM		;IS THIS A CTERM LINK?
	JRST	CTHRLS		;YES, GO RELEASE IT THAT WAY
	TXNN	R,NRTMO		;DID IT TIME OUT?
	JRST	NRTRS1		;NO, JUST DISCONNECT IT
	SETZRO	NRTMO,(W)	;CLEAR FLAG FOR NEXT CALL
	PUSHJ	P,INLMES##	;SEND SOME TEXT TO THE TTY
	  ASCIZ "
[ Idle line disconnected by host ]
"
	PJRST	NRTOT1		;SEND THE TEXT, THEN DISCONNECT THE LINK

NRTRS1:	MOVE	M,NRTSAP	;POINT TO NRT'S SAB
	MOVX	T1,.NSFSD	;SYNCHRONOUS DISCONNECT FUNCTION
	MOVEI	T2,2		;NUMBER OF ARGS PASSED
	CALL	NRTNSF		;INITIATE THE DISCONNECT PROCESS
	  JFCL			;IGNORE ERROR RETURN
	RET

;Here to disconnect a line for CTERM

CTHRLS:	CAIGE	P1,3		;DO WE HAVE ENOUGH BYTES?
	PJRST	NRTRS1		;NO, GIVE UP
	MOVEI	T1,.FMUNB	;YES, UNBIND IS MESSAGE TYPE TWO
	CALL	CFOBYT		;PUT INTO THE FOUNDATION MESSAGE
	LOAD	T1,CTUBR,(W)	;GET THE UNBIND REASON CODE
	CALL	CFOINT		;SEND IT AS A NETWORK INTEGER
	SETZRO	<NRTMO,NRCTM>,(W)	;SETUP TO BE RELEASED AFTER SENDING DATA
	SETONE	NRRLS,(W)	;MAKE SURE
	PJRST	NRTOT5		;SEND THE DATA AND RETURN
;CTHOUT - Try to send some CTERM messages
;
;Call, when DECnet is willing to accept data:
;	W/ Pointer to Link's CTB
;	U/ Points to LDB
;	P1/ Maximum byte count for storing via P2
;	P2/ Byte pointer (8-bit) to NRTRCO
;Return:
;	RET			;IF FATAL ERROR
;	RETSKP			;SUCCESS (USUALLY VIA NRTOT5)

CTHOUT:	TMNE	CTRLS,(W)	;PROTOCOL ERROR SEEN?
	JRST	CTHRLS		;YES, GIVE UP NOW
	TMNN	CTRUN,(W)	;IS THE FULL PROTOCOL RUNNING YET FOR THIS LINK?
	JRST	CTHOT2		;NO, SEE WHAT WE NEED TO DO TO START IT
	TMNE	CTCIB,(W)	;DO WE NEED TO CLEAR THE INPUT BUFFER?
	JRST	CTHCTA		;YES, GO SEND CLEAR-TYPEAHEAD
	MOVEI	T1,L1RCHP##	;SCNSER BIT FOR CHARACTERISTICS CHANGES
	TDNE	T1,LDBBYT##(U)	;DOES SCNSER WANT US TO CHANGE SOME?
	JRST	CTHONC		;YES, SET NEW CHARACTERISTICS
	TMNE	CTOBC,(W)	;DO WE NEED TO CHANGE OUR OUT-OF-BAND SET?
	CALL	CTHOOB		;YES, DO IT
	CALL	CTHDRQ		;SEND OFF A DRQ IF NECESSARY
	  PJRST	CCOFIN		;DID SOMETHING, SEND IT OFF
	CALL	CTHXMT		;TRY TO SEND CHARACTERS
	  PJRST	CCOFIN		;DONE
	LOAD	T1,CTUBR,(W)	;GET POSSIBLE UNBIND REASON
	JUMPN	T1,CTHRLS	;IF SET, DO THE SOFT UNBIND NOW
	RETSKP			;JUST RETURN SUCCESS IF NOTHING TO DO

CTHOT2:	MOVE	R,CT.FLG(W)	;GET FLAGS WORD
	TXNN	R,CTSPI		;WE'RE BOUND, HAVE WE SENT A PROTOCOL INIT?
	JRST	CTHOPI		;NO, GO SEND ONE
	TXNN	R,CTBND		;ARE WE STILL BINDING?
	RETSKP			;YES, DON'T BOTHER ME
	TXNN	R,CTRCS		;HAVE WE REQUESTED CHARACTERISTICS?
	JRST	CTHORC		;NO, MUST DO SO
	TXNN	R,CTRPI		;YES, HAVE WE ALSO RECEIVED ONE?
	RETSKP			;NO, WE CAN DO NOTHING UNTIL THEN
	TXNN	R,CTCHP		;YES, HAVE WE SEEN THEM YET?
	RETSKP			;NO, WE HAVE TO WAIT FOR THEM
	TXNN	R,CTCSD		;HAVE WE SENT OURS YET?
	JRST	CTHOSC		;NO, SEND THEM
	SETONE	CTRUN,(W)	;YES, ADMIT TO RUNNING THE PROTOCOL
	SETONE	CTOBC,(W)	;BUT WE HAVEN'T DONE A BREAK MASK YET
	CALL	TTFGRT##	;FIRE UP INITIA ON THE LINE
	JRST	CTHOUT		;AND TRY AGAIN THIS WAY
;CTHCTA - CTERM Clear-typeahead needs to be sent
;
;Call:
;	W/ Pointer to Link's CTB
;	U/ Points to LDB
;	P1/ Maximum byte count for storing via P2
;	P2/ Byte pointer (8-bit) to NRTRCO
;Return:
;	RET		;ON FATAL ERROR
;	RETSKP		;IF SUCCESS (VIA NRTOT5)

CTHCTA:	MOVEI	T1,.FMCMD	;COMMON DATA MESSAGE (DATA FOR CTERM LAYER)
	CALL	CFOINT		;SETUP FOR CTERM MESSAGES
	MOVEI	T1,2		;A TWO-BYTE SUB-MESSAGE
	CALL	CFOINT		;SET THE LENGTH
	MOVEI	T1,.CMUNR	;UNREAD (UNCONDITIONAL)
	CALL	CFOINT		;STUFF THE BYTES
	MOVEI	T1,2		;ANOTHER TWO-BYTE SUB-MESSAGE
	CALL	CFOINT		;SET THE LENGTH
	MOVEI	T1,.CMCTA	;CLEAR TYPEAHEAD
	CALL	CFOINT		;STUFF THE BYTES
	SETZRO	CTCIB,(W)	;WE ARE CLEARING THE INPUT BUFFER NOW
	TMNN	CTDRQ,(W)	;DOES OUR UNREAD MEAN ANYTHING?
	PJRST	NRTOT5		;NO, JUST SEND THE MESSAGE AND DISMISS
	SETONE	CTDRI,(W)	;YES, NOTE IT FOR THE READ-DATA HANDLER
	SETONE	CTURA,(W)	;AND THAT AN UNREAD IS ACTIVE
	PJRST	NRTOT5		;NOW SEND & DISMISS
;CTHOOB - CTERM Out-of-band characteristics need to be sent
;
;Call:
;	W/ Pointer to Link's CTB
;	U/ Points to LDB
;	P1/ Maximum byte count for storing via P2
;	P2/ Byte pointer (8-bit) to NRTRCO
;Return:
;	RET			;ALWAYS

;THESE BITS DEFINE WHAT WE CONSIDER TO BE A BREAK CHARACTER
CCBRK==<CHBRK##!CHUAE##!CHALT##!CHRIA##!CHINVL##!CHCRE##!CHNDFR##>

CTHOOB:	SETZRO	CTOBC,(W)	;WE'RE DOING OUR CHANGES NOW
	MOVE	CX,[POINT 8,CH.BKM(W)]	;POINT TO NETWORK BREAK MASK
	MOVSI	T3,-400		;LOOP OVER ALL CHARACTERS
CTHOB1:	MOVEI	T2,1		;NEW BYTE, START WITH LSB
	SETZ	T4,		;AND AN EMPTY BYTE
CTHOB2:	CALL	SPCHEK##	;SEE IF THIS CHARACTER IS SPECIAL
	  TRN			;MAYBE NOT
	TLNN	T1,CHBRK##!CHOOB##	;IS IT A BREAK (TO US)?
	CALL	CHRMAP		;OR IS IT MAPPED?
	  IOR	T4,T2		;YES OR YES, CONSIDER IT A BREAK
	LSH	T2,1		;MOVE THE BIT OVER
	TRNE	T2,BYTMSK	;IF STILL IN THIS BYTE
	AOBJN	T3,CTHOB2	;LOOP OVER IT
	ILDB	T2,CX		;GET MATCHING BYTE OF PREVIOUS STRING
	CAMN	T2,T4		;DO THEY MATCH?
	JRST	CTHOB3		;YES, DON'T UPDATE
	TRO	T3,400000	;NO, MARK THAT SOMETHING CHANGED
	DPB	T4,CX		;AND STORE THE NEW BYTE
CTHOB3:	AOBJN	T3,CTHOB1	;LOOP OVER ALL CHARACTERS
	TRNN	T3,400000	;DID WE CHANGE ANYTHING?
	RET			;NO, JUST RETURN
	SETONE	CTBMC,(W)	;YES, NOTE THE NEW BREAK MASK
	RET			;NOW RETURN

CHRMAP:	TRNN	T3,CK.CHR	;IF TESTING NUL,
	RET			;IT'S SPECIAL
	PUSH	P,T1		;SAVE SOME ACS
	PUSH	P,T2		;WE NEED THEM
	MOVE	T1,T3		;COPY CURRENT CHARACTER
	ANDI	T1,CK.CHR	;MASK OFF FUNNY STUFF
	LDB	T2,LDPUNP##	;GET UNPAUSE CHARACTER
	CAMN	T2,T1		;IS THIS IT?
	JRST	TTPOPJ##	;YES, GIVE MAPPED RETURN
	LDB	T2,LDPESC##	;NO, GET ESCAPE CHARACTER
	CAMN	T2,T1		;DOES THIS MATCH?
	JRST	TTPOPJ##	;YES, IT'S MAPPED
	LDB	T2,LDPSW1##	;NO, GET SWITCH-1
	CAMN	T2,T1		;MATCH?
	JRST	TTPOPJ##	;YES, MAPPED
	LDB	T2,LDPSW2##	;NO, GET SWITCH-2
	CAME	T2,T1		;UNLESS MATCH,
	AOS	-2(P)		;IT'S NOT MAPPED
	JRST	TTPOPJ##	;RESTORE ACS AND RETURN
;CTHONC - CTERM Characteristics message needs to be sent
;
;Call:
;	W/ Pointer to Link's CTB
;	U/ Points to LDB
;	P1/ Maximum byte count for storing via P2
;	P2/ Byte pointer (8-bit) to NRTRCO
;	T1/ L1RCHP
;Return:
;	RET			;IF FATAL ERROR
;	RETSKP			;SUCCESS (USUALLY VIA NRTOT5)

DEFINE	HAK(CHRS),<
 IRP CHRS,<
	LDB	T1,LDP'CHRS'##	;;GET CHARACTERISTIC TO HACK
	TRC	T1,1		;;CHANGE IT
	STOR	T1,CH'CHRS,(W)	;;CLOBBER OUR VALUE (SO WE SEND IT)
>>

CTHONC:	ANDCAM	T1,LDBBYT##(U)	;WE'RE GOING TO SEND THE CHARACTERSTICS MSG
	MOVEI	T1,.CMCHR	;MESSAGE TYPE FOR CTERM CHARACTERISTICS
	CALL	CCOST2		;SETUP FOR COMMON DATA/CTERM MESSAGE
	LDB	T1,LDPPIM##	;GET PIM BIT
	LOAD	T2,CHPIM,(W)	;AND OUR COPY
	CAMN	T1,T2		;DO THEY MATCH?
	JRST	CTHON4		;YES, DON'T CHANGE IT
	STOR	T1,CHPIM,(W)	;YES, UPDATE OUR COPY
	CALL	CHOPIM		;CHANGE IT
CTHON4:	LDB	T1,LDPIMI##	;GET IMAGE-MODE BIT
	LOAD	T2,CHIMI,(W)	;AND OUR COPY
	CAMN	T1,T2		;DO THEY MATCH?
	JRST	CTHON3		;YES, DON'T CHANGE IT
	STOR	T1,CHIMI,(W)	;YES, UPDATE OUR COPY
	CALL	CHOIMI		;CHANGE IT
CTHON3:	MOVE	R,CH.FLG(W)	;GET MODE BITS
	TXNE	R,CHPIM!CHIMI	;ARE WE IN IMAGE MODE?
	PJRST	CCOFIN		;YES, DON'T CLOBBER OUR IMAGE-MODE VALUES
	PUSH	P,P3		;WE NEED AN AC FOR AOBJN'ING
	MOVSI	P3,-CHRTBL	;FORM AOBJN INDEX TO TABLES
;	TMNE	CTBAD,(W)	;IS THIS THE SUB-STANDARD PROTOCOL?
;	MOVSI	P3,1-CHRTBL	;YES, DON'T MAKE RTPAD ACCVIO
CTHON1:	LDB	T2,@CHRSCN(P3)	;GET VALUE FROM SCNSER
	LDB	T1,CHRTAB(P3)	;AND FROM OURSELVES
	CAMN	T2,T1		;DO THEY MATCH?
	JRST	CTHON2		;YES, NOTHING TO CHANGE
	MOVE	T1,CHRPID(P3)	;NO, GET THE PROTOCOL ID OF THE VALUE
	CALL	CCOINT		;SAY WHAT VALUE WE'RE CHANGING
	MOVE	T1,T2		;MOVE THE NEW CHARACTERISTIC
	DPB	T1,CHRTAB(P3)	;UPDATE IN OUR RECORDS
	CALL	@CHRPUT(P3)	;SEND THE NEW VALUE
CTHON2:	AOBJN	P3,CTHON1	;LOOP OVER ALL OF TABLE
	POP	P,P3		;RESTORE AC
	PJRST	CCOFIN		;SEND THE MSG AND RETURN
;Build the characteristic tables for CTHONC

DEFINE	CHRS,<
	C	TTT,TTN,TTT
	C	WID,WID,INT
	C	LNB,LEN,INT
	C	LCT,RAI,BYT
	C	ECH,ECH,IVB
	C	DIS,TAM,DIS
	C	XNF,OFC,BYT
	C	8BT,CSZ,8BT	;;MUST BE LAST!!! (FOR *$&$&$& VMS)
>

CHRTAB:	DEFINE	C(NAM,PID,FMT),<POINTR CH.'NAM(W),CH'NAM>

	CHRS
CHRTBL==.-CHRTAB		;LENGTH OF THE TABLE

CHRSCN:	DEFINE	C(NAM,PID,FMT),<IFIW LDP'NAM'##>

	CHRS

CHRPID:	DEFINE	C(NAM,PID,FMT),<EXP .CC'PID>

	CHRS

CHRPUT:	DEFINE	C(NAM,PID,FMT),<IFIW CCO'FMT>

	CHRS
;CHOPIM & CHOIMI - Send appropriate characteristics for image modes

CHOPIM:	JUMPE	T1,CHOPM2	;GO ELSEWHERE IF CLEARING IT
	MOVE	T2,[POINT 8,PIMMSG]	;POINT TO PIM MESSAGE STRING
	MOVEI	T3,PIMLEN	;GET ITS LENGTH
;	TMNE	CTBAD,(W)	;IS THIS FOR VMS?
;	SUBI	T3,FT.8BC+2	;YES, DON'T TWEAK 8-BIT STUFF
	CALL	CCOSTR		;SEND THE BYTES
	RET			;BACK TO CTHONC
CHOPM2:	HAK	<LCT,8BT,ECH>	;SEND THE VALUES OF THESE
	RET			;BACK TO CTHONC

	PIM	RAI,0
	PIM	ECH,0
	PIM	CSZ,8		;MUST BE LAST FOR **&&* VMS!!

PIMMSG:	BYTSTR (PIM)
	PIMLEN==PIMLEN		;PUBLISH THE LENGTH


CHOIMI:	JUMPE	T1,CHOIM2	;GO ELSEWHERE IF CLEARING IT
	MOVE	T2,[POINT 8,IMIMSG]	;POINT TO IMAGE MESSAGE STRING
	MOVEI	T3,IMILEN	;GET ITS LENGTH
;	TMNE	CTBAD,(W)	;IS THIS FOR VMS?
;	SUBI	T3,FT.8BC+2	;YES, DON'T TWEAK 8-BIT STUFF
	CALL	CCOSTR		;SEND THE BYTES
	RET			;BACK TO CTHONC
CHOIM2:	HAK	<LCT,8BT,ECH,XNF>	;BE SURE TO SEND THESE
	RET			;BACK TO CTHONC

	IMI	RAI,0
	IMI	ECH,0
	IMI	OFC,0
	IMI	CSZ,8		;MUST BE LAST FOR **&&* VMS!!

IMIMSG:	BYTSTR (IMI)
	IMILEN==IMILEN		;PUBLISH THE LENGTH
;CTHXMT - CTERM Write message initiator
;
;Call:
;	W/ Pointer to Link's CTB
;	U/ Points to LDB
;	P1/ Maximum byte count for storing via P2
;	P2/ Byte pointer (8-bit) to NRTRCO
;Return:
;	RET			;IF TIME TO STOP (WE SEND SOMETHING)
;	RETSKP			;KEEP LOOKING FOR SOMETHING TO DO

;Define our default Write message flags

WRTMSK==WR.EOM!WR.BOM!WR.CDS!FLD(.WRLTU,WR.LOK)

CTHXMT:	MOVX	R,CTCTG		;CHARACTER-TO-GO BIT
	TDNE	R,CT.CTG(W)	;IS IT LIT?
	JRST	CTHXM1		;YES, GO USE IT
	CALL	XMTCHR##	;NO, GET ONE
	  RETSKP		;NOTHING TO DO IF NONE TO SEND
	JRST	CTHXM2		;YES, WE HAVE A CHARACTER
CTHXM1:	ANDCAM	R,CT.CTG(W)	;WE'RE ABOUT TO USE THE CHARACTER
	LOAD	T3,CTCHO,(W)	;FETCH IT
CTHXM2:	SAVEAC	P3		;CHARACTER BIT-TEST AC
	MOVEI	T1,.CMWRT	;START-WRITE MESSAGE TYPE
	CALL	CCOSET		;BEGIN CTERM MESSAGE
	MOVEI	T1,WRTMSK	;GET BITS TO SEND
	TRNE	T3,CK.IMG	;IF CHARACTER IS IMAGE,
	TRO	T1,WR.BIN	;THEN SO IS THIS WRITE
;IF WE EVER IMPLEMENT THE DOBE FUNCTION, TEST FOR IT HERE AND LIGHT WR.VFY
	CALL	CCOINT		;SEND THE FLAG BITS
	SETZ	T1,		;POSTFIX & PREFIX BYTES
	CALL	CCOINT		;WE HAVE NONE
CTHXM3:	MOVE	T1,T3		;MOVE CHARACTER FOR OUTPUT
	CALL	CCOBYT		;STUFF INTO MESSAGE
	JUMPLE	P1,CPOPJ##	;END OF MESSAGE IF FULL
	MOVE	P3,T3		;SAVE MESSAGE FOR CK.IMG COMPARISON
	CALL	XMTCHR##	;GET THE NEXT CHARACTER FOR OUTPUT
	  RET			;DONE IF NO MORE
	XOR	P3,T3		;GET CHANGE MASK
	TRNN	P3,CK.IMG	;DID IMAGE-MODE STATUS CHANGE?
	JRST	CTHXM3		;NO, SEND THE CHARACTER
	SETONE	CTCTG,(W)	;YES, NOTE THAT WE HAVE A CHARACTER TO SEND
	STOR	T3,CTCHO,(W)	;SAVE IT AWAY
	RET			;AND FINISH OFF THIS WRITE MESSAGE
;CTHDRQ - CTERM Send a start-read if appropriate
;
;Call:
;	W/ Pointer to Link's CTB
;	U/ Points to LDB
;	P1/ Maximum byte count for storing via P2
;	P2/ Byte pointer (8-bit) to NRTRCO
;Return:
;	RET			;IF A DRQ HAS BEEN PACKAGED TO SEND
;	RETSKP			;IF NOTHING TO DO (CONTINUE SCANNING)

;Define our default masks for Start-Read flags

SRDMSK==SR.TMR!SR.NEC!SR.CON!SR.VPT!FLD(.SRTRM,SR.UND)!FLD(.SRALL,SR.CCD)
				;BYTES 0 & 1
SR2MSK==0			;BYTE 2

CTHDRQ:	MOVE	T4,CT.FLG(W)	;GET THE FLAG BITS
	TXNE	T4,CTBMC	;HAS THE BREAK MASK CHANGED?
	TXNN	T4,CTDRQ	;YES, DID IT CHANGE DURING A READ?
	JRST	CTHDR1		;NO OR NO, KEEP GOING
	TXNE	T4,CTURA	;YES AND YES, DID I ALREADY SEND THE UNREAD?
	RETSKP			;YES, WE'RE DONE HERE (UNTIL READ DATA COMES)
	SETONE	CTURA,(W)	;NO, LIGHT UNREAD-ACTIVE FLAG
	MOVEI	T1,.CMUNR	;UNREAD REQUEST
	CALL	CCOSET		;SET IT UP
	SETZ	T1,		;NO FLAGS
	PJRST	CCOBYT		;STUFF FLAGS BYTE & RETURN TO CTHOUT
CTHDR1:	TXNE	T4,CTDRQ!CTXOF	;DO WE NEED TO SEND A DATA REQUEST?
	RETSKP			;NO, JUST GIVE CONTINUE RETURN
	MOVEI	T1,.CMSRD	;YES, GET START-READ MESSAGE TYPE
	CALL	CCOSET		;PREPARE TO SEND IT
	MOVEI	T1,SRDMSK	;GET BITS TO SEND
	TXNE	T4,CTBMC	;DID THE BREAK MASK CHANGE?
	TRO	T1,FLD(.SRUNT,SR.TRM)	;YES, WE'RE ALSO SENDING A NEW MASK
	TXNE	T4,CTDRZ	;WAS THE LAST READ-DATA NULL?
	TXZ	T1,SR.TMR	;YES, DON'T TIME THIS ONE
REPEAT 0,<		;DON'T DO THIS UNTIL TOPS-20'S SERVER WORKS
	TXNE	T4,CTCTG	;ONLY IF NOT WAITING
	JRST	CTHDR2		;CAN'T IF WE ARE
	MOVE	T2,LDBBY2##(U)	;NO, GET MISC. TERMINAL BITS
	TLNE	T2,L2LDEL##	;NO, ARE WE IN RUBOUT SEQUENCE?
	JRST	CTHDR2		;YES, CAN'T ECHO
	SKIPGE	T2,LDBDCH##(U)	;GET STATUS BITS, SKIP IF OUTPUT ACTIVE
	TLNE	T2,LDLNEC##!LDLLCP##!LDLCNE##!LDLBKA##!LDLIMI##	;PROGRAM CONTROL?
	JRST	CTHDR2		;YES
	TMNE	CHPIM,(W)	;PIM IS ALSO EXCESSIVE PROGRAM CONTROL
	JRST	CTHDR2		;SO CAN'T DO IT THEN, EITHER
	SKIPN	LDBIST##(U)	;IF DOING FANCY TWO-CHARACTER INPUT,
	SKIPGE	LDBCHM##(U)	;OR FANCY MAPPING
	JRST	CTHDR2		;CAN'T DO IT
		EXTERN	LMLNDS	;FLAG BIT REFERENCED
	MOVE	T2,LDBBYT##(U)	;GET THE DEFERED ECHO BITS
	TLNN	T2,L1LUNR##	;IF NOT IN UNREAD,
	TRNN	T2,L1RDEL##	;AND IF WAITING FOR A LINE
	JRST	CTHDR2		;NO, CAN'T ECHO
	TXZ	T1,SR.NEC	;YES, OK TO ECHO AFTER ALL
> ;END OF UNTIL TOPS-20 ETC.
CTHDR2:	CALL	CCOINT		;STUFF THE FLAG BITS
	MOVX	R,CTDRQ		;READ ACTIVE BIT
	TRNN	T1,SR.NEC	;ARE WE ALLOWING ECHO?
	TXO	R,CTECH		;YES, ADD IN THAT BIT
	IORM	R,CT.FLG(W)	;SET DRQ & ECH FLAGS APPROPRIATELY
	MOVEI	T1,SR2MSK	;GET THIRD BYTE OF FLAGS TO SEND
	CALL	CCOBYT		;SHIP IT
	LOAD	T1,CTIBS,(W)	;GET MAXIMUM BUFFER SIZE
	MOVSI	T2,LDLBKA##	;BREAK-ON-ALL CHARACTERS BIT
	TDNN	T2,LDBDCH##(U)	;IF SET,
	TXNE	T4,CTDRZ	;OR WE'RE BLOCKING THIS READ,
	MOVEI	T1,1		;THEN BREAK ON ALL
	CALL	CCOINT		;SEND AS THIS DRQ'S SIZE
	SETZ	T1,		;PRE-FILL LENGTH
	CALL	CCOINT		;END OF DATA IS AT START
	LDB	T1,LDPTIM##	;SEE IF WE'RE DOING IMAGE MODE
	SOSG	T1		;IF WE'RE NOT,
	MOVEI	T1,1		;WE STILL WANT TO SEE INPUT EVENTUALLY
	TXNE	T4,CTDRZ	;UNLESS WE'RE BLOCKING THIS READ,
	SETZ	T1,		;THEN DON'T UPSET VMS
	CALL	CCOINT		;SEND TIMEOUT DURATION
	SETZRO	CTDRZ,(W)	;NO LONGER NEED THIS BIT
	SETZ	T1,		;OTHER CHARACTER POSITIONS
	CALL	CCOINT		;WE'RE SENDING NO PROMPT
	CALL	CCOINT		;NO REDISPLAY POINT
	CALL	CCOINT		;NO LOW-WATER MARK
	TXNE	T4,CTBMC	;DID WE WANT TO SEND A BREAK MASK?
	MOVEI	T1,400/8	;YES, WE'LL SEND THIS MANY BYTES OF BKM
	CALL	CCOBYT		;SEND SIZE OF BKM LIST
	JUMPE	T1,CPOPJ	;DONE IF SENDING NONE
	MOVE	T3,T1		;COPY THE LENGTH TO SEND
	MOVE	T2,[POINT 8,CH.BKM(W)]	;POINT TO BREAK MASK BYTES
	SETZRO	CTBMC,(W)	;WE'RE SENDING THE MESSAGE NOW
	PJRST	CCOSTR		;SEND THEM VIA RETURN TO CTHOUT
;CTHOPI - CTERM Send a protocol initiate message
;
;Call:
;	W/ Pointer to Link's CTB
;	U/ Points to LDB
;	P1/ Maximum byte count for storing via P2
;	P2/ Byte pointer (8-bit) to NRTRCO
;Return:
;	RET			;ON ERROR
;	RETSKP			;SUCCESS (USUALLY VIA NRTOT5)

CTHOPI:	MOVEI	T1,.CMPIN	;PROTOCOL INIT MESSAGE
	CALL	CCOST2		;ENTER INTO A 'COMMON DATA' CARRIER
	MOVEI	T1,1		;MAJOR VERSION OF PROTOCOL IS ONE
	CALL	CFOBYT		;STORE IT
	SETZ	T1,		;ECO & MOD FIELDS ARE ZERO	
	CALL	CFOINT		;STORE ECO LEVEL & MOD LEVEL
	MOVE	T2,[POINT 8,CTHREV##] ;POINT TO REVISION STRING IN COMMON
	MOVEI	T3,8		;IT'S 8 CHARACTERS LONG
	CALL	CFOSTR		;STORE THE REVISION STRING
	MOVE	T2,[POINT 8,CPIMSG] ;POINT TO THE PARAMETERS WE NEED TO SET
	MOVEI	T3,CPILEN	;WE'RE SENDING THIS MANY MORE BYTES
	CALL	CFOSTR		;COPY THE BYTES INTO THE MESSAGE
	SETONE	CTSPI,(W)	;WE'RE SENDING THE PROTOCOL INIT NOW
	PJRST	CCOFIN		;BIND OFF & SEND THE MESSAGE

;Build our Protocol Initiate parameters

	CPI	MMS,NRTRIL	;OUR MAXIMUM INPUT MESSAGE SIZE
	CPI	SUP,MT.SUP	;WE SUPPORT ONLY THE REQUIRED MESSAGES

CPIMSG:	BYTSTR (CPI)		;DUMP THE STRING
	CPILEN==CPILEN		;PUBLISH THE LENGTH
;CTHORC - CTERM Send a read characteristics messge
;
;Call:
;	W/ Pointer to Link's CTB
;	U/ Points to LDB
;	P1/ Maximum byte count for storing via P2
;	P2/ Byte pointer (8-bit) to NRTRCO
;Return:
;	RET			;ON ERROR
;	RETSKP			;SUCCESS (USUALLY VIA NRTOT5)

CTHORC:	MOVEI	T1,.CMRCH	;MESSAGE TYPE TO READ CHARACTERISTICS
	CALL	CCOST2		;EMBED IN A 'COMMON DATA' MESSAGE
	MOVE	T2,[POINT 8,RSCMSG] ;POINT TO THE ACTUAL SELECTOR SEQUENCE
	MOVEI	T3,RSCLEN	;WE'RE SENDING THIS MANY MORE BYTES
	TMNE	CTBAD,(W)	;TALKING TO AN ERRANT RTPAD?
	SUBI	T3,.FTCCA	;YES, DON'T ASK ABOUT TTY QUOTE
	CALL	CCOSTR		;STORE INTO THE MESSAGE BUFFER
	SETONE	CTRCS,(W)	;WE'RE SENDING THE READ CHARACTERSTICS NOW
	PJRST	CCOFIN		;BIND OFF AND SEND MESSAGE

;Build our selectors for Read Characteristics

	RSC	TTN,		;TTY NAME TYPE
	RSC	TAM,		;DISPLAY BIT
	RSC	RAI,		;TTY LC
	RSC	ECH,		;TTY ECHO
	RSC	RSP,		;RECEIVE SPEED
	RSC	TSP,		;TRANSMIT SPEED
	RSC	CSZ,		;TTY EIGHTBIT
	RSC	OFC,		;TTY XONOFF
	RSC	OPS,		;TTY STOP
	RSC	WID,		;TTY WIDTH
	RSC	LEN,		;TTY LENGTH
	RSC	SSZ,		;TTY STOP N
	RSC	WRP,		;TTY CRLF
	RSC	HTM,		;TTY TAB
	RSC	FFM,		;TTY FORM
	RSC	CAT,"V"-100	;TTY QUOTE  (** MUST BE LAST **)

RSCMSG:	BYTSTR (RSC)		;DUMP THE STRING
	RSCLEN==RSCLEN		;PUBLISH THE LENGTH
;CTHOSC - CTERM Send the first set characteristics messge
;
;Call:
;	W/ Pointer to Link's CTB
;	U/ Points to LDB
;	P1/ Maximum byte count for storing via P2
;	P2/ Byte pointer (8-bit) to NRTRCO
;Return:
;	RET			;ON ERROR
;	RETSKP			;SUCCESS (USUALLY VIA NRTOT5)

CTHOSC:	MOVEI	T1,.CMCHR	;MESSAGE TYPE TO SET CHARACTERISTICS
	CALL	CCOST2		;START UP A 'COMMON DATA' MESSAGE
	TMNE	CTCTG,(W)	;ARE WE PART-WAY THROUGH HERE?
	JRST	CTHOS1		;YES, RESUME WITH STORED CHARACTER
	MOVE	T2,[POINT 8,CSCMSG] ;POINT TO THE SET CHARACTERISTICS MESSAGE
	MOVEI	T3,CSCLEN	;WE'RE SENDING THIS MANY MORE BYTES
	CALL	CFOSTR		;COPY THEM TO THE BUFFER
	SETONE	CTCTG,(W)	;WE'RE NOW PARTLY DONE
	TDZA	T3,T3		;FIRST TIME, START OFF WITH 0 (NUL)
CTHOS1:	LOAD	T3,CTCHO,(W)	;GET THE CHARACTER WE BROKE OFF WITH
CTHOS2:	CAIGE	P1,5		;DO WE HAVE ENOUGH ROOM TO STORE THE STATUS?
	JRST	CTHOS3		;NO, MUST BREAK OFF FOR NOW
	MOVEI	T1,.CCCAT	;YES, GET CHARACTERISTIC PID FOR CHARACTER BITS
	CALL	CCOINT		;INTRODUCE CHARACTER ATTRIBUTES
	MOVE	T1,T3		;COPY THE CHARACTER
	CALL	CCOBYT		;SETTING STATUS FOR THIS CHARACTER
	MOVEI	T1,CA.MSK	;SETTING ALL DEFINED BITS TO ZERO
	CAIE	T3,"Q"-100	;UNLESS THIS IS XON
	CAIN	T3,"S"-100	;OR XOFF,
	TRO	T1,CA.ENB_8	;THEN WE ENABLE ITS SPECIAL ACTION
	CALL	CCOINT		;SEND MASK & BITS
	AOS	T3		;BUMP THE CHARACTER
	TRNN	T3,140		;IS IT STILL A CONTROL CHARACTER?
	JRST	CTHOS2		;YES, SEND ITS STATUS TOO
	TMNN	CTBAD,(W)	;STOP AFTER 0-37 IF VMS
	TRNE	T3,CK.PAR	;NO, IS IT A TOP-HALF CHARACTER?
	JRST	CTHOS4		;YES, WE'RE DONE
	MOVEI	T3,177		;NO, DO RUBOUT AND TOP HALF CONTROLS
	JRST	CTHOS2		;LOOP OVER ALL WE CARE ABOUT

CTHOS3:	STOR	T3,CTCHO,(W)	;SAVE THE CHARACTER WHERE WE LEFT OFF
	PJRST	CCOFIN		;SEND MESSAGE AND RETURN

CTHOS4:	MOVX	R,CTCSD!CTCTG	;GET BITS TO CHANGE
	XORM	R,CT.FLG(W)	;NO MORE CTG, BUT CSD IS ON (WE'RE DONE HERE)
	PJRST	CCOFIN		;SEND MESSAGE AND RETURN

;Build our initial Characteristics message values

	CSC	FCP,1		;GIVE US XON/XOFF
	CSC	WRP,WP.PHY	;TRACK PRESUMED HARDWARE WRAPPING
	CSC	HTM,HT.PHY	;TABS ARE LITERAL IF WE SEND THEM
	CSC	FFM,FF.PHY	;FF IS LITERAL IF WE SEND IT
	CSC	VTM,VT.PHY	;VT IS ALSO LITERAL
	CSC	IGN,0		;ALLOW INPUT
	CSC	APE,0		;LEAVE OUT THE STUPID CONTROL-A
	CSC	CNT,CN.ALL	;ALWAYS SEND US INPUT-STATE MESSAGES
	CSC	IER,0		;NO ESCAPE RECOGNITION
	CSC	OER,0		;IN EITHER DIRECTION
	CSC	COP,1		;SEND US CONTROL-O AS DATA
	CSC	CPE,0		;DISABLE PARITY

CSCMSG:	BYTSTR (CSC)		;DUMP THE STRING
	CSCLEN==CSCLEN		;PUBLISH THE LENGTH
;CCOTTT - CTERM Layer output routine to send a terminal type
;
;Call:
;	W/ Pointer to Link's CTB
;	U/ Points to LDB
;	P1/ Maximum byte count for storing via P2
;	P2/ Byte pointer (8-bit) to NRTRCO
;	T1/ LDPTTT index to translate and send
;Return:
;	RET			;ON SUCCESS

CCOTTT:	PUSHJ	P,TORTCN##	;GET THE CLASS NAME
	CALL	CCOSIX		;SEND IT IN ASCIC FORMAT
	HAK	<DIS,WID,LNB,LCT,8BT,ECH,XNF>	;BE SURE WE SEND THESE
	RET			;RETURN TO CTHONC
;CCOSIX - CTERM Layer output routine to send a SIXBIT string in ASCIC
;
;Call:
;	W/ Pointer to Link's CTB
;	U/ Points to LDB
;	P1/ Maximum byte count for storing via P2
;	P2/ Byte pointer (8-bit) to NRTRCO
;	T1/ The SIXBIT word to be sent
;Return:
;	RET			;ON SUCCESS
;
;Uses:
;	T1-T4

;ASCIC format is the following:
;	First byte:	N	(the length of the actual string)
;	Next N bytes:	ascii character		(the string, from left to right)
; Total is N+1 bytes.

CCOSIX:	JUMPE	T1,CCOBYT	;ZERO BYTES IF BLANK NAME
	MOVE	T4,T1		;NOT SO SIMPLE.  SAVE THE NAME
	MOVNS	T1		;GET ITS NEGATIVE
	AND	T1,T4		;GET THE RIGHTMOST BIT
	JFFO	T1,.+1		;GET ITS BIT NUMBER
	IDIVI	T2,6		;GET WHICH BYTE IT OCCURS IN (0-5)
	MOVEI	T1,1(T2)	;GET TOTAL NUMBER OF BYTES TO SEND
	CALL	CCOBYT		;SEND LENGTH BYTE OF ASCIC
	MOVE	T2,T4		;COPY NAME TO FRIENDLIER AC
CCOSX1:	SETZ	T1,		;CLEAR OLD CRUFT
	LSHC	T1,6		;GET NEXT BYTE TO SEND
	ADDI	T1,"A"-'A'	;CONVERT TO ASCII FROM SIXBIT
	CALL	CCOBYT		;SEND THE NEXT CHARACTER
	JUMPN	T2,CCOSX1	;LOOP OVER ALL CHARACTERS IN WORD
	RET			;RETURN WHEN DONE
;CCODIS - CTERM Layer output routine to send the display characteristic
;
;Call:
;	W/ Pointer to Link's CTB
;	U/ Points to LDB
;	P1/ Maximum byte count for storing via P2
;	P2/ Byte pointer (8-bit) to NRTRCO
;	T1/ The value of LDPDIS to be sent
;Return:
;	RET			;ON SUCCESS

CCODIS:	LSH	T1,1		;THE BIT IS OFFSET BY ONE
		.CREF	TA%DIS	;NOTE WHAT WE'RE SETTING
	LDB	T2,LDPTTT##	;GET THE TTY TYPE
	SKIPE	T2		;IF WE KNOW THIS TTY TYPE,
	TRO	T1,TA%KNO	;THEN ADMIT IT
	PJRST	CCOINT		;TERMINAL ATTRIBUTES IS TWO BYTES
		.CREF	FT.TAM	;PROVE THAT WE KNOW IT
;CFOBYT - Foundation output routine to send a byte
;
;Call:
;	W/ Pointer to Link's CTB
;	U/ Points to LDB
;	P1/ Maximum byte count for storing via P2
;	P2/ Byte pointer (8-bit) to NRTRCO
;	T1/ Data byte to send
;Return:
;	RET			;ON SUCCESS
;
; It is the caller's responsibility to ensure that there is enough room
;  in the output record.  We will stopcode if there is not.

CCOIVB:	TRC	T1,1		;SEND INVERTED BYTE
CCOBYT:!
CFOBYT:	SOSGE	P1		;IS THERE ENOUGH ROOM?
	STOPCD	.,STOP,CTHOCE,	;++OUTPUT COUNT EXCEEDED
	IDPB	T1,P2		;YES, STORE IT AWAY
	RET			;DONE
;CFOSTR - Foundation output routine to send a string of N bytes
;
;Call:
;	W/ Pointer to Link's CTB
;	U/ Points to LDB
;	P1/ Maximum byte count for storing via P2
;	P2/ Byte pointer (8-bit) to NRTRCO
;	T2/ Byte pointer to string to send
;	T3/ Count of bytes in message
;Return:
;	RET			;ON SUCCESS
;
; It is the caller's responsibility to ensure that there is enough room
;  in the output record.  We will stopcode if there is not.

CCOSTR:!
CFOSTR:	SOSGE	T3		;MORE BYTES TO SEND?
	RET			;NO, WE'RE DONE
	ILDB	T1,T2		;YES, FETCH THE NEXT
	CALL	CFOBYT		;SEND IT OUT
	JRST	CFOSTR		;LOOP OVER THE STRING
;CFOINT - Foundation output routine to send a network integer
;
;Call:
;	W/ Pointer to Link's CTB
;	U/ Points to LDB
;	P1/ Maximum byte count for storing via P2
;	P2/ Byte pointer (8-bit) to NRTRCO
;	T1/ Data word to send
;Return:
;	RET			;ON SUCCESS
;
; It is the caller's responsibility to ensure that there is enough room
;  in the output record.  We will stopcode if there is not.

CCO8BT:	ADDI	T1,7		;CONVERT TO CHARACTER FRAME SIZE
CCOINT:!
CFOINT:	CALL	CFOBYT		;SEND THE LOW-ORDER PART FIRST
	ROT	T1,-8		;THE HIGH-ORDER PART COMES NEXT
	CALL	CFOBYT		;SEND THAT
	ROT	T1,8		;PUT THE WORD BACK THE WAY WE GOT IT
	RET			;DONE
;CCOSET - CTERM layer output setup (common data Foundation message)
;
;Call:
;	W/ Pointer to Link's CTB
;	U/ Points to LDB
;	P1/ Maximum byte count for storing via P2
;	P2/ Byte pointer (8-bit) to NRTRCO
;	T1/ CTERM message type
;Return:
;	RET			;ALWAYS

CCOST2:	SKIPA	T2,[CCOINT]	;USE INT IF GUARANTEED ZERO-FILL
CCOSET:	MOVEI	T2,CCOBYT	;BYTE MODE IF THERE COULD BE FLAGS
	PUSH	P,T1		;SAVE CTERM TYPE
	MOVEI	T1,.FMCMD	;COMMON DATA FOUNDATION TYPE
	CALL	CFOINT		;STORE TYPE & ZERO FILL
	MOVEM	P2,CTHCDP	;SAVE THE POINTER FOR LATER LENGTH STORAGE
	SETZ	T1,		;CURRENT LENGTH IS ZERO
	CALL	CFOINT		;MAKE ROOM FOR ACTUAL LENGTH TO BE STORED LATER
	MOVEM	P1,CTHCDL	;SAVE THE REMAINING BYTE COUNT FOR CCOFIN
	POP	P,T1		;RETRIEVE THE CTERM MESSAGE TYPE
	CALL	(T2)		;SET THE TYPE
	MOVEM	P2,CTHBUL	;BACK-UP LIMIT FOR CCOFIN NOT TO SEND AFTER ALL
	RET			;RETURN WITH MESSAGE ALL SET UP
;CCOFIN - CTERM layer output sender (end of CCOSET)
;
;Call:
;	W/ Pointer to Link's CTB
;	U/ Points to LDB
;	P1/ Remaining byte count for storing via P2
;	P2/ Byte pointer (8-bit) into NRTRCO
;Return:
;	via NRTOT5
;
;This routine inserts the actual length into the sub-message block
; of the Foundation's common data message, and then sends the message out.

CCOFIN:	CAMN	P2,CTHBUL	;SHOULD WE BOTHER SENDING IT?
	PJRST	NRTOT1		;NO, JUST CLAIM SUCCESS
CCOFN2:	MOVE	P2,CTHCDP	;RETRIEVE POINTER TO LENGTH FIELD
	MOVE	T1,CTHCDL	;AND STARTING FREE BYTE COUNT
	SUB	T1,P1		;FIND ACTUAL SUB-MESSAGE LENGTH
	ADDI	P1,2		;WE REALLY ALREADY STORED THESE TWO BYTES
	CALL	CFOINT		;UPDATE THE LENGTH
	PJRST	NRTOT5		;SEND THE MESSAGE AND RETURN
;NRTIN - Try to do some input from DECnet to SCNSER
;
;Call, when DECnet has something for us to read:
;	W/ Pointer to Link's NRB
;	U/ Points to LDB
;Return:
;	RET			;IF FATAL ERROR
;	RETSKP			;SUCCESS

NRTIN:	TMNN	NRCFG,(W)	;HAVE WE SENT A CONFIG MSG YET?
	RET			;NO, DON'T ACCEPT INPUT YET
	SAVEAC	<P1,P2>		;YES, PRESERVE OUR BYTE POINTER & COUNT ACS
NRTIN1:	MOVE	R,NR.FLG(W)	;GET FLAGS
	TXNN	R,NRCTM		;IF A NRT LINK,
	TXNN	R,NRXOF		;MAKE SURE SCNSER WANTS SOME CHARACTERS
	TRNA			;CTERM OR NOT XOFF'ED, GO AHEAD
	RETSKP			;NRT AND XOFF'ED, QUIT WHILE WE'RE AHEAD
	MOVE	M,NRTSAP	;POINT TO NRT'S SAB
	MOVEI	T1,NRTRIL	;GET MAX CHARS WE'LL ALLOW AT ONCE
	STOR	T1,SAAA1,(M)	;STORE LENGTH OF DATA TO SEND
	MOVX	T1,<<POINT 8,>!1B12> ;MAKE A 2-WORD BYTE POINTER
	STOR	T1,SAAA2,(M)	;STORE AS FIRST WORD OF BYTE POINTER
	XMOVEI	T1,NRTRCI	;GET EXTENDED ADDR OF INPUT RECORD
	STOR	T1,SAAA3,(M)	;STORE AS 2ND WORD OF BYTE POINTER
	SETZRO	SAEOM,(M)	;DON'T INSIST ON A WHOLE RECORD

	MOVX	T1,.NSFDR	;DATA RECEIVE FUNCTION
	MOVEI	T2,5		;NUMBER ARGS WE'RE PASSING
	CALL	NRTNSF		;GET DATA FROM DECnet
	  JRST	NRTINE		;ERROR, GO DEAL WITH IT

;Now we have some data, give it to SCNSER

	MOVE	P1,[POINT 8,NRTRCI] ;GET BYTE POINTER TO NRT'S RECORD
	MOVEI	P2,NRTRIL	;GET MAX WE SAID WE'D READ
	OPSTR	<SUB P2,>,SAAA1,(M) ;CALC # OF CHARS WE GOT
	JUMPE	P2,NRTIN3	;NONE?
	TMNE	NRCTM,(W)	;IS THIS A CTERM LINK?
	JRST	CTHIN		;YES, USE OTHER PROTOCOL
NRTIN2:	ILDB	T3,P1		;GET NEXT CHARACTER FROM DECnet
	CALL	RECPTY##	;GIVE THE CHAR TO SCNSER
	SOJG	P2,NRTIN2	;LOOP UNTIL ALL PASSED TO SCNSER

;CTERM protocol will merge here for more data

NRTIN3:	LOAD	U,NRLDB,(W)	;RESTORE LDB POINTER TO U
	LOAD	T1,NRSTS,(W)	;GET DECnet STATUS AFTER LAST SEND
	TXNE	T1,NSNDA	;NORMAL DATA STILL AVAILABLE?
	JRST	NRTIN1		;YES, GO GET IT
	RETSKP			;NO, SUCCESS RETURN NOW


;Here on DECnet error

NRTINE:	LOAD	T1,SAAST,(M)	;GET NEW STATUS
	LOAD	T1,NSSTA,+T1	;GET THE STATE FIELD FROM STATUS
	CAIN	T1,.NSSRN	;IN RUN STATE?
	BUG. CHK,NRTINP,NRTSER,SOFT,<NRT Input to DECnet failed>,,<

Cause:	This BUG is not documented yet.

>,NRTREL
	RET			;DON'T COMPLAIN NOW, ITS CLOSING
;CTHIN - Try to read some CTERM messages from DECnet
;
;Call, when DECnet has something for us to read:
;	W/ Pointer to Link's NRB
;	U/ Points to LDB
;	P1/ Byte pointer to input record
;	P2/ Byte count for reading from P1
;Return:
;	RET			;IF FATAL ERROR
;	RETSKP			;SUCCESS

CTHIN:	TMNE	CTRLS,(W)	;PROTOCOL ERROR SEEN?
	JRST	NRTIN3		;YES, JUST FLUSH THE BUFFER
	OPSTR	<SKIPE T1,>,CTIFL,(W)	;DO WE HAVE ANY BUFFERED BYTES?
	MOVE	T1,[POINT 8,CT.IFM(W)]	;YES, GET BYTE POINTER
	MOVEM	T1,CTHIFP	;STORE POINTER OR ZERO AS APPROPRIATE
CTHIN1:	LOAD	T1,CTIFT,(W)	;GET PAST INPUT FOUNDATION TYPE
	JUMPN	T1,CTHIN2	;ONE IN PROGRESS, RE-DISPATCH IT
	CALL	CFIBYT		;GET THE MESSAGE-TYPE BYTE
	  JRST	NRTIN3		;DONE HERE IF NONE
	CAILE	T1,0		;IS IT IN THE RANGE
	CAILE	T1,.FMMDD	;OF VALID FOUNDATION MESSAGE TYPES?
	JRST	CTHINE		;NO, DEAL WITH PROTOCOL ERROR
	STOR	T1,CTIFT,(W)	;YES, STORE IT
CTHIN2:	CALL	@CTHIFM(T1)	;YES, CALL ITS HANDLER
	  JRST	CTHINE		;NON-SKIP MEANS PROTOCOL ERROR SEEN
	JRST	NRTIN3		;MESSAGE OK, TRY FOR NEXT

CTHINE:	STOPCD	.,INFO,CTHPED,DIEBCM	;++PROTOCOL ERROR DETECTED
	SETONE	CTRLS,(W)	;LIGHT BIT TELLING CTHOUT TO UNBIND
	MOVEI	T1,.UBPED	;PROTOCOL ERROR UNBIND REASON
	STOR	T1,CTUBR,(W)	;STORE FOR CTHOUT'S UNBIND MESSAGE
	JRST	NRTIN3		;FLUSH THE BUFFER ON PROTOCOL ERRORS

;CTERM foundation layer input messages dispatch table

CTHIFM:	IFIW	CPOPJ##		;(0) ILLEGAL MESSAGE TYPE
	IFIW	CPOPJ##		;(1) BIND-REQUEST (ILLEGAL)
	IFIW	CTIFUB		;(2) UNBIND REQUEST
	IFIW	CPOPJ##		;(3) REBIND REQUEST (ILLEGAL)
	IFIW	CTIFBA		;(4) BIND-ACCEPT MESSAGE
	IFIW	CPOPJ##		;(5) ENTER MODE (ILLEGAL)
	IFIW	CPOPJ##		;(6) EXIT MODE (ILLEGAL)
	IFIW	CPOPJ##		;(7) CONFIRM MODE (ILLEGAL)
	IFIW	CPOPJ##		;(10) NO MODE (ILLEGAL)
	IFIW	CTIFCD		;(11) COMMON DATA
	IFIW	CPOPJ##		;(12) MODE DATA (ILLEGAL)

;Note that the 'mode' messages are illegal because we never send an
;enter-mode message.
;CTIFUB - CTERM Foundation input routine for Unbind requests
;
;Call:
;	W/ Pointer to Link's CTB
;	U/ Address of corresponding LDB
;	P1/ Byte pointer to read bytes from the current message
;	P2/ Number of bytes remaining in the current message
;	RET			;ALWAYS

CTIFUB:	MOVEI	T1,2		;WE NEED TWO ADDITIONAL BYTES
	CALL	CFICHK		;CALL THE INPUT BUFFER CHECKER
	  JRST	CFIRET		;FAILED, RETURN DEPENDS ON EOM FLAG
	CALL	CFIINT		;GET A NETWORK (2-BYTE) INTEGER
	  RET			;COULD STOPCODE HERE, SINCE JUST CHECKED
	CAIN	T1,.UBPED	;REMOTE COMPLAIN THAT WE SCREWED UP?
	STOPCD	.,INFO,CTHPER,DIEBCM	;++PROTOCOL ERROR REPORTED
	SETONE	CTREL,(W)	;NOTE THAT WE WANT TO RELEASE THIS CHANNEL
	PJRST	CFIFIN		;SUCCESSFUL END OF FUNCTION
;CTIFBA - CTERM Foundation input routine for Bind Accept
;
;Call:
;	W/ Pointer to Link's CTB
;	U/ Address of corresponding LDB
;	P1/ Byte pointer to read bytes from the current message
;	P2/ Number of bytes remaining in the current message
;	RET			;ALWAYS

CTIFBA:	TMNE	CTBND,(W)	;BETTER GET THIS ONLY ONCE
	RET			;PROTOCOL ERROR IF TWICE
	MOVEI	T1,^D16		;WE NEED SEVERAL ADDITIONAL BYTES
	CALL	CFICHK		;SEE IF WE CAN GET THE MESSAGE
	  JRST	CFIRET		;RETURN DEPENDING ON EOM
	MOVEI	T1,3		;THREE BYTES OF VERSION
	CALL	CFISKP		;SKIP OVER THEM
	  RET			;COULD STOPCODE, SINCE CHECKED
	CALL	CFIINT		;GET THE O/S TYPE
	  RET			;MAYBE STOPCODE?
	STOR	T1,CTROS,(W)	;SAVE FOR DEBUGGERS
	MOVX	R,CTBAD		;GET THE BAD-BOYS BIT
	CAIN	T1,O.VMS	;IF VMS,
	IORM	R,CT.BAD(W)	;REMEMBER THE SUB-STANDARD ALTERNATE PROTOCOL
	MOVEI	T1,^D8		;BYTES UNTIL LINE NUMBER
	CALL	CFISKP		;SKIP OVER THAT MANY BYTES (WE DON'T CARE)
	  RET			;COULD STOPCODE, SINCE JUST CHECKED
	CALL	CFIINT		;GET THE REMOTE'S LINE NUMBER
	  TRNA			;MAYBE STOPCODE?
	TRNE	T1,SGNBIT	;NEGATIVE?
	SETO	T1,		;YES, FLAG AS UNKNOWN
	STOR	T1,CTRLN,(W)	;SAVE FOR NETOP. UUO
	CALL	CFIBYT		;SKIP OPTIONS TYPE (RESERVED)
	  RET			;MAYBE STOPCODE?
	SETONE	CTBND,(W)	;FLAG THAT FOUNDATION IS RUNNING
	CALL	TOPOKE##	;WAKE UP OUR OUTPUT PROCESS
	PJRST	CFIFIN		;SUCCESSFUL END OF FUNCTION
;CTIFCD - CTERM Foundation input routine for Common Data (actual CTERM layer)
;
;Call:
;	W/ Pointer to Link's CTB
;	U/ Address of corresponding LDB
;	P1/ Byte pointer to read bytes from the current message
;	P2/ Number of bytes remaining in the current message
;	RET			;ALWAYS

CTIFCD:	CALL	CCIJNK		;SKIP ANY JUNK BYTES THERE MAY BE
	  RET			;SOMEBODY BLEW IT
	  RETSKP		;DEFER
	LOAD	T1,CTIMT,(W)	;GET DATA TYPE IN PROGRESS
	JUMPN	T1,CTIFC3	;RE-START SUB-MESSAGE IF APPLICABLE
	TMNE	CTIML,(W)	;DO WE HAVE A SUB-MESSAGE LENGTH?
	JRST	CTIFC2		;YES, TRY AGAIN FOR ITS TYPE
	TMNE	CTMI0,(W)	;IS THIS REALLY THE START OF THE DATA MESSAGE?
	JRST	CTIFC1		;NO, GET NEXT SUB-MESSAGE
	MOVEI	T1,1		;WE NEED A FILL BYTE
	CALL	CFICHK		;SEE IF WE CAN GET THE MESSAGE
	  JRST	CFIRET		;RETURN DEPENDING ON EOM
	CALL	CFIBYT		;GET ONE BYTE
	  RET			;BUT I JUST CHECKED...
	SETONE	CTMI0,(W)	;REMEMBER THAT WE'VE SKIPPED THE FILL BYTE
CTIFC1:	CALL	CFICK0		;SEE IF AT END OF MESSAGE
	  JRST	CTIFC4		;YES, FINISH UP
	MOVEI	T1,2		;NO, I NEED TWO BYTES FOR THIS MESSAGE TYPE
	CALL	CFICHK		;CAN I GET THEM?
	  JRST	CFIRET		;NO.
	CALL	CFIINT		;GET A NETWORK INTEGER (16-BIT)
	  RET			;SHOULDN'T FAIL
	JUMPE	T1,CTIFC1	;TRY AGAIN IF THIS SUB-MESSAGE IS NULL
	STOR	T1,CTIML,(W)	;SETUP LENGTH FOR CCI INPUT ROUTINES
CTIFC2:	CALL	CCIBYT		;GET THE MESSAGE TYPE (COUNTING THE BYTE)
	  RET			;THE BYTE WENT AWAY?!?
	  RETSKP		;DEFER IF WE MUST
	CAILE	T1,0		;IS IT IN RANGE
	CAILE	T1,.CMIST	;FOR THE CTERM MESSAGES WE SUPPORT?
	RET			;NO, RETURN A PROTOCOL ERROR
	STOR	T1,CTIMT,(W)	;NOTE THE FUNCTION IN PROGRESS
CTIFC3:	CALL	@CTIFCT(T1)	;CALL THE APPROPRIATE MESSAGE HANDLER
	  RET			;PROPAGATE PROTOCOL ERRORS
	  RETSKP		;AND DELAYS
	SETZRO	CTIMT,(W)	;CLEAR SUB-TYPE IN PROGRESS
	JRST	CTIFC1		;LOOP FOR NEXT MESSAGE
CTIFC4:	SETZRO	CTMI0,(W)	;NEXT TIME WE MUST SKIP THE FILL BYTE
	PJRST	CFIFIN		;SUCCESSFUL END OF FUNCTION

;The dispatch table for the supported CTERM layer functions

CTIFCT:	IFIW	CPOPJ##		;(0) TYPE ZERO IS ILLEGAL
	IFIW	CTICIM		;(1) INITIALIZE CTERM MODE
	IFIW	CPOPJ##		;(2) START READ (SEND ONLY)
	IFIW	CTICRD		;(3) READ DATA
	IFIW	CTICOB		;(4) OUT-OF-BAND CHARACTER
	IFIW	CPOPJ##		;(5) UNREAD (SEND ONLY)
	IFIW	CPOPJ##		;(6) CLEAR TYPEAHEAD (SEND ONLY)
	IFIW	CPOPJ##		;(7) WRITE DATA (SEND ONLY)
	IFIW	CTICWC		;(10) WRITE COMPLETE
	IFIW	CTICDS		;(11) DISCARD STATE (^O)
	IFIW	CPOPJ##		;(12) READ CHARACTERISTICS (SEND ONLY)
	IFIW	CTICCM		;(13) CHARACTERISTICS MESSAGE
	IFIW	CPOPJ##		;(14) READ COUNT CHECK (SEND ONLY)
	IFIW	CTICIC		;(15) INPUT COUNT
	IFIW	CTICIS		;(16) INPUT STATE TRANSITION
;CTICIM - CTERM layer input message to initialize the CTERM layer
;
;Call:
;	W/ Pointer to Link's CTB
;	U/ Address of corresponding LDB
;	P1/ Byte pointer to read bytes from the current message
;	P2/ Number of bytes remaining in the current message
;	CTIML(W)/ Count of bytes in this sub-message
;	RET			;PROTOCOL ERROR
;	RETSKP			;MUST WAIT FOR FURTHER FOUNDATION BYTES
;	DOUBLE-SKIP		;DONE
;
; Uses: T1-T4

CTICIM:	TMNE	CTRPI,(W)	;IS THIS THE FIRST ONE?
	RET			;PROTOCOL ERROR IF TWICE
	TMNE	CTMI1,(W)	;HAVE WE SKIPPED OUR CRUFT YET?
	JRST	CTICI1		;YES, DON'T SKIP IT AGAIN
	MOVEI	T1,^D12		;NO.  WE NEED 12 BYTES OF VERSION STRING & FILL
	CALL	CCISKP		;TRY TO GET PAST IT
	  RET			;ERROR
	  RETSKP		;MUST DEFER
	SETONE	CTMI1,(W)	;NOTE THAT WE SKIPPED IT
	MOVEI	T1,NRTRIL-12	;GET OUR MAXIMUM INPUT BUFFER SIZE
	STOR	T1,CTIBS,(W)	;SAVE IN CASE REMOTE DOESN'T SET IT
CTICI1:	CALL	CCIJNK		;SKIP OVER JUNK BYTES (IF ANY)
	  RET			;ERROR
	  RETSKP		;MUST DEFER
CTICI2:	TMNN	CTIML,(W)	;ANYTHING MORE TO READ?
	JRST	CTICIF		;NO, EXIT THE SUB-MESSAGE
	MOVEI	T1,2		;TO BE LEGAL, ANY PARAMETER MUST HAVE TWO BYTES
	CALL	CCICHK		;SEE IF I CAN READ THEM
	  RET			;ERROR
	  RETSKP		;DEFER
	MOVEI	T1,4		;I'D PREFER TO SEE 4, HOWEVER
	CALL	CCICHK		;CAN I GET THEM?
	  TRNA			;OK IF TOO SHORT
	  RETSKP		;WAIT IF THEY'RE POSSIBLE
	CALL	CCIBYT		;YES, GET THE PARAMETER TYPE INDEX
	  RET			;ERROR
	  RET			;STILL AN ERROR
	JUMPE	T1,CPOPJ##	;TYPE ZERO IS ILLEGAL
	MOVE	T4,T1		;COPY THE PARAMETER BYTE
	CALL	CCIBYT		;GET THE VALUE LENGTH BYTE
	  RET			;ERROR
	  RET			;STILL AN ERROR
	MOVE	T3,T1		;COPY THAT, TOO
	CALL	CCICHK		;CAN WE GET THAT MANY?
	  RET			;NO
	  JFCL			;DON'T DEFER (YET)
	CAILE	T4,3		;DO WE KNOW ABOUT THIS PARAMETER?
	JRST	CCIIM0		;NO, JUST SKIP IT
	JRST	@.(T4)		;YES, DISPATCH
	IFIW	CCIIM1		;(1) MAXIMUM MESSAGE SIZE ALLOWABLE
	IFIW	CCIIM2		;(2) MAXIMUM INPUT BUFFER SIZE ALLOWABLE
	IFIW	CCIIM3		;(3) MESSAGE TYPES SUPPORTED

CCIIM0:	STOR	T3,CTMIJ,(W)	;CLAIM THAT THE MESSAGE IS JUNK
	JRST	CTICI1		;AND SKIP OVER IT

CCIIM1:	CAILE	T3,2		;DOES IT LOOK LIKE THE SIZE MEANS ANYTHING?
	JRST	CCIIM0		;NO, DON'T BOTHER WITH IT
	XMOVEI	T1,CCIBYT	;ASSUME THE SIZE IS A BYTE
	CAIL	T3,2		;IS IT?
	XMOVEI	T1,CCIINT	;NO, GRAB AN INTEGER
	CALL	(T1)		;READ THE VALUE IN QUESTION
	  RET			;CAN'T DO IT
	  RET			;I ALREADY CHECKED FOR FOUR
	CAIGE	T1,SRVMMS	;WITHIN MINIMUM (FROM THE SPEC)?
	RET			;NO, GIVE UP
	LOAD	T2,CTSIZ,(W)	;YES, GET OUR MAXIMUM TO SEND
	CAMGE	T1,T2		;DOES IT FIT?
	STOR	T1,CTSIZ,(W)	;NO, LIMIT OURSELVES
	JRST	CTICI2		;CHECK FOR NEXT PARAMETER

CCIIM2:	CAILE	T3,2		;DOES IT LOOK LIKE THE SIZE WILL MATTER TO US?
	JRST	CCIIM0		;NO, SO SKIP IT
	XMOVEI	T1,CCIBYT	;ASSUME A 1-BYTE SIZE
	CAIL	T3,2		;VALID ASSUMPTION?
	XMOVEI	T1,CCIINT	;NO, IT'S 2 BYTES
	CALL	(T1)		;GET THE VALUE
	  RET			;ERROR
	  RET			;STILL AN ERROR
	CAIGE	T1,MINIBS	;WITHIN REQUIREMENTS OF THE SPEC?
	RET			;ERROR IF NOT
	CAIGE	T1,NRTRIL-12	;WITHIN OUR MAXIMUM?
	STOR	T1,CTIBS,(W)	;YES, REMEMBER IT
	JRST	CTICI2		;CHECK FOR NEXT PARAMETER

CCIIM3:	CAIGE	T3,2		;DO WE HAVE ENOUGH BYTES?
	RET			;DOESN'T SUPPORT ENOUGH, IT'S AN ERROR
	SUBI	T3,2		;YES, OFFSET BY HOW MANY WE'LL READ
	STOR	T3,CTMIJ,(W)	;ANY OTHERS ARE JUNK
	CALL	CCIINT		;READ THE BYTES WE CARE ABOUT
	  RET			;ERROR IF CAN'T
	  RET			;I ALREADY CHECKED FOR FOUR
	ANDI	T1,MT.SUP	;MASK DOWN TO THE MESSAGE TYPES WE CARE ABOUT
	CAIE	T1,MT.SUP	;ARE THEY ALL SUPPORTED?
	STOPCD	.,EVENT,CTHBCM,DIEBCM	;++BAD CONFIGURATION MESSAGE
	JRST	CTICI1		;YES, SKIP ANY POSSIBLE JUNK BYTES

CTICIF:	SETONE	CTRPI,(W)	;WE HAVE RECEIVED A VALID PROTOCOL INIT
	CALL	SETCHP##	;WAKE UP OUTPUT PROCESS
	PJRST	CCIFIN		;SUCCESSFUL END OF FUNCTION

DIEBCM:	PUSHJ	P,INLMES##	;TYPE SOME INFO
	ASCIZ	\	Node \
	MOVE	T1,W		;COPY CTB POINTER
	PUSHJ	P,NRTNFC	;GET NODE FROM CTB/NRB
	PJRST	PRNODE		;TYPE THE NODE SPEC
;CTICRD - CTERM layer input message to accept read data
;
;Call:
;	W/ Pointer to Link's CTB
;	U/ Address of corresponding LDB
;	P1/ Byte pointer to read bytes from the current message
;	P2/ Number of bytes remaining in the current message
;	CTIML(W)/ Count of bytes in this sub-message
;	RET			;PROTOCOL ERROR
;	RETSKP			;MUST WAIT FOR FURTHER FOUNDATION BYTES
;	DOUBLE-SKIP		;DONE
;
; Uses: T1-T4

CTICRD:	TMNE	CTMI1,(W)	;HAVE WE READ OUR OVERHEAD BYTES YET?
	JRST	CTICR1		;YES, DON'T OVERWRITE OUR HEADER INFO
	MOVEI	T1,7		;NO, I NEED 7 BYTES OF ONE-TIME DATA
	CALL	CCICHK		;CAN I GET THEM?
	  RET			;PROTOCOL ERROR
	  RETSKP		;MUST WAIT
	CALL	CCIBYT		;GET FLAGS BYTE
	  RET			;ERROR
	  RET			;STILL AN ERROR
	ANDI	T1,RD.IIP!RD.TRM	;KEEP ONLY RELEVANT BITS
	MOVE	T4,T1		;SAVE FOR LATER CHECK
	MOVEI	T1,4		;FOUR ARE JUST JUNK TO ME
	CALL	CCISKP		;SO TRY NOT TO READ THEM
	  RET			;ERROR
	  RET			;STILL AN ERROR
	CALL	CCIINT		;NOW GET THE NUMBER OF PRE-TERMINATOR CHARACTERS
	  RET			;ERROR
	  RET			;STILL AN ERROR
	OPSTR	<CAMLE	T1,>,CTIML,(W)	;DO WE HAVE THAT MANY TO READ?
	RET			;PROTOCOL ERROR IF NOT
	MOVX	R,CTECH		;DRQ-IS-ECHOING BIT
	TDNN	R,CT.ECH(W)	;IS IT?
	TDZA	T1,T1		;NO, FORGET ABOUT PRE-TERMINATOR COUNT
	ANDCAM	R,CT.ECH(W)	;YES, BUT NOT ANY MORE
	STOR	T1,CTMW1,(W)	;SAVE THE COUNT FOR CK.FDE FLAGGING
	SETONE	CTMI1,(W)	;WE HAVE READ OUR HEADER
	CAIN	T4,.RDTMO	;IF READ TIMED OUT,
	SKIPE	CT.IML(W)	;AND THERE ARE NO CHARACTERS AT ALL,
	JRST	CTICR1		;NO OR NO, FORGET THIS
	SETONE	CTDRZ,(W)	;YES, REMEMBER THE NULL DRQ
CTICR1:	CALL	CCIBYT		;TRY TO GET A CHARACTER TO STORE
	  JRST	CTICR2		;DONE IF NO MORE CHARACTERS
	  RETSKP		;DEFER IF WE MUST
	MOVE	T3,T1		;PUT CHARACTER WHERE SCNSER WANTS IT
	OPSTRM	<SOSL>,CTMW1,(W) ;TERMINATORS DON'T ECHO
	TRO	T3,CK.FDE	;FRONT-END DID THE ECHO
	MOVX	R,CTCIB!CTDRI	;GET BITS SAYING NOT TO STORE
	TDNN	R,CT.FLM(W)	;DON'T STORE IF THIS IS AN INVALID DRQ
	CALL	RECPTY##	;STUFF IT INTO THE INPUT CHUNKS
	JRST	CTICR1		;LOOP FOR AS MANY CHARACTERS AS WE CAN
CTICR2:	SETZRO	CTDRI,(W)	;OK, THE NEXT DRQ WILL BE VALID
	MOVX	R,CTDRQ!CTURA	;AND WE DON'T HAVE ONE OUTSTANDING
	ANDCAM	R,CT.FLG(W)	;AND ANY PENDING UNREAD IS COMPLETE
	PJRST	CCIFIN		;SUCCESSFUL END OF COMMON-DATA
;CTICOB - CTERM layer input message to accept an out-of-band character
;
;Call:
;	W/ Pointer to Link's CTB
;	U/ Address of corresponding LDB
;	P1/ Byte pointer to read bytes from the current message
;	P2/ Number of bytes remaining in the current message
;	CTIML(W)/ Count of bytes in this sub-message
;	RET			;PROTOCOL ERROR
;	RETSKP			;MUST WAIT FOR FURTHER FOUNDATION BYTES
;	DOUBLE-SKIP		;DONE
;
; Uses: T1-T4

CTICOB:	MOVEI	T1,2		;TWO DATA BYTES FOR THIS MESSAGE
	CALL	CCICHK		;DO I HAVE THEM?
	  RET			;PROTOCOL ERROR
	  RETSKP		;MUST WAIT FOR THEM
	CALL	CCIBYT		;GET FLAGS BYTE
	  RET			;ERROR
	  RET			;STILL AN ERROR
	TRNE	T1,OB.DIS	;SHOULD WE BE SUPPRESSING?
	CALL	STCTRO##	;YES, NOTIFY SCNSER
	CALL	CCIBYT		;GET THE CHARACTER IN QUESTION
	  RET			;ERROR
	  RET			;STILL ERROR
	MOVE	T3,T1		;MOVE IT TO CHARACTER AC
	CALL	RECPTY##	;FEED IT TO SCNSER
	JRST	CCIFIN		;DONE
;CTICWC - CTERM layer input message to accept a write completion notice
;
;Call:
;	W/ Pointer to Link's CTB
;	U/ Address of corresponding LDB
;	P1/ Byte pointer to read bytes from the current message
;	P2/ Number of bytes remaining in the current message
;	CTIML(W)/ Count of bytes in this sub-message
;	RET			;PROTOCOL ERROR
;	RETSKP			;MUST WAIT FOR FURTHER FOUNDATION BYTES
;	DOUBLE-SKIP		;DONE
;
; Uses: T1-T4

CTICWC:	MOVEI	T1,5		;FIVE DATA BYTES FOR THIS MESSAGE
	CALL	CCISKP		;CAN I EAT THEM?
	  RET			;PROTOCOL ERROR
	  RETSKP		;MUST WAIT FOR THEM
;Add code here to notify SCNSER as soon as we implement the DOBE function
	JRST	CCIFIN		;DONE
;CTICDS - CTERM layer input message to accept a new discard state
;
;Call:
;	W/ Pointer to Link's CTB
;	U/ Address of corresponding LDB
;	P1/ Byte pointer to read bytes from the current message
;	P2/ Number of bytes remaining in the current message
;	CTIML(W)/ Count of bytes in this sub-message
;	RET			;PROTOCOL ERROR
;	RETSKP			;MUST WAIT FOR FURTHER FOUNDATION BYTES
;	DOUBLE-SKIP		;DONE
;
; Uses: T1-T4

CTICDS:	CALL	CCIBYT		;READ THE SINGLE DATA BYTE
	  RET			;PROTOCOL ERROR
	  RETSKP		;WAIT FOR IT
	XMOVEI	T2,NOCTRO##	;ASSUME ENABLING OUTPUT
	TRNN	T1,DS.CDS	;BIT IS BACKWARDS
	XMOVEI	T2,STCTRO##	;NO, DISABLING
	CALL	(T2)		;INFORM SCNSER
	JRST	CCIFIN		;DONE
;CTICCM - CTERM layer input message to accept a characteristics message
;
;Call:
;	W/ Pointer to Link's CTB
;	U/ Address of corresponding LDB
;	P1/ Byte pointer to read bytes from the current message
;	P2/ Number of bytes remaining in the current message
;	CTIML(W)/ Count of bytes in this sub-message
;	RET			;PROTOCOL ERROR
;	RETSKP			;MUST WAIT FOR FURTHER FOUNDATION BYTES
;	DOUBLE-SKIP		;DONE
;
; Uses: T1-T4

CTICCM:	TMNE	CTMI1,(W)	;DID WE EAT THE HEADER YET?
	JRST	CTICC1		;YES, DON'T DO IT AGAIN
	CALL	CCIBYT		;TRY TO EAT IT
	  RET			;PROTOCOL ERROR
	  RETSKP		;WAIT FOR IT
	SETONE	CTMI1,(W)	;OK, WE ATE IT
	MOVEI	T1,1		;DEFAULT TTY QUOTE ON FOR RTPAD
	DPB	T1,LDPQOT##	;JUST IN CASE
CTICC1:	LOAD	T1,CTMW1,(W)	;DO WE HAVE A CHARACTERISTIC IN PROGRESS?
	JUMPN	T1,CTICC2	;IF SO, TRY IT AGAIN
CTICC4:	MOVEI	T1,2		;NO, NEED TWO BYTES
	CALL	CCICHK		;CAN WE HAVE THEM?
	  JRST	CTICC5		;WE'RE DONE
	  RETSKP		;MUST WAIT FOR THEM
	CALL	CCIINT		;GET THE IDENTIFIER
	  RET			;ERROR
	  RET			;STILL AN ERROR
	STOR	T1,CTMW1,(W)	;STORE THE WORD FOR LATER
CTICC2:	LSHC	T1,-8		;SPLIT INTO MAJOR & MINOR TYPES
	LSH	T2,-^D<36-8>	;POSITION BOTTOM TO WHERE IT BELONGS
	CAILE	T1,.CTCMH	;IS THE MAJOR TYPE ONE WE UNDERSTAND?
	RET			;NO, SO WE DIDN'T ASK
	JRST	@.+1(T1)	;YES, DISPATCH ON IT
	IFIW	CCICMP		;(0) PHYSICAL FOUNDATION VALUES
	IFIW	CCICML		;(1) LOGICAL FOUNDATION VALUES
	IFIW	CCICMC		;(2) CTERM HANDLER VALUES

CTICC3:	SETZRO	CTMW1,(W)	;DONE WITH CURRENT CHARACTERISTIC
	JRST	CTICC4		;TRY FOR ANOTHER

CTICC5:	CALL	SETCHP##	;START UP OUR OUTPUT SIDE
	SETONE	CTCHP,(W)	;WE HAVE RECEIVED A CHARACTERISTICS MESSAGE
	TMNE	CTBAD,(W)	;IS THIS VMS?
	CALL	CCIBYT		;YES, ALLOW RTPAD ITS TRASH
	  JRST	CCIFIN		;NO, FINISH UP AND RETURN
	  RETSKP		;YES, BUT WE HAVE TO WAIT FOR THE GARBAGE
	JRST	CCIFIN		;YES, AND WE GOT ITS JUNK BYTE, GO FINISH UP

CCICMP:	CAILE	T2,0		;IS THE SUB-TYPE
	CAILE	T2,.CMXFP&BYTMSK ;IN RANGE OF 'PHYSICAL' VALUES WE KNOW?
	RET			;NO, SO WE DIDN'T ASK
	JRST	@.(T2)		;YES, SO DISPATCH ON IT
	IFIW	CCMPRS		;(1) RECEIVE SPEED
	IFIW	CCMPXS		;(2) TRANSMIT SPEED
	IFIW	CCMPCS		;(3) CHARACTER SIZE
	IFIW	CCMPPE		;(4) PARITY ENABLE
	IFIW	CCMPPT		;(5) PARITY TYPE
	IFIW	CCMPMP		;(6) MODEM PRESENT (DATASET)
	IFIW	CCMPAB		;(7) AUTO-BAUD
	IFIW	CCMPMG		;(10) MANAGEMENT GUARANTEED
	IFIW	CCMPS1		;(11) SWITCH-CHARACTER ONE
	IFIW	CCMPS2		;(12) SWITCH-CHARACTER TWO
	IFIW	CCMP8C		;(13) EIGHT-BIT
	IFIW	CCMPME		;(14) MANAGEMENT-ENABLED

CCMPMP==CPOPJ##			;I DIDN'T ASK
CCMPAB==CPOPJ##			;I DIDN'T ASK
CCMPMG==CPOPJ##			;I DIDN'T ASK
CCMPS1==CPOPJ##			;I DIDN'T ASK
CCMPS2==CPOPJ##			;I DIDN'T ASK
CCMPME==CPOPJ##			;I DIDN'T ASK
CCMPPE==CPOPJ##			;I DIDN'T ASK
CCMPPT==CPOPJ##			;I DIDN'T ASK
CCMP8C==CPOPJ##			;I DIDN'T ASK

CCMPRS:	CALL	CCIINT		;GET THE BAUD RATE
	  RET			;NEVER MIND
	  RETSKP		;WAIT FOR IT
	CALL	CCMPSX		;CONVERT TO A -10 SPEED INDEX
	DPB	T2,LDPRSP##	;YES, STORE IN SCNSER
	JRST	CTICC3		;LOOP FOR NEXT PARAMETER

CCMPXS:	CALL	CCIINT		;GET THE BAUD RATE
	  RET			;NEVER MIND
	  RETSKP		;WAIT FOR IT
	CALL	CCMPSX		;CONVERT TO A -10 SPEED INDEX
	DPB	T2,LDPTSP##	;YES, STORE IN SCNSER
	JRST	CTICC3		;LOOP FOR NEXT PARAMETER

CCMPSX:	MOVSI	T2,-CCMPSL	;GET AOBJN POINTER TO SPEED TABLE
	CAME	T1,CCMPST(T2)	;DOES THE SPEED MATCH?
	AOBJN	T2,.-1		;NO, LOOK AGAIN
	HRRZS	T2		;ISOLATE SPEED INDEX
	RET			;PASS BACK THIS VALUE

CCMPST:	DEC	0,50,75,110,135,150,200,300,600,1200,1800,2400
	DEC	4800,9600,19200
CCMPSL==.-CCMPST

CCMPCS:	CALL	CCIINT		;GET THE VALUE
	  RET			;ERROR
	  RETSKP		;WAIT FOR IT
	CAIE	T1,8		;REMOTE HANDLING 8-BIT MODE?
	TDZA	T1,T1		;NO, ASSUME 7-BIT
	MOVEI	T1,1		;YES, LIGHT THE FLAG
	DPB	T1,LDP8BT##	;SET IT
	STOR	T1,CH8BT,(W)	;KEEP OUR OWN COPY
	JRST	CTICC3		;LOOP FOR NEXT PARAMETER

CCICML:	CAILE	T2,0		;IS IT IN RANGE OF THE LOGICAL
	CAILE	T2,.CMXFL&BYTMSK ;PARAMETERS WE KNOW ABOUT?
	RET			;NO, SO WE DIDN'T ASK
	JRST	@.(T2)		;YES, SO DISPATCH ON IT
	IFIW	CCMLMW		;(1) MODE WRITING ALLOWED
	IFIW	CCMLTA		;(2) TERMINAL ATTRIBUTES
	IFIW	CCMLTT		;(3) TERMINAL TYPE
	IFIW	CCMLOF		;(4) OUTPUT FLOW CONTROL
	IFIW	CCMLPS		;(5) PAGE STOP
	IFIW	CCMLFP		;(6) FLOW CHARACTER PASSTHROUGH
	IFIW	CCMLIF		;(7) INPUT FLOW CONTROL
	IFIW	CCMLLN		;(10) LOSS NOTIFICATION
	IFIW	CCMLLW		;(11) LINE WIDTH
	IFIW	CCMLFL		;(12) FORMS LENGTH
	IFIW	CCMLSL		;(13) STOP LENGTH
	IFIW	CCMLCR		;(14) CR-FILL
	IFIW	CCMLLF		;(15) LF-FILL
	IFIW	CCMLWR		;(16) WRAP HANDLING
	IFIW	CCMLHT		;(17) HT HANDLING
	IFIW	CCMLVT		;(20) VT HANDLING
	IFIW	CCMLFF		;(21) FF HANDLING

CCMLMW==CPOPJ##			;I DIDN'T ASK
CCMLFP==CPOPJ##			;I DIDN'T ASK
CCMLIF==CPOPJ##			;I DIDN'T ASK
CCMLLN==CPOPJ##			;I DIDN'T ASK
CCMLCR==CPOPJ##			;I DIDN'T ASK
CCMLLF==CPOPJ##			;I DIDN'T ASK
CCMLVT==CPOPJ##			;I DIDN'T ASK

CCMLTA:	CALL	CCIINT		;GET THE 2-BYTE BIT MASK
	  RET			;ERROR
	  RETSKP		;WAIT
	ANDI	T1,TA%DIS	;ONLY CARE IF IT'S VIDEO
	LSH	T1,-1		;POSITION WHERE IT BELONGS
	DPB	T1,LDPDIS##	;STORE IT AWAY
	STOR	T1,CHDIS,(W)	;KEEP OUR OWN COPY
	JRST	CTICC3		;LOOP OVER ALL PARAMETERS

CCMLTT:	LOAD	T1,CTIML,(W)	;GET NUMBER OF REMAINING BYTES
	CAILE	T1,7		;IF BEYOND RANGE THAT WE CARE ABOUT,
	MOVEI	T1,7		;MINIMIZE
	CALL	CCICHK		;SEE IF WE CAN HAVE THAT MANY
	  RET			;BUT IT'S IN RANGE!
	  RETSKP		;BE PATIENT
	CALL	CCIBYT		;GET THE STRING'S LENGTH
	  RET			;ERROR IF CAN'T
	  RET			;I JUST CHECKED FOR IN RANGE
	CAILE	T1,17		;CAN WE HANDLE THAT LONG A NAME?
	RET			;NO, BUT THAT MEANS IT'S TOO LONG
	JUMPE	T1,CTICC3	;DONE WITH IT IF IT'S NULL
	MOVE	T4,T1		;COPY THE LENGTH FOR LATER COMPARISON
	CALL	CCISIX		;READ SIXBIT
	  RET			;ERROR IF RAN OUT
	  RET			;I ALREADY CHECKED AVAILABILITY (6 BYTES MAX)
	STOR	T4,CTMIJ,(W)	;STORE NUMBER OF JUNK BYTES	
	MOVE	T2,T1		;GET TTY NAME WHERE COMCON WANTS IT
	PUSHJ	P,TTUTYP##	;TRY TO SET TTY NAME
	  JRST	CCMLT1		;DON'T STORE JUKN
	LDB	T1,LDPTTT##	;GOT IT,
	STOR	T1,CHTTT,(W)	;SAVE IN OUR COPY AS WELL
CCMLT1:	SETZ	T1,		;ZERO FILL CLASS
	DPB	T1,LDPFLC##	;REMOTE DOES ITS OWN FILL
	SETZRO	CTMW1,(W)	;NO LONGER DOING A CHARACTERISTIC
	CALL	CCIJNK		;SKIP ANY TRASH IN THE NAME
	  RET			;ERROR IF RAN OUT
	  RETSKP		;OK TO BE PATIENT NOW
	JRST	CTICC3		;LOOP OVER ALL PARAMETERS

CCMLOF:	CALL	CCIBYT		;GET THE VALUE
	  RET			;ERROR
	  RETSKP		;AWAIT IT
	DPB	T1,LDPXNF##	;STORE IT AWAY
	STOR	T1,CHXNF,(W)	;KEEP OUR OWN COPY
	JRST	CTICC3		;LOOP OVER ALL PARAMETERS

CCMLPS:	CALL	CCIBYT		;GET THE VALUE
	  RET			;ERROR
	  RETSKP		;AWAIT IT
	DPB	T1,LDPSPE##	;STORE IT AWAY
	SKIPE	T1		;IF ON,
	DPB	T1,LDPSST##	;IT IMPLIES SSTOP AS WELL
	JRST	CTICC3		;LOOP OVER ALL PARAMETERS

CCMLLW:	CALL	CCIINT		;GET THE VALUE
	  RET			;ERROR
	  RETSKP		;AWAIT IT
	JUMPE	T1,CTICC3	;IGNORE IT IF TOPS-20 NOWRAP
	CAILE	T1,^D255	;IS IT IN RANGE?
	MOVEI	T1,^D255	;NO, TAKE OUR MAXIMUM
	CAIGE	T1,^D16		;HOW ABOUT LOWER BOUND?
	MOVEI	T1,^D16		;HARUMPH
	DPB	T1,LDPWID##	;SAVE THE CARRIAGE WIDTH
	STOR	T1,CHWID,(W)	;KEEP OUR OWN COPY
	JRST	CTICC3		;LOOP OVER ALL PARAMETERS

CCMLFL:	CALL	CCIINT		;GET THE VALUE
	  RET			;ERROR
	  RETSKP		;WAIT
	CAILE	T1,^D255	;IN OUR RANGE LIMIT?
	SETZ	T1,		;NO, SAY NO MAXIMUM
	DPB	T1,LDPLNB##	;SET OUR LENGTH
	STOR	T1,CHLNB,(W)	;KEEP OUR COPY
	JRST	CTICC3		;LOOP FOR NEXT PARAMETER

CCMLSL:	CALL	CCIINT		;GET THE VALUE
	  RET			;ERROR
	  RETSKP		;WAIT
	CAILE	T1,^D255	;IN RANGE?
	SETZ	T1,		;NO, DON'T BOTHER
	DPB	T1,LDPSTB##	;SET OUR STOP SIZE
	JRST	CTICC3		;TRY FOR NEXT PARAMETER

CCMLWR:	CALL	CCIINT		;GET THE VALUE
	  RET			;ERROR
	  RETSKP		;WAIT
	CAIN	T1,WP.SFT	;IS IT REALLY DOING AUTO-WRAP?
	TDZA	T1,T1		;YES,
	MOVEI	T1,1		;OR NO
	DPB	T1,LDPNFC##	;SET NO-FREE-CRLF CORRESPONDINGLY
	JRST	CTICC3		;LOOP FOR NEXT CHARACTERISTIC

CCMLHT:	CALL	CCIINT		;GET THE VALUE
	  RET			;ERROR
	  RETSKP		;WAIT
	DPB	T1,LDPTAB##	;PROPAGATE INTO TTY TAB
		.CREF	HT.PHY	;NOTE VALUE PROPAGATED
	JRST	CTICC3		;LOOP FOR NEXT VALUE

CCMLFF:	CALL	CCIINT		;GET THE VALUE
	  RET			;ERROR
	  RETSKP		;WAIT
	DPB	T1,LDPFRM##	;PROPAGATE INTO TTY FORM
		.CREF	FF.PHY	;NOTE VALUE PROPAGATED
	JRST	CTICC3		;LOOP FOR NEXT VALUE

CCICMC:	CAILE	T2,0		;IS IT IN RANGE FOR CTERM CHARACTERISTICS
	CAILE	T2,.CMXMH&BYTMSK ;THAT WE KNOW ABOUT?
	RET			;NO, SO WE DIDN'T ASK
	JRST	@.(T2)		;YES, SO DISPATCH ON IT
	IFIW	CCMCII		;(1) IGNORE INPUT
	IFIW	CCMCCA		;(2) CHARACTER ATTRIBUTES
	IFIW	CCMCOP		;(3) CONTROL-O PASSTHROUGH
	IFIW	CCMCRI		;(4) RAISE INPUT
	IFIW	CCMCNE		;(5) NORMAL ECHO
	IFIW	CCMCIE		;(6) INPUT ESCAPE SEQUENCE RECOGNITION
	IFIW	CCMCOE		;(7) OUTPUT ESCAPE SEQUENCE RECOGNITION
	IFIW	CCMCCS		;(10) INPUT COUNT STATE
	IFIW	CCMCAP		;(11) AUTO-PROMPT
	IFIW	CCMCEP		;(12) ERROR PROCESSING

CCMCII==CPOPJ##			;I DIDN'T ASK
CCMCOP==CPOPJ##			;I DIDN'T ASK
CCMCIE==CPOPJ##			;I DIDN'T ASK
CCMCOE==CPOPJ##			;I DIDN'T ASK
CCMCCS==CPOPJ##			;I DIDN'T ASK
CCMCAP==CPOPJ##			;I DIDN'T ASK
CCMCEP==CPOPJ##			;I DIDN'T ASK

CCMCCA:	MOVEI	T1,3		;WE NEED THIS MANY MORE BYTES
	CALL	CCICHK		;SEE IF WE CAN HAVE THEM
	  RET			;CAN'T
	  RETSKP		;BE PATIENT
	CALL	CCIBYT		;YES, SEE WHAT CHARACTER THIS IF ABOUT
	  RET			;I ALREADY CHECKED FOR THIS
	  RET			;THIS, TOO
	CAIE	T1,"V"-100	;IS IT FOR ^V (SYN)?
	RET			;NO, THEN I DIDN'T ASK
	CALL	CCIINT		;YES, GET ITS BITS
	  RET			;I CHECKED FOR THIS ALREADY
	  RET			;AND FOR THIS
	TRNN	T1,CA.ENB_8	;IS ITS SPECIAL ACTION ENABLED?
	TDZA	T1,T1		;NO, LOAD A ZERO
	MOVEI	T1,1		;OR A ONE IF YES
	DPB	T1,LDPQOT##	;SET TTY QUOTE VALUE
	JRST	CTICC3		;LOOP OVER ALL VALUES

CCMCRI:	CALL	CCIBYT		;GET THE FLAG
	  RET			;CAN'T
	  RETSKP		;HAVE TO WAIT
	DPB	T1,LDPLCT##	;TTY [NO] LC
	STOR	T1,CHLCT,(W)	;KEEP OUR OWN COPY
	JRST	CTICC3		;LOOP FOR NEXT VALUE

CCMCNE:	CALL	CCIBYT		;GET THE FLAG
	  RET			;CAN'T
	  RETSKP		;WAIT
	TRC	T1,1		;OURS IS INVERTED
	DPB	T1,LDPECH##	;SET ECHO STATUS
	DPB	T1,LDPCNE##	;ALSO SET COMMMAND-LEVEL NO ECHO FROM IT
	STOR	T1,CHECH,(W)	;KEEP OUR OWN COPY
	JRST	CTICC3		;LOOP OVER ALL VALUES
;CTICIC - CTERM layer input message to accept a queued input count
;
;Call:
;	W/ Pointer to Link's CTB
;	U/ Address of corresponding LDB
;	P1/ Byte pointer to read bytes from the current message
;	P2/ Number of bytes remaining in the current message
;	CTIML(W)/ Count of bytes in this sub-message
;	RET			;PROTOCOL ERROR
;	RETSKP			;MUST WAIT FOR FURTHER FOUNDATION BYTES
;	DOUBLE-SKIP		;DONE
;
; Uses: T1-T4

CTICIC:	MOVEI	T1,4		;NUMBER OF BYTES REQUIRED
	CALL	CCICHK		;CAN I GET THEM?
	  TRNA			;OK IF NOT THERE
	  RETSKP		;HAVE TO WAIT FOR THEM
	MOVEI	T1,3		;NUMBER REALLY IN THE SPEC
	CALL	CCICHK		;CAN I GET THEM?
	  RET			;PROTOCOL ERROR IF CAN'T
	  RET			;ALREADY WAITED FOR FOUR
	CALL	CCIBYT		;EAT ONE
	  RET			;ERROR
	  RET			;STILL ERROR
	CALL	CCIINT		;GET THE COUNT
	  RET			;ERROR
	  RET			;STILL ERROR
;Add code here to deliver it to SCNSER once we can
	CALL	CCIBYT		;EAT THE VMS LOOK-AHEAD CHARACTER
	  TRNA			;WONDERFUL IF NOT THERE
	  RET			;I ALREADY CHECKED & WAITED HERE
	JRST	CCIFIN		;DONE
;CTICIS - CTERM layer input message to accept an input state message
;
;Call:
;	W/ Pointer to Link's CTB
;	U/ Address of corresponding LDB
;	P1/ Byte pointer to read bytes from the current message
;	P2/ Number of bytes remaining in the current message
;	CTIML(W)/ Count of bytes in this sub-message
;	RET			;PROTOCOL ERROR
;	RETSKP			;MUST WAIT FOR FURTHER FOUNDATION BYTES
;	DOUBLE-SKIP		;DONE
;
; Uses: T1-T4

CTICIS:	CALL	CCIBYT		;GET THE ONLY DATA BYTE
	  RET			;ERROR
	  RETSKP		;WAIT FOR IT
	TRNN	T1,IS.IIP	;DO WE CARE?
	JRST	CCIFIN		;NO, WE'RE DONE
	HRRZ	F,LDBDDB##(U)	;SEE IF THERE'S A DDB TO ANNOY
	JUMPE	F,CCIFIN	;NO, WE'RE STILL DONE
	SKIPE	DEVPSI(F)	;DON'T BOTHER IF NOT ENABLED
	CALL	PSIAVL##	;YES, NOTIFY THAT INPUT IS AVAILABLE
	JRST	CCIFIN		;DONE
;CFICHK - CTERM Foundation input routine to check remaining bytes
;
;Call:
;	W/ Pointer to Link's CTB
;	U/ Address of corresponding LDB
;	P1/ Byte pointer to read bytes from the current message
;	P2/ Number of bytes remaining in the current message
;	T1/ Number of bytes needed
;	RET			;NOT AVAILABLE, CHECK FOR EOM/MORE DATA
;	RETSKP			;AVAILABLE
;
; Uses:	T2, and T1 is clobbered on the non-skip return
;If the data is not available, any bytes which can be had are copied into
; the CTB for the foundation input routines, so more input can be had from
; DECnet even while blocking this link.

CFICHK:	JUMPE	T1,CFICK0	;SPECIAL-CASE ZERO BYTES
	CAMG	T1,P2		;ARE THERE ENOUGH IN THE CURRENT MESSAGE?
	RETSKP			;YES, NO PROBLEM
	SKIPE	T2,CTHIFP	;NO, IF USING STORED BYTES,
	LOAD	T2,CTIFL,(W)	;GET NUMBER OF BYTES CURRENTLY BUFFERED
	CAMG	T1,T2		;ENOUGH HERE?
	RETSKP			;YES, GIVE OK RETURN
	ADD	T2,P2		;FIND OUT HOW MANY THERE ARE TOTAL
	CAMG	T1,T2		;IS THIS ENOUGH?
	RETSKP			;YES, THIS IS OK
	CAILE	T2,^D16		;NO, WILL IT FIT?
	STOPCD	.,STOP,CTHIBO,	;++CTERM HOST INPUT BUFFER OVERFLOW
	JUMPE	T2,CPOPJ##	;SKIP OVERHEAD IF NO BYTES AVAILABLE AT ALL
	CALL	CFICMP		;COMPRESS OUT ANY USED-UP BYTES
	LOAD	T1,CTIFL,(W)	;GET BUFFER COUNT AGAIN
	MOVE	T2,T1		;COPY IT
	ADD	T2,P2		;GET THE TOTAL TO BE STORED (AGAIN)
	ADJBP	T1,[POINT 8,CT.IFM(W)]	;FORM STORAGE POINTER TO REST OF BUFFER
	STOR	T2,CTIFL,(W)	;STORE NEW BUFFER COUNT
	MOVE	T2,[POINT 8,CT.IFM(W)]	;GET COMPRESSED POINTER
	MOVEM	T2,CTHIFP	;SET IT IN CASE WASN'T IN USE BEFORE
CFICK2:	SOSGE	P2		;IS THERE ANOTHER BYTE TO COPY?
	RET			;NO, RETURN
	ILDB	T2,P1		;YES, FETCH IT
	IDPB	T2,T1		;AND BUFFER IT
	JRST	CFICK2		;LOOP OVER THE CURRENT MESSAGE

CFICK0:	LOAD	T2,CTIFL,(W)	;GET THE BUFFER COUNT
	CAMN	T2,P2		;DOES THE BUFFER COUNT EQUAL THE MESSAGE COUNT?
	SKIPE	T2		;AND ARE BOTH ZERO?
	RETSKP			;NO, MORE IS AVAILABLE
	PJRST	CFIRET		;YES, SEE IF AT END OF MESSAGE
;CFICMP - CTERM Foundation input buffer compressor
;
;Call:
;	W/ Pointer to Link's CTB
;	RET			;ALWAYS
;
; Uses:	T1-T4

CFICMP:	SKIPN	T3,CTHIFP	;ARE WE DOING INPUT THROUGH THE BUFFER?
	RET			;NO, NOTHING TO DO
	LOAD	T2,CTIFL,(W)	;YES, GET THE NUMBER OF BYTES TO TRANSFER
	MOVE	T1,[POINT 8,CT.IFM(W)] ;GET POINTER TO BEGINNING OF BUFFER
	CAMN	T3,T1		;ARE THEY THE SAME?
	RET			;YES, NOTHING TO DO
	MOVEM	T1,CTHIFP	;NO, UPDATE POINTER FOR READ ROUTINES
CFICM1:	SOSGE	T2		;IS THERE ANOTHER?
	RET			;NO, ALL DONE
	ILDB	T4,T3		;YES, FETCH IT
	IDPB	T4,T1		;STORE IN THE BEGINNING
	JRST	CFICM1		;LOOP OVER ENTIRE BUFFER
;CFIRET - CTERM Foundation input routine to check for EOM
;
;Call:
;	W/ Pointer to Link's CTB
;	U/ Address of corresponding LDB
;	RET			;EOM
;	RETSKP			;NOT EOM

CFIRET:	SAVEAC	M		;PRESERVE THE AC WE USE
	MOVE	M,NRTSAP	;NEED TO EXAMINE THE SAB
	TMNN	SAEOM,(M)	;EOM FLAG ON?
	AOS	(P)		;NO, SKIP RETURN
	RET			;YES, RETURN
;CFIBYT - CTERM Foundation input routine to read one byte
;
;Call:
;	W/ Pointer to Link's CTB
;	U/ Address of corresponding LDB
;	P1/ Byte pointer to read bytes from the current message
;	P2/ Number of bytes remaining in the current message
;	RET			;NOT AVAILABLE
;	RETSKP			;BYTE IN T1

CFIBYT:	SKIPN	CTHIFP		;ARE WE STILL READING FROM BUFFERED DATA?
	JRST	CFIBY1		;NO, GO READ FROM THE MESSAGE
	OPSTRM	<SOS>,CTIFL,(W)	;YES, DECREMENT THE COUNT OF REMAINING BYTES
	ILDB	T1,CTHIFP	;GET THE NEXT
	TMNN	CTIFL,(W)	;WAS THIS THE LAST?
	SETZM	CTHIFP		;YES, FLAG FOR NEXT TIME
	RETSKP			;RETURN WITH DATUM
CFIBY1:	SOSGE	P2		;ANOTHER BYTE IN MESSAGE?
	RET			;NO, RETURN FAILURE
	ILDB	T1,P1		;YES, FETCH IT
	RETSKP			;RETURN THE DATUM
;CFISKP - CTERM Foundation input routine to skip N bytes
;
;Call:
;	W/ Pointer to Link's CTB
;	U/ Address of corresponding LDB
;	P1/ Byte pointer to read bytes from the current message
;	P2/ Number of bytes remaining in the current message
;	T1/ Number of bytes to skip over
;	RET			;NOT ALL WERE AVAILABLE
;	RETSKP			;DONE
; Uses: T1 & T2

CFISKP:	MOVE	T2,T1		;COPY THE COUNT OF BYTES TO SKIP
CFISK1:	SOSGE	T2		;ANY MORE TO SKIP?
	RETSKP			;NO, WE'RE DONE
	CALL	CFIBYT		;YES, GET ONE
	  RET			;CAN'T DO IT
	JRST	CFISK1		;LOOP UNTIL REQUEST IS COMPLETED
;CFIINT - CTERM Foundation input routine to read a network integer
;
;Call:
;	W/ Pointer to Link's CTB
;	U/ Address of corresponding LDB
;	P1/ Byte pointer to read bytes from the current message
;	P2/ Number of bytes remaining in the current message
;	RET			;NOT AVAILABLE
;	RETSKP			;16-BIT INTEGER IN T1

CFIINT:	CALL	CFIBYT		;GET LOW-ORDER BYTE
	  RET			;PROPAGATE FAILURE
	SAVEAC	T2		;NEED ANOTHER AC
	MOVE	T2,T1		;SAVE LOW BYTE
	CALL	CFIBYT		;GET HIGH-ORDER BYTE
	  RET			;FAILED AGAIN	
	LSH	T1,8		;POSITION HIGH BYTE WHERE IT BELONGS
	IOR	T1,T2		;MERGE IN LOW BYTE
	RETSKP			;RETURN THE DATUM
;CFIFIN - CTERM Foundation input routine message exit routine
;
;Call:
;	W/ Pointer to Link's CTB
;	U/ Address of corresponding LDB
;	P1/ Byte pointer to read bytes from the current message
;	P2/ Number of bytes remaining in the current message
;	RET			;PROTOCOL ERROR
;	RETSKP			;WE'RE DONE SUCCESSFULLY

CFIFIN:	SETZRO	CTIFT,(W)	;NO LONGER HAVE A FUNCTION IN PROGRESS
	CALL	CFICK0		;CHECK FOR EOM
	  AOS	(P)		;ON, WE'RE GOLDEN
	RET			;OFF IS PROTOCOL ERROR

;EOM is required at this point because some Foundation messages are of
; otherwise indeterminate length.
;CCICHK - CTERM layer input routine to check on available bytes
;
;Call:
;	W/ Pointer to Link's CTB
;	U/ Address of corresponding LDB
;	P1/ Byte pointer to read bytes from the current message
;	P2/ Number of bytes remaining in the current message
;	T1/ Number of bytes needed
;	RET			;NOT AVAILABLE
;	RETSKP			;IN RANGE, BUT MUST DELAY
;	DOUBLE-SKIP		;AVAILABLE NOW
;
; Uses:	T1 & T2
;If the data is not available, any bytes which can be had are copied into
; the CTB for the foundation input routines, so more input can be had from
; DECnet even while blocking this link.

CCICHK:	OPSTR	<CAMLE	T1,>,CTIML,(W)	;IN RANGE OF CTERM BLOCK?
	RET			;NO, GIVE UP
	CALL	CFICHK		;YES, CHECK IF IN CURRENT BUFFER
	  JRST	CFIRET		;NO, RETURN DEPENDS ON EOM
	JRST	CPOPJ2##	;YES, IT'S AVAILABLE
;CCIBYT - CTERM layer input routine to read one byte
;
;Call:
;	W/ Pointer to Link's CTB
;	U/ Address of corresponding LDB
;	P1/ Byte pointer to read bytes from the current message
;	P2/ Number of bytes remaining in the current message
;	RET			;NOT AVAILABLE
;	RETSKP			;MUST WAIT FOR FURTHER FOUNDATION BYTES
;	DOUBLE-SKIP		;BYTE IN T1
;
; Uses: T1 & T2

CCIBYT:	MOVEI	T1,1		;WANT TO READ ONE BYTE
	CALL	CCICHK		;IS IT THERE?
	  RET			;NOT AT ALL
	  RETSKP		;MAYBE LATER
	OPSTRM	<SOS>,CTIML,(W)	;DECREMENT THE COUNT BY AMOUNT TO BE USED
	CALL	CFIBYT		;IN RANGE, GO FETCH
	  RET			;ERROR?!?
	JRST	CPOPJ2##	;GOT IT
;CCISKP - CTERM layer input routine to skip N bytes
;
;Call:
;	W/ Pointer to Link's CTB
;	U/ Address of corresponding LDB
;	P1/ Byte pointer to read bytes from the current message
;	P2/ Number of bytes remaining in the current message
;	T1/ Number of bytes to skip over
;	RET			;NOT AVAILABLE
;	RETSKP			;MUST WAIT FOR FURTHER FOUNDATION BYTES
;	DOUBLE-SKIP		;DONE
;
; Uses: T1 & T2

CCISKP:	CALL	CFICHK		;DO WE HAVE THEM AROUND?
	  JRST	CFIRET		;NO, RETURN BASED ON EOM
	LOAD	T2,CTIML,(W)	;YES, GET OUR REMAINING MESSAGE BYTE COUNT
	SUB	T2,T1		;ACCOUNT FOR BYTES ABOUT TO BE READ
	JUMPL	T2,CPOPJ##	;NOT ENOUGH BYTES
	STOR	T2,CTIML,(W)	;UPDATE BYTE COUNT
	CALL	CFISKP		;SKIP OVER THE BYTES
	  RET			;DIDN'T WORK
	JRST	CPOPJ2##	;BINGO
;CCIJNK - CTERM layer input routine to skip junk bytes
;
;Call:
;	W/ Pointer to Link's CTB
;	U/ Address of corresponding LDB
;	P1/ Byte pointer to read bytes from the current message
;	P2/ Number of bytes remaining in the current message
;	RET			;NOT AVAILABLE
;	RETSKP			;MUST WAIT FOR FURTHER FOUNDATION BYTES
;	DOUBLE-SKIP		;DONE
;
; Uses: T1-T2

CCIJNK:	LOAD	T1,CTMIJ,(W)	;GET THE REMAINING NUMBER OF JUNK BYTES
	JUMPE	T1,CPOPJ2##	;NO JUNK, GET NEXT VALUE BYTE
	LOAD	T2,CTIFL,(W)	;GET FOUNDATION BUFFER LENGTH
	ADD	T2,P2		;PLUS INPUT LENGTH
	JUMPE	T2,CFIRET	;CAN'T SKIP IF NO BYTES, RETURN DEPENDS ON EOM
	CAMG	T1,T2		;WILL WE NEED TO DEFER AGAIN?
	TDZA	T2,T2		;NO, NEW COUNT IS ZERO
	SUBM	T1,T2		;YES, NEW COUNT TO T2
	STOR	T2,CTMIJ,(W)	;UPDATE JUNK COUNT
	SUB	T1,T2		;CALCULATE HOW MANY TO SKIP NOW
	CALL	CCISKP		;EAT THE BYTES
	  RET			;ERROR
	  RET			;STILL AN ERROR
	JRST	CCIJNK		;CHECK AGAIN, JUST IN CASE
;CCIINT - CTERM layer input routine to read a network integer
;
;Call:
;	W/ Pointer to Link's CTB
;	U/ Address of corresponding LDB
;	P1/ Byte pointer to read bytes from the current message
;	P2/ Number of bytes remaining in the current message
;	RET			;NOT AVAILABLE
;	RETSKP			;MUST WAIT FOR FURTHER FOUNDATION BYTES
;	DOUBLE-SKIP		;16-BIT INTEGER IN T1
;
; Uses: T1 & T2

CCIINT:	MOVEI	T1,2		;WANT TO READ TWO BYTES
	CALL	CCICHK		;IS IT THERE?
	  RET			;NOT AT ALL
	  RETSKP		;MAYBE ANOTHER TIME
	MOVNI	T1,2		;GET AMOUNT FOR ADJUSTING BYTE COUNT
	OPSTRM	<ADDM T1,>,CTIML,(W)	;UPDATE REMAINING LENGTH
	CALL	CFIINT		;IN RANGE, GO FETCH
	  RET			;ERROR?!?
	JRST	CPOPJ2##	;GOT IT
;CCISIX - CTERM layer input routine to read sixbit from a string
;
;Call:
;	W/ Pointer to Link's CTB
;	U/ Address of corresponding LDB
;	P1/ Byte pointer to read bytes from the current message
;	P2/ Number of bytes remaining in the current message
;	T4/ Maximum number of characters available in the string
;	RET			;ON ERROR
;	RETSKP			;NEED MORE FOUNDATION BYTES
;	DOUBLE-SKIP		;ON SUCCESS, T1/ VALUE
;
; Uses: T1-T3, returns T4 decremented only by amount read

CCISIX:	SETZM	CTH6BW		;CLEAR OUR STORAGE WORD
	MOVE	T3,[POINT 6,CTH6BW] ;INITIALIZE OUR BYTE POINTER
CCISX1:	JUMPLE	T4,CCISX4	;EXIT IF NO MORE TO READ
	SUBI	T4,1		;ACCOUNT FOR THE NEXT READ
	CALL	CCIBYT		;FETCH A CHARACTER
	  RET			;ERROR
	  RET			;CAN'T WAIT HERE
	TRNN	T1,140		;IS IT A CONTROL CHARACTER?
	JRST	CCISX4		;YES, THIS ENDS THE STRING
	TRNE	T1,200		;IS IT AN EIGHT-BIT CHARACTER?
	RET			;THE SPEC CLAIMS ONLY 7-BIT IS LEGAL HERE...
	CAILE	T1,"a"		;IS IT A LOWERCASE CHARACTER?
	CAILE	T1,"z"		; (TEST)
	SUBI	T1,40		;NO, NEEDS CONVERSION TO SIXBIT
	IDPB	T1,T3		;STORE THE CHARACTER
	TLNE	T3,770000	;IS THERE ROOM FOR ANOTHER?
	JRST	CCISX1		;YES, READ IT
CCISX4:	MOVE	T1,CTH6BW	;GET OUR STORAGE WORD
	JRST	CPOPJ2##	;RETURN THE FANCY WORD
;CCIFIN - CTERM layer input routine to exit the sub-message
;
;Call:
;	W/ Pointer to Link's CTB
;	U/ Address of corresponding LDB
;	P1/ Byte pointer to read bytes from the current message
;	P2/ Number of bytes remaining in the current message
;	RET			;ON ERROR
;	DOUBLE-SKIP		;ON SUCCESS
;
; Uses: T1 & T2

CCIFIN:	TMNE	CTIML,(W)	;ARE WE DONE WITH THE MESSAGE?
	RET			;NO, SOMEBODY SCREWED UP
	SETZRO	CTMIJ,(W)	;NO MORE JUNK BYTES
	SETZRO	CTMI1,(W)	;NEXT MESSAGE MUST SKIP ITS OWN FILL
	JRST	CPOPJ2##	;GIVE SUCCESS RETURN TO FOUNDATION
;NJFRDR - Jiffy Service Routine for a link in DISCONNECT RECEIVED state
;
;Call:
;	W/ Pointer to Link's NRB
;	RET			;ALWAYS
;
;The link is in one of the "gone sour" states.  Close the link
;and free the TTY LDB.

NJFRDC:				;DISCONNECT CONFIRMED
NJFRDR:				;DISCONNECT RECEIVED
NJFRCF:				;NO CONFIDENCE
NJFRLK:				;NO LINK
NJFRCM:				;NO COMMUNICATION
NJFRNR:				;NO RESOURCES
	PJRST	NRTREL		;RELEASE THE LINK ALTOGETHER
;NRTNEP - Do an Enter Passive to hang out a new DECnet link
;
;Call:
;	NRTSAP/ Pointer to NRT's SAB
;	NRTSJP/ Pointer to NRT's SJB
;
;Return:
;	RET			;ALWAYS

NRTNEP:	SKIPE	NRTCWL		;ANY LINKS ALREADY WAITING?
	RET			;YES, DON'T HANG OUT ANY MORE
	SAVEAC	<M,W,P1>	;SAVE FOR SAB,NRB,CBLK POINTERS
	MOVEI	T1,NR.LEN	;LENGTH OF A NRB (AS DISTINGUISHED FROM CTB)
	MOVE	T2,[NRTOBJ,,NRTOBJ];REMOTE,,LOCAL OBJECTS
	CALL	CMNNEP		;DO COMMON ENTER PASSIVE STUFF
	  RET			;PASS ALONG FAILURE
	AOS	NRTCWL		;REMEMBER OUR NEW WAITER
	RET			;AND RETURN

CTHNEP:	SKIPE	CTHCWL		;ANY LINKS ALREADY WAITING?
	RET			;YES, DON'T HANG OUT ANY MORE
	SAVEAC	<M,W,P1>	;SAVE FOR SAB,NRB,CBLK POINTERS
	MOVEI	T1,CT.LEN	;LENGTH OF A CTERM BLOCK
	MOVE	T2,[CTSOBJ,,CTHOBJ];REMOTE,,LOCAL OBJECTS
	CALL	CMNNEP		;DO COMMON ENTER PASSIVE STUFF
	  RET			;FAILED
	AOS	CTHCWL		;REMEMBER THE NEW WAITER
	SETONE	NRCTM,(W)	;NOTE THAT THIS IS A CTERM LINK
	RET			;AND RETURN

CMNNEP:	MOVE	P1,T2		;SAVE OBJECT TYPES
	MOVE	M,NRTSAP	;POINT TO NRT'S SAB
	CALL	NRTGWD		;GET A NEW NRB OR CTB
	  RET			;COULDN'T
	MOVE	W,T1		;POINTER TO NRB

;Get and set up a connect block

	MOVEI	T1,CB.LEN	;GET PLACE TO PUT CONNECT BLK
	CALL	NRTGWD
	  JRST	[MOVE	T1,W	;CAN'T, DEALLOCATE NRB AS WELL
		 PJRST	NRTFWD]	;FREE NRB
	HLRZ	T2,P1		;GET REMOTE'S OBJECT NUMBER
	STOR	T2,PBOBJ,+CB.SRC(T1) ;SAVE IN CB
	HRRZ	T2,P1		;GET OUR OBJECT NUMBER
	STOR	T2,PBOBJ,+CB.DST(T1) ;SAVE FOR CONNECT
	MOVE	P1,T1		;P1 POINTS TO CONNECT BLOCK
	MOVEI	T1,PB.LEN	;LENGTH OF PDB
	STOR	T1,PBSIZ,+CB.SRC(P1) ;STORE SIZE OF SOURCE PDB
	STOR	T1,PBSIZ,+CB.DST(P1) ;STORE SIZE OF DEST PDB
	MOVEI	T1,0		;GET FORMAT TYPE 0
	STOR	T1,PBFOR,+CB.SRC(P1) ;STORE FORMAT OF SOURCE PDB
	STOR	T1,PBFOR,+CB.DST(P1) ;STORE FORMAT OF DEST PDB

;Now set up the SAB for an Enter Passive

	STOR	P1,SAAA1,(M)	;CONNECT BLK IS FIRST ARG
	STOR	P1,SACBP,(M)	;STORE POINTER TO CONNECT BLOCK HERE TOO

	MOVX	T1,.NSFEP	;ENTER PASSIVE FUNCTION CODE
	MOVEI	T2,3		;NUMBER OF ARGS
	CALL	NRTNSF		;ENTER PASSIVE
	  JRST	NRTNEE		;CAN'T, RETURN MEMORY & LEAVE
	CAMLE	T1,NRTCHL	;CAN WE HANDLE THIS CHANNEL NUMBER?
	JRST	[MOVX	T1,.NSFRL ;NO, RELEASE THE CHANNEL & TRY
		 MOVEI	T2,2	; FOR ANOTHER LATER, WHEN DECnet
		 CALL	NRTNSF	; HAS FREED UP SOME LOWER NUMBERS
		   JFCL		;IGNORE ERROR RETURN
		 JRST	NRTNEE]	;RETURN MEMORY & LEAVE

;Now collect returned info not already stored by NRTNSF

	LOAD	T1,SAACH,(M)	;GET NEW CHANNEL NUMBER
	STOR	T1,NRCHN,(W)	;STORE CHANNEL NUMBER IN NRB
	ADD	T1,NRTCHP	;CALC PTR TO CHANNEL TABLE ENTRY
	MOVEM	W,(T1)		;STORE NEW NRB PTR IN CHANNEL TABLE
	AOS	(P)		;PROPAGATE SUCCESS
NRTNEX:	MOVE	T1,P1		;GET POINTER TO CONNECT BLOCK
	PJRST	NRTFWD		;FREE IT

;Here on error when we have to deallocate an NRB

NRTNEE:	MOVE	T1,W		;DEALLOCATE NRB AS WELL
	CALL	NRTFWD		;FREE NRB
	JRST	NRTNEX		;FREE CONNECT BLOCK AS WELL

	SUBTTL	Subroutines -- NRTNSF - Call SCLINK's SCTNSF

;NRTNSF - Call SCLINK's SCTNSF and handle the return
;
; Call:
;	T1/ Function code
;	T2/ Number of Args not defaulted in SAB
;	M/ Extended pointer to filled-in SAB
;	W/ Pointer to NRB
;
; Return:
;	RET			;FAILED, CODE IN T1
;	RETSKP			;SUCCESS

NRTNSF:	STOR	T1,SAAFN,(M)	;FUNCTION CODE
	STOR	T2,SANAG,(M)	;STORE NUMBER OF ARGS

	SETONE	SAEVA,(M)	;BUFFERS WE PASS WILL BE IN EVA
	MOVE	T1,NRTSJP	;GET POINTER TO OUR SJB
	STOR	T1,SASJB,(M)	;STORE THE ADDRESS OF THE SJB
	XMOVEI	T1,NRTHBR	;POINT TO THE HIBER ROUTINE (BUG.)
	STOR	T1,SAHBA,(M)	;STORE IN THE HIBER ADDRESS ARGUMENT
	XMOVEI	T1,NRTWAK	;GET ADDRESS OF WAKE HANDLER
	STOR	T1,SAWKA,(M)	; AND TELL SCLINK ABOUT IT

	LOAD	T1,NRCHN,(W)	;GET CHANNEL NUMBER
	STOR	T1,SAACH,(M)	;STORE IN SAB
	MOVE	T1,M		;PASS SAB TO SCLINK
	SNCALL	(SCTNSF,MS.HGH)	;DO THE DECnet FUNCTION

	LOAD	T1,SAERR,(M)	;GET THE ERROR CODE
	JUMPN	T1,CPOPJ	;ERROR RETURN IF NON-ZERO
	LOAD	T1,SAAST,(M)	;GET NEW LINK STATUS
	STOR	T1,NRSTS,(W)	;STORE IN NRB
	RETSKP			;SUCCESS RETURN
	SUBTTL	Subroutines -- NRTREL - Release a Link

;NRTREL - Release a link and all that goes with it.
;
; Call:	W/ Pointer to the NRB to release
;
; Return:
;	RET			;ALWAYS, NRB IS DEALLOCATED
;
; Uses: W

NRTREL:	SAVEAC	<U,M>
	SETONE	NRREL,(W)	;TELL NRTLKS THIS NRB IS DOOMED

	OPSTR	<SKIPN U,>,NRLDB,(W) ;ANY LDB HERE?
	JRST	NRTRL1		;NO

;Here when there is an LDB to be freed

	CALL	NGVLDB		;FREE UP THE DDB/LDB

;Here to free the associated DECnet link

NRTRL1:	MOVE	M,NRTSAP	;POINT TO NRT'S SAB
	MOVX	T1,.NSFRL	;RELEASE FUNCTION CODE
	MOVEI	T2,2		;NUMBER OF ARGS PASSED
	CALL	NRTNSF		;RELEASE THE CONNECT
	  JFCL			;IGNORE ERROR RETURN

	LOAD	T1,NRCHN,(W)	;GET DECnet CHANNEL NUMBER
	ADD	T1,NRTCHP	;INDEX INTO CHANNEL TABLE
	SETZM	(T1)		;WE NO LONGER HAVE THIS CHANNEL OPEN

	MOVE	T1,W		;ADDRESS OF NRB
	CALL	NRTFWD		;FREE IT
	SETZ	W,		;DON'T LET CALLERS USE W
	RET			;LINK IS RELEASED NOW
	SUBTTL	Subroutines -- NGTLDB - Get an LDB for NRTSER

;NGTLDB - Get a remote LDB and make it mine
;
; Call:	W/ Pointer to NRB
;
; Return:
;	RET			;FAILED, REASON CODE IN T1
;	RETSKP			;SUCCESS, POINTER IN U
;
; Uses: W

NGTLDB:	SAVEAC	<P1,W>		;P1 WILL POINT TO NRB
	MOVE	P1,W		;PTR TO NRB

;Allocate an LDB

	MOVSI	T1,LTLNRT##	;FLAG A NEW NRT/CTERM TERMINAL
	MOVEI	T3,NRTDSP	;NRT'S ISR DISPATCH TABLE
	CALL	GETLDB##	;GET A REMOTE TTY LDB, POINTER IN U
	  JRST	[MOVX	T1,RSNOTB ; OBJECT TOO BUSY REASON CODE
		RET]		; GO ANNOUNCE THE FAILURE

;Finish making this a NRT LDB

	MOVEI	T1,NRTRTQ	;GET POINTER TO OUTPUT Q HEADER
	HRLZM	T1,LDBQUH##(U)	;STORE FOR SCNSER (TOPOKE/TOTAKE)
	STOR	U,NRLDB,(P1)	;REMEMBER OUR LDB
	MOVEM	P1,LDBNRT##(U)	;STORE NRB PTR IN LDB TOO
	MOVEI	T1,1		;MAKE CONTROL-A THE
	DPB	T1,LDPUNP##	;TTY UNPAUSE CHARACTER
	TMNE	NRCTM,(P1)	;IS THIS A NRT LINK?
	JRST	NGTLDC		;NO, CTERM, GO ELSEWHERE
	MOVEI	T1,APCNRT##	;GET NRTSER CODE
	DPB	T1,LDPAPC##	;SET ASYNC PORT CHARACTERISTIC

;Initialize the TTY with .HELLO force command

	CALL	TTFGRT##	;GO FORCE .HELLO
	RETSKP			;SUCCESS RETURN

;Here to finish up allocating a CTERM link's LDB

NGTLDC:	MOVEI	T1,APCCTM##	;GET CTERM CODE
	DPB	T1,LDPAPC##	;SET ASYNC PORT CHARACTERISTIC
	RETSKP			;RETURN GOODNESS NOW (DEFER TTFGRT UNTIL BOUND)
	SUBTTL	Subroutines -- NGVLDB - Give an LDB back to SCNSER

;NGVLDB - Give an LDB back to SCNSER
;
; Call:	U/ Pointer to LDB
;
; Return:
;	RET			;ALWAYS

NGVLDB:	SETZM	LDBNRT##(U)	;DISENGAGE LDB FROM NRB
	MOVEI	T1,IONND%	;"NODE DOWN" (PATH LOST/ETC) ERROR
	CALL	DETLDB##	;DETACH THE LDB/DDB
	PJRST	FRELDB##	;RETURN LDB TO SCNSER FREE POOL
	SUBTTL	Subroutines -- NRTWAK - Subroutine to do the WAKEs.

;NRTWAK - Called when SCLINK thinks we might want to wake the user
;
; Call:	T1/ Old Status,,PSI Mask
;	T2/ New Status,,Channel Number
;	T3/ Pointer to Session Control Job Block
;	T4/ Link identifier to pass to SCTWKQ
;
; Return:
;	RET			;Tells SCLINK not to queue SLB
;	RETSKP			;Tells SCLINK to queue SLB for SCTPSQ
;
; Uses: T1,T2,T3,T4
;
;SCLINK calls this routine (via SAWKA) when either the link
;state has changed or one of the status bits has changed from a
;zero to a one.
;
;This routine is called from extended section (on extended machine)
;so be careful not to change that.

NRTWAK:				;NRTNSF	PASSES THIS ADDR TO SCLINK
	MOVE	T1,T4		;PASS LINK IDENTIFIER TO SCTWKQ
	SNCALL	(SCTWKQ,MS.HGH)	;ASK SCLINK TO QUEUE THIS LINK FOR SCTPSQ
	SETOM	NRTPSQ		;TELL NRTSTO DECnet IS INTERESTING NOW
	RET			;ONLY RETURN
	SUBTTL	Subroutines -- NRTHBR - Subroutine to do the HIBERs.

;NRTHBR - Called by SCLINK to hibernate
;
; Call:
;	T1/ Pointer to SJB
;
; Return:
;	RET			;ONLY RETURN
;
; Uses: T1

NRTHBR:	BUG. CHK,NRTHBC,NRTSER,SOFT,<NRTHBR should never be called>,,<

Cause:	This BUG is not documented yet.

>,CPOPJ
	SUBTTL	Subroutine -- NRTLFC - Get a NRT Line number from channel

;NRTLFC - Gets a Line number given a NRT channel.
;
; Call:
;	U/ Channel number
;
; Return: U/ Line number or 0 if none found
;	RET			;Always return
; It is expected when this subroutine is called, that the calling
; routine has checked to be sure that the channel is in range of the
; channels that NRTSER has open.
;
; Used: T1,U


NRTLFC::MOVE	T1,NRTCHP	;GET THE POINTER TO THE NRB
	ADD	T1,U		;ADD IN THE CHANNEL NUMBER
	SKIPN	T1,(T1)		;ANYTHING THERE?
	 JRST	NRTRZR		;NONE, THEN RETURN ZERO
	LOAD	U,NRLDB,(T1)	;AND THEN THE POINTER TO THE LDB
	SKIPN	U		;ANYTHING THERE?
NRTRZR: TDZA	U,U		;CLEAR OUT U
	LDB	U,LDPLNO##	;GET THE LINE NUMBER
	POPJ	P,		;AND RETURN

	SUBTTL	Subroutine -- CWHNRT - Type a node spec for WHERE command

;CWHNRT - Types a node spec given a NRTSER-owned LDB.
;
; Call:
;	U/ Target LDB address
;	0(P)/ Command LDB address
;
; Return:
;	RET			;If success
;	via CWHNCN		;If line is not owned by NRTSER
;
; Used: T1-T4

CWHNRT::PUSHJ	P,NRTNFL	;GET NODE FROM LINE
	  PJRST	CWHNCN##	;NOT CONNECTED ANY MORE?
	PUSH	P,DEVNAM(F)	;SAVE DEVICE NAME
	PUSH	P,T1		;SAVE NODE ADDRESS
	PUSH	P,T2		;AND NODE NAME
	PUSHJ	P,TTYKLQ##	;ZAP USELESS TTY DDB
	EXCH	U,-3(P)		;RESTORE COMMAND LDB FOR TYPEOUT
	PUSHJ	P,INLMES##	;TYPE OUT
	  ASCIZ	/DECnet	/	;INTRODUCER
	DMOVE	T1,-1(P)	;RESTORE NODE SPEC
	PUSHJ	P,PRNODE	;FORMAT IT
	MOVE	T1,-3(P)	;GET TARGET LDB
	MOVE	T1,LDBNRT##(T1)	;GET CTB/NRT ADDRESS
	MOVX	T2,NRCTM	;CTERM-MODE BIT
	TDNN	T2,NR.CTM(T1)	;IS THIS A CTERM CONNECT?
	JRST	WHNRT1		;NO, CAN'T GIVE A LINE NUMBER
	LOADE	T1,CTRLN,(T1)	;YES, GET THE REMOTE'S LINE NUMBER
	JUMPL	T1,WHNRT1	;SKIP THIS IF UNKNOWN
	PUSH	P,T1		;SAVE IT
	PUSHJ	P,INLMES##	;TYPE SOME INTRO
	  ASCIZ	/ line # /
	POP	P,T1		;RESTORE IT
	PUSHJ	P,PRTDI8##	;LINE NUMBERS ARE OCTAL
WHNRT1:	MOVEI	T3," "		;SPACE TO SEPARATE
	PUSHJ	P,COMTYO##	;DO IT
	MOVE	T2,-2(P)	;DEVICE NAME
	PUSHJ	P,PRNAME##	;TYPE THAT
	PUSHJ	P,INLMES##	;MORE FORMATTING
	  ASCIZ	/ (/
	MOVE	T1,-3(P)	;GET TARGET LDB ADDRESS
	MOVE	T1,LDBNRT##(T1)	;GET CTB/NRB ADDRESS
	LOAD	T1,NRCTM,(T1)	;FIND OUT WHICH IT IS
	SKIPE	T1		;IF CTERM,
	SKIPA	T2,['CTERM ']	;LOAD THAT
	MOVSI	T2,'NRT'	;ELSE TYPE NRT
	PUSHJ	P,PRNAME##	;TYPE CONNECTION MODE
	MOVEI	T3,")"		;CLOSING TEXT
	PUSHJ	P,COMTYO##	;TYPE IT
	ADJSP	P,-4		;TRIM JUNK OFF THE STACK
	PJRST	PCRLF##		;END LINE AND RETURN
	SUBTTL	Subroutine -- NRTNFL - Get a NRT Node spec from line

;NRTNFL - Gets a Node spec given a NRTSER-owned LDB.
;
; Call:
;	U/ LDB address
;
; Return: T1/ Node address
;	  T2/ Node name
;	RETSKP			;If success
;	RET			;If line is not owned by NRTSER
;
; Used: T1-T4


NRTNFL::SE1ENT			;GET TO REASONABLE SECTION
	SETZ	T2,		;ASSUME NO NAME
	SKIPN	T1,LDBNRT##(U)	;GET NRB/CTB FROM LDB
	RET			;NO CAN DO
IFE FTXMON,<
	DNCALL	(NRTNFC)	;GET INFO FROM CTB/NRB
	RETSKP			;AND RETURN GOODNESS
>
IFN FTXMON,<
	AOS	(P)		;GIVE SKIP RETURN & FALL INTO NRTNFC
>

NRTNFC:	LOAD	T2,CTCHN,(T1)	;GET OUR CHANNEL NUMBER
	MOVE	T1,NRTSJP	;GET OUR SJB ADDRESS
	LOAD	T1,SJCHT,(T1)	;GET BASE OF OUR CHANNEL TABLE
	ADDI	T1,-1(T2)	;OFFSET BY CHANNEL INDEX (1 VS. 0 ORIGIN)
	MOVE	T1,(T1)		;PICK UP SLB FOR CHANNEL
	LOAD	T1,SLDNA,(T1)	;THEN GET DESTINATION NODE ADDRESS
	PUSH	P,T1		;SAVE ADDRESS
	SNCALL	(SCTA2N##,MS.HGH) ;GET NODE NAME FROM ADDRESS
	  TDZA	T2,T2		;NULL NAME IF CAN'T FIND IT
	MOVE	T2,T1		;COPY FOR PRNAME
	JRST	TPOPJ##		;RETURN ADDRESS & NAME

PRNODE:	PUSH	P,T1		;SAVE NODE ADDRESS
	CALL	PRNAME##	;TYPE NAME OUT IN SIXBIT
	MOVEI	T3,"("		;START FOR TYPING NODE ADDRESS
	CALL	COMTYO##	;TYPE ONE
	LOAD	T1,RN%ARE,(P)	;GET THE AREA NUMBER
	JUMPE	T1,PRNOD1	;DON'T TYPE IT IF ZERO
	CALL	RADX10##	;DUMP IN DECIMAL
	MOVEI	T3,"."		;SEPARATOR
	CALL	COMTYO##	;TYPE IT
PRNOD1:	LOAD	T1,RN%NOD,(P)	;GET THE IN-AREA NODE NUMBER
	CALL	RADX10##	;TYPE IT IN DECIMAL
	MOVEI	T3,")"		;END OF NODE ADDRESS
	CALL	COMTYO##	;TYPE IT
	JRST	TPOPJ##		;BALANCE STACK AND RETURN
	SUBTTL	NETDID - NETOP. function to give node ID for a TTY

;NETDID - NETOP. functin to return node ID for a NRT TTY
;
;Call: (in section 1 already)
;
;	U/ LDB of NRT 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

NETDID::MOVE	P1,M		;Get pointer to user's arg list
	EXCTUX	<SKIPN	M,5(P1)>;Does he want node name?
	  JRST	NTDID2		;No
	PUSHJ	P,NRTNFL	;Yes, get node number and name
	  JRST	NOPDNC##	;Not connected
	JUMPE	T2,NTDID1	;Handle differently if name is unknown
	MOVE	T1,T2		;Get node name
	PUSHJ	P,PU6STB##	;And put it into string block
	  JRST	NOPADC##	;Address check doing that
	JRST	NTDID2		;Skip code to store a node address
NTDID1:	MOVE	P2,T1		;Preserve the node address
	PUSHJ	P,CHKSTB##	;Address check the string block
	  JRST	NOPADC##	;Failed
	ADJSP	P,3		;Make some room
	MOVEM	P2,(P)		;Save node address
	SETZB	T1,T2		;Make some zeros
	DMOVEM	T1,-2(P)	;Clear storage words
	MOVEI	T3,-2(P)	;Start of storage
	TLO	T3,(POINT 8,,7)	;Byte pointer for storing (leading 0 for flag)
	MOVEI	P2,1		;Count one byte into the string
	LOAD	T1,RN%ARE,(P)	;Get area number
	PUSHJ	P,NTDNMO	;Stuff a decimal number
	MOVEI	T1,"."		;Separator
	IDPB	T1,T3		;Store
	AOS	P2		;Count the byte
	LOAD	T1,RN%NOD,(P)	;Get the in-area node number
	PUSHJ	P,NTDNMO	;Stuff a decimal number
	DMOVE	T1,-2(P)	;Get the string (eight bytes max)
	ADJSP	P,-3		;Balance stack
	PUSHJ	P,NTDSTO	;Store into the string block
	  JRST	NOPADC##	;Couldn't do it
NTDID2:	EXCTUX	<SKIPN	M,6(P1)>;Does he want port name?
	  RETSKP		;No.  We're done, then.
	PUSHJ	P,CHKSTB##	;Check out the string block
	  JRST	NOPADC##	;Address check
	MOVE	T1,LDBNRT##(U)	;Get NRB
	MOVX	T2,NRCTM	;Type flag
	TDNN	T2,NR.CTM(T1)	;Is this a CTERM connect?
	RETSKP			;No, we're done here
	LOADE	T1,CTRLN,(T1)	;Yes, get remote's line number
	JUMPL	T1,CPOPJ1	;Forget about storing a string if unknown
	SETZ	T2,		;Clean accumulation word
NTDID3:	LSHC	T1,-3		;Get next octal digit
	LSH	T2,-3		;Make room for full SIXBIT digit
	TLO	T2,'0  '	;Digitize it
	JUMPN	T1,NTDID3	;Loop until done with number
	MOVE	T1,T2		;Put into correct AC
	PUSHJ	P,PU6STB##	;Store into user's string block
	  JRST	NOPADC##	;Didn't work
	RETSKP			;That's all, folks!

NTDNMO:	IDIVI	T1,^D10		;Hardwired for positive decimal
	JUMPE	T1,NTDNM1	;Skip recursion if done
	PUSH	P,T2		;Save remainder for unwind
	PUSHJ	P,NTDNMO	;Typical recursive printer (in section 1)
	POP	P,T2		;Restore next remainder
NTDNM1:	ADDI	T2,"0"		;Make ASCII
	IDPB	T2,T3		;Salt it away
	AOJA	P2,CPOPJ	;Count byte and return

NTDSTO:	MOVE	T3,T1		;Save T1
IFN FTXMON,<PUSHJ P,SSPCS##>	;Preserve PCS
	MOVE	T1,M		;Copy address
	PUSHJ	P,SXPCS##	;Validate pointer
	  POPJ	P,		;Shouldn't happen since called CHKSTB
	PUSHJ	P,GETEWD##	;Fetch length word
	  POPJ	P,		;Shouldn't fail
	HRL	T1,P2		;Tell number of bytes we're storing
	PUSHJ	P,PUTEWD##	;Update count for user
	  POPJ	P,		;Should never happen
	CAILE	P2,(T4)		;Will the string fit?
	  POPJ	P,		;No room
	MOVE	T1,T3		;Yes, recover first word
	PUSHJ	P,PUTEW1##	;Store first word for user
	  POPJ	P,		;Address check
	CAIG	P2,4		;Is there really a second word?
	RETSKP			;No, don't store it
	MOVE	T1,T2		;Yes, get it
	PJRST	PUTEW1##	;And store that, too
	SUBTTL	NRTGWD - Get Some Words

;NRTGWD - Get some zeroed words
;
; Call:
;	T1/ Count of words we want
;
; Return:
;	RET			;ON ALLOCATION FAILURE
;	RETSKP			;WITH T1 POINTING TO WORDS
;
; Uses: T1-T4
;
;Note: The count of words allocated is stored in the word before the
;returned pointer.

NRTGWD:	SAVEAC	<P1,W,M>	;W & M ARE DECnet'S T5 & T6
	MOVE	P1,T1		;SAVE THE COUNT
	MOVEI	T2,1(T1)	;T2 GETS NUMBER OF WORDS.
	CALL	GETWDS##	;GO GET SOME FREE CORE
	  RET			;TELL CALLER WE LOST
	XMOVEI	T1,(T1)		;MAKE EXTENDED ADDR IN SECTION 1
	HRLI	P1,'NRT'	;MAKE A TEST THINGY
	MOVEM	P1,(T1)		;STORE COUNT IN RH OF OVERHEAD WORD
	AOJ	T1,		;RETURN POINTER TO USER PART OF BLOCK

;Zero the words.
	PUSH	P,T1		;SAVE USER ADDRESS OF NEW BLOCK
	HRRZ	T2,P1		;GET THE LENGTH OF THE BLOCK
	ADD	T2,T1		;AND POINT TO THE LAST WORD IN THE BLOCK
	SOJ	T2,		;POINT TO LAST WORD
	MOVEI	T3,0		;VALUE TO SMEAR INTO BLOCK
	SNCALL	(DNSWDS,MS.HGH)	;SMEAR ZEROES INTO BLOCK
	JRST	TPOPJ1##	;RESTORE ADDRESS AND GIVE GOOD RETURN
	SUBTTL	NRTFWD - Free Some Words

;NRTFWD - Free what NRTGWD took away
;
; Call:
;	T1/ Pointer to some words
;
; Return:
;	RET			;ALWAYS
;
; Uses: T1,T2

NRTFWD:	SOJLE	T1,[BUG.(CHK,NRTFW0,NRTSER,SOFT,<Tried to free words at zero>,,<

Cause:	This BUG is not documented yet.

>,CPOPJ)]
				;POINT TO HEADER WORD
	HLRZ	T3,(T1)		;GET THINGY TO CHECK AGAINST.
	CAIE	T3,'NRT'	;IS IT WHAT WE PUT THERE?
	  BUG. CHK,NRTBPM,NRTSER,SOFT,<Bad pointer passed to memory manager>,,<

Cause:	This BUG is not documented yet.

>,CPOPJ

	HRRZ	T2,(T1)		;GET THE WORD COUNT FOR GIVWDS
	AOJ	T2,		;ADD IN WORD OF OVERHEAD
	EXCH	T1,T2		;CORE1 WANTS THESE IN OTHER ORDER
	HRRZS	T2		;RESTORE ADDRESS TO SECTION 0
	PJRST	GIVWDS##	;LET GO OF OUR CORE AND RETURN
	SUBTTL	End of Program

	.XCMSY			;XCREF MACSYM TEMPS

				;PUT A LABEL ON THE LITERAL POOL
NRTLIT:	XLIST			;DON'T LIST THE LITERALS
	LIT
	LIST

	END