Google
 

Trailing-Edge - PDP-10 Archives - BB-BT99V-BB_1990 - 10,7/anf10/dntty.p11
There are 5 other files named dntty.p11 in the archive. Click here to see a list.
.SBTTL	DNTTY - TERMINAL ROUTINES  02-AUG-89

;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED
;  OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION
; 1976,1977,1978,1979,1980,1981,1982,1983,1984,1987,1988,1990.
;ALL RIGHTS RESERVED.

VRTTY=123			;FILE EDIT NUMBER



.IF NE <FT.CTY+TTYN+RDAN>


;DB.DCS STATUS BITS FOR TTY SERVICE

	TS.DFE=1	;DEFERED ECHO MODE
	TS..LC=2	;TRANSLATE LOWER CASE TO UPPER
	TS.FRZ=4	;OUTPUT HAS BEEN FROZEN BY TYPEIN OF XOF
	TS.IMI=10	;IMAGE MODE INPUT
	TS.IMO=20	;IMAGE MODE OUTPUT
	TS.PAG=40	;TTY PAGE IN EFFECT
	TS.TAP=100	;TTY TAPE FEATURE(IMPLIES SUPPRESS NORMAL CR HANDLING)
	TS.TAB=200	;TTY HAS HDW TAB
	TS.FRM=400	;TTY HAS HDW FORM FEED
	TS.8BI=1000	;8-BIT INPUT MODE
;	=2000		;FREE BIT
	TS.CRL=4000	;NO AUTO CR/LF ON LINE OVERFLOW
	TS.DTR=10000	;DATA TERMINAL READY
	TS.RNG=20000	;RING
	TS.CAR=20000	;CARRIER
;	=40000		;FREE BIT
;	=100000		;FREE BIT

	TS.RCN=TS..LC!TS.PAG!TS.TAB!TS.FRM!TS.CRL!TS.DTR!TS.RNG!TS.CAR  ;BITS TO PRESERVE ON A RECONNECT


;DB.DVT DEVICE-TYPE BITS FOR TTY SERVICE

	TT.DSL=B0		;DATASET LINE
	TT.ABD=B1		;AUTOBAUD THIS LINE
	TT.CSB=B2		;CAN SET BAUD RATE
;	=B3			;FREE BIT
;	=B4			;FREE BIT
	TT.801=B5		;AUTO-DIAL LINE
	TT.CSH=B6		;CAN SET HOST
	TT.RIC=B7		;RUN INITIA CUSP (IGNORED BY -10)
	TT.ABR=B8		;AUTOBAUD REQUESTABLE
	TT.8BL=B9		;8-BIT LINE (BY DEFAULT)


.IIF NDF,ESCF,ESCF=176			;NOTE, ESCF CANNOT BE > 177
;MACRO TO MAKE DEVICE DEPENDENT PORTION OF DEVICE BLOCK FOR TTY'S
.MACRO	SETLCB	QLCB
	.WORD	LCB'QLCB		;DB.LCB
.ENDM


.MACRO	DDXGEN	DEV,DV,DRQ,XBITS,XZZ
	ZZZ=1
	.REPT	NXTDH&17
		ZZZ=ZZZ*2
	.ENDR
	.WORD	ZZZ		;DB.BIT
	.BYTE	17&NXTDH		;DB..LN
Z=0
	.IF NDF	DV'XZZ'XS
		.IIF DF DEV'XS,DV'XZZ'XS=DEV'XS
	.ENDC
	.IF NDF	DV'XZZ'XS
		Z=LCB.AB		;AUTO BAUD LINE
		ZZXS=R.HSPD		;SCAN AT 2400 BAUD
	.IFF
		ZZXS=DV'XZZ'XS
		.IIF NE ZZXS-R.HSPD,DV'XZZ'ABD=0 ;NO AUTOBAUD AT WRONG SPEED
		.IIF DF DV'XZZ'ABD,.IIF NE DV'XZZ'ABD, Z=LCB.AB
	.ENDC
	.IF NDF DV'XZZ'RS
		.IIF DF	DEV'RS,DV'XZZ'RS=DEV'RS
	.ENDC
	.IIF NDF DV'XZZ'RS,ZZRS=ZZXS
	.IIF DF DV'XZZ'RS,ZZRS=DV'XZZ'RS
	.IF NE ZZRS-R.HSPD
		Z=Z&<^C<LCB.AB>>
		DV'XZZ'ABD=0
	.ENDC
	.MACRO	DHSSET	LINE
		ZZS=0
		.IIF DF DV'XZZ'XS,ZZS=1
		.IIF DF DV'XZZ'RS,ZZS=1
		.IF NE ZZS
			SPD	ZZXS,ZZRS	;CALCULATE LINE SPEED
			DHS'LINE=QQ
		.ENDC
	.ENDM	DHSSET
	DHSSET	\NXTDH
	.IIF DF DV'XZZ'DSL,.IIF NE DV'XZZ'DSL,	Z=Z!LCB.DS
	.MACRO	DHCSET	LINE
		DHC'LINE=Z
	.ENDM	DHCSET
	.MACRO	DHZSET	LINE
		DHZ'LINE=LCS.VG
		.IF EQ Z&LCB.DS
			DHZ'LINE=LCS.AB
			.IF EQ Z&LCB.AB
				DHZ'LINE=LCS.RU
			.ENDC
		.ENDC
	.ENDM
	DHCSET	\NXTDH
	DHZSET	\NXTDH
	.BYTE	12,12,20,12,12,12	;DB.FIL
	.BYTE	0			;DB.EPL
		SETLCB	\NXTDH		;DB.LCB
		DHINDX=DHINDX+1
.IF NE FTDN11
	Z=0
	.IF DF DV'XZZ'801
		Z=DV'XZZ'801
	.ENDC
	.BYTE	Z		;DB.DNS (DN11 STATUS)
	.BYTE	0		;DB.DNT (DN11 TIMER)
.ENDC;.IF NE FTDN11
	.WORD	0		;DB.TTS (TTY STATUS WORD)
	.BLKB	<DB.TSZ-DB.TZR>
	.EVEN
.ENDM	DDXGEN
NXTDZ=-1	;
NXTDH=-1	;LOCATE FIRST TTY LINE

DRESET=0
ASYDEV=ASY.DH	;BUILD DH LINES FIRST
	DDBGEN	TTY,T,TTYDHN,TTYDRQ,<DS.TTY!DS.OUT>	;MAKE DEVICE BLOCKS FOR TTYS
ASYDEV=ASY.DZ	;NOW DZ LINES
DRESET=1	;DONT BUILD NEW SYMBOLS
.MACRO	DDXGEN	DEV,DV,DRQ,XBITS,XZZ
	ZZZ=1
	.REPT	NXTDZ&7
		ZZZ=ZZZ*2
	.ENDR
	.WORD	ZZZ		;DB.BIT
	.BYTE	7&NXTDZ		;DB..LN
Z=0
	.IF NDF	DV'XZZ'XS
		.IIF DF DEV'XS,DV'XZZ'XS=DEV'XS
	.ENDC
	.IF NDF	DV'XZZ'XS
		Z=LCB.AB		;AUTO BAUD LINE
		ZZXS=R.HSPD		;SCAN AT 2400 BAUD
	.IFF
		ZZXS=DV'XZZ'XS
		.IIF NE ZZXS-R.HSPD,DV'XZZ'ABD=0 ;NO AUTOBAUD AT WRONG SPEED
		.IIF DF DV'XZZ'ABD,.IIF NE DV'XZZ'ABD, Z=LCB.AB
	.ENDC
	.IF NDF DV'XZZ'RS
		.IIF DF	DEV'RS,DV'XZZ'RS=DEV'RS
	.ENDC
	.IIF NDF DV'XZZ'RS,ZZRS=ZZXS
	.IIF DF DV'XZZ'RS,ZZRS=DV'XZZ'RS
	.IF NE ZZRS-R.HSPD
		Z=Z&<^C<LCB.AB>>
		DV'XZZ'ABD=0
	.ENDC
	.MACRO	DZSSET	LINE
		ZZS=0
		.IIF DF DV'XZZ'XS,ZZS=1
		.IIF DF DV'XZZ'RS,ZZS=1
		.IF NE ZZS
			SPD	ZZXS,ZZRS	;CALCULATE LINE SPEED
			DZS'LINE=QQ
		.ENDC
	.ENDM	DZSSET
	DZSSET	\NXTDZ
	.IIF DF DV'XZZ'DSL,.IIF NE DV'XZZ'DSL,	Z=Z!LCB.DS
	.MACRO	DZCSET	LINE
		DZC'LINE=Z
	.ENDM	DZCSET
	.MACRO	DZZSET	LINE
		DZZ'LINE=LCS.VG
		.IF EQ Z&LCB.DS
			DZZ'LINE=LCS.AB
			.IF EQ Z&LCB.AB
				DZZ'LINE=LCS.RU
			.ENDC
		.ENDC
	.ENDM
	DZCSET	\NXTDZ
	DZZSET	\NXTDZ
	.BYTE	12,12,20,12,12,12	;DB.FIL
	.BYTE	0			;DB.EPL
		SETLCB	\<NXTDZ+<NDH11*20>>  ;DB.LCB
		DZINDX=DZINDX+1
.IF NE FTDN11
	Z=0
	.IF DF DV'XZZ'801
		Z=DV'XZZ'801
	.ENDC
	.BYTE	Z		;DB.DNS (DN11 STATUS)
	.BYTE	0		;DB.DNT (DN11 TIMER)
.ENDC;.IF NE FTDN11
	.WORD	0		;DB.TTS (TTY STATUS WORD)
	.BLKB	<DB.TSZ-DB.TZR>
	.EVEN
.ENDM	DDXGEN
	DDBGEN	TTY,T,TTYDZN,TTYDRQ,<DS.TTY!DS.OUT>
.MACRO	DDXGEN	DEV,DV,DRQ,XBITS,XZZ
	ZZZ=1
	.REPT	NXTDH&17
		ZZZ=ZZZ*2
	.ENDR
	.WORD	ZZZ		;DB.BIT
	.BYTE	17&NXTDH		;DB..LN
Z=0
	.BYTE	12,12,20,12,12,12	;DB.FIL
	.BYTE	0		;DB.EPL
	.WORD	CT0LDB	;DUMMY LINE CONTROL BLOCK
.IF NE FTDN11
	Z=0
	.IF DF DV'XZZ'801
		Z=DV'XZZ'801
	.ENDC
	.BYTE	Z		;DB.DNS (DN11 STATUS)
	.BYTE	0		;DB.DNT (DN11 TIMER)
	.WORD	CT'XZZ'DDB+DB.TSZ	;CTY HAS NO DATASET FUNCTION
.ENDC
	.WORD	0		;DB.TTS (TTY STATUS WORD)
	.BLKB	<DB.TSZ-DB.TZR>
	.EVEN
.ENDM	DDXGEN
.IF NE FT.CTY
	DRESET=0
	NXTDH=0		;CTY ISN'T A DH DEV SO FAKE IT
.IF NDF CTYRNN
	.IIF DF TTYRNN,CTYRNN=TTYRNN	;SAME RESTRICTIONS AS TTYS
.ENDC
	DDBGEN	CTY,CT,1,TTYDRQ,<DS.OUT!DS.TTY>	;MAKE A DEVICE BLOCK FOR THE CTY
.ENDC
.IF NE FT.RDA		; IF WE HAVE IT, IT IS THE SAME
.MACRO	DDXGEN	DEV,DV,DRQ,XBITS,XZZ
	ZZZ=1
	.REPT	NXTDH&17
		ZZZ=ZZZ*2
	.ENDR
	.WORD	ZZZ		;DB.BIT
	.BYTE	17&NXTDH		;DB..LN
