	.sbttl	K11ECO	New RSTS/E connect code
	.psect
	.ident	/2.50.1/

	.include	/SY:[1,2]COMMON.MAC/


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

	.enabl	gbl
	
;	Copyright (C) 1986 Change Software, Inc
;
;	02-Apr-86  14:58:29  Brian Nelson
;
;	Warning: This uses binary I/O, thus you never want to
;
;	(1) Do I/O to channel zero
;	(2) Timeout on a terminal read
;
;	Either one of the above events will cause binary mode
;	to go away. We can't use multiple delimiters here due
;	to the terminal drivers processing of C1 controls.
;
;	This is tested only on RSTS/E 9.1 and Field Test 9.2
;	It should work fine on 8.0-07, but no gaurentees.


	.psect	concod	,ro,i,lcl,rel,con
	.psect	condat	,rw,d,lcl,rel,con


	.macro	READTT	buffer,size=#80.,lun,time=#0
	mov	time	,-(sp)
	mov	lun	,-(sp)
	mov	size	,-(sp)
	mov	buffer	,-(sp)
	call	$READTT
	.endm	READTT


	.macro	WRITETT buffer,size=#0,lun
	mov	lun	,-(sp)
	mov	size	,-(sp)
	mov	buffer	,-(sp)
	call	$WRITETT
	.endm	WRITETT
	
	.macro	fqcopy	dst	,src
	mov	src	,-(sp)
	mov	dst	,-(sp)
	call	$fqcopy
	.endm	fqcopy


	.macro	CLRFQB
	call	$clrfq
	.globl	$clrfq
	.endm	CLRFQB

	.macro	CLRXRB
	call	$clrxr
	.globl	$clrxr
	.endm	CLRXRB


	NODATA	==	13.		; no data for terminal read
	DETKEY	==	27.		; i/o to detached tt line

	.psect	condat

	.even
xksdon:	.blkw	1			; Remote terminal set done
ttsdon:	.blkw	1			; Local terminal set done
ioseen:	.blkw	1			; Some input was seen somewhere
ttio:	.blkw	1			; Console read worked
xkio:	.blkw	1			; Remote read worked
eseen:	.blkw	1			; Control \ happened at console
savtt:	.blkb	40			; Save local terminal chars
savxk:	.blkb	40			; Save outgoing line chars
bufqxk:	.blkw	1			; Connect line buffer quota
ttunit:	.blkw	1			; Our console terminal unit
xkunit:	.blkw	1			; Connected line's unit number
v9flag:	.blkw	1			; Iff version 9.x or later

XKSIZE	=	600			; Large buffers for remote reads
xkbuff:	.blkb	XKSIZE+2		; Buffer for connected line
ttbuff:	.blkb	80.			; Buffer for console terminal


	.psect	concod
	.enabl	lsb

doconn::call	init			; Startup
	bcs	100$			; Oops
	call	ttinit			; Save terminal characteristics
	bcs	90$			; Die
					;
10$:	mov	#ttbuff	,r4		; Pointer to local term buffer
	mov	#xkbuff	,r5		; Pointer to remotes buffers.
	READTT	buffer=r4,lun=#LUN.CO,size=#1 ; Look for data on LOCAL term
	tst	r0			; Was there anything there?
	bne	50$			; No
					;
	mov	sp	,ioseen		; Yes, flag that we saw some I/O
	movb	@r4	,r0		; Check for console commands
	bicb	#^C177	,r0		; Insure no parity set.
	cmpb	r0	,conesc		; Escape command prefix ?
	bne	20$			; No
	READTT	buffer=r4,lun=#LUN.CO,size=#1,time=#20
	tst	r0			; Successfull
	bne	50$			; No, ignore the data
	movb	@r4	,r0		; Check for console commands
	bicb	#^C177	,r0		; Insure no parity set.
	cmpb	r0	,conesc		; Escape command prefix ?
	beq	20$			; Yes, dump the character now.
	call	concmd			; Check for console command.
	br	80$			; And skip the next remote read

