Google
 

Trailing-Edge - PDP-10 Archives - BB-X140B-BB_1986 - 10,7/703anf/dntty.p11
There are 5 other files named dntty.p11 in the archive. Click here to see a list.
.SBTTL	DNTTY - TERMINAL ROUTINES  3 SEP 85

;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
;  OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (C) 1976,1977,1978,1979,1980,1981,1982,1983,1984 BY DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.

VRTTY=116			;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.TIW=1000	;JOB IS IN INPUT WAIT FOR TTY
	TS.LMD=2000	;LINE INPUT MODE
	TS.CRL=4000	;NO AUTO CR/LF ON LINE OVERFLOW
	TS.DTR=10000	;DATA TERMINAL READY
	TS.RNG=20000	;RING
	TS.CAR=20000	;CARRIER
	TS.DSR=40000	;DATASET READY
	TS.ADL=100000	;AUTO DIAL LINE (DN11)

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


.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=^D2400		;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,	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=^D2400		;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,	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=^D2400		;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,	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
	.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=^D2400		;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,	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
	.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

;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

;START OF SUBMESSAGE, DISPATCH BASED ON MESSAGE TYPE

TOGMS1:	TST	R0			;MESSAGE TYPE CAN'T BE NEGATIVE
	BLE	TOGBAD			;IF IT IS, WE COMPLAIN
	CMP	R0,#4			;ALSO CAN'T BE TOO BIG EITHER
	BGT	TOGBAD			;IF IT IS, WE COMPLAIN
	ASL	R0			;WORD INDEX
	JMP	@10$-2(R0)		;DISPATCH ON MESSAGE TYPE

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



;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.IMO,R0		;SET OR CLEAR IMAGE OUTPUT?
	BEQ	60$			;NO, ACT NORMALLY
	BIC	#TS.IMO,R0		;DON'T ACTUALLY DO IT NOW
	SAVE	R0			;SAVE BITS TO SET/CLEAR
	MOV	R1,R0			;COPY SET/CLEAR CODE
	DEC	R0			;CONVERT TO ESCAPE FUNCTION CODE
	JSR	PC,QTECHR		;PUT ESCAPE FUNCTION INTO DATA STREAM
	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$:	TST	R0			;DCT CAN'T BE TOO SMALL
	BLT	TOGBAD			;OR WE WILL GET UPSET
	CMP	R0,#4			;DCT ALSO CAN'T BE TOO BIG
	BGT	TOGBAD			;OR WE WILL GET UPSET
	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



;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 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 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 AND 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
.IF NE FT2741
	MOV	#BCDXIN-2-ELETAB,R1	;FIRST INDEX TO TRY
82$:	CMP	ELETAB(R1),R0		;HIT OUR BOY ?
	BNE	84$			;IF NOT RIGHT DON'T USE
	SWAB	R1			;POITION BITS
	ASR	R1			; DITTO
	BIC	#BCDCOD,DB.BCD(J)	;CLEAR OLD CODE
	BPL	86$			;BRANCH IF NOT 2741
	BIS	R1,DB.BCD(J)		;SET NEW CODE
84$:	DECB	R1			;ON TO NEXT
	DECB	R1
	BPL	82$
.ENDC
86$:	JSR	PC,DVGEXF		;GET 2741 BITS
.IF NE FT2741
	BIC	#<BCDTDY!BCDAPL!BCDHDB>,DB.BCD(J)
	BIC	#^C<BCDTDY!BCDAPL!BCDHDB>,R0
	BIS	R0,DB.BCD(J)
.ENDC
	BIC	#TT.APL,DB.TTS(J)	;CLEAR THE APL BIT INITIALLY
	BIT	#CHRAPL,R0		;MAKE SURE WE GET THE APL BIT
	BEQ	87$			;NOT SET, LEAVE IT CLEAR
	BIS	#TT.APL,DB.TTS(J)	;YES, SET IT
87$:	ASSERT EQ DB.OCN(J)		;COUNT SHOULD BE 0 NOW
	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