Z=0
	.IF NDF	DV'XZZ'XS
		.IIF DF DEV'XS,DV'XZZ'XS=DEV'XS
	.ENDC
	.IF NDF	DV'XZZ'XS
		ZZXS=R.HSPD		;SCAN AT 2400 BAUD
	.IFF
		ZZXS=DV'XZZ'XS
	.ENDC
	.IF NDF DV'XZZ'RS
		.IIF DF	DEV'RS,DV'XZZ'RS=DEV'RS
	.ENDC
	.IIF NDF DV'XZZ'RS,ZZRS=ZZXS
	.IIF DF DV'XZZ'RS,ZZRS=DV'XZZ'RS
	.MACRO	DHSSET	LINE
		ZZS=0
		.IIF DF DV'XZZ'XS,ZZS=1
		.IIF DF DV'XZZ'RS,ZZS=1
		.IF NE ZZS
			SPD	ZZXS,ZZRS	;CALCULATE LINE SPEED
			DHS'LINE=QQ
		.ENDC
	.ENDM	DHSSET
	DHSSET	\NXTDH
	.IIF DF DV'XZZ'DSL, .IIF NE DV'XZZ'DSL,	Z=Z!LCB.DS
	.MACRO	DHCSET	LINE
		DHC'LINE=Z
	.ENDM	DHCSET
	.MACRO	DHZSET	LINE
		DHZ'LINE=LCS.VG
		.IF EQ Z&LCB.DS
			DHZ'LINE=LCS.AB
			.IF EQ Z&LCB.AB
				DHZ'LINE=LCS.RU
			.ENDC
		.ENDC
	.ENDM
	DHCSET	\NXTDH
	DHZSET	\NXTDH
	.BYTE 	0,0,0,0,0,0		;DB.FIL
	.BYTE	0			;DB.EPL
		SETLCB	\NXTDH		;DB.LCB
		DHINDX=DHINDX+1
.IF NE FTDN11
	Z=0
	.IF DF DV'XZZ'801
		Z=DV'XZZ'801
	.ENDC
	.BYTE	Z		;DB.DNS (DN11 STATUS)
	.BYTE	0		;DB.DNT (DN11 TIMER)
.ENDC
	.WORD	0		;DB.TTS (STATUS)
	.BLKB	<DB.TSZ-DB.TZR>
	.EVEN
.ENDM	DDXGEN
ASYDEV=ASY.DH
DRESET=0
NXTDH=-1		; START WITH RIGHT LINE NUMBER

DDBGEN	RDA,D,RDADHN,RDADRQ,<DS.OUT>

.MACRO	DDXGEN	DEV,DV,DRQ,XBITS,XZZ
	ZZZ=1
	.REPT	NXTDZ&7
		ZZZ=ZZZ*2
	.ENDR
	.WORD	ZZZ		;DB.BIT
	.BYTE	7&NXTDZ		;DB..LN
Z=0
	.IF NDF	DV'XZZ'XS
		.IIF DF DEV'XS,DV'XZZ'XS=DEV'XS
	.ENDC
	.IF NDF	DV'XZZ'XS
		ZZXS=R.HSPD		;SCAN AT 2400 BAUD
	.IFF
		ZZXS=DV'XZZ'XS
	.ENDC
	.IF NDF DV'XZZ'RS
		.IIF DF	DEV'RS,DV'XZZ'RS=DEV'RS
	.ENDC
	.IIF NDF DV'XZZ'RS,ZZRS=ZZXS
	.IIF DF DV'XZZ'RS,ZZRS=DV'XZZ'RS
	.MACRO	DZSSET	LINE
		ZZS=0
		.IIF DF DV'XZZ'XS,ZZS=1
		.IIF DF DV'XZZ'RS,ZZS=1
		.IF NE ZZS
			SPD	ZZXS,ZZRS	;CALCULATE LINE SPEED
			DZS'LINE=QQ
		.ENDC
	.ENDM	DZSSET
	DZSSET	\NXTDZ
	.IIF DF DV'XZZ'DSL, .IIF NE DV'XZZ'DSL,	Z=Z!LCB.DS
	.MACRO	DZCSET	LINE
		DZC'LINE=Z
	.ENDM	DZCSET
	.MACRO	DZZSET	LINE
		DZZ'LINE=LCS.VG
		.IF EQ Z&LCB.DS
			DZZ'LINE=LCS.AB
			.IF EQ Z&LCB.AB
				DZZ'LINE=LCS.RU
			.ENDC
		.ENDC
	.ENDM
	DZCSET	\NXTDZ
	DZZSET	\NXTDZ
	.BYTE 	0,0,0,0,0,0		;DB.FIL
	.BYTE	0			;DB.EPL
		SETLCB	\<NXTDZ+<NDH11*20>>  ;DB.LCB
		DZINDX=DZINDX+1
.IF NE FTDN11
	Z=0
	.IF DF DV'XZZ'801
		Z=DV'XZZ'801
	.ENDC
	.BYTE	Z		;DB.DNS (DN11 STATUS)
	.BYTE	0		;DB.DNT (DN11 TIMER)
.ENDC
	.WORD	0		;DB.TTS (STATUS)
	.BLKB	<DB.TSZ-DB.TZR>
	.EVEN
.ENDM	DDXGEN
ASYDEV=ASY.DZ
DRESET=1
NXTDZ=-1
DDBGEN	RDA,D,RDADZN,RDADRQ,<DS.OUT>
.ENDC; .IF NE FT.RDA




.MACRO	DDXGEN	DEV,DV,DRQ,XBITS,XZZ	;REDEFINE FOR NEXT DEVICE
.ENDM	DDXGEN
.IF NE FT.TSK

.IIF NE FT.CTY,	.WORD	CTYDDB	;ADDRESS OF DEVICE BLOCK FOR CTY IS ENTRY "-1"

TTYTAB:

.MACRO	X	ART,ARG,ARX,ARY
	.IF EQ D'ART'L'ARG'-1
		.WORD	T'ARX'DDB
		ZTTY=ZTTY+1
	.IFF
		.IF EQ D'ART'L'ARG'-6
			.WORD	D'ARY'DDB
			ZRDA=ZRDA+1
		.IFF
			.WORD 	0
		.ENDC
	.ENDC
.ENDM

ZTTY=0			;START WITH TTY0 DDB
ZRDA=0			;START WITH RDA0 DDB

Z=0			;INITIALIZE INDEX FOR DH11

.REPT	DHLINE
	X	H,\Z,\ZTTY,\ZRDA
	Z=Z+1
.ENDR

Z=0			;RESET DZ11 LINE INDEX

.REPT	DZLINE
	X	Z,\Z,\ZTTY,\ZRDA
	Z=Z+1
.ENDR

.ENDC ;.IF NE FT.TSK
.IF NE FT.CTY

CT0LDB:	.WORD	0		;LC.CAR	DUMMY LDB FOR CTY
	.BYTE	LCS.RU		;LC.STA	LINE IS RUNNING
	.BYTE	0		;LC.MOD
	.WORD	B.300		;LC.SPD	300 BAUD
	.WORD	B.300		;LC.PSP	300 BAUD
	.WORD	CT0DDB		;LC.BLK
	.WORD	CTIINT		;LC.INS
	.WORD	CTOINT		;LC.OUS
	.IF NE NDZ11
		.WORD	0	;LC.CNT
		.WORD	0	;LC.BUF
	.ENDC

.ENDC
CTYSER:
TTYSER:	CMP	#TTYMML,DB.MML(J)	;DID HANDLER GIVE REASONABLE SIZE MSG ?
	BPL	10$			;IF SO USE IT
	MOV	#TTYMML,DB.MML(J)	;USE OUR SIZE CAUZ IT'S SMALLER
10$:	MOVB	#DCM.AS,DB.DCM(J)	;SET DATA CODE AND MODE
	MOVB	DB.TYP(J),R0		;GET ASYNC CONTROLLER TYPE
	ASR	R0			;MAKE INTO DIRECT VALUE (NOT INDEX)
.IF NE FT.CTY
	CMP	#CT0DDB,J		;IS THIS THE CTY?
	BEQ	11$			;YES,
.ENDC ;.IF NE FT.CTY
	INCB	R0			;NO,
11$:	INCB	R0			;CTY = 1; DH-11 = 2; DZ-11 = 3
	MOVB	R0,DB.DVV(J)		;SET CONTROLLER TYPE
	JSR	PC,DVCCFM		;SEND CONNECT CONFIRM
	BIT	#DS.CON,@J		;CONNECTED ?
	BNE	20$
	RTS	PC
20$:	JSR	PC,DVXDRQ		;SEND SOME DATA REQUESTS
	TST	DB.OBF(J)		;DID 10 SEND DATA ?
	BNE	TOGMSG
	JMP	TTYICK
;HERE TO OUTPUT THE "ESCAPE FUNCTION" CHARACTER

TOGESC:	JSR	PC,QTECHR		;QUEUE TWO OF 'EM SO THAT ONE
	BR	TOGMSG			;WILL ACTUALLY GET PRINTED


;START OF SUBMESSAGE, DISPATCH BASED ON MESSAGE TYPE

TOGMS1:	CMP	R0,#4			;MESSAGE MUST BE IN 0..4
	BHI	TOGBAD			;IF NOT, WE COMPLAIN (ACTUALLY 1..4)
	ASL	R0			;WORD INDEX
	JMP	@10$(R0)		;DISPATCH ON MESSAGE TYPE

10$:	TOGBAD				;00 - INVALID MESSAGE
	TOGMSG				;01 - DATA WITHOUT EOM
	TOGMSG				;02 - DATA WITH EOM
	TOGSTS				;03 - STATUS
	TOGCTL				;04 - CONTROL

;HERE WHEN WIN A DATA CHAR

TOGCHR:	CMP	R0,#ESCF		;IS THIS FUNCTION FLAG?
	BEQ	TOGESC			;YES, SPECIAL PROCESSING
	JSR	PC,QTYCHR		;QUEUE CHAR TO BE TYPED
TOGMSG:	JSR	PC,DVGBYT		;GET NEXT BYTE FROM THE NCL MESSAGE
	  BR	TOGCHR			;WON A DATA CHARACTER
	  BR	TOGMS1			;WON A MESSAGE TYPE
	  JMP	TOGDON			;ALL OUT OF MESSAGE


;HERE ON BAD MESSAGE TYPE OR FORMAT

TOGBAD:
.IF EQ DGUTS
	TRAP				;ILLEGAL MSG TYPE
.IFF
	CTYMSG	NCL
32$:	JSR	PC,DVGBYT		;GET NEXT BYTE OF MSG
	  BR	32$			;EAT BAD MSG
	  BR	TOGMS1			;TRY AGAIN WITH NEXT MSG
	  JMP	TOGDON			;ALL DONE
.ENDC
;HERE WHEN WE RECEIVE A STATUS MESSAGE

TOGSTS:	JSR	PC,DVGDBY		;GET CODE IN STATUS MSG
10$:	MOV	R0,-(P)			;SAVE CODE
	JSR	PC,DVGEXF		;GET BITS TO SET/CLEAR
	ASSERT	EQ DB.OCN(J)		;MAKE SURE NOTHING LEFT OVER
	MOV	(P)+,R1			;GET CODE AGAIN
	MOV	DB.DCS(J),-(P)		;SAVE CURRENT STATUS
	BIT	#TS.DTR,R0		;IF IT'S DTR
	BEQ	40$			; AND
	CMP	#2,R1			;HE WANTS IT CLEAR
	BNE	40$			; SKIP IF NOT "CLEAR"
	SAVE	<R1>			;GET A TEMP FOR A BIT
	BIT	#TS.FRZ,R0		;IS TEN CLEARING XOFF
	BEQ	15$			;NO,ONWARD
	SAVE	<R0,R2,R3,R4,R5>	;YES,SAVE SOME ACS
	JSR	PC,BEGXMT		;START OUTPUT
	RESTORE	<R5,R4,R3,R2,R0>	;RESTORE ACS
15$:	MOV	DB.LCB(J),R1		;GET POINTER TO THE LCB
	BEQ	35$			;GET OUT IF NO LCB
	ADD	#LC.STA,R1		;POINT TO DATASET STATE BYTE
	CMPB	#LCS.RC,@R1		;RUNNING NORMALLY?
.IF NE FTDN11
	BEQ	27$			;YES, -10 WANTS US TO HANG UP
	CMPB	#LCS.DL,@R1		;NO, DIALING OUT?
	BEQ	27$			;YES, -10 APPARENTLY WANTS TO ABORT
	CMPB	#LCS.DS,@R1		;DIALING OUT SUCCESSFUL?
.ENDC;.IF NE FTDN11
	BNE	35$			;YES, -10 STILL WANTS TO ABORT
