	.title	k11prt	pro/rt XC/XL interface
	.ident	/1.0.01/

;	13-Oct-84  11:02:39  Brian Nelson
;
;	6-May-85             Basically had to add in checks for xl and tsx
;                            and then roll in some of the code from k11tsx
;                            in order to properly use the cl lines under
;                            TSX.  (Ned W. Rhodes)
;
;	04-Nov-85  13:59:39  Mods suggested by Chuck Sandoian for TSX (BDN)
;			     All such edits marked by /37/
;
;	31-Dec-85  04:25:02  Added DTR control for RT11 5.2 and XC/XL
;	02-Sep-86  09:31:48  Fix SET SPEED for TSX+, edit /54/
;
;	Copyright (C) 1984 1985 Change Software, Inc.




;	NOTICE: !!!!!!
;
;	 To operate  properly with Kermits at high speed and with Kermits
;	not supporting xon/xoff flow control, the PRO/RT11 device handler
;	for XC: MUST be modified to increase the internal buffer size and
;	to  repress XON/XOFF  transmission within a packet.  This is very
;	easy to do.  In the file XL.MAC  from your PRO/RT kit, change the
;	line
;	from:		BUFSIZ	= 64.
;	to:		BUFSIZ	= 220.
;
;	and the line
;	from:		STPSIZ	= BUFSIZ/4
;	to:		STPSIZ	= BUFSIZ/2
;
;	 To recreate  XCX.SYS, first copy XC.MAC, XM.MAC, XL.MAC, XM.ANS
;	and SYSGEN.COM to DK: and then type  IND SYSGEN.  Tell it to use
;	the saved answer file  XM.ANS.  When SYSGEN exits,  it will have
;	created, among other files, a file called XM.CND which is needed
;	for the driver assembly.
;
;	Then:
;
;	assign dk: src:
;	copy xcx.sys xcx.old
; 	ren/nopro xcx.sys xcx.sys
;	unlo xc:
;	rem xc:
;	macro/obj:xcx (xm,xm.cnd,xc)
;	link/exe:xcx.sys xcx
;	ins xc:




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

	.psect

	.mcall	.ABTIO	,.READW	,.WRITW	,.SPFUN	,.TTINR	,.TTYIN	,.TTYOU
	.mcall	.MRKT	,.CMKT	,.TWAIT	,.WRITC
	.mcall	.LOOKUP	,.DSTAT	,.FETCH	,.CLOSE
	.mcall	.PRINT	,.GVAL	,.HRESET,.RELEAS
	.enabl	gbl

	.psect	XCRW	,rw,d,lcl,rel,con
xcwork:	.blkw	12			; for asynch calls to the XC driver
xcsts:	.word	0,0			; /51/ Saved from STSDRV
second:	.word	0,60.			; wait a full second
third:	.word	0,20.
tenth:	.word	0,6			; wait 1/10 second
break:	.word	0,17.			; for sending breaks, .283 seconds
wait:	.word	0,1			; wait one tick (1/60 second)
dtrlow:	.word	0,60.*1			; /41/ 2 second DTR drop
nobinar:.word	1			; /37/ assume XL/XC (no binary I/O)
r50dev::.word	0,0,0,0			; /37/ save name in rad50
devnam:	.word	0,0,0,0,0,0,0,0,0,0,0,0	; save the device name
ttctlc:	.blkw	1			; for control C things in connect mode
xoffed:	.word	0			; flag that we xoffed the other kermit
xcpoint:.word	xcrdbf			; current pointer into XCRDBF
xcsize:	.word	0			; size of last XC read (not used)
xcdone:	.word	0			; read is complete
xcwdon:	.word	0			; writc is complete
timwrk:	.blkw	4
	.even
xcrdbf:	.blkb	102			; for a local read buffer, always asciz
xcrdsi	=	100			; size of XCRDBF

m.tsxs:	.byte	35,'S			; Single Character
	.BYTE	35,'W			; Tape mode on
	.BYTE	35,'U			; No wait
	.BYTE	35,'Y			; High efficiency
	.BYTE	35,'R
	.BYTE	0
	.even
m.tsxr:	.byte	35,'T			; Single character off
	.byte	35,'X			; Tape mode off
	.byte	35,'Z			; Line feed echo
	.byte	0
	.even
hieff:	.byte	0,120			; Turn hi eff off


