	.sbttl	K11RCO	New RT11 connect code
	.psect
	.ident	/3.51.4/



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

	.enabl	gbl
	
;	Copyright (C) 1986 Change Software, Inc
;
;	07-MAY-1986 10:55  Brian Nelson
;
;	Edits:
;
;	16-May-86  11:12:55
;
;3.51.2	Add tasks to watch for carrier transitions and hung XOFF'ed
;	status (XC/XL/CL only).
;3.51.3 Check for tt output ring buffer overflow.
;3.51.4 Kludge to correct for bug in RT11 5.1 XL handler
;3.56.5 Allow XL a little time to finish 09-Dec-86  10:52:04
;3.56.6 Fix LF processing. Not strictly needed because the XL driver
;	under 5.2 and later filters LF's that follow CR's. We will do
;	it here anyway though for non-DEC drivers (like CL and KL).
;
;
;
;	 Complete rewrite of RT11 connect code.  For XC/XL/CL, we use
;	a multitasking  approach and drive it via interupts (actually
;	timer and read completions). For MultiTerminal data, see code
;	at DOMT:.  Maybe the MT code will run on SJ now, the XL/CL/XC
;	code will NOT.


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


	JSW	=	44
	ERRBYTE	=	52
	$XLV51	=	16.		; XL/XC for RT11 v5.1
	$XLV52	=	17.		; XL/XC for RT11 v5.2

	.mcall	.WRITC	,.SPFUN	,.TTINR	,.TTYIN	,.TTYOU	,.TTOUTR
	.mcall	.MRKT	,.CMKT	,.TWAIT	,.SCCA	,.QSET	,.PRINT
	.mcall	.RSUM	,.SPND	,.RCTRLO,.GVAL	,.SERR	,.HERR

	.iif ndf, SJ$TEST	,SJ$TEST = 0

	GLOBAL	<SJ$TEST>

	.if ne	,SJ$TEST
	.ift

	.macro	.RSUM
	.endm	.RSUM

	.macro	.SPND
	.endm	.SPND

	.macro	.MRKT	a,b,c,d,e,f
	.endm	.MRKT

	.macro	.TWAIT	a,b,c,d,e,f
	.endm	.TWAIT

	.macro	.CMKT	a,b,c
	.endm	.CMKT

	.endc				; IF ne, SJ$TEST




	.psect	condat

	.even

	.macro	BEEP
	mov	#7	,r0
	.TTOUTR
	.endm	BEEP

	.macro	SCHEDULE	taskheader
	mov	r0	,-(sp)
	mov	taskheader,r0
	mov	#runable,STATE(r0)
	mov	(sp)+	,r0
	.endm	SCHEDULE

	RUNABLE	=	1
	STATE	=	0
	TASKADDR=	2
	IODONE	=	4
	IOPEND	=	6
	IOBUFF	=	10
	IOSTALL	=	12

;	This is the schedulers 'JOB' table.


tlist:

;	      STATE    DISPATCH IODONE IOPEND  IOBUFF  IOSTALL

xkhead:	.word	0	,XKPROC	,0	,0	,0	,0
tthead:	.word	0	,TTPROC	,0	,0	,0	,0
rmhead:	.word	0	,RMPROC	,0	,0	,TTBUFF	,0
sthead:	.word	0	,STPROC	,0	,0	,0	,0
wthead:	.word	0	,WTPROC	,0	,0	,0	,0
	.word	-1	,-1	,-1	,-1	,0	,0

sjlist:	.word	STSDONE	,WTDONE	,TTDONE	,0

hdsize	=	tthead - xkhead






	.if NE	,SJ$TEST
	.ift
sj.dec:	.word	1			; Testing under XM
	.iff
sj.dec:	.word	0			; SJ and no .MRKT if NE
	.endc