20$:	tst	duplex			; Is this a half duplex line?
	beq	25$			; No, then don't echo the data
	WRITETT	buffer=r4,lun=#LUN.CO,size=#1
25$:	mov	r4	,r2		; Insure parity is setup now.
	mov	r1	,r3		; The byte count next
	beq	50$			; Nothing there ?
30$:	setpar	@r2	,(r2)+		; Set parity if need be.
	sob	r3	,30$		; Next character please.
	WRITETT	buffer=r4,lun=#LUN.XK,size=#1

50$:	READTT	buffer=r5,lun=#LUN.XK,size=#XKSIZE
	tst	r0			; Did the remote read succeed?
	beq	60$			; Yes, dump to local terminal.
	call	iocheck			; No, check for allowable errors
	br	80$			; And exit with C set for FATAL
60$:	mov	sp	,ioseen		; Had some input, flag no SLEEP
	mov	r5	,-(sp)		; Now get rid of XOFF characters
	mov	r1	,r0		; Save buffer address and byte count
	beq	75$			; Be SURE that byte count is nonzero.
65$:	cmpb	(r5)	,#'S&37		; If this is an off then replace it
	bne	66$			; will a NULL character please.
	clrb	(r5)			; Was an XOFF, so stuff a NULL in.
66$:	cmpb	parity	,#PAR$NONE	; Parity up?
	beq	70$			; No
	bicb	#200	,(r5)		; Yes, dump it
70$:	inc	r5			; Next please
	sob	r0	,65$		; Keep going
75$:	mov	(sp)+	,r5		; Restore the buffer pointer.
	WRITETT	buffer=r5,lun=#LUN.CO,size=r1
	call	dumplog			; May need to dump to log file
	clc				; Success flag

80$:	bcs	90$			; If set, it's time to EXIT
	tst	ioseen			; Not set, do we really want to
	bne	85$			; take a short nap ? If ne, no.
	CLRXRB				; Yes, insure future rsts/e's ok
	mov	#1	,XRB+0		; One second sleep
	.SLEEP				; Do it
85$:	clr	ioseen			; No more i/o has been seen
	br	10$			; Next please

90$:	call	ttrst			; Restore terminal chars
100$:	return

	.dsabl	lsb

	.sbttl	misc support routines
	.enabl	lsb


init:	clr	eseen			; No escape seen
	clr	xkio			; No remote I/O seen
	clr	ttio			; No local I/O seen
	clr	ioseen			; No I/O at all happened
	clr	ttsdon			; No terminal settings done yet
	clr	xksdon			; No terminal settings done yet
	CLRFQB				; Zap the firqb please
	movb	#UU.PRV	,FIRQB+FQFUN	; Execute a V9 only call so we
	.UUO				; can see if this is still v8
	clr	v9flag			; Assume v8
	tstb	FIRQB			; Did this call succeed?
	bne	10$			; No
	mov	sp	,v9flag		; Yes, this is 9.0 or later
10$:	tstb	ttname			; Any line previously defined?
	bne	30$			; Yes
	tstb	@argbuf			; Any name on the command line?
	bne	20$			; Yes
	MESSAGE	<Please use the SET LINE command>,cr
	jmp	90$			; Error exit
20$:	strcpy	#ttname	,argbuf		; No name, copy from command line
30$:	CLRFQB				; Get our console terminal unit #
	movb	#UU.SYS	,FIRQB+FQFUN	; Do the systat call now
	.UUO				; Simple
	movb	FIRQB+5	,ttunit		; Save our terminal unit number
	mov	#XRB	,r3		; Get the unit number next
	mov	#ttname	,r2		; Load up the XRB
	CLRFQB				; Insure no odd defaults around
	CLRXRB				; Ditto
	STRLEN	r2			; Get the length of the device name
	mov	r0	,(r3)+		; Copy the length of the name
	mov	r0	,(r3)+		; ...Copy the length of the name
	mov	r2	,(r3)+		; Copy the device name address
	.FSS				; Do a filename string scan now
	movb	FIRQB	,r0		; Successfull?
	bne	80$			; No, exit
	movb	FIRQB+FQDEVN,xkunit	; Save the connected line unit#
	bit	#20000!40000,XRB+10	; Did we REALLY get a devicename?
	bne	40$			; Yes
	movb	#6	,r0		; No, preload bad device name
	br	80$			; And exit with error MESSAGE