;	Edit 37 04-Nov-85  13:45:32  Brian Nelson
;
; /37/	 Conversations with Chuck Sandoian, (Compuserve 76703,414) have
;	determined that (1) the CL handler can run in 8bit mode  (NULLS
;	will, of course, not be passed). This is enabled by setting bit
;	11 in the .SPFUN code 250. Also, the CL driver DROPS DTR if the
;	driver is passed an  .SPFUN OFFDRV (code 205).  Ned Rhodes  had
;	the code for 250 set to 1427. With the release of v5 and v6, we
;	caln now use 8bit mode and control DTR,  so now it's 7427.  The
;	meaning of the bits follow:
;
;	0	Pass \014 <FF>		8	Send \015 <CR>
;	1	Pass \011 <HT>		9	Send CTL chars
;	2	Enable lower case	10	Raise DTR
;	3	Pass \012 <LF>		11	Enable 8bit mode
;	4	Accept \012		12	unknown
;	5	N/A			13	...ditto
;	6	Binary output		14	......and so on
;	7	Binary input		15	.........

xlset:	.word	7427			; /37/ Options to set (was 1427)
xlset2:	.word	40!10			; /44/ NOLFOUT and NOFORM0
xlset3:	.word	10			; /45/ Put LFOUT back in

;	The following tables are used for:
;
;	(1) On TSX+, map decimal speeds into .SPFUN speeds for setting
;	    speed on DH/DHV/DHU and DZ/DZV interfaces.
;	(2) At some future time when either TSX+ or RT supports it get
;	    the interface speed from  the exec and  insert a .TWAIT in
;	    front of the .SPFUN read call to reduce cpu usage at lower
;	    line speeds. For now, default to one tick unless a SET SPE
;	    command was given on TSX+.

	.word	0
splst:	.word	75.	,110.	,134.	,150.	,300.	,600.	; /44/
	.word	1200.	,1800.	,2000.	,2400.	,3600.	,4800.	; /44/
	.word	7200.	,9600.	,19200.	,0			; /44/

spmap:	.word	1	,2	,3	,4	,5	,6	; /44/
	.word	7	,10	,11	,12	,13	,14	; /44/
	.word	15	,16	,17				; /44/
								;
waitti:	.byte	1						; /52/
	.byte	6	,6	,6	,6	,6	,4	; /52/
	.byte	3	,2	,2	,2	,2	,1	; /52/
	.byte	1	,1	,0	,0	,0	,0	; /52/
	.even							; /52/
waitarg:.word	0,0						; /52/
xkspeed:.word	0						; /52/

	.psect	$CODE

	ERRBYT	=	52
	JSW	=	44


;	.SPFUN	codes for the XC/XL driver

	CLRDRV	==	201		; undo xon, reset the driver
	BRKDRV	==	202		; wc=0, end break else break
	SRDDRV	==	203		; special read, wc is max # of bytes
					; to read, always returns at least one
					; byte, up to max if data is there.
	STSDRV	==	204		; driver status, high byte is driver
					; version, low byte is:
					; bit 0 = 1 if sent xoff to host
					; bit 1 = 1 if rec xoff from host
					; bit 2 = 1 if CTS is ok
	OFFDRV	=	205		; disable interupts at program exit

	DTRDRV	=	206		; rt 5.2, set/clear DTR. If WC <> 0
					; then turn it on else turn it off.
	
	CLSET	=	250		; Set cl options for TSX-Plus
	CLRSET	=	251		; Reset cl option for TSX-Plus
	CLSPEED	=	256		; /44/ Speed control
	CLCLR	=	257		; /37/ Reset w/o dropping DTR

	XC.CONTROL == 	14		; channel for controlling the driver
	XC.AUX	   =	15		; /41/ Ditto


	.iif ndf, XON	  , XON = 'Q&37
	.iif ndf, XOFF	  , XOFF= 'S&37


	.sbttl	assign and init the XC/XL port
	.enabl	lsb

	.mcall	.SERR	,.HERR		; /51/

x.ttysav::
x.ttyrst::
x.deadev::
	mov	r1	,-(sp)		; /45/
	br	10$			; /45/
x.assdev::
	mov	r1	,-(sp)		; /44/ Save a register please
	mov	@r5	,r1		; /44/ Address of the devname
	call	mapxl			; /44/ Do we know about this dev?
	bcs	110$			; /44/ No, return error in R0
10$:	.SERR				; /51/
	tst	tsxcl			; Under tsx and using cl line?
	beq	100$			; Nope
	mov	#hieff,r0		; Get emt parameter block
	emt	375			; Turn off hi efficiency
	.PRINT	#m.tsxr			; Reset some terminal parameters
100$:	.HERR				; /51/
	clr	r0			; Success
110$:	mov	(sp)+	,r1		; /44/ Restore
	return				; not needed for PRO/RT


	.dsabl	lsb


;	T T Y I N I
;
;	input:	@r5	device name
;		2(r5)	LUN
;		4(r5)	modifiers
;
;	output:	r0	error code