crflag:	.blkw	1			; CR seen flag
xk:	.blkw	1			; Save flag
rt.v51:	.blkw	1			; Need to know Xl handler version
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
ttunit:	.blkw	1			; Our console terminal unit
xkunit:	.blkw	1			; Connected line's unit number
scca:	.word	0,0,0			; For getting control C's
mark:	.blkw	4			; For MARKTIME
short:	.word	0,1			;
mtime:	.word	0,0			; Timeout value
twait:	.word	0,0,0,0			; 'AREA' for TWAITS
cancel:	.word	0,0,0,0			; 'AREA' for CANCEL mark time
rmwork:	.word	0,0,0,0
rmtime:	.word	0,3*60.
ttmark:	.word	0,0,0,0
ttwait:	.word	0,3
suspend:.word	0
xkrd1:	.word	0,0,0,0,0,0
xkrd2:	.word	0,0,0,0,0,0
xkr1do:	.word	0
xkr2do:	.word	0
xkwork:	.word	0,0,0,0,0,0
done:	.word	0
xkmark:	.word	0,0,0,0
xktime:	.word	0,10.
idle:	.word	0
idmark:	.word	0,0,0,0
idtime:	.word	0,62.			; Check for idle state

stswork:.word	0,0,0,0,0,0		; For status watcher task's .SPFUN
stsmark:.word	0,0,0,0			; For .MRKT to schedule status watcher
ststime:.word	0,20.			; Schedule status watcher 20 ticks
wtmark:	.word	0,0,0,0			; For XOFF watcher
wttime:	.word	0,20.			; Do it every 20 ticks
xksts:	.word	0,0			; Save status
wtsts:	.word	0,0			; Save status again
wtcount:.word	0			; Save low 16 bits of char count
charcou:.word	0,0			; Total chars sent by HOST

tsxbrk:	.byte	0,133			; TSX+ SET break address
	.word	0			; No 'break' char
	.word	brkast			; Where to jump to
tsxnbrk:.byte	0,133			; TSX+, turn break AST's off
	.word	0,0			; Disable

XKSIZE	=	200			; Large buffers for remote reads
xkbuff:	.blkb	XKSIZE+2		; Buffer for connected line
xkpoint:.word	xkbuff
ttbuff:	.blkb	80.			; Buffer for console terminal
rmbuff:	.blkb	2
msg:	.blkb	110
co:	.asciz	/Connecting to /
spd:	.asciz	/  Speed: /<200>
	.even


	.psect	concod
	.enabl	lsb

doconn::call	check			; SJ checks
	.iif NE, SJ$TEST, clr clkflg	; For testing
	clr	xk			; Clear device type
	tstb	ttname			; Anything there ?
	bne	1$			; Yes
	message	<Please use the SET LINE command>,cr
	return				; Exit
1$:	strcpy	#msg	,#co		; Build a header up.
	strcat	#msg	,#ttname	; ...
	strcat	#msg	,#spd		; ......
	cmpb	ttname	,#'0		; Is this using XC/XL/CLn?
	blo	5$			; No
	cmpb	ttname	,#'9		; Well?
	bhi	5$			; No
	call	domt			; Switch modes then.
	return				; Exit
5$:	inc	xk			; Flag device class
	call	init			; Startup
	bcs	100$			; Oops
	call	ttinit			; Save terminal characteristics
	bcs	90$			; Die
					;

10$:	tst	done			; Time to go now ?
	bne	90$			; Yes, exit
	mov	#ttbuff	,r4		; Pointer to local term buffer
	inc	suspend			; Count the number of suspends
	.SPND				; Suspend ourself
	clr	idle			; No longer idle
	tst	sj.dec			; Minimal SJ system?
	beq	25$			; No
	mov	#sjlist	,r5		; Yes, No mark time so we will
20$:	tst	@r5			; have to call all of the watchers
	beq	25$			; If zero, all done
	jsr	pc	,@(r5)+		; Do it for Sj krud
	br	20$			; Check for more calls needed for SJ