40$:	cmpb	xkunit	,ttunit		; Are they one and the same ?
	bne	50$			; No, it's ok
	MESSAGE	<Connected line and console line are the same unit>,cr
	br	90$			; Error if so
50$:	tst	doallo			; /58/ Really assign it?
	beq	55$			; /58/ No
	CLRFQB				; Insure outgoing line is assigned
	movb	#UU.ASS	,FIRQB+FQFUN	; Subfunction code
	mov	#"KB	,FIRQB+FQDEV	; KB
	movb	xkunit	,FIRQB+FQDEVN+0	; Unit number
	movb	#377	,FIRQB+FQDEVN+1	; Unit number is real
	.UUO				; Simple
55$:	CALLS	ttspeed	,<#ttname>	; Get interface speed
	mov	r0	,r2		; Save the speed
	MESSAGE	<Connecting to: >	; Dump the data
	print	#ttname			; And the connect line name
	tst	r2			; Any speed info available?
	beq	60$			; No
	MESSAGE	< Speed: >		; Yes, dump the speed
	decout	r2			; Simple
	MESSAGE				; A crlf
	MESSAGE	<Type Control >		; How to return to the local kermit
	clr	-(sp)			; ....
	bisb	conesc	,(sp)		; The current control escape char.
	add	#100	,(sp)		; Convert to printable representation
	mov	sp	,r0		; .....
	print	r0			; .....
	MESSAGE	<C to return to the local Kermit-11>,cr ; All done.
	tst	(sp)+			; Pop this
60$:	MESSAGE				; A final CR/LF
					; 
70$:	clc				; Success
	br	100$			; Exit

80$:	direrr	r0			; Print RSTS/E error text
90$:	sec				; Failure
100$:	return				; Exit


	.dsabl	lsb


	.sbttl	save/set/restore terminal characteristics
	.enabl	lsb

ttinit:	movb	#377	,r0		; Console terminal first
	call	200$			; Get term chars, part 0
	FQCOPY	#savtt+0,#FIRQB		; Save the characteristics
	movb	xkunit	,r0		; Now for the CONNECTED terminal
	call	200$			; Ditto...
	FQCOPY	#savxk+0,#FIRQB		; Copy this also
	tst	v9flag			; Will the second part of the
	beq	10$			; get terminal chars succeed?
	clrb	bufqxk			; Clear buffer quota outz
	CLRFQB				; Yes, read the buffer quota
	movb	#UU.TRM	,FIRQB+FQFUN	; Again ...
	incb	FIRQB+4			; Subfunction = 1
	movb	xkunit	,FIRQB+5	; Unit number of connected line
	.UUO				; Read current buffer quota
	tstb	FIRQB			; Success?
	bne	10$			; No, ignore it
	movb	FIRQB+27,bufqxk		; Save it
	CLRFQB				; Clear again
	movb	#UU.TRM	,FIRQB+FQFUN	; ....
	incb	FIRQB+4			; Subfunction = 1
	movb	xkunit	,FIRQB+5	; Unit number
..CBFQ	== . + 2			;
	movb	#<XKSIZE*2>/40,FIRQB+27	; Buffer twice our internal size
	.UUO				; Do it ...
10$:	movb	#377	,r0		; Now set chars at last
	mov	#LUN.CO	,r1		; Channel number for open
	call	210$			; .....
	bcs	110$			; It failed?
	inc	ttsdon			; Set and open done for local term
	movb	xkunit	,r0		; Again please
	mov	#LUN.XK	,r1		; Channel number for open
	call	210$			; .....
	bcs	110$			; Save success flag
	inc	xksdon			; Set and open done for remote term
