Google
 

Trailing-Edge - PDP-10 Archives - AP-D543V_SB - scnser.mac
There are 14 other files named scnser.mac in the archive. Click here to see a list.
TITLE SCNSER - TERMINAL SCANNER SERVICE  FOR 6.03 MONITORS  V21400
SUBTTL R CLEMENTS/RCC/DAL/PMW/EJW	30 NOV 78
	SEARCH	F,S
	$RELOC
	$HIGH



;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
;  OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (C) 1973,1974,1975,1976,1977,1978 BY DIGITAL EQUIPMENT CORP., MAYNARD, MASS.
XP VSCNSR,21400
ENTRY SCNSER
SCNSER::


;               TABLE OF CONTENTS FOR SCNSER
;
;
;                        SECTION                                   PAGE
;    1. PARAMETER AND CONFIG DEFINITIONS..........................   2
;    2. DATA STRUCTURES
;         2.1   LINTAB AND DSCTAB.................................   4
;         2.2   LINE DATA BLOCK (LDB).............................   5
;         2.3   TTY DEVICE DATA BLOCK (DDB).......................  14
;    3. TRANSMIT INTERRUPT ROUTINE................................  15
;    4. RECEIVE INTERRUPT ROUTINE.................................  21
;    5. KA10 CONSOLE TELETYPE SERVICE.............................  40
;    6. FILLERS AND SIMULATION ROUTINES...........................  41
;    7. TIMING ROUTINE............................................  50
;    8. SUBROUTINES FOR INTERRUPT LEVEL CODE......................  55
;    9. CHUNK HANDLERS
;         9.1   READ FROM BUFFER..................................  64
;         9.2   STORE INTO BUFFER.................................  65
;         9.3   FREE A CHUNK......................................  67
;         9.4   GET A CHUNK FROM FREELIST.........................  67
;         9.5   CLEAR BUFFERS.....................................  68
;   10. UUO LEVEL ROUTINES FOR BUFFERED I/O.......................  69
;   11. DDT MODE CALLI'S..........................................  76
;   12. TTCALL AND TRMOP.
;        12.1   TTCALL DISPATCH...................................  77
;        12.2   OUTCHR AND IMAGE OUTCHR...........................  79
;        12.3   OUTSTR AND RESCAN.................................  80
;        12.4   SKPINL AND SKPINC.................................  81
;        12.5   GETLIN............................................  82
;        12.6   SETLIN, INCHSL, INCHWL, INCHRS & INCHRW...........  83
;        12.7   TRMNO. UUO........................................  84
;        12.8   TRMOP. DISPATCH...................................  85
;        12.9   SKIPS AND CLEARS..................................  93
;        12.10  TRMOP. I/O........................................  94
;        12.11  TRMOP. I/O SUBROUTINES............................  95
;        12.12  TRMOP. DATASET FUNCTIONS..........................  96
;   13. SUBROUTINES FOR I/O.......................................  99
;   14. COMMAND LEVEL ROUTINES.................................... 107
;   15. SUBROUTINES FOR COMCON OR UUO LEVEL....................... 120
;   16. ROUTINES FOR PTY.......................................... 139
;   17. IMPURE DATA............................................... 142
SUBTTL PARAMETER AND CONFIG DEFINITIONS

XP STTYBF,20

;DATASET TRANSACTION CODES FROM SCNSER TO/FROM XXXINT'S

XP DSTOFF,1		;DSCREC OR DSCTYP
XP DSTON,2		;DSCREC OR DSCTYP
XP DSTRNG,3		;DSCREC
XP DSTREQ,3		;DSCTYP
XP DSTINI,4		;TO AND FROM. SENDING COMPUTER WAS RESTARTED.
XP DSTSTS,5		;REQUEST DATA SET STATUS
XP DSTCRQ,10		;CALL REQUEST TO MODEM. WANT TO DIAL OUT.
XP DSTPND,20		;PRESENT NEXT DIGIT, TO AND FROM.
; NOTE - TO MODEM, 20-37 MEAN SEND DIGIT N-20
; WHERE DIGIT 17 MEANS END OF NUMBER (TO BOTH HARDWARE AND SOFTWARE)
; AND DIGIT 16 MEANS 5-SECOND DELAY TO SOFTWARE, FOR SECOND DIAL TONE.
XP DSTNAC,40		;NO ACTION -SYSINI (ONLY USER OF DSTREQ) SHOULD
			; NOT MODIFY LINE STATUS CODES (CARRIER ON/OFF)

;LINE CONTROL TRANSACTION CODES

XP LNTEHC,1	;ENABLE HUNG CHECK
XP LNTDHC,2	;DISABLE HUNG CHECK
IFNDEF STDALT,<STDALT==033>		;VALUE OF STANDARD ALTMODE
IFNDEF VTAB,<VTAB==10>			;VERTICAL TAB SPACING (MUST BE POWER OF 2)
IFNDEF FTMLOG,<XP FTMLOG,-1>		;NON-ZERO TO INCLUDE MIC LOG CODE

;SIZE OF CHUNKS
XP TTCHKS,4		;MUST AGREE WITH COMMON
XP TT2CHK,TTCHKS*2	;TWO CHUNKS

XP IMGTIM,^D10		;MUST FIT IN LDPTIM FIELD. HUNG TIME FOR IMI


;HARDWARE PARAMETERS OTHER THAN THOSE IN THE XXXINT ROUTINES

CTY=120		;HARDWARE DEVICE NUMBER OF THE KA10 CONSOLE TTY
SUBTTL DATA STRUCTURES -- LINTAB AND DSCTAB


;DATA STRUCTURES IN COMMON

;LINTAB:	BLOCK # OF LINES INCLUDING SCANNER,CTY AND PTY'S
;EACH WORD=	RH= LDB ADR
;		LH13-17=0 (FOR @ LINTAB)
;		LH 0-12 ARE COPIED INTO LDBDCH PERMANENT BITS BY LDBCLR
;		POINTER = LNPVRG

;DSCTAB:	BLOCK # OF DATASETS NEEDING TIMING
;		RH= LINKED TTY LINE NUMBER FOR DATA
;		LH= TIME IN 14-17, ALSO DSCHWC,DSCSWC,DSCFAI

IFN FTMODM,<
XP DSCHWC,400000	;WHEN LAST HEARD FROM, THE HARDWARE CARRIER WAS ON
XP DSCSWC,200000	;THE SOFTWARE CONSIDERS THE CARRIER TO BE ON OR
			; TO BE COMING ON IMMINENTLY
XP DSCFAI,100000	;CARRIER WENT OFF, BUT MAY BE BRIEF FAILURE
			; EXCEPT FOR GPO 2B MODEM, MUST QUIT IMMEDIATELY
XP DSCNCR,040000	;NEW CARRIER FLAG, ON FOR FRACTION OF SECOND FOR CLOCK SYNC
XP DSCBLI,020000	;BLIND FLAG - IGNORE EVERYTHING FOR 1 SEC AFTER CARRIER ON
XP DSCDLW,010000	;DIALLER WAIT. WAITING FOR RESULTS FROM DIALLER
XP DSCDLF,004000	;DIALLER FAIL. UNSUCCESSFUL DIALLER ATTEMPT
XP DSCDLC,002000	;DIALLER COMPLETE. SUCCESSFUL DIALLER ACTION.
XP DSCEON,001000	;END OF NUMBER. SENT ALL DIGITS TO DIALLER.
XP DSCTMM,77		;TIME MASK. MUST AGREE WITH DSTIMP POINTER.

;DEFINITIONS FOR INITIALIZATION ROUTINE IN SYSINI

XP DSCICL,DSCHWC!DSCSWC!DSCFAI!DSCDLW!DSCDLF!DSCDLC!DSCEON!DSCTMM
XP DSCIC1,DSCHWC!DSCSWC
XP DSCIC2,DSCTMM!DSCFAI!DSCDLW!DSCDLF!DSCDLC!DSCEON

>			;END OF FTMODM CONDITIONAL
	SUBTTL	DATA STRUCTURES -- LINE DATA BLOCK (LDB)

;PROTOTYPE LINE DATA BLOCK FOR A TTY (OR PTY) LINE

SCNLDB::
PHASE 0

LDBDDB::!XWD	ZERO5,0	;ADDRESS OF LINE'S ATTACHED DDB, IF ANY
XP LDBCMR,400000	;SIGN BIT OF LDBDDB IS COMMAND REQUEST BIT
			; MUST BE IN WORD ZERO, FOR @U, 13-17 MUST BE ZERO
XP LDBCMF,200000	;COMMAND FORCED. MEANS TYI ATE A CONTROL C
			; WHICH WAS DESTINED FOR COMCON, OR SOME OTHER COMMAND
			; IS TO BE FORCED, VIA LDPCMX. MUST BE IN SAME
			; WORD AS LDBCMR
XP LDBCMK,100000	;FORCING KJOB COMMAND
			;BITS 9-12 ARE INDEX FOR FORCED COMMAND, 
			; POINTER = LDPCMX

LDICLR::!		;ON RESTART, START CLEARING HERE
LDBBKU:!0		;COPY OF LDBTIP AT LAST BREAK RECINT
LDBTIP:!0		;T2 TO PUT CHARACTERS IN INPUT BUFFER
LDBTIT::!0		;T2 TO TAKE CHARACTERS FROM INPUT BUFFER
LDBTIC:!0		;COUNT OF ECHOED CHARACTERS IN INPUT BUFFER
LDBBKC::!0		;COUNT OF BREAK CHARACTERS IN INPUT BUFFER
LDBTOP:!0		;T3 TO PUT CHARACTERS IN OUTPUT BUFFER
LDBTOT:!0		;T2 TO TAKE CHARACTERS FROM OUTPUT BUFFER
LDBTOC::!0		;COUNT OF CHARACTERS IN OUTPUT BUFFER
LDBECT:!0		;T2 TO TAKE CHARACTERS FROM INPUT FOR ECHOING
LDBECC::!0		;COUNT OF CHARACTERS TO ECHO
LDBXNP::!0		;XON CLASS CHARACTER POINTER FOR OUTPUT
LDBFLP::!0		;FILLER CHARACTER POINTER FOR OUTPUT
LDBPBK::!0		;WORD OF UP TO 4 BREAK CHARACTERS (8 BIT)
			;FOR PACKED IMAGE MODE (PIM); SET WITH TRMOP 2037
LDICLE==:.-1		;ON RESTART, CLEAR THRU HERE
;MORE OF THE PROTOTYPE LINE DATA BLOCK
LDBDCH::!0		;DEVICE CHARACTERISTICS BITS

;BITS IN LH OF LDBDCH (CARRIED IN LH OF U DURING INTERRUPT ROUTINE)

LDLOIP==:400000		;OUTPUT IN PROGRESS. EXPECTING XMT INTERRUPT
			; MUST BE SIGN BIT.
LDLIMI==:200000		;IMAGE INPUT (KEEP NULLS)
LDLIRM==100000		;IRMA CATCHER (LOST XMT INTERRUPT)
LDLXON==:40000		;XON TRUE (PAPER TAPE INPUT)
LDLOSU==:020000		;OUTPUT SUPPRESS (^O)
LDLNEC==:010000		;NO ECHO, DUE TO PROGRAM
LDLORS==004000		;OUTPUT CLEAR RACE CONDITION SYNC
LDLFCS==:002000		;LINE INITED IN FULL CHAR SET MODE
LDLECS==001000		;EAT COMMAND SYNC, FOR TTCALL 10
LDLDLR==:000400		;SUPPRESS DOLLAR SIGN ON ALTMODES.
XP LDLCOM,000200	;LINE IS AT COMMAND LEVEL
LDLBKA==:000100		;BREAK ON ALL CHARACTERS (DDTIN, TTCALL)

;*** BEGINNING OF GROUP OF BITS POINTED TO BY LDPVR1 ***
;*** BEGINNING OF 4 BITS POINTED TO BY GETLP1 FOR GETLIN ****
XP LDLSLV,000040	;SLAVE. THIS TTY MAY BE ASSIGNED.
XP LDLLCT,000020	;LOWER CASE TRANSLATE TO UPPER
XP LDLTAB,000010	;LINE ACCEPTS TABS, NOT SPACES.
XP LDLLCP,000004	;LOCAL COPY (NO ECHO)
;*** END OF BITS POINTED TO BY GETLP1 ***
XP LDLFRM,000002	;LINE ACCEPTS FF AND VT (ELSE USE LF'S)
XP LDLNFC,000001	;NO FREE CARRIAGE RETURN AT 72 COLUMNS
;*** END OF GROUP FOR LDPVR1 ***
XP LDLECH,LDLNEC!LDLBKA!LDLLCP

;BITS TO BE CLEARED ON A 140 RESTART
ZZL==LDLOIP+LDLIMI+LDLIRM+LDLOSU+LDLNEC+LDLECS+LDLDLR+LDLBKA+LDLXON
XP LDLIIF,LDLIMI+LDLFCS		;IMAGE INPUT OR FULL CHAR SET MODE
;RH OF LDBDCH - BITS 27-35 = LINE NUMBER, POINTER = LDPLNO

LDRPTY==:400000		;PSEUDOTELETYPE
LDRCTY==:200000		;CONSOLE TTY
;*** START OF GROUP OF BITS POINTED TO BY LDPVR2 ***
LDRDIS==100000		;DISPLAY KEYBOARD CONSOLE
LDRDSD==:040000		;DATASET DATA LINE
LDR274==:020000		;LINE IS A 2741
LDRHLF==010000		;HALF DUPLEX LINE (TWX OR DC10C)
LDRRMT==004000		;REMOTE NON-DATASET LINE
XP LDRDSR,LDRDSD+LDRRMT	;REMOTE OR DATA SET LINE (FOR PATCH)
			; SO CAN'T ATTACH TO PROJECT 1 #
;*** END OF GROUP FOR LDPVR2 ***
LDRREM==:002000		;TTY AT REMOTE STATION
LDRSHC==:001000		;SUPPRESS HUNG CHECK -I.E. DON'T FORCE CHAR'S OUT
			;  WHEN NO XMIT FLAG.--SET BY 680 FOR SPECIAL
			;  DEVICES (E.G. 2741) & ITS OPR. TTY

;BITS TO BE CLEARED ON A 400 RESTART
ZZR==LDRPTY+LDRCTY+LDRSHC

;DEFINITIONS OF BITS FOR GETLIN UUO, CLOSELY ASSOCIATED WITH ABOVE

GTLRDY==100		;BIT FOR GETLIN TO INDICATE WAITING BREAK CHAR
GTLT37==20		;MODEL 37 BIT (COPY OF LDLLCT)
GTLT35==10		;MODEL 35 BIT (COPY OF LDLTAB)
GTLLCP==4		;LOCAL COPY (OLD FULTWX) (COPY OF LDLLCP)
GTLXON==2		;XON IS TRUE (COPY OF LDLXON)
GTLMSK==LDR274!777	;BITS TO CLEAR ON GETLIN
LGLSET==GTLT37+GTLT35+GTLLCP+GTLXON	;MAY BE SET BY SETLIN


;MORE OF THE PROTOTYPE LINE DATA BLOCK

LDBOFL::!
LDBBYT::!0		;A WORD OF BYTES FOR THIS LINE

;BITS	POINTER	USE
;35-28	LDPECK	ECHO CHECK FOR HALF DUPLEX LINES
;27-20	PHPOS	HORIZONTAL POSITION ON LINE
;19-15	LDPTIM	TIMEOUT ON IMAGE INPUT
;14-06	LDPSVC	SAVE CHARACTER DURING FREE CRLF, ^X, ETC.
;05-03	POHPOS	OLD HORIZONTAL POSITION. NEEDED FOR TAB SIMULATION
;02-01	LDPFLC	COUNT OF NUMBER OF FILLERS BY CLASS
;0	-1 IF FRONT END FOR THIS LINE IS
;	DOWN.  USE LDBOFL AS THE SYMBOL
;	TO SKIPGE/SKIPL ON.
L1LOFL==:400000		;THE OFF-LINE BIT
LDIBCM==477777		;MASK TO CLEAR LDBBYT AT TTYINI. ALL ARE CLEARED
			; EXCEPT LDPFLC

;ANOTHER BYTE WORD, FLAGS AT LEFT.
LDBBY2::!0
;BITS	POINTER	USE
;35-28	LDPRCS	MOST RECENT RECEIVED CHARACTER
;20-27	LDPWID	WIDTH OF TTY CARRIAGE
;18-19	BITS - SEE BELOW
;9-17	LDPDSC	DATASET CONTROL TABLE INDEX BACK POINTER
;0-8	BITS - SEE BELOW

L2LDEL==:400000		;LAST CHAR IN WAS A DELETE
L2LCCS==200000		;LAST CHAR IN WAS A ^C
L2LHD1==100000		;XMT DONE FLAG SEEN THIS CHAR ON HDX LINE
L2LHD2==040000		;RCV DONE FLAG SEEN THIS CHAR ON HDX LINE
L2LHD3==020000		;IGNORING RCV INTS DUE TO ECHO CHECK ERR ON HDX LINE
L2LHD4==010000		;NEXT RCV INT WILL BE CUE AFTER ECHO CHK
L2LHD5==004000		;RECEIVE ECHO WAS IN FACT NOT SAME AS XMT CHAR
L2LSND==:002000		;SEND ALLOWED WHILE BUSY
L2LTAP==:001000		;^Q FROM KEYBOARD TURNS ON LDLXON. SET BY .TTY TAPE COMMAND

L2LHDM==L2LHD1!L2LHD2!L2LHD3!L2LHD4!L2LHD5

L2LCLR==L2LDEL!L2LCCS!L2LHDM!L2LSND!L2LTAP
			;CLEARED ON INITIALIZATION

L2RORH==400000		;OUTPUT RACE HAPPENED.  INDICATES THAT TSETBO
			;WAS CALLED WHILE LDLORS WAS SET.
L2RIRH==200000		;INPUT RACE HAPPENED.  INDICATES THAT TSETBI
			;WAS CALLED WHILE LPLIRS WAS SET.

;PAGE COUNTER WORD AND PAGE FLAGS
LDBPAG::!0
;BITS	 POINTER USE
;30-35	PAGE COUNTER
;24-29	PAGE SIZE
;18-23	#LF'S REMAINING ON F.F. SIMULATION
;10-17	AUTO CRLF COUNTER
;8	WE ARE FORCING XMIT START VIA TOPOKE
;7	INPUT RACE SYNC
;6	SEND ALL PENDING
;5	DON'T OUTPUT ANY MORE SINGLE L.F.'S
;4	SUPPRESS BLANK LINES (SET TTY NO BLANK)
;3	ALTMODE CONVERSION (SET TTY ALT)
;2	AN XOFF WAS SENT, XON NEEDED SOMETIME
;1	SET TTY PAGE HAS BEEN DONE
;0	TELETYPE OUTPUT HAS BEEN STOPPED
			;(MUST BE SIGN BIT)
LPLSTP==400000		;TTY OUTPUT IS STOPPED
LPLPAG==:200000		;SET TTY PAGE COMMAND WAS EXECUTED
LPLXOF==100000		;SENT XOFF, ALWAYS SEND AN XON LATER
LPLALT==:40000		;ALTMODE CONV. (1:CONVERT 175,176 TO 033)
LPLBLK==:20000		;SUPPRESS BLANK LINES
LPLSLF==10000		;SUPPRESS LINE FEEDS
LPLSAP==:4000		;SEND ALL PENDING
LPLIRS==2000		;INPUT RACE SYNC
LPLPOK==1000		;WE ARE FORCING XMIT START VIA TOPOKE (PREVENT RACE)
LPLCLR==LPLSTP!LPLXOF!LPLBLK!LPLSLF!LPLSAP!LPLIRS!LPLPOK  ;CLEARED BY LDBINI
;FLAGS AND POINTER TO INTERUPT SERVICE ROUTINES
LDBISR::!BLOCK	1	
;BITS	POINTER	USE
;0	N/A	1 IF THE FRONT END IS CLEVER, 0 IF DUMB
;1-4	LDPTSP	TRANSMIT SPEED
;5-8	LDPRSP	RECEIVE SPEED
;9	LDPAPL	APL MODE
;10	LDPDBK	DEBREAK FEATURE EXISTS
;11	LDPRTC	CONTROL-R, CONTROL-T COMPATIBILITY
;12	LDPTDY	USER SAID "SET TTY TIDY"
;13-17	CONTAIN T1 FOR @LDBISR(U)
;18-35	ADDRESS OF ISR DISPATCH TABLE

LILCFE==:(1B0)		;CLEVER FRONT END
LILRSP==:(17B4)		;RECEIVE SPEED
LILTSP==:(17B8)		;TRANSMIT SPEED
LILAPL==:(1B9)		;APL MODE
LILDBK==:(1B10)		;LINE HAS DEBREAK
LILRTC==:(1B11)		;CONTROL-R, CONTROL-T ARE PASSED TO PGM
LILTDY==:(1B12)		;DO NOT EXPAND OUTPUT

;FUNCTIONS ARE
ISRTYP==0		;OUTPUT DATA IN T3 ON LINE POINTED TO BY U
ISRDSC==1		;DATA SET CONTROL
ISRCHK==2		;TEST FOR LOST PIA
ISRINI==:3		;INIT ISR
ISRCHP==:4		;CHANGE HARDWARE PARAMETERS
ISRLPC==:5		;SEND LINE PARAMETER CONTROL MSG
ISRELE==:6		;SET ELEMENT #
ISRREM==:7		;DO REMOTE TTY STUFF
ISROFL==:10		;SKIP IF FRONT END ON LINE
IFN FTD10H,<
;FLAGS FOR 2741 SUPPORT
LDBBCD::BLOCK	1

>;END IFN FTD10H
;FIVE WORDS FOR REMOTE STATION TELETYPE STATUS

IFN FTNET,<
LDBREM::!BLOCK	1	;LH = SCB POINTER, RH = BITS
LRRIDL==:LRRTTO!LRRSCG!LRRCHP!LRRADL
LRRNOT==:LRRSCG!LRRCHP!LRRADL!LRRXOF	;TTY ACTIVE BUT NOT TO OUTPUT DATA
LRRLEO==:400000		;FRONT END IS DOING LOCAL ECHOING
LRRTTO==:200000		;TTY OUTPUT READY TO GO (28-35 IS CHAR)
LRRTTW==:100000		;TTY OUTPUT WAITING FOR DATA REQ.
LRRSCG==:40000		;CONTROL O WANTS A CHARACTER GOBBLER
LRREPW==:20000		;ECHO PIPELINE MARKER WAITING
LRRCHP==:10000		;WE NEED TO SEND CHARACTERISTICS
LRRIMO==:4000		;IMAGE OUTPUT MODE IN PROCESS
LRRADL==:2000		;AUTO DIAL REQUEST
LRRXOF==:1000		;WE MUST REQUEST THE FRONT END TO SEND "XOFF"
;	777		;CHARACTER WAITING TO OUTPUT
;			;INCLUDES THE IMAGE MODE BIT
	BLOCK	1	;LH = DATA REQ. COUNT, RH = STATUS BITS
	BLOCK	1	;LH = LAST ECHO PIPELINE MARKER (BITS 10-17)
			;RH = BACKWARD/FORWARD LINK FOR ACTIVE TTYS
LRDDSL==:400000		;REMOTE DATA SET LINE
LRDDTR==:200000		;RING/CARRIER
LRDDSR==:100000		;DATA SET READY
LRDATO==:40000		;AUTO BAUD LINE
LRDADL==:20000		;AUTO DIAL OUT LINE (BELL 801)
LRD741==:10000		;REMOTE 2741
LRDTIW==:4000		;TI INPUT WAIT
LRDCLR==:LRDDSR!LRDDTR!LRDTIW		;BIT TO CLEAR
			;RH = UNUSED
	BLOCK	1	;ENCODED LAST CHARACTERISTICS SENT
	BLOCK	1	;BYTE (8)REMOTE LINE #,(14)SLA,DLA


;DEFINITIONS FOR SUPPORT OF RSX-20F TERMINALS

LDBTTD==:LDBREM+1	;SAVED OUTPUT CHAR
LDBLAR==:LDBREM+2	;CURRENT LINE ALLOCATION REMAINING
LDBSS1==:LDBREM+3	;FIRST WORD OF LINESPEED MESSAGE SENT TO FRONT-END
	LRSXOF==:1	;FLAG FOR TTDINT TO REMEMBER ^S/^Q FOR LINE
	LRSRBS==:2	;REMOTE BIT SENT (BECAUSE OF RSX-20F QUIRK, CAN
			;  ONLY SAY LINE IS REMOTE ONCE)
LDBSS2==:LDBREM+4	;SECOND WORD OF LINESPEED MESSAGE,,TTD DTE INDEX

>;END OF IFN FTNET

IFN	FTMIC,<		;IF MIC INCLUDED
;WORD FOR MIC TO USE
LDBMIC::0

;0	SET IF SOME BIT 1-14 IS SET
;1	SET IF A ^C HAS BEEN TYPED
;2	SET IF OPERATOR CHAR SEEN IN COLUMN1
;3	SET IF ERROR CHAR SEEN IN COLUMN 1
;4	SET IF A ^P HAS BEEN TYPED
;5	SET IF A ^B HAS BEEN TYPED
;6	SILENCE THIS LINE
;7	LINE IN MONITOR MODE
;		NOT SET IN LDBMIC BUT IS SET ON A MICGET
;8	LINE IN USER MODE AND IN TI WAIT OR IN MONITOR MODE
;	AND CAN ACCEPT A COMMAND
;		NOT SET IN LDBMIC BUT IS SET ON A MICGET
;9	LINE IS IN COLUMN 1 ON OUTPUT
;	USED FOR ERROR AND OPERATOR CHECKING
;10	SET IF A ^A HAS BEEN TYPED (ABORT)
;11	SET IF TELETYPE OUTPUT IS AVAILABLE
;15-21	ASCII CHAR TO BE TREATED AS OPERATOR CHAR
;		SET IN RESPONSE TO OPERATOR COMMAND
;		CLEARED IN RESPONSE TO NOOPERATOR COMMAND
;		OR ON LOGOUT
;22-28	ASCII CHAR TO BE TREATED AS ERROR CHAR
;		SET IN RESPONSE TO ERROR COMMAND
;		CLEARED IN RESPONSE TO NOERROR COMMAND
;		OR ON LOGOUT
;29-35	MIC MASTER JOB NUMBER - ENABLES MORE THAN ONE MIC TO RUN

	LDLCHK==400000
	LDL.CC==200000
	LDL.OP==100000
	LDL.ER==40000
	LDL.CP==20000
	LDL.CB==10000
	LDL.XX==4000
	LDL.MM==2000
	LDL.TI==1000
	LDL.TO==400
	LDLCL1==400
	LDL.CA==200	;^A TYPED
	LDL.RS==100	;ERROR RESPONSE
	LDL.SY==40	;RESPONSE CODE SYNC
IFN FTMLOG,<
	LDL.LG==20	;MIC IS LOGGING

LDBLOT::0		;LOG TAKER,,COUNT OF CHARS TO LOG
LDBLOC::0		;COUNT OF CHARACTERS TO LOG
>	;END OF FTMLOG CONDITIONAL
	>	;END OF MIC CONDITIONAL
DEPHASE

LDBLEN==:.-SCNLDB		;SIZE OF DATA BLOCK FOR A LINE
;DISPATCH TABLE FOR PTYS AND CTYS.

IFN FTKA10!FTKI10,<
CTYDSP::
>;END IFN FTKA10!FTKI10
ERRDSP::POPJ	P,0		;TYPEOUT
	POPJ	P,0		;MODEM CONTROL
	POPJ	P,0		;ONCE A SECOND
	POPJ	P,0		;INITIALIZATION
	POPJ	P,0		;CHANGE HARDWARE PARMS
	POPJ	P,		;LINE PARM CONTROL
	POPJ	P,		;SET ELEMENT
	POPJ	P,		;REMOTE STUFF
	JRST	CPOPJ1##	;IS LINE UP?

IFN FTKL10,<
;DISPATCH FOR CTY

CTYDSP::POPJ	P,0		;TYPEOUT
	POPJ	P,0		;MODEM CONTROL
	POPJ	P,0		;ONCE A SECOND
	JRST	CT0INI##	;INITIALIZATION
	POPJ	P,0		;CHANGE HARDWARE PARMS
	POPJ	P,		;LINE PARM CONTROL
	POPJ	P,		;SET ELEMENT
	POPJ	P,		;REMOTE STUFF
	JRST	CPOPJ1##	;IS LINE UP?
>;END IFN FTKL10

;LINE SPEED MNEMONICS

LS0000==:0	;ZERO BAUD
LS0050==:1	;50 BAUD
LS0075==:2	;75 BAUD
LS0110==:3	;110 BAUD
LS0134==:4	;134.5 BAUD
LS0150==:5	;150 BAUD
LS0200==:6	;200 BAUD
LS0300==:7	;300 BAUD
LS0600==:10	;600 BAUD
LS1200==:11	;1200 BAUD
LS1800==:12	;1800 BAUD
LS2400==:13	;2400 BAUD
LS4800==:14	;4800 BAUD
LS9600==:15	;9600 BAUD

;DATA POINTERS INTO LDB

LDPFLC::POINT	2,LDBBYT(U),2		;POINTER TO INDEX OF FILLER CLASSES
LDPLNO::POINT	9,LDBDCH(U),35		;POINTER TO HARDWARE LINE NUMBER
LDPSVC:	POINT	9,LDBBYT(U),14		;POINTER TO SAVED CHARACTER
					;TO BE USED AFTER FILLERS SENT
LDPTIM:	POINT	5,LDBBYT(U),19		;POINTER TO FIELD WHICH TIMES OUT
					; IMAGE MODE INPUT
IFN FTHDPX!FTTRACK,<
LDPECK::POINT	8,LDBBYT(U),35		;POINTER TO LAST CHARACTER SENT, FOR
					; ECHO CHECK ON HDX LINE
>
PHPOS::	POINT	8,LDBBYT(U),27		;POINTER TO POSITION ON LINE (0-71)
POHPOS:	POINT	3,LDBBYT(U),5		;POINTER TO LOW 3 BITS OF HPOS
					; BEFORE A TAB (FOR TAB SIMULATION)
LNPVRG:	POINT	13,LINTAB##(T1),12		;POINTER TO LOW CORE COPY OF BITS FOR RESTART
LDPVR1:	POINT	6,LDBDCH(U),17		;POINTER TO STORE SOME OF ABOVE BITS
LDPVR2:	POINT	5,LDBDCH(U),24		;POINTER TO STORE SOME MORE OF ABOVE.
LDPCMX::POINT	4,LDBDDB(U),12		;POINTER TO INDEX OF FORCED COMMANDS
IFN FTTRACK,<
LDPRCS:	POINT	8,LDBBY2(U),35		;POINTER TO RECEIVED CHARACTER
					; SAVED FOR WATCHING IN LIGHTS.
>
LDPWID::POINT	8,LDBBY2(U),27		;POINTER TO WIDTH OF TTY CARRIAGE
IFN FTMODM,<
LDPDSC::POINT	9,LDBBY2(U),17		;POINTER TO DATASET CONTROL TABLE INDEX
>

LDPPSZ::POINT	6,LDBPAG(U),29		;PAGE SIZE (# OF LINES)
LDPPCT:	POINT	6,LDBPAG(U),35		;PAGE COUNTER
LDPPFF:	POINT	6,LDBPAG(U),23		;L.F. COUNTER FOR SIMULATION OF V.T. & F.F.


IFN FTCAFE,<
LDPSPD::POINT	8,LDBISR(U),8		;BOTH SPEEDS
> ;END FTCAFE
LDPRTC::POINT	1,LDBISR(U),11		;^R, ^T COMPATIBILITY
LDPRSP::POINT	4,LDBISR(U),8		;RECEIVE SPEED
LDPTSP::POINT	4,LDBISR(U),4		;TRANSMIT SPEED
LDPAPL::POINT	1,LDBISR(U),9		;APL MODE BIT
LDPDBK::POINT	1,LDBISR(U),10		;DEBREAK FEATURE EXISTS
LDP274::POINT	1,LDBDCH(U),22		;LINE IS A 2741
LDPTDY::POINT	1,LDBISR(U),12		;DO NOT EXPAND OUTPUT
LDPACR::POINT	8,LDBPAG(U),17		;AUTO CRLF POINT
IFN FTNET,<
;BYTE POINTERS TO THE LDBREM
LDPRLN::POINT	8,LDBREM+4(U),7		;PHYSICAL REMOTE LINE NUMBER
LDPSLA::POINT	14,LDBREM+4(U),21	;SOURCE LINK ADDRESS
LDPDLA::POINT	14,LDBREM+4(U),35	;DESTINATION LINK ADDRESS
LDPEPM::POINT	8,LDBREM+2(U),17	;CURRENT ECHO PIPLE MARKER
LDPDRQ::POINT	8,LDBREM+1(U),17	;DATA REQUEST COUNT
LDPELE::POINT	4,LDBREM+1(U),9		;ELEMENT NUMBER
LDPALF::POINT	9,LDBREM+2(U),35	;FORWARD ACTIVE TTY POINTER
LDPALB::POINT	9,LDBREM+2(U),26	;BACKWARD
LDPBLF::POINT	9,LDBREM+2(T1),35	;LIKE ABOVE BUT FOR DIFFERENT TTY
LDPBLB::POINT	9,LDBREM+2(T1),26
>;END OF IFN FTNET

;BITS TO BE CLEARED ON A 140 RESTART

LDIDCM:	XWD	ZZL,ZZR			;TO CLEAR BITS IN LDBDCH
	SUBTTL	DATA STRUCTURES -- TTY DEVICE DATA BLOCK (DDB)

;PROTOTYPE SCANNER DDB. REPLICATED BY ONCE. ONE FOR EACH JOB.

	$LOW
TTYLST::			;LABEL FOR FIRST TTY DDB IN CHAIN

SCNDDB::			;GLOBAL LABEL
PHASE 0

	SIXBIT	/TTY0/		;DEVNAM (PHYSICAL NAME)
	XWD	0,STTYBF+1	;DEVCHR. SIZE OF USER BUFFER
	0			;DEVIOS
	XWD	0,SCNDSP	;DEVSER
	XWD	DVTTY+DVIN+DVOUT,<<1_A>+<1_AL>+<1_PIMMOD>+<1_I>>	;DEVMOD
	0			;DEVLOG (LOGICAL NAME)
	0			;DEVBUF
	XWD	R,0		;DEVIAD
	XWD	R,0		;DEVOAD
	0			;DEVSTS
	XWD	.TYTTY,0	;DEVSTA
	0			;DEVXTR
	0			;DEVEVM
	0			;DEVPSI
	0			;DEVESE
	0			;DEVHCW
	0			;DEVJOB
DDBLDB::!0			;DDBLDB LINKS TO THE LDB.

IFN FTACCT,<
DDCOFS==:DDBICC			;OFFSET OF COUNTS IN TTY DDB
DDBICC:  0			;INPUT CHARACTER COUNT
DDBOCC:  0			;OUTPUT CHARACTER COUNT
DDBBCC::!0			;COMMANDS TYPED,,INPUT WAKEUP CHARACTERS
>
DEPHASE
XP SCNDDS,.-SCNDDB
	$HIGH
BYTCNT:	POINT	12,DEVOAD(F),12


;DATA WITHIN THE DDB

;USE OF DEVIOS

;LEFT HALF
XP TTYOUW,400000	;REMEMBERS THAT IF IN IOW, IT IS FOR OUTPUT, AS
			; OPPOSED TO INPUT. I.E., WHICH INT WAKES JOB
FRCEND=:200000		;IN IMAGE INPUT, FORCE END OF FILE DUE TO TIMING
IOSBKA=100000		;BREAK ON ALL CHARACTERS, DUE TO DDTIN OR TTCALL

;RIGHT HALF
DLRSUP==400		;SUPPRESS ECHO OF DOLLAR SIGN ON ALTMOD
NOECHO==:200		;USER (E.G. LOGIN) SUPPRESSING ECHO
FCS==100		;USER WANTS ALL CHARACTERS.
SUBTTL TRANSMIT INTERRUPT ROUTINE

;ENTRY FROM DEVICE-DEPENDENT INTERRUPT SERVICE ROUTINE ON A
; TRANSMIT-DONE INTERRUPT. THE HARDWARE LINE NUMBER IS
; IN AC U
;ALSO ENTERED AT XMTIN0 AND XMTIN1 TO START ACTIVITY, SINCE CAN'T
; SET THE DONE FLAG ON AN INDIVIDUAL LINE IN THE SCANNER TO
; START THE DEVICE.


XMTINT::MOVE	U,LINTAB##(U)	;GET LINE DATA BLOCK ADDRESS
IFN FTRSP,<	AOS	%SCNXI	;COUNT INTERRUPT>
	MOVSI	T1,L1LOFL
	ANDCAM	T1,LDBOFL(U)
	SKIPL	LDBDCH(U)	;ARE WE EXPECTING THIS?
	PJRST	XMTDMC		;IN CASE 2741
IFN FTHDPX,<
	MOVE	T1,LDBDCH(U)	;SEE IF ITS A HALF DUPLEX LINE
	TRNE	T1,LDRHLF	; ..
	JRST	XMTHDX		;YES. SPECIAL HANDLING
>
XMTIN0:	HLL	U,LDBDCH(U)	;GET CHARACTERISTICS BITS
	HRRZ	T1,LDBDDB(U)	;TEST FOR PIM, GET DDB ADDRESS
	JUMPE	T1,XMTIN1	;NO DDB, CANT BE PIM
	MOVE	T1,DEVIOS(T1)	;GET WORD WITH MODE IN IT
	TRNE	T1,PIMMOD	;PIM MODE BIT SET?
	JRST	XMPIM		;YES, THIS LINE IN PIM 
IFN	FTMIC,<		;IF MIC
XMTIN1:	MOVEI	T1,LDRPTY
	TDNE	T1,LDBDCH(U)
	JRST	XMTBFZ
	SKIPE	LDBXNP(U)	;NEED XOFF OR BELL?
>	;END OF IF MIC BIT
IFE	FTMIC,<		;IF NOT MIC
XMTIN1:	SKIPE	LDBXNP(U)	;NEED XOF OR BELL?
>		;END OF IF NOT MIC BIT
	JRST	XMTXOF		;YES. GO SEND IT
XMTXOZ:	SKIPE	LDBFLP(U)	;NEED FILLERS FOR PREVIOUS OUTPUT?
	JRST	XMTFIL		;YES. GO SEND THEM.
XMTFIZ:	;RETURN HERE IF FILLER POINTER REACHES END OF FILLER STREAM
	SKIPLE	LDBTOC(U)	;CHARACTERS LEFT IN OUTPUT BUFFER?
	JRST	XMTBUF		;YES. GO SEND ONE.
XMTBFZ:	SKIPLE	LDBECC(U)	;CHARACTERS TO ECHO?
	JRST	XMTECH		;MAYBE. GO SEE.
XMTECZ:	;RETURN HERE IF NONE TO ECHO
XMTIDL:	;IF GET HERE, LINE IS NOW IDLE. CLEAN IT UP.

	MOVSI	T1,LDLOIP+LDLIRM	;CLEAR OUTPUT SYNC BIT AND
	ANDCAM	T1,LDBDCH(U)	; HUNG LINE SYNC BIT
IFN FTHDPX,<
	MOVSI	T1,L2LHDM	;CLEAR HALF DUPLEX FLAGS TOO
	ANDCAM	T1,LDBBY2(U)	; ..
>
IFN FTHIBWAK,<
	HRRZ	F,LDBDDB(U)	;ADDRESS OF LINKED DDB
	PUSH	P,J		;SAVE J
	JUMPE	F,XMTPSI	;JUMP IF NO DDB
	LDB	J,PJOBN##	;GET JOB NUMBER
	MOVE	T1,JBTSTS##(J)	;GET JOB STATUS
	TRNE	T1,JS.NTO	;HIBERING FOR NON-BLOCKING TTY OUTPUT?
	PUSHJ	P,WAKEJB##	;YES--WAKE HIM UP
XMTPSI:	POP	P,J		;RESTORE J
>
XMTDMC:
IFN FTCAFE&FT2741!FTNET,<
	SKIPGE	LDBDDB(U)	;ANY COMMAND?
	JRST	XMTWAK		;YES--WAIT FOR IT
	TLNE	U,LDLCOM	;AT COMMAND LEVEL?
	PUSHJ	P,UNLKBD	;YES--UNLOCK KEYBOARD
	HRRZ	F,LDBDDB(U)	;IF NO DDB ALL DONE
IFN	FTMIC,<		;IF MIC
	JUMPE	F,XMTWAK	; ..
>			;END OF IF MIC
IFE	FTMIC,<			;IF NOT MIC
	JUMPE	F,CPOPJ##	; ..
>			;END OF IF NOT MIC
	SKIPL	T1,DEVIOS(F)	;SKIP IF NOT IN INPUT WAIT
	TLNN	T1,IOW		;WAITING FOR INPUT
	JRST	XMTWK1		;NO--TEST FOR OUTPUT
	PJRST	UNLKBD		;YES--UNLOCK 2741
>	;END FTCAFE&FT2741!FTNET
XMTWAK::
IFN	FTMIC,<			;IF MIC
IFN FTMLOG,<
	SKIPE	T1,LDBMIC(U)
	TLNN	T1,LDL.LG
	PUSHJ	P,MLOGOF	;NOT REQUIRE LOG FEATURE
	HRRZ	T1,LDBLOC(U)	;HOW BIG IS LOG BUFFER
	CAIL	T1,^D79
	JRST	MICWAK		;WAKE MIC NOT JOB
	SKIPE	LDBMIC(U)
	PUSHJ	P,MICWAK	;WAKE MIC AS WELL
>	;END OF MIC LOG CONDITIONAL
>	;END OF IF MIC
	HRRZ	F,LDBDDB(U)	;GET ADDR OF ATTACHED DDB
	JUMPE	F,CPOPJ##	;IF NONE, SKIP THIS CODE
	MOVE	T1,DEVIOS(F)	;GET STATUS OF TTY FROM DDB
XMTWK1:	TLNE	T1,IOW		;JOB IN I/O WAIT FOR TTY?
	JUMPL	T1,TTWAKE	;WAKE JOB IF OUTPUT WAIT
	POPJ	P,0		;RETURN
;PACKED IMAGE MODE (PIM)  INTERRUPT LEVEL CODE...

XMPIM:
	SKIPE	LDBXNP(U)	;XOFF/XON TO BE SENT?
	JRST	XMPX		;YES, DO SO
XMPIM1:
IFN FTTPAG,<
	SKIPGE	LDBPAG(U)	;OUTPUT STOPPED BY XOF?
	JRST	XMTIDL		;YES, DONT TYPE ANY MORE
>	;END OF FTTPAG
	MOVE	T2,LDBTOT(U)	;IS TAKER
	CAME	T2,LDBTOP(U)	; CAUGHT UP?
	SOSGE	LDBTOC(U)	;ANY OUTPUT TO DO
	JRST	XMTIDL		;NO, GO IDLE
	SKIPE	LDBXNP(U)	;XOFF/XON TO BE SENT?
	JRST	ZAPIM		;POINTER OR COUNT MESSED UP
	IBP	LDBTOT(U)
	MOVE	T2,LDBTOT(U)
	PUSHJ	P,TTGETC	;GET THE CHARACTER, LINK IF NECESSARY
	  PUSHJ P,XMTBFF	;NEW CHUNK, FREE OLD
	MOVE	T1,LDBTOC(U)	;GET CHARACTER COUNT OF OUTPUT BUFFER
	CAIG	T1,12		;IF LESS THAN 10. CHARS LEFT IN OUTPUT BUFFER,
	PUSHJ	P,XMTWAK	;WAKE UP THE ATTATCHED JOB
	JRST	TYPE		;SENT CHARACTER IN T3 AND DISMISS

ZAPOUT:	CONO	PI,PIOFF##	;SOMEHOW WE GOT OUTPUT POINTERS
	SETZM	LDBTOC(U)	; OR COUNT MESSED UP.  ADJUST THEM
	MOVE	T2,LDBTOT(U)	; TO PREVENT VARIOUS CRASHES
	MOVEM	T2,LDBTOP(U)	; CAUSED BY RACE CONDITIONS
	CONO	PI,PION##	; SUCH AS CL0, RCC, ETC.
	POPJ	P,

ZAPIM:	PUSHJ	P,ZAPOUT
	JRST	XMTIDL

XMPX:	ILDB	T3,LDBXNP(U)	;SEND FORCED CHARACTER
	JUMPN	T3,TYPE		;TYPE IF ANY THERE
	SETZM	LDBXNP(U)	;ELSE,CLEAR POINTER WORD
	JRST	XMPIM1		;BACK
;HERE ON A TRANSMIT DONE INTERRUPT WHEN LDBTOC .GT. ZERO

XMTBUF:
IFN	FTMIC,<			;IF MIC

IFN FTMLOG,<
	MOVE	T2,LDBMIC(U)
	TLNE	T2,LDL.LG	;HAS HE ASKED FOR LOG
	SKIPE	LDBLOT(U)	;HAS HE GOT A LOG TAKER
	JRST	MICLG3
	MOVE	T2,LDBTOT(U)	;MAKE COPY OF TAKER
	MOVEM	T2,LDBLOT(U)

MICLG3:
>	;END OF FTMLOG CONDITIONAL
	LDB	T2,PHPOS	;HORIXONTAL POSITION
	JUMPN	T2,XMTOK	;IN COLUMN 1?
	SKIPE	T2,LDBMIC(U)	;IS HE RUNNING MIC OR
	TLNN	T2,LDL.RS!LDL.SY	;WANTS RESPONSE FEATURE
	JRST	XMTOK		;NO - MUST NOT INTERFERE
	TLNE	T2,LDL.ER	;HAS HE HAD ERROR?
	TLNE	T2,LDL.CC	;AND NOT ^C
	JRST	XMTOK		;NO - IGNORE
	MOVE	T2,LDBTOT(U)	;PREVIEW CHAR IN COL 1
	IBP	T2
	PUSHJ	P,TTGETC
	  JFCL

	LDB	T2,LDP.ER	;GET ERROR CHAR
	JUMPE	T2,XMTOK	;MUST BE ONE
	ANDI	T3,177		;JUST 7 BITS
	CAME	T3,T2		;SAME AS ERROR CHAR?
	JRST	XMTOK		;NO IGNORE

	MOVSI	T2,LDL.SY!LDLCHK ;SET THE SYNC
	IORB	T2,LDBMIC(U)
	TLNN	T2,LDL.RS	;BEEN THIS WAY BEFORE
	JRST	XMTBFZ		;YES JUST DO ECHOING

	HRRZ	F,LDBDDB(U)
	JUMPE	F,XMTBFZ	;NO ATTACHED DDB
	MOVE	S,DEVIOS(F)
	TLNN	S,IOW		;IN IO WAIT?
	JRST	XMTBFZ		;NO FORGET IT
	MOVSI	T2,LDL.RS
	ANDCAM	T2,LDBMIC(U)	;SAY SYNC
	PUSHJ	P,MICWAK
	JRST	XMTBFZ		;AND PUT THE PLUG IN

XMTOK:
>			;END OF IF MIC
IFN FTTPAG,<
	SKIPGE	LDBPAG(U)	;HAS OUTPUT BEEN STOPPED BY XOFF?
	JRST	XMTBFZ		;YES, THEN DON'T TYPE ANY MORE
>
	MOVE	T2,LDBTOT(U)	;BE SURE TAKER HASN'T
	CAME	T2,LDBTOP(U)	; CAUGHT UP TO PUTTER
	SOSGE	LDBTOC(U)	;BETTER TO DECREMENT BEFORE USING
	JRST	ZAPBUF		; POINTER OR COUNTER MESSED UP
	CONO	PI,SCNOFF##	;PROTECT AGAINST RACE
	IBP	LDBTOT(U)	;INCREMENT TO NEXT CHARACTER POSITION
	MOVE	T2,LDBTOT(U)	;...AND PUT INTO T2 FOR TTGETC
	PUSHJ	P,TTGETC	;GET THE CHAR. LINK IF NEEDED.
	  PUSHJ P,XMTBFF	;WENT ON TO ANOTHER CHUNK
	CONO	PI,SCNON##	;CHANNEL BACK ON
	MOVE	T1,LDBTOC(U)	;GET CHARACTER COUNT OF OUTPUT BUFFER
IFN FTMLOG,<
	SKIPE	LDBLOT(U)
	AOS	LDBLOC(U)
>	;END OF FTMLOG CONDITIONAL
	JUMPE	T3,XMTFIZ	;NULL, RETURN TO LDBTOC TEST
	CAIG	T1,12		;IF .LE. 10. CHARS LEFT IN OUT BUF,
	PUSHJ	P,XMTWAK	;WAKE UP THE ATTACHED JOB (IF ANY)

IFN FTTBLK,<
	MOVSI	T1,LPLBLK	;BLANK SUPPRESSION?
	TDNE	T1,LDBPAG(U)
	PUSHJ	P,BLKSUP	;YES
>
IFN FTTVP,<
	PUSHJ	P,ADJVP		;ADJUST VERTICAL POSITION
	  SKIPA	T1,LDBPAG(U)	;PAGE OVERUN - GET BITS
	JRST	TYPEF1
	TLNN	T1,LPLPAG	;ENABLED FOR PAGE HALTS?
	JRST	TYPEF1		;NO
	MOVSI	T1,LPLSTP	;YES - SET BIT
	IORM	T1,LDBPAG(U)
>	;IFN FTTVP

TYPEF1:	;ENTER HERE TO TYPE A CHARACTER WITH ITS FILLERS
	PUSHJ	P,ADJHP		;ADJUST THE HORIZONTAL POSITION.
	TRNE	T3,400
	JRST	TYPE
	PUSHJ	P,SETFLO	;SET UP THE POINTER TO ANY FILLERS
	  JRST XMTFIL		;NEED CRLF. GO SEND IT FIRST.
	JRST	TYPE		;SEND THE CHARACTER IN T3, RETURN.

ZAPBUF:	PUSHJ	P,ZAPOUT
	JRST	XMTBFZ
;HERE ON A TRANSMIT DONE INTERRUPT WHEN LDBXNP IS NON-ZERO.
;LDBXNP IS A NINE-BIT BYTE POINTER TO FORCED CHARACTERS SUCH AS
; XOFF AND BELL.

XMTXOF:	ILDB	T3,LDBXNP(U)	;GET A CHARACTER.
	JUMPN	T3,TYPE		;IF NOT AT END, SEND AND DISMISS
	SETZM	LDBXNP(U)	;REACHED END. CLEAR POINTER
	JRST	XMTXOZ		; AND RETURN TO MAIN FLOW OF XMTINT

;HERE ON A TRANSMIT-DONE INTERRUPT WHEN LDBFLP IS NON-ZERO.
;LDBFLP IS A NINE-BIT BYTE POINTER TO FILLER CHARACTERS, OR
; TO FREE CRLF'S OR TAB SIMULATIONS.

XMTFIL:	ILDB	T3,LDBFLP(U)	;GET A FILLER CHARACTER
	JUMPN	T3,XMTFI1	;IF NOT AT END, SEND IT AND DISMISS
IFN FTTALK,<
	MOVSI	T1,LPLSAP	;WAITING TO DO A
	TDNE	T1,LDBPAG(U)	;SEND ALL?
	JRST	[ANDCAM T1,LDBPAG(U)	;YES -- CLEAR BIT
	  MOVE	T1,SNDPTR##	;SET UP POINTER
	  MOVEM	T1,LDBFLP(U)	;STORE IN LDB
	  JRST	XMTFIL]		;TYPE THE STRING
>
	SETZB	T1,LDBFLP(U)	;END. CLEAR THE BYTE POINTER AND T1
IFN FTTVP,<
	LDB	T3,LDPPFF	;F.F. OR V.T. SIMULATION?
	SOJL	T3,XMTFI0	;NO
	DPB	T3,LDPPFF	;YES - OUTPUT ANOTHER L.F.
	MOVEI	T3,12
	JRST	XMTFI2
>	;IFN FTTVP
XMTFI0:	LDB	T3,LDPSVC	;SEE IF ANY SAVED CHARACTER
	JUMPE	T3,XMTFIZ	;IF NOT, RETURN TO XMTINT
	DPB	T1,LDPSVC	;CLEAR THE SAVED CHAR BYTE
XMTFI2:	MOVE	T1,LDBDCH(U)
	TDNN	T1,[LDLLCP+LDLNEC,,LDRHLF]
	SKIPE	LDBTOC(U)	;WAS THAT CHAR FOR INPUT OR OUTPUT?
	JRST	TYPEF1		;OUTPUT. GO SEND IT WITH FILLERS
	JRST	TYPEF2		; INPUT.

XMTFI1:	CAIE	T3,FLLFLG	;IS THIS A FLAG OR A CHARACTER?
	JRST	TYPE		;CHARACTER. GO TYPE IT.
	LDB	T1,LDPFLC	;FLAG. APPEND CRLF. WHAT FILLERS?
IFN FTNET,<
	MOVE	T3,LDBDCH(U)	;GET TTY BITS
	TRNE	T3,LDRREM	;REMOTE STATION TTY?
	SETZ	T1,		;YES, IT DOES ITS OWN FILL.
>
	MOVE	T3,FLLCRP(T1)	;GET RIGHT CRLF POINTER
	MOVEM	T3,LDBFLP(U)	;PLACE IN FILLER POINTER
	JRST	XMTFIL		;AND GO TYPE FROM IT.

XMTBFF:	MOVEM	T2,LDBTOT(U)	;STORE NEW OUTPUT ADDRESS
IFE FTMLOG,<
	PJRST	FRECHK		;AND GO RETURN THE CHUNK TO FREE LIST

>

IFN FTMLOG,<
	SKIPN	LDBLOT(U)	;IS MIC LOGGING
	PJRST	FRECHK		;NO-FREE UP THE CHUNK
	POPJ	P,0
>	;END OF FTMLOG CONDITIONAL
;HERE WHEN BUFFERED AND FILLER OUTPUT DONE, AND LDBECT IS NON-ZERO
;NEED TO ECHO A CHARACTER THAT HAS BEEN TYPED IN.

XMTECH:	MOVE	T2,LDBECT(U)	;ECHO CAUGHT UP
	SOSL	LDBECC(U)	; OR COUNT EXHAUSTED?
	CAMN	T2,LDBTIP(U)
	JRST	ZAPECH		;YES.  ERROR
	IBP	LDBECT(U)	;POINT TO NEXT CHAR TO ECHO
	MOVE	T2,LDBECT(U)	;AND GET UPDATED POINTER INTO T2
IFN FTRSP,<	AOS	%SCNEI>
	PUSHJ	P,TTGETC	;GET THE CHARACTER. LINK IF NEEDED
	  MOVEM T2,LDBECT(U)	;STORE NEW CHUNK ADDRESS
	PUSHJ	P,SPCHEK	;SEE IF IT'S SPECIAL.
	  JRST XMTEC1		;IT'S NOT.
	TLNE	T1,CHBRK	;YES. IS IT A BREAK CHAR?
	AOS	LDBBKC(U)	;YES. COUNT IT IN THE LDB
XMTEC1:	AOS	T2,LDBTIC(U)	;COUNT THE INPUT CHARACTERS
	TLNE	U,LDLBKA+LDLIMI	;BREAK ON ALL CHARACTERS?
	PUSHJ	P,RCVWKQ	;YES. GO DO SO IF NEEDED.
	CAIG	T2,^D72		;ARE THERE OVER 72. OF THEM?
	TLNE	T1,CHBRK	;OR IS IT A BREAK CHARACTER?
	PUSHJ	P,ECHBRK	;YES. WAKE THE JOB, IF ANY

IFN FTTVP,<
	PUSHJ	P,ADJVP		;ADJUST VERT. POSITION
	  JFCL			;IGNORE PAGE OVERRUN
>
TYPEF2:	PUSHJ	P,SETFLI	;SET FILLERS FOR ECHOING
	  JRST XMTFIL		;OUTPUT FROM FILLER POSITION.
IFN FTMIC,<
	SKIPN	T1,LDBMIC(U)	;RUNNING MIC?
	JRST	TYPE2B		;NO
	TLNN	T1,LDL.CB	;IN MIC BREAK?
	JRST	TYPE2A		;NO, DON'T DO ECHO CHECK
TYPE2B:				;YES, NORMAL CHECKING
>
	MOVE	T1,LDBDCH(U)	;GET LEFT AND RIGHT HALF BITS
	TDNE	T1,[XWD LDLLCP,LDRHLF!LDR2741]	;EITHER TYPE OF LOCAL COPY?
	JRST	XMTIN1		;YES. DO NOT ECHO THE CHARACTER
IFN FTNET,<
	MOVEI	T1,LRRLEO	;CHECK FOR LOCAL ECHO MODE
	TDNE	T1,LDBREM(U)
	JRST	XMTIN1		;DONT ECHO CHAR -- DC72 ALREADY DID
>
TYPE2A:
	TLNN	U,LDLCOM	;CHARACTER ITSELF SHOULD BE ECHOED
	TLNN	U,LDLNEC	;UNLESS USER LEVEL AND HE SAID NO
IFN	FTMIC,<			;IF MIC
	SKIPA	T1,LDBDCH(U)	;RESTORE LINE CHARACTERISTICS
	JRST	XMTIN1		;NO. STEP TO NEXT CHARACTER
	TRNN	T1,LDRPTY	;REMOTE OR PTY
	JRST	TYPE		;NO-JUST TYPE NORMALLY
	MOVE	T2,LDBMIC(U)
	TLNE	T2,LDL.XX
	JRST	TYPEF3
	PUSHJ	P,TTPTOC	;UPDATE BYTE POINTER, STORE CHARACTER
	AOS	LDBTOC(U)
TYPEF3:	PUSHJ	P,PTSTRT
	JRST	XMTIN1
>			;END OF IF MIC
IFE	FTMIC,<			;IF NOT MIC
	JRST	TYPE		;SEND CHARACTER
	JRST	XMTIN1		;NO, STEP TO NEXT CHARACTER
>			;END OF IF NOT MIC

ZAPECH:	CONO	PI,PIOFF##
	SETZM	LDBECC(U)	;FIX UP
	MOVE	T2,LDBTIP(U)	;MESSED UP
	MOVEM	T2,LDBECT(U)	;ECHOING
	CONO	PI,PION##
	JRST	XMTIDL
ECHBRK:	PUSHJ	P,COMQ		;IS LINE AT COMMAND LEVEL?
	  PJRST RCVWAK		;NO. WAKE JOB IF ANY.
	PJRST	COMSET		;YES. SET COMMAND REQUEST.

RCVWKQ:	PUSHJ	P,COMQ		;IS LINE AT COMMAND LEVEL?
	  PUSHJ P,RCVWAK	;NO. WAKE JOB.
	POPJ	P,0		;YES. DON'T MAKE COMMAND FOR LDLBKA

IFN FTHDPX,<
XMTHDX:	JUMPGE	T1,XMTIN0	;HANDLE NORMALLY IF NO XMT EXPECTED
	MOVSI	T1,L2LHD1	;FLAG THAT XMT DONE HAPPENED
	IORB	T1,LDBBY2(U)	; ..
	TLNN	T1,L2LHD2	;HAS REC INT OCCURRED ALSO?
	POPJ	P,0		;NO. WILL HANDLE WHEN RCV HAPPENS
	JRST	RHDERQ		;YES. GO SEE IF ERROR IN ECHO
>
SUBTTL RECEIVE INTERRUPT ROUTINE

;HERE FROM DEVICE-DEPENDENT INTERRUPT ROUTINE ON A RECEIVE INTERRUPT.
;AT THIS POINT, T3(28-35) HAS RECEIVED CHARACTER, U HAS PHYSICAL LINE #
;AS INDEX INTO LINTAB

RECINT::
IFN	FTMIC,<				;IF MIC
	CAMN	U,MICLIN	;IS MIC TYPING ON THIS LINE?
	POPJ	P,		;YES - IGNORE CHAR AT INTERRUPT LEVEL
>				;END OF IF MIC
RECINU:	ANDI	T3,377		;JUST 8 BITS OF CHARACTER.
				; END OF IF NOT MIC
				; CLEAR ANY DEVICE DEPENDENT BITS
IFN FTRSP,<	AOS	%SCNRI>
	MOVE	U,LINTAB##(U)	;GET ADDRESS OF LDB.
	MOVSI	T1,L1LOFL	;PUT TTY ON LINE
	ANDCAM	T1,LDBOFL(U)	;SINCE SOMEONE IS THERE
IFN FTMODM,<
	LDB	T1,LDPDSC	;GET DATASET TABLE INDEX
	MOVE	T1,DSCTAB##(T1)	;GET DATASET DATA
	TLNE	T1,DSCBLI	;WANT TO IGNORE INTERRUPTS?
	JRST	RECIN4		;MAYBE.  GO CHECK DATASET BIT
>
	MOVEI	T1,ST.NRT
	TDNE	T1,STATES##
	JRST	[HRR T1,LDBDCH(U)
		TRNN T1,LDRDSR
		JRST .+1
		HRRZ T1,LDBDDB(U)
		JUMPN T1,RECIN5
		JRST BEATIT]
RECIN5:
IFN FTACCT,<
	HRRZ	T1,LDBDDB(U)	;ADDRESS OF TTY DDB
	SKIPE	T1		;IS THERE ONE?
	AOS	DDBICC(T1)	;YES, COUNT INPUT CHARACTER
>
IFN FTTRACK,<DPB T3,LDPRCS	;SAVE RECEIVED CHARACTER FOR DEBUG>
IFN FTHDPX,<
	MOVE	T1,LDBDCH(U)	;SEE IF ITS HALF DUPLEX
	TRNE	T1,LDRHLF	; ..
	JRST	RECHDX		;YES. SPECIAL HANDLING
>
RECIN1:	HLL	U,LDBDCH(U)	;AND DEVICE BITS IN LH.
	HRRZ	T1,LDBDDB(U)	;TEST FOR PIM, GET DDB ADDRESS
	JUMPE	T1,RECINR	;NO DDB, CANT BE PIM
	MOVE	T1,DEVIOS(T1)	;GET DDB WORD WITH MODE IN IT
	TRNE	T1,PIMMOD	;PIM?
	JRST	REPIM		;YES, GO TO PIM CODE
RECINR:	MOVE	T1,TTFREN##	;ANY SPACE FOR CHARACTERS?
	CAIG	T1,3		; IN THE FREELIST?
	JRST	RCHLT1		;NO. SHUT IT DOWN.
	TLNN	U,LDLIMI	;IN IMAGE INPUT MODE?
	JRST	RECIN2		;NO.
	MOVEI	T1,IMGTIM	;YES. RESET TIMEOUT FIELD TO MAX
	DPB	T1,LDPTIM	; ..
	TRO	T3,400		;MARK IN NINTH BIT.
	JRST	RECINA		;AND GO STORE IN BUFFER. NO BREAK.

RECIN2:	PUSHJ	P,SPCHEK	;SEE IF IT'S SPECIAL. SET T1 UP.
	  JRST RECIN3		;NON-SPECIAL. SEE IF LOWER CASE
	TLNE	T1,CHRIA	;DOES THIS CHAR NEED SPECIAL RCV HANDLING?
	JRST	0(T1)		;YES. GO TO IT.
				;NO. FALL INTO ORDINARY CHAR HANDLER
IFE FTWATCH,<RICT:>
RECINA:	MOVE	T2,LDBTIC(U)	;COUNT CHARACTERS LINE HAS INPUT
	ADD	T2,LDBECC(U)	;PLUS  LEFT TO ECHO
	PUSH	P,T1		;SAVE CHARACTER BITS
	CAILE	T2,^D120	;TIME TO WARN HIM?
	JRST	RWARN		;YES.  GO SEND XOFF.
RWARNX:
	PUSHJ	P,TTPTIC	;UPDATE BYTE POINTER, STORE CHARACTER
IFN	FTMIC,<			;IF MIC
	SKIPE	LDBMIC(U)	;IS HE RUNNING MIC?
	PUSHJ	P,MICECH	;YES - SEE IF <CR> TYPED
>			;END OF IF MIC
	POP	P,T1		;RESTORE CHARACTER BITS
	AOS	LDBECC(U)	;COUNT CHARACTER TO ECHO
	TLNE	T1,CHBRK	;IS THIS A BREAK?
	MOVEM	T2,LDBBKU(U)	;SAVE FOR CONTROL-U CODE
	MOVE	S,FLLBSP	;PREPARE BACKSLASH POINTER
	MOVSI	T2,L2LDEL	;WAS PREVIOUS CHAR A RUBOUT?
	TDNN	T2,LDBBY2(U)	; ..
	JRST	RECIN6		;NO
	MOVEM	S,LDBFLP(U)	;YES. STORE BACKSLASH FILLER PTR
	PUSHJ	P,AOSHP		; AND COUNT POSITION OF BACKSLASHES
RECIN6:	TLNN	T1,CHCNC	;IS THIS CHARACTER A CONTROL C?
	TLO	T2,L2LCCS	;NO. PREPARE TO CLEAR L2LCCS BIT
	ANDCAM	T2,LDBBY2(U)	;CLEAR DELETE AND CONTROL C FLAGS
	MOVSI	T2,LPLPOK	;START LINE IF IDLE
	TDNN	T2,LDBPAG(U)	;OUTPUT STARTING?
	SKIPGE	LDBDCH(U)	;OUTPUT IN PROGRESS?
	SKIPA			;YES
	PUSHJ	P,XMTIN1	;NO. GO START IT UP.
	POPJ	P,0		;YES. DISMISS INTERRUPT.

RECIN3:	LDB	T2,[POINT 7,T3,35]	;GET SEVEN BITS OF CHARACTER
	CAIL	T2,140		;LOWER CASE LETTER?
	TLNN	U,LDLLCT	;YES. WANT TO BE UPPER?
	SKIPA
	TRC	T3,240		;YES. MAKE UPPER, CORRECT PARITY
	LDB	T2,LDPACR	;GET AUTO CRLF BYTE
	JUMPE	T2,RECINA	;IGNORE IF ZERO
	TLNN	U,LDLCOM
	TRNE	T3,137		;SEE IF SPACE
	JRST	RECINA		;NO--FORGET IT
	LDB	T4,PHPOS	;GET POSITION
	SUBI	T4,(T2)		;SEE IF ROOM
	JUMPL	T4,RECINA	;JUMP IF YES
	MOVEI	T3,215		;ELSE CONVERT TO
	JRST	RECIN2		;CR
IFN FTMODM,<
RECIN4:	MOVE	T1,LDBDCH(U)	;GET LINE CHARACTERISTICS
	TRNN	T1,LDRDSD	;IS IT A DATASET LINE?
	JRST	RECIN5		;NO.  PROCESS CHARACTER
	POPJ	P,0		;YES.  DISCARD CHARACTER
>
IFN FTHDPX,<

RECHDX:	JUMPGE	T1,RECIN1	;IF NOT OUTPUTTING, TREAT AS KEYBOARD FLAG
	MOVE	T1,LDBBY2(U)	;OUTPUTTING. CONSIDER ECHO.
	TLNE	T1,L2LHD3	;DURING IGNORE TIME?
	POPJ	P,0		;YES. IGNORE.
	MOVSI	T1,L2LHD2	;FLAG FOR RCV INT
	LDB	T2,LDPECK	;NO. GET CHAR LAST SENT OUT
	CAIE	T2,0(T3)	;IS IT CORRECT?
	TLO	T1,L2LHD5	;NO. PUT ERROR FLAG IN TOO
	IORB	T1,LDBBY2(U)	;SET RCV DONE AND ERROR IF ERROR OCCURRED
IFE FT630H,<
	TLNN	T1,L2LHD1	;HAS XMT FLAG HAPPENED TOO?
	POPJ	P,0		;NO. WAIT FOR IT.
>
RHDERQ:	TLNN	T1,L2LHD5	;ERROR ON RCV INT?
	JRST	XMTIN0		;NO. PROCESS AS XMT DONE
				;YES. FALL INTO ERROR ROUTINE
RHDERR:	MOVSI	T1,L2LHD4	;IS THIS AN ERROR OR THE RESPONSE TO IT?
	TDNN	T1,LDBBY2(U)	; ..
	JRST	RHDER1		;ERROR.
	ANDCAM	T1,LDBBY2(U)	;RESPONSE. CLEAR RESP FLAG
	MOVE	T2,T3		;CONSIDER WITHOUT PARITY
	ANDI	T2,177		; ..
	CAIN	T2,"O"-100	;CONTROL O?
	JRST	RHDER2		;YES.
	CAIE	T2,"C"-100	;CONTROL C?
	JRST	XMTIN0		;NO. RESUME TRANSMIT STREAM
	MOVSI	T1,L2LCCS	;YES. MAKE IT LOOK LIKE TWO OF THEM
	IORM	T1,LDBBY2(U)	; ..
RHDER2:	MOVSI	T1,LDLOIP+LDLIRM	;CLEAR OUTPUT BITS IN LDB
	ANDCAM	T1,LDBDCH(U)	; ..
	JRST	RECIN1		;AND GO PROCESS AS RECEIVE INTERRUPT

RHDER1:	MOVSI	T1,L2LHD3+L2LHD4	;ERROR. FLAG FOR IGNORE RCV INTS
	IORM	T1,LDBBY2(U)	; ..
	MOVE	T1,TICSEC##	;DELAY FOR HALF SECOND
	LSH	T1,-1
	HRLI	T1,ECHO		;COME TO ECHO AFTER DELAY
	CONO	PI,PIOFF##	;PUT REQUEST IN CLOCK QUEUE
	IDPB	T1,CLOCK##	; ..
	IBP	CLOCK##		;TWO WORDS PER ENTRY IN THE CLOCK QUEUE
	CONO	PI,PION##	; ..
	POPJ	P,0		;AND DISMISS INTERRUPT

ECHO:	MOVSI	J,MTTYLN##	;HERE AT CLK LEVEL. CLEAR TTY IGNORE FLAGS
	MOVSI	T1,L2LHD3	;IN ALL TTY LDB'S
ECHOL:	HRRZ	U,LINTAB##(J)	;GET AN LDB ADDRESS
	ANDCAM	T1,LDBBY2(U)	;CLEAR IGNORE BIT
	AOBJN	J,ECHOL		;DO FOR ALL LINES
	POPJ	P,0		;RETURN TO CLOCK LEVEL
>
;HERE ON RECEIVE INTERRUPT OF A CONTROL C CHARACTER

IFN	FTMIC,<			;IF MIC
RICA:	SKIPN	LDBMIC(U)	;IS MIC RUNNING FOR US?
	JRST	RECINA		;NO NORMAL CONTROL CHAR
				;YES - FALL INTO RICC

RICC:	PUSH	P,T1		;SAVE CHARACTER BITS
	SKIPE	T1,LDBMIC(U)	;IS MIC RUNNING FOR US?
	PUSHJ	P,MICRIC	;YES - EXTRA GOODIES
>			;END OF IF MIC
IFE	FTMIC,<			;IF NOT MIC
RICC:	PUSH	P,T1		;SAVE CHARACTER BITS
>			;END OF IF NOT MIC
	PUSH	P,T3		;RIDLN CLOBBERS T3
	PUSHJ	P,RIDLN		;DO THE CONTROL-U FUNCTION
	POP	P,T3		;RECOVER ^C FOR ECHO
	MOVSI	T1,L2LCCS	;SEE IF SECOND CONTROL C
	TDNN	T1,LDBBY2(U)	; ..
	JRST	RICC1		;NO
IFN FTTPAG,<
	MOVSI	T1,LPLSTP	;YES - CLEAR STOP BIT
	ANDCAM	T1,LDBPAG(U)
>
	PUSHJ	P,CNCCHK	;YES. AM I ALLOWED TO BELIEVE THE CONTROL C?
	  JRST RICC1		;SLAVE, OR NOT SECOND. JUST STORE
	PUSHJ	P,TTHALT	;JACCT AND TWO ^C^C
	HRRZ	F,LDBDDB(U)	;GET ATTACHED JOB
	JUMPE	F,RICC3		;MAKE SURE THERE IS ONE
	MOVE	T1,DEVMOD(F)	;THERE IS. IS IT ATTACHED?
	TLNE	T1,TTYATC	;OR JUST USING TTY AS IO DEVICE?
	JRST	RICC3		;ATTACHED. OK TO DO CONTROL C
	MOVEI	S,IODERR	;NOT ATTACHED
	IORB	S,DEVIOS(F)	;GIVE JOB AN ERROR BIT
	PUSHJ	P,TTWAKE	;AND WAKE IT UP
	SETZM	DEVNAM(F)	;MAKE IT INVISIBLE TO DEVSRC
	PUSH	P,U		;SAVE U IN CASE DDB IS KILLED
	PUSHJ	P,PTYDET	;GET LINE FREE OF DDB
	POP	P,U		;RESTORE U
RICC3:	POP	P,T1		;RESTORE STACK LEVEL
	PUSHJ	P,TSETBI	;FORCE ACTION. CLEAR BUFFERS
	PUSHJ	P,TSETBO	;BOTH INPUT AND OUTPUT. COMCON HAS
				; BEEN FLAGGED BY CNCCHK
	MOVE	T2,FILXCP	;POINTER TO CONTROL C ECHO
	JRST	RIFRET		;STORE IT AND RETURN

RICC1:	MOVSI	T1,L2LCCS	;SET "^C LAST IN" BIT
	IORM	T1,LDBBY2(U)	;NOT SECOND. STORE BIT.
	JRST	RICC2		;AND TREAT AS RCV CHARACTER
	$LOW
RICD:	MOVEI	T2,LDRDSR	;DATASET OR REMOTE
	TDNE	T2,LDBDCH(U)	; ..
	JRST	RECINA		;YES--SAY ^D
	HLRZ	T2,CD		;GET INSTRUCTION
	CAIE	T2,(JSR)	;BREAK POINT
	JRST	RECINA		;NO--IGNORE
	MOVEM	17,CDSAV+17	;SAVE 17
	MOVEI	17,CDSAV	;PLACE TO SAVE ACS
	BLT	17,CDSAV+16	;SAVE THEM
				;PLACE BREAKPOINT HERE . . .
CD::	MOVSI	17,CDSAV	;RESTORE ALL ACS
	BLT	17,17		;AND
	POPJ	P,		;RETURN FROM INTERRUPT
CDSAV:	BLOCK	20		;PLACE TO SAVE ACS AT CD BREAKPOINT
	$HIGH
;HERE ON CONTROL H (BACKSPACE) TO DETERMINE HOW TO TREAT
;IN THE VARIOUS CASES LIKE APL ETC.
RIBSP:	PUSHJ	P,SAVE1##	;SAVE P1
	PUSHJ	P,STOPCM
	HLLZ	P1,T1		;SAVE CHARACTER BITS
	LDB	T1,LDPAPL	;GET APL BIT
	JUMPN	T1,RECINA	;JUST STORE IN BUFFER (THIS APL)
IFN FTCAFE&FT2741,<
	MOVEI	T1,LDR2741	;IF 2741...
	TDNE	T1,LDBDCH(U)	;NON APL
	MOVEI	T3,377		;ACT LIKE RUBOUT
>;END OF FTCAFE&FT2741
	JRST	RIDELB
;HERE ON RECEIPT OF A CARRIAGE RETURN (CONTROL M)

RICM:	TLNE	U,LDLXON	;IS XON TRUE?
	JRST	RECINA		;YES. NOTHING SPECIAL. STORE.
	PUSHJ	P,RECINA	;NO. FIRST STORE THE C-R
	MOVEI	T3,12		;THEN GET A L-F (EVEN PARITY)
	JRST	RECIN1		;AND GO PRETEND IT WAS TYPED IN.

;HERE ON RECEIVE INTERRUPT OF A CONTROL O

RICO:	MOVSI	T1,LDLOSU	;COMPLEMENT STATE OF OUTPUT SUPPRESS BIT
	XORM	T1,LDBDCH(U)	;IN LINE DATA BLOCK
	DPB	T1,LDPSVC	;CLEAR ANY SAVED CHARACTER
	PUSHJ	P,TSETBO	;CLEAR OUTPUT BUFFER
	MOVE	T2,FILXOP	;POINTER TO ^O ECHO
	JRST	RIFRET		;STORE AND RETURN

;HERE TO DISCARD INPUT CHARACTER SUCH AS NULL OR "USED" ^O

	RINUL==CPOPJ##		;RETURN FROM RECINT.
;HERE ON RECEIVE INTERRUPT OF A CONTROL Q (XON)

RICQ:	PUSH	P,T1		;SAVE CHARACTER BITS
IFN FT5UUO,<
	MOVSI	T1,L2LTAP	;HAS TTY TAPE COMMAND BEEN TYPED?
	TDNN	T1,LDBBY2(U)	; ..
	JRST	RICC2A		;NO. DONT DO ANYTHING SPECIAL
>
	MOVSI	T1,LDLXON	;TURN ON BIT IN LINE CHAR WD
	IORM	T1,LDBDCH(U)	; ENTER HERE FOR OTHER BITS TOO
IFN FTNET,<			;ONLY REMOTE USES TAPE CHARACTERISTIC
	MOVEI	T1,ISRCHP
	PUSHJ	P,@LDBISR(U)	;TELL REMOTE STATION ABOUT THE ^Q.
>
	POP	P,T1
	JRST	CHKXN1
RICC2A:
IFN FTTPAG,<
	MOVSI	T1,LPLSTP	;CLEAR STOP BIT FOR TTY OUTPUT
	ANDCAM	T1,LDBPAG(U)	;..
	MOVSI	T1,LPLPAG	;HAS "SET TTY PAGE" BEEN ENABLED
	TDNN	T1,LDBPAG(U)	;..
	JRST	RICC2		;NO, DON'T DO ANYTHING SPECIAL WITH ^Q
IFN FTNET,<
	MOVEI	T1,ISRCHP	;TELL REMOTE STATION ABOUT ^Q
	PUSHJ	P,@LDBISR(U)
>
	POP	P,T1		;RESTORE T1
	PJRST	TOPOKE		;AND GO START OUTPUT AGAIN
>				;IFN FTTPAG

RICC2:	POP	P,T1		;RESTORE CHARACTER BITS
	JRST	RECINA		;AND ACCEPT THE CHARACTER
IFN	FTMIC,<		;IF MIC
;HERE ON RECEIVE INTERRUPT OF CONTROL P (PROCEED)

RICP:	SKIPN	T2,LDBMIC(U)	;IS MIC RUNNING FOR US?
	JRST	RECINA		;NO - JUST RETURN
	TLO	T2,LDLCHK!LDL.CP;YES - SET UP ^P FLAG
RICB2:	MOVEM	T2,LDBMIC(U)	;PUT WORD BACK
RICB3:	PUSH	P,T1		;PRESERVE T1
	PUSHJ	P,MICWAK	;WAKE UP MIC
	PJRST	TPOPJ##		;RESTORE T1 AND IGNORE THE CHAR

;HERE ON RECEIVE INTERRUPT OF CONTROL B (BREAK)

RICB:	SKIPN	T2,LDBMIC(U)	;IS MIC RUNNING FOR US?
	JRST	RECINA		;NO TREAT AS ORDINARY CHAR
	TLO	T2,LDLCHK!LDL.CB;YES - SET UP ^B FLAG
	JRST	RICB2		;AND TREAT AS ^P
>			;END OF IF MIC
;HERE ON A CONTROL T
IFN	FTWATCH,<
RICT:	PUSHJ	P,DOCTLT	;PROCESS THE CONTROL-T
	  JRST	RECINA		;WE WANT TO STORE IT
	  JRST	TTFORC		;WE WANT TO DO USESTAT
	JRST	RIBUSY		;LINE ALREADY HAS A COMMAND
DOCTLT:	LDB	T1,LDPRTC	;GET BIT FOR TTY RTCOMPAT
	JUMPN	T1,CPOPJ##	;IF IT IS =1 GIVE NON-SKIP RETURN
	HLL	U,LDBDCH(U)	;GET DEVICE FLAGS
	TLNE	U,LDLSLV	;SLAVE?
	JRST	CPOPJ##		;YES--DO NOT FORCE CONTROL-T
	HRRZ	F,LDBDDB(U)	;GET LINKED DDB ADDRESS
	JUMPE	F,RICT1		;FORCE COMMAND IF ZERO
	MOVE	T1,DEVMOD(F)	;GET DEVICE BITS
	TLNN	T1,TTYATC	;CONTROLING TTY?
	JRST	CPOPJ##		;NO--JUST STORE THE CONTROL-T
RICT1:	MOVEI	T1,TTFCXW	;FORCE USESTAT
	SKIPL	(U)		;COMMAND ALREADY PENDING?
	JRST	CPOPJ1##	;NO--GIVE SINGLE SKIP
	JRST	CPOPJ2##	;YES--GIVE DOUBLE SKIP
>	;END FTWATCH

;HERE ON A CONTROL R

RICR:	LDB	T2,LDPRTC	;GET RTCOMP BIT
	JUMPN	T2,RECINA	;STORE IF 1
	PUSHJ	P,FULLCQ	;PASS TO PROGRAM?
	 JRST	RECINA		;YES--STORE IN BUFFER
	MOVEI	T1,TTFCXT	;FORCE THE .TYPE
	SKIPGE	(U)
	JRST	RIBUSY
	PUSHJ	P,TTFORC	;COMMAND
	MOVE	T2,FLLBSC	;GIVE A FREE
	PJRST	RIFRET		;CRLF


;HERE ON RECEIVE INTERRUPT OF CONTROL S (XOFF)

RICS:	PUSH	P,T1		;SAVE CHARACTER BITS
	MOVSI	T1,LDLXON	;CLEAR THIS BIT
	ANDCAM	T1,LDBDCH(U)	;IN LINE CHARACTERISTICS WORD

IFN FTTPAG,<
	MOVSI	T1,LPLPAG	;HAS "SET TTY PAGE" BEEN ENABLED?
	TDNN	T1,LDBPAG(U)	;...
	JRST	RICC2		;NO, DON'T DO ANYTHING SPECIAL
	MOVSI	T1,LPLSTP	;SET STOP BIT FOR OUTPUT
	IORM	T1,LDBPAG(U)	;NO MORE OUTPUT UNTIL XON IS TYPED
	MOVEI	T1,ISRCHP	;GET DISPATCH OFFSET FOR CHP
	PUSHJ	P,@LDBISR(U)	;TELL REMOTE STATION (AND RSX-20F) ABOUT ^S
	PJRST	TPOPJ##		;DO NOT ECHO CHARACTER OR PUT IT IN INPUT STREAM
>				;IFN FTTPAG

IFE FTTPAG,<
	JRST	RICC2
>
BEATIT:	SKIPA	T2,[POINT 9,GAWTXT-1,26]
RIBUSY:	MOVE	T2,[POINT 9,BSYTXT]
	JRST	RIFRET

BSYTXT:	BYTE	(9)134,102,125,123,131,FLLFLG
GAWTXT:	BYTE	(9)123,324,101,116,104,240,101,314,317,116,305,FLLFLG
;PACKED IMAGE MODE (PIM) RECEIVE CHARACTER PROCESSING

REPIM:
IFN FTTPAG,<
	MOVSI	T2,LPLPAG
	TDNN	T2,LDBPAG(U)	;HAS SET TTY PAGE BEEN DONE?
	JRST	REPIM3		;NO, DONT LOOK FOR XON/XOFF
	CAIE	T3,221		;THIS CHARACTER AN XON?
	CAIN	T3,21		;IN EITHER PARITY?
	JRST	RICQ		;YES, TREAT AS NON PIM XON
	CAIE	T3,223		;OR IS IT AN XOFF
	CAIN	T3,23		;
	JRST	RICS		;TREAT AS NON PIM XOFF IF SO
>;END OF FTTPAG
REPIM3:	MOVE	T2,LDBTIC(U)	;# OF CHARS INPUT
	CAMG	T2,RPIMWN	;TIME TO WARN HIM?
	JRST	REPIM2		;NO, NOT YET
	SUBI	T2,^D20		;IS HE OVER 20 CHARS?
	CAMLE	T2,RPIMWN	;OVER CURRENT LIMIT?
	CAMG	T2,RPIMW1	;AND PREVIOUS?
	SKIPA			;NO, OK
	JRST	[MOVE	T1,LDBPAG(U)
		 TLNN	T1,LPLXOF	;SENT XOF YET?
		 JRST	RPIM25		;NO, DO IT NOW
		 JRST	RCHLT1]		;YES, EAT CHAR
RPIM25:	MOVSI	T2,LPLXOF	;YES, SET UP FOR XOFF
	IORM	T2,LDBPAG(U)	;FLAG FOR NEXT SEND
	MOVE	T2,FLPXOF	;SETUP XOF CHAR
	MOVEM	T2,LDBXNP(U)	;INTO LDB
	PUSH	P,T3		;SAVE T3
	PUSHJ	P,TOPOKE	;START OUTPUT IF NECESSARY
	POP	P,T3		;RESTORE T3
REPIM2:
	MOVE	T1,TTFREN##	;FREELIST COUNT
	CAIG	T1,3		;ANY SPACE IN FREELIST?
	JRST	RCHLT2		;NO, SHUT IT DOWN
	TRO	T3,400		;MARK NINTH BIT
	PUSHJ	P,TTPTIC	;UPDATE BYTE POINTER, STORE CHARACTER
	AOS	LDBTIC(U)	;UPDATE LDBTIC COUNT OF CHARS
	MOVEM	T2,LDBECT(U)	;MAKE CHAR LOOK ECHOED
	SKIPN	T2,LDBPBK(U)	;GET AND TEST BREAK CHARACTER WORD
	JRST	RCVWAK		;NOTHING SPECIFIED, BREAK ON ALL
	ANDI	T3,377		;CLEAR NINTH BIT FOR TEST
REPIM1:	LSHC	T1,9		;GET TEST CHARACTER
	XOR	T1,T3		;XOR WITH RECEIVED CHAR
	TRNN	T1,377		;MATCH?
	JRST	RCVWAK		;YES, BREAK CHAR, WAKE AND DISMISS
	JUMPE	T2,CPOPJ##	;DONE, DISMISS INTERRUPT
	JRST	REPIM1		;NO, TRY NEXT

;HERE ON A CONTROL U AT INTERRUPT LEVEL ONLY

RICU:	PUSHJ	P,FULLCQ	;BREAK ON ALL CHARACTERS?
	  JRST RECINA		;YES. STORE THE ^U IN BUFFER
	PUSHJ	P,RIDLN		;NO? DELETE THE CURRENT LINE
	SKIPGE	LDBDCH(U)	;TYPEOUT BUSY?
	JRST	RINUL		;YES. JUST DISCARD THE ^U
	MOVE	T2,FILXUP	;ELSE ECHO IT
	JRST	RIFRET		;GO PRINT FILLER

RIDLN:	PUSHJ	P,STOPCM	;STOP COMCON
	SKIPN	T1,LDBBKU(U)	;ANY BREAK POSITION SAVED?
	PJRST	TSETBI		;NONE THERE. MEANS ONLY THIS LINE IN BFR
RIDLN1:	MOVE	T1,LDBBKU(U)	;GET CONTROL-U POINTER
	CAME	T1,LDBTIP(U)	;ANYTHING TO DELETE ?
	PUSHJ	P,DELCHR	;DELETE 1 CHAR
	  POPJ	P,0		;NOTHING LEFT TO DELETE
	JRST	RIDLN1		;LOOP OVER LINE
DELCHR:	MOVE	T2,LDBTIP(U)	;GET POINTER TO INPUT STREAM
	CAMN	T2,LDBTIT(U)	;BUFFER EMPTY?
	  POPJ	P,0		;YES--NON-SKIP RETURN
	SOSGE	LDBECC(U)	;REDUCE ECHO COUNT AND SEE IF ANY
	JRST	ZAPECC		;NO MORE ECHOES
DELITE:	PUSHJ	P,DBP		;DECREMENT COPY OF LDBTIP
	PUSHJ	P,TTGETC	;SKIP ANY LINK
	  JFCL			;WE WANT TO STORE NEW POINTER
	TRNN	T2,-1		;IF NO PREDECESSOR
	MOVE	T2,LDBTIT(U)	;MOVE PUTTER TO TAKER
	MOVEM	T2,LDBTIP(U)	; IN ALL CASES
	SKIPN	LDBECC(U)	;HAD CHAR BEEN ECHOED
	MOVEM	T2,LDBECT(U)	;TIP HAS BACKED OVER ECT
	JRST	CPOPJ1##	;NO
ZAPECC:	SETZM	LDBECC(U)	;YES--RESTORE ECC
	SOSL	LDBTIC(U)	;AND UPDATE TIC
	JRST	DELITE		;ALL OK.  DELETE ANOTHER
ZAPIN:	CONO	PI,PIOFF##	;OOPS, COUNT WENT NEGATIVE
	SETZM	LDBBKC(U)
	SETZM	LDBTIC(U)
	SETZM	LDBECC(U)	;CLEAN UP INPUT
	MOVE	T2,LDBTIT(U)	; COUNTERS AND
	MOVEM	T2,LDBTIP(U)	; POINTERS,
	MOVEM	T2,LDBECT(U)	; INCLUDING ECHO
	CONO	PI,PION##
	POPJ	P,		;EXIT NO MORE DELETES
RWARN:	CAIGE	T2,^D300	;IF HE IS WAY OVER,
	SKIPG	TTFREN##	; OR WE ARE OUT OF CHUNKS,
	JRST	RECHLT		;  THEN TOSS THE INPUT CHAR.
	MOVE	T1,LDBPAG(U)	;SEE IF WE HAVE SENT AN XOFF,
	TLNE	T1,LPLXOF	;  AND IF WE HAVE, THEN
	JRST	RWARNX		;  DON'T SEND ONE AGAIN
	MOVSI	T1,LPLXOF	;MARK THAT AN XOFF WAS SENT
	IORM	T1,LDBPAG(U)	;THIS GUARANTEES AN XON LATER
IFN FTNET,<
	PUSH	P,T3		;SAVE T3
	MOVEI	T3,1		;CODE TO WARN OF LOW BUFFER
	MOVEI	T1,ISRREM
	PUSHJ	P,@LDBISR(U)	;INFORM THE ISR
	  SKIPA	T2,FLPXOF	;NORMAL RETURN, BUT GIVE HIM XOFF
	JRST	RWNX		;DONT SEND THE XOFF (DC72 HAS)
>
IFE FTNET,<
	MOVE	T2,FLPXOF	;NO BUT GIVE HIM XOFF
>
	MOVEM	T2,LDBXNP(U)	;STORE FOR OUTPUT SERVICE
IFN FTNET,<
RWNX:	POP	P,T3			;RESTORE CHAR
>;END IFN FTNET
	JRST	RWARNX		;CONTINUE INPUT ROUTINE

RECHLT:	POP	P,T1		;RESTORE T1 AND PASSDOWN LIST
RCHLT1:	MOVE	T1,FLPBEL	;THIS IS TOO MUCH. TELL HIM
	MOVEM	T1,LDBXNP(U)	;BY A BELL
IFN FTNET,<
	MOVEI	T3,2		;CODE FOR CHAR NOT STORED
	MOVEI	T1,ISRREM
	PUSHJ	P,@LDBISR(U)	;TELL THE ISR CHAR NOT STORED
>
RCHLT2:	PUSHJ	P,TOPOKE	;START TYPING IF NEEDED (USUALLY NOT NEEDED)
	PJRST	ECHBRK		;TRY TO WAKE JOB, THEN
				;DISMISS INTERRUPT, JUNKING CHARACTER

RECVRG:	PUSHJ	P,GETCHK	;GET A FREELIST CHUNK
	MOVEM	T2,LDBTIP(U)	;SET POINTERS TO INPUT LIST
	MOVEM	T2,LDBTIT(U)	; ..
	MOVEM	T2,LDBECT(U)	;AND THE ECHO POINTER
	SETZM	LDBBKU(U)	;BREAK LOCATION
	POPJ	P,0		;RETURN
;HERE ON A RUBOUT AT INTERRUPT LEVEL

RIDEL:	PUSHJ	P,SAVE1##	;SAVE P1
	PUSHJ	P,STOPCM
	HLLZ	P1,T1		;SAVE CHARACTER BITS
RIDELB:	PUSHJ	P,FULLCQ	;BREAK ON ALL CHARS, OR FCS?
	  JRST RECINA		;YES. STORE THE RUBOUT
	TLNE	U,LDLXON	;PAPER TAPE IN EFFECT?
	JRST	RINUL		;YES. DISCARD RUBOUT
	MOVE	T1,LDBTIT(U)	;IS BUFFER EMPTY?
	CAMN	T1,LDBTIP(U)	;IS BUFFER EMPTY?
	JRST	RIDEL1		;YES--GIVE CRLF
	MOVE	T1,LDBTIC(U)
	ADD	T1,LDBECC(U)
	JUMPE	T1,RIDEL1
	MOVE	T2,LDBTIP(U)	;GET ADDRESS OF INPUT STREAM
	CAMN	T2,LDBBKU(U)
	JRST	RIDEL1
	PUSHJ	P,TTGETC	;GET BACK INPUT CHARACTER
	  MOVEM T2,LDBTIP(U)	;UPDATED CA
	SOSGE	LDBECC(U)	;REDUCE ECHO COUNT
	JRST	DECTIC		;BACKED UP PAST ECHO
RIDEL5:	PUSHJ	P,DBP		;DECREMENT T2 BY 1 CHAR
	PUSH	P,T3		;SAVE CH OVER GETC
	PUSHJ	P,TTGETC	;DO THIS TO SKIP LINK WORD
	JFCL
	POP	P,T3		;RESTORE REAL CH.
	TRNN	T2,-1		;BACK TO BEGINNING?
	MOVE	T2,LDBTIT(U)	;YES, CLEAR STREM BY SETTING PUTTER BACK TO TAKER
	MOVEM	T2,LDBTIP(U)	;POINTER OK, USE IT
	SKIPL	LDBECC(U)	;WAS IT ECHOED?
	JRST	RIDEL2		;NO, DON'T ECHO DELETION, EITHER
	SETZM	LDBECC(U)	;LEAVE COUNT 0
	MOVEM	T2,LDBECT(U)	;ALSO BACK UP ECHO POINTER
RIDEL6:	TLNN	P1,CHDEL	;RUBOUT?
	SETZ	T3,0		;NO--SPECIAL ECHO
	TLNN	U,LDLNEC	;UNLESS NO ECHO
	DPB	T3,LDPSVC	;SAVE FOR AFTER BACKSLASH
	MOVEI	T2,1		;A PHONY BYTE POINTER TO A NULL
	TLNE	U,LDLNEC	;ECHO OFF?
	JRST	RIDEL3		;YES. DON'T OUTPUT
IFN FTCAFE&FT2741,<
	MOVEI	T3,LDR2741
	TDNE	T3,LDBDCH(U)
	JRST	RIDEL3
>

;CONTINUED ON NEXT PAGE
;HERE TO ECHO THE RUBOUT
	MOVE	T3,LDBDCH(U)	;IF ALREADY
	TDNN	T3,[LDLLCP,,LDRHLF]  ;ECHOED, DON'T BUT DO UPDATE HPOS
	MOVE	T2,[POINT 9,[BYTE (9)210,0]]
	TLNN	P1,CHDEL	;RUBOUT OR BACKSPACE
	JRST	RIDEL4		;BACKSPACE (ECHO AS SELF)
	MOVEI	T1,0
	MOVE	T3,LDBDCH(U)	;DIFFERENT FORMAT IF LOCAL COPY
	TDNN	T3,[LDLLCP,,LDRHLF]
	MOVSI	T1,L2LDEL	;WAS DELETE LAST CHARACTER TOO?
	TDNN	T1,LDBBY2(U)	;IF SO, DON'T OUTPUT ANOTHER BACKSLASH
	JRST	RIDEL0		;NO. GO SET UP A BACKSLASH
	MOVEI	T2,1		;PHONY BYTE POINTER
	JRST	RIDEL3		;GO STORE AND RETURN

DECTIC:	SOSL	LDBTIC(U)	;NO MORE ECHO COUNT - ANY INPUT?
	JRST	RIDEL5		;YES.  BACK THAT UP
	PUSHJ	P,ZAPIN		;NO. WE ARE MESSED UP
	JRST	RIDEL6		;CLEAN UP POINTERS AND COUNT AND CARRY ON


RIDEL0:	IORM	T1,LDBBY2(U)	;STORE THAT THIS IS DELETE
	PUSHJ	P,AOSHP		;COUNT BACKSLASH POSITION
	MOVE	T2,FLLBSP	;GET POINTER TO BACKSLASH
	JRST	RIDEL3		;GO STORE AND RETURN

RIDEL4:	MOVEI	T3,10		;UPDATE HPOS BY
	PUSHJ	P,ADJHP		; MINUS ONE
	PJRST	RIDEL3		;GO STORE AND RETURN

RIDEL1:	SKIPGE	LDBDCH(U)	;IS OUTPUT IN PROGRESS?
	JRST	RINUL		;YES.  DISCARD RUBOUT
	MOVE	T2,FLLBSC	;BACKSLASH CRLF
RIFRET:
	MOVEI	T1,0		;SET TO START OF LINE
	DPB	T1,PHPOS	; ..
	MOVSI	T1,L2LDEL	;INSIDE BACKSLASHES?
	TDNN	T1,LDBBY2(U)	; ..
	IBP	T2		;NO. SKIP BACKSLASH
	ANDCAM	T1,LDBBY2(U)	;NO LONGER IN BACKSLASHES
RIDEL3:	MOVEM	T2,LDBFLP(U)	;STORE FILLER POINTER
	PUSHJ	P,TOPOKE	;START OUTPUT IF NEEDED
RIDEL2:	JRST	RINUL		;NOW DISCARD RUBOUT

;HERE ON ANY OF THE THREE ALTMODES, TO DECIDE ON CONVERSION TO STDALT
RIALT:	PUSHJ	P,RIALTO
	JRST	RECINA
RIALTO:	ANDI	T3,177		;CLEAR PARITY
	CAIE	T3,STDALT	;REAL ALTMODE
	MOVEI	T1,0		;NO, ASSUME JUST AN ORDINARY CLEAR
	MOVSI	T2,LPLALT	;CONVERT OLD ALTMODES?
	TDNE	T2,LDBPAG(U)
	POPJ	P,		;NO
	MOVEI	T3,STDALT	;YES USE THE STANDARD ALTMODE
	MOVE	T1,CHTABL(T3)	;NOW A BREAK, SO GET ITS BITS
	POPJ	P,		;STORE WHATEVER THIS DECIDED ON
IFN FTSCLC,<

;RECEIVE INTERRUPT ROUTINE FOR LINE CONTROL TRANSACTIONS

;ENTER HERE FROM DEVICE-DEPENDENT ROUTINE WITH
;  TRANSACTION CODE IN T3,
;  PHYSICAL LINE # IN U (IDX FOR LINTAB, LDBDCH, ETC)
;    U'S RANGE CHECKED BY INTERRUPT ROUTINE
;  AC'S & PDL SETUP


LNCREC::MOVE	U,LINTAB##(U)
	CAIN	T3,LNTEHC	;DISPATCH ON CHARACTER CODE IN T3
	JRST	LNREHC		;ENABLE HUNG CHECK
	CAIE	T3,LNTDHC
	POPJ	P,		;ILLEGAL CODE--IGNORE

LNRDHC:	MOVEI	T3,LDRSHC	;DISABLE HUNG CHECK
	IORM	T3,LDBDCH(U)	;  TURN ON LDRSHC
	POPJ	P,

LNREHC:	MOVEI	T3,LDRSHC	;TURN OFF LDRSHC
	ANDCAM	T3,LDBDCH(U)
	POPJ	P,

>	;END OF IFN FTSCLC
IFN FTMODM,<			;CODE INCLUDED ONLY IF MODEMS SUPPORTED
;RECEIVE INTERRUPT ROUTINE FOR DATASET TRANSACTIONS

;ENTER HERE FROM DEVICE-DEPENDENT ROUTINE WITH TRANSACTION CODE IN
; T3, DSCTAB INDEX IN U, RANGE ALREADY CHECKED BY INTERRUPT
; ROUTINE, AC'S AND PDL SET UP.


DSCREC::MOVE	T2,DSCTAB##(U)	;GET TABLE ENTRY FIRST
	TLNE	T2,DSCBLI	;IGNORE INTERRUPTS?
	POPJ	P,0		;YES. DO SO.
IFN FTPI,<
	PUSHJ	P,SIGDSC	;SIGNA, DATA SET STATUS CHANGE
>	;END FTPI
	CAIN	T3,DSTRNG	;DISPATCH ON CODES
	JRST	DSRRNG		;RING FROM DATAPHONE
	CAIN	T3,DSTON	;CARRIER ON?
	JRST	DSRON		;YES.
IFN FTDIAL,<
	CAIN	T3,DSTPND	;DIALLER WANT ANOTHER DIGIT
	JRST	DSRPND		;YES
>
DSROFF:	CAIN	T3,DSTOFF	;OFF INTERRUPT?
	TLNN	T2,DSCHWC	;YES. DID I THINK HE WAS ON?
	POPJ	P,0		;NO. FORGET IT.
	TLNN	T2,DSCSWC	;DO I THINK HE SHOULD BE ON?
	JRST	DSROF1		;NO. JUST GO CLEAR HIM OUT.
	MOVEI	T1,5		;YES. TIME OUT IN CASE OF BRIEF FAILURE
	DPB	T1,DSTMPL	;STORE IN TIME BYTE.
	MOVSI	T1,DSCHWC	;CLEAR THE CARRIER BIT
	ANDCAM	T1,DSCTAB##(U)	; ..
	MOVSI	T1,DSCFAI	;AND FLAG POSSIBLE FAILURE CONDITION
	IORM	T1,DSCTAB##(U)	; ..
	POPJ	P,0		;LET CLOCK TIME HIM OUT NOW.
DSROF1:	MOVSI	T1,DSCHWC!DSCSWC!DSCIC2
	ANDCAM	T1,DSCTAB##(U)	;CLEAR ALL THESE BITS IN TABLE
IFN FTDIAL,<
	HRRZ	T1,DSCTAB##(U)	;GET TTY NUMBER FOR THIS MODEM
	CAMN	T1,DSDUNI##	;DIALLER CODE USED BY IT?
	SETZM	TTYDDA##	;YES. CLEAR INTERLOCK TO FREE IT.
>
	MOVEI	T3,DSTOFF	;AND SEND OFF-COMMAND TO DEVICE
DSCCAL::MOVE	T2,DSCTAB(U)	;T2 _ LINE NUMBER
	MOVEI	T1,ISRDSC	;DATASET CONTROL FUNCTION
	MOVE	T2,LINTAB##(T2)	;LDB ADDRESS
	PJRST	@LDBISR(T2)	;DISPATCH TO INTERUPT SERVICE

;SUBROUTINE TO SIGNAL DATA SET STATUS CHANGE
; ENTER T3=TRANSACTION CODE
IFN FTPI,<
SIGDSC::HRRZ	T1,LINTAB##(T2)	;GET LDB ADDRESS
	HRRZ	F,LDBDDB(T1)	;GET ADDRESS OF DDB
	MOVE	T4,J		;SAVE J
	JUMPE	F,SIGDS1	;ALL DONE IF ZERO
	LDB	J,PJOBN##	;GET JOB NUMBER
	JUMPE	J,SIGDS1	;JUMP IF JOB 0 (CAN THAT HAPPEN?)
	SIGNAL	C$DSET
	  EXCTUU <MOVEM T3,IBKISW##(M)>
SIGDS1:	MOVE	J,T4		;RESTORE J
	POPJ	P,		;RETURN
>
;STILL IN FTMODM
DSRON:
IFN FTDIAL,<
	TLNN	T2,DSCDLW	;IN DIALLER WAIT?
	JRST	DSRON1		;NO.
	MOVSI	T1,DSCDLW!DSCEON ;YES. CLEAR FLAGS FOR DIALLER
	ANDCAM	T1,DSCTAB##(U)	;IN TABLE IN CORE
	SETZM	TTYDDA##	;FREE UP DIALLER CODE
	MOVSI	T1,DSCDLC	;SET SUCCESSFUL COMPLETION BIT
	IORB	T1,DSCTAB##(U)	;IN DATASET CONTROL TABLE
	PUSH	P,T2		;SAVE OLD STATUS
	PUSHJ	P,DSCWAK	;WAKE THE JOB, IF ANY STILL THERE.
	POP	P,T2		;RESTORE OLD BITS
>
DSRON1:
IFN FTCAFE,< ;CAFE'S SAY HELLO AFTER AUTOMATIC BAUD DETECT EVEN ON
;		LOCAL LINES. THIS ALLOWS USER TO GET SIGN ON MESSAGE
	HRRZ	T1,DSCTAB##(U)	;GET REAL LINE NUMBER
	HRRZ	T1,LINTAB##(T1)	;GET ADDRESS OF LDB
	MOVE	T1,LDBDCH(T1)	;GET DEVICE BITS
	TRNN	T1,LDRDSD	;IS THIS A REAL DATASET LINE?
	JRST	DSRON2		;NO--LOCAL TTY JUST CAME UP
> ;END FTCAFE
	TLNE	T2,DSCHWC	;HE CAME ON. IS THAT NEWS TO ME?
	POPJ	P,0		;I THOUGHT HE WAS ON. FORGET IT.
	TLNN	T2,DSCSWC	;DO I WANT HIM ON?
	JRST	DSROF1		;NO. GO FORCE HIM OFF.
IFN FTGPO2B,<
	TLNE	T2,DSCFAI+DSCDLW ;A GPO2B MODEM CANNOT BE ALLOWED
	POPJ	P,		;TO RECOVER UNTIL THE TIMEOUT HAS
				;OCCURRED TO FORCE DETACH
				;BECAUSE 2B'S GENERATE SPURIOUS CARRIER
				;FROM DIAL TONE, BUSY, ETC.
>
	MOVSI	T1,DSCTMM+DSCFAI ;YES. CLEAR TIME AND FAILURE BITS
	ANDCAM	T1,DSCTAB##(U)	;IN THE TABLE (STILL IN T2)
	MOVSI	T1,DSCHWC	;MARK THAT HE CAME ON
	IORM	T1,DSCTAB##(U)	;IN TABLE
	TLNE	T2,DSCFAI+DSCDLW ;WAS ALL THIS A BRIEF FAILURE?
	POPJ	P,0		;YES. JUST DISMISS, HE'S BACK.
	MOVSI	T1,DSCBLI+DSCNCR  ;NO. NEW GUY. SET BLIND AND DELAY BITS
	HRRZ	F,LINTAB##(T2)	;LDB
	HRRZ	F,LDBDDB(F)	;DDB
	JUMPE	F,DSRN1A	;GO IF NO DDB
	MOVE	T4,DEVMOD(F)	;CHARACTERS
	TLNN	T4,TTYATC	;IF CONSOLE
	TRNN	T4,ASSCON!ASSPRG  ;AND NOT ASSIGNED
DSRN1A:	TLO	T1,^D60		;SET TIME OUT
	IORM	T1,DSCTAB##(U)	;IN DATASET CONTROL TABLE
DSRON2:	HRRZ	U,LINTAB##(T2)	;GET LDB ADDRESS FOR LINE
	PUSHJ	P,TSETBI	;CLEAR INPUT BUFFER
	MOVSI	T1,L1LOFL
	ANDCAM	T1,LDBOFL(U)
	SKIPGE	DEBUGF##
	POPJ	P,
	HRRZ	F,LDBDDB(U)	;GET DDB
	JUMPN	F,CPOPJ##	;DO NOT RUN INITIA IF THERE IS A
				; JOB ON THE LINE
	MOVEI	T1,TTFCXH	;GET HELLO COMMAND INDEX
	JRST	TTFORC		;FORCE HELLO COMMAND
>	;END CONDITIONAL ON FTMODM
TTFRC1:	AOS	(P)
TTFORC::DPB	T1,LDPCMX	;STORE FORCED COMMAND INDEX
	MOVSI	T1,LDBCMR+LDBCMF	;FORCED COMMAND REQUEST.
	JRST	COMST1		;SET COMMAND COUNT, IF NEEDED

IFN FTMODM,<
DSRRNG:	MOVE	T1,STATES##	;PHONE RINGING. MAY I ANSWER?
	TRNE	T1,ST.NRL		;CHECK THE SCHEDULE COMMAND WORD
	POPJ	P,0		;NOT ALLOWED. IGNORE.
IFN FTCAFE,<
	HRRZ	T1,DSCTAB##(U)	;GET REAL LINE NUMBER
	HRRZ	T1,LINTAB##(T1)	;GET ADR OF LDB
	MOVE	T1,LDBDCH(T1)	;GET DEVICE BITS
	TRNN	T1,LDRDSD	;IS THIS A DATASET LINE?
	  POPJ	P,		;NO
>;END OF IFN FTCAFE
	PUSH	P,U		;SAVE PTR TO DSCTAB
	LDB	U,[POINT 9,DSCTAB##(U),35]
	HRRZ	U,LINTAB##(U)	;GET ;DB PTR
IFN FTLOGIN,<
	HRRZ	F,LDBDDB(U)	;DDB PTR
	JUMPE	F,DSRRN2	;NO JOB, ALL  OK
	MOVE	T1,DEVMOD(F)	;DEVICE BITS
	TLNN	T1,TTYATC	;CONTROLLING TTY?
	JRST	DSRRN2		;NO, SO NO JOB
>	;END OF IFN FTLOGIN
				;IF WE GET HERE, WE HAVE RING ON LINE
				; WITH A JOB, WHICH IS NOT SUPPOSED
				; TO HAPPEN.  TO PREVENT SECURITY
				; PROBLEMS, WE DETATCH THE JOB
	MOVEI	T3,TTFCXD	;FORCE DETATCH COMMAND
	DPB	T3,LDPCMX	; INTO FORCED INDEX
	MOVSI	T3,LDBCMR+LDBCMF ;FORCE BITS
	IORM	T3,(U)		; IN LDB
	AOS	COMCNT##	;WAKE COMMAND SCANNER
	PUSHJ	P,CMDSET	;SETUP BITS
DSRRN2:	POP	P,U		;RESTORE DSCTAB PTR
	MOVEI	T3,0		;CLEAR VARIOUS
	DPB	T3,DSTMPL	; TIMERS
	MOVSI	T1,DSCFAI+DSCTMM	;CLEAR THE MOMENTARY FAILURE BIT
	ANDCAM	T1,DSCTAB##(U)	; ..
	MOVSI	T1,DSCSWC+^D30	;TURN ON ALLOW BIT, AND TIME.
DSRRN1:	IORM	T1,DSCTAB##(U)	;IN DATASET CONTROL TABLE
	MOVEI	T3,DSTON	;SEND A TURN-ON COMMAND TO DEVICE-
	PJRST	DSCCAL		; DEPENDENT ROUTINE, AND DISMISS

IFN FTDIAL,<
DSRPND:	TLNE	T2,DSCEON	;SENT ALL DIGITS?
	POPJ	P,0		;YES. IGNORE REQUEST
	MOVEI	T1,^D60		;ONE MINUTE FROM SENDING DIGIT
	DPB	T1,DSTMPL	;INTO TIME-OUT OF DATASET
	MOVSI	T1,DSCEON	;FLAG END OF NUMBER SENT, IF TRUE.
	ILDB	T3,TTYDDA##	;GET ANOTHER DIGIT
	CAIN	T3,17		;END OF NUMBER CODE?
	JRST	DSRPN1		;YES
	ADDI	T3,DSTPND	;CONVERT TO TRANSACTION CODE FOR XXXINT
	PJRST	DSCCAL		;AND SEND IT OUT
	

DSRPN1:	IORM	T1,DSCTAB##(U)	;SET FLAG IN TABLE
	POPJ	P,0		;DON'T SEND NUMBER
>				;END OF FTDIAL
>				;END OF FTMODM CONDITIONAL

IFE FTMODM,<
DSCREC==:CPOPJ##
>
SUBTTL KA10 CONSOLE TELETYPE SERVICE


IFN FTKA10!FTKI10,<
CTYINT::CONSO	CTY,50		;INTERRUPT FROM CTY?
	JRST	.-1
	JSR	SCNSAV##	;YES. SAVE AC'S, SET UP P
	MOVEI	U,TCONLN##	;PSEUDO LINE NUMBER FOR CTY
	CONSO	TTY,40		;INPUT OR OUTPUT
	JRST	CTYOUT		;OUTPUT.
CTYIN:	DATAI	CTY,T3		;INPUT. GET THE CHARACTER
	JRST	RECINT		;GO PROCESS IT

CTYOUT:	CONO	CTY,200+SCNCHN##	;CLEAR THE OUTPUT BIT
	JRST	XMTINT		;AND GO SERVICE INTERRUPT
>;END IFN FTKA10!FTKI10

REPEAT 0,<;CODE WHEN DTE USED TO BE ON PI CHANNEL 1


CTYINT::AOSE	CTYIFL##	;INTERRUPT FOR CTY?
	JRST	.-1		;NO
	CONO	PI,CLRCTY##	;CLEAR HAND-MADE INTERRUPT
	JSR	SCNSAV##	;YES, SAVE ACS
	MOVEI	U,TCONLN##	;SETUP CTY LINE NUMBER
	SKIPN	DTEMTI##	;INPUT?
	JRST	CTYOUT		;NO, SEE IF OUTPUT
CTYIN:	SETZM	DTEMTI##	;CLEAR INPUT FLAG
	MOVE	T3,DTEF11##	;GET CHARACTER
	PUSHJ	P,RECINT	;PROCESS THE CHAR
	PJRST	@CTYIND##	;AND GO TELL SERVICE INPUT IS DONE

CTYOUT:	SKIPN	DTEMTD##	;OUTPUT DONE INTERRUPT?
	HALT	.		;HAS TO BE
	SETZM	DTEMTD##	;CLEAR FLAG
	JRST	XMTINT		;PROCESS XFER DONE INTERRUPT

>;END REPEAT 0

SUBTTL FILLERS AND SIMULATION ROUTINES

;ROUTINE TO SET UP FILLERS FOR OUTPUT CHARACTERS

SETFLO:	PUSHJ	P,SPCHEK	;GET CHARACTER BITS
	  JFCL				;NON-SPECIAL CHAR RETURN.
	TLZ	T1,CHUAE+CHALT+CHCRE	;THESE ECHO MODES NOT USED ON OUTPUT
	TLO	T1,CHFILO	;FLAG OUTPUT-FILLER REQUEST
	JRST	SETFO1		;REST OF ROUTINE SAME AS ON INPUT

;ROUTINE TO SET FILLER POINTER FOR INPUT CHARACTERS (ECHOING)

SETFLI:	TLNE	U,LDLNEC	;NON-ECHOING?
	JRST	CPOPJ1##	;YES. JUST SKIP RETURN
	MOVE	T1,LDBDCH(U)	;GET LINE CHARACTERISTICS
	TDNE	T1,[XWD LDLLCP,LDRHLF]	;LOCAL COPY?
	TLNN	T1,LDLXON	;AND PAPER TAPE
	SKIPA				;NO.  SKIP
	JRST	CPOPJ1##	;YES.  NO FILLERS, ELSE GARBLE.
	PUSHJ	P,ADJHP		;ADJUST POSITION FOR INPUT CHAR
IFN	FTCAFE,<
IFN	FT2741,<
	MOVE	T1,LDBDCH(U)	;IS THIS A 2741
	TRNE	T1,LDR2741	; ??
	JRST	CPOPJ1##	;YES--FILLERS DONE BY PDP-11
> ;END FT2741
> ;END FTCAFE
	PUSHJ	P,SPCHEK	;SET T1 FOR CHAR DESCRIPTOR
	  JFCL			;IGNORE NON-SPECIAL RETURN
	TLNE	T1,CHALT	;POSSIBLE ALTMODE
	PUSHJ	P,RIALTO	;GO CHECK
SETFO1:
IFN FTTVP,<
	TLNN	T1,CHVPOS	;VERT. POSITIONING?
	JRST	SETFO3		;NO
	TLNE	U,LDLFRM	;YES - NEED TO SIMULATE?
	JRST	SETFO2		;NO
	MOVSI	T2,LPLPAG	;YES - USER WANT TO?(SET TTY PAGE)
	TDNN	T2,LDBPAG(U)
	JRST	SETFO2		;NO
	MOVEI	T3,12		;YES - USE LINEFEEDS
	JRST	SETFI0
SETFO2:	SETZM	T2		;CLEAR L.F. COUNTER SINCE WE
	DPB	T2,LDPPFF	;  HAVE FORM FEED HARDWARE
	JRST	SETFI0
SETFO3:
>				;IFN FTTVP
	LDB	T2,PHPOS	;GET CHARACTER POSITION ON LINE
	TLNE	U,LDLDLR	;USER WANT DOLLAR SUPPRESSED?
	TLZ	T1,CHALT+CHUAE+CHCRE	;YES. DO SO.
	TLNE	T1,CHUAE	;WILL ^X BE ADDED?
	ADDI	T2,2		;YES. ADD 2 TO HPOS
	TLNE	T1,CHALT	;IS IT GETTING A DOLLARSIGN?
	ADDI	T2,1		;YES. COUNT IT.
	PUSH	P,T1		;RUNNING OUT OF AC'S
	LDB	T1,LDPWID	;GET WIDTH OF THIS TTY
	CAMG	T2,T1		;NEED FREE CRLF NOW?
	JRST	SETFI1		;NO.
	MOVE	T2,[LDLNFC,,LDRREM]  ;YES.  DOES USER WANT FREE CRLF?
	TDNE	T2,LDBDCH(U)	;CHECK IN DATA BLOCK
	JRST	SETFI1		;NO. FORGET IT.
	LDB	T2,LDPFLC	;YES. GET POINTER AS F(FILLERS)
	MOVE	T2,FLLCRP(T2)	;GET APPROPRIATE POINTER TO STRING
	MOVEM	T2,LDBFLP(U)	;AND STORE IT IN THE LINE BLOCK
	MOVEI	T2,0		;CLEAR HPOS
	DPB	T2,PHPOS	;IN LDB
	DPB	T2,POHPOS	;AND OLD HPOS IN CASE OF TABS
	MOVSI	T2,LDLLCP	;DON'T ECHO INPUT CHARACTER AFTER FREE CRLF
	POP	P,T1		;IF THIS FREE CRLF IS ON INPUT,
	TLNN	T1,CHFILO	; BUT IF OUTPUT, DON'T EAT A CHARACTER
	TDNN	T2,LDBDCH(U)	;IF LOCAL COPY IS SET
	DPB	T3,LDPSVC	;SAVE CHARACTER FOR LATER
	POPJ	P,		;NON-SKIP RETURN (NEEDED CRLF)
SETFI1:	POP	P,T1		;RESTORE CHARACTER BITS
	TLNN	T1,CHFIL	;THIS CHAR NEED FILLERS?
	JRST	SETFI2		;NO.
SETFI0:	PUSH	P,T3		;SAVE THE CHARACTER
				;*** CHAR MUST BE AT 0(P) FOR SIMULATORS ***
				;*** EVEN THOUGH THIS IS BAD PRACTICE
IFN FT2741&FTCAFE,<
	MOVE	T3,LDBDCH(U)	;GET LINE CHARACTERISTICS
	TRNE	T3,LDR2741	;IS THIS A 2741?
	  JRST	ZFLPOP		;YES - DC76 WILL DO FILLERS
	MOVE	T3,(P)
>;END OF IFN FT2741&FTCAFE
	ANDI	T3,177		;JUST 7 BITS (NO PARITY)
	CAIG	T3,15		;NEED TO CALL ROUTINE FOR IT?
	JRST	@SETFLD-10(T3)	;YES. GO DO IT.
	CAIL	T3,21		;CONTROL Q THRU T?
	JRST	SETFI6		;YES. THEY HAVE SPECIAL HANDLERS TOO
	LDB	T1,LDPFLC	;GET FILLER CODE FOR TERMINAL
	JUMPE	T1,ZFLPOP	;NO. USER WANT FILLER SUPPRESSED?
	SKIPA	T2,FILLP1	;NO. ASSUME ONE FILLER IS ENOUGH
ZFLPOP:	MOVEI	T2,0		;POINTER FOR NO FILLERS
FLLPOP:	MOVEM	T2,LDBFLP(U)	;STORE THE FILLER POINTER
	JRST	CHPJ1		;RESTORE CHARACTER AND SKIP RETURN
				; SKIP IS BECAUSE T3 IS TO BE TYPED

SETFI2:	TLNN	T1,CHUAE+CHALT+CHCRE	;ECHO AS ^X OR $ ?
	JRST	CPOPJ1##	;NO. NOTHING SPECIAL. JUST SEND.
	TLNE	T1,CHALT	;ALTMODE?
	JRST	SETFI3		;YES.
	TLNE	T1,CHCRE	;ECHO AS UPARROW X CRLF?
	JRST	SETFI4		;YES.
	TRC	T3,300		;TURN ON 100 BIT, COMPLEMENT PARITY
	DPB	T3,LDPSVC	;STORE FOR AFTER THE UPARROW
	LDB	T2,PHPOS	;UPDATE HORIZONTAL POSITION
	ADDI	T2,1		;ADD ONE FOR THE ^
	DPB	T2,PHPOS	;STORE BACK IN LDB
	MOVE	T2,FLLUPA	;GET POINTER TO UPARROW CONST
SETFI5:	MOVEM	T2,LDBFLP(U)	;STORE IN LINE BLOCK
	POPJ	P,0		;NON-SKIP RETURN, TO FORCE OUT
				; THE UPARROW.

SETFI3:	PUSHJ	P,AOSHP		;COUNT SPACE FOR DOLLARSIGN
	MOVE	T2,FLLDLR	;GET POINTER TO DOLLARSIGN GRAPHIC
	JRST	SETFI5		;GO STORE AND RETURN

;CAN ONLY GET HERE FOR ^Z OR ^C. OTHERS NOT STORED IN INPUT BUFFER

SETFI4:	ANDI	T3,177		;NO PARITY
	MOVEI	T2,0		;PROTECTION
	DPB	T2,PHPOS	;RESET HORIZONAL POSITION
	CAIN	T3,"C"-100	;CONTROL C?
	MOVE	T2,FILXCP	;YES. ITS POINTER
	CAIN	T3,"Z"-100	;CONTROL Z?
	MOVE	T2,FILXZP	;YES. ITS POINTER
	IBP	T2		;SKIP BACKSLASH
	JRST	SETFI5		;STORE ECHO POINTER AND FORCE IT OUT

SETFI6:	TLNN	U,LDLDLR	;ECHOING GRAPHICS INHIBITED?
	TLNE	T1,CHFILO	;IS THIS FOR INPUT OR OUTPUT OF ^Q-^T?
	JRST	FILL1		;NO GRAPHICS. JUST THROW ON A RUBOUT.
	LDB	T2,PHPOS	;INPUT. PUT GRAPHIC ECHO OUT
	ADDI	T2,2		;ADD TWO TO THE CARRIAGE POSITION
	DPB	T2,PHPOS	;STORE HORIZONTAL POSITION
	MOVE	T2,STFLT2-21(T3) ;GET ECHO POINTER FOR CONTROL Q-T
	SOS	-1(P)		;NON-SKIP RETURN
	JRST	FLLPOP		;STORE FILLER AND RETURN

;SUBROUTINE AOSHP TO COUNT HPOS IN LDB.
;CALL WITH U SET UP, RESPECTS ALL AC'S

AOSHP:	PUSH	P,T1		;SAVE AC T1
	LDB	T1,PHPOS	;GET COLUMN FROM LINE DATA BLOCK
	ADDI	T1,1		;INCREMENT IT
	DPB	T1,PHPOS	;AND STORE IT BACK
	JRST	TPOPJ##		;RESTORE T1 AND RETURN
;DISPATCH TO SET FILLERS FOR SOME CHARACTERS

SETFLD:	EXP	FILLH,FILLI,FILLJ,FILLK,FILLL,FILLM
;POINTERS, CODE AND DATA FOR FILLER CHARACTERS

;HERE FOR A BACKSPACE AND HARDWARE VERTICAL TAB

FILLH:
FILLK2:
IFN FTNET,<
	MOVE	T1,LDBDCH(U)	;GET TTY BITS
	TRNE	T1,LDRREM	;REMOTE STATION TTY?
	JRST	ZFLPOP		;YES, IT DOES ITS OWN FILL.
>
	LDB	T1,LDPFLC	;GET FILLER-DESCRIPTOR CODE FOR LINE
	MOVE	T2,FILLHP(T1)	;GET FILLER BYTE POINTER
	JRST	FLLPOP		;GO STORE AND RETURN.

FLLFLG==:1				;FLAG TO ADD A CRLF AFTER THIS FILLER

FILXCP:	POINT	9,FILXCD	;CONTROL C ECHO
FILXCD:	BYTE	(9) 134,336,303,FLLFLG	;BACKSLASH, ^C CRLF
FILXUP:	POINT	9,FILXUD	;CONTROL U ECHO
FILXUD:	BYTE	(9) 134,336,125,FLLFLG	;BACKSLASH, ^U CRLF
FILXOP:	POINT	9,FILXOD	;CONTROL O ECHO
FILXOD:	BYTE	(9) 134,336,317,FLLFLG	;BACKSLASH, ^O CRLF
FILXZP:	POINT	9,FILXZD	;POINTER TO CONTROL Z ECHO
FILXZD:	BYTE	(9) 134,336,132,FLLFLG	;BACKSLASH, ^Z CRLF

;DISPATCH FOR ^Q TO ^T ECHOES

STFLT2:	POINT	9,FILXQD
	POINT	9,FILXRD
	POINT	9,FILXSD
	POINT	9,FILXTD

FILXQD:	BYTE	(9) 336,321,21,377,0	;^Q
FILXRD:	BYTE	(9) 336,322,22,377,0	;^R
FILXSD:	BYTE	(9) 223,336,123,0	;^S
FILXTD:	BYTE	(9) 24,336,324,0	;^T
FILLKP:					;POINTERS FOR BS AND VT
FILLHP:	0				;NO FILLERS
FILLP2:	POINT	9,FILLRZ,8	;2 FILLERS
	POINT	9,FILLRY,8	;6 FILLERS
	POINT	9,FILLRY,8	;6 FILLERS

FILLLP:					;POINTERS FOR FORMFEED
	0				;NO FILLERS
	POINT	9,FILLRX,26	;12 FILLERS
	POINT	9,FILLER,17	;21 FILLERS
	POINT	9,FILLER,17	;21 FILLERS

FILLJP:					;POINTERS FOR LINEFEED
	0				;NO FILLERS
FILLP1:	POINT	9,FILLRZ,17	;1 FILLER
	POINT	9,FILLRY,8	;6 FILLERS
	POINT	9,FILLRY,8	;6 FILLERS

FLLCRP:	POINT	9,FLLCR0	;TABLE OF POINTERS FOR FREE CRLF'S
	POINT	9,FLLCR1
	POINT	9,FLLCR2
	POINT	9,FLLCR2

FLLCR0:	BYTE	(9) 215,12,0	;DATA FOR FREE CRLF'S
FLLCR1:	BYTE	(9) 215,215,12,377,0
FLLCR2:	BYTE	(9) 215,215,12,377,377,377,377,377,0

FLLUPA:	POINT	9,FLLUP1	;POINTER TO UPARROW
FLLDLR:	POINT	9,FLLUP1,17	;POINTER TO DOLLARSIGN
FLLUP1:	BYTE	(9) 336,0,44,0	;UPARROW AND $, WITH PARITY
FLLBSP:	POINT	9,FLLBS1	;POINTER TO BACKSLASH
FLLBS1:	BYTE	(9) 134,0,134,FLLFLG	;BACKSLASH DATA
FLLBSC:	POINT	9,FLLBS1,17	;POINTER TO BACKSLASH - CRLF

FLLCOP:	0				;FILLERS FOR OUTPUT CR
	POINT	9,FLLCO1,17	;ONE EXTRA CR
	POINT	9,FLLCO1
	POINT	9,FLLCO1
FLLCO1:	BYTE	(9) 215,215,215,0	;EXTRA CARRIAGE RETURNS
;HERE TO GENERATE FILLERS OR SIMULATION FOR HORIZONTAL TAB
;PHPOS IS UPDATED ALREADY, BUT POHPOS HAS THE PREVIOUS POSITION,
;LOW ORDER THREE BITS, SO THE TAB SIMULATION CAN BE DONE FROM IT.

FILLI:
IFN FTNET,<
	MOVE	T1,LDBDCH(U)	;GET TTY BITS
	TRNE	T1,LDRREM	;REMOTE STATION TTY?
	JRST	ZFLPOP		;YES, IT DOES ITS OWN FILL.
>
	LDB	T1,LDPFLC	;GET FILLER COUNT
	TLNN	U,LDLTAB	;USE TAB, OR MAKE IT OUT OF SPACES?
	JRST	FILLI1		;SPACES.
	TRNN	T1,1		;FILL CLASS 0 OR 2?
	JRST	ZFLPOP		;YES, NO FILLERS
	LDB	T1,POHPOS	;GET OLD POSITION ON LINE.
	MOVE	T2,FILLP2	; ASSUME UNDER HALFWAY TO TAB STOP
	TRNE	T1,4		;TRUE?
FILL1:	MOVE	T2,FILLP1	;NO. NEED JUST ONE FILLERS.
	JRST	FLLPOP		;GO STORE FILLER POINTER, SEND
				; TAB, AND RETURN.

;HERE TO MAKE A TAB OUT OF SOME SPACES.

FILLI1:	MOVEI	T3,640		;WILL USE SPACES. DISCARD SAVED
				; TAB ON STACK.
				; IMAGE BIT BECAUSE HPOS NOW RIGHT
	LDB	T1,POHPOS	;GET LOW 3 BITS OF OLD HPOS
	MOVE	T2,FILLIP(T1)	;GET CORRESPONDING POINTER TO SPACES
	JRST	SCCHPJ		;GO STORE, TYPE FILLERS AND SVC
				; AND RETURN.

FILLJ:
IFN FTNET,<
	MOVE	T1,LDBDCH(U)	;GET TTY BITS
	TRNE	T1,LDRREM	;REMOTE STATION TTY?
	JRST	ZFLPOP		;YES, IT DOES ITS OWN FILLS.
>
	LDB	T1,LDPFLC	;NO, GET FILLER DESCRIPTOR FOR LINE
	MOVE	T2,FILLJP(T1)	;GET THE CORRESPONDING FILLERS
	JRST	FLLPOP		;FOR A LINEFEED, AND RETURN.

FILLK:	TLNE	U,LDLFRM	;THIS LINE HAVE FORM MOTION?
	JRST	FILLK2		;YES. USE SAME FILLERS AS BACKSPACE
	LDB	T1,LDPFLC	;NO. MUST SIMULATE WITH LF'S
	MOVE	T2,FLLKSP(T1)	;GET SIMULATION POINTER
FILLK1:	MOVEI	T3,12		;CLOBBER THE VT OR FF ON STACK
SCCHPJ:	DPB	T3,LDPSVC	;SAVE CHARACTER FOR AFTER FILLERS
	MOVEM	T2,LDBFLP(U)	;SET FILLER POINTER
	JRST	CHPOPJ		;AND NON-SKIP RETURN TO CAUSE FILLERS
FILLL:	TLNE	U,LDLFRM	;THIS LINE HAVE FORM MOTION?
	JRST	FILLL1		;YES. GO SET FILLERS.
	LDB	T1,LDPFLC	;NO. GET FILLERS FOR LINEFEEDS
	MOVE	T2,FLLLSP(T1)	;GET POINTER TO LINEFEEDS AND FILLERS
	JRST	FILLK1		;GO TO COMMON CODE

FILLL1:
IFN FTNET,<
	MOVE	T1,LDBDCH(U)	;GET TTY BITS
	TRNE	T1,LDRREM	;REMOTE STATION TTY?
	JRST	ZFLPOP		;YES, IT DOES ITS OWN FILLS.
>
	LDB	T1,LDPFLC	;NO, GET FILLER DESCRIPTOR
	MOVE	T2,FILLLP(T1)	;GET FILLERS FOR FORMFEED
	JRST	FLLPOP		;GO STORE THIS POINTER AND RETURN

FILLM:	MOVE	T2,LDBDCH(U)	;GET TTY BITS
	LDB	T4,LDPFLC	;GET FILL CLASS
IFN FTNET,<
	TRNE	T2,LDRREM	;REMOTE STATION TTY?
	SETZ	T4,		;YES, IT DOES ITS OWN TIMING
>
	TLNE	T1,CHFILO	;NO, IS THIS FOR IN OR OUTPUT?
	JRST	FILLM1		;OUTPUT.
	TLNE	U,LDLXON	;YES. XON IN EFFECT?
	JRST	ZFLPOP		;NO LOCAL, OR XON TRUE. THEREFORE,
	TDNN	T2,[XWD LDLLCP,LDRHLF]	;EITHER TYPE OF LOCAL COPY?
					; NO FREE CRLF, OR IT WILL BE ECHOED
	JRST	FILLM1		;NO LOCAL COPY
	MOVE	T2,FLLCRP(T4)	;NEED A FREE LINEFEED.GET CRLF
	IBP	T2		;AND COUNT IT PAST CR
	JRST	FLLPOP		;AND GO STORE RESULT

FILLM1:	MOVE	T2,FLLCOP(T4)	;GET FILLERS FOR CR OUTPUT
	JRST	FLLPOP		;GO STORE AND RETURN

RETYPE::SKIPN	T1,LDBBKU(U)	;SKIP IF BREAK IN BUFFER
	MOVE	T1,LDBTIT(U)	;ELSE GET START OF BUFFER
	MOVEM	T1,TTCMCA	;STORE POINTER
	HRRZM	U,CMDLIN	;REMEMBER LINE # IN CASE OF CONTROL-U
RETYPL:	PUSHJ	P,CCTYI		;GET A BYTE.
				;YOU MAY THINK WE SHOULD CALL COMTYI, YOU
				; ARE WRONG.
	CAIN	T3,12		;DONE?
	JRST	[SETZM CMDLIN	;YES
		 POPJ P,0]	;RETURN
	PUSHJ	P,USEARO	;TYPE OUT CHAR, IN ARROW MODE
	JRST	RETYPL		;LOOP FOR MORE

STOPCM:	HLLM	U,CMDLIN	;MAKE LH EQUAL
	CAMN	U,CMDLIN	;OUR LINE?
	SETZM	TTCMCA		;YES--STOP COMCON
	POPJ	P,0		;RETURN
;DATA SENT OUT AS FILLERS

FILLER:	BYTE	(9) 377,377,377,377	;BLOCK OF 23 RUBOUTS
	BYTE	(9) 377,377,377,377
FILLRX:	BYTE	(9) 377,377,377,377
	BYTE	(9) 377,377,377,377
FILLRY:	BYTE	(9) 377,377,377,377
FILLRZ:	BYTE	(9) 377,377,377,0	;ZERO TERMINATES THE STRING

KSPACE:	BYTE	(9) 240,240,240,240	;BLOCK OF 7 SPACES.
	BYTE	(9) 240,240,240,0

KLINEF:	BYTE	(9) 12,12,12,12	;BLOCK OF 7 LINEFEEDS
	BYTE	(9) 12,12,12,0

FILLIP:	POINT	9,KSPACE	;POINTERS FOR TAB SIMULATION
	POINT	9,KSPACE,8
	POINT	9,KSPACE,17
	POINT	9,KSPACE,26
	POINT	9,KSPACE,35
	POINT	9,KSPACE+1,8
	POINT	9,KSPACE+1,17
	0

FLSLD0:	BYTE	(9) 12,12,12,12	;LINEFEEDS W/O FILLERS.
FLSKD0:	BYTE	(9) 12,12,12,0	; ..

FLSLD1:	BYTE	(9) 377,377,12,377	;LINEFEEDS WITH 2 FILLERS.
	BYTE	(9) 377,12,377,377
	BYTE	(9) 12,377,377,12
FLSKD1:	BYTE	(9) 377,377,12,377
	BYTE	(9) 377,12,377,377
	BYTE	(9) 12,377,377,0

FLLKSP:	POINT	9,FLSKD0	;POINTERS TO SIMULATE ^K
	POINT	9,FLSKD0
	POINT	9,FLSKD1
	POINT	9,FLSKD1

FLLLSP:	POINT	9,FLSLD0	;POINTERS TO SIMULATE ^L
	POINT	9,FLSLD0
	POINT	9,FLSLD1
	POINT	9,FLSLD1

FLBLXF:	BYTE	(9) 207,223,377,0	;DATA - BELL,XOFF,RUBOUT
FLPBEL:	POINT	9,FLBLXF	;POINTER TO BELL-XOFF-RUBOUT
FLPXOF:	POINT	9,FLBLXF,8	;POINTER TO XOFF AND RUBOUT

FLLXON:	BYTE	(9) 21,377,0	;DATA - XON,RUBOUT
FLPXON:	POINT	9,FLLXON	;POINTER TO XON-RUBOUT
SUBTTL TIMING ROUTINE

;SUBROUTINE CALLED EVERY SECOND AT CLOCK LEVEL.
;CHECKS FOR IRMA. TIMES IMAGE INPUT. RUNS MODEMS.


SCNSEC::MOVEI	J,TCONLN##	;PREPARE TO SEARCH LINE TABLE
	PUSHJ	P,SAVE1##
	SETZM	%SCNAL
SCNSIL:	MOVE	U,LINTAB##(J)	;GET ADR OF LDB
	MOVE	T1,LDBDCH(U)	;GET LINE DESCRIPTION WORD
	TLNE	T1,LDLIMI	;IMAGE INPUT STATE?
	PUSHJ	P,SCSIMG	;YES. GO TIME IT
	MOVE	T1,LDBDCH(U)	;SCSIMG CAN CLOBBER THIS
	JUMPGE	T1,SCNSIN	;OUTPUT IN PROGRESS TRUE?
	AOS	%SCNAL
	TRNE	T1,LDRSHC!LDR2741!LDRREM ;YES - HUNG CHECKING?
	JRST	SCNSIN		;NO
IFN FTHDPX,<
	MOVE	T1,LDBBY2(U)	;GET HALF DUPLEX FLAGS
	TLNE	T1,L2LHD3+L2LHD4	;DURING ECHO FAILURE?
	JRST	SCNSIN		;YES. DONT DO HUNG CHECK
>
	MOVSI	T1,LDLIRM	;SET UP SYNC BIT
	TDNE	T1,LDBDCH(U)	;ON FROM 1 SECOND AGO?
	JRST	[MOVSI  T1,LDLOIP
		 ANDCAM T1,LDBDCH(U) ;CLEAR OUTPUT IN PROGRESS
		 PUSHJ  P,TOPOKE ;FORCE THE LINE TO GO
		 MOVSI	P1,L1LOFL
		 MOVEI	T1,ISROFL
		 PUSHJ	P,@LDBISR(U)
		 IORM	P1,LDBOFL(U)
		 JRST   SCNSIN]	;LOOK AT NEXT LINE
	IORM	T1,LDBDCH(U)	;TURN ON SYNC BIT FOR THIS SECOND
SCNSIN:	MOVE	T1,LDBTIC(U)
	ADD	T1,LDBECC(U)
	SKIPE	T1
	AOS	%SCNAL
	SKIPL	LDBOFL(U)
	JRST	SCNSIS
	MOVSI	P1,L1LOFL
	MOVEI	T1,ISROFL
	PUSHJ	P,@LDBISR(U)
	 SKIPA
	ANDCAM	P1,LDBOFL(U)
SCNSIS:	SOJGE	J,SCNSIL
	AOS	T2,%SCNAL
	CAIGE	T2,20
	MOVEI	T2,20
	MOVE	T1,TTFREN##
	IMULI	T1,^D12
	IDIV	T1,T2
	CAIGE	T1,^D80
	MOVEI	T1,^D80
	EXCH	T1,TIWRNN	;STORE NEW LIMIT AND GET PREVIOUS
	MOVEM	T1,TIWRN1	;STORE PREVIOUS
	SUBI	T1,^D20		;AND PREVIOUS PIM
	MOVEM	T1,RPIMW1	;EASIER TO RECOMPUT
	MOVE	T1,TIWRNN	;GET NEW BACK
	SUBI	T1,^D20		;SET UP PRIMWN
	MOVEM	T1,RPIMWN	;AND SAVE
IFE FTMODM,<
	PJRST	ISRSEC		;CALL EACH ISR
>
				;ELSE FALL THRU INTO DATASET ROUTINE
IFN FTMODM,<

;ROUTINE TO DO ONCE-A-SECOND TIMING OF MODEMS. TIMES OUT INTERVALS
;FROM RING TO CARRIER ON, FROM CARRIER ON TO LEGAL COMMAND,
; AND FROM CARRIER OFF TO HANG UP.


DSCSEC:	SKIPL	J,DSCPTR##	;GET DATASET CONTROL POINTER
	JRST	DSCSC1		;THERE ARE NONE IN THIS CONFIGURATION
	HLLZS	J		;CLEAR RIGHT HALF FOR INDEXING
DSCSLP:	MOVE	T1,DSCTAB##(J)	;GET TABLE ENTRY
	TLNE	T1,DSCBLI	;BLIND STILL ON?
	JRST	DSCSC3		;YES.
	CONO	PI,PIOFF##	;CAN'T ALLOW INTERRUPTS HERE
	LDB	T3,DSTIMP	;GET THE TIME SINCE RING OR CARRIER FAILURE
	SOSL	T3		;COUNT IT DOWN. WAS IT 0?
	DPB	T3,DSTIMP	;NO. STORE NEW VALUE
	JUMPN	T3,DSCSNX	;UNLESS NEWLY 0, GO ON TO NEXT
	MOVSI	T3,DSCFAI+DSCSWC	;CLEAR FAIL AND SOFTWARE BITS
	ANDCAB	T3,DSCTAB##(J)	; IN CORE
	CONO	PI,PION##	;OK FOR INTERRUPTS NOW.
IFN FTDIAL,<
	TLNE	T3,DSCDLW	;IN DIALLER WAIT?
	JRST	DSCSDF		;YES. DIALLER HAS FAILED.
>
	HRRZ	U,LINTAB##(T1)	;GET THE LDB ADDRESS
				; OF THE RELATED TTY LINE
	PUSHJ	P,LDBCLR	;CLEAR OUT LDB STATUS
IFN FTLOGIN,<
	HRRZ	F,LDBDDB(U)	;SEE IF THERE'S A JOB.
	JUMPE	F,DSCSC2	;SKIP THIS IF NO JOB
	MOVE	T1,DEVMOD(F)	;MAY BE A JOB. GET MODE WORD.
	TLNN	T1,TTYATC	;CONTROLLING A JOB.
	JRST	DSCSC2		;NOT A CONTROLLING TTY. NO COMMAND
>
	MOVEI	T3,TTFCXD	;DETACH COMMAND INDEX
	DPB	T3,LDPCMX	;STORE IN FORCED COMMAND INDEX BYTE
	MOVSI	T3,LDBCMR+LDBCMF	;SET FORCED COMMAND BIT
	IORM	T3,0(U)		;FOR COMMAND SCANNER TO SEE
	AOS	COMCNT##	;AND WAKE COMMAND DECODER
	PUSHJ	P,CMDSET
DSCSC2:	MOVEI	T3,DSTOFF	;SOFTWARE CODE TO TURN OFF DATASET
	MOVEI	U,0(J)		;TABLE ADDRESS AS LINE NUMBER
	PUSHJ	P,DSCCAL	;SEND TO APPROPRIATE HARDWARE DEVICE
DSCSNX:	CONO	PI,PION##	;OK TO INTERRUPT NOW.
	AOBJN	J,DSCSLP	;COUNT THROUGH ALL LINES
DSCSC1:	PJRST	ISRSEC		;DO ISR TIMING
;STILL IN FTMODM
DSCSC3:	MOVSI	T3,DSCBLI	;SET FOR BLIND BIT
	TLNE	T1,DSCNCR	;NEW CARRIER BIT STILL ON?
	MOVSI	T3,DSCNCR	;YES. CLEAR IT INSTEAD
	ANDCAM	T3,DSCTAB##(J)	;CLEAR BIT IN TABLE
	JRST	DSCSNX		;AND GO ON TO NEXT MODEM

IFN FTDIAL,<
DSCSDF:	SETZM	TTYDDA##	;CLEAR DIALLER CODE INTERLOCK
	MOVEI	U,0(J)		;COPY TABLE INDEX
	PUSHJ	P,DSROF1	;CLEAR OUT THE HARDWARE FOR THIS LINE.
	MOVSI	T1,DSCDLF	;FLAG THAT DIALLING LOST
	IORB	T1,DSCTAB##(J)	; ..
	PUSHJ	P,DSCWAK	;WAKE THE SLEEPING JOB, IF ANY
	JRST	DSCSNX		;LOOK FURTHER THRU DSCTAB

DSCWAK:	MOVE	T1,LINTAB##(T1)	;GET THE LDB ADDRESS FOR THIS DATASET'S TTY
	HRRZ	F,LDBDDB(T1)	;GET THE DDB, IF ANY
	SKIPE	T1		;ANY?
	LDB	T1,PJOBN##	;YES. GET JOB NUMBER
	JUMPE	T1,CPOPJ##	;ANY?
	PJRST	WAKJOB##	;YES. WAKE IT.
>				;END OF FTDIAL
DSTIMP:	POINT	6,DSCTAB##(J),17	;POINTERS TO TIME BYTE
DSTMPL:	POINT	6,DSCTAB##(U),17	;SAME BUT DIFFERENT AC INDEX
				;MUST AGREE WITH DSCTMM
>				;END OF FTMODM


ISRSEC:	PUSHJ	P,SAVE2##	;SAVE P1 AND P2
	HRREI	P1,TCONLN-1	;START WITH REAL LOCAL LINE
	JUMPLE	P1,CPOPJ##	;DON'T SCAN IF NO TTY'S
	MOVEI	P2,0		;CLEAR P2
ISRSEL:	MOVE	U,LINTAB##(P1)	;U _ POINTER TO LDB
	MOVEI	T1,ISRCHK	;FUNCTION TO CHECK STATUS
	HRRZ	T2,LDBISR(U)	;GET ISR ADDRESS
	CAME	T2,P2		;SAME AS LAST LINE?
	PUSHJ	P,@LDBISR(U)	;NO--CALL ISR
	HRRZ	P2,LDBISR(U)	;REMEMBER ADDRESS
	SOJG	P1,ISRSEL	;LOOK AT ALL THE LINES
	POPJ	P,		;RETURN
;SUBROUTINE TO TIME THE IMAGE MODE INPUT STATE, SET END OF FILE IF
;IT TIMES OUT, AND FORCE CONTROL C UNLESS SLAVED ON SECOND TIME-OUT


SCSIMG:	PUSH	P,J		;SAVE COUNTER. WILL BE CLOBBERED.
	LDB	T3,LDPTIM	;GET THE IMAGE TIME BYTE
	SOSL	T3		;COUNT IT DOWN. TOO LOW?
	DPB	T3,LDPTIM	;NO STORE NEW VALUE.
	JUMPG	T3,IPOPJ##	;IF NO TIMEOUT YET, GO BACK TO LOOP
	HRRZ	F,LDBDDB(U)	;GET LINE'S JOB DATA BLOCK
	JUMPE	F,SCSIM2	;NO JOB? TIME AGAIN
	MOVSI	S,FRCEND	;CAUSE UUO ROUTINE TO FORCE END
	TDNE	S,DEVIOS(F)	;ON YET?
	JRST	SCSIM1		;ON ALREADY. PANIC.
	IORB	S,DEVIOS(F)	;NO. SET IT NOW AND TIME OUT AGAIN
SCSIM2:	MOVEI	T3,IMGTIM	;SET TIME TO NEXT PANIC
	DPB	T3,LDPTIM	;STORE IN TIME BYTE
	PUSHJ	P,RCVWAK	;AND WAKE UP JOB
	JRST	IPOPJ##		;GO RESTORE J AND RETURN

SCSIM1:	MOVSI	S,TTYATC	;GET A BIT
	TDNE	S,DEVMOD(F)	;IS THIS AN I/O DEVICE?
	TLNE	T1,LDLSLV	;IS THIS A SLAVE TTY?
	JRST	SCSIM2		;YES. CAN'T DO CONTROL C
	PUSHJ	P,CNCMOD	;NO. SET TO COMMAND LEVEL
	MOVSI	T1,LDBCMF	;FORCE COMMAND
	DPB	T1,LDPCMX	;CONTROL C INDEX
	IORM	T1,0(U)		;AND FLAG COMMAND DECODER
	PUSHJ	P,COMSET	;WAKE UP COMMAND ROUTINE,
	JRST	IPOPJ##		;RESTORE AC AND RETURN
SUBTTL SUBROUTINES FOR INTERRUPT LEVEL CODE

;SUBROUTINE TO SEND A CHARACTER TO A LINE KNOWN TO BE IDLE
;LDB ADR IN LINE, CHAR IN CH.


TYPE:
IFN	FTMIC,<			;IF MIC
	MOVEI	T1,LDRPTY
	TDNE	T1,LDBDCH(U)
	PJRST	XMTBFZ
	MOVE	T1,LDBMIC(U)	;GET THE MIC WORD
	TLNE	T1,LDL.XX	;WANT OUTPUT SILENCED?
	JRST	XMTIN0		;YES - LOOK AS THOUGH WE HAVE A XMT INTERRUPT
	MOVSI	T1,LDLOIP	;SET OUTPUT IN PROGRESS
>				;IF MIC
IFE	FTMIC,<			;IF NOT MIC
	MOVSI	T1,LDLOIP	;SET OUTPUT IN PROGRESS
>				;END OF IF NOT MIC
	IORM	T1,LDBDCH(U)	; ..
	MOVSI	T1,LDLIRM	;CLEAR IRMA FLAG
	ANDCAM	T1,LDBDCH(U)	;SINCE ACTIVITY HAS NOW OCCURRED
IFN FTACCT,<
	HRRZ	T1,LDBDDB(U)	;DDB ADDRESS
	SKIPE	T1		;IS THERE A DDB?
	AOS	DDBOCC(T1)	;YES, COUNT THE NUMBER OF CHARACTERS OUTPUTED
>
IFN FTHDPX,<
	MOVSI	T1,L2LHDM	;CLEAR HDX FLAGS
	ANDCAM	T1,LDBBY2(U)	; ..
>
	LDB	T1,LDPLNO	;GET THE HARDWARE LINE NUMBER

IFN FTMS,<IFN FTCTY1,<
	CAIN	T1,CT1LIN##	;CTY1?
	PJRST	CT1TYO##	;YES - CODE IN CP1SER
>>

	CAIN	T1,TCONLN##	;IS IT THE CTY?
	JRST	CTYTYO		;YES -- SEND OUT THE DATA
	MOVEI	T1,ISRTYP	;FUNCTION TO XMIT DATA
TYPEX:	PJRST	@LDBISR(U)	;CALL THE INTERUPT SERVICE ROUTINE

IFN FTKL10,<EXTERNAL CTYTYO	;ITS IN TTDINT>

IFN FTKA10!FTKI10,<
CTYTYO:	ANDI	T3,377		;REMOVE JUNK
	DATAO	CTY,T3		;SEND TO CONSOLE TTY
IFN FTHDPX!FTTRACK,<
	DPB	T3,LDPECK	;FOR LIGHTS ONLY (CTY IS FDX)
>
	POPJ	P,0		;AND RETURN
>;END IFN FTKA10!FTKI10


;ROUTINE TO ADJUST HORIZONTAL POSITION COUNT FOR CHARACTER TO
;OUTPUT FROM BUFFER. CALL WITH T3, U SET UP.

ADJHP:	PUSH	P,T3		;SAVE VIRGIN CHARACTER
	TRZ	T3,200		;MASK OFF PARITY BIT
	LDB	T1,PHPOS	;GET CURRENT LINE POSITION
	CAIL	T3,40		;NON-IMAGE CONTROL CHAR?
	JRST	ADJHP1		;NO.
	CAIN	T3,10		;YES. CHECK FOR THOSE WHICH MODIFY HPOS
	SOJGE	T1,ADJHPX	;BACKSPACE. COUNT DOWN, STORE IF .GE. 0
	CAIN	T3,15		;CARRIAGE RETURN?
	JRST	ADJHP2		;YES. CLEAR AND STORE HPOS
	CAIE	T3,11		;HORIZ TAB?
	JRST	ADJHPZ		;NONE OF THESE, OR BS AT START.
	DPB	T1,POHPOS	;SAVE OLD POSITION FOR FILLER
	TRO	T1,7		;ADJUST TO NEXT 8TH COLUMN
	AOJA	T1,ADJHPX	; AND GO STORE IT.
ADJHP2:	MOVEI	T1,0		;CLEAR HPOS TO START OF LINE
ADJHPX:	DPB	T1,PHPOS	;STORE HPOS AS UPDATED
CHPOPJ:
ADJHPZ:	POP	P,T3		;RESTORE REAL CHARACTER
	POPJ	P,0		;RETURN FROM ADJHP

ADJHP1:	CAIGE	T3,177		;PRINTING CHARACTER?
	AOJA	T1,ADJHPX	;YES. COUNT BY ONE, GO STORE HPOS
	JRST	ADJHPZ		;RUBOUT OR IMAGE. DON'T COUNT.
;ROUTINE TO SUPPRESS BLANK LINES
IFN FTTBLK,<

BLKSUP:	LDB	T1,PHPOS	;HAVE WE MOVED OFF LEFT MARGIN?
	HRLI	T1,LPLSLF	;  (LPLSLF BIT IN LH)
	TRZE	T1,-1
	ANDCAM	T1,LDBPAG(U)	;YES - CLEAR BIT TO ALLOW L.F.
	CAILE	T3,14		;LF VT OR FF?
	CAIN	T3,213		;  (VT MAY HAVE PARITY)
	CAIGE	T3,12
	POPJ	P,		;NO
	CAIN	T3,12		;YES-SUPPRESS LF?
	TDNN	T1,LDBPAG(U)
	SKIPA	T3,[12]		;NO-TURN VT OR FF INTO LF
	MOVEI	T3,377		;YES-TURN LF INTO RUBOUT
	IORM	T1,LDBPAG(U)	;SET BIT TO SUPPRESS LF'S
	POPJ	P,
>				;IFN FTTBLK

;ROUTINE TO ADJUST VERTICAL POSITIONING
;RET+1	IF THIS IS END OF PAGE (FF OR LINE COUNT)
;RET+2	OTHERWISE

IFN FTTVP,<
ADJVP:	CAILE	T3,14		;LF VT OR FF?
	CAIN	T3,213		;  (VT MAY HAVE PARITY)
	CAIGE	T3,12
	JRST	CPOPJ1##	;NO - NOTHING TO DO - SKIP RETURN
	CAIN	T3,14		;WHAT IS IT? (ADJUST LINE COUNT)
	JRST	ADJVP4		;FORM FEED
ADJVP3:	LDB	T1,LDPPCT
	CAIE	T3,12
	TRO	T1,VTAB-1	;V.TAB.
	AOJA	T1,ADJVP6	;LINE FEED
ADJVP4:	LDB	T1,LDPPSZ
ADJVP5:	LDB	T2,LDPPCT	;CALC. DISPLACEMENT FROM CURRENT POSITION
	SUB	T2,T1
	MOVNS	T2
	DPB	T2,LDPPFF	;& SAVE FOR POSSIBLE SIMULATION
ADJVP6:	LDB	T2,LDPPSZ	;GET PAGE SIZE
	JUMPE	T2,ADJVPX
	CAIGE	T1,(T2)		;IS COUNT GREATER OR EQUAL?
	JRST	ADJVPX		;NO
	SUB	T1,T2		;YES - RESET COUNT MODULO SIZE
	SOS	(P)		;  & FORCE NON SKIP RETURN
				;  FOR POSSIBLE "STOP DISPLAY"
ADJVPX:	DPB	T1,LDPPCT	;STORE NEW COUNT
	JRST	CPOPJ1##	;& RETURN

>	;IFN FTTVP
;SUBROUTINE TO WAKE UP JOB IF IT IS IN TTY INPUT WAIT. CALL WITH
;LINE SET UP. IT WILL SET DDB AND S AS NEEDED.

RCVWAK:	HRRZ	F,LDBDDB(U)	;GET ADDRESS OF ATTACHED DDB
	JUMPE	F,CPOPJ##	;IF NONE,SKIP THIS CODE
IFN FTACCT,<
	AOS	DDBBCC(F)	;COUNT WAKEUPS
>
IFN FTHIBWAK,<	PUSH	P,T1	;SAVE T1
	LDB	T1,PJOBN##	;GET JOB NUMBER OF TTY OWNER
	MOVSI	S,TTILCE##	;IS JOB ENABLED FOR WAKE UP
	TDNE	S,JBTRTD##(T1)	;DURING A HIBERNATE
	JRST	WAKJB		;YES, GO WAKE JOB
WAKJBR:	POP	P,T1		;RESTORE T1
>

	MOVE	S,DEVIOS(F)	;GET STATUS OF TTY FROM DDB
IFN FTPI,<
	TLZ	S,IO		;MAKE SURE BIT IS RIGHT
>
	TLNE	S,IOW		;JOB IN I/O WAIT FOR TTY?
	TLNE	S,TTYOUW	;YES. FOR INPUT WAIT?
IFN FTPI,<
	JRST	PSIIOD##	;GENERATE PSI SO USER WILL KNOW I/O IS DONE
>
IFE FTPI,<
	POPJ	P,0		;NO--DONT WAKE JOB.
>
TTWAKE::PUSH	P,T1		;SAVE VOLATILE AC'S
	PUSH	P,T2		; ..
	LDB	T1,PJOBN##	;IS JOB # IN DDB ZERO?
	JUMPE	T1,TTWAKX	;EXIT IF ZERO
	MOVE	S,DEVIOS(F)	;MAKE SURE S IS CORRECT
IFN FTPSCD,<
	MOVE	T1,LDBDCH(U)	;LINE CHARACTERISTICS
	JUMPL	S,TTWAKO	;OUTPUT?
TTWAKI:	TRNE	T1,LDRPTY	;INPUT. PTY?
	 AOSA	%PISJB##	;YES
	  AOS	%TISJB##	;NO
	JRST	TTWAKB
TTWAKO:	TRNE	T1,LDRPTY	;OUTPUT. PTY?
	 AOSA	%POSJB##	;YES
	  AOS	%TOSJB##	;NO
TTWAKB:>
	PUSHJ	P,STTIOD##	;CALL STTIOD FOR TTYS, PTYS
	MOVE	S,[XWD IOW,IOACT]	;CLEAR WAIT BITS
	ANDCAB	S,DEVIOS(F)	;IN DDB FOR THIS JOB
TTWAKX:	POP	P,T2		;RESTORE AC'S
	PJRST	TPOPJ##		;RETURN FROM RCVWAK

;ROUTINE TO SEE IF CHARACTER SPECIAL HANDLING SHOULD BE SUPPRESSED

FULLCQ:	PUSHJ	P,COMQ		;IS LINE AT COMMAND LEVEL?
	  TLNN U,LDLBKA+LDLFCS	;NO. DOES USER WANT ALL CHARACTERS?
	AOS	(P)		;NO. COMMAND OR NOT SMART USER
	POPJ	P,0		;SMART USER. NON-SKIP RETURN.

IFN FTHIBWAK,<WAKJB:	PUSH	P,T2		;SAVE AC'S
	PUSH	P,T3
	MOVSI	T2,(JS.HIB)	;IS JOB SLEEPING
	TDNE	T2,JBTST2##(T1)	;OR HIBERNATING?
	PUSHJ	P,WAKJOB##	;HIBERNATING: WAKE THE JOB
	POP	P,T3		;RESTORE THE AC'S
	POP	P,T2
	JRST	WAKJBR		;RETURN TO NORMAL PROGRAM FLOW

;THE FOLLOWING ROUTINE IS CALLED BY THE HIBERNATE UUO TO
;PUT THE TTY INTO CHARACTER MODE.  T1 IS PRESERVED.

HIBTTY::PUSH	P,T1		;SAVE T1
	PUSHJ	P,TTYFND	;FIND THIS JOB'S TTY
	JUMPE	U,HIBRET	;NO TTY FOR THIS JOB
	MOVSI	T1,TTIACE##	;HIBERNATE IN CHARACTER MODE?
	TDNN	T1,JBTRTD##(J)
	JRST	HIBTTL		;NO, IT MUST BE LINE MODE
	PUSHJ	P,TTCCHK	;CHECK IF A CHARACTER IS ALREADY PRESENT
	JRST	HIBRET		;NO LINE
HIBSET:	MOVSI	T1,WAKEB##	;LINE OR CHARACTER PRESENT
	IORM	T1,JBTRTD##(J)	;DON'T HIBERNATE
HIBRET:	PJRST	TPOPJ##		;RESTORE T1 AND RETURN (TO UUOCON)
HIBTTL:	PUSHJ	P,TTLCHK	;CHECK FOR A LINE PRESENT
	JRST	HIBRET		;NO LINE
	JRST	HIBSET		;YES, DON'T GO TO SLEEP
>
;TABLE OF CONTROL CHARACTERS - LH=BITS, RH=DISP ADDR ON RCV INT

;DEFINITION OF BITS IN THIS TABLE
CHBRK==:1	;THIS IS A BREAK CHARACTER
CHUAE==:2	;THIS CHARACTER ECHOES AS ^X
CHFIL==4	;THIS CHARACTER REQUIRES FILLERS AT SOME SPEEDS
CHALT==10	;THIS CHARACTER IS ONE OF THE THREE ALTMODES.
CHRIA==20	;THIS CHARACTER REQUIRES RCV INT LEVEL ACTION
CHCRET==40	;THIS IS A CARRIAGE RETURN (NEEDED FOR SETFLO)
CHCNC==100	;THIS IS CONTROL C
CHDEL==200	;THIS IS DELETE
CHFILO==400	;BIT ADDED FOR OUTPUT FILLER ROUTINE (NOT IN TABLE)
CHCRE==1000	;THIS CHARACTER GETS CRLF AFTER ITS ^ X ECHO
CHVPOS==2000	;VERT. POSITIONING SIMULATED WITH FORM FEEDS
CHEPAR==:400000	;THIS BIT SET IF CHARACTER IS EVEN PARITY,MUST BE
		;  SIGN BIT -- THIS BIT IS EXPRESSLY IGNORED BY THE
		;  SPECIAL CHARACTER CHECK ROUTINE, (SPCHEK) AND IS
		;  USED FOR PEVEN8

CHTABL:	XWD	CHRIA+CHEPAR,RINUL		;^@ NUL 000
IFN FTMIC,<
	XWD	CHRIA+CHUAE,RICA		;^A SOH 001
	XWD	CHRIA+CHUAE,RICB		;^B STX 002
>
IFE FTMIC,<
	XWD	CHUAE,0				;^A SOH 001
	XWD	CHUAE,0				;^B STX 002
>
	XWD	CHUAE+CHBRK+CHRIA+CHCRE+CHCNC+CHEPAR,RICC	;^C ETX 003
	XWD	CHUAE!CHRIA,RICD		;^D EOT 004
	XWD	CHUAE+CHEPAR,0			;^E ENQ 005
	XWD	CHUAE+CHEPAR,0			;^F ACK 006
	XWD	CHBRK,0				;^G BEL 007
	XWD	CHBRK+CHRIA,RIBSP		;^H BS 010
	XWD	CHFIL+CHEPAR,0			;^I HT  011
	XWD	CHFIL+CHBRK+CHEPAR,0		;^J LF  012
	XWD	CHFIL+CHBRK+CHVPOS,0		;^K VT  013
	XWD	CHFIL+CHBRK+CHVPOS+CHEPAR,0	;^L FF  014
	XWD	CHRIA+CHFIL+CHCRET,RICM		;^M CR  015
	XWD	CHUAE,0				;^N SO  016
	XWD	CHUAE+CHRIA+CHCRE+CHEPAR,RICO	;^O SI  017
IFN FTMIC,<
	XWD	CHRIA+CHUAE,RICP		;^P DLE 020
>
IFE FTMIC,<
	XWD	CHUAE,0				;^P DLE 020
>
	XWD	CHUAE+CHFIL+CHRIA+CHEPAR,RICQ	;^Q XON 021
	XWD	CHUAE+CHFIL+CHRIA+CHBRK+CHEPAR,RICR	;^R TAPE 022
	XWD	CHUAE+CHRIA+CHFIL,RICS		;^S XOFF 023
	XWD	CHUAE+CHFIL+CHBRK+CHRIA+CHEPAR,RICT ;^T- NTAPE 024
	XWD	CHUAE+CHRIA+CHCRE+CHBRK,RICU	;^U NAK 025
	XWD	CHUAE,0				;^V SYN 026
	XWD	CHUAE+CHEPAR,0			;^W ETB 027
	XWD	CHUAE+CHEPAR,0			;^X CAN 030
	XWD	CHUAE,0				;^Y EM  031
	XWD	CHUAE+CHBRK+CHCRE,0		;^Z SUB 032
	XWD	CHBRK+CHALT+CHRIA+CHEPAR,RIALT	;^[ ESC 033
	XWD	CHUAE,0				;^\ FS  034
	XWD	CHUAE+CHEPAR,0			;^] GS  035
	XWD	CHUAE+CHEPAR,0			;^^ RS  036
	XWD	CHUAE,0				;^_ US  037

		0		;SPACE	040
	XWD	CHEPAR,0	;!	041
	XWD	CHEPAR,0	;"	042
		0		;#	043
	XWD	CHEPAR,0	;$	044
		0		;%	045
		0		;&	046
	XWD	CHEPAR,0	;'	047
	XWD	CHEPAR,0	;(	050
		0		;)	051
		0		;*	052
	XWD	CHEPAR,0	;+	053
		0		;,	054
	XWD	CHEPAR,0	;-	055
	XWD	CHEPAR,0	;.	056
		0		;/	057
	XWD	CHEPAR,0	;0	060
		0		;1	061
		0		;2	062
	XWD	CHEPAR,0	;3	063
		0		;4	064
	XWD	CHEPAR,0	;5	065
	XWD	CHEPAR,0	;6	066
		0		;7	067
		0		;8	070
	XWD	CHEPAR,0	;9	071
	XWD	CHEPAR,0	;:	072
		0		;;	073
	XWD	CHEPAR,0	;.LT.	074
		0		;=	075
		0		;.GT.	076
	XWD	CHEPAR,0	;?	077

		0		;@	100
	XWD	CHEPAR,0	;A	101
	XWD	CHEPAR,0	;B	102
		0		;C	103
	XWD	CHEPAR,0	;D	104
		0		;E	105
		0		;F	106
	XWD	CHEPAR,0	;G	107
	XWD	CHEPAR,0	;H	110
		0		;I	111
		0		;J	112
	XWD	CHEPAR,0	;K	113
		0		;L	114
	XWD	CHEPAR,0	;M	115
	XWD	CHEPAR,0	;N	116
		0		;O	117
	XWD	CHEPAR,0	;P	120
		0		;Q	121
		0		;R	122
	XWD	CHEPAR,0	;S	123
		0		;T	124
	XWD	CHEPAR,0	;U	125
	XWD	CHEPAR,0	;V	126
		0		;W	127
		0		;X	130
	XWD	CHEPAR,0	;Y	131
	XWD	CHEPAR,0	;Z	132
		0		;[	133
	XWD	CHEPAR,0	;/	134
		0		;]	135
		0		;^	136
	XWD	CHEPAR,0	;_	137

;THESE LETTERS ARE LOWER-CASE
	XWD	CHEPAR,0	;	140
		0		;A	141
		0		;B	142
	XWD	CHEPAR,0	;C	143
		0		;D	144
	XWD	CHEPAR,0	;E	145
	XWD	CHEPAR,0	;F	146
		0		;G	147
		0		;H	150
	XWD	CHEPAR,0	;I	151
	XWD	CHEPAR,0	;J	152
		0		;K	153
	XWD	CHEPAR,0	;L	154
		0		;M	155
		0		;N	156
	XWD	CHEPAR,0	;O	157
		0		;P	160
	XWD	CHEPAR,0	;Q	161
	XWD	CHEPAR,0	;R	162
		0		;S	163
	XWD	CHEPAR,0	;T	164
		0		;U	165
		0		;V	166
	XWD	CHEPAR,0	;W	167
	XWD	CHEPAR,0	;X	170
		0		;Y	171
		0		;Z	172
	XWD	CHEPAR+CHRIA,RECINA	;	173
	XWD	CHRIA,RECINA		;	174

;THE 3 HIGH SPECIALS
	XWD	CHRIA+CHEPAR+CHALT,RIALT		;       175
	XWD	CHRIA+CHEPAR+CHALT,RIALT		;       176
	XWD	CHBRK+CHRIA+CHDEL,RIDEL		;   DEL 177
;ROUTINE TO CHECK FOR A SPECIAL CHARACTER AND SET T1 TO ITS DESCRIPTOR
;ENTER WITH T3 SET UP
;SKIPS IF CHAR IS 0-37 OR 175-177
;IGNORES AND DOES NOT RETURN PARITY BIT (CHEPAR)


CHPJ1:	AOSA	-1(P)		;SKIP RETURN WITH T3 FROM STACK
	MOVEI	T1,0		;NON-SPECIAL T1
	JRST	CHPOPJ		;AND RESTORE T3 AND RETURN


SPCHEK::MOVE	T1,T3		;COPY CHAR
	ANDI	T1,177		;CLEAR PARITY
	TRNE	T3,400
	TDZA	T1,T1
	MOVE	T1,CHTABL(T1)	;GET TABLE ENTRY
	TLZ	T1,CHEPAR	;CLEAR PARITY BIT
	SKIPE	T1		;SPECIAL?
	AOS	(P)		;YES--SKIP
	POPJ	P,		;RETURN


;SUBROUTINE TO GET EVEN PARITY USING CHEPAR BIT OF CHTABL
;CALLED FROM SCNSER,PTPSER AND IN ONCE

;CALLING SEQUENCE:  PUSHJ	P,PEVEN8

;ON ENTRY, T3 CONTAINS A CHARACTER IN BITS 28 TO 35,
; BITS 0 TO 27 ARE IGNORED

;ON EXIT, BIT 28 IS CHANGED IF NECESSARY SUCH THAT THE PARITY
; OF BITS 28 TO 35 IS EVEN, AND BITS
; 0 TO 27 ARE ALL 0

PEVEN8::ANDI	T3,177		;CLEAR TO 7 BITS FOR INDEX
	SKIPL	CHTABL(T3)	;TEST WHETHER TABLE ENTRY INDICATES
				;...CHAR ALREADY EVEN PARITY
	TRO	T3,200		;WAS NOT, PUT IN PARITY BIT
	POPJ	P,

	SUBTTL CHUNK HANDLERS -- READ FROM BUFFER

;SUBROUTINE TO READ A CHARACTER FROM A TELETYPE BUFFER
;CALL WITH T2 CONTAINING A CP (CHARACTER POINTER) IN THE
;TTCLST (TELETYPE CHARACTER LIST).
;T2 MAY HAVE JUST BEEN IBP'ED OR DBP'ED INTO THE LINK WORD,
;SO THIS CASE MUST BE CONSIDERED AND THE LINKS FOLLOWED.
;THE 9-BIT CHARACTER IS RETURNED IN T3.
;SKIP RETURN IS TAKEN UNLESS A LINK HAS BEEN FOLLOWED, IN WHICH
;CASE, T2 IS UPDATED PAST THE LINK TO THE FIRST OR LAST BYTE IN
;THE RELEVANT CHUNK.
;T1 IS LEFT POINTING AT LINK WORD OF NEW CHUNK IF LINK FOLLOWED

TTGETC:	TRNE	T2,3		;POINTING TO A LINK WORD?
	JRST	TTGC1		;NO. GO GET THE BYTE.
	HRRZ	T3,T2		;GET BYTES ADDRESS
	CAML	T3,TTBASE	;IS IT IN RANGE?
	CAMLE	T3,RCCMAX##
	PUSHJ	P,RCCSTP	;NO
	TLNE	T2,770000	;P FIELD 0? IF SO LAST BYTE
	JRST	TTGC2		;FORWARD (T2 WAS IBP'ED)
	MOVEI	T3,0
	HLR	T2,0(T2)	;GET POINTER
	TRNN	T2,-1		;BACKED INTO 0 ?
	JRST	CPOPJ1##	;YES RETURN 0
	SKIPA
TTGC2:	HRR	T2,-4(T2)	;GET POINTER
	TRNN	T2,-4		;MAKE SURE THERE'S AN ADDRESS
	STOPCD	.,STOP,CL0,	;++CHUNK LINKS TO ZERO
	SOS	0(P)		;TAKE NON-SKIP RETURN, NEW T2
	HRRZM	T2,T1		;SAVE LOCATION OF THIS CHUNK IN T1
	AOS	T2		;INCREMENT POINTER PAST LINKS
	TLNN	T2,770000	;WAS POINTER DBP'ED?
	ADDI	T2,2		;YES, POINT AT LAST DATA WORD
TTGC1:	HRRZ	T3,T2		;DO RANGE CHECK HERE TOO
	CAML	T3,TTBASE
	CAMLE 	T3,RCCMAX##
	PUSHJ	P,RCCSTP	;CHUNK OUT OF RANGE!
	LDB	T3,T2		;ALLS WELL, GET CHARACTER
	JRST	CPOPJ1##	;AND RETURN (SKIP IF NOT LINKED)


;SUBROUTINE TO DECREMENT BYTE POINTER BY 1 9-BIT CHARACTER
;CALL WITH T2 CONTAINING POINTER TO BE DBP'ED
;RETURNS WITH T2 UPDATED

DBP:	ADD	T2,[9B5]	;INCREMENT POINTER P FIELD BY 1 CHAR
	SKIPGE	T2		;WRAP?
	SUB	T2,[44B5+1]	;YES,RESET P FIELD AND ADDRESS
	POPJ	P,0		;AND RETURN

TTBASE::0		;ADDRESS OF FIRST CHUNK

TTTPC:	POINT	9,1,8	;DUMMY POINTER AT FIRST BYTE
	SUBTTL CHUNK HANDLERS -- STORE INTO BUFFER
;SUBROUTINE TO PLACE A CHARACTER IN A TELETYPE BUFFER
;CALLING SEQUENCE JUST LIKE TTGETC (ABOVE) EXCEPT ALSO NEEDS THE
; CHARACTER TO PLACE IN BUFFER IN T3(27-35). 9 BITS ARE PLACED.
;IT IS ASSUMED THAT A LIST EXISTS. I.E., T2 NOT ZERO OR IN FIRST CHUNK
; OF THE TTCLST


TTPUTC:	TRNE	T2,3		;POINTING TO A LINK WORD?
	JRST	TTPC1		;NO. GO PLACE BYTE.
	HRRZ	T1,T2		;GET BYTE'S ADDRESS
	CAML	T1,TTBASE	;TOO SMALL?
	CAMLE	T1,RCCMAX##	;TOO LARGE?
	PUSHJ	P,RCCSTP	;OUT OF RANGE
	HRRZ	T1,-4(T2)	;ASSUME NEED FORWARD LINK.
	TLNN	T2,760000	;ERROR IF BACKWARD
	STOPCD	CPOPJ##,DEBUG,BTL,	;++BACKWARD TTY LINK
	JUMPN	T1,TTPC2	;IS THERE ALREADY A FORWARD LINK?
					; (PROBABLY NOT)
TTPC3:	PUSH	P,P1		;NO. NEED TO GET A CHUNK TO LINK. SAVE P1
	PUSH	P,T2		;SAVE AC IN WHICH WE DON'T WANT RESULT
	PUSHJ	P,GETCHK	;USE COMMON ROUTINE EVEN IF SLIGHTLY SLOWER
	POP	P,T2		;RESULT IN T1 & T2
	MOVEI	P1,0		;IN CASE NO PREDECESSOR
	TRNN	T2,-4		;IS THERE A PREDECESSOR?
	TDZA	T2,T2		;NO. CLEAR CA.
	MOVSI	P1,-4(T2)	;NEW REV LINK IS WHERE T2 CAME FROM,
				; AND FWD LINK IS 0 (END)
	MOVEM	P1,0(T1)	;STORE IN NEW CHUNK
IFN FTTRACK,<			;IF WE CARE
	SETZM	1(T1)		;ZERO OUT CHUNK
	SETZM	2(T1)		;SO WE ARE NOT
	SETZM	3(T1)		;CONFUSED IF WE
>				;USE DDT
	SKIPE	T2		;UNLESS NO PREDECESSOR,
	HRRM	T1,-4(T2)	;LET OLD CHAIN CONTAIN NEW CHUNK
	POP	P,P1		;RESTORE THE AC
;CONTINUED ON NEXT PAGE
TTPC2:	ADD	T1,TTTPC	;MAKE INTO BYTE POINTER
	MOVE	T2,T1		;PUT INTO T2
	SOS	0(P)		;DON'T SKIP RETURN (NEW T2 VALUE)
TTPC1:	HRRZ	T1,T2		;GET ADDRESS
	SOS	T1		;...OF CHUNK
	CAML	T1,TTBASE	;DO RANGE CHECK
	CAMLE	T1,RCCMAX##	;TOO BIG?
	PUSHJ	P,RCCSTP	;YES--DIE
	DPB	T3,T2		;STORE THE CHAR IN LIST
	JRST	CPOPJ1##	;SKIP RETURN, UNLESS NEW CHUNK

;SUBROUTINE TO SETUP POINTER TO CHUNKS IF NECESSARY
; ADVANCE THE BYTE POINTER, AND STORE THE
; CHARACTER IN THE INPUT STREAM BY CALLING TTPUTC.  CALL WITH THE
; CHARACTER IN T3, ALWAYS RETURNS CPOPJ
TTPTIC:	SKIPN	LDBTIP(U)	;ANY INPUT PUTTER STRING?
	PUSHJ	P,RECVRG	;NO, GO SET ON UP
	IBP	LDBTIP(U)	;COUNT INPUT PUTTER
	MOVE	T2,LDBTIP(U)	; AND INTO T2
	PUSHJ	P,TTPUTC	;STORE CHARACTER IN LIST
	  MOVEM T2,LDBTIP(U)	;NOW CHUNK. STORE POINTER BACK
	POPJ	P,		;RETURN
;SUBROUTINE WHICH IS THE SAME AS TTPTIC EXCEPT IT PUTS
; THE CHARACTER IN THE OUTPUT STREAM
TTPTOC:	SKIPN	LDBTOP(U)	;OUTPUT STRING EXIST?
	PUSHJ	P,TYOVRG	;NO, MAKE ONE
	IBP	LDBTOP(U)	;COUNT UP OUTPUT CHARACTER ADDRESS
	MOVE	T2,LDBTOP(U)	; AND GET IT IN T2
	PUSHJ	P,TTPUTC	;PLACE CHARACTER IN OUTPUT STREAM
	  MOVEM T2,LDBTOP(U)	;NEW CHUNK, UPDATE POINTER
	POPJ	P,		; AND RETURN
	SUBTTL	CHUNK HANDLERS -- FREE A CHUNK
;ROUTINE TO FREE UP A CHUNK OF THE CHARACTER LIST BY FLAGGING IT AS FREE (SETTING LINK WORD = -1)
;ASSUMES THAT TTGETC HAS JUST BEEN
;CALLED AS A RESULT OF AN IBP OF A POINTER ADDRESS TO A LINK WORD, AND
;THAT T1 IS AS TTGETC LEFT IT IN THAT CASE,
;I.E. AT LINK WORD OF THIS CHUNK

;CLOBBERS T1

;CALLED FROM UUO (INPUT) AND INTERRUPT (XMTBUF) LEVELS

FRECHK:	PUSH	P,T2		;WILL NEED AN AC FOR WORK
	HLRZ	T2,0(T1)	;GET BACKWARD LINK OF CURRENT CHUNK
	HRRZS	0(T1)		;AND THEN CLEAR IT
	SKIPE	T2		;IF BACKLINK=0
	SETOM	(T2)		;NONE TO FREE UP
	AOS	TTFREN##	;COUNT THE FREED CHUNK
	JRST	T2POPJ##
	SUBTTL	CHUNK HANDLERS -- GET A CHUNK FROM POOL

;ROUTINE TO GET A FREE CHUNK FROM THE POOL, AND RETURN
; ITS ADDRESS IN CA. CLOBBERS T1

GETCHK:
	SKIPG	TTFREN##
	STOPCD	.,STOP,FLE,	;++FREE LIST EMPTY

	MOVE	T1,TTFREE##	;POINT TO CHUNK LAST ASSIGNED
	HLRZ	T2,TTCLST##	;GET TOTAL # OF CHUNKS
STEPUP:	ADDI	T1,TTCHKS	;ADVANCE TO LINK WORD OF NEXT CHUNK
	CAML	T1,RCCMAX##	;HAVE WE GONE TOO FAR?
	MOVE	T1,TTBASE	;YES. WRAPAROUND
	SKIPGE	(T1)		;IS THIS CHUNK FREE. NOTE REAL BACK LINK ADDRESS CAN'T BE
	JRST	FOUND		; IN HIGH SEG (BIT0 CAN'T BE=1)
STEPON:	SOJG	T2,STEPUP	;NOT FREE. ADVANCE TO NEXT
	STOPCD	.,STOP,NFC,	;++ NO FREE CHUNKS

FOUND:	CONO	PI,PIOFF##	;LOOKED FREE. TRY TO GET IT
	SKIPGE	(T1)		;STILL FREE?
	JRST	REALLY		;YES
	CONO	PI,PION##	;SNEAKY US. GOT IT AT A HIGHER INTERRUPT LEVEL
	JRST	STEPON		;KEEP LOOKING
REALLY:	SETZM	(T1)		;WE GOT IT. FLAG NO LONGER FREE
	MOVEM	T1,TTFREE##	;REMEMBER WHERE WE FOUND IT
	SOS	TTFREN##	;COUNT ONE LESS FREE
	CONO	PI,PION##	;SAFE NOW
	MOVE	T2,T1		;SOME CALLERS WANT IT IN T2, SOME IN T1

IFN FTTRACK,<
	SETZM	1(T2)
	SETZM	2(T2)
	SETZM	3(T2)
>
	ADD	T2,TTTP1	;MAKE INTO CHAR POINTER
	POPJ	P,0		;RETURN WITH CHUNK IN T2

TTTP1:	POINT	9,0,35		;DUMMY
	SUBTTL	CHUNK HANDLERS -- CLEAR BUFFERS
;ROUTINES TO CLEAR INPUT AND OUTPUT BUFFERS


TSETBI::TRNN	U,-1
	STOPCD	.,STOP,LNS,	;++LINE NOT SETUP
	PUSHJ	P,STOPCM
	MOVSI	T1,LPLIRS
	CONO	PI,PIOFF##
	TDNE	T1,LDBPAG(U)
	JRST	TSETI1
TSETI2:	SETZM	LDBTIC(U)	;CLEAR COUNTS
	SETZM	LDBECC(U)	;OF INPUT CHARACTERS
	MOVE	T1,LDBTIT(U)	;MOVE PUTTERS BACK TO TAKER
	MOVEM	T1,LDBTIP(U)
	MOVEM	T1,LDBECT(U)	;NO ECHOING EITHER
	SETZM	LDBBKU(U)
	SETZM	LDBBKC(U)	; ..
	MOVSI	T1,LDLECS	;CLEAR BIT IN LDB WHICH
	ANDCAM	T1,LDBDCH(U)	; MIGHT CAUSE A LINE TO BE SKIPPED
	PUSHJ	P,CHKXON	;CHECK IF AN XON MUST BE SENT OUT
	PJRST	ONPOPJ##	;TURN PI BACK ON AND EXIT

TSETBO::
IFN FTTPAG,<
	MOVSI	T1,LPLSTP	;CLEAR OUTPUT STOP BIT
	ANDCAM	T1,LDBPAG(U)	;OUTPUT CAN NOW HAPPEN AGAIN
IFN FTNET,<
	MOVEI	T3,3		;CODE FOR CONTROL O PROCESSING
	MOVEI	T1,ISRREM
	PUSHJ	P,@LDBISR(U)	;TELL THE ISR
>
>
	CONO	PI,PIOFF##	;NO PI'S HERE
	MOVSI	T1,LDLORS	;TEST OUTPUT RACE SYNC
	TDNE	T1,LDBDCH(U)	;IN LINE BLOCK
	JRST	TSETO1		;SYNC ON. DON'T CLEAR BUFFER
IFN FTMLOG,<
TSETO2:	SKIPE	LDBLOT(U)
	JRST	MICLGC
	SETZM	LDBTOC(U)	;NO OUTPUT CHARACTERS LEFT
>	;END OF FTMLOG CONDITIONAL

IFE	FTMLOG,<		;IF NOT MIC LOG
TSETO2:	SETZM	LDBTOC(U)	;NO OUTPUT CHARACTERS LEFT
>			;END OF IF NOT MIC LOG
	MOVE	T1,LDBTOT(U)	;PUT PUTTER BACK AT TAKER
	MOVEM	T1,LDBTOP(U)	; ..
	JRST	ONPOPJ##	;AND RETURN.
TSETO1:	MOVEI	T1,L2RORH	;OUTPUT RACE HAPPENED BIT
	IORM	T1,LDBBY2(U)	;INDICATE THIS HAPPENED TO UUO LEVEL
	JRST	ONPOPJ##	;TURN PI ON AND RETURN
RCCSTP:	STOPCD	.,STOP,RCC,	;++RANGE CHECKED CHUNK
TSETI1:	MOVEI	T1,L2RIRH	;INPUT RACE HAPPENED BIT
	IORM	T1,LDBBY2(U)	;INDICATE THIS HAPPENED TO UUO LEVEL
	JRST	ONPOPJ##
SUBTTL UUO LEVEL ROUTINES FOR BUFFERED I/O

;DISPATCH TABLE FOR UUO'S AND INITIALIZATION



	JRST	REGSIZ##	;BUFFER SIZE CAN BE GOTTEN FROM DDB
	JRST	TTYINI##(P2)		;INITIALIZATION (140 RESTART)
	JRST	CPOPJ1##	;HUNG DEVICE (NEVER USED)
SCNDSP::JRST	TTYREL		;RELEASE
	JRST	OUT##		;CLOSE OUTPUT
	JRST	TTYOUT		;TTY OUTPUT UUO
;	JRST TTYIN			;TTY INPUT UUO
;FALL INTO TTYIN
;INPUT UUO PROCESSOR - CALLED FROM UUOCON ON INPUT UUO, DDB SET UP


TTYIN:	PUSHJ	P,SAVE3##	;SAVE P1-P3
	PUSHJ	P,CKATTI	;MAKE SURE ATTACHED. SET S.
	MOVEI	T1,DEPAIO	;IS THIS TTY IN ASYNC INPUT
	TDNN	T1,DEVAIO(F)	; MODE?
	JRST	TTYINA		;NO--FORGE AHEAD
	PUSHJ	P,TTLCHK	;IS THERE A LINE THERE?
	  POPJ	P,0		;NO--RETURN NOW
TTYINA:	TRNN	S,I		;IMAGE MODE?
	JRST	TTYIN0		;NO. SKIP SETUP STUFF
	TRNN	S,IODERR	;EOF DUE TO ^C ON UNATTACHED LINE?
	TLNE	S,FRCEND	;CLOCK ROUTINE WANT IT FINISHED?
	JRST	TTYIN9		;YES. GO DO SO.
	MOVE	T1,DEVMOD(F)	;IS THIS GUY ALLOWED IMAGE MODE INPUT?
	TRNN	T1,ASSCON	;I.E., HE HAS TTY ASSIGNED?
	JRST	TTYINE		;NO. ERROR BIT TO USER.
	MOVSI	T1,LDLIMI	;YES. SET IMAGE INPUT IN LINE DATA
	IORM	T1,LDBDCH(U)	; ..
TTYIN0:	PUSHJ	P,TWAITL	;BECOME ATTACHED, WAIT FOR LINE
				; OR FULL BUFFER CONDITION
	TLNE	S,FRCEND	;DID WE TIME OUT AT CLOCK
	JRST	TTYIN9		;LEVEL WHILE WAITING ?
TTYIN5:	HRRZ	T1,DEVIAD(F)	;PREPARE AND ADDR CHECK THE
	PUSHJ	P,BUFCLR##	; USER'S BUFFER
	  JRST ADRERR##			;OUT OF BOUNDS. STOP JOB.
	MOVE	P1,DEVIAD(F)	;BUFFER SIZE IN WORDS
IFN FTKI10!FTKL10,<
	TLZ	P1,R		;WHY PUSHJ TO DO ONE INSTRUCTION?
>
	EXCTUX	<LDB P2,[POINT 17,@P1,17]>
	SUBI	P2,1		;MINUS LINK
	TRNE	S,PIMMOD	;PACKED IMAGE MODE?
	JRST	TTPIMI		;YES, COMPUTE PIM BYTE POINTER
	TRNN	S,I		;UNLESS IMAGE MODE,
	IMULI	P2,5		; FIVE ITEMS PER WORD.
	HRRZ	U,DDBLDB(F)	;RESTORE LINE, CLOBBERED IN UUOCON
	HRRZ	P1,DEVIAD(F)	;PREPARE BYTE POINTER TO STORE
				; THE CHARACTERS IN HIS BUFFER
	PUSHJ	P,SRLPTR	;SETUP BYTE POINTER FOR ASCIZ OR IMAGE
				; AND RELOCATE IT KA OR KI10 STYLE
				;THESE BYTE POINTERS MUST BE RELOCATABLE BECAUSE USER
				; MAY BE SHUFFLED OR SWAPPED
				;FALL INTO MAIN PART OF ROUTINE
TTYIN1:	PUSHJ	P,TYICC		;GET A CHARACTER
	  JRST TTYIN3		; END OF BUFFER.
	MOVE	P3,T3		;COPY CHARACTER
	ANDI	P3,377		;STRIP IMAGE BIT
	EXCTUU	<IDPB P3,P1>	;AND STORE IN USER AREA
	TRNN	S,PIMMOD	;SKIP IF PIM
	TLNN	T1,CHBRK	;A BREAK?
	SOJG	P2,TTYIN1	;NO. LOOP FOR MORE, IF ROOM.
	MOVSI	S,IOEND		;COUNTED OUT, OR BREAK.
	MOVE	T1,DEVIOS(F)	;GET USER MODE BITS
	TRZ	T3,200		;STRIP OFF PARITY, NOT IMAGE.
	TRNN	T1,DLRSUP	;NON-SPECIAL MODE AND
	CAIE	T3,"Z"-100	;END OF FILE CHARACTER?
	MOVEI	S,0		;NO. NOT EOF.
	IORB	S,DEVIOS(F)	;STORE IN DDB S WORD
TTYIN3:	TRNN	S,PIMMOD	;BYTE COUNT IF PIM
	SKIPA	P2,DEVIAD(F)	;NOT PIM - BUFFER PTR IN P2
	SKIPA	P1,DEVIAD(F)	;PIM - DON'T DESTROY BYTE COUNT
	JRST	TTYINC		;NOT PIM-WORD COUNT
IFN FTKI10!FTKL10,<
	TLZ	P1,R
>
	EXCTUX	<LDB P1,[POINT 17,@P1,17]>  ;GET BUFFER SIZE IN WORDS
	SUBI	P1,1
	IMULI	P1,4		;ORIGINAL BYTE COUNT
	SUB	P1,P2		;MINUS END=BYTES USED
	SKIPA	P2,DEVIAD(F)	;ALREADY HAVE COUNT IN P1
TTYINC:
	SUBI	P1,1(P2)	;COMPUTE WORD COUNT FOR UUOCON
	AOS	P2		; TO PUT IN BUFFER HEADER.
IFN FTKI10!FTKL10,<
	TLZ	P2,R		;RELOCATE IT CORRECTLY FOR PORCESSOR TYPE
>
	EXCTUU	<HRRM P1,@P2>	;STORE WITH DATA IN RING
	PUSHJ	P,ADVBFF##	;ON TO NEXT BUFFER
	  SKIPA			;NO MORE THERE.
	JRST	TTYIN6		;MORE TO GO. USE IF IMAGE.
TTYIN8:	MOVSI	S,IOFST		;SET VIRGIN BUFFER BIT
TTYINX:	IORB	S,DEVIOS(F)	;IN DEV S WORD IN DDB
	HRRZ	U,DDBLDB(F)
	JUMPE	U,CPOPJ##
	PJRST	NOCTRO		;CLEAR CONTROL O. END OF UUO

TTYIN6:	TRNE	S,I		;IMAGE MODE?
	SKIPG	LDBTIC(U)	;AND MORE CHARACTERS TO READ?
	JRST	TTYIN8		;NO. QUIT.
	JRST	TTYIN5		;YES. GO PASS SOME MORE

;HERE IF ATTEMPT TO PUT UNASSIGNED TTY IN IMAGE INPUT STATE

TTYINE:	MOVEI	S,IOIMPM
	JRST	TTYINX		; AND RETURN

TTYIN9:	MOVSI	S,IOEND		;SET END OF FILE BIT IN S
	JRST	TTYINX

;PACKED IMAGE MODE, COMPUTE SPECIALISH BYTE POINTER

TTPIMI:	IMULI	P2,4		;4 PER WORD
	HRRZ	U,DDBLDB(F)	;RESTORE LINE,CLOBBERED IN UUOCON
	HRRZ	P1,DEVIAD(F)	;PREPARE BYTE PTR TO STORE CHARS IN HIS BUFFER
	PUSHJ	P,SLRPIM	;SET UP POINTER, RELOCATE PROPERLY
	JRST	TTYIN1		;AND RETURN TO MAIN PATH.
;OUTPUT UUO CALLS HERE

;CALLED ON OUTPUT OR OUTPUT CLOSE, FROM UUOCON, WITH DDB SET UP.


TTYOUT:	PUSHJ	P,SAVE2##	;SAVE P1-P2
IFN FTRSP,<
	PUSHJ	P,RSPTOR##	;RECORD RESPONSE SATISFIED BY TTY OUTPUT
>
	TRNE	S,IODERR	;^C TYPED?
	JRST	TTOUT3		;YES, RETURN
	PUSHJ	P,CKATOU	;FIRST, MAKE SURE THERE'S A
				; PHYSICAL LINE ATTACHED TO JOB, AT USER LEVEL
	TRNN	S,I		;UNLESS IMAGE MODE,
	PUSHJ	P,CLRIMI	;CLEAR IMAGE INPUT STATE
	MOVSI	S,IOBEG		;IS THIS THE FIRST BUFFER AFTER INIT?
	TDNN	S,DEVIOS(F)	;CHECK DDB
	JRST	TTOUT1		;NO.
	ANDCAM	S,DEVIOS(F)	;YES. CLEAR BEG BIT,
	PUSHJ	P,NOCTRO	; AND CONTROL O
TTOUT0:	SETZM	DEVSTS(F)	;CLEAR OLD PARTIAL BYTE POINTER IF ANY
TTOUT1:	MOVSI	T1,LDLOSU
	TDNE	T1,LDBDCH(U)	;IS CONTROL O ON NOW?
	JRST	TTOUT6		;YES. SKIP THIS WHOLE BUFFER.
IFN FTVM,<
	LDB	P1,BYTCNT	;RESIDUAL BYTE COUNT
	SKIPE	DEVSTS(F)	;DEVSTS NON-ZERO?
	JUMPE	P1,TTOUT6	;YES, ADVANCE BUFFER IF BYTE COUNT = 0
>
	MOVE	S,[IO!IOFST,,IOACT] ;MARK START OF NEW OUTPUT
	IORB	S,DEVIOS(F)	;IN DEVICE DATA BLOCK
	HRRZ	T1,DEVOAD(F)	;CHECK ADDRESSES OF OUTPUT BLOCK
	PUSHJ	P,UADRCK##	;GO CHECK BASE (DONT RETURN IF BAD)
	MOVE	P1,DEVOAD(F)	;GET END OF BUFFER
	ADDI	P1,1
IFN FTKI10!FTKL10,<
	PUSHJ	P,RLCPTR	; ..
>
	EXCTUX	<HRRZ P2,@P1>	; ..
	JUMPE	P2,TTOUT6	;SKIP THIS BUFFER IF EMPTY
	ADD	T1,P2		;ADD ON BUFFER SIZE
	ADDI	T1,1		;ROUND UP (BAD ADDRESS MAY CARRY TO LH)
	PUSHJ	P,UADRCK##	;CHECK THE RESULTS
	TRNE	S,PIMMOD	;PACKED IMAGE MODE?
	JRST	TTPIMO		;YES, GO MAKE PIM BYTE POINTER
	TRNN	S,I		;OK. NOW GET NUMBER OF ITEMS IN BUFFER
	IMULI	P2,5		;FIVE PER WORD UNLESS IMAGE
	HRRZ	P1,DEVOAD(F)	;CREATE BYTE POINTER TO BUFFER
	PUSHJ	P,SRLPTR	;SETUP BYTE POINTER FOR ASCIZ OF IMAGE
				; AND RELOCATE IT KA OR KI10 STYLE
TTOUTA:	SKIPE	DEVSTS(F)	;OUTPUT PENDING?
	JRST	TTOUTB		;USE PARTIAL POINTER
	MOVEM	P1,DEVSTS(F)
;LOOP TO DUMP OUT USER BUFFER
TTOUT2:	PUSHJ	P,CKROOM	;SEE IF WE SHOULD CALL TYO
	  JRST	TTOUT7		;IO WAIT WOULD HAPPEN
	EXCTUX	<ILDB T3,DEVSTS(F)>	;GET A USER'S CHARACTER
	TRNE	S,I!PIMMOD	;SEE IF IMAGE MODE OR PIM
	TROA	T3,400		;YES. SET BIT FOR SUPPRESSING FILLERS
	JUMPE	T3,TTOUT5	;DON'T OUTPUT NULLS
	TRNE	S,IODERR	;^C TYPED?
	JRST	TTOUT3		;YES, EXIT
	PUSHJ	P,TYO		;OUTPUT THIS CHARACTER (WAIT IF NEEDED)
TTOUT5:	SOJG	P2,TTOUT2	;COUNT USER'S ITEMS.
TTOUT6:	PUSHJ	P,ADVBFE##	;ADVANCE HIS BUFFERS
	  JRST	TTOUT3		;JUST SINGLE BUFFER FOR NOW
	MOVEI	T1,DEPAIO	;NON-BLOCKING I/O BIT
	TDNE	T1,DEVAIO(F)	;DOING NON-BLOCKING I/O
	JRST	TTOUT0		;YES, START THE NEXT BUFFER OUT
TTOUT3:	SETZM	DEVSTS(F)
	MOVEI	S,IOACT		;CLEAR ACTIVE BIT.
	ANDCAB	S,DEVIOS(F)	;IN DEVICE DATA BLOCK FOR THE JOB
PTSTRT:	JUMPE	U,CPOPJ##	;SKIP THIS IF NO LDB EXISTS
	MOVEI	T1,LDRPTY	;IS THIS A PTY-DRIVEN LINE?
	TDNE	T1,LDBDCH(U)	; ..
	PUSHJ	P,PTYPE##	;YES. WAKE IT UP.
	POPJ	P,0		;END OF UUO. RETURN TO USER

TTOUT7:	DPB	P2,BYTCNT	;SAVE BYTE COUNT
	MOVEI	T1,JS.NTO	;SET THE MAGIC
	IORM	T1,JBTSTS##(J)	; BIT IN JBTSTS

	MOVEI	S,IOACT		;CLEAR I/O ACTIVE BIT
	ANDCAB	S,DEVIOS(F)	;..
	POPJ	P,0		;RETURN
TTOUTB:	HRRZ	T1,DEVSTS(F)	;GET PARTIAL POINTER ADDRESS
	PUSHJ	P,UADRCK##	;STILL VALID
	PUSH	P,P3		;PROTECT AGAINST REMAINDER
	LDB	T3,[POINT 6,DEVSTS(F),11] ;GET CURRENT S
	LDB	P2,[POINT 6,DEVSTS(F),5] ; AND P VALUES
	IDIV	P2,T3		;BYTES IN CURRENT WORD
	MOVE	P3,P2		;SAVE BYTE COUNT OF CURRENT WORD
	LDB	P2,BYTCNT	;GET TOTAL BYTE COUNT
	SUB	P2,P3		;LESS CURRENT WORD
	MOVEI	T3,5		;5/WORD FOR ASCII
	TRNE	S,PIMMOD	;4/WORD FOR PIM
	MOVEI	T3,4
	SETZM	P3		;SO #REMAINDER" IS ZERO FOR IMAGE
	TRNN	S,I		;ONE/WORD FOR IMAGE
	IDIV	P2,T3		;HOW MANY WORDS?
	SKIPLE	P3		;REMAINDER?
	ADDI	P2,1		;YES
	POP	P,P3		;RECOVER
	ADDI	T1,(P2)		;GET END
	PUSHJ	P,UADRCK##	;VALID?
	LDB	P2,BYTCNT	;GET BYTES BACK
	JRST	TTOUT2

;COMPUTE PACKED IMAGE MODE BYTE POINTER

TTPIMO:	IMULI	P2,4		;4 PER WORD
	HRRZ	P1,DEVOAD(F)	;CREATE BYTE POINTER
	PUSHJ	P,SLRPIM	;AND SET IT UP
	JRST	TTOUTA		;AND RETURN TO MAIN STREAM

SLRPIM:	ADD	P1,[XWD 041000+R,1]	;ASSUME KA POINTER
IFN FTKI10!FTKL10,<
	PJRST RLCPTR		;HANDLES RELOCATION IF NECESSARY
>
IFN FTKA10,<
	POPJ	P,0
>

TTMORE::
IFN FTMS,<
	SKPCPU	(0)
	POPJ	P,0
>
	PUSHJ	P,SAVE2##	;SAVE P1-P2
	MOVEI	F,SCNDDB	;FIRST DDB
	MOVEI	P2,JS.NTO	;FLAG RESET
	MOVE	T1,.C0PC##	;GET THE CURRENT PC
	TLNE	T1,USRMOD	;IN USER MODE?
	MOVEM	T1,JOBPD1##(R)	;YES--MAKE SURE JOBPD1 IS RIGHT
MORE10:	LDB	T1,PJOBN##	;GET OWNER
	CAIN	T1,(J)		;IS IT THIS JOB?
	SKIPN	DEVSTS(F)	;IS OUTPUT WAITING?
	JRST	MORE20		;NO, TRY NEXT DDB
	MOVEI	T1,DEPAIO
	TDNN	T1,DEVAIO(F)	;NON-BLOCKING I/O ON THIS TERMINAL?
	JRST	MORE20		;NO, LOOK AT OTHER TERMINALS
	PUSHJ	P,MORE30	;GO TRY OUTPUT
	MOVEI	P2,0		;FLAG ONE ACTIVE
MORE20:	HLRZ	F,DEVSER(F)	;PICK UP NEXT DDB
	MOVSI	T1,DVTTY	;IS THIS A TTY?
	TDNE	T1,DEVMOD(F)	; ..
	JUMPN	F,MORE10	;YES--LOOK AT IT TOO
	ANDCAM	P2,JBTSTS(J)	;CLEAR THE STATUS
	POPJ	P,0		;RETURN
MORE30:	HRRZ	U,DDBLDB(F)	;GET ADDRESS OF LDB
	JUMPE	U,CPOPJ##	;PUNT IF DETACHED
	MOVE	S,DEVIOS(F)	;SET UP S FOR TYO
	LDB	P1,BYTCNT	;GET THE BYTE COUNT
IFN FTVM,<
	JUMPE	P1,MORE41	;IF BYTE COUNT=0 AND DEVSTS NON-0, BUFFER WASN'T ADVANCED
				; BECAUSE WHAT DEVOAD POINTED TO WAS PAGED OUT
>
MORE40:	PUSHJ	P,CKROOM	;ROOM FOR MORE DATA?
	  JRST	[DPB P1,BYTCNT	;NO--SAVE BYTE COUNT
		 POPJ P,0]	;RETURN
	MOVE	T1,DEVSTS(F)	;GET POINTER
	IBP	T1		;UPDATE POINTER
	TLZ	T1,-1		;CLEAR JUNK
	PUSHJ	P,IADRCK##	;MAKE SURE ITS LEGAL AND IN CORE
	  JRST	MORE50
	EXCTUX	<ILDB T3,DEVSTS(F)>	;GET THE NEXT BYTE
	TRNE	S,I!PIMMOD	;IF IMAGE OR PIM
	TROA	T3,400		;FLAG IT
	SKIPE	T3
	PUSHJ	P,TYO		;TYPE IT
	SOJG	P1,MORE40	;DO THE NEXT BYTE
IFN FTVM,<
MORE41:	HRRZ	T1,DEVOAD(F)	;BUF APR
	SOS	T2,T1		;WORD-1
	ADDI	T2,3		;THRU WORD1
	PUSHJ	P,ZRNGE##	;IN CORE?
	  JRST	MORE50		;NO
>
IFN FTPI,<
	TLO	S,IO		;FORCE FLAG TO OUTPUT
	PUSHJ	P,PSIIOD##
>
	JRST	TTOUT6		;ALL DONE

MORE50:
IFN FTVM,<
	DPB	P1,BYTCNT	;SAVE BYTE COUNT
	MOVE	T3,.C0PC##	;JOB'S PC
	TLNN	T3,USRMOD	;IN USER MODE?
	POPJ	P,		;NO, TRY AGAIN LATER
	MOVE	T3,[EXP IC.UOU+TTYFLT##]
	MOVEM	T3,.C0PC##	;GO TO TTYFLT
	MOVEM	T1,.UPMP+.UPUPF	;STORE FAULT ADDRESS
	POPJ	P,
>
IFE FTVM,<
	HLLZS	DEVOAD(F)	;ZERO IT TO AVOID IME
	JRST	TTOUT3		; AND GIVE UP
>
CKROOM:	MOVEI	T1,DEPAIO	;IF THIS JOB IS NOT USING
	TDNN	T1,DEVAIO(F)	; ASYNCHRONOUS I/O THEN
	JRST	CPOPJ1##	; JUST GIVE THE SKIP RETURN
	SKIPLE	T1,TTFREN##	;GET THE FREE CHUNK COUNT
	CAIG	T1,5		;ENOUGH ROOM?
	POPJ	P,0		;NO--QUIT NOW
	MOVE	T1,LDBTOC(U)	;GET OUTPUT BYTE COUNT
	ADDI	T1,^D25		;REDUCE ODDS OF LOSSAGE
	CAMG	T1,TIWRNN	;TOO MUCH STUFF?
	AOS	(P)		;NO--CALL TYO
	POPJ	P,0		;RETURN
SUBTTL DDT MODE CALLI'S

;INPUT TO DDT	- CALL AC,[SIXBIT /DDTIN/]  WHERE AC/ ADDR
;ADDR GETS UP TO 21 WORDS OF ASCIZ, BREAKING ON ANY CHARACTER


DDTIN::	PUSHJ	P,SAVE2##	;SAVE P1-P2
	PUSHJ	P,TTYFNU	;SET LINE AND DDB FOR THIS TTY
	PUSHJ	P,CKATTI	;MAKE SURE TTY ATTACHED
	PUSHJ	P,GETWDU##	;DO ADDRESS CHECKING FIRST
	HRRZS	T1
	PUSHJ	P,IADRCK##	; ..
	  JRST ADRERR##			;NO GOOD
	ADDI	T1,21		;CHECK END OF AREA
	PUSHJ	P,IADRCK##	; ..
	  JRST ADRERR##			;NO GOOD
	MOVSI	P1,440700+R	;SEVEN BIT BYTES, RELOCATED.
	HRRI	P1,-21(T1)	;IN USER AREA
IFN FTKI10!FTKL10,<
	PUSHJ	P,RLCPTR	;SET FOR KA OR KI10 RELOCATION
>
	MOVEI	P2,<21*5>-1	;NUMBER OF BYTES ALLOWED
	PUSHJ	P,TWAITC	;GET AT LEAST ONE CHARACTER
DDTINL:	SKIPG	LDBTIC(U)	;ANY MORE TO COME?
	JRST	DDTINX		;NO.
	PUSHJ	P,TYICC		;YES. GO GET ONE
	  JRST DDTINX			;WASNT ANY. I'M CONFUSED.
	TRNE	T3,177		;NULL?
	EXCTUU	<IDPB T3,P1>	;NO. STORE IN USER AREA
	SOJG	P2,DDTINL	;IF MORE SPACE, GET ANOTHER CHARACTER
DDTINX:	MOVEI	T3,0		;FLAG END OF STRING
	EXCTUU	<IDPB T3,P1>	; IN USER AREA
	PJRST	NOCTRO		;AND RETURN TO USER, CLEARING ^O FLAG

;DDTOUT - CALL AC,[SIXBIT /DDTOUT/], AC/ ADDR, ADDR/ ASCIZ /XXX/

DDTOUT::HRR	M,T1		;USER ADR. OF TEXT TO M
	PUSHJ	P,TTYFNU	;GET USER'S CONSOLE
	PUSHJ	P,CKATOU	;MAKE SURE AT USER LEVEL AND ATTACHED
	JRST	OUTSTR		;SAME AS THE CORRESPONDING TTCALL
	SUBTTL	TTCALL AND TRMOP. -- TTCALL DISPATCH
;TTCALL AC,E - VALUE OF AC DETERMINES ACTION OF UUO (051)


TTYUUO::PUSHJ	P,SAVE2##	;SAVE P1,P2
	PUSHJ	P,TTYFNU	;FIND CURRENT USER'S TTY
	MOVE	P2,TTUUOT(P1)	;GET PRE-CHECK BITS
	TLNE	P2,TC.ATW	;ATTACH OR WAIT?
	PUSHJ	P,CKATTO	;YES.  WAIT TILL ATTACHED
TTUUA:	TLNN	P2,TC.ATR	;ATTACH OR RETURN?
	JRST	TTUUB		;NO
	TRNN	U,-1		;YES.  LINE NON-ZERO?
	POPJ	P,0		;NO.  RETURN, NO TTY

TTUUB:	JUMPE	U,TTUUD		;ONE UUO-GETLCH-CAN BE HERE DETACHED
	HLL	U,LDBDCH(U)	;GET LINE DESCRIPTION
	TLNN	P2,TC.USR	;USER OR RETURN?
	JRST	TTUUC		;NO
	TLNE	U,LDLCOM	;YES.  USER LEVEL?
	POPJ	P,0		;NO.  RETURN.

TTUUC:	TLNE	P2,TC.USW	;USER OR WAIT?
	TLNN	U,LDLCOM	;YES.  AT USER LEVEL
	JRST	TTUUD		;USER LEVEL, OR NOT NEEDED
	PUSHJ	P,CKATOU	;TOP LEVEL.WAIT FOR USER.
	JRST	TTYUUO		;RESTART UUO IN CASE OF
				;ATTACH.
TTUUD:	TLNN	P2,TC.ADC	;ADDRESS CHECK NEEDED?
	JRST	TTUUE		;NO.  GO DISPATCH.
	HRRZ	T1,M		;ADDRESS TO P1, WHICH IS P1
	PUSHJ	P,UADCK1##	;CHECK THE ADDRESS
TTUUE:	JRST	@TTUUOT(P1)	;DISPATCH TO ROUTINE
;THE FOLLOWING TABLE IS USED TO PRE-CHECK AND DISPATCH THE TTCALL'S.
;BITS IN THE LEFT ARE CHECKED BEFORE DISPATCHING.
;INDIRECT AND INDEX MUST BE ZERO, FOR JRST INDIRECT, BUT THIS COULD
;EASILY BE CHANGED IF THE BITS RUN OUT.


TC.ADC==400000		;THIS FUNCTION MUST BE ADDRESS CHECKED
TC.USR==200000		;THIS FUNCTION MUST BE AT USER LEVEL, ELSE POPJ
TC.USW==100000		;THIS FUNCTION MUST BE AT USER LEVEL, ELSE WAIT
TC.ATW==040000		;THIS FUNCTION MUST BE ATTACHED, ELSE WAIT
TC.ATR==020000		;THIS FUNCTION MUST BE ATTACHED, ELSE POPJ
;DON'T ASSIGN BITS 13-17 WITHOUT CHANGING DISPATCH CODE

TTUUOT:	XWD TC.ATW+TC.USW+TC.ADC,INCHRW	;(00) INPUT CHARACTER, WAIT TILL TYPED
	XWD TC.ATW+TC.USW,ONEOUT	;(01) OUTPUT CHARACTER, WAIT IF NEEDED
	XWD TC.ATR+TC.USR+TC.ADC,INCHRS	;(02) INPUT A CHARACTER AND SKIP
	XWD TC.ATW+TC.USW,OUTSTR	;(03) OUTPUT AN ASCIZ STRING
	XWD TC.ATW+TC.USW+TC.ADC,INCHWL	;(04) INPUT A CHARACTER AND WAIT FOR LINE
	XWD TC.ATR+TC.USR+TC.ADC,INCHSL	;(05) INPUT A CHARACTER AND SKIP, LINE MODE
	XWD TC.ADC,GETLIN		;(06) GET LINE CHARACTERISTICS
	XWD TC.ATW+TC.ADC,SETLIN	;(07) SET LINE CHARACTERISTICS
	XWD TC.ATR,TRESCU		;(10) BACK UP INPUT POINTER TO COMMAND
	XWD TC.ATR,TSETBI		;(11) CLEAR INPUT BUFFER
	XWD TC.ATR,TSETBO		;(12) CLEAR OUTPUT BUFFER
	XWD TC.ATR+TC.USR,SKPINC	;(13) SKIP IF A CHARACTER TO BE INPUT
	XWD TC.ATR+TC.USR,SKPINL	;(14) SKIP IF A LINE TO BE INPUT
	XWD TC.ATW+TC.USW,IONEOU	;(15) IMAGE ONE-CHARACTER OUTPUT
	XWD 0,CPOPJ##		;(16) NOT IMPLEMENTED
	XWD 0,CPOPJ##		;(17) NOT IMPLEMENTED
	SUBTTL	TTCALL AND TRMOP. -- OUTCHR AND IMAGE OUTCHR
;SUBROUTINES FOR TTCALL

;ONEOUT OUTPUTS ONE CHARACTER FROM C(E)


ONEOUT:	PUSHJ	P,SAVE2##	;SAVE P2
	SKIPN	F		;ANY DDB?
	SKIPA	P2,[CCTYO]	;NO--MUST BE SLOPY
	MOVEI	P2,TYO7W	;YES--BE NEET
	IFN FTRSP,<		;RESPONSE DATA?
	PUSHJ	P,RSPTOR##	;RECORD RESPONSE SATISFIED BY TTY OUTPUT
>
ONEOU1:	PUSHJ	P,CLRIMI	;CLEAR IMAGE INPUT STATE
	PUSHJ	P,GETWDU##	;PICK UP USER'S WORD
	MOVE	T3,T1		;PUT IN RIGHT AC
	ANDI	T3,177		;MASK OUT ANY JUNK
	JUMPE	T3,CPOPJ##	;IF NOT NULL,
	PUSHJ	P,(P2)		;TYPE OUT, WITH PARITY, WAIT IF NEEDED
	PJRST	PTSTRT		;START PTY IF THIS IS PTY LINE

;IONEOU OUTPUTS ONE CHARACTER FROM LOW 8 BITS OF C(E)
IONEOU:	IFN FTRSP,<		;RESPONSE DATA?
	PUSHJ	P,RSPTOR##	;RECORD RESPONSE SATISFIED BY TTY OUTPUT
>
	PUSHJ	P,CLRIIQ	;NOT IN INPUT WAIT ANY MORE
	JUMPE	F,ONEOU1	;IF NO DDB, SEND 7 BITS
	PUSHJ	P,GETWDU##	;GET USER'S DATUM
	MOVE	T3,T1		;INTO RIGHT AC
	TRO	T3,400		;FLAG AS IMAGE CHARACTER (NO FILLER)
	PUSHJ	P,TYO9W		;SEND IMAGE CHARACTER (WAIT IF NEEDED)
	PJRST	PTSTRT		;START PTY IF THIS IS PTY LINE
	SUBTTL	TTCALL AND TRMOP. -- OUTSTR AND RESCAN
;OUTSTR OUTPUTS A STRING OF ASCIZ CHARACTERS

OUTSTR:	IFN FTRSP,<		;RESPONSE DATA?
	PUSHJ	P,RSPTOR##	;RECORD RESPONSE SATISFIED BY TTY OUTPUT
>
	PUSHJ	P,SAVE4##	;SAVE P1
	MOVEI	P3,TYO7W
OUTST3:	PUSHJ	P,CLRIMI	;CLEAR IMAGE INPUT STATE
IFN FTVM,<
	LDB	T1,[POINT 9,M,26] ;PAGE #
	PUSHJ	P,TPSHS##	;IS PAGE SHARED?
	JRST	OUTST6		;YES -- JUST USE
	HRROI	T1,(M)		;LEFT JUSTIFIED ASCIZ STRING
	PUSHJ	P,CKSTR##	;MAKE SURE ITS IN CORE AND LEGAL
	 JRST	UADERR##	;ADDRESS CHECK
OUTST6:
> ;END FTVM
	HRRI	M,-1(M)		;COMPENSATE FOR GETWD1
OUTST5:	MOVEI	P4,200		;MAXIMUM # OF WORDS IN ONE SHOT
OUTST2:	MOVE	P1,[POINT 7,P2]	;PREPARE TO READ BYTES
	PUSHJ	P,GETWD1##	;GET A USER'S WORD
	MOVE	P2,T1		;PUT WORD IN A SAFE AC
OUTST1:	TLNN	P1,760000	;ANY BYTES LEFT?
	JRST	OUTST4		;NO. GET ANOTHER WORD
	ILDB	T3,P1		;YES. GET ONE
	JUMPE	T3,PTSTRT	;NULL MARKS END OF STRING, START PTY
	PUSHJ	P,(P3)		;TYPE OUT CHARACTER WITH PARITY
	JRST	OUTST1		;AND GO BACK FOR MORE.
OUTST4:	SOJG	P4,OUTST2	;GO BACK FOR MORE. IS MESSAGE LONG?
	PUSHJ	P,SCDCHK##	;CHECK FOR CLOCK TICK
	JRST	OUTST5

;TRESCU IS FOR COMPIL TO READ COMMAND WHICH STARTED IT

TRESCU:	MOVE	T2,LDBDCH(U)	;SAVE OLD BIT FOR TEST
	MOVSI	T1,LDLECS	;CLEAR BIT IN LINE DATA BLOCK WHICH
	ANDCAM	T1,LDBDCH(U)	; WOULD CAUSE COMMAND TO BE SKIPPED
	TDNN	T2,T1		;SEE IF ANYTHING THERE
	TRNN	M,1		;NO--SEE IF USER WANTS TO KNOW
	POPJ	P,0		;NO--JUST RETURN
	JRST	CPOPJ1##	;YES--GIVE SKIP RETURN
	SUBTTL	TTCALL AND TRMOP. -- SKPINL AND SKPINC
;MORE SUBROUTINES FOR TTCALL UUO

;SKIP IF A LINE MAY BE INPUT

SKPINL:	PUSHJ	P,TYIEAT	;MAKE SURE NOT FAKED BY COMMAND
	PUSHJ	P,TTLCHK	;IS A LINE AVAILABLE?
	  SKIPA				;NO.  DON'T SKIP.
	AOS	0(P)		;YES. SKIP RETURN
	PJRST	NOCTRO		;IN ANY CASE, CLEAR ^O BIT

;SKIP IF A CHARACTER MAY BE INPUT

SKPINC:	PUSHJ	P,TYIEAT	;MAKE SURE NOT FAKED BY COMMAND
	SKIPG	LDBECC(U)
	SKIPLE	LDBTIC(U)	;ANY CHARACTERS IN LDB?
NCTRO1:	AOS	0(P)		;SKIP RETURN, CLEARING ^O
NOCTRO:	MOVSI	T1,LDLOSU	;CLEAR OUTPUT SUPPRESS BIT
	ANDCAM	T1,LDBDCH(U)	; IN LINE DATA BLOCK
	POPJ	P,0		;AND RETURN
	SUBTTL	TTCALL AND TRMOP. -- GETLIN
;GETLIN RETURNS A WORD OF INFORMATION ABOUT A LINE.


GETLIN:	PUSHJ	P,GETWDU##
	JUMPL	T1,GETLN1	;DOES HE WANT HIS OWN LINE
				; IF YES USE CURRENT C(U)
	TRZ	T1,.UXTRM	;CLEAR IO INDEX BIT
	CAIL	T1,TTPLEN##	;NO. DOES HE WANT A LEGAL ONE?
	JRST	GETLNZ		;NO. RETURN A ZERO
	MOVE	U,LINTAB##(T1)	;GET THE RIGHT LDB ADDRESS
GETLN1:	JUMPE	U,GETLNZ	;IN CASE RUNNING DETACHED
	HRRZ	F,LDBDDB(U)	;GET ATTACHED DDB
	SETZM	S		;ASSUME DETACHED
	SKIPE	F		;IS JOB DETACHED?
	MOVE	S,DEVIOS(F)	;GET STATUS BITS FOR TTY
	HLL	U,LDBDCH(U)	;GET DEVICE BITS FOR BELOW
	LDB	T1,LDPLNO	;GET THE LINE NUMBER FROM LDB
	TRO	T1,.UXTRM	;SET IO INDEX BIT
	HRL	T1,LDBDCH(U)	;GET RIGHT-HALF BITS.
	TLZ	T1,GTLMSK	;CLEAR BITS THAT ARE JUNK OR
				; THAT WILL BE SET BELOW
	LDB	T3,GETLP1	;GET BITS FROM LEFT OF LDBDCH
	DPB	T3,GETLP2	;AND PUT AT RIGHT PLACE IN T1
	TLC	T1,GTLT37	;THIS BIT IS WRONG SENSE
	JUMPE	F,GETLN5	;DONE IF NO DDB
	TLNE	U,LDLCOM	;IS LINE AT COMMAND LEVEL?
	JRST	GETLN4		;YES.  SEE IF SHOULD BE CONSIDERED FOR INPUT
GETLN3:	MOVE	T3,T1		;SAVE AWAY BITS SO FAR
	PUSHJ	P,TTLCK2	;SEE IF ANY LINE READY
	  TDZA	T1,T1		;NO. CLEAR T1
	MOVSI	T1,GTLRDY	;YES. SET BIT
	IOR	T1,T3		;PUT NEW BIT WITH OLD BIT

GETLN5:	TLNE	U,LDLXON	;XON TRUE?
	TLO	T1,GTLXON	;YES. FLAG THAT
GETLN2:	PJRST	PUTWDU##	;GIVE RESULT TO USER
				;AND RETURN

GETLNZ:	MOVEI	T1,0		;RETURN ZERO FOR BAD LINE
	JRST	GETLN2		;GO RETURN THAT
GETLN4:	HRRZ	T3,LDBDDB(U)	;GET LINKED DDB, IF ANY
	JUMPE	T3,GETLN3	;IF NONE, CHECK COUNTS
	MOVE	T3,DEVMOD(T3)	;GET DEVICE MODE BITS
	TLNN	T3,TTYATC	;IS TTY ATTACHED CONSOLE?
	JRST	GETLN3		;NO.  CHECK COUNTS
	JRST	GETLN5		;YES.  IGNORE COUNTS WHILE AT COMMAND LEVEL

GETLP1:	POINT	4,LDBDCH(U),15	;TO GET SOME BITS FROM LDB
GETLP2:	POINT	4,T1,15		;TO COPY THEM TO T1
	SUBTTL	TTCALL AND TRMOP. -- SETLIN, INCHSL, INCHWL, INCHRS & INCHRW
;ROUTINE TO SET LINE CHARACTERISTICS WHICH ARE LEGAL FOR USER TO DIDDLE

SETLIN:	PUSHJ	P,GETWDU##
	HLRZS	T1		;SEE WHAT HE WANTS TO SET THEM TO
	TRC	T1,GTLT37	;STORED AS COMPLEMENT
	ROT	T1,-2		;THIS IS BIT-DEPENDENT, MATCHING POINTER
	DPB	T1,SETLP1	;THESE THREE BITS CAN BE SET
	MOVSI	T3,LDLXON	;AND THIS ONE (NON-ADJACENT)
	SKIPGE	T1		;HE WANT IT ON?
	IORM	T3,LDBDCH(U)	;YES.
	SKIPL	T1		;OR OFF?
	ANDCAM	T3,LDBDCH(U)	;OFF.
	POPJ	P,0		;RETURN FROM SETLIN

SETLP1:	POINT	3,LDBDCH(U),15	;PART OF LEGAL BITS

INCHRS:	PUSHJ	P,SKPINC	;CAN I GET A CHARACTER (CLEAR ^O)
	  POPJ	P,0		;NO. GIVE NON-SKIP RETURN
	PUSHJ	P,TWAITC	;WAIT IN CASE NOT ECHOED YET
ICS3:	PUSHJ	P,TYIS		;GET A CHARACTER
	  JRST	NOCTRO		;NONE THERE.
	AOS	0(P)		;GIVE SKIP RETURN
	JRST	ICW1		;AND RETURN THE CHARACTER

INCHSL:	PUSHJ	P,SKPINL	;IS THERE A LINE AVAILABLE?
	  POPJ P,0		;NO. NON-SKIP RETURN TO USER
	PUSHJ	P,TWAITL
	JRST	ICS3		;YES. GO GET A CHARACTER FOR HIM

INCHWL:	PUSHJ	P,TWAITL	;WAIT FOR A LINE TO APPEAR
	PUSHJ	P,TYI		;GO GET A CHARACTER
	  MOVEI	T3,0		;IMPOSSIBLE. NO CHARACTERS. USER SET IODERR?
ICW1:	ANDI	T3,177		;MASK TO SEVEN BITS
	MOVE	T1,T3
	MOVE	R,JBTADR##(J)
	PUSHJ	P,PUTWDU##	;GIVE HIM THE CHARACTER
	JRST	NOCTRO		;AND NON-SKIP RETURN

INCHRW:	PUSHJ	P,TWAITC	;WAIT FOR A CHARACTER TO APPEAR
	PUSHJ	P,TYI		;GO GET THE CHARACTER
	  MOVEI	T3,0		;IMPOSSIBLE. NONE THERE. USER SET IODERR?
	JRST	ICW1		;GIVE HIM T3 AND RETURN

	SUBTTL	TTCALL AND TRMOP. -- TRMNO. UUO
IFN FT5UUO,<			;LEAVE OUT OF SMALL SYSTEMS
;TRMNO.	CALLI, TO GET TERMINAL NUMBER
;FOR SPECIFIED JOB NUMBER.
;	MOVE	AC,JOBNUMBER
;CALL	CALLI	AC,115
;	.ERROR RETURN
;	NORMAL RETURN		;AC HAS .UXTRM+LINE#

TRMNO::	CAMN	T1,[-1]		;IS ARG -1?
	MOVEI	T1,(J)		;YES, USE THIS JOB
	JUMPLE	T1,RTZER##	;ERROR IF JOB # 0 OR LESS THAN -1
	CAMLE	T1,HIGHJB##	; OR TOO BIG
	JRST	RTZER##		;..
	HRRZ	T1,TTYTAB##(T1)	;GET DDB ADDRESS
	JUMPE	T1,RTZER##	;ERROR IF NONE
	HRRZ	U,DDBLDB(T1)	;GET LDB ADDRESS
	JUMPE	U,RTZER##	;ERROR IF DETACHED
	LDB	T1,LDPLNO	;GET LINE NUMBER
	ADDI	T1,.UXTRM	;CONVERT TO UNIVERSAL
	JRST	STOTC1##	;SKIP RETURN INDEX TO USER

>				;END OF FT5UUO CONDITIONAL
	SUBTTL	TTCALL AND TRMOP. -- TRMOP. DISPATCH
IFN FT5UUO,<			;NOT IN SMALL SYSTEMS
;TRMOP. UUO, OR CALLI 116.
;UUO TO PERFORM MISCELLANEOUS FUNCTIONS FOR
;A SPECIFIED TERMINAL.
;
;CALL:	MOVE	AC,[XWD N,ADR]
;	CALLI	AC,116
;	  ERROR	RETURN
;	NORMAL	RETURN
;

TRMOP::	PUSHJ	P,SAVE4##	;SAVE THE PRESERVED AC'S
	MOVE	P4,T1		;USER'S ARGUMENT TO P4
	HRRM	T1,M		;ADDRESS OF ARGUMENT LIST
	HLRZ	T2,T1		;CHECK FOR LENGTH AT LEAST 2
	CAIL	T2,2
	PUSHJ	P,GETWRD##	;GET USER'S ARG AT M
	  JRST	TOPX3		;ERROR CODE 3, ILLEGAL ADDRESS
	HRRZ	P1,T1		;COPY USER ARGUMENT
	JUMPLE	P1,RTZER##	;ZERO ERROR IF BAD ARGUMENT CODE
	HRRI	M,1(M)		;POINT TO TERMINAL INDEX
	PUSHJ	P,GETWRD##	;GET IT, IF POSSIBLE
	  JRST	TOPX3		;NOT A LEGAL ADDRESS
	SUBI	T1,.UXTRM	;REMOVE TERMINAL OFFSET
	JUMPL	T1,RTZER##	;RANGE CHECK THE TERMINAL #
	CAIL	T1,TTPLEN##	;..
	  JRST	RTZER##		;BAD LINE NUMBER
	HRRZ	U,LINTAB##(T1)	;OK. GET THE LDB ADDRESS
	HRRZ	F,LDBDDB(U)	;AND DDB, IF ANY.
	HRRZ	T1,P1		;GET USER'S FUNCTION CODE
	TRNE	T1,3000		;READ/SET CODE?
	JRST	TOPRSQ		;PROBABLY. GO SEE.
	CAILE	T1,TOPLN0	;IS IT AN ACTION CODE?
	JRST	RTZER##		;NO. NO SUCH CODE
	HRRI	M,1(M)		;ADVANCE M
	MOVE	P3,TOPTB0-1(T1)	;PICK UP DISPATCH WORD
IFN FTMIC,<
	MOVSI	P2,(JB.LSY)	;PROGRAM FROM SYS BIT
	TLNE	P3,(TOP.MC)	;MIC TRMOP?
	TDNN	P2,JBTLIM##(J)	;AND DID THIS PROGRAM COME FROM SYS?
	JRST	CHKRED		;NO TO EITHER
	MOVSI	P2,'MIC'	;RUNNING MIC?
	CAMN	P2,JBTNAM##(J)	;SKIP IF NO
	JRST	CHKDDB		;RUNNING MIC, NO FUTHER CHECKING REQUIRED
CHKRED:	MOVSI	T1,JP.POK	;POKE ALLOWS ALL
	TLNE	P3,(TOP.MR)	;MUST BE MIC?
	PUSHJ	P,PRVBIT	;CHECK PRIVS
	  SKIPA
	JRST	TOPX1		;GIVE ERROR
>
	TLNN	P3,(TOP.RP)	;DO WE NEED READ PRIVS?
	JRST	CHKWRT		;NO--SEE IF WE NEED WRITE PRIVS
	PUSHJ	P,TREDOK	;YES--DO WE HAVE READ PRIVS?
	  JRST	TOPX1		;NO--GIVE ERROR RETURN
CHKWRT:	TLNN	P3,(TOP.WP)	;DO WE NEED WRITE PRIVS?
	JRST	CHKDDB		;NO--DISPATCH
	PUSHJ	P,TWRTOK	;YES--DO WE HAVE READ PRIVS?
	  JRST	TOPX1		;NO--GIVE ERROR RETURN
CHKDDB:	TLNN	P3,(TOP.NF)	;NEED F?
	JRST	(P3)		;NO--ALLSET
	PUSHJ	P,TOPDDB	;YES--GET DDB
	  JRST	TOPX6		;CAN'T GIVE ERROR
	JRST	(P3)		;YES--DO THE TRMOP.

;STILL IN FT5UUO CONDITIONAL

;HERE IF REQUESTED FUNCTION NOT FROM 1 THRU TOPLN0-1
;F AND U ARE SET UP TO THE DESIRED LINE.

TOPRSQ:	ANDI	P1,777		;JUST THE ITEM NUMBER
	TRZE	T1,1000		;READ CODE?
	JRST	TOPRED		;PROBABLY
	CAIL	T1,2000+TOPLN1	;NO. SET CODE?
	JRST	RTZER##		;NOT A LEGAL CODE
TOPSET:	HLRZ	T2,P4		;IS THERE ANOTHER DATUM?
	CAIGE	T2,3		;..
	JRST	TOPX3		;NO. CAN'T DO THE SET.
	HRRI	M,1(M)		;YES. GO GET IT
	PUSHJ	P,GETWRD##	;..
	  JRST	TOPX3		;NOT A LEGAL ADDRESS
	MOVE	P2,T1		;SAVE ARGUMENT
	PUSHJ	P,TWRTOK	;DOES HE HAVE WRITE PRIVS?
	  JRST	TOPX1		;NO. ERROR CODE 1.
TOPST1:	LDB	T1,TOPSYR	;LEGAL TO TRY SETTING.
	JUMPE	T1,TOPST2	;RANGE CHECK REQUIRED?
	HLRZ	T2,TOPSRT-1(T1)	;YES. GET MINIMUM VALUE
	CAMGE	P2,T2		;SUPPLIED .GE. MINIMUM?
	JRST	TOPX2		;NO. BAD ARG, TOO SMALL
	HRRZ	T2,TOPSRT-1(T1)	;OK. CHECK MAXIMUM
	CAMLE	P2,T2		;..
	JRST	TOPX2		;BAD. ARG TOO BIG.
TOPST2:	MOVE	T2,TOPTB1(P1)	;SET ALLOWED?
	TLNN	T2,(TOP.NI)	;ILLEGAL ON NET?
	JRST	TOPST3		;NO, SO GO ON
	MOVE	T1,LDBDCH(U)	;YES, IS TTY ON
	TRNE	T1,LDRREM	; THE NET?
	JRST	TOPX2		;YES, ERROR
TOPST3:	TLNE	T2,(TOP.SA)	;OK TO SET?
	JRST	TOPST4		;YES--DO SO
	TLNN	T2,(TOP.PS)	;NEED PRIVS?
	JRST	TOPX1		;NO--CAN NOT SET
	MOVSI	T1,JP.POK	;POKE BIT
	PUSHJ	P,PRVBIT	;IS IT SET?
	  JRST	TOPST4		;YES--DO SET
	JRST	TOPX1		;NO. NOT ALLOWED.
TOPST4:	MOVEI	T1,LDRPTY
	CAIN	P1,4		;SET SLAVE?
	TDNN	T1,LDBDCH(U)	; ON PTY?
	DPB	P2,0(T2)	;OK. CHANGE ITEM.
IFN FTD10H,<
	CAIN	P1,27		;ARE WE SETTING APL?
	DPB	P2,[POINT 1,LDBBCD(U),11]  ;YES, SET IT WHERE DLSINT
				; LOOKS FOR IT
>	;END OF D10H
IFN FTCAFE,<
TOPTFE:	MOVSI	T1,(TOP.PE)	;DO WE NEED TO CHANGE
	TDNN	T1,TOPTB1(P1)	; HARDWARE PARAMS FOR THIS LINE
	JRST	CPOPJ1##	;NO--JUST RETURN
	MOVEI	T1,ISRCHP	;CHANGE HARDWARE PARAMS
	PUSHJ	P,@LDBISR(U)	;CALL THE ISR
> ;END FTCAFE
	JRST	CPOPJ1##	;SKIP RETURN

;STILL IN FT5UUO CONDITIONAL
TOPRED:	CAIL	T1,TOPLN1	;LEGAL ITEM NUMBER?
	JRST	RTZER##		;NO. ERROR RETURN
	PUSHJ	P,TREDOK	;OK TO DO A READ?
	  JRST	TOPX1		;NO. PROTECTION FAILURE.
	MOVE	T1,TOPTB1(P1)	;OK. GET TABLE ENTRY.
	LDB	T1,0(T1)	;GET BYTE POINTED TO
	PJRST	STOTC1##	;AND RETURN IT TO USER

;STILL IN FT5UUO CONDITIONAL
;SUBROUTINE TO CHECK FOR READ PRIVS
;CALL WITH:
;	F = DDB OF TARGET OR 0
;	PUSHJ	P,TREDOK
;	  RETURN HERE IF ERROR
;	RETURN HERE IF OK TO READ

TREDOK:	PUSHJ	P,SAVE3##	;SAVE P1,P2, AND P3
	MOVSI	P1,PVSPYM	;LOAD UP THE SPY BIT
	JRST	MYTTY		;JUMP TO COMMON CODE

;SUBROUTINE TO CHECK FOR WRITE PRIVS
;CALL WITH:
;	F = DDB OF TARGET OR 0
;	PUSHJ	P,TWRTOK
;	  RETURN HERE IF ERROR
;	RETURN HERE IF OK
;PRESERVES ALL AC'S

TWRTOK:	PUSHJ	P,SAVE3##	;SAVE P1,P2, AND P3
	MOVSI	P1,JP.POK	;FALL INTO COMMON CODE
MYTTY:	SKIPE	P2,F		;IS THERE A DDB?
	LDB	P2,PJOBN##	;YES--GET THE OWNERS JOB NUMBER
	CAMN	P2,J		;DO I OWN THIS TTY
	JRST	MYTTY1		;CHECK PRIVS FOR MIC STYLE TRMOP.
MYTTY2:	EXCH	P1,T1		;SAVE T1 AND SET UP PRIV BIT
	PUSHJ	P,PRVBIT##	;CHECK THE BIT
	  AOS	(P)		;OK TO READ OR SET
	MOVE	T1,P1		;RESTORE T1
	POPJ	P,0		;RETURN
MYTTY1:	
IFE FTMIC,<
	JRST	CPOPJ1##	;OK TO DO YOUR THING
>
IFN FTMIC,<
	TLNN	P3,(TOP.MC)	;MIC TRMOP?
	JRST	CPOPJ1##	;NO--OK TO DO YOUR THING
	MOVE	P2,DEVMOD(F)	;IS TARGET TTY...
	TLNE	P2,TTYATC	;CONTROLLING HIS JOB?
	JRST	CPOPJ1##	;YES--OK TO DO MIC TRMOP.
	MOVE	P2,LDBDCH(U)	;NO--CHECK IF TARGET TTY..
	TRNE	P2,LDRCTY	; IS A CTY
	JRST	MYTTY2		;YES--CHECK PRIVS
	HRRZ	P3,TTYTAB##(J)	;GET USER'S TTY DDB ADDRESS
	JUMPE	P3,RTZER##	;ERROR IF NONE
	HRRZ	P3,DDBLDB(P3)	;LDB ADDRESS
	JUMPE	P3,MYTTY2	;DETACHED, MUST CHECK PRIVS
	MOVE	P3,LDBDCH(P3)	;USER'S TTY CHARACTERISTICS BITS
	TRNN	P3,LDRRMT	;IS HE A LOCAL TTY?
	JRST	CPOPJ1##	;YES--LET HIM DO MIC TRMOP TO EITHER REMOTE OR LOCAL TTY'S
	TRNE	P2,LDRRMT	;NO--TARGET TTY ANOTHER REMOTE TTY
	JRST	CPOPJ1##	;YES--DO IT
	JRST	MYTTY2		;NO--CHECK PRIVS
>

;STILL UNDER FT5UUO CONDITIONAL
;ERROR RETURNS

ERCODE	TOPX1,TRMNP%		;(1) ERROR CODE FOR PROT CHECK
ERCODE	TOPX2,TRMBR%		;(2) ERROR CODE FOR RANGE BAD
ERCODE	TOPX3,TRMIA%		;(3) ERROR CODE FOR ADDRESS BAD.
ERCODE	TOPX4,TRMCD%		;(4) ERROR CODE FOR NOT POSSIBLE TO DO
ERCODE	TOPX5,TRMDO%		;(5) ERROR IN DIALLER OPERATION
ERCODE	TOPX6,TRMND%		;(6) CAN NOT GET DDB

;STILL IN FT5UUO CONDITIONAL
;CONTENTS OF TOPTB1 ARE AS FOLLOWS
;BITS 0-5 ARE RANGE TABLE INDEX FOR RANGE CHECK ON SET.
;BITS 6-12 ARE FLAGS FOR DETERMINING LEGALITY OF TRMOP UUO
;RH IS ADDRESS OF BYTE POINTER.

TOP.SA==1B6	;SET ALLOWED
TOP.PS==1B7	;SET ALLOWED FOR PRIVILEGED JOB ONLY
TOP.PE==1B8	;POKE THE FRONT END IF SET
TOP.NI==1B9	;ILLEGAL IF TTY ON A NETWORK NODE

;NOTE: THESE DEFINITIONS MUST AGREE WITH LDB DEFINITIONS
TOPTB1:	EXP <0>B5+<0>+<[POINT 1,LDBDCH(U),^L<(LDLOIP)>]>	;1000
	EXP <0>B5+<0>+<[POINT 1,LDBDCH(U),^L<(LDLCOM)>]>	;1001
	EXP <0>B5+<TOP.SA+TOP.PE>+<[POINT 1,LDBDCH(U),^L<(LDLXON)>]>	;1002
	EXP <0>B5+<TOP.SA+TOP.PE>+<[POINT 1,LDBDCH(U),^L<(LDLLCT)>]>	;1003
	EXP <0>B5+<TOP.SA>+<[POINT 1,LDBDCH(U),^L<(LDLSLV)>]>	;1004
	EXP <0>B5+<TOP.SA>+<[POINT 1,LDBDCH(U),^L<(LDLTAB)>]>	;1005
	EXP <0>B5+<TOP.SA>+<[POINT 1,LDBDCH(U),^L<(LDLFRM)>]>	;1006
	EXP <0>B5+<TOP.SA>+<[POINT 1,LDBDCH(U),^L<(LDLLCP)>]>	;1007
	EXP <0>B5+<TOP.SA>+<[POINT 1,LDBDCH(U),^L<(LDLNFC)>]>	;1010
	EXP <0>B5+<TOP.PE>+<PHPOS>				;1011
	EXP <1>B5+<TOP.SA+TOP.PE>+<LDPWID>			;1012
	EXP <0>B5+<TOP.SA>+<[POINT 1,LDBBY2(U),^L<(L2LSND)>]>	;1013
	EXP <0>B5+<TOP.PS>+<[POINT 1,LDBDCH(U),^L<LDRHLF>]>	;1014
	EXP <0>B5+<TOP.PS>+<[POINT 1,LDBDCH(U),^L<LDRRMT>]>	;1015
	EXP <0>B5+<TOP.PS>+<[POINT 1,LDBDCH(U),^L<LDRDIS>]>	;1016
	EXP <2>B5+<TOP.SA+TOP.PE>+<LDPFLC>			;1017
	EXP <0>B5+<TOP.SA+TOP.PE>+<[POINT 1,LDBBY2(U),^L<(L2LTAP)>]>	;1020
	EXP <0>B5+<TOP.SA+TOP.PE>+<[POINT 1,LDBPAG(U),^L<(LPLPAG)>]>	;1021
	EXP <0>B5+<TOP.SA+TOP.PE>+<[POINT 1,LDBPAG(U),^L<(LPLSTP)>]>	;1022
	EXP <3>B5+<TOP.SA>+<LDPPSZ>				;1023
	EXP <3>B5+<LDPPCT>					;1024
	EXP <0>B5+<TOP.SA>+<[POINT 1,LDBPAG(U),^L<(LPLBLK)>]>	;1025
	EXP <0>B5+<TOP.SA>+<[POINT 1,LDBPAG(U),^L<(LPLALT)>]>	;1026
	EXP <0>B5+<TOP.SA+TOP.PE>+<LDPAPL>			;1027
	EXP <4>B5+<TOP.SA+TOP.PE>+<LDPRSP>			;1030
	EXP <4>B5+<TOP.SA+TOP.PE>+<LDPTSP>			;1031
	EXP <0>B5+<TOP.SA+TOP.PE>+<LDPDBK>			;1032
	EXP <0>B5+<TOP.PS>+<LDP274>				;1033
	EXP <0>B5+<TOP.SA+TOP.PE>+<LDPTDY>			;1034
	EXP <5>B5+<TOP.SA+TOP.PE>+<LDPACR>			;1035
	EXP TOP.SA+LDPRTC					;1036
	EXP <0>B5+<TOP.SA>+<[POINT 36,LDBPBK(U),35]>		;1037
TOPLN1==.-TOPTB1
IFN FTPATT,<
	EXP 0							;FOR PATCHING
	EXP 0							;FOR PATCHING
>
;STILL IN FT5UUO CONDITIONAL
TOPSYR:	POINT 6,TOPTB1(P1),5		;POINTER TO RANGE TABLE INDEX

;THIS IS THE RANGE TABLE
TOPSRT:	XWD	^D16,^D200		;(1)MIN AND MAX WIDTHS
	XWD	0,3			;(2)MIN AND MAX FILLER CLASSES
	XWD	0,^D63			;(3)MIN AND MAX PAGE LENGTH
	XWD	0,17			;(4)MIN AND MAX SPEED
	XWD	0,^D200			;(5)AUTO C.R. TABLE
IFN FTPATT,<
	0				;FOR PATCHING. NEW ONES ABOVE THIS WORD
>

;STILL IN FT5UUO CONDITIONAL
	TOP.RP==1B1		;NEED READ PRIVS TO DO THIS FUNCTION
	TOP.WP==1B2		;NEED WRITE PRIVS TO DO THIS FUNCTION
	TOP.NF==1B3		;NEED F SETUP TO DO THIS FUNCTION
IFN FTMIC,<
	TOP.MC==1B4		;THIS FUNCTION IS LEGAL IF RUNNING MIC
	TOP.MR==1B5
>

TOPTB0:	EXP	TOP.RP+TOPSIP	;1 - SKIP IF INPUT PRESENT
	EXP	TOP.RP+TOPSOP	;2 - SKIP IF OUTPUT PRESENT
	EXP	TOP.WP+TOPCIB	;3 - CLEAR INPUT BUFFER
	EXP	TOP.WP+TOPCOB	;4 - CLEAR OUTPUT BUFFER
	EXP	TOP.RP+TOP.WP+TOPOUC	;5 - OUTPUT CHAR
	EXP	TOP.RP+TOP.WP+TOP.NF+TOPOIC	;6 - OUTPUT IMAGE CHAR
	EXP	TOP.RP+TOP.WP+TOPOUS	;7 - OUTPUT STRING
	EXP	TOP.RP+TOP.WP+TOPINC	;10 - INPUT CHAR
	EXP	TOP.RP+TOP.WP+TOPIIC	;11 - INPUT IMAGE CHAR
	EXP	TOP.WP+TOPDSE	;12 - DATASET ENABLE
	EXP	TOP.WP+TOPDSC	;13 - DATASET CALL
	EXP	TOP.WP+TOPDSF	;14 - DATASET OFF
	EXP	TOP.RP+TOP.WP+TOPRES	;15 - RESCAN
IFN FTCAFE,<
IFN FT2741,<
	EXP	TOP.WP+TOPELE	;16 - SET TYPE ELEMENT
>
IFE FT2741,<
	EXP	RTZER##
>
	EXP	TOP.WP+TOPABR	;17 - ENABLE AUTO BAUD DETECT
> ;END FTCAFE
IFE FTCAFE,<
	EXP	RTZER##		;16 - NOT IMPLEMENTED
	EXP	RTZER##		;17 - NOT IMPLEMENTED
> ;END FTCAFE
	EXP	TOP.RP+TOP.WP+TOPISC	;20 - INPUT CHAR.
IFN FTMIC,<
	EXP	TOP.RP+TOP.WP+TOP.MC+TOPMTY	;21 - MICTYP
	EXP	TOP.RP+TOP.WP+TOP.MC+TOPMGT	;22 - MICGET
	EXP	TOP.RP+TOP.WP+TOP.MC+TOPMST+TOP.MR  ;23 - MICSET
	EXP	TOP.RP+TOP.WP+TOP.MC+TOPMCL	;24 - MICCLR
	EXP	TOP.RP+TOP.WP+TOP.MC+TOPMDP	;25 - MICDPY
	EXP	TOP.RP+TOP.WP+TOP.MC+TOPMRS	;26 - MICDSP
IFN FTMLOG,<
	EXP	TOP.MC+TOP.RP+TOP.WP+TOPMLG	;27 - MICLOG
>
IFE FTMLOG,<
	EXP	RTZER##		;27 - NOT IMPLEMENTED
>
>
IFE FTMIC,<
	EXP	RTZER##		;21 - NOT IMPLEMENTED
	EXP	RTZER##		;22 - NOT IMPLEMEMTED
	EXP	RTZER##		;23 - NOT IMPLEMENTED
	EXP	RTZER##		;24 - NOT IMPLEMENTED
	EXP	RTZER##		;25 - NOT IMPLEMENTED
	EXP	RTZER##		;26 - NOT IMPLEMEMTED
	EXP	RTZER##		;27 - NOT IMPLEMENTED
>
	EXP	TOPDSS		;30 - RETURN DATA SET STATUS
TOPLN0==.-TOPTB0
IFN FTPATT,<
	0			;FOR PATCHING
>


	SUBTTL	TTCALL AND TRMOP. -- SKIPS AND CLEARS
TOPSIP==SKPINC

TOPSOP:	SKIPG	LDBTOC(U)	;OUTPUT READY?
	SKIPGE	LDBDCH(U)	;OR OUTPUT IN PROGRESS?
	AOS	0(P)		;YES. SKIP RETURN
	POPJ	P,0		;RETURN
TOPCIB:	AOS	0(P)		;SUCCESS RETURN
	PJRST	TSETBI		;CLEAR INPUT BUFFER
TOPCOB:	AOS	0(P)		;SUCCESS RETURN
	PJRST	TSETBO		;CLEAR OUTPUT BUFFER

;FOLLOWING NOT DONE YET
	TOPIIC==RTZER##

IFE FTMODM,<
	TOPDSE==CPOPJ##
	TOPDSF==CPOPJ##
	TOPDSC==CPOPJ##
	TOPDSS==CPOPJ##
>

;STILL IN FT5UUO CONDITIONAL
	SUBTTL	TTCALL AND TRMOP. -- TRMOP. I/O
;OUTPUT 1 CHAR
TOPOUC:	AOS	(P)
	PUSHJ	P,TOPDDB	;GET A DDB
	  SETZM	F		;NO--DON'T NEED IT BADLY
	JRST	ONEOUT		;TYPE

;OUTPUT A STRING
IFN FTMIC,<
TOPMDP:	MOVSI	T1,LDLOSU	;CLEAR CONTROL O BIT
	ANDCAM	T1,LDBDCH(U)	;SO DATA WILL BE SEEN
	TDZA	F,F		;SO CCTYO WILL BE USED (AVOID TIOW)
>
TOPOUS:
IFN FTMIC,<
	SETOM	F		;SEARCH FOR A DDB
>
	AOS	(P)
	PUSHJ	P,GETWDU	;GET POINTER
	HRRZ	M,T1		;PUT IN RIGHT AC
IFN FTMIC,<
	SKIPE	F		;DON'T SEARCH FOR A DDB IF THIS IS MIC DISPLAY
>
	PUSHJ	P,TOPDDB	;GET A DDB
	  TDZA	F,F		;NONE
	PJRST	OUTSTR		;HAVE ONE DO OUTSTR
	PUSHJ	P,SAVE3##	;SAVE P1 AND P2
	MOVEI	P3,CCTYO	;ROUTINE TO USE
	PJRST	OUTST3		;DO PART OF OUTSTR

;OUTPUT IMAGE CHAR
TOPOIC::AOS	(P)		;SKIP RETURN			
	JRST	IONEOU		;TYPE IT

;INPUT A CHAR
TOPISC:	SKIPA	P1,[EXP INCHRW]
TOPINC:	MOVEI	P1,INCHWL
	AOS	(P)
	LDB	T1,PUUOAC##	;WHERE TO PUT ANSWER
	HRR	M,T1
	PUSHJ	P,TOPDDB
	  TDZA	F,F
	PJRST	(P1)		;GET A BYTE
	PUSHJ	P,TYI		;GET CHAR
	  MOVEI	T3,0		;NONE THERE--RETURN NULL
	MOVE	T1,T3		;COPY CHAR
	JRST	STOTAC##	;STORE FOR USER

;INPUT IMAGE CHAR
TOPIIC==RTZER##

;DO A RESCAN
TOPRES:	PUSHJ	P,TRESCU	;DO IT
	  JRST	CPOPJ1##	;WIN
	JRST	CPOPJ1##	;WIN

;STILL IN FT5UUO

	SUBTTL	TTCALL AND TRMOP. -- TRMOP. I/O SUBROUTINES
;GET A DDB FOR TRMOP. I/O

TOPDDB:	HRRZ	F,LDBDDB(U)	;GET DDB POINTER
	JUMPE	F,TOPDD1	;ANY DDB THERE?
	LDB	T1,PJOBN##	;YES--IS IT MINE?
	CAMN	T1,.C0JOB##	; ..
	AOS	(P)		;YES--USE IT
	POPJ	P,		;NO--ERROR

TOPDD1:	PUSHJ	P,TTYNAM	;GET SIXBIT NAME
	MOVE	T1,T2		;PUT IN T1
	PUSHJ	P,GETDDB	;GET A DDB
	  POPJ	P,		;NONE LEFT
	MOVEI	T1,ASSPRG	;INIT THE DDB SO
	IORM	T1,DEVMOD(F)	; IT WILL STICK
	MOVE	T1,.C0JOB	; AROUND AND WE
	DPB	T1,PJOBN##	; CAN WAKE OWNER
	AOS	(P)		;SKIP RETURN (CALL?)
	PUSHJ	P,@0(P)		;CALL OUR CALLER
	  JRST	.+2		;NON-SKIP
	AOS	-1(P)		;SKIP
	PUSHJ	P,TTYREL	;KILL OFF DDB
	JRST	TPOPJ##		;AND RETURN

;STILL IN FT5UUO
	SUBTTL	TTCALL AND TRMOP. -- TRMOP. DATASET FUNCTIONS
IFN FTMODM,<
;MORE SUBROUTINES FOR TRMOP

TOPDSE:	MOVE	T1,LDBDCH(U)	;GET DEVICE CHARACTERISTICS
IFN FTNET,<
	TRNE	T1,LDRREM	;REMOTE LINE
	JRST	NETDSE		;YES
>
	TRNN	T1,LDRDSD	;IS IT A DATASET?
	JRST	TOPX4		;NO. ERROR CODE 4
	LDB	U,LDPDSC	;GET THE TABLE OFFSET INTO U
	MOVSI	T1,DSCIC2	 ;CLEAR FAILURE, DIALLER FLAGS AND TIMER
	ANDCAM	T1,DSCTAB##(U)	; ..
	MOVSI	T1,DSCSWC	;SET TO ALLOW HIM ON
	PUSHJ	P,DSRRN1	;SEND TO MODEM HANDLER
	JRST	CPOPJ1##	;AND SKIP RETURN

TOPDSF:	MOVE	T1,LDBDCH(U)	;GET DEV CHARACTERISTICS
IFN FTNET,<
	TRNE	T1,LDRREM	;REMOTE LINE
	JRST	NETDSF		;YES
>
	TRNN	T1,LDRDSD	;IS IT A MODEM
	JRST	TOPX4		;NO. CANT DO THIS.
	PUSHJ	P,LDBCLR	;CLEAR OUT LDB
	HRRZ	F,LDBDDB(U)	;DDB?
	JUMPE	F,TOPDF1	;NOT CONTROLING JOB
	MOVE	T1,DEVMOD(F)
	TLNN	T1,TTYATC	;CONTROLING TTY?
	JRST	TOPDF1		;NOPE
	MOVEI	T1,TTFCXD	;DETACH IT
	PUSHJ	P,TTFORC
TOPDF1:	LDB	U,LDPDSC	;GET TABLE INDEX
	MOVSI	T1,DSCHWC	;CLEAR
	ANDCAM	T1,DSCTAB##(U)
	PUSHJ	P,DSROF1	;HANG IT UP
	JRST	CPOPJ1##	;AND SKIP RETURN

TOPDSS:	MOVE	T1,LDBDCH(U)	;CHARACTERISTICS
IFN FTNET,<
	TRNE	T1,LDRREM	;REMOTE?
	JRST	NETDSS		;YES, LET NETSER DO IT
>
	TRNN	T1,LDRDSD	;DATA SET?
	JRST	TOPX4		;NO, LOSE
	LDB	U,LDPDSC	;DSCTAB OFFSET
	SKIPL	DSCTAB##(U)	;HARDWARE CARRIER?
	TDZA	T1,T1		;NO
	MOVSI	T1,DSCHWC	;YES
	JRST	STOTC1##	;STORE ANSWER FOR USER
IFE FTDIAL,<
	TOPDSC==CPOPJ##
>
IFN FTNET,<
	;CODE TO CONTROL REMOTE DATA SET LINES
NETDSS:	MOVEI	T3,DSTSTS	;STATUS
	JRST	NETISR		;CALL NETSER
NETDSE:	MOVEI	T3,DSTON	;SET DATA SET ON
	JRST	NETISR		;CALL NETSER
NETDSF:	MOVEI	T3,DSTOFF	;SET DATA SET OFF
	JRST	NETISR		;CALL NETSER
NETDSC:	MOVEI	T3,DSTCRQ	;DIALER REQUEST
NETISR:	MOVEI	T1,ISRDSC	;DATA SET CONTROL FUNCTION
	PJRST	D85DSC##	;CALL NETSER DIRECTLY SICE NO DTA SET TIMING
>
IFN FTDIAL,<
IFE FTSLEEP,<	PRINTX DIALLER CODE REQUIRES SLEEP## FEATURE>
TOPDSC:	MOVE	T1,LDBDCH(U)	;DEVICE CHARACTERISTICS
IFN FTNET,<
	TRNE	T1,LDRREM	;REMOTE LINE
	JRST	NETDSC		;YES
>
	TRNN	T1,LDRDSD	;DATASET?
	JRST	TOPX4		;NO. CAN'T DIAL THEN.
	LDB	U,LDPDSC	;GET DSCTAB INDEX
	MOVE	T1,DSCTAB##(U)	;AND BITS
	TLNE	T1,DSCHWC!DSCSWC ;ALREADY IN USE?
	JRST	TOPX5		;YES. CAN'T DIAL ON IT.
TOPDC1:	HRRZ	T1,DSCTAB##(U)	;GET TTY NUMBER FOR MODEM
	CAME	T1,DSDUNI##	;BUSY FOR SAME UNIT, OR
	SKIPN	TTYDDA##	;DIALLER FREE?
	JRST	TOPDC2		;YES
	MOVEI	T1,5		;NO. WAIT FOR IT.
	PUSHJ	P,SLEEP##		; ..
	JRST	TOPDC1		;TRY AGAIN
TOPDC2:	MOVEM	T1,DSDUNI##	;SAVE LINE BEING DIALLED
	PUSHJ	P,GETWRD##	;FROM USER CORE
	  JRST	TOPX3		;ADDRESS CHECK
	MOVEM	T1,DSCNUM	;STORE FOR DIALLER CODE
	HRRI	M,1(M)		;AND SECOND WORD
	PUSHJ	P,GETWRD##	; ..
	  JRST TOPX3		;ADDRESS CHECK
	TRO	T1,17		;GUARANTEE AN END OF NUMBER CODE
	MOVEM	T1,DSCNUM+1	;STORE SECOND WORD
	MOVSI	T1,DSCIC2	;CLEAR OUT THESE BITS
	ANDCAM	T1,DSCTAB##(U)	;IN CONTROL TABLE
	MOVSI	T1,DSCSWC!DSCDLW!^D30
	IORM	T1,DSCTAB##(U)	;AND SET UP TO WAIT FOR DIALLER
	MOVE	T1,[POINT 4,DSCNUM]
	MOVEM	T1,TTYDDA##	;STORE INITIAL POINTER TO NUMBER
	MOVEI	T3,DSTCRQ	;CALL REQUEST CODE
	PUSHJ	P,DSCCAL	;TO THE DEVICE HANDLER
TOPDC3:	MOVEI	T1,^D15		;SLEEP FOR FIFTEEN SECONDS
	PUSHJ	P,SLEEP##		; ..
	MOVE	T1,DSCTAB##(U)	;SEE WHAT HAPPENED.
	TLNE	T1,DSCDLF	;FAIL?
	JRST	TOPX5		;YES.
	TLNE	T1,DSCDLC	;COMPLETED OK?
	JRST	CPOPJ1##	;YES. SKIP RETURN TO USER
	JRST	TOPDC3		;NEITHER YET. LOOP.

>	;END OF FTDIAL
>	;END OF FTMODM
;STILL IN FT5UUO
IFN FTCAFE,< ;IF WE SUPPORT THE DC76 COMPREHENSIVE ASYNCHRONOUS FRONT END

TOPABR:	MOVEI	T3,<LPCABR>B27	;SET UP FUNCTION
	MOVEI	T1,ISRLPC	;FUNCTION CODE
	SKIPGE	LDBISR(U)	;SKIP IF NOT DC76
	PUSHJ	P,@LDBISR(U)	;CALL SERVICE ROUTINE
	JRST	CPOPJ1##	;GIVE GOOD RETURN
> ;END FTCAFE CONDITIONAL

IF2,<
IFNDEF	TOPABR,<TOPABR==RTZER##>
IFNDEF	TOPELE,<TOPELE==RTZER##>
> ;END IF2 CONDITIONAL
;STILL IN FT5UUO
;HERE TO SET TYPE ELEMENT IN 2741
IFN FTCAFE&FT2741,<

;ASSUME THAT THE ELEMENT CAN BE SET.

TOPELE:	PUSHJ	P,GETWRD	;GET SETTING.
	  JRST	TOPX3		;ADDRESS CHECK
	MOVE	T3,T1
	MOVEI	T1,ISRELE	;FUNCTION
	PUSHJ	P,@LDBISR(U)	;CALL ISR
	  JRST	TOPX2		;BAD NUMBER
	JRST	CPOPJ1##	;WIN
> ;END FTCAFE&FT2741
>	;END OF FT5UUO CONDITIONAL
IFN FTMIC,<
SUBTTL	BYTE POINTERS INTO THE USER'S LDBMIC WORD

	;BYTE POINTERS INTO THE USER'S LDBMIC WORD

LDP.OP:	POINT	7,LDBMIC(U),21		;OPERATOR CHARACTER
LDP.ER:	POINT	7,LDBMIC(U),28		;ERROR CHARACTER
LDPMJN:	POINT	7,LDBMIC(U),35		;MIC MASTER JOB NUMBER
;STILL IN IFN FTMIC
SUBTTL	TYPE--- TYPE A STRING ON BEHALF OF A USER

;	TOPMTY	TYPE A STRING ON BEHALF OF USER

;ADDR:	LINE NO.
;	[ASCIZ/STRING/]

TOPMTY:	PUSHJ	P,SAVE1##	;SAVE AN AC
	LDB	P1,LDPLNO	;LINE NUMBER
	PUSHJ	P,GETWRD##	;GET ADDRESS OF STRING
	  JRST	TOPX3		;ADDRESS CHECK
	HRRI	M,-1(T1)	;AND PUT IT IN M FOR FUTURE GETWD1'S
IFN FTVM,<
	HRROS	T1		;LEFT JUSTIFIED ASCIZ STRING
	PUSHJ	P,CKSTR##	;MAKE SURE ITS IN CORE AND LEGAL
	  JRST	TOPX3		;ADDRESS CHECK
>
TOPMT1:	MOVE	P3,[POINT 7,P2]	;SET UP BYTE POINTER
	PUSHJ	P,GETWD1##	;GET NEXT WORD OF ASCIZ STRING
	MOVE	P2,T1		;AND SAVE IT
TOPMT2:	TLNN	P3,760000	;END OF CURRENT WORD?
	JRST	TOPMT1		;YES - GET NEXT ONE
	ILDB	T3,P3		;GET NEXT CHAR
	JUMPE	T3,CPOPJ1##	;EXIT ON END OF STRING
	PUSHJ	P,PEVEN8	;ADD PARITY
	MOVE	U,P1		;SET LINE NO.
	MOVEM	U,MICLIN	;SET LOCK TO IGNORE CHARS AT INTERRUPT LEVEL
	PUSHJ	P,RECINU	;GO AND TYPE IT
	SETOM	MICLIN		;UNSET LOCK
	JRST	TOPMT2		;AND GO GET NEXT CHAR
;STILL IN IFN FTMIC

SUBTTL	CLEAR/SET--- CLEAR DOWN LDBMIC/SET UP LDBMIC

;	MICCLR - CLEAR DOWN LDBMIC
;ADDR:	LINE NO.

;	MICSET - SET UP LDBMIC
;ADDR:	LINE NO.
;	STATUS
;
;	BOTH GIVE OLD CONTENTS OF LDBMIC IN ADDR+1

TOPMCL:	MOVEI	T1,0		;CLEAR T1
	JRST	TOPMS1		;CLEAR LDBMIC
TOPMST:	PUSHJ	P,GETWRD##	;GET THE ARGUMENT
	  JRST	TOPX3		;ADDRESS CHECK
	PUSH	P,T1
	ANDI	T1,177
	CAMLE	T1,HIGHJB##	;ISOLATE JOB NUMBER
	JRST	[POP P,T1
		 PJRST ECOD2##] ;RETURN ERROR CODE
	POP	P,T1
	TLZ	T1,LDL.TI!LDL.MM;CLEAR UNWANTED BITS
TOPMS1:	EXCH	T1,LDBMIC(U)	;EXCHANGE WITH OLD CONTENTS
	AOS	(P)		;GOOD RETURN
	PJRST	PUTWDU##	;AND GIVE IT BACK TO USER
;STILL IN IFN FTMIC

SUBTTL	GET-- GET THE STATUS FROM THE USERS LDBMIC WORD

;	MICGET - GET STATUS
;ADDR:	LINE
;	RETURN RESULT TO ADDR+1

TOPMGT:	PUSHJ	P,SAVE1##	;SAVE AN AC
	SKIPN	P1,LDBMIC(U)	;IS MIC RUNNING US?
	JRST	TOPMG1		;NO FAIL RETURN
	HRRZ	F,LDBDDB(U)	;SET UP F
	JUMPE	F,TOPMG1	;ZERO MEANS HE LOGGED OUT -LOOSE HIM
	LDB	J,PJOBN		;OTHERWISE - GET HIS JOB NO
	PUSHJ	P,UJBSTX##	;GO GET JBTSTS
	TLZ	P1,LDL.MM!LDL.TI!LDL.TO	;CLEAR VOLATILE BITS
	TLNE	T1,(1B2)	;IN MONITOR MODE?
	TLO	P1,LDLCHK!LDL.MM;YES - SET FLAGS
	TLNE	T1,(1B4)	;READY FOR I/P?
	TLO	P1,LDLCHK!LDL.TI;YES - SET FLAGS
IFN FTMLOG,<
	HRRZ	T1,LDBLOC(U)
	SKIPE	T1
	TLO	P1,LDLCHK!LDL.TO;SET TO FLAG
>	;END OF FTMLOG CONDITIONAL
	SKIPGE	0(U)		;COMMAND WAITING?
	TLZ	P1,LDL.TI	;YES - CLEAR TI BIT
	MOVE	T1,P1		;PUT LDBMIC INTO T1 FOR
	AOS	(P)		;GOOD RETURN
	PJRST	PUTWDU##	;RETURNING TO USER

TOPMG1:	SETZB	T1,LDBMIC(U)	;CLEAR DOWN LDBMIC
	PJRST	PUTWDU##	;AND EXIT
;STILL IN IFN FTMIC
SUBTTL	RESPONSE--- RECORD AN ERROR MESSAGE
;	MICRSP : RECORD ERROR MESSAGE
;ADDR:	LINE NO.
;	ADDRESS OF SPACE TO RETRIEVE RESPONSE

TOPMRS:	SKIPE	T2,LDBMIC(U)	;RUNNING MIC
	TLNN	T2,LDL.ER	;ERROR?
	JRST	TOPX4		;NO
	TLNN	T2,LDL.SY	;MAKE SURE GOT TO INT LEVEL WITH SYNC
	JRST	TOPX4		;NO

	PUSHJ	P,GETWRD##	;GET ADDRESS OF RESPONSE BUFFER
	  JRST	TOPX3		;ADDRESS CHECK
	PUSHJ	P,MICADC
	  JRST	TOPX3		;ADDRESS CHECK OF BUFFER
	PUSHJ	P,SAVE3##	;SAVE WORKING ACS
	MOVSI	P1,(<POINT 7,(R)>)
	HRRI	P1,(T1)
IFN FTKI10!FTKL10,<	;FTKI10 CONDITIONAL
	PUSHJ	P,RLCPTR	;RELOCATE BYTE POINTER
>	;END OF KI10 CONDITIONAL
	MOVEI	P2,<21*5>-1	;MAX SPACE IN BUFFER
	CAMLE	P2,LDBTOC(U)	;GOT THIS MANY?
	MOVE	P2,LDBTOC(U)	;NO - USE LESSER
	JUMPLE	P2,TOPX4	;NO CHARACTERS
	SKIPN	P3,LDBTOT(U)	;GET CHAR ADDRESS OF ERROR LINE
	JRST	TOPX4		;HASN'T GOT ONE?

TOPMR1:	IBP	P3		;GET NEXT CCHAR
	MOVE	T2,P3
	PUSHJ	P,TTGETC
	MOVE	P3,T2		;ADVANCE TO NEXT CHUNK

TOPMR2:	EXCTUU	<IDPB T3,P1>
	JUMPE	T3,TOPMR3	;EXIT HAVING MADE ASCIZ
	SOJG	P2,TOPMR1	;GET NEXT CHAR
	SETZ	T3,		;MAKE ASCIZ
	JRST	TOPMR2

TOPMR3:	MOVSI	T1,LDL.RS!LDL.SY	;CLEAR RESPONSE FLAG
	ANDCAM	T1,LDBMIC(U)
	AOS	(P)		;GOOD RETURN TO THE USER
	JRST	XMTIN0		;START UP TTY - GOOD EXIT
;STILL IN IFN FTMIC
SUBTTL	LOG--- RECORD ALL UUO LEVEL OUTPUT


IFN FTMLOG,<

;	MICLOG: RECORD ALL UUO LEVEL OUTPUT
;ADDR:	LINE NUMBER
;	ADDR LOG BUFFER

TOPMLG:	SKIPE	T2,LDBMIC(U)	;RUNNING MIC?
	TLNN	T2,LDL.LG	;WANT LOG FEATURE?
	JRST	TOPX4

	PUSHJ	P,GETWRD##
	  JRST	TOPX3		;ADDRESS CHECK
	PUSHJ	P,MICADC	;ADDRRESS CHECK ALL OF BUFFER
	  JRST	TOPX3		;ADDRESS CHECK
	AOS	(P)		;SET FOR GOOD RETURN TO THE USER
	PUSHJ	P,SAVE2##	;SAVE WORKING ACS
	MOVSI	P1,440700!R
	HRRI	P1,(T1)
IFN FTKI10!FTKL10,<	;KI10 CONDITIONAL
	PUSHJ	P,RLCPTR	;RELOCATE POINTER
>	;END OF KI10 CONDITIONAL
	MOVEI	P2,<21*5>-1

TOPML1:	HRRZ	T3,LDBLOC(U)	;PICK UP COUNT
	JUMPE	T3,TOPML2
	SOS	T3,LDBLOC(U)	;COUNT DOWN
	MOVE	T2,LDBLOT(U)	;GET TAKER
	IBP	T2		;BUMP THE TAKER
	PUSHJ	P,TTGETC	;GET THAT CHUNK
	  PUSHJ	P,FRECHK	;FREE CHUNK IF REQUIRED
	MOVEM	T2,LDBLOT(U)	;AND RESTORE CHAR ADDR

TOPML2:	EXCTUU	<IDPB T3,P1>
	JUMPE	T3,XMTWAK
	SOJG	P2,TOPML1
	SETZ	T3,
	JRST	TOPML2		;LOOP UNTIL COUNT EXHAUSTED OR END BUFFER
>	;END OF FTMLOG CONDITIONAL
;STILL IN IFN FTMIC


SUBTTL	SUBROUTINES CALLED FROM SCNSER AND OTHER PLACES

IFN FTMLOG,<

MICLGC:	MOVE	T1,LDBMIC(U)	;GET MIC STATUS
	TLNN	T1,LDL.LG	;LOGGING?
	JRST	MICLG1		;NO-MIC HAS GIVEN UP MUST TIDY

	MOVE	T1,LDBTOP(U)	;MOVE TAKER TO PUTTER
	MOVEM	T1,LDBTOT(U)	;SO MIC CAN CATCH UP WITH PUTPUT
	MOVE	T1,LDBTOC(U)	;REMEMBER HOW MANY
	ADDM	T1,LDBLOC(U)	;KEEP TRACK FOR MIC
	JRST	MICLG2
;MIC HAS GONE AWAY MUST TIDY UP LOG BUFFER

MICLG1:	MOVE	T1,LDBLOT(U)	;MOVE PUTTER AND TAKER
	MOVEM	T1,LDBTOT(U)
	MOVEM	T1,LDBTOP(U)	;BACK UP
	SETZM	LDBLOT(U)	;ZAP LOG BUFFER
MICLG2:	SETZM	LDBTOC(U)	;ZAP COUNT
	JRST	ONPOPJ##	;AND EXIT




>	;END OF FTMLOG CONDITIONAL
;STILL IN IFN FTMIC

;SUBROUTINE TO ADDRESS CHECK A USER BUFFER

MICADC:	PUSH	P,M
	PUSH	P,T1
	HRRI	M,(T1)
	PUSHJ	P,GETWRD##
	  JRST	MICAD1
	HRRI	M,21(M)
	PUSHJ	P,GETWRD##
	TRNA
	AOS	-2(P)
MICAD1:	POP	P,T1
	JRST	MPOPJ##
;SUBROUTINE TO SET UP HORIZONTAL POSITION FOR MIC AND TO CHECK FOR
;OPERATOR AND ERROR CHARS IN COLUMN 1

MICPOS:	PUSH	P,T3		;PRESERVE CHAR
	TRZ	T3,200		;MASK OFF PARITY
	PUSHJ	P,SPCHEK	;GET CHARACTERISTICS OF CHAR
	  JRST	MICPS2		;NOT SPECIAL
	TLNN	T1,CHCRET	;IS IT <CR>?
	JRST	MICPS1		;NOT - MUST CHECK OTHERS
	TLO	T2,LDLCL1	;SET COL 1 FLAG IN MICLDB
	MOVEM	T2,LDBMIC(U)
	JRST	CHPOPJ		;AND RETURN

MICPS1:	CAIE	T3,177		;IS IT A RUBOUT
	CAIN	T3,12		;OR LINE-FEED
	JRST	CHPOPJ		;YES - NO CHECKING
MICPS2:	TLZN	T2,LDLCL1	;ARE WE IN COLUMN 1?
	JRST	CHPOPJ		;NO - RETURN
	LDB	T1,LDP.OP	;GET OPERATOR CHAR
	CAMN	T1,T3		;HAVE WE FOUND ONE?
	TLO	T2,LDLCHK!LDL.OP;YES - SET BITS
	LDB	T1,LDP.ER	;GET ERROR CHAR
	CAMN	T1,T3		;ONE OF THOSE?
	TLO	T2,LDLCHK!LDL.ER;YES - SET ITS FLAGS
	MOVEM	T2,LDBMIC(U)	;STORE MIC WORD
	JRST	CHPOPJ		;RESTORE T3, AND RETURN
;STILL IN IFN FTMIC



IFN	FTMLOG,<
; AROUTINE TO FREE THE MIC LOG BUFFER IF REQUIRED

MLOGOF:	SKIPN	LDBLOT(U)	;HAS NOT GOT ONE
	POPJ	P,0
	CONO	PI,PIOFF##	;SNEAKY PEEK
	SKIPE	LDBTOC(U)	;OUTPUT BUFFER IDLE
	JRST	ONPOPJ##	;NO FORGET IT
	JRST	MICLG1		;YES-GO ZAP LOG BUFFER AND TURN ON PI

>	;END OF FTMLOG CONDITIONAL

;ROUTINE TO WAKE MIC UP WHEN CONTROLLED JOB REQUIRES INPUT
MICWAK:	LDB	T1,LDPMJN	;GET MASTER JOB #
	CAMLE	T1,HIGHJB##	;IS JOB # TOO BIG
	  JRST	MICWA1		;YES.. RETURN
	MOVE	T2,JBTSTS##(T1)	;CHECK JOB STATUS
	TLNN	T2,JLOG		;LOGGED IN?
	  JRST	MICWA1		;NO, JUST RETURN
	PUSHJ	P,WAKJOB	;GO WAKE MIC
MICWA1:	MOVE	T1,LDBDCH(U)	;RESTORE C(T1)
	POPJ	P,		;AND RETURN

MICECH:	MOVSI	T1,CHCRET	;CHECK IF <CR> TYPED
	TDNN	T1,-1(P)	;WITH CHARACTER BITS ON STACK
	POPJ	P,		;NO IT WASN'T - RETURN
	MOVSI	T1,LDLCL1	;YES - SET COL 1 BIT
	IORM	T1,LDBMIC(U)	;IN LDBMIC
	POPJ	P,		;AND RETURN
MICRIC:	CONSO	PI,PI.IPA	;AT INTERRUPT LEVEL?
	POPJ	P,		;NO, THEN MIC TYPED IT
	CAIE	T3,1		;IS THE CHAR A ^A
	CAIN	T3,201		;WITH POSSIBLE PARITY?
	JRST	MICRIA		;YES - GO DEAL WITH ^A
	TLO	T1,LDLCHK!LDL.CC;SAY THAT ^C WAS TYPED
	MOVEM	T1,LDBMIC(U)	;PUT IT BACK
	POPJ	P,		;AND RETURN

MICRIA:	TLO	T1,LDLCHK!LDL.CA;SAY ^A
	MOVEM	T1,LDBMIC(U)	;PUT IT AWAY!
	TRC	T3,202		;CONVERT CHAR INTO A ^C
	MOVSI	T1,CHBRK!CHCRE!CHCNC
	IORM	T1,-1(P)	;AND SET UP BITS TO LOOK LIKE ^C
	POPJ	P,

PTYMCK:	CAIN	T3,20
	TLO	T2,LDLCHK!LDL.CP
	CAIN	T3,2
	TLO	T2,LDLCHK!LDL.CB
	MOVEM	T2,LDBMIC(U)
	TLNE	T2,LDL.CP!LDL.CB
	JRST	RICB3
	JRST	PTYPT1

;HERE IF NO CHARACTERS IN OUTPUT BUFFER OF REMOTE LINES
MICRMT:	SKIPE	LDBMIC(U)		;IS THIS LINE RUNNING MIC
	SKIPN	LDBECC(U)		;YES--IS THERE ANYTHING IN HIS ECHO BUFFER
	POPJ	P,0			;NO TO BOTH OR EITHER
	PJRST	XMTECH			;YES TO BOTH
					;GO AND DEAL WITH ECHO OF MIC UUO LEVEL TYPE IN
>	;END IFN FTMIC
	SUBTTL	SUBROUTINES FOR I/O
;SUBROUTINE TO READ A CHARACTER AND KEEP THE BREAK COUNT RIGHT

;IT IS ASSUMED THAT THE CALLER HAS DONE ANY NECESSARY WAITING. THERE
;ARE TWO UNUSUAL CASES: FIRST, IF THERE ARE NO CHARACTERS IN THE
;BUFFER, TYI WILL NON-SKIP RETURN. IF THE CHARACTER READ IS A
;CONTROL C, AND IF THE TELETYPE IS IN USER MODE, NOT SLAVED,NOT
;IN IMAGE INPUT STATE, AND NOT RUNNING UNDER JACCT, THEN TYI CALLS
;ROUTINES TO PUT CONSOLE AT MONITOR LEVEL, AND GOES BACK INTO I/O
;WAIT UNTIL A POSSIBLE CONTINUE COMMAND.
TYICC:	PUSHJ	P,SAVE3##	;P1 IS BYTE POINTER, P2 COUNT
	SETZM	P3		;WAIT OK
	JRST	TYIC1		;DO NOT ZERO NUMBERS
TYIM:	SETZB	P1,P2		;INDICATE NO BUFFER
TYIC1:	TRNE	S,IODERR	;HAS HE GOTTEN A ^C?
	POPJ	P,		;YES, FORGET IT
	PUSHJ	P,TYIEAT	;EAT OLD COMMAND IF STILL THERE
	MOVEI	T1,L2RIRH	;INPUT RACE
	ANDCAM	T1,LDBBY2(U)	; HASN'T HAPPENED YET
	MOVSI	T1,LPLIRS	;SET INPUT RACE SYNC BIT
	IORM	T1,LDBPAG(U)	; IN LDB
	SOSGE	LDBTIC(U)	;COUNT CHARACTERS
	JRST	TYIA		;NONE THERE.
	IBP	LDBTIT(U)	;COUNT THE INPUT POINTER
	MOVE	T2,LDBTIT(U)	;AND RESTORE
	PUSHJ	P,TTGETC	;READ THE CHARACTER
	  PUSHJ P,TYIB		;FREE UP CHUNK, STORE NEW ADDR
	MOVSI	T1,LPLIRS	;SET TO CLEAR IRS BIT
	CONO	PI,PIOFF##	;NO PI'S HERE
	ANDCAM	T1,LDBPAG(U)	;CLEAR BIT
	MOVEI	T1,L2RIRH	;INPUT RACE HAPPENED BIT
	TDNE	T1,LDBBY2(U)	;DID ^U HAPPEN (ANY CLRBFI)
	JRST	TSETI2		;YES--DO REST OF FUNCTION
	CONO	PI,PION##	;ALL PI'S
	PUSH	P,T3		;PRESERVE CHAR.
	SKIPG	LDBTIC(U)	;IS THIS THE LAST CHARACTER IN THE BUFFER
	PUSHJ	P,CHKXON	;YES, GO CHECK IF XON IS NEEDED
	POP	P,T3		;RESTORE CHAR.
	HRRZ	T1,LDBDDB(U)	;GET DDB FOR PIM TEST
	JUMPE	T1,TYIC		;NO DDB, CANT BE PIM
	MOVE 	T1,DEVIOS(T1)	;GET MODE WORD
	TRNE	T1,PIMMOD	;PIM?
	JRST	CPOPJ1##	;YES, DONE HERE
TYIC:	MOVE	T1,LDBBKU(U)	;GET CONTROL-U POINTER
	CAMN	T1,T2		;JUST CROSS THE LINE?
	SETZM	LDBBKU(U)	;YES. CLEAR CONTROL-U POINTER.
	PUSHJ	P,SPCHEK	;SEE WHAT KIND OF CHARACTER IT IS
	  JRST CPOPJ1##		;NOTHING SPECIAL
	JUMPE	T3,TYIM		;IF NULL, SKIP IT.
	TLNE	T1,CHALT	;SOME ALT CHR?
	TLNE	U,LDLFCS	;FULL CHR SET?
	CAIA			;NO COVERSION
	PUSHJ	P,RIALTO	;CONVERT TO ESC
	TLNE	T1,CHBRK	;BREAK CHARACTER?
	SOS	LDBBKC(U)	;YES. COUNT IT DOWN.
	JUMPE	F,CPOPJ1##	;GOOD RETURN IF NO DDB
	TLNN	T1,CHCNC	;CONTROL C CHARACTER?
	JRST	CPOPJ1##	;NO JUST RETURN TO CALLER
	MOVE	T1,DEVMOD(F)	;GET SOME BITS
	TLNN	T1,TTYATC	;IS TTY CONTROLLING A JOB?
	JRST	CPOPJ1##	;NO, RETURN CHAR
	HLL	U,LDBDCH(U)	;GET LINE STATE FLAGS
	PUSHJ	P,CNCCHK	;SEE IF IT IS A CONTROL C
	  JFCL			;YES, STORE
	  JRST CPOPJ1##		;YES, BUT IT SHOULD BE STORED.
	MOVE	S,[XWD	IOW,IOACT]
	IORB	S,DEVIOS(F)
	SKIPN	P3		;WAIT?
	PUSHJ	P,TIWAIT	;NOW WAIT IN CASE TYPE CONTINUE
	JUMPE	P1,TYIM		;DONE IF NO PTR
	MOVE	T2,P2		;SETUP FOR LOOP
	MOVE	T3,P1		;SETUP FOR LOOP
TYICLP:	HRRZ	T1,T3		;COPY ADDRESS
	IBP	T3		;INCREMENT
	PUSHJ	P,UADRCK##	;MAKE SURE IT IS GOOD
	SOJG	T2,TYICLP	;LOOP OVER BUFFER
	JRST	TYIM		;AND LOOP AROUND AGAIN.
TYIS:	PUSHJ	P,SAVE3##	;REALLY SHOULD DO IT
	SETOM	P3		;FLAG DON'T WAIT IF NOTHING THERE
	JRST	TYIM
TYI:	PUSHJ	P,SAVE3##
	SETZM	P3		;FLAG WAIT IF GET ^C-CONT
	JRST	TYIM
TYIA:	CONO	PI,PIOFF##	;FREEZE TYPEIN COUNT
	ANDCAM	T1,LDBPAG(U)	;CLEAR INPUT RACE SYNC BIT
	AOSLE	LDBTIC(U)	;RESTORE CHAR COUNT
	JRST	ONPOPJ		;RESTORE PI AND NON SKIP RETURN
	SETZM	LDBBKU(U)	;CLEAR BREAK POSITION
	SETZM	LDBBKC(U)	;AND COUNT, SINCE EMPTY
	JRST	ONPOPJ		;RESTORE PI AND NON SKIP RETURN

TYIB:	MOVEM	T2,LDBTIT(U)	;STORE THE NEW T2
	HLL	U,LDBDCH(U)	;GET LINE DESCRIPTOR BITS
	PJRST	FRECHK		;T1 STILL AS TTGETC LEFT IT!
				;RETURN CHUNK, THEN BACK INTO TYI
;SUBROUTINE TO DISCARD A COMMAND FROM INPUT BUFFER IF LDLECS STILL ON

TYIEAT:	HLL	U,LDBDCH(U)	;GET BITS FOR DEVICE
	TLNN	U,LDLECS	;STILL WANT COMMAND EATEN?
	POPJ	P,0		;NO. RETURN.
TYIL:	SKIPG	LDBTIC(U)	;STILL CHARACTERS LEFT?
	JRST	TYID		;NO. QUIT.
	MOVEI	T1,L2RIRH	;INPUT RACE HAPPENED BIT
	ANDCAM	T1,LDBBY2(U)	;INDICATE NO PROBLEM YET
	MOVSI	T1,LPLIRS
	IORM	T1,LDBPAG(U)
	SOS	LDBTIC(U)	;COUNT ONE DOWN.
	IBP	LDBTIT(U)	;COUNT UP TO CHARACTER
	MOVE	T2,LDBTIT(U)	;AND INTO T2
	PUSHJ	P,TTGETC	;GET THE CHARACTER
	  PUSHJ P,TYIB		;MOVE UP CA.
	MOVSI	T1,LPLIRS	;SET TO CLEAR INPUT RACE SYNC
	CONO	PI,PIOFF##
	ANDCAM	T1,LDBPAG(U)
	MOVEI	T1,L2RIRH	;INPUT RACE HAPPENED BIT
	TDNE	T1,LDBBY2(U)	;WAS TSETBI CALLED AT INTERRUPT LEVEL?
	JRST	TSETI2		;YES, FINISH CLEARING LINE
	CONO	PI,PION##
	MOVE	T1,LDBBKU(U)	;GET BREAK POSITION
	CAIE	T1,0		;NONE AT ALL, OR
	CAMN	T1,T2		;HERE?
	SETZM	LDBBKU(U)	;YES. CLEAR CONTROL U POINTERS
	PUSHJ	P,SPCHEK	;GET CHARACTER DESCRIPTORS
	  JRST TYIL		;ORDINARY
	TLNE	T1,CHBRK	;BREAK CHAR?
	SOSA	LDBBKC(U)	;YES. COUNT IT AND QUIT
	JUMPN	T3,TYIL		;NO. LOOP IF STILL SOME TO GO
TYID:	MOVSI	T1,LDLECS	;NOW CLEAR THE BIT
	ANDCAM	T1,LDBDCH(U)	;IN THE DEVICE WORD
	POPJ	P,0

CCTYI::	SKIPE	T2,TTCMCA	;ADDRESS THERE TO USE?
	CAMN	T2,LDBTIP(U)	;YES. CAUGHT UP TO PUTTER?
	JRST	CCTYI1		;NO CHARACTERS TO GET
	IBP	T2		;YES. GET NEXT CHARACTER
	PUSHJ	P,TTGETC	;GET CHAR
	JFCL			;IGNORE NON-SKIP RETURN
	EXCH	T2,TTCMCA	;STORE UPDATED POINTER. T2 NOW
				; HAS OLD POINTER
	JUMPN	T2,CPOPJ##	;DONE IF OLD POINTER
	SETZM	TTCMCA		;STOPCM CALLED BETWEEN SKIPE AT
				; CCTYI AND EXCH. PRESERVE 0
CCTYI1:	MOVEI	T3,12		;RETURN BREAK CHAR
	POPJ	P,0		;SINCE NONE THERE
;SUBROUTINE TO SEE IF A CONTROL C SHOULD BE ACTED ON OR STORED.
;NON-SKIP MEANS STORE IT.
;SKIP MEANS JACCT SET
;DOUBLE SKIP MEANS .HALT DONE.

CNCCHK:	TLNE	U,LDLSLV+LDLIMI	;SHOULD ^C BE RETURNED?
	POPJ	P,0		;YES.
	AOS	(P)		;ADVANCE RETURN
	PUSH	P,T1		;MAYBE NOT. SAVE T1.
IFN FTLOGIN,<
	HRRZ	F,LDBDDB(U)	;GET LINE'S JOB
	JUMPE	F,CNCCK1	;IF NO DDB ATTACHED, ASSUME SHOULD DO ^C
	LDB	T1,PJOBN##	; ..
	MOVE	T1,JBTSTS##(T1)	;GET JOB STATUS WORD
	TDNE	T1,[XWD JACCT,JS.DEP]	;IS ^C LEGAL? (PRIVELDGED PROG OR
				; DAEMON ERROR PAUSE)
	JRST	TPOPJ##		;NO. GIVE IT TO CUSP
>
	PUSHJ	P,CNCMOD
CNCCK1:	PUSHJ	P,TTHALT	;FORCE CONTROL C
	JRST	TPOPJ1##	;RESTORE T1, SKIP RETURN

CLRIIQ:	HRRZ	F,LDBDDB(U)	;GET DDB, IF ANY.
	JUMPE	F,CLRIM1	;CLEAR BIT IF NO DDB
	MOVE	S,DEVIOS(F)	;GET STATUS WORD.
	TRNE	S,I		;IF STILL IMAGE, DON'T CLEAR BIT
	POPJ	P,0		;IMAGE. JUST RETURN
CLRIMI:	HRRZ	F,LDBDDB(U)	;GET ATTACHED JOB, IF ANY
	JUMPE	F,CLRIM1	;IF NONE, SKIP PART OF THIS
	MOVSI	S,FRCEND	;ALSO CLEAR FORCED END OF FILE BIT
	ANDCAB	S,DEVIOS(F)
CLRIM1:	MOVSI	T1,LDLIMI	;NO. CLEAR IMAGE BIT AND TIME
	DPB	T1,LDPTIM	; ..
	ANDCAM	T1,LDBDCH(U)	; ..
	POPJ	P,0		; AND RETURN
;ROUTINE TO MAKE THIS TTY VISIBLE TO COMMAND DECODER, IF AT COM LEVEL
;CALL WITH LINE SET UP

COMSET::PUSHJ	P,COMQ		;IS LINE AT COMMAND LEVEL?
	  POPJ P,0		;NO. JUST RETURN
	MOVSI	T1,LDBCMR	;OK. SET REQUEST BIT
COMST1:	CONO	PI,PIOFF##	;CAN'T LOOK AT 0(U) HERE
	SKIPL	0(U)		;WAS COMMAND REQUEST ON?
	AOS	COMCNT##	;NO. WAKE COMCON
	IORM	T1,0(U)		;SET THE BITS IN 0(U)
	CONO	PI,PION##	;FALL INTO CMDSET

;SUBROUTINE TO SET/CLEAR BIT IN COMMAND MAP

CMDSET::SKIPA	T1,[IORM T3,CMDMAP##(T2)]
CMDCLR::MOVE	T1,[ANDCAM T3,CMDMAP##(T2)]
	PUSH	P,T3		;SAVE T3
	SETZM	T3
	LDB	T2,LDPLNO	;GET LINE #
	LSHC	T2,-5		;SET TO WORD ADDRESS
	ROT	T3,5		;BIT WITHIN WORD
	MOVE	T3,BITTBL##(T3)	;GET THE BIT
	XCT	T1		;SET OR CLEAR
	PJRST	T3POPJ##	;RETURN

;ROUTINE TO PUT TTY INTO MONITOR COMMAND MODE. DON'T CALL THIS
;ROUTINE IF TTY IS A SLAVE, UNLESS YOU WANT SLAVE BIT CLEARED TOO.
;CALL WITH LINE SET.


CNCMOD::MOVSI	T1,LDLOSU+LDLIMI+LDLNEC+LDLDLR+LDLBKA+LDLECS
	ANDCAM	T1,LDBDCH(U)	;CLEAR ALL THESE BITS
	PUSH	P,F		;MAKE SURE THAT PIMMOD
	MOVEI	T1,PIMMOD	;IS NOT SET IN THE
	HRRZ	F,LDBDDB(U)	;DDB
	SKIPE	F		;
	ANDCAM	T1,DEVIOS(F)	;
	POP	P,F		;
	MOVSI	T1,LDLCOM	;AND SET THIS ONE
	IORB	T1,LDBDCH(U)	; ..
	TRNE	T1,LDRPTY	;IS THIS LINE PTY-DRIVEN?
	PUSHJ	P,PTMNMD##	;YES. TELL PTYSER ABOUT IT.
	PJRST	NOCTRO		;BE SURE REMOTES ARE INFORMED
;SUBROUTINE TO SKIP IF TTY IS AT COMMAND LEVEL AND NOT SLAVED


COMQ:	SKIPGE	0(U)		;LDBCMR ON?
	JRST	CPOPJ1##	;YES. ASSUME COMMAND LEVEL
	HLL	U,LDBDCH(U)	;GET LINE STATE
	TLNE	U,LDLCOM	;AT TOP LEVEL?
	TLNE	U,LDLSLV	;AND NOT SLAVED?
	POPJ	P,0		;NO. JUST RETURN
	HRRZ	F,LDBDDB(U)	;IS LINE ATTACHED TO A JOB?
	JUMPE	F,CPOPJ1##	;JUMP IF NOT
	PUSH	P,T1		;SAVE AN AC
	MOVE	T1,DEVMOD(F)	;GET DEVICE ASSIGN BITS
	TLNE	T1,TTYATC	;ATTACHED TO JOB?
	JRST	TPOPJ1##	;YES. SKIP RETURN
	LDB	T1,PJOBN##	;IS JOB NUMBER ZERO?
	JUMPE	T1,TPOPJ1##	;IF SO,SKIP RETURN
	JRST	TPOPJ##		;IF NOT ATTACHED, CAN'T DO COMMAND
TTFCOM::				;FORCED COMMAND TABLE
PHASE 0
TTFCXC:!SIXBIT /.HALT/			;CONTROL C
IFN FTMODM,<
TTFCXD::!SIXBIT /.BYE/			;DATAPHONE DISCONNECT
TTFCXH::!SIXBIT /.HELLO/			;DATAPHONE CONNECT
>
TTFCXR::!SIXBIT /.RESTA/			;SYSTEM RESTART
TTFCXK:!SIXBIT /KJOB/			;FORCED KILL JOB
IFN FTCCLX,<
TTFCXI::!SIXBIT /INITIA/			;INITIALIZING CUSP CALL
>
IFN FTJCON,<
TTFCXJ::!SIXBIT /.FCONT/			;FORCED CONTINUE
>
IFN FTDAEM!FTSET,<
TTFCXU::!SIXBIT /.DUMP/			;CCL RUN OF DUMP
>
TTFCXT:!SIXBIT	/.TYPE/			;RETYPE LINE
IFN FTWATCH,<
TTFCXW:!SIXBIT	/USESTA/		;1 LINE SYSTAT
>
IFN FTNET,<
TTFCXL::!SIXBIT	/.NETLD/		;AUTO DOWN LINE LOAD OF DAS80'S SERIES.
>
TTFCXS:!SIXBIT	/HALT/			;STOP JOB REGARDLESS OF ^C TRAPPING


IFN FTPATT,<
TTFCXX:!SIXBIT /CTEST/			;FOR PATCHING
>
DEPHASE
TTFCML==:.-TTFCOM
MTTFCM==:-TTFCML				;MINUS LENGTH OF FORCED COMMAND TABLE
IFG TTFCML -20,<PRINTX ?TOO MANY FORCED COMMANDS!>
SUBTTL COMMAND LEVEL ROUTINES
;ROUTINE TO SET UP TO READ A COMMAND FROM ANY REQUESTING LINE
;CALL FROM CLOCK LEVEL:
;	PUSHJ P,TTYCOM
;	  NONE FOUND
;	FOUND ONE	;F, U SET UP. J HAS JOB # IF ANY,
;			;T2 HAS TYPEIN T2

TTYCOM::MOVE	T1,LINSAV##	;LAST COMMAND LINE +1
	CAIL	T1,TTPLEN##	;GREATER THAN HIGHEST LINE #?
TTYCM0:	SETZB	T1,LINSAV##	;YES, START AT LINE 0
	LSH	T1,-5		;SHIFT TO RIGHT PLACE
	HRLI	T1,TTCMPT##(T1)	;FORM AN AOBJN POINTER
TTYCM1:	SKIPE	T2,CMDMAP##(T1)	;GET A WORD OF BITS
TTYCM2:	JFFO	T2,TTYCM3	;FIND FIRST ONE BIT
	AOBJN	T1,TTYCM1	;LOOP TO TOP OF TABLE
	SKIPE	LINSAV##	;LOOKED AT THE ENTIRE TABLE?
	JRST	TTYCM0		;NO, STATY AT THE BEGINNING
	POPJ	P,0		;GIVE FAIL RETURN
TTYCM3:	MOVEI	T4,(T1)		;COPY WORD #
	LSH	T4,5		;SHIFT TO RIGHT PLACE
	ADDI	T4,(T3)		;ADD IN BIT NUMBER
	CAML	T4,LINSAV##	;SKIP IF LINE IS TOO SMALL
	JRST	TTYCM4		;ELSE FIX # AND PROCESS
	TDZ	T2,BITTBL##(T3)	;CLEAR BIT
	JRST	TTYCM2		;AND TRY NEXT
TTYCM4:	MOVEM	T4,LINSAV##	;SAVE THIS LINE #
	AOS	(P)		;GIVE SKIP RETURN
TTCM4A:	HRRZ	U,LINTAB##(T4)	;PICK UP LDB POINTER
TRESCN::HRRZ	F,LDBDDB(U)	;GET DDB ADDRESS IF ANY
	JUMPE	F,TRESC1	;JUMP IF NO DDB
	MOVE	T3,DEVMOD(F)
	TLNN	T3,TTYATC
TRESC1:	TDZA	J,J
	LDB	J,PJOBN##
	MOVE	T3,0(U)		;KILL OR COMMAND?
	TLNN	T3,LDBCMF	;FORCED COMMAND?
	TLNN	T3,LDBCMK	;NO, FORCED KJOB?
	JRST	.+2		;NO.
	JRST	TTYCM5		;FORCED KJOB!

;DO FORCED COMMANDS 1ST, THEN FORCED KJOBS, THEN TYPED-IN COMMANDS
	HRRM	U,CMDLIN	;MUST BE SAVED WHEN TTCMCA IS USED
	MOVE	T2,LDBTIT(U)	;GET TYPEIN CHAR ADR
	MOVEM	T2,TTCMCA	;AND SAVE IT FOR CCTYI
	HRRI	T3,40		;PRIME THE TYI ROUTINE
	TLNE	T3,LDBCMF	;IS IT A FORCED COMMAND?
	MOVEI	T3,12		;YES. PREVENT EXTRA ARGUMENTS
	HRRZM	T3,TTCMCH	;JUST FOR SURE.
	PUSHJ	P,FNDPDB##	;ADDRESS OF PDB
	  JFCL
	POPJ	P,0

TTYCM5:	MOVEI	T1,TTFCXC	;FORCE HALT 1ST SINCE IF TTKJOB IS CALLED DURING A COMMAND
	SKIPGE	JBTSTS##(J)	;MUST BE A JOB.  IS IT RUNING
	JRST	TTYCM6		;NO.  JUST KILL IT
	MOVSI	T1,LDBCMK	;CLEAR KILL
	ANDCAM	T1,0(U)		;FLAG
	MOVEI	T1,TTFCXK
TTYCM6:	PUSHJ	P,TTFORC	;FORCE COMMAND
;DON'T CALL CMDCLR, OR DELAYED COMMAND WILL NEVER BE SEEN AGAIN
	MOVE	T4,LINSAV##	;FIND LINE
	JRST	TTCM4A		;AGAIN


TTKJOB::PUSHJ	P,CNCMOD	;CONSOLE TO COMMAND LEVEL
	MOVSI	T1,LDBCMK	;SET KILL REQUEST
	IORM	T1,0(U)		;IN LDB
	HRRZ	F,LDBDDB(U)
	SKIPE	J,F
	LDB	J,PJOBN##
	AOS	COMCNT##	;MAKE COMCON SEE IT
	SKIPL	JBTSTS##(J)	;SKIP IF JOB IS IN RUN STATE
				; THIS DEPENDS UPON:
				; 1. RUN BIT BEING SIGN OF JBTSTS
				; 2. J=0 IF NO JOB
				; 3. JBTSTS+0 = 0
	PJRST	CMDSET

TTHALT:				;THIS ROUTINE DOES NOT SET TTY TO
				;  COMMAND LEVEL BECAUSE JACCT
				;  PROGRAMS MAY STILL NEED TO TYPEOUT
				;  AND THAT WOULD BLOCK THEM IN TO
	MOVEI	T1,TTFCXC	;HALT COMMAND INDEX
	PJRST	TTFORC		;FORCE THE ^C

;ROUTINES TO ATTACH TTY TO A JOB

;1) CALL WHEN COMMAND DECODER DECIDES TO CREATE A JOB DUE TO
;A COMMAND BEING TYPED IN. THE LDB WILL ALREADY HAVE BEEN
;SET UP, BUT IT IS NOT YET LINKED TO A DDB

;CALL:	MOVE LINE,ADDRESS OF LDB
;	MOVE J,NEW JOB NUMBER
;	PUSHJ P,TTYATI
;	  ERROR RETURN	;ALREADY SOMEONE THERE (DDB POINTS AT HIM), OR
			;NO MORE FREE DDB'S (DDB CONTAINS 0)
;	OK RETURN	;DDB, DDBLDB, AND LDBDDB SET UP

;2) CALL FROM COMMAND DECODER ON AN ATTACH COMMAND.

;CALL:	MOVE LINE,ADDRESS OF LDB
;	MOVE J,JOB TO ATTACH TO
;	PUSHJ P,TTYATT
;	  ERROR RETURN	;SOMEONE ALREADY ATTACHED (DDB POINTS TO HIM) OR
			;NO SUCH DDB (DDB=0)
;	OK RETURN	;DDB, LDBDDB, NEW DDBLDB SET UP. OLD DDBLDB CLEARED


IFN FTATTACH,<


TTYATT::PUSH	P,U
	PUSHJ	P,TTYISA	;SEE IF DDB FOR TARGET JOB CAN BE ATTACHED
	  JRST LPOPJ##		;NO, CAN'T DO IT
IFE FTPI,<
	JUMPE	T1,TTYAT2	;JUMP IF NO JOB IS ATTACHED TO LINE
>
IFN FTPI,<
	JUMPE	T1,TTYAT1	;JUMP IF DETACHED BUT SIGNAL DETACHING
>
	MOVEM	T1,(P)		;SAVE LDB OF TARGET JOB

	LDB	T1,LDPLNO	;OPERATOR DOING PREEMPTIVE ATTACH
				; GET OPERATOR'S LINE NUMBER
	EXCH	U,0(P)		;GET LDB OF OBJECT JOB
	LDB	T3,LDPLNO	;GET ITS LINE NUMBER TOO
	CAIE	T3,0(T1)	;ARE THEY THE SAME? (OPR ATTACHING
				; TO HIMSELF?)
	PUSHJ	P,PTYDET	;NO. DETACH OBJECT JOB, NOW IN LINE.
				; MUST RESPECT F
				;F NOW POINTS TO JOB BEING
				;PICKED UP BY TTY IN 0(P)
	JRST	TTYAT2		;GO DO THE ATTACH
IFN FTPI,<
TTYAT1:	PUSHJ	P,SIGDET	;SIGNAL DETACHING
	JRST	TTYAT2		;GO DO THE ATTACH
>
>
TTYATI::PUSH	P,U		;SAVE LINE DATA BLOCK ADDRESS
	PUSHJ	P,TTYSRC	;SEE IF THERE'S ALREADY A DDB. SHOULDNT BE.
	  PUSHJ P,DDBSRC	;OK. GET A NEW DDB.
	    JRST LPOPJ##	;ERROR. EITHER TTYSRC WON OR DDBSRC LOST
TTYAT2:	MOVE	U,0(P)		;GET LDB ADDR FROM STACK
	PUSH	P,F		;AND SAVE NEW DDB ADDRESS
	HRRZ	F,LDBDDB(U)	;GET OLD DDB IF ANY
	SKIPE	F		;ANY THERE?
	PUSHJ	P,TTYDT1	;YES. DETACH FROM IT BUT DON'T SET MONITOR CODE
	SKIPN	U		;SKIP IF LDB WAS FOUND
	PUSHJ	P,TTYKLQ	;NO, KILL OFF DDB
	MOVE	F,0(P)
IFN FTMODM,<
	MOVE	U,-1(P)		;GET LDB ADDRESS, FOR DS POINTER
	MOVSI	T1,LDBCMF
	TDNE	T1,(U)
	JRST	TTYAT3
	MOVE	T1,LDBDCH(U)	;LOOK AT DATA SET BIT
	TRNN	T1,LDRDSD	;IF NOT A DATA SET
	JRST	TTYAT3		;NO DSCTAB ENTRY
	LDB	U,LDPDSC	;GET DATASET TABLE INDEX
	MOVEI	T1,0		;CLEAR TIME FIELD OF DATASET ENTRY
	DPB	T1,DSTMPL	; ..
>
TTYAT3:	MOVE	U,-1(P)		;ATTACH LDB FROM STACK TO DDB
	MOVE	T1,[XWD TTYATC,ASSCON]	;SET ATTACHED AND ASSIGNED BITS
	IORM	T1,DEVMOD(F)	;IN THE DEV DATA BLOCK
	HRRM	F,LDBDDB(U)	;SET LINK FROM DDB TO LDB
	HRRM	U,DDBLDB(F)	;AND LINK FROM LDB TO DDB
	PUSHJ	P,SETDVL##	;AND JOB NUMBER IN DDB
	HRRZM	F,TTYTAB##(J)	;STORE CONTROLLING DDB BY JOB NUMBER
	PUSHJ	P,SCNNAM	;SET UP PHYSICAL LINE NAME AND PUNIT
IFN FTNET,<
	PUSHJ	P,SETSTA	;SET CORRECT STATION NUMBER
>

;CONTINUED ON NEXT PAGE
;THIS CODE MAKES SURE BATCH BIT STAYS CORRECT
IFN FTATTA&FTTLIM&FTPTYUUO,<
	PUSHJ	P,CTLJBU##	;GET PTY LDB IF ANY
	MOVSI	T1,DVDIBP	;GET BATCH PTY BIT
	MOVE	T2,JBTLIM##(J)	;GET JBTLIM
	TDNN	T1,DEVCHR(F)	;IS IT A BATCH PTY?
	JRST	TTYAT4		;NO
	TLON	T2,(JB.LBT)	;YES, MAKE IT A BATCH JOB
	AOS	BATNUM		;AND COUNT UP BATNUM
	MOVEM	T2,JBTLIM##(J)	;RESTORE JBTLIM
TTYAT4:
>
;END FTATTA&FTTLIM&FTPTYUUO
IFN FTPI,<
	LDB	T2,LDPLNO
	ADDI	T2,.UXTRM
	SIGNAL	C$DATT
	  EXCTUU <MOVEM T2,IBKISW##(M)>
>	;END FTPI
	POP	P,F
	JRST	UPOPJ1##	;SKIP RETURN TO COMCON.
;SUBROUTINE TO LOOK FOR POSSIBLE LINE ALREADY ATTACHED TO TARGET JOB
;ARGS	U=LINE ATTACH WAS TYPED OR
;	J=JOB NUMBER OF TARGET JOB
;VALUES	T1=ADDR OF LDB ATTACHED TO TARGET JOB OR 0 IF NONE
;NON-SKIP RETURN IF NO DDB FOR TARGET JOB OR DDB FOUND BUT MANY NOT ATTACH
;SKIP RETURN IF DDB FOUND AND MAY ATTACH TO IT

TTYISA::PUSHJ	P,SAVE2##	;SAVE P1 AND P2
	PUSH	P,U		;SAVE LINE BLOCK ADR OF GUY TYPING COMMAND
	PUSHJ	P,TTYSRC	;FIND THE DDB CONTROLLING THAT JOB
	  JRST LPOPJ##		;THERE ISN'T ANY. COMCON HAS GOOFED?
	SETZ	T1,
	JUMPE	U,LPOPJ1##	;IF NONE ATTACHED, GO ATTACH.
	EXCH	U,0(P)		;SOMEONE IS ATTACHED. ONLY THE OPERATOR
				;MAY USURP THE EXISTING CONNECTION
IFN FTLOGIN<
	PUSH	P,F		;SAVE NEW DDB
	HRRZ	F,LDBDDB(U)	;DDB OF OLD USER
	SKIPE	T1,F		;IF F=0, MAKE T1 0, SINCE PJOBN IS MEANINGLESS IF F=0
	LDB	T1,PJOBN##	;HIS JOB NUMBER
	LDB	P1,LDPLNO	;GET TTY LINE # IN P1
	SUBI	P1,PTYOFS##	;SUBTRACT OFFSET OF PTY0
	JUMPL	P1,TTYIS1	;SEE IF A PTY
	CAIGE	P1,PTYN##	; ..
	SKIPA	F,PTYTAB##(P1)	;IT IS A PTY, GET DDB
TTYIS1:	TDZA	P1,P1		;NOT A PTY, USE JOB 0
	LDB	P1,PJOBN##	;GET JOB OWNING PTY
	POP	P,F		;RESTORE F
	MOVE	P2,FSFPPN##	;GET [1,2]
	CAME	P2,JBTPPN##(T1)	;IS JOB THAT TYPED COMMAND [1,2]?
	CAMN	P2,JBTPPN##(P1)	;OR COMMAND TYPED BY SON OF OPR?
	JRST	TPOPJ1##	;YES, ATTACH IS LEGAL
>
	HRRZ	T1,OPRLDB##
	CAIE	T1,0(U)		;IS THIS THE OPR?
	JRST	TPOPJ##		;NO. DISCARD OBJECT JOB'S LDB FROM
	JRST	TPOPJ1##	;STACK, AND GIVE ERROR RETURN TO COMCON
				;WITH DDB POINTING AT GUY ALREADY ATTACHED
;ROUTINE TO DETACH TTY FROM A JOB.
;CALL:	MOVE F,ADDRESS OF TTY DDB TO BE DETACHED
;	PUSHJ P,TTYDET
;	ALWAYS RETURN HERE

;CALLED FROM TTYATT AND COMCON (DETACH COMMAND)
;KILLS DDB IF NOT ATTACHED, ASSIGNED, OR INITED
;CLEARS LINKS TO DDB
;RESPECTS DDB


TTYDET::
IFN FTPI,<
	PUSHJ	P,SIGDET
>
	HRRZ	U,DDBLDB(F)	;GET LDB ADDRESS
	LDB	T1,PJOBN##	;GET JOB NUMBER
	MOVE	T1,JBTSTS##(T1)	;IS HE LOGGED IN?
	TLNE	T1,JLOG		; ..
	JRST	PTYDET		;YES, LOGGED IN
	LDB	T2,PJOBN##	;GET JOB NUM
	MOVE	T1,[SIXBIT/LOGOUT/]  ;DONT CLEAR
	CAMN	T1,JBTNAM##(T2)	;FOR LOGOUT SINCE USER COULD
	JRST	TTKJOB		;THEN GET OUT OVER QUOTA
	MOVSI	T1,JACCT	;CLEAR JACCT
	ANDCAM	T1,JBTSTS##(T2)	;IN STATUS
	JRST	TTKJOB		;GO KILL HIM
PTYDET::PUSHJ	P,TTYDT1	;DISCONNECT DDB FROM LDB
	JUMPE	U,TTYKLQ	;IF NO LDB KILL OFF DDB
	PUSHJ	P,CNCMOD	;MAKE SURE LDB AT TOP LEVEL

;ROUTINE TO KILL DDB IF IT IS AN IDLE TTY DDB


TTYKLQ::PUSH	P,T1		;RESPECT T1
	MOVE	T1,DEVMOD(F)	;GET DEVICE MODE AND USE BITS
	TLNE	T1,DVTTY	;IS IT A TTY DDB?
	TDNE	T1,[XWD TTYATC,ASSCON+ASSPRG]	;YES, ANY REASON TO KEEP DDB?
	JRST	TPOPJ##		;YES.
	PUSHJ	P,TTYKIL	;NO. GO KILL THE DDB
	JRST	TPOPJ##		;AND RESTORE T1 ON RETURN
;SUBROUTINE TO DISCONNECT A TTY FROM A JOB WITHOUT SETTING TTY TO MONITOR LEVEL
;THIS IS SO ATTACH UUO WILL LEAVE TTY AT ITS ORIGINAL LEVEL (MONITOR OR USER MODE)

TTYDT1:	HRRZ	U,DDBLDB(F)	;GET LINKED LINE ADDRESS
	HLLZS	DDBLDB(F)	;DISCONNECT LDB FROM DDB
	JUMPE	U,TTYDTX	;IF NO LDB, KILL OFF DDB
	HLLZS	LDBDDB(U)	;DISCONNECT DDB FROM LDB
	HRRZS	DEVNAM(F)	;CLEAR LH OF DEVNAM TO NOT CONFUSE DEVCHR, ETC.
				;KEEP RH FOR SYSTAT, ETC.
IFN FTDAEM!FTTLIM,<
	LDB	T1,PJOBN##	;SEE IF THIS JOB WAITING FOR DAEMON
>
IFN FTTLIM,<
	MOVSI	T2,(JB.LBT)	;BATCH BIT
	TDNE	T2,JBTLIM##(T1)	;IF WAS BATCH JOB
	SOS	BATNUM##	;DECR. BATCH JOB COUNT
	ANDCAM	T2,JBTLIM##(T1)	;CLEAR BIT SO OPERATOR CAN DETACH
>
IFN FTDAEM,<
	MOVE	T1,JBTSTS##(T1)	;GET JOB STATUS WORD
	TRNN	T1,JDC		;DCORE COMMAND WAITING?
>
	PUSHJ	P,TYIEAT	;NO. CLEAR ANY PENDING COMMAND
	MOVE	T1,LDBDCH(U)	;GET LINE CHARACTERISTICS
	TRNE	T1,LDRPTY	;A PTY LINE?
	PUSHJ	P,PTMNMD##	;YES. WAKE CONTROLLER
TTYDTX:	POPJ	P,

IFN FTPI,<
SIGDET:	SIGNAL	C$DATTY
	  EXCTUU	<SETOM IBKISW##(M)>
	POPJ	P,
>
;ROUTINE TO RELEASE A TTY DDB. CALL WITH DDB SET UP.


TTYREL::MOVE	T1,[XWD IOW,IOACT]	;CLEAR OUT S
	ANDM	T1,DEVIOS(F)	; IN CORE
	SKIPE	DINITF##	;IN SYSINI?
	JRST	TTYRL2		;YES--SKIP THIS
	HRRZ	T1,USRHCU##	;HIGHEST CHANNEL IN USE

TTYRL1:	HRRZ	T2,USRJDA##(T1)	;ADDRESS OF AN INITED DDB
	CAIE	T1,(P1)		;CHANNEL BEING RELEASED?
	CAIE	T2,(F)		;NO, SAME DDB OPENS ON ANOTHER CHANNEL
	SOJGE	T1,TTYRL1	;NO
	JUMPGE	T1,TTYRS1	;JUMP IF OPEN ON ANOTHER CHANNEL
IFN FT2741&FTCAFE <
	HRRZ	U,DDBLDB(F)	;GET LINE BLOCK ADR
	JUMPE	U,TTYRL2
	MOVSI	T1,LILAPL	;BIT FOR APL MODE
	ANDCAM	T1,LDBISR(U)	;CLEAR APL MODE
>;END OF IFN FT2741&FTCAFE
TTYRL2:	MOVE	T1,[XWD TTYATC,ASSCON]	;IS TTY ATTACHED OR ASSIGNED?
	TDNE	T1,DEVMOD(F)	; ..
	JRST	TTYRS1		;YES. KEEP DDB AROUND. RETURN.
;	JRST TTYKIL			;NO. GO DISCARD DDB.
;ROUTINE TO CLEAR A TTY F AND MAKE IT AVAILABLE TO THE POOL

;CALL:	MOVE F,ADDRESS OF DEVICE DATA BLOCK KNOWN TO BE THROUGH USE.
;	PUSHJ P,TTYKIL
;	ALWAYS RETURN HERE
;RESPECTS F & S, CLOBBERS T1


TTYKIL::SETZM	DEVNAM(F)	;CLEAR PHYSICAL NAME
	SETZM	DEVLOG(F)	;CLEAR LOGICAL NAME
	MOVSI	T1,IOFST	;INITIAL STATE OF S WORD
	MOVEM	T1,DEVIOS(F)	;PLACE IN CORE STATUS WORD
	PUSHJ	P,CLRDVL##	;NO JOB OWNS IT ANY MORE.
	PUSH	P,U
	HRRZ	U,DDBLDB(F)	;GET LINK TO LINE DATA BLOCK
	JUMPE	U,TTYKL1	;BYPASS IF NO LINK.
	PUSHJ	P,TTYSTC	;PUT LINE AT COMMAND LEVEL
	PUSHJ	P,TTYCPT	;CLEAR PAPER TAPE BITS
	MOVSI	T1,LPLCLR	;CLEAR PAGE BITS
	ANDCAM	T1,LDBPAG(U)	;SO XON AND XOFF ARE ECHOED PROPERLY
	HLLZS	LDBDDB(U)	;REMOVE LINK TO DEAD DDB
	PUSHJ	P,CLRIM1	;MAKE SURE NOT IN IMAGE MODE
	PUSH	P,S		;IN CASE SOME CALLER SOMEWHERE CARES
	MOVEI	S,0		;CLEAR ALL THOSE BITS IN LDBDCH
	PUSHJ	P,UUOLDB	;CLEAR OUT LDB
	POP	P,S		;THIS IS REALLY SUPERCAUTION
TTYKL1:	HLLZS	DDBLDB(F)	;REMOVE LINK FROM DDB TO LINE DATA BLOCK
	MOVE	T1,[XWD TTYUSE+TTYATC,ASSCON+ASSPRG]
	ANDCAB	T1,DEVMOD(F)	;LAST CLEAR THESE, MAKING DDB AVAILABLE
	JRST	UPOPJ##		;AND RETURN TO CALLER.
;SUBROUTINE CALLED ON RESET FROM UUOCON


TTYRES::MOVEI	T1,JS.NTO
	TDNN	T1,JBTSTS##(J)
	JRST	TTYRS0
	ANDCAM	T1,JBTSTS##(J)
	MOVEI	F,SCNDDB
TTYRSA:	LDB	T1,PJOBN##
	CAIE	T1,(J)
	JRST	TTYRSB
	SETZB	T1,DEVSTS(F)
	DPB	T1,BYTCNT
TTYRSB:	HLRZ	F,DEVSER(F)
	MOVE	T1,DEVMOD(F)
	TLNE	T1,DVTTY
	JRST	TTYRSA
TTYRS0:	HRRZ	F,TTYTAB##(J)	;GET CONTROLLING DDB ADDRESS
	JUMPE	F,CPOPJ##	;REALLY HAS TO BE ONE
TTYRS1:	MOVE	S,[XWD IOSBKA,DLRSUP+FCS+D] ;GET BITS
				; THE FOLLOWING CHECK FOR NOT LOGGED IN,
				; RUNNING "LOGIN" IS TO AVOID BREAKING
				; ANCIENT "FEATURE" OF NOECHO GETTING SET
				; BY LOGIN COMMAND
	MOVE	T1,JBTSTS##(J)	;GET THIS STATUS
	MOVE	T2,JBTPRG##(J)	; AND THE PROGRAM
	TLNN	T1,JLOG		;IS HE NOT LOGGED IN?
	CAME	T2,[SIXBIT /LOGIN/] ; AND RUNNING LOGIN
	IORI	S,NOECHO	;NOT BOTH, WE CAN CLEAR NOECHO

	ANDCAB	S,DEVIOS(F)	;CLEAR THESE BITS ON RESET
	HRRZ	U,DDBLDB(F)	;LINK TO LDB
	JUMPE	U,CPOPJ##	;SKIP IT IF DETACHED
	MOVEI	T1,0		;CLEAR THE AUTO
	DPB	T1,LDPACR	;CRLF COUNTER
	PUSHJ	P,CLRIM1	;CLEAR IMAGE MODE
	JRST	UUOLDB		;AND MAKE LDB AGREE
COMTYI::PUSH	P,T2		;SAVE AC FOR OUTSIDE WORLD
	SKIPN	T3,TTCMCH	;IS ANYTHING THERE FROM BEFORE?
	MOVEI	T3,12		;NO. ASSUME END OF LINE
	PUSHJ	P,SPCHEK	;YES. WAS IT A BREAK?
	  JFCL
	TLNN	T1,CHBRK	; ..
COMTI1:	PUSHJ	P,@COMTIA	;NO. GET ANOTHER CHARACTER (CCTYI OR ONCE)
	ANDI	T3,177		;COMCON DOESNT WANT PARITY
	PUSHJ	P,SPCHEK	;CONVERT TO CONSISTENT BREAKS
	  JFCL				;ORDINARY CHARACTER
	TLNE	T1,CHCRET	;CARRIAGE RETURN?
	JRST	COMTI1		;YES. GO GET LINEFEED INSTEAD
	TLNE	T1,CHBRK	;BREAK?
	MOVEI	T3,12		;YES--MAKE INTO LINE FEED
	TLNE	T1,CHCNC	;IS THIS A CONTROL-C?
	MOVEI	T3,3		;YES--CONTROL-C IS STRONGER THAN LF
	MOVEM	T3,TTCMCH	;STORE THIS CHARACTER
COMTIX:	PJRST	T2POPJ##	;RESTORE AC T2 AND RETURN

;PRESERVES T2 & T3
COMTYO::PUSH	P,T2		;SAVE AC
	PUSH	P,T3
	ANDI	T3,177		;SAVE PUSHJ TO PEVEN8, DO IT HERE
	SKIPL	CHTABL(T3)	;IS CHAR ALREADY EVEN PARITY?
	TRO	T3,200		;NO, MAKE IT SO
	PUSHJ	P,@COMTOA	;CALL CCTYO, CTYWAT, OR ONCE ROUTINE
				; (CTYWAT DOES NOT USE INTERRUPT SYSTEM
				; PRINTS ERROR INFO ON CTY ON MEM PARITY ERROR
				; JUST BEFORE SYSTEM HALTS)
	POP	P,T3
	PJRST	T2POPJ##	;RESTORE T2 AND RETURN.

;SUBROUTINE TO SEND 1 CHAR, SENDING CONTROL CHARS AS ^X
;OTHERWISE, SAME AS COMTYO

USEARO::PUSHJ	P,SPCHEK	;SPECIAL CHAR?
	  JRST	COMTYO		;NO, FORGET IT
	TLNN	T1,CHUAE		;ECHO AS ^X?
	  JRST	COMTYO		;NO, GO ECHO NORMALLY
	PUSH	P,T3		;SAVE THE CHAR
	MOVEI	T3,336		;GET AN ARROW
	PUSHJ	P,COMTYO	;SEND IT
	POP	P,T3			;RESTORE CHAR
	TRC	T3,300		;CONVERT TO LETTER
	JRST	COMTYO		;AND GO TYPE IT

;ROUTINE TO SWITCH TTY TO USER PROGRAM LEVEL AND START USER RUNNING


TTYUSW::TDZA	S,S		;DON'T CLEAR WAIT BITS
TTYUSR::MOVE	S,[XWD IOW,IOACT]	;CLEAR WAIT BITS
	HRRZ	F,LDBDDB(U)	;GET ATTACHED DDB IF ANY
	JUMPE	F,TTYUS1	;JUMP IF NOT ATTACHED
	ANDCAB	S,DEVIOS(F)	; ..
	PUSHJ	P,UUOLDB	;MAKE LINE AND DEVIOS AGREE
TTYUS1:	MOVE	T1,LDBDCH(U)	;GET DEVICE BITS
	TRNE	T1,LDRPTY	;IS THIS A PTY?
	PUSHJ	P,PTMNMZ##	;YES. TELL CONTROLLER
	MOVSI	T1,LDLCOM	;PUT TTY IN USER MODE
	ANDCAM	T1,LDBDCH(U)	;MAY BE DETACHED, BUT WILL WAIT
					; AT UUO LEVEL IF NEEDED
	PJRST	SETRUN##	;SET USER'S RUN BIT AND RETURN

;HERE AT COMPLETION OF A COMMAND

TTYCMR::PUSH	P,T1		;SAVE PREVIOUS LDPCMX
	TRNN	F,-1		;ANY JOB?
	PUSHJ	P,TTYCPT	;NO. CLEAR PAPER-TAPE BITS
	AOS	T1,LINSAV##
	CAIL	T1,TTPLEN##
	SETZM	LINSAV##
	HLL	T2,0(U)		;GET COMMAND REQUEST BITS
	POP	P,T1		;COMMAND JUST FINISHED
	LDB	T3,LDPCMX	;CURRENT
	CAME	T1,T3		;CHANGED?
	TLNN	T2,LDBCMF	;FORCED
	SKIPA			;NO CHANGE OR NOT FORCED
	POPJ	P,		;NEW FORCED-DO IT
	MOVSI	T1,LDLECS	;SET EAT-COMMAND-SYNC BIT
	TLNN	T2,LDBCMF	;(UNLESS FORCED COMMAND)
	IORM	T1,LDBDCH(U)	;IN LINE DATA BLOCK
	MOVSI	T1,LDBCMR+LDBCMF	;CLEAR COMMAND REQUEST BITS
	ANDCAB	T1,0(U)		;IN BASE WORD OF LDB
	MOVE	T1,LDBDCH(U)	;GET THE LINE CHARACTERISTICS
	TLNN	T1,LDLBKA+LDLIMI ;ARE WE BREAKING ON ALL CHARACTERS
				; OR IN IMAGE MODE?
	JRST	TTCMR1		;NO, CONTINUE ON
	SKIPLE	LDBTIC(U)	;YES, DO WE HAVE ANY CHARACTERS
				; IN THE INPUT BUFFER?
	PUSHJ	P,RCVWAK	;YES, WAKE THE JOB
				;NO...
TTCMR1::MOVE	T1,0(U)		;GET THE LINE'S LDBDDB AND CONTINUE
	TLNE	T1,LDBCMK	;FORCED KJOB PENDING?
IFN	FTMIC,<			;IF MIC
	PJRST	MICWAK		;YES - DO NOT CLEAR COMMAND BIT
	PUSHJ	P,CMDCLR	;CLEAR COMMAND BIT
	PJRST	MICWAK		;WAKE MIC UP IF NEC & RETURN TO COMCON
>			;END OF IF MIC
IFE	FTMIC,<			;IF NOT MIC
	POPJ	P,0		;YES--DO NOT CLEAR COMMAND BIT
	PJRST	CMDCLR		;CLEAR COMMAND BIT
>			;END OF IF NOT MIC

TTYSTC::HLL	U,LDBDCH(U)	;SEE IF THIS LINE IS SLAVED
	MOVSI	T1,LDLCOM	;PREPARE TO SET BIT
	TLNN	U,LDLSLV	;SLAVED?
IFN	FTMIC,<			;IF MIC
	IORM	T1,LDBDCH(U)	;NO. SET COMMAND BIT
	PUSHJ	P,MICWAK	;WAKE MIC IF NECESSARY
>			;END OF IF MIC
IFE	FTMIC,<			;IF NOT MIC
	IORB	T1,LDBDCH(U)	;NO, SET COMMAND BIT
>			;END OF IF NOT MIC BIT
	TRNE	T1,LDRPTY	;PTY-DRIVEN LINE?
	PUSHJ	P,PTMNMD##	;YES. TELL CONTROLLER
TTYSTR::MOVE	T1,LDBDCH(U)	;GET DEVICE BITS
	TRNE	T1,LDRPTY	;IS IT A PTY?
	PUSHJ	P,PTYPE##	;YES. WAKE THE PTY CONTROLLER
	PUSHJ	P,COMQ		;AT COMMAND LEVEL?
	  PJRST NOCTRO			;NO. JUST CLEAR ^O BIT
	PUSHJ	P,TYIEAT	;YES. CLEAR THE COMMAND IN CASE MORE
	SKIPLE	LDBBKC(U)	;ANY MORE COMMANDS?
	PUSHJ	P,COMSET	;MAYBE. SET BIT IF AT COM LEVEL
	PJRST	NOCTRO		;CLEAR OSU AND RETURN

SUBTTL SUBROUTINES FOR COMCON OR UUO LEVEL

;COMMON UUO LEVEL ROUTINES
;TYO7W IS USED TO TAKE A 7-BIT CHARACTER IN T3, ADD THE
; CORRECT PARITY, GO INTO I/O WAIT IF JOB DETACHED OR IF THE LINE'S
; OUTPUT BUFFER IS RATHER BIG, THEN PLACE THE CHARACTER IN OUTPUT
; STREAM, AND START OUTPUT IF NEEDED.
;TYO9W IS SAME, BUT ASSUMES PARITY AND NINTH BIT ARE AS DESIRED.
;TYO CHOOSES ONE OF THE ABOVE, DEPENDING ON MODE IN S

;CALL WITH DDB SET UP, CHARACTER IN CH.
;IF CALLED AT TYO, S MUST BE SET UP ALSO


TYO:	TRNE	S,I!PIMMOD	;IMAGE MODE USE OWN PARITY
	JRST	TYO9W
TYO7W:	ANDI	T3,177
	SKIPL	CHTABL(T3)	;EVEN ALREADY?
	TRO	T3,200		;NO, MAKE IT SO
TYO9W:	MOVE	S,DEVIOS(F)	;GET DEVIOS
	TRNE	S,IODERR	;WAS ^C TYPED?
	POPJ	P,		;YES, EXIT
	PUSHJ	P,CKATTO	;WAIT FOR ATTACH, SET LINE.
	MOVE	T1,TTFREN##	;MAKE SURE THERE'S SOME CHARACTER SPACE LEFT
	CAIGE	T1,3		;LEAVE 3 CHUNKS FOR SAFETY
	JRST	TYONFC		;NO, GO INTO I/O WAIT UNTIL SOME FREE
	MOVE	T1,LDBTOC(U)	;GET OUTPUT STREAM LENGTH
	CAML	T1,TIWRNN	;IS HE OVER QUOTA?
	JRST	TYOOBF		;YES. WAIT FOR IT TO EMPTY.
IFN FTMLOG,<
	SKIPN	LDBLOT(U)	;IS HE LOGGING
	JRST	TYO9M		;NO
	ADD	T1,LDBLOT(U)
	HRRZS	T1
	CAIL	T1,^D100
	JRST	MICLGX		;GO WAKE UP MIC

TYO9M:
>	;END OF FTMLOG CONDITIONAL
	HLL	U,LDBDCH(U)	;CHECK IF STILL WANT TO OUTPUT
	SKIPL	LDBOFL(U)
	TLNE	U,LDLOSU	; ..
	POPJ	P,0		;NO. JUST RETURN DUE TO ^O
TYO9A:	MOVEI	T1,L2RORH	;OUTPUT RACE HAPPENED BIT
	ANDCAM	T1,LDBBY2(U)	;CLEAR IN LDB
	MOVSI	T1,LDLORS	;SET SYNC BIT FOR TSETBO TO SEE
	IORM	T1,LDBDCH(U)	;IN LINE DATA BLOCK
	CONO	PI,SCNOFF##
	PUSHJ	P,TTPTOC	;UPDATE BYTE POINTER, STORE CHARACTER
	AOS	LDBTOC(U)	;COUNT USED OUTPUT LENGTH
	CONO	PI,SCNON##
IFN FTMIC,<			;IF MIC
	SKIPE	T2,LDBMIC(U)	;MIC RUNNING FOR US?
	PUSHJ	P,MICPOS	;YES SET UP AND CHECK POSITION
>	;END OF IF MIC
	MOVSI	T1,LDLORS	;SET TO CLEAR SYNC BIT
	CONO	PI,PIOFF##	;WITH PI OFF
	ANDCAM	T1,LDBDCH(U)	; IN THE LDB
	MOVEI	T1,L2RORH	;SET TO CHECK FOR OUTPUT CLEAR
	TDNE	T1,LDBBY2(U)	;DID TSETBO GET CALLED?
	JRST	TSETO2		;YES. GO FINISH IT UP.
	CONO	PI,PION##	;PI BACK ON
TOPOKE::MOVE	T1,LDBDCH(U)	;SEE IF THIS IS A PTY-DRIVEN LINE
	TRNE	T1,LDRPTY	;OR REMOTE STATION TTY
	POPJ	P,0		;YES. DON'T START ANY HARDWARE
	MOVSI	T1,LDLOIP	;SEE IF NEED TO START OUTPUT
	CONO	PI,PIOFF##	;DONT GET CONFUSED BY FINISHING LAST T3 HERE
	TDNE	T1,LDBDCH(U)	;IS OUTPUT GOING?
	JRST	TYO9W1		;YES. DONT DO A DATAO.
	MOVSI	T1,LPLPOK	;ALREADY FORCING
	TDNE	T1,LDBPAG(U)	;AT SOME LEVEL?
	JRST	TYO9W1		;YES. LET HIM DO IT
	IORM	T1,LDBPAG(U)	;WE ARE NOW!
	CONO	PI,PION##	;ALLOW INTERRUPTS
	PUSH	P,F		;SAVE F INCASE ATTACH HAS OCCURRED
				; SINCE XMT INT ROUTINE WILL LOAD FROM LDB
	PUSHJ	P,XMTIN0	;GO START TTY OUTPUT
	POP	P,F		;RESTORE DEVICE DATA BLOCK
	MOVSI	T1,LPLPOK	;ALL COUNTS UPDATED
	ANDCAM	T1,LDBPAG(U)	;LET NEXT FORCE WIN
	POPJ	P,0		;RETURN FROM TYO ROUTINE

TYO9W1:
	CONO	PI,PION##	;REENABLE INTERRUPT SYSTEM
	POPJ	P,0		;RETURN FROM TYO8W

TYOVRG:	PUSHJ	P,GETCHK	;GET A CHUNK FROM FREELIST
	CONO	PI,PIOFF##
	MOVEM	T2,LDBTOP(U)	;PUT IN TYPEOUT STRING ADDRESSES
	MOVEM	T2,LDBTOT(U)
	JRST	ONPOPJ##	;REENABLE INTERRUPTS AND RETURN


;HERE IF NO FREE CHUNKS
TYONFC:	PUSH	P,16		;ACS USED BY SETSLP
	PUSH	P,17
	PUSH	P,T3
	PUSH	P,U
	MOVEI	T1,5		;SLEEP FOR 5 SEC.
	PUSHJ	P,SLEEP##	; ..
	POP	P,U		;RESTORE AC(S
	HRRZ	F,LDBDDB(U)
	POP	P,T3
	POP	P,17
	POP	P,16
	JRST	TYO9W


IFN FTMLOG,<
MICLGX:	PUSHJ	P,MICWAK

> 	;END OF FTMLOG CONDITIONAL
;HERE IF OUTPUT BUFFER FULL
TYOOBF:	PUSHJ	P,TOWAT1
	JRST	TYO9W

;SUBROUTINE TO SETUP AND RELOCATE A BYTE POINTER TO A USER'S BUFFER
;CALLING SEQUENCE:
;	MOVE	S,DEVIOS(F)
;	HRRZ	P1,RELATIVE ADDRESS OF BUFFER
;	PUSHJ	P,SRLPTR
;RETURN HERE - P1=USER VIRTUAL ADDRESS FOR XCT PAGED IF KI10
;OR EXEC VIRTUAL ADDRESS IF KA10

SRLPTR:	ADD	P1,[XWD 010700+R,1] ;ASSUME POINTER AND KA10 RELOCATION
	TRNE	S,I		;CHECK FOR IMAGE MODE
	HRLI	P1,004400+R	;36 BIT POINTER AND KA10 RELOCATION
IFN FTKI10!FTKL10,<
RLCPTR::			;RELOCATION IS DONE IF KA10
	TLZ	P1,R		;KI10 - CHANGE TO USER VIRTUAL ADDRESS
>
	POPJ	P,		;RETURN
;SUBROUTINE FOR COMMAND LEVEL OUTPUT


CCTYO::	JUMPE	U,CPOPJ##	;U MUST BE SET UP
	MOVE	T1,LDBTOC(U)	;GET COUNT
	SUBI	T1,^D200
	SKIPLE	T2,TTFREN##	;SPACE IN STRINGS?
	CAML	T1,TIWRNN	;YES. SPACE IN THIS GUY'S AREA?
	POPJ	P,0		;NO. QUIT.
	CAIL	T2,3
	SKIPN	TTFREE##	;IS THERE A FREE LIST?
	POPJ	P,		;NO--PUNT
	ANDI	T3,177		;FORCE EVEN PARITY SINCE CCTYO NEVER DOES IMAGE
	SKIPL	CHTABL(T3)	; AND TRMOP CALLERS FORGOT TO ADD PARITY
	TRO	T3,200
	JRST	TYO9A		;YES. GO TYPE IT.

	$LOW			;MUST BE IN THE LOW SEGMENT FOR ONCE-ONLY
;SUBROUTINE TO PRINT ON CTY IN EMERGENCY OR ONCE-ONLY
; WHEN INTERRUPT SYSTEM CANNOT BE USED OR TRUSTED
;CALL:	MOVEI	T1,ADR OF ASCIZ MESSAGE
;	PUSHJ	P,CTYTYP
;	ALWAYS	RETURN


CTYTYP::HRLI	T1,440700	;FORM BYTE POINTER
CTYTYL:	ILDB	T3,T1		;GET NEXT CHARACTER
	JUMPE	T3,LCPOPJ	;END OF MESSAGE?
				;(CPOPJ IS IN HISEG, SO DONT USE IT)
	PUSHJ	P,CTYWAT	;NO, PRINT IT ON CTY AND WAIT
	JRST	CTYTYL		;GO GET NEXT CHAR.

;SUBROUTINE FOR ERROR MESSAGE TO CTY DURING PARITY ERROR STOP
;CALL:	MOVEI	T3,CHARACTER
;	PUSHJ	P,CTYWAT
;	RETURN AFTER CHARACTER HAS BEEN TYPED
;NOTE:  DOES NOT USE INTERRUPT SYSTEM SO MESSAGE WILL GET OUT BEFORE HALT
;THIS SUB CALLED BY COMTYO WHEN COMTOA PATCHED


CTYWAT::PUSH	P,T1
	PUSHJ	P,CTYPAR	;COMPUTE PARITY WITH LOSEG ROUTINE

IFN FTKA10!FTKI10,<
	CONSZ	CTY,20		;WAIT FOR CTY TO BE IDLE
	JRST	.-1		;NO, SO NOT GARBLE ON GOING OUTPUT
	DATAO	CTY,T3		;YES, SEND OUT CHAR
	PUSHJ	P,OPRFIL
	CONSZ	CTY,20		;WAIT FOR CTY TO BE IDLE
	JRST	.-1		;NO, OTHERWISE HALT OR RESET WILL CLOBBER LAST CHAR
	JRST	OPRFI2		;YES, OK TO RETURN
> ;END FTKA10!FTKI10


IFN FTKL10,<
IFN FTMS,<
	SKPCPU	(0)	;IF THIS IS CPU1,
	JRST	CTYWT1	;OUTPUT TO CPU1 (T1 STILL ON STACK)
>;END IFN FTMS
	PUSHJ	P,SPCTYO##	;SEND CHAR OVER
	PUSHJ	P,SPCWTO##	;WAIT FOR OUTPUT TO COMPLETE
	  JRST	.-1
	JRST	OPRFI2		;RESTORE T1
				;AND RETURN

;STILL IN FTKL10 CONDITIONAL
IFN FTMS&FTKL10,<
	;SYMBOLS FROM DTEPRM.MAC FOR SLAVE USE ONLY
	DT.MTO==10B27		;OUTPUT CHARACTER SECONDARY PROTOCOL FUNCTION
	TO11DB==1B22		;RING 11 DOORBELL
	DTE==200

CTYWT1:	MOVEI	T3,DT.MTO(T3)
	MOVEM	T3,DT1CMD##	;INTO CPU1 AREA
	CONO	DTE,TO11DB
	ANDI	T3,377		;JUST CHAR AGAIN
	SKIPN	DT1MTD##
	JRST	.-1
	SETZM	DT1MTD##	;WAIT UNTIL DONE, THEN CLEAR
	JRST	OPRFI2		;RESTORE T1 NOW
				;RETURN

	PURGE TO11DB,DT.MTO	;MAKE SURE THESE ARE NOT USED AGAIN
	PURGE	DTE
>;END IFN FTMS
>;END IFN FTKL10


;ROUTINE RESIDING IN LOSEG TO COMPUTE PARITY.
; USED ONLY FOR EMERGENCY CTY OUTPUT ROUTINES.
; USES T1

CTYPAR:	MOVEI	T1,(T3)
	LSH	T1,-4		;FOLD INTO LOW 4 BITS
	XORI	T1,(T3)
	TRCE	T1,14		;CHECK BITS 32 AND 33
	TRNN	T1,14
	TRC	T3,200		;IF EVEN PARITY COMPLEMENT RESULTS
	TRCE	T1,3
	TRNN	T1,3
	TRC	T3,200		;IF EVEN PARITY COMPLEMENT RESULTS
	POPJ	P,		;RETURN
	$HIGH			;BACK TO THE HIGH SEGMENT
;SUBROUTINE TO CLEAR PAPER TAPE INPUT BITS, RETURNS LDBDCH IN T1
TTYCPT:: MOVSI	T1,L2LTAP	;CLEAR TTY TAPE COMMAND BIT
	ANDCAM	T1,LDBBY2(U)	;IN BY2
	MOVSI	T1,LDLXON	;CLEAR XON IN EFFECT
	ANDCAB	T1,LDBDCH(U)	;AND RETURN NEW STATUS
	POPJ	P,		;RETURN

	$LOW			;MUST BE IN THE LOW SEG FOR EMERGENCIES

;SUBROUTINE TO ADD A DELAY FOR SLOW CTY'S
;CALL WITH:
;	MOVEI	T3,CHAR
;	PUSHJ	P,OPRFIL
;USED ONLY WITH PI SYSTEM OFF
OPRFIL::ANDI	T3,177		;ONLY CHAR BITS
	PUSH	P,T1		;SAVE T1
	MOVEI	T1,0		;ASSUME NO FILLERS
	CAIN	T3,12		;LF GETS
	MOVEI	T1,CTYDLF##	;8 TICKS
	CAIN	T3,15		;CR GETS
	MOVEI	T1,CTYDCR##	;18 TICKS
	JUMPE	T1,OPRFI2	;RETURN
	ADDM	T1,TIME##	;UPDATE TIME
IFN FTKA10!FTKI10,<
OPRFI1:	CONSO	APR,XP.CLK	;DID CLOCK TICK?
	JRST	OPRFI1		;NO -- WAIT FOR IT
	CONO	APR,XP.CCF	;CLEAR CLOCK FLAG
>;END IFN FTKA10!FTKI10

IFN FTKL10,<
OPRFI1:	CONSO	TIM,TI.ITD	;CLOCK "TICK" ?
	JRST	OPRFI1		;NOT YET
	CONO	TIM,@ONCKLT##	;YES, CLEAR AND SET FOR ANOTHER "TICK"
>;END IFN FTKL10
	SOJG	T1,OPRFI1	;LOOP FOR WHOLE TIME
OPRFI2:	POP	P,T1		;--
LCPOPJ:	POPJ	P,		;LOCAL CPOPJ FOR USE WHEN HISEG ISN'T MAPPED
	$HIGH			;BACK TO THE HIGH SEGMENT
;ROUTINE TO FIND A FREE TTY DEVICE DATA BLOCK

;CALL FROM CLOCK LEVEL TO DO AN ATTACH ON A NEW JOB, OR
;FROM UUO LEVEL ON AN INIT OF A NEW LINE.

;CALL:	NO ARGUMENTS
;	PUSHJ P,DDBSRC
;	  ERROR RETURN		;NONE AVAILABLE. F=0. T1 CLOBBERED
;	OK RETURN		;ADDRESS IN F, TTYUSE SET IN DEVMOD
;				;RESPECTS J,U,T2.
;				;IF YOU DECIDE NOT TO USE DDB, YOU BETTER
;				;FREE IT UP AGAIN.


DDBSRC:	PUSHJ	P,DDBSR0	;TRY TO GET A DDB
	  SKIPA			;LOST -- TRY AGAIN
	PJRST	CPOPJ1##	;WE WON
DDBSR0:
	MOVEI	F,TTYLST	;START OF THE TTY DDB'S
DDBSRL:	MOVSI	T1,TTYUSE	;FLAG THAT A DDB ISN'T FREE
	CONO	PI,PIOFF##	;MAKE SURE NO CONFLICT HERE
	TDNN	T1,DEVMOD(F)	;IS THIS DDB FREE?
	JRST	DDBSR1		;YES. GO GRAB IT.
	CONO	PI,PION##	;NO. REENABLE PI SYSTEM
	PUSHJ	P,TTYKLQ	;KILL OFF IF IDLE
	HLRZ	F,DEVSER(F)	;LINK DOWN THE DDB CHAIN
	MOVE	T1,DEVMOD(F)	;MAKE SURE STILL A TTY DDB
	TLNE	T1,DVTTY	;IS IT?
	JUMPN	F,DDBSRL	;YES. (UNLESS END OF CHAIN)
	MOVEI	F,0		;NO MORE TTY DDB'S. WE LOSE.
	POPJ	P,0		;RETURN NON-SKIP, WITH 0 IN DDB

DDBSR1:	IORM	T1,DEVMOD(F)	;SET BIT SO WE HAVE THE DDB
	CONO	PI,PION##	;NOW PI'S CAN HAPPEN AGAIN
	PUSHJ	P,CLRDVL##	;CLEAR JOB NO. IN CASE OF JUNK
	MOVE	T1,[XWD TTYATC,ASSCON+ASSPRG]	;LIKEWISE MODE BITS
	ANDCAM	T1,DEVMOD(F)	; ..
	SETZM	DEVLOG(F)	;AND LOGICAL NAME
	MOVSI	T1,IOFST	;AND INITIAL S WORD
	MOVEM	T1,DEVIOS(F)	;WHICH SHOULD LEAVE IT PRETTY CLEAN
	JRST	CPOPJ1##	;SKIP RETURN. WE HAVE A DDB.

;ROUTINE TO FIND A TTY DDB WHICH IS ATTACHED TO, I.E.
;CONTROLLING, A PARTICULAR JOB NUMBER.

;CALLED AT COMMAND LEVEL BY ATTACH COMMAND, AND AT UUO LEVEL
;BY REFERENCES TO DEVICE "TTY" OR TTCALLS, ETC.

;CALL:	MOVE J,JOB NUMBER DESIRED
;	PUSHJ P,TTYSRC
;	  ERROR RETURN.	;NOT FOUND. AC'S U,F,S NOT GUARANTEED
;	NORMAL RETURN	;U, S AND F SET UP. NOTE THAT THIS DOES
;			;!NOT! IMPLY THAT ANYONE IS ATTACHED. THAT IS,
;			; U MAY CONTAIN A ZERO

;			;CLOBBERS T1



TTYSRC::JUMPLE	J,CPOPJ##	;NOBODY CONTROLS JOB ZERO. YOU ARE CONFUSED.

	HRRZ	F,TTYTAB##(J)	;GET CONTROLLING TTY DDB ADDRESS
	JUMPE	F,CPOPJ##	;RETURN IF NONE
	MOVE	T1,DEVMOD(F)	;GET DEVICE BITS FROM DDB
	TLNN	T1,TTYATC	;IS THIS THE CONTROLLING TTY?
	POPJ	P,0		;NO. IT WAS A SLAVE OR SOMETHING.
	HRRZ	U,DDBLDB(F)	;YES. GET THE LDB LINK (MAY BE 0)
	MOVE	S,DEVIOS(F)	;AND I/O STATUS WORD
	JRST	CPOPJ1##	;GIVE SUCCESS RETURN.
;ROUTINE CALLED WHEN DEVSRC CAN'T FIND DEVICE XXX (IN T1), AND
; IT WANTS TO SEE IF IT IS A PHYSICAL TTY. GETDDB CHECKS NAME,
; AND IF IT SHOULD BE A TTY, LOOKS FOR ITS DDB, OR MAKES ONE.

;CALL:	MOVE J,JOBNUMBER
;	MOVE T1,SIXBIT DEVICE NAME, ALLEGEDLY A PHYSICAL TTY NAME
;	PUSHJ P,GETDDB
;	  ERROR RETURN, NOT A TTY OR THERE ARE NO DDB'S AVAILABLE.
;	OK RETURN. IT IS A TTY, AND F AND U ARE NOW SET TO IT.
;RESPECTS T1 ON THE OK RETURN ONLY

;CALLED FROM DEVSRC, SO MAY BE AT UUO OR CLOCK LEVEL


GETDDB::PUSHJ	P,TTYPHY	;LOOK FOR THIS PHYSICAL NAME
	  POPJ	P,0		;IT ISNT A TTY
	JUMPN	F,GETDB5	;IS THERE A DDB ALREADY?
				;IF SO, SOMEONE HAS CALLED GETDDB WHO
				; COULD HAVE CALLED DEVSRC.
	PUSHJ	P,DDBSRC	;NO. NEED A NEW DDB. TRY TO GET ONE.
	  POPJ	P,0		;NONE AVAILABLE. FAIL RETURN
	HRRM	F,LDBDDB(U)	;SUCCESS. SET LINKS TO AND FROM DDB
	HRRM	U,DDBLDB(F)	; AND LINE DATA BLOCK.
	PUSHJ	P,SCNNAM	;FILL IN REAL NAME AND PUNIT
IFN FTNET,<
	PUSHJ	P,SETSTA	;PUT STA # IN DDB
>
GETDB5:	MOVE	T1,DEVNAM(F)	;RESTORE REAL NAME TO T1
	JRST	CPOPJ1##	;AND GIVE SUCCESSFUL RETURN FROM GETDDB

IFN FTTALK!FT5UUO,<
;SUBROUTINE TO PUT PHYSICAL NAME INTO T2 FOR U WHOSE LDB IS IN U
;EVEN THOUGH THERE MAY BE NOTHING IN F OR LDBDDB


TTYNAM::PUSH	P,[SIXBIT /CTY/] ;SEE IF CTY
	LDB	T1,LDPLNO	;GET LINE NUMBER
	CAIN	T1,TCONLN##	; ..
	JRST	T2POPJ##	;YES.
	MOVSI	T3,(SIXBIT /TTY/) ;NO. CHANGE TO TTY
	MOVEM	T3,0(P)		;ON STACK
	MOVEI	T3,0(P)		;PREPARE ARG FOR SCNNMR
	HRLI	T3,220600	;POINT 6,0,17
	PUSHJ	P,SCNNMR	;AND CALL SAME ROUTINE AS SCNNAM DOES
	PJRST	T2POPJ##	;PUT ANSWER IN T2
				;AND RETURN FROM TTYNAM
>	;END CONDITIONAL ON FTTALK
;SUBROUTINE TO FIND LDB FOR A PHYSICAL NAME, IF ITS A TTY
;AND LOAD F WITH LINKED DATA BLOCK, IF ANY, BUT DONT MAKE ONE IF NONE YET
;SKIP RETURN IF ITS A TTY


TTYPHX:	PUSHJ	P,TSTOPR##	;SEE IF OPR AND FUDGE T1
	PUSHJ	P,SAVE2##
	PUSH	P,T1		;SAVE NAME
	MOVEI	P1,TCONLN##	;TRY CTY FIRST. GET ITS LINE NUMBER
	CAMN	T1,[SIXBIT /CTY/] ;IS CTY WANTED?
	JRST	TTYPH1		;YES. GO USE TCONLN
	HLLZ	P1,T1		;GET FIRST THREE CHARACTERS
	CAMN	P1,[SIXBIT /TTY/] ;ARE THEY TTY?
	TRNN	T1,770000	;AND ALSO IS FOURTH CHAR NON-BLANK?
	PJRST	TPOPJ##		;NO. NOT A LEGAL NAME.
	MOVE	P2,[POINT 6,0(P),17] ;POINTER TO READ CHARS
	MOVEI	P1,0		;INITIALIZE LINE TO 0
TTYPH4:	ILDB	T1,P2		;GET A SIXBIT CHARACTER FROM NAME
	JUMPE	T1,TTYPH2	;JUMP IF END OF NAME.
	TRC	T1,"0"-40	;CONVERT SIXBIT TO BINARY
	CAILE	T1,7		;IS IT AN OCTAL DIGIT?
	JRST	TPOPJ##		;NO. BAD CHAR IN NAME
	ASH	P1,3		;MULTIPLY BY 8
	ADDI	P1,0(T1)	;ADD IN THIS DIGIT
	TLNE	P2,770000	;CHECK FOR MORE DIGITS
	JRST	TTYPH4		;LOOP FOR MORE DIGITS
TTYPH2:
	CAMLE	P1,P3		;IS IT A LEGAL HARDWARE LINE #?
	JRST	TPOPJ##		;NO. TOO BAD.
TTYPH1:	HRRZ	U,LINTAB##(P1)	;GET LINE DATA BLOCK ADDRESS
	HRRZ	F,LDBDDB(U)	;GET ATTACHED DDB, IF ANY.
	JRST	TPOPJ1##	;GOOD RETURN
TTYPHY::PUSH	P,P3		;SET UP FOR PHYSICAL ONLY
	MOVEI	P3,TCONLN##
TTYPHZ:	PUSHJ	P,TTYPHX	;CALL COMMON SUBROUTINE
	SOS	-1(P)		;REMEMBER NON-SKIP RETURN
	POP	P,P3		;BY PROPAGATING IT
	JRST	CPOPJ1##

TTYALL::PUSH	P,P3		;TRY ALLL-PHYSICAL & VIRTUAL
	MOVEI	P3,TTPLEN##
	JRST	TTYPHZ
;SUBROUTINE TO FIND TTY FOR A JOB IN J (TTYFND) OR FOR
; CURRENT JOB (TTYFNU)
;RETURN WITH F AND U SET UP.
;GOES TO ERROR IF NO TTYDDB FOR THE JOB.


TTYFNU::MOVE	J,JOB##		;GET CURRENT UUO LEVEL JOB NUMBER
TTYFND::PUSHJ	P,TTYSRC	;FIND THE JOB'S TTY DDB, ALSO U AND S
	  STOPCD CPOPJ##,DEBUG,NDJ,	;++NO DDB FOR JOB
TTYFNX:	POPJ	P,0		;SUCCESS. RETURN.

;SUBROUTINE TTYFUW (TELETYPE FIND FOR CURRENT USER AND WAIT), TO
;FIND CURRENT USER'S TTY AND WAIT FOR IT TO COME OUT OF OUTPUT
;WAIT, AND BE ATTACHED.
;SUBROUTINE TOWAIT, TO WAIT FOR TYPEOUT ACTIVITY TO (NEARLY) COMPLETE,
;IF NECESSARY.


TTYFUW::PUSHJ	P,TTYFNU	;FIND USER'S TTY
	PUSHJ	P,CKATTO	;CHECK THAT IT'S ATTACH. WAIT IF NOT.
IFN	FTMIC,<			;IF MIC
	MOVE	T1,LDBMIC(U)
	TLNE	T1,LDL.RS!LDL.SY
	POPJ	P,0		;IF HE WANTS RESPONSE STUFF DO NOT TO
>			;END OF IF MIC
;ROUTINE TO WAIT FOR NEARLY EMPTY OUTPUT BUFFER. CALL ONLY AT UUO LEVEL
TOWAIT:	MOVE	S,[XWD	TTYOUW+IO+IOW,IOACT]  ;SET ACTIVE & WAITING FIRST TO AVOID COMPLETION
	IORM	S,DEVIOS(F)	;BETWEEN TEST FOR COMPLETION & IOACT SET
	MOVE	T1,LDBTOC(U)	;GET COUNT OF TYPE-OUT CHARACTERS WAITING.
	CAIL	T1,10		;OVER 7?
	JRST	TOWAT2		;YES. HAVE TO WAIT
	ANDCAB	S,DEVIOS(F)	;NO. NOT WAITING, SO TURN OFF BITS
	POPJ	P,		;& RETURN
TOWAT1:	MOVE	S,[XWD TTYOUW+IO,IOACT]	;FLAG OUTPUT WAIT ACTIVITY
TOWAT2:	IORB	S,DEVIOS(F)	;IN THE DEVICE DATA BLOCK
	PUSHJ	P,PTSTRT	;WAKE UP SUBJOB, IF ANY
	PUSHJ	P,WSYNCS	;WAIT FOR IO TO COMPLETE
	HRRZ	U,DDBLDB(F)	;SET UP LDB IN CASE DETACH/ATTACHAPPENED WHILE WAITING
	JUMPE	U,TTYFUW	;MAKE SURE STILL ATTACHED
	POPJ	P,		;AND RETURN
WSYNCS:	PJRST	WSYNC##		;WAIT AND RETURN WHEN IO DONE
;SUBROUTINE TTYERP TO FIND TTY DDB FOR A MONITOR ERROR MESSAGE.
;CALL WITH J SET TO JOB NUMBER TO BE TYPED AT.
;IF JOB IS ZERO, OR IF DESIRED JOB IS DETACHED, TTYERP RETURNS
;WITH U SET TO OPERATOR'S CONSOLE, AND F SET FROM IT,
;BUT OF COURSE THAT DDB MAY BE ZERO, SINCE MAY BE NO JOB AT OPR.


TTYERP::PUSHJ	P,TTYSRC	;FIND THE TTY DDB IF POSSIBLE
	  JRST TTYERO		;NONE THERE. MAYBE JOB 0. GO FIND OPR
IFE FTOPRERR,<
	JUMPN	U,CPOPJ##	;IF U NON-ZERO, HAVE FOUND WHAT WE WANT
>
IFN FTOPRERR,<
	JUMPN	U,CPOPJ1##	;SKIP RETURN TO SIGNAL LDB FOUND
>
TTYERO:	SKIPN	U,OPRLDB##	;GET OPERATOR LINE FROM ONCE
	STOPCD	CPOPJ##,DEBUG,NOT,	;++NO OPR TTY
	HRRZ	F,LDBDDB(U)	;GET DDB ADR, IF ANY.
TTYERX:	POPJ	P,0		;AND RETURN FROM TTYERP


;SUBROUTINES TO SET UP LINE AND MAKE SURE ATTACHED.
;CALL WITH DDB SET UP, FROM UUO LEVEL ONLY.
;RETURN WHEN ATTACHED AND AT USER LEVEL, WITH LINE SET UP.

;ONE ROUTINE FOR INPUT, ONE FOR OUTPUT, ONE FOR OUTPUT AND USER LEVEL

CKATTI:	IFN FTRSP,<		;RESPONSE DATA?
	PUSHJ	P,RSPTIR##	;RECORD RESPONSE SATISFIED BY TTY INPUT UUO
>
CKATT0:	MOVSI	S,IO		;INDICATE INPUT
	ANDCAB	S,DEVIOS(F)	;SET UP STATUS WORD
	HRRZ	U,DDBLDB(F)	;GET LINE BLOCK ADDR
	JUMPN	U,CKATI1	;IF THERE, GO ON
CKATIW:	MOVSI	S,IO+TTYOUW	;MUST WAIT FOR ATTACH
	ANDCAM	S,DEVIOS(F)	;CLEAR DIRECTION BIT
	MOVEI	S,IOACT		;AND SET WAIT BIT FOR INPUT
	IORB	S,DEVIOS(F)	; ..
	PUSHJ	P,WSYNCS	;WAIT FOR ATTACH
	JRST	CKATT0		;GET LINE SET UP AND RETURN.

CKATI1:	MOVE	T1,DEVMOD(F)	;SEE IF TTY IS CONTROLLING JOB.
	TLNE	T1,TTYATC
	JRST	CKATI2		;YES.
	MOVSI	T1,LDLCOM	;NO. MAKE IT BE
	ANDCAM	T1,LDBDCH(U)	;AT USER LEVEL
CKATI2:	HLL	U,LDBDCH(U)	;GET DEVICE BITS
	TLNE	U,LDLCOM	;AT COMMAND LEVEL?
	JRST	CKATIW		;YES. CAN'T DO INPUT.
	PUSHJ	P,TYIEAT	;NO. SKIP ANY COMMANDS
	PJRST	UUOLDB		;AND GO ADJUST LINE BITS.

CKATOU:	PUSHJ	P,CKATTO	;FIRST MAKE SURE A LINE ATTACHED TO DDB
	TLNN	U,LDLCOM	;IS LINE AT COMMAND LEVEL?
	POPJ	P,0		;NO. USER LEVEL. RETURN.
	MOVE	T1,DEVMOD(F)	;COMMAND LEVEL.  SEE IF CONTROLLER OR I/O DEVICE
	TLNN	T1,TTYATC	;..
	POPJ	P,0		;I/O DEVICE.  LET IT THROUGH.
	PUSHJ	P,TOWAT1	;CONTROLLER.  WAIT SO DON'T CLOBBER COMMANDS
	JRST	CKATOU		;THEN TRY AGAIN FOR USER LEVEL

CKATTO:	MOVSI	S,IO		;INDICATE OUTPUT
	IORB	S,DEVIOS(F)	;SET UP STATUS WORD
	HRRZ	U,DDBLDB(F)	;GET LINE ADDR IF ANY
	JUMPN	U,CKATO1	;IF HAVE ONE, SEE IF TOP LEVEL
CKATOW:	PUSHJ	P,TOWAT1	;WAIT FOR OUTPUT DONE. (WHICH
				; IS FORCED ON ATTACH)
	JRST	CKATTO		;AND SET UP LINE, TO RETURN.
CKATO1:	HLL	U,LDBDCH(U)	;GET LINE DESCRIPTOR BITS
;	PJRST UUOLDB		;FALL INTO UUOLDB

UUOLDB:
	MOVEI	T1,0		;MAKE LDB AGREE WITH S
	MOVE	T2,LDBDCH(U)	;SAVE OLS STATUS
	TRNE	S,DLRSUP	;COPY THESE BITS TO THEIR
	TLO	T1,LDLDLR	; CORRESPONDING LINE BITS
	TRNE	S,FCS		; ..
	TLO	T1,LDLFCS
	TRNN	S,PIMMOD	;TURN OFF REMOTE ECHO IF PIM
				;(IRRELEVANT ON NON-REMOTE LINES)
	TRNE	S,NOECHO
	TLO	T1,LDLNEC
	TLNE	S,IOSBKA	;SINGLE CHARACTER MODE?
	TLO	T1,LDLBKA	;YES. SET THAT BIT
	IORM	T1,LDBDCH(U)	;SET THOSE NEEDING SETTING
	TLC	T1,LDLNEC+LDLFCS+LDLDLR+LDLBKA
	ANDCAM	T1,LDBDCH(U)	;AND CLEAR THE OTHERS
IFN FTNET,<
	MOVEI	T1,LDRREM	;IS THIS A NETWORK TTY?
	CAME	T2,LDBDCH(U)	;CALL ISR IF STATUS CHANGED
	TDNN	T1,LDBDCH(U)
	POPJ	P,		;NO, DON'T TAKE THE TIME TO CALL ISR
	PUSH	P,T3		;MOST OF SCNSER DOESN'T THINK OF THIS AS TEMPORARY
	MOVEI	T1,ISRCHP
	PUSHJ	P,@LDBISR(U)	;TELL ISR THAT CHARACTERISTICS MAY HAVE CHANGED
	POP	P,T3
>
	POPJ	P,

;HERE FROM UUOCON WHEN A TTY HAS BEEN INITED.

TTYOPN::HRRZ	U,DDBLDB(F)	;GET LDB ADDRESS
	JUMPE	U,TPOPJ1##	;FORGET IT IF DETACHED
	MOVSI	T2,LDLCOM	;GET COMMAND LEVEL BIT
	MOVSI	T1,TTYATC	;IS TTY CONTROLLING THE JOB?
	TDNN	T1,DEVMOD(F)	;OR IS IT AN I/O DEVICE?
	ANDCAM	T2,LDBDCH(U)	;I/O PUT IT AT USER LEVEL
	PUSHJ	P,UUOLDB	;SETUP THE LDB FROM S
	JRST	TPOPJ1##	;AND RETURN
;SUBROUTINE TIWAIT TO WAIT FOR SOME INPUT, AND SEND XON IF NEEDED.


IFN	FTMIC,<			;IF MIC
TIWAIT:	PUSHJ	P,MICWAK	;WAKE MIC IF NECESSARY AND SET UP T1 WITH LDBDCH
	TRNE	T1,LDRPTY	;IS THIS LINE PTY-DRIVEN?
>			;END OF IF MIC
IFE	FTMIC,<			;IF NOT MIC
TIWAIT:	MOVEI	T1,LDRPTY	;IS THIS LINE PTY-DRIVEN?
	TDNE	T1,LDBDCH(U)	;CHECK	IN THE LDB CHARACTERISTICS
>			;END OF IF NOT MIC
	PUSHJ	P,PTYOW##	;YES. GO MARK THIS WAIT.
IFN FTCAFE,< IFN FT2741!FTNET,< ;IF WE SUPPORT 2741'S ON THE DC76
	PUSHJ	P,UNLKBD	;UNLOCK KEYBOARD
> ;END FT2741
> ;END FTCAFE
	MOVSI	S,IO+TTYOUW	;MARK DIRECTION AS INPUT.
	ANDCAM	S,DEVIOS(F)	;CLEAR IN CORE
	MOVE	S,DEVIOS(F)
	MOVEI	T1,IMGTIM	;TIMEOUT FOR IMAGE MODE
	TRNE	S,I		;TTY IN IMAGE MODE?
	DPB	T1,LDPTIM	;YES. STORE TIMEOUT TIME
	PUSHJ	P,CHKXON	;SEND X-ON IF NEEDED
	JRST	WSYNCS		;WAIT FOR INPUT

;SUBROUTINE TWAITL TO WAIT FOR AN INPUT LINE

TWAITL:	PUSHJ	P,CKATTI	;FIRST WAIT FOR ATTACH. SET DDB AND LINE
	PUSHJ	P,TTLCHK	;CHECK FOR A LINE BEING PRESENT
	  JRST	TWATLK		;BE SURE
	POPJ	P,		;LINE PRESENT, RETURN
TWATL1:	PUSHJ	P,TIWAIT	;NO. GO WAIT FOR ONE.
	TRNE	S,IODERR	;GOT A ^C?
	POPJ	P,		;YES, LINE PRESENT
	JRST	TWAITL		;MAKE SURE DID'T DETACH DURING WAIT

;SUBROUTINE TO WAIT FOR SINGLE CHARACTER INPUT

TWAITC:	PUSHJ	P,CKATTI	;MAKE SURE ATTACHED
	PUSHJ	P,TTCCHK	;CHECK FOR A CHARACTER PRESENT
	SKIPA			;NONE PRESENT, GO WAIT
	POPJ	P,0		;YES. RETURN
	MOVE	S,[XWD	IOW,IOACT]  ;SET BOTH ON TO AVOID RACE WITH COMPLETION
	IORB	S,DEVIOS(F)	;SO NOT GO INTO TI WITH SOMETHING THERE
	PUSHJ	P,TIWAIT	;NO. GO WAIT FOR ONE
	TRNE	S,IODERR	;GOT A ^C?
	POPJ	P,		;YES, THAT'S ENOUGH
	JRST	TWAITC		;MAKE SURE ONE THERE IN CASE OF ^C
TWATLK:	MOVE	S,[XWD IOW,IOACT]	;FLAG ACTIVE AND WAITING SO
	IORB	S,DEVIOS(F)	;INTERRUPT WILL NOT FIND HIM ACTIVE
	PUSHJ	P,TTLCHK	;BUT NOT WAITING.  THEN LOOK AGAIN
	JRST	TWATL1		;NOTHING ARRIVED SINCE LAST TEST
	MOVE	S,[XWD IOW,IOACT]	;SOMETHING DID SNEAK IN!
	ANDCAB	S,DEVIOS(F)	;SO FORGET ABOUT WAITING
	POPJ	P,
;SUBROUTINE TO CHECK IF A LINE HAS BEEN INPUT
;THIS ROUTINE ALSO PUTS THE TTY INTO LINE MODE
;CALL:	PUSHJ P,TTLCHK			;WITH F AND U SET UP
;	RETURN HERE IF NO LINE PRESENT
;	RETURN HERE IF LINE PRESENT

TTLCHK::MOVSI	S,IOSBKA	;CLEAR ALL-CHARACTERS BIT IN S
	TRNE	F,-1		;IF THERE IS A DDBF
	ANDCAB	S,DEVIOS(F)	; . .
TTLCK1:	MOVSI	T1,LDLBKA	;CLEAR BREAK ON ALL CHARACTERS BIT
	ANDCAM	T1,LDBDCH(U)	;IN LINE DATA BLOCK
TTLCK2:	LDB	T1,PIOMOD##	;GET IO MOD
	CAIE	T1,PIMMOD	;SKIP IF PIM MODE
	CAIN	T1,I		;IMAGE MODE? (NO BREAKS)
	SKIPG	LDBTIC(U)	;YES, BREAK IF ANYTHING
	SKIPLE	LDBBKC(U)	;IS THERE A LINE ALREADY
	JRST	CPOPJ1##	;YES, RETURN
	MOVE	T1,LDBTIC(U)	;GET INPUT CHAR COUNT
	CAIL	T1,^D70		;UP TO WARNING POINT?
	JRST	CPOPJ1##	;YES. SKIP, LINE AVAILABLE.
	TLNE	U,LDLIMI	;NO. IMAGE INPUT STATE?
	TLNN	S,FRCEND	;YES. ALSO TIMED OUT?
	POPJ	P,0		;NO. NO LINE READY.
	JRST	CPOPJ1##	;YES. LINE READY.

;SUBROUTINE TO CHECK IF A CHARACTER HAS BEEN TYPED
;THIS ROUTINE PUTS THE TTY INTO CHARACTER MODE
;CALL:	PUSHJ P,TTCCHK			;WITH F AND U SET UP
;	RETURN HERE IF NO CHARACTER
;	RETURN HERE IF CHARACTER PRESENT

TTCCHK:	MOVSI	S,IOSBKA	;SET CHARACTER BY CHAR BIT
	IORB	S,DEVIOS(F)	;IN DEVICE DATA BLOCK
	MOVSI	T1,LDLBKA	;SET "BREAK ON ALL CHARACTERS" BIT
	IORM	T1,LDBDCH(U)	;IN LINE DATA BLOCK
	SKIPLE	LDBTIC(U)	;IS THERE A CHARACTER ALREADY?
	AOS	(P)		;YES, SKIP RETURN
	POPJ	P,		;NO, NON-SKIP RETURN
;ROUTINE TO CHECK IF AN XOFF HAS BEEN SENT OUT
;AND IF SO, TO SEND AN XON.
;CALLED BY:
;	PUSHJ	P,CHKXON
;	RETURN HERE ALWAYS (CLOBBERS T1,T3)


CHKXON:	MOVSI	T1,LPLXOF	;IS PAGE MODE ENABLED?
	TDNN	T1,LDBPAG(U)	;GUARANTEE XON IF TALKING TO
				;ANOTHER COMPUTER
	POPJ	P,		;XON IS NOT NEEDED

CHKXN1:	MOVEI	T1,LDRPTY	;XON NOT APPROPRIATE IF
	TDNE	T1,LDBDCH(U)	;THIS IS A PTY
	POPJ	P,		;PTY! JUST RETURN
	MOVE	T1,LDBTIC(U)	;GET # OF INPUT CHARS
	ADD	T1,LDBECC(U)	;PLUS THOSE TO BE ECHOED
	CAILE	T1,^D80		;TOO MANY?
	POPJ	P,		;YES, GO AWAY
	MOVSI	T1,LPLXOF	;CLEAR XOFF BIT
	ANDCAM	T1,LDBPAG(U)	;SO ONLYONE XON IS SENT
	MOVE	T1,FLPXON	;GET POINTER TO XON
	MOVEM	T1,LDBXNP(U)	;STORE WHERE IT WILL BE FORCED OUT.
	PJRST	TOPOKE		;START TTY MOVING
				;IFN FTTPAG

;ROUTINE TO GET DDB OUT OF TI WAIT IF NEEDED
;CALLED BY:
;	MOVE	J,JOB #
;	PUSHJ	P,CLRTI
;	RETURN	HERE
;RESPECTS	T1,T2
CLRTI::	PUSH	P,T1		;SAVE SOME AC'S
	PUSH	P,T2
	LDB	T1,PJBSTS##	;GET WAIT STATE CODE
	CAIE	T1,TIOWQ##	;IN TI WAIT?
	JRST	CLRTI1		;NO--EXIT
	PUSHJ	P,TTYSRC	;FIND TTY DDB
	  JRST	CLRTI1		;NO DDB?
	MOVE	T1,[IOW,,IOACT]
	ANDCAM	T1,DEVIOS(F)
CLRTI1:	POP	P,T2
	JRST	TPOPJ##

IFN FTCAFE!FTNET,<	;INCLUDE THIS CODE IF WE HAVE A DC76
IFN FT2741!FTNET,<	; WITH 2741 SUPPORT
;SUBROUTINE TO UNLOCK 2741 KEYBOARD:
;CALL WITH:
;	MOVEI	U,ADDRESS-OF-LDB
;	PUSHJ	P,UNLKBD
;	RETURN HERE
UNLKBD:	MOVE	T1,[XWD LDLXON, LDR2741] 	;SET UP 2741 BIT
	TDNN	T1,LDBDCH(U)	;SKIP IF 2741 LINE
	POPJ	P,0		;NOT A 2741
	SKIPN	LDBBKC(U)	;DON'T GIVE UP IF HAVE BRK CHAR
	SKIPGE	LDBDCH(U)	;SKIP IF NOT OUTPUT IN PROGRESS
	POPJ	P,0		;JUST RETURN
	PUSH	P,T2		;SAVE T2
	PUSH	P,T3		;AND T3
	MOVEI	T1,ISRLPC	;FUNCTION
	MOVEI	T3,<LPCUKB>B27	;SUBFUNCTION
	PUSHJ	P,@LDBISR(U)	;CALL D76INT (OR WHATEVER)
	POP	P,T3		;RESTORE T3
	PJRST	T2POPJ##	;RESTORE T2 AND RETURN
>	;END FT2741
>	;END FTCAFE
;ROUTINE TO PUT SIXBIT NAME IN DEVNAM(DDB), AND TO SET PUNIT.

;CALL:	SET DDB TO DEVICE DATA BLOCK TO RECEIVE THE NAME AND UNIT
;	SET LINE TO LINE DATA BLOCK WHERE LINE NUMBER WILL BE FOUND
;	AND SET OR CLEAR IMAGE BIT IN DEVMOD DEPENDING ON
;	WHETHER THIS LINE WILL BE PTY-DRIVEN OR NOT
;	PUSHJ P,SCNNAM
;	RETURN
;CLOBBERS T1 AND T3


SCNNAM:	MOVSI	T1,(SIXBIT /CTY/)	;FIRST SET TO CTY
	MOVEM	T1,DEVNAM(F)	;IN CASE MAYBE IT IS.
	LDB	T1,LDPLNO	;GET PHYSICAL LINE NUMBER
	DPB	T1,PUNIT##	;AND STORE IT IN THE DDB
	SETZM	DEVSTS(F)
	MOVEI	T3,<1_I>	;GET IMAGE MODE BIT.
	IORM	T3,DEVMOD(F)	;SET IT IN THE DDB
	MOVE	T1,LDBDCH(U)	;GET DEVICE BITS
	TRNE	T1,LDRPTY	;IS THIS A PTY?
	ANDCAM	T3,DEVMOD(F)	;YES. CLEAR THE BIT.
	TRNE	T1,LDRCTY	;IS THIS THE CTY?
	JRST	SCNNMC		;YES. LEAVE CTY IN NAME WORD.
	MOVSI	T3,(SIXBIT /TTY/)	;NO. DEVICE IS "TTYNNN"
	MOVEM	T3,DEVNAM(F)	;SET UP THE "TTY" PART
	MOVE	T3,[POINT 6,DEVNAM(F),17]	;SET POINTER FOR "NNN"
	PUSH	P,T1+1		;SAVE AN AC FOR DIVIDE BELOW
	LDB	T1,LDPLNO	;RESTORE LINE NUMBER
	PUSHJ	P,SCNNMR	;GO PUT NUMBER IN NAME
	POP	P,T1+1		;RESTORE THE AC
SCNNMC:	POPJ	P,0		;RETURN FROM SCNNAM

;SUBSIDIARY ROUTINE TO DO RADIX PRINT TO CORE.

SCNNMR:	IDIVI	T1,10		;DEVICE NAMES ARE OCTAL
	HRLM	T1+1,0(P)	;STORE A DIGIT ON STACK
	SKIPE	T1		;NEED MORE DIGITS?
	PUSHJ	P,SCNNMR	;YES. GO MAKE THEM.
	HLRZ	T1,0(P)		;RETRIEVE A DIGIT FROM STACK
	ADDI	T1,"0"-40	;CONVERT TO SIXBIT
	IDPB	T1,T3		;STORE IN OBJECT WORD (DEVNAM)
	POPJ	P,0		;POP UP TO SCNNMR OR BACK TO SCNNAM

IFN FTNET,<

;ROUTINE TO LOCATE A NEW TTY DDB

SETSTA:	PUSHJ	P,FNDSTA	;FIND STATION
	DPB	T1,PDVSTA##	;PUT STA # IN DEVICE LOC FIELD
	POPJ	P,		;RETURN

FNDSTA::MOVE	T1,LDBDCH(U)	;GET TTY BITS
	TRNN	T1,LDRPTY	;TTY A PTY LINE?
	JRST	DDBRL		;NO - BRANCH FOR REAL TTY
	LDB	T1,LDPLNO	;YES, GET LINE NUMBER ONLY
	SUBI	T1,PTYOFS##	;DECREMENT TO PTY LINE NUMBER
	PUSH	P,F		;SAVE TTY DDB FOR A SECOND
	MOVE	F,PTYTAB##(T1)	;GET PTY DDB
	LDB	T1,PDVSTA##	;GET LOCATION OF PTY
	POP	P,F		;RESTORE TTY DDB
	POPJ	P,		;AND RETURN TO CALLER

DDBRL:	TRNN	T1,LDRREM	;REMOTE STATION TTY?
	JRST	DDBRL1		;NO, MUST BE A LOCAL TTY
	HLRZ	T1,LDBREM(U)	;YES, GET ADDRESS OF SCB
	JUMPE	T1,DDBRL1	;LOCAL(?)
	HLRZ	T1,NDBNNM##(T1)	;GET THE NODE NUMBER
	POPJ	P,		;RETURN.

DDBRL1:	MOVEI	T1,LOCSTA##	;LOCAL STATION
	POPJ	P,		;RETURN


>
;ROUTINE TO ESTABLISH DEVICE OPR IF POSSIBLE
;CALL:	MOVE	T1,DEVICE NAME
;	PUSHJ	P,STDOPR
;RETURN CPOPJ IF ILLEGAL
;SKIP RETURN WITH DEVICE CHANGED
STDOPR::PUSHJ	P,TTYPHY	;LOOK FOR THIS PHYSICAL NAME
	  POPJ	P,		;FAILED IF NOT POSSIBLE
	HRRZM	U,OPRLDB##	;SAVE NEW LDB ADDRESS
	MOVEM	T1,DEVOPR##	;SAVE NEW NAME
	JRST	CPOPJ1##	;RETURN
SUBTTL ROUTINES FOR PTY


;PTYGET IS CALLED FROM PTYSER TO GET A CHARACTER SENT TO A TTY LINE
;AND IS THEREFORE A SIMPLIFIED VERSION OF XMTINT

PTYGET::MOVE	T2,LDBTOT(U)	;BE SURE PUTTER
	CAME	T2,LDBTOP(U)	;IS NOT=TAKER
	SOSGE	LDBTOC(U)	;COUNT IS POSITIVE
	JRST	ZAPPTO

	IBP	LDBTOT(U)	;GET CURRENT CHARACTER ADDRESS
	MOVE	T2,LDBTOT(U)	;AND INTO T2
	PUSHJ	P,TTGETC	;GET THE CHARACTER
	  PUSHJ P,XMTBFF		;UPDATE CHUNK ADDRESS AND FREE CHUNK
	JUMPE	T3,PTYGET	;IF A NULL, LOOP AROUND
	PUSHJ	P,XMTWAK	;WAKE UP PTY-DRIVEN JOB
	JRST	CPOPJ1##	;AND GIVE SUCCESSFUL RETURN
ZAPPTO:
IFE FTMIC,<
	PJRST	ZAPOUT		;BE SURE POINTERS AND COUNT OK
>
IFN FTMIC,<			;IF MIC, HE CAN HAVE
	PUSHJ	P,ZAPOUT
	PJRST	MICRMT		;MIC ECHOES
>

;PTYPUT IS CALLED FROM PTYSER TO PLACE A CHARACTER IN A TTY INPUT
;BUFFER AS THOUGH THE TTY HAD BEEN TYPED ON. NO ECHOING IS ALLOWED,
;THOUGH AND THIS ROUTINE IS A SIMPLIFIED VERSION OF RECINT AND
;XMTECH, TO MAKE THE CHARACTERS VISIBLE TO THE CONTROLLED JOB WITHOUT ECHOING

CNTRLO==17
PTYPUT::PUSHJ	P,SAVE4##	;SAVE P1
	TLNE	T1,CHALT	;ALTMODE?
	PUSHJ	P,RIALTO	;CONVERT
	MOVE	P1,T1		;SAVE BITS
	CAIN	T3,CNTRLO
	PJRST	FLPCNO
IFN	FTMIC,<			;IF MIC
	SKIPE	LDBMIC(U)
	CAIE	T3,1		;CONTROL A COUNTS AS ^C TO MIC
>			;END OF IF MIC
	CAIN	T3,3		;CONTROL C?
	JRST	PTYCC		;YES. SPECIAL CHECKING
IFN FTWATCH,<
	CAIN	T3,"T"-100
	JRST	PTYCT
PTYINA:>
	MOVSI	T2,L2LCCS	;NOT CONTROL C, SO
	ANDCAM	T2,LDBBY2(U)	;CLEAR SYNC BIT
IFN	FTMIC,<			;IF MIC
	SKIPE	T2,LDBMIC(U)
	JRST	PTYMCK
>			;END OF IF MIC
PTYPT1:	MOVE	T2,LDBTIC(U)	;IS THIS LINE ALREADY FULL?
	CAIG	T2,^D200	; ..
	SKIPG	TTFREN##	;OR LISTS EXHAUSTED?
	POPJ	P,0		;YES. DISCARD CHAR
	SKIPN	TTFREE##	;ANY FREELIST
	POPJ	P,0		;NO--PUNT
IFN	FTMIC,<			;IF MIC
	SKIPE	LDBMIC(U)
	PUSHJ	P,MICECH	;SAY COL1 TO MIC
>	;END OF IF MIC
	PUSHJ	P,TTPTIC	;UPDATE BYTE POINTER, STORE CHARACTER
	TLNE	P1,CHBRK	;IS THIS A BREAK CHARACTER?
	MOVEM	T2,LDBBKU(U)	;YES. STORE NEW ^U POINTER
	IBP	LDBECT(U)	;NOW COUNT ECHO POINTER
	MOVE	T2,LDBECT(U)
	PUSHJ	P,TTGETC	;AND GET THE CHARACTER (TO ADJUST T2)
	  MOVEM T2,LDBECT(U)		;NEW CHUNK. STORE CA.
	TLNE	P1,CHBRK	;BREAK CHAR?
	AOS	LDBBKC(U)	;YES. COUNT BREAKS
	AOS	T2,LDBTIC(U)	;COUNT TYPEIN COUNT
	TLNE	U,LDLBKA	;TTY IN BREAK-ON-ALL MODE?
	PUSHJ	P,RCVWKQ	;YES. WAKE JOB IF WAITING
	CAIG	T2,^D79		;ENOUGH TO WAKE ON?
	TLNE	P1,CHBRK	;OR A BREAK CHARACTER?
	PUSHJ	P,ECHBRK	;YES. WAKE THE JOB
	JRST	CPOPJ1##	;SUCCESFUL RETURN TO PTYSER
;MORE OF PTYPUT. SPECIAL CODE FOR CONTROL C

PTYCC:
IFN	FTMIC,<			;IF MIC
	SKIPE	T1,LDBMIC(U)
	PUSHJ	P,MICRIC
>			;END OF IF MIC
	PUSHJ	P,RIDLN		;YES. DO SO.
	MOVSI	T1,L2LCCS	;SECOND CONTROL C?
	TDNE	T1,LDBBY2(U)	; ..
	PUSHJ	P,CNCCHK	;YES. FORCE CONTROL C IF POSSIBLE
	  JRST	PTYCC1		;NOT SECOND--GO SET BIT
	  JRST	PTYCC4		;NO. (JACCT) JUST PASS THE CHARACTER
	PUSHJ	P,TSETBI	;YES. CLEAR BUFFERS
	PUSHJ	P,TSETBO	; ..
	JRST	CPOPJ1##	;AND RETURN TO PTYSER
PTYCC4:	PUSHJ	P,TTHALT	;FORCE .HALT COMMAND
PTYCC1:	MOVSI	T1,L2LCCS	;SET "^C LAST IN" BIT
	IORM	T1,LDBBY2(U)	;SET BIT FOR NEXT TIME
	JRST	PTYPT1		;AND GO STORE CONTROL C IN INPUT BUFFER


;HERE ON ^O TO PTY

FLPCNO:	MOVSI	T1,LDLOSU	;FLIP THE ^O BIT WHEN PTY OR REMOTE
	XORM	T1,LDBDCH(U)	;SENDS ^O
	PUSHJ	P,TSETBO	;CLEAR THE OUTPUT BUFFER
	PJRST	XMTWAK		;WAKE JOB IF IN OUTPUT WAIT
IFN FTWATCH,<
PTYCT:	PUSHJ	P,DOCTLT
	  JRST	PTYINA
	  JRST	TTFRC1
	JRST	CPOPJ1##
>
;TWO SUBROUTINES TO INITIALIZE THE LDB. LDBCLR SETS UP THE BITS FROM
;INITIAL STATE FOUND IN LINTAB, THEN FALLS INTO LDBINI. LDBINI JUST
;CLEARS AS REQUIRED ON 140 RESTART.
;BOTH SHOULD BE CALLED WITH LINE SET UP.

LDBCLR::LDB	T1,LDPLNO	;GET LINE NUMBER
	LDB	T1,LNPVRG	;GET VIRGIN-STATE BITS FROM LINTAB
	TRZ	T1,4		;CLEAR INITIA BIT
	DPB	T1,LDPVR2	;STORE THEM AROUND THE LDB
	LSH	T1,-5		; ..
	DPB	T1,LDPVR1	; ..
	LSH	T1,-6		; ..
	DPB	T1,LDPFLC	;LAST IS THE FILLER CLASS
IFN FTCAFE&FT2741,<
	LDB	T1,LDPSPD
	MOVEI	T2,LDR2741
	CAIN	T1,104
	IORM	T2,LDBDCH(U)
>
LDBINI::MOVSI	T1,LDBCMR	;CLEAR COMMAND REQUEST BIT
	ANDCAM	T1,LDBDDB(U)	;IN LINE DATA BLOCK
	HRLOI	T1,LDIBCM	;BYTE WORD CLEAR MASK
	ANDCAM	T1,LDBBYT(U)	;CLEAR MOST BYTES
	MOVE	T1,LDIDCM	;CLEAR DEVICE CHARACTERISTICS
	ANDCAM	T1,LDBDCH(U)	; AS APPROPRIATE
	MOVEI	T1,^D72		;INITIAL VALUE OF TTY WIDTH
	DPB	T1,LDPWID	;STORE IN LDB
	MOVSI	T1,L2LCLR	;CLEAR NECESSARY BITS IN LDBBY2
	ANDCAM	T1,LDBBY2(U)	; ..
	LDB	T3,LDPLNO	;COPY LINE NUMBER
	MOVSI	T1,LDLCOM+LDLLCT	;ASSUME AT COMMAND LEVEL AND UPPER CASE
IFN	FTD10H,<		;CODE FOR 2741 ON DC10H
	HLRZ	T2,LINTAB##(T3)	;GET BITS FROM LINTAB
	TRNN	T2,TTVDIS##	;IS IT A DISPLAY LINE
				; WHICH INDICATES ITS A DC10H LINE?
	  JRST	.+4		;NO
	MOVSI	T2,LILCFE	;SET CLEVER BIT
	IORM	T2,LDBISR(U)	; IN THE LDB.
	TRO	T1,LDR2741	;ALSO TELL LDB ITS A 2741
>;END IFN FTD10H
	CAIN	T3,TCONLN##	;IS THIS THE CTY'S LINE NUMBER?
	TRO	T1,LDRCTY	;YES--SET CTY BIT
	CAILE	T3,TCONLN##	;ABOVE TCONLN?
	TRO	T1,LDRPTY	;YES. SET PTY BIT
	IORM	T1,LDBDCH(U)	;PUT THESE BITS IN THE LDB
	TRNE	T1,LDRPTY	;IS THIS A PTY?
	PUSHJ	P,TSETBI	;YES--CLEAR INPUT BUFFER
	MOVSI	T1,LPLCLR	;CLEAR PAGE BITS
	ANDCAM	T1,LDBPAG(U)	;...
	MOVSI	T1,LPLALT
	XCT	TTDALT##	;IORM OR ANDCAM DEPENDING ON DEFAULT
				; FOR TTY ALT (SEE COMDEV)
IFN	FTMIC,<			;IF MIC
	SETZM	LDBMIC(U)	;CLEAR MIC WORD
>			;END OF IF MIC
	MOVSI	T3,L1LOFL	;OFF LINE BIT
	MOVEI	T1,ISROFL
	PUSHJ	P,@LDBISR(U)
	IORM	T3,LDBOFL(U)
	POPJ	P,0		;RETURN FROM LDBINI
SUBTTL IMPURE DATA

	$LOW
CMDLIN::0				;LDB USING NEXT 4 WORDS
COMTIA::0				;COMMAND TYI ADDRESS
COMTOA::0				;COMMAND TYO ADDRESS
TTCMCH::0				;COMMAND LEVEL CHARACTER LAST READ
TTCMCA::0				;COMMAND LEVEL CHAR ADDR
IFN FTDIAL,<
DSCNUM:	BLOCK 2			;PHONE NUMBER BEING DIALLED, OR LAST DIALLED
>
IFN FTMIC,<
MICLIN:-1
>

.GTSCN::
IFN FTRSP,<
;SCNSER RESPONSE DATA
%SCNRI::0			;(0)NUMBER OF RCV INTERRUPTS
%SCNXI::0			;(1)NUMBER OF XMT INTERRUPTS
%SCNEI::0			;(2)NUMBER OF ECHO INTERRUPTS (SUBSET OF %SCNXI)
>	;END FTRSP
IFE FTRSP,<
	BLOCK	3		;0,1,2 IF NO RSP DATA
>
TIWRNN::EXP	^D80		;(3)MAX BUFFER SIZE
%SCNAL::0			;(4)NUMBER OF ACTIVE LINES
RPIMWN::EXP	^D60		;(5) PIM BUFFER SIZE
EXP	RECINT			;(6)FOR MONITOR TEST
EXP	XMTINT			;(7)PROGRAMS
EXP	TYPEX			;(10)
SCNMXL==:<<.-.GTSCN-1>B26>
TIWRN1:	^D80			;WORD TO SAVE OLD BUFFER LIMIT
RPIMW1:	^D80			;WORD TO SAVE OLD PIM LIMIT

	$LIT

SCNEND:	END