25$:	mov	#tlist	,r5		; Find out who woke up
30$:	cmp	taskaddr(r5),#-1	; End of the table now?
	beq	50$			; Yes, suspend again
	tst	state(r5)		; Runnable task ?
	beq	40$			; No
	jsr	pc	,@taskaddr(r5)	; Yes, run the sucker.
40$:	add	#HDSIZE	,r5		; Next task control block please
	br	30$			; ...
50$:	br	10$			; Go away until something happens

90$:	.CMKT	#cancel,#0		; Kill all marktime requests
	call	ttrst			; Restore terminal chars

100$:	bic	#40000+10000+100,@#JSW	; Clear special modes
	.SCCA	#scca,#0		; Enable control C stuff again
	.CMKT	#cancel,#0		; Kill all marktime requests
	return

	.dsabl	lsb

	.sbttl	misc support routines
	.enabl	lsb
	.mcall	.scca


	$TCFIG	=	424

ttinit:	clc				; Basically a NO-OP
	return				; Exit

init:	tst	tsxsave			; True TSX+ today?
	beq	5$			; No
	.SERR				; To be safe
	mov	#tsxbrk	,r0		; Set break AST
	EMT	375			; Do it.
	.HERR				; Normal now
5$:	mov	#tlist	,r0		; Clear out task list
10$:	cmp	TASKAD(r0),#-1		; All done with list
	beq	20$			; Yes
	clr	STATE(r0)		; No
	clr	IODONE(r0)		; ...
	clr	IOPEND(r0)		; ...
	clr	IOSTALL(r0)		; Stalled flag.
	add	#HDSIZE	,r0		; Next please
	br	10$			; ...
20$:	clr	eseen			; No escape seen
	clr	crflag			; No carriage returns yet
	clr	idle			;
	clr	done			; ...
	clr	xkr1done		; Clear out
	clr	xkr2done		; Ditto
	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
	clr	charcount		; Clear out data count
	clr	charcount+2		; All 32 bits of it please.
	mov	#1	,suspend	; Suspension count
	mov	#xkbuff	,xkpoint	; Current pointer into buffer.
	.SCCA	#scca	,#scca+4	; Trap all control c's
	calls	ttyset	,<#ttname,#LUN.XK>
	calls	ttyini	,<#ttname,#LUN.XK,#0>
	tst	r0			; Successfull setup of port?
	beq	25$			; Yes, continue
	jmp	90$			; No, exit
					;
25$:	.print	#msg			; A header
	message	<Unknown>,cr		; ...
	message	<Type your local escape sequence to return to RT11>,cr
					;
					; All done, prime the system.
	.MRKT	#idmark,#idtime,#iddone,#11
	.MRKT	#stsmark,#ststime,#stsdone,#7
	.MRKT	#wtmark,#wttime,#wtdone,#10
	.SPFUN	#stswork,#XC.CONTROL,#STSDRV,#xksts,#0,#1	
	clr	rt.v51			; Flag if 5.1 or 5.2 please
	cmpb	xksts+1	,#$XLV51	; Is this a 5.1 system?
	bne	30$			; No, must be 5.2 or later.
	inc	rt.v51			; Yes, a serious bug in XL/XC
30$:					;
	.SPFUN	#xkrd1,#LUN.XK,#203,#xkbuff,#xksize,#1,#xkdone
	.MRKT	#ttmark,#ttwait,#ttdone,#3
	clc				; Successfull exit
	br	100$			; Exit
					;
90$:	mov	r0	,r1		; Save error code
	message	<Error from line initialization - >
	direrr	r1
	sec				; Failure to initialize things
100$:	return				; Exit INIT code

	.dsabl	lsb


	.sbttl	Restore line settings, check options for SJ exec