100$:	clc				; Say success and exit
110$:	return				; At last


200$:	CLRFQB				; Insure FIRQB is cleared out
	movb	#UU.TRM	,FIRQB+FQFUN	; Terminal call today.
	movb	r0	,FIRQB+5	; Console terminal this time
	.UUO				; Simple
	clrb	FIRQB+4			; Insure this field is (v8/v9)
	bisb	FIRQB+36,FIRQB+20	; Get 8bit setting in correct loc.
	clr	FIRQB+36		; And clear this field out
	return				; Exit

210$:	CLRFQB				; Clear FIRQB again....
	movb	#UU.TRM	,FIRQB+FQFUN	; Terminal call today.
	movb	r0	,FIRQB+5	; Console terminal this time
	movb	#377	,FIRQB+12	; XON
	movb	#377	,FIRQB+35	; GAG
	movb	#31	,FIRQB+20	; 8bit and NoParity
	movb	#200	,FIRQB+11	; LC output
	movb	#377	,FIRQB+15	; LC input
	movb	#377	,FIRQB+23	; No Uparrow
	movb	#200	,FIRQB+30	; No delimiters please
	.UUO				; Simple
	cmpb	r0	,#377		; Console terminal?
	bne	215$			; No
	movb	ttunit	,r0		; Yes, insure valid unit number
					;
215$:	CLRXRB				; Clear the XRB
	mov	#3	,XRB+0		; Function (disable echoing)
	mov	r0	,XRB+2		; Terminal number
	movb	#TTYHND	,XRB+7		; The device driver index next
	.SPEC				; Do it.
					;
	CLRFQB				; Now open the terminal up
	movb	#OPNFQ	,FIRQB+FQFUN	; Function code
	movb	r1	,FIRQB+FQFIL	; Channel number
	aslb	FIRQB+FQFIL		; Times two, of course.
	mov	#100001	,FIRQB+FQMODE	; Binary mode
	mov	#"KB	,FIRQB+FQDEV	; Device type
	movb	r0	,FIRQB+FQDEVN+0	; Unit
	movb	#377	,FIRQB+FQDEVN+1	; It's for real
	CALFIP				; Open it up and exit
	movb	FIRQB	,r0		; Did the open succeed?
	beq	220$			; Yes
	MESSAGE	<Failure to open terminal line - >
	direrr	r0			; No, an error MESSAGE please
	sec				; Exit
	return				; Bye
220$:	clc				; Success
	return				; Exit

	.dsabl	lsb



	.sbttl	restore terminals

	.iif ndf, TTYHND, TTYHND = 2


ttrst:	CLRFQB				; Close channels up please
	movb	#CLSFQ	,FIRQB+FQFUN	; Close a channel function
	movb	#LUN.XK*2,FIRQB+FQFIL	; Channel number times 2
	CALFIP				; Simple
	CLRFQB				; Insure FIRQB is clear again
	movb	#CLSFQ	,FIRQB+FQFUN	; Close a channel function
	movb	#LUN.CO*2,FIRQB+FQFIL	; Channel number times 2
	CALFIP				; Simple
	CLRXRB				; Reset echoing on console term
	mov	#2	,XRB+0		; Function (enable echoing)
	mov	ttunit	,XRB+2		; Terminal number
	movb	#TTYHND	,XRB+7		; The device driver index next
	.SPEC				; Do it.

	tst	ttsdon			; Did we ever set this?
	beq	10$			; No
	FQCOPY	#FIRQB	,#savtt+0	; Restore console terminal
	movb	#UU.TRM	,FIRQB+FQFUN	; Function code
	clrb	FIRQB+4			; Insure cleared for v9..x
	movb	#377	,FIRQB+5	; Console
	.UUO				; Simple