.IF NE FT2741
	MOV	DB.BCD(J),R0		;GET 2741 STATUS
	SWAB	R0
	BIC	#^C7,R0			;LEAVE ONLY ELEMENT CODE
	ROL	R0
	MOV	ELETAB(R0),R0		;GET ELEMENT NUMBER FOR TTY
.IFF
	CLR	R0			;FOR NON 2741 80'S SEND ZIP
.ENDC
	JSR	PC,DVPEXD
.IF NE FT2741
	MOV	DB.BCD(J),R0		;2741 BITS
	BIC	#^C<BCDTDY!BCDAPL!BCDHDB>,R0 ;STRIP EXTRA BITS
.ENDC
	BIT	#TT.APL,DB.TTS(J)	;MAKE SURE WE SEND THE APL BIT
	BEQ	30$			;NOT SET, LEAVE IT CLEAR
	BIS	#CHRAPL,R0		;YES, SET IT
30$:	JSR	PC,DVPEXD
	BIC	#DS.XCH,@J		;HAVE SENT THEM NOW
TYICK3:
;CHECK TO SEE IF WE WANT TO TURN LINE AROUND
.IF NE FT2741
	MOV	DB.BCD(J),R0		;GET 2741 STATUS
	BPL	20$			;IF NOT 2741 WE ARE DONE
	BIT	#BCDPRL,R0		;IS THE PRINTER LOCKED ?
	BNE	20$			;IF SO WE ARE DDONE
	BIT	#DS.ACT,@J		;IS TRANSMITTER ACTIVE ?
	BNE	20$			;IF SO CAN'T GIVE IT UP
	BIT	#TS.TIW,DB.DCS(J)	;DEVICE IN INPUT WAIT ?
	BEQ	20$			;IF NOT WE ARE DONE
	MOV	#<4*400>+1,DB.TIM(J)	;START CLOCK
	BIS	#BCDPRL!BCDCDB,DB.BCD(J)
	BIS	#DS.ACT,@J
.ENDC;.IF NE FT2741
20$:
.IF NE FT.TSK
	BIT	#DS.Q10,(J)		;ID THERE STUFF IN THIS ?
	BEQ	24$
	BIC	#DS.Q10,(J)		;NOT ANY LONGER
	BIC	#TS.TIW,DB.DCS(J)	;TEN NO LONGER HUNGRY
	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$:
44$:
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
.IF NE FT2741
	TCLK02				;(TCLK02)
	TCLK04				;(TCLK04)
	TCLK06				;(TCLK06)
	TCLK10				;(TCLK10)
	30$				;(TCLK12)
.IFF;.IF NE FT2741
	30$ 				;(TCLK02)
	30$ 				;(TCLK04)
	30$ 				;(TCLK06)
	30$ 				;(TCLK10)
	30$				;(TCLK12)
.ENDC;.IF NE FT2741

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
	BIC	#^C177,R1		;STRIP EXTRA BITS
	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
	TST	R1
	BEQ	RECINX			;FLUSH NULLS
	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	#215,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
	ADD	#140,R0			;CONVERT TO UPPER CASE AND
					; COMPLEMENT PARITY
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
.IF NE FT2741
	TST	DB.BCD(J)		;IS THIS A 2741 ?
	BMI	50$			;IF SO GO INTO DEFERRED ECHO MODE
.ENDC
	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$
	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	#223,R0			;GET XOFF
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 ALREAY 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
.IF NE FT2741
	TSTB	DB.TIM+1(J)		;DOING 2741 FUNCTION ?
	BNE	20$			;IF SO DON'T STOP TIMER
.ENDC
	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:
.IF NE FT2741
	TST	DB.BCD(J)		;2741S USE DB.ASP FOR OTHER THAN XOF/XON
	BMI	1$			;SO DON'T CHECK HERE
.ENDC
	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 BOUT 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$:
.IF NE FT2741
	TST	DB.BCD(J)		;GET 2741 STATUS BITS
	BPL	10$			;BRANCH IF NOT 2741
	MOVB	DB.ASP(J),R1		;HOLDING A CHARACTER ?
	BEQ	10$
	CLRB	DB.ASP(J)
	BR	38$
.ENDC
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.DCS(J)	;IMAGE MODE?
	BEQ	39$			;NO,
	MOV	R1,R0			;YES, COPY CHARACTER
	JMP	TYPE90			; NO EDITING