x.TTYINi::
	save	<r1,r2,r3,r4>		; /37/ always save temps please
	mov	@r5	,r1		; get the device name address
	mov	2(r5)	,r0		; copy the device name please
	asl	r0			; lun times two please
	movb	(r1)	,devnam(r0)	; save it please
	movb	1(r1)	,devnam+1(r0)	; both ascii characters please
	clr	r0			; assume success
	tstb	@r1			; perhaps the console ?
	beq	100$			; yes, don't do anything
	cmpb	@r1	,#'T&137	; TT: ?
	beq	100$			; do nothing then

1$:	clr	xoffed			; reset 'sent an XOFF' flag
	mov	#xcrdbf	,xcpoint	; a pointer into the XC: buffer
	mov	#xcrdbf	,r2		; xc device, zero the buffer
	mov	#xcrdsi+2,r0		; the size of the buffer
5$:	clrb	(r2)+			; clear it out
	sob	r0	,5$		; next please

	call	mapxl			; /44/ See if XL/XC or CLn passed
	bcs	95$			; /44/ No, exit with ER$UKN
	mov	r0	,r2		; /44/ Point to RAD50 device name
10$:	calls	fetch	,<@r2>		; get the device loaded ?
	tst	r0			; did it work ?
	bne	95$			; no
20$:	clr	xcdone			; nothing pending to read from XC:
	mov	r2	,r3		; /37/ get pointer to rad50 of dev
	mov	#r50dev	,r4		; /37/ where to save r50 of name
	mov	(r3)+	,(r4)+		; /37/ copy rad50 of device name
	mov	(r3)+	,(r4)+		; /37/ copy rad50 of device name
	mov	(r3)+	,(r4)+		; /37/ copy rad50 of device name
	mov	(r3)+	,(r4)+		; /37/ copy rad50 of device name
	.LOOKUP	#rtwork,2(r5),r2	; try to open the port up please
	bcs	60$			; oops
	.LOOKUP	#rtwork,#XC.CONTROL,r2	; also open a control channel
	bcs	60$			; should never happen, of course
	call	200$			; /51/ Extra for driver version
	call	tsxopt			; /37/ set CLn: if it's TSX+
	tst	nobinary		; can we do binary i/o to XC: ?
	beq	30$			; yes
	cmpb	parity	,#par$no	; currently PARITY NONE ?
	bne	30$			; no
	movb	#par$sp	,parity		; set space parity to fake it
30$:	clr	r0			; all is well today
	br	100$			; exit with sucess



60$:	mov	#xcierr	,r0		; open error on X?0: device
	br	90$			; map it to a global error
70$:	mov	#xcspfun,r0		; .SPFUN error for X?0:
	br	90$			; map it to a global error

90$:	clr	r1			; now map to the global error code
	movb	@#ERRBYT,r1		; get RT11's error code
	asl	r1			; times 2 for word indexing
	add	r0	,r1		; point to the global error code
	mov	@r1	,r0		; and get it
95$:	mov	2(r5)	,r1		; clear the saved device name
	asl	r1			; times two please
	clr	devnam(r1)		; simple
100$:	unsave	<r4,r3,r2,r1>		; /37/ pop scratch registers and exit
	return				; bye


200$:	.SPFUN	#rtwork,#XC.CONTROL,#STSDRV,#xcsts,#0,#1
	.SPFUN	#rtwork,#XC.CONTROL,#CLRDRV,#0,#0,#1
	bit	#1	,xcsts		; Did we ever xoff the host?
	beq	210$			; No
	.WRITC	#rtwork,2(r5),#$xon,#1,#290$,#1
210$:	return

290$:	return				; .WRTIC completion

	.save
	.psect	$pdata	,ro,d,lcl,rel,con
	.even
$xon:	.byte	'Q&37,0
	.even
	.restore



	.sbttl	TSX+ things


tsxopt:	tst	tsxcl			; /37/ TSX+ and CL:
	beq	100$			; /37/ No
	cmp	nobinary,#1		; /37/ currently set to default?
	bne	10$			; /37/ no, don't change it
	clr	nobinary		; /37/ Yes, we can do 8BIT I/O on CL
10$:	.GVAL	#rtwork,#-4		; get tsx leadin
	movb	r0,m.tsxr		; set in place
	movb	r0,m.tsxr+2		; set in place
	movb	r0,m.tsxr+4		; set in place
	movb	r0,m.tsxs		; set in place
	movb	r0,m.tsxs+2		; set in place
	movb	r0,m.tsxs+4		; set in place
	movb	r0,m.tsxs+6		; set in place
	movb	r0,m.tsxs+8.		; set in place
	.PRINT	#m.tsxs			; set the options
	.SPFUN	#rtwork,#xc.control,#clset,#xlset,#1,#0
					; set some cl options
	.SPFUN	#rtwork,#xc.control,#clrset,#xlset2,#1,#0
					; reset some cl options
	bis	#40000!10000!100,@#JSW	; lower case, no wait, and special