10$:	tst	xksdon			; Did we set the remote up?
	beq	100$			; No
	FQCOPY	#FIRQB	,#savxk+0	; Restore connected terminal
	movb	#UU.TRM	,FIRQB+FQFUN	; Function code
	clrb	FIRQB+4			; Insure cleared for v9..x
	movb	xkunit	,FIRQB+5	; Console
	.UUO				; Simple
	tst	v9flag			; Version 9 or later?
	beq	100$			; No
	CLRFQB				; Yes, restore buffer quota
	movb	#UU.TRM	,FIRQB+FQFUN	; Function
	incb	FIRQB+4			; Subfunction = 1
	movb	xkunit	,FIRQB+5	; Unit number
	movb	bufqxk	,FIRQB+27	; Stuff saved buffer quota
	.UUO				; Do it
100$:	clc				; Say it worked and exit
	return				; Bye




	.sbttl	read/write terminals


$READTT:mov	#XRB	,r0		; Point to the XRB please
	tst	10(sp)			; No wait desired today?
	beq	10$			; Yes (the normal case)
	mov	10(sp)	,(r0)		; No, SLEEP instead of TIMEOUT
	.SLEEP				; Sleep until tmo or something
10$:	mov	4(sp)	,(r0)+		; is typed. Stuff a buffer size
	bne	20$			; Make sure the buffer size is ok
	inc	-2(r0)			; Not ok, make it one character
20$:	clr	(r0)+			; Clear returned byte count
	mov	2(sp)	,(r0)+		; Buffer address
	movb	6(sp)	,(r0)		; Channel number
	aslb	(r0)+			; Times two
	clrb	(r0)+			; Unused (byte)
	clr	(r0)+			; Unused (word)
	clr	(r0)+			; No timeouts with binary mode
	mov	#8192.	,(r0)+		; No stalling please
	.READ				; Do it
	clr	r1			; Assume no data
	movb	FIRQB	,r0		; Success?
	bne	100$			; No
	mov	XRB+XRBC,r1		; Yes, return byte count
100$:	mov	(sp)	,10(sp)		; Move return address up
	add	#4*2	,sp		; Pop parameters and exit
	return				; Bye

$writet:mov	r1	,-(sp)		; Save it
	mov	4+2(sp)	,r0		; Size of the write
	bne	10$			; It's ok
	mov	2+2(sp)	,r1		; No, get the asciz size now
	strlen	r1			; ....
10$:	mov	#XRB	,r1		; Point to XRB please
	mov	r0	,(r1)+		; Byte count
	mov	r0	,(r1)+		; Byte count again
	mov	2+2(sp)	,(r1)+		; Buffer address
	movb	6+2(sp)	,(r1)		; Channel number
	aslb	(r1)+			; Times two
	clrb	(r1)+			; Unused (byte)
	clr	(r1)+			; Unused (word)
	clr	(r1)+			; Unused (word) again
	mov	#4096.	,(r1)+		; IO.WAL
	.WRITE				; Do it
	mov	(sp)+	,r1		; Restore this one
	mov	(sp)	,6(sp)		; Move return address up
	add	#3*2	,sp		; Ignore parameters
	return







$fqcopy:save	<r0,r1,r2>		; Copy a block of data
	mov	2+6(sp)	,r2		; Destination
	mov	4+6(sp)	,r1		; Source
	mov	#40	,r0		; Size of a FIRQB
10$:	movb	(r1)+	,(r2)+		; Copy a byte
	sob	r0	,10$		; Next please
	unsave	<r2,r1,r0>		; Pop registers
	mov	(sp)	,4(sp)		; Move return address
	cmp	(sp)+	,(sp)+		; Pop stack
	return				; Exit


	.enabl	lsb

iocheck:cmpb	r0	,#DETKEY	; I/O to detached Keyboard?
	beq	80$			; Yes, it's fatal
	cmpb	r0	,#NODATA	; Simply no data present?
	beq	70$			; Yes, that one is ok
	movb	#ERRFQ	,FIRQB+FQFUN	; Dump error text out next
	movb	r0	,FIRQB+4	; Pass the error code also
	CALFIP				; Simple to do
	clrb	FIRQB+37		; Insure .asciz
	WRITETT	buffer=#FIRQB+4,lun=#LUN.CO
	WRITETT	buffer=#220$,lun=#LUN.CO; A finishing CRLF