ttrst:	.TWAIT	#twait,#short		; Eat up extra .RSUM's ?
	.TWAIT	#twait,#short		; ...Ditto (one Tick)
	.TWAIT	#twait,#short		;    ...Ditto
	.TWAIT	#twait,#short		;       ...Ditto
	calls	ttyfin	,<#ttname,#LUN.XK>; Drop things and exit
	calls	ttyrst	,<#ttname,#LUN.XK>;
	.SERR				; To be safe
	tst	tsxsave			; TSX+
	beq	100$			; No
	mov	#tsxnbrk,r0		; Yes, turn break AST's off
	EMT	375			; Do it
100$:	.HERR				; Restore
	return				; Bye


	.enabl	lsb

	$CONFIG	=	300
	$SYSGEN	=	372

	SJMON	=	1		; RMON offset 300 (Config)
	CLOCK	=	100000		; RMON offset 300 (Config)
	MRKTIM	=	2000		; RMON offset 372 (Sysgen)

	.mcall	.GVAL


check:	.GVAL	#xkwork,#$CONFIG	; Get the configuration word
	bit	#SJMON	,r0		; Is this a SJ monitor ?
	bne	100$			; No, just exit
	bit	#CLOCK	,r0		; SJ, is there a clock present
	bne	10$			; Yes
	message	<%Kermit-W  Kermit needs a line or programable CLOCK>,CR
10$:	.GVAL	#xkwork	,#$SYSGEN	; Check for MARK TIME support
	bit	#MRKTIM	,r0		; Well?
	bne	100$			; Yes, support is present
	message	<%Kermit-W  The SJ executive should have timer support>,CR
	message	<sysgen'ed for the optimal operation of Kermit.>,CR
	inc	sj.dec			; Save the result
	sec				; Flag
	return				; Exit
100$:	clc				; Success
	return				; Exit




	.sbttl	reading from XK (XC/XL/CL) and TT:
	.enabl	lsb

ttdone:	mov	r0	,-(sp)		; Save this
	clr	tthead+state		; Assume no data present
	bis	#40000+10000+100+20,@#JSW; Enable special modes
	.TTINR				; Check for input waiting for term
	bcs	90$			; Nothing to do
	bicb	#^C177	,r0		; Strip any parity bits please
	tst	rt.v51			; Is this RT11 5.1 and OLD XL/XC
	bne	10$			; Yes, kludge a bug in the handler
	asr	crflag			; See if a carriage return preceeds
	bcc	5$			; a line feed. Was last one a CR?
	cmpb	r0	,#12		; Ignore LINE feeds Please
	beq	90$			; Exit on <LF>
5$:	cmpb	r0	,#15		; Is this one a carriage return?
	bne	10$			; No
	inc	crflag			; Yes, save for next time.
10$:	movb	r0	,ttbuff		; Insure we save this
	SCHEDULE #TTHEAD		; Get a process going to use data
	tst	suspend			; Fix up the .SPND count
	beq	20$			; ...
	dec	suspend			; ...
	.RSUM				; Get scheduler going
20$:	br	100$			; Exit
					;
90$:	.MRKT	#ttmark,#ttwait,#ttdone,#3
					;
100$:	mov	(sp)+	,r0		; Restore this
	return				; Exit


	.dsabl	lsb

ttproc:	clr	STATE(r5)		; Don't come back right away
	save	<r0,r1,r4>		; Save registers we use
	mov	#ttbuff	,r4		; Point to terminal buffer
	movb	@r4	,r0		; Get the data please
	cmpb	r0	,conesc		; Escape sequence today?
	bne	50$			; No, must dump character as is
	mov	#10*60.	,r1		; Loop a while looking for data
10$:	bis	#40000+10000+100+20,@#JSW ; Enable special modes
	.TTINR				; Was the escape characters, trynext
	bcc	30$			; Got something valid
	.TWAIT	#twait,#short		; Nothing, wait a little bit
	tst	sj.dec			; Did we have timer support?
	beq	20$			; Yes
	CPUWAIT	#1			; No (really should boot FB up)
20$:	sob	r1	,10$		; Next please
	br	100$			; Exit as we did not get any data