100$:	return				; back to caller



mapxl:	save	<r1,r2,r3>		; /44/ Save these please
	clr	r3			; /44/ Current index
	sub	#50	,sp		; /44/ Allocate a buffer for new name
	mov	sp	,r2		; /44/ And also a pointer to it
5$:	cmpb	(r1)	,#':		; /44/ While ( *devnam != ':' )
	beq	6$			; /44/   {
	movb	(r1)	,(r2)+		; /44    *newnam++ = *devnam
	beq	6$			; /44/   if ( *devnam == NULL) break
	inc	r1			; /44/   devnam++
	br	5$			; /44/   } ;
6$:	clrb	(r2)			; /44/ *newnam = NULL
	mov	sp	,r2		; /44/ newnam = newnam_base_address

10$:	tst	200$(r3)		; /44/ End of the list yet ?
	beq	90$			; /44/ Yes, exit with ER$UKN
	strcmp	r2	,200$(r3)	; /44/ Find a device name match?
	tst	r0			; /44/ Well ?
	beq	20$			; /44/ Yes
	tst	(r3)+			; /44/ No, try the next entry
	br	10$			; /44/ ....
20$:	mov	#310$	,r0		; /44/ Success, copy r50 devicename
	mov	300$(r3),@r0		; /44/ Just copy over first word
	add	#50	,sp		; /44/ Pop local buffer....
	clc				; /44/ No errors
	br	100$			; /44/ Exit
90$:	mov	#ER$UKN	,r0		; /44/ Return error and exit
	add	#50	,sp		; /44/ Pop local buffer....
	sec				; /44/ Flag error
100$:	unsave	<r3,r2,r1>		; /44/ Exit
	return


200$:	.word	201$,202$,203$,204$
	.word	210$,211$,212$,213$,214$,215$,216$,217$
	.word	220$,221$
	.word	0
201$:	.asciz	/XC/
202$:	.asciz	/XL/
203$:	.asciz	/XC0/
204$:	.asciz	/XL0/
210$:	.asciz	/CL0/
211$:	.asciz	/CL1/
212$:	.asciz	/CL2/
213$:	.asciz	/CL3/
214$:	.asciz	/CL4/
215$:	.asciz	/CL5/
216$:	.asciz	/CL6/
217$:	.asciz	/CL7/
220$:	.asciz	/KL/
221$:	.asciz	/KL0/
	.even
300$:	.rad50	/XC /
	.rad50	/XL /
	.rad50	/XC /
	.rad50	/XL /
	.rad50	/CL0/
	.rad50	/CL1/
	.rad50	/CL2/
	.rad50	/CL3/
	.rad50	/CL4/
	.rad50	/CL5/
	.rad50	/CL6/
	.rad50	/CL7/
	.rad50	/KL /
	.rad50	/KL0/
310$:	.rad50	/   /
	.rad50	/   /
	.rad50	/   /
	.rad50	/   /






	.sbttl	close the line up
	.enabl	lsb

x.ttyfin::
	save	<r1,r2>			; /37/ save temps please
	.TWAIT	#rtwork,#third		; /37/ insure ack for B packet done
	tst	tsxcl			; /45/ Tsx+ and CLn?
	beq	1$			; /45/ No
	.SPFUN	#rtwork,#xc.control,#clset,#xlset3,#1,#0 ; /45/ Yes, SET LFOUT
1$:	clr	wasxc			; was not xc/xl and pure RT
	mov	2(r5)	,r1		; get the internal lun
	asl	r1			; map it
	cmpb	devname(r1),#'C&137	; /44/ CLn: and TSX+ ?
	beq	2$			; /44/ Yes, let it through
	cmpb	devname(r1),#'X&137	; see if the device was X?:
	bne	10$			; no, then do nothing
2$:	call	clrxc			; reset the driver
	mov	#CLCLR	,r2		; /37/ assume TSX CL function 257
	tst	tsxcl			; tsx and cl?
	bne	5$			; yes
	mov	sp	,wasxc		; flag for .exit that this was XC/XL
	mov	#OFFDRV	,r2		; /37/ No, was real RT11 today
5$:	.SPFUN	#rtwork,#XC.CONTROL,r2,#0,#0,#1 ;disable interupts at exit
	.ABTIO	2(r5)			; try to stop all i/o please
	.ABTIO	#XC.CONTROL		; /51/
	.CLOSE	2(r5)			; yes, was XC/XL, thus close it
	.CLOSE	#XC.CONTROL		; and close the controller port
	clr	xcwdone			; nothing as far as writes either
	clr	xcdone			; nothing pending to read from XC:
	mov	#xcrdbf	,xcpoint	; reset the pointer to the buffer
	clrb	@xcpoint		; stuff a null in please