70$:	clc				; Not fatal
	return				; Exit
80$:	WRITETT	buffer=#210$,lun=#LUN.CO; Dump an error MESSAGE please
	sec				; This is FATAL
	return				; Bye


	.save
	.psect	rwdata	,d,lcl,rel,con,rw

200$:	.asciz	/%Read error - /
210$:	.asciz	/??DETKEY error - DTR not present or has been lost/<CR><LF>
220$:	.byte	CR,LF,0
	.even

	.restore
	.dsabl	lsb





	.sbttl	concmd	terminal emulation escape commands
	.enabl	lsb

concmd::mov	r1	,-(sp)		; Save it
	movb	@r4	,r1		; Get the character to check
	bicb	#^C177	,r1		; Must drop parity 
	scan	r1	,#200$		; look for a match here
	asl	r0			; word offsets
	jsr	pc	,@210$(r0)	; dispatch to the correct routine
100$:	mov	(sp)+	,r1		; Pop R1 and exit
	return


	.save
	.psect	rwdata	,rw,d,lcl,rel,con

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

	.restore			; Pop code psect context
	.dsabl	lsb			; Turn off current symbol block


con.$:	WRITETT	buffer=#$bel,lun=#LUN.CO; Send a beep out for unknown
	clc				; commands. Say it is not fatal.
	return				; Bye


con.c:	sec				; Exit connection
	return				; And return


con.i:	CALLS	ttydtr	,<#ttname>	; try to force DTR up on the line
	clc				; And say it's NOT fatal
	return				; Exit


con.q:	bic	#log$co	,trace		; turn off console logging
	clc				; Successfull
	return				; Exit


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


con.x:	WRITETT	buffer=#$xon,lun=#LUN.XK; Try hard to send an xon done
	CALLS	ttxon	,<#ttname>	; and try to clear our xoffed state
	clc				; Success
	return				; Exit

con.br:	CALLS	ttspee	,<#ttname>	; get the remotes terminal speed
	mov	r0	,r2		; save the old speed
	CALLS	setspd	,<#ttname,#50.,#LUN.XK>;try to set it down to 50 baud
	tst	r0			; did it work ?
	bne	100$			; no, forget it
	WRITETT	buffer=#null2,lun=#LUN.XK,size=#2
	CALLS	setspd	,<#ttname,r2,#LUN.XK>; restore the terminal's speed
100$:	clc
	return

	.save
	.psect	$PDATA	,D
null2:	.byte	0,0
	.restore



con.hl::WRITETT	buffer=#hlptxt,lun=#LUN.CO
	clc
	return

	.save
	.psect	rwdata	,rw,d,lcl,rel,con
hlptxt:	.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




	.sbttl	dump i/o to a log file ?


;	Passed:	R5	buffer address
;		R1	buffer size


dumplo:	bit	#LOG$CO	,trace		; Is this enabled ?
	beq	100$			; No
	bit	#LOG$OP	,trace		; Is it open
	beq	100$			; No
	save	<r1,r2,r5>		; Save work registers
	mov	r1	,r2		; Get the number of characters
	beq	90$			; Nothing to do ?
10$:	clrb	r0			; Avoid sign extension
	bisb	(r5)+	,r0		; Get the next character
	mov	#LUN.LO	,r1		; Unit number
	call	putcr0			; Thats it folks
	sob	r2	,10$		; Next please
90$:	unsave	<r5,r2,r1>		; Pop registers and exit
100$:	clc				; May as well say it worked
	return				; Bye



	.save
	.psect	rwdata
$xon:	.byte	'Q&37,0
$xoff:	.byte	'S&37,0
$bel:	.byte	'G&37,0
	.even
	.restore


	.end