27$:	MOVB	#LCS.HA,@R1		;FORCE DATASET TO HANG UP
35$:	RESTORE	<R1>			;GET SET/CLEAR BACK (IT'S CLEAR)
40$:	BIC	#TS.DTR!TS.CAR,R0	;IGNORE -10'S OPINION OTHERWISE
42$:	BIT	#TS.ESC,R0		;SET OR CLEAR IMAGE OUTPUT?
	BEQ	60$			;NO, ACT NORMALLY
	SAVE	R0			;SAVE BITS TO SET/CLEAR
	SAVE	R1			;PRESERVE ORIGINAL SET/CLEAR CODE
	DEC	R1			;MAKE SET=0 AND CLEAR=1
	SAVE	R1			;PRESERVE THAT AS WELL
	MOV	R0,R1			;COPY THE BITS TO TEST
	MOV	#MAXESC,R0		;START WITH THE MAXIMUM VALID INDEX
44$:	BIT	R1,ESCTAB(R0)		;CHECK IF THIS BIT IS TO BE TWEAKED
	BEQ	45$			;SKIP THIS NONSENSE IF NOT
	ADD	@P,R0			;YES, MAKE SURE OF THE FUNCTION CODE
	JSR	PC,QTECHR		;PUT IT INTO THE OUTPUT STREAM
	SUB	@P,R0			;RESTORE THE TABLE INDEX
45$:	SUB	#2,R0			;INDEXING THE TABLE TWO AT A TIME
	BPL	44$			;UNTIL OFF THE TOP
	TST	(SP)+			;POP JUNK
	RESTOR	R1			;RETRIEVE SET/CLEAR CODE
	RESTOR	R0			;GET BITS TO SET/CLEAR BACK

;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE

;DO "SET" BITS IF REQUESTED

60$:	CMP	#1,R1			;DOES HE WANT A SET BITS ?
	BNE	70$
	BIS	R0,DB.DCS(J)		;SET BITS
	BR	90$			;AND NOW DONE


;DO "CLEAR" BITS IF REQUESTED

70$:	CMP	#2,R1			;WANT TO CLEAR BITS ?
	BNE	80$
	BIC	R0,DB.DCS(J)		;CLEAR THE BITS LIKE BEFORE
	BR	90$			;NOW DONE


;NOT "SET" OR "CLEAR" BITS

80$:
.IF EQ DGUTS
	TRAP
.IFF
	TST	(P)+			;GET STACK BACK INTO SYNC
	CTYMSG	NCL			;LOG BAD NCL MSG ERROR
	RTS	PC			;AND EXIT
.ENDC ;.IF EQ DGUTS


;SEE IF ANYTHING CHANGED, TELL THE -10 IF NEEDED

90$:	TRACE	DV
	MOV	DB.DCS(J),R0		;COPY OF NEW STATUS
	BIC	#TS.DTR!TS.CAR,(P)	;IGNORE DTR AND CAR (THIS IS TO AVOID
	BIC	#TS.DTR!TS.CAR,R0	; A STATUS MESSAGE WAR WITH THE -10)
	CMP	R0,(P)+			;DID DEVICE CONTROL STATUS CHANGE?
	BEQ	95$			;NO, ALL SET
	BIS	#DS.XDS,@J		;YES, SEND -10 OUR NEW STATUS
95$:	BR	TOGMSG
;HERE WHEN WE RECEIVE A CONTROL MESSAGE

TOGCTL:	JSR	PC,DVGDBY		;GET DCT BYTE
52$:	CMP	R0,#5			;DCT ALSO CAN'T BE TOO BIG
	BHI	TOGBAD			;DCT MUST BE IN RANGE 0..5
	ASL	R0			;WORD INDEX
	JSR	PC,@54$(R0)		;DISPATCH ON DCT CODE
	BR	TOGMSG			;FIRE UP ANOTHER MESSAGE

54$:	TOGC00				;00 - ECHO PIPELINE MARKER
	TOGC01				;01 - CHARACTER GOBBLER
	TOGC02				;02 - TTY CHARACTERISTICS
	TOGC03				;03 - AUTO DIAL
	TOGC04				;04 - XOFF REQUEST
	TOGC05				;05 - AUTOBAUD REQUEST



;HERE WHEN RECEIVE A DIAL-OUT REQUEST

TOGC03:
.IF NE FTDN11
	JSR	PC,DNSTRT		;START DIALING
	RTS	PC			;NOTHING MORE HERE
.IFF
	TST	(P)+			;POP RETURN ADDRESS
	BR	TOGBAD			;BUMMER
.ENDC



;HERE WHEN RECEIVE AN ECHO-PIPELINE MARKER

TOGC00:	JSR	PC,DVGDBY		;GO GET MARKER
	TST	DB.IBF(J)		;MORE STUFF PENDING ?
	BNE	99$			;IF SO CAN'T GO TO LOCAL ECHO
	CMPB	R0,DB.EPL(J)		;DOES IT MATCH LAST I SENT ?
	BNE	99$			;IF NOT IGNORE IT
	BIC	#TS.DFE,DB.DCS(J)	;BACK INTO LOCAL ECHO MODE
	BIS	#DS.XDS,(J)		;SEND NEW STATUS TO HOST
99$:	RTS	PC			;ALL DONE HERE



;HERE TO SEND AN XOFF MSG ASAP

TOGC04:	JSR	PC,SNDXOF		;SEND XOFF RIGHT AWAY
	BIC	#DS.IST,@J		;LET THE -10 GENERATE THE XON
	RTS	PC			;AND KEEP WORKING
;HERE WHEN RECEIVE A CHARACTER GOBBLER

TOGC01:	PIOFF				;DISABLE INTERRUPTS FOR A WHILE
	MOV	DB.TOB(J),R0		;GET POINTER TO OUTPUT CHARS
	MOV	DB.TOB+2(J),R1		;SAVE END POINTER ALSO
	CLR	DB.TOC(J)		;ZERO OUTPUT COUNT
	CLR	DB.TOB(J)		;NO OUTPUT TAKER
	CLR	DB.TOB+2(J)		;AND NO TAKER
	PION				;REENABLE INTERRUPTS
	BIC	#TS.FRZ,DB.DCS(J)	;START OUTPUT IF STOPPED
	MOV	R1,-(SP)		;MOVE TO A MORE CONVENIENT PLACE
	TST	R0
	BEQ	40$
10$:	CMP	R0,(P)			;WAS THAT LAST CHARACTER TO THROW AWAY?
	BEQ	30$			;YES, WE'RE DONE
	ADVCNK	R0,FREE			;ADVANCE A FREE CHUNK (IF NECESSARY)
	MOVB	(R0)+,R1		;GET NEXT CHARACTER
	CMP	R1,#ESCF		;IS IT FUNCTION ESCAPE CHARACTER?
	BNE	10$			;NO, KEEP FLUSHING
	ADVCNK	R0,FREE			;ADVANCE CHUCKS, IF NEEDED
	MOVB	(R0)+,R1		;GET FUNCTION CODE
	JSR	PC,DOESCF		;PERFORM FUNCTION
	BR	10$			;AND CONTINUE FLUSHING

30$:	DEC	R0			;ENSURE WE HAVEN'T RUN OFF CHUNK
	BIC	#CNKSIZ-1,R0		;FREE REST OF LIST
	JSR	PC,FRECKS		;FRECK IT!
40$:	TSTB	(P)+			;CLEAN UP STACK
	RTS	PC			;BACK FOR MORE MESSAGES
;HERE WHEN RECEIVE A CHARACTERISTICS MESSAGE
TOGC02:	MOV	J,R2			;COPY DEVICE BLOCK POINTER
	ADD	#DB.FIL,R2		;POINT TO FILLER SECTION
	MOV	#6,R3			;COUNTER
66$:	JSR	PC,DVGEXF		;GET AN EXTENSIBLE FIELD
	CLC				;NEED LOGICAL SHIFT (DIVIDE BY 2)
	ROR	R0			;GET FILL TIME AS SEC/500
	BEQ	67$			;IF 0 JUST USE IT
	ASR	R0			;GET FILL TIME AS SEC/250
	ADD	#4,R0			;FOR ROUND OFF
	BIT	#37000,R0		;IS TIME TOO LARGE FOR TICK TIMER
	BEQ	68$
	NEG	R0
	SWAB	R0			;GET FILL TIME IN SEC
	BR	67$
68$:	ASR	R0			;GET FILL TIME IN SEC/125
	ASR	R0			;GET FILL TIME IN SEC/62.5
67$:	MOVB	R0,(R2)+		;SAVE FILLER
	SOB	R3,66$			;LOOP BACK FOR REST OF FILLER
;NOW GET SPEED FROM CHARACTERISTICS MESSAGE
	JSR	PC,DVGEXF		;GET RECEIVE SPEED
.IF NE TTYN
	JSR	PC,75$			;CONVERT RECEIVE SPEED TO A DH11 CODE
	MOV	DB.LCB(J),R2		;POINT TO LINE CONTROL BLOCK
	MOV	LC.SPD(R2),R2		;GET INITIAL GUESS FOR SPEED
	MOV	R2,-(P)
	TST	R1			;CHECK SPEED TABLE INDEX FROM 75$
	BLT	72$			;IF DIDN'T FIND SPEED
	BIC	#^C377,R2		;MASK OUT JUNK
	SWAB	R1			;POSITION RECEIVE CODE IN "LH"
	BIS	R1,R2			;SET NEW RECEIVE SPEED IN OUR COPY
.ENDC
72$:	JSR	PC,DVGEXF		;GET TRANSMIT SPEED
.IF NE TTYN
	JSR	PC,75$			;CONVERT THAT TO A DH11 CODE
	TST	R1
	BLT	74$			;IF DIDN'T FIND SPEED
	BIC	#377,R2			;MASK OUT JUNK
	BIS	R1,R2			;PUT NEW SPEED IN OUR COPY
74$:	CMP	R2,(P)+			;SAME AS LAST SPEED ?
	BEQ	TYSR60			;IF SO IGNORE
	PIOFF
	MOV	R2,-(P)			;SAVE SPEED
	MOV	DB.LCB(J),R2		;POINT TO LCB
	CMPB	#LCS.AB,LC.STA(R2)	; AUTO BAUD ?
	BNE	73$			; NO
	MOVB	#LCS.RU,LC.STA(R2)	;SET TO RUN STATE
	BIC	#LCB.TM,LC.CAR(R2)	;CLEAR TIMER
73$:	JSR	PC,SETSPD		;SET NEW SPEED
	TST	(P)+			;POP THE SPEED
	PION
	BR	TYSR60
;HERE TO SEARCH SPEED TABLE FOR DH11 CODE
75$:	MOV	#SPDLIM-SPDTAB,R1	;MAKE SPEED TABLE INDEX
76$:	CMP	R0,SPDTAB(R1)		;CHECK FOR MATCH
	BEQ	78$
	SUB	#2,R1			;LOWER INDEX TO SPDTAB
	BPL	76$
78$:	ASR	R1			; FORM TRUE INDEX
	RTS	PC
.ENDC
TYSR60:	JSR	PC,DVGEXF		;GET WIDTH
	MOVB	R0,DB.WID(J)
	JSR	PC,DVGEXF		;GET AUTO CAR RETURN POSITION
	MOVB	R0,DB.ACR(J)
	JSR	PC,DVGEXF		;GET ELEMENT NUMBER
86$:	JSR	PC,DVGEXF		;GET 2741 BITS
	MOV	R0,DB.TTS(J)		;STUFF INTO DDB
	BIT	#TT.DFT,R0		;FORMS TYPE PRESENT?
	BEQ	99$			;NO, DON'T PROCESS IT
	TST	DB.OCN(J)		;ANY MORE IN THIS SUBMESSAGE?
	BEQ	99$			;NO--IT'S NOT REALLY THERE
	MOV	#DB.DFT,R2		;YES, GET ITS OFFSET
	ADD	J,R2			;THEN ITS ADDRESS
	MOV	#6,R3			;AND LIMIT OF CHARACTERS
91$:	JSR	PC,DVGDBY		;GET NEXT BYTE
	DEC	R3			;TEST AGAINST STORAGE LIMIT
	BMI	92$			;SKIP STORAGE IF RAN OUT
	MOVB	R0,(R2)+		;SAVE CHARACTER
92$:	TSTB	R0			;CHECK SIGN BIT
	BMI	91$			;LOOP OVER EXTENSIBLE ASCII
	BICB	#200,-(R2)		;MAKE SURE PROPERLY TERMINATED
99$:	ASSERT EQ DB.OCN(J)		;COUNT SHOULD BE 0 NOW
	RTS	PC			;BACK FOR MORE [SUB]MESSAGES
;HERE WHEN WE RECEIVE AN AUTOBAUD REQUEST

TOGC05:
.IF NE TTYN
	ASSERT EQ DB.OCN(J)		;COUNT SHOULD BE 0 NOW
	BIT	#TT.ABR,DB.DVT(J)	;CHECK FOR LEGALITY OF REQUEST
	BEQ	99$			;ILLEGAL--SEND SPEED BACK TO TEN NOW
	MOV	DB.LCB(J),R2		;GET LCB ADDRESS
	JSR	PC,SET.AB		;SETUP TO DO AUTOBAUD
	BIC	#DS.XCH,@J		;DON'T SEND CHARACTERISTICS YET
	RTS	PC			;BACK FOR MORE [SUB]MESSAGES

99$:	BIS	#DS.XCH,@J		;SEND CHARACTERISTICS TO TEN IF NO A/B
.ENDC ;.IF NE TTYN
	RTS	PC			;BACK FOR MORE [SUB]MESSAGES
TOGDON:	BIT	#DS.XDS,(J)		;SEND STATUS IF REQUIRED
	BEQ	20$
	JSR	PC,DVPDCS
20$:
.IF NE FT.TSK
	JSR	PC,TK0WAK		;WAKE 'GET PRINTER' TASK IF ANY
	MOV	J,R3			;COPY DDB ADDRESS
24$:	MOV	DB.TSK+6(J),J		;GET ADDRESS OF 'PUT KEYBOARD' TASK
	BEQ	26$
	JSR	PC,TSKWAK
26$:	MOV	R3,J			;RESTORE DDB ADDRESS
.ENDC
	JSR	PC,BEGXMT		;START TYPING
;HERE TO CHECK FOR INPUT TO GO TO THE 10
TTYICK:	BIT	#DS.ACT,@J		;UNLESS ACTIVE
	BNE	10$
	BIT	#DS.DIE!DS.DSC,(J)	;ARE WE DONE WITH THE CONNECTION
	BEQ	10$			;IF NOT, SEE IF THERE IS INPUT
	JMP	DVCCFM			;NO LONGER CONNECTED.  SEND
					;  DISCONNECT CONFIRM AND CLEAN DDB
10$:
.IF NE DN11N
.IF NE FT.RDA&FT.TSK
	TST	DB.RDT(J)		; CHECK FOR RDA DEVICE
	BEQ	17$			;  NO
	JSR	PC,DNSTTJ		; CHECK FOR AUTO DIAL ON DEVICE
	JSR	PC,RDXSTA		; CHECK STATUS
17$:
.ENDC
.ENDC
	BIT	#DS.IQU,@J		;IS NCL ALREADY SENDING OUR INPUT ?
	BEQ	16$
12$:;	JMP	TYICK9			;IF SO HOLD REST
	RTS	PC			;SAVE 2 BYTES
;NOW SHIP THE CHARACTERS
16$:	BIT	#DS.IST,(J)		;DID WE STOP INPUT?
	BEQ	15$			;NO, BRANCH
	JSR	PC,SNDXON		;YES, SEND AN XON
	BIC	#DS.IST,(J)		;AND CLEAR XOFF FLAG
15$:
.IF NE FT.TSK
	CMP	DB.ICC(J),#TTYMIC	;HOW MANY CHARS IN MSG?
	BHIS	18$			;IF FULL SEND IT
	BIT	#DS.PAU,(J)		;CHECK WHETHER WE SHOULD HOLD
	BNE	12$
.ENDC
18$:
.IF NE FT.RDA
	TST	DB.RDT(J)		; RDA DEVICE ??
	BEQ	19$			; NO, KEEP GOING
	TST	DB.IDR(J)		; INPUT DATA REQUESTS ??
	BNE	11$			; SEND DATA
	RTS	PC			; NO, GO BACK
11$:	JMP	RDACN0
19$:
.ENDC

	BIT	#DS.EPL,@J		;NEED TO SEND AN ECHO PIPELINE MARKER ?
	BEQ	20$			;IF NOT DON'T BOTHER
	MOV	#4,R0			;CODE THIS IS A CONTROL MSG
	JSR	PC,DVPBSM		;BEGIN CONTROL SUBMESSAGE
	  BCS	TYICK3			;IF WE CAN'T SEND MSG,
					;PRETEND WE DIDN'T WANT TO
	CLR	R0			;CODE IS ECHO-PIPELINE-MARKER
	JSR	PC,DVPDAT
	  BCS	20$			;ERROR RETURN
	MOVB	DB.EPL(J),R0		;SERIAL # FOR MARKER
	INC	R0			;INCREMENT SERIAL NUMBER
	JSR	PC,DVPDAT
	  BCS	20$			;ERROR RETURN
	BIC	#DS.EPL,@J		;FLAG WE HAVE DONE IT NOW
	INCB	DB.EPL(J)		;INCREMENT SERIAL NUMBER FOR REAL

;HERE TO CONSIDER SENDING CHARACTERISTICS
20$:	BIT	#DS.XCH,@J		;NEED TO SEND CHARACTERISTICS ?
	BEQ	TYICK3
	MOV	#4,R0			;CHARACTERISTICS IS CONTROL SUBMSG
	JSR	PC,DVPBSM		;BEGIN SUBMESSAGE
	  BCS	TYICK3			;IF WE CAN'T SEND MSG,
					;PRETEND WE DIDN'T WANT TO
	MOV	#2,R0			;CODE IS 2 FOR CHARACTERISTICS
	JSR	PC,DVPDAT
	  BCS	TYICK3			;ERROR RETURN
	MOV	#6,R2			;ESTABLISH COUNTER FOR FILLS
	MOV	J,R4			;COPY DEVICE BLOCK ADDRESS
	ADD	#DB.FIL,R4		;POINT TO FILLERS
22$:	MOVB	(R4)+,R0		;GET NEXT FILLER
	BIC	#^C377,R0		;STRIP EXTRA BITS
	ASL	R0
	ASL	R0
	ASL	R0
	ASL	R0
	JSR	PC,DVPEXD		;PUT EXTENSIBLE FIELD IN SUBMESSAGE
	SOB	R2,22$			;LOOP BACK FOR REST OF FILLERS
.IF NE TTYN
	MOV	DB.LCB(J),R0		;POINT TO LINE CONTROL BLOCK
	MOV	LC.SPD(R0),R0		;GET SPEED
	MOV	R0,-(P)
	SWAB	R0
	ASL	R0			;MAKE INTO INDEX
	JSR	PC,24$
	MOV	(P)+,R0
	ASL	R0
	JSR	PC,24$
	BR	26$
24$:	BIC	#^C76,R0		;STRIP EXTRA BITS
	MOV	SPDTAB(R0),R0		;TRANSLATE TO BAUD
	JMP	DVPEXD
26$:
.IFF
	MOV	#^D110,R0		;DEFAULT IS 110 BAUD
	JSR	PC,DVPEXD		;PUT INTO SUBMSG
	MOV	#^D110,R0		;DEFAULT IS 110 BAUD
	JSR	PC,DVPEXD
.ENDC

	MOVB	DB.WID(J),R0		;WIDTH
	JSR	PC,DVPEXA
	MOVB	DB.ACR(J),R0		;AUTO CRLF POSITION
	JSR	PC,DVPEXA
	CLR	R0			;FOR NON 2741 80'S SEND ZIP
	JSR	PC,DVPEXD		; (ELEMENT NUMBER)
	MOV	DB.TTS(J),R0		;GET THE "2741" BITS
	JSR	PC,DVPEXD
	TSTB	DB.DFT(J)		;CHECK AGAIN
	BEQ	50$			;DON'T SEND A NULL TYPE
	MOV	J,R4			;DDB ADDRESS
	ADD	#DB.DFT,R4		;FORMS TYPE
	BICB	#200,5(R4)		;MAKE SURE OF TERMINATION
40$:	MOVB	(R4),R0			;GET NEXT BYTE OF TTY TYPE
	JSR	PC,DVPDAT		;SEND AS DATA
	TSTB	(R4)+			;CHECK WHAT WE SENT
	BMI	40$			;LOOP OVER EXTENSIBLE BYTES
50$:	BIC	#DS.XCH,@J		;HAVE SENT THEM NOW
TYICK3:
.IF NE FT.TSK
	BIT	#DS.Q10,(J)		;IS THERE STUFF IN THIS ?
	BEQ	24$
	BIC	#DS.Q10,(J)		;NOT ANY LONGER
	BR	26$
.ENDC
24$:	BIT	#DS.XDS,@J		;NEED TO SEND DEVICE STATUS ?
	BEQ	40$
26$:
	JSR	PC,DVPDCS		;PUT DEVICE STATUS INTO THE MESSAGE
40$:
RDACN0:	MOV	DB.IBF(J),R0		;GET MESSAGE POINTER
	BEQ	TYICK9			;IF NO CORE
.IF NE FT.RDA
	TST	DB.RDT(J)		;RDX DEVICE ?
	BEQ	45$			; NO
	BPL	39$			;NO BREAK SEEN
	BIC	#RDEBRK,DB.RDT(J)	;CLEAR BREAK SEEN
38$:	DECB	DB.IDR(J)		;COUNT REQUEST OFF
	BR	45$
39$:	CMP	DB.ICC(J),#TTYMIC	;DO WE HAVE TO SHIP IT ?
	BHIS	38$			; YES
	BR	TYICK9			;RETURN TO USER
45$:
.ENDC
	TST	DB.ICN(J)		;UNFINISHED SUBMESSAGE ?
	BEQ	46$
	JSR	PC,DVPSBM		;CLOSE OFF SUBMESSAGE
46$:	MOV	J,CN.DDB(R0)		;SAVE DEVICE BLOCK ADDRESS
	BIS	#DS.IQU,@J		;SO WE DON'T SEND MORE FOR WHILE
	CLR	DB.ICC(J)		;NO LONGER HOLDING TTY CHARS
	JSR	PC,NCLIN1		;GET RID OF MESSAGE
	CLR	DB.IBF(J)		;FORGET BUFFER
	CLR	DB.IAD(J)		;FORGET BYTE POINTER
;
;	Here after we have cleared our count of input
;	characters that gets maintained at interupt level.
;	NOTE that we moved the XON code from higher up to down
;	here, since we want to make sure all is idle before we
;	let the terminal start up again
;
.IF NE FT.RDA
	TST	DB.RDT(J)		;IS THIS AN RDA
	BNE	TYICK9			;YES, SKIP THIS
.ENDC
	BIT	#DS.IST,(J)		;DID WE STOP INPUT?
	BEQ	TYICK9			;NO, BRANCH
	JSR	PC,SNDXON		;YES, GO SEND AN XON
	BIC	#DS.IST,(J)		;AND CLEAR XOFF FLAG
TYICK9:	RTS	PC
SPDTAB:	.WORD	^D0
	.WORD	^D50
	.WORD	^D75
	.WORD	^D110
	.WORD	^D134
	.WORD	^D150
	.WORD	^D200
	.WORD	^D300
	.WORD	^D600
	.WORD	^D1200
	.WORD	^D1800
	.WORD	^D2000
	.WORD	^D2400
	.WORD	^D3600
	.WORD	^D4800
	.WORD	^D7200
	.WORD	^D9600
	.WORD	^D19200
	.WORD	^D1
SPDLIM:	.WORD	^D2


.MACRO X Q			;MACRO TO MAKE IT EASY TO DEFINE DISPATCH ENTRYS
    .IF DF Q
	.WORD	Q
    .IFF
	.WORD	TRPINT
    .ENDC
.ENDM


DEVTYP:	;DISPATCH FOR TYPE OF DEVICE TO TYPE ON
	X	DHTYPE
	X	DZTYPE

DEVSPD:	;DISPATCH FOR TYPE OF DEVICE TO SET SPEED ON
	X	DHSPD
	X	DZSPD

DEVBKN:	;DISPATCH TO TURN ON XMIT-BREAK
	X	DHBKON
	X	DZBKON

DEVBKF:	;DISPATCH TO TURN OFF XMIT-BREAK
	X	DHBKOF
	X	DZBKOF
;DEVICE TIMER (USED FOR IRMA CATCHER)

RDATIM:
CTYTIM:
TTYTIM:
	JMP	@10$(R0)		;DISPATCH ON TIMER CODE
10$:	TCLK00				;(TCLK00) FILLER
	30$ 				;(TCLK02)
	30$ 				;(TCLK04)
	30$ 				;(TCLK06)
	30$ 				;(TCLK10)
	30$				;(TCLK12)

30$:	RTS	PC			;HERE TO JUST RETURN

TCLK00:	PIOFF
	BIT	#DS.ACT,@J		;BE SURE IS ACTIVE
	BEQ	90$			;THIS IS A RACE CONDITION
	JSR	PC,XMTINT		;FAKE TRANSMIT DONE INTERRUPT
90$:	PION
100$:	RTS	PC

TYPHIA:	MOV	#HIAMSG,R1		; GET "HOST IS AVAILABLE"
	BR	TTYMSG			; AND PRINT IT ON THE TTY

TYPNHA:	MOV	#NHAMSG,R1		;GET "NO HOST AVAILABLE"
	BR	TTYMSG			; AND GIVE IT TO THE USER

TYPWCC:	MOV	#WCCMSG,R1		;GET "WAITING FOR CONNECT CONFIRM"
	BR	TTYMSG

TYPHSD:	MOV	#HSDMSG,R1		;GET "HOST SENT DISCONNECT"
	BR	TTYMSG

TYPHWA:	MOV	#HWAMSG,R1		;GET "HOST WENT AWAY"
	BR	TTYMSG

TYPIBF:	MOV	#IBFMSG,R1		;GET "INPUT BUFFER FULL"
;	BR	TTYMSG


;TTYMSG	ROUTINE TO START A TTY TYPING A FIXED STRING.  (WON'T
;  TYPE STRING IF AN RDA LINE, OR IF ONE IS ALREADY TYPING.)
;ENTER WITH
;  R1/	ADDRESS OF STRING TO TYPE
TTYMSG:	TST	DB.STR(J)		;DON'T FORCE THE MSG IF
	BNE	99$			;ONE IS ALREADY TYPING OUT
.IF NE FT.RDA
	TST	DB.RDT(J)		;RDA ??
	BNE	99$			;YES,  DON'T SEND HIM GARBAGE.
.ENDC
	MOV	R1,DB.STR(J)
;	CLRB	DB.TIM(J)		;CLEAR TIMER SO OUTPUT SURE TO START.
;					; (THIS IS NECESSARY BECAUSE IF WE
;					;  ARE PRINTING A DISCONNECT MSG,
;					;  CLRDDB WILL CLEAR TIMER AND STOP US)
	JSR	PC,BEGXMT		;START THE TTY TYPING
99$:	RTS	PC
TYMSG1:	RTS	PC


;HERE FROM LOOP WITH INPUT CHAR IN R0, DEVICE BLOCK ADR IN J
RECINT:	BIT	#DS.DIE!DS.DSC,@J	;DID TEN DIE ?
	BNE	TYMSG1			;TOSS CHAR AND LET DISCONNECT
					; CODE TELL USER WHAT'S GOING ON

.IF NE FTHOST!FT.RDA
	BIT	#DS.CON,@J		;IS TTY CONNECTED ?
	BNE	RECIN0
.ENDC

.IF NE FT.RDA
	TST	DB.RDT(J)		; IS THIS RDA DEV ??
	BNE	TYMSG1			; YES, DUMP IT
.ENDC
.IF NE FTHOST
	JSR	PC,FNDPFH		;TRY TO CONNECT TO HOST
	BEQ	TYPNHA			;IF NO HOST AVAILABLE, TELL THE USER
	JSR	PC,SNDCON		;TRY TO CONNECT TO THE HOST
	BR	TYPWCC			;TELL THE GUY WE SENT A CONNECT FOR HIM
.ENDC

;HERE TO PROCESS THE CHARACTER

RECIN0:
.IF NE FTHOST
	TST	DB.RLA(J)		;ARE WE HALF WAY THERE
	BEQ	TYPWCC			;IF SO, SAY "WAITING FOR CONFIRM"
.ENDC
.IF NE FT.TSK
	BIT	#DS.PAU,(J)		;DID THIS COME FROM A TASK
	BEQ	14$			;NO, INTERUPT LEVEL CHECKS BUFFER FULL
	CMP	#TTYMIC,DB.ICC(J)	;HOW MANY CHARS ALREADY WAITING ?
	BMI	TYPIBF			;TELL USER THAT INPUT BUFFER IS FULL
.ENDC
14$:	BIC	#^C377,R0		;STRIP EXTRA BITS
	MOV	R0,R1			;COPY CHARACTER
	BIT	#TT.8BT,DB.TTS(J)	;IS THIS AN 8-BIT TERMINAL?
	BNE	13$			;YES, DON'T TRIM TO 7-BIT
	BIC	#^C177,R1		;NO, STRIP EXTRA BITS
13$:	CMPB	R1,#21			;IS THIS AN "XON"
	BNE	15$			;NO, MOVE ALONG
	SAVE	<R0,R1>			;SAVE CHARACTER
	JSR	PC,BEGXMT		;YES, START TYPING
	RESTORE	<R1,R0>			;GET BACK CHARACTER
15$:	BIT	#DS.XDS,(J)		;SEND NEW STATUS TO HOST?
	BEQ	16$			;NO, KEEP GOING
	SAVE	<R0,R1>			;PROTECT OUR CHAR FROM DNDEV
	JSR	PC,DVPDCS		;SEND STATUS TO THE -10
	RESTORE	<R1,R0>			;GET THE CHARACTER BACK
16$:	BIT	#TS.IMI,DB.DCS(J)	;CHECK FOR IMAGE INPUT MODE
	BNE	RECIN1			;IN WHICH WHICH CASE NO EDITING
	CMP	R1,#40			;SPACE?
	BNE	20$			;NOPE, DON'T DO AUTO CRLF CHECK
	MOVB	DB.ACR(J),R2		;GET ACR POSITION
	BEQ	20$			;0 SAYS WE DON'T DO IT
	CMPB	R2,DB.COL(J)		;HAVE WE REACHED THAT POINT?
	BHI	20$			;NOT YET, KEEP GOING
	MOV	#15,R0			;CHANGE SPACE INTO CR
	MOV	#15,R1			;IN BOTH PLACES
20$:	BITB	#CF..LC,CHRTAB(R1)	;IS CHARACTER LOWER CASE ?
	BEQ	RECIN1
	BIT	#TS..LC,DB.DCS(J)	;DO WE WANT TO CONVERT LC TO UPPER ?
	BEQ	RECIN1
	BICB	#40,R0			;CONVERT TO UPPER CASE
RECIN1:
.IF NE FT.RDA
	TST	DB.RDT(J)		; RDA ??
	BNE	99$			; YES, CHECK FOR BREAK
.ENDC
42$:	BIT	#TS.DFE,DB.DCS(J)	;IN DEFERED ECHO MODE ?
	BNE	55$			;SEND IT WITH A NEW ECHOPIPELINE MARKER
	BIT	#DS.ACT,@J		;IS LINE ALREADY TYPING ?
	BNE	50$			;IF SO GO INTO DEFERRED ECHO MODE
	BIT	#<TS.TAP!TS.IMI>,DB.DCS(J) ;TAPE OR IMAGE MODE?
	BNE	43$			;IF SO, THEN <CR> NOT SPECIAL
	CMPB	#15,R1			;IS CHAR A CARRIAGE RETURN ?
	BEQ	48$			;IF SO SPECIAL ACTION
43$:	BITB	#CHRDEF,CHRTAB(R1)	;DOES THIS CHAR PUT US INTO DEFERRED ECHO MODE ?
	BNE	50$
	TSTB	R0			;CHECK FOR 8-BIT CHARACTER
	BPL	41$			;NO, IT'S DEFINITELY NORMAL
	BIT	#TS.8BI,DB.DCS(J)	;YES, TEST FOR 8-BIT INPUT MODE
	BEQ	50$			;NO, WE NEED DEFERRED ECHO AFTER ALL
41$:	MOV	R0,-(P)			;SAVE CHAR
.IF NE FT.TSK
	JSR	PC,TK0WAK		;WAKE UP THE 'GET PRINTER' TASK
	BEQ	46$			;IF NONE, JUST ECHO
	JSR	PC,QTYCHR		;USE NCL ENTRY
	BR	49$
.ENDC
46$:	TSTB	DB.HLD(J)		;IF ALREADY HOLDING A CHAR BETTER FORCE IT OUT
	BEQ	44$
47$:	JSR	PC,BEGXMT		;ECHO IT
	MOVB	(P),DB.HLD(J)		;SAVE CHAR
	BR	45$
44$:	MOVB	R0,DB.HLD(J)		;SAVE CHAR
49$:	JSR	PC,BEGXMT		;ECHO IT
45$:	MOV	(P)+,R0			;GET CHAR BACK
.IF NE FT.HLD				;IF WE ARE HOLDING CHARACTERS
	CMP	#<TTYMIC/2>,DB.ICC(J)	;DO WE HAVE PLENTY OF CHARACTERS?
	BMI	60$			;YES, SEND THE MESSAGE NOW
	TWIDDLE				;FOR THISE WHO WATCH
	TWIDDLE DB.ICC(J)		;SEE HOW MANY CHARS IN THE MESSAGE
	JSR	PC,DVPDAT		;PUT BYTE INTO THE MESSAGE
	BR	70$			;GO RETURN
.IFF
	BR	60$			;PUT CHAR IN INPUT QUEUE
.ENDC;.IF NE FT.HLD			;IF WE ARE HOLDING CHARACTERS
;HERE WHEN USER TYPES A CARRIAGE RETURN WHILE IN LOCAL ECHO MODE
48$:
.IF NE FT.TSK
	JSR	PC,TK0WAK		;WAKE UP 'GET PRINTER' TASK
	BEQ	51$
	MOV	R0,-(P)			;SAVE CHARACTER <CR>
	JSR	PC,QTYCHR		;ECHO THE <CR>
	MOV	#12,R0			;AND APPEND A <LF>
	JSR	PC,QTYCHR
	MOV	(P)+,R0			;GET THE <CR> BACK
	BR	52$			;NOW SEND THE <CR> TO THE HOST
.ENDC
51$:	MOV	#CRLMSG,DB.STR(J)	;TYPE A CR/LF
52$:	JSR	PC,55$			;PUT CARRIAGE RETURN INTO MSG
	BIS	#TS.DFE,DB.DCS(J)	;SET DEFERED ECHO MODE
	JSR	PC,BEGXMT
	JMP	DVPDCS			;SEND NEW STATUS TO 10

;IF RDA, CHECK FOR BREAK
.IF NE FT.RDA
99$:	CMP	#RDABRK,R1		;BREAK ??
	BNE	60$			; NO
	BIS	#RDEBRK,DB.RDT(J)	;SET IT SEEN
	BR	60$
.ENDC

;HERE TO GO INTO DEFERRED ECHO MODE
50$:	BIS	#TS.DFE,DB.DCS(J)	;SET DEFERED ECHO FLAG
	MOV	R0,-(P)			;SAVE INPUT CHAR
	JSR	PC,DVPDCS		;PUT STATUS INTO MESSAGE
	MOV	(P)+,R0			;GET CHAR BACK
55$:	BIS	#DS.EPL,@J		;NEED TO SEND A NEW ECHO PIPELINE MARKER
60$:	JSR	PC,DVPDAT		;PUT BYTE INTO THE MESSAGE
98$:	JSR	PC,QUEDEV		;WAKE SERVICE ROUTINE
70$:
.IF NE FT.RDA!FT.TSK
.IF NE FT.RDA
	TST	DB.RDT(J)		;IS THIS AN RDA DEVICE?
	BNE	75$			;YES, NEED TO COUNT CHAR
.ENDC
.IF NE FT.TSK
	BIT	#DS.PAU,(J)		;DID THIS COME FROM A TASK?
	BEQ	RECINX			;NO, DON'T COUNT, INTERUPT LEVEL HAS
.ENDC
75$:	INC	DB.ICC(J)		;COUNT CHAR INTO THE MESSAGE
.ENDC ; .IF NE FT.RDA!FT.TSK
RECINX:	RTS	PC
;HERE TO SEND XON
SNDXON:	MOVB	#21,R0			;GET XON
	BR	SNDNOW			;GO SEND IT

;HERE TO SEND XOFF
SNDXOF:	MOVB	#23,R0			;GET XOFF
	BIT	#TT.8BT,DB.TTS(J)	;IS THIS AN 8-BIT TTY?
	BNE	SNDNOW			;YES, SEND AS IS
	BIT	#TT.8BL,DB.DVT(J)	;NO, IS IT AN 8-BIT LINE?
	BNE	SNDNOW			;YES, LEAVE IT ALONE ANYWAY
	BIS	#200,R0			;NO, MUST SEND WITH PARITY
SNDNOW:	PIOFF				;INTERUPTS OFF
	BIT	#DS.ACT,@J		;ARE WE ALREADY OUTPUTING?
	BEQ	10$			;NO, START OUTPUT
	MOVB	R0,DB.ASP(J)		;YES, WE'LL CATCH IT AT NEXT XMT INT
	BR	20$			;TURN ON INTERRUPTS AND EXIT
10$:	BIS	#DS.ACT,@J		;SAY WE ARE TYPING
	JSR	PC,TYPE90		;GO SEND IT
20$:	PION				;INTERUPTS BACK ON
	RTS	PC			;RETURN

BEGXMT:	PIOFF				;DISABLE INTERRUPTS
	BIT	#DS.ACT,@J		;ARE WE ALREADY TYPING ?
	BNE	20$			;IN CASE ALREADY TYPING
	BIS	#DS.ACT,@J		;SET ACTIVE FLAG
	TSTB	DB.TIM(J)		;IF TIMER IS RUNNING,EXIT
	BNE	20$
	JSR	PC,XMTINT
20$:	PION				;REENABLE INTERRUPTS
	RTS	PC

;HERE WHEN NO OUTPUT LEFT AND MAY WANT TO RELEASE OUTPUT CHUNK
XMT.80:	TST	DB.OBF(J)
	BNE	XMT.90
	DEC	R0			;BACK UP TAKER
	BIC	#CNKSIZ-1,R0		;MAKE INTO A CHUNK ADR
	JSR	PC,FRECNK		;RELEASE CHUNK
	CLR	DB.TOB(J)		;CLEAR POINTER
	CLR	DB.TOB+2(J)		;AND PUTTER

;HERE WHEN NOTHING MORE TO TYPE
XMT.90:	JSR	PC,QUEDEV		;SEND DATA REQUESTS MAYBE
	BIC	#DS.ACT,@J		;CLEAR ACTIVE FLAG
.IF NE FT.TSK
	MOV	J,-(P)			;SAVE DDB ADR
	MOV	DB.TSK+4(J),J		;GET TASK BLOCK ADR
	BEQ	12$			;IF NONE WE ARE DONE
	JSR	PC,TSKWAK		;WAKE UP THE TASK
12$:	MOV	(P)+,J			;RESTORE DDB ADR
.ENDC
20$:	RTS	PC
;HERE AT INTERRUPT LEVEL TO SEE IF THERE ARE MORE CHARS TO TYPE

TTDZOU:
TTDHOU:
XMTINT:	MOVB	DB.ASP(J),R0		;DO WE WANT TO SEND A CHARACTER FAST?
	BEQ	1$			;NO
	CLRB	DB.ASP(J)		;YES, CLEAR OUT THE CHAR
	JMP	TYPE90			;AND SEND IT
1$:	CMP	#20,JIFFLG		;IF CLOCK LEVEL HAS RUN RECENTLY
	BGE	XMT.0			; THEN IT'S OK TO RUN TERMINALS NOW
	MOVB	#3,DB.TIM(J)		;IF WE'VE BEEN TYING UP THE MACHINE
	BIS	#DS.ACT,@J		;FLAG THE LINE AS "ACTIVE"
5$:	RTS	PC			;BUT OTHERWISE SHUT IT DOWN
					; (LETTING IRMA RESTART IT LATER)

XMT.0:	CLR	DB.TIM(J)		;CLEAR THE TIMER
.IF NE FT.RDA
	TST	DB.RDT(J)		;RDA DEVICE ??
	BNE	33$			; YES
.ENDC
	MOV	DB.LCB(J),R1		;POINT TO LCB OF LINE
	BIT	#LCB.DS,@R1		;IS THIS A DATA SET LINE?
	BEQ	2$			;  NO, SO GO AHEAD
	CMPB	#LCS.CD,LC.STA(R1)	;SEE IF WE ARE AUTOBAUDING (OR ABOUT TO)
	BGT	2$			;  STATE < LCS.CD
	CMPB	#LCS.AB,LC.STA(R1)	;MAX STATE TO HOLD ON
	BLT	2$			;  STATE > LCS.AB
	MOVB	#-6,DB.TIM(J)		;WAIT FOR LATER TO CHECK FOR OUTPUT
	RTS	PC
2$:
10$:	MOV	DB.FTM(J),DB.TIM(J)	;SET IRMA TIMER WAITING IN WINGS
	BEQ	20$			;IF NONE FIND NEXT CHAR TO TYPE
	CLR	DB.FTM(J)
	RTS	PC			;WAIT FOR TIMER TO GO OFF
20$:	TST	DB.STR(J)		;IS THERE A MESSAGE TO TYPE ?
	BEQ	30$
	MOVB	@DB.STR(J),R1		;GET NEXT CHAR IN STRING
	BNE	22$
	CLR	DB.STR(J)		;HAVE EXHAUSTED STRING
	BR	30$
22$:	INC	DB.STR(J)		;ADVANCE STRING POINTER
	BR	38$
30$:	MOVB	DB.HLD(J),R1		;HOLDING A CHARACTER ?
	BEQ	32$			; FROM FREE CR/LF ?
	CLRB	DB.HLD(J)		;DON'T TYPE IT TWICE
	BR	38$			;BUT GO TYPE IT NOW
32$:	BIT	#TS.FRZ,DB.DCS(J)	;IS OUTPUT STOPPED WITH XOF ?
	BNE	XMT.90			;IF SO STOP TYPING
33$:
.IF NE FT.TSK
	MOV	DB.PTK(J),R0		;GET PRINTER TAKER (TASK)
	BEQ	50$			;IF NON, TRY FOR STUFF FROM NCL
	DEC	DB.PCN(J)		;ADJUST COUNT
	ASSERT	PL
	JSR	PC,XMTGET		;POINT TO NEXT CHARACTER IN CHUNKS
	MOVB	(R0)+,R1		;GET NEXT BYTE
	CMP	R0,DB.PPT(J)		;WAS THAT THE LAST
	BNE	46$
	DEC	R0
	BIC	#CNKSIZ-1,R0		;RESTORE CHUNK POINTER
	JSR	PC,FRECNK		;RELEASE CHUNK
	CLR	DB.PPT(J)		;CLEAR PUTTER
	CLR	R0
46$:	MOV	R0,DB.PTK(J)		;SAVE UPDATED PUTTER
	BR	38$
50$:	TST	DB.TSK(J)		;IS THERE A 'GET PRINTER' TASK
	BNE	XMT.90			;IF SO STOP THE XMITTER
.ENDC
36$:	MOV	DB.TOB(J),R0		;GET POINTER TO OUTPUT CHARS
	BEQ	XMT.90			;IF NONE WE ARE DONE
	CMP	R0,DB.TOB+2(J)		;SAME AS PUTTER ?
	BEQ	XMT.80
	JSR	PC,XMTGET		;POINT TO NEXT BYTE
	MOVB	(R0)+,R1		;GET NEXT BYTE
	MOV	R0,DB.TOB(J)
	DEC	DB.TOC(J)		;COUNT CHAR OUT OF CHUNKS
	CMP	R1,#ESCF		;IS IT ESCAPE FUNCTION CHARACTER?
	BNE	38$			;NO, CONTINUE NORMALLY
	JSR	PC,XMTGET		;POINT TO NEXT CHARACTER
	MOVB	(R0)+,R1		;GET FUNCTION
	MOV	R0,DB.TOB(J)		;UPDATE TAKER
	DEC	DB.TOC(J)		;AND ACCOUNT FOR CHARACTER
	CMP	R1,#ESCF		;ANOTHER ESCAPE?
	BEQ	38$			;YES, PASS IT ON AS DATA
	JSR	PC,DOESCF		;NO, DO FUNCTION
	BR	36$			;LOOK FOR ANOTHER CHARACTER
38$:	MOVB	#-2,DB.TIM(J)		;RESET IRMA CATCHER
	BIT	#TS.IMO,DB.TTC(J)	;IMAGE MODE?
	BEQ	39$			;NO,
	MOV	R1,R0			;YES, COPY CHARACTER
	JMP	TYPE90			; NO EDITING

39$:	CMPB	#11,R1			;IS THIS A TAB?
	BEQ	40$			; IF SO, GO DO FILL
	BIT	#TT.8BT,DB.TTS(J)	;IS THIS AN 8-BIT TTY?
	BNE	TYPEIT			;YES, GO DO IT
	CMPB	#211,R1			;NO, IS THE OTHER FLAVOR OF TAB ?
	BNE	TYPEIT
40$:	MOVB	DB.COL(J),R2		;GET CURRENT COLUMN
	ADD	#10,R2			;WHERE WE WILL BE WHEN DONE
	BIC	#7,R2
	BIT	#TS.CRL,DB.TTC(J)	;EVER DO FREE CR/LF
	BNE	62$
	CMPB	R2,DB.WID(J)		;IS THAT INSIDE BOUNDRY ?
	BLOS	62$
	MOV	R1,R0			;PUT CH WHERE IT IS EXPECTED
	JMP	TYPE85			;IF NOT TYPE CR FIRST
62$:	BIT	#TS.TAB,DB.TTC(J)	;DOES TTY HAVE HARDEWARE TAB ?
	BNE	XMT.2
	INCB	DB.COL(J)		;ADVANCE COLUMN POINTER
	BITB	#7,DB.COL(J)		;WAS THAT LAST ?
	BEQ	XMT.1
	MOVB	R1,DB.HLD(J)		;SAVE TAB FOR LATER
XMT.1:	MOV	#40,R1
	DECB	DB.COL(J)		;SPACES WILL INC LATER
	BR	TYPEIT
XMT.2:	MOVB	R2,DB.COL(J)		;SAVE COLUMN
	BR	TYPEIT			;GO TYPE CHARACTER

;SUBROUTINE TO ADVANCE CHUNKS AND CAUSE DATA REG UNITS TO BE SENT
;CALL	MOV	<CHUNK ADDRESS<,R0
XMTGET:	BIT	#CNKSIZ-1,R0		;ARE WE PAST END OF CURRENT CHUNK?
	BNE	10$			;NO, NOTHING SPECIAL
	JSR	PC,QUEDEV		;YES, WAKE SERVICE ROUTINE AT LOOP LEVEL
10$:	ADVCNK	R0,FREE			;POINT TO NEXT BYTE
	RTS	PC			;RETURN TO CALLER
;SUBROUTINE TO DO ESCAPE FUNCTION
; CALL	MOV	<FNC>,R1
;	JSR	PC,DOESCF		;GET FUNCTION IN REGISTER
DOESCF:	CMP	R1,#ESCF		;IS IT A SECOND ESCAPE CHARACTER?
	BEQ	10$			;IF SO, RETURN IMMEDIATELY
	CMP	R1,#MAXESC+1		;CHECK RANGE
	ASSERT	LE
.IF NE DGUTS
	BHI	10$			;SIGH
.ENDC
	MOV	R1,-(SP)		;SAVE SET/CLEAR STATUS
	BIC	#1,R1			;REDUCE TO VALID INDEX
	MOV	ESCTAB(R1),R1		;GET BIT TO TWEAK
	BIT	#1,(SP)+		;TEST FOR SET VS. CLEAR
	BNE	5$			;CLEAR
	BIS	R1,DB.TTC(J)		;SET
	BR	10$			;DONE SETTING
5$:	BIC	R1,DB.TTC(J)		;CLEAR THE BIT
10$:	RTS	PC

TS.ESC=0				;START OUT WITH NO SYNCHRONOUS FUNCTIONS
.MACRO	X BIT				;DISPATCHING MACRO
	.WORD	TS.'BIT			;THE BIT TO TEST AGAINST
	TS.ESC=TS.ESC!TS.'BIT		;INCLUDE IT IN THE MASK
.ENDM
ESCTAB:					;ESCAPE FUNCTION TABLE
	X	IMO			;IMAGE OUTPUT
	X	TAB			;HARDWARE TABS
	X	FRM			;HARDWARE FORM FEED
	X	CRL			;NO FREE CRLF
MAXESC=.-ESCTAB-2			;MAXIMUM LEGAL INDEX

TS.ESC=TS.ESC				;BITS TO HANDLE SYNCHRONOUSLY
;HERE TYPE A CHAR
; CALL	JSR	PC,TYPEIT		;WITH J SET UP AND CHAR IN R1
TYPEIT:
TYPE40:	MOV	R1,R0			;COPY CHARACTER
	BIT	#TS.IMO,DB.TTC(J)	;IMAGE MODE OUTPUT ?
	BNE	TYPE90			;IF SO NO EDITING
	BIT	#TT.8BT,DB.TTS(J)	;8-BIT TTY?
	BNE	30$			;YES, AVOID PARITY
	BIC	#^C177,R1		;STRIP PARITY BIT
	MOV	R1,R0			;COPY JUST IN CASE
	BIT	#TT.8BL,DB.DVT(J)	;8-BIT LINE?
	BNE	30$			;YES, AVOID PARITY
	MOVB	PARTAB(R1),R0		;PUT PARITY ON CHARACTER
30$:	BITB	#CHRHMO,CHRTAB(R1)	;IS THIS A NORMAL ASCII CHARACTER ?
	BNE	TYPE82			;IF SO JUST ADJUST COUNT
	BITB	#CHRFLL,CHRTAB(R1)	;DOES CHAR REQUIRE FILLERS ?
	BEQ	61$
	MOV	R1,R2			;COPY 7 BIT CHAR
	ADD	#DB.FIL-10,R2
	ADD	J,R2
	MOVB	@R2,DB.FTM(J)		;SET FILL TIMER FOR LATER USE
61$:	CMPB	#10,R1			;IS CHAR A BACKSPACE ?
	BEQ	TYPE81			;BACKUP COLUMN POINTER
	CMPB	#11,R1			;IS CHAR HORIZONTAL TAB ?
	BEQ	TYPE90			;IF SO DB.COL ALREADY COUNTED
	CMPB	#204,R1			;IS THIS A NEW-LINE?
	BEQ	62$			;TREAT LIKE CR
	CMPB	#15,R1			;IS THIS A CARRIAGE RETURN ?
	BNE	TYPE90
62$:	CLRB	DB.COL(J)		;BACK IN COLUMN 0 !
	BR	TYPE90

;HERE WHEN TYPING A BACKSPACE
TYPE81:	DECB	DB.COL(J)		;BACK UP COLUMN COUNTER
	BGE	TYPE90			;IF STILL POSITIVE TYPE IT
	CLRB	DB.COL(J)		;ELSE BACK TO COLUMN ZERO
	BR	TYPE90			;THEN TYPE IT

;HERE FOR USUAL PRINTING CHARACTERS
TYPE82:	INCB	DB.COL(J)		;COUNT COLUMNS
TYPE83:	CMPB	DB.COL(J),DB.WID(J)	;WAS THIS ALREADY ON RH MARGIN ?
	BLOS	TYPE90			;IF OK CONTINUE
	BIT	#TS.CRL,DB.TTC(J)	;EVER DO FREE CR/LF
	BNE	TYPE90			;IF NOT DON'T DO ONE NOW
TYPE85:	MOVB	R0,DB.HLD(J)		;SAVE CHARACTER FOR LATER
	MOV	#CRLMSG,DB.STR(J)	;DO A CR/LF FIRST
	JMP	XMTINT			;AND START OVER
;HERE WHEN HAVE SET FILLERS ETC.
TYPE90:

.IF NE TTYN+RDAN+FT.CTY
.IF NE FT.CTY
	CMP	J,#CTYDDB		;IS THIS FOR THE CTY ?
	BNE	33$
	JMP	CTYTYP			;IF SO DO IT
33$:
.ENDC
	MOV	DB.LCB(J),R1		;POINT TO LCB
	CMPB	#LCS.RU,LC.STA(R1)	;LINE OK?
	BGT	95$			; NO, DONT PRINT IT
	CMPB	#LCS.RC,LC.STA(R1)	;LINE OK?
	BLT	95$			; NO, DONT PRINT IT
	JINDEX	JMP,DB.TYP(J),R2,DEVTYP
95$:	MOVB	#-1,DB.TIM(J)		;SIMULATE 600 BAUD
	RTS	PC			;IRMA WILL CATCH THIS LATER
.ENDC
.IIF EQ TTYN,	BR	CTYTYP
.SBTTL	TABLES FOR AUTO BAUD UP TO 9600 BAUD (LOW BIT IS MASKED OFF)

HSPMSK=376			;MASK FOR UNWANTED BITS (HIGH SPEED AUTOBAUD)
HSPCHR=377			;CHAR TO SWITCH TO HIGH SPEED DETECT
LSPCHR=000			;CHAR TO SWITCH TO LOW SPEED DETECT

LSPTAB:	.BYTE	174		;110 BAUD ^C
	.BYTE	214		;110 BAUD CR
	.BYTE	234		;110 BAUD CR
	.BYTE	346		;150 BAUD CR
	.BYTE	036		;150 BAUD ^C
	.BYTE	215		;300 BAUD CR
	.BYTE	015		;300 BAUD CR, ODD
	.BYTE	003		;300 BAUD ^C
	.BYTE	203		;300 BAUD ^C, ODD
	.BYTE	376		;1200 BAUD ^C, EVEN
LSPEND:				;END OF TABLE

;TABLE OF LOW SPEED INDEX'S

LSP.IG=200			;THROW AWAY NEXT CHAR AFTER AB CHAR (SIGN BIT)
LSP.SP=017			;MASK FOR SPEED INDEX

LSPSPD:	.BYTE	00		;110 BAUD ^C
	.BYTE	LSP.IG!00	;110 BAUD CR
	.BYTE	LSP.IG!00	;110 BAUD CR
	.BYTE	LSP.IG!01	;150 BAUD CR
	.BYTE	01		;150 BAUD ^C
	.BYTE	02		;300 BAUD CR
	.BYTE	02		;300 BAUD CR, ODD
	.BYTE	02		;300 BAUD ^C
	.BYTE	02		;300 BAUD ^C, ODD
	.BYTE	04		;1200 BAUD ^C, EVEN
	.EVEN

;HIGH SPEED TABLE (NOTE THAT HSPMSK MASKS CHARACTERS BEFORE COMPARE)

HSPTAB:	.BYTE	200		;300 BAUD CR OR ^C, ODD OR EVEN
	.BYTE	036		;1200 BAUD ^C, ODD OR EVEN
	.BYTE	346		;1200 BAUD CR, ODD OR EVEN
	.BYTE	006		;1800 BAUD ^C, ODD OR EVEN
	.BYTE	072		;1800 BAUD CR, ODD OR EVEN
	.BYTE	002		;2400 BAUD ^C, EVEN
	.BYTE	202		;2400 BAUD ^C, ODD
	.BYTE	214		;2400 BAUD CR, EVEN
	.BYTE	014		;2400 BAUD CR, ODD
	.BYTE	370		;4800 BAUD ^C, ODD
	.BYTE	360		;4800 BAUD ^C, EVEN
	.BYTE	374		;4800 BAUD ^C, EVEN
	.BYTE	376		;9600 BAUD ^C OR CR, ODD OR EVEN
HSPEND:				;END OF TABLE

;TABLE OF HIGH SPEED INDEX'S

HSPSPD:	.BYTE	LSP.IG!2	;300 BAUD CR OR ^C
	.BYTE	LSP.IG!04	;1200 BAUD ^C
	.BYTE	LSP.IG!04	;1200 BAUD CR
	.BYTE	05		;1800 BAUD ^C
	.BYTE	05		;1800 BAUD CR
	.BYTE	06		;2400 BAUD ^C
	.BYTE	06		;2400 BAUD ^C
	.BYTE	06		;2400 BAUD CR
	.BYTE	06		;2400 BAUD CR
	.BYTE	07		;4800 BAUD ^C
	.BYTE	07		;4800 BAUD ^C
	.BYTE	07		;4800 BAUD ^C
	.BYTE	10		;9600 BAUD ^C, CR
	.EVEN

;DH11 HARDWARE SPEEDS

SPDPAR:	.WORD	B.110		;00
	.WORD	B.150		;01
	.WORD	B.300		;02
	.WORD	B.600		;03
	.WORD	B.1200		;04
	.WORD	B.1800		;05
	.WORD	B.2400		;06
	.WORD	B.4800		;07
	.WORD	B.9600		;10

.SBTTL	TTY INPUT INTERRUPT SERVICE

.IF NE TTYN
ABCHAR:	.WORD	0		;STORE THE AUTOBAUD CHARACTER HERE

;HERE ON A DH11 OR DZ11 CHARACTER INTERUPT
TTDZIN:
TTDHIN:
	MOV	DB.LCB(J),R2		;POINT TO LCB
	BIT	#LCB.IG,LC.CAR(R2)	;ARE WE IGNORING THIS LINE FOR 1 CHAR
	BEQ	10$			;NO
	BIC	#LCB.IG,LC.CAR(R2)	;YES, SKIP THIS CHAR AND GRAB NEXT
	BR	LRTS

10$:	CMPB	#LCS.AB,LC.STA(R2)	;AUTO BAUD?
	BEQ	REC.AB			; YES
	CMPB	#LCS.RU,LC.STA(R2)	;LINE OK?
	BGT	LRTS			; IF IT ISN'T, PUNT THE CHAR
	CMPB	#LCS.RC,LC.STA(R2)	;LINE OK?
	BLT	LRTS			; IF IT ISN'T, PUNT THE CHAR
	BIT	#DHRFER,R1		;CHECK FOR A FRAMING ERROR
	BEQ	REC.00			;BRANCH IF NORMAL CHARACTER

;HERE TO HANDLE A FRAMING ERROR - PROBABLY A BREAK
	BIT	#LCB.BK,LC.CAR(R2)	;WAS LAST CHAR A BREAK?
	BNE	30$			;YES, WE HAVE GOTTEN TWO IN A ROW
	BIS	#LCB.BK,LC.CAR(R2)	;NO, FLAG THIS ONE
	BR	LRTS			;AND IGNORE IT
30$:	BIT	#LCB.AB,LC.CAR(R2)	;IF THIS ISN'T AN AUTO-BAUD
	BEQ	LRTS			;LINE, THEN DON'T RESET SPEED
SET.AB:	MOVB	#LCS.AB,LC.STA(R2)	;RESET STATE TO AUTO-BAUD
	BIS	#LCB.TM,LC.CAR(R2)	;GIVE HIM FOREVER TO RESPOND
	BIC	#LCB.LS,LC.CAR(R2)	;USE HIGH SPEED TABLE
	MOV	#B.HSPD,-(P)		;PUSH A SPEED OF 2400 BAUD,
	JSR	PC,SETSPD		;AND SET THE LINE TO IT.
	TST	(P)+			;CLEAN UP THE STACK
LRTS:	RTS	PC			;AND GO HOME

REC.AB:	MOVB	R1,ABCHAR		;SAVE CHAR
	BIT	#LCB.LS,LC.CAR(R2)	;USING LOW SPEED TABLE?
	BEQ	15$			;NO, USE HIGH SPEED
	CMPB	#HSPCHR,R1		;IS THIS A HIGH SPEED CHARACTER?
	BEQ	60$			;YES, SET HIGH SPEED AND TRY AGAIN
	MOV	#LSPTAB,R0		;GET START OF TABLE
10$:	CMP	R0,#LSPEND		;AT END OF TABLE
	BEQ	60$			;BRANCH IF END OF TABLE
	CMPB	R1,(R0)+		;DOES CHAR MATCH
	BNE	10$			;LOOP IF NOT
	MOVB	LSPSPD-LSPTAB-1(R0),R0	;GET CHAR STATUS
	BR	30$			;GO TO COMMON CODE
15$:	MOV	#HSPTAB,R0		;GET START OF TABLE
	BICB	#^C<HSPMSK>,R1		;STRIP OFF UNWANTED BITS
	CMPB	#LSPCHR,R1		;IS THIS A LOW SPEED CHARACTER?
	BEQ	20$			;YES, GO SEARCH LOW SPEEDS
20$:	CMP	R0,#HSPEND		;AT END OF TABLE
	BEQ	50$			;BRANCH IF END OF TABLE
	CMPB	R1,(R0)+		;DOES CHAR MATCH
	BNE	20$			;LOOP IF NOT
	MOVB	HSPSPD-HSPTAB-1(R0),R0	;GET CHAR STATUS
30$:	BPL	40$			;BRANCH IF NOT IGNORING NEXT CHAR
	BIS	#LCB.IG,LC.CAR(R2)	;IGNORE THE NEXT CHAR ON THIS LINE
40$:	MOV	R0,R2			;MAKE COPY
	BIC	#^C<LSP.SP>,R2		;GET INDEX BITS
	ASL	R2			;MAKE IT A WORD
	MOV	SPDPAR(R2),-(P)		;GET THE DH11 SPEED BITS
	JSR	PC,SETSPD		;GO SET NEW SPEED
	TST	(P)+			;NOW POP OFF USED SPEED BITS
	MOV	DB.LCB(J),R1		;GET POINTER TO LCB
	MOVB	#LCS.RU,LC.STA(R1)	;GO TO RUNNING STATE
	BIC	#LCB.TM,LC.CAR(R1)	;STOP ANY TIMERS
	BIS	#DS.XDS,@J		;ALSO TELL THE -10
	MOVB	#1,DB.TIM(J)		;KICK THE IRMA TIMER
	BIT	#TT.8BL,DB.DVT(J)	;CHECK FOR 8-BIT LINE
	BNE	44$			;GO IF WANT 8-BIT
	BIC	#TT.8BT,DB.TTS(J)	;MAKE SURE WE START IN 7-BIT
	MOV	#215,R1			;A CR
	BR	46$			;MAKE IT LOOK LIKE THE USER TYPED IT
44$:	BIS	#TT.8BT,DB.TTS(J)	;MAKE SURE WE START IN 8-BIT
	MOV	#015,R1			;A CR
46$:	JMP	TTYINP			;LOOKS LIKE THE USER TYPED IT
50$:	BIS	#LCB.IG,LC.CAR(R2)	;IGNORE THE NEXT CHARACTER
	MOV	#B.LSPD,-(P)		;PUSH A SPEED OF 300 BAUD
	BIS	#LCB.LS,LC.CAR(R2)	;USE LOW SPEED TABLE
	BR	70$			;GO TO COMMON CODE
60$:	MOV	#B.HSPD,-(P)		;PUSH A SPEED OF 2400 BAUD,
	BIC	#LCB.LS,LC.CAR(R2)	;USE HIGH SPEED TABLE
70$:	JSR	PC,SETSPD		;AND SET THE DETECTION SPEED
	TST	(P)+			;CLEAN UP THE STACK
	RTS	PC			;DON'T DO ANYTHING WITH THE CHAR
REC.00:	BIC	#LCB.BK,LC.CAR(R2)	;CLEAR BREAK CHAR FLAG
	JMP	TTYINP			;PASS INPUT TO QUEUE
.ENDC;NE TTYN
;CTY INPUT INTERRUPT

.IF NE FT.CTY
CTIINT:	SAVE	<J>
	MOV	#CTYDDB,J		;GET DEVICE BLOCK FOR CTY
	SAVE	<R0,R1>
	TSTB	CTISTS			;CHECK IT WAS DATA INTERRUPT
	BGE	CTIIN9			;TRASH INTERRUPT
	SPL	7			;LOCK OUT EVERYTHING ELSE
	MOV	CTICHR,R1		;GET KEYBOARD DATA & CLEAR FLAG
.IF NE FT.DDT
	CMP	#204,R1			;DID I TYPE A CTRL/D?
	BNE	CD1			;NOPE, IGNORE
CD:	BR	CTIIN9			;PUT BREAKPOINT HERE
CD1:
.ENDC
	JSR	PC,TTYINP		;HAVE TTY INPUT
CTIIN9:	RESTORE	<R1,R0>
	RESTORE	<J>
	RTI				;DISMISS INTERRUPT


;CTY OUTPUT INTERRUPT

CTOINT:	SAVE	<R0,R1,R2,R3,J>
	MOV	#CTYDDB,J		;LOAD DEVICE BLOCK ADDRESS
	CLR	CTOSTS			;DISABLE INTERRUPTS

	JSR	PC,XMTINT		;GO SEE WHAT WE CAN DO NEXT
	RESTORE	<J,R3,R2,R1,R0>
	RTI
CTYTYP:	MOVB	R0,CTOCHR		;TYPE NEXT CHAR
	MOVB	#100,CTOSTS		;ENABLE INTERUPTS
	RTS	PC

.ENDC
;HERE TO QUEUE A CHAR TO TYPED
; CALL:	LOAD J WITH TTY DEVICE BLOCK ADDRESS
;	MOV	<CHR>,R0
;	JSR	PC,QTYCHR
QTYCHR:	MOV	R0,R3			;COPY BYTE
	PIOFF
	JSR	PC,QTYCH		;QUEUE THE CHARACTER
	PION
	RTS	PC


;SUBROUTINE TO QUEUE ESCAPE CHARACTER + FUNCTION CODE
; CALL	MOV	<FNC>,R0		;PUT FUNCTION IN R0
;	JSR	PC,QTECHR		;ASSUMES J CONTAINS DDB ADDRESS
QTECHR:	PIOFF
	MOV	R0,-(P)			;SAVE FUNCTION CODE
	MOV	#ESCF,R3		;GET ESCAPE CHARACTER
	JSR	PC,QTYCH		;QUEUE IT
	MOV	(P),R3			;RETRIEVE FUNCTION
	JSR	PC,QTYCH		;QUEUE IT ALSO
	MOV	(P)+,R0			;RETURN R0 INTACT
	PION
	RTS	PC


QTYCH:	MOV	DB.TOB+2(J),R0		;GET POINTER TO LAST DATA CHAR
	BNE	14$
	JSR	PC,ERSGET		;TAKE FROM EMERGENCY STORE
	TST	(R0)+			;SKIP LINK WORD
	MOV	R0,DB.TOB+2(J)		;SET LIMIT WORD
	MOV	R0,DB.TOB(J)		;SET 1ST BYTE POINTER
14$:	ADVCNK	R0 EXTEND		;ADVANCE TO NEXT CHARACTER
;					;ALLOCATING A NEW CHUNK IF REQUIRED
16$:	MOVB	R3,(R0)+		;PUT BYTE INTO CHUNK
	MOV	R0,DB.TOB+2(J)		;RESET LIMIT BYTE POINTER
	INC	DB.TOC(J)		;COUNT CHAR INTO THE CHUNKS
	RTS	PC
;HERE TO PASS TTY INPUT CHAR TO TASK OF NCL
; CALL WITH J POINTING TO LINE BLOCK
; AND INPUT CHAR IN R1
TTYINP:
.IF NE FT.TSK
	MOV	DB.TSK+2(J),R0		;GET TASK BLOCK THAT WANTS INPUT
	BEQ	TYPIN0
	SAVE	<J>
	MOV	R0,J
	JSR	PC,TSKWAK		;WAKE THE TASK
	RESTORE	<J>
	MOV	DB.KPT(J),R0		;GET KEYBOARD PUTTER
	ADD	J,R0			;MAKE ADR ABSOLUTE
	MOV	R1,(R0)+		;PUT CHAR INTO BUFFER
	SUB	J,R0			;MAKE ADR RELATIVE AGAIN
	CMP	R0,#DB.KQU+TQS+TQS	;DID WE HIT END OF QUEUE ?
	BNE	20$
	MOV	#DB.KQU,R0		;YES SO POINT TO START
20$:	CMP	R0,DB.KTK(J)		;WOULD THIS OVERTAKE TAKER ?
	BEQ	90$			;IF SO DON'T DO IT
	MOV	R0,DB.KPT(J)		;NO SO FREEZE IT
90$:	RTS	PC
.ENDC
TYPIN0:	CMP	#TTYMIC,DB.ICC(J)	;HOW MANY CHARS ALREADY WAITING ?
	BPL	5$			;STILL OK
	JMP	TYPIBF			;TELL USER THAT INPUT BUFFER IS FULL
5$:	MOV	R1,R0			;COPY THE CHARACTER
	BIT	#TT.8BT,DB.TTS(J)	;CHECK FOR 8-BIT TTY
	BNE	10$			;YES, DON'T STRIP "PARITY"
	BIC	#^C177,R0		;NO, CLEAR PARITY IN THE COPY
10$:	BIT	#TS.PAG,DB.DCS(J)	;ARE WE IN PAGE MODE?
	BEQ	20$			;NO, DON'T CHECK XON/XOFF
	CMPB	#23,R0			;WAS THE CHAR ^S (XOFF)?
	BNE	12$			;NO, CHECK ^Q
	BIS	#TS.FRZ,DB.DCS(J)	;YES, STOP OUTPUT
	BR	20$			;QUEUE THE XOFF
12$:	CMPB	#21,R0			;WAS THE CHAR A ^Q (XON)?
	BNE	20$			;NO, NORMAL CHAR
	BIC	#TS.FRZ,DB.DCS(J)	;YES, START OUTPUT
20$:	QUEPUT	TI			;PUT THE CHAR IN THE INPUT QUEUE
;
;	Stop input from a terminal at interupt level, thereby
;	avoiding any problems with loop level begin unable
;	to keep up with TTY input.
;
.IF NE FT.RDA
	TST	DB.RDT(J)		;Is this an RDA device?
	BNE	35$			;Yes, skip this
.ENDC
	BIT	#DS.IST,(J)		;Have we already sent XOFF
	BNE	35$			;Yes, don't bother with another
	INC	DB.ICC(J)		;Count this character
	CMP	#TTYMIC-^D20,DB.ICC(J)	;Are we in danger of overrunning?
	BHI	35$			;No, all is well
	JSR	PC,SNDXOF		;Yes, ship an XOFF now
	BIS	#DS.IST,(J)		;Signal that we sent an XOFF
35$:	RTS	PC			;Let loop level worry about the char.
PARTAB:	.BYTE	000,201,202,003,204,005,006,207
	.BYTE	210,011,012,213,014,215,216,017
	.BYTE	220,021,022,223,024,225,226,027
	.BYTE	030,231,232,033,234,035,036,237
	.BYTE	240,041,042,243,044,245,246,047
	.BYTE	050,251,252,053,254,055,056,257
	.BYTE	060,261,262,063,264,065,066,267
	.BYTE	270,071,072,273,074,275,276,077
	.BYTE	300,101,102,303,104,305,306,107
	.BYTE	110,311,312,113,314,115,116,317
	.BYTE	120,321,322,123,324,125,126,327
	.BYTE	330,131,132,333,134,335,336,137
	.BYTE	140,341,342,143,344,145,146,347
	.BYTE	350,151,152,353,154,355,356,157
	.BYTE	360,161,162,363,164,365,366,167
	.BYTE	170,371,372,173,374,175,176,377
; HERE TO SET LINE SPEED
.IF NE TTYN
; CALL:	JSR	PC,SETSPD	; WITH J SETUP
; 	RETURN			; USES R0 & R1

SETSPD:
	SAVE	<R2,R3>
.IF NE FT.CTY
	CMP	J,#CTYDDB		; IS THIS FOR THE CTY ?
	BEQ	99$			; CAUSE CTY NOT DH11
.ENDC
	BIS	#DS.XCH,@J		; SO WE SEND CHARACTERISTICS TO 10
	MOV	@DB.DHB(J),R0		; GET DH11 HDW ADDRESS
	MOV	6(P),R1			; GET NEW LINE SPEED
	MOVB	DB..LN(J),R2		; FETCH THE DH11 LINE #
	JINDEX	JSR,DB.TYP(J),R3,DEVSPD
	BCS	98$			; CARRY SET IS ERROR
	MOV	DB.LCB(J),R2		; SUCCESS, GET ADDRESS OF LCB
	MOV	R1,LC.SPD(R2)		; AND PUT NEW ACTUAL SPEED IN LCB
98$:
99$:	RESTORE	<R3,R2>
	RTS	PC
.IFF
SETSPD:	RTS	PC
.ENDC
.ENDC