10$:	clr	devnam(r1)		; no device active now
	clr	r0			; no error are possible
	unsave	<r2,r1>			; /37/ pop temp and exit
	return				; bye

	.dsabl	lsb


x.finrt::				; /37/ clear the line for good
	tst	r50dev			; /37/ anything ever opened up ?
	beq	10$			; /37/ no
	.LOOKUP	#rtwork,#XC.CONTROL,#r50dev 	     ; /37/ yes, open it
	.SPFUN	#rtwork,#XC.CONTROL,#OFFDRV,#0,#0,#1 ; /37/ and kill it
10$:	tst	wasxc			; /37/ need a .HRESET ?
	beq	20$			; /37/ no
	.ABTIO	#XC.CONTROL		; /51/
	.CLOSE	#XC.CONTROL		; /51/
	.HRESET				; /51/
	br	100$			; /51/ And exit
					;
20$:	.CLOSE	#XC.CONTROL		; /37/
100$:	clr	r0			; /37/ bye
	return


	.save
	.psect	XCDATA	,rw,d,lcl,rel,con
XCNAME:	.rad50	/XC /
	.rad50	/   /
	.rad50	/   /
	.rad50	/   /
XLNAME:	.rad50	/XL /
	.rad50	/   /
	.rad50	/   /
	.rad50	/   /
	.restore





	.sbttl	binrea	read binary


;	B I N R E A
;
;	input:	@r5	LUN
;		2(r5)	timeout
;	output:	r0	error code
;		r1	character just read
;
;	To avoid rewriting the terminal emulation code, the case
;	where we get passed a timeout of -1 is used to do a  qio
;	to the XC port and then subsequent calls simply check to
;	see if it completed. If so, get whats in the buffer.  If
;	it's not done, exit and check  next time.  This  is only
;	done from the connect code,  so perhaps later I will get
;	around to rewriting it.
;
;	For the normal Kermit timed packet read, we post the qio
;	and loop waiting for it to complete. If it does not com-
;	plete  within the specified time, we cancel  the i/o and
;	reset the driver.
;	For proper operation, the XC driver must be modified  as
;	described at the beginning of the file.

rdmode:	.word	0

x.xbin::mov	sp	,rdmode
	br	rdcom
x.binr::clr	rdmode
rdcom:	save	<r2,r3,r4>		; we may want to use these here
	mov	@r5	,r2		; get the lun to use
	asl	r2			; if TT: then do it different
	cmpb	devnam(r2),#'C&137	; /44/ CLn: and TSX+ ?
	beq	10$			; /44/ Yes, let it through
	cmpb	devnam(r2),#'X&137	; XC: ?
	beq	10$			; yes (or at least assume so)
	call	ttread			; yes, get from the console tt
	br	100$			; bye

10$:	cmp	xcpoint	,#xcrdbf+xcrdsi	; insure no buffer overflows
	bhis	20$			; gone too far, XC driver is %$#@!
	tstb	@xcpoint		; anything left in the readbuffer?
	bne	30$			; no
20$:	mov	#xcrdbf	,xcpoint	; reset the pointer to the buffer
	clrb	@xcpoint		; stuff a null in please
	call	xxread			; load the buffer with as much as can
	tst	r0			; did this read succeed ?
	bne	100$			; no
30$:	clr	r1			; avoid sxt even if the fubar XC
	bisb	@xcpoint,r1		; driver always drops bit 7 (future?)
	inc	xcpoint			; point to the next one in the buffer
	clr	r0			; insure success and exit

100$:	unsave	<r4,r3,r2>
	return


xxread:	mov	2(r5)	,r3		; timeout in seconds here
	bne	10$			;
	inc	r3			; convert nothing to one second
10$:	cmp	r3	,#-1		; no wait ?
	beq	15$			; yes
	mul	#60.	,r3		; no, convert time to ticks then
	br	20$			; and check on the i/o status
15$:	mov	#1	,r3		; no wait (really, one tick)

20$:	tst	xcdone			; no timout, last read ever finish?
	bmi	30$			; no, keep waiting then
	mov	#-1	,xcdone		; read without waiting for it
	mov	xkspeed	,r1		; /52/ Get current line speed
	movb	waitti(r1),waitarg+2	; /52/ Insert the desired delay now
	.TWAIT	#rtwork,#waitarg	; /52/ Now delay processing a moment
	.SPFUN	#xcwork,@r5,#SRDDRV,#xcrdbf,#xcrdsi,#1,#200$