30$:	bicb	#^C177	,r0		; Strip junk from the character
	movb	r0	,@r4		; Insure we save this
	cmpb	r0	,conesc		; Double escape sequence read?
	beq	50$			; Yes, dump that character as is
	call	concmd			; No, check for emulator command
	br	100$			;
50$:	tst	duplex			; Need local echoing today?
	beq	60$			; No
	.TTOUTR				; Yes, echo the data please
60$:	setpar	(r4)	,(r4)		; Set parity up if needed
	SCHEDULE #RMHEAD		; Dump the data down the line
100$:	.MRKT	#ttmark,#ttwait,#ttdone,#3
	unsave	<r4,r1,r0>		; Pop and exit
	return				; Exit




xkdone:	SCHEDULE #XKHEAD		; Get things going when we exit
	clr	xkhead+iopend		; I/O is complete
	mov	sp	,xkhead+iodone	; Say so.
	mov	#xkbuff	,xkpoint	; Reset buffer pointer now.
	tst	suspend			; Fix up suspention count
	beq	100$			; No
	dec	suspend			; Yes, suspend--
	.RSUM				; Resume mainline
100$:	return				; Thus XKPROC will get called


xkredo:	SCHEDULE #XKHEAD		; If we need to retry terminal output
	tst	suspend			; Fix up suspention count
	beq	100$			; No
	dec	suspend			; Yes, suspend--
	.RSUM				; Resume mainline
100$:	return				; Thus XKPROC will get called


xkproc:	mov	r0	,-(sp)		; Save please
	mov	r1	,-(sp)		; Ditto
	mov	r3	,-(sp)		; ....
	mov	xkpoint	,r1		; Dump the buffer now
	mov	sp	,ioseen		; Say we got some data
210$:	tstb	(r1)			; All done yet?
	beq	240$			; Yes
	movb	(r1)+	,r0		;
	cmpb	parity	,#PAR$NO	; No parity?
	bne	215$			; No, clear high bit
	tst	con8bit			; SET CON 7/8 ?
	bne	215$			; No
	bicb	#200	,r0		; Strip high bit now
215$:	.TTOUTR				; No, dump the data
	bcs	220$			; If we fail, come back later
	add	#1	,charcount	; Bump up the character count
	adc	charcount+2		; The high part also.
	inc	xkpoint			; Remember where we were at now.
	br	210$			; Next please
					;
220$:	.MRKT	#xkmark,#xktime,#xkredo,#13 ; Output ring buffer is FULL.
	inc	IOSTALL(r5)		; Flag we are stalled.
	clr	STATE(r5)		; No longer runable please
	br	250$			; Exit
					;
240$:	mov	#xkbuff	,xkpoint	; Reset the pointer now.
	mov	#xkbuff	,r3		; Disk logging next
	call	dumplog			;
	clr	STATE(r5)		;
	clr	IODONE(r5)		; 
	clr	IOSTALL(r5)		;
	mov	sp	,IOPEND(r5)	; ...
	.TWAIT	#twait	,#short		; /56/
	.SPFUN	#xkrd1,#LUN.XK,#203,#xkbuff,#xksize,#1,#xkdone
250$:	mov	(sp)+	,r3		; Pop r3
	mov	(sp)+	,r1		; Pop r1
	mov	(sp)+	,r0		; And R0 please
	return				; Exit


rmproc:	mov	r0	,-(sp)		; Save
	mov	r1	,-(sp)		; ...
	tst	IOPENDING(r5)		; Are we still waiting for XC/XL?
	beq	30$			; /56/ No
	.CMKT	#cancel	,#3		; /56/ Disable terminal input checking
	mov	#10.	,r1		; /56/ Wait a total of 10 ticks
10$:	tst	IOPENDING(r5)		; /56/ Done YET?
	beq	20$			; /56/ Yes, at last
	.TWAIT	#twait	,#short		; /56/ Wait a tick
	sob	r1	,10$		; /56/ And go back and take a peek
