	.TITLE	K11MCO - Robin's Connect Code
	.IDENT	/1.1/
	.ENABL	LC

; Note:
;
; This  code  is  (currently,  13-Feb-86 13:24:03) selected with the SET
; RSX CON ALT command. At some near point in the future it  will  likely
; be  default for M+. The older K11CON.MAC will always be used for P/OS.
;
; As of 28-Feb-86  09:14:26, it is the default for RSX11M/M+ (not P/OS).
; As of 05-Mar-86  12:30:29, K11CON is historical, K11PCO is for P/OS.
;
;							Brian Nelson
;							13-Feb-86  13:26
; 12-Sep-86  13:48:12 BDN Changes for I/D space
; 07-Feb-89  00:00:00 Jerry Hudgins
;			Added buffering to local terminal handling to
;			prevent high-speed local input from overwriting
;			outgoing modem QIO buffer.



	.if ndf, K11INC
	.ift
	.include	/IN:K11MAC.MAC/
	.endc


;+
;
;			  Free software BY
;		       Northern Telecom, Inc.
;
; This  software  is  furnished  for  free and may be used and copied as
; desired.  This software or any other copies thereof may be provided or
; otherwise  made  available  to  any  other  person.  No  title  to and
; ownership of the software is hereby transferred or allowed. 
;
; The  information  in this software is subject to change without notice
; and should not be construed as a commitment by NORTHERN TELECOM, INC.
;
; NORTHERN TELECOM assumes no responsibility for the use or  reliability  
; of this software on any equipment whatsoever.
;
;	Northern Telecom, Inc.
;	Network Support Systems Division
;	54 Regional Drive
;	Concord, New Hampshire 03301
;	(603) 224-6511 Ext. 2529
;
;
; Title:	K11RTM
; Author:	Robin Miller
; Date:		January 29, 1986
;
; Description:
;
;	This module contains the connect code which is used in virtual
; terminal mode when talking to a remote system.
;
;-

	.enabl	lsb


doconn::
xdorsx::tstb	ttname			; insure that a device name is set
	bne	1$			; ok
	message	<You must first define an output port:>,cr	;jfp 840607
	message	<Use the SET LINE command for this.>,cr
	return

	
1$:	message	<Connecting to line >	; Print the line and speed out
	print	#ttname			; the link name
	calls	ttspee	,<#ttname>	; get the speed now
	tst	r0			; not if we can't get it
	ble	5$			; yes, do not print 0 or -1 baud
	message	< at >			; and the speed
	sub	#10	,sp		; try to format the response a little
	mov	sp	,r1		; allocate a buffer and point to it
	deccvt	r0,r1,#4		; convert to decimal, 4 wide
	print	r1	,#4		; print it
	add	#10	,sp		; pop the buffer
	message	< baud>,cr		; and finish off the message
5$:	message	< Type CTRL >
	clr	-(sp)			; allocate a text buffer
	bisb	conesc	,(sp)		; get it
	add	#100	,(sp)		; convert it back to printable
	mov	sp	,r0		; point to it now
	print	r0	,#1		; at last
	tst	(sp)+			; pop the buffer
	message	< and then C to return to command level>,cr
	call	altrsx			; /44/


100$:	return

	.dsabl	lsb

	global	<conesc	,getsys	,ttcons	,ttname	,lun.co	,lun.ti>


	.enabl	gbl
	.NLIST	BEX

	.MCALL	ALUN$S, ASTX$S, CLEF$S, CMKT$S, DIR$, DSAR$S, DSCP$S
	.MCALL	ENAR$S, ENCP$S, EXIT$S, MRKT$S, QIOW$, QIOW$S, QIO$
	.MCALL	QIO$S, SETF$S, SREX$S, TTSYM$, WTSE$S


	TTSYM$				; Define terminal symbols.

	global	<conesc, getsys, ttcons, ttname, lun.co, lun.ti>

	.SBTTL	Definitions

;	Event flags:

	ef.rem	= 14.			; Remote event flag.
	ef.loc	= 15.			; Local event flag.
	ef.kill	= 16.			; Kill I/O event flag.
	ef.time	= 17.			; Mark time event flag.
	ef.wait	= 18.			; Main wait event flag.
	ef.sync	= 19.			; Synchronize event flag.

;	Marktime equates:

	TICKS	=	1		; Ticks.
	SECNDS	=	2		; Seconds.
	MINUTE	=	3		; Minutes.
	HOURS	=	4		; Hours.

;	ASCII Equates.

	XON	=	17.		; Transmission on (CTRL/Q).
	XOFF	=	19.		; Transmission off (CTRL/S).

;	Remote terminal equates.

	BUFSIZ	=	512.		; Size of transmission buffers.
	COMCHR  = 	32.		; Size of each remote buffer.
	COMTIM  = 	6.		; Max time for buffer fill (ticks).
	COMNBF  =    <BUFSIZ/COMCHR>	; Number of remote buffers.
	COMQNM	=	4		; Number of reads to queue.
	COMCTS  =     <COMCHR*3>	; Number of bytes before XOFF.
	COMSIZ	=   <COMNBF*COMCHR>	; Size of main remote buffer.

; 	Local terminal equates.

	TTYCHR  = 	64.		; Maximum local bytes to write.
	LOCSIZ	=:	64.		; /60/ size of circular local input
;					; /60/ buffer, bytes

	.SBTTL	FILTBL - Terminal Fill Table.
;
;	This table defines the amount of time to wait for a remote
;	buffer to fill.  Since this time is speed dependent, the speed
;	selected is used to index this table and set the fill time.
;
;	Note:	The time here will actually be multiplied by the
;		number of active remote reads which speed dependant.
;

	.psect	$PDATA	,D

FILTBL:	.BYTE	12.		; S.0
	.BYTE	12.		; S.50
	.BYTE	12.		; S.75
	.BYTE	12.		; S.100
	.BYTE	12.		; S.110
	.BYTE	10.		; S.134
	.BYTE	10.		; S.150
	.BYTE	10.		; S.200
	.BYTE	10.		; S.300
	.BYTE	8.		; S.600
	.BYTE	8.		; S.1200
	.BYTE	8.		; S.1800
	.BYTE	6.		; S.2000
	.BYTE	6.		; S.2400
	.BYTE	6.		; S.3600
	.BYTE	6.		; S.4800
	.BYTE	6.		; S.7200
	.BYTE	6.		; S.9600
	.BYTE	6.		; S.EXTA
	.BYTE	6.		; S.EXTB
	.BYTE	4.		; S.19.2
	.BYTE	4.		; S.38.4
	.EVEN

	.SBTTL	CHRTBL - Character Read Table.
;
;	This table is used to set the maximum number of characters
;	per remote read QIO.  At slower speeds, the size is reduced
;	since it takes too much time to fill each read buffer.  The
;	affect of this is smoother output to the local terminal since
;	input and output are taking place at the same time.
;
CHRTBL:	.WORD	COMCHR/8.	; S.0
	.WORD	COMCHR/8.	; S.50
	.WORD	COMCHR/8.	; S.75
	.WORD	COMCHR/6	; S.100
	.WORD	COMCHR/6	; S.110
	.WORD	COMCHR/4	; S.134
	.WORD	COMCHR/4	; S.150
	.WORD	COMCHR/3	; S.200
	.WORD	COMCHR/3	; S.300
	.WORD	COMCHR/2	; S.600
	.WORD	COMCHR/2	; S.1200
	.WORD	COMCHR/2	; S.1800
	.WORD	COMCHR		; S.2000
	.WORD	COMCHR		; S.2400
	.WORD	COMCHR		; S.3600
	.WORD	COMCHR		; S.4800
	.WORD	COMCHR		; S.7200
	.WORD	COMCHR		; S.9600
	.WORD	COMCHR		; S.EXTA
	.WORD	COMCHR		; S.EXTB
	.WORD	COMCHR		; S.19.2
	.WORD	COMCHR		; S.38.4

	.SBTTL	QUETBL - Queue Reads Table.