30$:	tst	xcdone			; return that fast (?)
	bgt	40$			; yes
	tst	clkflg			; /37/ system have a clock?
	bne	34$			; /37/ yes
	cpuwait	#1			; /37/ no, loop to wait
	br	35$			; /37/ next please
34$:	.TWAIT	#rtwork,#wait		; no, sleep for 1/60 second
35$:	sob	r3	,30$		; and see if we should keep waiting
	tst	xcdone			; got it from the XC buffer now?
	bmi	50$			; no, return no data and exit

40$:	clr	r1			; all done, get character and exit
	bisb	xcrdbf	,r1		; and set the error code to zero
	clr	xcdone			; que a new read next time called
	clr	r0			; in r0
	br	100$			; bye

50$:	cmp	2(r5)	,#-1		; no xon's if we are looping no tmo
	beq	60$			;
	tst	rdmode			; /45/ From CONNECT or DIAL ?
	bne	60$			; /45/ Yes, please drop XON's then
	call	clrxc			; insure interupts are ok, also XON
60$:	mov	#ER$NIN	,r0		; no data has come it yet
	br	100$			; exit

100$:	return


200$:	mov	#1	,xcdone		; flag a read completion and exit
	return				; so we will break the .TWAIT loop




	.sbttl	raw i/o from the console TT


ttread:	bis	#40000!10000!100,@#JSW	; lower case, no wait
	cmp	2(r5)	,#-1		; read without any wait ?
	bne	10$			; no
	.TTINR				; one char from the console tt:
	bcs	80$			; it worked
	mov	r0	,r1		; and exit with success
	clr	r0			; bye
	br	100$			; exit at last

10$:	mov	2(r5)	,r1		; get the timeout in seconds
	mul	#60.	,r1		; into ticks now
20$:	.TTINR				; try a character from TT:
	bcc	30$			; it worked, get the ch into r1
	dec	r1			; been here too long ?
	beq	80$			; yes, exit with error
	.TWAIT	#rtwork,#wait		; sleep a moment please
	br	20$			; and try again please

30$:	clr	r1			; it worked, get the character and exit
	bisb	r0	,r1		; simple
	clr	r0			; success
	br	100$			; and exit

80$:	mov	#ER$NIN	,r0		; no data today
	clr	r1			; same here, return a null
100$:
	tst	tsxcl			; tsx and cl
	bne	101$			; yes
	bic	#40000!10000!100,@#JSW	; reset some tt options
101$:	return




	.sbttl	binary write



;	B I N W R I
;
;	binwri( %loc buffer, %val buffer_size, %val lun )
;
;	output:	r0	error code

	$XLV51	=	16.
	$XLV52	=	17.


x.binwri::
	save	<r1,r2,r3,r4>
	clr	r0			; presume no errors
	tst	2(r5)			; any i/o to do at all?
	beq	100$			; no
	mov	4(r5)	,r4		; check for TT: please
	asl	r4			; by indexing to DEVNAM:
	cmpb	devnam(r4),#'T&137	; TT: ?
	bne	20$			; no
	mov	@r5	,r4		; simple
	mov	2(r5)	,r2		; number of characters to write
15$:	.TTYOUT	(r4)+			; dump via .TTYOU to avoid .PRINT's
	sob	r2	,15$		; problems with 8bit characters please
	clr	r0			; and exit
	br	100$			; bye

20$:	mov	#-1	,xcwdone	; Done yet?
	mov	(r5)	,r3		; Copy the data to a local buffer
	mov	xklgbuf	,r2		; Pick up pointer to a buffer
	mov	2(r5)	,r4		; The byte count for the write
	mov	r4	,r1		; Set byte count for the copy.
25$:	movb	(r3)+	,(r2)+		; for (i=bytecount;i>0;i--)
	sob	r4	,25$		;   *buffer++ = *source++
	mov	r1	,r4		; restore  the byte count
	dec	r4			; if bytecount <> 1
	beq	40$			;  then
	cmpb	-(r3)	,#CR		;    if lastcharacter == CR
	bne	30$			;     then
	movb	#LF	,(r2)+		;       *bufffer++ = NULL
	inc	r1			;       bytecount++
30$:	clr	xoffed			;    xoffed = false ;
;-	tst	rtflow			;    if (needflowcontrol)
;-	beq	35$			;     then
;-	movb	#XOFF	,(r2)+		;      *buffer++ = XOFF
;-	inc	r1			;      bytecount++
;-	mov	sp	,xoffed		;      xoffed = true
35$:

40$:	clrb	(r2)+			; *buffer++ = NULL ;
	inc	r1			; bytecount++ 
	asr	r1			; bytecount = bytecount/2
	.WRITC	#xcwork,4(r5),xklgbuf,r1,#200$,#1
	mov	#10.*60.,r3		; wait at most 10 seconds (?)