20$:	.MRKT	#ttmark,#ttwait,#ttdone,#3 ; /56/ Reenable terminal checking
30$:	mov	IOBUFF(r5),r1		; /56/ Pointer to I/O buffer
	movb	@r1	,rmbuff		; Copy the data
	clrb	rmbuff+1		; Tack a NULL on the end.
	mov	sp	,IOPENDING(r5)	; Flag that we are waiting here.
	.MRKT	#rmwork,#rmtime,#300$,#5; Start timer to clear driver.
	.WRITC	#xkwork,#LUN.XK,#rmbuff,#1,#200$,#1
100$:	mov	(sp)+	,r1		; Pop
	mov	(sp)+	,r0		; ...
	clr	STATE(r5)		; Don't reschedule please.
	return				; Simple
					;
					; XC/XL WRITE completion.
200$:	clr	RMHEAD+IOPENDING	; I/O no longer pending
	.CMKT	#rmwork,#5		; Stop the marktime for XOFFED
	return				; Ast completion is a NO-OP
					;
					; MARKTIME completion.
300$:	call	x.ttxon			; Force a driver reset.
	clr	RMHEAD+IOPENDING	; Say we are ready for MORE data
	return				; Done.


	.sbttl	Status watchers

stsdone:mov	r0	,-(sp)		; Save this (?)
	SCHEDULE #STHEAD		; Schedule the status checker
	br	wtexit			; Exit now

wtdone:	mov	r0	,-(sp)		; Save this (?)
	SCHEDULE #WTHEAD		; Schedule the xon/xoff checker
wtexit:	tst	suspend			; Fix the suspended count
	beq	100$			; No
	dec	suspend			; Yes, suspend--
	.RSUM				; Start scheduler now
100$:	mov	(sp)+	,r0		; Pop R0 and exit
	return				; Exit the ast now


	.enabl	lsb

stproc:	save	<r0,r1,r2>		; Save registers we may need
	clr	STATE(r5)		; No longer runnable
	mov	xksts	,r2		; Save old status word
	.SPFUN	#stswork,#XC.CONTROL,#STSDRV,#xksts,#0,#1
	bcs	100$			; Failed??
	mov	xksts	,r1		; Get the current status
	bic	#^C4	,r2		; Leave only the carrier detect
	bic	#^C4	,r1		; bits on for the status
	cmp	r1	,r2		; Are they the same?
	beq	100$			; Yes, then ignore
	BEEP				; Make a small noise
	tst	r1			; Not the same, did we loose it?
	bne	10$			; No, we must have just gotten it
	message	<%Kermit-11 Carrier lost>,cr
	br	100$			; Exit
10$:	message	<%Kermit-11 Carrier detected>,cr
100$:	.MRKT	#stsmark,#ststime,#stsdone,#7 ; Reschedule us
	unsave	<r2,r1,r0>		; Pop registers and exit
	return				; Exit

	.dsabl	lsb

	.sbttl	Check for hung driver

	.enabl	lsb

wtproc:	save	<r0,r1,r2>		; Save registers please
	clr	STATE(r5)		; No longer runnable
	mov	wtsts	,r2		; Save old Status flags
	.SPFUN	#stswork,#XC.CONTROL,#STSDRV,#wtsts,#0,#1
	bcs	100$			; It should ALWAYS work.
	mov	wtsts	,r1		; Get new status
	bic	#^C3	,r2		; Leave only XOFF'ed status
	bic	#^C3	,r1		; Same for the current status word
	tst	r1			; See if XOFF'ed at either end
	beq	100$			; No, so just reschedule ourself
	cmp	r2	,r1		; Same status as last time here?
	bne	100$			; No, just exit normally then.
	mov	#tlist	,r0		; Ok, check for any i/o stalled.
10$:	cmp	TASKAD(r0),#-1		; End of list so far ?
	beq	20$			; Yes, fix the line up
	tst	IOSTALL(r0)		; No, anybody stalled intentionally?
	bne	100$			; Yes, just reschedule ourself
	add	#HDSIZE	,r0		; No, check next task out
	br	10$			; Next please
