Google
 

Trailing-Edge - PDP-10 Archives - BB-M081Y-SM - monitor-sources/ttysrv.mac
There are 50 other files named ttysrv.mac in the archive. Click here to see a list.
; Edit= 9146 to TTYSRV.MAC on 9-Feb-90 by GSCOTT
;Turning off TT%PGM didn't really work on LAT terminals because the LAT server
;was not being told to turn off flow control in both directions, which makes
;the LAT session go into passall mode, because the definiton of SL.DXF was
;wrong. Also removes edit 9144. 
; Edit= 9126 to TTYSRV.MAC on 3-Oct-89 by GSCOTT
;Don't CFOBF% at LOG21 unless the SOBE% loop times out, don't clear SBDLP at
;CSBDAV, remove edit 9120 as it was a bad idea.
; Edit= 9117 to TTYSRV.MAC on 20-Jul-89 by GSCOTT
;TVTSOF now assigns buffers based on network packet size. TVTCSO and OPSCAN
;now use a bittable (TVTSOQ) to indicate which TVT lines need to be serviced.
;GTOCHR now releases TTY buffers when the last character is removed from the
;buffer. Certain SOUT%s to terminals now use a quick output routine called
;BLAST. Improve "LINK FROM" message in TLINK%.
; Edit= 9072 to TTYSRV.MAC on 28-Feb-89 by RASPUZZI
;Prevent NSKDIS BUGHLTs when attaching to a job from a CTERM terminal. Small
;race condition existed where someone else could have the CTMLOK and deep down
;in the bowls of CTHSRV, we would try to LOCK the CTMLOK and of course want to
;block since someone else had it. You can't block when you are NOSKED.
; Edit= 9062 to TTYSRV.MAC on 19-Jan-89 by GSCOTT
;TTYASO was two instructions too big.
; Edit= 9041 to TTYSRV.MAC on 13-Dec-88 by RASPUZZI
;Finish off some of the security features that were started at one time (like
;password expiration). Also, add new features to help a system manager secure
;the system.
; Edit= 8986 to TTYSRV.MAC on 28-Oct-88 by JROSSELL, for SPR #21549
;Correct some problems with SET TERMINAL characteristics 
; Edit= 8977 to TTYSRV.MAC on 4-Oct-88 by JROSSELL, for SPR #21689
;Add support for optionally not flushing NULs when a terminal is in ASCII
;mode. 
; Edit= 8944 to TTYSRV.MAC on 25-Aug-88 by GSCOTT
;Update BUG. documentation.
; UPD ID= 8666, RIP:<7.MONITOR>TTYSRV.MAC.16,  24-Feb-88 18:45:22 by RASPUZZI
;More of TCO 7.1230 - Fix misguidance in TTMSG% comments.
; UPD ID= 8659, RIP:<7.MONITOR>TTYSRV.MAC.15,  22-Feb-88 12:22:20 by GSCOTT
;More of TCO 7.1230 - Remove stray angle brackets, update TTMSG comments.
; UPD ID= 8657, RIP:<7.MONITOR>TTYSRV.MAC.14,  22-Feb-88 11:10:35 by GSCOTT
;TCO 7.1075 - Table of contents.
; UPD ID= 8656, RIP:<7.MONITOR>TTYSRV.MAC.13,  22-Feb-88 11:07:39 by GSCOTT
;More of TCO 7.1230 - Correct problem with previous edit, fix TDCALL macro
; to detect a mistaken lower case "d" or "s".
; UPD ID= 8652, RIP:<7.MONITOR>TTYSRV.MAC.12,  18-Feb-88 20:45:26 by GSCOTT
;TCO 7.1230 - Default CTY to type contained in CTYTY.
; UPD ID= 8637, RIP:<7.MONITOR>TTYSRV.MAC.11,  11-Feb-88 18:55:36 by GSCOTT
;TCO 7.1218 - Update copyright date.
; UPD ID= 8465, RIP:<7.MONITOR>TTYSRV.MAC.10,   5-Feb-88 15:56:34 by GSCOTT
;More TCO 7.1210 - Correct TTLOKB.
; UPD ID= 8449, RIP:<7.MONITOR>TTYSRV.MAC.9,   4-Feb-88 16:44:17 by GSCOTT
;TCO 7.1210 - Set CTYSTK, TTYBBO, and TTYNTB normally not dumpable.
; UPD ID= 184, RIP:<7.MONITOR>TTYSRV.MAC.8,  21-Oct-87 17:25:58 by RASPUZZI
;TCO 7.1076 - Add support for cluster sendall. Have TTMSG% call into
;             CLTMSG when it has a sendall for another node besides the
;             local node. Also rework how GETSAL makes the sendall header.
; UPD ID= 156, RIP:<7.MONITOR>TTYSRV.MAC.7,  13-Oct-87 14:38:27 by RASPUZZI
;Last of TCO 7.1070 - Remove SNTIM too.
; UPD ID= 155, RIP:<7.MONITOR>TTYSRV.MAC.6,  13-Oct-87 14:34:39 by RASPUZZI
;More of TCO 7.1070 - Forgot to rip out some other code at TTINIT.
; UPD ID= 153, RIP:<7.MONITOR>TTYSRV.MAC.5,  13-Oct-87 14:26:56 by RASPUZZI
;TCO 7.1070 - Remove routine TTYCHK from scheduler overhead. It wastes time
;and does nothing useful these days.
; UPD ID= 113, RIP:<7.MONITOR>TTYSRV.MAC.4,  15-Sep-87 18:55:28 by GSCOTT
; TCO 7.1056 - Allow TTMSG with -2 in ac 1 to go to 20F only.
; UPD ID= 54, RIP:<7.MONITOR>TTYSRV.MAC.3,  27-Jul-87 16:15:36 by MCCOLLUM
;TCO 7.1024 - Change call to CTHSPS to CTHOBS
; *** Edit 7435 to TTYSRV.MAC by GSCOTT on 3-Apr-87, for SPR #21488
; Enable control of DTR on RSX20F lines by MTOPR functions .MOHUP and .MOUHU
; and raise and lower DTR when a TTY is opened and closed if it's not CTRLTT 
; *** Edit 7390 to TTYSRV.MAC by RASPUZZI on 13-Nov-86
; Fix minor problem with 7342 - We're always sending an XON and not waiting for
; the line to reach the threshold. 
; *** Edit 7342 to TTYSRV.MAC by RASPUZZI on 28-Jul-86, for SPR #20938
; Get rid of a race condition between TTYSRV and RSXSRV by putting the XON/XOFF
; logic in TTCH7 (TTYSRV) after chars have been moved from TTBBUF to their
; individual line buffers. 
; *** Edit 7328 to TTYSRV.MAC by MCCOLLUM on 24-Jun-86, for SPR #21297
; Check bit SF%LAT for allowing LAT terminal logins instead of SF%RMT 
; *** Edit 7310 to TTYSRV.MAC by RASPUZZI on 2-Jun-86
; Prevent SKDPF1 BUGHLTs by making TTNTM1, TTSNTF & FENTM resident routines 
; *** Edit 7256 to TTYSRV.MAC by MRASPUZZI on 11-Mar-86, for SPR #20978
; Clear inhibit bit and receive/ref user msgs bit on job startup for terminals 
; *** Edit 7200 to TTYSRV.MAC by MELOHN on 18-Nov-85 (TCO 6.1.1560)
; Make CTERM respond faster to ^O. Remove Edit 7167 because it brakes CTMSTR.
; *** Edit 7193 to TTYSRV.MAC by WONG on 14-Nov-85
; Fix undefined symbol (LPTTIM) when LPTN=0
; Edit 7167 to TTYSRV.MAC by TBOYLE on 21-Oct-85, for SPR #19350
; Fix double prompts and multiple linefeeds at TCI,TCIB,TTSMOD. 
; Edit 7141 to TTYSRV.MAC by PRATT on 28-Aug-85, for SPR #17825 (TCO 6.1.1531)
; Fix half-duplex line count never incrementing problem. 
; Edit 7119 to TTYSRV.MAC by PRATT on 8-Aug-85 (TCO 6-1-1509)
; Fix problem with NTINF error code not being set up in T1. 
; UPD ID= 2248, SNARK:<6.1.MONITOR>TTYSRV.MAC.62,  19-Jun-85 20:47:55 by MELOHN
;TCO 6.1.1465 - Fix problems with CTERM and line wrapping/data mode.
; UPD ID= 2020, SNARK:<6.1.MONITOR>TTYSRV.MAC.61,  28-May-85 12:10:20 by MCCOLLUM
;TCO 6.1.1238 - Fix more BUG. documentation
; UPD ID= 1997, SNARK:<6.1.MONITOR>TTYSRV.MAC.60,  23-May-85 14:23:18 by MELOHN
;More of previous edit.
; UPD ID= 1993, SNARK:<6.1.MONITOR>TTYSRV.MAC.59,  17-May-85 18:04:13 by MELOHN
;TCO 6.1.1398 - Make LAT lines remote.
; UPD ID= 1937, SNARK:<6.1.MONITOR>TTYSRV.MAC.58,   7-May-85 22:54:02 by MCCOLLUM
;TCO 6.1.1238 - Fix more BUG. documentation
; UPD ID= 1915, SNARK:<6.1.MONITOR>TTYSRV.MAC.57,   6-May-85 20:12:52 by GROSSMAN
;TCO 6.1.1363 - Preserve T2 in ASGSHT on error returns.
; UPD ID= 1832, SNARK:<6.1.MONITOR>TTYSRV.MAC.56,  26-Apr-85 09:44:13 by MCCOLLUM
;TCO 6.1.1238 - Fix more BUG. documentation
; UPD ID= 1798, SNARK:<6.1.MONITOR>TTYSRV.MAC.55,  23-Apr-85 13:36:27 by MCCOLLUM
;TCO 6.1.1238 - Fix more BUG. documentation
; UPD ID= 1775, SNARK:<6.1.MONITOR>TTYSRV.MAC.54,  22-Apr-85 13:20:46 by MCCOLLUM
;TCO 6.1.1238 - Fix BUG. documentation
; UPD ID= 1685, SNARK:<6.1.MONITOR>TTYSRV.MAC.53,  25-Mar-85 16:16:13 by MELOHN
;Change previous edit to set same line types to NO parity
; UPD ID= 1656, SNARK:<6.1.MONITOR>TTYSRV.MAC.52,  19-Mar-85 17:32:20 by MELOHN
;TCO 6.1.1277 - LAT, CTERM, NRT lines don't do parity.
; UPD ID= 1584, SNARK:<6.1.MONITOR>TTYSRV.MAC.51,   5-Mar-85 10:33:58 by MOSER
;TCO 6.1.1228 - ITRLGO from TTCKSP
; UPD ID= 1421, SNARK:<6.1.MONITOR>TTYSRV.MAC.50,  29-Jan-85 11:38:10 by PAETZOLD
;TCO 6.1.1159 - Add TVT dependant call in SETOBF.
; UPD ID= 1288, SNARK:<6.1.MONITOR>TTYSRV.MAC.49,   8-Jan-85 14:23:59 by MCCOLLUM
;TCO 6.1.1119 - Add OKINTs in error returns in SALLIN.
; UPD ID= 1219, SNARK:<6.1.MONITOR>TTYSRV.MAC.48,  18-Dec-84 12:49:18 by TBOYLE
;TCO 6.1.1092 - Fix jobs hung in LOGOUT - Remove TTDOBE from TTHNGU
; UPD ID= 1099, SNARK:<6.1.MONITOR>TTYSRV.MAC.47,  19-Nov-84 15:31:25 by MELOHN
;TCO 6.1.1059 - Fix TDCALL where CTERM was trying to deallocate TTY on detach.
;TCO 6.1.1058 - Eliminate TDCALL CTHLGO, and replace it with CTHNGU.
; UPD ID= 961, SNARK:<6.1.MONITOR>TTYSRV.MAC.46,   5-Nov-84 19:52:59 by PRATT
;TCO 6.1.1032 - Make TTYSRV compile independently:
;  Change TTYASN to TTYASG since it conflicts with global FILMSC routine
;  Change INTRAN to DINTRN since it conflicts with global in STG
;  Remove traces of DC, DZ, RP, and KCFLG code
;    In cases where DC, DZ, or RP was the only line type in a TDCALL,
;    the TDCALL remains, but has been commented out.
;  Change TDCALx's to always assemble for all known line types.
;    If a line type is not actually configured, and no default action
;    is to be taken, a BADTTY bughlt will result by jumping to the 
;    dummy symbol in STG.
;  Make some labels global so that NRTSRV and RSXSRV can get them
;  Move some resident storage defs to STG (TT1LIN, and send all stuff)
;  Put dummy symbols for NRTSRV and RSXSRV at end of TTYSRV
;  Put an TNXEND/END in the file
;  Remove big repeat 0 code at end of the old TTYSRV
;  Put TDCALx definitions back in TTYSRV
; UPD ID= 940, SNARK:<6.1.MONITOR>TTYSRV.MAC.45,   1-Nov-84 14:48:32 by PRATT
;Merge M60: edits 4899 and 4951
; UPD ID= 4951, SNARK:<6.MONITOR>TTYSRV.MAC.159,  17-Oct-84 19:03:26 by TBOYLE
;TCO 6.2251 - TTXONF, Force XON to FE at .STPAR, J0TC60, TTYDED, remove
; TTXFF maneuvers at TTCBF7 because only TTXONP is used, Change code at
; J0TC60 to test for TTSFG as well as TTRXF.
; UPD ID= 4899, SNARK:<6.MONITOR>TTYSRV.MAC.155,   8-Oct-84 05:07:19 by TBOYLE
;TCO 6.2238 - handle speed setting properly.
; UPD ID= 933, SNARK:<6.1.MONITOR>TTYSRV.MAC.44,  28-Oct-84 11:33:24 by PRATT
;TCO 6.1.1022 - Add code for finding remote hostname for NTINF%
; UPD ID= 795, SNARK:<6.1.MONITOR>TTYSRV.MAC.40,  10-Sep-84 19:30:01 by WEISBACH
;LAT terminals user ^A for default PAUSE/UNPAUSE (in TTSET).
; UPD ID= 787, SNARK:<6.1.MONITOR>TTYSRV.MAC.39,   4-Sep-84 15:35:38 by WEISBACH
;Merge in M60:edit 4763.
; UPD ID= 4763, SNARK:<6.MONITOR>TTYSRV.MAC.153,  27-Aug-84 17:44:48 by TBOYLE
;TCO 6.2204 (QAR 706053) Pass line# to SALWAT. Have SALWAT convert to DD ptr.
; UPD ID= 764, SNARK:<6.1.MONITOR>TTYSRV.MAC.38,  27-Aug-84 15:55:42 by PRATT
;TCO 6.1.1010 - Make TTANDV assemble independently of TTYSRV
; UPD ID= 742, SNARK:<6.1.MONITOR>TTYSRV.MAC.37,  17-Aug-84 09:52:38 by PAETZOLD
;Even more TCO 6.1733 - no more NTTNVT.
; UPD ID= 740, SNARK:<6.1.MONITOR>TTYSRV.MAC.36,  13-Aug-84 14:19:38 by WEISBACH
;Merge in M60: edits 4630,4634,4645, and 4663
; UPD ID= 4663, SNARK:<6.MONITOR>TTYSRV.MAC.151,   7-Aug-84 22:38:02 by PAETZOLD
;More TCO 6.1733 - no more NTTNVT.
; UPD ID= 4645, SNARK:<6.MONITOR>TTYSRV.MAC.150,   1-Aug-84 17:54:07 by TBOYLE
;TCO 6.2158 - Fix the check for send-all in progress at TTCBF6-2.
; UPD ID= 4634, SNARK:<6.MONITOR>TTYSRV.MAC.149,  30-Jul-84 17:54:11 by MURPHY
;TCO 6.2155 - Make mode word returned by TTRMOD correct.
; UPD ID= 4630, SNARK:<6.MONITOR>TTYSRV.MAC.148,  30-Jul-84 09:41:11 by HAUDEL
;TCO 6.2130 - Check for CTYLNO before using the J0TCOT scheduler test.
;Add a bugchk (CTYSTK) to indicate that J0TCOT has reloaded the Front-End.
; UPD ID= 712, SNARK:<6.1.MONITOR>TTYSRV.MAC.35,  26-Jul-84 08:30:22 by MCINTEE
;Add CTERM - NRT support
; UPD ID= 705, SNARK:<6.1.MONITOR>TTYSRV.MAC.34,  24-Jul-84 15:30:09 by MCINTEE
;Modify echoing for CTERM - remove some now unneeded CTERM TDCALLs
; UPD ID= 685, SNARK:<6.1.MONITOR>TTYSRV.MAC.33,  16-Jul-84 10:51:25 by MCINTEE
;Add CTERM TDCALL to STTYP% jsys code, add CTERM TDCALL to STRTOU
; UPD ID= 651, SNARK:<6.1.MONITOR>TTYSRV.MAC.32,   2-Jul-84 14:59:12 by MCINTEE
;CTERM device dependent call changes. 
; UPD ID= 630, SNARK:<6.1.MONITOR>TTYSRV.MAC.31,  18-Jun-84 13:59:05 by WEISBACH
;	Add LAT terminals to device dependent call in SETOBF to make LAT
;	 terminals high speed output devices.
;	Fix typo in TDCALL in routine TTHNGU for LAT terminals.
; UPD ID= 623, SNARK:<6.1.MONITOR>TTYSRV.MAC.30,  13-Jun-84 13:46:45 by MCINTEE
;remove call to CTHSET
; UPD ID= 576, SNARK:<6.1.MONITOR>TTYSRV.MAC.29,  29-May-84 14:18:07 by WEISBACH
;Add check for LAT Host terminal to CTYMCB so NRTREL does not deallocate a
; LAT terminal's TDB.
; UPD ID= 574, SNARK:<6.1.MONITOR>TTYSRV.MAC.28,  29-May-84 10:26:48 by MCINTEE
;Remove references to newly nonexistent CTERM TDCALLs.
; UPD ID= 544, SNARK:<6.1.MONITOR>TTYSRV.MAC.27,  23-May-84 07:49:17 by MCINTEE
;Merge from M60:
; UPD ID= 4177, SNARK:<6.MONITOR>TTYSRV.MAC.147,   7-May-84 13:31:27 by LOMARTIRE
;More TCO 6.2047 - Fix all possible cases of NOSKED/OKSKED at PI 6 from TTYDED
; UPD ID= 4165, SNARK:<6.MONITOR>TTYSRV.MAC.146,   1-May-84 14:40:42 by LOMARTIRE
;TCO 6.2047 - Prevent KPALVH by only doing NOSKED/OKSKED at PI 7 in TTYDED
; UPD ID= 4156, SNARK:<6.MONITOR>TTYSRV.MAC.145,  30-Apr-84 16:42:46 by LOMARTIRE
;TCO 6.2030 - Teach TLINK% to use fork controlling terminal for TTY: if one
; UPD ID= 481, SNARK:<6.1.MONITOR>TTYSRV.MAC.26,  30-Apr-84 09:40:51 by WEISBACH
;~6.0 - Add LAT Host terminal type.
; UPD ID= 404, SNARK:<6.1.MONITOR>TTYSRV.MAC.25,  21-Mar-84 15:02:06 by MCINTEE
;More TCO 6.1959 - Allow all two character interrupt sequences
; UPD ID= 382, SNARK:<6.1.MONITOR>TTYSRV.MAC.24,  12-Mar-84 14:58:50 by MCINTEE
;Fix NRT bug - in TTYDE0
; UPD ID= 356, SNARK:<6.1.MONITOR>TTYSRV.MAC.23,  27-Feb-84 09:13:10 by MCINTEE
;Merge from M60:
; UPD ID= 3764, SNARK:<6.MONITOR>TTYSRV.MAC.143,  27-Feb-84 08:56:43 by MCINTEE
;More TCO 6.1959 - Account for failure return for .MORTC - routine TTERED.
; UPD ID= 3730, SNARK:<6.MONITOR>TTYSRV.MAC.142,  22-Feb-84 14:00:04 by MCCOLLUM
;TCO 6.1979 - Allow prived users to send to lines with TT%NUM set
; UPD ID= 3612, SNARK:<6.MONITOR>TTYSRV.MAC.141,   1-Feb-84 08:50:41 by MCINTEE
;TCO 6.1959 - Add support for two chracter escape sequences.
; UPD ID= 335, SNARK:<6.1.MONITOR>TTYSRV.MAC.22,  16-Feb-84 17:45:17 by PRATT
;Call TVMSNT, not TVSMNT at TTMSH1 plus lots
; UPD ID= 331, SNARK:<6.1.MONITOR>TTYSRV.MAC.21,  13-Feb-84 14:34:00 by MCINTEE
;Fix SETOBF so that NRT gets its rightful buffer
; UPD ID= 292, SNARK:<6.1.MONITOR>TTYSRV.MAC.20,  16-Jan-84 08:32:39 by MCINTEE
;Merge from M60:
; UPD ID= 3396, SNARK:<6.MONITOR>TTYSRV.MAC.139,   3-Jan-84 10:38:14 by PRATT
;More TCO 6.1796 - Add the code that checks TT%NTM and TT%NUM
; UPD ID= 3318, SNARK:<6.MONITOR>TTYSRV.MAC.138,  14-Dec-83 14:37:13 by PRATT
;TCO 6.1796 - Add TT%NTM and TT%NUM code for TLINK and TTMSG
; UPD ID= 201, SNARK:<6.1.MONITOR>TTYSRV.MAC.19,  27-Sep-83 09:09:36 by PAETZOLD
;Remove TCO 5.1691 - STRTTO Q1 smasher mousetrap
; UPD ID= 186, SNARK:<6.1.MONITOR>TTYSRV.MAC.18,   2-Aug-83 09:23:39 by MCINTEE
;TCO 6.1725 - Make TTPPCS CALL ULKTTY when returning TTYX02 error
;TCO 6.1689 - Move fork tables to extended section
;	Reference FKINT and FKSTA2 via DEFSTR
; UPD ID= 178, SNARK:<6.1.MONITOR>TTYSRV.MAC.17,  26-Jul-83 16:27:00 by PAETZOLD
;TCO 6.1733 - No more NCP so no more NVTs.  Also create real TTYSDN.
; UPD ID= 2413, SNARK:<6.MONITOR>TTYSRV.MAC.133,   3-May-83 16:26:42 by COBB
;TCO 6.1639 - ?s in PRINTX messages...
; UPD ID= 2349, SNARK:<6.MONITOR>TTYSRV.MAC.132,  26-Apr-83 21:30:08 by MCLEAN
; TCO 6.1626 BYTE POINTER IS LOST IF SENDALL LOCK IS LOCKED.
; UPD ID= 116, SNARK:<6.1.MONITOR>TTYSRV.MAC.14,  26-Apr-83 11:49:27 by MCINTEE
;Remove RS%SE0 from TTYASC's call to ASGRES
; UPD ID= 106, SNARK:<6.1.MONITOR>TTYSRV.MAC.13,  18-Apr-83 13:13:20 by PAETZOLD
;TCO 6.1557 - TCP Merge
; UPD ID= 2073, SNARK:<6.MONITOR>TTYSRV.MAC.130,  24-Mar-83 12:44:02 by HALL
;TCO 6.1502 - Allow resident free space in extended section
;	Add EA.ENT to TTEMES
; UPD ID= 84, SNARK:<6.1.MONITOR>TTYSRV.MAC.11,  22-Mar-83 10:32:09 by LEAPLINE
;TCO 6.1561 FIX TEST FOR TTSHU IN CKSALL
; UPD ID= 2038, SNARK:<6.MONITOR>TTYSRV.MAC.128,  20-Mar-83 12:44:27 by HALL
;TCO 6.1502 - Allow resident free space in extended section
;	Allocate dynamic data from extended section.
;	Use one-word global byte pointers to point to sendall buffer and
;		I/O buffers, which must be in section 0 for the DTE.
;	Change handling of end of I/O buffers, and definition of WRPMSK,
;		to reflect use of one-word globals
;	Make everything run in section 1
; UPD ID= 1975, SNARK:<6.MONITOR>TTYSRV.MAC.127,  11-Mar-83 00:33:59 by MOSER
;TCO 5.1510 WAKE UP ON CR FOR HALF DUPLEX LINES
; UPD ID= 1957, SNARK:<6.MONITOR>TTYSRV.MAC.126,  10-Mar-83 14:27:17 by MCINTEE
;TCO 6.1502 - Change MOVEIs to MOVXs in previous edit
; UPD ID= 1944, SNARK:<6.MONITOR>TTYSRV.MAC.125,   9-Mar-83 10:08:13 by HALL
;TCO 6.1502 - Allow free space in extended section
;	Fix caller to ASGRSB, too
; UPD ID= 1943, SNARK:<6.MONITOR>TTYSRV.MAC.124,   9-Mar-83 07:44:51 by HALL
;TCO 6.1502 - Allow free space in extended section
;	Make the rest of the callers set RS%SE0 (sigh)
; UPD ID= 1941, SNARK:<6.MONITOR>TTYSRV.MAC.123,   8-Mar-83 11:41:42 by HALL
;TCO 6.1502 - Allow free space in extended section
;	Make INICTY set RS%SE0
; UPD ID= 1883, SNARK:<6.MONITOR>TTYSRV.MAC.122,  27-Feb-83 22:09:45 by MURPHY
; Set page mode from bit in TTYPE1.
; UPD ID= 1819, SNARK:<6.MONITOR>TTYSRV.MAC.121,  17-Feb-83 16:33:30 by WEAVER
;MORE TCO 6.1485 - Clear TT%XFF after we have called TTXONA
; UPD ID= 1734, SNARK:<6.MONITOR>TTYSRV.MAC.120,   1-Feb-83 18:20:02 by WEAVER
;TCO 6.1485 - Fix TCO 6.1480, put TT%XFF in dynamic storage block.
; UPD ID= 1710, SNARK:<6.MONITOR>TTYSRV.MAC.119,  27-Jan-83 22:57:33 by WEAVER
;TCO 6.1480 - Create bit TT%XFF to force XOFF/XON status to front end, set
;this bit when we receive 2 consecutive ^C's or a ^O.
; UPD ID= 1622, SNARK:<6.MONITOR>TTYSRV.MAC.118,   6-Jan-83 15:54:43 by CDUNN
;TCO 6.1444 - Fix the fix of the bug introduced by TCO 6.1390. Move the label
;TTCHN1 up one so all cases work.
; UPD ID= 1612, SNARK:<6.MONITOR>TTYSRV.MAC.117,   3-Jan-83 15:30:06 by LOMARTIRE
;TCO 6.1433 - Add code for ^ESET [NO] LOGINS-ALLOWED DECNET-LINES command
; UPD ID= 1598, SNARK:<6.MONITOR>TTYSRV.MAC.116,  29-Dec-82 10:47:20 by DONAHUE
;TCO 6.1417 - Prevent OKSKBG at SALLI2
; UPD ID= 1592, SNARK:<6.MONITOR>TTYSRV.MAC.115,  28-Dec-82 14:37:50 by GUNN
; Fix bug introduced by TCO 6.1390 at TTCHN1, T2 contained dynamic ptr
; rather than static
; UPD ID= 1571, SNARK:<6.MONITOR>TTYSRV.MAC.114,  27-Dec-82 08:29:40 by GRANT
;TCO 6.1426 - check for CTY or MCB TTY when processing an NVT's escape character
; UPD ID= 1525, SNARK:<6.MONITOR>TTYSRV.MAC.113,   9-Dec-82 15:58:04 by HAUDEL
;MORE TCO 6.1266 - Filter multiple or single carriage returns.
; UPD ID= 1484, SNARK:<6.MONITOR>TTYSRV.MAC.112,  29-Nov-82 13:35:18 by MURPHY
;TCO 6.1390 - Shut off 20F line if more than 2 noise characters in one second.
; UPD ID= 1473, SNARK:<6.MONITOR>TTYSRV.MAC.111,  23-Nov-82 10:25:15 by GRANT
;TCO 5.1.1109 - Make carrier off, @ATT, and @UNA of a SETHOSTed line work
; UPD ID= 1463, SNARK:<6.MONITOR>TTYSRV.MAC.110,  18-Nov-82 13:47:20 by MOSER
;TCO 6.1372 - ALWAYS RETURN NUMBER OF BYTE FOR SOBE
; UPD ID= 1402, SNARK:<6.MONITOR>TTYSRV.MAC.108,   2-Nov-82 08:28:13 by COBB
;TCO 6.1343 - Reset TTPFK when deassigning permanent lines [TTYDE3]
; UPD ID= 1351, SNARK:<6.MONITOR>TTYSRV.MAC.107,  18-Oct-82 16:35:09 by PAETZOLD
;TCO 6.1320 - Make sure SAVELN in TTYDEA happens even after the TDCALL
; UPD ID= 1349, SNARK:<6.MONITOR>TTYSRV.MAC.106,  18-Oct-82 13:34:13 by COBB
;TCO 6.1315 - In TTYASC, don't let user assign TTY being CRJOB'd on
; UPD ID= 1331, SNARK:<6.MONITOR>TTYSRV.MAC.105,  13-Oct-82 06:51:31 by GRANT
;TCO 6.1309 - In GETSAL, change MOVEI to HRROI so disabled TTMSG% has proper format
;TCO 6. XXX - MOVE DEFINITIONS INTO TTYDEF.UNV
;TCO 6. XXX - CHANGES FOR CTERM
; UPD ID= 1258, SNARK:<6.MONITOR>TTYSRV.MAC.104,  29-Sep-82 08:20:48 by GRANT
;Typo in previous edit
; UPD ID= 1253, SNARK:<6.MONITOR>TTYSRV.MAC.103,  28-Sep-82 08:45:16 by GRANT
;TCO 5.1.1071 - limit the char. count given to TTMSG, this prevents overflowing
;the 6-bit field TSALC
; UPD ID= 1243, SNARK:<6.MONITOR>TTYSRV.MAC.102,  24-Sep-82 16:31:08 by PAETZOLD
;More TCO 6.1266 - fix a bug
; UPD ID= 1183, SNARK:<6.MONITOR>TTYSRV.MAC.101,  14-Sep-82 19:51:40 by PAETZOLD
;TCO 6.1266 - Do not allow control characters in non-prived TTMSGs
; UPD ID= 1176, SNARK:<6.MONITOR>TTYSRV.MAC.100,  14-Sep-82 10:53:07 by PAETZOLD
;TCO 6.1263 - Change TYLMD defstr so that it doesn't conflict with TTOCN
; Delete pre release 5 edit history
; UPD ID= 1100, SNARK:<6.MONITOR>TTYSRV.MAC.99,  19-Aug-82 17:52:28 by LEACHE
;TCO 6.1232 Change TTYX01 to TTYX03
; UPD ID= 1089, SNARK:<6.MONITOR>TTYSRV.MAC.98,  17-Aug-82 19:56:01 by LEACHE
;TCO 6.1229 - Make TTMSH1 clear SEND-ALL lock on insufficient privileges
; UPD ID= 1001, SNARK:<6.MONITOR>TTYSRV.MAC.97,  21-Jul-82 09:19:10 by WALLACE
;TCO 6.1105 - Remove conditional assembly of CTS Dynamic Data symbols
;  Use XBLTA in INITDB
; UPD ID= 983, SNARK:<6.MONITOR>TTYSRV.MAC.96,   9-Jul-82 11:59:32 by PAETZOLD
; TCO 5.1.1044 - Move TTXOFC to avoid stopping lines allready stopped
; UPD ID= 937, SNARK:<6.MONITOR>TTYSRV.MAC.95,  15-Jun-82 14:21:27 by WALLACE
;TCO 6.1170 - In routine TCOUBF, if the call to LCKTTY fails, then get
;  the internal line number from saved AC (Q1) rather than off of the
;  stack.
; UPD ID= 933, SNARK:<6.MONITOR>TTYSRV.MAC.94,  14-Jun-82 19:51:12 by PAETZOLD
;TCO 6.1169 - Prevent BADTTY BUGHLTs from TTDAL
; UPD ID= 850, SNARK:<6.MONITOR>TTYSRV.MAC.93,   6-Jun-82 13:29:18 by MURPHY
;TCO 6.1147 - Move bugdefs from BUGS.MAC to here and put them in-line.
; UPD ID= 799, SNARK:<6.MONITOR>TTYSRV.MAC.92,   1-Jun-82 08:30:59 by GRANT
;TCO 6.1148 - Prevent DECnet logins when remote logins are disallowed
; UPD ID= 792, SNARK:<6.MONITOR>TTYSRV.MAC.91,  26-May-82 20:11:25 by WALLACE
;TCO 6.1105 - Add Canonical Terminal Support
;  Add routine INITDB for initialization of a CTS Terminal Data Base
;  Define and initialize TTDBA, CTS Terminal Data Base Active flag
;  Add internal routine GETTYP in order to get terminal type faster
; UPD ID= 753, SNARK:<6.MONITOR>TTYSRV.MAC.90,  15-May-82 10:43:20 by MILLER
;FIxes fro TTPINI
; UPD ID= 752, SNARK:<6.MONITOR>TTYSRV.MAC.89,  15-May-82 10:20:21 by MILLER
;TCO 6.1066. ADD TTPINI FOR RSP LINES
; UPD ID= 733, SNARK:<6.MONITOR>TTYSRV.MAC.88,  11-May-82 17:44:16 by MURPHY
;More of same - call LODCFE instead of LOADFE.
; UPD ID= 690, SNARK:<6.MONITOR>TTYSRV.MAC.87,   4-May-82 18:03:29 by MURPHY
;TCO 6.1123 - Timeout job 0 TTY output.
; UPD ID= 665, SNARK:<6.MONITOR>TTYSRV.MAC.86,  27-Apr-82 16:51:47 by MURPHY
;TCO 6.1106 - TTWAKN
; UPD ID= 660, SNARK:<6.MONITOR>TTYSRV.MAC.85,  26-Apr-82 10:26:52 by MILLER
;TCO 6.1066. Add call to CLSTRO in STRTTO
; UPD ID= 648, SNARK:<6.MONITOR>TTYSRV.MAC.84,  15-Apr-82 22:52:33 by PAETZOLD
;More TCO 5.1772 - Take out the AC reference of the JRST in TCOU6
; UPD ID= 603, SNARK:<6.MONITOR>TTYSRV.MAC.83,   6-Apr-82 15:46:03 by PAETZOLD
;TCO 5.1772 - Handle short blocks in TCOU6 and TCOU7
; UPD ID= 579, SNARK:<6.MONITOR>TTYSRV.MAC.82,   2-Apr-82 14:16:03 by MURPHY
;TCO 6.1074 - REVISE BUILD PROCEDURES.
; UPD ID= 541, SNARK:<6.MONITOR>TTYSRV.MAC.81,  21-Mar-82 03:52:19 by PAETZOLD
;TCO 5.1767 - Make SALLI2 use LCKTT and ULKTT
; UPD ID= 521, SNARK:<6.MONITOR>TTYSRV.MAC.80,  17-Mar-82 14:37:20 by MILLER
; MORE OF THE SAME. PUT IN CODE FOR COBF OF CONSOLE LINES
; UPD ID= 492, SNARK:<6.MONITOR>TTYSRV.MAC.79,  15-Mar-82 13:12:22 by MILLER
; UPD ID= 465, SNARK:<6.MONITOR>TTYSRV.MAC.78,  11-Mar-82 17:18:24 by MILLER
; UPD ID= 457, SNARK:<6.MONITOR>TTYSRV.MAC.77,  11-Mar-82 11:46:13 by MILLER
;TCO 6.1066. Use XTRCH7 to do configuration-dependent line scanning
; UPD ID= 430, SNARK:<6.MONITOR>TTYSRV.MAC.76,   1-Mar-82 20:53:17 by PAETZOLD
;TCO 5.1691 - Mousetrap Q1 getting trashed in STRTTO from TTYQOC
; UPD ID= 419, SNARK:<6.MONITOR>TTYSRV.MAC.75,  22-Feb-82 17:56:08 by HALL
;TCO 6.1000 - Don't try to have DECnet terminals until NSP settles down
; UPD ID= 410, SNARK:<6.MONITOR>TTYSRV.MAC.74,  19-Feb-82 15:53:19 by MURPHY
;TCO 5.1733 - Don't translate ESC if .TTATE mode.
; UPD ID= 406, SNARK:<6.MONITOR>TTYSRV.MAC.73,  16-Feb-82 11:20:58 by HALL
;TCO 6.1000 -Change name of module for KC
; UPD ID= 400, SNARK:<6.MONITOR>TTYSRV.MAC.72,  13-Feb-82 15:24:51 by HALL
;TCO 6.1000 - Support the 2080
;	Set only .MCFLG and .PTFLG for now. Still need console lines
; UPD ID= 362, SNARK:<6.MONITOR>TTYSRV.MAC.71,  29-Jan-82 15:58:15 by MILLER
;TCO 5.1678. FIX CODE AT TTYASO, TTYASC AND TTSETL TO HANDLE TTACTL BETTER
; UPD ID= 351, SNARK:<6.MONITOR>TTYSRV.MAC.70,  25-Jan-82 16:43:54 by MURPHY
;Revise previous slightly.
; UPD ID= 331, SNARK:<6.MONITOR>TTYSRV.MAC.69,  20-Jan-82 09:20:53 by PAETZOLD
;TCO 5.1691 - prevent Q1 and Q2 trashing in TTYQOC
; UPD ID= 327, SNARK:<6.MONITOR>TTYSRV.MAC.68,  19-Jan-82 15:16:27 by MURPHY
;TCO 5.1688 - report noisy line only once.
; UPD ID= 316, SNARK:<6.MONITOR>TTYSRV.MAC.67,  18-Jan-82 14:55:59 by MILLER
;TCO 5.1678 again. Remove ATACTT routine
; UPD ID= 308, SNARK:<6.MONITOR>TTYSRV.MAC.66,  16-Jan-82 17:37:49 by MILLER
;TCO 5.1678. Add NOSKED to TTYDEA
; UPD ID= 298, SNARK:<6.MONITOR>TTYSRV.MAC.65,  14-Jan-82 04:20:21 by PAETZOLD
;More TCO 5.1665 - Fix problems with previous edit
; UPD ID= 294, SNARK:<6.MONITOR>TTYSRV.MAC.64,  13-Jan-82 14:27:53 by PAETZOLD
;TCO 5.1665 - Generate TTLOKB BUGHLT when TTLCK overdecrement detected
; detected in LCKTT, ULKTTY, and ULKTT
; UPD ID= 280, SNARK:<6.MONITOR>TTYSRV.MAC.63,   6-Jan-82 14:55:59 by PAETZOLD
;TCO 5.1655 - preserve C around the TDCALL in TTMS20
; UPD ID= 247, SNARK:<6.MONITOR>TTYSRV.MAC.62,  11-Dec-81 14:06:49 by PAETZOLD
;TCO 5.1635 - make sure we are NOINT at all times in STPAR even when we have to
;negotiate TELNET protocol options
; UPD ID= 229, SNARK:<6.MONITOR>TTYSRV.MAC.61,   3-Dec-81 10:48:24 by MURPHY
;TCO 5.1625 - Create job on CR and LF as well as ^C.

;	COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION 1976, 1990.
;	ALL RIGHTS RESERVED.
;
;	THIS SOFTWARE IS FURNISHED UNDER A  LICENSE AND MAY BE USED AND  COPIED
;	ONLY IN  ACCORDANCE  WITH  THE  TERMS OF  SUCH  LICENSE  AND  WITH  THE
;	INCLUSION OF THE ABOVE  COPYRIGHT NOTICE.  THIS  SOFTWARE OR ANY  OTHER
;	COPIES THEREOF MAY NOT BE PROVIDED  OR OTHERWISE MADE AVAILABLE TO  ANY
;	OTHER PERSON.  NO  TITLE TO  AND OWNERSHIP  OF THE  SOFTWARE IS  HEREBY
;	TRANSFERRED.
;
;	THE INFORMATION IN THIS  SOFTWARE IS SUBJECT  TO CHANGE WITHOUT  NOTICE
;	AND SHOULD  NOT  BE CONSTRUED  AS  A COMMITMENT  BY  DIGITAL  EQUIPMENT
;	CORPORATION.
;
;	DIGITAL ASSUMES NO  RESPONSIBILITY FOR  THE USE OR  RELIABILITY OF  ITS
;	SOFTWARE ON EQUIPMENT THAT IS NOT SUPPLIED BY DIGITAL.

	SEARCH PROLOG,TTYDEF,SCAPAR	;[7.1076]
	TTITLE	(TTYSRV,TTYSRV,< - Terminal Service Routines >)

	SALL
	Subttl	Table of Contents

;		     Table of Contents for TTYSRV
;
;				  Section		      Page
;
;
;    1. Definitions
;        1.1    Tables for each Line Type  . . . . . . . . . .   3
;        1.2    Default TTY Modes  . . . . . . . . . . . . . .   4
;        1.3    TDCALx Macros  . . . . . . . . . . . . . . . .   5
;    2. Once-Only Initialization . . . . . . . . . . . . . . .   7
;    3. Line Number/Address Conversion . . . . . . . . . . . .  16
;    4. Allocation/Deallocation  . . . . . . . . . . . . . . .  22
;    5. JSYS Support Routines  . . . . . . . . . . . . . . . .  33
;    6. Full Wake-Up Classes Support . . . . . . . . . . . . .  65
;    7. TTMSG JSYS . . . . . . . . . . . . . . . . . . . . . .  70
;    8. STO JSYS . . . . . . . . . . . . . . . . . . . . . . .  88
;    9. STTYP/GTTYP JSYSes . . . . . . . . . . . . . . . . . .  91
;   10. STPAR JSYS . . . . . . . . . . . . . . . . . . . . . .  93
;   11. TLINK JSYS . . . . . . . . . . . . . . . . . . . . . .  95
;   12. Miscellaneous Global Routines  . . . . . . . . . . . . 108
;   13. Buffer Control . . . . . . . . . . . . . . . . . . . . 120
;   14. Character Information Table (CHITAB) . . . . . . . . . 123
;   15. TCO (First Level Output) . . . . . . . . . . . . . . . 126
;   16. TCOY (Second Level Output) . . . . . . . . . . . . . . 132
;   17. TCOY For Control Characters  . . . . . . . . . . . . . 136
;   18. TCOUT (Third Level Output) . . . . . . . . . . . . . . 143
;   19. TCI (Get Char From Input Buffer) . . . . . . . . . . . 153
;   20. Miscellaneous Routines . . . . . . . . . . . . . . . . 160
;   21. TTCH7 (Empty TTBBUF, Process TTCS Words) . . . . . . . 163
;   22. TTCHI (Move Char From TTBBUF To Input Buffer)  . . . . 175
;   23. TTEMES (Send Short Message)  . . . . . . . . . . . . . 196
;   24. BIGSTO (Store Char In TTBBUF)  . . . . . . . . . . . . 198
;   25. TTSNDO (Non-Interrupt Character Send)  . . . . . . . . 200
;   26. TTSND (Send Character To Line) . . . . . . . . . . . . 203
;   27. PTY Device Dependent Code  . . . . . . . . . . . . . . 211
;   28. End of TTYSRV  . . . . . . . . . . . . . . . . . . . . 215
	SUBTTL Definitions -- Tables for each Line Type

;TABLE OF INSTRUCTIONS TO SET/CLEAR PARITY BIT AS FUNCTION OF LINE TYPE

PARTBL:	TRO T1,200		;FE
	TRZ T1,200		;MC
	TRO T1,200		;PT
	TRZ T1,200		;TV
	TRZ T1,200		;CH
	TRZ T1,200		;LH
IFN .-PARTBL-NLTYPS,<PRINTX %PARTBL SIZE DOES NOT AGREE WITH NLTYPS>

;SIZE OF DYNAMIC DATA BASE TO BE ALLOCATED

DDLTBL:	TTDDLN			;FE
	TTMCLN			;MC
	TTDDLN			;PT
	TVTLEN			;TV
	TTDDLN			;CH
	TTDDLN			;LH
IFN .-DDLTBL-NLTYPS,<PRINTX %DDLTBL SIZE DOES NOT AGREE WITH NLTYPS>


;TABLE TO CONVERT INTERNAL LINE TYPES TO EXTERNAL (USER USABLE) LINE TYPES

	SWAPCD			;THIS TABLE CAN BE SWAPPABLE

LTYTAB::NW%FE 			;[9072] FE - Table now global
	NW%MC 			;MC
	NW%PT 			;PT
	NW%TV 			;TV
	NW%CH 			;CH
	NW%LH 			;LH
IFN .-LTYTAB-NLTYPS,<PRINTX %LTYTAB SIZE DOES NOT AGREE WITH NLTYPS>

	RESCD			;BACK TO RESIDENT STORAGE
	SUBTTL Definitions -- Default TTY Modes
	RESCD

;INDEX TO DEV TABLES FOR TTY0

DEVTT0:: DVXTT0


;USUAL DEVICE FLAGS AND STATUS
; 66 LINES/PAGE, 75 CHARS/LINE
; WAKEUP ON ALL, ECHO MODE 2 (DEFERRED OR IMMED), Refuse Links
; DATA MODE ASCII, 'RAISE' LC INPUT (ALSO CONVERTS OLD-STYLE ALT-MODES)

NORMTF::^D66B10+^D72B17+17B23+2B25+1B29+1B31+TT%PGM ;[9041]
NORMTY::.TTDEF			;[7.1230] Non-CTY terminal type
CTYTY:: .TT120			;[7.1230] CTY terminal type defaults to LA120

TAB81::	EXP 1B0+1B8+1B16+1B24+1B32
TAB82::	EXP 1B4+1B12+1B20+1B28
TAB83:	EXP 1B0+1B8+1B16+1B24+1B32

;NORMAL CONTROL CHARACTER SETTINGS

TTICB1::BYTE (2) 0,1,1,1,1,1,1,2,1,2,3,1,1,2,1,1,1,1
TTICB2::BYTE (2) 1,1,1,1,1,1,1,1,1,3,1,1,1,1


;	DEFAULT DEFINITIONS FOR TERMINAL WAKE-UP

TTWKDF:	EXP -20			;WAKE-UP ON ALL CHARACTERS
	EXP -20
	EXP -20
	EXP -20

;POINTERS TO TERMINAL TYPE FIELDS
;ASSUME TYPE NUMBER IN 3

TTMBIT:	POINT 3,TTYPE0(3),2	;MECHANICAL BITS
TTCRPD:	POINT 4,TTYPE0(3),7	;CR PADDING FOR FULL LINE
TTLFPD:	POINT 4,TTYPE0(3),11	;LF PADDING FOR ONE LINE
TTTBPD:	POINT 4,TTYPE0(3),15	;TAB PAD FOR 4 SPACES
TTFFPD:	POINT 4,TTYPE0(3),19	;FF PAD FOR FULL PAGE
TTTWID:	POINT 8,TTYPE0(3),27	;WIDTH OF LINE
TTTLEN:	POINT 8,TTYPE0(3),35	;LENGTH OF PAGE

CTRLOF::0			;NEW CTRL-O HANDLING POSSIBLE
	SUBTTL Definitions -- TDCALx Macros

;This code supports a number (NLTYPS) of different types of terminals.  The
;general code is in this module (TTYSRV), and there is another module for each
;terminal type which contains the device-dependent code for that type.  Device
;dependent code is called via a macro defined below.

;The macro accepts a list of pairs, where each pair indicates a line type and a
;routine to be called for that type.  If no specification is given for a line
;type, control passes through the TDCALL with no effect.

;TDCALL - Macro to do the device dependent subroutine call.
;Use:
;	TDCALL S,<list>,default
;	 or
;	TDCALL D,<list>,default
; where
;  S indicates that a static pointer is in T2,
;  D indicates that a dynamic pointer is in T2.
;  list is the list of dispatches for this function
;	where each item is a pair of the form <ty,adr>, where
;	  ty = one of the set FE, MC, PT, CH, LH indicating
;		the line type for which the adr is relevant
;	  adr = the address of a routine to CALL for this type
;  default, if present, is the instruction to assemble in the absence
;	of the line type and/or the line case

;The macros ultimately assemble something of the form:
;	LOAD CX,line-type
;	CALL [	JRST FECASE
;		JRST MCCASE
;		..
;		JRST DZCASE](CX)
;where the literal must be exactly NLTYPS long and must be in the proper order.
;If no specification is found for a particular line type, a RET (or the
;default) is assembled in that literal location.  There is also a variant
;(TDCALX) if the line type is already in an AC.
DEFINE TDCALL (DT,VECTOR,DEFLT)<
  IFIDN <DT><S>,<LOAD CX,TTSTY,(T2)>
  IFIDN <DT><D>,<LOAD CX,TLTYP,(T2)>
  IFDIF <DT><S>,<		;;[7.1230]
	IFDIF <DT><D>,<		;;[7.1230]
		PRINTX ? Bad use of TDCALL "DT,VECTOR,DEFLT">> ;;[7.1230]
	CALL [..TDC1 (<VECTOR>,<FE,MC,PT,TV,CH,LH>,<DEFLT>) ](CX)
  >

DEFINE ..TDC1 (VECTOR,TYLST,DEFLT)<
  IRP TYLST,<
    ..F==0			;;FLAG TO SEE IF HAVE THIS TYPE
    IRP VECTOR,<..TDC2 (VECTOR,TYLST)>	;;SEE IF MATCH AND ASSEMBLE DISPATCH
    IFE ..F,<
      IFNB <DEFLT>,<DEFLT>
      IFB <DEFLT>,<RET>
    >>>

DEFINE ..TDC2 (VECTOR,LTY)<..TDC3 (VECTOR,LTY)>

DEFINE ..TDC3 (TY,ADR,LTY)<
  IFIDN <TY><LTY>,<
     ..F=1			;;NOTE ASSEMBLED WORD HERE
     JRST ADR>>


;VARIENT MACRO USED IF LINE TYPE ALREADY IN AC

DEFINE TDCALX (AC,VECTOR,DEFLT)<
	CALL [..TDC1 (<VECTOR>,<FE,MC,PT,TV,CH,LH>,<DEFLT>) ](AC)>
	SUBTTL Once-Only Initialization

;INITIALIZATION. CALLED FROM STG AT SYSTEM STARTUP

	RESCD			;MUST BE RESIDENT

;INITIALIZE CHAIN OF LINE BUFFERS.  LINE BUFFERS ARE OF SIZE TTSIZ.
;THIS CODE MAKES WORD 0 OF BUFFER N CONTAIN THE ADDRESS OF BUFFER N-1
;AND TTFREB CONTAIN THE ADDRESS OF THE HIGHEST-NUMBERED BUFFER

TTINIT::MOVEI 1,TTBUFS		;COMPUTE BEGINNING OF BUFFERS
	SETOM TTQCNT		;INIT SCAN COUNT
	TRNE 1,TTSIZ-2		; TO BE N*TTSIZ+1
	ADDI 1,TTSIZ		;FIRST WORD IN BUFFER AREA
	ANDCMI 1,TTSIZ-1	;WHICH IS 0 MOD TTSIZ
	ADDI 1,1		;SUCH THAT EACH BUFFER ENDS 0 MOD ADR
	MOVEI 2,NTTBF
	MOVEM 2,TTFREC		;FREE BUFFER COUNT
	SUBI 2,1
	MOVEM 1,TTSIZ(1)	;CONSTRUCT LIST OF FREE BUFFERS
	ADDI 1,TTSIZ
	SOJG 2,.-2
	MOVEM 1,TTFREB		;FREE BUFFER LIST

;INITIALIZE THE STATIC DATA FOR ALL LINES. TTSPWD IS DONE BY DTEINI

	SETOM SALLCK		;INIT SENDALL LOCK
	MOVEI T1,NLINES		;DO ALL LINES
	SETZ T2,		;START WITH LINE 0
TTINI1:	SETZM TTSTAT(T2)	;CLEAR STATUS WORD
	MOVEI T3,MXFECC		;GET DEFAULT LINE ALLOCATION
	STOR T3,TSFMC,(T2)	; AND SAVE IT FOR THIS LINE
	SETZM TTACTL(T2)	;NO DYNAMIC DATA YET
	AOS T2			;GO TO NEXT LINE
	SOJG T1,TTINI1		; UNTIL ALL LINES ARE DONE
	;..
;THIS CODE ESTABLISHES THE TYPE OF EACH LINE. LINES OF A TYPE ARE ASSIGNED
;CONSECUTIVELY, STARTING WITH LINES THAT ARE LOCAL TO THE MACHINE.  THIS
;CODE STORES THE LINE TYPE WITH THE LINE AND SETS UP TT1LIN
;FOR EACH TYPE TO CONTAIN THE NUMBER OF THE FIRST LINE.

	;..
	MOVEI T2,0		;T2/ FIRST LINE IS LINE 0
	MOVEI T3,TT.FE		;T3/ CODE FOR FRONT-END LINES
	MOVEI T4,NTTFE		;T4/ NUMBER OF FRONT END LINES
	CALL SETTYP
	MOVEI T3,TT.MCB		;T3/ CODE FOR MCB LINES
	MOVEI T4,NTTMCB		;T4/ NUMBER OF MCB LINES
	CALL SETTYP
	MOVEI T3,TT.PTY		;T3/ CODE FOR PSEUDO-TERMINALS
	MOVEI T4,NTTPTY		;T4/ NUMBER OF PTY'S
	CALL SETTYP
	HRLI T4,-NTTTVT		;NUMBER OF TVTs
	HRR T4,T2		;FIRST TVT LINE
	MOVEM T4,TVTPTR		;SAVE AOBJN AC FOR TVTs
	MOVEI T3,TT.TVT		;T3/ CODE FOR TCP LINES
	MOVEI T4,NTTTVT		;T4/ NUMBER OF TVTs
	CALL SETTYP
	MOVEI T3,TT.CTH		;T3/ CODE FOR CTERM HOST LINES
	MOVEI T4,NTTCTH		;T4/ NUMBER OF CTERM HOST LINES
	CALL SETTYP
	MOVEI T3,TT.LAH		;CODE FOR LAT HOST LINES
	MOVEI T4,NTTLAH		;NUMBER OF LAT HOST LINES
	CALL SETTYP		;

;INITIALIZE POINTERS TO TTBBUF

	SETZM TTBIGO
	SETZM TTBIGC
	SETZM TTBIGI

	SETZM TTCQLN		;INITIALIZE FOR TTHNG4

   REPEAT 0,<			;WAS ONLY USED FOR DZ'S

	SAVEAC <Q1>
	MOVSI Q1,-NLTYPS	;FIND NUMBER OF LINE TYPES
TYINLP:	TDCALX Q1,<>,<RET>
	AOBJN Q1,TYINLP		;DO ALL TYPES

   >;END OF REPEAT 0

	CALLRET TTSTRT
;SETTYP - SET THE TERMINAL TYPE FOR A GROUP OF LINES

;ACCEPTS:
;	T2/ CURRENT LINE NUMBER (FIRST FOR THIS TYPE)
;	T3/ LINE TYPE
;	T4/ NUMBER OF LINES OF THIS TYPE

;	CALL SETTYP

;RETURNS +1: ALWAYS
;		T2/ UPDATED LINE NUMBER (FIRST LINE OF NEXT TYPE)

SETTYP:	JUMPG T4,SETTY2		;IF NO LINES OF THIS TYPE,
	SETOM TT1LIN(T3)	;SET FIRST LINE TO -1
	RET			; AND RETURN

SETTY2:	MOVEM T2,TT1LIN(T3)	;STORE FIRST LINE FOR THIS TYPE
SETTY1:	STOR T3,TTSTY,(T2)	;SAVE LINE TYPE FOR THIS LINE
	AOS T2			;NEXT LINE NUMBER
	SOJG T4,SETTY1		;GO DO THE NEXT LINE IN THIS TYPE
	CAMN T3,CTYTYP		;IS THIS THE LINE TYPE FOR THE CTY?
	JRST [	CALL INICTY	;YES. INITIALIZE IT
		AOS T2		;POINT TO NEXT LINE
		RET]
	RET
;INICTY - INITIALIZE THE CTY

;ACCEPTS:
;	T2/ INTERNAL LINE NUMBER
;	T3/ LINE TYPE

;	CALL INICTY

;RETURNS +1: ALWAYS

;CTY IS A SPECIAL CASE. IT IS ALWAYS LINE 'CTYLNO', AND ITS DYNAMIC DATA
;IS PERMANENTLY ALLOCATED. CTYUNT AND CTYINT WILL BE FIXED BY IDCTY.

INICTY:	SAVET
	MOVEM T2,CTYLNO		;SAVE INTERNAL LINE NUMBER
	HRLM T3,CTYLNO		;SAVE THIS TOO
	SETOM CTYINT		;INITIALIZE INTERNAL EQUIVALENT OF ACTUAL
				; CTY LINE ON .FEDLS DEVICE
	HRRZ T1,DDLTBL(T3)	; AND FULL LENGTH BLOCK
	HRLI T1,.RESP1		;INDICATE NOT SWAPPABLE
	MOVX T2,RS%SE0!.RESTP	;WE'RE RUNNING IN SECTION 0 HERE
	CALL ASGRES		;GET RESIDENT SPACE
	 BUG.(HLT,NOCTY,TTYSRV,SOFT,<Unable to allocate data for CTY>,,<

Cause:	During initialization of terminal lines, a call to ASGRES was made to
	get resident free space for the CTY's data base.  The call got a
	failure return - no free space available.
>)
	HRRZ T2,CTYLNO		;T2/ LINE NUMBER, T1/ ADDRESS OF BLOCK
	HLRZ T3,CTYLNO		;RECOVER LINE TYPE
	STOR T3,TTSTY,(T2)
	HRRZS CTYLNO		;FIX UP WORD
	CALL TTSETL		;[7.1230] (T1,T2/) Set initial dynamic data
	SKIPN SAVTRE		;[7.1230] Saving trees?
	IFSKP.			;[7.1230] If so, set line type from CTYTY
	  MOVE T3,CTYTY		;[7.1230] Load CTY line type
	  STOR T3,TTTYP,(T1)	;[7.1230]  and save it in dynamic data
	  LDB T4,TTTWID		;[7.1230] Load that type's width
	  STOR T4,TPWID,(T1)	;[7.1230] Store CTY's width in dynamic data
	  LDB T4,TTTLEN		;[7.1230] Load that type's length
	  STOR T4,TPLEN,(T1)	;[7.1230] Store CTY's length in dynamic data
	  LDB T4,TTMBIT		;[7.1230] Get mechanical (fill) bits
	  DPB T4,[POINT 3,TTFLGS(T1),3]	;[7.1230] Store where STTYP would
	ENDIF.			;[7.1230] End of saving trees code
	SETZRO TT%ALK,TTFLGS(T1) ;[7.1230] Set CTY to refuse links (and advice)
	SETONE TTPRM,(T1)	;DON'T DEALLOCATE THIS DYNAMIC DATA
	MOVEM T1,TTACTL(T2)	;POINT TO DYNAMIC DATA
	RET
;TTSET - SET INITIAL VALUES FOR A LINE

;ACCEPTS:
;	T1/ ADDRESS OF DYNAMIC DATA
;	T2/ LINE NUMBER

;CALL TTSET

;RETURNS +1: ALWAYS
;Leaves TTACTL unchanged to protect against state changes
; * * * *
;NEEDS WORK - CAN'T INIT TOO MANY WORDS
; * * * *

TTSETL:	LOAD T4,TTSTY,(T2)	;GET THE LINE TYPE
	MOVE T4,DDLTBL(T4)	;GET LONG BLOCK LENGTH
	JRST TTSET

TTSETS:
TTSETM:	MOVEI T4,MSGLEN		;INDICATE MESSAGE BLOCK
	JRST TTSET

TTSET:	SAVEQ
	TDCALL S,<<FE,TTSETF>>	;INIT STUFF FOR RSX20F
	LOAD T3,TTSTY,(T2)	;GET LINE TYPE FROM STATIC
	STOR T3,TLTYP,(T1)	; AND COPY TO DYNAMIC
	MOVE Q1,NORMTY		;GET NORMAL TERMINAL TYPE
	STOR Q1,TTTYP,(T1)	;SET IN DYNAMIC DATA
	STOR T2,TINTL,(T1)	;MAKE DYNAMIC DATA POINT TO STATIC
	MOVE T3,IBFRC		;GET DEFAULT BUFFER CONTROL
	MOVEM T3,TTBFRC(T1)	; AND STORE IN DYNAMIC DATA
	CAIN T4,MSGLEN		;IS THIS A MESSAGE-LENGTH BLOCK?
	RET			;YES. NO MORE INITIALIZATION
;TTSET...

	CAME T2,CTYLNO		;CTY ASSIGN?
	CALL SETOBF		;NO, SET OUTPUT BUFFER COUNTS
	SETONE TTIPSI,(T1)	;SET NO PSI
	SETONE TTOPSI,(T1)	;INPUT OR OUTPUT
	SETONE TTPSFK,(T1)	;AND NO FORK
FTCTS <	SETZRO TTDBA,(T1)	;No CTS Terminal Data Base
>				;End of Conditional Assembly
	MOVE Q1,TTICB1		;SETUP USUAL CONTROL CHARACTER MODES
	MOVEM Q1,FCMOD1(T1)
	MOVE Q1,TTICB2
	MOVEM Q1,FCMOD2(T1)
	SETOM TTLINK(T1)	;NO LINKS TO OTHER LINES
	SETZRO <MO%NUM+MO%NTM>,T3 ;[7256] Mask for user messages and inhibit
	CALL TTSNTF		;[7256] Clear them on job startup
	MOVE Q1,NORMTF		;USUAL DEVICE FLAGS AND STATUS
	LOAD T3,TTSTY,(T2)	;GET TYPE OF LINE AGAIN
	CAIN T3,TT.PTY		;IS IT A PTY?
	TXZ Q1,TT%PGM		;YES. NO XON/XOFF THEN
	LOAD T3,TT%WID,Q1	;GET STANDARD WIDTH
	LOAD T4,TT%LEN,Q1	;GET LENGTH
	SETZRO <TT%WID,TT%LEN>,Q1 ;CLEAR OUT THESE VALUES
	DPB Q1,[POINT 35,TTFLGS(T1),35] ;STORE STANDARD VALUES IN DYNAMIC DATA
	PUSH P,T2		;SAVE
	MOVE T2,T1
	STOR T3,TPWID,(T2)	;SET UP STANDARD WIDTH
	STOR T4,TPLEN,(T2)	;STORE PAGE LENGTH
	MOVEI T3,PGMOC2		;SET DEFAULT PAGE UNPAUSE CHARACTER
	TDCALL D,<<MC,RSKP>,<CH,RSKP>,<LH,RSKP>> ;DECNET NVT, CTERM, OR LAT ?
	 MOVEI T3,PGMONC	;NO, USE SAME AS COMMAND UNPAUSE
	STOR T3,TTUPC,(T2)
	TDCALL D,<<MC,RSKP>,<CH,RSKP>,<LH,RSKP>> ;DECNET NVT, CTERM, OR LAT ?
	 MOVEI T3,PGMOFC	;NO, USE SAME AS COMMAND PAUSE
	STOR T3,TTPPC,(T2)
	SETONE TWFRK,(T2)	;INDICATE NO FORK WAITING
	MOVE Q1,JOBNO		;GET THIS JOB NUMBER
	STOR Q1,TCJOB,(T2)	;INDICATE THAT IT OWNS THE TERMINAL
	SETONE TTPFK,(T2)	;NO SCTTY FORK YET
	SETZRO TTDEV,(T2)	;CLEAR THE DEVICE-DEPENDENT WORD
	XMOVEI T1,TTWKDF	;POINT TO DEFAULT 4-WORD MASK
	CALL TTSBM		;GO SET IT
	SETZ T1,		;TURN OFF FIELD WIDTH
	CALL TTSFW
	MOVE T1,T2		;RESTORE T1
	POP P,T2		;RESTORE T2
	RET
;TTSTRT - ACTIVATE ALL LINES.  USED ON RESTART AS WELL AS START

TTSTRT:	SETZM TTHNGT
	SETZM TTHNGN

   REPEAT 0,<			;WAS ONLY USED FOR DZ'S

	SAVEQ			;SAVE REGISTERS
	MOVSI Q1,-NLTYPS	;GET THE COUNT OF TYPES
TYRSLP:	; TDCALX Q1,<>,<RET>
	AOBJN Q1,TYRSLP		;DO ALL LINES

   >;END OF REPEAT 0

	RET


;TTRSET - RESUME RUNNING TTY'S AFTER POWER FAILURE

;* * * *
;DON'T DO THIS FOR FE LINES.  MAYBE REMOVE ALL OF IT
; * * * *

;THIS CODE HANDLES ALL LINES. IN FACT, NON-PHYSICAL LINES WON'T HAVE
;TTOTP SET, SO TTSND0 WILL NOT BE CALLED FOR THEM

TTRSET::MOVSI 2,-NLINES		;DO ALL LINES
TTRST1:	PUSH P,T2		;SAVE LINE NUMBER
	CALL STADY		;IS LINE ACTIVE?
	 JRST TTRST2		;NOT AT ALL
	JE TTOTP,(T2),TTRST2	;ACTIVE IN SOME WAY. WAS OUTPUT IN PROGRESS?
	SETZRO TTOTP,(T2)	;YES, CLEAR FLAG SO IT WILL GET RESTARTED
	CALL TTSND0		;RESTART IT
TTRST2:	POP P,T2		;RESTORE COUNTER AND LINE NUMBER
	AOBJN 2,TTRST1
	CALLRET TTSTRT		;ACTIVATE DATASETS, ETC.
;INITDB - Initialize CTS Terminal Data Base
;T1/ Monitor Address of Data Base
;T2/ Terminal Line Number
;	CALL INITDB
; Returns +1: Failure
;  T1/ Error Code
; Returns +2: Success

	FTCTS <
INITDB::STKVAR <DYNDAT,LINNUM>	;Allocate some temporary storage
	MOVE T4,T1		;Save address of data base
	MOVEM T2,LINNUM		;Save the line number
	CALL LCKTTY		;Lock the Dynamic Data
	 RETBAD			;Pass failure to caller
	LOAD T3,TTDBA,(T2)	;Get flag for Data Base Active
	SKIPN T3		;Test if Data Base already Active
	 IFSKP.			;If Data Base is already active
	  CALL ULKTTY		;  unlock the Dynamic Data
	  RETSKP		;  and give successful return
	 ENDIF.
	MOVEM T2,DYNDAT		;Save address of the Dynamic Data
	MOVEI T1,TDBSIZ*PGSIZ-1	;Get size of data base area (minus one, because
				;  we clear first word ourselves)
	MOVE T2,T4		;Get address of source block
	SETZM (T2)		;Clear first source word
	MOVE T3,T2		;Get address of
	AOJ T3,			;  destination block
	CALL XBLTA		;Clear and forcibly LOCK the data base
	MOVE T1,LINNUM		;Get the line number
	ADDI T1,.TTDES		;Form a terminal designator
	MOVEM T1,.TDIOJ(T4)	;Initialize terminal designator in data base
	SETOM .TDLOK(T4)	;Unlock the data base
	MOVE T2,DYNDAT		;Get address of the Dynamic Data
	SETONE TTDBA,(T2)	;Say Terminal Data Base is Active
	CALL ULKTTY		;Unlock the Dynamic Data
	RETSKP			;Give successful return
	ENDSV.			;End STKVAR Range
>				;End of Conditional Assembly
;THE FOLLOWING ROUTINES PROVIDE THE MECHANISM FOR INSURING THAT A LINE
;REMAINS ACTIVE (AND THUS THE ADDRESS OF ITS DYNAMIC DATA REMAINS VALID)
;WHILE ITS DYNAMIC DATA IS BEING USED.  TO ADDRESS A LINE'S DYNAMIC DATA
;FROM PROCESS CONTEXT, DO THE FOLLOWING:

;1. CALL LCKTTY, WHICH WILL INCREMENT THE LOCK COUNT IN THE LINE'S DYNAMIC
;DATA AND RETURN NOINT.

;2. IF A DISMISS MUST BE DONE, CALL TTYDIS, WHICH WILL PLACE AN ENTRY ON THE
;JOB'S JSB STACK AND GO OKINT.  AT THIS POINT THE USER CAN CTRL/C, IN
;WHICH CASE THE PROCESSING OF THE JSB STACK WILL DECREMENT THE LINE'S
;LOCK COUNT.

;3. WHEN THE DISMISS COMPLETES, CALL TTYAWK, WHICH WILL REMOVE THE STACK
;ENTRY AND RETURN NOINT

;4. WHEN THE DYNAMIC DATA IS NOT LONGER NEEDED, CALL ULKTTY, WHICH WILL
;DECREMENT THE LOCK COUNT AND RETURN OKINT.

;WHEN ADDRESSING DYNAMIC DATA FROM SCHEDULER CONTEXT, CALLING LCKTTY
;AND ULKTTY IS LEGAL BUT DOES NOT INCREMENT THE COUNT.  IT IS ASSUMED
;THAT THE DYMAMIC DATA WILL NOT DISAPPEAR WHILE THE SCHEDULER IS RUNNING.
;THEREFORE, CALLING STADYN WILL HAVE THE SAME EFFECT; I.E. CONVERTING
;LINE NUMBER TO ADDRESS OF DYNAMIC DATA

;IF THE DYNAMIC DATA IS TO BE ADDRESSED OVER A VERY SHORT PERIOD, THE
;CALLER CAN GO NOSKED, CALL STADYN, ADDRESS THE DATA, AND THEN GO
;OKSKED
	SUBTTL Line Number/Address Conversion

;STADYN - CONVERT STATIC LINE NUMBER TO DYNAMIC ADDRESS

;ACCEPTS:
;	T2/ INTERNAL LINE NUMBER

;	CALL STADYN

;RETURNS +1: LINE DOES NOT HAVE FULL-SIZED DYNAMIC DATA BASE,
;		T2/ -1 IF LINE IS BECOMING ACTIVE
;			OR
;		T2/ 0 IF LINE IS TOTALLY INACTIVE
;			OR
;		T2/ ADDRESS OF DYNAMIC DATA BLOCK IF BLOCK IS NONSTANDARD
;	+2: LINE HAS FULL-SIZED DYNAMIC DATA BASE,
;		T2/ ADDRESS OF DYNAMIC DATA BLOCK

;CLOBBERS NO AC'S

;CALLER SHOULD INSURE THAT THE TERMINAL'S DATA CANNOT GO AWAY EITHER
;BY BEING NOSKED OR BY CALLING LCKTTY

STADYN::SKIPLE T2,TTACTL(T2)	;HAVE A BLOCK?
	RETSKP			;YES. FULLY ACTIVE LINE
	CAME T2,[-1]		;NO. IS IT BECOMING ACTIVE?
	TXZ T2,TTSHBK		;NO. IS MESSAGE OR SHORT. RETURN IT
	RET			;DONE

;VARIENT OF ABOVE - RETURNS +1 IF NO BLOCK PRESENT, +2 IF ANY BLOCK PRESENT

STADY::	SKIPLE T2,TTACTL(T2)	;FULL BLOCK?
	RETSKP			;YES
	CAME T2,[-1]
	TXZ T2,TTSHBK
	JUMPG T2,RSKP		;RETURN +2 IF ANY BLOCK
	RET

;DYNSTA - CONVERT ADDRESS OF STATIC DATA BASE TO INTERNAL LINE NUMBER

;ACCEPTS: T2/ ADDRESS OF STATIC DATA BASE

;	CALL DYNSTA

;RETURNS +1: ALWAYS,
;		T2/ INTERNAL LINE NUMBER

DYNSTA::LOAD T2,TINTL,(T2)	;GET FROM DYNAMIC DATA
	RET			;RETURN
;LCKTTY - GET ADDRESS OF DYNAMIC DATA AND PREVENT DEALLOCATION

;ACCEPTS:
;	T2/ INTERNAL LINE NUMBER

;	CALL LCKTTY

;RETURNS +1: LINE DOES NOT HAVE FULL-SIZED DYNAMIC DATA BASE,
;		T2/ -1 IF LINE IS BECOMING ACTIVE
;			OR
;		T2/ 0 IF LINE IS TOTALLY INACTIVE
;			OR
;		T2/ ADDRESS OF DYNAMIC DATA BLOCK IF BLOCK IS NONSTANDARD
;	+2: LINE HAS FULL-SIZED DYNAMIC DATA BASE,
;		T2/ ADDRESS OF DYNAMIC DATA BLOCK

;NOTE THAT THE CALLER MUST CALL ULKTTY BEFORE THE DATA BLOCK CAN BE
;DEASSIGNED. ULKTTY WILL ACCEPT ANY OUTPUT FROM LCKTTY, SO IF THE CALLER
;IS INTERESTED ONLY IN FULLY ACTIVE BLOCKS, IT SHOULD CALL ULKTTY EVEN
;IF LCKTTY TAKES A NON-SKIP RETURN

;CLOBBERS NO AC'S

LCKTTY::NOSKD1			;NO OTHER JOBS RUNNING UNTIL DATA LOCKED
	SKIPG T2,TTACTL(T2)	;ANY DATA BASE AT ALL?
	JRST [	SKIPE T2	;NOT FULLY ACTIVE. IS IT ASSIGNED?
		CAMN T2,[-1]	;OR BECOMING ACITVE?
		RETBAD (,<OKSKD1>) ;NOT A BLOCK
		TXZ T2,TTSHBK	;MESSAGE OR SHORT. MAKE IT ADDRESSABLE
		CALLRET LCKTT]	;LOCK IT
	CALL LCKTT		;LINE IS FULLY ACTIVE. DO THE LOCKING
	RETSKP			;INDICATE FULL-LENGTH BLOCK
;LCKTT - DO THE REAL LOCKING

;ACCEPTS:
;	T2/ ADDRESS OF DYNAMIC DATA

;	CALL LCKTT

;RETURNS +1: ALWAYS, NOINT

;PRESERVES ALL AC'S

LCKTT:	SETZRO TTDAL,(T2)	;FLUSH DEALLOCATE REQUEST IF ANY
	SKIPE INSKED		;DON'T LOCK IF IN SCHEDULER
	RET
	NOINT			;BE NOINT WHILE LINE IS LOCKED
LCKTT1:	INCR TTLCK,(T2)		;BUMP THE LOCK
	JE TTLCK,(T2),LCKTT2	;CHECK FOR BAD LOCK
	OKSKD1			;ALLOW SCHEDULING ONCE LOCKED
	RET
LCKTT2:				;HERE TO HANDLE BAD LOCK
	BUG.(HLT,TTLOKB,TTYSRV,SOFT,<TTLCK - Bad TTY lock>,,<

Cause:	The monitor tried to lock a TTY line and discovered the lock count was
	overdecremented.
>)
	JRST LCKTT1		;HANDLE IF WE ARE CONTINUED FROM BUGHLT
;ULKTTY - CLEAR LOCK BIT

;ACCEPTS:
;	T2/ OUTPUT FROM LCKTTY

;	CALL ULKTTY

;RETURNS +1: ALWAYS, OKINT

;CLOBBERS NO AC'S

ULKTTY::SKIPN INSKED		;DON'T DECREMENT COUNT IF IN SCHEDULER
	SKIPG T2		;NO COUNT IF INACTIVE OR BECOMING ACTIVE
	RET
	JE TTLCK,(T2),ULKTMP	;CHECK FOR OVERLY DECREMENTING
	DECR TTLCK,(T2)		;DECREMENT LINE'S LOCK COUNT
	IFQN. TTDAL,(T2)	;DID SOMEBODY TRY TO DEALLOCATE THIS?
	  CALL TTYDED		;YES, DO IT NOW
	   NOP
	ENDIF.
	OKINT			;ALLOW INTERRUPTS NOW THAT BLOCK IS UNLOCKED
	RET

ULKTMP:	SAVELN
	LOAD T2,TINTL,(T2)
	BUG.(CHK,ULKBAD,TTYSRV,SOFT,<Unlocking TTY when count is zero>,<<T2,TTYLIN>>,<

Cause:	A call has been made to ULKTTY to unlock a terminal but the lock count
	is already zero.  This indicates a coding problem.

Action:	If this BUGCHK is reproducible, set it dumpable and submit an SPR with
	the dump and instructions on reproducing the problem.

Data:	TTYLIN - TTY line number
>)
	OKINT
	RET
;ULKTT - DECREMENT THE LOCK COUNT. CALLED ONLY FROM FREE

ULKTT::	JE TTLCK,(T2),ULKTT2	;CHECK FOR BAD UNLOCK
	DECR TTLCK,(T2)		;UNLOCK THE TTY
ULKTT1:	IFQN. TTDAL,(T2)	;DID SOMEBODY TRY TO DEALLOCATE THIS?
	  CALL TTYDED		;YES, DO IT NOW
	   NOP
	ENDIF.
	RET
ULKTT2:				;HERE ON BAD UNLOCK
	BUG.(CHK,TTULKB,TTYSRV,SOFT,<Bad TTY unlock in ULKTT>,,<

Cause:	The monitor tried to unlock the TTY and it was already unlocked.

Action:	If this BUGCHK is reproducible, set it dumpable and submit an SPR with
	the dump and instructions on reproducing the problem.
>)
	JRST ULKTT1		;HANDLE IF CONTINUE AFTER BUGHLT
;ROUTINES TO ADJUST LOCK STATUS BEFORE AND AFTER DISMISSING.
;THIS CODE PUTS AN ENTRY ON THE JSB STACK IN THE EVENT THE PROCESS
;IS INTERRUPTED WHILE DISMISSED.

;PUT ENTRY ON JSB STACK, AND GO OKINT
;ACCEPTS:	T2/ ADDRESS OF DYNAMIC DATA

	REPEAT 0,<		;NOT USED
TTYDIS:	JE TTLCK,(T2),R		;THIS IS A HACK TO KEEP FSIINI HAPPY.
				;SINCE THE SWAPPABLE MONITOR IS NOT
				;LOADED YET, WE CAN'T USE THE NORMAL
				;LOCKING STATEGY. THIS IS ACCEPTABLE
				;HERE SINCE NO CONFUISION CAN RESULT.
	SKIPE INSKED		;IN THE SCHEDULER?
	RET			;YES. DON'T MANIPULATE THE JSB STACK
	SAVET			;SAVE ALL REGISTERS
	LOAD T1,TINTL,(T2)	;GET INTERNAL LINE NUMBER
	MOVEI T2,STKCD3		;GET PROPER CODE
	CALL JSBSTK		;QUEUE UP THE ENTRY
	OKINT			;ALLOW INTS NOW
	RET			;AND DONE

;DISMISS WAS SATISFIED. DEQUEUE THE ENTRY AND GO NOINT

TTYAWK:	JE TTLCK,(T2),R		;THIS IS A HACK TO KEEP FSIINI HAPPY.
				;SINCE THE SWAPPABLE MONITOR IS NOT
				;LOADED YET, WE CAN'T USE THE NORMAL
				;LOCKING STATEGY. THIS IS ACCEPTABLE
				;HERE SINCE NO CONFUISION CAN RESULT.
	SKIPE INSKED		;IN THE SCHEDULER?
	RET			;YES. DON'T MANIPULATE THE JSB STACK
	SAVET			;SAVE ALL REGISTERS
	NOINT			;PREVENT INTS
	LOAD T1,TINTL,(T2)	;GET INTERNAL LINE NUMBER
	MOVEI T2,STKCD3		;GET TYPE
	CALLRET JSFRMV		;REMOVE ENTRY AND DONE
	>			;END OF REPEAT 0
	SUBTTL Allocation/Deallocation

;TTYASO - ASSIGN TERMINAL FOR OPENF

;ACCEPTS:
;	T2/ LINE NUMBER

;	CALL TTYASO

;RETURNS +1: FAILED,
;		T1/ 1B0 + ADDRESS OF ROUTINE IF NEED TO DISMS
;		T1/ ERROR CODE IF FAILED
;	 +2: SUCCEEDED

;PRESERVES T2

	SWAPCD
TTYASO::SAVELN
	STKVAR <TTYALN>
	MOVEM T2,TTYALN		;SAVE LINE NUMBER
	NOSKD1			;NO STATE CHANGE PLEASE
	CALL STADYN		;IS LINE FULLY ACTIVE?
	 SKIPA			;NO.
	JRST TTYAO4		;FULLY ACTIVE. HANDLE SPECIALLY
	JUMPLE T2,TTYAO1	;SEE IF SHORT OR MESSAGE BLOCK IN USE

;TTACTL greater than 0.  Line is temporarily active for system message or
;sendall.  Wait until TTACTL less than or equal to 0 or full-length block has
;been assigned and try again.

	OKSKD1
	MOVX T1,1B0+TSACT1	;[9062] Return flag and block routine address
	RETBAD 			;LET CALLER DO A DISMS

TTYAO1:	JUMPE T2,TTYAO2		;SEE IF LINE BECOMING ACTIVE

;TTACTL less than 0.  Line is becoming active (another fork in this job is
;initializing it).  Wait until line is inactive or has full-length block and
;try again.

	OKSKD1
	MOVX T1,1B0+TSACT2	;[9062] Return a block routine and flag
	RETBAD 			;LET CALLER DO A DISMS
;TTACTL=0.  Assign a dynamic block for the line and initialize its values.

TTYAO2:	MOVE T2,TTYALN		;GET LINE NUMBER
	SETOM TTACTL(T2)	;INDICATE BEING INITIALIZED
	OKSKD1
	LOAD T1,TTSTY,(T2)	;GET THE LINE TYPE
	MOVE T1,DDLTBL(T1)	;GET LONG BLOCK LENGTH
	HRLI T1,.RESP3		;T1/ INDICATE PROCESS CONTEXT
	MOVX T2,.RESTP		;EXTENDED SECTION, TERMINAL POOL
	CALL ASGRES		;GET SOME FREE SPACE
	 JRST TTYAO3		;NO SPACE AVAILABLE
	MOVE T2,TTYALN		;T2/ LINE NUMBER, T1/ ADDRESS OF DYNAMIC BLOCK
	CALL TTSETL		;INITIALIZE VALUES FOR TERMINAL
	MOVEM T1,TTACTL(T2)	;MAKE STATIC DATA POINT TO DYNAMIC
	RETSKP

;FAILED TO GET RESIDENT STORAGE. LET THE OPENF FAIL

TTYAO3:	MOVE T2,TTYALN		;GET LINE NUMBER
	SETZM TTACTL(T2)	;RESTORE TTACTL TO PREVIOUS VALUE
	RETBAD (MONX05)
;Line was already active.  If permanent, it may be becoming active.  In that
;case, make it active.

TTYAO4:	OKSKD1
	JE <TTBAC,TTPRM>,(T2),RSKP	;IF NOT BECOMING ACTIVE, OK AS IS
	MOVE T3,JOBNO		;GET THIS JOB'S NUMBER
	STOR T3,TCJOB,(T2)	;INDICATE IT OWNS THIS TERMINAL
	SETZRO TTBAC,(T2)	;INDICATE NOT BECOMING ACTIVE
	RETSKP

	ENDSV.			;END STKVAR

;TSACT1 - SCHEDULER TEST TO SEE IF LINE IS AVAILABLE

;ACCEPTS:
;	T1/ INTERNAL LINE NUMBER

;CAUSES WAKEUP IF LINE IS INACTIVE, BECOMING ACTIVE, OR HAS A FULL-LENGTH
;BLOCK

	RESCD
TSACT1::HRRZ T2,T1		;GET LINE NUMBER
	CALL STADYN		;POINT TO DYNAMIC DATA
	 JUMPG T2,0(T4)		;NOT FULLY ACTIVE
	JRST 1(T4)		;FULLY ACTIVE. WAKEUP

;TSACT2 - SCHEDULER TEST TO SEE IF LINE IS AVAILABLE

;ACCEPTS:
;	T1/ INTERNAL LINE NUMBER

;CAUSES WAKEUP IF LINE IS INACTIVE OR FULLY ACTIVE

TSACT2:	HRRZ T2,T1		;GET LINE NUMBER
	CALL STADYN		;POINT TO DYNAMIC DATA
	JUMPN T2,0(T4)		;NOT FULLY ACTIVE
	JRST 1(T4)		;FULLY ACTIVE. WAKEUP
;Init terminal state after assign.
;Called from FILMSC to do "process context" assign functions
;	T2/ internal line number
;Returns:	+1 always
;	Clobbers temps

TTPINI::STKVAR<DLINE>
	CALL LCKTTY		;LOCK IT UP
	IFNSK.
	 SKIPLE T2		;DID SOMETHING GET LOCKED?
	 CALL ULKTTY		;YES.
	 RET			;AND DONE
	ENDIF.
	MOVEM T2,DLINE		;SAVE THIS
	TDCALL D,<<FE,TTEXF>,<MC,MCEXF>,<LH,LTEXF>,<CH,CTHEXF>> ;ENABLE XOFF
	MOVE T2,DLINE		;GET BACK DYNAMIC DATA
	CALLRET ULKTTY		;AND DONE
;TTYASC - ASSIGN TERMINAL AS CONTROLLING TERMINAL FOR A JOB

;ACCEPTS:
;	T2/ INTERNAL LINE NUMBER

;	CALL TTYASC

;RETURNS +1: FAILED,
;		T1/ ERROR CODE
;	 +2: SUCCEEDED

;PRESERVES T2

TTYASC::CAMN T2,CRJTTY		;TRYING TO ASSIGN A TTY BEING CRJOB'D ON?
	SKIPGE CRJFLG		;YES, NO GOOD UNLESS WE'RE THAT JOB!
	SKIPA			;DIFFERENT TTY OR WE'RE THE CRJOB...GO ON
	RETBAD (DEVX2)		;BAD, SAY DEVICE ASSIGNED
TTYASG::			;SCHED-LEVEL ENTRY FOR NRTHOST'S MC TTYs
	SAVELN			;SAVEAC T2
	STKVAR <TTYALN>
       	MOVEM T2,TTYALN		;SAVE LINE NUMBER
	NOSKD1
	CALL STADYN		;POINT TO DYNAMIC DATA
	 SKIPA			;NOT FULLY ACTIVE
	JRST TTYAC4		;FULLY ACTIVE. GO HANDLE SPECIALLY
	JUMPLE T2,TTYAC1	;SEE IF SHORT OR MESSAGE BLOCK IN USE

;TTACTL greater than 0.  Line is temporarily active for system message or
;sendall.  Fail on the assumption that the user will type another control C.

	OKSKD1
	RETBAD (TTYX03)
;TTACTL less than or equal to 0.  Line is inactive or becoming active.  Assign
;storage and initialize values.

TTYAC1:	MOVE T2,TTYALN		;GET LINE NUMBER
	SETOM TTACTL(T2)	;INDICATE BEING INITIALIZED
	OKSKD1
	LOAD T1,TTSTY,(T2)	;GET THE LINE TYPE
	MOVE T1,DDLTBL(T1)	;GET LONG BLOCK LENGTH
	HRLI T1,.RESP2		;T1/ INDICATE MAYBE SCHEDULER CONTEXT
	MOVX T2,.RESTP		;EXTENDED SECTION, TERMINAL POOL
	CALL ASGRES		;GET SOME FREE SPACE
	 JRST TTYAC3		;NO SPACE AVAILABLE
	MOVE T2,TTYALN		;T2/ LINE NUMBER, T1/ ADDRESS OF DYNAMIC BLOCK
	CALL TTSETL		;INITIALIZE VALUES FOR TERMINAL
	MOVEM T1,TTACTL(T2)	;MAKE STATIC DATA POINT TO DYNAMIC
	RETSKP

;FAILED TO GET RESIDENT STORAGE. FAIL

TTYAC3:	MOVE T2,TTYALN		;GET LINE NUMBER
	SETZM TTACTL(T2)	; INDICATE INACTIVE
	RETBAD (MONX05)

;LINE WAS ALREADY ACTIVE. IF PERMANENT, IT MAY BE BECOMING
;ACTIVE. IN THAT CASE, MAKE IT ACTIVE.

TTYAC4:	OKSKD1
	JE TTPRM,(T2),RSKP
	MOVE T3,JOBNO		;GET THIS JOB'S NUMBER
	STOR T3,TCJOB,(T2)	;INDICATE IT OWNS THIS TERMINAL
	SETZRO TTBAC,(T2)	;INDICATE NOT BECOMING ACTIVE
	RETSKP

	ENDSV.			;END STKVAR
;TTYDEA - DEALLOCATE A DYNAMIC BLOCK

;ACCEPTS:
;	T2/ INTERNAL LINE NUMBER

;	CALL TTYDEA

;RETURNS +1: FAILURE, (NO CASES CURRENTLY)
;	 +2: SUCCESS

	RESCD

TTYDED::SAVELN			;ENTRY WITH T2/ DYNAMIC PTR
	STKVAR <TTYDLN,TTYDAD>
	DYNST
	JRST TTYDE4

TTYDEA::TDCALL S,<<TV,TVTDET>>
	NOP
TTYDE0::SAVELN
	STKVAR<TTYDLN,TTYDAD>
TTYDE4:	MOVEM T2,TTYDLN		;SAVE INTERNAL LINE NUMBER
	CALL STADYN		;POINT TO DYNAMIC DATA
	 JRST TTYDE1		;NOT ACTIVE. SHOULDN'T HAPPEN
	JN TTNUS,(T2),TNUKIL	;HANDLE DECNET NVT SPECIALLY
	JN TTPRM,(T2),TTYDE3	;HANDLE PERMANENT BLOCK SPECIALLY
	JN TTLCK,(T2),TTYDE2	;IF LOCKED, WAIT FOR COUNT TO GO TO 0
	JN TTSAL,(T2),TTYDE2	;IF DOING SENDALL, WAIT UNTIL DONE
	MOVEM T2,TTYDAD		;SAVE ADDRESS OF DYNAMIC DATA
	CONSO PI,77000		;SKIP NOSKED IF NOT AT PI LEVEL 7
	NOSKD1			;NO SCHEDULING WHILE CHNOFF IN FORCE
	CHNOFF DLSCHN		;TURN OFF TTY CHANNEL
	CALL TTRLOB		;RELEASE OUTPUT BUFFERS
	MOVE T2,TTYDAD		;T2/ ADDRESS OF DYNAMIC DATA
	CALL TTCIBF		;CLEAR INPUT, RELEASE BUFFERS IF NEEDED
	MOVE T2,TTYDAD		;DYNAMIC DATA ADDRESS AGAIN
	CALL TTXONF		;MAKE SURE IS NOT X-OFF'ED
	MOVE T2,TTYDAD		;GET DYN ADDRESS
	SETZRO TT%PGM,TTFLGS(T2) ;INSURE WE WILL TURN XOFF FLAGS OFF
	TDCALL D,<<FE,TTEXF>,<MC,MCEXF>,<CH,CTHEXF>,<LH,LTEXF>> ;SET FE XOFF RECOGNITION
	MOVE T3,TTYDLN		;GET LINE NUMBER
	TMNE TT%AUT,TTSTAT(T3)	;IF LINE IS NOT AUTOSPEED
	  IFSKP.
	  TMNN TT%FEM,TTSTAT(T3) ;AND IS REMOTE..
	  ANSKP.
	  MOVE T1,TTSVPD(T2)	;RETRIEVE THE SAVED LINE SPEED
	  MOVEM T1,TTSPWD(T3)	;RESTORE LINE SPEED
	  ENDIF.
	MOVE T2,TTYDLN		;GET BACK LINE NUMBER
	SETZM TTACTL(T2)	;INDICATE NO DYNAMIC DATA
	CHNON DLSCHN		;TURN CHANNEL BACK ON

	CONSO PI,77000		;SKIP OKSKED IF NOT AT PI LEVEL 7
	OKSKD1			;OK TO SCHED NOW
	MOVE T1,TTYDAD		;T1/ ADDRESS OF BLOCK
	CALL RELRES		;RELEASE THE RESIDENT SPACE
	RETSKP			;SUCCESS
;LINE IS NOT ACTIVE. THIS SHOULD NOT HAPPEN

TTYDE1:	MOVE T2,TTYDLN		;GET LINE NUMBER
	BUG.(CHK,TTNAC7,TTYSRV,SOFT,<Deallocating inactive line>,<<T2,TTYLIN>>,<

Cause:	TTYDEA was called to deallocate a terminal's dynamic data block but the
	line was inactive and had no block.

Action:	If this BUGCHK is reproducible, set it dumpable and submit an SPR with
	the dump and instructions on reproducing the problem.

Data:	TTYLIN - TTY line number
>)
	RETSKP

;DYNAMIC DATA IS LOCKED OR SENDALL IN PROGRESS.  REQUEST DEALLOCATION
;WHEN FINISHED

TTYDE2:	SETONE TTDAL,(T2)	;REQUEST DEALLOCATION WHEN FINISHED
	RETSKP

;PERMANENT BLOCK. DON'T DEALLOCATE IN THE USUAL WAY

TTYDE3:	SETZM TTPSI(T2)		;CLEAR INTERRUPTS
	SETZM TTDPSI(T2)	; AND DEFERRED INTERRUPTS
	SETONE TCJOB,(T2)	;INDICATE NO OWNING JOB
	SETONE TTPFK,(T2)	;AND NO SCTTY TREE
	MOVE T1,TTYDLN		;T1/ LINE NUMBER
	CALL CHKPTY		;IS THIS A PTY?
	 RETSKP			;NO.
	CALL PTYFIN		;YES. INDICATE HUNGRY
	RETSKP

	ENDSV.			;END STKVAR
;ASGMSG - ASSIGN BLOCK FOR MESSAGE
;ASGMSL- ASSIGN FULL LENGTH MESSAGE BLOCK FOR SPECIAL PURPOSES

;ACCEPTS:
;	T2/ INTERNAL LINE NUMBER

;	CALL ASGMSG
;	CALL ASGMSL

;RETURNS +1: FAILURE,
;		T1/ ERROR CODE
;	 +2: SUCCESS,
;		T2/ LINE NUMBER

	RESCD
ASGMSG:	TDZA T4,T4		;EXTRA LENGTH
ASGMSL:	MOVEI T4,TTDDLN-MSGLEN	;"LONG MESSAGE BLOCK"
	STKVAR <ASGMLN>
	MOVEM T2,ASGMLN		;SAVE LINE NUMBER
	MOVSI T1,.RESP2		;INDICATE CAN'T TAKE PAGE FAULT
	HRRI T1,MSGLEN(T4)	;T1/ (SIZE,,PRIORITY)
	MOVX T2,.RESTP		;EXTENDED SECTION, TERMINAL POOL
	CALL ASGRES		;GET SOME FREE SPACE
	 RETBAD	(MONX05)	;FAILED
	MOVE T2,ASGMLN		;GET LINE NUMBER
	CALL TTSETM		;INITIALIZE VALUES
	SETONE TTMES,(T1)	;INDICATE MESSAGE BLOCK
	TXO T1,TTSHBK		;SAY IS A SPECIAL BLOCK
	MOVEM T1,TTACTL(T2)	;MAKE STATIC POINT TO DYNAMIC
	AOSG TTQCNT		;FIRST SPECIAL LINE?
	MOVEM T2,TTCQLN		;YES. START SCAN HERE THEN
	TXZ T1,TTSHBK		;RETURN ADDRESSABLE BLOCK
	RETSKP			;INDICATE SUCCESS

	ENDSV.			;END STKVAR
;ASHSHT - ASSIGN A SHORT (SENDALL) BLOCK

;ACCEPTS:
;	T2/ INTERNAL LINE NUMBER

;	CALL ASGSHT

;RETURNS +1: FAILURE,
;		T1/ ERROR CODE
;	 +2: SUCCESS,
;		T1/BUFFER ADDRESS
;		T2/ LINE NUMBER

	SWAPCD

ASGSHT:	LOAD T1,TTSTY,(T2)	; Get line type
	CAIN T1,TT.TVT		; NVT?
	RET			; Yes, don't do this then
	STKVAR <ASGSLN>
	MOVEM T2,ASGSLN		;SAVE LINE NUMBER
	MOVSI T1,.RESP3		;INDICATE CAN TAKE PAGE FAULT
	HRRI T1,MSGLEN		;T1/ (SIZE,,PRIORITY)
	MOVX T2,.RESTP		;EXTENDED SECTION, TERMINAL POOL
	CALL ASGRES		;GET SOME FREE SPACE
	 RETBAD	(MONX05,<MOVE T2,ASGSLN>) ;FAILED, MAKE SURE LINE # STILL SETUP
	MOVE T2,ASGSLN		;GET LINE NUMBER
	CALL TTSETS		;INITIALIZE VALUES
	SETONE TTSHT,(T1)	;INDICATE MESSAGE BLOCK
	RETSKP			;INDICATE SUCCESS

	ENDSV.			;END STKVAR
	SUBTTL JSYS Support Routines

;TTCOBF - CLEAR OUTPUT BUFFER

;TTCOB1 - ENTRY POINT FOR CALLING FROM WITHIN TTYSRV

;ACCEPTS:
;	T2/ INTERNAL LINE NUMBER

;	CALL TTCOB1

;RETURNS +1: ALWAYS

;IF LINE HAS NO OUTPUT BUFFERS, RETURNS QUIETLY. IF IT HAS A MESSAGE BLOCK,
;IGNORES LINKS.  IF FULLY ACTIVE, HANDLES LINKS

	RESCD

TTCOB1:	SAVELN			;SAVE LINE NUMBER
	CALL LCKTTY		;POINT TO DYNAMIC DATA
	 JRST [	JUMPLE T2,TTCOB3 ;IF BECOMING ACTIVE OR INACTIVE, NO BUFFERS
		JE TTMES,(T2),TTCOB3 ;IF NOT A MESSAGE BLOCK, NO BUFFERS
		CALL TTCBF9	;MESSAGE BLOCK (HAS NO LINKS). CLEAR
		CALLRET ULKTTY]	;ALLOW DEALLOCATION
	CALL TTCBF9		;DO IT

TTCOB3:	CALLRET ULKTTY		;ALLOW DEALLOCATION
;TTCOBF - ENTRY FOR OUTSIDE OF TTYSRV

;ACCEPTS:
;	T2/ ADDRESS OF DYNAMIC DATA

;	CALL TTCOBF

;RETURNS +1: ALWAYS

;LINE MUST BE FULLY ACTIVE AND ITS DYNAMIC BLOCK LOCKED WHEN CALLED FROM OUTSIDE

TTCOBF::SAVELN
TTCOB2:	MOVE C,TTLINK(B)	;GET LINES THAT THIS LINE IS LINKED TO
	CAMN C,[-1]		;ANY LINKS?
	CALLRET TTCBF2		;NO. JUST CLEAR THIS LINE'S BUFFERS

;LINE IS LINKED TO ONE OR MORE LINES. LOOP THROUGH TTLINK, PICKING UP
;A LINE NUMBER AND CLEARING ITS OUTPUT BUFFERS UNTIL ALL LINKS ARE
;PROCESSED

	PUSH P,B		;SAVE ADDRESS OF DYNAMIC DATA
TTCBF3:	SETZ B,			;INITIALIZE TO GET LINE NUMBER
	LSHC B,^D9		;GET NEXT LINE LINKED TO
	CAIN B,777		;THIS FIELD BEING USED?
	JRST TTCBF4		;NO
	CALL LCKTTY		;GET ADDRESS OF DYNAMIC DATA AND PREVENT DEALLOCATION
	 JRST [	CALL ULKTTY
		JRST TTCBF4]	;NOT ACTIVE. DON'T DO ANYTHING
	PUSH P,C		;SAVE LINK WORD
	CALL TTCBF2		;GO CLEAR BUFFER FOR LINKED LINE
	CALL ULKTTY		;ALLOW DEALLOCATION
	POP P,C			;RESTORE LINK WORD
TTCBF4:	JUMPN C,TTCBF3		;GO DO ALL OF THEM

;ALL LINKS HAVE BEEN PROCESSED. NOW PROCESS THE ORIGINAL LINE AND QUIT

	POP P,B			;RESTORE ADDRESS OF DYNAMIC DATA
	CALLRET TTCBF2		;CLEAR BUFFERS FOR THIS LINE
;TTCBF2 - CLEAR OUTPUT BUFFER FOR ONE LINE

;ACCEPTS:
;	T2/ ADDRESS OF DYNAMIC DATA

;	CALL TTCBF2

;RETURNS +1: ALWAYS

;CALLER MUST HAVE CALLED LCKTTY ON THIS LINE

TTCBF2:	CALL SKCOE		;SKIP CTRL-O INTERRUPT ENABLED
	 SKIPN CTRLOF		;NEW STYLE?
	JRST TTCBF9		;NO
	CALL OWNTTY		;YES, TTY OWNED BY THIS JOB?
	JRST TTCBF9		;NO
	JE TTFLO,(T2),R		;DO NOTHING UNLESS FLUSHING OUTPUT
	NOSKD1
	CHNOFF DLSCHN
TTCBF8:	CALL GTOCHR		;GET CHAR FROM OUTBUF
	 JRST TTCBF7		;NOW EMPTY
	CAIE T1,TTOMRK		;A MARKER?
	JRST TTCBF8		;NO, KEEP FLUSHING
	SETZRO TTFLO,(T2)	;CLEAR FLUSH FLAG
	JRST TTCBF7		;DONE

TTCBF9::NOSKD1
	CHNOFF DLSCHN		;TURN OFF CHANNEL ALSO
	JE TTSAL,(T2),TTCBF6	;CHECK FOR SENDALL IN PROGRESS
	CALL CLRSAL		;CLEAR IT
TTCBF6:
	CALL CFEOB		;CLEAR FE OUTBUF
TTCOB5::SETZM TTOCT(2)		;ZERO OUTPUT COUNT
	SETZB 3,TTOOUT(2)	;CLEAR OUTPUT POINTER
	EXCH 3,TTOIN(2)		;CLEAR INPUT POINTER
	CALL TTRLBF		;RELEASE BUFFERS
TTCBF7:	CHNON DLSCHN
	CALL TTXONP		;REACTIVATE OUTPUT IF NECESSARY
	OKSKD1
	TDCALL D,<<TV,TVTCOB>>	;CLEAR NVT OUTPUT BUFFER (SEND SYNCH)
	CALLRET CHKBKO		;PERHAPS FORK WAITING FOR OBUF EMPTY
;OWNTTY - SKIP IF THIS TTY IS OWNED BY THIS JOB
; T2/ DYNAMIC PTR

OWNTTY:	SKIPE INSKED		;SCHED?
	RET			;YES, NOT A JOB
	LOAD T1,TCJOB,(T2)	;GET CONTROLLING JOB FOR THIS TTY
	CAME T1,JOBNO		;THIS JOB?
	RET			;NO
	RETSKP			;YES

;CLEAR OUTBUF OF FE
; T2/ DYNAMIC PTR
; RETURN +1 ALWAYS

CFEOB:	TDCALL D,<<FE,TTCOB4>,<MC,MCCOBF>,<LH,LTCOBF>>;
	RET
;TTCIBF - CLEAR INPUT BUFFER

;ACCEPTS:
;	T2/ ADDRESS OF DYNAMIC DATA

;	CALL TTCIBF (TTCIB0 TO CLEAR RESCAN POINTER TOO)

;RETURNS +1: ALWAYS,
;		T2 PRESERVED

TTCIB0::PUSH P,2		;SAVE ADDRESS OF DYNAMIC DATA
	DYNST			;GET LINE NUMBER
	CAMN 2,CTRLTT		;CONTROLLING TTY?
	SETZM RSCNPT		;YES, CLEAR RESCAN POINTER TOO
	POP P,2			;RESTORE ADDRESS OF DYNAMIC DATA

TTCIBF::SAVELN			;SAVE LINE NUMBER
	CONSO PI,77000		;SKIP NOSKED IF NOT AT PI LEVEL 7
	NOSKD1
	SETZRO <TTRFG>,(T2)	;CLEAR BKJFN FLAG
	SETZB T1,TTICT(T2)	;CLEAR COUNT OF INPUT CHARACTERS
	STOR T1,TYLCH,(T2)	;CLOBBER LAST CH IN CASE CR
	SETZB 3,TTIOUT(T2)	;CLEAR POINTER FOR REMOVING CHARACTERS
	EXCH 3,TTIIN(2)		; AND POINTER FOR ADDING CHARACTERS
	CALL TTRLBF		;RELEASE INPUT BUFFERS
	CONSO PI,77000		;SKIP OKSKED IF NOT AT PI LEVEL 7
	OKSKD1
	TDCALL D,<<CH,CTHCLI>>	;DO DEVICE-DEPENDENT STUFF
	CALL SNDXON		;SEND XON IF NEEDED
	RET
	SWAPCD
;TTSIBE - SKIP IF INPUT BUFFER IS EMPTY

;ACCEPTS:
;	T2/ ADDRESS OF DYNAMIC DATA
;	T3/ BYTE SIZE OF OPEN OR 0 IF A JFN WAS NOT GIVEN BY CALLER

;	CALL TTSIBE

;RETURNS +1: INPUT BUFFER IS NOT EMPTY
;		T1/ COUNT OF CHARACTERS
;	 +2: INPUT BUFFER IS EMPTY
;		T1/ 0

;THIS ROUTINE COUNTS NUMBER OF CHARACTERS AVAILABLE FOR INPUT FROM LINE
;IN T2.  THE COUNT IS RETURNED IN T1.  THE QUANTITIES ACCUMULATED ARE
;THE FOLLOWING:
;
;	1)	RECIRCULATED CHARACTER, LIKE IF BKJFN WAS DONE
;	2)	RSCANED DATA(*)
;	3)	TYPEAHEAD THAT'S STILL IN THE INPUT BUFFER
;	4)	PHANTOM LINEFEED, ASSUMED IF LAST READ CHARACTER WAS CR
;
;	(*)	THERE IS A BUG HERE.  THIS ROUTINE ONLY EXAMINES THE
;		RSCAN BUFFER IF THE TERMINAL IS THE PROGRAM'S
;		CONTROLLING TERMINAL.  THE CORRECT PROCEDURE IS TO
;		EXAMINE THE RSCAN BUFFER FOR WHICHEVER TERMINAL IS
;		BEING INTERRAGATED.  THIS IS A BIT TRICKY, SINCE THE
;		RSCAN STATUS IS STORED IN SOMEON'S JSB, AND YOU FIRST
;		HAVE TO FIGURE OUT WHO, THEN CALL SETJSB, ETC...
TTSIBE::LOAD T1,TTRFG,(T2)	;0 IF NO RECIRCULATED CHARACTER, 1 IF SO
	PUSH P,T3		;SAVE THE BYTE SIZE
	PUSH P,T2		;SAVE ADDRESS OF DYNAMIC DATA
	DYNST			;GET LINE NUMBER
	MOVE T3,FORKN		;GET JOB FORK NUMBER
	LOAD T3,FRKTTY,(T3)	;GET POSSIBLE FORK CONTROLLING TERMINAL
	CAIE T3,.TTDES(T2)	;IS SIBE BEING DONE ON FORK'S OWN TERMINAL?
	CAMN T2,CTRLTT		;NO, IS THIS THE CONTROLLING TERMINAL FOR THIS JOB?
	SKIPN T3,RSCNPT		;YES. GET RESCAN POINTER
	JRST TTSIB1		;NOT CONTROLLING OR POINTER IS 0
TTSIB2:	ILDB T4,T3		;PICK UP CHARACTER FROM RSCAN BUFFER
	JUMPE T4,TTSIB1		;LEAVE LOOP IF NO MORE.
	AOJA T1,TTSIB2		;COUNT LENGTH OF RSCAN BUFFER
TTSIB1:	POP P,T2		;RESTORE ADDRESS OF DYNAMIC DATA
	POP P,T4		;GET BACK BYTE SIZE
	ADD T1,TTICT(T2)	;ADD CHARACTERS IN REGULAR INPUT BUFFER
	LOAD T3,TT%DAM,TTFLGS(T2) ;GET CURRENT MODE
	CAIE T4,10		;BINARY MODE OPEN ON THE JFN?
	JUMPN T3,[LOAD T3,TYLCH,(T2) ;NOT BINARY, CHECK LAST CHAR
		  LOAD T4,TYLMD,(T2) ; GET DATA MODE OF LAST CHAR
		  CAIN T3,.CHCRT ;CR?
		  CAIN T4,.TTBIN ; YES, INPUT IN NON-BINARY?
		  JRST .+1	; NO TO EITHER, NO LF.
		  AOJA T1,.+1]	;YES TO BOTH, LF STILL AVAILABLE
	TDCALL D,<<CH,CTHCKI>>	;DO DEVICE-DEPENDENT STUFF
	CAILE T1,0		;POSITIVE COUNT?
	RET			;YES, SO TAKE NON-SKIP RETURN
	RETSKP			;NO. SKIP
;TTSOBE - SKIP IF OUTPUT BUFFER IS EMPTY

;ACCEPTS:
;	T2/ ADDRESS OF DYNAMIC DATA

;	CALL TTSOBE

;RETURNS +1: OUTPUT BUFFER NOT EMPTY
;		T1/ COUNT
;	 +2: OUTPUT BUFFER IS EMPTY
;		T1/ 0
	RESCD

TTSOBE::CALL SKCOE		;SKIP IF CTRL-O INTERRUPT ENABLED
	 SKIPN CTRLOF		;NEW STYLE?
	IFSKP.
	  CALL OWNTTY		;JOB OWN TTY?
	  IFSKP.
	    MOVEI T1,TTOMRK	;YES, JUST PUT MARKER IN STREAM
	    CALL TCOUM
	    SETZ T1,
	    RETSKP		;SAY OUTBUF EMPTY
	  ENDIF.
	ENDIF.
	LOAD T1,TSALC,(T2)	;[9117] Get sendall count in case return noskip
	JN TTSAL,(T2),R		;[9117] Return noskip if sendall in progress
	MOVE 1,TTOCT(2)		;GET # OF BYTES
	JN TTOTP,(T2),R		;RETURN NOSKIP IF OUTPUT IS STILL ACTIVE
	JUMPG T1,R		;[9117] Return noskip if bytes still in memory
	TDCALL D,<<FE,TTSBEF>,<MC,MCSBEF>> ;[9126]
	 RETSKP			;DEVICE BUFFER (IF ANY) ALSO EMPTY
	RET			;DEVICE BUFFER NOT EMPTY

;TTSOBF - SKIP IF OUTPUT BUFFER IS FULL

;ACCEPTS:
;	T2/ ADDRESS OF DYNAMIC DATA

;	CALL TTSOBF

;RETURNS +1: OUTPUT BUFFER IS NOT FULL
;		T1/ COUNT
;	 +2: OUTPUT BUFFER IS FULL
;		T1/ COUNT
	SWAPCD

TTSOBF::LOAD 3,TOMAX,(2)	;CAPACITY OF OUTPUT BUFFER
	MOVE 1,TTOCT(2)		;GET NUMBER OF CHARACTERS IN BUFFER
	CAIL 1,0(3)		;FULL?
	RETSKP			;YES. SKIP
	RET			;NO. NONSKIP
;TTDOBE - DISMISS UNTIL OUTPUT BUFFER IS EMPTY

;ACCEPTS:
;	T2/ ADDRESS OF DYNAMIC DATA

;	CALL TTDOBE

;RETURNS +1: NEED TO RETRY
;	+2 DONE. BUFFER IS EMPTY

;WAITS UNTIL OUTPUT BUFFER IS EMPTY

TTDOBE::CALL SKCOE		;SKIP IF CTRL-O INTERRUPT ENABLED
	 SKIPN CTRLOF		;NEW STYLE?
	IFSKP.
	  MOVEI T1,TTOMRK	;YES, JUST PUT MARKER IN OUTPUT STREAM
	  CALL TCOUM
	  RETSKP
	ENDIF.
	CALL TSOBED		;SEE IF OUTPUT IN PIPE
	IFSKP. <RETSKP>		;NO, RETURN OK

;CHARACTERS ARE PRESENT. DISMISS UNTIL THEY ARE GONE

TTDBE1:	TDCALL D,<<PT,CHKPTA>>	;CHECK FOR INTERRUPT NEEDED
	SETONE TTBKO,(T2)	;NOTE WAITING FOR OUTPUT EVENT
	DYNST T1		;GET STATIC DATA ADDRESS
	CALL ULKTTY		;UNLOCK TTY
	HRLZS T1		;LINE # TO LH
	HRRI 1,TTOBET		;1/(LINE NUMBER,,ROUTINE TO CALL)
	MOVSI T2,FHV5		;BLOCK PRIORITY
	HDISMS
	RET			;SAY NEED TO RETRY
;TTDIBE - DISMISS UNTIL INPUT BUFFER IS EMPTY

;ACCEPTS:
;	T2/ ADDRESS OF DYNAMIC DATA

;	CALL TTDIBE

;RETURNS +1: NEED TO RETRY
;	+2 DONE. BUFFER EMPTY

;WAITS UNTIL INPUT BUFFER IS EMPTY

TTDIBE::SKIPG TTICT(T2)		;BUFFER EMPTY NOW?
	RETSKP
	DYNST T1		;GET LINE NUMBER
	CALL ULKTTY		;UNLOCK TTY
	HRLZS T1		;LINE # TO LH
	HRRI 1,TTIBET		;1/(LINE NUMBER,,ROUTINE TO CALL)
	MDISMS
	RET			;NEED TO RETRY
;SCHEDULER TESTS FOR TTDOBE AND TTDIBE
	RESCD

;TTOBET - CAUSES WAKEUP IF OUTPUT BUFFER IS EMPTY (INCLUDING CHARACTERS
;EN ROUTE TO THE LINE)

;ACCEPTS:
;	T1/ INTERNAL LINE NUMBER

TTOBET::PUSH P,T4		;PUT RETURN ON STACK SO RET, RETSKP WORK
	HRRZ T2,T1		;GET LINE NUMBER
	JRST TTOBE0		;DO THE WORK

;HERE FOR NORMAL CALL
; T2/ LINE NUMBER
; RETURN +1 OUT BUFFER NOT EMPTY
;	+2 OUT BUFFER EMPTY

TSOBEX:	SAVEAC <T2>
TTOBE0:	CALL STADYN		;GET ADDRESS OF DYNAMIC DATA
	 RETSKP			;NOT ACTIVE. THIS SHOULDN'T HAPPEN

;ENTER HERE IF DYNAMIC PTR  IN T2
; T2/ DYNAMIC PTR
; RETURN +1: NOT EMPTY
;	+2: EMPTY

TSOBED:	SKIPE TTOCT(T2)		;IS OUTPUT BUFFER EMPTY?
	RET			;NO. DON'T WAKE UP
	JN TTOTP,(T2),R		;NO IF STILL OUTPUT ACTIVE
	TDCALL D,<<FE,TTSBEF>,<MC,MCSBEF>> ;[9126]
	IFSKP. <RET>		;SKIPS IF BUFFER *NOT* EMPTY
	SETZRO TTBKO,(T2)	;NOTE WAIT COMPLETED
	RETSKP

;TTIBET - CAUSES WAKEUP IF INPUT BUFFER IS EMPTY

;ACCEPTS:
;	T1/ INTERNAL LINE NUMBER

TTIBET:	HRRZ T2,T1		;GET LINE NUMBER
	CALL STADYN		;GET ADDRESS OF DYNAMIC DATA
	 JRST 1(T4)		;NOT ACTIVE. THIS SHOULDN'T HAPPEN
	SKIPE TTICT(T2)		;IS INPUT BUFFER EMPTY?
	JRST 0(4)		;NOT EMPTY. DON'T WAKE UP
	JRST 1(4)		;EMPTY. WAKE UP
;TAB GET/SET - PHASED OUT
	SWAPCD

TTGTBS::
TTSTBS::RET

;TTRMOD - CODE TO DO THE RFMOD JSYS

;ACCEPTS:
;	T2/ ADDRESS OF DYNAMIC DATA

;RETURNS +1: ALWAYS
;		T1/JFN MODE WORD

;Note: If page width or length is greater than 177 octal, returns 1 in these
;fields.  User must then do an MTOPR to get the real value.

TTRMOD::SAVELN
	MOVE T1,TTFLGS(T2)	;READ MODES
	LOAD T3,TPWID,(T2)	;GET WIDTH
	LOAD T4,TPLEN,(T2)	;AND PAGE LENGTH
	CAILE T3,177		;OLD MAXIMUM VALUE
	MOVEI T3,DFLWID		;TOO BIG. GET DEFAULT WIDTH
	CAILE T4,177		;OLD MAXIMUM VALUE
	MOVEI T4,DFLLEN		;TOO BIG. GET DEFAULT LENGTH
	STOR T3,TT%WID,T1	;STORE OLD STYLE WIDTH
	STOR T4,TT%LEN,T1	;STORE OLD STYLE LENGTH
	CALL TTCBM		;GET A TT%WAK FROM THE BREAK MASK
	DYNST			;GET LINE NUMBER
	JE TTCON,(T2),R		;RETURN UNLESS CARRIER IS ON
	SETONE TT%CAR,T1	;INDICATE CARRIER ON
	RET
;TTSMOD - SET TERMINAL MODE

;ACCEPTS:
;	T1/ JFN MODE WORD
;	T2/ ADDRESS OF DYNAMIC DATA

;RETURNS +1: ALWAYS

;IMPLEMENTS SFMOD JSYS

TTSMOD::PUSH P,1
	TRNE 1,400000		;THIS BIT MUST BE ZERO
	ITERR(DECRSV,<CALL ULKTTY>)	;NOT ZERO - ERROR RETURN
	XOR 1,TTFLGS(2)		;FIND THE CHANGED BITS
	ANDX 1,TT%OSP+TT%WAK+TT%IGN+TT%ECO+TT%DAM ;CHANGE ONLY THESE BITS
	TDCALL D,<<CH,CTHSFM>>	;[7180] CTERM check discard state change
	XORM 1,TTFLGS(2)
	SKIPE CTRLOF		;NEW STYLE AND CHANGING OUTPUT SUPPRESS?
	TXNN T1,TT%OSP
	IFSKP. <
	  CALL SKCON		;SKIP IF CTRL-O NOT ENABLED
	  IFSKP. <
	  MOVEI T1,TTOMRK	;YES, PUT MARKER IN OUTPUT STREAM
	  CALL TCOUM>>
	LOAD T1,TYLMD,(T2)	;[9117] Get last data mode
	CAIE T1,.TTBIN		;[9117] Was the last mode binary?
	IFSKP.			;[9117] Yes, it was
	  SETZRO TYLCH,(T2)	;[9117] Clear last character
	ENDIF.			;[9117] 
	LOAD T1,TT%DAM,TTFLGS(T2) ;GET TERMINAL DATA MODE
	STOR 1,TYLMD,(T2)	;CHANGE IT FOR PI LEV ALSO
	POP P,T1
	TXNE T1,TT%IGN		;SHOULD WE IGNORE THE TT%WAK BITS
	RET			;YES - THEN DON'T FORCE WAKE-UP
	CALL TTCFM		;COMPUTE AND SET FULL MASK
	CALLRET TTFWAK		;FORCE WAKEUP
;TTRPOS - READ POSITIONS

;ACCEPTS:
;	T2/ ADDRESS OF DYNAMIC DATA

;	CALL TTRPOS

;RETURNS +1: ALWAYS,
;	T1/ (LINE POSITION WITHIN PAGE,,CHARACTER POSITION WITHIN LINE)

TTRPOS::MOVE 1,TTLPOS(2)	;READ POSITION
	RET

;TTSPOS - SET POSITION

;ACCEPTS:
;	T1/ (LINE POSITION WITHIN PAGE,,CHARACTER POSITION WITHIN LINE)
;	T2/ ADDRESS OF DYNAMIC DATA

;	CALL TTSPOS

;RETURNS +1: ALWAYS

TTSPOS::MOVEM 1,TTLPOS(2)	;SET LINE CHARACTER POSITION
	RET
;TTRCOC - READ CONTROL CHARACTER OUTPUT CONTROL WORDS

;ACCEPTS:
;	T2/ ADDRESS OF DYNAMIC DATA

;	CALL TTRCOC

;RETURNS +1: ALWAYS,
;		T1/ FIRST WORD
;		T3/ SECOND WORD

TTRCOC::MOVE 1,FCMOD1(2)	;READ CONTROL CHARACTER MODES
	MOVE 3,FCMOD2(2)
	RET

;TTSCOC - SET CONTROL CHARACTER OUTPUT CONTROL WORDS

;ACCEPTS:
;	T1/ FIRST WORD
;	T2/ ADDRESS OF DYNAMIC DATA
;	T3/ SECOND WORD

;	CALL TTSCOC

;RETURNS +1: ALWAYS

TTSCOC::MOVEM 1,FCMOD1(2)	;SET CONTROL CHARACTER MODES
	MOVEM 3,FCMOD2(2)
	RET
;TTBKPT - "BACKUP" INPUT POINTER - CAN ONLY BACKUP ONE

;ACCEPTS:
;	T2/ INTERNAL LINE NUMBER

;	CALL TTBKPT

;RETURNS +1: FAILURE
;	 +2: SUCCESS

TTBKPT::MOVE C,FORKN		;GET OUR FORK NUMBER
	LOAD C,FRKTTY,(C)	;GET POSSIBLE CONTROLLING TERMINAL
	CAIE C,.TTDES(B)	;USE RSCAN BUFFER IF READING FROM CONTROLLING TERMINAL
	CAMN 2,CTRLTT		;JOB CONTROLLING TTY?
	SKIPN A,RSCNPT		;YES, USING RESCAN BUFFER?
	JRST TTBKP1		;NO, DO NORMAL THING
	MOVE C,RSCNBP		;GET POINTER TO RSCAN BUFFER
	HRLI C,(POINT 7,0,34)	;SEE IF AT START OF BUFFER
	CAMN A,C
	JRST TTBKP1		;YES, DONT BACK IT UP MORE
	CALL DBP		;BACK UP BYTE POINTER
	MOVEM A,RSCNPT		;PUT IT BACK
	RETSKP			;INDICATE SUCCESS

TTBKP1:	CALL LCKTTY		;GET DYNAMIC DATA AND LOCK DYNAMIC BLOCK
	 JRST [	CALL ULKTTY	;NOT ACTIVE. CAN'T BACKUP
		RETBAD (TTYX01)]
	TMNE TTRFG,(T2)		;HAS BACKUP ALREADY BEEN DONE?
	JRST [	CALL ULKTTY	;YES. CAN'T DO ANOTHER
		RETBAD (BKJFX1)]
	SETONE TTRFG,(T2)	;NOT SET. SET IT TO BE NOTICED AT NEXT TCI
	CALL ULKTTY		;ALLOW DEALLOCATION
	RETSKP			;SUCCESS


;GET DEVICE DEPENDENT BITS

TTGSTS::LOAD T3,TLTYP,(T2)	;GET VECTOR ADR FOR THIS TTY
	SETZ T1,
	XCT PARTBL(T3)		;SEE IF PARITY BIT WOULD GET SET
	CAIE T1,0
	MOVX T1,GD%PAR		;YES
	RET			;AND DONE
;TTSSPD - CODE TO DO A SET LINE SPEED
;ACCEPTS:
;	T2/ INTERNAL LINE NUMBER
;	USER 3/ INPUT SPEED,,OUTPUT SPEED
;
;	CALL TTSSPD
;
;RETURNS +1:	ON ERROR (CURRENTLY ONLY FOR ACJ REJECTION)
;	 +2:	ON ALL OTHER CONDITIONS
;
;SETS SPEEDS OF FRONT END LINES ONLY. IGNORES ALL OTHERS
;IMPLEMENTS THE .MOSPD FUNCTION OF MTOPR

TTSSPD::
	STKVAR <TTSLIN>		;SAVE LINE NUMBER HERE
	CAIL B,NLINES		;VALID LINE NUMBER?
	RETSKP			;NO. JUST RETURN QUIETLY
	MOVEM B,TTSLIN		;SAVE LINE NUMBER
	UMOVE C,C		;GET SPEED
	GTOKM (.GOTBR,<B,C>,[RETBAD ()]) ;DO GETOK IF NECESSARY AND RETBAD IF ERROR
	TDCALL S,<<FE,TTSSP2>,<CH,CTHSSP>>
	MOVE B,TTSLIN		;GET BACK LINE NUMBER
	CALL LCKTTY		;GET DYNAMIC DATA ADDRESS
	 JRST [	CALL ULKTTY	;FAILED TO LOCK, NOT INTERESTING
		RETSKP]		; UNLOCK AND RETURN QUIETLY
	MOVE T1,T2		;GET DYNAMIC DATA ADDRESS
	MOVE T2,TTSLIN		;GET LINE NUMBER AGAIN
	CALL SETOBF		;SET BUFFERING
	MOVE T2,T1		;GET DYNAMIC DATA ADDRESS
	CALL ULKTTY		;DONE, UNLOCK DATA
	RETSKP			; AND RETURN SUCCESS

	ENDSV.			;END STKVAR
;TTRSPD -READ OUT THE SPEED OF A TERMINAL

;ACCEPTS:
;	T2/ INTERNAL LINE NUMBER

;	CALL TTRSPD

;RETURNS +1: ALWAYS,
;		USER T3/ (INPUT SPEED,,OUTPUT SPEED)
;			OR
;		    -1 IF NOT PHYSICAL TERMINAL OR SPEED NOT SET

;IMPLEMENTS THE .MORSP FUNCTION OF MTOPR

TTRSPD::CAIL B,NLINES		;LEGAL LINE NUMBER?
	JRST TTRSP2		;NO. RETURN NO SPEED	;@@NO CTERM HERE
	TDCALL S,<<MC,RSKP>,<PT,RSKP>,<TV,RSKP>> ;SKIP IF SPEED NOT KNOWN
	 SKIPA C,TTSPWD(B)	;GET SPEED SETTING
TTRSP2:	SETO C,			;NO. ASSUME UNKNOWN
	UMOVEM C,C		;RETURN IT TO THE CALLER
	SETZ C,			;GET AN ACCUMULATOR
	TMNE TTFEM,(B)		;REMOTE?
	TXO C,MO%RMT		;YES
	TMNE TTAUT,(B)		;AUTO?
	TXO C,MO%AUT		;YES
	XCTU [HLLM C,2]		;RETURN FLAGS
	RET			;AND DONE


;TTSSIG - ROUTINE TO SET THE "IGNORE INPUT ON INACTIVE LINE" BIT
;
;ACCEPTS IN T1/ NEW SETTING (0 OR 1)
;	    T2/ LINE NUMBER
;		CALL TTSSIG
;RETURNS: +1 ALWAYS

TTSSIG::STOR T1,TTIGI,(T2)	;STORE NEW SETTING OF IGNORE INPUT BIT
	RET			;DONE, RETURN
;ROUTINE TO INIT OUTPUT BUFFERING PARAMETERS.
;CALLED FROM TTSETL AND TTSSPD.
;ONLY CALLED FOR NON-CTY ASSIGNS
;	T1/ DYNAMIC DATA ADDRESS
;	T2/ LINE NUMBER
;RETURNS:	+1 ALWAYS
;ALL REGS PRESERVED

	RESCD

SETOBF::SAVET			;[9117] Save T1 through T4
	MOVE T3,TTSPWD(T2)	;GET LINE SPEED
	CAME T3,[-1]		;KNOWN SPEED?
	IFSKP.
	  TDCALL S,<<TV,TVTSOF>,<CH,CTHSOF>,<MC,NRTSOF>,<LH,LTSOF>> ;(T2/T3,T4)NO. DEVICE-DEPENDENT.
	   RET			;NONE. GIVE UP.
	ELSE.
	  HRRZS T3		;YES. GET OUTPUT SPEED
	  MOVE T4,IBFRC		;ASSUME SLOW SPEED
	  CAILE T3,LOWSPD	;ACCEPTABLE?
	  MOVE T4,IBFRC1	;NO. GET OTHER VALUE
	ENDIF.
	MOVEM T4,TTBFRC(T1)	;SET COUNT FIELDS
	SETZ T4,0		;NO BUFFER COUNT IF LOW SPEED
	CAILE T3,LOWSPD
	MOVEI T4,OVRBCT		;SET OVER QUOTA BUFFER COUNT
	STOR T4,TTOCN,(T1)	;SET COUNT
	SETZRO TTOMX,(T1)	;INDICATE OVERBUFFER NOT IN USE
	RET			;AND DONE

	SWAPCD
; .MOTPS - ENABLE FOR PSI INTERRUPTS ON NON-CONTROLLING TERMINAL I/O

;CALL WITH:
;B/		TERMINAL NUMBER
;USER AC3/	POINTER TO USER ARGUMENT BLOCK
;BLOCK+0/	LENGTH OF BLOCK (INCLUDING THIS WORD)
;BLOCK+1/	OUTPUT PSI,,INPUT PSI

TTYNPS::ACVAR <W1>		;GET A REGISTER
	MOVE W1,B		;SAVE LINE NUMBER
	MOVEI A,1		;OFFSET 1 IN ARG BLOCK
	CALL GETWRD		;GET IT
	 RETBAD(MTOX13)		;ERROR, NO SUCH ARG
	HLRZ A,B		;GET OUTPUT PSI CHANNEL
	CALL TTNPCK		;VALIDITY CHECK IT
	 RETBAD(MTOX14)		;ILLEGAL PSI CHANNEL
	HRRZ A,B		;GET INPUT PSI CHANNEL
	CALL TTNPCK		;VALIDITY CHECK IT
	 RETBAD(MTOX14)		;ILLEGAL PSI CHANNEL
	EXCH W1,B		;GET BACK LINE NUMBER SAVE CHANNELS
	CALL LCKTTY		;LOCK TTY DATABASE
	 RETBAD(TTYX01,<CALL ULKTTY>)
	HLRZ A,W1		;GET OUTPUT PSI
	STOR A,TTOPSI,(B)	;STORE IN TTY DATABLOCK
	STOR W1,TTIPSI,(B)	;STORE INPUT PSI
	CAMN W1,[-1]		;TURNING OFF BOTH CHANNELS?
	JRST TTYNP1
	MOVE A,FORKX		;NO, GET CALLING FORK NUMBER
	STOR A,TTPSFK,(B)	;STORE IT AS WELL
	SETONE PSUTPS		;FLAG .MOTPS DONE TO THIS FORK
	JRST TTYNP2

TTYNP1:	SETONE TTPSFK,(B)
TTYNP2:	CALL ULKTTY		;RELEASE TTY DATABASE
	RETSKP			;SUCCESS
;VALIDITY CHECK AN ASSIGNABLE PSI CHANNEL

TTNPCK:	CAIE A,-1		;-1 = DEASSIGN
	CAIG A,5		;0-5 OK
	RETSKP
	CAIL A,^D24
	CAILE A,^D35
	RET			;NOT 24-35, ILLEGAL
	RETSKP			;OK

	ENDAV.			;END ACVAR W1

;TTDTPS - REMOVE CURRENT FORK FROM TTPSFK OF ALL TERMINALS

TTDTPS::SAVET
	SETZRO PSUTPS			;CLEAR BIT THAT GOT US HERE
	MOVEI T1,NLINES-1		;GET HIGHEST LINE NUMBER
TTDTP1:	MOVE T2,T1			;GET LINE NUMBER
	CALL LCKTTY			;LOCK DATABASE
	 JRST TTDTP2			;NOT FULLY ACTIVE, SKIP
	LOAD T3,TTPSFK,(T2)		;GET FORK RECEIVING INT
	CAME T3,FORKX			;SAME AS CURRENT?
	JRST TTDTP2			;NO, SKIP IT
	SETONE TTPSFK,(T2)		;YES, CLEAR IT
TTDTP2:	CALL ULKTTY			;UNLOCK DATABASE
	SOJGE T1,TTDTP1			;LOOP THRU ALL LINES
	RET
;TTSNTS - CODE TO DO A SET/RESET NON-TERMINAL STATUS FOR TTY LINE.
; THIS IS PRIMARILY FOR SUPPRESSING UNWANTED SYS MESSAGES
;ACCEPTS:
;	2/ LINE TO SET STATUS OF
;	3/ STATUS VALUE (1 TO TURN OFF MESSAGES, 0 TO TURN ON)

;	CALL TTSNTS

;RETURNS +1: ALWAYS

;IGNORES NON-FRONT END LINES

;IMPLEMENTS .MOSNT FUNCTION OF MTOPR

TTSNTS::CAIL B,NLINES		;LEGAL LINE NUMBER?
	RET			;NO. IGNORE IT THEN
	TDCALL S,<<FE,TTSNT1>,<PT,RSKP>>	;@@ NO CTERM DISPATCH HERE
	 SKIPA
	RET			;DON'T CHANGE IT
	STOR T3,TTNTS,(T2)	;SAVE THE NEW STATUS
	RET


;TTRNTS - READ TTY NON-TERMINAL DEVICE STATUS
;ACCEPTS:
;	2/ INTERNAL LINE NUMBER

;	CALL TTRNTS

;RETURNS +1 : ALWAYS,
;		3/ STATUS (0 IF SYSTEM MESSAGES ACCEPTED, 1 IF NOT)

;IMPLEMENTS .MORNT FUNCTION OF MTOPR

TTRNTS::SETZ C,			;GET DEFAULT VALUE
	CAIL B,NLINES		;A VALID TERMINAL LINE?
	RET			;NO. ASSUME DEFAULT
	LOAD T3,TTNTS,(T2)	;GET NON-TERMINAL STATUS
	RET
	RESCD			;[7310] Make TTSNTF & FENTM resident

;TTSNTF - Implements .MOSTF function of MTOPR. code to do a set/clear 
;some terminal flags. The program should perform a .MORTF to read
;all current settings, set the bits to be chaged, and then do .MOSTF.
;Call with:
;
;	2/ line to set status of
;	3/ bits
;	CALL TTSNTF
;Returns +1: always

TTSNTF::SAVEAC <A>
 	CAIL B,NLINES		;LEGAL LINE NUMBER?
	RET			;NO. IGNORE IT THEN
	TDCALL S,<<FE,FENTM>> 	;FOR MO%NTM, FE LINES ARE SPECIAL
	LDB A,[POINTR C,MO%NTM] ;PICK UP THE FLAG
	STOR A,TTNTM,(B)	;AND SAVE IT
	LDB A,[POINTR C,MO%NUM] ;PICK UP THE FLAG
	STOR A,TTNUM,(B)	;AND SAVE IT
	RET

;Here for FE lines
;Turns sendalls off in the FE: if refusing terminal messages 
; or 
;Turns sendalls on in the FE:
;	If we're allowing messages and the monitor thinks 
;	  sendalls should be allowed.

FENTM:	SAVEAC <C>
	TXNE C,MO%NTM		;GOING TO REFUSE ALL MESSAGES ?
	 JRST SNTM2		;YES
	LOAD C,TTNTS,(B)	;GET SYSTEM-MESSAGE STATUS
	CAIE C,.MOSMN		;ALREADY REFUSING THOSE ?
SNTM2:	 CALL TTNTM1		;NO, MAKE FE TURN OFF SENDALLS
	RET
	SWAPCD			;[7310]

;TTRNTF - Read terminal flags. Implements .MORTF function of MTOPR
;Accepts:
;	2/ internal line number
;	CALL TTRNTM
;Returns +1 : always,
;	      3/ flags

TTRNTF::SETZ C,			;GET DEFAULT VALUE
	CAIL B,NLINES		;A VALID TERMINAL LINE?
	RET			;NO. ASSUME DEFAULT
	LOAD A,TTNTM,(B)	;GET TERMINAL INHIBIT STATUS
	DPB A,[POINTR C,MO%NTM] ;SAVE IT
	LOAD A,TTNUM,(B)	;GET REFUSE USER-MESSAGE STATUS
	DPB A,[POINTR C,MO%NUM] ;SAVE IT
	RET
;Read the two character escape sequence
;Implements the MTOPR% function .MORTC - read the two character escape sequence
;CALL TTERED with
;	T2/ line number
;Returns +1 on failure with error in T1
;Returns +2 on success with
;	T1/  two ASCII character escape sequence, right justified.
TTERED::CALL STADYN		;Get dynamic data
	 RETBAD (TTYX01)	;Failed.
	LOAD T1,TTCH1,(T2)	;Get first character of the sequence
	LOAD T3,TTCH2,(T2)	;Get first character of the sequence
	LSH T1,7		;Put them 
	IOR T1,T3		; together
	RETSKP			;Success

;Set up the two character escape sequence
;Implements the MTOPR% function .MOTCE - set up the two character escape sequence
;CALL TTESET with
;	T1/ two ASCII character escape sequence, right justified.
;	T2/ line number
;	T3/ action routine index (index into table TTESC)
;Returns +1 on failure, +2 on success
;NOTE: cannot allow any characters that could have a PSI associated with it
;      as the first character of the sequence.
TTESET::CALL STADYN		;Get dynamic data
	RET			;Failed
	LDB T4,[POINT 7,T1,28]	;Get the first character
	ANDI T1,177		;Get the second character
	CAMN T1,T4		;Are they the same ?
	RET            		;Yes. Not allowed
	SKIPE T1		;Are either of
	SKIPN T4		; them null ?
	RET             	;Yes. Not allowed.
	STOR T4,TTCH1,(T2)	;Set the
	STOR T1,TTCH2,(T2)	; sequence.
        STOR T3,TTETP,(T2)	;Set the action routine index.
	RETSKP

;[8977]TTANUL - Routine to enable or disable NUL passthrough in ASCII mode
;[8977]         Called by MTOPR's .MOANU function
;[8977]Accepts:
;[8977]       T2/ Dynamic block address
;[8977]       T3/ ASCII NUL passthrough flag
;[8977]		 .MOANN - flush NULs from TTBBUF
;[8977]		 .MOANY - pass  NULs from TTBBUF to the input buffer
;[8977]
;[8977]Returns +1: Illegal argument value specified
;[8977]        +2: TDB updated with latest ASCII NUL passthrough flag value

TTANUL::CAIL T3,.MOANN		;[8977]Check for a valid lower bound
	CAILE T3,.MOANY		;[8977]Check for a valid upper bound
	RET			;[8977]Indicate an error has occurred
	STOR T3,TTNUL,(T2)	;[8977]Update the NUL passthrough flag
	RETSKP			;[8977]Indicate success

;NWTRRH - Return network information for terminal
;
; Given the line #, returns the originating hostname, line and
; network type. Places this info in the users NTINF% .NWRRH
; argument block.  NTINF has already checked the user arguments
; for validity.
;
; Call with T1/ Output jfn or designator
;	    T2/ Line number
;	    T3/ Address of users .NWRRH arg block
;
; Returns + 1 on error with T1/ error code
;	  + 2 on sucess

MXHL==^D12			;[9041] Max length of hostname (words)

NWTRRH::TRVAR <NWTJFN,NWTDB,NWTUAB,<NWTARG,.NWNU1+1>,<NWTHST,MXHL>>
	MOVEM T1,NWTJFN
	MOVEM T3,NWTUAB
	CALL LCKTTY		;GET ADR OF DYNAMIC DATA, PREVENT DEALLOCATION
	 RETBAD <TTYX01>,<CALL ULKTTY>
	MOVEM T2,NWTDB		;SAVE THE TDB ADR
	XMOVEI T1,NWTARG	;POINT AT TEMP ARG BLOCK
	MOVEM T2,.NWLIN(T1)	;SAVE TDB
	SETZM .NWNNU(T1)	;CLEAR THE NODE NUMBERS (WORDS 1 AND 2)
	SETZM .NWNU1(T1)
	LOAD T4,TLTYP,(T2)	;GET THE LINE TYPE, FOR NOW AND FOR TDCALX
	MOVE T3,LTYTAB(T4)	;CONVERT TO USER USABLE NUMBER
	MOVEM T3,.NWTTF(T1)	;SAVE IT IN ARG BLOCK
	XMOVEI T3,NWTHST	;GET POINTER TO TEMPORARY HOSTNAME AREA
	TXO T3,<OWGP. 7,>	;FORM A OWGBP
	MOVEM T3,.NWNNP(T1)	;SAVE IN ARG BLOCK
	MOVEI T3,MXHL*5		;MAX # OF BYTES IN HOSTNAME
	MOVEM T3,.NWABC(T1)	;SAVE IN COUNT WORD OF TEMP ARG BLOCK
	TDCALX T4,<<TV,TVRRH>,<LH,LHRRH>,<MC,MCRRH>,<CH,CHRRH>>,<JRST DEFRRH>
	 RETBAD <>,<CALL NWTTDB>
;NWTRRH...

	CALL NWTTDB		;UNLOCK TDB
	XMOVEI T1,NWTARG	;POINT AT TEMP ARG BLOCK
	MOVE T2,NWTUAB		;AND AT USER ARG BLOCK
	DMOVE T3,.NWNNU(T1)	;GET NODE NUMBERS
	XCTU [DMOVEM T3,.NWNNU(T2)] ;SAVE IN USER ARG BLOCK
	MOVE T3,.NWTTF(T1)	;GET FLAGS AND TYPES WORD
	UMOVEM T3,.NWTTF(T2)	;AND SAVE IN USER ARG BLOCK
	MOVE T1,NWTJFN		;GET USER OUTPUT DESIGNATOR
	XMOVEI T2,NWTHST	;GET POINTER TO TEMPORARY HOSTNAME AREA
	TXO T2,<OWGP. 7,>	;FORM A OWGBP
	CALL TSOUTA		;DEPOSIT THE STRING
	 RETBAD ()		;ERROR
	MOVE T3,NWTUAB		;GET ADR OF USER ARG BLOCK
        UMOVEM T1,.NWNNP(T3)	;UPDATE USERS BYTE POINTER
	RETSKP

;HERE TO UNLOCK THE TDB 

NWTTDB:	MOVE T2,NWTDB		;GET DYNAMIC DATA ADDRESS
	CALL ULKTTY		;UNLOCK IT
	RET

	ENDTV.
;Here to set up user arg block when line is not a network terminal
;
; Call with T1/ address of internal arg block
;
;   ARG+.NWABC/ # of bytes available for host name
;   ARG+.NWFNC/ not used
;   ARG+.NWNNP/ byte pointer to store hostname string
;   ARG+.NWLIN/ address of dynamic data for line
;   ARG+.NWTTF/ flags, and network and terminal types
;   ARG+.NWNNU/ node # word 1
;   ARG+.NWNU1/ node # word 2
;
; Returns + 1 on error with T1/ error code
;	  + 2 on success

DEFRRH:	SETZ T2,
	IDPB T2,.NWNNP(T1)	;OUTPUT A NULL TO HOSTNAME
	MOVX T4,NW%NNN		;SAY "NO NODE NAME KNOWN"
	IORM T4,.NWTTF(T1)
	MOVX T4,NW%NNT		;SAY "NON-NETWORK TERMINAL"
	DPB T4,[POINT 9,.NWTTF(T1),17]
	RETSKP

;TSOUTA - Output host string to user
;
; Call with T1/ user jfn or string ptr
;	    T2/ pointer to asciz hostname string
;
; Return + 1 on failure with T1/ error code
;   	 + 2 on success, T1/ updated

TSOUTA:	MOVE T3,T2		;MOVE HOSTNAME POINTER TO T3
TSOUT1:	ILDB T2,T3		;GET A HOSTNAME BYTE
	CALL TBOUTA		;GO OUTPUT THE CHARACTER
	 RETBAD ()		;ERROR
	JUMPE T2,RSKP		;DONE ON NULL
	JRST TSOUT1		;TRY FOR MORE



;TBOUTA - Output byte to user
;
; Call with T1/ user jfn or string ptr
;	    T2/ byte
;
; Return + 1 on failure with T1/ error code
;   	 + 2 on success, T1/ updated  T2/ destroyd


TBOUTA:	SAVEAC <T2>
	TLNN T1,777777		;STRING POINTER?
	JRST [BOUT		;NO, CAN DO BOUT
	       ERJMPR R		;[7119] ILLEGAL DESIGNATOR
	      RETSKP]
	TLC T1,777777		;YES
	TLCN T1,777777		;LH = -1?
	HRLI T1,440700		;YES. FILL IN
	XCTBU [IDPB T2,T1]	;DEPOSIT THE BYTE
	PUSH P,T1		;SAVE THE POINTER
	SETZ T2,
	XCTBU [IDPB T2,T1]	;STORE NULL BYTE AT END
	POP P,T1		;RESTORE THE POINTER
	RETSKP
;TTSTIH - TEST INPUT REQUIRED

;ACCEPTS:
;	T2/ ADDRESS OF DYNAMIC DATA

;	CALL TTSTIH

;RETURNS +1: ALWAYS,
;		1/ 0 IF NOT HUNGRY
;		-1 IF HUNGRY

;HUNGRY IS DEFINED AS EITHER OF THE FOLLOWING:
;	1 - THERE IS NO CONTROLLING JOB FOR THIS LINE (IE, CTRL/C
;		WILL CAUSE JOB CREATION)
;	2 - A FORK IS IN INPUT WAIT ON THE LINE AND THERE IS CURRENTLY
;		NO REASON TO WAKE IT UP (IT WILL READ A CHARACTER THAT
;		IS SENT TO THIS LINE)

;NOT HUNGRY IS RETURNED IF ANY OF THE FOLLOWING IS TRUE:
;	1. THE CONTROLLING JOB NUMBER IS INVALID
;	2. NO FORK IS IN INPUT WAIT ON THIS LINE
;	3. FORCED WAKEUP IS SET SO THAT THE WAITING FORK WILL WAKE UP SOON
;	4. THE OUTPUT BUFFER IS ABOUT TO OVERFLOW (INPUT CHARACTERS ARE THROWN
;		AWAY WHEN NOT ECHOED)
;	5. AN INTERRUPT IS PENDING FOR THE WAITING FORK

TTSTIH::LOAD T3,TCJOB,(T2)	;GET OWNING JOB IF ANY
	CAIN T3,-1		;IS THIS TERMINAL ASSIGNED?
	JRST [	JE TTBAC,(T2),TTSTI2 ;NO, HUNGRY UNLESS BECOMING ACTIVE
		JRST TTSTI1]
	CAIL T3,NJOBS		;VALID JOB NUMBER?
	JRST TTSTI1		;NO, RETURN FALSE
	LOAD T1,TWFRK,(T2)	;GET FORK IN INPUT WAIT
	CAIN T1,-1		;IS THERE ONE?
	JRST TTSTI1		;NO. SAY NOT HUNGRY
	JN TTFWK,(T2),TTSTI1	;YES. IF ABOUT TO WAKEUP BECAUSE INPUT BUFFER
	TMNE FKINX,(T1)		;IF INTERRUPT IS PENDING, SAY NOT HUNGRY
TTSTI1:	TDZA 1,1		;RETURN NOT HUNGRY
TTSTI2:	SETO 1,			;RETURN HUNGRY
	RET
;ROUTINES TO SET/READ MODE FIELDS. CALLED FROM MTOPR FUNCTIONS
;IN FILMSC

;SET/READ TERMINAL WIDTH
;ACCEPTS:	T1/ NEW WIDTH
;		T2/ ADDRESS OF DYNAMIC DATA

TTSWID::JUMPE T1,TTSWI1		;ALLOW ZERO WIDTH
	CAIL T1,10		;MUST BE GREATER THAN 10
	CAIL T1,400		;AND LESS THAN 400
	RET			;ILLEGAL WIDTH
TTSWI1:	STOR T1,TPWID,(T2)	;GOOD VALUE. STORE IT
	TDCALL D,<<CH,CTHSWD>>	
	RETSKP			;DONE

TTRWID::LOAD T1,TPWID,(T2)	;READ WIDTH
	RET			;DONE

;SET/READ TERMINAL LENGTH
;SAME ARGS AS ABOVE

TTSLEN::JUMPE T1,TTSLE1		;ALLOW ZERO
	CAIL T1,2		;MUST BE GREATER THAN 2
	CAIL T1,400		;AND LESS THAN 400
	RET			;INVALID LENGTH
TTSLE1:	STOR T1,TPLEN,(T2)	;GOOD VALUE. STORE IT
	TDCALL D,<<CH,CTHSLN>>	
	RETSKP			;DONE

TTRLEN::LOAD T1,TPLEN,(T2)	;READ LENGTH
	RET			;DONE

;SET/READ LINE COUNTER

TTSLC::	MOVEM A,TTLINE(B)	;STORE NEW VALUE
	RET

TTRLC::	MOVE A,TTLINE(B)
	RET

;SET/READ MAXIMUM LINE COUNTER

TTSLM::	MOVEM A,TTLMAX(B)
	RET

TTRLM::	MOVE A,TTLMAX(B)
	RET
;SET/CLEAR XOFF/XON PROCESSING BIT
;	T3/ 0= honor XON/XOFF
;           1= don't honor XON/XOFF

TTXSET::SKIPE T3		;WANT TO DO OUTPUT STOP?
	MOVEI T3,1		;YES. MAKE SURE BIT IS THERE
	STOR T3,TTNXO,(T2)	;STORE NEW VALUE
	CALLRET TTXONP		;AND START OUTPUT IF NECESSARY

;READ VALUE OF XOFF BIT

TTRXOB::LOAD T1,TTNXO,(T2)	;GET THE BIT
	RET			;DONE


;SET/READ PAGE PAUSE CHARACTER
; T1/ PAUSE CHARACTER ,, UNPAUSE CHARACTER
; T2/ DYNAMIC PTR

TTPPCS::HRRZ T3,T1		;CHECK UNPAUSE CHARACTER
	CAIN T3,PGMOFC		;CTRL-S?
	ITERR (TTYX02,<CALL ULKTTY>) ;YES, DOESN'T WORK
	TDCALL D,<<CH,CTHPPC>>,<RETSKP> ;[8986]Do device dependent routind
	ITERR (TTYX02,<CALL ULKTTY>) ;[8986]Quit now if illegal character
	STOR T1,TTUPC,(T2)
	HLRZ T1,T1
	STOR T1,TTPPC,(T2)
	RET

TTPPCR::LOAD T1,TTUPC,(T2)
	LOAD T3,TTPPC,(T2)
	HRL T1,T3
	RET
	SUBTTL Full Wake-Up Classes Support

	RESCD

;SET/READ FUNCTIONS FOR  FIELD WIDTH AND 128-CHARACTER MASK WAKE-UPS

;TTSBM - SET BREAK MASK
;ACCEPTS:	T1/ADDRESS OF FOUR WORD MASK
;		T2/DYNAMIC  DATA ADDRESS
;RETURNS:	+1, ALWAYS
;			DESTROYS T3 & T4

TTSBM::	TDCALL D,<<CH,CTHSBM>>
	DMOVE T3,(T1)		;FIRST TWO WORDS OF MASK
	DMOVEM T3,TTCHR1(T2)	;SET NEW VALUES
	DMOVE T3,2(T1)		;LAST TWO WORDS OF MASK
	DMOVEM T3,TTCHR3(T2)	;SET LAST TWO WORDS
	RET

;TTRBM - READ BREAK MASK
;ACCEPTS:	T1/ADDRESS OF FOUR WORD AREA
;		T2/DYNAMIC  DATA ADDRESS
;RETURNS:	+1, ALWAYS
;			DESTROYS T3 & T4

TTRBM::	DMOVE T3,TTCHR1(T2)	;GET MASK VALUES
	DMOVEM T3,(T1)		;FIRST TWO WORDS OF MASK
	DMOVE T3,TTCHR3(T2)	;GET LAST TWO WORDS
	DMOVEM T3,2(T1)		;AND STORE
	RET
;TTSFW - SET THE FIELD WIDTH
;ACCEPTS:	T1/FIELD WIDTH
;		T2/DYNAMIC DATA ADDRESS
;RETURNS:	+1,ALWAYS

TTSFW::	SUB T1,TTICT(T2)	;SUBTRACT NUMBER ALREADY IN BUFFER
	JUMPLE T1,[	SETZRO TTFCNT,(T2)	;YES - DISABLE FIELD WIDTH
		CALLRET TTFWAK]	;GO WAKE PROCESS
	STOR T1,TTFCNT,(T2)	;SET THE FIELD WIDTH
	RET

;TTRFW - READ THE FIELD WIDTH
;ACCEPTS:;		T2/DYNAMIC DATA ADDRESS
;RETURNS:	+1,ALWAYS
;			T1/FIELD WIDTH

TTRFW::	LOAD T1,TTFCNT,(T2)	;READ THE FIELD WIDTH
	RET
	SWAPCD
;ROUTINE TO COMPUTE TT%WAK BITS FROM FULL CHARACTER BIT MASK
;ACCEPTS:	T1/ TERMINAL MODE WORD
;		T2/ DYNAMIC DATA ADDRESS
;	CALL TTCBM
; RETURN +1,	T1/ UPDATED TERMINAL MODE WORD
;		T3/ CLOBBERED
;		T4/ CLOBBERED

TTCBM:	SAVEAC <Q1>
	TXZ T1,TT%WAK		;WE SET THIS FIELD
	TXZ T1,TT%IGN		;MAKE SURE THE "IGNORE" BIT IS OFF
	MOVSI Q1,-NRPTB		;SET TO SCAN WORDS OF TABLE
	XMOVEI T4,TTCHR1(T2)	;POINT TO BREAK MASK WORD 1
TTSW1:	MOVE T3,0(T4)		;GET USER MASK
	TDNE T3,RPTB(Q1)	;ANY PUNCTUATION HERE?
	TXO T1,TT%WKP		;YES, SET WAKEUP ON PUNCT
	TDNE T3,RATB(Q1)	;ANY ALPHANUMERICS HERE?
	TXO T1,TT%WKA		;YES, SET WAKEUP ON ALPHA
	AOS T4
	AOBJN Q1,TTSW1		;SCAN ALL MAK WORDS
	MOVE T3,TTCHR1(T2)	;GET USERS FIRST WORD
	TXNE T3,MO%WN1-400	;ANY FORMAT CONTROLS HERE?
	TXO T1,TT%WKN		;YES, SET WAKEUP ON NON-FORMAT CTL
	TXNE T3,MO%WF1-400	;ANY FORMAT CONTROLS HERE?
	TXO T1,TT%WKF		;YES, SET WAKEUP ON FORMAT CTL
	TXNE T1,TT%WAK		;SPECIAL CASE FOR ESCAPE AND RUBOUT
	RET			;ALL SET - ESCAPE AND RUBBOUT TAKEN CARE OF
	TXNE T3,400		;IS THERE AN ESCAPE?
	TXO T1,TT%WKF		;YES - THEN SET IN TT%WAK
	MOVE T3,TTCHR4(T2)	;SEE IF RUBOUT IS ON
	TXNE T3,20
	TXO T1,TT%WKF		;YES - THEN SET IT
	RET

;PUNCTUATION MASK TABLE

RPTB:	MO%WP1-400		;0-37, EXCLUDE ESC
	MO%WP2			;40-77
	MO%WP3			;100-137
	MO%WP4-20		;140-177, EXCLUDE RUBOUT
NRPTB==.-RPTB

;ALPHANUMERICS MASK TABLE

RATB:	MO%WA1-400		;0-37, EXCLUDE ESC
	MO%WA2			;40-77
	MO%WA3			;100-137
	MO%WA4-20		;140-177, EXCLUDE RUBOUT
; ROUTINE TO COMPUTE AND SET FULL BREAK MASK FROM THE TT%WAK BITS
;
;ACCEPTS:	T1/ MODE WORD
;		T2/ ADDRESS OF DYNAMIC DATA
;RETURNS: +1,	WITH MASK SET
TTCFM:	STKVAR <<TTSMH1,2>,<TTSMH2,2>,<TTMS1,4>>
	DMOVEM T3,TTSMH1	;SAVE T3 & T4
	DMOVEM Q1,TTSMH2	;SAVE Q1 & Q2
	SETZB T3,T4
	SETZB Q1,Q2
	TXNN T1,TT%WAK		;ARE ANY BITS SET?
	JRST TTMSET		;NO - THEN CLEAR WAKE-UP MASK AND GO
	TXO T3,400		;SET THE ESCAPE BIT
	TXO Q2,20		;SET THE RUBOUT
	TXNE T1,TT%WKF		;WANT FORMATTING CONTROLLS
	TXO T3,MO%WF1		;YES - SET FORMATTING CONTROLS
	TXNE T1,TT%WKN		;WANT NON-FORMATTING CONTROLS?
	TXO T3,MO%WN1		;YES - SET THEM UP
	TXNE T1,TT%WKP		;WANT PUNCTUATION?
	JRST [	TXO T3,MO%WP1
		TXO T4,MO%WP2
		TXO Q1,MO%WP3
		TXO Q2,MO%WP4
		JRST .+1]
	TXNE T1,TT%WKA		;WANT ALPHANUMERICS?
	JRST [	TXO T3,MO%WA1
		TXO T4,MO%WA2
		TXO Q1,MO%WA3
		TXO Q2,MO%WA4
		JRST .+1]
TTMSET:	DMOVEM T3,TTMS1		;SAVE FIRST TWO WORDS OF MASK
	XMOVEI T3,TTMS1		;POINT TO SECOND TWO WORDS
	ADDI T3,2
	DMOVEM Q1,(T3)		; LAST TWO WORDS
	MOVE T3,T1
	XMOVEI T1,TTMS1		;POINT TO FULL MASK
	CALL TTSBM		;SET THE MASK
	MOVE T1,T3
	DMOVE T3,TTSMH1		;RESTORE T3 AND T4
	DMOVE Q1,TTSMH2		; AND Q1 AND Q2
	RET

	ENDSV.			;END STKVAR
;ROUTINE USED BY TEXTI TO COMPUTE PARITY FOR AN EDITING
;CHARACTER.
;	T2/ THE CHARACTER.
;RETURNS +1 ALWAYS. WITH EVEN PARITY IN B

TTCMPP::SKIPGE CHITAB(T2)	;NEED PARITY ON THIS CHARACTER?
	TRO T2,200		;YES. SO DO IT
	RET			;AND DONE
	SUBTTL TTMSG JSYS

;TTMSG JSYS - Sends messages to all lines

;Accepts:
;	AC1/ -1 		for all lines on this system
;	 or  flags,,.TTDES+n	where n is terminal number to send to
;	 or  0			zero means arg in AC3 for historical use
;	AC2/ pointer to string	
;	TTMSG
;
;Returns +1: always

;Flags given in AC1:
;	TT%REM==1B1		;Remote sendall (local sendall if not set)
;	.TTCIN==37B17		;CI node designator (.CSALL==37 for all)
;	.TTTTY==777777B35	;Terminal line number
	
;Can ITERR, but returns success if line refuses sendall.

;Note: The TTNTS bit, which prevents sendall to a given line, applies to TTMSG
;with T1 containing -1 (for all lines), not with T1 containing a specific line
;number.
;TTMSG...

.TTMSG::MCENT
	TRVAR <TTMSBY,TTMSCT,TTCAPF,TTNODE,TTREM,TTY> ;[7.1076]
	SETZM TTCAPF		;[7.1056] Assume no privileges
	SETZM TTREM		;[7.1076] And assume local
	CALL CKMMOD		;[7.1056] Is caller in monitor mode?
	IFSKP.			;[7.1056] Skip if yes
	  AOS TTCAPF		;[7.1056] Set priv word to +1 for monitor
	ELSE.			;[7.1056] 
	  GTOKM (.GOTTM,<T1>)	;[9041] ACJ letting them?
	  MOVE D,CAPENB		;[7.1056] Get capabilities
	  TXNE D,SC%WHL!SC%OPR	;[7.1056] Is he privileged?
	  SETOM TTCAPF		;[7.1056] Yes, set priv word to -1 for user
	ENDIF.			;[7.1056] 
	SKIPN TTCAPF		;ENABLED?
	SKIPL CTRLTT		;NO, MUST NOT BE DETACHED
	IFSKP. <ITERR GTDIX1>
;TTMSG...

	MOVEM A,TTY		;[7.1076] Save destination TTY
	IFGE. A			;[7.1076] Was -1 supplied (send all on local node)?
	  TXNN A,TT%REM		;[7.1076] Doing a remote send?
	  IFSKP.		;[7.1076] If so,
	    LOAD D,.TTCIN,A	;[7.1076] Get CI node to send to
	    MOVEM D,TTNODE	;[7.1076] And save it here
	    MOVS D,[.CSALL]	;[7.1076] Get send to all node indicator
	    CAME D,TTNODE	;[7.1076] User trying to send to all nodes?
	    IFSKP. <SETOM TTNODE> ;[7.1076] If so, indicate all nodes
	    CALL SC.PRT		;[7.1076] (/A) Get our port number
	     ITERR ()		;[7.1076] If no port, tell user to get lost
	    CAMN A,TTNODE	;[7.1076] Is the node ours?
	    IFSKP.		;[7.1076] No...
	      SETOM TTREM	;[7.1076] Say remote send
	      SKIPGE A,TTNODE	;[7.1076] Doing all nodes?
	      IFSKP.		;[7.1076] If not,
	        CAIL A,0	;[7.1076] CI node negative?
	        CAIL A,C%SBLL	;[7.1076] Or too big?
	        ITERR (TTMSX3)	;[7.1076] Say bad CI node
	        MOVE A,TTY	;[7.1076] Restore original terminal number
	      ENDIF.		;[7.1076] Finished with node validation
	    ELSE.		;[7.1076] Node is ours
	      SETZM TTREM	;[7.1076] Indicate local TTMSG%
	      SETZM TTNODE	;[7.1076] And make sure nothing is left over here
	      HRRZS A		;[7.1076] Make it local by getting just TTY number
	    ENDIF.		;[7.1076]
	  ENDIF.		;[7.1076]
	ENDIF.			;[7.1076]

;Get the sendall lock next

	NOINT
TTMSH1:	AOSN SALLCK		;[7.1056] Can we get the sendall lock?
	IFSKP.			;[7.1056] Nope 
	  OKINT
	  MOVEI A,^D30000	;WAIT 30 SEC MAX
	  CALL SETBKT		;SETUP TIMER TEST WORD
	  HRRI A,SALTST
	  MDISMS		;WAIT FOR LOCK FREE OR 30 SEC
	  NOINT
	  AOSE SALLCK		;HAVE LOCK NOW?
	  ITERR TTMSX1		;NO, SOMETHING PROBABLY BUSTED
	ENDIF.
	MOVEI A,1		;INIT COUNT OF ACTIVE LINES, +1 WHILE HEREIN
	MOVEM A,SALCNT
;[7.1056] Check user's line number argument as furnished in AC1.  An
;[7.1056] undocumented feature allows you to specify 0 in AC1 and the argument
;[7.1056] is pulled from AC3.  Monitor is allowed to supply a line number of -2
;[7.1056] (DTESRV), -1, and or course .TTDES+number (subject to TTNTM).  A
;[7.1056] prived user can specify -1 for all lines or .TTDES+number (subject to
;[7.1056] TTNTM).  Anyone can specify .TTDES+number subject to TTNTM and TTDUM.

	UMOVE A,1		;[7.1056] Get user's specified line number
	SKIPN A			;[7.1056] Is AC1 equal to 0?
	UMOVE A,3		;[7.1056] Yes, use AC3 (undocumented feature?)

	CAME A,[-2]		;[7.1056] Send to RSX20F only?
	IFSKP.			;[7.1056] If so
	  SKIPLE TTCAPF		;[7.1056] Is the monitor requesting this?
	  JRST TTMSH4		;[7.1056] Monitor and RSX20F only, allow it
	ENDIF.			;[7.1056] User will get a GTJIX2 (ill line num)

	CAME A,[-1]		;[7.1056] Is it a send to all lines?
	IFSKP.			;[7.1056] If so
	  SKIPN TTCAPF		;[7.1056] Is the user prived or monitor?
	  ITERR GTDIX1,<CALL ULKSAL> ;[7.1056] (/) Reset lock, OKINT, give err
	ELSE.			;[7.1056] Otherwise
	  HRRZ A,TTY		;[7.1076] Just get terminal number
	  SKIPE TTREM		;[7.1076] Doing remote send?
	  IFSKP.		;[7.1076] If not, validate terminal
	    CAIL A,.TTDES	;[7.1076] Make sure TTY argument is not
	    CAIL A,.TTDES+NLINES ;[7.1076] too small and not too large
	    ITERR GTJIX2,<CALL ULKSAL> ;[7.1076] (/) Reset lock, OKINT, give err
	    MOVEI B,.TTDES(A)	;[7.1076] Remove device designator (400000)
	    JN TTNTM,(B),TTRJCT	;[7.1076] If destination inhibiting, reject
	    JE TTNUM,(B),TTMSH4	;[7.1076] Jump if not refusing users
	    SKIPN TTCAPF	;[7.1076] Wheel, Operator, or monitor?
	    JRST TTRJCT		;[7.1076] If destination refusing users, reject
	  ELSE.			;[7.1076] Send is remote
	    LOAD D,.TTTTY,A	;[7.1076] Get destination terminal number
	    CAIE D,.TTTTY	;[7.1076] Trying all terminals on remote?
	    IFSKP.		;[7.1076] If so,
	      SKIPN TTCAPF	;[7.1076] Allow only if he has privs
	      ITERR GTDIX1,<CALL ULKSAL> ;[7.1076] Unlock send all lock, OKINT and error
	    ENDIF.
	    SKIPL TTNODE	;[7.1076] Trying to send to all nodes?
	    IFSKP.		;[7.1076] If so,
	      SKIPN TTCAPF	;[7.1076] Let him if he is prived
	      ITERR GTDIX1,<CALL ULKSAL> ;[7.1076] Unlock send all lock, OKINT and error
	    ENDIF.		;[7.1076]
	  ENDIF.		;[7.1076]
	ENDIF.			;[7.1056] 
;[7.1056] Line number has been checked, now make the sendall buffer

TTMSH4:	UMOVE B,2		;[7.1056] Pick up the byte pointer
	TLC B,-1		;CHECK SOURCE PTR
	TLCN B,-1		;HAD A -1 IN LH?
	HRLI B,(POINT 7,)	;YES. GET STANDARD BYTE POINTER
	UMOVEM B,B		;RETURN BYTE POINTER
	SKIPL P3,A		;SAVE ARG, ALL LINES?
	TXZ P3,.TTDES		;NO, GET LINE NUMBER
	BLCAL. GETSAL,<<.,SALBFR>,<.,TTMSCT>,<.,TTMSBY>,TTCAPF,TTNODE,TTY,TTREM> ;[7.1076]
				;SETUP SENDALL BFR
	 ITERR ,<CALL ULKSAL>	;[7.1056] (/) Release lock, OKINT, ITRAP error

;BUFFER IS SET UP WITH TEXT. IF THERE ARE NO CHARACTERS,
;WE ARE DONE.

	SKIPN TTMSCT		;AT LEAST ONE BYTE?
	JRST TTMS50		;NO. GO FINISH
	SKIPN TTREM		;[7.1076] Doing remote send?
	IFSKP.			;[7.1076] If so,
	  HRLZ A,TTNODE		;[7.1076] Get node number
	  HRRI A,.TTDES(P3)	;[7.1076] And saved line number
	  MOVE B,SALBFR		;[7.1076] Retrieve the send all buffer
	  MOVE C,TTMSCT		;[7.1076] Pass on character count in buffer
	  MOVE D,TTCAPF		;[7.1076] Pass on privs
	  XCALL (XCDSEC,CLTMSG)	;[7.1076] (A,B,C,D/) Do the remote sends
	   ITERR ,<CALL RELSAL	;[7.1076] (/) Release send all buffer and release lock
	    	  OKINT>	;[7.1076] Go OKINT and return an error
	  SKIPL TTNODE		;[7.1076] Are we doing ALL nodes?
	  JRST TTMS51		;[7.1076] No, then we are done
	  HRRZ A,TTY		;[7.1076] Get terminal line number back
	  CAIN A,.TTTTY		;[7.1076] Did user want to send to all?
	  SETO P3,		;[7.1076] Yes, indicate all lines on this system too
	ENDIF.			;[7.1076]
	JUMPL P3,TTMS25		;[7.1056] Jump if it is a sendall
	MOVE B,P3		;SINGLE LINE, GET LINE NUMBER
	TDCALL S,<<FE,TTMSSN>,<MC,MCCKSA>,<TV,TVMSNT>,<CH,RSKP>,<LH,LTSALL>> ;SKIP TO SEND
	 JRST TTMS50		;SKIP THIS LINE
	CALL SALLIN		;DO THE LINE
	 JFCL			;FAILED. IGNORE IT.
	JRST TTMS50		;DONE
;GET THE FIRST LINE OF THIS LINE TYPE

TTMS25:	SETZ C,			;[7.1056] Send all, start with line type 0
TTMS26:	MOVE B,TT1LIN(C)	;GET FIRST LINE OF THIS TYPE
	JUMPL B,TTMS24		;JUMP IF NO LINES OF THIS TYPE
	JRST TTMS20		;GO DO IT

;GO TO NEXT LINE.  IF THE LINE TYPE CHANGES, DON'T PROCEED WITH THE NEW
;LINE.  INSTEAD, GO TO THE NEXT LINE TYPE AFTER THE ONE JUST PROCESSED.
;THIS CODE ASSUMES THAT ALL LINES OF A GIVEN TYPE ARE NUMBERED CONSECUTIVELY.

TTMS21:	LOAD C,TTSTY,(B)	;GET CURRENT TYPE
	ADDI B,1		;GO TO NEXT LINE
	CAIL B,NLINES		;BEYOND END OF LINES?
	JRST TTMS24		;YES. GO TO NEXT LINE TYPE
	LOAD A,TTSTY,(B)	;GET TYPE OF NEW LINE
	CAME C,A		;SAME AS PREVIOUS LINE?
	JRST TTMS24		;NO. GO TO NEXT LINE TYPE

;SAME LINE TYPE AS PREVIOUS ONE. DO ACCORDING TO DEVICE DEPENDENT CODE
;DEVICE-DEPENDENT CODE RETURNS:
;	+1: DON'T DO THIS LINE
;	+2 AND T2/-1: DON'T DO ANY LINES OF THIS TYPE
;	+2 AND T2/LINE NUMBER: DO THIS LINE

TTMS20:	MOVE A,SALBFR		;PASS BYTE PTR
	HRLI A,(POINT 9,0)
	MOVE D,C		;SAVE THE LINE TYPE FOR THE TDCALL
	MOVE C,TTMSCT		;PASS COUNT
	CAMN P3,[-2]		;[7.1056] Send to front end only?
	IFSKP.			;[7.1056] No, send to all lines
	  TDCALL S,<<FE,TTMSAL>,<MC,MCCKSA>,<PT,TTMSNO>,<TV,TVMSNT>,<CH,RSKP>,<LH,LTSALL>>;
	   JRST TTMS21		;DON'T DO THIS LINE. GO ON TO NEXT LINE
	ELSE.			;[7.1056] 
	  TDCALL S,<<FE,TTMSAL>>,<JRST TTMSNO> ;[7.1056] (A,B,C/B) Do CFE lines
	  JRST TTMS21		;[7.1056] Don't do this line, check next
	ENDIF.			;[7.1056] 
	MOVE C,D		;RESTORE LINE TYPE
	JUMPL B,TTMS24		;SKIP THE ENTIRE GROUP
;HERE WHEN DEVICE DEPENDENT CODE WANTS THE SENDALL DONE FOR IT

TTMS22:	JN TTNTM,(B),TTMS21     ;DON'T DO IF NO TERMINAL MESSAGES
	JN TTNTS,(B),TTMS21	;DON'T DO IF NON-TERMINAL
	CALL SALLIN		;DO SENDALL FOR THE LINE
	 JFCL			;FAILED. IGNORE IT.
	JRST TTMS21		;THEN GO GET NEXT LINE

;FINISHED THE CURRENT LINE TYPE OR THE LINE TYPE IS NOT TO BE PROCESSED
;GO TO THE NEXT TYPE

TTMS24:	AOS C			;GO TO NEXT LINE TYPE
	CAIL C,NLTYPS		;BEYOND END OF LEGAL TYPES?
	JRST TTMS50		;YES. DONE
	JRST TTMS26		;DO NEXT TYPE
;HERE WHEN ALL LINES HAVE BEEN PROCESSED FOR CURRENT BUFFERFUL.
;WAIT UNTIL ALL ARE SENT

TTMS50:	CALL DECSAL		;SEE IF ANY LINES GOING NOW
	OKINT
	JRST MRETN

;RETURN -1 IN B TO CAUSE ALL LINES OF THIS TYPE TO BE SKIPPED

TTMSNO:	SETO B,
	RETSKP

TTMS51:	CALL RELSAL		;[7.1076] (/) Release send all storage
	OKINT			;[7.1076] Interrupts are OK
	JRST MRETN		;[7.1076] And back to user

;HERE WHEN THE MESSAGE IS REJECTED BY THE DESTINATION TERMINAL

TTRJCT:	CALL ULKSAL 		;[7.1056] (/) Clear the lock, go OKINT
	ITERR TTMSX2		;GENERATE "REJECTED" MESSAGE

;[7.1056] Here to release SALLCK and go OKINT (used for error routines)
;[7.1056] Returns +1 always, OKINT and SALLCK unlocked.

ULKSAL:	SETOM SALLCK		;[7.1056] Release the lock
	OKINT			;[7.1056] OK for interrupts now
	RET			;[7.1056] Return to caller
;SALLIN - DO SENDALL TO A SINGLE LINE

;ACCEPTS:
;	T2/ LINE NUMBER

	SWAPCD

SALLIN:	SAVELN			;SAVE LINE NUMBER
	STKVAR <SALLLN>
	MOVEM T2,SALLLN		;SAVE LINE NUMBER
	JN TTSHU,(T2),R		;IF LINE SHUT OFF, FORGET IT
	NOINT
	NOSKED
	CALL STADYN		;DOES LINE ALREADY HAVE DYNAMIC DATA?
	IFSKP.
SALLI2:	  TMNN <TTSAL,TTHPO>,(T2) ;YES, SENDALL PTR FREE?
	  JRST SALLI5		;YES, GO AHEAD
	  CALL LCKTT		;LOCK THE TTY DATA WHILE WE DISMIS
	  OKINT
	  MOVEI T1,SALWAT	;WAIT TEST FOR SENDALL PTR FREE
	  HRL T1,SALLLN		;LINE NUMBER
	  MDISMS
	  NOSKED		;NOSKED AGAIN
	  CALL ULKTT		;UNLOCK THE TTY DATA
	  JRST SALLI2		;TRY AGAIN
	ENDIF.
;SALLIN...

	JUMPG T2,SALLI5		;HAS A MESSAGE BLOCK. OK TO USE
	JUMPL T2,[ OKSKED	;GO OKSKED FIRST
		OKINT		;AND OKINT
		RET]		;LINE IS BECOMING ACTIVE. CAN'T USE IT
	MOVE T2,SALLLN		;GET LINE NUMBER
	SETOM TTACTL(T2)	;INDICATE BECOMING ACTIVE
	OKSKED
	CALL ASGSHT		;GO GET A SHORT BLOCK
	 JRST [	SETZM TTACTL(T2) ;RESET ACTIVE POINTER
		OKINT
		RETBAD]
	NOSKD1
	TXO T1,TTSHBK		;SAY IS A SPECAIL
	MOVEM T1,TTACTL(T2)	;SAVE DYNAMIC STORAGE ADDRESS
	AOSG TTQCNT		;FIRST SPECIAL LINE?
	MOVEM T2,TTCQLN		;YES. START SCAN HERE THEN
	TXZ T1,TTSHBK		;MAKE ADDRESSABLE BLOCK
	MOVE T2,T1
SALLI5:	AOS SALCNT		;INCREMENT COUNT OF LINES DOING SENDALL
	MOVE T1,SALBFR		;GET SENDALL BFR ADDRESS
	HRLI T1,670000		;MAKE BYTE PTR
	MOVEM T1,TTSAL2(T2)	;SAVE POINTER TO SENDALL STRING
	MOVE T1,TTMSCT		;GET COUNT OF CHARACTERS
	STOR T1,TSALC,(T2)	;SAVE COUNT OF SENDALL STRING
	SETONE TTSAL,(T2)	;INDICATE LINE IS DOING A SENDALL
	SETZ T3,		;FAKE OUT STRTOU
	CALL STRTOU		;START OUTPUT IF NEEDED
	MOVE T3,TTMSCT		;GET CHAR COUNT
	IDIVI T3,^D10		;MINIMUM OUTPUT RATE, 10 CHARS/SEC
	ADDI T3,5		;PLUS A SMALL PAD
	STOR T3,TSALT,(T2)
	CALL TSENDQ		;QUEUE A CHECK OF THE LINE
	OKINT
	RETSKP

	ENDSV.			;END STKVAR
	ENDTV.			;END TRVAR
;PERIODIC ROUTINE TO UNHANG STUCK SENDALL LINES
;CALLED FROM DOLINE (TTCH7)
; T2/ LINE NUMBER

	RESCD			;RESDIENT STUFF

CKSALL:
	SAVEAC <T1>
	MOVE T1,T2		;SAVE LINE NUMBER
	CALL STADY		;STILL ACTIVE?
	 RET			;NO, DONE
	JE TTSAL,(T2),R		;DONE IF NO LONGER DOING SENDALL
	LOAD CX,TINTL,(T2)	;TCO 6.1561 GET INTERNAL LINE NUMBER
	JN TTSHU,(CX),[CALLRET CLRSAL] ;IF LINE SHUT OFF, CLEAR IMMED.
	DECR TSALT,(T2)		;COUNTDOWN SECONDS
	JN TSALT,(T2),[CALLRET TSENDQ] ;NOT EXPIRED, QUEUE ANOTHER CHECK
	CALLRET CLRSAL		;EXPIRED, CLEAR THE LINE

;QUEUE A CHECK OF A LINE DOING A SENDALL
; T2/ DYNAMIC PTR

TSENDQ:	SAVEAC <T2>
	MOVEI T1,^D1000		;ONE SECOND
	LOAD T2,TINTL,(T2)	;NEED LINE NUMBER HERE
	MOVEI T3,CKSALL		;ROUTINE TO CALL
	CALLRET TTQAD		;QUEUE IT
;CLEAR SENDALL STATE FOR LINE
; T2/ DYNAMIC PTR

CLRSAL::SETZRO <TSALC>,(T2)	;CLEAR SENDALL POINTER, COUNT
	SETZM TTSAL2(T2)	;[6.1354] (T2) NEEDED
	SETZRO TTSAL,(T2)	;INDICATE NO LONGER DOING SENDALL
	IFQN. TTDAL,(T2)	;DID SOMEBODY TRY TO DEALLOCATE THIS?
	  CALL TTYDED		;YES, DO IT NOW
	   NOP
	ENDIF.

DECSAL::SOSE SALCNT		;[7.1056] Decrement count of sendall lines
	RET			;[7.1056] Return if someone still using it
				;[7.1056] Fall thru to release storage and lock

;RELEASE SENDALL STORAGE

RELSAL:	SAVEAC <T1,T2>
	MOVE T1,SALBFR
	CALL RELRES
	SETOM SALLCK		;RELEASE LOCK
	RET

;WAIT FOR LINE TO FINISH USING SENDALL PTR
;CALLED AS SCHEDULER TEST
; T1/ LINE NUMBER
;	JSP T4,SALWAT
;	 +1: STILL WAITING
;	 +2: READY

SALWAT::HRRZ T2,T1		;GET LINE NUMBER
	CALL STADYN		;GET POINTER TO DYNAMIC DATA
	 JRST 1(T4)		;FAILURE, SHOULD NEVER HAPPEN
	TMNE <TTSAL,TTHPO>,(T2)	;STILL DOING IT?
	JRST 0(T4)		;YES
	JRST 1(T4)		;NO, WAKEUP

;TEST FOR SALLCK FREE OR TIME EXPIRED
; T1/ VALUE FOR TIME TEST

SALTST::SKIPGE SALLCK		;LOCK FREE?
	JRST 1(T4)		;YES, WAKEUP
	JRST BLOCKT		;NO, CHECK TIME

	SWAPCD
;GETSAL - GET SENDALL BUFFER AND STORE LINE OF TEXT IN IT

;RETURNS +1: FAILURE
;	 +2: SUCCESS,
;		@TTMSCT/ COUNT OF BYTES
;		@TTMSBY/ LAST BYTE
;		@TTMSBF/ BUFFER ADDRESS
;		TTCAPF/ -1 IF PRIVILEGED
;[7.1076] Add the following to BLCAL.
;		NODE/ Destination node to receive message (unchanged upon return)
;		DESTTY/ Destination terminal (unchanged upon return)
;		REMOTE/ 0 if send is local, (unchanged upon return)

GETSAL:	BLSUB. <TTMSBF,TTMSCT,TTMSBY,TTCAPF,NODE,DESTTY,REMOTE> ;[7.1076]
	STKVAR <SAVPTR,<SAVNOD,2>,ERROR> ;[7.1076] Temp storage
	UMOVE B,B		;GET BYTE PTR
	SETZ C,			;INIT COUNT
GETSB2:	XCTBU [ILDB A,B]	;SCAN BYTES
	 ERJMP [RETBAD ARGX10]	;CAN'T REFERENCE IT
	JUMPE A,GETSB1		;NUL IS END OF STRING
	CAIN A,.CHLFD		;LF?
	ADDI C,4		;YES, WILL INCLUDE 4 FILLS
	AOJA C,GETSB2		;COUNT CHARS

GETSB1:	MOVEM C,@TTMSCT		;SAVE COUNT
	SKIPN TTCAPF		;PRIVILEGED?
	ADDI C,^D85		;[7.1076] No, figure in header
	CAIL C,TSALCM		;CHECK THE MAXIMUM ALLOWED
	RETBAD (ENQX19)		;TOO BIG
	ADDI C,4		;ROUND UP
	IDIVI C,4		;COMPUTE NUMBER WORDS REQUIRED
	BLCAL. ASGRSB,<C,[.RESP3],[RS%SE0!.RESTP]> ;GET RES STG FROM TERMINAL POOL
	 RETBAD()		;FAILED - SHOULDN'T HAPPEN
	MOVEM A,@TTMSBF		;SAVE ADDRESS
	HRLI A,(POINT 9,0)	;BUILD BYTE PTR - 8-BIT, INCLUDES PARITY BIT
	SKIPE TTCAPF		;CAPABILITIES?
	IFSKP.
	  HRROI B,[ASCIZ /From /] ;[7.1076] No, must prefix header
	  CALL GSALCP		;BUILD STRING IN RES STG
	  HRROI B,USRNAM+1
	  CALL GSALCP		;USER NAME
	  HRROI B,[ASCIZ / on node /] ;[7.1076]
	  CALL GSALCP		;[7.1076] (A,B/A) Prefix to node
	  HRROI B,OURNAM	;[7.1076] Node name kept here
	  CALL GSALCP		;[7.1076] (A,B/A) Put node name in
	  HRROI B,[ASCIZ / line /]
	  CALL GSALCP
	  MOVE B,CTRLTT
	  MOVEI C,^D8		;LINE NUMBER, OCTAL
	  NOUT
	   NOP
	  HRROI B,[ASCIZ / to /] ;[7.1076] Prime destination
	  CALL GSALCP		;[7.1076] (A,B/A)
	  SKIPN REMOTE		;[7.1076] Doing a remote send?
	  IFSKP.		;[7.1076] If so, fill in "to node"
	    SKIPL NODE		;[7.1076] Doing all nodes?
	    IFSKP.		;[7.1076] If so,
	      HRROI B,[ASCIZ /all nodes /] ;[7.1076] Say so
	      CALL GSALCP	;[7.1076] (A,B/A) And put in sendall buffer
	    ELSE.		;[7.1076] If not all nodes
	      HRROI B,[ASCIZ /node /] ;[7.1076] Say which one
	      CALL GSALCP	;[7.1076] (A,B/A)
	      MOVEM A,SAVPTR	;[7.1076] Save byte pointer a minute
	      MOVE A,NODE	;[7.1076] Get CI node number
	      CALL CFSNOD	;[7.1076] (A/B,C) Now get CFS node name
	      IFNSK.		;[7.1076] If failed,
	        MOVEM A,ERROR	;[7.1076] Stash error while we cleanup
	        MOVE A,@TTMSBF	;[7.1076] Return send all buffer to terminal free space
	        CALL RELRES	;[7.1076] (A/) Give it back
	        MOVE A,ERROR	;[7.1076] Retrieve error code
	        RETBAD ()	;[7.1076] And vamoose
	      ENDIF.		;[7.1076]
	      DMOVEM B,SAVNOD	;[7.1076] Save node name
	      MOVE A,SAVPTR	;[7.1076] Get saved byte pointer back
	      HRRI B,SAVNOD	;[7.1076] Put node name in send all buffer
	      HRLI B,(POINT 8,)	;[7.1076] We're talking 8-bit bytes for nodes
	      CALL GSALCP	;[7.1076] (A,B/A) Store it
	      HRROI B,[ASCIZ / /] ;[7.1076] Neatness counts, put space
	      CALL GSALCP	;[7.1076] (A,B/A) after node name
	    ENDIF.		;[7.1076]
	  ENDIF.		;[7.1076] Done with remote section

	  HRRZ C,DESTTY		;[7.1076] Get destination terminal
	  CAIE C,.TTTTY		;[7.1076] Are we doing all terminals?
	  IFSKP.		;[7.1076] If so,
	    HRROI B,[ASCIZ /all lines/] ;[7.1076] Say doing all lines
	    CALL GSALCP		;[7.1076] (A,B/A) And make it regular
	  ELSE.			;[7.1076] Else make line singular
	    HRROI B,[ASCIZ /line /] ;[7.1076]
	    CALL GSALCP		;[7.1076] (A,B/A) Update send all buffer
	    HRRZ B,DESTTY	;[7.1076] Get line number ready for JSYS
	    TXZ B,.TTDES	;[7.1076] Remove terminal designator part
	    MOVEI C,^D8		;[7.1076] Display it in decimal
	    NOUT%		;[7.1076] Put it in send all string
	     NOP		;[7.1076] Won't happen
	  ENDIF.		;[7.1076]
	  HRROI B,[ASCIZ /: /]
	  CALL GSALCP
	  HRRZ B,A		;COMPUTE NUMBER BYTES IN HEADER STRING
	  SUB B,@TTMSBF		;NUMBER FULL WORDS
	  IMULI B,4		;NUMBER BYTES
	  ADDM B,@TTMSCT	;ADJUST COUNT
	  LDB B,[POINT 3,A,2]	;P FIELD, HIGH-ORDER 3 BITS
	  MOVN B,B
	  ADDI B,4		;NUMBER BYTES IN LAST (PARTIAL) WORD
	  ADDM B,@TTMSCT	;ADJUST COUNT
	ENDIF.
;Loop through characters in user's string, copying to internal buffer.  Add
;fill after line feed.  Stop at end of line or when buffer is full, whichever
;is first.

	MOVE C,A		;DEST BYTE PTR
	MOVE D,@TTMSCT
	SETZ P5,		;SET FLAG FOR <CR> TO ZERO
GETSA1:	XCTBUU [ILDB P1,B]	;GET NEXT BYTE
	 ERJMP [MOVE A,@TTMSBF	;FAILED, RETURN STORAGE
		CALL RELRES
		RETBAD(ARGX10)]	;AND RETURN TO CALLER
	JUMPE P1,GETSA6		;STOP ON NULL
	ANDI P1,177		;USE ONLY 7-BIT ASCII
	SKIPE TTCAPF		;PRIV'ED?
	 JRST GETSA2		;YES ALL CHARS ARE ACCEPTABLE
	CAIL P1," "		;BETWEEN SPACE AND
	 CAILE P1,"Z"+40	;LOWER CASE Z?
	  SKIPA			;YES MUST BE A CONTROL CHARACTER
	   JRST GETSA2		;REGULAR CHARACTERS ARE OK
	CAIN P1,"M"-100		;CR?
	JRST GETSA4		;YES
	 CAIN P1,"J"-100	;LF?
	 JRST GETSA5		;YES
	CAIE P1,"G"-100		;BELL?
	 CAIN P1,"I"-100	;TAB?
	  JRST GETSA2			;YES THEY ARE OK
	   JRST GETSA1		;NON NICE CHARACTER SO DO NOT DEPOSIT IT
GETSA4:	AOS P5			;INCREMENT FLAG FOR <CR>
	SOJL D,GETSA6		;COUNT CHARACTERS
	JRST GETSA1		;NOT END OF STRING
GETSA5:	SKIPG P5		;PREVIOUS CHARACTER A <CR>
	JRST GETSA2		;NO
	SOJL D,GETSA6		;END OF STRING
	SETZ P5,		;CLEAR FLAG
	MOVEI P1,"M"-100	;GET A <CR>
	SKIPG CHITAB(P1)	;NEED PARITY BIT?
	TRO P1,200		;YES
	IDPB P1,C		;PUT A <CR> IN OUTPUT STRING
	MOVEI P1,"J"-100	;GET A <LF> AND CONTINUE
GETSA2:				;HERE WHEN THE CHARACTER IS ACCEPTABLE
	SKIPG CHITAB(P1)	;NEED PARITY BIT?
	TRO P1,200		;YES. APPLY IT THEN
	SOJL D,GETSA6		;COUNT CHARS
	IDPB P1,C		;USE IT
	CAIE P1,.CHLFD		;A LINE FEED?
	JRST GETSA1		;NO, LOOP
;END OF LINE. INSERT 4 FILLS

	MOVEI P4,4		;FILLS TO DO
	MOVEI P2,TTFILL		;THE FILL CHARACTER
GETSA3:	SOJL D,GETSA6		;JUMP IF BUFFER FULL
	IDPB P2,C		;INSERT A FILL
	SOJG P4,GETSA3		;DO ALL FILLS
	JRST GETSA1		;LOOP

;END OF STRING OR COUNT EXHAUSTED (COUNT CAN ONLY BE WRONG IF STRING
;IN USER SPACE CHANGED SINCE WE COUNTED IT.)

GETSA6:	MOVEM P1,@TTMSBY	;SAVE LAST BYTE COPIED
	RETSKP
	ENDSV.			;[7.1076] For GETSAL's STKVAR

;LOCAL SUBROUTINE TO COPY STRING
; A/ DEST BYTE PTR
; B/ SOURCE BYTE PTR
;	CALL GSALCP
;COPY UNTIL NULL
; RETURN +1: ALWAYS, NULL FOLLOWS END OF DEST STRING

GSALCP:	HLRZ C,B		;CHECK SOURCE PTR
	CAIN C,-1		;NEEDS INIT?
	HRLI B,(POINT 7,0)	;YES
      DO.
	ILDB T3,T2		;GET BYTE
	IDPB T3,T1		;STORE IT
	JUMPN T3,TOP.		;LOOP IF NOT NULL
      OD.
	CALLRET DBP		;DECREMENT DEST PTR OVER NULL AND RETURN

	ENDBS.
;SIMULATE TTY INPUT

;ACCEPTS:
;	T1/ CHARACTER
;	T2/ INTERNAL LINE NUMBER

;CALL TTSTI

;RETURNS +1: ALWAYS

	RESCD			;USED TO DUMP CTY BYTES INTO LINES

TTSTI::	ANDI 1,377		;ISOLATE CHARACTER
	NOSKD1
	CAME 2,CTYINT		;CTY ALIAS?
	CALL TTCHI		;NO. PUT CHAR INTO LINE BUFFER
	 JRST [	OKSKED		;FAILED, BUFFER FULL
		RETBAD IOX33]
TTSTIX:	OKSKD1
	RETSKP

REPEAT 0,<
;OBNFT - SCHEDULER TEST FOR OUTPUT BUFFER NOT FULL

;ACCEPTS:
;	T1/ INTERNAL LINE NUMBER

;CAUSES WAKEUP IF OUTPUT BUFFER IS NOT FULL

	RESCD			;MUST BE RESIDENT
OBNFT:	MOVE T2,T1		;SETUP LINE
	CALL STADYN		;GET ADDRESS OF DYNAMIC DATA
	 JRST 1(T4)		;SHOULDN'T HAPPEN. WAKE PROCESS
	LOAD T3,TOMAX,(T2)
	CAMG T3,TTOCT(T2)	;FULL?
	JRST 0(T4)		;YES
	JRST 1(T4)		;NO
>
	SUBTTL STO JSYS

	SWAPCD			;SWAPPABLE. CALLED AS A JSYS
.STO::	MCENT
STO11:	UMOVE 1,1
	CALL CHKTTY		;CHECK GIVEN DESIGNATOR
	 ITERR()		;NOT TTY
	CALL LCKTTY		;GET ADDRESS OF DYNAMIC DATA AND PREVENT DEALLOCATION
	 JRST [	CALL ULKTTY
		ITERR (TTYX01)]	;NOT ACTIVE. RETURN ERROR
	CALL TTSTO
	 JRST STO11		;BLOCKED. TRY AGAIN
	UMOVEM 1,2		;RETURN CHAR IN 2
	CALL ULKTTY		;ALLOW DEALLOCATION OF DYNAMIC DATA
	JRST MRETN

	RESCD			;MAKE RESIDENT FOR EFFICIENCY
;TTSTO - REMOVE CHARACTER FROM OUTPUT BUFFER

;ACCEPTS:
;	T2/ ADDRESS OF DYNAMIC DATA

;	CALL TTSTO

;RETURNS +1: BLOCKED, TRY AGAIN
;	+2 SUCCESS
;		T1/ CHARACTER

TTSTO::	NOSKD1
	CHNOFF DLSCHN		;CAN'T ALLOW SCANNER PI HERE
	CALL GTOCHR		;GET CHAR FROM OUT BFR
	 JRST TTSTO1		;EMPTY, BLOCK
	TXNN A,TTOESC		;A MARKER?
	IFSKP.
	  CAIE T1,TTOMRK	;SYNCH?
	  IFSKP. <
	    SETZRO TTFLO,(T2)>	;YES, CLEAR FLUSH FLAG
	  SETZ T1,		;RETURN A NUL
	ENDIF.
	CHNON DLSCHN
	OKSKD1
	RETSKP

;WAIT UNTIL BUFFER BECOMES NONEMPTY AND LINE INACTIVE

TTSTO1:	CHNON DLSCHN
	OKSKD1
	SETONE TTBKO,(T2)	;NOTE WAITING FOR OUTPUT EVENT
	DYNST T1		;GET STATIC LINE NUMBER
	CALL ULKTTY
	HRLZS T1		;LINE NUMBER TO LH
	HRRI T1,TTOAV		;TEST FOR BUFFER NOT EMPTY AND LINE INACTIVE
	MDISMS			;WAIT UNTIL SPECIFIED TEST IS SATISFIED
	RET			;SAY WE BLOCKED. TRY AGAIN
;TTOAV -  SCHEDULER TEST FOR OUTPUT AVAILABLE ON A LINE

;ACCEPTS:
;	T1/ INTERNAL LINE NUMBER

;CAUSES WAKEUP IF OUTPUT BUFFER IS NOT EMPTY AND LINE IS INACTIVE

TTOAV::	HRRZ T2,T1		;GET LINE NUMBER
	CALL STADYN		;GET ADDRESS OF DYNAMIC DATA
	 JRST 1(T4)		;NOT ACTIVE. THIS SHOULDN'T HAPPEN
	TMNN TTOTP,(T2)		;IS LINE ACTIVE?
	SKIPN TTOCT(T2)		;NO. ARE THERE CHARACTERS?
	JRST 0(T4)		;ACTIVE OR NO CHARACTERS AVAILABLE. DON'T WAKEUP
	SETZRO TTBKO,(T2)	;NOTE WAIT COMPLETED
	JRST 1(T4)		;INACTIVE AND CHARACTERS AVAILABLE. WAKEUP
	SUBTTL STTYP/GTTYP JSYSes

;.STTYP - SET TERMINAL TYPE

;ACCEPTS:
;	T1/ TERMINAL DESIGNATOR
;	T2/ TERMINAL TYPE NUMBER

;	STTYP

;RETURNS +1: ALWAYS

	SWAPCD
.STTYP::MCENT
	CALL CHKTTY
	 ITERR ()		;ASSUME CHKTTY SET UP ERROR REASON
	UMOVE 3,2		;GET TERMINAL TYPE SPECIFIED
	CAIL 3,0		;REASONABLE NUMBER?
	CAIL 3,NTTYPS
	ITERR (STYPX1)		;TERMINAL TYPE NOT IN RANGE
	CALL LCKTTY		;GET DYNAMIC DATA AND PREVENT DEALLOCATION
	 JRST [	CALL ULKTTY	;NOT ACTIVE. ALLOW DEALLOCATION
		ITERR (TTYX01)]
	STOR 3,TTTYP,(2)	;STORE NEW TERMINAL TYPE
	LDB 1,TTMBIT		;GET MECH BITS
	DPB 1,[POINT 3,TTFLGS(2),3] ;PUT WHERE NOTICED
	LDB 1,TTTWID		;GET STANDARD WIDTH
	STOR 1,TPWID,(2)	;SET IT FOR THIS LINE
	LDB 1,TTTLEN		;STANDARD LENGTH
	STOR 1,TPLEN,(2)	;SET IF FOR THIS LINE
	TMNN TT1PRQ,(T3)	;PAGE MODE REQUIRED?
	IFSKP.
	  SETONE TT%PGM,TTFLGS(T2) ;YES
	ENDIF.			;OTHERWISE LEAVE IT AS IS
	;LOAD T1,DSPTB,(T3)	;GET VIDEO ATTRIBUTES TABLE
	;SKIPE T1		;IS THIS A VIDEO TERMINAL?
	;MOVEI T1,1		;YES.
	;STOR T1,TTNXO,(T2)	;SET PAGE STOP BIT APPROPRIATELY
	TDCALL D,<<CH,CTHTYP>>	
	CALL ULKTTY		;ALLOW DEALLOCATION
	JRST MRETN
;.GTTYP - GET TERMINAL TYPE

;ACCEPTS:
;	T1/ TERMINAL DESIGNATOR


;	GTTYP

;RETURNS +1: ALWAYS
;		T2/ TERMINAL TYPE
;		T3/ (NUMBER INPUT BUFFERS,,NUMBER OUTPUT BUFFERS)

.GTTYP::MCENT
	CALL CHKTTR
	 JRST [	XCTU [SETZM 2]	;NOT TTY, RETURN 0
		JRST MRETN]
	CALL LCKTTY		;POINT TO DYNAMIC DATA AND PREVENT DEALLOCATION
	 JRST [	CALL ULKTTY	;NOT ACTIVE. ALLOW DEALLOCATION
		ITERR (TTYX01)]
	LOAD 1,TTTYP,(2)	;GET TERMINAL TYPE
	UMOVEM 1,2
	LOAD 1,TTNIN,(2)	;GET NUMBER OF INPUT BUFFERS
	LOAD 3,TTNOU,(2)	;GET NUMBER OF OUTPUT BUFFERS
	HRLI 3,0(1)		;COMBINE THEM FOR USER
	UMOVEM 3,3
	CALL ULKTTY		;ALLOW DEALLOCATION OF DYNAMIC DATA
	JRST MRETN


;GETTYP - Get Terminal Type
;T2/ Line Number
;	CALL GETTYP
; Returns +1: Failure, Line Not Active
;  T1/ Error Code
; Returns +2: Success
;  T1/ Terminal Type

	FTCTS <
GETTYP::CALL LCKTTY		;Point to Dynamic Data and prevent deallocation
	 RETBAD (TTYX01,<CALL ULKTTY>)	;If failure, return error and unlock
	LOAD T1,TTTYP,(T2)	;Get terminal type
	CALL ULKTTY		;Allow deallocation of Dynamic Data
	RETSKP			;Give successful return
>				;End of Conditional Assembly
	SUBTTL STPAR JSYS

;.STPAR - SET TERMINAL PARAMETERS

;ACCEPTS:
;	T1/ TERMINAL DESIGNATOR
;	T2/ NEW JFN MODE WORD

;	STPAR

;RETURNS +1: ALWAYS

.STPAR::MCENT
	CALL CHKTTR		;IS THIS A TTY?
	 MRETNG			; NO, THEN THIS IS A NOOP
	CALL CHKTTY		;CAN WE GET TO IT?
	 EMRETN ()		; NO, ERROR OUT WITH REASON
	CALL LCKTTY		;POINT TO DYNAMIC DATA AND PREVENT DEALLOCATION
	 JRST [	CALL ULKTTY	;NOT ACTIVE. ALLOW DEALLOCATION
		ITERR (TTYX01)]
;STPAR...

	NOINT			;I WILL NOT DIE
	UMOVE 1,2		;GET NEW JFN MODE WORD
	TDCALL D,<<PT,STPAR5>,<TV,TVTPAR>,<CH,CTHSPR>>
	PUSH P,1
	XOR 1,TTFLGS(2)
	ANDI 1,TT%ECM+TT%UOC+TT%LIC+TT%DUM+TT%PGM ;CHANGE THESE BITS
	XORM 1,TTFLGS(2)
	TXNE T1,TT%PGM		;DID PAGE MODE CHANGE?
	IFNSK. <TDCALL D,<<FE,TTEXF>,<MC,MCEXF>,<LH,LTEXF>,<CH,CTHEXF>>> ;YES, FIX XOFF RECOG IN FE
	PUSH P,1
	TXNE 1,TT%PGM		;CHANGING PAGE MODE?
	CALL TTXONF		;YES, BE SURE OUTPUT NOT STOPPED
	SETZ 1,
	STOR 1,TPGPS,(2)	;AND RESET PAGE POSITION
	POP P,1
	LDB 1,[POINT 7,0(P),10]
	JUMPE T1,STPAR2		;ALLOW ZERO LENGTH
	CAIL 1,2		;LEGAL PAGE SIZE?
	CAIL 1,200
	JRST STPAR0		;ILLEGAL SIZE DOES NOT CHANGE SETTING
STPAR2:	STOR T1,TPLEN,(2)
STPAR0:	LDB 1,[POINT 7,0(P),17]
	JUMPE T1,STPAR3		;ALLOW ZERO WIDTH
	CAIL 1,10		;LEGAL WIDTH
	CAIL 1,200
	JRST STPAR1		;ILLEGAL WIDTHS DON'T CHANGE THE SETTING
STPAR3:	STOR T1,TPWID,(2)
STPAR1:	LDB 1,[POINT 3,0(P),3]
	DPB 1,[POINT 3,TTFLGS(2),3] ;LH BITS
	POP P,1
	CALL ULKTTY		;ALLOW DEALLOCATION OF DYNAMIC DATA
	JRST MRETN
	SUBTTL TLINK JSYS

;.TLINK - ESTABLISH/REMOVE LINKS BETWEEN TERMINALS

;ACCEPTS:
;	T1/ (FLAGS,,OBJECT LINE NUMBER)
;	T2/ REMOTE LINE NUMBER OR -1 FOR ALL

;	TLINK

;RETURNS +1: FAILURE
;		T1/ ERROR CODE
;	 +2: SUCCESS

;FLAGS:
;	TL%CRO - B0 - CLEAR REMOTE TO OBJECT
;	TL%COR - B1 - CLEAR OBJECT TO REMOTE
;	TL%EOR - B2 - SET OBJECT TO REMOTE
;	TL%ERO - B3 - SET REMOTE TO OBJECT
;	TL%SAB - B4 - SET OR CLEAR ACCEPT LINKS ACCORDING TO B5
;	TL%ABS - B5 - SET ACCEPT LINKS
;	TL%STA - B6 - SET OR CLEAR ACCEPT ADVICE ACCORDING TO B7
;	TL%AAD - B7 - SET ACCEPT ADVICE

;'OBJECT' IS USUALLY THE CALLER OF THE JSYS; 'REMOTE' IS THE OTHER LINE

.TLINK::MCENT
	CALL CKMMOD		;[9041] Coming from monitor?
	IFNSK.			;[9041] If not, this must be blessed
	  GTOKM (.GOTLK,<T1,T2>,MRETNE) ;[9041] Ask ACJ for permission
	ENDIF.			;[9041]
	TRVAR <OBJNO,OBJADR,REMNO,TLSAV1,LNKWRN>
	SETOM LNKWRN		;ASSUME LINK MESSAGE IS NEEDED
	MOVEI T1,-.TTDES(T1)	;TURN OBJECT DESIGNATOR INTO LINE NUMBER
	CAIE T1,-1-.TTDES	;SPECIFIED -1 FOR OWN TERMINAL?
	IFSKP.			;YES
	  HRRZ T1,FORKN		;GET NUMBER OF FORK
	  LOAD T1,FRKTTY,(T1)	;GET FORK CONTROLLING TERMINAL
	  TRZ T1,.TTDES		;OBTAIN LINE NUMBER
	ENDIF.
	CAIN T1,-1-.TTDES	;IS THERE ONE FOR THE FORK?
	SKIPL T1,CTRLTT		;NO, USE JOB CONTROLLING TERMINAL
	CAIL T1,NLINES		;VALIDATE LINE NUMBER
	 RETERR(DESX1)		;ILLEGAL
	MOVEM T1,OBJNO		;SAVE LINE NUMBER
	ADDI T1,.TTDES		;CREATE DESIGNATOR AGAIN
	CALL CHKDEV		;SEE IF TERMINAL IS AVAILABLE TO THIS JOB
	 SKIPA T1,CAPENB	;NO, MUST CHECK WHEEL
	JRST TLKOBG		;YES, PROCEED
	TXNN T1,SC%WHL!SC%OPR	;PRIVILEGED TO LINK RANDOM TERMINALS?
	RETERR (WHELX1)		;NO, LOSE
	SETZM LNKWRN		;NO MESSAGE IS TYPED LATER
TLKOBG:	MOVE T2,OBJNO		;GET BACK LINE NUMBER
	CALL LCKTTY		;POINT TO DYNAMIC DATA, PREVENT DEALLOCATION
	 JRST [	CALL ULKTTY	;NOT ACTIVE.
		RETERR (TTYX01)]
	MOVEM T2,OBJADR		;SAVE ADDRESS OF DYNAMIC DATA FOR OBJECT
	UMOVE 1,1		;GET BITS AND OBJECT DESIGNATOR
	TLNN 1,(74B5)		;SECOND DESIGNATOR REQUIRED?
	JRST TL1		;NO

;USER IS SETTING OR CLEARING LINKS. GET SECOND ARGUMENT, WHICH IS A LINE
;NUMBER (OR -1 FOR ALL LINES IF CLEARING LINKS)

	XCTU [HRRZ 2,2]
	CAIN 2,-1		;'ALL' ?
	JRST TL1		;YES, LEAVE AS IS
	TRZE 2,.TTDES		;4XXXXX?
	JRST TL2		;YES
	MOVE 1,2		;ASSUME REGULAR JFN
	CALL CHKTTY
	 JRST TLINK9
TL2:	CAIL 2,NLINES		;LEGAL LINE?
	JRST TL3		;NO. TOO LARGE
	CAIL 2,0		;NEGATIVE IS ILLEGAL
	CAMN T2,CTYINT		;ALIAS FOR CTY?
TL3:	JRST [	MOVEI T1,DESX1	;INVALID LINE. FAIL
		JRST TLINK9]
;T2/ LINE NUMBER FOR REMOTE OR -1

TL1:	MOVEM T2,TLSAV1		;SAVE REMOTE LINE NUMBER IF ANY
	MOVE FX,OBJNO		;GET BACK OBJECT NUMBER
	UMOVE Q2,1		;GET FUNCTION FLAGS
	TXNE Q2,TL%CRO		;CLEAR REMOTE TO OBJECT?
	CALL TLINK0		;YES. GO DO IT
	TXNE Q2,TL%COR
	 JRST [	CALL TLINK1	;CLEAR OBJECT TO REMOTE
		 JRST TLINK9	;FAILED. GO RETURN ERROR
		JRST .+1]
	TXNE Q2,TL%EOR
	JRST [	CALL TLINK2	;SET OBJECT TO REMOTE
		 JRST TLINK9	;FAILED
		JRST .+1]
	TXNE Q2,TL%ERO
	JRST [	CALL TLINK3	;SET REMOTE TO OBJECT
		 JRST TLINK9
		JRST .+1]
	TXNE Q2,TL%SAB
	CALL TLINK4		;SET ACCEPT BIT TO C(B5)
	TXNE Q2,TL%STA		;SET ADVICE BIT?
	CALL TLINK5
	MOVE T2,OBJADR		;T2/ ADDRESS OF OBJECT'S DATA
	CALL ULKTTY		;ALLOW DEALLOCATION
	SMRETN

;AN ERROR OCCURRED. UNLOCK DATA AND RETURN FAILURE

TLINK9:	SKIPE T2,OBJADR		;T2/ ADDRESS OF OBJECT'S DATA
	CALL ULKTTY		;ALLOW DEALLOCATION
	RETERR			;RETURN ERROR CODE
;CLEAR REMOTE TO OBJECT

;ACCEPTS:
;	TLSAV1/ REMOTE LINE NUMBER OR -1
;	FX/ OBJECT LINE NUMBER

;	CALL TLINK0

;RETURNS +1: ALWAYS

;DETERMINES WHETHER USER WANTS TO CLEAR ALL OR ONE. CALLS ROUTINE
;FOR EACH REMOTE LINE NUMBER

TLINK0:	MOVE T2,TLSAV1		;GET REMOTE LINE NUMBER
	CAIE 2,-1		;ALL REMOTES?
	CALLRET TL0C		;NO, DO THE ONE SPECIFIED

;CLEAR LINKS FROM ALL REMOTES TO THIS OBJECT. LOOP THROUGH LINES

	MOVEI 2,0		;T2/ REMOTE LINE NUMBER
	CALL TL0C		;CLEAR LINKS FROM REMOTE TO OBJECT
	CAIGE 2,NLINES-1	;AT END OF LINES?
	AOJA 2,.-2		;NO. KEEP GOING
	RET			;YES. DONE

;TL0C - CLEAR ALL LINKS FROM SPECIFIED REMOTE TO OBJECT

;ACCEPTS:
;	T2/ REMOTE LINE NUMBER
;	FX/ OBJECT LINE NUMBER

;CALL TL0C

;RETURNS +1: ALWAYS

TL0C:	SAVELN
	CALL LCKTTY		;POINT TO DYNAMIC DATA FOR REMOTE
	 CALLRET ULKTTY		;NOT ACTIVE
TL0C1:	CALL TLTST1		;FIND LINK TO OBJECT IN REMOTE
	JUMPL 1,TL0C2		;DONE IF NO LINKS TO OBJ
	MOVEI 1,777		;FOUND ONE. CLEAR IT
	DPB 1,Q1		;CLEAR THE LINK JUST FOUND
	JRST TL0C1		;GO FIND ANOTHER

;DONE WITH THIS REMOTE LINE

TL0C2:	CALLRET ULKTTY		;ALLOW DEALLOCATION FOR REMOTE
;TLINK1 - CLEAR OBJECT TO REMOTE

;ACCEPTS:
;	FX/ OBJECT LINE NUMBER
;	TLSAV1/ REMOTE LINE NUMBER OR -1

;	CALL TLINK1

;RETURNS +1: FAILURE
;	 +2: SUCCESS

TLINK1:	MOVE T2,TLSAV1		;GET REMOTE LINE NUMBER
	CAIE 2,-1		;ALL?
	CALLRET TL1C		;NO, CLEAR SPECIFIC

;CLEAR ALL LINKS FROM THIS OBJECT. LOOP THROUGH LINK WORD

	MOVE Q1,[POINT 9,TTLINK(4),-1] ;POINT TO LINK WORD
TL12:	MOVE 4,OBJADR		;GET ADDRESS OF OBJECT'S DATA
	ILDB 2,Q1		;GET A LINE NUMBER
	CAIN 2,777		;IS THIS SLOT FREE?
	JRST TL14		;YES. SKIP IT
	PUSH P,Q1		;NO. SAVE BYTE POINTER
	CALL TL1C		;GO CLEAR ALL LINKS TO THIS REMOTE
	 RETBAD (,<POP P,Q1>)	;SOME SORT OF FAILURE
	POP P,Q1		;RESTORE BYTE POINTER
TL14:	TLNE Q1,(7B2)		;AT END OF LINK WORD?
	JRST TL12		;NO. GO TO NEXT FIELD
	RETSKP			;YES. DONE
;TL1C - CLEAR ALL LINKS FROM OBJECT TO THIS REMOTE

;ACCEPTS:
;	T2/ REMOTE LINE NUMBER
;	FX/ OBJECT LINE NUMBER

;	CALL TL1C

;RETURNS +1: FAILURE
;	 +2: SUCCESS

TL1C:	CALL TLTST2		;FIND LINK TO REMOTE
	JUMPL 1,RSKP		;NONE, DONE

;OBJECT POINTS TO REMOTE. DON'T ALLOW CLEARING IF REMOTE ALSO POINTS
;TO OBJECT

	MOVE 1,CAPENB
	TRNE 1,SC%WHL+SC%OPR	;PRIVILEGED?
	JRST TL13		;YES, SKIP CHECK
	MOVEM T2,REMNO		;SAVE REMOTE LINE NUMBER
	CALL LCKTTY		;POINT TO REMOTE DYNAMIC DATA
	 JRST [	CALL ULKTTY
		JRST TL13]
	PUSH P,Q1
	CALL TLTST1		;SEE IF REMOTE POINTS TO OBJECT
	CALL ULKTTY		;UNLOCK REMOTE'S DATA
	POP P,Q1		;RESTORE POINTER TO REMOTE LINK WORD
	JUMPGE 1,TL15		;ERROR IF REMOTE POINTS TO OBJECT
TL13:	MOVEI 1,777
	DPB 1,Q1		;CLEAR LINK JUST FOUND
	MOVE T2,REMNO		;RESTORE REMOTE LINE NUMBER
	JRST TL1C

TL15:	RETBAD (TLNKX1)
;TLINK2 - SET OBJECT TO REMOTE

;ACCEPTS:
;	FX/ OBJECT LINE NUMBER
;	TLSAV1 / REMOTE LINE NUMBER OR -1

;	CALL TLINK2

;RETURNS +1: FAILURE
;	 +2: SUCCESS

TLINK2:	STKVAR <TLNKT>
	MOVEI T2,5		;MAX TRIES IF REMOTE IF REFUSING
	MOVEM T2,TLNKT		;SAVE IT
TLNK2:	MOVE T2,TLSAV1		;GET REMOTE LINE NUMBER
	CAIN 2,-1		;SPECIFIED ALL?
	RETBAD (DESX1)		;NON-SPECIFIC DESIGNATOR ILLEG HERE
	CAMN 2,FX		;LINK TO SELF?
	RETSKP			;YES, IGNORE
	CALL TLTST2		;LINK ALREADY EXISTS?
	JUMPG 1,RSKP		;IGNORE IF YES
	MOVEI T2,777		;LOOK FOR AN EMPTY SLOT
	CALL TLTST2		; THAT WE COULD ACCEPT WITH
	JUMPL T1,[RETBAD (TLNKX3)] ;ALL LINKS ARE IN USE ALREADY
	MOVE T2,TLSAV1		;GET BACK THE REMOTE LINE NUMBER

;IF REMOTE IS NOT ACCEPTING LINKS, RING THE BELL AND WAIT TO SEE IF
;USER DECIDES TO ACCEPT

	CALL LCKTTY		;POINT TO REMOTE DYNAMIC DATA
	 JRST [	CALL ULKTTY
		RETBAD (TTYX01)]
;REPEAT SEQUENCE OF CHECKING ACCEPT BIT, RINGING BELL, AND WAITING
;UNTIL EITHER REMOTE ALLOWS LINKS OR WE TIME OUT

TL21:	MOVE 3,TLSAV1		;GET THE REMOTE LINE NUMBER
	JN TTNTM,(3),TL26	;IF NO TERMINAL MSGS - GENERATE ERROR 
	MOVEI 3,TT%ALK		;ACCEPT BIT
	MOVE 4,CAPENB
	TRNN 4,SC%WHL+SC%OPR	;PRIVILEGED? OR
	TDNE 3,TTFLGS(2)	;REMOTE ACCEPTING?
	JRST TL22		;YES
	SOSGE TLNKT		;TRY AGAIN?
	JRST TL24		;NO. CAN'T DO THE LINK
	CALL ULKTTY		;FREE REMOTE LOCK
	SKIPE T2,OBJADR		;GET OBJECT ADDRESS
	CALL ULKTTY		;FREE IT AS WELL
	SETZM OBJADR		;SAY NO LOCK HERE
	MOVEI 4,^D10		;A RING IS 10 BELLS

TL23:	NOSKED			;OWN MACHINE FOR A WHILE
	HRROI T1,[BYTE (7) .CHBEL] ;GET A BELL
	PUSH P,4		;SAVE COUNTER
	MOVE T2,TLSAV1		;GET REMOTE LINE NUMBER
	CALL TTEMES		;OUTPUT A BELL
	HRROI T1,[BYTE (7) .CHBEL] ;GET A BELL AGAIN
	MOVE T2,FX		;GET OBJECT LINE NUMBER
	CALL TTEMES		;OUTPUT A BELL HERE TOO
	POP P,4			;RESTORE COUNTER
	OKSKED			;RELEASE MACHINE NOW
	SOJG 4,TL23

;WAIT A WHILE

	MOVEI 1,^D3000		;WAIT FOR 3 SECONDS, THE BELL WILL BE
	DISMS			;RINGING FOR THE FIRST SECOND OF WAIT
	MOVE T2,FX		;GET OBJECT LINE NUMBER
	CALL LCKTTY		;LOCK IT UP
	 JRST [	CALL ULKTTY	;FREE IT
		RETBAD (TTYX01)] ;AND GIVE ERROR
	MOVEM T2,OBJADR		;SAY IT IS NOW LOCKED
	JRST TLNK2		;AND TRY AGAIN

	ENDSV.			;END STKVAR
;REMOTE IS ACCEPTING LINKS

TL22:	CALL ULKTTY
	MOVEI 2,777
	CALL TLTST2		;FIND FREE FIELD IN OBJECT
	JUMPL 1,[RETBAD (TLNKX3)] ;LINKS FULL
	MOVE T2,TLSAV1		;GET REMOTE LINE NUMBER
	DPB 2,Q1		;DEPOSIT REMOTE NUMBER IN FIELD
	MOVE T2,OBJADR		;GET OBJECT DYNAMIC DATA
	CALL ULKTTY		;FREE IT
	SETZM OBJADR		;NO LOCK HELD
	SKIPN LNKWRN		;LINKING FROM MY OWN JOB?
	JRST TL25		;NO, SKIP MESSAGE
	MOVE T1,OBJNO		;GET TERMINAL NUMBER
	ADDI T1,.TTDES		;TURN INTO DESIGNATOR
	HRROI T2,[ASCIZ /
[Link from /]			;[9117] Start the message
	SETZ 3,
	SOUT			;MSG ON OBJECT ALSO SEEN ON REMOTE
	 ERJMP TL25
	MOVE 2,JOBNO
	HRRZ 2,JOBDIR(2)	;USER ON THIS JOB
	HRLI 2,USRLH		;TURN IT INTO A USER NUMBER
	DIRST			;TYPE HIS NAME
	 JFCL
	HRROI T2,[ASCIZ /, TTY/] ;[9117] Label the following number
	SOUT
	 ERJMP TL25
	MOVE 2,FX		;OBJECT LINE NUMBER
	MOVEI 3,10
	NOUT
	 ERJMP TL25
	HRROI T2,[ASCIZ /]
/]				;[9117] Close the message
	SETZ T3,
	SOUT
	 ERJMP TL25

TL25:	MOVE T2,FX		;GET OBJECT LINE NUMBER
	CALL LCKTTY		;LOCK IT AGAIN
	 JRST [	CALL ULKTTY	;OOPS. WENT AWAY
		RETBAD (TTYX01)] ;GIVE ERROR
	MOVEM T2,OBJADR		;SAY HOLD LOCK
	RETSKP

TL24:	CALL ULKTTY
	RETBAD (TLNKX2)

TL26:	CALL ULKTTY
	RETBAD (TTMSX2)
;TLINK3 - SET REMOTE TO OBJECT

;ACCEPTS:
;	TLSAV1/ REMOTE LINE NUMBER OR -1
;	FX/ OBJECT LINE NUMBER

;	CALL TLINK3

;RETURNS +1: FAILURE
;	 +2: SUCCESS

TLINK3:	MOVE T2,TLSAV1		;GET REMOTE LINE NUMBER
	CAIN 2,-1
	RETBAD (DESX1)		;MULTIPLE DESIGNATOR ILLEGAL
	CAMN 2,FX		;LINK TO SELF?
	RETSKP			;YES, IGNORE
	CALL LCKTTY
	 JRST [	CALL ULKTTY
		RETBAD (TTYX01)]
	CALL TLTST1		;SEE IF REMOTE POINTS TO OBJECT
	JUMPG 1,TL33		;IF SO, ALREADY DONE
	MOVE 1,CAPENB
	TRNE 1,SC%WHL+SC%OPR	;PRIVILEGED?
	JRST TL31		;YES, SKIP CHECK
	EXCH T2,TLSAV1		;GET REMOTE LINE NUMBER
	CALL TLTST2		;SEE IF OBJECT POINTS TO REMOTE
	JUMPL 1,[MOVEI T1,TLNKX1 ;IF NOT, ERROR
		EXCH T2,TLSAV1	;GET BACK REMOTE ADDRESS
		CALLRET ULKTTY]
	EXCH T2,TLSAV1		;GET BACK ADDRESS OF REMOTE
TL31:	PUSH P,FX
	MOVEI FX,777
	CALL TLTST1		;FIND FREE FIELD IN REMOTE
	POP P,FX
	JUMPL 1,[MOVEI T1,TLNKX3
		CALLRET ULKTTY]
	DPB FX,Q1		;DEPOSIT OBJ NUMBER IN FIELD
TL33:	CALL ULKTTY
	RETSKP
;TLINK4 - SET ACCEPT BIT

TLINK4:	MOVE T2,OBJADR
	MOVEI 1,TT%ALK		;IT IS BIT 26 IN TTFLGS
	TLNE Q2,(1B5)		;SET IT?
	IORM 1,TTFLGS(T2)	;YES
	TLNN Q2,(1B5)		;CLEAR IT?
	ANDCAM 1,TTFLGS(T2)	;YES
	RET

;SET OR CLEAR ACCEPT ADVICE

TLINK5:	MOVE T2,OBJADR
	MOVEI 1,TT%AAD		;YES, GET BIT
	TLNE Q2,(1B7)
	IORM 1,TTFLGS(T2)	;YES
	TLNN Q2,(1B7)		;CLEAR IT?
	ANDCAM 1,TTFLGS(T2)	;YES
	RET
;CHECK FOR EXISTENCE OF REMOTE TO OBJECT

;ACCEPTS:
;	T2/ ADDRESS OF REMOTE
;	FX/ OBJECT LINE NUMBER

;	CALL TLTST1

;RETURNS +1: ALWAYS,
;		T1/ NUMBER OF OBJECT
;			OR
;		   -1 IF REMOTE DOESN'T POINT TO OBJECT
;		Q1/ BYTE POINTER TO LINK WORD FOR REMOTE

;CLOBBERS NO AC'S

TLTST1:	MOVE Q1,[POINT 9,TTLINK(2),-1]
TLT1:	ILDB 1,Q1		;SCAN REMOTE
	CAMN 1,FX		;FOUND OBJECT?
	RET			;YES
	TLNE Q1,(7B2)		;NO, SCANNED ALL FIELDS?
	JRST TLT1		;NO
	SETO 1,			;YES, RETURN NEGATIVE VALUE
	RET

;TLTST2 - CHECK FOR EXISTENCE OF OBJECT TO REMOTE

;ACCEPTS:
;	T2/ REMOTE LINE NUMBER

;	CALL TLTST2

;RETURNS +1: ALWAYS,
;		T1/ NUMBER OF REMOTE
;			OR
;		    -1 IF OBJECT DOESN'T POINT TO REMOTE
;		Q1/ BYTE POINTER TO LINK WORD FOR OBJECT WHERE REMOTE WAS FOUND

;CLOBBERS NO AC'S

TLTST2:	MOVE 3,OBJADR		;GET ADDRESS OF OBJECT
	MOVE Q1,[POINT 9,TTLINK(3),-1] ;POINT TO LINK WORD IN OBJECT
TLT2:	ILDB 1,Q1		;SCAN OBJECT
	CAMN 1,2		;FOUND REMOTE?
	RET			;YES
	TLNE Q1,(7B2)		;NO, SCANNED ALL FIELDS?
	JRST TLT2		;NO
	SETO 1,			;YES, RETURN NEG VALUE
	RET

	ENDTV.			;END TRVAR
	SUBTTL Miscellaneous Global Routines

;NOTE: THE FOLLOWING ROUTINES WERE WRITTEN TO SOLVE A PARTICULAR PROBLEM;
;I. E., MODULES OTHER THAN TTYSRV WERE REFERENCING TELETYPE DATA. EACH
;OF THESE ROUTINES REPLACES CODE IN ONE OR MORE MODULES SO THAT THOSE
;MODULES NO LONGER REFERENCE TELETYPE DATA. ADDITIONS OF CALLS TO THESE
;ROUTINES MUST TAKE INTO ACCOUNT THE RULES ABOUT LOCKING/UNLOCKING DYNAMIC
;DATA.

;GTCJOB - GET JOB NUMBER FOR WHICH THIS IS THE CONTROLLING TERMINAL

;ACCEPTS: T2/ INTERNAL LINE NUMBER

;	CALL GTCJOB

;RETURNS +1: LINE IS NOT ACTIVE
;	 +2: LINE IS ACTIVE,
;		T3/ JOB NUMBER OF OWNING JOB

	RESCD

GTCJOB::SAVELN
	CALL STADYN		;POINT TO DYNAMIC DATA
	 RETBAD (TTYX01)	;LINE NOT FULLY ACTIVE
	LOAD T3,TCJOB,(T2)	;GET OWNING JOB
	RETSKP

;STCJOB - SET CONTROLLING JOB

;ACCEPTS:
;	T1/ JOB NUMBER
;	T2/ LINE NUMBER

;	CALL STCJOB

;RETURNS +1: ALWAYS

	SWAPCD
STCJOB::CALL LCKTTY
	CALLRET ULKTTY
	STOR T1,TCJOB,(T2)
	CALLRET ULKTTY
;GTTOPF - GET TOP FORK OF A SCTTY GROUP

;ACCEPTS:
;	T2/ INTERNAL LINE NUMBER

;	CALL GTTOPF

;RETURNS +1: LINE NOT ACTIVE
;	 +2: LINE IS ACTIVE,
;		T3/ FORK NUMBER OF TOP FORK (OR -1)
	RESCD

GTTOPF::SAVELN
	CALL STADYN		;POINT TO DYNAMIC DATA
	 RETBAD (TTYX01)	;LINE NOT FULLY ACTIVE
	LOAD T3,TTPFK,(T2)	;GET TOP FORK
	RETSKP

;STTOPF - SET TOP FORK OF A SCTTY GROUP

;ACCEPTS:
;	T1/ FORK NUMBER OR -1 TO STORE IN TTPFK
;	T2/ INTERNAL LINE NUMBER

;	CALL STTOPF

;RETURNS +1: ALWAYS

STTOPF::SAVELN
	CALL LCKTTY		;POINT TO DYNAMIC DATA
	 CALLRET ULKTTY		;NOT AN ACTIVE LINE
	STOR T1,TTPFK,(T2)	;STORE NEW FORK DATA
STTOPX:	CALLRET ULKTTY
	SWAPCD
;GTWFRK - GET NUMBER OF FORK IN INPUT WAIT ON THIS TERMINAL

;ACCEPTS:
;	T2/ INTERNAL LINE NUMBER

;	CALL GTWFRK

;RETURNS +1: ALWAYS,
;		T1/ NUMBER OF FORK OR -1 IF NONE

	RESCD

GTWFRK::SAVELN
	CALL STADYN
	 JRST GTWFR1
	LOAD T1,TWFRK,(T2)
	RET
GTWFR1:	MOVEI T1,-1
	RET

;TTCLFK - CLEAR WAITING FORK ON TERMINAL

;ACCEPTS:
;	T2/ LINE NUMBER

;	CALL TTCLFK

;RETURNS +1: ALWAYS

	SWAPCD

TTCLFK::NOSKED			;PREVENT RESCHEDULING
	CALL STADYN		;GET TTY'S DATA BASE
	 JRST TTCLF1		;NOT ACTIVE. IGNORE IT
	SETONE TWFRK,(T2)	;INDICATE NO WAITING FORK
TTCLF1:	OKSKED			;ALL DONE
	RET
;PTYTTY - CONVERT PTY NUMBER TO INTERNAL LINE NUMBER (TTY NUMBER)

;ACCEPTS:
;	T2/ PTY NUMBER

;	CALL PTYTTY

;RETURNS +1: ALWAYS
;		T2/ INTERNAL LINE NUMBER

;CLOBBERS NO ACS

	SWAPCD
PTYTTY::ADD T2,TT1LIN+TT.PTY	;ADD NUMBER OF FIRST PTY LINE TO GET LINE NO.
	RET

;TTYPTY - CONVERT INTERNAL LINE NUMBER TO PTY NUMBER

;ACCEPTS:
;	T1/ INTERNAL LINE NUMBER

;	CALL TTYPTY

;RETURNS +1:ALWAYS,
;		T1/ PTY NUMBER

;CLOBBERS NO ACS

	RESCD
TTYPTY::SUB T1,TT1LIN+TT.PTY		;SUBTRACT FIRST PTY LINE TO GET PTY NUMBER
	RET

;CHKPTY - SEE IF THIS LINE NUMBER IS A PTY

;ACCEPTS:
;	T1/ INTERNAL LINE NUMBER

;	CALL CHKPTY

;RETURNS +1: NOT A PTY
;	 +2: A PTY
;		T1/ PTY NUMBER

CHKPTY::ACVAR <W1>		;GET AN AC TO WORK WITH
	LOAD W1,TTSTY,(T1)	;GET LINE TYPE FOR THIS LINE
	CAIE W1,TT.PTY		;IS IT A PTY?
	RETBAD			;NO. FAILURE
	CALL TTYPTY		;CONVERT TO PTY NUMBER
	RETSKP			;RETURN SUCCESS
	SWAPCD

	ENDAV.			;END ACVAR
;CKPHYT - SEE IF THIS IS A PHYSICAL TERMINAL

;ACCEPTS:
;	T2/ INTERNAL LINE NUMBER

;	CALL CKPHYT

;RETURNS +1: A PTY
;	 +2: A PHYSICAL TERMINAL

;PRESERVES AC'S

	RESCD

CKPHYT::TDCALL S,<<PT,RSKP>>
	 RETSKP			;NOT A PTY
	RET			;A PTY

;CKPHYD - SAME AS ABOVE BUT FOR DYNAMIC PTR
; T2/ DYNAMIC PTR

CKPHYD:	TDCALL D,<<PT,RSKP>>
	 RETSKP			;NOT A PTY
	RET			;A PTY

;CLRINT - CLEAR INTERRUPT WORD FOR A GIVEN LINE

;ACCEPTS:
;	T1/ INTERRUPT BIT
;	T2/ LINE NUMBER

;	CALL CLRINT

;RETURNS +1: ALWAYS

CLRINT::CALL LCKTTY		;POINT TO DYNAMIC DATA, PREVENT DEALLOCATION
	 CALLRET ULKTTY		;NOT FULLY ACTIVE. IGNORE
	ANDCAM T1,TTPSI(T2)	;CLEAR INTERRUPT BIT
CLRIN1:	CALLRET ULKTTY		;ALLOW DEALLOCATION
;TTSINT - SET UP INTERRUPT WORD FOR TERMINAL

;ACCEPTS:
;	T1/ DESIRED CONTENTS OF TTPSI
;	T2/ INTERNAL LINE NUMBER
;	T3/ DESIRED CONTENTS OF TTDPSI

;RETURNS +1: ALWAYS
	SWAPCD

TTSINT::SAVELN
	CALL LCKTTY		;GET ADDRESS OF DYNAMIC DATA
	 CALLRET ULKTTY		;NOT FULLY ACTIVE
	EXCH T1,TTPSI(T2)	;STORE INTERRUPT WORD, GET OLD ONE
	EXCH T3,TTDPSI(T2)	;DITTO DEFERRED INTERRUPT WORD
	TDCALL D,<<CH,CTHOBS>>	;[7.1024]IF CTERM, SEND THE INFO TO THE SERVER
	CALLRET ULKTTY		;ALLOW DEALLOCATION

;ROUTINE USED BY ATACH JSYS TO SEE IF AN ATTEMPTED ATACH IS LEGAL
;
;ACCEPTS:	T2/ TTY LINE NUMBER
;RETURNS:	+1  ILLEGAL ATACH
;		+2  OK TO ATACH
   REPEAT 0,<
ATACTT::NOSKED			;INSURE INTEGRITY WHILE LOOKING AT TTY DATA
	CALL STADYN		;HAVE A FULL DATA BLOCK?
	IFNSK.			;NO
	   SKIPE T2		;BECOMING ACTIVE?
	   JRST ATACTL		;YES - LOSE
	   JRST ATACTW		;NO, SHORT BLOCK - WIN
	ENDIF.
	TMNN TTPRM,(T2)		;HAVE FULL BLOCK, IS IT PERMANENT?
	JRST ATACTL		;NO - LOSE
	TMNE TTBAC,(T2)		;YES, IS IT BECOMING ACTIVE?
	JRST ATACTL		;YES - LOSE
	LOAD T3,TCJOB,(T2)	;NO, GET ASSOCIATED JOB
	HRRES T3		;MAKE A FULL WORD
	SKIPL T3		;IS THERE CURRENTLY A JOB?
	JRST ATACTL		;YES - LOSE
ATACTW:	OKSKED			;DONE WITH DATA BASE
	RETSKP			;ATACH IS LEGAL

ATACTL:	OKSKED			;DONE WITH DATA BASE
	RET			;ATACH IS NOT LEGAL
   >				;End of REPEAT 0
;CKBJFN - SEE IF BKJFN HAS ALREADY BEEN DONE ON THIS LINE

;ACCEPTS:
;	T2/ INTERNAL LINE NUMBER

;	CALL CKBJFN

;RETURNS +1: BKJFN HAS NOT BEEN DONE
; 	 +2: BKJFN HAS ALREADY BEEN DONE

	SWAPCD
CKBJFN::SAVELN
	CALL STADYN		;GET ADDRESS OF DYNAMIC DATA
	 RETBAD			;NOT ACTIVE. BKJFN HAS NOT BEEN DONE
	JN TTRFG,(T2),RSKP	;IF FLAG SET, BKJFN HAS BEEN DONE
	RETBAD			;OTHERWISE, HASN'T BEEN DONE

;TTCKAD - SEE IF LINE IS ACCEPTING ADVICE

;ACCEPTS:
;	T2/ ADDRESS OF DYNAMIC DATA

;	CALL TTCKAD

;RETURNS +1: NOT ACCEPTING ADVICE
;	 +2: ACCEPTING ADVICE

TTCKAD::JE TT%AAD,TTFLGS(T2),R	;IF NOT, NONSKIP
	RETSKP			;INDICATE ACCEPTING
;GTBPTY - GETAB ROUTINE TO GET PTY INFO

;RETURNS +1: ALWAYS
;	T1/ (NUMBER OF PTYS,,FIRST PTY NUMBER)

GTBPTY::HRLI T1,NTTPTY		;NUMBER OF PTYS
	HRR T1,TT1LIN+TT.PTY	;GET FIRST LINE NUMBER
	RET

;GTBTTF - GETAB ROUTINE FOR TTFORK TABLE

;ACCEPTS:
;	T2/ LINE NUMBER

;RETURNS +1: ALWAYS,
;	T1/ (CONTROLLING JOB,,WAITING FORK)
;		OR
;	    -1 IF LINE IS INACTIVE
;		OR
;	    (-2,,-1) IF JOB IS BEING CREATED ON THE LINE

GTBTTF::CALL LCKTTY		;POINT TO DYNAMIC DATA, PREVENT DEALLOCATION
	 JRST GTBTT1		;NOT ACTIVE.
	JN TTPRM,(T2),[	JE TTBAC,(T2),.+1 ;IF PERMANENT, AND BECOMING
			HRLOI T1,-2 ; ACTIVE, RETURN (-2,,-1)
			CALLRET ULKTTY] ;GO CLEAN UP

;LINE IS EITHER FULLY ACTIVE AND NOT PERMANENT, OR PERMANENT AND NOT BECOMING ACTIVE.
;GET OWNING JOB AND WAITING FORK AND RETURN THEM

	LOAD T1,TWFRK,(T2)	;GET WAITING FORK
	LOAD T3,TCJOB,(T2)	;GET OWNING JOB
	HRL T1,T3		;COMBINE THEM
	CALLRET ULKTTY

;LINE IS NOT FULLY ACTIVE.  RETURN -1 IF INACTIVE, (-2,,-1) IF
;BECOMING ACTIVE

GTBTT1:	SETOM T1		;NOT ACTIVE. INDICATE NO OWNER OR FORK
	SKIPGE T2		;IS JOB BEING CREATED ON THIS LINE?
	HRLI T1,-2		;YES. INDICATE THAT
	CALLRET ULKTTY		;ALLOW DEALLOCATION
;STPRM - SET THE PERMANENT BIT IN DYNAMIC DATA

;ACCEPTS:
;	T2/ ADDRESS OF DYNAMIC DATA

;	CALL STPRM

;RETURNS +1: ALWAYS

STPRM::	SETONE TTPRM,(T2)
	RET

;CLRPRM - CLEAR THE PERMANENT BIT

;ACCEPTS:
;	T2/ ADDRESS OF DYNAMIC DATA

;	CALL CLRPRM

;RETURNS +1: ALWAYS

CLRPRM::SETZRO TTPRM,(T2)
	RET

;CKINP - CHECK FOR INPUT BUFFER EMPTY

;ACCEPTS:
;	T2/ INTERNAL LINE NUMBER

;	CALL CKINP

;RETURNS +1: INPUT BUFFER IS EMPTY
;	 +2: INPUT BUFFER IS NOT EMPTY

	RESCD
CKINP::	CALL LCKTTY		;POINT TO DYNAMIC DATA, PREVENT DEALLOCATION
	 CALLRET ULKTTY		;NOT ACTIVE. INDICATE NO CHARACTERS
	SKIPE TTICT(T2)		;ACTIVE. ANY INPUT CHARACTERS?
	JRST [	CALL ULKTTY	;YES. ALLOW DEALLOCATION
		RETSKP]		;INDICATE NON-ZERO COUNT
	CALLRET ULKTTY		;ALLOW DEALLOCATION INDICATE ZERO COUNT
;TTCKSP - ROUTINE CALLED FROM SYSINE TO SEE IF THIS LINE NEEDS A SET SPEED
;DONE BEFORE JOB INITIALIZATION

;ACCEPTS:
;	T2/ INTERNAL LINE NUMBER

;	CALL TTCKSP

;RETURNS +1: ALWAYS

;THIS IS RELEVANT FOR REMOTE FRONT END LINES ONLY.  WHEN A JOB LOGS OFF OF A REMOTE
;LINE AND THE NEXT CARRIER-ON INTERRUPT COMES IN ON THIS LINE,
;BIT TTFSP IN TTFWED IS SET, INDICATING THAT THE SPEED MUST BE RESET
;TO THE DEFAULT. THIS ROUTINE LOOKS FOR THAT BIT
;THE (INPUT,,OUTPUT) SPEEDS ARE IN TTSPWD FOR THIS LINE

	SWAPCD
TTCKSP::JE <TTFEM,TTFSP>,(B),R	;IF NOT REMOTE, GO AWAY
				;OR IF DON'T NEED SPEED SETTING
	SETZRO TTFSP,(B)	;CLEAR SPEED SETTING REQUIRED
	TMNN TTAUT,(B)			;NON-AUTO LINE?
	SKIPG C,TTSPWD(B)	;HAVE A SPEED TO SET?
	RET			;NO. GIVE IT UP
	MOVEI A,.TTDES(B)	;A/ DEVICE DESIGNATOR FOR THIS LINE
	MOVEI B,.MOSPD		;B/ THE FUNCTION
	MTOPR			;GO SET THE SPEED
 	 ERJMP .+1		;IGNORE FAILURE (ACJ REFUSAL)
	RET			;AND DONE


;INIT SPEED WORDS
TTSPIN::MOVSI B,-NLINES		;ONLY DO THE REAL LINES
	SETOM TTSPWD(B)		;INITIALIZE THE LINE SPEEDS
	AOBJN B,.-1		;DO ALL LINES
	ret			;all done
;TTHNGU - HANG UP DATASET

;ACCEPTS:
;	T2/ LINE NUMBER

;	CALL TTHNGU

;RETURNS +1: ALWAYS

;CALLED BY THE LGOUT JSYS IF THE JOB ON THIS LINE WAS NOT LOGGED IN.

	SWAPCD
TTHNGU::CAMN 2,CTYLNO		;IS THIS THE CTY?
	RET			;YES. DON'T HANG IT UP
 REPEAT 0,<
	PUSH P,T2		;SAVE LINE NUMBER
	CALL LCKTTY		;POINT TO DYNAMIC DATA, PREVENT DEALLOCATION
	 JRST TTHNG1		;NOT ACTIVE. CAN'T HAVE OUTPUT
	CALL TTDOBE		;WAIT TILL NO OUTPUT
	 JRST [	POP P,T2	;GET BACK LINE
		JRST TTHNGU]	;TRY AGAIN
TTHNG1:	CALL ULKTTY		;ALLOW DEALLOCATION
	POP P,T2		;RESTORE LINE NUMBER
 >;END REPEAT 0 - SOBE LOOP HAS BEEN DONE ALREAYD AT LOG2. TTDOBE CAUSES HANGS

	TDCALL S,<<FE,TTHU2>,<MC,MCHNGU>,<TV,TVTDTS>,<CH,CTHNGU>,<LH,LTHNGU>>;
	RET

;TTUHUP - Routine to "unhangup" a line (raise DTR for dialout modems)
;	Called via MTOPR's .MTUHU function and when a JFN to terminal closed.
;
;Accepts:
;	T2/ internal line number
;
;Returns +1: Always

TTUHUP::TDCALL S,<<FE,TTUHU>>	;[7435] (T2/) Only applies to front end lines
	RET			;[7435] No-op on all other line types
;TTABRT - ROUTINE TO ABORT JOB STARTUP

;ACCEPTS:
;	T2/ INTERNAL LINE NUMBER

;	CALL TTABRT

;RETURNS +1: ALWAYS

;THIS ROUTINE IS CALLED BY JOBSRT WHEN IT CANNOT START A JOB
;BECAUSE OF SOME FULL CONDITION.  IF THE LINE IS NOT A PERMANENT
;BLOCK, TTACTL SHOULD BE -1; THIS ROUTINE SETS IT TO 0.  IF THE LINE
;IS A PERMANENT BLOCK, TT%BAC SHOULD BE SET; THIS ROUTINE CLEARS IT
;THIS ALLOWS TTEMES TO SEND THE 'FULL' TO THE LINE

	RESCD
TTABRT::SAVELN
	SKIPG T3,TTACTL(T2)	;IS LINE ACTIVE?
	JRST [	SETZM TTACTL(T2) ;INDICATE NOT ACTIVE
		RET]
	SETZRO TTBAC,(T3)	;INDICATE NOT BECOMING ACTIVE
	RET
	SUBTTL Buffer Control

;ASSIGN AND SETUP TTY BUFFERS
; 3/ NUMBER OF BUFFERS TO GET
;  RETURNS +1 TRANSPARENT, EXCEPT
; 3/ BYTE POINTER FOR INPUT AND OUTPUT POINTER WORDS
;THIS ROUTINE ASSUMES THAT IT IS PROTECTED FROM RESCHEDULING

	RESCD

TTGTBF:	PUSH P,1		;TRANSPARENT TO ALL AC'S EXCEPT 3
	PUSH P,4
	PUSH P,3		;SAVE COUNT
	SETZ 1,
TTGTB1:	CHNOFF DLSCHN
	SOSGE TTFREC		;REDUCE FREE BUFFER COUNT
	JRST TTGTB3		;NONE LEFT
	HRRZ 3,@TTFREB		;GET BUFFER FROM LIST
	EXCH 3,TTFREB
	CHNON DLSCHN
	HRRZ 4,1
	JUMPE 1,[MOVSI 1,0(3)	;FIRST BUFFER, REMEMBER ITS ADDRESS
		JRST .+2]
	HRRZM 3,0(4)		;CONC NEW BUFFER ONTO LIST
	HRRI 1,0(3)
	SOSLE 0(P)		;GOT REQUESTED NUMBER OF BUFFERS?
	JRST TTGTB1		;NO
	HLRZ 3,1		;ADDRESS OF FIRST BUFFER IN LIST
	HRRZ 4,1		;ADDRESS OF LAST BUFFER IN LIST
	HRRZM 3,0(4)		;MAKE LAST POINT TO FIRST
	ADD 3,[XWD 670000,1]	;CONSTRUCT 9-BIT BYTE POINTER TO FIRST BYTE
	AOS -3(P)		;GIVE GOOD RETURN
TTGTB2:	ADJSP P,-1		;JUNK
	POP P,4
	POP P,1
	RET
TTGTB3:	BUG.(CHK,TTYNTB,TTYSRV,SOFT,<Ran out of TTY buffers>,,<

Cause:	TTGTBF was called to assign and set up TTY buffers but TTFREC indicates
	that there are no buffers available.

Action:	If this BUGCHK is reproducible, set it dumpable and submit an SPR with
	the dump and instructions on reproducing the problem.
>,,<DB%NND>)			;[7.1210] 
	AOS TTFREC		;GIVE BACK FRUITLESS SOS
	CHNON DLSCHN		;RESTORE THE CHANNEL
	HRRZ 4,1
	JUMPE 1,TTGTB2		;RETURN IF THERE WERE NONE
	HLRZ 3,1		;COMPLETE THE ONES WE GOT
	HRRZM 3,0(4)
	ADD 3,[670000,,1]
	CALL TTRLBF		;THEN GIVE THEM BACK
	JRST TTGTB2
;RELEASE LIST OF TTY BUFFERS
; 3/ BYTE POINTER ANYWHERE IN ANY BUFFER OF LIST
;  RETURNS +1, CLOBBERS 3
;	PRESERVES 1
;ASSUMES INTERRUPT PROTECTION AS ABOVE

TTRLBF:	MOVEI 3,0(3)		;GET ADDRESS WITHOUT BYTE POINTER
	JUMPE 3,R		;IN CASE NO BUFFERS
	PUSH P,1
	TDNN 3,WRPMSK		;NOW AT END OF BUFFER?
	SUBI 3,TTSIZ		;YES
	ANDCM 3,WRPMSK		;NORMALIZE POINTER TO FIRST WD OF BFR
	ADDI 3,1		;WHICH IS 1 AFTER THE 0 MOD TTSIZ
	PUSH P,3		;SAVE ADDRESS OF FIRST BUFFER
	PUSH P,[0]		;DON'T CHNOFF IF ALREADY OFF
	CONSO PI,1B<DLSCHN+^D28>
	SETOM 0(P)		;INDICATE ALREADY OFF
TTRLB1:	MOVEI 1,0(3)
	HRRZ 3,0(3)		;NEXT BUFFER IN LIST
	SKIPN 0(P)		;LEAVE CHANNEL ALONE
	CHNOFF DLSCHN
	EXCH 1,TTFREB		;PUT BUFFER ON FREE LIST
	MOVEM 1,@TTFREB
	AOS TTFREC
	SKIPN 0(P)		;NO CHANNEL ON IF ALREADY OFF
	CHNON DLSCHN
	CAME 3,-1(P)		;CIRCLED AROUND TO FIRST BUFFER?
	JRST TTRLB1		;NO
	ADJSP P,-2		;RESTORE STACK
	POP P,1
	RET

;TTRLOB - RELEASE OUTPUT BUFFERS
;ACCEPTS:
;	T1/ ADDRESS OF DYNAMIC DATA
;  RETURNS +1: ALWAYS

;CLOBBERS 3 BUT PRESERVES 1
;LINE MAY BE FULLY ACTIVE OR ACTIVE WITH A MESSAGE BLOCK
;ASSUMES INTERRUPT PROTECTION AS ABOVE

TTRLOB:	SKIPN 3,TTOOUT(2)	;OUTPUT BUFFERS TO RELEASE?
	RET			;NO
	SETZM TTOCT(T2)		;CLEAR COUNT OF BYTES
	SETZM TTOOUT(2)		;YES. CLEAR OUTPUT POINTER
	SETZM TTOIN(2)		;CLEAR INPUT POINTER
	CALL CHKBKO		;PERHAPS FORK WAITING FOR OBUF EMPTY
	CALLRET TTRLBF		;RELEASE THEM
	SUBTTL Character Information Table (CHITAB)

	RESCD

;CHARACTER INFORMATION TABLE
;B0 - PARITY BIT FOR CHARACTER
;B12-17 - CHARACTER WAKEUP CLASS
;B18-35 - DISPATCH ADDRESS (CONTROL CHARACTERS ONLY)

PCLASS:	POINT Q2,CHITAB(1),17	;POINTER TO CLASS BITS

AN==1				;ALPHANUMERIC CLASS BIT
PC==2				;PUNCTUATION CLASS BIT
CT==4				;CONTROL (NON-FORMATTING) CLASS BIT
FC==10				;FORMATTING CONTROL CLASS BIT

DEFINE CH(PAR,CLS,DSP)<
   IFNB <DSP>,<<PAR>B0+<CLS>B17+DSP>
   IFB <DSP>,<<PAR>B0+<CLS>B17+TCOUT>>

CHITAB::CH(0,CT)		; 0 NULL
	CH(1,CT)		; 1 ^A
	CH(1,CT)		; 2 ^B
	CH(0,CT)		; 3 ^C
	CH(1,CT)		; 4 ^D
	CH(0,CT)		; 5 ^E
	CH(0,CT)		; 6 ^F
	CH(1,CT)		; 7 ^G

	CH(1,FC,TTSM4)		; 10 ^H BACKSPACE
	CH(0,PC,TTSM1)		; 11 ^I TAB
	CH(0,FC,TTSM12)		; 12 ^J LF
	CH(1,CT)		; 13 ^K
	CH(0,FC,TTSM3)		; 14 ^L FORMFEED
	CH(1,FC,TTSM5)		; 15 ^M CR
	CH(1,CT)		; 16 ^N
	CH(0,CT)		; 17 ^O

	CH(1,CT)		; 20 ^P
	CH(0,CT)		; 21 ^Q
	CH(0,CT)		; 22 ^R
	CH(1,CT)		; 23 ^S
	CH(0,CT)		; 24 ^T
	CH(1,CT)		; 25 ^U
	CH(1,CT)		; 26 ^V
	CH(0,CT)		; 27 ^W

	CH(0,CT)		; 30 ^X
	CH(1,CT)		; 31 ^Y
	CH(1,CT)		; 32 ^Z
	CH(0,17,TTSME)		; 33 ^[ ESC
	CH(1,CT)		; 34 ^\
	CH(0,CT)		; 35 ^]
	CH(0,CT)		; 36 ^^
	CH(1,CT)		; 37 ^_
	CH(1,PC)		; 40 SPACE
	CH(0,PC)		; 41 !
	CH(0,PC)		; 42 "
	CH(1,PC)		; 43 #
	CH(0,PC)		; 44 $
	CH(1,PC)		; 45 %
	CH(1,PC)		; 46 &
	CH(0,PC)		; 47 '

	CH(0,PC)		; 50 (
	CH(1,PC)		; 51 )
	CH(1,PC)		; 52 *
	CH(0,PC)		; 53 +
	CH(1,PC)		; 54 ,
	CH(0,PC)		; 55 -
	CH(0,PC)		; 56 .
	CH(1,PC)		; 57 /

	CH(0,AN)		; 60 0
	CH(1,AN)		; 61 1
	CH(1,AN)		; 62 2
	CH(0,AN)		; 63 3
	CH(1,AN)		; 64 4
	CH(0,AN)		; 65 5
	CH(0,AN)		; 66 6
	CH(1,AN)		; 67 7

	CH(1,AN)		; 70 8
	CH(0,AN)		; 71 9
	CH(0,PC)		; 72 :
	CH(1,PC)		; 73 ;
	CH(0,PC)		; 74 <
	CH(1,PC)		; 75 =
	CH(1,PC)		; 76 >
	CH(0,PC)		; 77 ?

	CH(1,PC)		; 100 @
	CH(0,AN)		; 101 A
	CH(0,AN)		; 102 B
	CH(1,AN)		; 103 C
	CH(0,AN)		; 104 D
	CH(1,AN)		; 105 E
	CH(1,AN)		; 106 F
	CH(0,AN)		; 107 G

	CH(0,AN)		; 110 H
	CH(1,AN)		; 111 I
	CH(1,AN)		; 112 J
	CH(0,AN)		; 113 K
	CH(1,AN)		; 114 L
	CH(0,AN)		; 115 M
	CH(0,AN)		; 116 N
	CH(1,AN)		; 117 O
	CH(0,AN)		; 120 P
	CH(1,AN)		; 121 Q
	CH(1,AN)		; 122 R
	CH(0,AN)		; 123 S
	CH(1,AN)		; 124 T
	CH(0,AN)		; 125 U
	CH(0,AN)		; 126 V
	CH(1,AN)		; 127 W

	CH(1,AN)		; 130 X
	CH(0,AN)		; 131 Y
	CH(0,AN)		; 132 Z
	CH(1,PC)		; 133 [
	CH(0,PC)		; 134 \
	CH(1,PC)		; 135 ]
	CH(1,PC)		; 136 ^
	CH(0,PC)		; 137 _

	CH(0,PC)		; 140 `
	CH(1,AN)		; 141 a
	CH(1,AN)		; 142 b
	CH(0,AN)		; 143 c
	CH(1,AN)		; 144 d
	CH(0,AN)		; 145 e
	CH(0,AN)		; 146 f
	CH(1,AN)		; 147 g

	CH(1,AN)		; 150 h
	CH(0,AN)		; 151 i
	CH(0,AN)		; 152 j
	CH(1,AN)		; 153 k
	CH(0,AN)		; 154 l
	CH(1,AN)		; 155 m
	CH(1,AN)		; 156 n
	CH(0,AN)		; 157 o

	CH(1,AN)		; 160 p
	CH(0,AN)		; 161 q
	CH(0,AN)		; 162 r
	CH(1,AN)		; 163 s
	CH(0,AN)		; 164 t
	CH(1,AN)		; 165 u
	CH(1,AN)		; 166 v
	CH(0,AN)		; 167 w

	CH(0,AN)		; 170 x
	CH(1,AN)		; 171 y
	CH(1,AN)		; 172 z
	CH(0,PC)		; 173 {
	CH(1,PC)		; 174 |
	CH(0,PC)		; 175 }
	CH(0,PC)		; 176 ~
	CH(1,17)		; 177 RUBOUT
	SUBTTL TCO (First Level Output)

;OUTPUT CHARACTER TO TERMINAL
; TCO - FIRST LEVEL, TRANSLATE ACCORDING TO PROGRAM DESIRES
; TOCY- SECOND LEVEL, DO LINKS AND FORMAT FOR PARTICULAR DEVICE
; TCOUT-THIRD LEVEL, DO BUFFERING ETC.

;TCO - FIRST LEVEL OUTPUT

;ACCEPTS:
;	T1/ CHARACTER (UP TO 9 BITS)
;	T2/ ADDRESS OF DYNAMIC DATA

;RETURNS +1: ALWAYS

;CALLED BY BOUT CODE FOR A SINGLE CHARACTER

TCO::	LOAD T3,TT%DAM,TTFLGS(T2) ;GET TERMINAL DATA MODE
	JUMPE T3,TCOB1		;GO DO BINARY MODE
	TDCALL D,<<CH,CTHASC>>,<RET> ;CTERM - SET MODE TO ASCII
	PUSH P,1		;NO. SAVE THE CHARACTER
	ANDI 1,177		;T1/ CHARACTER IN 7 BITS
	CAIE T3,.TTATE		;TRANSLATE ECHO ONLY?
	JRST TCOE1		;NO. SOME OUTPUT TRANSLATION REQUIRED
	CAIE T1,.CHESC		;AN ESC?
	JRST TC1B		;NO
	CALL TCOUT		;YES, NO TRANSLATE
	JRST TC1C
;[9117] BLAST routine to provide fast output to terminal for short strings.
;Call with T2/ line number, user's T2 and T3 set up for a SOUT
;Returns +1 Blast successful
;	 +2 Blast unsuccessful, must use slow methods
;
;In order for blasting to occur, the following conditions are to be met:
;		1) TTY in binary mode
;		2) No links
;		3) Exact byte count specified (-n in user's AC3)
;		4) Entire string fits in currently available TTY output buffer

BLAST::	SAVEQ			;[9117] Get some work registers
	XCTU [SKIPL Q1,3]	;[9117] Get count of chars
	RETSKP			;[9117] Can't blast if not exact count
	MOVE T1,TTFLGS(T2)	;[9117] Get flags
	TXNE T1,TT%DAM		;[9117] Binary data mode?
	RETSKP			;[9117] Nope, can't have a blast
	MOVE T1,TTLINK(T2)	;[9117] Check for any links
	AOJN T1,RSKP		;[9117] No blast if any links
	JN TOFLG,(T2),RSKP	;[9117] No blast if output being flushed?
	DYNST T3		;[9117] Get internal line number
	CAMN T3,CTYINT		;[9117] Is this an alias for the cty?
	RETSKP			;[9117] Yes, no blasting
	LOAD T3,TOMAX,(T2)	;[9117] Capacity of output buffers
	SUB T3,TTOCT(T2)	;[9117] Minus space already used
	ADD T3,Q1		;[9117] Minus number of bytes we need
	SKIPE TTOIN(T2)		;[9117] Do the buffers exist?
	CAIGE T3,^D20		;[9117] Allow some slush
	RETSKP			;[9117] Not enough space to have a blast
	TDCALL D,<<PT,CKPTOU>,<MC,CKMCOU>>,RETSKP ;[9117] Output possible?
	RETSKP			;[9117] No, take failure return
	NOSKED			;[9117] Turn off timesharing
	CHNOFF DLSCHN		;[9117] Must prevent deassign of buffers
	SKIPN T3,TTOIN(T2)	;[9117] Buffers exist?
	JRST BLASTF		;[9117] No, can't blast
	LOAD T3,TOMAX,(T2)	;[9117] Capacity of output buffers
	SUB T3,TTOCT(T2)	;[9117] Minus space already used
	ADD T3,Q1		;[9117] Minus number of bytes we need
	JUMPLE T3,BLASTF	;[9117] Not enough left, can't blast
				;[9117] Fall through to start blasting
;[9117] We can blast, cover your ears and copy the short string out now.

	MOVE T3,TTOIN(T2)	;[9117] Get pointer to output buffer
BLAST1:	XCTBUU [ILDB T1,2]	;[9117] Get a byte to blast
	TDNE T3,WRPMSK		;[9117] End of buffer?
	IFSKP.			;[9117] Yes
	  HRRZ T4,T3		;[9117] Copy local address of global pointer
	  LDB Q2,[POINT 6,T3,5] ;[9117] Get byte position and size
	  CAIN Q2,73		;[9117] Pointing to last byte?
	  HRR T3,1-TTSIZ(T4)	;[9117] Yes, get address of next buffer
	ENDIF.			;[9117] Ready to put character in buffer
	IDPB T1,T3		;[9117] Put it in buffer
	AOJL Q1,BLAST1		;[9117] Repeat for whole string

;[9117] Blasting done, update pointers and counts and return.

	MOVEM T3,TTOIN(T2)	;[9117] Save updated pointer
	XCTU [MOVN T4,3]	;[9117] Get positive number of bytes
	ADDM T4,TTOCT(T2)	;[9117] Update count
	CHNON DLSCHN		;[9117] Turn dls back on
	ADDM T4,NTTYOT		;[9117] Update count of tty output characters
	SETZ T1,		;[9117] Get a zero
	UMOVEM T1,3		;[9117] Set user's ac3 to zero
	CALLRET STRTOU		;[9117] (T2,T3/) Start output to line if needed

;[9117] Here if we discovered we can't blast after turning of PI and scheduler.

BLASTF:	CHNON DLSCHN		;[9117] Turn on TTYSRV PI level
	OKSKED			;[9117] Turn on timesharing again
	RETSKP			;[9117] Take skip return, can't blast
;TCOE - ECHO OUTPUT

;ACCEPTS:
;	T1/ CHARACTER
;	T2/ ADDRESS OF DYNAMIC DATA

;RETURNS +1: ALWAYS

;THIS IS A SPECIAL ENTRY POINT USED BY TTCH7 (IN SCHEDULER CONTEXT)
;FOR IMMEDIATE ECHOING AND BY TCI FOR DEFERRED ECHOING.
;IF TCOUT IS UNABLE TO OUTPUT THE CHARACTER AND IS BEING CALLED
;FROM THE SCHEDULER, IT WILL SET TCOERR TO -1.
;THE SCHEDULER MUST CLEAR THIS WORD BEFORE CALLING AND CHECK IT UPON RETURN
;IF IN PROCESS CONTEXT AND UNABLE TO OUTPUT, IT WAITS UNTIL IT CAN DO
;THE OUTPUT

;NOTE: APPARENTLY THIS CODE IS NEVER CALLED IF TERMINAL DATA MODE IS BINARY

TCOE:	TMNE TTNXO,(T2)		;DOING PAGE STOP?
	JRST [	SETZRO TPGPS,(T2) ;YES. CLEAR LINE POSITION WITHIN PAGE
		JRST .+1]	; TO PREVENT XOFF
	PUSH P,1		;SAVE THE CHARACTER
	ANDI 1,177		;T1/ CHARACTER IN 7 BITS
	CAIN 1,.CHDEL		;RUBOUT?
	JRST TC1C		;YES, DON'T ECHO
	LOAD T3,TT%DAM,TTFLGS(T2) ;GET TERMINAL DATA MODE
	CAIE T3,.TTASC		;TRANSLATE OUTPUT AND ECHO?
	CAIN T3,.TTATE		;NO. TRANSLATE ECHO ONLY?
	JRST TCOE1		;YES. ECHO TRANSLATION REQUIRED
	JRST TC1B		;NO ECHO TRANSLATION

;CONTROL CHARACTER TRANSLATION IS REQUIRED (OUTPUT OR ECHOING).
;IF THIS IS A CONTROL CHARACTER, DO THE TRANSLATION. OTHERWISE,
;CALL LEVEL 2

 TCOE1:	CAIL 1,40		;CONTROL GROUP?
	JRST TC1B		;NO. GO CALL LEVEL 2 CODE
	;..
;TCO..

;TRANSLATE CONTROL CHARS ACCORDING TO CC OUTPUT CONTROL MODES IN FCMOD1/FCMOD2
; 00 - SEND NOTHING
; 01 - INDICATE, E.G. ^A
; 1X - DO FUNCTION (SECOND LEVEL HANDLES SIMULATION IF NECESSARY)
;	10 - SEND ACTUAL CODE
;	11 - SIMULATE FORMAT ACTION

	;..
	MOVE 4,FCMOD2(2)
	MOVE 3,FCMOD1(2)	;GET MODE BITS
	ROTC 3,0(1)
	ROTC 3,0(1)
	CAIN 1,.CHESC		;ESC SPECIAL CASE?
	JRST [	TLNN 3,(3B1)	;YES, FLUSH CASE?
		JRST TC1C	;YES
		TLNN 3,(1B1)
		JRST TC1B	;10 CASE, OUTPUT REAL CHAR
		TLNN 3,(1B0)
		JRST TC1D	;01 CASE, INDICATE WITH ^[
		MOVEI 1,"$"	;11 CASE, 'SIMULATE' WITH $
		JRST TC1B]

;DETERMINE ACTION ACCORDING TO CONTROL CHARACTER OUTPUT CONTROL BITS

	TLNE 3,(1B0)		;DO?
	JRST TC1B		;YES. CALL LEVEL 2 TO SEND CODE
				; OR SIMULATE FORMAT ACTION
	TLNN 3,(1B1)		;FLUSH?
	JRST TC1C		;YES. DON'T SEND ANYTHING

;INDICATE CONTROL CHARACTER BY ^

TC1D:	ADDI 1,100		;CONVERT TO PRINTING EQUIV.
	PUSH P,1
	MOVEI 1,TTCIND		;GET ^
	SKIPE IMECHF		;ECHOING?
	AOS LINKF		;YES. FORCE IT OUT
	CALL TCOY		;PRINT INDICATOR
	POP P,1			;GET BACK THE CHARACTER
	CALL TCOY		;OUTPUT THE CHARACTER
	SKIPE IMECHF		;DOING ECHO?
	SOS LINKF		;YES.
	JRST TC1C		;GO RETURN

;CALL LEVEL 2 TO OUTPUT THE CHARACTER. IF NECESSARY, IT WILL
;DO CONTROL CHARACTER SIMULATION

TC1B:	CALL TCOY		;CALL LEVEL 2
TC1C:	POP P,1			;RETURN THE CHARACTER
	RET
;TCOB - ENTRY FOR BINARY OUTPUT. NO TRANSLATION


;ACCEPTS:
;	T1/ CHARACTER (UP TO 9 BITS)
;	T2/ ADDRESS OF DYNAMIC DATA

;	CALL TCOB

;RETURNS +1: ALWAYS

TCOB::
TCOB1:	TDCALL D,<<CH,CTHBIN>>,<RET> ;CTERM - SET MODE TO BINARY
	ANDI T1,377		;7 BITS OF CHARACTER + PARITY
	CALLRET TCOU1		;GO OUTPUT THE CHARACTER WITHOUT ADDING PARITY
	SUBTTL TCOY (Second Level Output)

;SECOND LEVEL - HANDLE DEVICE IDEOSYNCRACIES AND CHAR ACCOUNTING

;ACCEPTS:
;	T1/CHARACTER IN 7 BITS
;	T2/ ADDRESS OF DYNAMIC DATA

;IMECHF IS -1 IF THIS CHARACTER IS BEING OUTPUT FOR IMMEDIATE ECHOING
;WHEN TAKEN OUT OF TTBBUF BY TTCH7

;CALLED FROM TCO (FIRST LEVEL OUTPUT). BY NOW, IF THIS IS A CONTROL
;CHARACTER, THE CONTROL CHARACTER OUTPUT CONTROL SPECIFIED EITHER
;	10 - SEND ACTUAL CODE
;		OR
;	11 - SIMULATE FORMAT ACTION

;WE CAN ALSO GET HERE WHEN TT%DAM HAS .TTATO SET AND WE ARE DOING ECHO
;OR TT%DAM HAS .TTATE AND WE ARE DOING OUTPUT

TCOY:	SAVEQ
	CAIN 1,.CHDEL
	JRST [	CALL TCOUT	;RUBOUT, SEND DIRECTLY
		JRST TCOY3]
	SKIPE IMECHF		;IMMED ECHO CHAR?
	JRST [	MOVE 3,TTFLGS(2) ;YES, CHECK DUPLEX BITS
		TXNN T3,TT%ECO	;IS ECHOING OFF?
		JRST TCOY3	;YES - THEN DON'T ECHO
		SKIPN LINKF	;LINKED CHAR? OR
		TRCN 3,3B33	;FULL?
		JRST .+1	;YES
		CALL TTCOHA	;ACCOUNT SPACING FOR CHAR
		CAIGE 1,40	;IS CONTROL CHAR AND MODE 2?
		TRNN 3,3B33
		JRST [	MOVE T3,TTLINK(T2) ;NO. GET LINK WORD
			CAME T3,[-1] ;ANY LINKS?
			CALL TTLNK3 ;YES. DO THEM
			JRST TCOY3] ;AND DONE
		JRST TTCO1]	;YES, ECHO CONTROL FN
;EITHER NOT IMMEDIATE ECHOING OR IMMEDIATE ON A FULL-DUPLEX TERMINAL
;IF CONTROL CHARACTER, GO HANDLE SPECIALLY

	CAIGE 1,40
	JRST TTCO1		;CONTROL GROUP

;NOT A CONTROL CHARACTER. RAISE IF NECESSARY

	MOVE 3,TTFLGS(2)
	TXNE 3,TT%LCA		;TERMINAL HAS LOWER CASE?
	JRST TTCO6		;YES, NO TRANSLATION NEEDED
	CAIL 1,"A"		;UPPER CASE LETTER?
	CAILE 1,"Z"
	JRST [	CAIL 1,"A"+40	;NO, LOWER CASE LETTER?
		CAILE 1,"Z"+40
		JRST TTCO6	;NO
		SUBI A,40	;YES, CONVERT TO UPPER CASE
		JRST TTCO6]

;CHARACTER IS UPPER CASE. IF FLAGGING IS REQUIRED, CALL THIRD LEVEL
;ROUTINE TO PRINT A '^' BEFORE PRINTING THE CHARACTER

	TXNN 3,TT%UOC		;INDICATE?
	JRST TTCO6		;NO
	PUSH P,1		;YES, SAVE CHAR
	MOVEI 1,TTLIND		;OUTPUT INDICATOR
	CALL TCOP
	POP P,1
TTCO6:	CALL TCOP		;OUTPUT CHAR AND ACCOUNT SPACE
TCOY3:	RET
;TCOP - SECOND LEVEL SUBROUTINE - OUTPUT SINGLE SPACING CHARACTER
;ACCEPTS:
;	T1/ THE CHARACTER IN 7 BITS
;	T2/ ADDRESS OF DYNAMIC DATA FOR THIS LINE

;	CALL TCOP

TCOP:	AOS T3,TTLPOS(T2)	;GET CURRENT POSITION ON LINE
				;INCREMENT COUNT
	HRRZS T3
	TDCALL D,<<CH,RTN>>,<RETSKP> ;CTERM TERMINAL ?
	 JRST TCOUT		;YES. FOLDING DONE IN SERVER.
	LOAD 4,TPWID,(T2)	;GET RIGHT MARGIN
	JUMPE 4,TCOUT		;0 MEANS NEVER FOLD
	CAIL 4,0(3)		;CHECK FOR OVERFLOW
	CALLRET TCOUT		;NO OVERFLOW, OUTPUT CHAR

;REACHED END OF LINE. HANDLE WRAPAROUND AND GO BACK TO OUTPUT THE CHARACTER

	PUSH P,1		;LINE OVERFLOW, DO CR AND CONTINUATION
	MOVEI 1,15		;T1/ CARRIAGE RETURN
	CALL TTSM5		;DO CR
	MOVEI 1,12		;T1/ LINE FEED
	CALL TTSM2		;DO LF
	SETZRO TLNPS,(T2)	;RESET LINE POSITION TO 0
   REPEAT 0,<			;** FOLD INDICATION DISABLED
	MOVEI 1,2		;COUNT 2 *'S
	HRRM 1,TTLPOS(2)
	MOVEI 1,52
	CALL TCOUT
	CALL TCOUT
   >
	POP P,1
	JRST TCOP		;GO OUTPUT THE CHARACTER
;TTCOHA - ACCOUNT SPACING PERFORMED BY HALF-DUPLEX TERMINAL
;TERMINAL HAS PRINTED THE CHARACTER. THIS MERELY ACCOUNTS FOR THE
;RESULTING POSITION ON THE TERMINAL

;ACCEPTS:
;	T1/ CHARACTER IN 7 BITS
;	T2/ ADDRESS OF DYNAMIC DATA

TTCOHA:	CAIL 1,40		;SPACING CHAR?
	JRST [	INCR TLNPS,(T2)	;YES. INCREMENT POSITION ON LINE
		RET]
;;;;	CAIE T1,.CHLFD		;[7141] LF?
	CAIN 1,15		;CR?
	JRST [	SETZRO TLNPS,(T2) ;YES. RESET TO LEFT MARGIN
		RET]
	CAIN 1,.CHLFD		;LF?
	CALLRET INCLIN		;COUNT LINES
	CAIN 1,.CHFFD		;FF?
	JRST [	SETZRO TPGPS,(T2) ;YES. RESET TO TOP OF PAGE
		RET]
	CAIE 1,.CHBSP		;BACKSPACE?
	RET			;NO
	JE TLNPS,(T2),R		;YES. IF NOT AT LEFT MARGIN,
	DECR TLNPS,(T2)		; DECREMENT CHARACTER POSITION WITHIN PAGE
	RET
	SUBTTL TCOY For Control Characters

;HERE WHEN THE CHARACTER TO BE OUTPUT IS A CONTROL CHARACTER

;ACCEPTS:
;	T1/CHARACTER IN 7 BITS
;	T2/INTERNAL LINE NUMBER

;THIS IS PART OF THE SECOND LEVEL OUTPUT AND IS CALLED BY TCOY.
;CHITAB CONTAINS THE ROUTINE THAT WILL PROCESS THE CHARACTER
;IN SOME CASES, IT CONTAINS TCOUT, THE THIRD LEVEL ROUTINE.
;IN OTHER CASES, IT CONTAINS A SPECIAL ROUTINE, WHICH DOES SOME TRANSLATION
;AND THEN CALLS TCOUT

;FOR EACH CHARACTER, ACTION IS CONTROLLED BY TWO BITS IN FCMOD1 OR FCMOD2:
; 00 = IGNORE, DO NOT SEND
; 01 = SEND PRINTING INDICATION (I.E. &C)
; 10 = SEND ACTUAL CODE AND ACCOUNT LINE AND PAGE POSITION
; 11 = SIMULATE FORMAT ACTION AND ACCOUNT
;WHEN THIS CODE IS CALLED, LEVEL 1 OUTPUT HAS ALREADY HANDLED THE
;TRANSLATION OF CONTROL CHARACTER IF MODE 0 OR 1 IS IN EFFECT

TTCO1:	MOVE 4,FCMOD2(2)	;SECOND CONTROL MODES WORD
	MOVE 3,FCMOD1(2)	;FIRST CONTROL MODES WORD
	ROTC 3,0(1)		;GET TWO BIT MODE FOR THIS CHAR
	ROTC 3,0(1)
	HRRZ 4,CHITAB(1)	;GET DISPATCH ADDRESS
	CALL 0(4)		;DISPATCH TO FORMAT ROUTINE
	JRST TCOY3
;TAB

;ACCEPTS:
;	T1/ THE CHARACTER IN 7 BITS
;	T2/ ADDRESS OF DYNAMIC DATA
;	T3/ CONTROL CHARACTER OUTPUT CONTROL BITS IN BITS 0-1

;	CALL TTSM1

TTSM1:	PUSH P,3		;SAVE OUTPUT MODE
	LOAD 3,TLNPS,(2)	;OLD POSITION
	IDIVI T3,TABSIZ		;COMPUTE SPACES BEYOND CURRENT STOP
	MOVEI FX,TABSIZ
	SUB FX,T4		;COMPUTE SPACES TO NEXT STOP
	POP P,3			;MODE WORD
	MOVSI 4,(1B2)		;HAS-TAB BIT
	TLNN 3,(1B1)		;SIMULATE REQUESTED?
	TDNN 4,TTFLGS(2)	;OR NO MECH TAB ON DEVICE?
	JRST TTSM13		;YES, GO SIMULATE
	MOVEI 1,.CHTAB		;SEND REAL TAB
	CALL TCOUT
	MOVE 4,FX		;PLUS RUBOUTS TO KILL TIME
	IDIVI 4,4		;ASSUME FOUR SPACES PER RUBOUT
	LOAD 3,TTTYP,(2)	;GET TYPE OF TERMINAL
	LDB 1,TTTBPD		;GET NUMBER PADS PER FOUR SPACES
	IMULI 4,0(1)
	JUMPLE 4,TTSM14
	PUSH P,FX		;SAVE NEW POSITION
	MOVEI FX,0(4)		;ITERATION
TTSM16:	MOVEI 1,TTFILL
	CALL TCOUT
	SOJG FX,.-1
	POP P,FX		;RESTORE LINE POSTION
TTSM14:	OPSTR <ADD FX,>,TLNPS,(2) ;UPDATE POSITION
	STOR FX,TLNPS,(2)
	RET

TTSM13:	MOVEI 1,40		;SIMULATE WITH SPACES
	CALL TCOP		;SEND ONE
	SOJG FX,TTSM13		;SEND ALL OF THEM
	RET
;LINE FEED

;ACCEPTS:
;	T1/ THE CHARACTER IN 7 BITS
;	T2/ ADDRESS OF DYNAMIC DATA
;	T3/ CONTROL CHARACTER OUTPUT CONTROL BITS IN BITS 0-1

;	CALL TTSM12

TTSM12:	TXNN T3,<1B1>		;CODE 2?
	JRST TTSM2		;YES, DO LF ONLY
	MOVEI T1,.CHCRT		;DO CR FIRST
	OPSTR <SKIPE T3,>,TLNPS,(T2)
	CALL TTSM5
	MOVEI T1,.CHLFD		;THEN LF
	;..

;LOCAL LINEFEED - DOES NOT INCLUDE CR

TTSM2:	CALL INCLIN		;ACCOUNT FOR LINE
	LOAD 3,TPLEN,(T2)	;GET PAGE LENGTH
	JUMPE 3,TTSM2X		;NO CHECK IF LENGTH 0
	LOAD 1,TPGPS,(2)	;GET CURRENT PAGE POSITION
	CAML 1,3		;PAGE FULL?
	JRST [	SETZRO TPGPS,(2) ;YES. RESET TO TOP OF PAGE
		CALL TTXOFF	;DO XOFF IF IN PAGE MODE
		JRST .+1]
TTSM2X:	MOVEI 1,.CHLFD		;GET LINE FEED
	CALL TCOUT		;OUTPUT LINE FEED
	LOAD 3,TTTYP,(2)	;GET TERMINAL TYPE
	LDB Q1,TTLFPD		;LF PADDING
	CALLRET TTSPAD		;DO PADDING

;ROUTINE TO KEEP LINE COUNTER AND MAX UPDATED.

INCLIN:	SAVET			;PRESERVE TEMPS
	INCR TPGPS,(T2)		;INCREMENT LINE POSITION ON PAGE
	AOS A,TTLINE(B)		;INCREMENT LINE COUNTER
	CAMLE A,TTLMAX(B)	;NEW MAXIMUM?
	MOVEM A,TTLMAX(B)	;YES, REMEMBER IT
	RET
;FORM FEED


;ACCEPTS:
;	T1/ THE CHARACTER IN 7 BITS
;	T2/ ADDRESS OF DYNAMIC DATA
;	T3/ CONTROL CHARACTER OUTPUT CONTROL BITS IN BITS 0-1

TTSM3:	LOAD 4,TPGPS,(2)	;GET PRESENT PAGE POSITION
	SETZRO TPGPS,(T2)	;RESET TO TOP OF PAGE
	PUSH P,3
	LOAD 3,TPLEN,(2)	;PAGE SIZE
	JUMPE T3,[SETZM Q1	;IF ZERO PAGE LENGTH, SAY AT THE END
		JRST TTSM34]
	IDIVI 4,0(3)
	SUBM 3,Q1		;Q1/ DIFFERENCE TO END OF PAGE
TTSM34:	POP P,3
	MOVSI 4,(1B1)
	TDNE 4,TTFLGS(2)	;DEVICE HAS MECH FF?
	TLNE 3,(1B1)		;AND SEND DIRECT REQUESTED?
	JRST TTSM32		;NO, SIMULATE FF
	CALL TCOUT		;SEND REAL CHARACTER
	LOAD 3,TTTYP,(2)	;GET TERMINAL TYPE
	LDB Q1,TTFFPD		;FF PADDING
	CALL TTSPAD		;DO PADDING
	JRST TTSM3Y


;SIMULATE FORM FEED BY OUTPUTTING AS MANY LINE FEEDS AS ARE NEEDED
;TO GET TO THE TOP OF THE NEXT PAGE

TTSM32:	PUSH P,TTLPOS(2)	;SAVE LINE AND PAGE POSITIONS
	PUSH P,Q1		;SAVE NUMBER OF LINES LEFT IN PAGE
TTSM33:	CALL TTSM2		;SIMULATE ONE FORM FEED
	SETZRO TPGPS,(T2)	;PREVENT TTSM2 FROM DOING X-OFF
	SOSLE 0(P)		;COUNT LF'S
	JRST TTSM33		;LOOP ON LF'S
	POP P,Q1		;FLUSH TEMP
	POP P,TTLPOS(2)		;RESTORE LINE AND PAGE POSITIONS
TTSM3Y:	LOAD 1,TPLEN,(2)	;CHECK PAGE LENGTH
	JUMPE T1,R		;DO XOFF UNLESS PLENGTH IS 0
	CALLRET TTXOFF		;DO XOFF
;ROUTINE TO INSERT PADDING

;ACCEPTS:
;	T1/ THE CHARACTER IN 7 BITS
;	T2/ ADDRESS OF DYNAMIC DATA
;	T3/ CONTROL CHARACTER OUTPUT CONTROL BITS IN BITS 0-1
;	Q1/ NUMBER OF FILLS TO SEND
;	CALL TTSPAD
; RETURN +1 ALWAYS

TTSPAD:	MOVEI 1,TTFILL		;FILLER
	JUMPLE Q1,R		;DONE IF COUNT EXHAUSTED
	CALL TCOUT		;SEND ONE
	SOJA Q1,TTSPAD		;COUND DOWN RUBOUTS

;BACKSPACE

;ACCEPTS:
;	T1/ THE CHARACTER IN 7 BITS
;	T2/ ADDRESS OF DYNAMIC DATA
;	T3/ CONTROL CHARACTER OUTPUT CONTROL BITS IN BITS 0-1

TTSM4:	LOAD 4,TLNPS,(2)	;GET LINE POSITION
	JUMPE 4,TTSM45		;IF AT BEGINNING SKIP REST
	MOVE 4,TTFLGS(2)	;GET CURRENT LINE STATE
	TRNN 4,3B33		;IN HALF DUPLEX?
	JRST [	DECR TLNPS,(T2) ;NO. ACCOUNT FOR BACKSPACE
		JRST .+1]
TTSM45:	TLNN 3,200000		;REAL OR SIMULATED
	CALLRET TCOUT		;NO. OUTPUT DIRECTLY
	MOVEI 1,15		;SIMULATE WITH CR AND SPACES (UGH)
	CALL TCOUT
	LOAD 4,TLNPS,(2)	;GET CHARACTER POSITION WITHIN LINE
TTSM44:	MOVEI 1,40		;GET SPACE
	JUMPE 4,R		;IF AT LEFT MARGIN, QUIT
	PUSH P,4		;SAVE COUNTER
	CALL TCOUT		;OUTPUT A SPACE
	POP P,4			;RESTORE COUNTER
	SOJA 4,TTSM44		;DO ALL NECESSARY SPACES
;CARRIAGE RETURN

;ACCEPTS:
;	T1/ THE CHARACTER IN 7 BITS
;	T2/ ADDRESS OF DYNAMIC DATA
;	T3/ CONTROL CHARACTER OUTPUT CONTROL BITS IN BITS 0-1

TTSM5:	MOVEI 1,.CHCRT		;T1/ CARRIAGE RETURN
	CALL TCOUT		;OUTPUT THE CARRIAGE RETURN
	LOAD 4,TLNPS,(2)	;GET CHARACTER POSITION WITHIN LINE
	SETZRO TLNPS,(2)	;RESET LINE POSITION
	LOAD 3,TTTYP,(2)	;GET TERMINAL TYPE
	LDB Q1,TTCRPD		;CR PADDING
	IMULI 4,0(Q1)		;COMPUTE POSN/72*PAD, I.E. PAD IS
	ADDI 4,^D71		;AMOUNT FOR 72 CHAR LINE, SO PRO-RATE
	IDIVI 4,^D72		;BASED ON FULLNESS OF LINE, ROUNDING
	MOVEI Q1,0(4)		;PAD COUNT UP TO NEXT INTEGER
	CALLRET TTSPAD		;DO PADDING

;ESC

;ACCEPTS:
;	T1/ THE CHARACTER IN 7 BITS
;	T2/ ADDRESS OF DYNAMIC DATA
;	T3/ CONTROL CHARACTER OUTPUT CONTROL BITS IN BITS 0-1

TTSME:	TLNN 3,(3B1)		;00?
	RET			;YES, NO SEND
	TLNE 3,(1B1)		;01 OR 11?
	JRST [	MOVEI 1,"$"	;YES, SEND $
		CALLRET TCOP]
	CALLRET TCOUT		;SEND ACTUAL CODE

;TTXOFF - STOP OUTPUT TO A TERMINAL, I.E. PAUSE ON END-OF-PAGE

;ACCEPTS:
;	T2/ ADDRESS OF DYNAMIC DATA

;CALLED WHEN OUTPUT TO A TERMINAL CAUSES THE PAGE TO FILL UP. IF TERMINAL
;IS IN PAGE MODE, PUTS SPECIAL CHARACTER IN OUTPUT STREAM TO CAUSE 'XOFF' ACTION
;WHEN ENCOUNTERED AT INTERRUPT LEVEL

TTXOFF:	MOVX 1,TT%PGM
	TMNE TTNXO,(T2)		;DOING PAGE STOP?
	TDNN 1,TTFLGS(2)	;IN PAGE MODE?
	RET			;NO, DO NOTHING
	MOVEI 1,"G"-100		;OUTPUT BELL TO TELL USER THAT
	CALL TCOUT		; HE MUST RESTART OUTPUT
	MOVEI 1,TTOPFC		;PUT SPECIAL FUNCTION CODE IN OUTPUT
	CALLRET TCOU3		; STREAM TO STOP OUTPUT AT THAT POINT
	SUBTTL TCOUT (Third Level Output)

;OUTPUT ONE CHARACTER TO SPECIFIED TTY LINE

;ACCEPTS:
;	T1/ CHARACTER IN 7 BITS
;	T2/ ADDRESS OF DYNAMIC DATA

;RETURNS +1: ALWAYS

;IF IN SCHEDULER AND UNABLE TO SEND CHARACTER, SETS TCOERR TO -1

;SPECIAL ENTRY POINT WHEN ENTERING FROM TTEMES

;ACCEPTS:
;	T1/ CHARACTER
;	T2/ ADDRESS OF DYNAMIC DATA (FULL-LENGTH OR TTEMES BLOCK)

;RETURNS +1: ALWAYS

;IF UNABLE TO SEND CHARACTER AND IN SCHEDULER, SETS TCOERR TO -1

SCDTCO:	SKIPL CHITAB(T1)	;TEST PARITY BIT FOR THIS CHARACTER
	JRST TCOU6		;NO PARITY NEEDED. GO ON
	CALL SPARTY		;SET PARITY BIT
	JRST TCOU6		;GO STORE IN OUTPUT BUFFER

;PUT MARKER IN OUTPUT STREAM - IGNORE TOFLG

TCOUM::	CALL CKPHYD		;PTY?
	 RET			;YES, DO NOTHING
	JRST TCOUM1		;ENTER OUTPUT SEQUENCE

;PHYSICAL LINE. APPLY PARITY

TCOUT:	SKIPL CHITAB(1)		;TEST PARITY BIT FOR THIS CHAR
	JRST TCOU1		;NO PARITY NEEDED. GO ON
	CALL SPARTY		;SET PARITY BIT AS NEEDED

;FULLY ACTIVE LINE. PROCESS LINES LINKED TO THIS ONE

TCOU1::	MOVE C,TTLINK(B)	;ANY LINKS?
	CAME C,[-1]
	CALL TTLNK3		;YES. GO DO THEM
	; ..
	; ..

;SEE IF THERE IS ROOM IN THE OUTPUT BUFFER

TCOU3:	JN TOFLG,(T2),R		;LOSE CHARACTER IF CTRL/O TYPED
TCOUM1:	DYNST T3		;GET INTERNAL LINE NUMBER
	CAMN T3,CTYINT		;IS THIS AN ALIAS FOR THE CTY?
	RET			;YES. IGNORE CHARATCER
TCOU6::	TDCALL D,<<CH,CTHOOE>>,<RETSKP> ;DEVICE DEPENDENT ROUTINE -
				; IS THIS AN ECHO OF A CHARACTER THAT
				; HAS ALREADY BEEN ECHOED BY A DEVICE THAT
				; KNOWS ABOUT ECHOING ?
	 RET                    ;YES. ECHOING WAS DONE IN SERVER.
	LOAD 3,TOMAX,(2)	;CAPACITY OF OUTPUT BUFFERS
	SKIPE IMECHF		;IMMEDIATE ECHO CHARACTER?
	ADDI 3,2		;YES. EXTRA ROOM FOR THIS CHARACTER
	CAMLE 3,TTOCT(2)	;FULL?
	JRST TCOU5		;NO
	CALL TCOUBF		;YES, BLOCK IF POSSIBLE
	 RET			;CAN'T BLOCK, RETURN NOW
	JRST TCOU3		;TRY AGAIN
;ACTION WHEN BUFFER FULL
; T1/ CURRENT OUTPUT CHARACTER
; T2/ DYNAMIC PTR
;	CALL TCOUBF
; RETURN +1: CAN'T BLOCK, RETURN ERROR
;	+2: READY TO TRY AGAIN

TCOUBF:	SAVEAC <T1,Q1>
	SKIPN INSKED		;ARE WE IN THE SCHEDULER?
	SKIPE NSKED		;NO. ARE WE NOSKED?
	IFNSK.
	  SETOM TCOERR		;YES. INDICATE FAILURE FOR SCHEDULER
	  RET			;AND RETURN
	ENDIF.
	TDCALL D,<<PT,CHKPTA>,<CH,CTHFOU>> ;DO DEVICE-DEPENDENT STUFF
	SETONE TTBKO,(T2)	;NOTE BLOCK FOR OUTPUT EVENT
	DYNST Q1		;GET LINE NUMBER
	CALL ULKTTY		;(T2) UNLOCK THE TTY
	SKIPE JOBNO		;JOB 0?
	IFSKP.
	  CAME Q1,CTYLNO	;YES, IS LINE THE CTY?
	ANSKP.
	  MOVE T1,TODCLK	;YES, TIME THE BLOCK
	  MOVE T2,FORKX
	  STOR T1,FKST2,(T2)	;SAVE TIME NOW
	  SETOM J0RLDF		;NOTE FE NOT RELOADED YET
	  MOVEI T1,J0TCOT	;USE SPECIAL SCHED TEST
	ELSE.
	  MOVEI 1,TCOTST	;SETUP SCHEDULER TEST WORD
	ENDIF.
	HRL 1,Q1		; LINE NO,,TEST ROUTINE ADR
	MOVSI T2,FHV5		;WAIT PRIORITY
	HDISMS
	MOVE T2,Q1		;GET STATIC LINE NUMBER
	CALL LCKTTY		;LOCK UP THE TTY
	IFNSK.
	  CALL ULKTTY		;UNLOCK THE LINE I CASE IT GOT LOCKED
	  MOVE T2,Q1		;GET BACK LINE NUMBER
	  CALL TCOU7		;GET SPECIAL BLOCK
	ENDIF.
	RETSKP
;BUFFER IS NOT FULL.  SEE IF THERE IS A BUFFER. IF NOT, GET AS MANY
;AS ARE NEEDED

TCOU5:	TDCALL D,<<PT,CKPTOU>,<MC,CKMCOU>,<LH,LTTCOU>>,RETSKP ;SEE IF OUTPUT POSSIBLE
	 RET
	NOSKD1
	CHNOFF DLSCHN		;MUST PREVENT DEASSIGN OF BUFFERS
	SKIPE 3,TTOIN(2)	;BUFFERS EXIST?
	JRST TCOU4		;YES.

;THIS LINE HAS NO OUTPUT BUFFERS. GET SOME IF POSSIBLE. IF NONE
;AVAILABLE, WAIT FOR THEM UNLESS IN SCHEDULER. IN THAT CASE, SET
;ERROR FLAG AND RETURN

	CHNON DLSCHN		;NO. ALLOW DLS INTERRUPTS
	LOAD 3,TTNOU,(2)	;GET NUMBER TO ASSIGN
	CALL TTGTBF		;ASSIGN THEM
	 JRST [	OKSKD1		;FAILED. ALLOW SCHEDULING
		SKIPN INSKED	;ARE WE IN THE SCHEDULER?
		SKIPE NSKED	;NO. ARE WE NOSKED?
		JRST [	SETOM TCOERR ;YES. INDICATE ERROR FOR SCHEDULER
			RET]	; AND RETURN
		PUSH P,1	;SAVE CHARACTER
		LOAD 1,TTNOU,(2);NO, CAN WAIT FOR BUFFERS
		MOVSI 1,0(1)	;NUMBER NEEDED
		HRRI 1,TTBUFW
		MDISMS
		POP P,1		;RESTORE CHARACTER
		JRST TCOU5]	;BUFFERS ARE AVAILABLE. GO GET THEM
	CHNOFF DLSCHN
	MOVEM 3,TTOOUT(2)
	MOVEM 3,TTOIN(2)
;BUFFERS ARE AVAILABLE. AC 3 CONTAINS BYTE POINTER FOR ADDING NEXT
;CHARACTER. STORE THE CHARACTER.

TCOU4:	TDNN 3,WRPMSK		;END OF BUFFER?
	JRST [	LDB 4,[POINT 6,3,5] ;LOOK AT P,S FIELD OF BYTE POINTER
		CAIE 4,73	;POINTING TO LAST BYTE?
		JRST .+1	;NO.
		HRRZ T4,T3	;YES. GET ADDRESS OF CURRENT WORD
		HRR T3,1-TTSIZ(T4) ;POINT TO NEXT BUFFER IN CHAIN
		MOVEM T3,TTOIN(T2) ;SAVE CHARACTER POINTER
		JRST .+1]
	IDPB T1,TTOIN(T2)	;GET CHARACTER
	AOS 3,TTOCT(2)		;INCREMENT COUNT OF CHARACTERS IN BUFFER
	CHNON DLSCHN		;SAFE TO TURN CHN ON AFTER AOS
	AOS NTTYOT		;COUNT ALL OUTPUT
	CALLRET STRTOU		;START OUTPUT TO LINE IF NEEDED

;SET PARITY BIT IF REQUIRED FOR THIS LINE TYPE
; T2/ DYNAMIC DATA PTR
; T1/ CHARACTER
;RETURN +1 ALWAYS, T1 MODIFIED

SPARTY:	LOAD CX,TLTYP,(T2)	;GET LINE TYPE
	XCT PARTBL(CX)		;SET OR CLEAR BIT
	RET
;HERE WHEN DID TCOTST BLOCK AND AWOKE TO FIND LINE
;HAS BEEN DEASSIGNED

	SWAPCD			;GET HERE ONLY IN PROCESS CONTEXT
TCOU7:	STKVAR <LNNUMB>
	MOVEM T2,LNNUMB		;SAVE LINE NUMBER
TCOU75:	NOSKED			;OWN THE MACHINE
TCOU76:	MOVE T2,LNNUMB		;GET LINE #
	CALL LCKTTY		;CHECK IT NOW
	SKIPA   		;IF UNASSIGNED, GO ON
	JRST [	OKSKED		;ALLOW SCHEDULING
		RET]		;AND DONE
	CALL ULKTTY		;UNLOCK IN CASE IT GOT LOCKED
	JUMPG T2,TCOU77		;IF BLOCK IS SHORT WAIT IT TO BE DEALLOCATED
	MOVE T2,LNNUMB		;LINE # AGAIN
	CALL ASGMSL		;GET A MESSAGE BLOCK
	 JRST TCOU77		;FAILED
	CALL STADY		;SUCCESS. GET DYNAMIC DATA ADDRESS
	 JRST TCOU77		;SOMETHING VERY WRONG. TRY AGAIN
	SETOM TTLINK(T2)	;NO LINKS
	JRST TCOU76		;AND PROCEED

TCOU77:	MOVEI T1,^D1000		;WAIT 1 SEC
	CALL SETBKT		;COMPUTE WAIT
	HRRI T1,BLOCKT		;THE TEST
	RDISMS			;WAIT HERE
	JRST TCOU75		;TRY AGAIN

	ENDSV.			;END STKVAR

	RESCD			;BACK TO RESIDENT MONITOR
;TTLNK3 - SCAN LINK WORD, SENDING CHAR TO LINES SPECIFIED BY NON-777 BYTES

TTLNK3::SKIPE IMECHF		;ECHO CHARACTER?
	JRST [	PUSH P,T2	;SAVE DYNAMIC DATA ADDRESS
		JRST TTLN33]	;AND PROCEED
	DYNST T4		;GET LINE NUMBER
	PUSH P,T4		;SAVE LINE NUMBER
	CALL ULKTTY		;UNLOCK THE TTY
TTLN33:	;AOS LINKF		;BE SURE CHARS GO OUT
TTLNK2:	SETZ 2,
	LSHC 2,^D9		;GET NEXT FIELD
	CAIN 2,777
	JRST TTLNK1		;MEANS NOT IN USE
	PUSH P,3
	PUSH P,1		;SAVE CHARACTER
	CALL LCKTTY		;LOCK UP DESTINATION TTY
	 JRST TTLNK4		;NOT ACTIVE. DON'T SEND TO IT
	TRNN 1,200		;THIS CHARACTER HAVE PARITY?
	JRST TTLK11		;NO. GO ON
	CALL SPARTY		;SET PARITY BIT
TTLK11:	CALL TCOU3		;GO SEND EXACT CHARACTER
TTLNK4:	CALL ULKTTY		;FREE UP THE TTY
	POP P,1
	POP P,3
TTLNK1:	JUMPN 3,TTLNK2		;DO MORE IF ANY
;	SOS LINKF		;NO LONGER LINKING
	SKIPE IMECHF		;DOING ECHOING?
	JRST PB2		;YES. CLEAN UP AND DONE
	PUSH P,1		;SAVE BYTE
	MOVE T2,-1(P)		;GET BACK LINE NUMBER
	CALL LCKTTY		;LOCK IT UP AGAIN
	 JUMPLE T2,[MOVE T2,-1(P) ;GET LINE # AGAIN
		CALL TCOU7	;GET A SPECIAL BLOCK
		JRST .+1]	;AND PROCEED
	POP P,T1		;GET BYTE
	ADJSP P,-1		;CLEAN UP STACK
	RET			;AND PROCEED
;TCOTST - CALLED FROM SCHEDULER TO TEST FOR RUNNABLE

;ACCEPTS:
;	T1/ INTERNAL LINE NUMBER
;	CALL TCOTST
; RETURN +1: DON'T WAKEUP
;	+2: WAKEUP
;CAUSES WAKEUP IF OUTPUT BUFFER IS NOT TOO FULL TO ADD A CHARACTER TO IT

TCOTST::MOVEI 2,0(1)		;LINE NUMBER TO REGULAR AC
	CALL STADYN		;POINT TO DYNAMIC DATA
	 RETSKP			;NOT ACTIVE. SHOULDN'T HAPPEN
	LOAD 1,TOWRN,(2)	;REGULAR WAKEUP COUNT
	TMNE FKINX,(FX)		;BUT IF INTERRUPT WAITING,
	LOAD 1,TOMAX,(2)	;WAKEUP IF BUFFER IS NOT FULL
	CAMG 1,TTOCT(2)		;AT WAKEUP LEVEL?
	RET			;NO
	SETZRO TTBKO,(T2)	;NOTE WAIT COMPLETED
	RETSKP			;YES
;SPECIAL OUTPUT BLOCK WAIT - TIMES BLOCK
; T1/ LINE NUMBER
; FX/ FORKX
;	CALL J0TCOT
; RETURN +1: REMAIN BLOCKED
;	+2: UNBLOCK

J0TCOT:	CALL TCOTST		;SEE IF NORMAL COMPLETION
	IFSKP.
	  RETSKP		;YES, ALL OK.
	ENDIF.
	MOVE T1,TODCLK		;OUTPUT STILL BLOCKED, SEE HOW MUCH TIME
	OPSTR <SUB T1,>,FKST2,(FX) ; HAS ELAPSED
	CAIGE T1,^D30000	;30 SECONDS?
	RET			;LESS THAN 30 SECONDS - KEEP WAITING.
	CAIL T1,^D90000		;90 SECONDS OR MORE?
	JRST J0TC90		;YES
	CAIL T1,^D60000		;60 - 90 SECONDS?
	JRST J0TC60		;YES
	DYNST T3		;FIRST TIMEOUT - GET LINE NUMBER
	IFQN. TTSHU,(T3)	;IS LINE SHUT OFF?
	  BLOCK.
	  SAVEAC <T2>		;SAVE DYN PTR
	  MOVE T2,T3		;PASS LINE NUMBER
	  TDCALL S,<<FE,TTTOBL>> ;(T2) TURN LINE ON
	  ENDBK.
	ENDIF.
	IFQN. <TTSFG,TTRXF>,(T2) ;OUTPUT XOFF?
	  CALL TTXONF		;(T2) CLEAR IT AND RESTART OUTPUT
	ENDIF.
	RET			;OUTPUT MAY BE GOING NOW...
;LINE HAS BEEN STUCK FOR 60 SECONDS OR MORE, BUT LESS THAN 90.

J0TC60:	AOSE J0RLDF		;HAS FE BEEN RELOADED?
	RET			;YES, KEEP WAITING
	CALL LODCFE		;REQUEST RELOAD OF CONSOLE FE
	BUG.(CHK,CTYSTK,TTYSRV,HARD,<FE reload requested because CTY is stuck>,,<

Cause:	A job 0 fork was trying to output to the console, but was unable to.
	The job entered the J0TCOT scheduler test to wait for the CTY to clear,
	so that output could begin again.  However, the CTY has remained hung
	for a while and a FE reload has been requested.

Action:	Check the CTY to see if it is functioning properly, has not run out of
	paper, and has not been left at the RSX20F PARSER prompt.  If the
	problem persists, contact Field Service to have them check out the CTY
	and front end hardware.
>,,<DB%NND>)			;[7.1210] 
	RET			;KEEP WAITING

;LINE HAS BEEN STUCK FOR 90 SECONDS OR MORE.

J0TC90:	CALL TTCBF2		;(T2) CLEAR OUTPUT BUFFER, ENSURES UNBLOCK.
	RETSKP

;TTBUFW - CALLED FROM SCHEDULER TO WAIT FOR BUFFERS

;ACCEPTS:
;	T1/ NUMBER OF BUFFERS NEEDED

;CAUSES WAKEUP IF THE NEEDED NUMBER OF BUFFERS ARE AVAILABLE

TTBUFW:	CAMLE 1,TTFREC
	JRST 0(4)
	JRST 1(4)
	SUBTTL TCI (Get Char From Input Buffer)

;ROUTINE TO GET CHARACTER FROM LINE INPUT BUFFER
;CONVERT FROM ASCII TO INTERNAL AND GENERATE ECHOS
;AS REQUESTED

;ACCEPTS IN T2/	LINE #
;	CALL TCI
;RETURNS +1:	NEEDED TO BLOCK, CALLER MUST VERIFY IF THE TTY BEING
;			INPUT FROM IS STILL THE CORRECT ONE.  IN
;			PARTICULAR, WAS THE JOB DETACHED?
;	 +2:	SUCCESSFUL, CHARACTER IN T1
;N.B. T2 MUST BE PRESERVED IN THIS ROUTINE

TCI::
TCI1:	LOAD T3,TT%DAM,TTFLGS(T2) ;GET CURRENT DATA MODE
	JUMPE T3,TCIB2		;JUMP IF BINARY
	LOAD T1,TYLCH,(T2)	;GET LAST CHARACTER TAKEN FROM INPUT BUFFER
	TMNE TTRFG,(T2)		;REPEAT LAST CHARACTER (BKJFN)?
	JRST [	SETZRO TTRFG,(T2) ;YES. CLEAR FLAG
		TXO T1,TTXECO	;INDICATE ALREADY ECHOED
		JRST TCI3]
	LOAD T3,TYLMD,(T2)	; GET MODE OF LAST CHAR INPUT
	CAIN T1,.CHCRT		;LAST CHAR WAS A CR?
	CAIN T3,.TTBIN		; YES, LAST MODE NON-BINARY?
	JRST [	CALL TCI0	; NO TO EITHER - GET NEXT CHAR FROM BUFFER
		 RETBAD		;NEEDED TO BLOCK. TELL THE CALLER.
		JRST TCI3]	; AND CONTINUE
	MOVE T1,[.CHLFD+TTXECO]	;YES, RETURN LF WITH NO ECHO

;NEXT CHARACTER IS IN RIGHT 9 BITS OF T1. IF IT HAS BEEN ECHOED,
;BIT TTXECO IS SET

TCI3:	CALL TCITTI		;TEST FOR TERMINAL INTERRUPT AND HANDLE IT
	 RETBAD			;IT WAS, RETURN FAILURE

;NOT AN INTERRUPT CHARACTER. RAISE AND/OR ECHO AS NEEDED AND RETURN
;IT TO THE CALLER IN 7 BITS.

	MOVE T4,T1		;T4/ CHARACTER AND ECHO BIT
	ANDI 1,177		;T1/ CHARACTER IN 7 BITS
	MOVE 3,TTFLGS(2)	;T3/ TTFLGS FOR THIS LINE
	CAIN T1,.CHCRT		;A CR?
	JRST [	CALL TCIECO	;YES, ECHO CR-LF
		MOVEI T1,.CHLFD
		CALL TCIECO
		MOVEI T1,.CHCRT	;RETURN CR THIS TIME
		JRST TCIR]
	CALL TTRAIS		;TRANSLATE, RAISE, ETC.
	CALL TCIECO		;ECHO CHARACTER IF NECESSARY
	JRST TCIR
;TCIB - ENTRY FOR BINARY INPUT

;ACCEPTS:
;	T2/ INTERNAL LINE NUMBER

;	CALL TCIB

;RETURNS +1: NEEDED TO BLOCK
;	 +2: SUCCESS
;		T1/ CHARACTER

TCIB::
TCIB2:	TMNE TTRFG,(T2)		;REPEAT LAST CHARACTER?
	JRST [	SETZRO TTRFG,(T2) ;YES. CLEAR FLAG
		LOAD T1,TYLCH,(T2) ;GET LAST CHARACTER INPUT
		JRST TCIB1]
	MOVEI T3,.TTBIN		;USE BINARY TERINAL DATA MODE
	CALL TCI0		;GET A CHAR
	 RETBAD			;NEEDED TO BLOCK. RETURN TO CALLER.
	CALL TCITTI		;CHECK FOR TERMINAL INTERRUPT
	 RETBAD			;IT WAS, RETURN FAILURE
TCIB1:	ANDI T1,377		;RETURN CHARACTER + PARITY

;ALL ECHOING, ETC., HAS BEEN DONE. STORE IN DYNAMIC DATA AND
;RETURN THE CHARACTER TO THE CALLER

TCIR:	STOR T1,TYLCH,(T2)	;SAVE LAST CHAR
	LOAD T3,TT%DAM,TTFLGS(T2) ;GET CURRENT DATA MODE
	STOR T3,TYLMD,(T2)	;AND STORE AS DATA MODE FOR LAST CHAR INPUT
	RETSKP			;SKIP TO INDICATE BUFFER WASN'T EMPTY
;TCIECO -DO DEFERRED ECHO IF NECESSARY

;ACCEPTS:
;	T1/ CHARACTER IN 7 BITS
;	T2/ ADDRESS OF DYNAMIC DATA
;	T3/ TTFLGS FOR THIS LINE
;	T4/ CHARACTER IN 9 BITS

TCIECO:	TXNE T3,TT%ECO		;ECHOS ON?
	TRNE T4,TTXECO		;AND CHARACTER NEEDS ECHO?
	RET			;NO, DO NOTHING
	PUSH P,T3		;SAVE 3 FOR CALLER
	PUSH P,T4		;SAVE 4 FOR CALLER
	CALL CLOFLG		;CLEAR CTRL-O FLAG IF NECESSARY
	CALL TCOE		;SEND IT
	POP P,T4
	POP P,T3
	RET

;TTCLPS - ROUTINE TO CLEAR PAGE COUNTER ON ENABLED INTERRUPT CHARACTER
;IF LINE IS IN PAGE MODE

;ACCEPTS:
;	T2/ ADDRESS OF DYNAMIC DATA

;	CALL TTCLPS

;RETURNS +1: ALWAYS,
;	ALL AC'S PRESERVED

TTCLPS:	JE TTNXO,(T2),R		;IF NO PAGE STOP, DONE
	SETZRO TPGPS,(B)	;YES. CLEAR PAGE POSITION
	RET			;AND RETURN

;CLEAR CTRL-O FLAG
; T2/ DYNAMIC PTR

CLOFLG:	JNOR <TOFLG,TTFLO>,(T2),R ;RETURN IF NEITHER FLAG SET
	SAVEAC <T1>
	MOVEI T1,TTOMRK		;YES, PUT MARKER IN STREAM
	SKIPE CTRLOF		;BUT ONLY IF NEW MODE
	CALL SKCON		;AND INTERRUPT NOT ENABLED
	IFSKP. <
	  CALL TCOUM>
	SETZRO TOFLG,(T2)	;CLEAR MAIN LEVEL FLAG
	RET
;TCI..

;TEST FOR DEFERRED TERMINAL INTERRUPT CHARACTER.  INITIATE
;INTERRUPT IF NECESSARY.
; T1/ CHARACTER
; T2/ ADDRESS OF DYNAMIC DATA
;	CALL TCITTI
; RETURN +1: INTERRUPT CHAR, INTERRUPT INITIATED
; RETURN +2: NON-INTERRUPT CHAR, T1 PRESERVED

TCITTI:	SAVEAC <Q1>
	MOVEM T1,Q1		;SAVE CHAR
	ANDI T1,177		;EXTRACT ASCII
	CALL GPSICD		;GET PSI CODE IF ANY
	JUMPL T1,TCITT1		;JUMP IF NONE
	MOVE T3,BITS(T1)
	TDNN T3,TTPSI(T2)	;THIS CODE ENABLED?
	JRST TCITT1		;NO

;THIS IS A DEFERRED INTERRUPT CHARACTER.  INITIATE THE INTERRUPT
;AND WAIT UNTIL IT HAS TAKEN

	CALL TTCLPS		;YES. CLEAR OUT PAGE MODE STUFF
	MOVEM T2,Q1		;SAVE ADDRESS OF DYNAMIC DATA
	MOVE T3,T1		;PASS CODE IN T3 FOR TTPSRQ
	NOSKED
	CALL ULKTTY		;ALLOW DEALLOCATION
	DYNST			;T2/ INTERNA LINE NUMBER
	CALL TTPSRQ		;INITIATE INTERRUPT. RETURNS FORK ID IN 2
	OKSKED
	AOS TTINTS		;COUNT INTERRUPTS
	MOVEI T1,TCIPIT		;SETUP SCHED TEST FOR INTERRUPT PROCESSED
	HRL T1,T2		;GET FORK THAT GOT THE INTERRUPT
	TMNE FKINX,(T2)		;INTERRUPT STILL PENDING?
	MDISMS			;YES, WAIT A WHILE
	MOVE T2,Q1		;RESTORE ADDRESS OF DYNAMIC DATA
	RET			;RETURN NOSKIP TO RELOCK DATA

;NOT AN INTERRUPT CHARACTER.  GIVE SKIP RETURN

TCITT1:	MOVE T1,Q1		;RESTORE INPUT CHAR
	RETSKP			;RETURN TO CONTINUE PROCESSING CHAR

;TCIPIT - SCHEDULER TEST FOR MDISMS. CAUSES WAKEUP IF THE
;PROCESS POINTED TO BY AC 1 HAS NO PENDING INTERRUPTS

;ACCEPTS:
;	T1/ FORK HANDLE

TCIPIT:	TMNE FKINX,(T1)		;SCHED TEST FOR INTERRUPT STILL PENDING
	JRST 0(T4)		;STILL PENDING
	JRST 1(T4)		;COMPLETED
;TCI..

;TCI0 - GET ONE CHARACTER FROM LINE INPUT BUFFER

;ACCEPTS:
;	T2/ ADDRESS OF DYNAMIC DATA
;	T3/ TERMINAL DATA MODE IN BITS 34-35

;RETURNS +1: LINE BUFFER WAS EMPTY, HAD TO WAIT
;	 +2: LINE BUFFER WAS NOT EMPTY,
;		T1/ CHARACTER IN 9 BITS

;CALLER MUST HAVE CALLED LCKTTY ON THE LINE. IF BLOCK ON INPUT
;WAIT OCCURS, THIS ROUTINE CALLS ULKTTY

TCI0:	NOSKED
	CALL GTTCI		;GET CHAR FROM INPUT BUFFER
	 JRST TCI01		;EMPTY
	OKSKED
	CALL SNDXON		;SEND XON IF NEEDED
	RETSKP			;SKIP TO INDICATE NO WAIT

;TAKE NEXT CHAR FROM TTY IN BFR
; T2/ TERMINAL DATA BLOCK
; RETURN +1: BUFFER EMPTY
;	+2: T1/ CHAR

GTTCI::	SKIPG 1,TTICT(2)	;ANY CHARS IN BUFFER?
	RET			;NO
	SKIPN 3,TTIOUT(2)	;GET POINTER
	BUG.(HLT,TTICN0,TTYSRV,SOFT,<GTTCI - No buffer pointer but count non-zero>,,<

Cause:	At TCI0 (get a character from the line's input buffer) the pointer to
	the dynamic data base for the line was 0.  This could either be a
	coding error or the resident table containing the pointers was
	clobbered.  Examination of the stack in the dump should indicate which
	routine called TCI0 without the pointer.
>)
	HRRZ 4,3
	TDNN 3,WRPMSK		;AT END OF CURRENT BUFFER?
	JRST [	LDB 1,[POINT 6,3,5] ;GET BYTE POSITION AND SIZE
		CAIN 1,73	;POINTING TO LAST BYTE?
		HRR 3,1-TTSIZ(4) ;YES. GET ADDRESS OF NEXT BUFFER
		JRST .+1]
	ILDB 1,3		;GET NEXT CHARACTER
	MOVEM 3,TTIOUT(2)	;SAVE UPDATED BYTE POINTER
	SOSG TTICT(2)		;REDUCE COUNT, NOW EMPTY?
	JRST [	SETZB 3,TTIOUT(2) ;YES, RELEASE BUFFERS
		EXCH 3,TTIIN(2)
		CALL TTRLBF
		JRST .+1]
	RETSKP
;ACTION IF BUFFER IS EMPTY. MAKE SURE NO OTHER FORK IS WAITING.
;THEN GO INTO INPUT WAIT

TCI01:	OKSKED
TCI11:	LOAD T1,TWFRK,(T2)	;GET FORK WAITING FOR THIS LINE
	CAIE T1,-1		;IS THERE ONE?
	JRST TCIF1		;YES. GO RESOLVE THE CONFLICT

;NO OTHER FORK IS WAITING. GO INTO INPUT WAIT ON THIS LINE
;NOTE: THE TEST ON TTLCK IS A BIG HACK TO KEEP FSIINI HAPPY.
;DON'T TRY TO MAKE USE OF IT FOR ANYTHING ELSE!!
;ALL CALLERS OF TCI SHOULD HAVE CALLED LCKTTY

TCIF2:	STOR T3,TYLMD,(T2)	;SAVE DATA MODE THIS INPUT
	PUSH P,3		;SAVE DATA MODE
	MOVE T3,FORKX		;GET INDEX OF THIS FORK
	STOR T3,TWFRK,(T2)	;RECORD THIS FORK WAITING FOR TTY
	SETZRO TTFWK,(T2)	;INDICATE NO FORCED WAKEUP
	TDCALL D,<<PT,TCIPTY>,<TV,TVTIGA>,<CH,CTHTCI>>
	SETZRO TTWFG,(T2)	;CLEAR WAIT RESTARTED FLAG
	PUSH P,T2		;SAVE ADDRESS OF DYNAMIC DATA
	DYNST			;GET LINE NUMBER
	HRL T1,T2		;SAVE LINE NUMBER
	POP P,T2		;RESTORE ADDRESS OF DYNAMIC DATA
;	TMNE TTLCK,(T2)		;DON'T UNLOCK IF IT'S NOT LOCKED
	CALL ULKTTY		;ALLOW DEALLOCATION
	HRRI 1,TCITST		;T1/(LINE NUMBER,,ROUTINE)
	PUSH P,T2
	MOVSI T2,FHV4		;WAIT PRIORITY - BETTER THAN AVERAGE
	HDISMS
	POP P,T2
	POP P,3			;RESTORE CURRENT MODE
	RET			;GIVE NON-SKIP RETURN TO SAY A BLOCK
				;  OCCURRED

;A FORK IS WAITING FOR INPUT ON THIS TERMINAL. IF IT IS THE CURRENT
;FORK, PROCEED AS USUAL. IF NOT, RESOLVE THE CONFLICT BY HALTING THE
;OTHER FORK IF IT IS INFERIOR TO THIS ONE OR WAITING FOR THE OTHER
;FORK IF IT IS SUPERIOR TO THIS ONE OR IN ANOTHER JOB

TCIF1:	ANDI A,7777
	CAMN A,FORKX		;IS IT THIS FORK?
	JRST TCIF2		;YES. GO TO IT THEN
	CALL ULKTTY		;RELEASE TTY LOCK AND GO OKINT
	CALLRET TTFRKT		;GO RESOLVE CONFLICT BY HALTING FORK
	SUBTTL Miscellaneous Routines

;FORCE WAKEUP OF FORK NOW WAITING FOR SPECIFIED TTY LINE
; 2/ ADDRESS OF DYNAMIC DATA

TTFWAK::PUSH P,FX
	LOAD FX,TWFRK,(2)	;GET INDEX OF FORK IN INPUT WAIT
	CAIN FX,-1		;IS A FORK WAITING?
	JRST TTFW1		;NO
	ANDI FX,7777		;YES, FLUSH FLAGS
	SETONE TWFRK,(T2)	;INDICATE NO FORK WAITING
	SETZRO TTFWK,(T2)	;DON'T FORCE WAKEUP ON THIS FORK
				; UNTIL INPUT BUFFER FULL AGAIN
	CALL TTUBLK		;UNBLOCK THE FORK
TTFW1:	POP P,FX
	RET

;UNBLOCK TTY INPUT FORK ONLY IF STILL WAITING FOR TTY INPUT
; FX/ FORK INDEX
;	CALL TTUBLK
; RETURN +1: ALWAYS, FORK UNBLOCKED IF IN TCITST

TTUBLK:	SAVELN
	MOVE 1,FX		;SETUP ARG
	CALLRET UNBLKF		;TELL SCHED TO UNBLOCK THE FORK
;SCHEDULER TEST ROUTINE FOR FORKS WAITING FOR TTY INPUT
;CALLED WITH JSP 4,
;AC 1 CONTAINS LINE NUMBER
;AC FX CONTAINS FORK NUMBER OF FORK BEING TESTED

TCITST::MOVE T2,T1		;GET LINE NUMBER
	CALL STADYN		;POINT TO DYNAMIC DATA
	 JRST 1(4)		;LINE ISN'T ACTIVE. WAKE UP THE PROCESS
	LOAD T1,TWFRK,(T2)	;GET INDEX OF FORK IN INPUT WAIT
	CAIN T1,-1		;IF NONE, WAKEUP
	JRST 1(T4)
	JN <TTFWK,TTWFG>,(T2),1(T4)	;IF FORCED WAKEUP SET, WAKE THE PROCESS
				;WAKEUP IF WE'VE BEEN HERE BEFORE
	SKIPE TTICT(T2)		;WAKEUP IF BUFFER ISN'T EMPTY
TCITS1:	JRST 1(T4)		;WAKE THE PROCESS
	SETONE TTWFG,(T2)	;INDICATE WE'VE BEEN HERE WITHOUT WAKING
	JRST 0(T4)		;DON'T WAKE NOW

;SPECIAL CODE FOR TTY SIMULATORS. THIS ROUTINE PERFORMS THE PROPER
;TESTS FOR THE SPECIAL SIMULATOR. TO USE IT, PUT ITS ADDRESS
;IN THE LINE TYPE VECTOR AT TCIF2+7 AND PATCH IN THE PROPER LINE
;NUMBERS BELOW

TTCTRA:	MOVEI T1,"A"-100	;OUTPUT CHAR IS CONTROL-A
	DYNST (T3)		;GET STATIC DATA IS T3
	CAIL T3,.-.
	CAILE T3,.-.		;WITHIN RANGE?
	RET			;NO. DON'T SEND ^A THEN
	CALLRET TCOUT		;YES. SEND CHARACTER
;'RAISE' INPUT

;ACCEPTS:
;	T1/ THE CHARACTER IN 7 BITS
;	T3/ TTFLGS FOR THE LINE

TTRAIS:	TXNE T3,TT%LIC		;IF NOT RAISING INPUT
	CAIGE T1,"A"+40		; OR NOT IN RANGE
	RET			;RETURN UNCHANGED
	CAIG T1,"Z"+40		;IF LOWER CASE ALPHABETIC
	TRZ T1,40		; CONVERT TO UPPER CASE ALPHABETIC
	CAIE T1,.CHALT		;CONVERT OLD ASCII ALTMODE
	CAIN T1,.CHAL2		; AND ALTERNATE FORM
	MOVEI T1,.CHESC		; TO THE ESC CODE
	RET

;GPSICD - GET PSI CODE FOR CHARACTER
; 1/ CHARACTER
;	CALL GPSICD
; RETURN +1 ALWAYS, 1/ PSI CODE OR -1 IF NOT A POSSIBLE PSI CHAR

GPSICD::CAIG 1," "		;WITHIN NON-PSI CHAR RANGE?
	JRST GPSIC1		;NO
	CAIL 1,175
	JRST GPSIC3		;NO
GPSIC2:	SETO 1,			;YES, RETURN -1
	RET

GPSIC1:	CAIN 1," "		;SPACE?
	SKIPA T1,[^D29]		;YES, RETURN CODE
	CAIG 1,33		;CONTROL CHAR OR ESC?
	RET			;YES, CODE EQUAL CHARACTER
	JRST GPSIC2		;NOT A PSI CHAR

GPSIC3:	CAIN 1,177		;RUBOUT?
	SKIPA T1,[^D28]		;YES, RETURN CODE
	MOVEI 1,^D27		;NO, IS OLD ALT-MODE
	RET

;SKIP IF FLOCHR IS ENABLED AS A PSI
; T2/ DYN PTR

SKCOE:	MOVX CX,1B<FLOCHR>
	TDNN CX,TTPSI(T2)
	RET
	RETSKP

;SKIP IF FLOCHR NOT ENABLED AS A PSI
; T2/ DYN PTR

SKCON:	MOVX CX,1B<FLOCHR>
	TDNE CX,TTPSI(T2)
	RET
	RETSKP
	SUBTTL TTCH7 (Empty TTBBUF, Process TTCS Words)

;TELETYPE INPUT CHANNEL 7 ROUTINE
;RUN EVERY SO OFTEN TO MOVE CHARACTERS FROM BIG BUFFER TO LINE BUFFERS,
;GENERATE ECHOS AND HANDLE CARRIER TRANSITIONS
;ENTERED BY  CALL  FROM SCHED
;CALLED IN SCHEDULER CONTEXT

TTCH7::	SKIPG TTBIGC		;BIG BUFFER EMPTY?
	JRST TTCH7X		;YES, RETURN
	AOS T3,TTBIGO		;[7342] NO. INCREMENT POINTER TO LOAD FROM
	CAIN T3,TTBSIZ		;[7342] AT END OF TTBBUF?
	SETZB T3,TTBIGO		;[7342] YES. POINT TO START OF TTBBUF
	MOVE T1,TTBBUF(T3)	;[7342] GET NEXT ENTRY
	SOS TTBIGC		;DECREMENT COUNT OF ENTRIES
	HLRZ T2,T1		;[7342] GET LINE NUMBER
	MOVEI Q2,0(T1)		;[7342] SAVE ALL ORIGINAL FLAGS
	SOS T3,TTSTAT(T2)	;[7342] Update TTBBF count
	JN TTFXO,(T2),DOXON	;[7342] Send XON if needed
TTCH7A:	TRNE T1,TTPIRQ		;NON CONTROLLING TERMINAL PSI?
	JRST [	CALL STADYN	;CONVERT TO DYNAMIC DATA POINTER
		 JRST TTCH7	;NONE
		LOAD T1,TTOPSI,(T2) ;[7342] GET PSI
		LOAD T2,TTPSFK,(T2) ;GET FORK
		CAIE T2,-1
		CALL PSIRQ	;IF FORK SETUP, REQUEST INTERRUPT
		JRST TTCH7]	;AND TRY NEXT
	TRNE T1,TTOIRQ		;[7342] OUTPUT INTERRUPT REQUEST?
	JRST [	MOVX T3,.TICTO	;[7342] YES. OUTPUT BUFFER WENT EMPTY AND PROCESS
		CALL TTPSRQ	; ENABLED FOR INTERRUPT. ISSUE IT
		JRST TTCH7]	;DONE WITH WORD
	TRNE T1,DLSCXF		;[7342] CARRIER TRANSITION?
	JRST TT7CX		;YES
	TRNN T1,DLSRCF		;[7342] RECEIVER?
	JRST TTCH7		;NO (SHOULD NOT HAPPEN) - RESUME  SCAN

;A CHARACTER WAS FOUND. SAVE IT IN 8 BITS AND GO STORE IN BUFFER.
;THEN GO GET NEXT WORD FROM TTBBUF

	ANDI T1,377		;[7342] GET 7 BITS OF CHARACTER + PARITY
	CALL TTCHI		;PUT CHAR IN LINE BFR
	 NOP			;IGNORE FAILURE
	JRST TTCH7		;DO NEXT
;This routine decides whether to send an XON to an XOFF'd line.
;The XON will only be sent in this one place to prevent a race
;condition that used to exist between TTYSRV and RSXSRV.
;
;	T2 - Line number
;	T3 - TTY status word for this line

DOXON:	ANDI T3,TTFBB		;[7342] Get just the big buffer count for this line
	JUMPN T3,TTCH7A		;[7342] Wait until no more chars in BIGBUF
	CALL STADYN		;[7342] (T2/T2) Get dynamic data block
	JRST TTCH7		;[7342] Not all there
	LOAD T3,TIMAX,(T2)	;[7342] Get maximum size of buffer
	MOVE T4,TTICT(T2)	;[7342] Get current input buffer count
	DYNST			;[7342] Back to static pointer
	CAIL T3,MINICT(T4)	;[7342][7390] Too many characters in BIGBUF?
	CALL SNDXNS		;[7342] () No, he needs an XON
	JRST TTCH7A		;[7342] Continue...
;SEND XON IF NECESSARY
; SNDXON
;	T2/ DYNAMIC
;SNDXNS
;	T2/ STATIC

SNDXON:	SAVEAC <T1,T2>		;[7342]
	MOVE T1,TTICT(T2)	;[7342] Get input character count
	CAIL T1,MINXON		;[7342] Few enough to allow an XON?
	RET			;[7342] No, don't send an XON now
	DYNST			;[7342]
	JE TTFXO,(T2),R		;[7342] Do nothing if not XOFF'd
	LOAD T1,TTFBB,(T2)	;[7342] Get count of chars in TTBBU
	CAIL T1,MAXBBC		;[7342] Is TTBBUF too full with stuff from this line?
	RET			;[7342] Yes, don't XON him yet
SNDXNS:	TDCALL S,<<FE,SNDXN2>,<MC,MCSXON>,<CH,SNDXN2>> ;SEND XON IF NEEDED
	RET
;TTCH7..

;TTBBUF IS EMPTY. DO DEVICE DEPENDENT FUNCTIONS IF NEEDED

TTCH7X:	CALL CKQLN		;CHECK QUEUED LINES
	CALL TTYQOC		;START OUTPUT ON QUEUED LINES
	CALL XTRCH7		;DO CONFIGURATION DEPENDENT SCANNING (IN STG)
	CALL MCSRV 		;DECNET LINES
	SKIPGE TTQCNT		;HAVE SOME SCANNING TO DO?
	RET			;NO. ALL DONE THEN

;BEFORE LEAVING, CHECK 8 LINES TO SEE IF THERE IS A SHORT BLOCK TO RELEASE

TTHNG4:	MOVE 2,TTCQLN		;GET NEXT LINE TO BE CHECKED
	MOVEI 4,10		;LIMIT OF 10 LINES FOR THIS PASS
TTCQ3:	SKIPGE TTQCNT		;ALL DONE?
	JRST TTCQ5		;YES, GO SAVE LINE NUMBER AND RETURN
	CALL CKSBK		;CHECK FOR SHORT BLOCK

;GO TO NEXT LINE. IF THE LINE TYPE CHANGES, DON'T PROCEED WITH THE NEW
;LINE. INSTEAD, GO TO THE NEXT LINE TYPE AFTER THE ONE JUST PROCESSED.
;THIS CODE ASSUMES THAT ALL LINES OF A GIVEN TYPE ARE NUMBERED CONSECUTIVELY.

TTCQ2:	LOAD C,TTSTY,(B)	;NO. GET CURRENT TYPE
	ADDI B,1		;GO TO NEXT LINE
	CAIL B,NLINES		;VALID LINE NUMBER?
	JRST TTCQ6		;NO. GO TO NEXT LINE TYPE
	LOAD A,TTSTY,(B)	;GET TYPE OF NEXT LINE
	CAMN C,A		;NEW TYPE?
	JRST TTCQ1		;NO. GO ON

;FINISHED THE CURRENT LINE TYPE OR THE CURRENT TYPE IS NOT TO BE PROCESSED
;GO TO THE NEXT TYPE AND SEE IF IT IS TO BE PROCESSED

TTCQ6:	AOS C			;GO TO NEXT LINE TYPE
	CAIL C,NLTYPS		;BEYOND END OF LEGAL TYPES?
	SETZ C,			;YES. GO BACK TO BEGINNING
	MOVE B,TT1LIN(C)	;GET FIRST LINE OF THIS TYPE
	JUMPL B,TTCQ6		;IF LINE GROUP IS NOT HERE, GO GET NEXT

;PROCESS THIS LINE UNLESS WE HAVE DONE ENOUGH FOR THIS PASS

TTCQ1:	SOJG 4,TTCQ3		;DONE ENOUGH FOR THIS TIME?
TTCQ5:	MOVEM 2,TTCQLN		;YES, START AT THIS LINE NEXT TIME
	RET
;TTCH7...
CKSBK:	SAVET
	CALL STADYN		;POINT TO DYNAMIC DATA
	 SKIPG T2		;NOT FULLY ACTIVE.  ANY DYNAMIC DATA?
	RET			;INACTIVE, BECOMING ACTIVE, OR FULL-LENGTH
	JN <TTLCK,TTSAL>,(T2),R ;DON'T RELEASE IF DOING SENDALL OR LOCKED
	JN TTSHT,(T2),DOLIN2	;IF SHORT AND SENDALL DONE, RELEASE BLOCK
	CALL TTSOBE		;IS OUTPUT COMPLETE?
	 RET			;NOT FINISHED WITH THE BLOCK YET

;HAVE A MESSAGE BLOCK.  RELEASE THE BLOCK AND RELEASE THE ASSOCIATED
;OUTPUT BUFFERS (IF ANY)

	SKIPE T3,TTOOUT(T2)	;RELEASE OUTPUT BUFFERS IF ANY
	CALL TTRLBF		; ARE ASSIGNED

;READY TO RELEASE THE BLOCK.  T2 HAS ITS ADDRESS

DOLIN2:	MOVE T1,T2		;T1/ ADDRESS OF BLOCK TO RELEASE
	DYNST			;GET LINE NUMBER
	SETZM TTACTL(T2)	;INDICATE NO DATA FOR THIS LINE
	CALL RELRES		;RELEASE THE BLOCK
	SOS TTQCNT		;ONE MORE DONE
	RET
;TTCH7..

;TTQAD - ADD ITEM TO CONTROL QUEUE

;ACCEPTS:
;	T1/ TIME UNTIL EVENT (ACTUAL MAY BE LONGER)
;	T2/ INTERNAL LINE NUMBER
;	T3/ ROUTINE TO BE CALLED AT GIVEN TIME
;	  N.B. - ROUTINE MUST BE IN TABLE HEREIN

;	CALL TTQAD (TTQAD1 FOR DEFAULT TIME LIMIT)

;RETURNS +1: ALWAYS

TTQAD1:	MOVEI T1,^D3000		;ITEM TO BE DONE IN 3 SEC.
TTQAD::	SAVEAC <T4>
	ADD T1,TODCLK		;COMPUTE ABSOLUTE TIME TO DO FUNCTION
	CAMLE T1,TTCSTM(T2)	;LATER THAN NOW SET?
	MOVEM T1,TTCSTM(T2)	;YES, SAVE TIME FOR DOING THE FUNCTION
	MOVSI T4,-NTQFN		;SCAN TABLE FOR SPECIFIED ROUTINE
TTQAD2:	CAMN T3,TQFNT(T4)	;THIS ONE?
	JRST TTQAD3		;YES
	AOBJN T4,TTQAD2		;NO
	BUG.(CHK,TTQADX,TTYSRV,SOFT,<TTYSRV - Unknown function requested>,<<T3,ADR>>,<

Cause:	TTQAD has been called with a routine address that is not in its local
	table of known routines.  To diagnose this problem, look at the stack
	to find the call to TTQAD.  Then find the name of the routine being
	passed and add it to the TQFNT table.

Action:	If this BUGCHK is reproducible, set it dumpable and submit an SPR with
	the dump and instructions on reproducing the problem.

Data:	ADR - Address of bogus routine
>)
	RET

TTQAD3:	MOVE T1,BITS(T4)	;GET BIT TO REPRESENT FUNCTION
	IORM T1,TTCSAD(T2)	;SET IT
	MOVE T3,T2
	IDIVI T3,^D36		;GET LOCATION IN BIT MATRIX
	MOVE T4,BITS(T4)
	IORM T4,TQLNQ(T3)	;NOTE LINE NEEDS SERVICE
	RET
;SERVICE QUEUED LINES

CKQLN:	SAVEAC <P1,P2,P3>
	MOVSI P1,-NTSQWD	;SET TO SCAN BIT MATRIX
CKQL1:	SKIPE T1,TQLNQ(P1)	;ANY LINES HERE?
CKQL2:	JFFO T1,CKQL3		;YES, GET ONE
	AOBJN P1,CKQL1
	RET

CKQL3:	MOVE P2,BITS(T2)	;GET BIT FOR LINE
	HRRZ T3,P1
	IMULI T3,^D36		;COMPUTE LINE NUMBER
	ADD T2,T3
	MOVE T1,TODCLK
	CAMGE T1,TTCSTM(T2)	;TIME TO DO FUNCTION
	JRST CKQL4		;NO, MOVE ON TO NEXT LINE
	ANDCAM P2,TQLNQ(P1)	;REMOVE LINE FROM ATTENTION TABLE
	SKIPE T3,TTCSAD(T2)	;ANY FUNCTIONS REQUESTED?
CKQL5:	JFFO T3,CKQL6		;FIND A FUNCTION TO DO
CKQL4:	MOVN T1,P2		;LOOK AT REST OF WORD ONLY
	ANDCA T1,TQLNQ(P1)
	JRST CKQL2

CKQL6:	MOVE P3,BITS(T4)	;SAVE FUNCTION BIT
	ANDCAM P3,TTCSAD(T2)	;CLEAR FUNCTION REQUEST (MAY BE SET AGAIN BY ROUTINE)
	HRRZ T1,TQFNT(T4)	;GET ROUTINE ADDRESS
	CALL [	SAVEAC <T2>	;SAVE LINE NUMBER
		CALLRET 0(T1)]	;DO FUNCTION
	MOVE T1,TODCLK
	CAMGE T1,TTCSTM(T2)	;TIME BUMPED?
	JRST CKQL4		;YES, QUIT THIS LINE
	MOVN T3,P3		;LOOK AT REST OF BITS
	ANDCA T3,TTCSAD(T2)
	JRST CKQL5

;TABLE OF KNOWN TTQAD FUNCTIONS - MAXIMUM 36

TQFNT:	TTTOBL
	TTSN10
	TTCOF
	TTCON1
	NTYCOF
	CKSALL
	CKNOIS
NTQFN==.-TQFNT
IFG NTQFN-^D36,<PRINTX ?TQFNT TOO LARGE>
;TTCH7..

;WORD IN TTBBUF INDICATED CARRIER TRANSITION (DLSCXF WAS SET).
;IF CARONB IS SET, CARRIER WENT ON. IF NOT, CARRIER WENT OFF

TT7CX:	TRNN A,CARONB		;DID CARRIER JUST COME ON?
	JRST TTCX1		;NO, OFF

;CARRIER WENT ON. IF THE LINE IS IN USE OR A JOB IS BEING
;CREATED ON IT, DON'T GO CREATE ANOTHER JOB ON IT

	SETONE TTCON,(B)	;SET CARRIER ON FOR THIS LINE
	TDCALL S,<<FE,RSKP>,<CH,RSKP>>
	 JRST TTCH7		;DO NOTHING
	CALL TTCON1		;CREATE JOB
	JRST TTCH7		;DONE

;TTCON1 - CREATE JOB AS RESULT OF CARRIER COMING ON

;ACCEPTS:
;	T2/ INTERNAL LINE NUMBER

;	CALL TTCON1

;RETURNS +1: ALWAYS

;CARRIER HAS COME ON FOR REAL. TREAT THIS LIKE A CTRL/C AND CREATE
;A JOB IF POSSIBLE

TTCON1:	MOVEM B,C		;SAVE LINE NUMBER
	CALL STADYN		;SEE IF THE LINE IS INACTIVE
	 SKIPE B		;YES. CREATE JOB ON IT IF ALLOWED
	RET			;ACTIVE OR BECOMING ACTIVE. IGNORE CARRIER-ON
	MOVE B,C		;RESTORE LINE NUMBER
	MOVE A,FACTSW		;SEE IF REMOTE LOGINS ALLOWED
	TXNN A,SF%RMT		;...
	JRST [	HRROI A,[ASCIZ /
?LOGGING IN ON DATASETS IS CURRENTLY DISALLOWED.
/]
		CALL TTEMSS	;NO. SAY SO
		RET]		;DONE
	SETONE TTFSP,(B)	;SAY LINE NEEDS SPEED SET
	CALL TTC7SK		;GO CREATE JOB
	 JFCL			;ALWAYS DOES RETSKP
	RET
;TTCH7...

;CARRIER WENT OFF

TTCX1:	JE TTCON,(B),TTCH7	;IF CARRIER WASN'T ALREADY ON, IGNORE IT
	SETZRO TTCON,(B)	;INDICATE CARRIER NO LONGER ON
	TDCALL S,<<FE,RSKP>,<CH,RSKP>>
	 JRST TTCH7		;NOTHING TO DO NOW
	CALL NTYCOF		;DO IT
	JRST TTCH7

;TTCOF - ROUTINE TO SEE IF CARRIER IS STILL OFF.  SCHEDULED (VIA TTQAD)
;TO BE CALLED FOR A LINE WHEN CARRIER GOES OFF ON THE LINE
;NOT USED FOR FRONT END LINES

;ACCEPTS:
;	T2/ LINE NUMBER

;RETURNS +1: ALWAYS
;		T2/ LINE NUMBER

TTCOF:	JN TTCON,(B),R		;IF CARRIER IS BACK ON NOW, DON'T HANGUP
	CALL NTYCOF
	CALLRET TTHU0		;DO HANGUP-REACTIVATE
;NTYCOF - HANDLE CARRIER OFF

;ACCEPTS:
;	2/INTERNAL LINE NUMBER

;	CALL NTYCOF

;RETURN +1: ALWAYS,
;		T2/ LINE NUMBER

;CALLED WHEN CARRIER GOES OFF FOR ANY PHYSICAL LINE. FLUSHES OUTPUT,
;ISSUES AN INTERRUPT IF A PROCESS HAS ENABLED FOR CARRIER-OFF INTERRUPT,
;ISSUES A MONITOR-INTERNAL INTERRUPT THAT CAUSES THE TOP FORK
;TO GO TO JOBCOF IN MEXEC

;ALSO CALLED FOR A LINE ASSOCIATED WITH A PTY WHEN THE PTY IS CLOSED.

NTYCOF::JUMPL T2,R		;[9117] Do nothing if already detached
	CALL TTCOB1		;FLUSH OUTPUT
	CALL CHKCTT		;SEE IF THIS IS A CONTROLLING TERMINAL
	 CALLRET TTJBDT		;NO. DON'T ISSUE INTERRUPT
	MOVE B,C		;YES. B/ADDRESS OF DYNAMIC DATA
	MOVEI C,.TICRF		;C/CODE FOR THIS CONDITION
	MOVE A,BITS(C)		;GET THE BIT
	PUSH P,B		;SAVE ADDRESS OF DYNAMIC DATA
	TDNE A,TTPSI(B)		;IS THE CODE ENABLED?
	CALL TTPSI2		;YES. GIVE THE INTERRUPT
	POP P,B			;RESTORE ADDRESS OF DYNAMIC DATA
	DYNST			;GET BACK THE LINE NUMBER
	CALLRET TTJBDT		;GO DETACH JOB
;TTJBDT - ROUTINE TO GENERATE AN INTERRUPT WHEN CARRIER GOES OFF

;ACCEPTS:
;	T2/ LINE NUMBER

;RETURNS +1: ALWAYS
;		T2/ LINE NUMBER

;ISSUES AN INTERRUPT TO THE TOP FORK IN THE JOB. CAUSES THE JOB TO
;BE DETACHED

TTJBDT::CALL TTCOB1		;CLEAR OUTPUT BUFFERS
	CALL CHKCTT		;SEE IF THIS IS A CONTROLLING TERMINAL
	 RET			;NO
	SETONE TOFLG,(T3)	;FLUSH SUBSEQUENT OUTPUT
   REPEAT 0,<			;FOLLOWING CODE DOES NOT
				;WORK BECAUSE IT CAUSES PAGE
				;FAULTS IN SCHEDULER. NEED TO
				;MOVE THIS ELSEWHERE SOME DAY
	TMNE TTAUT,(B)		;IS THIS AN AUTO SPEED LINE?
	SETOM TTSPWD(B)		;YES. INIT SPEED
   >				;END OF REPEAT 0
	PUSH P,B		;SAVE LINE NUMBER
	HRRZ B,JOBPT(A)		;GET TOP FORK INDEX
	SETONE <FKPS0,FKICO>,(B) ;REQUEST CARRIER OFF ACTION
	CALL PSIR4
	POP P,B			;RESTORE LINE NUMBER
	RET
;TTCH7..

;CHKCTT - CHECK TO SEE TERMINAL IS A CONTROLLING TERMINAL FOR A JOB

;ACCEPTS:
;	T2/ LINE NUMBER

;	CALL CHKCTT

;RETURNS +1: NOT A CONTROLLING TERMINAL
;		T2/ LINE NUMBER
;	 +2: CONTROLLING TERMINAL,
;		T1/ JOB NUMBER
;		T2/ LINE NUMBER
;		T3/ ADDRESS OF DYNAMIC DATA

CHKCTT:	SASUBR <CHKCJN,CHKCSV,CHKCSD>
	SETOM CHKCJN		;SAY NO CONTROLLING JOB
	CALL STADYN		;POINT TO DYNAMIC DATA
	 RET			;NOT ACTIVE
	LOAD C,TCJOB,(B)	;GET OWNING JOB
	CAIN C,-1		;IS THERE ONE?
	RET			;NONE.
	MOVEM C,CHKCJN		;SAVE JOB NUMBER
	MOVEM B,CHKCSD		;RETURN DYNAMIC PTR
	HLRZ A,JOBPT(C)		;GET CONTROLLING TERMINAL FOR JOB
	CAMN A,CHKCSV		;IS THIS THE CONTROLLING TERMINAL?
	RETSKP			;YES, SUCCESS
CHKCT1:	RET			;FAILURE RETURN

	ENDSA.			;END SASUBR

;TTHU0 - HANGUP-REACTIVATE SEQUENCE

;ACCEPTS:
;	T2/ LINE NUMBER

;	CALL TTHU0

;RETURNS +1: ALWAYS

;SCHEDULED BY TTCOF WHEN A LINE HAS LOST CARRIER. CAUSES HANGUP OF THE
;LINE FOLLOWED BY ACTIVATE

TTHU0:	TDCALL S,<<FE,TTHU2>,<TV,TVTDTS>>
	RET
	SUBTTL TTCHI (Move Char From TTBBUF To Input Buffer)

;TTCHI - PROCESS CHARACTER AS INPUT

;ACCEPTS:
;	T1/ CHARACTER IN 8 BITS
;	T2/ INTERNAL LINE NUMBER

;	CALL TTCHI

;RETURNS +1: ALWAYS
;		T2/ LINE NUMBER

;CALLED BY TTCH7 WHEN A CHARACTER HAS BEEN FOUND IN TTBBUF
;INITIATES AN INTERRUPT IF NEEDED; ECHOES IF APPROPRIATE;
;WAKES UP WAITING PROCESS IF NEEDED; STORES CHARACTER IN LINE BUFFER

;CALLED FROM SCHEDULER CONTEXT AND PROCESS CONTEXT
;IF IN PROCESS CONTEXT, MUST BE NOSKED, SO THAT THE SETTING AND
;TESTING OF TCOERR IN TCOUT WILL BE CONSISTENT

;TTCHID - ALTERNATE ENTRY POINT, T2/ DYNAMIC PTR

TTCHID::SAVEAC <T2,Q1,FX>
	DYNST			;GET LINE NUMBER
	JRST TTCHD1

TTCHI::	CAIL 2,NLINES		;REASONABLE LINE?
	RET			;NO
	SAVEAC <T2,Q1,FX>
TTCHD1:	STKVAR <TTCHSV,TTCHFL>	;MUST COME AFTER SAVELN
	MOVEM T2,TTCHSV		;SAVE LINE NUMBER
	MOVEM T1,TTCHIC		;SAVE ORIGINAL CHARACTER
	ANDI T1,377		;USE 8 BITS FOR LOCAL COMPARES
	CALL STADYN		;IS THIS A FULLY ACTIVE LINE?
	 JRST TTC7N		;NO. GO HANDLE THIS CASE SEPARATELY
	MOVX T3,1B<.TITCE>	;Two character
	TDNN T3,TTPSI(T2)	; escape sequence enabled ?
	JRST TTCHD2		;No.
	CALL TTTWES		;(T1,T2/T1,T2) Yes. Check it out.
	 RETSKP			;Drop the character.
TTCHD2:	JN TTNUS,(T2),TTMCNU	;JUMP IF NETWORK USER STATE
       	CALL TTCHXX		;CHECK FOR XON, XOFF
	 RETSKP			;IT WAS, RETURN NOW
	JRST TTCHIF		;CONTINUE
;SEE IF CHARACTER IS XON OR XOFF AND HANDLE AS NECESSARY
; RETURN +1: WAS XOFF OR XON
; 	+2: WAS NOT XOFF OR XON

TTCHXX::JE TT%PGM,TTFLGS(T2),RSKP ;IF IGNORING XOFF/XON, CONTINUE
	CAIE 1,PGMONC+1B28
	CAIN 1,PGMONC		;XON?
	IFNSK.
	  LOAD T3,TTUPC,(T2)	;YES, SEE IF PAGE UNPAUSE CHARACTER TOO
	  TMNN TTRXF,(T2)	;NOW IN COMMAND PAUSE?
	  CAIE T3,PGMONC
	  CALLRET TTXONC	;UNPAUSE COMMAND ONLY
	  CALLRET TTXONP	;PAGE UNPAUSE ONLY
	ENDIF.
	CAIE 1,PGMOFC		;XOFF?
	CAIN 1,PGMOFC+1B28
	SKIPA			;YES
	RETSKP			;NO
TTXOFC:	JN TTRXF,(T2),R		;SEE IF ALREADY STOPPED
	SETONE TTRXF,(T2)	;YES. INDICATE CTRL/S TYPED
	TMNN <TTSAL,TTHPO>,(T2)	;SPECIAL OUTPUT GOING?
	IFNSK. <
	  TDCALL D,<<FE,TTCHI3>,<CH,TTCHI3>> ;NO, STOP THE LINE
	 >,<
	  TDCALL D,<<FE,TTXON1>,<CH,TTXON1>>> ;YES, RESTART THE LINE
	RET
;TTXON - DO 'XON' - CLEAR STOP FLAG AND RESTART OUTPUT TO TERMINAL IF NECESSARY
; TTXONA - RESTART ALL CASES
; TTXONC - RESTART FROM COMMAND STOP ONLY
; TTXONP - RESTART FROM PAGE STOP ONLY
; TTXONF - RESTART ALL CASES AND FORCE XON TO FRONT END IF NECESSARY

;ACCEPTS:
;	T2/ ADDRESS OF DYNAMIC DATA

;	CALL TTXONx

;RETURNS +1: ALWAYS

;CALLED IN ANY OF THE FOLLOWING CASES:
;	CLEAR OUTPUT BUFFER
;	STPAR
;	USER TYPES XON

TTXONA:	SETZRO TTSFG,(T2)	;CLEAR CTRL/S
TTXONC:	JE TTRXF,(T2),TTXON2	;JUMP IF HOST SIMULATED XOF ONLY
	TDCALL D,<<FE,TTXON1>,<MC,MCLNON>,<CH,TTXON1>>
	SETZRO TTRXF,(T2)
TTXON2:	MOVE 3,TTOCT(2)		;GET COUNT OF CHARACTERS IN OUTPUT BUFFER
	CONSO PI,77000		;SKIP OKSKED IF NOT AT PI LEVEL 7
	NOSKD1			;NOSKED FOR STRTOU CALL
	CALLRET STRTOU		;RESTART OUTPUT

TTXONP:	SETZRO TTSFG,(T2)
	JRST TTXON2		;RESTART OUTPUT

TTXONF:	IFQN. TTRXF,(T2)	;WAS XOFF RECIEVED
	  SETONE TTXFF,(T2)	;YES, FORCE XON TO FRONT END
	ENDIF.
	JRST TTXONA		;JOIN TO RESTART ALL CASES
;CHECK FOR MCB OR LAT TTY OR CTY
;ACCEPTS:	T2/ TDB
;RETURNS:	+1  LINE IS CTY, LAT, OR MCB
;		+2  LINE IS NEITHER CTY, LAT, NOR MCB 

CTYMCB::LOAD T3,TINTL,(T2)	;GET LINE NUMBER
	CAMN T3,CTYLNO		;IS IT THE CTY?
	RET			;YES
	LOAD T3,TLTYP,(T2)	;GET LINE TYPE
	CAIE T3,TT.LAH		;A LAT HOST OR
	CAIN T3,TT.MCB		; AN MCB LINE?
	RET			;YES
	RETSKP			;NO
;Table of interrupt routines for two character escape sequences 
;indexed by TTETP field in TTY block
;ANY ROUTINE IN THIS TABLE MUST RETURN +1 ALWAYS AND PRESERVE T2
TTESC:	IFIW ! TTEUSR		;From user context - give PSI.
REPEAT 7,< IFIW ! R>		;7 slots are free


;Give PSI for the two character escape sequence (user mode)
;CALL TTEUSR with:
;	T2/ address of TTY dynamic data block
;Returns +1 always with T2 preserved
TTEUSR:	SAVEAC <T2>
        MOVEI T3,.TITCE		;Get two character escape sequence code
        CALLRET TTPSI2		;(T2,T3) Give interrupt (trashes T2)
;DO PAGE PAUSE ON COMMAND FROM USER
;DO PAGE PAUSE ON COMMAND FROM USER
;THE HEURISTICS AREN'T NEEDED UNLESS WE ARE USING A CHARACTER THAT
;ALSO HAS SOME OTHER FUNCTION (E.G. ^U).  IN THAT CASE, WE ONLY
;WANT TO DO THE PAUSE IF THE CHARACTER IS NOT PART OF REGULAR TYPEIN

TTXOFP:	LOAD T3,TTPPC,(T2)	;GET PAUSE CHARACTER
	CAIL T3,40		;A CONTROL CHAR?
	IFSKP.
	  MOVE T3,BITS(T3)	;YES, SEE WHAT KIND
	  TDNN T3,TTXOBM	;HAS SYSTEM USE IN INPUT STREAM?
	  JRST TTXFP1		;NO, EXECUTE IT
	ENDIF.
	SKIPE TTICT(T2)		;ANY TYPEAHEAD?
	RET			;YES, DO NOTHING
	LOAD T3,TWFRK,(T2)
	CAIN T3,-1		;OR FORK WAITING?
	IFSKP.
	  MOVE T3,TTOCT(T2)	;YES, SEE HOW MUCH OUTPUT QUEUED
	  CAIG T3,^D40		;LOTS?
	  RET			;NO, DON'T PAUSE
	ENDIF.
TTXFP1:	SETONE TTSFG,(T2)	;PAUSE
	RETSKP

;MASK OF CONTROL CHARACTERS WHICH HAVE DEFINED SYSTEM USE IN
;INPUT STREAM

TTXOBM:	BYTE (1)0,0,0,0,0,0,1,0,1,1,1,1,1,1,0,0,0,0,1,0,0,1,1,1,0,0,1,0,0,0,0,0
TTCHIF:	ANDI T1,177		;USE 7 BITS FOR LOCAL COMPARES
	JE TTPRM,(T2),TTCHI2	;YES. PERMANENT BLOCK?
	LOAD T3,TCJOB,(T2)	;YES. GET CONTROLLING JOB
	CAIN T3,-1		;IS THERE ONE?
	JRST TTC7N		;NO

;SEE IF ANY PAGE PAUSE OR UNPAUSE FUNCTIONS REQUESTED

TTCHI2:	JE TT%PGM,TTFLGS(T2),TTCHI1 ;BYPASS ALL THIS IF NO PAGE MODE
	JE TTNXO,(T2),TTCHI1
	LOAD T3,TTUPC,(T2)	;GET PAGE UNPAUSE CHARACTER
	CAME T1,T3		;AND UNPAUSE ON PAGE CHARACTER?
	IFSKP.
	  TMNN TTSFG,(T2)	;ALREADY PAUSING?
	  IFSKP.
	    CALL TTXONP		;YES, RESTART OUTPUT
	    RETSKP		;RETURN NOW, LOSE CHARACTER
	  ENDIF.
	  LOAD T3,TTPPC,(T2)	;NOT PAUSING NOW,
	  CAMN T1,T3		;THIS THE PAUSE CHARACTER TOO?
	  IFSKP.
	    CAIL T1,40		;NO, SEE IF KEEP IT OR FLUSH IT
	    IFSKP.
	      MOVE T3,BITS(T3)	;A CONTROL CHAR, SEE WHAT KIND
	      TDNN T3,TTXOBM	;HAS SYSTEM USE IN INPUT STREAM?
	      RETSKP		;NO, FLUSH IT
	    ENDIF.
	   ELSE.
	    CALL TTXOFP		;YES, MAYBE PAUSE NOW
	    IFSKP. <RETSKP>	;RETURN NOW IF PAUSED
	  ENDIF.
	ENDIF.
	LOAD T3,TTPPC,(T2)	;GET PAGE PAUSE CHARACTER
	CAME T1,T3		;AND PAUSE CHARACTER?
	IFSKP.
	  CALL TTXOFP		;YES, MAYBE PAUSE NOW
	  IFSKP. <RETSKP>	;DID PAUSE, LOSE CHARACTER
	ENDIF.
;LINE IS ACTIVE. IT MAY OR MAY NOT BE A CONTROLLING TERMINAL FOR
;A JOB. HOWEVER, THE JOB CANNOT DO AN ATI EXCEPT ON ITS CONTROLLING
;TERMINAL. THEREFORE, SEE IF THE JOB HAS DONE AN ATI FOR THE CHARACTER

TTCHI1:	MOVE T3,T1		;COPY CHAR
	CALL GPSICD		;GET PSI CODE FOR CHAR
	EXCH 1,3		;1/CHARACTER; 3/CODE OR -1
	JUMPL 3,TTCHI6		;-1 MEANS NO CODE
	MOVE Q1,BITS(3)		;BIT FOR THIS CODE
	TDNE Q1,TTPSI(2)	;CODE ENABLED?
	JRST TTCH11		;YES
	SKIPE CTRLOF		;NEW CTRL-O HANDLING?
	CAIE T1,FLOCHR		;AND A CTRL-O?
	JRST TTCHI6		;NO
	; ..
;WE HAVE A ^O AND WE WANT MONITOR HANDLING OF IT.  ^O IS A TOGGLE, SO
;WE DO SOMETHING DIFFERENT DEPENDING ON ITS CURRENT STATE.

	; ..
	CALL CKPHYD		;PTY?
	 JRST TTCHI6		;YES, DO NOTHING
	CALL [	SAVEAC <T1>	;YES
		CALLRET TTXONA]	;CLEAR POSSIBLE XOFF
	TMNN TTFLO,(T2)		;ALREADY ON?
	IFSKP. <
	  CALL CLOFLG		;YES, DO MARKER
	  RETSKP>
	MOVE T1,[670000,,[BYTE (9)"[","^","O",".",".",".",.CHDEL]]
	MOVEM T1,TTSAL2(T2)	;SEND INDICATION (WITH FILLS ON CR AND LF)
	SETONE TTHPO,(T2)	;NOTE HP OUTPUT QUEUED
	SETONE TTFLO,(T2)	;FLUSH OUTPUT
	LOAD T3,TWFRK,(T2)	;SEE IF A FORK WAITING
	CAIE T3,-1
	CALL CLOFLG		;YES, PUT MARKER THROUGH
	RETSKP
;TERMINAL NOT IN PAGE MODE OR THIS WAS NOT XON OR XOFF
;IF TERMINAL DATA MODE IS BINARY, GO STORE CHARACTER IN LINE BUFFER
;WITHOUT TRANSLATION OR ECHOING

TTCHI6:	AOS NTTYIN		;COUNT INPUT
	LOAD 3,TYLMD,(2)	;CHECK MODE NOW IN FORCE
	CAIE 3,.TTBIN		;BINARY?
	JRST TTCHI4		;NO.
TTMCI1::LOAD 3,TIMAX,(2)	;YES. GET CAPACITY OF INPUT BUFFER
	CAMLE 3,TTICT(2)	;ROOM FOR CHAR IN INPUT BUFFER?
	JRST TTCHI9		;YES. GO PUT IT IN
	RET			;NO. LOSE CHARACTER

;SOME TRANSLATION (OUTPUT OR ECHOING OR BOTH) IS REQUIRED BY TERMINAL
;DATA MODE. SEE IF ECHOING IS REQUIRED

TTCHI4: IFE. 1			;[8977]Is this a NUL?
	  TMNN TTNUL,(2)	;[8977]Yes, are NULs being flushed?
	  RETSKP		;[8977]Yes, so flush this one
	ENDIF.			;[8977] 
	LOAD 3,TIMAX,(2)	;CAPACITY OF INPUT BUFFERS
	CAMG 3,TTICT(2)		;FULL?
	JRST TTCH12		;YES, ECHO BELL
	MOVE 3,TTFLGS(2)
	TRNE 3,TT%DUM		;REGULAR FDX LINE?
	JRST TTCHI7		;HDX - 'ECHO' IMMED
	TRNN 3,TT%ECO		;ECHOS ON?
	JRST TTCHI9		;NO
	TRNE 3,TT%ECM		;STANDARD ECHO MODE?
	JRST TTCHI7		;NO, IMMEDIATE ALWAYS
	LOAD 4,TWFRK,(2)	;GET WAITING FORK IF ANY
	CAIN 4,-1		;IS THERE A WAITING FORK?
	JRST TTCHI9		;NO. DON'T ECHO NOW
	; ..
;EITHER IMMEDIATE ECHOING IS REQUIRED OR DEFERRED IS REQUIRED AND
;A FORK IS IN INPUT WAIT ON THIS TERMINAL. ECHO THE CHARACTER NOW
;AND SET TTXECO WITH THE CHARACTER IN TTCHIC. THIS WILL BE STORED
;IN THE LINE BUFFER SO THAT TCI WILL NOT ECHO IT AGAIN

	; ..
TTCHI7:	CALL CLOFLG		;CLEAR CTRL-O FLAG IF NECESSARY
	MOVE T3,TTFLGS(T2)	;GET FLAGS FOR TTRAIS
	SETOM IMECHF		;FLAG ECHO CHARACTER FOR TCOUT
	CAIE T1,.CHCRT		;CR?
	JRST TTCH8A		;NO CHECK RAISES
	SETZM TCOERR		;YES, INIT ERROR INDICATOR
	CALL TCOE		;YES, ECHO CR-LF
	LOAD T1,TTDUM,(T2)	;GET THE DUPLEX MODE
	CAIE T1,.TTHDX		;HDX?
	CAIN T1,.TTLDX		;...
	JRST [ SETONE TTFWK,(T2) ;MAYBE A APPLICATION BLOCK LINE (X29)
		JRST .+1]	;SO WAKE IT
	SKIPA T1,[.CHLFD]	;ECHO THE LINE FEED
TTCH8A:	CALL TTRAIS		;RAISE FOR ECHO IF NECESSARY
TTCHI8:	SETZM TCOERR		;INIT ERROR INDICATOR
	SETZM TTCHFL		;INITIALIZE ECHO INDICATOR
	CALL TCOE		;ECHO VIA NORMAL OUTPUT STREAM
	SKIPE TCOERR		;DID TCOUT FAIL?
	 JRST [	SETZM IMECHF	;FAILED TO ECHO. RESET IMMEDIATE ECHO FLAG
		SETOM TTCHFL	;INDICATE CHARACTER NOT ECHOED
		JRST TTCHI9]	;GO STORE CHARACTER WITHOUT MARKING IT ECHOED
	MOVEI T4,TTXECO		;CHARACTER WAS ECHOED. INDICATE IT
	IORM T4,TTCHIC		; SO THAT TCI WON'T ECHO IT LATER
	SETZM IMECHF		;RESET IMMEDIATE ECHO INDICATOR
	; ..
;TTCHI..

;HERE IF THE CHARACTER IS NOT AN INTERRUPT CHARACTER, OR THE
;JOB HAS ENABLED ONLY FOR DEFERRED INTERRUPT ON THE CHARACTER
;IF ECHOING WAS REQUIRED, IT HAS BEEN DONE
;GET INPUT BUFFER IF NEEDED; PUT CHAR IN BUFFER

;	2/ ADDRESS OF DYNAMIC DATA

	;..
TTCHI9:	SKIPN 3,TTIIN(2)	;INPUT BUFFERS EXIST?
	JRST [	LOAD 3,TTNIN,(2);NO, GET NUMBER TO ASSIGN
		CALL TTGTBF	;ASSIGN THEM
		 JRST TTCH12	;NO BUFFERS, DING
		MOVEM 3,TTIOUT(2) ;SAVE BYTE POINTER FOR REMOVING CHARACTERS
		JRST .+1]
	TDNN 3,WRPMSK
	JRST [	LDB 1,[POINT 6,3,5] ;LOOK AT P,S FIELD OF BYTE POINTER
		CAIE 1,73	;POINTING TO LAST BYTE?
		JRST .+1	;NO.
		HRRZ T4,T3	;YES. GET ADDRESS OF CURRENT WORD
		HRR T3,1-TTSIZ(T4) ;POINT TO NEXT BUFFER IN CHAIN
		JRST .+1]
	MOVE T4,TTCHIC		;GET INPUT CHARACTER
	IDPB T4,3		;STORE IN INPUT LINE BUFFER
	MOVEM 3,TTIIN(2)	;SAVE UPDATED POINTER FOR ADDING TO BUFFER
	AOS 3,TTICT(2)		;INCREMENT COUNT OF CHARACTERS

;IF INPUT BUFFER IS FULL, SEND XOFF TO TERMINAL

	LOAD D,TIMAX,(B)	;GET CAPACITY OF BUFFERS
	CAIL C,-MINICT(D)
	JRST [	PUSH P,B	;SAVE TTY
		DYNST
		TDCALL S,<<FE,SNDXO2>,<CH,SNDXO2>> ;SEND XOFF
		POP P,B		;RESTORE LINE
		JRST .+1]
	TMNE TTNUS,(T2)		;NET USER?
	JRST [	CALL REQNS	;YES, QUEUE A SEND
		RETSKP]		;AND DONE

;IF THIS STORE MADE THE BUFFER GO NON-EMPTY, AND JOB HAS ENABLED FOR
;INTERRUPTS ON THAT CONDITION, ISSUE THE INTERRUPT

	CAIN 3,1		;JUST BECAME NON-0?
	CALL TTCH22
	;..
;TTCHI..

;IF A FORK IS IN INPUT WAIT ON THIS TERMINAL, WAKE IT UP IF EITHER
;	1. THE TERMINAL DATA MODE IS BINARY
;	2. THE INPUT BUFFER IS FULL
;	3. THE CHARACTER IS IN A WAKEUP CLASS SPECIFIED BY THE JOB

	;..
	LOAD 3,TWFRK,(2)	;IF NO FORK WAITING FOR THIS LINE,
	CAIN 3,-1
	JRST TTCH1X		; THEN SKIP WAKEUP CHECKS
	LOAD 3,TYLMD,(2)	;GET TERMINAL DATA MODE FOR LAST CHARACTER
	CAIE 3,.TTBIN		;WAKE ALWAYS IF BINARY
	IFSKP.
	  CALL TTFWAK		;WAKE LISTENING PROCESS
	  JRST TTCH1X		;SUCCESS
	ENDIF.
	LOAD 3,TIMAX,(2)	;CAPACITY OF INPUT BUFFERING
	SUBI 3,MINCT1		;LESS AN ARBITRARY AMOUNT
	CAMLE 3,TTICT(2)	;BUFFER NOW THAT FULL?
	IFSKP.
	  SETONE TTFWK,(2)	;YES. FORCE WAKEUP OF WAITING FORK
	ENDIF.
	CAIN T1,.CHCRT		;IS THIS A CARRIAGE RETURN
	MOVEI T1,.CHLFD		;YES-FORCE IT TO BE ALINE FEED
	SKIPL TTCHFL		;DID WE FAIL TO ECHO CHARACTER?
	CALL TTWAKE		;DETERMINE IF CHARACTER IS IN WAKE-UP CLASS
	IFNSK.
	  CALL TTFWAK		;YES, FORCE WAKEUP
	  AOS TTWAKN		;COUNT FOR STATISTICS
	  JRST TTCH1X		;DONE
	ENDIF.
	LOAD FX,TWFRK,(2)	;GET WAITING FORK IF ANY
	CAIN FX,-1		;IS THERE ONE?
	JRST TTCH1X		;NO, JUST RETURN
	JE TTFWK,(2),TTCH1X	;YES. IS THE WAKEUP BIT SET?
	ANDI FX,7777		;YES, FLUSH FLAGS
	CALL TTUBLK		;MAKE THE FORK RUN TO EMPTY BUFFER
TTCH1X:	RETSKP
;TTCHI..

;HERE WHEN RECEIVED TERMINAL INTERRUPT CHARACTER.
;CHECK WHETHER DEFERRED OR IMMEDIATE, INITIATE INTERRUPT IF NECESSARY.

;	T1/ ORIGINAL CHARACTER, 7 BITS
;	T2/ADDRESS OF DYNAMIC DATA
;	T3/THE CODE
;	Q1/ BIT FOR CONTROL CODE FOR THIS CHARACTER

TTCH11::TDNN Q1,TTDPSI(2)	;DEFERRED CHARACTER?
	JRST TCHI1		;NO
	LDB 4,TTIIN(2)		;GET LAST INPUT CHAR
	CAMN T4,TTCHIC		;LAST CHAR SAME AS THIS ONE?
	JRST TTCHI5		;YES, MAKE IMMEDIATE

;HANDLE DEFERRED INTERRUPT

	PUSH P,1
	CALL TTFWAK		;FORCE WAKEUP SO PGM CAN SEE INT
	POP P,1
	LOAD 3,TIMAX,(2)	;MUST PUT DEFERRED CHAR IN BUFFER
	ADDI 3,1		;1 RESERVED FOR INT CHAR
	CAMG 3,TTICT(2)		;IS ROOM?
	JRST [	DPB 1,TTIIN(2)	;NO, SMASH CHAR ON TOP OF LAST ONE
		JRST TCHIX]	;RETURN
	JRST TTCHI9		;YES. PUT IN BUFFER W NO ECHOS

;DEFERRED CHARACTER TWICE IN A ROW

TTCHI5:	PUSH P,3		;SAVE CODE
	CALL TTCIBF		;CLEAR INPUT BUFFER ON DOUBLE INT
	POP P,3			;RESTORE CODE
TCHI1:	CALL TTPSI2		;GO ISSUE THE INTERRUPT
TCHIX:	RETSKP

;TTPSI2 - ISSUE INTERRUPT TO PROCESS THAT HAS ENABLED FOR IT
;VIA ATI

;ACCEPTS:
;	T2/ADDRESS OF DYNAMIC DATA
;	T3/CODE

;	CALL TTPSI2

;RETURNS +1: ALWAYS

;NOTE: TTPSRQ CLOBBERS T2

TTPSI2::CALL TTCLPS		;CLEAR PAGE COUNTER
	DYNST			;T2/ INTERNAL LINE NUMBER
	CALL TTPSRQ		;REQUEST INTERRUPT FROM PSI SYSTEM
	AOS TTINTS		;COUNT INTERRUPTS
	RET			;AND DONE
;INPUT BUFFER GETTING FULL. SEND BELL AND LOSE CHARACTER

TTCH12:	LOAD T3,TLTYP,(T2)	;CHECK LINE TYPE
	CAIN T3,TT.PTY		;PTY?
	RET			;YES
	MOVEI T1,"G"-100	;NO, ECHO BELL
	CALLRET SCDTCO

;DO INPUT INTERRUPT IF ENABLED

TTCH22:	LOAD T4,TTPSFK,(T2)	;CHECK FOR FORK
	CAIN T4,-1
	JRST TTCH23		;IGNORE IF NOT SET
	LOAD T4,TTIPSI,(T2)	;CHECK FOR NON CONTRL TERM PSI
	CAIL T4,^D36		;CHECKLEGAL
	JRST TTCH23		;NO TRY FOR CONTROL TERMINAL
	SAVET			;SAVE TEMPS
	MOVE T1,T4		;GET PSI
	LOAD T2,TTPSFK,(T2)	;GET FORK
	CALLRET PSIRQ		;DO REQUEST

TTCH23:	MOVX 4,1B<.TICTI>
	TDNN 4,TTPSI(2)		;YES, SEE IF INPUT INTERRUPT WANTED
	RET			;NO
	MOVX 3,.TICTI		;YES, REQUEST IT
	SAVET			;SAVE ACS
	DYNST			;T2/ INTERNAL LINE NUMBER
	CALLRET TTPSRQ		;REQUEST INTERRUPT

;NOTE: DOESN'T SET OR TEST TCOERR. IGNORES FAILURE TO SEND BELL
;TTCHI..

;RECEIVED CHARACTER ON LINE THAT IS NOT ASSIGNED A FULL-LENGTH
;DYNAMIC BLOCK.

;	T1/ CHARACTER
;	T2/-1 IF LINE IS BECOMING ASSIGNED
;		OR
;	0 IF NOT AT ALL ASSIGNED
;		OR
;	POSITIVE ADDRESS OF SHORT OR TTEMES BLOCK

TTC7N:	ANDI T1,177
	CAIN T1,.CHNUL		;FLUSH NULLS
	JRST TTCHN1		;AND CHECK FOR NOISY LINE
	MOVE T4,TTCHSV		;GET LINE NUMBER
	JN TTIGI,(T4),TTCHN1	;RETURN IF IGNORING CHARACTERS ON THIS LINE
	CAIE T1,.CHCRT		;CR OR LF?
	CAIN T1,.CHLFD
	JRST TTCH71		;YES, TRY TO CREATE JOB
	CAIN T1,.CHCNC		;CONTROL-C?
	JRST TTCH71		;YES.
	JUMPL T2,R		;IF BECOMING ACTIVE, IGNORE
	JUMPE T2,TTCH73		;IF INACTIVE, SEND BELL
	JE TTPRM,(T2),TTCH73	;IF TEMPORARILY ACTIVE AND NOT PERMANENT, SEND BELL
	JN TTBAC,(T2),R		;IF PERMANENT AND BECOMING ACTIVE, IGNORE

TTCH73:	HRROI T1,[BYTE(7) .CHBEL]  ;SEND A BELL
	MOVE T2,TTCHSV		;T2/ INTERNAL LINE NUMBER
	CALL TTEMES		;GO SEND A BELL AND LOSE CHARACTER

TTCHN1:	MOVE T2,TTCHSV		;T2/ INTERNAL LINE NUMBER
	TDCALL S,<<FE,TTCHNL>>	;NOISY LINE CHECK
	RET
;A CONTROL/C WAS RECEIVED OR CARRIER CAME ON FOR A REMOTE LINE
;IF LINE IS TOTALLY INACTIVE, GO CREATE A JOB ON IT
;IF LINE IS BECOMING ACTIVE, IGNORE THE CHARACTER
;IF LINE HAS SHORT OR MESSAGE BLOCK, IGNORE THE CHARACTER

TTCH71:	JUMPE T2,TTCH75		;ACCEPT IF NOT AT ALL ACTIVE
	JUMPL T2,R		;IGNORE IF BECOMING ACTIVE
	JE TTPRM,(T2),R		;IF NOT PERMANENT, ASSUME BLOCK WILL GO AWAY
	JN TTBAC,(T2),R		;PERMANENT. IGNORE IF BECOMING ACTIVE

;LINE  HAS NO DYMAMIC DATA OR IT HAS A PERMANENT BLOCK AND 1) HAS NO
;CONTROLLING JOB AND 2) IS NOT BECOMING ACTIVE. CREATE A JOB ON IT IF
;LOGINS ARE ALLOWED

TTCH75:	MOVE T1,FACTSW		;SEE WHAT LOGINS ARE ALLOWED
	MOVE T2,TTCHSV		;RESTORE LINE NUMBER
TTC7SJ:	CAMN 2,CTYLNO		;CTY?
	JRST [	TXNE T1,SF%CTY	;YES, CTY LOGIN ALLOWED?
		JRST TTC7SK	;YES, GO LOGIN
		HRROI 1,[ASCIZ/
?LOGGING IN ON THE CTY IS CURRENTLY DISALLOWED.
/]
		CALLRET TTEMSS] ;NO LOGIN ALLOWED ON CTY
	TDCALL S,<<FE,RSKP>,<PT,TTC7S2>,<TV,TTC7SN>,<MC,TTC7MC>,<CH,TTC7MC>,<LH,TTC7LT>>;
	 JRST [	JUMPL T1,TTC7SK	;IF NEG, GO START A JOB
		RET]		;ELSE FAIL

;LINE IS ON THE FRONT END OR THE DC10. SEE IF LINE IS LOCAL OR REMOTE

TTC7S1:	JN TTFEM,(T2),TTCHS3	;IF REMOTE, GO CHECK REMOTE LOGINS
	TXNE T1,SF%LCL		;LOCAL LOGINS ALLOWED?
	JRST TTC7SK		;YES. GO CREATE JOB
	HRROI 1,[ASCIZ/
?LOGGING IN ON LOCAL TERMINALS IS CURRENTLY DISALLOWED.
/]
	CALLRET TTEMSS		;LOCAL LOGINS NOT ALLOWED. SEND MESSAGE
;LINE IS DECNET NVT

TTC7MC:	TXNE T1,SF%MCB		;DECNET LOGINS ALLOWED?
	JRST RTRUE		;YES, GO CREATE JOB
	HRROI T1,[ASCIZ/
?LOGGING IN ON DECNET TERMINALS IS CURRENTLY DISALLOWED.
/]
	CALL TTEMSS		;PRINT MESSAGE
	JRST RFALSE		;DISALLOW LOGIN

;LINE IS REMOTE

TTCHS3:	TXNE 1,SF%RMT		;...
	JRST TTC7SK		;YES. GO CREATE JOB
	SETONE TTFSP,(T2)
	HRROI 1,[ASCIZ/
?LOGGING IN ON DATASETS IS CURRENTLY DISALLOWED.
/]
	CALLRET TTEMSS		;REMOTE LOGINS NOT ALLOWED, SEND MESSAGE

;LAT terminals

TTC7LT:	TXNE 1,SF%LAT		;[7328]Logins allowed?
	JRST RTRUE		;YES, GO CREATE JOB
	HRROI T1,[ASCIZ/
?LOGGING IN ON LAT TERMINALS IS CURRENTLY DISALLOWED.
/]
	CALL TTEMSS		;PRINT MESSAGE
	JRST RFALSE		;DISALLOW LOGIN

;LOGINS ARE ALLOWED.

TTC7SK:	MOVEI 1,JOBSRT		;REQUEST SCHEDULER- START JOB
	HRLI 1,0(2)		;ON SPECIFIED TTY LINE
	SKIPLE T3,TTACTL(T2)
	JRST [	JE TTPRM,(T3),.+1
		SETONE TTBAC,(T3)
		JRST TTC7S3]
	SETOM TTACTL(T2)	;INDICATE LINE BECOMING ACTIVE
TTC7S3:	CALL SCDRQ7
	RETSKP

	ENDSV.			;END STKVAR
;Handle the two character escape sequence being enabled
;CALL TTTWES with 
;	T1/ character
;	T2/ address of dynamic data
;Returns +1 if character doesn't go into line buffer
;Returns +2 if character goes into line buffer with:
;	T1/ character
;	T2/ address of dynamic data
;Uses T3 & T4
TTTWES:	MOVE T3,T1		;Make it 
	ANDI T3,177		; ASCII
	OPSTR <SKIPE>,TTFLA,(T2) ;Seen first character ?
	IFSKP.
	  OPSTR <CAME T3,>,TTCH1,(T2) ;No. Is this the first character ?
	  RETSKP     		;No. Use the character.
	  SETONE TTFLA,(T2) 	;Yes. Flag it
	  RET       		; and drop this character
	ENDIF.
	SETZRO TTFLA,(T2) 	;We saw the first character last time.
	LOAD T4,TTETP,(T2)	;Get the interrupt type
	OPSTR <CAMN T3,>,TTCH2,(T2) ;Is this the second character ?
	CALLRET @TTESC(T4)	;(T2/T2) Yes. Give "interrupt", drop character
	LOAD T4,TTCH1,(T2) 	;Is this
	CAMN T3,T4       	; the first character again ?
	RETSKP      		;Yes. Just continue. (This is the quote)
;Here when must call TTCHI recursively.
	STKVAR <CHAR,DYNAM>	;No. Save
	MOVEM T1,CHAR		; this character.
	MOVEM T2,DYNAM		;Save TTY block address
	MOVE T1,T4		;Get the first character of the sequence
	MOVEM T1,TTCHIC		; put it here, too.
	MOVX T3,1B<.TITCE>	;Clear two character flag (to avoid
	ANDCAM T3,TTPSI(T2)	; infinite loop)
	CALL TTCHID		;(T1,T2) Pass the first character 
	 NOP
	MOVE T2,DYNAM		;Get TTY block address
	MOVX T3,1B<.TITCE>	;Set the two character 
	IORM T3,TTPSI(T2)	; flag
	MOVE T1,CHAR        	;Get the character we were working on
	MOVEM T1,TTCHIC		; put it here, too.
      	RETSKP      		; and use it
	ENDSV.

TTTWE1:	SAVEAC <T2,Q1,FX>
       	STKVAR <TTCHSV,TTCHFL>	;MUST COME AFTER SAVELN
	JRST TTCHD2		;(T1,T2/T1,T2) and put it in the line buffer.
	ENDSV.			;End STKVAR
; TTWAKE - DETERMINE IF CHARACTER IS IN WAKE-UP CLASS

;ACCEPTS:
;	T1/ 7-BIT ASCII CHARATER
;	T2/ ADDRESS OF DYNAMIC DATA

;RETUNS:	+1, CHARACTER BELONGS TO A WAKE-UP CLASS
;		+2, CHARACTER NOT IN ANY WAKE-UP CLASS

TTWAKE:	LOAD T3,TTFCNT,(T2)	;DECREMENT FIELD WIDTH COUNT
	JUMPLE T3,TTMASK	;JUMP IF FIELD WIDTH DISABLED (=0)
	SOS T3			;ENABLED - DECREMENT THE COUNT
	STOR T3,TTFCNT,(T2)	;SAVE NEW VALUE
	SKIPN T3		;SKIP IF COUNT NOT EXHAUSTED
	RET			;COUNT EXHAUSTED - WAKE PROCESS

;HERE TO CHECK WAKE-UP MASK (FIELD WIDTH DISABLED OR NOT EXHAUSTED)

TTMASK:	MOVE T3,T1		;MOVE THE ASCII CHARACTER
	IDIVI T3,^D32		;COMPUTES WHICH WORD MASK BIT IS IN
	MOVE T4,BITS(T4)	;GET THE BIT MASK FOR TESTING
	ADD T3,T2		;BUMP INTO PROPER WORD OF MASK
	TDNE T4,TTCHR1(T3)	;SKIP IF NO WAKE-UP ON THIS CHARACTER
	RET			;PROCESS SHOULD BE AWAKENED
	CAIE T1,.CHLFD		;IS THIS A LF ON A PTY?
	RETSKP			;NO, NO WAKEUP
	LOAD T3,TLTYP,(T2)
	CAIN T3,TT.PTY		;PTY?
	RET			;YES, WAKEUP
	RETSKP			;PROCESS SHOULD NOT BE AWAKENED
	SUBTTL TTEMES (Send Short Message)

;TTEMES - SEND SHORT MESSAGE FROM SCHEDULER

;ACCEPTS:
;	T1/ BYTE POINTER TO STRING TO BE OUTPUT
;	T2/ LINE NUMBER

;	CALL TTEMES

;RETURNS +1: ALWAYS

;CALLED AT SCHEDULER LEVEL TO SEND A SHORT MESSAGE TO A LINE
;IF LINE IS ACTIVE, APPENDS CHARACTERS TO OUTPUT BUFFER. IF NOT
;ACTIVE, CREATES A MESSAGE-LENGTH DYNAMIC BLOCK FOR THE LINE

;TTEMSS - ENTRY POINT TO CLEAR OUTPUT BUFFER BEFORE OUTPUTTING

TTEMSS:	PUSH P,A		;SAVE STRING POINTER
	CALL TTCOB1		;CLEAR CURRENT GARABGE OUT
	POP P,A			;AND GO SEND THE MESSAGE

;TTEMES - NORMAL ENTRY POINT

TTEMES::EA.ENT
	SAVELN			;PRESERVE LINE NUMBER
	STKVAR <TTEMBP,TTEMAC,TTEMLN>
	MOVEM T1,TTEMBP		;SAVE BYTE POINTER TO STRING
	MOVEM T2,TTEMLN		;SAVE LINE NUMBER
	MOVEM Q1,TTEMAC		;SAVE WORK REGISTER
	CALL STADYN		;GET POINTER TO DYNAMIC DATA
	 SKIPA			;NOT FULLY ACTIVE
	JRST TTEME2		;FULLY ACTIVE. USE REGULAR BUFFERS
	JUMPL T2,TTEME3		;IF BECOMING ACTIVE, CAN'T SEND MESSAGE
	JUMPE T2,TTEME1		;IF INACTIVE, GO GET A BLOCK
	JN TTSHT,(T2),TTEME3	;IF SHORT BLOCK, CAN'T SEND MESSAGE
	JRST TTEME2		;HAS MESSAGE BLOCK. APPEND STRING
TTEME1:	MOVE T2,TTEMLN		;T2/LINE NUMBER
	CALL ASGMSG		;GET A BLOCK
	 JRST TTEME3		;COULDN'T GET ONE
	MOVE T2,T1		;GET ADDRESS OF DYNAMIC DATA
;T2/ ADDRESS OF DYNAMIC DATA FOR FULL-LENGTH OR MESSAGE BLOCK

TTEME2:
	MOVE T1,TTEMBP		;RESTORE BYTE POINTER
	TLC 1,-1
	TLCN 1,-1		;LH = 777777 ?
	HRLI 1,440700		;YES, MAKE BYTE PTR
	MOVEM T1,TTEMBP		;SAVE BYTE POINTER
TTEME4:	ILDB 1,TTEMBP		;GET CHARACTER
	JUMPE 1,TTEME3		;NULL TERMINATES.
	MOVEI Q1,0(1)		;SAVE THE BYTE
	CALL SCDTCO		;OUTPUT IT
	CAIE Q1,.CHCRT		;A CARRIAGE RETURN?
	CAIN Q1,.CHLFD		;OR A LF?
	SKIPA			;GO FILL
	JRST TTEME4		;NO. GET NEXT CHARACTER
	MOVEI Q1,3		;NUMBER OF FILLS TO DO
TTEME5:	MOVEI A,TTFILL		;THE FILL CHARACTER
	CALL SCDTCO		;OUTPUT IT
	SOJGE Q1,TTEME5		;DO ALL FILLS
	JRST TTEME4		;GO DO NEXT BYTE

TTEME3:	MOVE T1,TTEMBP		;RESTORE BYTE POINTER
	MOVE Q1,TTEMAC		;RESTORE WORK REGISTER
	CALLRET TTYQOC		;GET OUTPUT STARTED

	ENDSV.			;END STKVAR
	SUBTTL BIGSTO (Store Char In TTBBUF)

;BIGSTO - ROUTINE TO STORE DATA IN TTBBUF
;DATA CONSISTS OF STATUS BITS OR DLSRCF+CHARACTER IN 8 BITS
;CALLED AT INTERRUPT LEVEL OR WITH TELETYPE INTERRUPTS DISABLED
;SOMETIMES CALLED IN SCHEDULER CONTEXT

;ACCEPTS:
;	T1/ (INTERNAL LINE NUMBER,,DATA)
;	T2/ INTERNAL LINE NUMBER (MUST BE PHYSICAL LINE)

;RETURNS +1: ALWAYS

BIGSTO::MOVEI 3,TTBSIZ		;GET SIZE OF TTBBUF
	CAMLE 3,TTBIGC		;HAS TTBBUF OVERFLOWED?
	IFSKP.
	  BUG.(CHK,TTYBBO,TTYSRV,HARD,<TTYSRV - Big buffer overflow>,,<

Cause:	The buffer for incoming TTY characters was full.  The character was
	discarded and the line XOFFed.

Action:	Some device connected to the system is filling the buffer for incoming
	terminal characters.  The device is probably not responding quickly
	enough to XON/XOFF commands.
>,,<DB%NND>)			;[7.1210] 
	  RET
	ENDIF.
	TDCALL S,<<FE,BIGST2>>
	 RET			;FLUSH CHAR
	AOS 3,TTBIGI		;NO. POINT TO NEXT WORD IN TTBBUF
	CAIN 3,TTBSIZ		;AT END OF TTBBUF?
	SETZB 3,TTBIGI		;YES. WRAPAROUND
	MOVEM 1,TTBBUF(3)	;STORE CURRENT DATA
	AOS TTBIGC		;COUNT CONTENTS
	RET
;INPUT DONE AND CHARACTER PRESENT (CALLED FROM INTERRUPT ROUTINES)
; T1/ CHARACTER
; T2/ LINE NUMBER
;	CALL TTIDON
; RETURN +1 ALWAYS

TTIDON::CAIE T1,PGMOFC+1B28	;PARITY AND XOFF
	CAIN T1,PGMOFC		;CHECK FOR XOFF
	CALL TTYSTC		;YES CHECK ON WHAT TO DO
TTICNT::TRO T1,DLSRCF		;INDICATE RECEIVED CHARACTER
	HRL T1,T2		;COMBINE LINE NUMBER WITH CHAR
	CALLRET BIGSTO		;PUT IN BUG BUFFER

TTYSTC:	SAVEAC <T1,T2>
	CALL STADYN		;GET DYN ADDRESS
	 RET			;INACTIVE
	JE TT%PGM,TTFLGS(T2),R	;IF NO XOFF, GO AWAY
	CALLRET TTXOFC		;DO XOFF ON COMMAND
	SUBTTL TTSNDO (Non-Interrupt Character Send)

;TTSND0 - SEND ROUTINE CALLABLE FROM NON-PI CONTEXT

;ACCEPTS:
;	T2/ INTERNAL LINE NUMBER

;	CALL TTSN10

;RETURNS +1: ALWAYS

;USE THIS ENTRY POINT IF ONLY LINE NUMBER IS AVAILABLE

TTSN10::NOSKD1
	CALL STADYN		;POINT TO DYNAMIC DATA
	 JRST [	JUMPG T2,.+1	;IF SEND-ALL OR MESSAGE,PROCEED
		OKSKD1		;NOT ACTIVE
		RET]
	JRST TTSN11

;TTSND0 - MAIN ENTRY POINT

;ACCEPTS:
;	T2/ ADDRESS OF DYNAMIC DATA

;	CALL TTSND0

;	RETURNS +1: ALWAYS

;STARTS OUTPUT TO THE SPECIFIED LINE

TTSND0:	NOSKD1
TTSN11:	CALLRET STRTOU		;QUEUE START - INCLUDES OKSKD1
;STRTOU - START OUTPUT TO A LINE

;ACCEPTS:
;	T2/ ADDRESS OF DYNAMIC BLOCK
;	T3/ COUNT OF CHARACTERS IN OUTPUT BUFFER

;	CALL STRTOU
;	MUST BE NOSKD1!

;RETURNS +1: ALWAYS OKSKD1

STRTOU:	JN TTOTP,(T2),STRT11	;IF ACTIVE, NO NEED TO START IT
	TDCALL D,<<PT,STRTO2>,<MC,MCSTRO>,<TV,TVTCSO>,<LH,LTSTRO>,<CH,CTHSTO>>
	 TRNA			;NORMAL START
	JRST STRT11		;NOTHING ELSE TO DO
	SAVELN
	DYNST			;GET LINE NUMBER
	IDIVI T2,^D36		;COMPUTE BIT POSITION IN QUEUE
	MOVE T3,BITS(T3)
	IORM T3,TTSOQ(T2)	;REQUEST START NEXT BIGBUF CYCLE
STRT11:	CONSO PI,77000		;SKIP OKSKED IF NOT AT PI LEVEL 7
       	OKSKD1			;ALLOW SHCEDULING NOW
	RET
;ROUTINE TO START OUTPUT ON QUEUED LINES
;CALLED ONLY ON SCHED SHORT CYCLE AT TTCH7X

TTYQOC:	SAVEAC <Q1,Q2>
	MOVSI Q1,-NTSQWD	;SETUP NUMBER OF WORDS TO CHECK
TTYQO5:	SKIPE T1,TTSOQ(Q1)	;ANY QUEUED LINES IN THIS WORD?
TTYQO4:	JFFO T1,TTYQO2		;YES, FIND ONE
	AOBJN Q1,TTYQO5		;DO ALL WORDS
	RET

TTYQO2:	MOVE Q2,BITS(T2)	;CLEAR REQUEST THIS LINE
	ANDCAM Q2,TTSOQ(Q1)	;CLEAR REQUEST BIT
	HRRZ T3,Q1		;COMPUTE LINE NUMBER
	IMULI T3,^D36
	ADD T2,T3
	CALL STADY		;GET DATA ADDRESS
	IFSKP. <
	  PUSH P,T2		;SAVE T2 ALSO
	  CALL STRTTO		;START PHYSICAL DEVICE
	  POP P,T2>		;RESTORE T2
	MOVN T1,Q2
	ANDCA T1,TTSOQ(Q1)	;LOOK AT REST OF WORD ONLY
	JRST TTYQO4		;CONTINUE

;START PHYSICAL TTY OUTPUT DEVICE
; T2/ DYNAMIC PTR
; RETURN +1 ALWAYS

STRTTO:	SAVEAC <Q1,Q2>		;SOME CRETIN KNOWN TO BE CLOBBERING HEREIN
	TDCALL D,<<FE,FESTRO>,<MC,MCSTRO>,<PT,PTYCTM>,<CH,CTHSTO>,<LH,LTSTRO>>;
	 RET
	RET

;CONSTANTS

WRPMSK::TTSIZ-1			;MASK FOR WRAPAROUND OF CHAR POINTER
	SUBTTL TTSND (Send Character To Line)

;ACCEPTS:
;	T2/ ADDRESS OF DYNAMIC DATA
;	CALL TTSND
; RETURN +1: NO OUTPUT AVAILABLE
;	+2: T1/ CHARACTER FOR OUTPUT

;CALLED AT INTERRUPT LEVEL
;OR IN SCHEDULER CONTEXT WITH TELETYPE INTERRUPTS DISABLED
;OR IN PROCESS CONTEXT WITH TELETYPE INTERRUPTS DISABLED

;SEND CHARACTER TO TTY LINE,
;FROM OUTPUT BUFFER IF NOT EMPTY; OTHERWISE
;CLEAR OUTPUT-ACTIVE FLAG

TTSND::
TTSND6:	JN <TTSFG,TTRXF>,(T2),[
		SETZRO TTOTP,(T2) ;IF CTRL/S TYPED, CLEAR OUTPUT ACTIVE
		RET]
	TMNN TTHPO,(T2)		;HP MESSAGE QUEUED?
	IFSKP.
	  ILDB T1,TTSAL2(T2)	;YES, GET NEXT CHAR
	  CAIE T1,.CHDEL	;END OF STRING?
	  RETSKP		;NO, RETURN CHARACTER
	  SETZRO TTHPO,(T2)	;RUBOUT MARKS END OF STRING, CLEAR
	ENDIF.
	TMNN TTSAL,(T2)		;SENDALL?
	IFSKP.
	  OPSTR <SKIPG>,TSALC,(T2) ;ANY MORE CHARACTERS TO SEND?
	  IFSKP.
	    ILDB T1,TTSAL2(T2)	;GET NEXT CHARACTER
	    DECR TSALC,(T2)	;DECREMENT COUNT OF REMAINING CHARACTERS
	    TRNE 1,200		;THIS CHARACTER HAVE PARITY?
	    CALL SPARTY		;SET PARITY BIT APPROPRIATELY FOR LINE TYPE
	    RETSKP		;RETURN THE CHAR
	  ENDIF.
	  CALL CLRSAL		;CLEAR SENDALL FOR LINE
	ENDIF.
	CALL GTOCHR		;GET CHAR FROM OUTBUF
	 RET			;EMPTY
	CAIE T1,TTOBIN		;Got a character - was it binary mode marker?
	CAIN T1,TTOASC		;or ascii mode marker?
	 RETSKP			;Yes. put in output buffer (CTHSRV will handle)
	TRNE T1,TTOESC		;No. A FUNCTION ESCAPE CHARACTER?
	JRST TTSND3		;HANDLE ESCAPE SPECIAL
	JN TTFLO,(T2),TTSND6	;IF FLUSHING OUTPUT, GO GET ANOTHER CHAR
	RETSKP
;GET CHARACTER FROM TTY OUT BFR
; T2/ DYNAMIC PTR
; RETURN +1: BUFFER EMPTY
;	+2: T1/ CHAR (9 BITS)

GTOCHR:	SKIPLE TTOCT(T2)	;[9117] Any characters in output buffer?
	IFSKP.			;[9117] Nope the count is zero
	  SETZRO TTOTP,(T2)	;[9117] Clear the output active bit
	  RET			;[9117]  and return
	ENDIF.			;[9117] There are characters in output buffer

	CALL CHKWRN		;SEE IF FORK WAKEUP NEEDED
	SKIPN 3,TTOOUT(2)	;GET BUFFER POINTER
	BUG.(HLT,TTONOB,TTYSRV,SOFT,<GTOCHR - No buffer but count non-zero>,,<

Cause:	At TTSND7 (send a character to a line) the pointer to the line's data
	base was 0.  This is either a coding error or the resident table
	containing the pointers was clobbered.  Examination of the stack in the
	dump should indicate which routine made the call without a pointer.
>)
	TDNN 3,WRPMSK		;AT END OF BUFFER?
	JRST [	LDB 4,[POINT 6,3,5] ;LOOK AT P,S FIELD OF BYTE POINTER
		CAIE 4,73	;POINTING TO LAST BYTE?
		JRST .+1	;NO.
		HRRZ T4,T3	;YES. GET ADDRESS OF CURRENT WORD
		HRR T3,1-TTSIZ(T4) ;POINT TO NEXT BUFFER IN CHAIN
		MOVEM 3,TTOOUT(2)	;SAVE POINTER
		JRST .+1]

	ILDB T1,TTOOUT(2)	;GET NEXT CHARACTER

;[9117] We now release TTY buffers when the last character is removed, instead
; of releasing them when an attempt is made to read from the empty buffers.
; This frees up lots of TTY output buffers which would otherwise hang around
; forever because of device drivers which only remove the number of chars
; specified by TTOCT, and therefore never attempt to read from the empty buffer
; chain.

	SOSLE TTOCT(T2)		;[9117] Skip if we just emptied the tty buffer
	RETSKP			;[9117] Nope, just return now
	SAVET			;[9117] Yep, save T1-T4
	CALL CLENUP		;[9117] (T2/) and go release those buffers
	RETSKP			;[9117] All done, buffers released
;BACKUP OUTPUT PTR BY ONE (E.G. BECAUSE DTE QUEUE FULL)
; T2/ DYN PTR

BAKTTO::MOVNI T3,1
	TMNN <TTSAL>,(T2)	;SENDALL?
	IFSKP. <INCR TSALC,(T2)> ;YES, ADJUST COUNT
	TMNN <TTHPO,TTSAL>,(T2)	;HP OR SENDALL STRING?
	IFSKP.
	  ADJBP T3,TTSAL2(T2)	;YES, BACKUP BYTE PTR
	  MOVEM T3,TTSAL2(T2)
	  RET
	ENDIF.
	SKIPE TTOOUT(T2)	;[9117] Is there a tty buffer?
	IFSKP.			;[9117] Nope
	  SAVET			;[9117] Save the temps (sigh)
	  MOVE T1,T4		;[9117] Get the byte back
	  CALLRET TCOU5		;[9117] (T1,T2/) Send it to output stream again
	ENDIF.			;[9117] So there is a tty buffer
	ADJBP T3,TTOOUT(T2)
	MOVEM T3,TTOOUT(T2)	;RESTORE IT
	AOS TTOCT(T2)		;RESET COUNT
	RET
;FUNCTION ESCAPE CHARACTER ENCOUNTERED IN OUTPUT STREAM

TTSND3:	CAIE T1,TTOMRK		;OUTPUT MARKER?
	IFSKP.
	  JE TTFLO,(T2),TTSND6	;IGNORE IF NOT FLUSHING OUTPUT
	  MOVE T1,[670000,,[BYTE (9)"]",.CHCRT,.CHLFD,0,0,0,0,0,.CHDEL]]
	  MOVEM T1,TTSAL2(T2)	;SEND INDICATION (WITH FILLS ON CR AND LF)
	  SETONE TTHPO,(T2)	;NOTE HP OUTPUT QUEUED
	  SETZRO TTFLO,(T2)	;STOP FLUSHING OUTPUT
	  JRST TTSND6		;TRY FOR MORE OUTPUT
	ENDIF.
	JN TTFLO,(T2),TTSND6	;FLUSH OTHER CASES IF FLUSHING OUTPUT
	CAIE T1,TTOPFC		;PAGE FULL FUNCTION?
	IFSKP. <
	  SETONE TTSFG,(T2)	;YES. SIMULATE CTRL/S
	  JRST TTSND6>		; AND GO CLEAR OUTPUT ACTIVE
	PUSH P,T2		;SAVE ADDRESS OF DYNAMIC DATA
	DYNST			;GET LINE NUMBER TO PRINT
	BUG.(CHK,TTILEC,TTYSRV,HARD,<TTSND - Unrecognized escape code>,<<2,TDB>,<3,TTY>>,<

Cause:	An unrecognized function escape character was encountered in a TTY
	output stream.

Action:	If this BUGCHK is reproducible, set it dumpable and submit an SPR with
	the dump and instructions on reproducing the problem.

Data:	TDB - Terminal dynamic data block address
	TTY - TTY line number
>)
	POP P,T2		;RESTORE ADDRESS OF DYNAMIC DATA
	JRST TTSND6
;CHKWRN - CHECK FOR WAKEUP NEEDED FROM OUTPUT BLOCK
;CALLED WHEN CHARACTERS TAKEN FROM OUTPUT BUFFER AND TTOCT REDUCED
; T2/ DYNAMIC DATA PTR

CHKWRN::JN TTNUS,(T2),R		;DO NOTHING IF NET USEER
	JE TTBKO,(T2),R		;RETURN IMMED IF NO FORK WAITING ON LINE
	LOAD T3,TOWRN,(T2)	;GET WARNING LEVEL COUNT
	CAMLE T3,TTOCT(T2)	;CAN WAKE?
	CALL CHKTOT		;YES, POKE SCHED
	RET

;CHKBKO - CHECK FOR WAKEUP NEEDED ON OUTPUT EVENT
; T2/ DYNAMIC DATA PTR

CHKBKO:	JE TTBKO,(T2),R		;RETURN IMMED IF NO FORK WAITING ON LINE
	CALLRET CHKTOT		;REQUEST CHECK OF OUTPUT-BLOCKED FORKS

;CLENUP - GET RID OF OUTPUT BUFFERS

;ACCEPTS:
;	T2/ ADDRESS OF DYNAMIC DATA

;	CALL CLENUP

;RETURNS +1: ALWAYS

;OUTPUT BUFFERS ARE EMPTY.  RELEASE THEM. IF INTERRUPT
;ON EMPTY OUTPUT BUFFER IS REQUESTED, PUT A WORD IN TTBBUF WITH BIT
;TTOIRQ SET.  TTCH7 WILL FIND IT WHEN IT IS RUN AGAIN.

CLENUP:	CALL TTRLOB		;RELEASE OUTPUT BUFFERS, SINCE EMPTY
	MOVX 3,1B<.TICTO>
	TMNE <TTMES,TTSHT>,(T2)	;A NORMAL BLOCK?
	RET
	LOAD T1,TTPSFK,(T2)	;GET FORK #
	CAIE T1,-1		;SKIP IF NOT SET
	JRST CLENU1		;SET, NON-CONTROLLING TERMINAL PSI REQUESTED
CLENU2:	TDNN 3,TTPSI(2)		;OUTPUT INTERRUPT WANTED?
	RET			;NO. RETURN
	MOVEI T1,TTOIRQ		;YES, PUT REQUEST IN BIG BUF
	JRST CLENU3

CLENU1:	LOAD T1,TTOPSI,(T2)	;GET PSI CHANNEL NUMBER
	CAIL T1,^D36		;SETUP?
	JRST CLENU2		;NO TRY OLD WAY
	MOVEI T1,TTPIRQ		;SET UP TO DO INTERRUPT
CLENU3:	SAVELN
	DYNST			;GET LINE NUMBER
	HRL T1,T2
	CALLRET BIGSTO		;REQUEST INTERRUPT


;ROUTINES CALLED FROM INTERRUPT ROUTINES

;POST OUTPUT DONE.
; 2/ LINE NUMBER

TTODON::CALL STADY		;GET ADDRESS OF DYNAMIC DATA
	 RET			;RETURN IF BECOMING ACTIVE OR INACTIVE
	CALLRET STRTTO		;START OUTPUT AGAIN
;TTDALL - ROUTINE CALLED FROM POWER RESTART CODE TO DETACH ALL JOBS
	RESCD			;MUST BE RESIDENT

TTDALL::SETZ C,			;START WITH FIRST LINE TYPE
	JRST TTDAL5		;GO CHECK THEM


;GO TO NEXT LINE. IF THE LINE TYPE CHANGES, DON'T PROCEED WITH THE NEW
;LINE. INSTEAD, GO TO THE NEXT LINE TYPE AFTER THE ONE JUST PROCESSED.
;THIS CODE ASSUMES THAT ALL LINES OF A GIVEN TYPE ARE NUMBERED CONSECUTIVELY.

TTDAL3:	LOAD C,TTSTY,(B)	;GET CURRENT TYPE
	ADDI B,1		;GO TO NEXT LINE
	CAIL B,NLINES		;BEYOND END OF LINES?
	JRST TTDAL7		;YES. GO TO NEXT LINE TYPE
	LOAD A,TTSTY,(B)	;GET TYPE OF NEXT LINE
	CAME C,A		;NEW TYPE?
	JRST TTDAL7		;YES. GO INCREMENT THE LINE TYPE

;TRANSFER ACCORDING TO THE VECTOR IN A. CERTAIN TYPES ARE NEVER
;PROCESSED.

TTDAL8:	TDCALX C,<<FE,RSKP>,<TV,RSKP>,<CH,RSKP>,<LH,RSKP>> ;SKIP IF DETACH SHOULD BE DONE
	 JRST TTDAL7		;DON'T DO IT

;DETACH THE JOB ON THIS LINE IF THERE IS ONE

	CAME B,CTYLNO		;IS THIS THE CTY?
	CALL TTJBDT		;DETACH THE JOB
	JRST TTDAL3		;GO PROCESS NEXT LINE

;FINISHED THE CURRENT LINE TYPE OR THE CURRENT TYPE IS NOT TO BE PROCESSED
;GO TO THE NEXT TYPE AND SEE IF IT IS TO BE PROCESSED

TTDAL7:	AOS C			;GO TO NEXT LINE TYPE
	CAIL C,NLTYPS		;BEYOND END OF LEGAL TYPES?
	RET			;YES. DONE ALL LINES
TTDAL5:	MOVE B,TT1LIN(C)	;GET FIRST LINE OF THIS TYPE
	JUMPL B,TTDAL7		;IF NONE OF THIS TYPE DO NEXT TYPE
	JRST TTDAL8		;GO DETACH IT
;ROUTINES TO ENABLE/DISABLE DATASETS.
;CLOBBERS ALL TEMP REGISTERS:

DTRMEN::TDZA D,D		;GET A ZERO TO DO ENABLE
DTRMDS::MOVEI D,1		;GET A ONE TO DISABLE
	SAVEQ
	MOVSI Q1,-NLTYPS	;DO ALL LINE TYPES
TTLIL2:	TDCALX Q1,<<FE,FEDABL>>,<RET>
	AOBJN Q1,TTLIL2
	RET

	RESCD

TTBUGH::BUG.(HLT,BADTTY,TTYSRV,SOFT,<Transfer to nonexistent TTY code>,,<

Cause:	The transfer vector for a non-existent TTY line type was referenced.
	The stack should indicate which routine caused the reference.
>)
	RET
	SUBTTL PTY Device Dependent Code

;*** PTY SPECIFIC CODE ***

	SWAPCD

; STPAR JSYS DEVICE DEPENDENT CODE

STPAR5:	TXZ A,TT%PGM		;YES. CAN'T SET PAGE MODE THEN
	RET

	RESCD

;DEVICE DEPENDENT CODE FOR START OUTPUT LINE
;LINE IS PTY.

STRTO2:	MOVE T3,TTOCT(T2)	;GET OUTPUT COUNT
	CAIN T3,1		;BUFFER WAS EMPTY BEFORE THIS CHAR?
	JRST [	SETONE TTDD1,(T2)	;NOTE OUTPUT EVENT
		JRST .+1]
	LDB T1,TTOIN(T2)	;CHECK CHAR BEING OUTPUT
	ANDI T1,177
	CAIN T1,.CHLFD		;END OF LINE?
	CALL CHKPT1		;MAYBE POKE CONTROLLING JOB
	RET
;PTYCTM - CALLED PERIODICALLY BY TTCH7 TO SEE IF OUTPUT START NEEDED
; T2/ DYNAMIC DATA PTR
; RETURN +2 TO PREVENT NORMAL OUTPUT START SEQUENCE

PTYCTM:	SKIPG TTOCT(T2)		;YES, ANY OUTPUT HERE?
	RETSKP			;NO
	CALL CHKPT1		;DO THE WORK
	RETSKP

CHKPT1:	CALL CHKBKO		;PERHAPS WAKEUP FORK WAITING FOR OUTPUT
	JE TTDD1,(T2),R		;RETURN IF NO OUTPUT EVENT RECENTLY
	SETZRO TTDD1,(T2)	;ONCE ONLY
	LOAD T1,TINTL,(T2)	;GET LINE NUMBER
	CALL TTYPTY		;CONVERT OT PTY NUMBER
	CALL PTYFOU		;NOTE PTY OUTPUT EVENT
	RET

;CHKPTA - CALLED WHEN FORK IS BLOCKING TO WAIT FOR SOME OUTPUT ACTIVITY
; IF LINE IS PTY, OUTPUT SHOULD BE STARTED IMMEDIATELY
; T2/ DYNAMIC DATA PTR

CHKPTA:	SAVET
	JRST CHKPT1		;YES, START IT

;CHECK PTY FOR OUTPUT POSSIBLE
;IF THE PTY HAS BEEN CLOSED, OUTPUT SHOULD NOT BE DONE BECAUSE
;NOTHING WILL EVER EMPTY THE OUTPUT BUFFER
; T2/ DYNAMIC PT
; RETURN +1: NO OUTPUT
;	+2: OUTPUT OK

CKPTOU:	SAVEAC <T2>
	DYNST		;GET LINE NUMBER
	CALL PTYSKO	;IS IT OPEN?
	 RET
	RETSKP
;LINE IS A PTY. SEE IF PTY LOGINS ARE ALLOWED

TTC7S2:	TXNE T1,SF%PTY		;SEE IF PTY LOGINS ALLOWED
	JRST RTRUE		;YES, GO LOGIN IN
	HRROI 1,[ASCIZ/
?LOGGING IN OVER PTY'S IS CURRENTLY DISALLOWED.
/]
	CALL TTEMSS
	JRST RFALSE		;FAIL

;DEVICE DEPENDENT CODE FOR TCI

TCIPTY:	CALL CHKPTA		;POKE OUTPUT FIRST
	PUSH P,T2		;SAVE ADDRESS OF DYNAMIC DATA
	DYNST			;GET LINE NUMBER
	MOVE T1,T2		;T1/LINE NUMBER
	CALL TTYPTY		;CONVERT TO PTY NUMBER IN T1
	CALL PTYFIN		;NOTE PTY INPUT EVENT
	POP P,T2		;RESTORE ADDRESS OF DYNAMIC DATA
	RET
;PMES - Outputs a message to the CTY
;Accepts AC1/pointer to string
;Returns +1 always.

PMES::	MOVE T2,CTYLNO		;[7193] GET THE CTY LINE NUMBER
	CALL TTEMES		;(T1,T2)[7193] OUTPUT THE MESSAGE
	RET
	SUBTTL End of TTYSRV

	TNXEND
	END