39$:	CMPB	#211,R1			;IS THIS A TAB?
	BEQ	40$			; IF SO, GO DO FILL
	CMPB	#11,R1			;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.DCS(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.DCS(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	#240,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
	ASL	R1			;MAKE INDEX INTO ESCTAB
	CMP	R1,#MAXESC		;CHECK RANGE
	ASSERT	LE
	JSR	PC,@ESCTAB(R1)		;DO FUNCTION
10$:	RTS	PC
ESCTAB:					;ESCAPE FUNCTION TABLE
	IMOON				;IMAGE OUT ON
	IMOOFF				;IMAGE OUT OFF
MAXESC=.-ESCTAB-2			;MAXIMUM LEGAL INDEX
IMOON:	BIS	#TS.IMO,DB.DCS(J)
	RTS	PC
IMOOFF:	BIC	#TS.IMO,DB.DCS(J)
	RTS	PC
;HERE TYPE A CHAR
; CALL	JSR	PC,TYPEIT		;WITH J SET UP AND CHAR IN R1
TYPEIT:
.IF NE FT2741
	MOV	DB.BCD(J),R3		;GET 2741 STATUS BITS
	BMI	10$			;BRANCH IF 2741
	JMP	TYPE40			;NOT 2741 SO NO SPECIAL HANDLING

10$:	TRACE	27
	BIT	#BCDPRL,R3		;TEST FOR PRINTER LOCKED
	BEQ	TYPE31			;BRANCH IF NOT LOCKED
	BIT	#BCDBRK,R3		;GO ON IF RCVBRK FLAG IS SET
	BNE	TYPE31
	MOVB	R1,DB.ASP(J)		;SAVE CHAR FOR LATER
	BIT	#BCDHDB,R3		;TEST FOR REVERSE BREAK FEATURE
	BEQ	6$			;BRANCH IF DOESN'T HAVE IT
	BIT	#BCDCDB,R3		;CHECK FOR OK TO DODEBREAK
	BEQ	6$
	BIT	#BCDRCR,R3		;WAS LAST CHAR IN A CR ?
	BNE	6$			;IF SO WE'LL GET CONTROL SOON ANYWAY
	JINDEX	JSR,DB.TYP(J),R3,DEVBKN	;CALL DRIVER TO SEND BREAK
	BIS	#BCDKBL!BCDXRB,DB.BCD(J);PRINTER LOCKED, XMT REV BREAK
	MOV	#<6*400>+^D21,DB.TIM(J)	;TIMER TO STOP BREAK
6$:	RTS	PC			;AND RETURN TO CALLER
TYPE31:	BIC	#^C177,R1		;STRIP PARITY
	;BEQ	XMTINT			;FLUSH NULLS
	;CMP	#177,R1			;TRANSMITTING RUBOUT ?
	;BEQ	XMTINT			;FLUSH RUBOUTS

;MAKE SPECIAL CHECKS FOR CARRIAGE RETURN
	CMP	#15,R1			;IS THIS A CARRIAGE RETURN
	BNE	10$			;BRANCH IF NOT A CR
	BIT	#BCDOCR,R3		;2ND CR IN A ROW ?
	BNE	11$			;PROBABLY FILLER - FLUSH IT
	MOV	#BCDCRL,R0		;CARRIAGE RETURN CHAR
	JMP	TYPE37			;GO TYPE CR
10$:	BIT	#BCDOCR,R3		;DID 10 JUST SEND A CR ?
	BEQ	12$			;IF NOT DON'T CHECK FURTHER
	BIC	#BCDOCR,R3		;CLEAR THE FLAG
	MOV	R3,DB.BCD(J)		;IN CASE FOLLOWING IS LF
	CMP	#12,R1			;IS THIS A LINE FEED ?
	BNE	12$			;NO, KEEP GOING
11$:	JMP	XMTINT			;FLUSH LINE FEEDS