20$:					;
	.SPFUN	#stswork,#XC.CONTROL,#CLRDRV,#0,#0,#1
100$:	.MRKT	#wtmark,#wttime,#wtdone,#10
	mov	charcount,wtcount	; Copy low 16 bits of char count.
	unsave	<r2,r1,r0>		; Pop registers 
	return				; Exit

	.dsabl	lsb


iddone:	inc	idle			; Has anything happended in a while?
	cmp	idle	,#3		; Well?
	ble	100$			; No
	clr	idle			; Yes, force a .RSUM
	clr	suspend			; Clear suspended flag
	.RSUM				; Force mainline to run
100$:	.MRKT	#idmark,#idtime,#iddone,#11 ; Reshedule
	return				; And exit




	.sbttl	Connect for RT11 Multiple terminal service ONLY

;	Rewitten: 08-May-86  14:49:40  Brian Nelson


	.save
	.psect	mtdata	,rw,d,lcl,rel,con
chcount:.word	0
needxon:.word	0
mtbuff:	.word	0
mttime:	.word	0,0
mtwait:	.word	0,1
	.restore
	.enabl	lsb

domt:	clr	done			; Not done yet, please.
	mov	#10	,chcount	; Count down for rt11 to do an XOFF
	.SCCA	#scca,#scca+4		; No control C's please
	clr	needxon			; Don't need to send xon yet
	calls	noecho	,<#ttname>	; Don't want echoing please
	calls	ttyini	,<#ttname,#LUN.XK,#0>
	tst	r0			; Did the initialization work ?
	beq	1$			; Yes
	jmp	90$			; No, exit
1$:	calls	ttyset	,<#ttname>	; Ok, set some useful things up
	mov	#mtbuff	,r3		; A tiny one character buffer.
	.print	#msg			;
	calls	ttspeed	,<#ttname>	; ......
	tst	r0			; This is getting tedious
	bgt	5$			; ...
	message	<Unknown>,cr		; 
	br	6$			; And so on
5$:	decout	r0			; A REAL speed that RT11 knows about
	message				; CR/LF
6$:	message	<Type your local escape sequence to return to RT11>,cr
	mov	r3	,r4		; Compatibility with XM code


	.sbttl	Main loop for MT reading



10$:	tst	done
	bne	100$			; Exit
	calls	xbinrea	,<#LUN.XK,#-1>	; Try to get a charater from remote
	tst	r0			; Did the read succeed?
	bne	20$			; No, try console terminal then
	clrpar	r1			; Yes, drop any aprity bits please
	clr	@r3			; Insure .asciz string here.
	bisb	r1	,@r3		; Yes, get the character and print
	cmpb	r1	,#'S&37		; Xoff?
	beq	15$			; Yes, ignore
	movb	r1	,r0		; Copy the data now.
	.TTOUTR				; Dump the character
15$:	call	dumplo			; Dump to a log file perhaps
	dec	chcount			; Is it time to do a RT11 XOFF ?
	bne	25$			; No, wait a while then
	mov	#2	,needxon	; Will need to send xon later
	call	sxoff			; Yes, send an xoff please
	mov	#10	,chcount	; And reset the character counter
	br	25$			; And look for local terminal input
20$:	tst	needxon			; Really send an xon today?
	beq	25$			; No
	dec	needxon			; Don't overdo sending xon's please
	call	sxon			; No data, send an xon please
					;
25$:	bis	#40000+10000+100+20,@#JSW ; Insure special modes
	.TTINR				; Try to read something now
	bcs	70$			; No data, exit
	movb	r0	,@r3		; yes, get it and send it to the
	bic	#^C177	,r0		; insure no high bits are set.
	cmpb	r0	,#12		; Ditch LINE FEEDS Please.
	beq	25$			; A Line Feed, next please?
	cmpb	r0	,conesc		; other system unless it's the escape
	bne	50$			;
	mov	#20*60	,r1		; Loop a bit for a read