50$:	tst	xcwdone			; ast completion as of yet ?
	bne	60$			; yes
	tst	clkflg			; A clock?
	bne	55$			; Yes
	CPUWAIT	#1			; No, loop and fall thru, twait is NOP
55$:	.TWAIT	#rtwork,#wait		; still not complete, wait a tick
	sob	r3	,50$		; and check again
	call	clrxc			; clear the driver out, send XON
	clr	r0
	br	100$			; exit

60$:	tst	r4			; was that a single character i/o?
	beq	70$			; yes
	tst	xoffed			; in case a virgin xcdriver, wait.
	beq	70$			; no, skip the wait and xon then.
	.TWAIT	#rtwork,#tenth		; no, sleep for a moment please
	.TWAIT	#rtwork,#tenth		; at 9600, we need this one also
	call	300$			; xon the other side please
70$:	clr	r0			; success
	clr	xcwdone			; reset the i/o in progress flag

100$:	unsave	<r4,r3,r2,r1>		; pop registers and exit
	return				; bye


200$:	mov	#1	,xcwdone	; flag ast level completion
	return				; and exit


300$:	tst	xoffed			; did we xoff the other side?
	beq	310$			; no
	.WRITC	#xcwork,4(r5),#320$,#1,#0,#1 ; synch i/o this time please
310$:	clr	xoffed			; say no xoff's anymore please
	return

320$:	.byte	XON,0


clrxc:	.SPFUN	#rtwork,#XC.CONTROL,#CLRDRV,#0,#0,#1 ; clear the driver
	return


	.sbttl	cantyp	try to dump all typeahead


x.cantyp::
	save	<r1,r2>			; save temps
	mov	#200	,r2		; loop for no more than 128 characters
	mov	#xcrdbf	,xcpoint	; reset the pointer to the buffer
	clrb	@xcpoint		; stuff a null in please
10$:	calls	binrea	,<2(r5),#-1>	; try to get something
	tst	r0			; did it work ?
	bne	20$			; no, exit
	sob	r2	,10$		; yes, eat somemore characters
20$:	.ABTIO	2(r5)			; try to reinit the driver and exit
	call	clrxc			; this also please
100$:	unsave	<r2,r1>			; pop temp and exit
	clr	r0
	return				; bye


x.ttxon::
	call	clrxc			; get the driver to clear xoff status
	return


x.senbrk::
	.SPFUN	#rtwork,#XC.CONTROL,#BRKDRV,#0,#1,#1
	tst	brklen			; /43/ User set a BREAK length?
	beq	10$			; /43/ No
	mov	brklen	,break+2	; /43/ Yes, use it
10$:	.MRKT	#timwrk,#break,#20$,#20
	clr	r0
	return

20$:	.SPFUN	#rtwork,#XC.CONTROL,#BRKDRV,#0,#0,#1
	clr	r0
	return


;	Drop dtr for a moment, For RT11 5.2 only
;	Added 31-Dec-85  03:46:44 Edit 2.41

	.enabl	lsb

x.ttyhan::
x.ttydtr::
	save	<r1>			; /41/ Save a register
	mov	(r5)	,r1		; /44/ Get device name address in R1
	call	mapxl			; /44/ See if device names maps
	bcs	100$			; /44/ No, so exit
	mov	r0	,r1		; /44/ Point to it
10$:	calls	fetch	,<@r1>		; /41/ Insure handler is loaded
	.LOOKUP	#rtwork,#XC.AUX,r1	; /41/ Now open it up
	bcs	90$			; /41/ Oops, should not happen
	.SPFUN	#rtwork,#XC.AUX,#DTRDRV,#0,#0,#1 ;/41/ Now DROP DTR
	.TWAIT	#rtwork,#dtrlow			 ;/41/ And let it stay low for
	.TWAIT	#rtwork,#dtrlow			 ;/41/ And let it stay low for
	.TWAIT	#rtwork,#dtrlow			 ;/41/ And let it stay low for
	.SPFUN	#rtwork,#XC.AUX,#DTRDRV,#0,#1,#1 ;/41/ while, then bring it up
	.CLOSE	#XC.AUX			; /41/ Close controlling channel
	br	100$
90$:	movb	@#52	,r1
	message	<Error from .lookup >
	decout	r1
	message
100$:	unsave	<r1>			; /41/ Pop saved register
	clr	r0			; /41/ Assume that it worked
	return				; /41/ And exit

	.dsabl	lsb


	.sbttl	parse terminal unit


;	T T P A R S
;
;	input:	@r5	address of RT11 Multiple terminal service unit string
;	output:	r0	unit in binary