;
;	This table is used to set the number of reads to queue to the
;	remote whenever input arrives.  At high speeds, a large number
;	of reads must be queued or else input is lost.  At slow speeds
;	this number can be less so we reduce the number of reads queued
;	to minimumize overhead.
;
QUETBL:	.BYTE	COMQNM-2.	; S.0
	.BYTE	COMQNM-2.	; S.50
	.BYTE	COMQNM-2.	; S.75
	.BYTE	COMQNM-2	; S.100
	.BYTE	COMQNM-2	; S.110
	.BYTE	COMQNM-2	; S.134
	.BYTE	COMQNM-2	; S.150
	.BYTE	COMQNM-2	; S.200
	.BYTE	COMQNM-2	; S.300
	.BYTE	COMQNM-2	; S.600
	.BYTE	COMQNM-2	; S.1200
	.BYTE	COMQNM-1	; S.1800
	.BYTE	COMQNM-1	; S.2000
	.BYTE	COMQNM-1	; S.2400
	.BYTE	COMQNM-1	; S.3600
	.BYTE	COMQNM		; S.4800
	.BYTE	COMQNM		; S.7200
	.BYTE	COMQNM		; S.9600
	.BYTE	COMQNM		; S.EXTA
	.BYTE	COMQNM		; S.EXTB
	.BYTE	COMQNM		; S.19.2
	.BYTE	COMQNM		; S.38.4
	.EVEN

	.SBTTL	Local Terminal Characteristics.

	.psect	RWDATA	,D,RW,LCL,REL,CON

;	Local terminal characteristics to save.

TTYSV:	.BYTE	TC.ACR,0		; {No} Wrap-around.
	.BYTE	TC.BIN,0		; {No} Read-passall.
	.BYTE	TC.FDX,0		; {No} Full-duplex.
	.BYTE	TC.HLD,0		; {No} Hold screen.
	.BYTE	TC.NEC,0		; {No} Echo.
	.BYTE	TC.RAT,0		; {No} Typeahead.
	.BYTE	TC.SCP,0		; {No} Scope.
	.BYTE	TC.SMR,0		; {No} Lowercase.
	.BYTE	TC.SLV,0		; {No} Slave.
	.BYTE	TC.TTP			; Terminal type.
TTYPE:	.BYTE	T.V100			; Default terminal type.
	TTYSVL = .-TTYSV

;	Local characteristics to fix at startup time.

FIXCH:	.BYTE	TC.BIN,0		; No Read-passall.
	.BYTE	TC.NEC,0		; Echo.
	FIXCHL=.-FIXCH

;	Local characteristics to change.

TTYCH:	.BYTE	TC.ACR,0		; No Wrap-around.
	.BYTE	TC.BIN,1		; Read-passall.
	.BYTE	TC.FDX,1		; Full-duplex.
	.BYTE	TC.HLD,0		; No Hold screen.
	.BYTE	TC.NEC,1		; No Echo.
	.BYTE	TC.RAT,1		; Typeahead.
	.BYTE	TC.SCP,1		; Scope.
	.BYTE	TC.SMR,1		; Lowercase.
	TTYCHL = .-TTYCH

	.SBTTL	Remote Terminal Characteristics.

;	Remote terminal characteristics to save.

COMSV:	.BYTE	TC.ACR,0		; {No} Wrap-around.
	.BYTE	TC.BIN,0		; {No} Read-passall.
	.BYTE	TC.FDX,0		; {No} Full-duplex.
	.BYTE	TC.HLD,0		; {No} Hold screen.
	.BYTE	TC.NEC,0		; {No} Echo.
	.BYTE	TC.NBR,0		; {No} Broadcast.
	.BYTE	TC.RAT,0		; {No} Typeahead.
	.BYTE	TC.SCP,0		; {No} Scope.
	.BYTE	TC.SMR,0		; {No} Lowercase.
	.BYTE	TC.SLV,0		; {No} Slave.
	.byte	TC.PTH,0		; /60/ {no} pasthru
	.byte	TC.8BC,0		; /60/ {no} EBC
	.byte	TC.HHT,0		; /60/ {no} hardware tab
	.byte	TC.HFF,0		; /60/ {no} hardware FF
	.byte	TC.HFL,0		; /60/ {no} horizontal fill
	.byte	TC.VFL,0		; /60/ {no} vertical fill
	.byte	TC.ESQ,0		; /60/ {no} ESC sequence recognition
	.BYTE	TC.TBS,0		; Typeahead buffer size.
	COMSVL = .-COMSV

;	Remote characteristics to save for modems.

COMDSV:	.BYTE	TC.ABD,0		; {No} Autobaud.
	.BYTE	TC.WID,0		; Terminal width.
	.BYTE	TC.DLU,0		; {No} Remote.
	RMODEM == .-1			; The remote modem flag <> 0 = True.
	COMDSL = .-COMDSV

;	Remote terminal characteristics to change.

COMCH:	.BYTE	TC.ACR,0		; No Wrap-around.
	.BYTE	TC.BIN,1		; Read-Passall.
	.BYTE	TC.FDX,1		; Full-duplex.
	.BYTE	TC.HLD,0		; No Hold-screen.
	.BYTE	TC.NEC,1		; No Echo.
	.BYTE	TC.NBR,1		; No Broadcast.
	.BYTE	TC.RAT,1		; Typeahead.
	.BYTE	TC.SCP,1		; Scope.
	.BYTE	TC.SMR,1		; Lowercase.
	.BYTE	TC.SLV,1		; Slave.
	.byte	TC.PTH,1		; /60/ pasthru
	.byte	TC.8BC,1		; /60/ EBC
	.byte	TC.HHT,1		; /60/ hardware tab
	.byte	TC.HFF,1		; /60/ hardware FF
	.byte	TC.HFL,0		; /60/ no horizontal fill
	.byte	TC.VFL,0		; /60/ no vertical fill
	.byte	TC.ESQ,0		; /60/ no escape sequence recognition
	.BYTE	TC.TBS,255.		; Typeahead buffer size.
	COMCHL = .-COMCH

;	Remote characteristics to change for modems.

COMDCH:	.BYTE	TC.ABD,0		; No Autobaud.
	.BYTE	TC.WID,255.		; Terminal width.
	.BYTE	TC.DLU,0		; {No} Remote.
	SMODEM == .-1			; The remote modem location to change.
	COMDCL = .-COMDCH

;	Ensure we are saving all changed remote characteristics.

	.IF NE <COMSVL-COMCHL>
	.ERROR	; Remote save and change characteristics length different.
	.ENDC


;	Clear the remote typeahead buffer.

COMCLR:	.BYTE	TC.TBF,0		; Clear the typeahead buffer.
	COMCLN = .-COMCLR

;	Save the remote terminal speed (if possible).

COMSPD:	.BYTE	TC.RSP,0		; The receive speed.
	.BYTE	TC.XSP,0		; The transmit speed.
	COMSPL = .-COMSPD		; Length of speed params.

	.SBTTL	Data/Buffer Area.