12$:	MOV	R3,R2			;MAKE A COPY OF THE STATUS WORD
	BIC	#^CBCDCOD,R2		;LEAVE CODE ONLY
	MOV	R2,R0			;IN CASE IS NOT TIDY
	ADD	R1,R2
	MOVB	BCDXOU(R2),R1		;TRANSLATE CHARACTER
	BGE	40$			;BRANCH IF THIS CHAR ISN'T AFFECTED BY TIDY
	BIT	#BCDTDY!BCDAPL,R3	;CHECK FOR APL MODE OR TIDY
	BNE	40$			;IN WHICH CASE NOTHING SPECIAL
	BIC	#^C177,R2		;STRIP EXTRA BITS
	MOVB	R2,DB.ASP(J)		;SAVE CHAR IN CASE WE DON'T TYPE IMMEDIATELY
	BIT	#BCDCON,R3		;HAVE WE ALREADY TYPED THE TICK ?
	BNE	30$			;IF SO DONE FOR NOW
	MOVB	ARROW+BCDXOU(R0),R1	;IN CASE WE WANTED A ^
	TSTB	TDYTAB(R2)		;DO WE WANT A ' OR A ^
	BGE	23$
	MOVB	QUOTE+BCDXOU(R0),R1	;WANTS A ' INSTEAD OF AN ARROW
23$:	JSR	PC,60$			;BE SURE CASE SHIFT IS RIGHT
	BIS	#BCDCON,R3		;SET HAVE SENT ' OR ^ FLAG
	BR	TYPE35			;JUST TYPE IT

30$:	MOVB	TDYTAB(R2),R2		;CONVERT THE CHAR
	BIC	#^C177,R2		;STRIP EXTRA BITS
	ADD	R0,R2			;ADD IN CHARACTER SET
	MOVB	BCDXOU(R2),R1		;GET WHAT TO TYPE INSTEAD
	JSR	PC,60$			;BE SURE CASE SHIFT IS RIGHT
	CLRB	DB.ASP(J)		;CLEAR SO WE DON'T TYPE AGAIN
	BIC	#BCDCON,R3		;CLEAR FLAG

40$:	JSR	PC,60$			;BE SURE CASE SHIFT IS RIGHT
	BR	TYPE35
;HERE TO BE SURE WE ARE IN RIGHT CASE SHIFT
; CALL	JSR	PC,60$
;	RETURN IF IN RIGHT SHIFT
60$:	CMP	#BCDSPC,R1		;TEST FOR CHAR IS A SPACE
	BEQ	68$			;IF SO DON'T CHECK SHIFT
	BIT	#10,R1			;CHECK FOR NON-PRINTING CHARS
	BEQ	61$			; WHICH DON'T CARE ABOUT SHIFT CASE
	BIT	#4,R1			;DISTINGUISHED BY 14 BITS IN CODE
	BNE	68$			;ONE OF THEM
61$:	BIT	#100,R1			;TEST FOR UPPER SHIFT CHAR
	BNE	64$			;BRANCH IF NEED SHIFT
	BIT	#BCDUPS,R3		;ARE WE ALREADY IN DOWN SHIFT ?
	BEQ	68$			;BRANCH IF SO
	BIC	#BCDUPS,R3
	MOV	#BCDLCS,R0		;DOWN SHIFT CHAR
	BR	66$
64$:	BIT	#BCDUPS,R3		;ARE WE ALREADY IN UP SHFIT ?
	BNE	68$			;BRANCH IF SO
	BIS	#BCDUPS,R3		;SET UP SHIFT
	MOV	#BCDUCS,R0
66$:	TST	(P)+			;CLEAN OFF STACK
	TSTB	DB.ASP(J)		;ALREADY HOLDING A CHAR ?
	BNE	TYPE39			;TYPE CHAR
	MOVB	R2,DB.ASP(J)		;SAVE CHAR TO TYPE LATER
	BR	TYPE39
68$:	RTS	PC
;HERE TO SET FILLER TIMES FOR 2741
TYPE35:	MOV	R3,DB.BCD(J)		;UPDATE STATUS
	MOV	R1,R0			;COPY CHAR
	CMPB	#035,R0			;IS CHAR A BACKSPACE ?
	BNE	10$			;NO
	JMP	TYPE81
10$:	CMPB	#057,R0			;HORIZONTAL TAB?
	BNE	22$