30$:	bis	#40000+10000+100,@#JSW	; Insure special modes
	.TTINR				; Try to read something now.
	bcc	40$			; Successfull read, exit
	.TWAIT	#twait,#short		; Wait a moment now.
	sob	r1	,30$		; Try again
	br	70$			; Nothing, ignore please
40$:	bic	#^C177	,r0		; Insure no high bits are set.
	cmpb	r0	,#12		; Ditch LINE FEEDS Please.
	beq	30$			; A Line Feed, next please?
	movb	r0	,@r3		; Must save it here!
	cmpb	r0	,conesc		; Really send the escape ?
	beq	50$			; Yes
	call	concmd			; Yes, do the command
	br	70$			; No, next please
					;
50$:	setpar	@r3	,@r3		; Insure correct outgoing parity now
	calls	binwri	,<r3,#1,#LUN.XK>; The data is for the remote system
	tst	duplex			; Full or half duplex connection?
	beq	70$			; Full
	movb	@r3	,r0		; Half duplex, echo the data now.
	.TTOUTR				; Simple to do.
70$:					;
80$:	br	10$			; and back for more

		
90$:	direrr	r0			; problems in getting the connection

100$:	calls	ttyfin	,<#ttname,#LUN.XK>
	bic	#40000+10000+100,@#JSW	; Get rid of special modes
	.SCCA	#scca,#0		; Get rid of control C trapping
	return				; And exit now.

	.dsabl	lsb


sxon:	tst	conflow
	beq	100$
	calls	binwri	,<#$xon,#1,#LUN.XK>
100$:	return

sxoff:	tst	conflow
	beq	100$
	calls	binwri	,<#$xoff,#1,#LUN.XK>
100$:	return




	.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.$:	movb	$bel	,r0
	.TTOUTR				; Beep a little
	clc				; commands. Say it is not fatal.
	return				; Bye


con.c:	mov	sp	,done		; 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


	.enabl	lsb

con.x:	tst	xk			; MT or XC/XL/CL today?
	beq	30$			; MT service
	.SPFUN	#200$,#XC.CONTROL,#CLRDRV,#0,#0,#1
	mov	#tlist	,r0		; Ok, check for any i/o stalled.
10$:	cmp	TASKAD(r0),#-1		; End of list so far ?
	beq	20$			; Yes, fix the line up
	clr	IOSTALL(r0)		; Clear task stalled flags
	add	#HDSIZE	,r0		; No, check next task out
	br	10$			; Next please
20$:	.WRITC	#200$,#LUN.XK,#$xon,#1,#190$,#1
	br	100$			; Exit
30$:	calls	ttxon	,<#ttname>	; and try to clear our xoffed state
100$:	clc				; Success
	return				; Exit

190$:	return				; AST write completion

	.save
	.psect	rwdata	,d,lcl
200$:	.word	0,0,0,0,0,0,0
	.restore
	.dsabl	lsb

brkast:	call	con.br
	mov	#tsxbrk	,r0
	EMT	375
	return

con.br:	calls	senbrk	,<#ttname,#lun.ti>
	clc
	return



con.hl::.print	#hlptxt
	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:	r3	buffer address


dumplo:	bit	#LOG$CO	,trace		; Is this enabled ?
	beq	100$			; No
	bit	#LOG$OP	,trace		; Is it open
	beq	100$			; No
	save	<r0,r1,r2,r3>		; Save work registers
	strlen	r3			; Get size
	mov	r0	,r2		; Copy size
	beq	90$			; Nothing to do ?
10$:	clrb	r0			; Avoid sign extension
	bisb	(r3)+	,r0		; Get the next character
	mov	#LUN.LO	,r1		; Unit number
	call	putcr0			; Thats it folks
	sob	r2	,10$		; Next please
90$:	unsave	<r3,r2,r1,r0>		; 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