BUFADR:	.WORD	0		; ENDING BUFFER ADDRESS
BUFLEN:	.WORD	0		; # OF BYTES TO WRITE
BUFSRT:	.WORD	0		; START OF BUFFER
BUFLUN:	.WORD	0		; LUN TO WRITE TO
BUFEND:	.WORD	0		; END OF BUFFER AREA

ESEEN:	.WORD	0		; Interrupt character seen.
TTYBUF:	.WORD	0		; Local input buffer.
locbuf:	.blkw	<LOCSIZ+1>/2	; /60/ circular local input write buffer
locptr:	.blkw	1		; /60/ local input write buffer pointer

COMBUF:	.BLKB	COMSIZ		; The main remote input buffer.
COMEND:				; Ending address of main buffer.

SRTCOM:	.REPT	COMNBF		; Generate remote QIO buffers.
	.BLKW	2		; The I/O status block.
	.BLKB	COMCHR		; The remote buffer area.
	.ENDR
ENDCOM:				; End of remote QIO buffer area.
LSTCOM:	.WORD	SRTCOM		; Pointer to first/next buffer.

; -=user did CTRL/S, +=buffer ovrflw caused CTRL/S, 0=no CTRL/S

COMCTL:	.WORD	0		; The XON/XOFF control flag.

;	Debug storage area:

MAXBC:	.WORD	0		; Maximum size of read completed.
MAXCOM:	.WORD	0		; Maximum count of remote buffer.
COMABO:	.WORD	0		; Reads completed via abort code.
COMKIL:	.WORD	0		; Marktime I/O kill operations.
COMFUL:	.WORD	0		; Number of full read completed.
COMNOT:	.WORD	0		; Remote AST notification count.
RCHIN:	.BLKW	2		; The remote characters in.
QIOCNT:	.WORD	0		; Number of remote reads issued.
MINFRE:	.WORD	COMNBF		; Minimum number of free buffers.
PGMXOF:	.WORD	0		; XOFF's sent by the program.
USRXOF:	.WORD	0		; XOFF's sent by the user.
PGMXON:	.WORD	0		; XON's sent by the program.
USRXON:	.WORD	0		; XON's sent by the user.

;	End of debug storage area.

COMFRE:	.WORD	COMNBF		; Number of free remote buffers.
COMPTR:	.WORD	COMBUF		; Pointer to remote input buffer.
COMCNT:	.WORD	0		; Character count in remote buffer.
COMMKT:	.WORD	0		; # of MRKT$'s outstanding for remote.
COMNUM:	.WORD	COMQNM		; Current number of reads to queue.
COMQIO:	.WORD	COMCHR		; Number of characters for remote QIO.
COMQUE:	.WORD	COMQNM		; Number of remote reads to queue.
TTYCNT:	.WORD	TTYCHR		; Number of characters for local QIO.
FILTIM:	.WORD	COMTIM		; Time to wait for buffer to fill.

RIOSB:	.BLKW	2		; The remote I/O status block.
LIOSB:	.BLKW	2		; The local I/O status block.
XIOSB:	.BLKW	2		; The transfer I/O status block.
ERRFLG:	.WORD	0		; Error on remote read QIO$.	<> 0 = TRUE
EXFLG:	.WORD	0		; EXIT TO SYSTEM FLAG		<> 0 = TRUE
INTFLG:	.WORD	0		; INTERRUPT CHARACTER TYPED	<> 0 = TRUE