20$:	MOVB	DB.COL(J),R1		;TAB USES SAME OBSTRUSE FORMULA FOR FILL
	BIC	#^C377,R1		;AS LOSER HAS SET HIS TABS TO 8N FLAVOR
	MOV	R1,-(SP)		;SAVE CURRENT POSITION
	BIS	#7,R1			;FIND NEXT MULT OF 8
	INC	R1
	SUB	(SP)+,R1		;GET DELTA
	ADD	#8.+8.+1,R1		;TWICE THE CONSTANT + ROUNDER
	ASR	R1			;DELTA/2 + 8 (ROUNDED)
	MOVB	R1,DB.FTM(J)		;SET FILLER
	BR	TYPE83			;GO CONSIDER FREE CRLF

22$:	CMPB	#056,R0			;IS CHAR A LINE FEED?
	BNE	23$
	MOVB	#5,DB.FTM(J)		;LINE FEED FILL IS ABOUT ONE CHAR TIME
	BR	TYPE90
23$:	CMPB	#055,R0			;IS CHAR A CARRIAGE RETURN ?
	BEQ	TYPE37
	CMPB	#075,R0			;IS CHAR AN IDLE ?
	BNE	TYPE82			;NORMAL PRINTING CHAR
	BR	TYPE90			;JUST TYPE IT

;HERE WHEN TYPEING CR ON A 2741
TYPE37:	BIS	#BCDOCR,R3		;SET SPECIAL FLAG
	JSR	PC,CRF274
TYPE39:	MOV	R3,DB.BCD(J)
	BR	TYPE90

CRF274:	MOV	R1,-(SP)		;COMPUTE CR FILLER
	MOVB	DB.COL(J),R1		;SET FILL TIME=67.5<1.5+INCHES> MS
	BIC	#^C377,R1		;FLUSH SIGN EXTENSION AS COL MAY BE > 127
	ASR	R1			;USE 5<1.5+COL/10.> JIFFIES
	ADD	#10,R1			;  =COL/2+8 JIFFIES
	CMP	R1,#177			;MAKE SURE RESULT IS POSITIVE BYTE TO GET JIFFIES
	BLE	1$
	MOV	#177,R1
1$:	MOVB	R1,DB.FTM(J)		;SET CR FILLER
	CLRB	DB.COL(J)		;NOW BACK AT COLUMN 0
	MOV	(SP)+,R1
	RTS	PC
.ENDC
TYPE40:	MOV	R1,R0			;COPY CHARACTER
	BIT	#TS.IMO,DB.DCS(J)	;IMAGE MODE OUTPUT ?
	BNE	TYPE90			;IF SO NO EDITING
	BIC	#^C177,R1		;STRIP PARITY BIT
	MOVB	PARTAB(R1),R0		;PUT PARITY ON CHARACTER
	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	#15,R1			;IS THIS A CARRIAGE RETURN ?
	BNE	TYPE90
	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.DCS(J)	;EVER DO FREE CR/LF
	BNE	TYPE90			;IF NOT DON'T DO ONE NOW
.IF NE FT2741
	TST	DB.BCD(J)		;IF WE ARE A 2741, R0 IS BCD NOW
	BPL	TYPE85
	MOV	R2,R0			;R2 STILL HAS ASCII - USE IT