x.ttpars::
	clr	r0			; always unit zero for PRO/RT
	return



	.sbttl	GTTNAM	get MT unit of current console (set tt:consol=nn)

;	G T T N A M
;
;	input:	@r5	address of console name to be written
;	output:	@r5	current console name
;		consave	same thing

x.gttnam::
	mov	@r5	,r0		; for PRO/RT, always return TT:
	movb	#'T&137	,@r0
	movb	(r0)+	,consave
	movb	#'T&137	,@r0
	movb	(r0)+	,consave+1
	movb	#':	,@r0
	movb	(r0)+	,consave+2
	clrb	@r0
	clrb	consave+3
	clr	r0
	return


	global	<consave>



	.sbttl	terminal i/o things we don't need, can't do or haven't done yet

;	Edit:	/54/ Remove ASL R3 to get correct speed indexing

x.setspd::
	clr	xkspeed			; /52/ No saved speed now
	tst	tsxcl			; /44/ TSX+ and CL ?
	beq	110$			; /44/ No can do if not
	save	<r1,r2,r3>		; /44/ Save a register or three
	clr	r3			; /44/ Match passed speed in table
10$:	tst	splst(r3)		; /44/ End of the speed table ?
	beq	90$			; /44/ Yes, exit please
	cmp	splst(r3),2(r5)		; /44/ Speeds match up ?
	beq	20$			; /44/ Yes, exit loop
	tst	(r3)+			; /44/ No, try next entry then
	br	10$			; /44/ Next please
20$:	mov	(r5)	,r1		; /44/ Get device name address in R1
	call	mapxl			; /44/ See if device names maps
	bcs	100$			; /44/ No, so exit
	mov	r0	,r1		; /44/ Point to it
	calls	fetch	,<@r1>		; /44/ Insure handler is loaded
	.LOOKUP	#rtwork,#XC.AUX,r1	; /44/ Now open it up
	bcs	100$			; /44/ Oops, should not happen
	add	#spmap	,r3		; /45/ for the speed
	.SPFUN	#rtwork,#XC.AUX,#CLSPEED,r3,#1,#0 ; /45/ Address NOT value
	bcs	40$			; /52/ Oops
	mov	(r3)	,xkspeed	; /52/ Save it please
40$:	.CLOSE	#XC.AUX			; /44/ Close controlling channel
	br	100$			; /44/ Exit
90$:	mov	#ER$SPE	,r0		; /44/ Return UNKNOWN speed
100$:	unsave	<r3,r2,r1>		; /44/ Pop saved registers
	clr	r0			; /44/ Assume that it worked
	return				; /44/ And exit

110$:	mov	#377	,r0
	return




x.ttsp::clr	r0			; /54/ Presume failure
	tst	tsxcl			; /54/ CL and TSX+
	beq	100$			; /54/ No
	mov	xkspeed	,r0		; /54/ Get from last SET SPEED
	asl	r0			; /54/ Word indexing
	mov	splst-2(r0),r0		; /54/ Copy and exit
100$:	return				; /54/ Bye

x.ttset::
x.ttrfin::
x.ttrini::
	clr	r0
	return



	.mcall	.TTYIN
	jsw	=	44

x.kbread::
	mov	r2	,-(sp)
	mov	r3	,-(sp)
	bis	#40000	,@#jsw		; enable lower case tt: input
	tst	tsxcl			; tsx and cl?
	beq	5$			; nope
	bic	#10000!100,@#jsw	; ditch single ch input and wait
	br	7$			; jump ahead

5$:	bic	#10000	,@#jsw		; ditch single ch input please

7$:	mov	@r5	,r1		; a buffer to put the chars
	mov	#80.	,r3		; size of the buffer here
;10$:	.SCCA	#area	,#kmonbf	; so we can catch control Z
10$:	.TTYIN				; read a character please
	tstb	r0
	beq	15$			; a null
	cmpb	r0	,#'Z&37		; control Z ?
	beq	20$			; yes
	cmpb	r0	,#'C&37		; control C ?
	beq	20$			; yep
	cmpb	r0	,#15		; carriage return ?
	beq	30$			; yep
	movb	r0	,(r1)+		; return what we just got
	cmpb	r0	,#14		; form feed ?
	beq	40$			; yep
15$:	sob	r3	,10$		; next please
20$:	mov	#ER$EOF	,r0		; say read error and exit
	br	100$			; bye
30$:	movb	#cr	,(r1)+		; return all terminators please
	movb	#lf	,(r1)+		; simple
	.TTYIN				; eat the line feed now
40$:	clrb	@r1
	sub	@r5	,r1		; the length
	clr	r0
100$:	mov	(sp)+	,r3
	mov	(sp)+	,r2
	return



	.end