;	Directive Parameter Blocks (DPB's).

ASTLOC:	QIOW$	IO.ATA,lun.co,ef.loc,,LIOSB,,<TTYAST> ; Local UNSOL/AST attach.

ASTREM:	QIOW$	IO.ATA!TF.NOT,lun.ti,ef.rem,,RIOSB,,<COMAST> ; Remote UNSOL/AST.

ATTREM:	QIOW$	IO.ATT,lun.ti,ef.rem,,RIOSB ; Attach the remote terminal.

CLRCOM:	QIOW$	SF.SMC,lun.ti,ef.rem,,RIOSB,,<COMCLR,COMCLN> ; Clear typeahead.

DETLOC:	QIOW$	IO.DET,lun.co,ef.loc	; Detach the local terminal.

DETREM:	QIOW$	IO.DET,lun.ti,ef.rem	; Detach the remote terminal.

GETLOC:	QIOW$	SF.GMC,lun.co,ef.loc,,LIOSB,,<TTYSV,TTYSVL> ; Get local.

GETREM:	QIOW$	SF.GMC,lun.ti,ef.rem,,RIOSB,,<COMSV,COMSVL> ; Get remote.

GETDLU:	QIOW$	SF.GMC,lun.ti,ef.rem,,RIOSB,,<COMDSV,COMDSL> ; Get modem.

GETSPD:	QIOW$	SF.GMC,lun.ti,ef.rem,,RIOSB,,<COMSPD,COMSPL> ; Get speed.

HANGUP:	QIOW$	IO.HNG,lun.ti,ef.rem,,RIOSB	; Hangup remote modem.

KILLOC:	QIO$	IO.KIL,lun.co,ef.kill	; Kill local terminal I/O.

KILREM:	QIO$	IO.KIL,lun.ti,ef.kill	; Kill remote terminal I/O.

RESLOC:	QIOW$	SF.SMC,lun.co,ef.loc,,LIOSB,,<TTYSV,TTYSVL> ; Local restore.

RESREM:	QIOW$	SF.SMC,lun.ti,ef.rem,,RIOSB,,<COMSV,COMSVL> ; Remote restore.

RESDLU:	QIOW$	SF.SMC,lun.ti,ef.rem,,RIOSB,,<COMDSV,COMDSL> ; Modem restore.

SETLOC:	QIOW$	SF.SMC,lun.co,ef.loc,,LIOSB,,<TTYCH,TTYCHL> ; Local changes.

SETREM:	QIOW$	SF.SMC,lun.ti,ef.rem,,RIOSB,,<COMCH,COMCHL> ; Remote changes.

SETDLU:	QIOW$	SF.SMC,lun.ti,ef.rem,,RIOSB,,<COMDCH,COMDCL> ; Modem changes.

SETSPD:	QIOW$	SF.SMC,lun.ti,ef.rem,,RIOSB,,<COMSPD,COMSPL> ; Set speed.

XOFREM:	QIO$	IO.WAL!TF.WBT,lun.ti,,,,,<CTRLS,1,0> ; Send XOFF to remote.

XONREM:	QIO$	IO.WAL!TF.WBT,lun.ti,,,,,<CTRLQ,1,0> ; Send XON to remote.

rmtout:	Qio$	IO.WAL!TF.WBT,lun.ti,,,,,<0,1,0> ; /60/ write to remote port
;
; ASCII messages.
;
	.NLIST	BEX

CTRLQ:	.ASCII	<XON>		; Transmission ON character.
CTRLS:	.ASCII	<XOFF>		; Transmission OFF character.

	.EVEN

	.psect	$CODE	,I


	.SBTTL	XDORSX  - Mainline Code.
;+
;
; XDORSX - Mainline code.
;
;-

	.psect	$CODE	,I

ALTRSX:	call	getprv			; Enable task privilege.
	clr	eseen			; Show escape not yet seen.
	mov	#locbuf,locptr		; /60/ init local write buffer ptr
	calls	ttpars	,<#ttname>	; Get the remote unit number.
	alun$s	#lun.ti,r1,r0		; Assign LUN to the remote.
	alun$s	#lun.co,#"TI,#0		; Assign our local terminal
;
;	Setup the buffer pointers and associated variables:
;
	MOV	#COMNBF,COMFRE		; Set all remote buffers free.
	MOV	#COMNBF,MINFRE		; Set minimum buffers free.
	MOV	#SRTCOM,LSTCOM		; Set pointer to 1st buffer.
	CLR	COMCNT			; Clear the buffer count.
	CLR	COMCTL			; CLear the XOFF/XON flag.
	MOV	#COMBUF,COMPTR		; Reset the buffer pointer.
	CLR	EXFLG			; Initialize the exit flag.
	CLR	INTFLG			; Reset the interrupt flag.

;	Get the current local terminal characteristics.

	DIR$	#GETLOC			; Get local characteristics.

; Detach the local terminal and re-attach with unsolicited AST input.

	DSAR$S				; Disable AST'S for a while.
	DIR$	#DETLOC			; Detach the local terminal.

;	Set up the new local terminal characteristics.

	DIR$	#SETLOC			; Setup local characteristics.
	CALL	CHKLIO			; Check/report any errors.
	DIR$	#ASTLOC			; Attach local with unsol/AST.
	CALL	CHKLIO			; Check/report any errors.

;	Now get the remote characteristics and setup new ones.

	DIR$	#GETREM			; Get remote characteristics.
	DIR$	#GETDLU			; Get modem characteristics.
	DIR$	#GETSPD			; Get the remote port speed.
	CLRB	SMODEM			; Presume it's not a modem.
	TSTB	RMODEM			; Is terminal set for modem ?
	BEQ	50$			; If EQ, no.
	MOVB	#2,SMODEM		; Yes, change value of TC.DLU.
50$:	DIR$	#SETREM			; Setup remote characteristics.
	DIR$	#SETDLU			; Setup modem characteristics.
	DIR$	#SETSPD			; Set the remote port speed.
	BCS	60$			; If CS, presume not variable.

;	Set up various parameters based on the remote speed.

	MOVB	COMSPD+1,R2		; Copy the remote port speed.
	MOVB	FILTBL(R2),FILTIM	; Set time for remote buffer fill.
	MOVB	QUETBL(R2),COMQUE	; Set number of reads to queue.
	ASL	R2			; Convert into a word index.
	MOV	CHRTBL(R2),COMQIO	; Set maximum remote read count.

60$:	DIR$	#DETREM			; Detach the remote terminal.
	DIR$	#ASTREM			; Reattach with UNSOL/AST'S.
	CALL	CHKRIO			; Check/report any errors.
	DIR$	#CLRCOM			; Clear the typeahead buffer.

	ENAR$S				; Re-enable AST'S.
	dscp$s				; *** DISABLE CHECKPOINTING ***
	SREX$S	#RSXABO			; Setup the abort AST routine.

	.SBTTL	LOOP - Loop Reading From Terminals.
;+
;
; LOOP - Loop reading from local and remote terminals.
;
; This is the mainline routine which simply waits for input from the
; remote and then controls output to the local terminal.  Since all
; local and remote input is either done or activated via AST's, we
; don't have to post any reads in this routine.
;
;-
LOOP:	TST	COMCTL			; Did the user type XOFF ?
	BMI	50$			; If MI, yes (wait awhile).
	TST	COMCNT			; Anything in main buffer ?
	BEQ	40$			; If EQ, no.
	DSAR$S				; Yes, disable AST'S.
	CMP	COMCNT,MAXCOM		; Need to update max count ?
	BLOS	5$			; If LOS, no.
	MOV	COMCNT,MAXCOM		; Yes, so set new maximum.
5$:	MOV	COMPTR,BUFADR		; Save the buffer pointer.
	MOV	TTYCNT,BUFLEN		; Set the local output size.
	MOV	COMCNT,R3		; Copy the main buffer count.
	SUB	TTYCNT,R3		; Adjust the buffer count.
	BHIS	10$			; If HIS, not too much.
	ADD	R3,BUFLEN		; TTYCNT was too many.
	CLR	R3			; Initialize the buffer count.

10$:	MOV	R3,COMCNT		; Save new main buffer count.
	SUB	R3,BUFADR		; Point to end of this group.
	BCS	20$			; If CS, rewrap.
	CMP	BUFADR,#COMBUF		; Pointed before beginning ?
	BHIS	30$			; If HIS, no.
20$:	ADD	#COMSIZ,BUFADR		; Point to that much before end.
30$:	ENAR$S				; Enable AST'S.
	MOV	#COMBUF,BUFSRT		; Set the starting address.
	MOV	#COMEND,BUFEND		; Set the ending address.
	MOV	#lun.co,BUFLUN		; Set the LUN to write to.
	CALL	BUFOUT			; Write buffer to device.

40$:	TST	COMCTL			; Did the progam send XOFF ?
	BLE	45$			; If LE, no (user did).
	CMP	COMCNT,#COMCTS		; Still near buffer overflow ?
	BHIS	45$			; If HIS, yes.
	BIC	#77777,COMCTL		; Clear the XOFF flag
	DIR$	#XONREM			; Send an XON to the remote.
	INC	PGMXON			; Adjust program XON count.

45$:	TST	INTFLG			; Was interrupt key typed ?
	BNE	100$			; If NE, yes.
	TST	COMCNT			; Anything else to output ?
	BNE	LOOP			; If NE, yes (write more).

;	We simply wait here for something to do.

50$:	WTSE$S	#ef.wait		; Wait for something to do.
	CLEF$S	#ef.wait		; Clear our wait event flag.

;	If the exit flag is set, go exit the program.

	TST	EXFLG			; Was exit set via abort AST ?
	BEQ	60$			; If EQ, no.
	JMP	EXISYS			; Yes, so exit to the system.

;	If the interrupt key was typed, request a command.

60$:	TST	INTFLG			; Was interrupt key typed ?
	BNE	100$			; If NE, yes.
;
;	If the remote error was "Device Not Ready" (IE.DNR) then reset
;	the remote terminal characteristics and speed since the terminal
;	driver changes certain characteristics when a modem is hungup.
;
	TST	ERRFLG			; Was there a remote error ?
	BEQ	70$			; If EQ, no.
	CMPB	#IE.DNR,RIOSB		; Was error "Device Not Ready" ?
	BNE	65$			; If NE, no.
	calls	suspend	,<#2,#0>	; Wait for device to be ready.
	DIR$	#SETREM			; Setup remote characteristics.
	DIR$	#SETSPD			; Set the remote port speed.
65$:	CLR	ERRFLG			; Reset the remote error flag.

70$:	JMP	LOOP			; Go check for local output.

;	Exit virtual terminal mode.

100$:	CALL	CANCEL			; Cancel all outstanding I/O.
	DIR$	#RESLOC			; Reset local characteristics.
	DIR$	#DETLOC			; Detach the local terminal.
	CALL	REMRES			; Restore/detach remote port.
	encp$s				; *** ENABLE CHECKPOINTING ***
	call	setcc			; Set CTRL/C handler ???
	call	drpprv			; Drop task privilege.
	return				; Return from connect mode.

	.SBTTL	TTYAST - Local Character AST Routine.
;+
;
; TTYAST - Local terminal character AST routine.
;
; This routine is entered when the user types a character at the local
; terminal.  If we're in command mode, we check for CTRL/C to set the
; abort flag for file transfer commands.  Otherwise, we process special
; characters such as XON and XOFF, then write the character to the remote.
;
; Inputs:
;	(SP) = The local input character.
;
;-
TTYAST:
	mov	(SP)+,ttybuf		; /60/ fetch the local character
	Save	<R0,R1>			; save some registers.
	movb	ttybuf,R1		; /60/ copy byte to R1
	bicb	#200,R1			; /60/ clear possible parity bit.
	movb	R1,@locptr		; /60/ save it in the write buffer

;	Check for the local escape character.

	cmpb	r1,conesc		; /60/ Console escape ?
	bne	10$			; If NE, no.
	tst	eseen			; Already seen one escape ?
	bne	20$			; If NE, yes (send this one).
	inc	eseen			; No, show escape was seen.
	br	90$			; And exit the routine ...

;	If escape has been seen, process the following character.

10$:	tst	eseen			; Character following escape ?
	beq	20$			; If NE, no (send it).
	call	concmd			; Yes, so go process it.
	clr	eseen			; Clear the escape seen flag.
	tst	r0			; Should we exit CONNECT mode ?
	beq	20$			; If EQ, not a valid command.
	blt	90$			; If LT, it's a valid command.
	MOV	#-1,INTFLG		; Else, show interrupt typed.
	DIR$	#KILLOC			; Kill I/O on the local port.
	DIR$	#KILREM			; Kill I/O on the remote port.
	SETF$S	#ef.wait		; Wakeup the mainline.
	BR	90$			; And use common exit.

20$:	clr	eseen			; Clear the escape seen flag.

;	Check for special control characters.

30$:	CMPB	#XOFF,R1		; /60/ Was CTRL/S typed ?
	BNE	40$			; If NE, no.
	BIS	#100000,COMCTL		; Yes, show XOFF typed.
	INC	USRXOF			; Adjust user XOFF count.
	BR	70$			; Send it to the remote.

40$:	CMPB	#XON,R1			; /60/ Was CTRL/Q typed ?
	BNE	70$			; If NE, no.
	BIC	#100000,COMCTL		; Yes, clear XOFF flag.
	INC	USRXON			; Adjust user XON count.
	SETF$S	#ef.wait		; Wakeup mainline to output.
	TST	COMCTL			; Did we send an XOFF ?
	BNE	90$			; If NE, yes (no XON yet).
;
;	If local echo, append this character to the remote buffer
;	for output via the mainline.  The character will also get
;	written to the logfile using this mechanism.
;
70$:	TSTB	duplex			; Need to do a local echo ?
	BEQ	80$			; If EQ, no.
	SETF$S	#ef.wait		; Wakeup mainline to output.
	MOVB	R1,@COMPTR		; /60/ Copy character main buffer.
	INC	COMPTR			; Adjust the buffer pointer.
	INC	COMCNT			; Adjust the buffer count.
	CMP	COMPTR,#COMEND		; Are we at end of buffer ?
	BNE	80$			; If NE, no.
	MOV	#COMBUF,COMPTR		; Yes, wrap to beginning.

;	Write the local character to the remote port.

80$:	setpar	@locptr,@locptr		; /60/ set correct outgoing parity.
	mov	locptr,rmtout+Q.IOPL	; /60/ address of byte in DPB
	Dir$	#rmtout			; /60/ write character to remote port
	BCC	85$			; /60/ If CC, success.
	CALL	CHKDIR			; Else, report the error.
85$:
	inc	locptr			; /60/ point at next buffer position
	cmp	#locbuf+LOCSIZ,locptr	; /60/ time to wrap buffer pointer?
	bne	90$			; /60/ nope, no yet
	mov	#locbuf,locptr		; /60/ yes, point at beginning
90$:
	Unsave	<R1,R0>			; restore saved registers.
	ASTX$S				; Exit from the AST.

	.SBTTL	COMAST - Remote Character AST Routine.
;+
;
; COMAST - Remote character AST routine.
;
; This routine is entered to notify us that characters have arrived
; on the remote port.  Since this is notification only, characters
; arriving are stored in the typeahead buffer until we issue a read.
;
; Inputs:
;	(SP) = The AST parameter in our attach QIO.
;
; Outputs:
;	All registers are preserved.
;
;-
COMAST:	TST	(SP)+			; Discard stack parameter.
	TST	EXFLG			; Does user want to exit ?
	BNE	100$			; If NE, yes (discard).
	TST	INTFLG			; Exiting the connect code ?
	BNE	100$			; If NE, yes (discard).
	INC	COMNOT			; Count AST notifications.
	MOV	R4,-(SP)		; Save R4
	MOV	R5,-(SP)		;     and R5.
	MOV	COMQUE,COMNUM		; Set number of reads to queue.
;
;	If we're queuing up another set of reads, that means characters
;	are arriving faster than our current reads can complete.  When
;	this happens, we'll send an XOFF to stop the remote output.
;
	MOV	#COMNBF,R4		; Set number of free buffers.
	SUB	COMQUE,R4		; Calculate number now free.
	CMP	COMFRE,R4		; Queing another set of reads ?
	BHIS	10$			; If HIS, no.
	TST	COMCTL			; Did we already send XOFF ?
	BNE	10$			; If NE, yes.
	DIR$	#XOFREM			; Send an XOFF to the remote.
	INC	COMCTL			; Show we sent the XOFF.
	INC	PGMXOF			; Adjust program XOFF count.

10$:	BR	COMARM			; Queue up the remote reads.
;
;	If in command mode, clear the remote typeahead buffer or else
;	additional notifiation AST's won't be delevered when we return
;	to the virtual terminal mode.
;
100$:	DIR$	#CLRCOM			; Clear the typeahead buffer.
	ASTX$S				; Exit the AST.

	.SBTTL	COMARM - Arm The Remote Reads.
;+
;
; COMARM - Arm the remote reads.
;
; This routine is used to queue the read requests to the remote terminal.
; For each read, a marktime is also scheduled.  When all marktimes have
; expired, this means that little or no data has arrived on the remote
; port and all queued reads get killed.  The read AST routine will then
; copy any characters which have arrived to the main buffer where they
; will be output to the local terminal by the mainline routine.
;
;	Note:  This routine is called at AST level.
;
; Inputs:
;	2(SP) = The saved R5.
;	4(SP) = The saved R4.
;
; Outputs:
;	All registers are preserved.
;
;-
	.ENABL	LSB

COMARM:	TST	ERRFLG			; Was there a remote error ?
	BNE	100$			; If NE, yes (no QIO's).
	TST	COMFRE			; Are all the buffers in use ?
	BLE	100$			; If LE, yes.
	TST	COMNUM			; Already queued enough reads ?
	BLE	100$			; If LE, yes.

QIOCOM:	MOV	LSTCOM,R4		; Set address of next buffer.
	MOV	R4,R5			; Copy starting buffer address.
	ADD	#4,R5			; Point past I/O status block.
	QIO$S	#IO.RAL,#lun.ti,,,R4,#REMAST,<R5,COMQIO>
	BCS	90$			; If CS, the directive failed.
	INC	QIOCNT			; Count number of remote QIO's.
	DEC	COMFRE			; Adjust the free buffer count.
	CMP	COMFRE,MINFRE		; Low water free buffer mark ?
	BHIS	10$			; If HIS, no.
	MOV	COMFRE,MINFRE		; Set new low water buffer mark.
10$:	DEC	COMNUM			; Adjust the reads queued count.
	MRKT$S	,FILTIM,#TICKS,#TIMCOM 	; Set the timer for buffer fill.
	BCS	90$			; If CS, the directive failed.
	INC	COMMKT			; Count number of timers queued.
	MOV	R4,LSTCOM		; Copy the current buffer address.
	ADD	#COMCHR+4,LSTCOM	; Point to the next free buffer.
	CMP	LSTCOM,#ENDCOM		; Are we at end of buffer area ?
	BNE	20$			; If NE, no.
	MOV	#SRTCOM,LSTCOM		; Yes, point to starting area.
20$:	BR	COMARM			; Try to arm another read.

90$:	CALL	CHKDIR			; Report the directive error.

100$:	MOV	(SP)+,R5		; Restore R4
	MOV	(SP)+,R4		;       and R5.
	SETF$S	#ef.wait		; Wakeup mainline for output.
	ASTX$S				; And exit the AST.

	.DSABL	LSB

	.SBTTL	TIMCOM - Remote Marktime AST Routine.
;+
;
; TIMCOM - Remote Marktime AST routine.
;
; This routine is entered when the marktime issued after a read to the
; remote expires.  After all marktimes have expired, the remote I/O is
; killed and REMAST is entered with the bytes received from the remote.
;
;-
TIMCOM:	TST	EXFLG			; EXIT FLAG SET ?
	BNE	10$			; IF NE, YES (KILL I/O)
	TST	INTFLG			; Exiting the connect code ?
	BEQ	20$			; IF EQ, NO (CONTINUE)
;
; If exiting the connect code or exiting the program, cancel marktimes,
; and kill remote I/O so KERMIT commands will not get screwed.
;
10$:	CMKT$S	,#TIMCOM		; Cancel any remote marktimes.
	CLR	COMMKT			; Initialize the marktime count.
	BR	30$			; And kill the remote I/O.
20$:	DEC	COMMKT			; Adjust the marktime count.
	BNE	40$			; If NE, more timers queued.
30$:	DIR$	#KILREM			; Else, kill the remote I/O.
	INC	COMKIL			; Adjust kill operation count.
40$:	TST	(SP)+			; Remove event flag number.
	ASTX$S				; And exit the AST.

	.SBTTL	REMAST - Remote Read AST Routine.
;+
;
; REMAST - Remote read AST completion routine.
;
; This routine is entered when a remote read completes.  Its function
; is to copy any characters received to the main buffer, wakeup the
; mainline to start output to the local terminal, and to re-issue the
; read if there have been no errors and something was read.
;
; Inputs:
;	(SP) = The I/O status block address.
;
; Outputs:
;	All registers are preserved.
;
;-
REMAST:	INC	COMFRE			; Adjust free buffer count.
	TST	EXFLG			; Are we exiting the program ?
	BNE	10$			; If NE, yes.
	TST	INTFLG			; Exiting the connect code ?
	BEQ	20$			; If EQ, no (continue ...)
10$:	TST	(SP)+			; Remove status block address.
	ASTX$S				; And exit the AST.

20$:	MOV	R4,-(SP)		; Save
	MOV	R5,-(SP)		;    some
	MOV	R1,-(SP)		;     registers
	MOV	R3,-(SP)		;      on the stack.
	MOV	COMPTR,R1		; Copy the buffer pointer.
	MOV	COMCNT,R3		; And the buffer byte count.
	MOV	10(SP),R4		; Copy status block address.
	MOV	R4,R5			; Copy this address,
	ADD	#4,R5			; and point to the data area.
	TSTB	(R4)			; Was there any errors ?
	BPL	50$			; If PL, no.
	CMPB	#IE.ABO,(R4)		; Was the read killed ?
	BNE	40$			; If NE, no.
	INC	COMABO			; Adjust aborted reads count.
;
;	When the reads get killed, only the current outstanding read
;	has an AST delivered.  All other reads which are queued, get
;	killed, but the specified AST is not delevered.  Therefore,
;	we must set all buffers as free when abort is detected.
;
	MOV	#COMNBF,COMFRE		; Yes, set all buffers free.
;
;	Sometimes when our read is killed, there is a very large byte
;	count in the I/O status block.  Just another RSX-11M mystery.
;
	CMP	#COMCHR,2(R4)		; Is byte count too large ?
	BLO	80$			; If LO, yes (don't use).
	BR	50$			; Don't report this error.

40$:	MOV	(R4),RIOSB		; Copy the I/O error code.
	CALL	CRIOSB			; Write the error message.
	MOV	#-1,ERRFLG		; Show there was an error.

50$:	MOV	2(R4),R4		; Copy the byte count.
	BEQ	85$			; If EQ, nothing was read.
	CMP	R4,MAXBC		; Is this the MAX so far ?
	BLO	55$			; If LO, no.
	MOV	R4,MAXBC		; Yes, save for status.

55$:	ADD	R4,RCHIN+2		; Count the characters read.
	ADC	RCHIN			; Add in the carry (if any).
	CMP	R4,COMQIO		; Is this a full buffer ?
	BNE	60$			; If NE, no.
	INC	COMFUL			; Adjust full buffer count.

60$:	tst	con8bit			; Should we pass eight bits ?
	bne	65$			; If NE, yes.
	bicb	#200,(r5)		; No, so clear the high bit.

65$:	MOVB	(R5)+,(R1)+		; Copy bytes to main buffer.
	INC	R3			; Adjust the byte count.
	CMP	R1,#COMEND		; At end of main buffer ?
	BNE	70$			; If NE, no.
	MOV	#COMBUF,R1		; Yes, reset to beginning.

70$:	SOB	R4,60$			; Loop until we're done.
	CMP	R3,#COMCTS		; Getting near buffer overflow ?
	BLO	80$			; If LO, no.
	TST	COMCTL			; Did we already send XOFF ?
	BNE	80$			; If NE, yes.
	DIR$	#XOFREM			; Send as XOFF to the remote.
	INC	COMCTL			; Show we sent the XOFF.
	INC	PGMXOF			; Adjust program XOFF count.

80$:	MOV	10(SP),R4		; Copy the status block address.
	MOV	R1,COMPTR		; Save the new buffer pointer
	MOV	R3,COMCNT		;   and the main buffer count.
	TST	ERRFLG			; Was there a remote error ?
	BEQ	90$			; If EQ, no (continue ...)
	CMPB	#IE.DNR,(R4)		; Was error "Device Not Ready" ?
	BNE	90$			; If NE, no (queue next read).

85$:	MOV	(SP)+,R3		; Restore
	MOV	(SP)+,R1		;    all
	MOV	(SP)+,R5		;     saved
	MOV	(SP)+,R4		;      registers.
	TST	(SP)+			; Remove status block address.
	SETF$S	#ef.wait		; Wakeup mainline for output.
	ASTX$S				; And exit the AST.

90$:	MOV	(SP)+,R3		; Restore R3
	MOV	(SP)+,R1		;        and R1.
	MOV	R4,R5			; Copy the status block address.
	ADD	#4,R5			; Point to the data buffer.
	MOV	2(SP),4(SP)		; Move R4 down on the stack.
	MOV	(SP)+,(SP)		; Move R5 down and clean stack.
	JMP	QIOCOM			; Now go queue another read.

	.SBTTL	BUFOUT - Write Buffer to Device.
;+
;
; BUFOUT - Write a buffer to a device.
;
; Inputs:
;	BUFADR = The ending address to write.
;	BUFSRT = The starting buffer address.
;	BUFEND = The ending buffer address.
;	BUFLUN = The device LUN to write to.
;	BUFLEN = The number of bytes to write.
;
; Outputs:
;	All registers are preserved.
;
;-
BUFOUT:	CALL	$SAVAL			; Save all registers.
	TST	EXFLG			; Is the exit flag set ?
	BNE	20$			; If NE, yes.
	TST	INTFLG			; Exiting the connect code ?
	BNE	20$			; If NE, yes.
	MOV	BUFLUN,R0		; Copy the LUN to write to.
	MOV	BUFADR,R2		; Copy the ending address.
	SUB	BUFLEN,R2		; Calculate starting address.
	CMP	R2,BUFSRT		; Does buffer wrap around ?
	BLT	10$			; If LT, yes.

;	Write the buffer to the log file and the terminal.

	MOV	BUFLEN,R3		; Copy the byte count.
	CALL	WRTLOG			; Write it to the logfile,
	QIOW$S	#IO.WAL,R0,#ef.sync,,#XIOSB,,<R2,R3,#0> ; & terminal.
	CALL	CHKXIO			; Check/report any errors.
	BR	20$			; Use common return.

;	The buffer wraps around, use two QIO's to write buffer.

10$:	MOV	BUFADR,R3		; Copy the ending address.
	SUB	BUFSRT,R3		; Calculate bytes from start.
	MOV	R3,-(SP)		; Save beginning byte count.
	MOV	BUFLEN,R3		; Copy # of bytes to write.
	SUB	(SP),R3			; Minus chars at beginning.
	MOV	BUFEND,R2		; Copy the ending address.
	SUB	R3,R2			; Calculate starting address.

;	Write the buffer to the log file and the terminal.

	CALL	WRTLOG			; Write it to the logfile,
	QIOW$S	#IO.WAL,R0,#ef.sync,,#XIOSB,,<R2,R3,#0> ; & terminal.
	CALL	CHKXIO			; Check/report any errors.
	MOV	(SP)+,R3		; Restore beginning byte count.
	BEQ	20$			; If EQ, nothing to write.
	CMPB	XIOSB,#IE.ABO		; Was the first QIO aborted ?
	BEQ	20$			; If EQ, yes (no 2nd QIO).
	TST	EXFLG			; Is the exit flag set ?
	BNE	20$			; If NE, yes.
	TST	INTFLG			; Exiting the connect code ?
	BNE	20$			; If NE, yes.

;	Write the buffer to the log file and the terminal.

	MOV	BUFSRT,R2		; Copy the starting address.
	CALL	WRTLOG			; Write it to the logfile,
	QIOW$S	#IO.WAL,R0,#ef.sync,,#XIOSB,,<R2,R3,#0> ; & terminal.
	CALL	CHKXIO			; Check/report any errors.

20$:	RETURN

	.SBTTL	CANCEL - Cancel Local and Remote I/O.
;+
;
; CANCEL - Cancel the local and remote I/O.
;
; Be careful if calling this routine from AST level since outstanding
; I/O will cause us to hang since other I/O can't complete.
;
;-
CANCEL:	DIR$	#KILLOC			; Kill I/O on local port.
	BCS	10$			; If CS, don't wait.
	WTSE$S	#ef.kill		; Wait for the kill I/O.

10$:	DIR$	#KILREM			; Kill I/O on remote port.
	BCS	20$			; If CS, don't wait.
	WTSE$S	#ef.kill		; Wait for the kill I/O.

20$:	RETURN

	.SBTTL	CHKDIR - CHECK FOR DIRECTIVE ERROR
	.SBTTL	CHKLIO - CHECK FOR LOCAL I/O ERROR
	.SBTTL	CHKRIO - CHECK FOR REMOTE I/O ERROR
;+
;
; CHKDIR - Check for a directive error.
; CHKLIO - Check for local I/O error code.
; CHKRIO - Check for remote I/O error code.
;
; These routines are called to check for QIO errors for both
; the local terminal and the remote terminal port.
;
; Inputs:
;	$DSW, LIOSB, RIOSB, or XIOSB status blocks.
;
; Outputs:
;	C bit clear/set = success/failure.
;
;	All registers are preserved.
;
;-
	.ENABL	LSB

CHKDIR:	JSR	R2,$SAVVR		; Save R0 - R2.
	BCC	100$			; If CC, then success.
	MOV	$DSW,R0			; Else, copy the error code.
	BR	20$			; And use common code.

CHKXIO:	BCS	CHKDIR			; If CS, directive error.
	JSR	R2,$SAVVR		; Save R0 - R2.
	MOVB	XIOSB,R0		; Copy the I/O code.
	BPL	100$			; If PL, then success.
	BR	10$			; Else, use common code.

CHKLIO:	BCS	CHKDIR			; If CS, directive error.
	JSR	R2,$SAVVR		; Save R0 - R2.
	MOVB	LIOSB,R0		; Copy the I/O code.
	BPL	100$			; If PL, then success.
	BR	10$			; Continue ...

CHKRIO:	BCS	CHKDIR			; If CS, directive error.
CRIOSB:	JSR	R2,$SAVVR		; Save R0 - R2.
	MOVB	RIOSB,R0		; Copy the I/O code.
	BPL	100$			; If PL, then success.

10$:	CMPB	#IE.ABO,R0		; Was the I/O killed ?
	BEQ	100$			; If EQ, yes (expected).

20$:	CALL	CHKERR			; Check/write error message.
;	SEC				; Show we've had an error.
	RETURN				; Return status from CHKERR.

100$:	CLC				; Success or non-fatal error.
	RETURN

	.DSABL	LSB	

	.SBTTL	CHKERR - Check/Write An Error Message.
;+
;
; CHKERR - Check and write an error message.
;
; Thie routine checks a table for allowable errors and if the error
; code isn't found in the table, the error is reported.
;
; Inputs:
;	R0 = The error code.
;
; Outputs:
;	C bit clear/set = Allowable/Unacceptable Error.
;
;	All registers are preserved.
;
;-
CHKERR:	mov	r5	,-(sp)		; insure this is saved
	movb	r0,r5			; Copy the error code.
	scan	r5	,#$errlst	; allowable error code ?
	tst	r0			; well
	bne	180$			; yes, let it through
	neg	r5			; make > 0 for direrr macro
	direrr	r5			; simple
	sec				; failure, exit to command level
	br	190$			; bye
180$:	clc				; success, stay in connect code
190$:	mov	(sp)+	,r5		; restore old r0 please
	return

	.save
	.psect	$PDATA	,D
$errlst:.byte	IE.BCC	,IE.DAO	,IE.IES	,IE.NOD	,IE.PES	,IE.VER	,IE.ABO ,0
	.even
	.restore

	global	<conesc, ttcons, ttname, lun.co, lun.ti>

	.SBTTL	WRTLOG - Write I/O to a log file.
;+
;
; WRTLOG - Write I/O to a log file.
;
; This routine is used to write output from the remote system to
; a log file (if enabled).
;
; Inputs:
;	R2 = The buffer address.
;	R3 = The buffer byte count.
;
; Outputs:
;	All registers are preserved.
;
;-
WRTLOG:	call	$saval			; Save all registers.
	bit	#log$co	,trace		; is this enabled ?
	beq	100$			; no
	bit	#log$op	,trace		; is it open
	beq	100$			; no

10$:	movb	(r2)+,r0		; Copy the next character.
	mov	#lun.lo	,r1		; Set the unit number.
	call	putcr0			; Write it to the log file.
	sob	r3,10$			; Write the next character.

100$:	return


	global	<lun.lo, putcr0, trace, conflow>

	.SBTTL	REMRES - Restore Remote Characteristics.
;+
;
; REMRES - Restore the remote characteristics.
;
; Restore the remote characteristics and detach the terminal.
;
;-
REMRES:	DIR$	#KILREM			; Kill any I/O on remote LUN.
	WTSE$S	#ef.kill		; Wait for the kill to complete.
	DIR$	#RESREM			; Yes, reset the characteristics.
	DIR$	#RESDLU			; Reset the modem characteristics.
	DIR$	#DETREM			; Detach the remote terminal.
100$:	RETURN

	.SBTTL	RSXABO - Process an ABORT AST.
;+
;
; RSXABO - Process an ABORT AST.
;
; This routine is called as the result of KERMIT being ABOrted.  The
; first time we are entered we simply kill all I/O and try to wakeup
; the mainline to actually exit the program.  We also start a timer
; which if it expires, will simply exit the program so we don't hang.
; We don't do too much work here because if we stay at AST level, we
; prevent other AST's from completing which may hang the program.
;
;
; Inputs:
;	(SP)  = Number of bytes to remove from the stack.
;	2(SP) = The reason for being aborted.
;
;-
RSXABO:	ADD	(SP),SP			; Remove abort information.
	SREX$S				; Remove abort AST routine.
	CMKT$S				; Cancel outstanding timers.
	SETF$S	#ef.time		; Set the delay event flag.
	DIR$	#KILLOC			; Kill I/O on local port.
	DIR$	#KILREM			; Kill I/O on remote port.
	SETF$S	#ef.wait		; Wakeup the mainline.
	MOV	#-1,EXFLG		; Tell the mainline to exit.
	MRKT$S	,#5,#SECNDS,#ABOTMO	; Initiate an abort timer.
	ASTX$S				; Exit the AST.
;+
;
; This routine is entered when the marktime issued in the abort AST
; routine expires.  If this timer expires, this means the mainline
; hasn't detected our exit request so we cancel all I/O, reset the
; terminal characteristics, and then exit the program.
;
;-
ABOTMO:	TST	(SP)+			; Remove marktime parameter.
EXISYS:	CALL	CANCEL			; Cancel all outstanding I/O.
	DIR$	#RESLOC			; Reset local characteristics.
	CALL	REMRES			; Restore/detach remote port.
	DIR$	#HANGUP			; Ensure the modem is hungup.
	EXIT$S				; And exit to the system ...


	.sbttl	concmd	terminal emulation escape commands
	.enabl	lsb

concmd::save	<r1>
	bicb	#^C177	,r1
	scan	r1,#200$		; look for a match here
	tst	r0			; if no match, return 0
	beq	100$			; ok
	asl	r0			; word offsets
	jsr	pc	,@210$(r0)	; dispatch to the correct routine
	tst	r0			; if not set then set to -1
	bne	100$			; already set
	dec	r0			; set to -1
100$:	unsave	<r1>			; pop r1 and exit
	return


	.save
	.psect	$PDATA	,D

200$:	.byte	'C&137	,'c!40		; drop connection ctrl \ C
	.byte	'I&137	,'i!40		; init the line
	.byte	'Q&137	,'q!40		; quit logging but leave file open
	.byte	'R&137	,'r!40		; resume logging if file is open
	.byte	'X&137	,'X!40		; control Q and then thats all
	.byte	'B&137	,'b!40
	.byte	'?	,177		; help, rub for send break
	.byte	'H&137	,'h!40
	.byte	0
	.even

210$:	.word	con.$			; unknown escape command
	.word	con.c	,con.c		; drop connection
	.word	con.i	,con.i		; get modems attention
	.word	con.q	,con.q		; turn console logging off
	.word	con.r	,con.r		; turn it back on please
	.word	con.x	,con.x		; send XON
	.word	con.br	,con.br		; break
	.word	con.hl	,con.br		; print out commands
	.word	con.hl	,con.hl		; help

$bell:	.byte	'G&37
$xon:	.byte	'Q&37
$null2:	.byte	0,0
	.even
	.restore
	.dsabl	lsb


con.$:	calls	binwri	,<#$bell,#1,#lun.co>	; beep at user
	clr	r0
	return



con.c:	mov	#1	,r0		; set flag to exit connect code
	return				; simple


con.i:	calls	ttydtr	,<#ttname>	; try to force DTR up on the line
	clr	r0
	return


con.q:	bic	#log$co	,trace		; turn off console logging
	clr	r0
	return


con.r:	bit	#log$op	,trace		; if the file is open do it
	beq	100$			; no
	bis	#log$co	,trace		; yes, enable this
100$:	clr	r0
	return


con.x:	calls	binwri	,<#$xon,#1,#lun.ti>; insure a control Q goes down
	calls	ttxon	,<#ttname>
	Call	getprv			; /60/ restore privs dropped by TTXON
	clr	r0
	return


con.br:	save	<r1,r2>			; save scratch registers please
	clr	-(sp)			; clear a sf.gmc buffer out
	clr	-(sp)			; ditto
10$:	mov	sp	,r2		; and a pointer to it please
	movb	#tc.xsp	,@r2		; we want the current speed settings
	movb	#tc.rsp	,2(r2)		; ditto
	QIOW$S	#SF.GMC,#LUN.TI,,,,,<r2,#4>
	movb	1(r2)	,r1		; save the old speed setting please
	mov	sp	,r2		; reset the buffer address please
	movb	#tc.xsp	,(r2)+		; stuff xmitter change code in
	movb	#s.300	,(r2)+		; and the desired speed now
	movb	#tc.rsp	,(r2)+		; stuff receiver change code in
	movb	#s.300	,(r2)+		; and the desired speed now
	mov	sp	,r2		; point back to the buffer now
	QIOW$S	#SF.SMC,#LUN.TI,,,,,<r2,#4>
	QIOW$S	#IO.WAL,#LUN.TI,,,,,<#$null2,#2>
	mov	sp	,r2		; reset the buffer address please
	movb	#tc.xsp	,(r2)+		; stuff xmitter change code in
	movb	r1	,(r2)+		; and the old speed now
	movb	#tc.rsp	,(r2)+		; stuff receiver change code in
	movb	r1	,(r2)+		; and the old speed now
	mov	sp	,r2		; point back to the buffer now
	QIOW$S	#SF.SMC,#LUN.TI,,,,,<r2,#4>
100$:	cmp	(sp)+	,(sp)+		; pop local buffer and exit
	clr	r0			; no errors are ever returned
	unsave	<r2,r1>			; pop local registers and exit
	return				; bye






con.hl::strlen	#htxt
	calls	binwri	,<#htxt,r0,#lun.co>
	clr	r0
	return

	.save
	.psect	$PDATA	,D

htxt:	.ascii	/B	Try to send a  break to the  remote/<cr><lf>
	.ascii	/C	Connect back to the local Kermit-11/<cr><lf>
	.ascii	/I	Drop  and raise DTR (for RSTS only)/<cr><lf>
	.ascii	/Q	Quit console logging.   See SET LOG/<cr><lf>
	.ascii	/R	Resume console logging. See SET LOG/<cr><lf>
	.ascii	/X	Send XON and cancel any active XONs/<cr><lf>
	.asciz	/RUBOUT	Try to fake a break to the remote/<cr><lf>
	.ascii	/?	Print this message/<cr><lf>
	.byte	0
	.even
	.restore

	.END