.ENDC
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	372		;600 BAUD CR, EVEN (CAN'T DETECT ^C AT 600)
	.BYTE	362		;600 BAUD CR, 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	03		;600 BAUD CR
	.BYTE	03		;600 BAUD CR
	.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	362		;4800 BAUD CR, ODD
	.BYTE	372		;4800 BAUD CR, 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	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	07		;4800 BAUD CR
	.BYTE	07		;4800 BAUD CR
	.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	99$

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 FRAMMING ERROR
	BEQ	REC.00			;BRANCH IF NORMAL CHARACTER

;HERE TO HANDLE A FRAMING ERROR - PROBABLY A BREAK
.IF NE FT2741
	TST	DB.BCD(J)		;CHECK TO SEE IF LINE IS 2741
	BPL	20$			;IF IT IS SPECIAL HANDLING
	JMP	RCVBRK			;KROQUE
20$:
.ENDC
	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	99$			;AND IGNORE IT
30$:	BIT	#LCB.AB,LC.CAR(R2)	;IF THIS ISN'T AN AUTO-BAUD
	BEQ	99$			;LINE, THEN DON'T RESET SPEED
	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
99$:	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
	MOV	#215,R1			;A CR
	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
LRTS:	RTS	PC			;DON'T DO ANYTHING WITH THE CHAR
REC.00:
	BIC	#LCB.BK,LC.CAR(R2)	;CLEAR BREAK CHAR FLAG
.IF NE FT2741
	MOV	DB.BCD(J),R3		;GET 2741 STATUS BITS
	BPL	REC.60			;BRANCH IF NOT 2741
	BIT	#BCDRCR,R3		;TEST FOR LAST CHAR WAS A CR
	BNE	RCVEOT			;IF SO TREAT THIS CHAR AS AN EOT
	BIC	#^C77,R1		;CLEAR PARITY BIT
	CMP	#<BCDEOT&77>,R1
	BEQ	RCVEOT
	BIT	#BCDKBL,R3		;IS THE KEYBOARD LOCKED ?
	BNE	RCVEOA			;IS SO THIS MUST BE AN EOA
	CMP	#<BCDUCS&77>,R1		;IS THIS UP SHIFT ?
	BEQ	BCDRUS			;BRANCH IF WE RECEIVED AN UPSHIFT
	CMP	#<BCDLCS&77>,R1		;IS THIS A DOWN SHIFT ?
	BEQ	BCDRDS			;BRANCH IF WE RECEIVED A DOWN SHIFT
	MOV	R3,R2			;MAKE ANOTHER COPY OF DB.BCD
	BIC	#^C<BCDCOD+BCDUPS>,R2	;LEAVE ONLY FIELD FOR CODE & SHIFT
	ADD	R2,R1			;COMBINE CODSET WITH CHARACTER
	MOVB	BCDXIN(R1),R1		;TRANSLATE CHARACTER
	BEQ	99$			;IF NULL THROW CHAR AWAY
	BIC	#BCDRCR,R3		;CLEAR CARRIAGE RETURN BIT
	CMP	#15,R1			;KEEP TRACK OF CARRIAGE POSITION
	BNE	20$
	BIS	#BCDRCR!BCDKBL,R3
	BR	34$
20$:	CMP	#40,R1			;CHECK ALL SPACING CHARS
	BGT	21$			;BR IF CONTROL CHAR (MAYBE)
	CMP	#174,R1
	BGE	30$			;SPACING CHARS = SPACE (40) TO VERT. BAR (174)
21$:	CMP	#11,R1			;CHECK TAB
	BEQ	29$			;BR IF SO
	CMP	#10,R1			;CKECK BACKSPACE
	BNE	34$			;IF NOT THEN CARRIAGE NOT AFFECTED
	DECB	DB.COL(J)		;BACKSPACE
	BR	34$
29$:	BISB	#7,DB.COL(J)		;TAB TO NEXT MULTTIPLE OF 8
30$:	INCB	DB.COL(J)		;ADVANCE CARRIAGE POSITION
34$:	BIT	#BCDAPL,R3		;TEST FOR APL MODE
	BNE	REC.50			;BRANCH IF NO TRANSLATION
	BIT	#BCDCON,R3		;IS THIS THE CHARACTER FOLLOWING AN ARROR ?
	BEQ	40$
	BIC	#BCDCON,R3		;CLEAR FOLLOWING AN ARROW BIT
	CMP	R1,#10			;WAS CHAR A BACKSPACE ?
	BEQ	BCD.99			;IF IT WAS JUST STORE STATUS
	CMP	R1,#40			;TEST TO SEE IF CHAR MUST BE TRANSLATED
	BMI	REC.50			;BRANCH IF NO TRANSLATION
	MOVB	ARRTAB-40(R1),R1	;TRANSLATE AGAIN
37$:
	BR	REC.50
40$:	CMP	R1,#ARROW		;TEST FOR THIS CHAR IS AN ARROW
	BNE	REC.50
	BIS	#BCDCON,DB.BCD(J)	;SET ARROW MODE
99$:	RTS	PC			;AND DONE
REC.50:	MOV	R3,DB.BCD(J)		;RESTORE 2741 STATUS
REC.60:
.ENDC

	JMP	TTYINP			;PASS INPUT TO QUEUE
.IF NE FT2741
;HERE FROM REC.00 WHEN RECEIVE AN EOA
RCVEOA:	BIT	#BCDPRL,R3		;IS THE PRINTER ALREADY LOCKED ?
	BEQ	BCD.98			;IF NOT THIS MUST BE JUNK
	CMP	#BCDEOA,R1		;IS CHARACTER AN EOA ?
	BNE	BCD.98			;IF NOT IGNORE
	BIC	#BCDKBL!BCDUPS,R3	;KEYBOARD UNLOCKED & LOWER SHIFT
	BR	BCD.99			;RESTORE STATUS THEN DISMISS

;HERE WHEN RECEIVE AN EOT FROM A 2741 LINE
RCVEOT:	;BIT	#TS.TIW,DB.DCS(J)	;WAITING FOR INPUT ?
	;BEQ	10$
	BIC	#TS.TIW,DB.DCS(J)	;NO LONGER WAITING
	BIS	#DS.XDS,@J		;NEED TO SEND STATUS TO CONTROLLER
10$:	BIS	#BCDKBL!BCDPRL,R3	;SET ALL LOCKED
	BIT	#BCDXRB,R3		;TEST FOR WE WERE SENDING REVERSE BREAK
	BNE	BCD.99			;IF WE ARE IGNORE THIS EOT
	MOV	#<2*400+^D10>,DB.TIM(J)	;GIVE IT A TENTH OF A SECOND TO SETTLE
	BIT	#BCDRCR,R3		;CHECK FOR CR CASE
	BEQ	20$
	JSR	PC,CRF274		;YES, CALC. PROPER FILLER
	CLRB	DB.FTM+1(J)		;MAKE SURE DB.FTM FCN IS FILLER!
20$:	BIC	#BCDCON!BCDUPS!BCDRCR,R3 ;CLEAR UPPERSHIFT & PRINTER LOCKED
	BIS	#DS.ACT,@J		;WE WILL SEND A CHARACTER LATER
	BIT	#BCDRCR,DB.BCD(J)	;TEST AGAINST CORE COPY CUZ CLEARED R3
	BNE	BCD.99			;IF FOLLOWED CR WE ARE DONE
	BIT	#BCDAPL,R3		;IS LINE IN APL-MODE ?
	BEQ	BCD.99			;IF NOT WE ARE DONE
	MOV	#BELL,R1		;MAKE A BELL
	BR	REC.50			;GIVE THAT GUY A BELL

BCDRDS:	BIC	#BCDUPS,R3
	BR	BCD.99
BCDRUS:	BIS	#BCDUPS,R3		;SET UPPER SHIFT
BCD.99:	MOV	R3,DB.BCD(J)		;RESTORE STATUS TO 2741 TABLE
BCD.98:	RTS	PC

.ENDC
.ENDC
;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
	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,
	BIC	#^C177,R0		; AND CLEAR PARITY IN THE COPY
	BNE	10$			;IF NOT A NULL,  GO CHECK ^S
	BIT	#TS.IMI,DB.DCS(J)	;IF WE ARE IN IMAGE MODE
	BNE	10$			; THEN KEEP THE NULL
	RTS	PC			;IF NOT IMAGE MODE, IGNORE NULLS
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 let loop 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
.IIF NE FT2741,PIOFF
	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$:
.IF NE FT2741
	BIC	#BCDB27,DB.BCD(J)	; CLEAR 2741 BITS
	CMP	#B.134,LC.SPD(R2)	; IS IT A 2741
	BNE	20$			; IF NOT, NOTHING SPECIAL
	BIS	#BCD274!BCDVRG,DB.BCD(J); VIRGIN 2741
	BR	21$			; AND EXIT
20$:	CLR	DB.BCD(J)		; NO LONGER 2741
21$:	PION
.ENDC
99$:	RESTORE	<R3,R2>
	RTS	PC
.IFF
SETSPD:	RTS	PC
.ENDC
.ENDC