Trailing-Edge
-
PDP-10 Archives
-
BB-F494Z-DD_1986
-
10,7/nrt.mac
There are 4 other files named nrt.mac in the archive. Click here to see a list.
TITLE NRT - DECnet Intersystem Remote Terminal service
SUBTTL Anthony J. Rizzolo/AJR/VB/WGN/KBY 17-Jun-82
SUBTTL Program to talk to 10, 20, RSTS, RSX, or VMS
SUBTTL Source Copyright notice
IF2,<
PLM
;+
;.control
;.lm 5.rm 75.autop
;.fig 20
;.center 80;PLM for NRT.MAC
;.nonum
;.page
;.nsl
.lit
COPYRIGHT (C) DIGITAL EQUIPMENT CORPORATION 1984.
Digital Equipment Corporation, Maynard, Massachusetts, U.S.A.
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 which is not supplied by Digital.
.el .select ;&+-
PLM
;+
;.page
;.nm 1
;.Chapter Introduction
; This is the PLM for NRT.MAC. It is intended to document the
;purpose of each section of code in the NRT program. It is ^&NOT\&
;intended to give the general flow through NRT. For the general flow,
;the reader is referred to the NRT.MAN file.
;.Chapter Operating System Independent Support
; This first section of source is to set up all the definitions.
;The following are defined here:
;.list 1
;.le
;UUO and monitor interface symbols
;.le
;Flag bits
;.le
;AC definitions
;.le
;Feature tests
;.le
;Assembly parameters
;.end list
;.hl 1 AC definitions
; The ACs are defined with two sets of 4: T1 through T4 (the "temporary"
;ACs) and P1 through P4 (the "preserved" ACs). The names "temporary" and
;"preserved" are somewhat of misnomers, as they are in the monitor, although
;the convention is generally followed. These are defined as ACs 1-4 and
;ACs 5-10 (octal) respectively. They may be moved, but should be kept so
;that the T ACs are consecutive and the P ACs are also consecutive. CX,
;defined as AC 11 (octal) is a temporary AC used by macros and a general
;scratch AC. It is never preserved. ACs 12 through 16 are used as NSP.
;UUO argument blocks. Each AC takes its name from the corresponding
;_.NSxxx offset in a NSP. UUO argument block, minus the leading ".".
;These ACs are not considered to be preserved, except NSACH once the
;link is up and running; and only the channel part of it, not the status.
;AC 17 is the pushdown pointer, P. AC 0 is used for flag bits.
;Bits in AC F are defined with symbols of the form F$xxxx.
;Note that NRT has four sets of ACs: the "UUO level" ACs, the TTY: service
;ACs, the NSP service ACs, and the timer service ACs. NRT also has four
;PDLs to correspond to the four AC sets. Upon entry to each of the interrupt
;service routines, NRT exchanges the current set of ACs for the set which
;is to be used for the current interrupt routine. Note therefore that interrupt
;routines are ^&NOT\& reentrant. Note also that AC F is global and is ^&NOT\&
;exchanged as are the other ACs.
;-
MLP
>
SUBTTL SEARCHes, et al.
SEARCH JOBDAT ;For Job data area locations
SEARCH MACTEN ;For DEC-10 Definitions
SEARCH UUOSYM ;For UUO definitions
SEARCH MACSYM ;For break mask definitions
;.Requires
.TEXT "/LOCALS/SYMSEG:HIGH"
;.Directives
.DIREC .XTABM ;Supress tabs from macro expansions
.DIREC FLBLST ;List first line of binary only
.DIREC SFCOND ;Supress failing conditionals
SALL ;Supress all macro expansiosn
;Defaults and Feature tests
IFNDEF DEFESC,<DEFESC==.CHCNP> ;Set Default escape character
IFNDEF MAXPMR,<MAXPMR==7> ;Maximum number of nodes in PMR string
IFNDEF LSTPLM,<LSTPLM==0> ;Don't list the PLM in the source
IFNDEF OUTQUO,<OUTQUO==200> ;Number of outstanding output buffers
IFNDEF FTFUNCTION,<FTFUNCTION==0> ;Don't type out function code
IFNDEF FTPERF,<FTPERF==0> ;Default to no performance stuff
IFNDEF FTPMR,<FTPMR==0> ;PMR off.
IFNDEF FTDBUG,<FTDBUG==0> ;Special debugging features
IFNDEF FTPARANOID,<
IFE FTDBUG,<FTPARANOID==0>
IFN FTDBUG,<FTPARANOID==-1>
> ;Special checks
IFNDEF FTCROCK,<
FTCROCK==-1
> ;Code 'cause other systems don't work
IFNDEF FT703,<
FT703==-1 ;Assemble for 7.03 style SCNSEr
>
IFNDEF FTPSECT,<FTPSECT==0> ;PSECTs still lose
.HIGH.=:400000
IFE FTPSECT,<TWOSEG .HIGH.>
;Additional stuff:
IFN FTPMR,<
SEARCH PMR
.REQUEST PMR
>
IFN FTPERF,<
.PRCOM==1 ;Comment record in file
.PRDAT==2 ;Data record in file
>
;Version Information
DRTWHO==0 ;WHO EDITED LAST
DRTVER==4 ;MAJOR VERSION NUMBER
DRTMIN==0 ;MINOR VERSION NUMBER
DRTEDT==223 ;EDIT NUMBER
IF2,<
IFN FTPERF,<PRINTX [NRT - Performance diagnostic tool.]>
IFN FTPMR,<PRINTX [NRT - Poor Mans Routing (PMR) code.]>
> ;End IF2
LOC <.JBVER> ;GO TO THE VERSION NUMBER
VRSN. DRT ;ASSEMBLE IN THE VERSION NUMBER
PURGE DRTWHO, DRTVER, DRTMIN, DRTEDT
IFE FTPSECT,<RELOC .HIGH.>
IFN FTPSECT,<.PSECT .HIGH.> ;Hiseg starts here
SUBTTL Revision History
COMMENT |
7 Fix TECO to VMS.
10 Re-add character queing for VMS. This is because VMS
does not respond rapidly to ^C and does not in fact
allow any characters to be input until a read QIO is
recieved. When we recieve a Read QIO, set a new flag
F$RQIO (This was better than using the fact that we had
a Message ID that was non zero. Also clear the flag
when we send the message out. Also fix a problem with
VMS <CRLF> so that it does not mess up and delete a line
feed when it shouldn't be.
11 Fix problem with when you ^C out of the prompt routine.
It will now call the TTYRST routine to reset the TTY
parameters to there saved values at start up.
12 Fix the routine ECHON, so that it uses the right registers.
It was doing the GETLCH in CX and the SETLCH on T1. My
Fault about that. Also remove code to set the Terminal type
As it is no longer neccesary.
13 Add a CLRBFI at the exit (NSPER1) from the error routine
so that user type ahead is not seen by the -10.
14 ?
15 Fix a problem with local links hanging during the config message
transmission. This is because on local links it is possible
for the link to already have data. In this case the hiber did not
wake up. So you must check the status of the link to see if there
is valid data available. If there is, just read it and don't sleep,
If there is none, then HIBER until we are awakened.
16 Fix a problem with NRT hanging because when GETCFG does not
have enough data it used to skip return to the calling routine. Now,
it should just loop back to GETCFG and wait for all the data to
become available.
17 Fix a problem in using the TO command.
20 Restructure program to be PSI driven as much as possible.
Implement output buffer queueing to the network to prevent
infinite loops waiting for network I/O. Restructure the
VMS support to fix various problems with ^C, ^Z, etc.
Implement the new VMS 3.0+ protocol. Fix various problems
with carriage control to VMS. Implement usage of the
break mask feature for VMS. Version 3A(20).
21 Fix ^C/^Y loops if VAX doesn't respond before user types
another character (we'd keep finding it as a special character
but never could send the AST because it really wasn't special
any more as the ASTs are one-time enables and the VAX hadn't
reset them). Partially fix character drops on 10/20 seemingly
caused by not retrying the OUT immediately after it fails.
22 Restructure RSX section. Fix a few minor bugs in VMS; in
particular change the free line feed logic to not give such
if the terminal is no-echo and no prompt is given, or
if there is a <LF> anywhere in the last write operation.
Implement broadcast mailboxes for VMS. Fix bugs in setting
second characteristics word for VMS. Fix sending extra
zero length data messages to 10/20 which at best is clogs up
the network line and at worst really confuses PSTHRU tasks.
Version 3B(22).
23 Repair RSTS code. Fix MONITO so it doesn't reset the TTY:
status until after typing out messages. This prevents user
from messing himself up with CCONT.
24 Update version number to reflect new code. Fix command scanner so
that it doesn't wait forever for a node name to be typed.
Implement escape sequence processing (VMS). Fix routine
handling PMR NAKs so that it doesn't get an illegal UUO.
Fix sending null messages to VMS on a BROADCAST if no broadcast
mailbox is enabled.
Version 4(24).
25 Implement minimal SWITCH.INI support and EXPERT mode.
26 Implement automatic Poor Man's Routing (under FTPMR) which
will use file DNHOST.TXT on SYS:.
27 Implement /MODE:NOTIFY and make /MODE:EXPERT not beep terminal
on entering command mode. Make either of those be in character mode
and also accept the break character twice as equivalent to the "P"
command. Fix certain SETLCHable bits getting turned off caused by
not giving GETLCH a line number.
30 Implement ^X to RSX. Fix ^X to VMS not to echo ^U unless
in input wait.
31 Do fancier rubouts when possible.
32 Implement segment size code for slow terminals
33 Make independent AC sets and PDLs for each level. This is implemented
so that if the network gets sick, you can't get stuck on a blocking
input (since you are in EW at PSI level, you cannot get the
break character through at this point).
34 VMS sometimes sends (at least) BROADCAST messages with identifiers
of zero or some which come out negative. We used to use negative
ones to indicate that the message had already been ACKd; that is
no longer necessary so just remove the crock. In the case of
zero, just don't ACK the message. VMS.AK does this anyway; VMS.BC
does it's ACKing by hand and should do likewise (until we understand
this problem better).
35 Fix up the performance analysis tool.
36 Make NRT more resistant to running out of output buffer room:
implement to queue an incomplete buffer without EOM.
37 Fix RSX unsolicited input: it is not supposed to take effect if
the terminal is "attached" (in the RSX sense).
40 Implement FTCROCK for that code which has to be in because
other operating systems don't behave as expected. This is
currently for RSX11, which will hang if the monitor ever
tells the link to turn off. The FTCROCK code sets the
goal to 0 so that we don't do optimistic buffering and won't
ever turn the link ff.
41 Implement F$USRV: "UUO level" service. This makes it so
that spurious wakeups to the main level don't force us into
TTY: service. May be required if SCNSER doesn't get fixed
correctly to handle some deferred echo bugs.
42 For FTPMR on, make PMR use device DCN: instead of SYS: so
it is a little harder to get automatic PMR as we don't support it.
43 Implement doing VMS free line feeds more correctly: use flag
F$CLF (Cancel Line Feed) if ending an echoing read line with <CR>
then echo as <CR><LF> and eat the "free" line feed (explicit or
implied) in the next read.
44 Begin implementation of noticing "permanent" characteristics
for terminals on VAX. Implementation starts with observing
no-echo and passall properly.
45 Fix it so we break on each character after part of a buffer has
been eaten. This makes ^R, ^U work as advertised correctly after
a ^T to VAX. This was caused by the TRMOP. failing due to a zero
field width. Make TTYSST more defensive to use a field width
of one if zero was specified. Also, make VM.STT maximize the mask
size rather than ANDIing it so that 1000 doesn't turn into zero.
46 Fix numerous bugs in RSX Read Single Characters mode. These
were not able to be tested before due to lack of test case;
it was found that TECO exercises things to some degree.
47 RSX expects a terminator even if the request is satisfied not
by terminator, but by character count. Give him a <NUL> for
a terminator in those cases.
50 VMS count of lines in postfix/prefix carriage control are
supposed to be new lines (=<CR><LF>). They have previously
been interpreted as <LF> only. Do only one <CR> as that is
all that really makes sense. Also set F$CLF for ^Z to see
if that eliminates extra <LF>s.
51 VMS ^U/^R broken after ^U after ^T. We still have the field
width set to one so all characters get eaten by the prog and,
although the monitor is doing the ^U, there aren't any characters
left for it to process.
52 VMS doesn't give a free line feed after a broadcast which ends
in <CR> iff there is no prompt. This can cause characters to
over-write. This is probably somewhat of a bug in VMS, but
we will "duplicate" it here since that is a fairly easy thing
to do anyway. To fix it "right" requires a lot of interesting
logic (to prevent you from necessarily getting extra <LF>s) and
should be done when one knows exactly how VMS has decided it wants
the line to look in such cases. Note that there is still a <CR><LF>
generated by SOS on ^R after ^T. This should be considered a
feature rather than bug since it makes the retyped line NOT
overwrite the ^T output. This is not, however, what happens
on a VMS hardwired terminal.
53 VMS actually does give one a zero length read, occasionally. Right
now, zero length read gets treated as a length one read so that a
character gets tossed. Fix it for VMS and RSX.
54 For TOPS-10/20: Implement F$EOMN which means never send an EOM
on a message unless this is the last buffer to be output. This
will cause LLINKS to buffer up more characters and use the line
more efficiently when it is backed up. If response looks too slow
for this, we may have to implement a timer or counter to force EOM
to be sent more frequently.
55 Add a CLRBFI after the MONRT. for prompt dialogue option "M"
(return to monitor mode leaving link open). This is so the
<LF> which seems to get left lying around doesn't confuse things.
56 Try to make RSX <CR><LF>s right. Do not echo break characters
even on real read, if read single characters (F$PALL) in effect.
Echo terminator otherwise, even if no-echo. Change the default
break mask to include most control characters. If
the request contains no characters but the break the the break
is not a <CR>, then toss the characters.
57 Make VMS free line feed logic apply to broadcast data too.
60 Fix TTYSST to set <CR> as a break character even if it
isn't if we are on a system that NEVER wants <CR> to generate
<CR><LF>. This is so we don't get an extra <LF>.
Set the bit for VMS, RSX at initialization. Don't clear F$CLF
and F$FLF for VMS after outputting a prompt if the read is for
zero characters.
61 Phase IV VAXen don't like small seg sizes. Since it's not
really important for VAXen anyway (since ^O etc. are handled
locally), make a subroutine called by TOPS-10/TOPS-20
(or anyone else that wants to) to affect the link quotas.
Since one can't change segment size after the link comes up,
change the percentage of buffers allocated for input.
size stuff to be a subroutine. Call only during TOPS-10/TOPS-20
initialization. This is where it is needed the most anyway.
62 After processing an out-of-band character for VMS, don't set
^R, ^U, and <RUB> processing unless there are actually some
characters in the internal input buffers (i.e. already read).
63 Range check the number of characters in the comment string for
the performance analysis feature.
64 Update for new format for DNET. UUO. Clean up code a little;
get rid of parameter MAXQUE and affiliated variables as they
are no longer used. Make /MODE:EXPERT and /MODE:NOTIFY consistent
even if the help text is typed.
65 Change SWITCH.INI support to us .LKNAM so that switches can
be abbreviated to uniqueness. Change .LKNAM and routines
that call it to use AOBJN pointers instead of IOWDs. Change
.LKNAM and routines that use it so that .LKNAM can return
an offset into the found table entry instead of an absolute
address. Tidy up command tables. Change MONITO to
use .LKNAM command tables.
66 Add PLM to file. Make code slightly prettier. Change
RET/RETSKP/CALL to POPJ P,/JRST CPOPJ1/PUSHJ P, for consistency
(no other reason).
67 RSX needs to do rubouts, ^U, and ^R in the special circumstance
of unsolicited input (due to edit 56). Make the VMS routines
general and move them out of the VMS section to the operating
system independent section. Implement the required RSX routines
to use them.
70 RSTS also needs rubout processing if user types break character
in the middle of a line. VMS doesn't handle this particular
case either. Fix them.
71 Add more table entries to the terminal type and rubout tables.
72 One of the cleanup edits fiddled around with ^C trapping and moved
the point ^C trapping was actually turned on to before the
connect was done. This is bad if we get hung in the connect. Even
though we aren't slaved, we are in EW and the monitor won't let us out
until the UUO finishes.
73 Move the initial turning off of ^C trapping to after label RESTRT
so if user types "CONTINUE" after an exit, it gets turned off
correctly. Move the turning ON of ^C to after slaving the
user doesn't accidently kill the link after it just gets started up.
74 Somebody (VAXen related) doesn't like NRT to use a Format-1
block with "Tops-10 NRT-SERVER" as the source block anymore.
Change it to use Format-0 with the same object (.OBHTH) as
the destination PDB.
75 Make NSP argument blocks prototypes BLTed to the low segment
instead of pure. This is so the PMR can do aliasing correctly.
76 Change EKOBRK to echo printing characters as themselves if not
in the echo table. Move range checking of mask width for TRMOP.
function .TOSBS into TTYSST so it will always get done, instead
of in VM.STT. Make VM.COB check for mask to set
even if the ID=0.
77 Fix control-U putting user into an infinite loop on VMS if it
is set as a break character in the mask, but F$RALL or F$PALL
is not set or read physical isn't done.
100 Make VMS write check to see if a read snuck in while we did
^O so that if satisfying a read request, ^O flag goes off.
101 Change VMS.BC to do a free line feed if not noecho and set F$CLF
if it had to do one. This only applies of nothing is done
previously in VMS.BC to alter the F$FLF/F$CLF settings. Don't
change F$FLF/F$CLF on read completion, only after doing prompts
and stuff if not a zero-length read.
102 Change VAX timeout stuff to empty the chunks into the stream.
Implement the IO$M_TYPEAHDCNT and IO$M_MODEM modifiers to the
IO$_SENSMODE functions on the VAX.
103 Implement unsupported functions return for VAX. Return it for
IO$_SETMODE with IO$M_MODEM modifiers.
104 Change TTYPSI to not go through buffer allocation if F$FRC is
on; this can cause characters to be read twice.
105 Change VM.ETI to clear F$NEOM when testing it. Otherwise, we
can get into an infinite loop because it thinks there is still
output to eat, but NSPIN returned because the buffer was full.
NSPIN won't re-initialize the buffer unless F$NEOM is off.
106 Since VMS has become more tolerant, re-implement the segment
size code.
107 Trap for ATTACH/DETACH so we can change the UDX and release
the old TTY: correctly.
110 For "UUO level" service, don't just call TTYPSI with PIs turned
off. Instead, trap for WAKE UUOs so we get to PSI level. This
is so that we can actually get an ATTACH/DETACH PSI at any
time it is important, as that is also made to have a higher
priority. Make TTY: service wait on output if TTYUDX is
negative, implying a DETACH was done.
111 Make VMS.KI ACK messages - they actually have non-zero
REFIDs. Causes VMS jobs to hang in MWAIT.
112 Make RSX unsolicited input type ahead work right.
113 (VAX) Don't echo type-ahead until it is known the character is not
a break character.
114 Add copyright notice.
115 Give DOCTR another argument: a routine to call after outputting
the "^R<CR><LF>". This is so that VMS can output the prompt again.
Pass a zero if there is no routine.
116 Give RSX the prompt stuff of edit 115.
117 Implement flush output routine for TOPS-10/20 to make things
a little faster.
120 Convert to non-blocking buffer TTY: output so can respond
to commands faster (make 117 work better).
121 Move clearing of F$FLF and F$CLF yet again to just before
setting it for last character echoed being a <CR> echoed
as <CRLF>. Don't change setting if only stuff read is an
escape sequen, which is supposed to be invisible. This
keeps $SET TERMINAL/INQUIRE on VMS from giving an extra line
feed.
122 Begin using F$CLF in RSX to prevent double <LF>s in, say, PIP,
which uses "regular" I/O.
123 Fix ^H to work for RSX and VMS. It is not a break character nor
does it perform the function of <RUB>.
124 Make TTYSST wait for output to complete before blasting buffers.
125 Fix VMS Kill I/O once and for all. The REFID is the REFID of the
request is to be killed. If it exists (read request are really only
relevent here) it should be completed with SS$_ABORT status. Otherwise
the Kill I/O is ignored. The Kill I/O itself is never ACKed.
126 Make typed ahead <RUB> work better - set IO.LEM so the monitor won't
jump on them for us. Depending on what the user wants when a request
actually gets queued, do the "right" thing.
127 Make NSPERR save the function done so that if it does have
to output it, it won't always come out as .NSFRS.
130 Read/save/transmit the WRAP (complement of the .TONFC) bit for VMS.
Don't clear it automatically. Change TTY: type and WRAP bit for
Set Characteristics/Mode.
131 Implement a number of minor improvements to speed up ^O type things.
Make DCNPSI check and grant a TTY: input if one is pending before
looping back to NEWNET. Make TOOUT defer the out if LDBECC (read
by TRMOP. function .TOECC) is non-zero so that "echo" will get done
and we can get input interrupts.
132 Change VMS Unsolicited input to go into character mode if no
read request is enabled.
133 Make VMS Write Physical actually write things in image mode.
134 Make the RC.CTA function work for RSX Set/Get terminal characteristics.
135 Make ^Q/^S excepted from break masks unless in some flavour of
passall mode. In that case, always include them.
136 Make type-ahead echoing and prompt echoing immune to the output
queue clearing effects of ^O (doesn't affect if it is in the chunks).
Implement a break (escape) character count instead of the flag.
137 Make "read active shuts off write" for VAX. This has the problem
of using too much core if the other side keeps sending.
140 Change HIBER loop in WATOUT to use WAIT UUO. Put output
quota on number of buffers which can be queued before the
program physically will block in TO state. The number is
determined by assembly parameter OUTQUO.
141 Change the WAIT back to a HIBER as WAIT seems to cause loss of
PSI interrupts (WAIT turns of DEVAIO). Let ^O be done
by the monitor and try to follow the monitor's bit.
142 Change the connect back to Format 1, object 0, process name
"TOPS-10 NRT". Object type 23 is now privileged and VAXen don't
seem to care again.
143 Make GETCFG able to type out multi-line PMR NAK messages.
144 Re-do handling of special characters for RSX when a Read Single
is also active.
145 Make VMS and RSX continue scanning if we get an "ignore" return
from their respective special character handlers.
146 Make ^W always in IMASK (only 10/20s support it and their in PIM).
147 Set correct value for RC.CCT in config message since we are really
trying to do postfixing.
150 In the check for non-zero LDBECC, check first to see if there
is a non-zero LDBBKC to prevent hanging while we have a pending
PSI.
151 Always light IO.ABS in the SETSTS word. Although it has no effect
in PIM, it does make .TOSOP skip correctly.
152 Implement $TOICL and $TOOIN for RSX write-breaks-through-read
vs. those writes which don't.
153 Implement minimal IAS support as a special case of RSX.
154 Change TOHIBR to use SLEEP so pending PSIs don't bother us.
Set SLPFLG to one (will be AOSEd by TTYDFR) if to be "woken"
on output done (actually, we just set queue a one tic clock
request then).
155 Clear F$PALL before calling RX.SPC so things really get done.
156 Break WATOUT into WATDEQ, which waits for all buffers queued for
output to be output, and WATIDL, which waits for the line to become
idle. Call WATOUT only for things like when preceding an ^O bit
change, or doing a FRCUUO. Call WATDEQ when all we care about is
that our buffers are empty. WATOUT can cause the terminal to
look hung for 60 seconds if the user is using ^S, since we don't
get an I/O done interrupt if the user's buffer was empty but
characters were still in the chunks. This means the sleep request
is never cancelled. **This is a heuristic solution**
157 Don't echo RSTS break characters if no-echoed (obvious!)
160 SETICH sets the count to be greater than or equal to zero
so the count returned by VMS sense won't be wrong if
SETICH was negative (a timeout was previously processed).
161 Segment size table forgot about 1800 baud.
162 Change DATPSI to do a SLEEP for zero instead of a WAKE (since
TOHIBR called by DATPSI uses sleep). If we really happen to be
HIBERing, it won't conceptually make a difference.
163 Clear PS.REF in TTYSTS on doing an IN: it must have been cleared
by the time we finish an IN UUO. Causes F$USRV to get stuck
on otherwise.
164 PJRST TTYSST doesn't necessarily do the right thing: we may
not get an interrupt. Most PJRST TTYSSTs change to
PUSHJ P,TTYSST followed by PJRST FRCTTI to be sure we see
the changes correctly. Ones which are left the same:
(1) those preceded by a call to FRCTTI; (2) those in the
initialization routines since FRCTTI gets called anyway);
(3) those that don't change the mask.
165 Occasionally, a TTY: PSI seems to get lost. The scenario
involves calling TTYPS1 from network PSI level (this is an
optimization) so that some TTY: messages can get in over
long network messages). However, nothing happens (not really
an unusual circumstance, since F$USRV just means we should look
because something unusual MAY have happened) but we do not
get a PSI when things are done and although the WAKE PSI
from the original setting of F$USRV isn't set, we don't
do anything. Don't clear F$USRV and remember TTYSTS over
the call, restoring (IORM) the original bits if calling
at network level. This means unecessary calls to TTYPS1, but
is less serious than missed PSIs. This will hopefully change
when full support for break masks, character PSIs, and PSI
on input available is implemented in SCNSER. The times we loop
at network level for a flood of network messages should
be few enough that this has relatively little effect in
reality. The NETCHR routine used only for TOPS-10/20 will
continue to clear the bit as this is not a real problem for
transparent protocols (typing an additional character will
force a PSI).
166 Add TTY BLANK to the setup and save characteristics tables;
setting TTY NO BLANK does interesting things on VMS and RSX
in particular.
167 Remove edit 165; it doesn't work. Look for the problem elsewhere.
170 Another possibility for the bug which is the source of the
last few edits is a change in and out of PIM for image
mode output. After changing back via TTYSST, do a .TOSIP
to kick the terminal and call FRCTTI as well.
171 Fix CHKCTH to use $TOOIN. Put ^H into IMASK for all VAX requests.
172 Remove edit 170. The actual problem is in the monitor: if one
of the FRCUUOs is done at exactly the right moment, and LDBCMR
is up when the break count (LDBBKC) gets incremented, then
PSIIOD doesn't get called.
173 VMS Broadcast really doesn't override ^O. Remove code to do so.
Clean up broadcast code in light of this change.
174 Even if in EXPERT or NOTIFY modes, wait for the controlling TTY:
to go to user level (or detach) before continuing so user can't
mess himself up with CCONT. Make DATPSI reset TTY mode to
ASCII and wait if in monitor mode.
175 Make T10/T20 scan input stream for command character if F$XPT
is set and the controlling terminal is the same as the I/O terminal.
This allows ALL command characters to be done correctly in EXPERT
and NOTIFY modes instead of just the double escape-character
case. New entry to MONITO: MONITC, which allows the character
to be passed in T3.
176 Change CHKPRM to cancel F$CLF if first character is not a <CR> or
<LF>. Shown by NCP SHOW<CR> on the VAX.
177 Light F$ACO when setting VMS out-of-band if ^O is in the mask.
Shown by EMACS on the VAX. OR the new bits into IMASK and call
TTYSST then too. Note that some old bits might be left over,
but we know how to handle this anyway.
200 Turn on/off page mode when it changes on the VAX. EMACS on
the VAX again.
201 Fix the out-of-band VAX stuff to handle ^S/^Q right; add special
character routines to handle ^S/^Q if we get them.
202 Fix bug in VMS FORTRAN type carriage control.
203 Change VMS.BC to clear F$CLF and F$FLF if a read request is active
(actually, present) and then set F$FLF if there is input or a
prompt present.
204 More free LF bugs: make CHKPRM parse for ESCAPE sequences
if F$ESC is set and treat them as "invisible" characters (which
don't check/affect the settings of F$FLF and F$CLF).
205 Turn on RC.CRT in the RSX configuration mask. Update for
new NSP. error code format.
206 Do appropriate things for setting of terminal types for RSX.
This allows EDT to run on RSX-11. Still needed: way to turn
off auto-crlf.
207 Fix copyrights.
210 Make no lower case default for RSX (that's what the -11 defaults
to anyway). Allow SET TERMINAL CHARACTERISTICS to do the TRMOPs
where possible.
211 Put range checker on OS type we get back so we won't get PC
Out of Bounds for some system which returns a bum configuration
message. Fix comments about what is being checked
as a PMR NAK. Note that the code here is slightly different
than the code in the PMR subroutine.
212 Fix bug in ^U routine DOCTU which causes extra character to be
erased.
213 Add RM.UNL function to RF.RSC (RSX only).
214 Add additional terminal types and correct VAX terminal type
tables.
215 Fix scanner bug so that it eats to end of line on RESCAN.
216 Fix bad sense test for message level bits. Minor cosmetic
fixes.
217 Add the "DEAR" command to the rescan table.
220 Fix bug wherein HELP command in EXPERT or NOTIFY modes automatically
exits user. Fix the same bug when an illegal character is
pre-scanned from the input stream.
221 Implement FT703 to feature test those things which only need to
be on for 7.02 (due to SCNSER bugs). Put the HPOS routines under
IFE FT703.
222 Crock ULTRIX to act like TOPS-10/TOPS-20. This should be
switched some time to key off of the protocol mask rather than
the OS type.
223 Update system types to include all known systems. Fix VMS
$BRDCST to do carriage control at least empirically right
for V4.
| ;End comment
SUBTTL Table of Contents
; Table of Contents for NRT
;
;
; SECTION PAGE
; 1. Program to talk to 10, 20, RSTS, RSX, or VMS.............. 1
; 2. Source Copyright notice................................... 1
; 3. SEARCHes, et al........................................... 2
; 4. Revision History.......................................... 3
; 5. Table of Contents......................................... 5
; 6. .EXE File Copyright....................................... 5
; 7. AC Definitions............................................ 6
; 8. Flag definitions in F..................................... 7
; 9. Operating System (Returned in CONFIG message)............. 8
; 10. Constant definitions...................................... 9
; 11. Device channel definitions................................ 10
; 12. Internal input and output buffer block definitions........ 11
; 13. UUO definitions........................................... 12
; 14. MACRO Definitions
; 14.1 PLM MACROs........................................ 13
; 14.2 FALL (Address).................................... 14
; 14.3 PJRST(X).......................................... 15
; 14.4 ERR(PRE,MSG)...................................... 16
; 14.5 ERRMAC(code,pre,text)............................. 17
; 14.6 FCNMAC - Table of NSP. function codes and text.... 18
; 14.7 Typeout MACROS.................................... 19
; 14.8 AC saving MACROS.................................. 20
; 14.9 Break masks....................................... 21
; 14.10 ASSUME............................................ 22
; 14.11 NETOCH macro - output character to network........ 23
; 14.12 NETALC - Allocate contiguous buffer space......... 24
; 14.13 OSDSP............................................. 25
; 14.14 NAMTAB............................................ 26
; 14.15 TRMCHR............................................ 27
; 14.16 VTTCHR............................................ 28
; 14.17 ASCII8............................................ 29
; 15. Start the Program......................................... 30
; 16. LPROMPT - Long Dialogue................................... 31
; 17. PROMPT - Short initialization dialogue.................... 32
; 18. Check for Poor Man's Routing in User's String............. 33
; 19. DOPMR - Subroutine to do the Poor mans routine string..... 34
; 20. BLDPMR - Builds the PMR string............................ 35
; 21. DOCONN - Initiatiate a DECnet connection.................. 36
; 22. MAIN - Main wait loop for all systems..................... 37
; 23. FRCTTY - Force a look at the TTY:......................... 38
; 24. OSJMP - Dispatch table for systems........................ 39
; 25. Initialization subroutines
; 25.1 Initialize the Data Base.......................... 40
; 25.2 Process RESCAN Input.............................. 41
; 26. FNDFNC - Find function routine............................ 43
; 27. NETCHR - Output a stream of network data to TTY........... 44
; 28. Exit Routines
; 28.1 MONITO (Exit Dialogue)............................ 45
; 28.2 Dispatch Table.................................... 46
; 28.3 Help Routine...................................... 47
; 28.4 Flush Network Messages............................ 48
; 28.5 Return to Monitor................................. 49
; 29. Continue Remote Session................................... 50
; 30. REENTR - REENTR code...................................... 51
; 31. Performance analysis
; 31.1 Start session..................................... 52
; 31.2 Start a response measurement...................... 53
; 31.3 Record a response................................. 54
; 31.4 End of session.................................... 55
; 31.5 Performance string and length..................... 56
; 31.6 Get ASCIZ string (for comment).................... 57
; 31.7 Get character from string......................... 58
; 31.8 Get a decimal number.............................. 59
; 31.9 Output a comment to the file...................... 60
; 31.10 Output a data record to the file.................. 61
; 31.11 Output any record to the file..................... 62
; 32. NETICH - Get a network character from the network buffer.. 63
; 33. RBYTEC - Get a byte from the network...................... 64
; 34. CONECT - Routine to set up the connection................. 65
; 35. SNDPMR - Send the PMR string to the remote system......... 66
; 36. Error Routines
; 36.1 SETNER - Set up NSPECD with error code............ 67
; 36.2 NSPERR - Give an NSP. error message............... 68
; 36.3 DOERR - Output an error message................... 69
; 37. NSPERC - NSP. Error message table......................... 70
; 38. FCNTAB - NSP. function text table......................... 71
; 39. XMTMSG - Transmit network message........................ 72
; 40. TTYOPN - Routine to OPEN the TTY.......................... 73
; 41. Routine to set desired TTY: characterstics................ 74
; 42. Routine to reset the TTY: characteristics................. 75
; 43. TTY: Output and Echo Routines............................. 76
; 44. Set Horizontal Position................................... 77
; 45. Miscellaneous terminal routines........................... 80
; 46. TTY Input Routines
; 46.1 INCHR - Get terminal character.................... 81
; 47. Output SIXBIT argument to controlling TTY:................ 82
; 48. Node Name Output Routines................................. 83
; 49. SIXBIT Input.............................................. 84
; 50. Scanning Routines
; 50.1 .LKNAM............................................ 85
; 50.2 .MKMSK............................................ 86
; 51. Memory manglement
; 51.1 Core allocator.................................... 87
; 51.2 Core De-allocator................................. 88
; 52. SWITCH.INI support
; 52.1 Read SWITCH.INI................................... 89
; 52.2 Switch handling routines.......................... 90
; 52.3 I/O Routines...................................... 91
; 52.4 Switch tables..................................... 92
; 53. FILHGH - Prototype FILOP. UUO block....................... 93
; 54. GETCFG - Get the configuration message for the system..... 94
; 55. Compute mask bit & word for ESCCHR........................ 95
; 56. Fatal errors in job....................................... 96
; 57. ATTACH/DETACH PSI routine................................. 97
; 58. DECnet interrupt routine.................................. 98
; 59. TMR PSI routine........................................... 99
; 60. WAKE PSI Service.......................................... 100
; 61. TTY: PSI Service.......................................... 101
; 62. TTY: Service
; 62.1 Flush all type-ahead.............................. 102
; 62.2 Set Data Mode and Mask............................ 103
; 62.3 Check for line editing............................ 104
; 62.4 Check/Set ^O bit.................................. 105
; 62.5 Wait for output to finish......................... 106
; 62.6 Wait for available buffer......................... 107
; 62.7 Scan input for special characters................. 108
; 62.8 Count number of escape characters................. 109
; 62.9 Input scan routines............................... 110
; 62.10 Check for break character......................... 111
; 62.11 Control-H Routine................................. 112
; 62.12 Escape Sequence processing........................ 113
; 62.13 Escape sequence processing tables................. 114
; 62.14 Echo type-ahead................................... 115
; 62.15 Rubout processing................................. 116
; 62.16 Routine to do display for <RUB>................... 117
; 62.17 Handle Control-U.................................. 118
; 62.18 Handle Control-R.................................. 119
; 62.19 Set to handle ^U, ^R, <RUB>....................... 120
; 62.20 Clear Handling of ^U, ^R, <RUB>................... 121
; 63. PSION/OFF - Turn on/off the software interrupt system..... 122
; 64. NSP. Routines
; 64.1 NSPEA - Make an active connection................. 123
; 64.2 Set Link Quotas................................... 124
; 64.3 NSPIN - NSP. Input routine........................ 125
; 64.4 NSPOUT - Outputs OTPBUF to the network............ 126
; 65. SETNOD - Sets up node name in ASCNOD in the connect block. 128
; 66. SIX2SB - Store SIXBIT T1 in string block pointed to by T2. 129
; 67. INIOBF - Initialize OBUF and IBUF......................... 130
; 68. BPLENG - Compute length of byte pointer in T1............. 131
; 69. Miscellaneous support - Digest a mask..................... 132
; 70. Miscellaneous Support
; 70.1 GET & PUT word routines........................... 133
; 71. Miscellaneous Routines.................................... 134
; 72. Returns................................................... 135
; 73. EXCACS.................................................... 136
; 74. Operating System Specific Support......................... 137
; 75. RSTS Support
; 75.1 Protocol definitions.............................. 138
; 75.2 RSTS network input................................ 139
; 75.3 TTY: input........................................ 140
; 75.4 RST.IN - Initialization Routine................... 141
; 75.5 RST.CT - RSTS control Message..................... 142
; 75.6 RST.DA - Recieve Data message..................... 143
; 75.7 Handle special characters......................... 144
; 75.8 Check Set/Clear of Local ^U/^R/<RUB>.............. 145
; 75.9 Break Echo Table.................................. 146
; 76. RSX Support
; 76.1 Protocol defintions............................... 147
; 76.2 RSX.IN - Initialization........................... 149
; 76.3 Network interrupt................................. 150
; 76.4 TTY: input........................................ 151
; 76.5 NOP function...................................... 154
; 76.6 Set unsolicited characters........................ 155
; 76.7 Kill I/O.......................................... 156
; 76.8 Disconnect link................................... 157
; 76.9 Single character mode............................. 158
; 76.10 ATTACH/DETACH..................................... 159
; 76.11 Get terminal characteristics...................... 160
; 76.12 Set terminal characteristics...................... 161
; 76.13 Read data, Read with prompt....................... 162
; 76.14 Output prompt string.............................. 164
; 76.15 Handle special characters......................... 165
; 76.16 Check about ^U/^R/<RUB> processing................ 166
; 76.17 Count ^Cs......................................... 167
; 76.18 Set TTY: up....................................... 168
; 76.19 handle timed requests............................. 169
; 76.20 Write data........................................ 170
; 76.21 Eat common header................................. 171
; 76.22 Build header for output message................... 172
; 76.23 Queue read request................................ 173
; 77. VMS Support
; 77.1 Protocol definitions.............................. 174
; 77.2 VAX/VMS network input routine..................... 176
; 77.3 VMS TTY: input routine............................ 177
; 77.4 VMS.DA - Recieve VMS data......................... 178
; 77.5 Routine to do carriage control.................... 180
; 77.6 Routine to actually write the record.............. 181
; 77.7 Check to see if REFRESH needed.................... 182
; 77.8 Read and Read with prompt......................... 183
; 77.9 Routine to output prompt.......................... 185
; 77.10 Break echo string table........................... 186
; 77.11 Routine to queue a read request for VMS........... 187
; 77.12 Eat and store common header....................... 188
; 77.13 Handle Control-O.................................. 189
; 77.14 VMS.KI - Kill I/O................................. 190
; 77.15 VMS.AK - Write complete and Acknowledge........... 191
; 77.16 VMS.BH - Build Header............................. 192
; 77.17 VMS.IN - Initialization message................... 193
; 77.18 VM.STM - timed requests........................... 194
; 77.19 Set TTY: up for this read......................... 195
; 77.20 Set Unsolicited mode.............................. 196
; 77.21 Set CHRTAB........................................ 197
; 77.22 Handle special characters......................... 198
; 77.23 VMS.AT - Send Attention........................... 199
; 77.24 VMS.ST - Set characteristics/mode................. 200
; 77.25 VMS.NI - Unsolicited Data Message................. 201
; 77.26 Checkout-of-band character........................ 202
; 77.27 Check ^R, ^U, and <RUB>........................... 203
; 77.28 Out-of-band ATTN.................................. 204
; 77.29 VMS.BC - Broadcast data........................... 205
; 77.30 VMS.SN - Sense Mode message....................... 206
; 77.31 Return unsupported................................ 207
; 78. TOPS-10/20 support
; 78.1 Network service................................... 208
; 78.2 TTY: service...................................... 209
; 78.3 Timer service..................................... 210
; 78.4 Initialization.................................... 211
; 79. Unsupported System support................................ 212
; 80. O/S Name table............................................ 213
; 81. Protocal Dispatch Blocks
; 81.1 RSTS.............................................. 214
; 81.2 RSX............................................... 215
; 81.3 VMS............................................... 216
; 82. Lowseg Initializers Stored in Hiseg....................... 217
; 83. NSP. Connect Block........................................ 218
; 84. Special stuff for VAX..................................... 222
; 85. Special stuff for RSX..................................... 223
; 86. Useful break masks........................................ 224
; 87. Terminal information tables............................... 225
; 88. Terminal strings for <RUB>................................ 226
; 89. Literal storage........................................... 227
; 90. STORAGE................................................... 228
; 91. NSP. UUO DSTPDB Block..................................... 230
; 92. Configuration & Control Messages.......................... 231
; 93. Performance analysis low segment.......................... 232
; 94. Low segment for Interrupt system.......................... 233
; 95. .JBINT stuff.............................................. 234
; 96. Data base for timed I/O requests.......................... 235
; 97. Low segment for core manager.............................. 236
; 98. Low segment AC blocks and PDLs............................ 237
; 99. End of Program............................................ 238
SUBTTL .EXE File Copyright
COPYRIGHT (C) DIGITAL EQUIPMENT CORPORATION 1984.
SUBTTL AC Definitions
F=0 ;Flag register
T1=1 ;THE TEMPS
T2=2
T3=3
T4=4
P1=5 ;THE (NEVER) PRESERVED
P2=6
P3=7
P4=10
CX==11 ;SCRATCH AC
;The following ACS are for use with NSP. argument blocks.
NSAFN=12 ;Function Type
NSACH=13 ;Channel Number
NSAA1=14 ;First argument word
NSAA2=15 ;Second argument word
NSAA3=16 ;Third argument word
P=17 ;STACK POINTER
SUBTTL Flag definitions in F
F$IOQ==1B0 ;Inhibit queueing of output buffers
F$UAST==1B1 ;User wants unsolicted input
F$NEC==1B2 ;No-echo
F$LEM==1B3 ;(VMS) Nofilter=set IO.LEM
F$ESC==1B4 ;User wants escape sequence processing (VMS, RSX)
F$ESA==1B5 ;Escape sequence being processed
F$PIM==1B6 ;Set TTY: to PIM mode
F$XPT==1B7 ;EXPerT mode
F$IEC==1B8 ;Ignore LDBECC at TOOUT
F$NEOM==1B9 ;Not EOM on NSP.
F$PERF==1B10 ;We are doing a performance test
F$PION==1B11 ;PSISER is on
F$BRK==1B12 ;Saw a break character (SCNSPC)
F$CTO==1B13 ;Control-O in effect
F$P2==1B14 ;General PASS2 flag (core allocator, SCNLCH)
F$CAST==1B15 ;VMS user wants to see ^C
F$YAST==1B16 ;VMS user wants to see ^Y
F$READ==1B17 ;Read request outstanding (mostly VMS)
F$TMR==1B18 ;Timeout active (RSX)
F$PALL==1B19 ;Passall (even if in line mode)
F$RALL==1B20 ;Temporary passall (READALL, VMS)
F$FLF==1B21 ;(VMS)Free <LF> may be needed
F$ICO==1B22 ;Ignore setting of ^O bit (one time)
F$RUB==1B23 ;I need to process rubout,^R, and ^U
F$ACO==1B24 ;Allow ^O in mask (for RSTS)
F$TEX==1B25 ;Timeout expired (RSX)
F$SCM==1B26 ;(RSX) Single character mode
F$CVL==1B27 ;Temporary CVTLOW. **MUST=VAX CVTLOW**
F$BAD==1B28 ;Terminating due to bad escape sequence
F$NDB==1B29 ;Don't do a DEBRK. (TTY: service)
F$USRV==1B30 ;TTY service call requested at non-PSI level
F$CLF==1B31 ;(VMS, RSX) Free <LF> already given
F$EOMN==1B32 ;(T10/20) Don't put EOM except on last message
F$RU1==1B33 ;First time through unsolicited code (after request
;is enabled)
F$NLF==1B34 ;Don't allow extra <LF> on <CR> to be generated
F$FRC==1B35 ;TTY: service wants to be called even if no chars
SUBTTL Operating System (Returned in CONFIG message)
OST10==11 ;TOPS-10
OST20==10 ;TOPS-20
OSVMS==7 ;VAX/VMS
OSRST==2 ;RSTS
OS11M==4 ;RSX-11M
OSIAS==6 ;IAS
OSUTX==22 ;ULTRIX-32
MAXOS==22 ;Maximum value for an OS type
SUBTTL Constant definitions
PDLLEN==100 ;STACK LENGTH
TTBFSZ==100 ;TTY OUTPUT BUFFER SIZE.
SUBTTL Device channel definitions
$TTY==6 ;Devices
$SWI==7 ;SWITCH.INI
IFN FTPERF,<
$PRF==7 ;Performance analysis (can't read SWITCH.INI then)
>
SUBTTL Internal input and output buffer block definitions
PHASE 0
IBF.LK: BLOCK 1 ;Length,,Link to next buffer
;Note that the length is NEGATIVE
;if this is the last block in the chain
IBF.CT: BLOCK 1 ;Count of characters in buffer
IBF.PT: BLOCK 1 ;Pointer into buffer
IBF.DT: ;Data starts here
DEPHASE
IF2,<
IFL OBUFSZ-%MINBF,<
PRINTX ?Output buffer size is too small
>
>
IFNDEF OBUFSZ,<OBUFSZ==200> ;Be able to do a big request
PHASE 0
OBF.CT: ;Current count to outputin LH,
OBF.LK: BLOCK 1 ;Link to next in RH
OBF.PT: BLOCK 1 ;Byte pointer
OBF.DT: BLOCK OBUFSZ ;Output buffer size
DEPHASE
PHASE 0
TOB.CT:
TOB.FL:
$TOICL==1B0 ;Immune to output queue flush
$TOOIN==1B1 ;Override inhibit output
$TOCNT==777B17 ;Count
TOB.LK: BLOCK 1 ;flags+Count,,link.
TOB.DT: ;Start of data area (run time determined size)
DEPHASE
SUBTTL UUO definitions
IFN FTDBUG,<
OPDEF PJ [260B8]
>
SUBTTL MACRO Definitions -- PLM MACROs
;PLM affiliated MACROs:
DEFINE PLM,<IF1,<>
IF2,<IFE LSTPLM,<XLIST>>>
DEFINE MLP,<IF1,<>
IF2,<IFE LSTPLM,<LIST>>>
IF1,<
DEFINE .LIT <
MLP
COMMENT ->
> ;End IF1
IF2,<
DEFINE .LIT <>
> ;End IF2
PLM
;+
MLP
; The following MACROS are defined for use in NRT:
;.list 1
;.le
;The PLM MACRO controls listing of the PLM in the source listing, as
;dictated by feature test switch LSTPLM. The MLP MACRO reverts normal listing
;if necessary. The .LIT and .EL MACROs are defined for the copyright notice
;at the beginning.
PLM
;-
MLP
SUBTTL MACRO Definitions -- FALL (Address)
PLM
;+
;.le
MLP
;The FALL MACRO is used to insure that the contiguity assumptions
;about routine addresses (so that the extra JRST is not required) are correct.
;FALL will print an error message if the assumption is incorrect.
PLM
;-
MLP
DEFINE FALL(ADDRESS),<
IF2,<IFN .-ADDRESS,<PRINTX ?Cannot fall into Routine 'ADDRESS>>
> ;End FALL
SUBTTL MACRO Definitions -- PJRST(X)
PLM
;+
;.le
MLP
;PJRST is defined elsewhere with an OPDEF unless FTDBUG is turned on.
;This is so that PJRSTs become traceable in a dump if a problem is being
;debugged. The PJRST macro turns off the optimization of turning a PUSHJ
;followed by a POPJ into a JRST.
PLM
;-
MLP
;PJRST is defined here only if FTDBUG is on so that PC stack tracing
;becomes easier
IFN FTDBUG,< ;For debugging only
DEFINE PJRST(X)<PUSHJ P,[PUSHJ P,X
POP P,(P)
POPJ P,]
>
>
SUBTTL MACRO Definitions -- ERR(PRE,MSG)
PLM
;+
;.le
MLP
;The ERR MACRO is used to define a fatal error condition for NRT.
;It assembles with a three letter mneumonic which expands the location
;calling the ERR MACRO into the symbol "E..sym". It calls the error
;routine specifying a prefix and a message for output. The error routine
;saves context for a possible dump and exits.
PLM
;-
MLP
DEFINE ERR(PRE,MSG,CONTIN<JRST NSPER1>)<
E..'PRE::PUSHJ P,[PUSHJ P,DOERR ;; Do an error message
CAI [ASCIZ |PRE|]
CAI [ASCIZ |MSG|]
CONTIN ]>
SUBTTL MACRO Definitions -- ERRMAC(code,pre,text)
PLM
;+
;.le
MLP
;ERRMAC is used to make the standard DECnet error message table.
PLM
;-
MLP
DEFINE ERRMAC(code,pre,text),<
IF1,<IFN code*2-<.-NSPERC>,<
PRINTX ?NSP. error code out of order in NSPERC table>>
[ASCIZ |pre|]
ERRMC1(\code,text)
>
DEFINE ERRMC1(code,text),<[ASCIZ |code; text|]>
SUBTTL MACRO Definitions -- FCNMAC - Table of NSP. function codes and text
PLM
;+
;.le
MLP
;FCNMAC is called to make the NSP. UUO function description table.
PLM
;-
MLP
DEFINE FCNMAC(code,text),<
IFN code-<.-FCNTAB>,<PRINTX ?NSP. function code out of order>
[ASCIZ /text/]
>
;MAX MACRO
DEFINE MAX(A,B)<
IFN <<A-B>&400000000000><B>
IFE <<A-B>&400000000000><A>
>
DEFINE SAVE(ACS)<
IRP <ACS><PUSH P,ACS>
>
DEFINE RESTORE(ACS)<
IRP <ACS><POP P,ACS>
>
SUBTTL MACRO Definitions -- Typeout MACROS
PLM
;+
;.le
MLP
;There are three MACROS for various forms of typeout:
;.list 1
;.le
;TYPE is called to output an ASCIZ string to the controlling terminal.
;.le
;TYPCRLF is called to output a carriage return-line feed to the controlling
;terminal.
;.le
;TSIX is called to output a SIXBIT string to the controlling
;terminal.
;.end list
PLM
;-
MLP
DEFINE TYPE(STR)<OUTSTR [ASCIZ `STR`]>
DEFINE TYPCRLF<OUTSTR [ASCIZ `
`]>
DEFINE TSIX(STR)<
PUSH P,STR
PUSHJ P,.TSIX
ADJSP P,-1
>
SUBTTL MACRO Definitions -- AC saving MACROS
PLM
;+
;.le
MLP
;There are many AC saving MACROS which call the appropriate routines.
;All of these macros use AC CX as a temporary AC:
;.list 1
;.le
;SAVE1 saves P1
;.le
;SAVE2 saves P1 and P2
;.le
;SAVE4 saves P1 through P4
;.le
;SAVET1 saves T1
;.end list
;There is also a routine, not called by a MACRO, to save all T ACs (SAVT).
PLM
;-
MLP
DEFINE SAVE1,<JSP CX,.SAV1>
DEFINE SAVE2,<JSP CX,.SAV2>
DEFINE SAVE4,<JSP CX,.SAV4>
DEFINE SAVET1,<JSP CX,.SAVT1>
SUBTTL MACRO Definitions -- Break masks
PLM
;+
;.le
MLP
;The BRKMSK MACRO is used to define a break mask for usage by NRT.
;The two arguments are a string of control characters to use as the mask
;(except for convenience the user types in the string with all the characters
;"uncontrolified", e.g., to put "^A" in the break mask, specify "A" as
;a character of the first argument to the MACRO) and the "regular" character
;string, which inclues all characters which are not control characters.
PLM
;-
MLP
DEFINE CTLMSK(STRING)<...BRK==0
IRPC STRING,<...BRK==...BRK!1B<"STRING"&^O37>>
>
DEFINE BRKMSK(CTLSTR,REGSTR)<
CTLMSK(CTLSTR)
BRMSK. (...BRK,,,,,'REGSTR')
>
SUBTTL MACRO Definitions -- ASSUME
PLM
;+
;.le
MLP
;The ASSUME MACRO is analagous to the FALL MACRO but is used for values
;rather than addresses.
PLM
;-
MLP
DEFINE ASSUME (A,B)<IF2 <
IFN <A-B>,<
PRINTX %Assumption wrong: 'A does not equal 'B
>
>
>
SUBTTL MACRO Definitions -- NETOCH macro - output character to network
PLM
;+
;.le
MLP
;The NETOCH MACRO is used to output one character to the network. It takes
;as arguments the AC containing the character and the address of the error
;routine if there is insufficient room in the current buffer. The default
;action taken if no error address is given is to queue the network buffer
;without outputting it and allocate a new buffer in which to continue
;depositing characters.
PLM
;-
MLP
DEFINE NETOCH (AC,ERRADR<[PUSHJ P,NETQUE
JRST .-1]>)<
PUSHJ P,[SOSGE OBFCTR
JRST ERRADR
IDPB AC,OBFPTR
POPJ P, ]
>
SUBTTL MACRO Definitions -- NETALC - Allocate contiguous buffer space
PLM
;+
;.le
MLP
;The NETALC MACRO is used to allocate space in the network output buffer
;without actually outputting anything. If the requested amount cannot be
;allocated in the current buffer, it is queued for output (but not output)
;and a new buffer is allocated. The requested allocated space is taken
;from the new buffer. Note that NETALC should not be called with a size
;bigger than the maximum buffer size. If this occurs, an error
;message will be output.
PLM
;-
MLP
DEFINE NETALC (SIZE)<
IFNDEF %MINBF,<
%MINBF==SIZE
>
IFG SIZE-%MINBF,<
%MINBF==SIZE
>
MOVEI CX,SIZE ;;How much he wants
SUBM CX,OBFCTR ;;Will it fit?
SKIPL OBFCTR ;;(Negative if so
JRST [PUSHJ P,NETQUE
JRST .-3] ;;Try allocate new buffer
MOVNS OBFCTR ;;Make right sign
ADJBP CX,OBFPTR
MOVEM CX,OBFPTR
>
SUBTTL MACRO Definitions -- OSDSP
PLM
;+
;.le
MLP
;The OSDSP MACRO is used to create a dispatch vector for the OSJMP table.
;The arguments to the OSDSP MACRO include the addresses of the operating
;specific initialization routine, network service routine, and TTY:
;service routine.
PLM
;-
MLP
DEFINE OSDSP (INIT,NETWORK,TTY)<
INIT,,[TTY,,NETWORK]
>
SUBTTL MACRO Definitions -- NAMTAB
PLM
;+
;.le
MLP
;The NAMTAB MACRO is used to generate a table of SIXBIT names with appropriate
;symbols for the beginning and length of the list (in words). It is used
;to generate tables for use by the .LKNAM routine. This routine is called
;when RESCANning the command line (to parse the possible commands
;by which NRT can be run), the SWITCH.INI support (to parse switches),
;and the exit dialogue in NOVICE mode.
PLM
;-
MLP
DEFINE NAMTAB(name,list),<
name'L==0
name'A:
IRP list,< name'L==name'L+1
EXP <SIXBIT |list|>>
>
SUBTTL MACRO Definitions -- TRMCHR
PLM
;+
;.le
MLP
;The TRMCHR MACRO is used to define a table of TTY: characteristics to
;save/restore/set.
;-
MLP
DEFINE TRMCHR (CHR,VAL,MNEU<SV>)<
T'MNEU'CHR: VAL,,.TO'CHR
>
SUBTTL MACRO Definitions -- VTTCHR
PLM
;+
;.le
MLP
;The VTTCHR MACRO is used to define a VAX terminal characteristic word.
;This word consists of the terminal type in the right half and the
;high order byte of the TT2 characteristics word in the left half.
;This assumes the ANSI/DEC CRT bit is in that byte. The args for the
;MACRO are the ANSI/DEC CRT bit to use and the (up to) three character
;suffix to the DT$xxx symbol for the terminal type.
PLM
;-
MLP
DEFINE VTTCHR (CRTBIT,TYPE)<
ASSUME T2ACRT,100000000
ASSUME T2DCRT,4000000000
<CRTBIT>_-^D24,,DT$'TYPE
>
SUBTTL MACRO Definitions -- ASCII8
PLM
;+
;.le
MLP
;ASCII8 makes eight-bit ASCII strings.
PLM
;-
MLP
DEFINE ASCII8 (TEXT),<
%%%LEN==0
%%%WRD==0
IRPC TEXT,<
%%%WRD==<%%%WRD_10>+<"TEXT"_4>
%%%LEN==%%%LEN+1
IFE %%%LEN-4,<
EXP %%%WRD
%%%WRD==0
%%%LEN==0
>
>
IFN %%%LEN,<
%%%WRD==%%%WRD_<<4-%%%LEN>*10>
EXP %%%WRD
>
>
PLM
;+
;.end list
;-
MLP
SUBTTL Start the Program
PLM
;+
;.HL 2 Section from GO to LPROMPT
MLP
; This section contains the first part of the initialization logic.
;It first sets up basic defaults and flags that this is the first time
;through (sets variable RSTFLG to -1). It then enters RESTRT, which is
;where the program restarts itself if fatal errors occur or the user
;attempts to continue the program from a non-continuable state. RESTRT
;(the label where restarting begins) sets up the pushdown list and reads
;the user's SWITCH.INI file (if present), resetting any defaults to
;those values. If restarting, we then go to label PROMPT for the short
;dialogue, otherwise we attempt to rescan the line and either take arguments
;from the rescanned line if successful or go to LPROMPT for the long
;dialogue if not. If the rescan is successful, we call
;INITDB to initialize NRT's database here and proceed directly to CHKPMR to
;attempt to set up the connection.
PLM
;-
MLP
GO: JFCL ;Ignore CCL entry
SETOM RSTFLG ;Use long dialogue if necessary
SETZ F,
RESTRT: MOVX T1,ER.ICC ;Turn of any left-over ^C
ANDCAM T1,ERRBLK+.ERCLS ;..
MOVEI T1,DEFESC ;Default escape char
MOVEM T1,ESCCHR ;
MOVE P,[IOWD PDLLEN,PDL] ;Set up A Stack
PUSHJ P,SWTINI ;Read SWITCH.INI
AOSE RSTFLG ;If restarting
JRST PROMPT ;Use short dialogue
RESCAN 1 ;Rescan the command line
PUSHJ P,DORSCN ;Go process the RESCAN line
JRST LPROMPT ;Error or no node name
PUSHJ P,INITDB ;Set up the data base
JRST CHKPMR ;Note that T2 still has first node name
SUBTTL LPROMPT - Long Dialogue
PLM
;+
;.hl Routine LPROMPT
MLP
; Routine LPROMPT is resposible for the long dialogue. Upon
;displaying the current "escape character" (which may be the assembled
;default or the default as obtained from the user's SWITCH.INI) and
;accepting a new one (if requested to by the user by typing a character
;other than <CR> to the question), we proceed to fall into the short
;dialogue (routine PROMPT).
PLM
;-
MLP
LPROMPT:
OUTSTR [ASCIZ /DECnet Intersystem Remote Terminal service
Escape character (/]
MOVE T1,ESCCHR ;Get escape character
CAIL T1," " ;Control?
JRST LPR0 ;No
OUTCHR ["^"]
MOVEI T1,100(T1)
LPR0: OUTCHR T1
OUTSTR [ASCIZ/): /]
LPR1: INCHRW T1 ;Get new character
CAIN T1,.CHCRT ;Carriage Return?
JRST LPR1 ;Get the LF
CAIE T1,.CHLFD ;Line feed?
MOVEM T1,ESCCHR ;Store escape character
PUSHJ P,CMPESC ;Compute mask for interrupt level
LPROM1: TYPCRLF ;Be friendly
FALL PROMPT ;Put out the normal prompt
SUBTTL PROMPT - Short initialization dialogue
PLM
;+
;.hl Routine PROMPT
MLP
; Routine PROMPT handles the short initialization dialogue. Note that
;the short dialogue is a subset of the long dialogue (which falls into here).
;After requesting the desired remote host's name from the user and inputting
;it, we fall into CHKPMR which establishes the connection. Note that we also
;initialize NRT's data base here.
PLM
;-
MLP
PROMPT: PUSHJ P,INITDB ;Init the data base
TYPE <Node Name: >
PRM2: PUSHJ P,SIXINW ;Get node name user wants
CAIN T1,.CHCNZ ;User want out?
JRST NSPER1 ;OK to continue
JUMPE T2,PROMPT ;Ignore null node name
FALL CHKPMR
SUBTTL Check for Poor Man's Routing in User's String
PLM
;+
;.hl Section from CHKPMR to DOPMR
MLP
; We enter this section from a number of points; most obviously by
;falling in from the short dialogue. However, we come here with the
;data base initialize and all values for escape character and
;initial node name set up. We check for Poor Man's Routing here;
;if the user specified it we go and parse the string before
;establishing the connection, otherwise we just establish the connection.
;We cue on the user having actually specified a double colon
;as the key to whether he specified PMR or not. The special case
;of the user specifying a double colon followed by a <CR> is checked
;for at DOPMR if FTPMR is turned off so that we don't bomb out
;the user on this special case. This routine is entered
;with T2 containing the name of the first remote node.
PLM
;-
MLP
CHKPMR: MOVEM T2,RNODE ;Save first node
CAIN T1,":" ;Is it a ":"?
INCHSL T1 ;Yes, get a character
JRST DOCONN ;Not PMR if no more characters
CAIE T1,":" ;Second colon?
JRST DOCONN ;Do the connect
FALL DOPMR ;Fall into appropriate PMR routine
SUBTTL DOPMR - Subroutine to do the Poor mans routine string
PLM
;+
;.hl Routine DOPMR
MLP
; Routine DOPMR is fallen into when CHKPMR decides that the
;user may have specified Poor Man's routing. If NRT has been assembled with
;FTPMR turned off, we check for the special case of the user
;typing a double colon followed by a carriage return. If this is the
;case, we proceed with the connection; if not we output an error
;message and exit.
;FTPMR is turned on, we parse the node names in the string and
;store them as sixbit values, one to a word, in the table starting
;at location RNODE. After parsing the string, we proceed to BLDPMR to actually
;build the string to send to the remote PSTHRU task.
PLM
;-
MLP
DOPMR:
IFE FTPMR,<
INCHSL T1
JRST DOCONN ;Nope
CAIN T1,.CHCRT ;<CR>?
JRST DOCONN ;Yes, then do the connect
CLRBFI ;Clear the input buffer
ERR NPM,<Version not compiled with Poor Man's Routing>
> ;End IFE FTPMR
IFN FTPMR,<
MOVE P1,[-<MAXPMR-1>,,1] ;Already have first node
PMRL1: SKPINL ;Anything inputable?
SOJA P1,BLDPMR ;Index
PUSHJ P,SIXIN ;Get the next name
JUMPE T2,.-2 ;If really nothing
MOVEM T2,RNODE(P1) ;Store the first one
CAIGE T1," " ;Printing?
JRST BLDPMR ;No, must be done
CAIE T1,":" ;Correct break?
ERR EDC,<Expecting Double colon in PMR string>
INCHSL T1 ;Get character
JRST E..EDC ;Oops
CAIE T1,":"
JRST E..EDC ;Oops again
AOBJN P1,PMRL1
ERR TMN,<Too many nodes in PMR string>
> ;End IFN FTPMR
SUBTTL BLDPMR - Builds the PMR string
PLM
;+
;.hl Routine BLDPMR
MLP
; Routine BLDPMR translates the node string which was parsed by
;DOPMR and stored as SIXBIT nodes in the RNODE table into an eight-bit
;ASCII string suitable for sending to the first node's PSTHRU task.
;It is entered from DOPMR only with P1 containing the maximum index
;into the RNODE table at which a node name was stored. This is
;equivalent to the number of nodes in the string minus one.
PLM
;-
MLP
IFN FTPMR,<
BLDPMR: HRRZM P1,NODCNT ;Store
MOVE P1,[POINT 8,PMRMSG] ;Get the PMR message
SETZ P3, ;Clear out a count
MOVEI T1,1 ;Start of PMR
AOS P3 ;Increment number of bytes
IDPB T1,P1 ;Put it into the string
MOVE P2,[POINT 6,RNODE+1] ;Get the pointer
BLD0: MOVEI T3,^D6 ;Six character maximum
BLD1: ILDB T1,P2 ;Get a byte from the node list
JUMPE T1,EATBLD ;Eat the rest and finish this one
BLD11: MOVEI T1," "(T1) ;Make it ASCII
AOS P3 ;Increment byte count
IDPB T1,P1 ;Store it
SOJG T3,BLD1 ;Loop for all of them
BLD2: MOVEI T1,":" ;Get the break
IDPB T1,P1
IDPB T1,P1 ;"::"
ADDI P3,2 ;Increment byte count by 2
BLD3: MOVEI T3,^D6 ;Get the number left
ILDB T1,P2 ;Get the first character
JUMPE T1,ENDPMR ;End of the string
JRST BLD11 ;Loop around to store this one too
EATBLD: SOJLE T3,BLD2 ;Put the break
ILDB T1,P2 ;Get the next byte
JRST EATBLD ;End check
ENDPMR: MOVE P2,[POINT 7,[ASCIZ |"23="|]] ;Get the ending string
ENDPM1: ILDB T1,P2 ;Get the byte
JUMPE T1,ENDPM2 ;Do the connect if done
IDPB T1,P1 ;Put it intot he string
AOS P3 ;Increment the byte count
JRST ENDPM1 ;Loop around
ENDPM2: MOVEM P3,PMRMSG-1 ;Save the count
FALL DOCONN
> ;End IFN FTPMR
SUBTTL DOCONN - Initiatiate a DECnet connection
PLM
;+
;.hl Section from DOCONN to MAIN
MLP
; We enter here with all of NRT's data base set up to do final
;initialization and initiate the connection to the remote system.
;We first OPEN device TT: and initialize the core manager.
;We check to see if the user is attempting to connect
;to the same node on which he is running; if so we issue a warning before
;proceeding. We set up the network I/O buffers and call CONECT to initiate
;the connection to the remote node. After a [successful] return from
;CONECT, we read the configuration message. We add all the appropriate
;things the software interrupt system, set up ^C trapping through .JBINT
;(we actually trap on any job error or control-C; although the terminal
;is slaved one can use a FRCUUO function of .HALT to force the program
;to trap in case it gets stuck; this is useful for debugging purposes).
;We then use the information from the remote host's configuration message
;(in particular the operating system type) to set the
;addresses of the operating system specific network and TTY: routines.
;We then call the operating system specific initialization routine
;and call FRCTTY to get things started.
PLM
;-
MLP
DOCONN: PUSHJ P,TTYOPN ;OPEN the TTY: now
HRRZ T1,.JBFF
SOJ T1,
IORI T1,777 ;Round to page boundary
MOVEM T1,HICORE ;For core allocator
SETZM FRELST ;Clear free core pointer
MOVX T2,<DN.FLE!<.DNLNN,,.DNNMS+1>>
MOVEM T2,NODBLK+.DNFFL
MOVEI T2,NODBLK ;Get the argument pointer
DNET. T2, ;Do the UUO
JRST DOCN1 ;Do the connect anyway
IFN FTPMR,<
MOVE T2,NODCNT ;If PMR, get last node
MOVE T2,RNODE(T2)
>
IFE FTPMR,<
MOVE T2,RNODE
>
CAME T2,NODBLK+.DNNMS ;Is it this node?
JRST DOCN1 ;No, no warning
OUTSTR [ASCIZ |
%Already at node |] ;Give a message
PUSHJ P,TNODE1 ;Type it out
OUTSTR [ASCIZ | - Proceeding with connection anyway.
|]
DOCN1: PUSHJ P,INIOBF ;INITIALIZE THE FAKE BUFFERS
PUSHJ P,CONECT ;SET UP THE CONNECTION
OPTTY: MOVEI T1,REENTR ;Get routine to handle
MOVEM T1,.JBREN ;Save it
PUSHJ P,GETCFG ;Get the configuration stuff
MOVE T1,OSTYPE ;Get the Operating system type
MOVE T1,OSJMP(T1) ;Point to proper routine
MOVE T2,(T1) ;Get TTY routine,,NETWORK routine
HRRZM T2,OSNET ;Save address of network routine
HLRZM T2,OSTTY ;And TTY: routine
HLRZ T1,T1 ;Point to initialization routine
PUSHJ P,(T1) ;Call it this time
MOVE CX,[PS.FAC!PSYNSP]
PISYS. CX,
ERR CDP,<Can't add DECnet NSP. traps to PSISER>
MOVE NSAFN,[.NSFPI,,.NSAA1+1] ;Now set psi mask
MOVEI NSAA1,(NS.NDA!NS.STA!NS.NDR) ;Just tell me when things can be read
MOVEI T1,NSAFN
NSP. T1,
ERR NPI,<NSP. UUO to set PSI mask failed>
MOVE CX,[PS.FAC!PSYTMR] ;Add timer traps too
PISYS. CX,
ERR CAT,<Can't add TIMER traps to PSISER>
PUSHJ P,SETTTY ;Slave the TTY:
MOVEI T1,ER.ICC ;Trap now
IORM T1,ERRBLK+.ERCLS ;..
PUSHJ P,TTYSST ;Set TTY: up
MOVEI T1,.TOCIB
MOVE CX,[2,,T1]
MOVE T2,TTYUDX
TRMOP. CX,
JFCL ;Try to make PIM happy
PUSHJ P,FRCTTI ;Wake us up
PUSHJ P,PSION ;Turn on the PI
SUBTTL MAIN - Main wait loop for all systems
PLM
;+
;.hl MAIN loop (section from MAIN to FRCTTY)
MLP
; The MAIN loop is simply a HIBER UUO. We expect to be woken by
;PSI interrupts when any events of any significance occur.
; The exception to this is a break mask change. This most
;often occurs at network interrupt level. Unfortunately, if type-ahead
;in the input buffer does not satisfy the current break mask, but the break
;mask is then changed so that the existing type-ahead now fulfils the
;current break mask, the monitor does not grant a PSI interrupt. Therefore,
;NRT traps for WAKE UUOs as well as any other conditions and WAKEs itself
;and sets F$USRV (via a call to FRCTTY) if it wishes to force a TTY: interrupt.
;MAIN always returns to sleep if woken.
PLM
;-
MLP
MAIN: MOVSI T1,(HB.RWJ) ;Defend against others
HIBER T1, ;OR UNTIL SOMETHING HAPPENS
JFCL
JRST MAIN ;Go look for more to do
SUBTTL FRCTTY - Force a look at the TTY:
PLM
;+
;.hl Routines FRCTTY and FRCTTI
MLP
; As mentioned above, since changing the break mask doesn't
;cause a PSI interrupt if input is done, we need to wake ourselves
;and set F$USRV. Routine FRCTTY is called to do this, or any
;other time we wish to act as if a TTY: service PSI occured. Enter
;at label FRCTTI to be sure PS.RID gets set in TTYSTS, or call
;FRCTTO to be sure PS.ROD gets set in TTYSTS. It uses T1.
PLM
;-
FRCTTO: SKIPA T1,[PS.ROD]
FRCTTI: MOVEI T1,PS.RID
IORM T1,TTYSTS ;Set the bit
FRCTTY: TXOE F,F$USRV ;Set flag
POPJ P, ;Already done
SETO T1, ;Wake ourselves
WAKE T1, ;..
TXZ F,F$USRV ;Oops
POPJ P, ;Return
SUBTTL OSJMP - Dispatch table for systems
PLM
;+
;.hl OSJMP table
MLP
; The OSJMP table uses the OSDSP MACRO to define the transfer
;vectors for each type of operating system. See the documentation of
;the OSDSP MACRO for further details. The OSJMP table is a table of
;OSDSP vectors indexed by operating system type.
PLM
;-
MLP
OSJMP: OSDSP RST.IN,RST.NT,RST.TT ;RSTS/E
OSDSP DORT11,DORT11,DORT11 ;RT-11
OSDSP RST.IN,RST.NT,RST.TT ;RSTS-E
OSDSP RSX.IN,RX.NET,RSX.TT ;RSX11-S
OSDSP RSX.IN,RX.NET,RSX.TT ;RSX11-M
OSDSP RSX.IN,RX.NET,RSX.TT ;RSX11-D
OSDSP RSX.IN,RX.NET,RSX.TT ;IAS
OSDSP VMS.IN,VMS.NT,VMS.TT ;VAX/VMS
OSDSP T10.IN,T20.NT,T20.TT ;TOPS-20
OSDSP T10.IN,T10.NT,T10.TT ;TOPS-10
OSDSP DORTS8,DORTS8,DORTS8 ;RTS-8
OSDSP DOOS8,DOOS8,DOOS8 ;OS-8
OSDSP DORXMP,DORXMP,DORXMP ;RSX-M+
OSDSP DOCOPOS,DOCOPOS,DOCOPOS ;COPOS
OSDSP DOPS11,DOPS11,DOPS11 ;P/OS
OSDSP DOELAN,DOELAN,DOELAN ;VAX/ELAN
OSDSP DOCPM,DOCPM,DOCPM ;CP/M
OSDSP DOMSDS,DOMSDS,DOMSDS ;MS-DOS
OSDSP UTX.IN,UTX.NT,UTX.TT ;ULTRIX-32
OSDSP DOUX11,DOUX11,DOUX11 ;ULTRIX-11
SUBTTL Initialization subroutines -- Initialize the Data Base
PLM
;+
;.hl Routine INITDB
MLP
; The INITDB subroutine is called at initialization time to
;initializae the low segment data base.
;It is also this routine's responsiblity to intialize the software
;interrupt system. It sets up the AC sets and pushdown
;lists for the interrupt level routines. It turns of control-C trapping
;(in case this was a restart) so that the user can easily exit
;at this time. It figures the bit mask position and word for the
;escape character so that it can be added easily to any break mask
;at interrupt level. It destroys only AC CX.
PLM
;-
MLP
INITDB: PUSHJ P,SAVT ;Save everything
SETZM TIBUF ;So won't try to reset
RESET ;Clear the world now
MOVEI T1,VECBAS ;Get the base of the block
PIINI. T1, ;Error
ERR PIF,<PIINI. UUO failed>
SETZM OSTMR ;No timer stuff yet
SETZM ERRBLK+.EROPC ;Be sure we trap again
STORE T1,FSTZER,LSTZER,0 ;Clear out the zeroable low segment
MOVE T1,[HILOST,,LOLOST] ;Setup Nonzero stuff in loseg
BLT T1,LOLOND ;
SETOM INTLVL ;Interrupt level is available
SETOM LICHCT ;For those who use it
MOVEI T1,.NSDOB+1 ;Get the length of a PDB
MOVEM T1,DSTPDB+.NSDFL ;Store it
SETZM DSTPDB+.NSDFM ;This is the format type
PUSHJ P,CMPESC ;Compute escape bit and mask
SETZM .JBREN ;Tell REENTER its not OK to REENTER
MOVE T1,[IOWD PDLLEN,TTYPDL] ;TTY: PDL pointer
MOVEM T1,TTYACS+P ;Set up all interrupt stacks
MOVE T1,[IOWD PDLLEN,NSPPDL] ;NSP pointer
MOVEM T1,NSPACS+P
MOVE T1,[IOWD PDLLEN,TMRPDL]
MOVEM T1,TMRACS+P
MOVE T1,[PS.FAC![ .PCDAT
DATVEC-VECBAS,,0
2,,0 ]] ;Higher priority
PISYS. T1,
JFCL
MOVE T1,[PS.FAC![ .PCWAK
WAKVEC-VECBAS,,0
Z ]]
PISYS. T1,
ERR CWT,<Can't add PSI WAKE. Traps>
POPJ P, ;Only return
SUBTTL Initialization subroutines -- Process RESCAN Input
PLM
;+
;.hl Routine DORSCN
MLP
; The DORSCN routine parses input as RESCANed from the command line.
;NRT may be run with a variety of command forms; this is so that those
;used to different conventions may find it easy to HOST out to another system.
;The exact commands which may be used are defined with the NAMTAB MACRO.
PLM
;The ways NRT may be run include:
;.list 1
;.le
;SET HOSTESS node
;.le
;HOST node
;.le
;NRT node
;.le
;TO node
;.le
;R or RUN NRT
;.le
;START
;.le
;DEAR
;.end list
;-
MLP
NAMTAB LIST1,<SET,RUN,START,NRT,HOST,TO,DEAR> ;FIRST TOKEN
NAMTAB LIST2,<HOSTESS> ;AFTER "SET"
DORSCN: SAVE1 ;Save P1
PUSHJ P,SIXIN ;Get SIXBIT Token From INCHRL
JUMPE T2,DORSCE ;If Nothing There, Error Return
MOVE P1,T1 ;Save Delimiter in P1
MOVE T1,[-LIST1L,,LIST1A]
PUSHJ P,.LKNAM ;See If T2 Holds One of these names
JRST DORSCE ;No, Eat rest of line
JRST @[ DORSC1 ;"SET"
DORSC2 ;"RUN"
DORSC2 ;"START"
DORSC3 ;"NRT"
DORSC3 ;"HOST"
DORSC3 ;"TO"
DORSC3](T1) ;"DEAR"
;Here if the first token was "SET", delimiter in P1
DORSC1: PUSHJ P,SIXIN ;Get "HOSTESS"
JUMPE T2,DORSCE ;No?
MOVE P1,T1 ;Save delimiter for DORSCE
MOVE T1,[-LIST2L,,LIST2A]
PUSHJ P,.LKNAM ;Is it HOSTESS or Some Abbrev?
JRST DORSCE ;No
JRST DORSC3 ;Yes, Get node name now
;Here if the first token was "RUN", delimiter in P1
DORSC2: CAIE P1,"-" ;Was Program name defaulted
CAIN P1,"(" ;with Either - OR (?
JRST DORSC3 ;Yes, Go get Node name
CAIGE P1," " ;If control
JRST DORSCE ;Error return
PUSHJ P,SIXIN ;No, get program name
MOVE P1,T1 ;Get delimiter again (For DORSCE Too)
JUMPE T2,DORSCE ;Error return if None
JRST DORSC2 ;Ignore node name, try again for delimiter
;Here if the next token is the node name we're after
DORSC3: PUSHJ P,SIXIN ;Get node name
MOVE P1,T1 ;SAVE DELIMITER FOR DORSCE
JUMPN T2,CPOPJ1 ;SUCCESS RETURN IF NAME IS THERE
JRST DORSCE ;NONE, ERROR RETURN
;Here if we had an error in the RESCAN, eat rest of line & return
DORSCE: MOVE T1,P1 ;SET UP FOR DORSE1
DORSE1: CAIE T1,.CHLFD ;CRLF YET?
CAIN T1,.CHESC ;OR ESCAPE?
POPJ P, ;Yes, error return now
INCHSL T1
POPJ P, ;Return now if no more chars to read
JRST DORSE1 ;LOOP UNTIL EOL
SUBTTL FNDFNC - Find function routine
PLM
;+
;.hl Routine FNDFNC
MLP
; The FNDFNC routine is provided to dispatch to an address based
;on a value which must not be consecutive. It is called with the table's
;base address in P1 and the value to match on in T1. The format of the
;table it uses is:
PLM
;.lm 20.nofill.noautop.tp 7.bl 1
MLP
; TABLE: value,,address
; value,,address
; .
; .
; .
; 0
PLM
;.just.autop.lm 5.bl 1
MLP
;It returns CPOPJ if the function was not found or CPOPJ1 (after
;dispatching) if it was.
PLM
;-
MLP
FNDFNC: SKIPN CX,(P1) ;Anything?
POPJ P, ;Yes, then give unsupported return
CAIE T1,(CX) ;Are they the same?
AOJA P1,FNDFNC ;Loop for all of them
HLRZS CX
PUSHJ P,(CX) ;Go handle it
JFCL ;Skip return is possible but not error
JRST CPOPJ1 ;And skip return when done
SUBTTL NETCHR - Output a stream of network data to TTY
PLM
;+
;.hl Routine NETCHR
MLP
; The NETCHR routine is used by the TOPS-10 and TOPS-20 network
;service. It takes all characters from the network input buffer
;and outputs then on the TTY:. It also calls RECRSP to record
;response times if the user is running a performance analysis experiment.
;It exits through DOOUT1 to force out the last buffer to the TTY:.
;It uses T1, CX, and the NSP. ACs. NETCHR will grant a TTY: interrupt
;via TTYPS1 if it notices F$USRV is on.
PLM
;-
MLP
NETCHR:
IFN FTPERF,<
TXNE F,F$PERF ;Doing perf analysis?
PUSHJ P,RECRSP ;Yes, record response time
> ;End FTPERF
NETCH1: PUSHJ P,NETICH ;Read 1 byte from remote
PJRST DOOUT1 ;Finish up
TXZE F,F$USRV ;Want an interrupt?
PUSHJ P,TTYPS1 ;Grant a TTY: interrupt
TXNN F,F$CTO ;If supposed to flush
PUSHJ P,OUTTTY ;Output character to TTY
JRST NETCH1 ;Go see if there are more chars
SUBTTL Exit Routines -- MONITO (Exit Dialogue)
PLM
;+
;.hl Routine MONITO
MLP
; MONITO is responsible for handling the exit dialogue. It uses
;all T ACs and CX. It is called by the operating system dependent
;TTY: service routine when the user types the break character. It outputs
;the appropriate exit dialogue based on the setting of the user's /MODE
;switch (which translates into flag F$XPT and location NOTICH: F$XPT only is
;non-zero for /MODE:EXPERT and both F$XPT and NOTICH are non-zero for
;/MODE:NOTIFY, and both are zero for /MODE:NOVICE).
;In the case of the "M[onitor]/(CONTINue,REENTEr)", "P[ass]", "O[bscure]",
;"R[econnect]", or "C[hange]" commands, MONITO returns to the caller
;with the escape character in T1. For the "P[ass]" command,
;MONITO returns CPOPJ1 to flag to the caller
;to pass the escape character through to the remote host. For the other
;commands, MONITO returns CPOPJ to inform the caller to proceed as
;if the escape character had not been typed. It is, however, the
;caller's responsibility to remove the break character from any internal
;input stream if that is applicable.
; MONITO has an additional entry point, MONITC, which can be used
;to pass the command character (assuming expert or notify modes) which
;will be "input" to the command parser. The character is passed in T3
;or is passed as zero if there is none.
PLM
;-
MLP
MONITO: SETZ T3, ;No character input
MONITC: PUSHJ P,PIOSAV ;Turn off the PI
PUSH P,T3 ;Save character, if any
PUSHJ P,TTYRST ;Reset the TTY
POP P,T3 ;Restore character
IFN FTPERF,<
TXZ F,F$PERF ;Clear the performance flag
SETZM TSTPTR ;Zero out the pointer
> ;End IFN FTPERF
TXNN F,F$XPT ;Expert mode?
JRST MONIT0 ;Below only for experts
SETO T1, ;Controlling TTY:
GETLCH T1 ;Get TTY: characteristics
TXO T1,GL.NEC ;Turn off echo
SETLCH T1 ;..
JRST EXCT0 ;Skip typeout
MONIT0: TYPE <
[Connection broken, Back at node > ;Type out the header
MOVE T2,NODBLK+.DNNMS ;Get the sixbit local node name
PUSHJ P,TNODE1 ;Type out the node name
TYPE <::]> ;Type this out
EXCOPT: TXNN F,F$XPT ;Want message?
OUTSTR [ASCIZ/
NRT_EXIT> /] ;Yes
EXCT0: SKIPE T1,NOTICH ;Want notification?
OUTSTR (T1) ;Output the string
EXCT1: TXNE F,F$XPT ;Expert?
SKIPA T2,[INCHRW T1] ;Yes
SKIPA T2,[INCHWL T1] ;No
SKIPN T1,T3 ;If any character
XCT T2 ;Get the character
TXNE F,F$XPT ;Expert mode?
CAME T1,ESCCHR ;Yes, is this escape character?
TRNA ;No or no
MOVEI T1,"P" ;Make "P" command then
CAIN T1,.CHCRT ;Have a CRLF?
INCHSL 1(P) ;Eat LF
CAIGE T1," " ;Printing?
JRST NSPER1 ;No, exit
EXCT2:
CAIL T1,"a" ;Lower case?
SUBI T1,"a"-"A" ;Make it UC
EXCOP1: MOVEI T2,-<" "-' '>(T1) ;Convert to SIXBIT
LSH T2,5*6 ;Left justify
TXNE F,F$XPT ;No eats in expert mode
JRST EXCOP2 ;No eats nor SIXIN
PUSHJ P,SIXINA ;Input token
EXCOPX: CAIE T1,.CHCRT ;CR?
CAILE T1," " ;Noise?
INCHSL T1 ;Must eat more
JRST EXCOP2 ;No more to eat
JRST EXCOPX ;Continue
EXCOP2: MOVE T1,[-EXITL,,EXITA] ;Exit function table
PUSHJ P,.LKNAM ;Lookup
JRST EXCP2A ;Not found
SKIPL T1,EXITDS(T1) ;Change status? Get entry.
TXNN F,F$XPT ;Expert mode?
JRST (T1) ;Don't bother if no-echo anyway
SETO T3, ;Controlling TTY:
GETLCH T3
TXZ T3,GL.NEC
SETLCH T3
JRST (T1) ;Dispatch
EXCP2A: TXNN F,F$XPT ;Expert?
OUTSTR [ASCIZ/
%Illegal command, type "H"<CR> for Help/]
SETZ T3, ;No rescans this time
JRST EXCOPT ;Ask again
SUBTTL Exit Routines -- Dispatch Table
PLM
;+
;.hl Exit Routine Dispatch Tables
MLP
; This set of tables associates the exit routine keywords with
;the appropriate dispatch vectors. It is assembled to be scanned
;via .LKNAM. The dispatch vectors table entries consist of the
;address of the routine in the right half, and the sign bit in the
;left half iff the routine does not want the echo mode changed
;before execution of the actual command (the echo mode may have
;been explicitly turned off due to the setting of F$XPT).
PLM
;-
MLP
NAMTAB EXIT,<EXIT,REENTER,PASS,CHANGE,MONITOR,HELP,OBSCURE>
EXITDS: NSPER1 ;Exit
G0 ;Reenter
GX ;Pass
REENTR ;Change
EXCOP3 ;Monitor
400000,,EXCHLP ;Help
FLUSH ;Flush network messages
IFN .-EXITDS-EXITL,<
PRINTX %Wrong number of EXIT functions
>
SUBTTL Exit Routines -- Help Routine
PLM
;+
;.hl Routine EXCHLP
MLP
; This routine outputs the appropriate help text ("H[elp]" command)
;and re-enters the exit dialogue.
PLM
;-
MLP
EXCHLP:
IFN FTPERF,<
OUTSTR [ASCIZ |
E - To exit to monitor and close the current link.
H - To type this text.
M - To Exit to monitor and leave link open.
P - To continue and pass the break character to the system.
R - To reconnect to remote system
O - To flush network output (TOPS-10/TOPS-20 only).
C - To change break character and continue or enter performance mode.|]
> ;Performance text
IFE FTPERF,<
OUTSTR [ASCIZ |
E - To exit to monitor and close the current link.
H - To type this text.
M - To Exit to monitor and leave link open.
P - To continue and pass the break character to the system.
R - To reconnect to remote system
O - To flush network output (TOPS-10/TOPS-20 only).
C - To change break character and continue.|] ;End of text message
> ;No performance test
TXNE F,F$XPT
TYPCRLF ;Look pretty
SETZ T3, ;No character already read
JRST EXCOPT ;And back to the question
SUBTTL Exit Routines -- Flush Network Messages
PLM
;+
;.hl Routine FLUSH
MLP
; FLUSH is called to flush network messages ("O[bscure]" command;
;TOPS-10/20 only). This is in lieu of ^O working "correctly" for TOPS-10/20
;connections.
PLM
;-
MLP
FLUSH: MOVE T1,OSTYPE ;Get the OS type
CAIE T1,OST10 ;TOPS-10?
CAIN T1,OST20 ;or TOPS-20?
JRST DOFLSH ;Yes
ERR N10,<Not connected to TOPS-10 or TOPS-20, command ignored>,<POPJ P,>
PJRST G0 ;Toss it
DOFLSH: PUSHJ P,CLRTOQ ;Clear the TO queue etc.
MOVEI T1,T10.TM ;Set the routine
MOVEM T1,OSTMR ;..
TXO F,F$CTO ;Set flag
MOVEI T4,[ASCIZ/[^O]
/]
MOVE T1,[3,,T2]
MOVEI T2,.TOOUS
MOVE T3,TTYUDX
TRMOP. T1,
JFCL ;In case I/O mode was different
PUSHJ P,T10.TM ;Boot it up
PJRST G0 ;And reconnect
SUBTTL Exit Routines -- Return to Monitor
PLM
;+
;.hl Routine EXCOP3
MLP
; EXCOP3 is used to return to monitor level ("M[onitor]" command).
PLM
;-
MLP
EXCOP3: OUTSTR [ASCIZ |
[CONTINUE to resume connection, REENTER to change escape character]
|]
MONRT. ;CALL THE MONITOR
CLRBFI ;Eat junk
FALL G0 ;Continue the session
SUBTTL Continue Remote Session
PLM
;+
;.hl Section from G0 to REENTR
MLP
; This section is entered when the user wishes to continue
;the program from the exit dialogue. Enter at label G0 with F$PERF set
;appropriately for entering performance analysis mode. Enter at GX
;to pass the break character through to the host (i.e. to give skip
;return to the caller). This routine outputs the necessary messages
;and returns to the caller (of MONITO) with T1 containing the escape
;character.
PLM
;-
MLP
G0:
IFN FTPERF,<
TXNN F,F$PERF ;Are we doing performance testing
>
JRST G1 ;No
IFN FTPERF,<
MOVEI T1,[ASCIZ/
[Performance testing for /]
JRST G2 ;Tell him what we're doing
> ;End IFN FTPERF
GX: AOS (P) ;Flag to pass character
G1: TXNE F,F$XPT ;Expert mode?
JRST G3 ;Return
MOVEI T1,[ASCIZ/
[Reconnected to /]
G2: OUTSTR (T1)
MOVE T3,OSTYPE ;Type it out right
TSIX OSNAME(T3) ;Type out the operating system
TYPE < system >
IFE FTPMR,SETZ T2, ;Zero if not using PMR
IFN FTPMR,MOVE T2,NODCNT ;Get the number of nodes
MOVE T2,RNODE(T2) ;Get the last node name
PUSHJ P,TNODE1 ;And type that out
TYPE <::]> ;And the close
TYPCRLF
G3: PJOB T1, ;Get current job
MOVNS T1 ;For JOBSTS
JOBSTS T1, ;Get word
SETZ T1,
SKIPL TTYUDX ;Detached?
TLNN T1,(JB.UML) ;No, at monitor level?
JRST G4 ;Detached or at user level, proceed
SETZ T1,
OUTCHR T1 ;(We couldn't have reset PIM yet)
CLRBFI ;Make PIM happy
G4: SETSTS $TTY,@TTYBLK ;TTYSST will do this, but could get
;confused if we were in PIM and output
;can get garbled.
PUSHJ P,TTYSST ;Reset TTY: status
PUSHJ P,SETTTY ;Slave TTY:
MOVE T1,ESCCHR ;Get the escape character
TXNE F,F$PIM
POPJ P, ;No ^O if PIM
TXZ F,F$ICO
PJRST SETCTO ;Set ^O and return
SUBTTL REENTR - REENTR code
;PLM
;+
;.hl Routine REENTR
MLP
; This section is entered when the user wishes to change the escape
;character. This is if the user either enters the "C[hange]" command
;to the exit dialogue or REENTErs after a "M[onitor]" command to the
;exit dialogue. We output the correct prompt here and perhaps the
;option of entering performance analysis mode, if the user is logged
;in and NRT is assembled with FTPERF turned on. We exit with
;the new escape character set to label G0 (or through DOPERF if the
;user requests performance analysis). If the escape character is changed,
;we compute the new bit mask and word position here.
PLM
;-
MLP
REENTR: OUTSTR [ASCIZ /Enter new escape character/]
IFN FTPERF,<
PJOB T2, ;Me
MOVNI T2,(T2)
JOBSTS T2, ;Am I logged in?
SETO T2, ;Assume I am
TXNE T2,JB.ULI ;?
OUTSTR [ASCIZ | or [P] to enter performance test mode|]
> ;End IFN FTPERF
REN1: OUTSTR [ASCIZ |: |] ;And the close
INCHRW T1 ;Get new character
TYPCRLF
JUMPE T1,REENTR ;Start over if <NUL>
IFN FTPERF,<
TXNN T2,JB.ULI ;Only if logged in
JRST REN2
CAIE T1,"p" ;Lower case OK
CAIN T1,"P" ;Is this the performance stuff
JRST DOPERF ;Yes, then do it
>
REN2: CAIN T1,15 ;Carriage Return?
JRST [INCHRS T1 ;Yes, get its LF
JFCL ;(What? no LF)
JRST REENT1] ;and leave old escape chr
MOVEM T1,ESCCHR ;Store escape character
PUSHJ P,CMPESC
REENT1: TYPCRLF ;Yes, Add a CRLF
PUSHJ P,TYPESC ;Say what the escape is
JRST G0 ;Continue where ^C interrupted
SUBTTL Performance analysis -- Start session
PLM
;+
;.hl Routine DOPERF
MLP
; This routine is entered when performance analysis has been requested.
;It opens the file DSK:NETRSP.DAT for append access and asks the user
;for the comment string for the record and the number of times to
;send the performance analysis string. It checks to be sure we are
;talking to a TOPS-10 or TOPS-20 remote host and returns to the exit
;dialogue if so as performance analysis only works to those types of systems.
;We output the comment string and various environmental information
;to the data file, set F$PERF and return to G0 to continue the link.
PLM
;-
MLP
IFN FTPERF,<
DOPERF:
MOVE T2,OSTYPE ;Get what we are
CAIE T2,OST10 ;Must be -10
CAIN T2,OST20 ;Or -20
JRST PERFOK ;Is, let him do it
OUTSTR [ASCIZ/
%Performance analysis only works to TOPS-10 or TOPS-20 nodes
/]
JRST EXCOPT
PERFOK: INCHSL T1 ;Eat
JRST DOPR0
CAIN T1,.CHCRT ;Carraige return?
JRST PERFOK ;Loop then
CAIE T1,.CHLFD ;Line feed?
JRST PERFOK ;Go till we get one
DOPR0: OUTSTR [ASCIZ |
NRT Performance Diagnostic tool
|] ;Output a header
MOVX T1,<XWD FILHGH,FILBLK> ;BLT pointer for block
BLT T1,FILBLK+^D6 ;set it all up
MOVX T1,<SIXBIT |DAT|> ;Get the extension
MOVEM T1,PRFFIL+1 ;Save it
SETZM PRFFIL+2 ;Clear out the rest of the block
SETZM PRFFIL+3 ;For good measure
SETZM PRFFIL+4
SETZM FILBLK+.FOPAT ;No path block
MOVE T1,[XWD 7,FILBLK] ;Length,,pointer
FILOP. T1, ;get the file
ERR FUF,<FILOP. UUO failed to open performance file>
GETCOM: OUTSTR [ASCIZ |
Comment string for this record (<CR> when done):
|] ;Ask for a string
PUSHJ P,GETSTR ;Get the string
MOVE P2,[POINT 7,COMREC] ;Get byte pointer
PUSHJ P,COMOUT ;Output comment record to file
OUTSTR [ASCIZ |Number of times to send string: |]
PUSHJ P,GETDEC ;Get a decimal number
MOVEM P1,TSTREP ;Number of repetitions
MOVE T1,[POINT 7,PRFSTR] ;Get a pointer to the test string
MOVEM T1,TSTPTR
MOVE T1,PRFLEN ;Get the length
MOVEM T1,TSTLFT ;Save it
TXO F,F$PERF ;Set the flag
JRST G0 ;And go back to it
SUBTTL Performance analysis -- Start a response measurement
PLM
;+
;.hl Routine STTRSP
MLP
; This routine is called to record a beginning time for a performance
;analysis measurement. It records the current daytime in UDT format
;and the current MSTIME in variables TSTTIM and TSTBEG, respectively.
PLM
;-
MLP
STTRSP: MOVX T1,%CNDTM ;Get the UDT
GETTAB T1, ;From the monitor
JFCL
MOVEM T1,TSTTIM ;Save it
MSTIME T1, ;Get the MSTIME for the CPU
MOVEM T1,TSTBEG ;Save it
POPJ P, ;Return
SUBTTL Performance analysis -- Record a response
PLM
;+
;.hl Routine RECRSP
MLP
; RECRSP gets the current MSTIME and stores the difference
;between it and the MSTIME taken at the time STTRSP was called
;(from variable TSTBEG) in variable TSTTOT.
PLM
;-
MLP
RECRSP: MSTIME T1, ;Get the MSTIME at the end
MOVEM T1,TSTEND ;Save it
SUB T1,TSTBEG ;Get how long it took
MOVEM T1,TSTTOT ;Save the time it took him
PJRST DATOUT ;Output this delay
SUBTTL Performance analysis -- End of session
PLM
;+
;.hl Routine TSTRET
MLP
; TSTRET is called either when the performance string has been
;sent the specified number of times, or when the user aborts the
;performance analysis experiment by typing the escape character.
;It closes the performance analysis file and proceeds to MONITO to
;enter the exit dialogue again.
PLM
;-
MLP
;Still under FTPERF
TSTRET: OUTSTR [ASCIZ |
End of NRT network performance test
|] ;Say that this is the end
CLOSE $PRF, ;Close the file
JRST MONITO ;Go back to monitor
SUBTTL Performance analysis -- Performance string and length
PLM
;+
;.hl Performance string
MLP
; The performance string is a simple thirty character string which
;is sent to the remote host. It begins with an exclamation point, which
;is a comment character on TOPS-10 and TOPS-20.
PLM
;-
MLP
;Still under FTPERF
PRFSTR: ASCIZ /!1234567890123456789012345678
/
PRFLEN: EXP ^D30 ;Length of PRFSTR in characters
SUBTTL Performance analysis -- Get ASCIZ string (for comment)
PLM
;+
;.hl Routine GETSTR
MLP
; GETSTR reads the comment string for the performance analysis record
;from the controlling TTY:. The maximum length of a comment string is 250
;(decimal) characters (this is hard coded). The string is stored
;at location COMREC; P1 contains the number of characters in the record.
PLM
;-
MLP
;Still under FTPERF
GETSTR: STORE P1,COMREC,COMREC+^D50-1,0 ;Clear out the record
MOVSI P1,-^D250 ;Range check it
MOVE P2,[POINT 7,COMREC] ;Point to the storage place
GETS1: INCHWL T1 ;Wait for a character
CAIN T1,12 ;Is it a LF?
JRST GETS2
CAIN T1,15 ;<CR>
JRST GETS1 ;Eat the LF and end
IDPB T1,P2 ;Put into the record
AOBJN P1,GETS1 ;Loop for the next one
OUTSTR [ASCIZ/
%Comment string too long, try again
/]
JRST GETSTR ;And try again
GETS2: HRRZS P1 ;Clear left half
POPJ P,
SUBTTL Performance analysis -- Get character from string
PLM
;+
;.hl Routine GETPRC
MLP
; GETPRC is called to begin a response measurement and return with
;the next character from the performance analysis string. It calls STTRSP
;to begin the measurement. The character is returned in AC T1. It
;uses only T1. It returns CPOPJ with the character or CPOPJ1 if no more
;characters are to be sent.
PLM
;-
MLP
;Still under FTPERF
GETPRC: PUSHJ P,STTRSP ;Start response measurement
SOSGE TSTLFT ;Any characters left?
JRST NXTTST ;No, then repeat the test again
ILDB T1,TSTPTR ;Get the character
POPJ P,
NXTTST: SOSG TSTREP ;Any more left to do?
JRST CPOPJ1 ;Skip return, we're done
MOVE T1,[POINT 7,PRFSTR] ;Get a pointer to the test string
MOVEM T1,TSTPTR
MOVE T1,PRFLEN ;Get the length
MOVEM T1,TSTLFT ;Save it
JRST GETPRC ;And do it again
SUBTTL Performance analysis -- Get a decimal number
PLM
;+
;.hl Routine GETDEC
MLP
; GETDEC is called to input a decimal number from the controlling TTY:.
;It returns with the number in P1 and waits until one is typed. It uses
;T1, T2, and P1.
PLM
;-
MLP
;Still under FTPERF
GETDEC: SETZ P1, ;Zero the count
GETD1: INCHWL T1 ;Get the digit
CAIN T1,.CHCRT ;<CR>
INCHSL T1
JFCL
CAIGE T1," " ;Control?
CAIN T1," " ;Except <TAB>
TRNA
JRST GETDE
SUBI T1,"0" ;Make it a real number
CAIL T1,0 ;Legal?
CAILE T1,9 ;number
JRST GETDER ;Give an error and start over
IMULI P1,^D10 ;Make this the next one in line
ADDI P1,(T1) ;Add into the low part
JRST GETD1 ;And do the next one
GETDE: JUMPN P1,CPOPJ ;Have one
MOVEI P1,^D10 ;Default is ^D10
POPJ P, ;And return
GETDER: ERR ILD,<Illegal digit in number - re-input number>,<POPJ P,>
CLRBFI ;Eat junk
JRST GETDEC
SUBTTL Performance analysis -- Output a comment to the file
PLM
;+
;.hl Routine COMOUT
MLP
; COMOUT is called to output a comment record to the performance
;analysis file. It is called with P1 containing the number of bytes in
;the record and P2 containing the byte pointer ot the string. Uses T1,
;P1, and P2.
PLM
;-
MLP
;Still under FTPERF
COMOUT: MOVEI T1,.PRCOM ;Header type
PUSHJ P,OUTPRF ;Output it
MOVE T1,P1 ;Get the count
PUSHJ P,OUTPRF ;And put it into the file
COML: ILDB T1,P2 ;Get a byte for the file
ROT T1,-^D7 ;Put it in the high order 7 bits
PUSHJ P,OUTPRF ;Output it
SOJG P1,COML ;Go to the end
POPJ P, ;And return
SUBTTL Performance analysis -- Output a data record to the file
PLM
;+
;.hl Routine DATOUT
MLP
; DATOUT is called to output data to the performance file. It outputs
;the contents of TSTTIM and TSTTOT to the file (the time the character was
;sent and the time it took for the response).
PLM
;-
MLP
;Still under FTPERF
DATOUT: MOVEI T1,.PRDAT ;Get a header item
PUSHJ P,OUTPRF ;Output it
MOVE T1,TSTTIM ;UDT type
PUSHJ P,OUTPRF ;To the file
MOVE T1,TSTTOT ;And the differance
PUSHJ P,OUTPRF ;Output that also
POPJ P, ;And return
SUBTTL Performance analysis -- Output any record to the file
PLM
;+
;.hl Routine OUTPRF
MLP
; OUTPRF outputs a single character (in T1) to the performance
;analysis file.
PLM
;-
MLP
;Still under FTPERF
OUTPRF: SOSGE FOBUF+.BFCTR ;Anything left in buffer
JRST PRFOUT ;Then output the buffer
IDPB T1,FOBUF+.BFPTR ;Into the buffer with it
POPJ P, ;And return now
PRFOUT: OUT $PRF, ;The file is on channel $PRF
JRST OUTPRF ;Good return
GETSTS $PRF,T1 ;For the dump
ERR POF,<Performance file output failure>
> ;End IFN FTPERF
SUBTTL NETICH - Get a network character from the network buffer
PLM
;+
;.hl Routine NETICH
MLP
; NETICH is called to get one character (returned in T1) from the
;network. It returns CPOPJ1 with the character if there is one. If there
;are no remaining characters, the action taken depends on the setting of
;F$NEOM (F$NEOM is cleared regardless of which action is taken). If
;F$NEOM was clear, we take the error return (CPOPJ). If F$NEOM was set,
;we call NSPIN which will dismiss any interrupt we are in until data
;is actually available, at which point it will return to us with the new
;buffer.
PLM
;-
MLP
NETICH: SOSGE IBFCNT ;Any characters left in the buffer?
JRST ENDBUF ;No, then check for end of message set
ILDB T1,IBFPTR ;Get a character
JRST CPOPJ1 ;And skip return
ENDBUF: TXZN F,F$NEOM ;Did we have End of Message?
POPJ P, ;Yes, then just return
PUSHJ P,NSPIN ;No, then get the next buffer
JRST NSPERR ;Error return for NSP.
JRST NETICH ;And continue on as before
SUBTTL RBYTEC - Get a byte from the network
PLM
;+
;.hl Routine RBYTEC
MLP
; RBYTEC is called to input one character from the network and stop
;if none is available. It calls NETICH and stops with a UED stopcode
;if NETICH takes the error return.
PLM
;-
MLP
RBYTEC: PUSHJ P,NETICH ;Read byte with end an error
ERR UED,<Unexpected end to netork data>
POPJ P, ;Return
SUBTTL CONECT - Routine to set up the connection
;PLM
;+
;.hl Routine CONECT
MLP
; CONECT is called at initialization time to set up a connection
;to the remote host. It will first call SETNOD to set up the node name
;to connect to in the destination process descriptor block. It will
;call NSPEA to decide whether to enter object .OBHTH or .OBPST and do
;the NSP. UUO to perform the enter active function. It will then send
;the PMR string by exitting through SNDPMR if that is required.
PLM
;-
MLP
CONECT: PUSHJ P,SETNOD ;SET UP THE NODE NAME IN THE DEST PDB
PUSHJ P,NSPEA ;DO THE ENTER ACTIVE
JRST NSPERR
IFN FTPMR,<
SKIPG NODCNT ;Doing PMR?
> ;End IFN FTPMR
POPJ P, ;No
IFN FTPMR,<
FALL SNDPMR
>
SUBTTL SNDPMR - Send the PMR string to the remote system
PLM
;+
;.HL Routine SNDPMR
MLP
; SNDPMR is entered from CONECT if a PMR string must be sent.
;The PMR message has already been assembled by DOPMR at location PMRMSG.
PLM
;-
MLP
IFN FTPMR,<
SNDPMR: MOVE NSAFN,[NS.WAI!NS.EOM!<.NSFDS,,.NSAA2+1>]
MOVE NSAA1,PMRCNT
MOVE NSAA2,[POINT 8,PMRMSG,]
MOVEI T1,NSAFN
NSP. T1,
ERR PMR,<Can't send PMR string>
POPJ P,
> ;End IFN FTPMR
SUBTTL Error Routines -- SETNER - Set up NSPECD with error code
PLM
;+
;.hl Routine SETNER
MLP
; SETNER is called with a NSP. UUO error code in T1 to store it
;for later analysis by the NSPERR routine.
PLM
;-
MLP
SETNER: MOVEM T1,NSPECD ;Store NSP. error code for NSPERR
POPJ P, ;Only return
SUBTTL Error Routines -- NSPERR - Give an NSP. error message
PLM
;+
;.hl Routine NSPERR
MLP
; NSPERR is called when any NSP. UUO error code is encountered. The
;code has been previously stored in location NSPECD, probably by the SETNER
;routine. If the current state of the connection in DR, we output the
;message "[Connection to remote node aborted]"; otherwise we output a
;standard DECnet error message with the numeric code of the error. The
;program is exitted and set up to not continue.
PLM
;-
MLP
NSPERR:
PUSH P,NSAFN ;Save the current function
PUSHJ P,WATDEQ ;Wait for output to quiet down
MOVE NSAFN,[NS.WAI!<.NSFRS,,.NSACH+1>]
MOVEI T1,NSAFN
NSP. T1,
JFCL
LDB T1,[POINT 6,NSACH,^L<NS.STA>+5]
CAIN T1,.NSSDR ;State Disconnect Received?
JRST [OUTSTR [ASCIZ/
[Connection to remote node aborted]/] ;Output nice message instead
JRST NSPER1] ;Finish nicely
POP P,NSAFN ;Restore the failing function now
MOVE T1,NSPECD ;Get the error code
IFN FTPMR,<
JUMPE T1,NSPER1 ;If PMR, assume zero is routing failure
>
OUTSTR [ASCIZ/
?NRT/]
IMULI T1,2 ;prefix & text
OUTSTR @NSPERC(T1) ;Output the refix
LDB T1,[POINTR(NSAFN,NS.AFN)] ;GET FUNCTION CODE FROM ARGS
CAILE T1,FCNTBL ;OFFSET OK?
MOVEI T1,0 ;NO, CALL IT ILLEGAL
MOVE T2,[-1,,.GTWCH] ;Get the watch bits for this job
GETTAB T2, ;Do the GETTAB
SETZ T2, ;Default
TXNN T2,JW.WMS ;Any set?
TXO T2,JW.WFL!JW.WPR ;No, set default
TXNN T2,<JW.WCN!JW.WFL> ;Prefix only?
JRST NSPER1 ;Yes, finished with error message
OUTSTR [ASCIZ | Network |] ;Make it sound bad
OUTSTR @FCNTAB(T1) ;Output the text
OUTSTR [ASCIZ | failure |] ;And the failure part
MOVE T1,NSPECD ;GET ERROR CODE SET UP BY SETNER
IMULI T1,2 ;allow for prefix
CAIG T1,MAXERR ;DO WE KNOW THIS ERROR CODE?
SKIPA T1,NSPERC(T1) ;GET THE POINTER TO THE ERROR TEXT
MOVEI T1,[ASCIZ/Out of range/]-1
OUTSTR 1(T1) ;GIVE THE ERROR CODE
IFN FTFUNCTION,<
OUTSTR [ASCIZ /, function /]
LDB T1,[POINTR(NSAFN,NS.AFN)] ;GET FUNCTION CODE FROM ARGS
CAILE T1,FCNTBL ;OFFSET OK?
MOVEI T1,0 ;NO, CALL IT ILLEGAL
MOVE T1,FCNTAB(T1) ;GET PTR TO ASCIZ STRING
OUTSTR (T1) ;OUTPUT THE STRING
>;END OF IFN FTFUNCTION
TYPCRLF
NSPER1: PUSHJ P,TTYRST ;Be sure the TTY: gets unslaved
SETZM .JBREN ;Tell REENTER its not OK to REENTER
CLRBFI ;Clear out his input buffer in case of type ahead
PJOB T1, ;Get the job number
MOVNS T1 ;Set up for JOBSTS
JOBSTS T1, ;Do the JOBSTS
JRST TYPDOT ;Then type out a DOT
TXNN T1,JB.ULI ;Is job logged in?
TYPDOT: OUTSTR [ASCIZ |
.|] ;Type out the dot
SETZM TIBUF ;Be sure we don't reset again.
RESET ;Clear the world
EXIT 1, ;Polite return to monitor
JRST RESTRT ;Restart on CONTINUE
SUBTTL Error Routines -- DOERR - Output an error message
PLM
;+
;.hl Routine DOERR
MLP
; DOERR is called via the ERR MACRO. Its purpose is to output the
;text and prefix part of the message. DOERR is responsible for observing
;the user's verbosity bit settings. It is called with text of the error
;at (P)+1 and the prefix at (P)+2. The program cannot be continued.
PLM
;-
MLP
DOERR: ASSUME P,17 ;P must be last for code to work
MOVEM P,CRSACS+P
MOVEI P,CRSACS
BLT P,CRSACS+P-1 ;Save error ACs
MOVE P,CRSACS+P ;Restore old P
HRRZ T1,(P) ;Get return address
HRRZ T1,(T1) ;Get the address
OUTSTR [ASCIZ |
?NRT|]
OUTSTR (T1) ;and the text
OUTCHR [.CHTAB] ;Output a tab
MOVE T2,[-1,,.GTWCH] ;Get the watch bits for this job
GETTAB T2, ;Do the GETTAB
SETO T2, ;Set them all
HRRZ T1,(P) ;Get 1+return address
HRRZ T1,1(T1) ;And the message
TXNN T2,JW.WMS ;Any set?
TXO T2,JW.WFL!JW.WPR ;No, set default
TXNN T2,<JW.WCN!JW.WPR> ;Prefix only?
OUTSTR (T1) ;and the message
TYPCRLF
POPJ P, ;Return to finish up
SUBTTL NSPERC - NSP. Error message table
PLM
;+
;.hl Table NSPERC
MLP
; The NSPERC table uses the ERRMAC MACRO to assemble a table
;of text and prefixes for standard DECnet error codes.
PLM
;-
MLP
NSPERC: ERRMAC 0,UEC,<Unknown Error Code>
ERRMAC NSABE%,ABE,<Argument Block Format Error>
ERRMAC NSALF%,ALF,<Allocation failure>
ERRMAC NSBCN%,BCN,<Bad channel number>
ERRMAC NSBFT%,BFT,<Bad format type in process block>
ERRMAC NSCFE%,CBE,<Connect Block format error>
ERRMAC NSIDL%,IDL,<Interrupt data too long>
ERRMAC NSIFM%,IFM,<Illegal flow control mode>
ERRMAC NSILF%,ILF,<Illegal function>
ERRMAC NSJQX%,JQE,<Job quota exhausted>
ERRMAC NSLQX%,LQE,<Link quota exhausted>
ERRMAC NSNCD%,NCD,<No connect data to read>
ERRMAC NSPIO%,POB,<Percentage input out of bounds>
ERRMAC NSPRV%,NEP,<No Privileges to Perform Function>
ERRMAC NSSTB%,OBS,<Obsolete>
ERRMAC NSUKN%,UNN,<Unknown node name>
ERRMAC NSUXS%,UNS,<Unexpected State: Unspecified>
ERRMAC NSWNA%,WNA,<Wrong number of arguments>
ERRMAC NSWRS%,FWS,<Function called in wrong state>
;New error codes (to be re-ordered):
ERRMAC NSCBL%,CBL,<Connect block length error>
ERRMAC NSPBL%,PBL,<Process block length error>
ERRMAC NSSBL%,SBL,<String block length error>
ERRMAC NSUDS%,DSN,<Unexpected State: Disconnect Sent>
ERRMAC NSUDC%,DCN,<Remote node not accepting connects>
ERRMAC NSUCF%,RNR,<Remote node not responding>
ERRMAC NSULK%,RBL,<Remote Node broke link to local node>
ERRMAC NSUCM%,NNR,<Network Node not currently reachable>
ERRMAC NSUNR%,RSR,<Remote system out of resources>
;Error codes which correspond to DECnet disconnect codes.
ERRMAC NSRBO%,RTR,<Remote terminal server rejected connection>
ERRMAC NSDBO%,RTB,<Remote terminal server broke link>
ERRMAC NSRES%,NRR,<No Resources at Remote Node>
ERRMAC NSUNN%,UNN,<Unrecognized Node Name>
ERRMAC NSRNS%,RNS,<Remote Node Shut Down>
ERRMAC NSURO%,NRT,<No remote terminal server at node>
ERRMAC NSIOF%,ION,<Invalid Object Name Format>
ERRMAC NSOTB%,OTB,<Object Too Busy>
ERRMAC NSABM%,NMA,<Network Management aborted connection>
ERRMAC NSABO%,RTA,<Remote terminal server aborted connection>
ERRMAC NSINF%,INN,<Invalid Node Name Format>
ERRMAC NSLNS%,LNS,<Local Node Shut Down>
ERRMAC NSACR%,SPR,<System Password rejected>
ERRMAC NSNRO%,RTO,<Remote Terminal server did not reply in time>
ERRMAC NSNUR%,NNR,<Node Unreachable>
ERRMAC NSNLK%,NLN,<No Link>
ERRMAC NSDSC%,DCM,<Disconnect Complete>
ERRMAC NSIMG%,IFL,<Image Field Too Long>
ERRMAC NSREJ%,URR,<Unspecified Reject Reason>
ERRMAC NSBCF%,BCF,<Bad combination of NS.EOM & NS.WAI flags>
ERRMAC NSADE%,ADE,<Address Error>
MAXERR==.-NSPERC-1
SUBTTL FCNTAB - NSP. function text table
PLM
;+
;.hl Table FCNTAB
MLP
; FCNTAB is the table of text descriptions of each function
;to the NSP. UUO. Its primary purpose is for the typeout of
;functions if NRT is assembled with FTFUNCTION turned on; however,
;the maximum offset is also considered to be the maximum NSP. function
;we should be doing and is used as a legality check in the error routines.
PLM
;-
MLP
FCNTAB: FCNMAC 0, <Illegal function code>
FCNMAC .NSFEA,<Connection>
FCNMAC .NSFEP,<Enter Passive>
FCNMAC .NSFRI,<Connection>
FCNMAC .NSFAC,<Accept Connect>
FCNMAC .NSFRJ,<Reject Connect>
FCNMAC .NSFRC,<Connection>
FCNMAC .NSFSD,<Synchronous Disconnect>
FCNMAC .NSFAB,<Abort>
FCNMAC .NSFRD,<Read Disconnect Data>
FCNMAC .NSFRL,<Release Channel>
FCNMAC .NSFRS,<Read Channel Status>
FCNMAC .NSFIS,<Send Interrupt Data>
FCNMAC .NSFIR,<Receive Interrupt Data>
FCNMAC .NSFDS,<Send>
FCNMAC .NSFDR,<Receive>
FCNMAC .NSFSQ,<Set Quotas>
FCNMAC .NSFRQ,<Read Quotas>
FCNMAC .NSFJS,<Set Job Quotas>
FCNMAC .NSFJR,<Read Job Quotas>
FCNMAC .NSFPI,<Set PSI Reasons>
FCNTBL==.-FCNTAB
SUBTTL XMTMSG - Transmit network message
PLM
;+
;.hl Routines XMTMSG and XMTMSS
MLP
; These routines are called to send output to the network.
;XMTMSG is called with T1 pointing to a message block which consists
;of the number of bytes in the message located in the first word, followed
;by the message. XMTMSS is used to force out current network output.
;XMTMSS merely calls NSPOUT and stopcodes on any error.
PLM
;-
MLP
XMTMSG: SKIPN P4,(T1) ;Get char count
POPJ P,
HRLI T1,(POINT 8,,35) ;8-BIT BYTES
XMTMS1: ILDB P3,T1 ;get
NETOCH P3 ;Output a network character
SOJG P4,XMTMS1 ;Copy it
XMTMSS: PUSHJ P,NSPOUT ;SEND OUT THE BUFFER
JRST [PUSHJ P,NSPERR ;Report the error
JRST XMTMSS] ;..
POPJ P,
SUBTTL TTYOPN - Routine to OPEN the TTY
PLM
;+
;.hl Routine TTYOPN
MLP
; TTYOPN is called to open device TT:. This is normally the same as
;device TTY:, except it can be reassigned away to another terminal to
;aid debugging. Note that the feature of hitting the break twice
;can have inconsistent results if TT: is assigned to a terminal other than
;TTY:. We remember the UDX of the terminal here in the variable
;TTYUDX and the UDX position in various other TRMOP. blocks.
;The TTY: is OPENed in ASCII line mode with asynchronous I/O.
;The TTY: is added to the sofware interrupt system at this point.
;We also save the TTY: characteristics specified in table TTYSAV here.
;We also read the TTY: baud rate here so we can do the fancy
;segment size and quotas/goals code later for those systems which want it.
;Finally, we read the type of TTY: this is and save it for any
;fancy configuration messages which may have to be sent (e.g. VMS).
PLM
;-
MLP
TTYOPN: MOVE T1,[BMASK,,IMASK] ;Set up default break mask
BLT T1,ENDMSK ;Set default mask up
MOVE T1,[BMASK+1,,LMASK] ;Set the logical mask too
BLT T1,ELMASK
MOVE T1,[UU.AIO!.IOASL] ;Set line mode
MOVEM T1,TTYBLK
SETO T2, ;Ourselves
TRMNO. T2, ;Get controlling TTY:
SETO T2,
MOVEM T2,CTLTTY ;In case different from I/O TTY:
MOVE T2,TTYBLK+.OPDEV ;Get device
IONDX. T2,
SETO T2,
MOVEM T2,TTYUDX
MOVEM T2,HPSUDX ;For horizontal position
MOVEM T2,LEDUDX ;For checking line editing stuff
MOVEM T2,ECCUDX ;For checking echo count
MOVEM T2,BKCUDX ;Count or break characters
MOVEM T2,CTOUDX ;For checking ^O bit
MOVEM T2,COSUDX ;For setting ^O
MOVEM T2,PAGUDX ;For checking the page bit
OPEN $TTY,TTYBLK ;Open the TTY:
ERR ODT,<OPEN of device TTY failed>
INBUF $TTY,1 ;One input buffer
OUTBUF $TTY,10 ;Get the buffers
MOVEI T1,TTYBLK ;Point to the block
DEVSIZ T1, ;...
ERR DSF,<DEVSIZ for device TTY: failed>
MOVEI T1,-3(T1) ;Subtract header
HLL T1,TOBFH+.BFPTR ;Left half of pointer
MOVEM T1,BUFCHR ;Save the characteristics
SOJ T1, ;Last word of a buffer
HRLI T1,T2 ;Indexed by T2
MOVEM T1,LASTT2 ;Save it
MOVEI T1,1(T1) ;Increment back, clear left half
IMULI T1,5 ;We're starting in ASCII
MOVEM T1,CHPBUF ;Characters per buffer
MOVEI T1,5
MOVEM T1,BYTPWD ;Save it
MOVSI T4,-TSVNUM ;Read TTY: characteristics
TSVLP: HRRZ T1,TTYSAV(T4) ;Get characteristic
MOVE CX,[2,,T1]
TRMOP. CX,
SETZ CX,
HRLM CX,TTYSAV(T4)
AOBJN T4,TSVLP
;The below are done separately so we won't try to reset them later.
MOVE CX,[2,,T1] ;Find receive speed so can...
MOVEI T1,.TOTSP ;Set the seg size
TRMOP. CX,
SETZ CX, ;Assume max
MOVEM CX,TTBAUD ;Save it
MOVE CX,[2,,T1]
MOVEI T1,.TOTRM ;Get the TTY: type
TRMOP. CX,
SETZ CX,
MOVSI T1,-TTPLEN ;Length of type table
TTYPLP: CAME CX,TTPTB(T1) ;This type?
AOBJN T1,TTYPLP
SKIPL T1 ;If actually found one
SETO T1,
HRREM T1,TTYTYP ;Save the index
MOVE T1,[PS.FAC!T2]
MOVEI T2,$TTY ;Channel to add
MOVE T3,[TTYVEC-VECBAS,,PS.RID!PS.REF!PS.ROD] ;Input done
MOVSI T4,1 ;PI level 1
PISYS. T1, ;Add it
ERR CTP,<Can't add TTY: to PSI system> ;Can't
POPJ P, ;Return with it set up
SUBTTL Routine to set desired TTY: characterstics
PLM
;+
;.hl Routine SETTTY
MLP
; SETTTY is called at initialization time to set any characteristics
;we desire to be set on the user's TTY:. The characteristics should have
;previously been saved. This routine is table driven through
;the TTYSET table.
PLM
;-
MLP
SETTTY: MOVSI T4,-TSTNUM
MOVE CX,[3,,T1]
MOVE T2,TTYUDX
TTSTLP: HRRZ T1,TTYSET(T4)
MOVEI T1,.TOSET(T1)
HLRE T3,TTYSET(T4)
TRMOP. CX,
MOVE CX,[3,,T1]
AOBJN T4,TTSTLP
POPJ P, ;Return with it slaved
SUBTTL Routine to reset the TTY: characteristics
PLM
;+
;.hl Routine TTYRST
MLP
; TTYRST is called upon returning to monitor level or executing
;the exit dialogue. It restores the characteristics saved in the
;TTYSAV table. Enter at TTYRS1 if only the TRMOP. characteristics are to
;be done and the TTY: is not to be set to normal ASCII line mode.
PLM
;-
MLP
TTYRST: SKIPN TIBUF ;Anything set up?
POPJ P, ;No
SETSTS $TTY,.IOASL ;Set to a "normal" mode
TLZ F,(F$CVL) ;Clear all convert bits
TTYRS1: MOVSI T4,-TSVNUM
MOVE CX,[3,,T1]
MOVE T2,TTYUDX
TRSTLP: HRRZ T1,TTYSAV(T4)
MOVEI T1,.TOSET(T1)
HLRZ T3,TTYSAV(T4)
TRMOP. CX,
MOVE CX,[3,,T1] ;Ignore error
AOBJN T4,TRSTLP
PJRST CLRCO1 ;Undo ^O for now
SUBTTL TTY: Output and Echo Routines
PLM
;+
;.hl TTY: Output and Echo Routines
MLP
; This section contains routines to output characters and strings
;to the TTY:
PLM
;.list 1
;.le
MLP
;STROUT accepts the address of an ASCIZ string in T4 and outputs the string
;to the TTY:. It uses T1 and T4.
PLM
;-
MLP
STROUT: HRLI T4,(POINT 7,,)
STRLP: ILDB T1,T4 ;Get character
JUMPE T1,CPOPJ ;Done
PUSHJ P,OUTTTY ;Copy it
JRST STRLP ;Continue
PLM
;+
;.le
MLP
;OUTTTY accepts a character in T1 to output to the TTY:. AC CX is used.
PLM
;-
MLP
OUTTTY: SOSGE TOBUF+2 ;Any character space left?
JRST DOOUT ;No, Then output the current buffer
IFE FT703,< ;7.03 doesn't need this
TXNN F,F$PIM ;PIM?
PUSHJ P,DOHPOS ;No, compute HPOS
>
IDPB T1,TOBUF+1 ;Output the buffer
POPJ P, ;And return to caller
DOOUT: AOS TOBUF+2 ;Not really -1 characters left
PUSHJ P,DOOUT1 ;Do the actual out
JRST OUTTTY ;And try again
PLM
;+
;.le
MLP
;EKOBRK does break string echoing. Call with T4=AOBJN pointer to break table
;and T1 containing the break character to echo. Uses T1, T2, and T4.
PLM
;-
MLP
EKOBRK: TXNE F,F$ESC ;Escape sequence processing?
CAIE T1,.CHESC ;And processing an escape?
TRNA ;No to one of the above
POPJ P, ;Done
HLRZ T2,(T4)
CAIE T2,(T1) ;The right character?
AOBJN T4,EKOBRK
JUMPL T4,EKOBR1 ;Found
CAIGE T4," " ;Printing?
POPJ P, ;No, ignore
PUSHJ P,OUTTTY ;Output character
JRST DOOUT1 ;Force out
EKOBR1: HRRZ T4,(T4) ;Point to echo string
PUSHJ P,STROUT ;Output the string
FALL DOOUT1 ;Fall into DOOUT1
PLM
;+
;.le
MLP
;DOOUT1 is called to force out any remaining output to the TTY:
;The buffer is queued for output and we allocate a new one.
;We then fall into TOOUT to try to push data out to the TTY:.
;AC CX is used. Note that if location BUFQUO becomes zero or negative,
;DOOUT1 willcall TOBLOK to sleep until a buffer is available.
PLM
;-
MLP
DOOUT1: PUSH P,T1 ;Save T1
IFE FT703,< ;7.03 can handle HPOS right
TXNN F,F$PIM ;PIM?
PUSHJ P,STHPOS ;Set HPOS then
>
SKIPN TOBUF ;Is there really one?
JRST TOQ5 ;No
MOVE T1,CHPBUF ;Get total number of available chars
SUB T1,TOBUF+2 ;Real number of characters
JUMPLE T1,TPOPJ ;Nothing to do
SOSGE BUFQUO ;Any more buffers left?
PUSHJ P,TOBLOK ;Wait for output to come back
IOR T1,TOFLGS ;Include the flag bits
HRLM T1,@TOBUF ;Store the count
TOQOUT: HRRI T1,TOQUE-TOB.LK ;Point to output queue
TOQ1: HRL T1,TOB.LK(T1) ;Get link
TLNN T1,-1 ;Another buffer?
JRST TOQ4 ;No
HLRZS T1 ;Point ahead
JRST TOQ1 ;Continue
TOQ4: HRL T1,TOBUF ;Get buffer pointer
HLRM T1,TOB.LK(T1) ;Link it in
TOQ5: HRRZ T1,BUFCHR ;Size of buffer
MOVEI T1,TOB.DT(T1) ;Include link word
PUSHJ P,CORGET ;Get core block
HLL T1,BUFCHR ;Header pointer
MOVEM T1,TOBUF+1 ;Pointer
HRRZM T1,TOBUF ;The buffer
MOVE T1,CHPBUF ;Number of characters per buf
MOVEM T1,TOBUF+2 ;Set it
POP P,T1 ;Restore T1
FALL TOOUT
PLM
;+
;.le
MLP
;TOOUT is called either at interrupt level to try to output more data
;to the TTY:, or we fall into it from DOOUT1 to try to force out
;data. It dequeues TTY: buffers queued for output. AC CX used.
;If entered at TOOUTA, T1-T4 are used also.
PLM
;-
MLP
TOOUT: PUSHJ P,SAVT ;Save T1-T4
TOOUTA: TXZN F,F$IEC ;Ignore ECC?
TXNE F,F$USRV!F$PIM ;Already have input? or PIM?
JRST TOOUTB ;ECC not reliable then
MOVE T1,[2,,BKCTRM] ;Any break characters?
TRMOP. T1,
SETZ T1,
JUMPN T1,TOOUTB ;Yes, ignore ECC
MOVE T1,[2,,ECCTRM] ;Check the echo stream
TRMOP. T1, ;..
SETZ T1,
JUMPN T1,CPOPJ ;Don't start output if echo pending
TOOUTB: MOVEI T1,PS.ROD ;Going to service this now
ANDCAM T1,TTYSTS ;..
MOVEI T3,TOQUE ;Where to point
SKIPLE TOBFH+.BFCTR ;Any space?
JRST TOOUT1 ;Yes, go BLT in data
TOOUT0: SKIPGE TTYUDX ;Got detached?
PUSHJ P,DETWAT ;Wait
;Note there's a window here where you can get stuck
;if we get detached at exactly this point.
OUT $TTY, ;Do the output
TRNA ;Fine
JRST CHKERR ;See if got detached
TOOUT1: SKIPE T1,(T3) ;Anything to output?
TRNN T1,-1 ;Really anything?
POPJ P,
HLRE T2,TOB.CT(T1) ;Get count
ASSUME F$IOQ,<1B0>
JUMPGE F,TOOUT4 ;Don't worry about inhibit bit
TRNE T2,($TOOIN) ;Override?
JRST TOOUT4 ;Yes
MOVEI T3,(T1) ;Point ahead
JRST TOOUT1
TOOUT4: ANDI T2,($TOCNT) ;Preserve only count
HRLI T1,TOB.DT(T1) ;Point to data
HRR T1,TOBFH+.BFPTR ;Data area
IBP TOBFH+.BFPTR ;Normalize
SOJLE T2,NOADJ ;If nothing more to increment by
ADJBP T2,TOBFH+.BFPTR ;Increment the pointer
MOVEM T2,TOBFH+.BFPTR ;Store it
NOADJ: ASSUME TOB.DT,1
AOS T2,T1 ;Point to real area
BLT T1,@LASTT2 ;Move data
SETOM TOBFH+.BFCNT ;Set count to -1
HRRZ T1,(T3) ;Point to buffer
HRRZ T2,TOB.LK(T1) ;Link to next
HRRM T2,(T3) ;Point to it
HRRZ T2,BUFCHR ;Size of buffer
MOVEI T2,TOB.DT(T2) ;Increment
PUSHJ P,CORFRE ;Free the buffer
AOS BUFQUO ;Just freed a buffer
JRST TOOUT0 ;and try to output
CHKERR: GETSTS $TTY,T1 ;Get the status
TRNE T1,IO.ERR&<-1!IO.EOF> ;Any error bits?
ERR OTF,<OUT to TTY: failed>
TRNN T1,IO.EOF ;EOF?
POPJ P,
MOVEI T1,PS.REF ;Clear EOF pending
ANDCAM T1,TTYSTS
CLOSE $TTY, ;Clear the EOF
JRST TOOUT0 ;Try again
DETWAT: MOVEI T1,^D60 ;Time to sleep
PUSHJ P,TOHIBR
SKIPGE TTYUDX ;Still waiting?
JRST DETWAT ;Nope
POPJ P,
PLM
;+
;.le
MLP
;CLRTOQ is called to clear all output in progress; both queued buffers
;and that currently being output. CLRTOQ does NOT clear buffers which
;have the $TOICL bit on in the buffer status word. CLRTOQ DOES
;do a Clear Output Buffer TRMOP. It uses nothing.
PLM
;-
MLP
CLRTOQ: PUSHJ P,PIOSAV ;Since we're mucking with the queues
PUSHJ P,SAVT ;Save the Ts
MOVE T1,[2,,T2] ;Clear any output in progress
MOVEI T2,.TOCOB ;Clear output
MOVE T3,TTYUDX
TRMOP. T1,
JFCL
HRRZ T2,BUFCHR ;Size of output buffer
MOVEI T2,1(T2) ;Including link word
MOVEI T4,TOQUE-TOB.LK ;Start
MOVSI T3,($TOICL) ;Inhibit clearing
CLRTO1: SKIPE T1,TOB.LK(T4) ;Anything in queue?
TRNN T1,-1 ;Really one there?
POPJ P, ;Return if nothing
TDNE T3,TOB.FL(T1) ;Inhibit clear?
JRST CLRTO2 ;No
HRRM T3,TOB.LK(T4) ;De-link it
AOS BUFQUO ;Add another buffer
PUSHJ P,CORFRE
JRST CLRTO1 ;Continue
CLRTO2: MOVE T4,T1 ;New last chunk
JRST CLRTO1 ;Continue
PLM
;+
;.end list
;-
MLP
IFE FT703,< ;Only required for 7.02
SUBTTL Set Horizontal Position
PLM
;+
;.hl Horizontal position tables and routines
MLP
;These routines are called to set and compute the horizontal position
;correctly. They all use only CX. They are not assembled for 7.03 NRT since
;SCNSER can correctly handle horizontal position.
PLM
;.list 1
;.le
;DOHPOS and STHPOS
MLP
;DOHPOS does the "right" thing to variable HPOS given the
;character in T1. It should be called when a character is put in the
;TTY: output buffer. STHPOS sets the monitor's value of HPOS to ours.
;This should be called just before outputting a buffer. This is done
;because image mode doesn't do the right thing for us.
PLM
;-
MLP
STHPOS: MOVE CX,[3,,HPSTRM] ;The TRMOP.
TRMOP. CX,
JFCL
POPJ P,
DOHPOS: CAIL T1," " ;Printing?
CAILE T1,174 ;?
JRST DOHPS1 ;No
AOS HPOS
POPJ P, ;Do simple thing
DOHPS1: CAIL T1," " ;The real controls?
POPJ P, ;No, don't do anything
MOVEI CX,(T1) ;Dupe character
LSH CX,-1 ;Shift
TRNE T1,1 ;Was it odd?
SKIPA CX,HPSTBL(CX) ;Yes, use right side
HLRZ CX,HPSTBL(CX) ;Else use left
TRNE CX,-1
JRST (CX) ;Go if routine
POPJ P, ;Else return
;Still under IFE FTHPOS
PLM
;+
;.le
MLP
;HPSTBL is the dispatch table, in half word addresses, indexed by
;character, of what to do to HPOS for a given character. A zero entry
;means do nothing.
PLM
;-
MLP
HPSTBL: Z ;<NUL>,^A
Z ;^B,^C
Z ;^D,^E
Z ;^F,^G
CHHPOS,,CIHPOS ;^H,<TAB>
Z ;<LF>,<VT>
0,,CMHPOS ;<FF>,<CR>
Z ;^N,^O
Z ;^P,^Q
Z ;^R,^S
Z ;^T,^U
Z ;^V,^W
Z ;^X,^Y
Z ;^Z,<ESC>
Z ;34,35
Z ;36,37
;Still under IFE FTHPOS
PLM
;+
;.le
MLP
;CHHPOS sets HPOS for a backspace. CMHPOS zeroes HPOS for a <CR>.
PLM
;-
MLP
CHHPOS: SOSGE HPOS
CMHPOS: SETZM HPOS ;No negative positions
POPJ P,
PLM
;+
;.le
;CIHPOS sets HPOS for a <TAB>.
PLM
;-
MLP
CIHPOS: MOVEI CX,7 ;Round up
ADD CX,HPOS ;By seven
ANDCMI CX,7 ;Back to next multiple
MOVEM CX,HPOS
POPJ P,
;PLM
;+
;.end list
;-
MLP
> ;End IFE FTHPOS
SUBTTL Miscellaneous terminal routines
PLM
;+
;.hl Routine OUTCRL
MLP
; OUTCRL is called to output a <CR><LF> to the TTY:
PLM
;-
MLP
OUTCRL: PUSH P,T1 ;Save current character
MOVEI T1,.CHCRT ;Get a CR
PUSHJ P,OUTTTY ;Output to the TTY
MOVEI T1,.CHLFD ;Get a LFD
PUSHJ P,OUTTTY ;Output the LFD
POP P,T1 ;Restore character
POPJ P, ;And return to caller
SUBTTL TTY Input Routines -- INCHR - Get terminal character
PLM
;+
;.hl Routine INCHR
MLP
; INCHR is called to get a character from the input buffer.
;The characters have actually already been input in the operating
;system independent interrupt service routine; we are here just
;taking them from our internal buffers. Returns CPOPJ1 with
;character in T1, or CPOPJ if there are no more. If a character
;has been stored in variable INPCHR, this is read instead. This
;is a method of forcing a character to be processed immediately.
;Note that ICHCNT is only an upper bound on the number
;of characters available; this is because SCNSER in reality returns
;a word count rather than a byte count. This routine uses T1-T2.
PLM
;-
MLP
INCHR: SKIPE T1,INPCHR ;Leftover character to read?
JRST [SETZM INPCHR ;Yes. eat it
SOS ICHCNT ;Adjust ICHCNT
JRST CPOPJ1] ;and win
INCHR0: PUSHJ P,TTYCHR ;Get character from TTY:
POPJ P, ;None to read
ANDI T1,177 ;Mask to 7 bits
INCHR1: TXNE F,F$PIM ;In line mode?
JRST CPOPJ1 ;No, then all is legal
JUMPE T1,INCHR0 ;If null, eat it
JRST CPOPJ1 ;And return
TTYCHR:
SKIPE T1,INPQUE ;Anything in queue?
SOSGE ICHCNT ;Any characters left?
JRST NOCHRS ;None to input
TTYCH1: SOSGE IBF.CT(T1) ;Any more chars in this buffer?
JRST NEWIBF ;No, go to next
ILDB T1,IBF.PT(T1) ;Get character
JRST CPOPJ1 ;And return with it
NOCHRS: SKIPN T1,INPQUE ;Anything in queue?
POPJ P, ;No
HRRZ T2,IBF.LK(T1) ;This should be zero, but just in case
HRRZM T2,INPQUE
HLRE T2,IBF.LK(T1) ;Return it if so (should be only 1!)
PUSHJ P,CORFRE
JRST NOCHRS ;Check to be sure all deallocate
NEWIBF: PUSH P,T2 ;Save T2
HRRZ T2,IBF.LK(T1) ;Point to next entry
HRRZM T2,INPQUE ;Point to next
HLRE T2,IBF.LK(T1) ;Get size of this buffer
PUSHJ P,CORFRE ;Free the old buffer
HRRZ T1,INPQUE ;Clear left half, put in T1
POP P,T2 ;Restore T2
JUMPN T1,TTYCH1 ;Be defensive
POPJ P,
SUBTTL Output SIXBIT argument to controlling TTY:
PLM
;+
;.hl Routine .TSIX
MLP
; .TSIX is called by th TSIX MACRO. The MACRO pushes the argument
;onto the stack and calls .TSIX. No ACs are used.
PLM
;-
MLP
.TSIX: EXCH T1,-1(P) ;Fetch argument
PUSH P,T2
.TSIXL: SETZ T2,
ROTC T1,6
MOVEI T2,<" "-' '>(T2)
OUTCHR T2
JUMPN T1,.TSIXL
POP P,T2
EXCH T1,-1(P)
POPJ P, ;Return
SUBTTL Node Name Output Routines
PLM
;+
;.hl Routines TNODE and TNDLST
MLP
; These routines are used to output a single node (supplied in T2)
;and a list of nodes (for Poor Man's Routing; supplied from table RNODE),
;respectively. TNODE expects the node name in T2 and does not use an ACs;
;TNDLST uses CX and T2.
PLM
;-
MLP
TNODE:
IFN FTPMR,<
SKIPE NODCNT ;Doing PMR
JRST TNDLST ;Type the whole list
> ;End IFN FTPMR
TNODE1: TSIX T2
POPJ P, ;Return
IFN FTPMR,<
;< ;This is here so that MACRO will not get confused
TNDLST: OUTSTR [ASCIZ |, Routing => |] ;Tell him how he is getting there
SETZ CX, ;Clear out a flag
TNDL1: MOVE T2,RNODE(CX) ;Type it out
JUMPE T2,CPOPJ ;Return when done
TSIX T2 ;Type it out
SKIPE RNODE+1(CX) ;Anything left to type?
OUTSTR [ASCIZ |::|] ;Yes.
AOJA CX,TNDL1 ;Type out the whole list
> ;End IFN FTPMR
SUBTTL SIXBIT Input
PLM
;+
;.HL SIXBIT Input routines: SIXIN, SIXINW, and SIXINA
MLP
; These routines all input a SIXBIT value from the controlling
;TTY: in AC T2. They return with T3 trashed, T2 containing the SIXBIT
;value, and T1 containing the terminating character.
;SIXIN expects the input to be already waiting to be read from the monitor.
;SIXINW waits until a line is typed before beginning to input.
;SIXINA expects T2 to have been set up with the first character of the
;argument already. The argument is returned left-justified.
PLM
;-
MLP
SIXINW: SETZ T2, ;Build target here
MOVE T3,[POINT 6,T2] ;Set up bp
SIXIN1: INCHWL T1 ;Get a character
CAIE T1," " ;Is it a space
CAIN T1," " ;or a tab?
JRST SIXIN1 ;Yes, ignore it
JRST SIXIN3 ;No, use it
SIXIN: SKIPA T3,[POINT 6,T2] ;Set up bp
SIXINA: SKIPA T3,[POINT 6,T2,5] ;First character already
TDZA T2,T2 ;Build target here
SETZ T1, ;In case no terminator
SIXIN0: INCHSL T1 ;Get a character
POPJ P, ;Nothing
CAIE T1," " ;Eat spaces and tabs
CAIN T1," " ;..
JRST SIXIN0
JRST SIXIN3
SIXIN2: INCHSL T1 ;Get next character
POPJ P, ;Thats all
SIXIN3: CAIL T1,"a" ;Make lowercase
CAILE T1,"z"
TRNA
TRZ T1,"a"-"A"
CAIL T1,"A" ;Alpha?
CAILE T1,"Z" ;.....?
TRNA ;No
JRST SIXIN4 ;Yes
CAIL T1,"0" ;Numeric?
CAILE T1,"9" ;...?
JRST SIXIN5 ;No, done
SIXIN4: MOVEI T1,-40(T1) ;Convert to sixbit
TRNN T2,77 ;Any room left
IDPB T1,T3 ;store
JRST SIXIN2 ;Get next...
SIXIN5: CAIN T1,.CHCRT ;<CR>?
INCHSL 1(P) ;Yes
JFCL
POPJ P,
SUBTTL Scanning Routines -- .LKNAM
PLM
;+
;.hl Routine .LKNAM
MLP
; .LKNAM is called to search a command table for a match. It is called
;with T1 containing the AOBJN pointer to the defined commands table and T2
;containing the SIXBIT command name to search for. .LKNAM will allow
;abbreviation to uniqueness. It returns CPOPJ if the specified command is
;a duplicate or is not found in the table. It returns CPOPJ1 with the right
;half of T1 containing the offset from the beginning of the command table
;to the specified entry. The left half of T1 is returned as zero if the
;specified command word was an abbreviation or less than zero if it was
;an exact match. .LKNAM uses T3 and T4 but preserves T2.
PLM
;-
MLP
.LKNAM: JUMPGE T1,[SETOM T1 ;FLAG UNKNOWN
POPJ P,] ;ERROR RETURN
SAVE2 ;SAVE P1, P2
PUSH P,T1 ;SAVE ARGUMENT
MOVE T3,T2 ;SET ARG TO MASK MAKER
PUSHJ P,.MKMSK ;MAKE MASK
MOVE T2,T3 ;RESTORE NAME
MOVE P1,T1 ;SAVE FOR MATCHING
MOVE T1,(P) ;Recover argument
SETOM P2 ;SET ABBREVIATION MATCH COUNTER
NAME1: MOVE T3,(T1) ;FETCH TABLE ENTRY
TLNE T3,(3B1) ;NOTE THAT * IS 12 IN SIXBIT
JRST NAME2 ;NOT FORCED MATCH
LSH T3,6 ;SEE IF IT MATCHES
XOR T3,T2 ;EVEN IN AN ABBR.
TRZ T3,77 ;CLEAR LAST CHAR SINCE WE DON'T KNOW IT
AND T3,P1 ;..
JUMPE T3,NAME9
JRST NAME3 ;NO--LOOP
NAME2: XOR T3,T2 ;SEE IF EXACT MATCH
JUMPE T3,NAME9 ;YES--A WINNER
AND T3,P1 ;SEE IF A SUITABLE ABBREVIATION
JUMPN T3,NAME3 ;NO--LOOP BACK FOR MORE
MOVE T4,T1 ;SALT AWAY THE LOCATION JUST IN CASE
AOS P2 ;YES--COUNT
NAME3: AOBJN T1,NAME1 ;ADVANCE--LOOP IF NOT DONE YET
HRRZ T1,T4 ;RESTORE LOCATION OF A WINNER
JUMPE P2,NAME9 ;DONE--JUMP IF ONE ABBREVIATION
MOVE T1,P2 ;GIVE FLAG TO CALLER
POP P,(P) ;Fix stack
POPJ P, ;NONE OR TWO, SO FAIL
NAME9: POP P,T3
HRRZS T3
SUBI T1,(T3) ;Make relative index
JRST CPOPJ1 ;And give good return
SUBTTL Scanning Routines -- .MKMSK
PLM
;+
;.hl Routine .MKMSK
MLP
; Routine .MKMSK is called to make a mask (returned in T1) with
;"77" (octal) in word positions which are non-blank in the SIXBIT word
;specified in T3. It also uses T2.
PLM
;-
MLP
.MKMSK: MOVEI T1,0 ;CLEAR MASK
MOVSI T2,(77B5) ;START AT LEFT END
MAKMS1: TDNE T3,T2 ;SEE IF SPACE HERE
IOR T1,T2 ;NO--IMPROVE MASK
LSH T2,-6 ;MOVE RIGHT ONE CHAR
JUMPN T2,MAKMS1 ;LOOP UNTIL DONE
POPJ P, ;RETURN
SUBTTL Memory manglement -- Core allocator
PLM
;+
;.hl Routine CORGET
MLP
; CORGET is the allocation portion of the memory manager. It is
;called with T1 containing the size (in words) of the block desired. It
;exits CPOPJ with T1 containing the address of the obtained block. It will
;stopcode if the core is not available and the program cannot expand.
;CORGET preserves all ACs except T1.
PLM
;-
MLP
CORGET:
PUSHJ P,PIOSAV ;Turn off PSI
IFN FTPARANOID,<
JUMPLE T1,[ERR ICA,<Illegal core allocation>]
>
PUSH P,T2 ;Save the world
PUSH P,T3
PUSH P,T4
SKIPN T2,FRELST ;Any blocks on the free list?
JRST CORG20 ;No, make the block
SETZB T3,T4 ;Not remembering any block
HRLI T2,FRELST ;Remember precessor
CORG1: PUSH P,(T2) ;Push size of block
HLRZS (P) ;Move to right half
CAMN T1,(P) ;Same size as we want?
JRST CORG7 ;Yes, allocate it
CAML T1,(P) ;Do we want smaller than this block?
JRST CORG6 ;No, don't remember it
JUMPE T3,CORG4 ;If not remembering anything, then this
CAMG T4,(P) ;Else is this closer to the size than previous remembered?
JRST CORG6 ;No, remember previous then
CORG4: MOVE T3,T2 ;Remember this block & its predecessor
MOVE T4,(P) ;And its size
CORG6: POP P,(P) ;Fix stack
HRLI T2,(T2) ;Remember precessor
HRR T2,(T2) ;Point to successor
TRNE T2,-1 ;If there is one
JRST CORG1 ;There is, check it out
JUMPE T3,CORG20 ;If didn't find anything
MOVE T2,T3 ;Point T2 to block we want
PUSH P,(T2) ;And push its size
HLRZS (P) ;on the right side
CORG7: CAMN T1,(P) ;Size the same as we want?
JRST CORG9 ;Yes, just de-link it then
PUSH P,(P) ;Duplicate size of desired block
SUBM T1,(P) ;No, subtract out what we want
MOVNS (P) ;Leaving size left
HRRZI T3,(T2) ;Start of the block as it is
ADDI T3,(T1) ;Where it will now start
POP P,(T3) ;Put new size in
MOVSS (T3) ;left half, of course
HRL T3,(T2) ;Get successor
HLRM T3,(T3) ;and place in new block
MOVSS T2 ;Point to predecessor
HRRM T3,(T2) ;Point it to new block
HRRZM T1,(P) ;Put desired size on
HLRZ T1,T2 ;Return with new block in T1
JRST CORG30 ;Cleared, of course
CORG9: HRRZI T1,(T2) ;Point T1 to desired block
HRRZ T3,(T2) ;Get successor
MOVSS T2 ;Get predecessor
HRRM T3,(T2) ;Link to new sucessor
JRST CORG30 ;Clear it and return
CORG20: PUSH P,T1 ;Save size
MOVE T2,.JBFF ;Point to first free location
ADDI T2,(T1) ;The address which must be allocated to
CAMLE T2,HICORE ;Does that far exist?
JRST CORG23 ;No, go allocate it
MOVE T1,.JBFF ;Point to block
MOVEM T2,.JBFF ;Update first free
JRST CORG30 ;Clear and return
CORG23: MOVE T1,.JBFF ;Point to new block
MOVEM T2,.JBFF ;Store pointer to new
IORI T2,777 ;To next page
MOVEM T2,HICORE ;Save max
CORE T2, ;Get it
ERR CUF,<CORE UUO failed>
CORG30: EXCH T1,(P) ;Exchange size for address
HRRZ T2,(P) ;Make BLT pointer
HRLI T2,1(T2) ;..
SETZM (T2) ;Clear first location
SOJLE T1,CORG40 ;Skip the BLT if only one word
MOVSS T2
ADD T1,(P) ;Last location(+1)
BLT T2,(T1) ;Clear core
CORG40: POP P,T1
POP P,T4
POP P,T3
POP P,T2
POPJ P,
SUBTTL Memory manglement -- Core De-allocator
PLM
;+
;.hl Routine CORFRE
MLP
; CORFRE is the de-allocation portion of the memory manager. Enter
;it iwth T1 containing the address of the block to free and the absolute
;value of T2 containing the number of words to free. Blocks which are freed
;are placed on a linked list of free blocks for later re-use. Address space
;is never shrunk when core is de-allocated. CORFRE preserves all ACs but
;destroys the setting of F$P2.
PLM
;-
MLP
CORFRE: PUSHJ P,PIOSAV
IFN FTPARANOID,<
CAILE T1,LSTZER ;Be sure core in reasonable place
SKIPN T2
ERR ICD,<Illegal core deallocation>
>
TLZ F,(F$P2) ;First pass
PUSHJ P,SAVT
SETZM (T1) ;No links here yet!
MOVMS T2 ;Be sure it's positive
ADDI T2,(T1) ;Compute end address(+1)
HRLI T3,FRELST
HRR T3,FRELST ;Get free list pointer
TRNN T3,-1
JRST CORF10
CORF1: HLRZ T4,(T3) ;Get size of block
ADDI T4,(T3) ;Compute its last addr(+1)
CAME T4,T1 ;Does that block end at us?
JRST CORF4 ;No
SUBI T2,(T1) ;Get length again
TLON F,(F$P2) ;Pass 2?
JRST CORF2 ;No, don't return yet
MOVSS T2 ;Put in left half
ADDM T2,(T3) ;Make that block bigger
POPJ P, ;Return
CORF2: HLRZ T4,(T3) ;Get length of existing block
ADDI T2,(T4) ;Add length of new block
MOVEI T1,(T3) ;Point T1 at new larger block
CORF3: HRR T3,(T3) ;Point T3 at successor
MOVSS T3 ;Get predecessor
HLRM T3,(T3) ;Point it at sucessor
SETZM (T1) ;No links yet to new block
ADDI T2,(T1)
MOVSS T3 ;Point T3 at current block
JRST CORF9 ;And continue scan
CORF4: CAIE T2,(T3) ;Does our block end at his?
JRST CORF7 ;No
SUBI T2,(T1) ;Get length again
HLRZ T4,(T3) ;And length of this block
ADDI T2,(T4) ;Get length of new block
TLON F,(F$P2) ;Pass 2?
JRST CORF3 ;No, de-link and continue search
HRLM T2,(T1) ;Store in proper place
HRRZ T2,(T3) ;Get successor block
HRRM T2,(T1) ;And point us to him
MOVSS T3 ;Get predecessor
HRRM T1,(T3) ;And point him to us
POPJ P, ;Return
CORF7: HRLI T3,(T3) ;Remember us as prececessor
HRR T3,(T3) ;Get successor
CORF9: TRNE T3,-1 ;See if there is one
JRST CORF1 ;Yes, check it
CORF10: MOVSS T3 ;No, point back to last block
HRRM T1,(T3) ;Save
SUBI T2,(T1) ;Get real length again
HRLM T2,(T1) ;Store it
POPJ P, ;Return, turning PSISER on on the way
SUBTTL SWITCH.INI support -- Read SWITCH.INI
PLM
;+
;.hl Routine SWTINI
MLP
; SWTINI is the main routine which provides support of reading SWITCH.INI.
;It looks up DSK:SWITCH.INI[,] and parses each line searching for a line
;which begins with "NRT". It will attempt to parse each switch on the line;
;if a switch parses incorrectly, SWTINI will abort scanning the line
;and return to the caller. SWTINI uses all T ACs.
PLM
;-
MLP
SWTINI: OPEN $SWI,[ .IOASC
SIXBIT/DSK/
DSKHDR ]
POPJ P, ;Oh well
MOVE T1,[SIXBIT/SWITCH/]
MOVSI T2,'INI'
SETZ T3,
JFCL
GETPPN T4,
JFCL
LOOKUP $SWI,T1 ;Lookup the file
JRST RELFIL ;Done
FNDNRT: PUSHJ P,SIXDSK ;Get sixbit token from disk
CAMN T2,[SIXBIT/NRT/] ;For us?
JRST HAVNRT
PUSHJ P,DSKEAL ;Eat a disk line
JRST RELFIL ;Done
JRST FNDNRT ;Loop around
NRTSWT: PUSHJ P,SIXDSK ;Get it
MOVE T1,[-SWTL,,SWTA] ;The table
PUSHJ P,.LKNAM ;Look for a switch
TRNA ;Do what we can
PUSHJ P,@SWTDSP(T1) ;Process the switch
JRST RELFIL ;Oops
HAVNRT: CAIN P1,"/" ;Look for switches
JRST NRTSWT ;Process switch
PUSHJ P,DSKCH ;Get a character
JRST RELFIL ;Done
CAIE P1," " ;Tab is OK
CAIL P1," " ;But other control chars aren't
JRST HAVNRT ;Continue
RELFIL: RELEAS $SWI,
POPJ P,
SUBTTL SWITCH.INI support -- Switch handling routines
PLM
;+
;.hl Switch handling routines
MLP
; The following routines handle individual switches:
PLM
;.list 1
;.le
MLP
;ESCSWT handles the /ESCAPE:character switch.
PLM
;-
MLP
ESCSWT: CAIN P1,":" ;Validate last character
PUSHJ P,DSKCH
POPJ P,
MOVEM P1,ESCCHR
PJRST DSKCH ;Get next character and return
PLM
;+
;.le
MLP
;MODSWT handles the /MODE switch. Non-understandable settings of /MODE are
;equivalent to /MODE:NOVICE.
PLM
;-
MLP
MODSWT: CAIE P1,":" ;Does he really know what he's doing
JRST CPOPJ1 ;Ignore just this
PUSHJ P,SIXDSK ;Get string
MOVE T1,[-MODL,,MODA] ;The table
PUSHJ P,.LKNAM ;Lookup
JRST CPOPJ1 ;Ignore this switch
IOR F,MODTAB(T1) ;The correct flag bits
MOVE T1,MODTB2(T1) ;Get the notify string
MOVEM T1,NOTICH ;Save it
JRST CPOPJ1
PLM
;+
;.end list
;-
MLP
SUBTTL SWITCH.INI support -- I/O Routines
PLM
;+
;.hl Miscellaneous SWITCH.INI support routines
MLP
; The following routines are used to support the reading of SWITCH.INI:
PLM
;.list 1
;.le
MLP
;SIXDSK returns an alphanumeric SIXBIT token in T2, terminating
;character in P1. It uses T2 and P1.
PLM
;-
MLP
SIXDSK: SETZ T2,
DSKSX1: PUSHJ P,DSKCH ;Get a disk character
POPJ P,
CAIL P1,"a"
CAILE P1,"z" ;Convert lower case
TRNA
ANDI P1,137 ;...
CAIL P1,"A" ;Alphanumeric?
CAILE P1,"Z"
JRST DSKSX4
DSKSX3: LSH T2,6
ADDI T2,<'0'-"0">(P1)
JRST DSKSX1
DSKSX4: CAIL P1,"0"
CAILE P1,"9"
TRNA
JRST DSKSX3
JUMPE T2,CPOPJ ;Done
DSKSX5: TLNE T2,770000 ;Left justify
POPJ P,
LSH T2,6
JRST DSKSX5
PLM
;+
;.le
MLP
;DSKEAL eats characters until a <LF> is seen. It uses P1.
PLM
;-
MLP
DSKEAL: PUSHJ P,DSKCH
POPJ P,
CAIE P1,.CHLFD
JRST DSKEAL
AOS (P)
POPJ P,
PLM
;+
;.le
MLP
;DSKCH returns with the next character from the file in P1.
;It returns CPOPJ1 if no errors; CPOPJ and P1 zero if error or EOF.
;It uses P1 only.
PLM
;-
MLP
DSKCH: SETZ P1,
SOSGE DSKHDR+.BFCTR
JRST DSKIN
ILDB P1,DSKHDR+.BFPTR
AOS (P)
POPJ P,
DSKIN: IN $SWI,
JRST DSKCH
POPJ P,
PLM
;+
;.end list
;-
MLP
SUBTTL SWITCH.INI support -- Switch tables
PLM
;+
;.hl Tables SWTA and SWTDSP
MLP
; These are the tables which define legal switches and correspond
;them with appropriate actions. SWTA is generated with the NAMTAB MACRO.
;SWTDSP is the list of addresses. The offset of each address corresponds
;to the offset of the affiliated command from the beginning of the SWTA
;table.
PLM
;-
MLP
NAMTAB SWT,<ESCAPE,MODE>
SWTDSP: ESCSWT
MODSWT ;Mode switch
IFN .-SWTDSP-SWTL,<
PRINTX %SWITCH.INI dispatch table doesn't match switch table
>
PLM
;+
;.hl Tables MODA, MODTB2, and MODTAB
MLP
; These tables define the legal settings of the /MODE switch and
;the corresponding bit setting of F$XPT the value of NOTICH. The offset into
;MODA defined by the input keyword corresponds to the offset into
;MODTAB to obtain the correct flag and MODTB2 to obtain the value
;of NOTICH.
PLM
;-
MLP
NAMTAB MOD,<EXPERT,NOTIFY>
;Table for /MODE flag bits. Must match order of /MODE names above
MODTAB: EXP F$XPT
EXP F$XPT
IFN .-MODTAB-MODL,<
PRINTX %SWITCH.INI /MODE bits table doesn't match MODES table
>
;Table for value of NOTICH. Must match order of /MODE names above
MODTB2: Z
[ASCIZ//]
IFN .-MODTB2-MODL,<
PRINTX %SWITCH.INI /MODE NOTICH value table doesn't match MODES table
>
SUBTTL FILHGH - Prototype FILOP. UUO block
PLM
;+
;.hl Data block FILHGH
MLP
; FILHGH is the prototype FILOP. argument block used by the performance
;analysis routines.
PLM
;-
MLP
IFN FTPERF,<
FILHGH: $PRF,, .FOAPP ;Channel,,Mode
EXP .IOIMG!UU.RRC ;Mode!Update rib on new file data
SIXBIT /DSK/ ;Device
XWD FOBUF,FIBUF ;Outpbut buffer,,Input buffer headers
XWD 3,3 ;Number of output,,Input buffers
XWD 0,PRFFIL ;Pointer to Lookup/Enter block
Z ;No path block
Z ;Clear out PPN
>; End IFN FTPERF
SUBTTL GETCFG - Get the configuration message for the system
PLM
;+
;.hl Routine GETCFG
MLP
; GETCFG is called to read the configuration message from the
;remote terminal server. It will read the PMR message and confirm
;that it is a positive response (first byte =/= 2) if that is necessary.
;It will then read and store OSTYPE and PROTMD (the protocol modifier).
;It will type the connect confirmation and escape character reminder
; messages before returning to the user. Enter at TYPESC to just type the
;escape character reminder message.
PLM
;-
MLP
GETCFG:
TXZ F,F$NEOM ;Force new buffer
PUSHJ P,NSPINW ;Wait for input
JRST NSPERR ;Oh well
IFN FTPMR,<
SKIPN NODCNT ;Using PMR?
JRST GETCF0 ;Get the next part of message
PUSHJ P,RBYTEC ;Get data
CAIE T1,2 ;Is it a PMR NAK?
JRST GETCF ;No, then it is ok
PUSHJ P,TTYRST ;Reset the TTY:
PMRERR: PUSHJ P,NETCHR ;Output data from network
TXZN F,F$NEOM ;If EOM
PUSHJ P,OUTCRL ;He doesnt supply this either
PUSHJ P,NSPINW ;Get more data
JRST [PUSHJ P,DOOUT1 ;Force out last
JRST RESTRT ] ;And re-ask him
JRST PMRERR ;Continue outputting
GETCF: TXZ F,F$NEOM ;Wait for some input
PUSHJ P,NSPINW
JRST NSPERR ;Failed
> ;End IFN FTPMR
GETCF0: PUSHJ P,RBYTEC ;Get byte (defines this as config msg)
GETCF1: PUSHJ P,RBYTEC ;Get a first byte
PUSHJ P,RBYTEC ;Protocol ECO
MOVEM T1,PROTMD ;Save it
PUSHJ P,RBYTEC ;Protocol modifier
PUSHJ P,RBYTEC ;OS type
MOVE T3,T1 ;save it
CAILE T3,MAXOS ;Is this legal?
ERR IOR,<Illegal operating system type returned in configuration>
MOVEM T3,OSTYPE ;Save this
PUSHJ P,RBYTEC ;2nd byte of O/S type
PUSHJ P,GETWRD ;Supported protocols
GETCF9: TYPE <
[Connected to >
TSIX OSNAME(T3) ;System type
TYPE < system>
IFN FTPMR,SKIPG NODCNT ;Poor mans routing
OUTCHR [" "] ;No, then output the space
MOVE T2,RNODE ;Type nodeid
PUSHJ P,TNODE ;
TYPE <::]
>
TYPESC: TYPE <[Type > ;Say how to get out
MOVE T2,ESCCHR ;
CAIL T2," " ;Is it control?
JRST TYPES1 ;No. nothing special
TYPE <Control-> ;
MOVEI T2,"A"-""(T2)
TYPES1: OUTCHR T2 ;Type it
SKIPN T2,ESCCHR ;Get escape back
TYPE < (Control-space)>
CAIN T2,"" ;Control uparrow?
TYPE < (Control-~ on VT100)> ;Some terminals like this better
CAIN T2,"" ;Control backarrow?
TYPE < (Control-? on VT100)> ;
TYPES2: TYPE < to return]
> ;
POPJ P, ;
SUBTTL Compute mask bit & word for ESCCHR
PLM
;+
;.hl Routine CMPESC
MLP
; CMPESC is called to compute the offset bit and word from the
;beginning of a mask. These values are stored in ESCBIT and ESCWRD
;respectively. This is for fast adding of the escape character to the
;break set at interrupt level when using break masks.
PLM
;-
MLP
CMPESC: MOVE T1,ESCCHR ;Get the escape character
IDIVI T1,^D32 ;Compute bit, etc. for later
MOVEM T1,ESCWRD ;The word
MOVNS T2
MOVSI T1,(1B0) ;And the bit
LSH T1,(T2)
MOVEM T1,ESCBIT
POPJ P,
SUBTTL Fatal errors in job
PLM
;+
;.hl Routine ERRTRP
MLP
; The ERRTRP routine is entered if the program ever gets a trap
;through .JBINT. .JBINT traps are enabled for any kind of fatal error
;(such as illegal memory references, pushdown overflows, etc.) and control-C
;interrupts. These things are specifically not enabled with PSISER because
;the PSI system may be turned off when the error occurs. This routine
;saves the ACs in location CRSACS and loads up a crash pushdown pointer.
;It then attempts to restore the state of the TTY: (unslave it, in
;particular) and exit. The program may then be SAVEd and the dump
;analyzed later with FILDDT.
PLM
;-
MLP
ERRTRP: MOVEM P,CRSACS+P ;Save P
ASSUME P,17 ;P must be last
MOVEI P,CRSACS ;Save all ACs
BLT P,CRSACS+P-1
MOVE P,[-10,,CRSPDL] ;Point to crash PDL
IFE FTDBUG,<
PUSHJ P,TTYRST ;Free the TTY:
>
IFN FTDBUG,<
PJ P,TTYRST ;Free the tty:
>
RESET ;Clear the world
EXIT 1, ;Die relatively gracefully
JRST RESTRT ;Restart the prog
SUBTTL ATTACH/DETACH PSI routine
PLM
;+
;.hl Routine DATPSI
MLP
;DATPSI handles an ATTACH/DETACH PSI interrupt. This is so we can reset
;the old terminal and init the new terminal. Note that anything set
;after initialization time will not be preserved over an ATTACH.
;Note that ATTACH/DETACH PSIs occur at a higher PSI level than other
;interrupts.
PLM
;-
MLP
DATPSI: ADJSP P,4 ;Save the Ts (Don't have our own ACs)
DMOVEM T1,-3(P)
DMOVEM T3,-1(P)
SKIPGE T1,TTYUDX ;Don't reset if was detached
JRST DATPS1 ;Don't reset if was detached
CAME T1,CTLTTY ;TTY: reassigned?
JRST DATRET ;No
PUSHJ P,TTYRS1 ;Reset the settables
DATPS1: MOVE T1,DATVEC+.PSVIS ;Get the UDX
MOVEM T1,TTYUDX ;Save in all the appropriate places
MOVEM T1,HPSUDX
MOVEM T1,LEDUDX ;For checking line editing
MOVEM T1,CTLTTY ;Same as before
MOVEM T1,ECCUDX ;..
MOVEM T1,BKCUDX ;Count of characters to echo
MOVEM T1,CTOUDX
MOVEM T1,COSUDX
MOVEM T1,PAGUDX ;...
JUMPL T1,DATRET ;If just got detached, return
PJOB T1, ;Get current job
MOVNS T1
JOBSTS T1, ;Get job status word
SETZ T1, ;Oh well
TLNN T1,(JB.UML) ;We at monitor level?
JRST ATTOK ;No, proceed
MOVEI T1,.IOASC ;Set a reasonable mode
SETSTS $TTY,(T1)
ASSUME .IOASC,0
OUTCHR T1 ;Wait for user level
CLRBFI ;Make PIM happy
SETSTS $TTY,@TTYBLK ;Reset TTY:
ATTOK: PUSHJ P,SETTTY ;Set the settables
PUSHJ P,TTYSST ;According to what it should be
SETZ T1,
SLEEP T1, ;Cancel old clock req
DATRET: DMOVE T1,-3(P) ;Restore Ts
DMOVE T3,-1(P)
ADJSP P,-4
DEBRK.
JRST E..DNI
POPJ P,
SUBTTL DECnet interrupt routine
PLM
;+
;.hl Routine DCNPSI
MLP
; DCNPSI is the operating system independent NSP. interrupt service
;routine. It calls EXCACS to set up the NSP. ACs. It then decides if
;this is more data available for a previously not completely read
;network message. If so, in dispatches to NSPCON to finish the read.
;Otherwise, it checks the state of the connection, and, if it it is
;DR, it outputs the "[Connection to remote node aborted]" message and
;exits through NSPER1. If neither of the above is true, it checks for
;network input and inputs any available, then attempts to
;push out any pending network output. If any network input now exists,
;it calls the operating system dependent network interrupt service
;routine (whose address was stored at initialization in OSNSP). Upon
;return it loops to check for more input and to attempt to send out
;pending output. When no input is available, it restores the ACs in
;use before the interrupt and dismisses the interrupt.
PLM
;-
MLP
DCNPSI: AOSE INTLVL ;Get the interlock
ERR INA,<Interlock not available>
PUSHJ P,EXCACS ;Get right ACs
EXP NSPACS ;Which set
TXNE F,F$NEOM ;EOM seen?
JRST NSPCON ;No, continue
LDB T1,[POINT 6,NSPVEC+.PSVIS,^L<NS.STA>+5] ;Get current state
CAIN T1,.NSSDR ;Disconnect Received?
JRST NSPERR ;Go clean up
NEWNET: PUSHJ P,NSPIN ;See if any network input
JRST NSPERR ;Oops
PUSHJ P,NSPO ;Output network stuff if can
JRST NSPERR ;Oops
SKIPG IBFCNT ;If nothing the sleep
JRST NSPRET ;Restore the world and return
PUSHJ P,@OSNET ;Process network input
PUSHJ P,DOOUT1 ;Force the buffer out then
TXZE F,F$USRV ;Want TTY: service?
PUSHJ P,TTYPS1 ;Yes
JRST NEWNET ;Check for more
NSPRET: PUSHJ P,EXCACS ;Get the ACs back
EXP NSPACS
SETOM INTLVL ;Clear the interlock
DEBRK.
JRST E..DNI ;Not implemented
POPJ P, ;In case not called at PSI level
SUBTTL TMR PSI routine
PLM
;+
;.hl Routine TMRPSI
MLP
; This is the operating system independent PITMR. trap routine.
;It first loads up the timer service ACs. If OSTMR is non-zero, it
;treats it as the address of the operating system dependent timer service
;routine and dispatches there. Upon return, or if OSTMR is zero, it
;loads up the AC set in use at the time of the interrupt and dismisses
;the interrupt. The check for non-zero OSTMR is because this routine is
;not used by all operating systems, and, even then, not all the time.
;Although we should not take a trap unless OSTMR is non-zero, it is probably
;not harmful to dismiss any interrupt we may get.
PLM
;-
MLP
TMRPSI: AOSE INTLVL ;Get the interlock
JRST E..INA ;Interlock not available
PUSHJ P,EXCACS ;Switch ACs
EXP TMRACS ;Which ACs
SKIPE OSTMR ;Any routine?
PUSHJ P,@OSTMR ;Yes, call it
PUSHJ P,EXCACS
EXP TMRACS ;Restore the ACs
SETOM INTLVL ;Free the interlock
DEBRK.
JRST E..DNI
POPJ P,
SUBTTL WAKE PSI Service
PLM
;+
;.hl Routine WAKPSI
MLP
; WAKPSI is the WAKE UUO PSI service routine. This consists merely of
;checking to see if F$USRV is set. If it is, we proceed to TTYPSI; if not
;we just dismiss the interrupt.
PLM
;-
MLP
WAKPSI: TXZE F,F$USRV ;Really wanted this?
JRST TTYPSI ;Yes, proceed
DEBRK. ;Toss it
JRST E..DNI ;Oops
POPJ P,
SUBTTL TTY: PSI Service
PLM
;+
;.hl Routine TTYPSI
MLP
; TTYPSI is entered via a PSI interrupt for I/O done to the TTY:
;or via a WAKE UUO. TTY: I/O PSIs happen at a higher interrupt than
;other PSIs (except ATTACH/DETACH PSIs). If another interrupt is in
;progress, the location INTLVL is non-negative and TTYPSI will store
;the status bits for the requesting interrupt, queue a forced TTY:
;interrupt via FRCTTY, and dismiss the higher level interrupt.
;Like all interrupt service routines, it first loads up its own AC set.
;If in PIM mode, TTYPSI proceeds to directly read input. Otherwise,
;it checks to see if there is an outstanding read. If there is, it
;proceeds to read, first checking to be sure the TTY: is echoed if it
;should be. If there is not read outstanding, we make sure the TTY: is
;not echoed. This is to simulate the ECHO DEFERed mode which systems
;such as VMS expect. We then attempt to read TTY: input. If the IN
;fails, be check if IO.EOF or any error bits are set. If IO.EOF is set,
;we CLOSE the TTY: and try the read again. If any error bits are set,
;we stopcode. If neither is true, we restore ACs and dismiss the interrupt.
;We then check to be sure OSTTY is non-zero (in case this came in
;before we were set up). If zero, we restore ACs and dismiss the interrupt.
;Otherwise, we allocate an internal buffer for the input and chain it off
;of any existing buffers. We move the haracters to the input buffer and
;call the operating system dependent TTY: service routine. Upon return,
;we loop back to check for more input.
PLM
;-
MLP
TTYPS1: TXO F,F$NDB ;Don't DEBRK.
JRST TTYPS2 ;Continue
TTYPSI: AOSE INTLVL ;Get the interlock
JRST TTYDFR ;Defer the interrupt
TTYPS2: PUSHJ P,EXCACS ;Set AC set
EXP TTYACS ;TTY: ACs
TXNN F,F$PIM ;PIM?
PUSHJ P,CHKCTO ;Read it
MOVE T1,TTYVEC+.PSVFL ;Reasons
IORM T1,TTYSTS ;Set what we need to do
TTYPS3: MOVEI T1,PS.ROD!PS.REF ;Output done some time?
TDNE T1,TTYSTS ;?
PUSHJ P,TOOUTA ;See if can output anything
MOVEI T1,PS.RID!PS.REF ;Input done
TDNN T1,TTYSTS ;?
JRST TTYRET ;Nothing more to do
TTYNEW: MOVEI T1,PS.RID!PS.REF ;We are going to service this now
ANDCAM T1,TTYSTS ;So clear it here
TXNE F,F$PIM ;PIM
JRST ISREAD ;Skip this stuff then
MOVEI T1,IO.SUP ;Get SUP bit
TXNN F,F$READ ;Read active?
TDNE T1,TTYBLK ;Is it already on?
JRST ISREAD ;No problem
IORB T1,TTYBLK ;Update status
SETSTS $TTY,(T1) ;Make TTY: reflect it
ISREAD: IN $TTY, ;Get a buffer
JRST TTINOK ;Win
TXNN F,F$FRC ;Force set?
TXNN F,F$PIM ;No, is PIM set?
TRNA ;Force is or PIM is not
JRST TTYRET ;Can't get EOF on PIM anyway
PUSHJ P,SETCTO ;Set the ^O bit
GETSTS $TTY,T1 ;Get tty status
TRNN T1,IO.EOF!IO.ERR ;Error or EOF?
JRST TTCFRC ;Check the force flag
TRNN T1,IO.EOF ;EOF?
ERR ITF,<IN UUO for TTY: failed>
MOVEI T1,PS.REF ;Clear EOF pending
ANDCAM T1,TTYSTS
CLOSE $TTY, ;Close TTY:
JRST ISREAD ;Check again
TTCFRC: TXNN F,F$FRC ;Force set?
JRST TTYRET ;Done if not
JRST TTYDBK ;But don't allocate buffers
TTINOK: SKIPG T1,TIBUF+.BFCNT ;Get number of bytes
JRST TTYDBK ;Don't bother allocating buffer
IDIV T1,BYTPWD ;Compute number of words
SKIPE T2
AOJ T1, ;Get it
MOVEI T1,IBF.PT+1(T1) ;Include header
MOVNI T2,(T1) ;Get negative size in T2
PUSH P,T1 ;Save on stack
PUSHJ P,CORGET ;Get a block of core
HRLZM T2,IBF.LK(T1) ;Save size
MOVEI T2,INPQUE-IBF.LK ;Point to input queue
QUECHK: SKIPG IBF.LK(T2) ;End yet?
JRST QUEFND ;Yes
HRRZ T2,IBF.LK(T2) ;Point to next
JRST QUECHK
QUEFND: MOVNS IBF.LK(T2) ;Make it not last
HRRM T1,IBF.LK(T2) ;Point previous to us
MOVE T2,TIBUF+.BFCNT ;Get character count
MOVEM T2,IBF.CT(T1) ;Save it
SKIPGE ICHCNT ;If count is negative
SETZM ICHCNT ;Zap it here
ADDM T2,ICHCNT ;And increase total # of chars
HLL T2,TIBUF+.BFPTR ;Get size
HRRI T2,IBF.DT-1(T1) ;Where it will go
MOVEM T2,IBF.PT(T1) ;Point there
HRL T2,TIBUF+.BFPTR ;First address of data
ADJSP T2,1 ;Add [1,,1]
ADD T1,(P) ;Compute last word of buffer
POP P,(P) ;Fix stac
BLT T2,-1(T1) ;Copy the data
TTYDBK: SKIPN OSTTY ;Be sure there's a routine
JRST TTYDB1
TXNN F,F$FRC ;Force set?
SKIPLE ICHCNT ;Or nothing to do
PUSHJ P,@OSTTY ;Call the OS's TTY input routine
MOVEI T1,PS.RID ;Be sure we check
IORM T1,TTYSTS ;..
JRST TTYPS3 ;Check for more TTY: input
TTYDB1: TXZ F,F$FRC ;Will exit on no more input
JRST TTYPS3 ;If F$FRC not set
TTYRET: MOVEI T1,PS.RID!PS.ROD!PS.REF ;Defer something?
TDNE T1,TTYSTS ;?
TXO F,F$USRV ;Make sure can get here if not immediately
PUSHJ P,EXCACS
EXP TTYACS ;Restore the old ACs
TXZE F,F$NDB ;DEBRK.?
POPJ P, ;No
SETOM INTLVL ;Free the interlock
DEBRK.
JRST E..DNI
POPJ P, ;If not called at PSI level
;Here if the interrupt level database is interlocked. Queue the interrupt
;for later
TTYDFR: PUSH P,T1 ;Save T1
MOVE T1,TTYVEC+.PSVFL ;Get condition
IORM T1,TTYSTS ;Say what we want to do
TRNE T1,PS.ROD ;Output done?
AOSE T1,SLPFLG ;Waiting for it?
TRNA ;No
SLEEP T1, ;Kill old sleep queue entry
PUSHJ P,FRCTTY ;Queue an interrupt for later
POP P,T1
DEBRK.
JRST E..DNI
POPJ P, ;?
SUBTTL TTY: Service -- Flush all type-ahead
PLM
;+
;.hl Routine FLSTAH
MLP
; FLSTAH is called to flush all type-ahead, both in internal
;chunks and monitor chunks. It uses no ACs.
PLM
;-
MLP
FLSTAH: PUSHJ P,SAVT ;Save the Ts
SETZM ICHCNT ;No characters
SETZM BRKNUM ;No breaks to pass
SKIPN T1,INPQUE ;Get queue contents
JRST FLSTAM ;None
FLSTAL: SETZM IBF.CT(T1) ;Clear the count
SKIPLE T1,IBF.LK(T1) ;Point to next
JRST FLSTAL
JUMPG T1,FLSTAL ;If more, continue
FLSTAM: MOVE T1,[2,,T2] ;Clear the chunks too
MOVEI T2,.TOCIB
MOVE T3,TTYUDX
TRMOP. T1,
JFCL ;Oh well
POPJ P,
SUBTTL TTY: Service -- Set Data Mode and Mask
PLM
;+
;.hl Routine TTYSST
MLP
; TTYSST is the general routine to change the state of the terminal.
;It will set the data mode to .IOPIM if F$PIM is set, otherwise it sets
;it to .IOASL with IO.ABS set so break masks may be enabled. Location
;IMASK is used as the argument to the .TOSBS TRMOP. TTYSST guarantees
;that the escape character is part of the break mask. TTYSST also
;includes or excludes ^Q/^S in the mask depending on the setting of
;the page mode bit for the TTY: (.TOPAG TRMOP.) TTYSST uses no ACs.
;TTYSST will clear buffers if the terminal mode changes and it will change
;the pointers in the buffer header blocks. It will also attempt to wait
;(read "BLOCK") for all output buffers to finish being output to the
;TTY: if the data mode (byte size) changes.
PLM
;-
MLP
TTYSST:
SAVE <T1,T2> ;No registers get clobbered
MOVEI T1,IO.ABS ;Always on, for .TOSOP
TXNE F,F$READ ;Read not set, always noecho
TXNE F,F$NEC ;Read set, is noecho?
TRO T1,IO.SUP ;Yes. supress it locally
TLNE F,(F$PIM) ;Want to use PIM (passall)?
TROA T1,.IOPIM ;Use PIM mode
TROA T1,.IOASL ;Use ASCII line if not PIM
SKIPA T2,[POINT 8,4,35] ;PIM is 8 bit bytes, 4/word
MOVE T2,[POINT 7,5,35] ;ASCII is 7 bit bytes, 5/word
TXNN F,F$LEM!F$PALL!F$RALL ;If these are set
TXNN F,F$READ ;Logical read outstanding?
TRO T1,IO.LEM ;No, swallow these too
TLO T1,(UU.AIO) ;Set ASYNC I/O
CAMN T1,TTYBLK ;Any changes?
JRST SETBKM ;No. Just set break mask
XORM T1,TTYBLK ;Get differences
EXCH T1,TTYBLK ;Get XOR, save new status
TRNN T1,IO.MOD ;Any mode differences?
JRST NBFCHG ;No buffer changes
PUSHJ P,WATDEQ ;Wait for buffers to dequeue
HLLM T2,TIBUF+.BFPTR
HLLM T2,TOBFH+.BFPTR ;Set output pointer
HLLM T2,BUFCHR
HRRZM T2,BYTPWD ;Save byte size (for interrupt level)
HRRZ T2,BUFCHR ;Number of words in buffer
IMUL T2,BYTPWD ;Total number of chars in buffer
MOVEM T2,CHPBUF ;Set number of characters in buffer
SETZM TIBUF+.BFCTR ;Clear buffers
NBFCHG: SETSTS $TTY,@TTYBLK ;Set the bits
SETBKM: TLNE F,(F$PIM) ;Using PIM?
JRST TTYSSZ ;Yes, don't bother with break mask
MOVE T1,ESCBIT ;Escape character bit
MOVE CX,ESCWRD ;Word
IORM T1,IMASK+1(CX) ;Be sure the break character's there
MOVX T1,1B<.CHCNW> ;No one supports ^W
TXNE F,F$NLF
TXO T1,1B<.CHCRT> ;If <CR> isn't to generate <LF>
TXNE F,F$ESC ;Want escape recognition?
TXO T1,1B<.CHESC> ;Yes
IORM T1,IMASK+1 ;Set it
MOVE T1,[2,,PAGTRM] ;Find the page bit
TRMOP. T1,
SETZ T1, ;Default
JUMPE T1,TTSNPG ;Don't change anything
MOVX T2,<1B<.CHCNS>!1B<.CHCNQ>>
IORM T2,IMASK+1 ;Default we get them
ANDCM T2,OBMASK ;VAX needs to see these
ANDCM T2,OBMASK+1
TXNN F,F$RALL!F$PALL ;Readall or passall?
ANDCAM T2,IMASK+1 ;Default can't get them
TTSNPG: MOVX T1,1B<.CHCNO>
IORM T1,IMASK+1 ;Default we see it
TXNN F,F$ACO!F$RALL!F$PALL ;Allow ^O if we need to
ANDCAM T1,IMASK+1
SKIPN T1,IMASK ;If field width got zapped,
MOVEI T1,1 ;Make it one
CAIL T1,400 ;Max is 377 (octal)
MOVEI T1,377 ;So set that
MOVEM T1,IMASK ;..
MOVE T1,[7,,TRMBKS] ;Set break set
TRMOP. T1,
JFCL ;Oops
TTYSSZ: RESTORE <T2,T1> ;
POPJ P, ;Return
SUBTTL TTY: Service -- Check for line editing
PLM
;+
;.hl Routine CHKLED
MLP
; CHKLED is called to see if line editing needs to be done on
;type-ahead we haven't yet seen. Return CPOPJ if something needs to
;be done; CPOPJ1 if not. **THE BREAK SET IN USE IS ALTERED HERE
;AND NOT CHANGED BACK, BUT IMASK IS LEFT AS THE "DESIRED" MASK**.
;AND IS ALTERED BACK ONLY IF THERE IS NO LINE EDITING TO DO.
;IMASK IS LEFT AS THE "DESIRED" MASK IN ALL CASES, HOWEVER.**
;It uses nothing.
;-
MLP
CHKLED: PUSHJ P,SAVT ;Save the ACs
MOVE T1,[7,,LEDTRM] ;See if anything to do
TRMOP. T1,
JRST CHKLEX
MOVE T1,[2,,T2] ;Find number of characters now
MOVEI T2,.TOBKC ;..
MOVE T3,TTYUDX
TRMOP. T1,
JRST CHKLEX
JUMPN T1,CPOPJ
CHKLEX: AOS (P)
MOVE T1,[7,,TRMBKS] ;Restore the mask
TRMOP. T1,
JFCL
POPJ P,
SUBTTL TTY: Service -- Check/Set ^O bit
PLM
;+
;.hl Routines CHKCTO, SETCTO, and CLRCTO
MLP
; These routines handle the control-O bit in relation to F$CTO.
;CHKCTO sets F$CTO according to the bit as the monitor sees it.
;SETCTO sets the output suppression bit if F$CTO is set. **IT DOES
;NOTHING IF F$CTO IS CLEAR**. CLRCTO clears both F$CTO and the monitor's
;output suppression bit. These routines use CX.
PLM
;-
MLP
CHKCTO: TXNE F,F$ICO ;Didn't do this earlier so could make
POPJ P, ;PIM check at TTYPSI: faster
MOVE CX,[2,,CTOTRM]
TRMOP. CX,
SETZ CX,
DPB CX,[POINT 1,F,<^L<F$CTO>>]
JUMPN CX,CLRTOQ ;Be sure queue is cleared
POPJ P,
SETCTO: TXNN F,F$ICO ;Ignore?
TXNN F,F$CTO
POPJ P, ;Assuming it's clear
MOVE T1,[3,,CTOTRS] ;The TRMOP.
SETOM COSVAL
TRMOP. T1,
JFCL
POPJ P,
CLRCTO: TXZ F,F$CTO!F$ICO
CLRCO1: MOVE CX,[3,,CTOTRS]
SETZM COSVAL
TRMOP. CX,
JFCL
POPJ P,
SUBTTL TTY: Service -- Wait for output to finish
PLM
;+
;.hl Routines WATOUT, WATDEQ, and WATIDL
MLP
; These routines are called to block for various forms of TTY: output
;to complete. WATDEQ waits until all buffers are dequeued and the buffer
;is empty. WATIDL waits until the characters are also out of the chunks.
;WATOUT first calls WATDEQ and then WATIDL. These routines uses no ACs.
PLM
;-
MLP
WATOUT: PUSHJ P,WATDEQ
PJRST WATIDL
WATDEQ: PUSHJ P,SAVT ;Save the Ts
PUSH P,F ;Save the flags
TXZ F,F$IOQ ;Must ignore here
SKIPN TOBUF ;Is there a buffer already?
JRST WOUT5A ;No
MOVE T1,CHPBUF ;Get total number of available chars
SUB T1,TOBUF+2 ;Real number of characters
JUMPG T1,WOUT2 ;Nothing to do
HRRZ T1,TOBUF ;Get buffer pointer
HRRZ T2,BUFCHR ;Size
MOVEI T2,1(T2) ;Plus link
PUSHJ P,CORFRE ;Deallocate it
JRST WOUT5
WOUT2: HRLM T1,@TOBUF ;Store the count
HRRI T1,TOQUE ;Point to output queue
WOUT3: HRL T1,(T1) ;Get link
TLNN T1,-1 ;Another buffer?
JRST WOUT4 ;No
HLRZS T1 ;Point ahead
JRST WOUT3 ;Continue
WOUT4: HRL T1,TOBUF ;Pointer to buffer
HLRM T1,(T1) ;Link it in
WOUT5: SETZM TOBUF
SETZM TOBUF+1
SETZM TOBUF+2 ;Zap old pointers
WOUT5A: MOVE T4,TTYUDX
MOVEI T1,^D60 ;Long wait for queueing
TXO F,F$IEC ;Ignore LDBECC
WOUT6: SKIPN TOQUE ;Anything more to queue?
SKIPGE TOBFH+.BFCNT ;Or output?
JRST WOUT7 ;Try to dequeue buffer
WATRET: POP P,T1 ;Saved flags
TXNE T1,F$IOQ ;Was this set before?
TXO F,F$IOQ ;Yes, set it again
TXZ F,F$IEC
POPJ P,
WOUT7: PUSHJ P,TOOUT ;Dequeue buffers
SKIPN TOQUE ;Still stuff to dequeue?
SKIPGE TOBFH+.BFCTR ;Or wait for I/O complete?
PUSHJ P,TOHIBR ;Wait a bit
JRST WOUT6
WATIDL: PUSHJ P,SAVT ;Save the Ts
PUSH P,F ;Save the flags
TXZ F,F$IOQ ;Must ignore here
WATID1: DMOVE T2,[ 2,,T3
.TOSTP ] ;Output stopped?
TRMOP. T2,
SETZ T2, ;Assume it isn't
SKIPN T2 ;Output stopped?
TDZA T1,T1 ;No, short wait
MOVEI T1,^D60 ;Else long wait
DMOVE T2,[ 2,,T3
.TOSOP ] ;Is output going on?
TRMOP. T2,
JRST WATRET
PUSHJ P,TOHIBR ;Turn PIs off and wait
JRST WATID1 ;Try to force out again
SUBTTL TTY: Service -- Wait for available buffer
PLM
;+
;.hl Routines TOBLOK and TOHIBR
MLP
; Call TOBLOK to sleep until a buffer ready. TOBLOK uses no ACs.
;Note that TOBLOK only waits for one buffer to become available
;(although more may in fact be available. TOHIBR is used by TOBLOK and WATOUT
;to HIBER using the bits specified in T1 to HIBER with PSI turned off
;(HIBER doesn't hiber if this is not true and an interrupt is pending).
;TOHIBR destroys nothing.
PLM
;-
MLP
TOBLOK: PUSHJ P,SAVT
MOVEI T1,^D60 ;Sleep time
PUSH P,F ;Save F
TXO F,F$IEC ;Ignore ECC
TXZ F,F$IOQ ;Clear this too
TOBLK1: SKIPLE BUFQUO ;One available?
JRST TOBLK2 ;Return
PUSHJ P,TOHIBR ;So can use PIOSAV
PUSHJ P,TOOUT
JRST TOBLK1
TOBLK2: TXZ F,F$IEC
POP P,T1
TXNE T1,F$IOQ ;Was this on?
TXO F,F$IOQ ;Yes
POPJ P,
TOHIBR: PUSHJ P,TOHB2 ;So can use PIOSAV
SLEEP T1,
POPJ P,
TOHB2: PUSHJ P,PIOSAV ;Must, so HIBER works
SETZM SLPFLG
AOS SLPFLG ;Set sleep flag
POPJ P, ;Return
SUBTTL TTY: Service -- Scan input for special characters
PLM
;+
;.hl Routine SCNSPC
MLP
; Call SCNSPC to scan the input queue for "special" characters.
;Enter with T2 pointing to the appropriate "special" character table
;Returns CPOPJ1 if a special character is not found.
;Returns CPOPJ if one is found, with P4 pointing to
;the input buffer the character was found in (or 0 if in INPCHR),
;P1 containing the character,
;P3 containing the number of characters left in the buffer pointed to by P4,
;and P2 containing the LDB pointer to the character found (NOT ILDB!)
;Table CHRTAB is the bit mask to the "special" characters.
;SCNSPC will also set F$BRK if a break character (as defined by LMASK)
;is seen during the scan (i.e. before a special character if one is
;seen or in the whole string if no special characters). ICHCNT will
;also be updated to be "correct" (no nulls counted) up to the point
;of scan termination. Note that SCNSPC should NOT be called if
;not in "line" mode (as specified by F$PIM). If neither a break nor a
;special character is found, P1 contains the last non-null character scanned.
;SCNSPC uses ALL ACs.
PLM
;-
MLP
SCNSPC: SETZ P1, ;Assume no special chars
TXNE F,F$PIM ;In "line" mode?
JRST CPOPJ1 ;No, nothing is special
PUSH P,P1 ;Last non-special character
TXZ F,F$BRK!F$ESA ;Clear break seen, escape active
SETZ P4, ;In case we find it here
SKIPN P1,INPCHR ;Is there already one there?
JRST SCNSP1 ;Not set
PUSHJ P,SPCCHK ;Special character?
TRNA ;No
JRST TPOPJ ;Clear junk and return
SCNSP1: MOVE P1,BRKNUM ;Total number of breaks to pass
MOVEM P1,BRKCNT ;Initialize the count
PUSHJ P,SCNINI ;Init the character scanner
SPCLP: PUSHJ P,SCNCHR ;Get character from stream
JRST P1POJ1 ;Get last non-special and return
JUMPN P1,SPLOOK ;Look at character
SOS IBF.CT(P4) ;Get rid of null in
SOS ICHCNT ;Both character counts
JRST SPCLP
SPLOOK: PUSHJ P,SPCCHK ;Is it special?
TRNA ;Normal
JRST TPOPJ ;Clear junk and return
PUSHJ P,CHKBRK ;Break character?
TLOA F,(F$BRK) ;Set seen
MOVEM P1,(P)
JRST SPCLP ;And look for more
;Here if want to continue scanning
CONSCN: PUSH P,[0] ;Last non-special
JRST SPCLP ;Continue
;PLM
;+
;.hl Routine SPCRMV
MLP
; SPCRMV is a routine to remove a "special" character from
;the input stream and shuffle succeeding characters down.
;Call with P2, P3, P4 as returned from SCNSPC. It uses P1-P3 and CX.
PLM
;-
MLP
SPCRMV: SOS IBF.CT(P4) ;Take the character out of the string
SOS ICHCNT ;Total number of chars now one less
MOVNI P1,1 ;Back up the byte pointer
ADJBP P1,P2
JUMPE P3,CPOPJ ;If last character, don't worry
SPCRM1: ILDB CX,P2 ;Get next character
IDPB CX,P1 ;Move it back
SOJG P3,SPCRM1 ;Move ahead
POPJ P, ;Done
PLM
;+
;.hl Routine SPCFLS
MLP
; SPCFLS is a routine to FLUSH input up to the special chracter found
;by SCNSPC. Call with P2, P3, P4 as returned from SCNSPC. It uses T1-T2.
PLM
;-
MLP
SPCFLS: MOVE T1,IBF.CT(P4) ;Get total number of chars in buffer
SUBI T1,(P3) ;# skipped over
SUBM T1,ICHCNT ;ICHCNT now has -#chars
MOVEM P3,IBF.CT(P4) ;Set the count
MOVEM P2,IBF.PT(P4) ;Set the pointer
MOVEI T1,INPQUE-IBF.LK ;Point to start of input
FLSLP: HRRZ T1,IBF.LK(T1) ;Point to this buffer
CAIN T1,(P4) ;The current buffer?
JRST FLSDON ;Yes
SKIPLE T2,IBF.CT(T1) ;If real characters,
ADDM T2,ICHCNT ;"Subtract" from total
SETZM IBF.CT(T1) ;None there
JRST FLSLP ;Next buffer
FLSDON: MOVNS ICHCNT ;Make positive again
PJRST CNTESC ;Count number of breaks
PLM
;+
;.hl Routine SPCCHK
MLP
; This is a routine to check if character in P1 is a "special" character.
;Return CPOPJ1 if it's special, CPOPJ otherwise. It uses T1-T3.
PLM
;-
MLP
SPCCHK: SOSGE BRKCNT ;Count down number of breaks
CAME P1,ESCCHR ;No, is this it?
TRNA ;Yes or no
JRST CPOPJ1 ;It's special
TRNE F,F$PALL!F$RALL ;Pass all?
POPJ P, ;Yes
MOVEI T1,(P1) ;Make copy of char
IDIVI T1,^D36 ;Make bit mask
MOVNS T2
MOVSI T3,400000
LSH T3,(T2) ;Get the mask
TDNE T3,CHRTAB(T1) ;Check the bit
AOS (P) ;Flag found character
POPJ P,
SUBTTL TTY: Service -- Count number of escape characters
PLM
;+
;.hl Routine CNTESC
MLP
; CNTESC is called to count the number of escape characters in the
;input stream and set BRKNUM to that number.
PLM
;-
MLP
CNTESC: SAVE4
PUSHJ P,PIOSAV ;..
PUSHJ P,SCNINI ;Count number of escapes in stream
SETZM BRKNUM ;Number of break characters
CNTBRK: PUSHJ P,SCNCHR ;Get character
POPJ P, ;Done
CAMN P1,ESCCHR ;Escape character?
AOS BRKNUM ;Yes
JRST CNTBRK ;Continue
SUBTTL TTY: Service -- Input scan routines
PLM
;+
;.hl Routines SCNINI SCNCHR, SCNLBK and SCNLCH
MLP
; These routines are used to scan the input queue
;for certain conditions being met. You must preserve all
;"P" ACs across calls to these routines in order to use these routines.
PLM
;.list 1
;.le
MLP
;SCNINI - Set up "P" ACs for an input scan.
;SCNINI uses no ACs other than the "P"s.
PLM
;-
MLP
SCNINI: SKIPN P4,INPQUE ;Point to input queue
JRST [MOVEI P4,INPQUE-IBF.LK
SETZ P3, ;There's nothing to read
POPJ P, ]
MOVE P3,IBF.CT(P4) ;Count
MOVE P2,IBF.PT(P4) ;Pointer
SETZ P1, ;No initial character
POPJ P,
PLM
;+
;.le
MLP
;SCNCHR - Return with next input character in T1. Return CPOPJ1 if
;a character is present, CPOPJ if done.
PLM
;-
MLP
SCNNEW: SKIPG P4,IBF.LK(P4) ;Point to next buffer
POPJ P, ;If none
MOVE P3,IBF.CT(P4)
MOVE P2,IBF.PT(P4)
SCNCHR: SOJL P3,SCNNEW ;New buffer time
ILDB P1,P2
ANDI P1,177 ;Strip parity
JRST CPOPJ1
PLM
;+
;.le
PLM
;SCNPOS - Given ACs as returned from SCNSPC, figure the position
;in the input stream of the special character. It uses T1-T2.
PLM
;-
MLP
SCNPOS: MOVNI T1,(P3) ;Initialize the count
MOVEI T2,(P4) ;Init buffer link
POSLP: SKIPG T2,IBF.LK(T2) ;Next
JRST POSDON ;Done
SUB T1,IBF.CT(T2) ;Subtract the characters
JRST POSLP
POSDON: ADD T1,ICHCNT ;From total
POPJ P,
PLM
;+
;.le
MLP
;SCNLBK - Scan to last break character before character pointed to
;by P2. It uses T1-T4 also.
PLM
;-
MLP
SCNLBK: MOVE T1,P2 ;Save pointer
PUSHJ P,SCNINI ;Re-initialize
ADJSP P,4 ;Allocate stack space
DMOVEM P1,-3(P)
DMOVEM P3,-1(P) ;Initially the beginning
PUSH P,T1 ;And save the pointer
SCNLB1: CAMN P2,(P) ;The final pointer?
JRST SCNLB3 ;Yes
PUSHJ P,SCNCHR ;Scan a character
ERR CSC,<Couldn't find specified character>
PUSHJ P,CHKBRK ;Is it a break?
CAMN P2,(P) ;Yes, but not the target char
JRST SCNLB1 ;No, loop back
DMOVEM P1,-4(P) ;Save the ps
DMOVEM P3,-2(P) ;..
JRST SCNLB1
SCNLB3: POP P,(P) ;...
PJRST .RES4 ;Restore Ps
PLM
;+
;.le
MLP
;SCNLCH - Scan to immediately preceding character.
;Scan to character preceding that pointed to by P4.
;Return with Ps intact, and Ts set to values from SCNINI/SCNCHR.
PLM
;-
MLP
SCNLCH: SAVE4 ;Save the Ps
PUSHJ P,SCNINI ;Initialize a scan
TXO F,F$P2 ;General PASS2 flag
SCNLC1: DMOVE T1,P1 ;Save it's first character
DMOVE T3,P3
PUSHJ P,SCNCHR ;Get chracter
POPJ P, ;?
CAMN P2,-3(P) ;POinters match
POPJ P, ;Return if so
TXZE F,F$P2 ;If haven't already
AOS (P) ;Flag at least one char to undo
JRST SCNLC1
PLM
;+
;.le
MLP
;SETICH - Set ICHCNT to be accurate (toss nulls).
PLM
;-
MLP
SETICH: SAVE4 ;Save the Ps
PUSHJ P,SCNINI ;Input a character
ICHLP: PUSHJ P,SCNCHR ;Get a character
JRST SETIC2 ;More
JUMPN P1,ICHLP ;If non-zero, nothing
SOS IBF.CT(P4) ;Decrement chunk count
SOS ICHCNT ;And total count
JRST ICHLP
SETIC2: SKIPGE ICHCNT
SETZM ICHCNT ;It's really zero
POPJ P,
PLM
;+
;.end list
;-
MLP
SUBTTL TTY: Service -- Check for break character
PLM
;+
;.hl Routines CHKBRK and CHKBR1
MLP
; Enter at CHKBRK with the character in question in P1;
;enter at CHKBR1 with character in T1 to save T1 (RH only saved)
;Return CPOPJ if character IS in the break set, CPOPJ1 otherwise
PLM
;.note
MLP
;Location BRKSIZ is incremented each time a compenent of a break is passed.
;***IT IS THE RESPONSIBILITY OF THE CALLER TO BE SURE LOCATION BRKSIZ
;IS ZEROED AT THE RIGHT TIME***
PLM
;.end note
MLP
;Both routines use T1-T4 and CX, except that CHKBR1 saves the right half
;of T1. If the character in T1 IS a break character, CHKBR1 will store it
;in the left half of location BRKCHR.
PLM
;-
MLP
CHKBRK: SKIPA T1,P1 ;Copy to T1
CHKBR1: HRLM T1,BRKCHR ;Assume it's a character
TXNE F,F$ESC ;Want escape sequences?
JSP CX,CHKESC ;Yes
IDIVI T1,^D32 ;Compute index to word
MOVSI CX,(1B0) ;Make a mask
MOVNS T2
LSH CX,(T2) ;Compute bit mask
TDNN CX,LMASK(T1)
AOSA (P) ;Skip return if not a break
AOSA BRKSIZ ;Increment break size
SKIPA T1,BRKCHR ;Get character back
SKIPA T1,BRKCHR ;...
HRRZS BRKCHR ;No break yet
HLRZS T1 ;And restore character to T1
POPJ P,
SUBTTL TTY: Service -- Control-H Routine
PLM
;+
;.hl Control-H processing
MLP
;CHKCTH uses T1 and is called to see if the character in P1 is a control-H
;and if so, see if we should output one to the TTY:. This is for the benefit
;of those operating systems from whom control-H doesn't function as a rubout
;and isn't a break.
PLM
;-
MLP
CHKCTH: MOVE T1,ICHCNT ;Get characters available
EXCH T1,LICHCT ;Update
CAME T1,LICHCT ;As we last remember it?
CAIE P1,.CHCNH ;Yes, did we break for ^H?
POPJ P, ;Doesn't apply then
TXNE F,F$NEC ;Noechoed?
POPJ P, ;Doesn't apply then
MOVEI T1,($TOOIN) ;Override inhibit
MOVEM T1,TOFLGS
MOVEI T1,.CHCNH ;Else output one
PUSHJ P,OUTTTY
PUSHJ P,DOOUT1
SETZM TOFLGS
POPJ P,
SUBTTL TTY: Service -- Escape Sequence processing
PLM
;+
;.hl Escape sequence processing
MLP
;CHKESC is called to check if an escape sequence is beginning or ending.
;If the escape sequence finishes, then F$BRK is set. If an escape sequence
;begins, then F$ESA is set. If a bad character is encountered during
;processing, then F$BAD is set. CHKBRK/CHKBR1 and EKOTAH use this routine.
;It will increment BRKSIZ appropriately to the size of the escape sequence.
;An <ESC> will be stored in BRKCHR. The table driven routine for validating
;the escape sequences is rumoured to let a few bad sequences through, but
;should definitely pass all good ones. It was obtained from WSM of ISWS
;who borrowed it from another ISWSite who modified it from VMS' TTDRIVER
;(friend of a friend of a friend...).
PLM
;.note
MLP
;***Note that it is the caller's responsibility to initialize the appropriate
;parts of the data base, in particular, F$ESA. Note also that in general
;the base must be re-inited at each read request because of multiple
;scanning passes of the same stream with each read request, so
;all bets are off if a partial escape sequence has to be stored
;(i.e. the escape sequence gets split over a read request). VMS
;doesn't guarantee integrity across such anyway and RSX states nothing
;about it. The processing uses T1-T4 and CX.
PLM
;.end note
;-
MLP
CHKESC: TXNE F,F$ESA ;Escape sequence already active?
JRST ESCACT ;Yes
CAIE T1,.CHESC ;Is this an escape?
JRST (CX) ;No
TXO F,F$ESA ;Escape sequence now active
AOS BRKSIZ ;BRKSIZ one bigger
SETZM RULE ;Let's start at the very beginning...
TXZ F,F$BAD ;Assume a good escape sequence
SETOM IMASK+1 ;Break on all now
MOVE T1,[IMASK+1,,IMASK+2]
BLT T1,ENDMSK
MOVEI T1,1 ;Let the field width be 1
MOVEM T1,IMASK
AOS (P) ;Not a break yet
PUSHJ P,TTYSST ;Set up TTY:
PJRST FRCTTI ;Be sure see changes
ESCACT: JUMPE T1,CPOPJ1 ;Toss nulls (incomplete requests)
MOVE CX,RULE ;Get the current rule
PUSH P,T2 ;Need another bunch of ACs
PUSH P,T3 ;...
ESCLOP: LDB T2,[POINT 7,ESCTAB(CX),6]
LDB T3,[POINT 7,ESCTAB(CX),13] ;Get lower and upper bounds
CAIL T1,(T2)
CAILE T1,(T3) ;Is character between them?
JRST ESCAC5 ;No
AOS BRKSIZ ;Break is one character bigger
HRRZ CX,ESCTAB(CX) ;In between, more rules?
JUMPE CX,ESCDON ;No, finished
MOVEM CX,RULE
AOS -2(P) ;Skip return
JRST ESCRET ;Restore T2, T3 an return
ESCAC5: HRRZ T2,ESCTAB(CX) ;Didn't fit, another rule?
JUMPE T2,ESCERR ;Bad escape sequence
AOJA CX,ESCLOP ;Check it
ESCERR: TXO F,F$BAD ;Bad escape sequence
ESCDON: TXZ F,F$ESA ;No longer active escape
MOVEI T3,.CHESC ;Break character is escape
HRLM T3,BRKCHR ;Save it
ESCRET: POP P,T3
POP P,T2 ;Restore ACs
PJRST TTYSST ;Return, resetting TTY:
SUBTTL TTY: Service -- Escape sequence processing tables
PLM
;+
;.hl Table ESCTAB
MLP
; ESCTAB is the rule table used by CHKESC to define what is a legal
;ANSI escape sequence.
PLM
;-
MLP
ESCTAB:
<ASCII |;;|> !$10-ESCTAB ; <ESC><;><40:57>...<60:176>
<ASCII |??|> !$10-ESCTAB ; <ESC><?><40:57>...<60:176>
<ASCII |OO|> !$20-ESCTAB ; <ESC><O><40:57>...<100:176>
<ASCII |YY|> !$30-ESCTAB ; <ESC><Y><40:176>...<40:176>
;ANSI control sequence
<ASCII |[[|> !$15-ESCTAB ; <ESC><[><40:77>...<40:57>...<100:176>
;ESCape sequence <ESC><40:57>...<60:176>
$10: <ASCII | /|> !$10-ESCTAB
<ASCII |0~|> !0
$15: <ASCII |0?|> !$15-ESCTAB
$20: <ASCII | /|> !$20-ESCTAB
<ASCII |@~|> !0
$30: <ASCII | ~|> !$40-ESCTAB
$40: <ASCII | ~|> !0
Z
SUBTTL TTY: Service -- Echo type-ahead
PLM
;+
;.hl Routine EKOTAH
MLP
; EKOTAH is called to echo all characters in the input queue. It should,
;of course, only be called once for a given input stream. It uses T1-T4.
PLM
;-
MLP
EKOTAH: TXNE F,F$NEC ;Noecho?
POPJ P, ;Nice if filtered out earlier, but...
SAVE4 ;Save the Ps
TXO F,F$NEC ;Set no-echo
PUSHJ P,TTYSST
PUSHJ P,CLRCTO
PUSHJ P,WATDEQ ;Wait for output to complete
MOVEI P1,($TOICL!$TOOIN) ;Buffer flags
IORM P1,TOFLGS
PUSHJ P,SCNINI ;Init a scan
ECHOLP: PUSHJ P,SCNCHR ;Get a character
JRST EKOTAD ;Done
MOVEI T1,(P1) ;Copy character
PUSHJ P,CHKBR1 ;Break?
JRST [PUSHJ P,DOOUT1
SETZM TOFLGS
JRST EKOTAR ] ;Done
TXNE F,F$ESC ;Wanted ESC stuff?
TXZN F,F$ESA ;It became active?
TRNA
JRST EKOTAR
PUSHJ P,OUTTTY ;For now, assume just print it
JRST ECHOLP ;Continue
EKOTAD: PUSHJ P,DOOUT1 ;Force it out
SETZM TOFLGS ;Clear the flags
PUSHJ P,WATOUT ;Wait for it to complete
;Note that the below is a heuristic algorithm rather than a water-tight one.
DOFRCU: MOVE T1,[2,,T2] ;Make sure it's OK to do this
MOVEI T2,.TOBKC ;Get break count
MOVE T3,TTYUDX
TRMOP. T1, ;...
JRST EKOTAR
JUMPN T1,EKOTAR ;Don't do it
MOVE T1,[2,,T2] ;Only if priv'd, but c'est la vi
MOVE T2,[SIXBIT/.TYPE/]
MOVE T3,TTYUDX
FRCUUO T1,
JFCL
EKOTAR: TXZ F,F$NEC
PJRST TTYSST
SUBTTL TTY: Service -- Rubout processing
PLM
;+
;.hl Routine DORUB
MLP
; DORUB is called to do the "normal" thing on a rubout, that is,
;rub out the last character. It uses T1-T4 and P1-P4. Call it with
;P1-P4 set from SCNSPC.
PLM
;-
MLP
DORUB: PUSHJ P,SCNLCH ;Scan to last character
JRST SPCRMV ;Remove the <RUB> and return
ADJSP P,4 ;Allocate stack space
DMOVEM T1,-3(P) ;Save where last char is
DMOVEM T3,-1(P) ;..
PUSHJ P,SPCRMV ;Remove the rubout
DMOVE P1,-3(P) ;Restore stuff to Ps
DMOVE P3,-1(P)
ADJSP P,-4 ;and fix stack
PUSHJ P,CHKBRK ;Is this a break?
POPJ P, ;Just toss rubout if break
LDB T1,P2 ;Get character rubbed out
CAMN T1,ESCCHR ;Escape character?
SOS BRKNUM ;Yes, one less to scan past
PUSHJ P,RUBCHR ;Do a rubout
PUSHJ P,SPCRMV ;Remove character
POPJ P, ;Return
SUBTTL TTY: Service -- Routine to do display for <RUB>
PLM
;+
;.hl Routines RUBCHR and VIDRUB
MLP
; RUBCHR is called with the rubbed out character in T1. Its purpose
;is to do the "right" think on the screen. VIDRUB is called if we are on
;a CRT; it uses a table indexed by TTY: type to decide the sequence to
;rubout the character on the screen. Otherwise, the rubbed out character
;is delimeted by backslashes (consecutive characters get two backslashes
;between them).
PLM
;-
MLP
RUBCHR:
PUSH P,T1 ;Save character
MOVEI T1,($TOOIN)
MOVEM T1,TOFLGS
SKIPL T1,TTYTYP ;Can we do a video rubout?
JRST VIDRUB ;yes
MOVEI T1,"\" ;Delimit rubbed out char
PUSHJ P,OUTTTY
POP P,T1 ;Restore character
PUSHJ P,OUTTTY ;...
MOVEI T1,"\"
PUSHJ P,OUTTTY ;..
RUBRET: PUSHJ P,DOOUT1
SETZM TOFLGS
POPJ P,
VIDRUB: PUSH P,T4 ;Save T4
SOSGE T4,HPOS ;Be sure this is set correctly
SETZ T4, ;No negative positions
PUSH P,T4
HRRZ T4,RUBS1(T1) ;Point to string
PUSHJ P,STROUT ;Output it
POP P,HPOS ;Set HPOS correctly
POP P,T4 ;Restore T4
POP P,T1
JRST RUBRET
SUBTTL TTY: Service -- Handle Control-U
PLM
;+
;.hl Routine DOCTU
MLP
; DOCTU is called to do "normal" Control-U processing. Call it with
;P1-P4 set from SCNSPC. It uses P1-P4 and T1-T4.
PLM
;-
MLP
DOCTU: ADJSP P,3 ;Allocate stack space
DMOVEM P2,-2(P) ;Save P2 and P3
HRRZM P4,(P) ;And right half of P4
PUSHJ P,SCNLBK ;Scan to last break
HRRZS P4 ;Be sure only right half
CAMN P4,(P) ;In the same chunk?
JRST DOCTU5 ;Yes, handle differently
SUBM P3,ICHCNT ;All remaining chars in this chunk gone
SUBM P3,IBF.CT(P4) ;And here
MOVNS IBF.CT(P4) ;Keep the right sign
DOCTU2: HRRZ P4,IBF.LK(P4) ;Point to next link
CAMN P4,(P) ;One with the ^U in it?
JRST DOCTU3 ;Yes
MOVE T1,IBF.CT(P4) ;Get the count
ADDM T1,ICHCNT ;Remember ICHCNT has the wrong sign
SETZM IBF.CT(P4) ;No chars in this chunk
JRST DOCTU2 ;Until we hit the ^U
DOCTU3: POP P,P4 ;Restore where ^U was
POP P,P2 ;Count
POP P,IBF.PT(P4) ;It's where input will start
EXCH P2,IBF.CT(P4) ;Number of chars left
SUB P2,IBF.CT(P4) ;Difference=# chars skipped
ADDM P2,ICHCNT ;Take out of total
MOVNS ICHCNT ;And make right sign
DOCTU4: MOVEI T4,[ASCIZ/^U
/] ;Tell what we did
MOVEI T1,($TOOIN)
MOVEM T1,TOFLGS ;Override stuff
PUSHJ P,STROUT
PUSHJ P,DOOUT1 ;Force it out
SETZM TOFLGS
PJRST CNTESC ;Set BRKNUM
DOCTU5: ;Here if ^U and last break in same chunk
SUB P3,-1(P) ;# of chars skipped in chunk
MOVNS P3 ;Make negative
ADDM P3,ICHCNT ;So can take out of total
ADDM P3,IBF.CT(P4) ;And in this chunk
POP P,T4 ;Restore pointers in Ts
POP P,T3
POP P,T2
JUMPE T3,DOCTU4 ;If nothing else to do
DOCTU6: ILDB P1,T2
IDPB P1,P2 ;Else shuffle characters down
SOJGE T3,DOCTU6
JRST DOCTU4 ;Then return
SUBTTL TTY: Service -- Handle Control-R
PLM
;+
;.hl Routine DOCTR
MLP
; DOCTR is called to handle a Control-R. Call it with P1-P4 set
;up from SCNSPC and T1 set to address of routine to call after
;outputting "^R<CR><LF>", or zero if none.. It uses P1-P4 and T1-T4.
PLM
;-
MLP
DOCTR: MOVEI T4,[ASCIZ/^R
/] ;Preceed with <CRLF>
PUSH P,T1 ;Save the routine address
MOVEI T1,($TOOIN)
MOVEM T1,TOFLGS
PUSHJ P,STROUT ;Output it
POP P,T1 ;Get the routine address
JUMPE T1,DOCTR0 ;None
PUSHJ P,(T1) ;Call it
MOVEI T1,($TOOIN)
MOVEM T1,TOFLGS ;Some routines trash this
DOCTR0: PUSHJ P,SCNLBK ;Scan to last break
DOCTR1: PUSHJ P,SCNCHR ;Get a character
JRST DOCTR3 ;Finish up then
CAIN P1,.CHCNR ;Is this the ^R?
JRST DOCTR2 ;Yes
MOVEI T1,(P1) ;Get character
PUSHJ P,OUTTTY ;Output it
JRST DOCTR1
DOCTR2: PUSHJ P,SPCRMV ;Remove the character now
DOCTR3: PUSHJ P,DOOUT1 ;Force out
SETZM TOFLGS
POPJ P, ;Return
SUBTTL TTY: Service -- Set to handle ^U, ^R, <RUB>
PLM
;+
;.hl Routine STRURB
MLP
; STRURB is called to set up masks and the TTY: to be sure we
;handle Ctl-U, Ctl-R, and Rubout ourselves. It uses T1.
PLM
;-
MLP
STRURB: TXO F,F$RUB ;Flag to handle it ourselves
MOVX T1,<1B<.CHCNR>!1B<.CHCNU>>
IORM T1,IMASK+1
MOVEI T1,1B31 ;<RUB>
IORM T1,IMASK+1+3
SETZM IMASK ;TTYSST sets field width to 1
PUSHJ P,TTYSST ;Set up TTY:
PJRST FRCTTI ;Wake us up
SUBTTL TTY: Service -- Clear Handling of ^U, ^R, <RUB>
PLM
;+
;.hl Routines UNRURB and UNRALL
MLP
; UNRURB and UNRALL clear NRT's handling of Ctl-R, Ctl-U, and Rubout.
;Call UNRALL to clear checking of Ctl-R, Ctl-U, and Rubout unconditionally.
;Call UNRURB to clear "specialness" of UNRURB but not in the mask
;if they are supposed to be reak characters. These routines use T1 and T2.
;Call them with T3 containing the field width to be set (field width
;gets set to one so we can handle Ctl-U, Ctl-R, and Rubout correctly).
PLM
;-
MLP
UNRURB: MOVX T1,<1B<.CHCNR>!1B<.CHCNU>>
XOR T1,LMASK
ANDX T1,<1B<.CHCNR>!1B<.CHCNU>>
MOVEI T2,1B31 ;Rubout
XOR T2,LMASK+3
ANDI T2,1B31
JRST DOUNRU
UNRALL: MOVX T1,<1B<.CHCNR>!1B<.CHCNU>>
MOVEI T2,1B31 ;And rubout
DOUNRU: ANDCAM T1,IMASK+1
ANDCAM T2,IMASK+1+3
MOVEM T3,IMASK
PUSHJ P,TTYSST
PJRST FRCTTI ;Wake up and return
;No-filter
SUBTTL PSION/OFF - Turn on/off the software interrupt system
PLM
;+
;.hl Routines PSIOFF, PSION, and PIOSAV
MLP
; These routines are used to manipulate the software interrupt system.
;PSIOFF turns the interrupt system of and PSION turns it on. PIOSAV
;is a co-routine called to be sure the interrupt system is off for a subroutine
;and automatically turn it back on (if it was on entry to the subroutine) on
;exit from the subroutine. All routines use only CX.
PLM
;-
MLP
PSIOFF: SAVET1
MOVX T1,<PS.FOF>
PISYS. T1,
ERR UTF,<PISYS. UUO Unable to turn off interrupts>
TLZ F,(F$PION) ;PSI isn't on
POPJ P,
PIOSAV: TLZN F,(F$PION) ;If PSI wasn't on,
POPJ P, ;Just return
PUSHJ P,PSIOFF ;Turn off PSI
PUSHJ P,@(P) ;Call caller
TRNA ;Non-skip
AOS -1(P) ;Skip
POP P,(P)
PSION: SAVET1 ;save T1
TLO F,(F$PION) ;PSI is on
MOVX T1,<PS.FON> ;Turn the system on
PISYS. T1, ;Now
ERR UTN,<PISYS. UUO Unable to turn on interrupts>
POPJ P, ;Return
SUBTTL NSP. Routines -- NSPEA - Make an active connection
PLM
;+
;.hl Routine NSPEA
MLP
; NSPEA does an enter active to a remote's NRTSRV. We are assuming
;that CONBLK has been set up already. NSPEA decides to enter either .OBHTH
;or .OBPST depending on the number of nodes the user has specified.
;NSPEA uses CX. NSPEA returns CPOPJ with the NSP. error code set
;up by SETNER on error, or returns CPOPJ1 with the connection set up.
;If FTPMR is on, NSPEA calls PMR, an external subroutine to actually
;do the connection so. PMR handles "automatic" Poor Man's Routing
;as specified in the file DCN:DNHOST.TXT.
PLM
;-
MLP
NSPEA: SAVET1 ;Save T1
IFN FTPMR,SKIPG NODCNT ;Doing PMR?
SKIPA T1,[.OBHTH] ;Not PMR
MOVEI T1,.OBPST ;PMR.
MOVEM T1,DSTPDB+.NSDOB ;Store it
MOVE NSAFN,[NS.WAI!<.NSFEA>B17!<.NSAA2>+1] ;Set up the function word
SETZ NSACH, ;No channel yet
MOVEI NSAA1,CONBLK ;Point to the connect block
MOVE NSAA2,TTBAUD ;Get baud rate
CAILE NSAA2,SEGMAX ;Bigger than max?
SETZ NSAA2, ;Use default then
MOVE NSAA2,SEGTBL(NSAA2) ;Get the entry
MOVEI T1,NSAFN ;Point to the function block
IFN FTPMR,<
TXO T1,PMR$RMR!PMR$DCN ;Set to always do direct connection
PUSHJ P,PMR## ;(Look on DCN: to keep TEN happy)
>
IFE FTPMR,<
NSP. T1, ;Enter Active
>
PJRST SETNER ;Set up NSP. error code for NSPERR
MOVEM NSACH,NSPACS+NSACH ;Channel is global
MOVEM NSACH,TTYACS+NSACH
MOVEM NSACH,TMRACS+NSACH
JRST CPOPJ1 ;Return
SUBTTL NSP. Routines -- Set Link Quotas
PLM
;+
;.hl Routine SETQUO
MLP
; This routine is called to set the link quotas of the link based
;on the controlling TTY:'s baud rate. This is so that if functions
;(such as ^O to TOPS-10 or TOPS-20, for example) which are handled
;remotely are requested, they will not take too long due to network
;messages which have already been buffered ahead.
SETQUO: MOVE NSAFN,[.NSFRQ,,.NSAA3+1]
MOVEI T1,NSAFN
NSP. T1,
POPJ P, ;Can't do anything
MOVE CX,TTBAUD ;Get the baud rate
CAILE CX,QUOMAX ;Up to a certain point only
SETZ CX,
HRLI NSAFN,.NSFSQ ;Set quotas and goals
MOVEI T1,NSAFN
;Note that the below could be done in one NSP. UUO. It is done
;in two so that if the setting of the goal fails, the %input will
;still get set. We assume that the goal may fail due to privilege
;violation if the default goal is set to a low value (at this point
;the monitor doesn't privilege check at all; the goal at this
;point in time is to make the monitor fail if the user tries to set
;the goal higher than the default but not lower. This may change,
;however).
HLRE NSAA2,QUOTBL(CX) ;Get % to allocate
JUMPL NSAA2,SETQU1 ;No change
NSP. T1,
POPJ P, ;Oh well
SETQU1: HRRE NSAA3,QUOTBL(CX) ;Get goal
JUMPL NSAA3,CPOPJ ;No change
NSP. T1,
JFCL
POPJ P,
SUBTTL NSP. Routines -- NSPIN - NSP. Input routine
PLM
;+
;.hl Routines NSPIN and NSPINW
MLP
; NSPIN is called to input data from the network. It returns
;CPOPJ1 on success, or through SETNER on failure. On success, INPBUF
;will contain the network data, IBFCNT will contain the byte count, and
;IBFPTR is the ILDB pointer to the data stored at INPBUF. If called at
;NSPINW, the routine will block until a complete message is read or
;the buffer is full. If called at NSPIN and an incomplete message is
;only available (and the buffer isn't filled), then it will restore ACs
;and dismiss the interrupt in progress.
PLM
;.note ***WARNING***
MLP
;NOTE THAT BECAUSE OF THE ABOVE, NSPIN SHOULD BE CALLED ONLY AT NETWORK
;INTERRUPT LEVEL.
PLM
;.end note
MLP
;When a network interrupt signals more data is ready, network interrupt
;service will return here to complete the message. When it is complete
;(or the buffer is full), NSPIN will return to the caller.
;These routines use CX and the NSP ACs.
PLM
;-
MLP
NSPINW: SKIPA NSAFN,[NS.WAI!<.NSFDR>B17!4]
NSPIN: MOVE NSAFN,[<.NSFDR>B17!4] ;Set up function word
SAVET1 ;Save T1
NSPCON: TXNE F,F$NEOM ;Seen EOM last?
JRST DONSPI ;No, don't re-init
SETZM IBFCNT
MOVEI NSAA1,IBUFSZ ;Get this many bytes if possible
MOVE NSAA2,[POINT 8,INPBUF] ;Make up the pointer
DONSPI: MOVEI T1,NSAFN ;Point to the function block
MOVE CX,NSAA1 ;Copy available chars to T1
NSP. T1, ;Data Read
PJRST SETNER ;Set up NSP. error code for NSPERR
TXNN NSAFN,NS.EOM ;End of message?
TXOA F,F$NEOM ;Set the NOT EOM flag
TXZ F,F$NEOM ;Clear the more to come flag
SUB CX,NSAA1 ;Calculate how many we have
ADDM CX,IBFCNT
TXNE NSACH,NS.NDA ;Normal data available?
TXNE NSAFN,NS.EOM ;Yes, is was EOM seen?
TRNA ;No data available or EOM
JUMPG NSAA1,DONSPI ;No EOM and data available, get if more room
SKIPN IBFCNT ;Anything there?
TXZ F,F$NEOM ;No, then clear this flag
JUMPE NSAA1,NINSAT ;Satisfied if full
TXNN F,F$NEOM ;EOM seen
JRST NINSAT ;Satisfied
PUSHJ P,EXCACS ;Restore the ACs
EXP NSPACS
SETOM INTLVL ;Free the interlock
DEBRK.
ERR DNI,<DEBRK. not implemented>
POPJ P,
NINSAT: MOVE T1,[POINT 8,INPBUF-1,35] ;Make the pointer up again
MOVEM T1,IBFPTR ;Fake this, also
JRST CPOPJ1
SUBTTL NSP. Routines -- NSPOUT - Outputs OTPBUF to the network
; Called: OBFPTR/ byte pointer to last data byte
PLM
;+
;.hl Routine NSPOUT
MLP
; NSPOUT is called to output the buffer pointer to by OBFPTR to
;the network. This routine call QUEOUT to output buffer, and falls
;into NSPO which attempts to output the buffer. NSPO is also called
;at network interrupt level to force out any buffers which had previously
;been queued (via calling NSPOUT) but could not be output. When buffers
;are completely output, they are returned to the free core pool.
;NSPOUT uses no ACs (other than the NSP ACs); NSPO uses T1-T4.
;The buffer will be sent with EOM unless the sign bit is on in the
;count field of the buffer header, or F$NEOM is set and this is NOT
;the last buffer in the queue.
PLM
;-
MLP
NSPOUT: PUSHJ P,SAVT ;Save the Ts
PUSHJ P,QUEOUT ;Queue netword output buffer
FALL NSPO ;Fall into NSPO
NSPO: SKIPN T2,OUTQUE ;Anything in the output queue?
JRST CPOPJ1 ;Done
HLRZ NSAA1,OBF.CT(T2);Get count
MOVE NSAA2,OBF.PT(T2);And pointer
MOVE NSAFN,[NS.EOM!<.NSFDS>B17!.NSAA2+1] ;Set up function word
;NSAA1 (the count was set up before)
HRRZ T3,OBF.LK(T2) ;Pointer to next
JUMPE T3,NSPO1 ;If zero, follow EOM in buffer
TXNN F,F$EOMN ;Else use set flag
NSPO1: TRZE NSAA1,400000 ;Sign bit set?
TXZ NSAFN,NS.EOM ;Then clear EOM
MOVEI T1,NSAFN ;Pointer to argument block
NSP. T1, ;Data Send
PJRST SETNER ;Set up NSP. error code and return
MOVEI T1,(T2) ;Transfer ACs
JUMPN NSAA1,NSPEXI ;If didn't finish
HRRZM T3,OUTQUE ;Point to it
MOVEI T2,OBUFSZ+OBF.DT;Size of buffer
PUSHJ P,CORFRE ;Deallocate it
JRST NSPO ;Back for more
NSPEXI: HRLM NSAA1,OBF.CT(T1);Save count
MOVEM NSAA2,OBF.PT(T1);And pointer
AOS (P)
POPJ P, ;Success return
PLM
;+
;.hl Routines NETQUE and QUEOUT
MLP
; NETQUE and QUEOUT are called to queue the buffer pointed to by
;OTPBUF into the network output queue, where it will be pushed out via
;NSPO. NETQUE uses no ACs; QUEOUT uses T1-T4. Both use the byte pointer
;in the buffer header to compute the number of bytes in the buffer. If
;the sign bit of OTPBUF is on, the buffer will be flagged to be output without
;EOM. This is done by setting the sign bit of the count word of the buffer.
;These routines also call INOBUF after queueing the current buffer to
;initialize a new one.
PLM
;-
MLP
NETQUE: PUSHJ P,SAVT ;With all ACs saved
HRROS OTPBUF ;Force no EOM
QUEOUT: MOVE T1,OTPBUF ;Point to buffer
MOVE T1,OBF.PT(T1) ;Get pointer
MOVE T2,OBFPTR ;Get current location pointer
PUSHJ P,BPLENG ;Calculate length based on difference
SKIPGE T2,OTPBUF ;See if sign bit is set...
TRO T1,400000 ;Set no EOM when sending
HRLZM T1,OBF.CT(T2) ;Store count there
MOVEI T3,OUTQUE-OBF.LK
OUTCHK: SKIPE T4,OBF.LK(T3) ;Make first time a litte faster
TRNN T4,-1 ;Pointer to next?
JRST OUTFND ;No
HRRZI T3,(T4) ;Get next entry
JRST OUTCHK ;Continue
OUTFND: HRRM T2,OBF.LK(T3) ;Queue it up
PJRST INOBUF ;Re-init the output buffers
SUBTTL SETNOD - Sets up node name in ASCNOD in the connect block
PLM
;+
;.HL Routine SETNOD
MLP
; SETNOD is called to translate the SIXBIT node name stored at RNODE
;into an eight-bit ASCII name in the connect block, suitable for use in
;the NSP. .NSFEA function. It falls into SIX2SB and therefore uses
;T1-T2 and P1-P2.
PLM
;-
MLP
SETNOD: MOVE T1,RNODE ;Get the node name
MOVEI T2,ASCNOD ;PUT IT IN THIS STRING BLOCK
FALL SIX2SB ;Do it
SUBTTL SIX2SB - Store SIXBIT T1 in string block pointed to by T2
PLM
;+
;.HL Routine SIX2SB
MLP
; SIX2SB takes a SIXBIT string in T1 and translates it to eight-bit
;ASCII, placing the result in the string block pointed to by T2. SIX2SB
;uses P1-P2 as well.
PLM
;-
MLP
SIX2SB: SAVE2 ;Save P1,P2
MOVE P1,T2 ;Preserve the string block pointer
MOVE P2,[POINT 8,1(P1)] ;Set up byte pointer to data part of block
SETZ T2, ;Use T2 for count
MOVE T3,[POINT 6,T1] ;and T1 for a byte pointer into SIXBIT name
SIXS21: ILDB T4,T3 ;Get a byte from SIXBIT name
JUMPE T4,SIXS22 ;Nothing there, must be end of name
ADDI T4," " ;ASCIIize the byte
IDPB T4,P2 ;Store it in the string block
CAIE T2,6 ;If we've hit six bytes, don't try anymore
AOJA T2,SIXS21 ;Otherwise, loop
SIXS22: HRLM T2,(P1) ;Put the count in the first block
ASH T2,-2 ;Make count into words
ADDI T2,2 ;Some overhead
HRRM T2,(P1) ;Put max length in
POPJ P, ;And return
SUBTTL INIOBF - Initialize OBUF and IBUF
PLM
;+
;.hl Routines INIOBF and INOBUF
MLP
; These routines are called to initialize IBFPTR/IBFCNT, and
;OBFCNT/OBFPTR. INIOBF initializes both input and output buffers;
;INOBUF initializes only output buffers. They use T1-T2. The input buffer
;is fixed; the output buffers are allocated dynamically from the free core
;pool.
PLM
;-
MLP
INIOBF:
SETZM IBFCNT ;Just being paranoid
MOVE T1,[POINT 8,INPBUF-1,35]
MOVEM T1,IBFPTR
INOBUF: MOVEI T1,OBUFSZ+OBF.DT ;Include the header
PUSHJ P,CORGET ;Get a buffer
HRRZM T1,OTPBUF ;Save it (Default to send EOM)
MOVE T2,[POINT 8,OBF.DT,] ;Make byte pointer to data portion
ADD T2,T1 ;Put into proper perspective
MOVEM T2,OBFPTR ;Set pointer
MOVEM T2,OBF.PT(T1) ;Save for later output
MOVEI T1,4*OBUFSZ
MOVEM T1,OBFCTR ;For those who care...
POPJ P, ;Return to sender
SUBTTL BPLENG - Compute length of byte pointer in T1
PLM
;+
;.hl Routine BPLENG
MLP
; BPLENG is called to compute the number of bytes in the buffer. It
;is called with the byte pointer to the beginning of the buffer in T1 and
;the byte pointer to the end of the buffer in T2. Both pointers
;must specify eight-bit bytes and the beginning pointer must be word aligned.
;BPLENG returns with the number of bytes in T1. T1 and T2 are used.
PLM
;-
MLP
BPLENG: SAVE2 ;Save P1,P2
DMOVE P1,T1 ;Preserve the byte pointers
HLRZ T1,P1 ;Get the s and p stuff
CAIE T1,(POINT 8,) ;Is it word aligned and 8 bits?
ERR IBP,<Illegal byte pointer>
HRRZ T1,P2 ;Get the address part of new BP
HRRZ T2,P1 ;and old BP
SUB T1,T2 ;Get the difference
ASH T1,2 ;Make it into bytes
LDB T2,[POINT 6,P2,6+5] ;Get S field of byte pointer
CAIE T2,^D8 ;Is it eight bits?
ERR IBS,<Illegal byte size>
LDB T2,[POINT 6,P2,5] ;Get P field of byte pointer
SUBI T2,4 ;P starts at the right
ASH T2,-3 ;Divide by eight
SUBI T2,4 ;Reverse the order
SUB T1,T2 ;Figure out the final count
POPJ P, ;And return
SUBTTL Miscellaneous support - Digest a mask
PLM
;+
;.hl Routine CPYMSK
MLP
; CPYMSK is called to take a mask from the current position of
;the network input buffer and copy it to the place specified by the
;byte pointer in T3. Enter with T4 containing the count for the
;mask; T4 must be non-zero.
; This routine is provided for systems like RSX and VMS which
;provide a break mask for input termination where the bytes appear
;in the network buffer from low-order to high order and the correspondance
;of bits to ASCII character values (in each byte) proceeds with the
;high order bit representing the highest character value. In TOPS-10
;format we translate the following into the B0-B32 format:
PLM
;.bl 1.lit
; B7,B6,B5,B4,B3,B2,B1,B0 B15,B14,B13,B12,B11,B10,B9,B8 ...
; \_____first byte_____/ \________second byte________/ ...
PLM
;.end lit
PLM
;CPYMSK uses T1-T4.
PLM
;-
MLP
CPYMSK: PUSHJ P,RBYTEC ;Get a byte
MUL T1,[100200401002] ;Reverse the bits
AND T2,[20420420020];via HACKMEM
ANDI T1,41
DIVI T1,1777 ;Casting out 2**10.-1's
IDPB T2,T3
SOJG T4,CPYMSK ;And continue copying the mask
POPJ P, ;Return
SUBTTL Miscellaneous Support -- GET & PUT word routines
PLM
;+
;.hl Routines GETWRD, PUTWRD, GETLWD, and PUTLWD
MLP
; These routines are for -11 flavoured machines which have
;bytes in reversed order. The GETxxx routines input the appropriate
;quanity (2 bytes for WRD and 4 bytes for LWD) into T1 from the
;current position in the network input buffer; the PUTxxx routines
;output from P1 to the current position in the output buffer.
;These routines use CX and the appropriate argument AC.
;The PUTxxx routines do not destroy the argument.
PLM
;-
MLP
PUTWRD: NETOCH P1 ;Network character
ROT P1,^D-8 ;Shift down
NETOCH P1 ;And second half
ROT P1,^D8 ;Make it look right
POPJ P, ;And return
PUTLWD: MOVEI CX,^D3 ;Number of times to do it
PUTL1: NETOCH P1
ROT P1,-^D8 ;Do the next 8
SOJG CX,PUTL1 ;Loop for all of them
NETOCH P1
ROT P1,-^D12 ;In place again
POPJ P, ;And return
GETWRD: PUSHJ P,RBYTEC ;Get a byte from the system
PUSH P,T1 ;Save it
PUSHJ P,RBYTEC ;And another
LSH T1,^D8 ;Put the upper 8 bits first
IOR T1,(P) ;OR in the lower 8 bits
POP P,(P) ;Loose the number we stored
POPJ P, ;And return
GETLWD: MOVSI T1,20000 ;Get an indicator in T1
GETLW1: PUSH P,T1 ;Save T1
PUSHJ P,RBYTEC ;Get a data byte
MOVE T2,T1 ;Save the number in T1+1
POP P,T1 ;Restore the old stuff
ROTC T1,-^D8 ;Put it in place
JUMPGE T2,GETLW1 ;Loop for all of them
ASH T1,-^D4 ;Use the lower 32 bits
POPJ P, ;And return
SUBTTL Miscellaneous Routines
PLM
;+
;.hl AC saving routines
MLP
; These are the AC saving/restoring routines/co-routines. Most of
;them are called by MACROS. This is shown in the following table:
PLM
;.nofil.bl 1.ts 10,20,30,40,50
;^&
MLP
; Routine MACRO Call Function
PLM
;.bl 1
;\&
MLP
; .SAVT1 SAVT1 JSP Save/restore T1
; SAVT --- PUSHJ Save/restore T1-T4
; REST --- JRST Restore T1-T4
; .SAV1 SAVE1 JSP Save/restore P1
; TPOPJ --- JRST Restore T1
; P1POJ1 --- JRST Restore P1/skip return
; P1POPJ --- JRST Restore P1
; .SAV2 SAVE2 JSP Save/restore P1-P2
; .SAV4 SAVE4 JSP Save/restore P1-P4
; .RES4 --- JRST Restore P1-P4
PLM
;.fill.just.ts.bl 1
MLP
;In the above, JSP calls use AC CX. Restoration routines restore ACs from
;the stack.
PLM
;-
MLP
.SAVT1: PUSH P,T1
PUSHJ P,0(CX)
TRNA
AOS -1(P)
POP P,T1
POPJ P,
SAVT: EXCH T1,(P)
PUSH P,T2
PUSH P,T3
PUSH P,T4
PUSH P,[REST]
PUSH P,T1
MOVE T1,-5(P)
POPJ P,
REST: TRNA
AOS -4(P)
POP P,T4
POP P,T3
TTPOPJ: POP P,T2
TPOPJ: POP P,T1
POPJ P,
.SAV1: PUSH P,P1
PUSHJ P,0(CX)
TRNA
P1POJ1: AOS -1(P)
P1POPJ: POP P,P1
POPJ P,
.SAV2: PUSH P,P1
PUSH P,P2
PUSHJ P,0(CX)
TRNA
AOS -2(P)
POP P,P2
POP P,P1
POPJ P,
.SAV4: ADJSP P,4
DMOVEM P1,-3(P)
DMOVEM P3,-1(P)
PUSHJ P,(CX)
TRNA
AOS -4(P)
.RES4: DMOVE P1,-3(P)
DMOVE P3,-1(P)
ADJSP P,-4
POPJ P,
SUBTTL Returns
PLM
;+
;.hl Routines TPOPJ1, CPOPJ1, and CPOPJ
MLP
; These are return routines which are JRSTed to: TPOPJ1 restores
;T1 from the stack and skips, CPOPJ1 skip returns, and CPOPJ just returns.
PLM
;-
MLP
TPOPJ1: POP P,T1
CPOPJ1: AOS (P) ;Skip
CPOPJ: POPJ P, ;Return to caller
SUBTTL EXCACS
PLM
;+
;.hl Routine EXCACS
MLP
; EXCACS is called by the interrupt service routines to exchange
;AC sets. Call is:
PLM
;.bl 1.nofill.ts 8,16,24,32,40,48,56
MLP
; PUSHJ P,EXCACS ;Call
; EXP ACset ;Block of 20 locations with which to
; ;exchange current ACs
PLM
;.fill.just.ts.bl 1
MLP
;AC F is not altered.
PLM
;-
MLP
ASSUME F,0
ASSUME P,17
EXCACS: PUSH P,@(P) ;Push addr of AC block on stack
MOVEM F,@(P) ;Save F
MOVE F,T1 ;Save T1 in F
POP P,T1 ;Address of AC block in T1
EXCH F,T1(T1) ;Switch the T1s
PUSH P,T2 ;Save T2
MOVE T2,P(T1) ;Get the right PDL pointer
EXCH T2,P ;New pointer to P, old one to T2
ADJSP P,2 ;Allocate space
POP T2,(P) ;T2 to new PDL
POP T2,-1(P) ;Return addr to new PDL
MOVEM T2,P(T1) ;What P to restore
POP P,T2 ;Restore T2
EXCH T2,T2(T1) ;And now do the others
EXCH T3,T3(T1)
EXCH T4,T4(T1)
EXCH P1,P1(T1)
EXCH P2,P2(T1)
EXCH P3,P3(T1)
EXCH P4,P4(T1)
EXCH CX,CX(T1)
EXCH NSAFN,NSAFN(T1)
EXCH NSACH,NSACH(T1)
EXCH NSAA1,NSAA1(T1)
EXCH NSAA2,NSAA2(T1)
EXCH NSAA3,NSAA3(T1)
MOVE T1,F(T1) ;Restore flags to T1
EXCH T1,F ;Flags to F, T1 to T1
AOS (P) ;Skip the AC block designator
POPJ P, ;And return
SUBTTL Operating System Specific Support
PLM
;+
;.Chapter Operating System Specific Support
;.hl Overview
MLP
; The rest of the code in NRT is concerned with supporting specific
;operating system's remote terminal servers. This section contains an
;overview of the general requirements for supporting an operating system.
; Each operating system requires an initialization routine,
;a network interrupt service routine, and a TTY: service interrupt routine.
; The initialization routine is called when NRT knows what type
;of operating system the remote host is. This information is passed in the
;configuration message from the remote host. The initialization routine
;is responsible for setting flags as to which data mode the TTY: should
;be in (PIM or ASCII line) and calling TTYSST to set that up. It is also
;responsible for sending the appropriate return configuration message
;and any other messages which should be sent to the remote host at
;initialization time (e.g. the unsolicited interrupt to VMS to simulate
;typing a <CR> on a terminal).
; The network interrupt routine is responsible for handling any
;messages sent by the remote host over DECnet. This can range
;from simply outputting the data to the TTY: (as is the case
;for TOPS-10 and TOPS-20) or processing the messages as various
;flavours of I/O requests (as is the case for VMS and RSX).
;The network interrupt service is called by DCNPSI, the operating system
;independent network interrupt service routine, when a complete message
;is available or the network input buffer is full.
; The TTY: interrupt service has the responsiblity of handling
;characters typed by the user. It is responsible for noticing the
;escape character was typed and calling MONITO. Other than that, its
;responsibilities may be simply to ship the characters typed by the
;user out to the network (as is the case for TOPS-10 and TOPS-20), or
;they may include local processing and buffering of characters until
;the remote host requests them (VMS and RSX). The TTY: interrupt service
;is called by the operating system independent TTY: service routine
;(TTYPSI) when new TTY: input is available.
; Currently there are two basic types of protocols used.
;The first type is referred to henceforth as a TRANSPARENT protocol; the second
;as a MESSAGE protocol. Some operating systems combine elements from
;each type of protocol.
; A transparent protocol is one in which the DECnet messages
;passed between the local and remote hosts consist simply of the characters
;typed by the user and sent from the programs running on the remote host.
;Messages are passed when the connection is established to confirm that
;the correct protocol is being used, but from that point forward any message
;sent is considered to be data to be input by the remote host or displayed
;on the terminal by the local host. All echoing and special character
;handling is handled by the remote host. Generally, type-ahead is also
;handled by the remote host. Transparent protocols are usually handled
;by doing terminal I/O in PIM mode and simply passing the characters
;directly through to the remote host. Any characters sent from the
;remote host are sent immediately to the terminal. Since all echoing
;is done by the remote host, the remote host is also responsible for
;handling echo deferring, etc.
; A message protocol exists where the DECnet messages passed between
;the local and remote host consist of requests for characters or information
;(generally sent only from the remote to the local host) and acknowledgements
;fulfillments of the above mentioned requests (may be sent in either
;direction). In general, in a message protocol, typed characters are
;not sent from the local to the remote host until they are requested by
;the remote host. Echoing and special character handling are normally
;done by the local host in a message protocol. Type-ahead
;is the responsiblity of the local host. A message protocol
;is handled by not transferring the user's typed characters from NRT's
;internal buffers to the network until a request is received from the
;remote host for them. The remote host provides a break mask (or utilizes
;an implied mask) and a maximum count with each request. At this point,
;characters will be transferred to the remote host as dictated by the
;specific request. If the characters arrive after the request, NRT will
;have allowed the monitor to echo them (assuming they are to be echoed).
;If the characters are typed before the request is received, NRT will
;not allow the monitor to echo them and will echo them when they are
;sent out over the network.
; Rather than describe each routine in detail, the rest of the
;PLM will consist of a general description of each operating system type
;and pointers to appropriate reference manuals. The general description
;will outline the type of protocol which is used to communicate with the
;remote host and any peculiarities of the particular operating system.
;This lack of detailed documentation is in part intentional. The user
;should NOT try to repair any operating system specific routines unless
;he thoroughly understands both NRT's general approach (as described in
;in this manual) AND the appropriate internals (not just the external
;appearance) of the remote host. To this effect, lists of appropriate
;documents will be provided, but it is the user's responsibility to
;read the suggested references.
; In debugging NRT, it is very helpful to utilize the DNSNUP
;program provided on the DECnet Tools Tape. This program is invaluable
;in providing a trace of what the remote operating system is actually
;sending you (as opposed to what the spec says).
; I repeat for emphasis:
PLM
;.note ***WARNING*** ***WARNING***
MLP
;DO NOT TRY TO "FIX" ANY OPERATING SYSTEM SPECIFIC CODE UNLESS YOU THOROUGHLY
;UNDERSTAND THE REMOTE HOST OPERATING SYSTEM, UNDER PENALTY OF GETTING BOTH
;NRT AND YOUR FINGERS BROKEN.
PLM
;.end note
;-
MLP
SUBTTL RSTS Support -- Protocol definitions
PLM
;+
;.hl 2 RSTS Support
; RSTS is implemented by a protocol which is a combination of
;transparent and message protocols. Characters are passed from the local to
;the remote host as they are typed, but they are bound in a message.
;Echoing is done on the local host.
; RSTS supports five types of messages:
;.list 1
;.le
;Configuration message (Type 1): This is the normal configuration message.
;This is passed only when the link is being established.
;.le
;Control message (Type 2): This is sent to request a change of various
;terminal states, such as to turn of echoing.
;.le
;Unsupported protocol message (Type 3): This message is sent when one end
;requests a function which the other end does not support.
;It should never be sent during the normal course of
;events.
;.le
;Reserved for DEC (Type 4)
;.le
;Data message (Type 5): This message passes characters to be displayed
;(from the remote to the local host) or characters typed by the user
;(from the local to the remote host).
;.end list
; Reference documents:
;.list 1
;.le
;^&DECnet/E Virtual Terminal Protocol (VTP) Version 1.0\& -
;This memo, dated 20-Jan-79, describes the types of messages which
;comprise RSTS' protocol. A difference between the memo and reality
;is that the data message is Type 5 rather than Type 4.
;It was also distributed on the TOPS-20 version 5 SWSKIT tape.
;.end list
;-
MLP
;Message types:
MT$CFG==1 ;Configuration message
MT$CTL==2 ;Control message
MT$UNS==3 ;Unsupported protocol message
MT$DAT==5 ;Data message
;Menu items (control message)
MN$EKO==1 ;Echo control
MN$MSK==2 ;Change delimiter mask
MN$WID==4 ;TTY: width
;Echo state:
EK$OFF==1 ;Off
EK$ON==2 ;On
SUBTTL RSTS Support -- RSTS network input
RST.NT: PUSHJ P,NETICH ;Anything from the other end?
POPJ P, ;None?
MOVEI P1,RSSFNC ;Get the function code table
PUSHJ P,FNDFNC ;Find the function
ERR IRS,<Illegal RSTS function>
POPJ P, ;Return
SUBTTL RSTS Support -- TTY: input
RST.TT: PUSHJ P,SCNSPC ;Scan for special characters
JRST [PUSHJ P,RST.SC ;Handle them
JRST .-1 ] ;Check again
TXZN F,F$BRK ;Is there a break?
JRST SCRURB ;No, check rubout stuff
MOVEI T1,MT$DAT ;Data message
NETOCH T1 ;Set it
PUSH P,OBFPTR ;Save pointer to counts
NETALC 3 ;Allocate 3 bytes in network buffer
SETZ P1, ;Init character counter
RST.T1: PUSHJ P,INCHR ;Go get what we can from the TTY
JRST RST.T5 ;Nothing
CAMN T1,ESCCHR ;Is this the escape character?
SOS BRKNUM ;Yes, one less
RST.T3: NETOCH T1 ;Output char to networkk
PUSHJ P,CHKBR1 ;Break character?
AOJA P1,RST.T4 ;Yes
AOJA P1,RST.T1 ;Count character
RST.T4: TXNE F,F$NEC ;Noecho?
JRST RST.T5 ;Yes, don't do it then
HLRZ T1,BRKCHR
MOVE T4,[-RSBLEN,,RSBTBL]
PUSHJ P,EKOBRK ;Echo the break character
RST.T5: MOVE T1,OBFPTR
EXCH T1,(P)
MOVEM T1,OBFPTR ;Point to counts
MOVEI T1,3 ;Fudge counts
ADDM T1,OBFCTR
MOVEI T1,(P1) ;Data count
MOVEI P1,4(P1) ;Message size
PUSHJ P,PUTWRD
NETOCH T1 ;Data size
POP P,OBFPTR ;Point to real end of message
PUSHJ P,XMTMSS ;Output the message
MOVE T2,RSTDMK ;Get count
PJRST SCRURB ;Clear as appropriate
SUBTTL RSTS Support -- RST.IN - Initialization Routine
RST.IN: MOVEI T1,RST$CF ;Send config
TXO F,F$READ!F$ACO ;Always outstanding read
TXZ F,F$PIM
PUSHJ P,XMTMSG ;
MOVEI T1,RST$UN ;Send input
PUSHJ P,XMTMSG
MOVE T1,[RSTDMK,,IMASK]
BLT T1,ENDMSK
MOVE T1,[RSTDMK+1,,LMASK]
BLT T1,ELMASK
PJRST TTYSST ;Set up TTY
SUBTTL RSTS Support -- RST.CT - RSTS control Message
RST.CT: PUSHJ P,GETWRD ;Get length of message
PUSHJ P,RBYTEC ;Get menu count
XCT [PUSHJ P,RBYTEC ;Get menu bytes (one byte)
PUSHJ P,GETWRD
PUSHJ P,[PUSHJ P,RBYTEC
PUSH P,T1
PUSHJ P,GETWRD
LSH T1,^D8
IOR T1,(P)
POP P,(P)
POPJ P, ]
PUSHJ P,GETLWD
PUSHJ P,[PUSHJ P,GETLWD
PUSH P,T1
PUSHJ P,RBYTEC
JRST TPOPJ ]
PUSHJ P,[PUSHJ P,GETLWD
PUSH P,T1
PUSHJ P,GETWRD
JRST TPOPJ ]]-1(T1) ;Ignore high order for now
MOVE P1,T1 ;Save it
PUSHJ P,RBYTEC ;Get echo specifier
TRNN P1,MN$EKO ;Change it?
JRST RS.CT1 ;No
TRNE T1,EK$OFF ;Turn echo off?
TXOA F,F$NEC ;Yes
TXZ F,F$NEC
RS.CT1: TRNN P1,MN$MSK ;Set mask?
JRST RS.CT3 ;No, skip some
MOVE T3,[POINT 8,IMASK+1,] ;Destination pointer
MOVEI T4,^D32 ;Number of bytes
PUSHJ P,CPYMSK ;Copy it
MOVE T1,[IMASK+1,,LMASK] ;Set logical mask too
BLT T1,ELMASK
RS.CT3: PUSHJ P,TTYSST ;Set up TTY:
PJRST FRCTTI ;Look at changes
SUBTTL RSTS Support -- RST.DA - Recieve Data message
RST.DA: IBP IBFPTR ;Skip over the count
IBP IBFPTR ;Second byte
IBP IBFPTR ;And count of characters
MOVNI T1,^D3 ;Adjust for what we just took
ADDM T1,IBFCNT
PJRST NETCHR ;Get some data
SUBTTL RSTS Support -- Handle special characters
RST.SC: CAME P1,ESCCHR ;Escape?
JRST RS.CTU ;Check Control-U, etc.
PUSHJ P,MONITO ;Return to command level
TRNA ;Skip next
AOSA BRKNUM ;One more break to ignore
PUSHJ P,SPCRMV ;Remove if required
PJRST SCRURB ;Check rubout status
RS.CTU: CAIE P1,.CHCNU ;Control-U?
JRST RS.CTR ;Control-R
PUSHJ P,DOCTU ;Do the control-U
PJRST UNRURB ;Clear the bits
RS.CTR: CAIE P1,.CHCNR ;Control-R?
PJRST DORUB ;Must be rubout
SETZ T1, ;No routine
PUSHJ P,DOCTR ;Do the Control-R
PJRST SPCRMV ;Remove ^R and return
SUBTTL RSTS Support -- Check Set/Clear of Local ^U/^R/<RUB>
SCRURB: SKIPN ICHCNT ;Any chars in buffer?
JRST SURURB ;No, clear
MOVEI T1,<1B<.CHCNR>!1B<.CHCNU>>
AND T1,LMASK ;Don't set special if he's to see
XORI T1,<1B<.CHCNR>!1B<.CHCNU>>
IORM T1,CHRTAB
LDB T1,[POINT 1,LMASK+3,31] ;Get the rubout bit
LSH T1,^D36-^D19 ;Position it
TRC T1,1B19 ;Complement it
IORM T1,CHRTAB+3 ;Set appropriate
PJRST STRURB ;Set mask bits
SURURB: MOVEI T1,<1B<.CHCNR>!1B<.CHCNU>>
ANDCAM T1,CHRTAB ;Clear specialness
MOVEI T1,1B19
ANDCAM T1,CHRTAB+3 ;...
PJRST UNRURB
SUBTTL RSTS Support -- Break Echo Table
RSBTBL: .CHCRT,,[ASCIZ/
/] ;<CR>
.CHCNZ,,[ASCIZ/^Z
/] ;^Z
.CHESC,,[ASCIZ/$/] ;<ESC>
.CHCNC,,[ASCIZ/^C
/] ;^C
.CHCNO,,[ASCIZ/^O
/] ;^O
RSBLEN==.-RSBTBL
SUBTTL RSX Support -- Protocol defintions
PLM
;+
;.hl 2 RSX Support
; RSX utilizes a message protocol. There are twelve
;types of message requests
;which may be passed, including the configuration message. In most cases,
;a request is generated in the remote host. The local host responds when
;able to complete the request with a complementary message containing the
;same operation code. There also a reference identifier which is sent
;in the original message; this must also be returned when the request
;is acknowledged.
; There are two exceptions to the above protocol:
;.list 1
;.le
;Exception condition message (Message Type 12 (decimal) or 14 (octal)):
;This message is only sent from the local to the remote host and is sent
;when the user types certain special characters that could require
;immediate attention, for example, ^C.
;.le
;Write operation with No-Write-Complete modifier: Like any other
;message, a Write message should be acknowledged when it is completed.
;It is possible, however, for the remote host to specify that the
;Write request is not to be acknowledged. If this is the case, then
;the local host should perform the Write request but not acknowledge it.
;.end list
; Reference documents:
;.list 1
;.le
;^&RSX I/O Users Guide\& - This gives a general idea of what an RSX program
;expects to see.
;.le
;^&RMT Protocol Specification for RMT/RMHACP version 1.08\& -
;This memo specifies the RSX remote terminal
;protocol. It describes the types of messages passed and the
;appropriate responses. Author: S. Goldfarb; reviewed by
;S. Seufert, J. Schriesheim, and J. Forecast
;.end list
; A further current peculiarity of RSX is its inability to handle having
;the link turned off. This is actually done within the monitor, as TOPS-10
;does optimistic buffering and will occasionally have to request that a
;remote host send no more DECnet messages. For RSX, if this happens, the link
;will shut off but will never turn on again when the monitor requests the
;remote host to begin sending messages again. This is handled in NRT by
;turning off the optimistic buffering during initialization. This
;feature is currently under FTCROCK.
; RSX seems to have a further peculiarity in tossing characters
;during unsolicted input if only the break character is typed (and it's
;not a <CR>). This is implemented for unsolicited input by first breaking
;on all characters, and then breaking under a complete request.
;-
MLP
RF.NOP==0 ;NO-OP
RF.SSD==1 ;Set system data (Configuration)
RF.DIS==2 ;Disconnect
RF.WTD==3 ;Write data to terminal
RF.RDD==4 ;Read data from terminal
RF.WRD==5 ;Write-then-read
RF.UNS==6 ;Unsolicited input
RF.RSC==7 ;Single Characters
RF.KIL==10 ;Kill I/O
RF.ATT==11 ;Attach task to terminal (as RSX means it)
RF.GTC==12 ;Get terminal Characteristics
RF.STC==13 ;Set terminal Characteristics
RF.ECR==14 ;Exception condition request
;MODE definitions
RM.WBN==1 ;Image write (RF.(WTD,WRD))
RM.OSA==1 ;Only system attention characters (RF.RSC)
RM.WBT==2 ;Write breaks through read (RF.(WTD,WRD)
RM.NSA==2 ;No system attention characters (RF.RSC)
RM.RBN==4 ;Image read (RF.(RDD,WRD))
RM.NOT==4 ;Notify (RF.RSC)
RM.RTC==10 ;Terminate on all CTL (RF.(RDD,WRD))
RM.RNE==20 ;Read no echo (RF.(RDD,WRD,RSC))
RM.RTO==40 ;Reset timeout on each char (RF.RSC)
RM.CUR==40 ;Cursor info imbedded (RF.(WTD,WRD))
RM.RTT==40 ;Terminator mask supplied (RF.RDD)
RM.RTM==100 ;Timeout (RF.(RDD,WRD))
RM.UNL==100 ;Read entire line (RF.RSC)
RM.NWC==200 ;No write complete (RF.WTD)
RM.TUI==200 ;Terminate unsolicited input (RF.UNS)
RM.TSC==200 ;Terminate single character input (RF.RSC)
RM.DET==200 ;Detach (RF.ATT)
;Flags
RM.PRI==2 ;Process immediately
RM.CAO==4 ;Cancel abort-output
;Status returns:
XS.SFC==0 ;Successful
XS.FPE==1 ;Function processing error
XS.UFC==2 ;Unsupported function requested
XS.IPF==3 ;Illegal protocol function
XS.IPD==4 ;Illegal protocal data
XS.ICF==5 ;Illegal characteristics function
;Exception condition code descriptions
RE.SAR==0 ;System attention request (^C)
RE.HAO==1 ;Host abort output (^O)
;Characteristic variables
RC.TBL==1 ;Buffer size
RC.CCT==2 ;Carriage control type
RC.SCI==3 ;Read single characters
RC.ACL==4 ;Autocrlf
RC.WBT==5 ;Write breaks through read
RC.CAO==6 ;Cancel I/O
RC.LUC==7 ;Case conversion
RC.RNE==^D8 ;Noecho
RC.RTC==^D9 ;Terminate on control characters
RC.CRT==^D10 ;CRT support
RC.RIL==^D11 ;^R
RC.RWB==^D12 ;Image
RC.UNS==^D13 ;Unsolicited input
RC.SCX==^D14 ;Read single extensions
RC.RTT==^D15 ;Break masks
RC.NUC==^D16 ;Case conversion
RC.HFF==^D17 ;Hardware for feeds
RC.HHT==^D18 ;Hardware tabs
RC.NEC==^D19 ;Echo
RC.RSP==^D20 ;Receive speed
RC.TSP==^D21 ;Transmit speed
RC.TTP==^D22 ;TTY: type
RC.SCP==^D23 ;CRT
RC.BIN==^D24 ;Passall
RC.SPN==^D25 ;Suspended output
RC.HFL==^D26 ;Horizontal fill characters
RC.VFL==^D27 ;Vertical fill characters
RC.TPL==^D28 ;Page size
RC.ETA==^D29 ;Typeahead
RC.CTA==^D30 ;Read/clear typeahead buffer
RC.REB==^D31 ;Eight bit characters
RC.RTM==^D32 ;Timeout
RC.CUR==^D33 ;Cursor
RC.CCF==^D34 ;Control-C flush
RC.FDX==^D35 ;Full duplex
RC.IMG==^D36 ;Ignore messages
RC.RAT==^D37 ;Read type-ahead
RC.SMO==^D38 ;Enable lowercase output
RC.SMP==^D39 ;Force lowercase input
RC.MAX==^D39 ;Maximum type
RC.VER==^D127 ;Version type
;Terminal types:
RXV52==11 ;VT52
RXV100==15 ;VT100
RXV101==24 ;VT101
RXV102==25 ;VT102
RXV125==27 ;VT125
RXV132==31 ;VT132
RXV61==13 ;VT61
RXV55==12 ;VT55
;RSX digested header block:
PHASE 0
R.LINK: ;(RH) Link to next request
R.IDENT: ;(LH) Identifier for this request
BLOCK 1
R.MOD: ;(LH) Modifiers for this request
R.FLAG: BLOCK 1 ;(RH) Flags for this request
R.TIME: BLOCK 1 ;Timeout time if applicable
R.PROMPT:
BLOCK 1 ;Byte count,,pointer to prompt block
R.COUNT: ;I/O request count (read request)
BLOCK 1
R.MASK: BLOCK ^D8 ;Terminator mask
REQSIZ==.
DEPHASE
ISBTBL: .CHCRT,,[BYTE(7)15] ;<CR> For IAS
.CHCNZ,,[ASCIZ/^Z/] ;No extra <CR>s for IAS
RXBTBL: .CHCRT,,[ASCIZ/
/] ;<CR> for unsolicited read
.CHCNZ,,[ASCIZ/^Z
/] ;^Z for unsolicited read
.CHESC,,[ASCIZ/$/] ;<ESC>
.CHCNC,,[ASCIZ/^C
/] ;^C
RXBLEN==.-RXBTBL
ISBLEN==.-ISBTBL
SUBTTL RSX Support -- RSX.IN - Initialization
RSX.IN: TXO F,<F$UAST!F$NLF> ;Flag no extra <LF>s
TXZ F,F$PIM ;And not PIM
IFN FTCROCK,< ;Turn of optimistic buffering
MOVEI CX,NSAFN ;Since -11 will hang
MOVE NSAFN,[.NSFRQ,,.NSAA3+1]
NSP. CX,
JRST RX.INC ;Oops
MOVEI CX,NSAFN
HRLI NSAFN,.NSFSQ ;Set quota
SETZ NSAA3, ;To zero
NSP. CX,
JFCL
RX.INC:> ;Done
MOVEI T1,RSX$CF ;Send back configuration msg
PUSHJ P,XMTMSG ;
MOVEI T1,RSX$UN ;Send a message
MOVE T2,OSTYPE ;Get OS
CAIE T2,OSIAS ;RSX? (Might be IAS)
PUSHJ P,XMTMSG ;IAS doesn't like this
MOVE T1,[RXDMSK,,IMASK] ;Set RSX default break mask
BLT T1,ENDMSK ;Set up
MOVE T1,[RXDMSK+1,,LMASK] ;Set the local mask too
BLT T1,ELMASK
MOVX T1,<1B<.CHCNC>!1B<.CHCNO>!1B<.CHCNX>>
MOVEM T1,CHRTAB ;Set ^C, ^O as special
IORM T1,IMASK+1 ;Be sure they're breaks for us
MOVE T1,[3,,T2] ;Set no lower case as that
MOVEI T2,.TOSET+.TOLCT ;Is the default
MOVE T3,TTYUDX
SETO T4,
TRMOP. T1,
JFCL
PJRST TTYSST ;Set up TTY
SUBTTL RSX Support -- Network interrupt
RX.NET: PUSHJ P,RBYTEC ;Get the function
MOVEI P1,RSXFNC ;Point to function table
PUSHJ P,FNDFNC ;Go do it
ERR IXF,<Illegal RSX function>
POPJ P, ;Return
SUBTTL RSX Support -- TTY: input
RSX.TT: SKIPE P4,READQ ;Is there an outstanding read?
PJRST RX.CRQ ;Finish up
SKIPE P4,XSCREQ ;Is there a single char request?
JRST RX.TT1 ;Yes
HRROS XUNREQ ;Flag from TTY: service
RX.RCN: PUSHJ P,SCNSPC ;Scan special characters
JRST RX.TT0 ;Then anything special
RX.NES: MOVE P4,XUNREQ ;Get the unsolicited request
HRRZS XUNREQ ;Make it the way it was
TXNE F,F$UAST ;Want unsolicited input?
TRNN P4,-1 ;Is there an unsolicted request?
POPJ P, ;Doesn't want it
FALL RX.TU1 ;Fall into unsolicited support
;Here to see if unsolicited input is enabled
RX.TU1: PUSHJ P,CLRCTO
MOVEM F,RSXSVF ;So won't send extra message
MOVE T1,R.COUNT(P4) ;Get its count
TXZN F,F$BRK ;See a break?
CAMG T1,ICHCNT ;Or count satisfied?
JRST RX.TU3 ;Satisfied, one way or another
TXNN F,F$RU1 ;First time through here?
PJRST CHKCTH ;See about ^H stuff
PUSHJ P,SCNINI ;Else echo the char
PUSHJ P,SCNCHR ;...
PJRST XCRURB ;Nothing
MOVEI T1,(P1) ;Put in useful AC
CAIG T1," " ;Not control or space?
CAIN T1,.CHCRT ;But <CR> is special
JRST RX.TU2 ;Output it
PUSHJ P,INCHR ;Eat character
JFCL ;?
PJRST XCRURB ;See about ^U/^R/<RUB>
RX.TU2: TXZ F,F$RU1 ;No longer in first character
PUSHJ P,EKOTAH ;Echo all the type-ahead
MOVE T1,[LMASK,,IMASK+1]
BLT T1,ENDMSK ;Set reasonable mask now
MOVX T1,1B<.CHCNH> ;Be sure can see this
IORM T1,IMASK+1
PUSHJ P,FRCTTI ;Force wakeup
PUSHJ P,CHKLED ;Need to do editing?
POPJ P, ;Yes, do it
PJRST XCRURB ;Set ^U, ^R, etc. in mask
;Note this calls TTYSST
;Here if the read is really satisfied
RX.TU3: SETOM LICHCT ;A read satisfied
MOVEI T1,RF.UNS ;Unsolicited function
PUSHJ P,RSX.BH ;Build the header
SETZ P1,
NETOCH P1 ;Reserved
PUSH P,OBFPTR ;Save pointer
NETALC 2 ;Allocate read count
PUSHJ P,PUTWRD ;And write count
MOVN P1,R.COUNT(P4) ;Get the count
HRLZI P1,(P1)
RX.TU4: PUSHJ P,INCHR ;Get character
JRST RX.TU9 ;Oops
CAMN T1,ESCCHR ;Escape?
SOS BRKNUM ;One less break
RX.TU5: NETOCH T1
PUSHJ P,CHKBR1 ;If still a break,
JRST RX.TU7 ;Then check it's echo
TLNN P4,400000 ;From TTY: service?
PUSHJ P,OUTTTY ;No, echo character
AOBJN P1,RX.TU4 ;..
SETZ T1, ;Use <NUL> terminator if none
TRNA ;Already have character
RX.TU7: HLRZ T1,BRKCHR
TLNN P4,400000 ;From TTY: service?
PUSHJ P,DOOUT1 ;No, make sure characters get out
MOVE T4,[-RXBLEN,,RXBTBL] ;Break echo table
MOVSI T3,RM.RNE ;To see if noecho
TDNN T3,R.MOD(P4) ;Is it?
TRNN P1,-1 ;Yes, any chars other than term?
JRST RX.TU9 ;No chars except term or noecho
CAIE T1,.CHCNZ ;^Z?
CAIN T1,.CHCRT ;<CR>?
TXOA F,F$CLF ;Warn to cancel <LF>
TXZ F,F$CLF
PUSHJ P,EKOBRK ;Echo break character
RX.TU9: MOVE T1,OBFPTR
EXCH T1,(P) ;Point to count word
MOVEM T1,OBFPTR
MOVEI T1,2 ;Putting in 2 chars
ADDM T1,OBFCTR
PUSHJ P,PUTWRD ;Put the count in
POP P,OBFPTR ;Restore the real pointer
PUSHJ P,XMTMSS ;Send message
PUSHJ P,XCRURB ;Clear ^R/^U/<RUB>
JRST RX.DUN ;Reset up unsolicited
;Here to handle special characters
RX.TT0: PUSHJ P,RX.SPC ;Handle it
JRST RSX.TT ;If a return
PUSHJ P,CONSCN ;?Continue the scan
JRST RX.TT0 ;See about that one
JRST RX.NES ;?
;Here if there is a read single characters active
RX.TT1: PUSHJ P,SCNINI ;Init a scan (in case we need it)
RX.T1A: PUSHJ P,SCNCHR ;Get character
JRST RX.TT2
CAME P1,ESCCHR ;Escape character?
JRST RX.T1A ;No
PUSHJ P,MONITO ;Return
PUSHJ P,SPCRMV ;Remove character
RX.TT2: SKIPN ICHCNT ;Anything really there?
POPJ P,
MOVE P4,XSCREQ ;Restore request block
TXZ F,F$TEX ;Flag from TTY: service
;Here for timeouts on single characters
RX.SSS: HLRZ T4,R.MOD(P4) ;Get modifiers
ANDI T4,RM.UNL!RM.NOT!RM.NSA!RM.OSA ;Save only relevant bits
JUMPE T4,RX.ACH ;If any character
CAIE T4,RM.UNL ;Notification for line
CAIN T4,RM.NOT ;Only want notification?
JRST RX.NOT ;Do that then
CAIN T4,RM.NSA ;Only want non-system?
JRST RX.NSA ;Yes, see if that's what is in
CAIN T4,RM.NSA!RM.OSA ;Want any character?
JRST RX.ACH ;Yes, send then
CAIE P1,.CHCNC ;^C?
JRST RX.NOT ;Not system attention, just notify
TXNE F,F$TEX ;From TTY: service?
JRST RX.SCH ;No
RX.ACH: MOVSI T1,RM.RTO ;Reset on each character...
SKIPE R.TIME(P4) ;Any timeout or,
TDNE T1,R.MOD(P4) ;?
JRST RX.SCH ;Terminate request now
POPJ P, ;Didn't timeout yet
RX.SCH: MOVEI T1,RF.RSC ;Function
NETOCH T1
HLRZ T1,R.MOD(P4) ;Get the modifiers
ANDCMI T1,RM.NOT ;We aren't just notifying
JUMPE T1,RX.SCZ ;Doesn't care about character
TRZ T1,RM.OSA ;Assume it's a normal character
TRO T1,RM.NSA ;..
CAIE P1,.CHCNC ;Attention?
TRC T1,RM.OSA!RM.NSA ;No, normal
RX.SCZ: NETOCH T1 ;Put in modifiers
SETZ P1,
ASSUME XS.SFC,0
PUSHJ P,PUTWRD ;Completion status and flags
HLRZ T2,R.IDENT(P4) ;Get request ID
NETOCH T2
ASSUME XS.SFC,0 ;From above
NETOCH P1 ;Reserved byte
PUSH P,OBFPTR ;Save current pointer
SETZB P1,P2 ;Count, last character
PUSHJ P,PUTLWD ;no writes
HLRZ P3,R.MOD(P4) ;Modifiers
TRC P3,RM.OSA!RM.NSA ;Easier to test zeroes
RX.TT3: PUSHJ P,INCHR ;Get character
JRST RX.TT4 ;None
TRNN P3,RM.OSA!RM.NSA ;Were both set?
CAIN T1,P2 ;Or are both the same?
JRST RX.T3A ;Both the same or both not set
JUMPE P2,RX.T3A ;Or if this is first character
CAIE T1,.CHCNC ;Is this a ^C?
CAIN P2,.CHCNC ;Or was that?
TRNA ;One was (blast!)
JRST RX.T3A ;Neither was, continue
EXCH T1,(P) ;Save character, get pointer
MOVEI T2,2
ADDM T2,OBFCTR ;Fudge count
PUSH P,OBFPTR ;Save old pointer
MOVEM T1,OBFPTR ;Fudged pointer
PUSHJ P,PUTWRD ;Current counter
POP P,OBFPTR ;Real pointer
PUSHJ P,XMTMSS ;Send the message
MOVEI T1,RF.RSC ;Function
NETOCH T1 ;Rebuild header
POP P,T1 ;Restore saved character
MOVEI T2,RM.NSA ;Assume normal
CAIN T1,.CHCNC ;Is it?
TRC T1,RM.OSA!RM.NSA ;No
NETOCH T2 ;Output modifiers
SETZ P1,
ASSUME XS.SFC,0
PUSHJ P,PUTWRD ;Completion status and flags
HLRZ T2,R.IDENT(P4) ;Get request ID
NETOCH T2
ASSUME XS.SFC,0 ;From above
NETOCH P1 ;Reserved byte
PUSH P,OBFPTR ;Save current pointer
SETZB P1,P2 ;Count, last character
PUSHJ P,PUTLWD ;no writes
RX.T3A: MOVE P2,T1 ;Remember character
NETOCH T1
AOJA P1,RX.TT3
RX.TT4: MOVEI T1,2
ADDM T1,OBFCTR ;Fudge count
MOVE T1,OBFPTR
EXCH T1,(P) ;Point to read count
MOVEM T1,OBFPTR
PUSHJ P,PUTWRD
POP P,OBFPTR
SKIPE R.TIME(P4) ;Is there a timeout?
PUSHJ P,RX.STM ;Yes, reset it
PJRST XMTMSS ;Send the message
;Here if only want non-system characters
RX.NSA: CAIN P1,.CHCNC ;Is it ^C?
JRST RX.TT0 ;Yes
PJRST RX.ACH ;Send the char
;Here if only notifying
RX.NOT: TRNE T4,RM.UNL ;Only for line?
CAIN P1,.CHCRT ;Line in the RSX sense?
TRNA
POPJ P, ;Don't notify yet
MOVEI T1,RF.RSC ;Function
NETOCH T1
HLRZ T1,R.MOD(P4)
NETOCH T1
SETZ P1, ;Flags and reserved
ASSUME XS.SFC,0
PUSHJ P,PUTWRD
PUSHJ P,PUTLWD ;Counts
PJRST XMTMSS
SUBTTL RSX Support -- NOP function
;Also here is the RX.CCO routine to clear F$CTO in both F and the RSXSVF
;copy of F.
RX.NOP: PUSHJ P,RBYTEC ;Get modifiers (0)
PUSHJ P,RBYTEC ;Get flags
TRNN T1,RM.CAO ;Cancel abort I/O?
POPJ P,
RX.CCO: PUSHJ P,CLRCTO ;Do the cancel
MOVEM F,RSXSVF ;Save F
POPJ P,
SUBTTL RSX Support -- Set unsolicited characters
RX.SUN: PUSHJ P,RSX.EH ;Eat header
PUSHJ P,GETWRD ;Count
MOVEM T1,R.COUNT(P4) ;Set it
MOVSI T1,RM.TUI ;Terminate?
TDNE T1,R.MOD(P4) ;?
JRST RX.TUN ;Yes
MOVEM P4,XUNREQ ;Point to it
SKIPE READQ ;Read pending?
POPJ P, ;Yes
RX.DUN: TXNE F,F$UAST ;Set read status unless attached
TXO F,F$READ!F$RU1 ;Read outstanding, just got re-enabled
MOVE T1,R.COUNT(P4) ;Get the count
MOVEM T1,IMASK ;Set it
MOVE T2,[RXDMSK+1,,LMASK]
BLT T2,ELMASK ;Set both masks
SETOM IMASK+1 ;Break on all chars at first
MOVE T2,[IMASK+1,,IMASK+2]
SOSG T1 ;If more than one character to what we planned
HRLI T2,RXDMSK+1 ;Else it is default too
BLT T2,ENDMSK
JUMPLE T1,RX.DU4
MOVX T2,<1B<.CHCNC>!1B<.CHCNO>!1B<.CHCNR>!1B<.CHCNU>!1B<.CHCNS>!1B<.CHCNQ>!1B<.CHCNX>>
ANDCAM T2,IMASK+1 ;But don't break on these
MOVEI T2,1B31 ;Same for <RUB>
ANDCAM T2,IMASK+1+3
RX.DU4: TXZ F,F$NEC ;Must echo
MOVX T1,<1B<.CHCNC>!1B<.CHCNO>!1B<.CHCNX>>
IORM T1,CHRTAB
IORM T1,IMASK+1 ;Be sure we see them
PUSHJ P,FRCTTI ;Force TTY: check
PUSHJ P,TTYSST ;Set up TTY:
PJRST RX.RCN ;In case some type-ahead
RX.TUN: SKIPN READQ ;Not a read unless there really is one
TXZ F,F$READ
MOVEI T1,(P4)
MOVEI T2,REQSIZ
PUSHJ P,CORFRE
MOVE T1,XUNREQ
SETZM XUNREQ
PJRST CORFRE
SUBTTL RSX Support -- Kill I/O
RX.KIL: NETOCH T1 ;ACK the function
SETZ P1,
PUSHJ P,PUTWRD ;No flags or modifiers
ASSUME XS.SFC,0
NETOCH P1 ;Status is success
PUSHJ P,RBYTEC ;Get modifiers (0)
PUSHJ P,RBYTEC ;Get flags
TRNE T1,RM.CAO ;Cancel ^O?
PUSHJ P,RX.CCO
PUSHJ P,RBYTEC ;Status
PUSHJ P,RBYTEC ;Request ID
NETOCH T1 ;Put it in
MOVEI P2,(T1) ;Save it
HRRZ P4,READQ ;Get current request
JUMPE P4,XMTMSS ;ACK and return
MOVEI P3,READQ-R.LINK ;Predecessor
RX.KI1: HLRZ T1,R.IDENT(P4) ;Get the identifier
CAIE T1,(P2) ;Right one?
JRST [HRRZI P3,(P4) ;This is last block
JRST RX.KI3 ] ;Continue
HRL P3,R.LINK(P4) ;Successor
HLRM P3,R.LINK(P3) ;Link to predecessor
RX.KIA: SKIPN T1,R.PROMPT(P4) ;Prompt?
JRST RX.KI2 ;No
HLRZ T2,T1 ;Size
LSHC T2,-2
TLNE T3,600000
AOJ T2,
HRRZI T1,(T1)
PUSHJ P,CORFRE
RX.KI2: HRRZI T1,(P4) ;Point T1 at core block
MOVEI T2,REQSIZ
PUSHJ P,CORFRE
RX.KI3: HRRZ P4,R.LINK(P3) ;Point to next
JUMPN P4,RX.KI1 ;More
SKIPN P4,XSCREQ ;Single?
JRST RX.KI4 ;No
HLRZ T1,R.IDENT(P4) ;Get identifier
CAIE T1,(P2) ;The required ID?
JRST RX.KI4 ;No
MOVEI P3,XSCREQ-R.LINK ;Fake predecessor
SETZM XSCREQ ;No request any more
SKIPN P4,READQ ;Read request?
TXZA F,F$NEC!F$PALL ;No, clear noecho and passall
TXZ F,F$PALL ;Yes, just clear passall
JRST RX.KIA ;Deallocate
RX.KI4: SKIPN P4,XUNREQ ;Unsolicited request?
JRST RX.KI5
HLRZ T1,R.IDENT(P4)
CAIE T1,(P2) ;Right thing?
JRST RX.KI5 ;No
SETZM XUNREQ
HRRI P3,XUNREQ-R.LINK ;Fake predecessor
JRST RX.KIA ;Kill
RX.KI5: SKIPN READQ
SKIPE XUNREQ
PJRST XMTMSS
SKIPN XSCREQ
TXZ F,F$READ
PJRST XMTMSS
SUBTTL RSX Support -- Disconnect link
RX.DIS: POPJ P, ;We'll find out soon enough
SUBTTL RSX Support -- Single character mode
RX.SSC: PUSHJ P,RSX.EH ;Digest it
MOVSI T1,RM.TSC ;If terminate,
TDNE T1,R.MOD(P4) ;Then exit now
JRST RX.TSC ;And perform it
PUSHJ P,GETLWD ;Eat counts
PUSHJ P,RBYTEC ;Timeout
JUMPE T1,RX.SC1
IMULI T1,^D4000 ;Convert to MS
IDIVI T1,^D60
CAIL T2,^D30
AOJ T1,
TLO T1,(1B0) ;Flag in MS
MOVEM T1,R.TIME(P4) ;Save
RX.SC1: MOVEM P4,XSCREQ ;Save it
SKIPE READQ ;Is there a read outstanding?
POPJ P, ;Then its charactersitics apply
;Enter here with P4 pointing to block
RX.SCS: HLRZ T1,R.MOD(P4)
TRNE T1,RM.RNE ;NO echo?
TXOA F,F$NEC ;Yes
TXZ F,F$NEC ;No
SKIPE R.TIME(P4) ;Timeout?
PUSHJ P,RX.STM ;Yes
MOVEI T1,1 ;Break on each character
MOVEM T1,IMASK
SETOM IMASK+1
MOVE T1,[IMASK+1,,IMASK+2]
ASSUME LMASK,<<ENDMSK+1>>
BLT T1,ELMASK ;..
TXO F,F$PALL ;Set no special characters
PUSHJ P,TTYSST ;Set TTY: up
PUSHJ P,FRCTTI ;Force TTY: look
PJRST RX.TT1 ;See if any typeahead
RX.TSC: SKIPN READQ ;If no read
TXZ F,F$TMR ;Cancel timeout
MOVEI T1,(P4)
MOVEI T2,REQSIZ
PUSHJ P,CORFRE
MOVE T1,XSCREQ
SETZM XSCREQ
PUSHJ P,CORFRE
SKIPN P4,READQ ;Read request?
TXZA F,F$NEC!F$PALL ;No, clear noecho and passall
TXZA F,F$PALL ;Yes, just clear passall
JRST RX.CUN ;Check unsolicited
PUSHJ P,FRCTTI ;Force TTY: look
PJRST RX.PM5 ;In case satisfied from typeahead
SUBTTL RSX Support -- ATTACH/DETACH
RX.DAT: PUSHJ P,RBYTEC ;Get modifiers
TRNE T1,RM.DET ;Detach?
JRST RX.DET ;Yes
TXZ F,F$UAST ;Don't really want unsolicited
SKIPN READQ ;When ATTACHed, if not a read
TXZ F,F$READ ;Then there really isn't one
PUSHJ P,TTYSST ;Change mask
PJRST FRCTTI ;Check for input
RX.DET: TXO F,F$UAST ;Want unsolicited if enabled
SKIPN P4,XUNREQ ;Request?
POPJ P, ;No
PJRST RX.DUN ;Reset unsolicited
SUBTTL RSX Support -- Get terminal characteristics
RX.GTC: MOVEI T1,RF.GTC ;ACK the function
NETOCH T1
SETZ P1, ;Modifiers & flags
PUSHJ P,PUTWRD
PUSHJ P,GETWRD ;Get modifiers, flags
TRNE T1,<RM.CAO>B<35-8>
PUSHJ P,RX.CCO
PUSHJ P,RBYTEC ;Status
ASSUME XS.SFC,0
NETOCH T1 ;Assume it stays the same
PUSHJ P,GETWRD ;Identifier, reserved
MOVE P1,T1
PUSHJ P,PUTWRD ;Return it
PUSHJ P,GETLWD ;Eat counts
SETZ P1,
PUSHJ P,PUTLWD ;Put zero for them
RXCHLP: PUSHJ P,NETICH ;Get characteristic
JRST RXCHGX ;Done
JUMPE T1,RXCHGX ;Or this way
NETOCH T1 ;Type
CAIE T1,RC.CTA ;Type-ahead?
JRST RXCH1 ;No
PUSHJ P,SETICH ;Set ICHCNT
MOVE T1,[2,,T2]
MOVE T2,TTYUDX
MOVEI T3,.TOTTC ;Figure it out
TRMOP. T1,
SETZ T1,
ADD T1,ICHCNT ;..
TRNA ;Skip normal loading
RXCH1: MOVE T1,RXCHTB-1(T1) ;Get the answer
NETOCH T1 ;Put in
PUSHJ P,RBYTEC ;Eat the "field"
JRST RXCHLP ;Proceed
RXCHGX: SETZ T1,
PUSHJ P,PUTWRD
PJRST XMTMSS ;Finish off and end
SUBTTL RSX Support -- Set terminal characteristics
RX.STC: NETOCH T1 ;Output the function
PUSHJ P,GETWRD ;Get modifiers and flags
TRNE T1,<RM.CAO>B<^D35-8> ;?
PUSHJ P,RX.CCO
SETZ P1,
PUSHJ P,PUTWRD ;Modifiers and flags
ASSUME XS.SFC,0
NETOCH P1 ;Status
PUSHJ P,RBYTEC ;Input status
PUSHJ P,GETWRD ;ID, reserved
MOVE P1,T1 ;Transfer
PUSHJ P,PUTWRD ;And do it
PUSHJ P,GETLWD ;Get counts
MOVE P1,T1
PUSHJ P,PUTLWD
RXSCLP: PUSHJ P,NETICH ;Get a characteristic
SETZ T1,
JUMPE T1,[PUSHJ P,TTYSST
PJRST XMTMSS ]
MOVEI P1,(T1) ;Save it
PUSHJ P,RBYTEC ;Get set field
MOVEM T1,RXCHTB-1(P1) ;Save it
CAIN P1,RC.BIN ;Binary?
XCT [TXZ F,F$PALL ;Yes, set it
TXO F,F$PALL](T1) ;appropriately
CAIN P1,RC.NEC
XCT [TXZ F,F$NEC
TXO F,F$NEC](T1)
CAIN P1,RC.CTA ;Type-ahead function?
PUSHJ P,FLSTAH ;Clear all type-ahead
SKIPN T2,RXTRMP(P1) ;Should we do a TRMOP. here?
JRST RXSCLP ;Continue
TLZE T2,400000 ;Sign bit set?
TRC T1,1 ;Yes, complement setting
MOVE T4,T1 ;Copy
CAIE P1,RC.TTP ;Set TTY: type?
JRST RXSTRM ;No, set other characteristics then
MOVSI T2,-TTPLEN ;Terminal table
HRRZ T3,RTPTB(T2) ;Get RSX terminal type
CAIE T3,(T4) ;Match ours?
AOBJN T2,.-2 ;Keep looking if not
JUMPGE T2,RXSCLP ;Oh well, don't know it
MOVE T4,TTPTB(T2) ;Get TOPS-10 name
RXSTRM: MOVE T3,TTYUDX
MOVE T1,[3,,T2]
TRMOP. T1,
JFCL
JRST RXSCLP
SUBTTL RSX Support -- Read data, Read with prompt
RX.PRD: SKIPA P1,[-1] ;This is a prompt request
RX.RED: SETZ P1,
PUSHJ P,RX.CCO ;Cancel ^O
TXO F,F$READ ;Read outstanding
PUSHJ P,RSX.EH ;Eat the header
MOVEM P1,R.PROMPT(P4) ;Save prompt status
PUSHJ P,GETWRD ;Get read count
MOVEM T1,R.COUNT(P4) ;Save
MOVSI T2,RM.RTM ;Timeout?
TDNN T2,R.MOD(P4) ;??
JRST RX.NT1 ;No
ANDI T1,377 ;Clear count
ANDCAM T1,R.COUNT(P4) ;Clear timout value in count
LSH T1,-^D8 ;Two instrs to save precision
IMULI T1,^D10 ;Convert to seconds
MOVEM T1,R.TIME(P4) ;Save timeout
RX.NT1: SETZ T1, ;Default nothing
MOVSI T2,RM.RTT ;The terminator mask bit
SKIPN R.PROMPT(P4) ;Wanted prompt?
TDNE T2,R.MOD(P4) ;See if terminator bit set
PUSHJ P,GETWRD ;Get write/terminator count
SKIPN R.PROMPT(P4) ;Want prompt?
SKIPN T4,T1 ;Copy count to T4
JRST RX.NMK ;There really isn't a mask
MOVE T3,[POINT 8,R.MASK(P4),];Point to mask area
PUSHJ P,CPYMSK ;Copy in the mask
SETZ T1, ;Can't combine mask and prompt
RX.NMK: MOVSI T2,RM.RTC ;See if terminate on characters
TDNN T2,R.MOD(P4) ;?
JRST RX.NCC ;No
MOVE T2,[777777,,777760] ;Set it
MOVEM T2,R.MASK(P4) ;Control chars
MOVEI T2,7B31 ;Also include <ALT>s and <RUB>
MOVEM T2,R.MASK+3(P4) ;Set them all
RX.NCC: JUMPE T1,RX.NPT ;No prompt
PUSH P,T1 ;Save size of string
LSHC T1,-2
TLNE T2,600000 ;Check remainder
AOS T1
PUSHJ P,CORGET ;Get block for prompt
HRRM T1,R.PROMPT(P4) ;Save it
POP P,T4 ;Get byte count
HRLM T4,R.PROMPT(P4) ;Save it
MOVEI T2,(T1) ;Point to block
HRLI T2,(POINT 8,,) ;Make a byte pointer
RX.PM1: PUSHJ P,RBYTEC ;Get byte of string
IDPB T1,T2
SOJG T4,RX.PM1
RX.NPT: TXZ F,F$PALL ;Not while read active
MOVEI T1,RM.PRI ;Process immediately?
MOVE T4,READQ
TDNN T1,R.FLAG(P4) ;Is this process immediately?
JUMPN T4,XQREAD ;No, queue request here
MOVEM P4,READQ ;This is now current request
HRRM T4,R.LINK(P4) ;In case this is a PRI
RX.NRQ: TXO F,F$IOQ ;Inhibit output
PUSHJ P,XPROMT ;Output the prompt
RX.CTM: SKIPE T1,R.TIME(P4) ;Is there a timeout?
TXO F,F$TMR ;Set there is a timeout
RX.PM5: PUSHJ P,RX.STT ;Set TTY: up for this request
PUSHJ P,CHKLED ;See if need to do editing
PJRST FRCTTI ;Yes, do it
PUSHJ P,EKOTAH ;Echo type-ahead
TLZA P4,400000 ;Flag not from TTY: service
FALL RX.CRQ ;Fall in CRQ
;Here from TTY: service to see if request can now be completed
RX.CRQ: PUSHJ P,CLRCTO ;Clear ^O
MOVEM F,RSXSVF ;Saved copy
TLO P4,400000 ;Flag from TTY: service
TXNE F,F$TMR ;Timeout?
SKIPN R.TIME(P4) ;Really? (not RSC)
TRNA ;Nope
PUSHJ P,RX.STM ;Set it up
MOVEM P4,READQ ;Save the request
PUSHJ P,SCNSPC ;Any special characters in input?
JRST RX.CSC ;Check special characters
RX.NSC: MOVE P4,READQ ;Get the request back
HRRZ T1,R.COUNT(P4) ;Get count desired
CAMLE T1,ICHCNT ;Do we have at least that many?
TLZE F,(F$BRK) ;Or have we seen a break?
JRST RX.RDS ;Read is satisfied
PUSHJ P,XCRURB ;See about rubout etc.
PJRST CHKCTH ;Check ^H
;Also enter here with P4 pointing to header block from TIMEOUT service
RX.RDS: SETOM LICHCT ;Flag to do ^H next time
SETZM XSPCNT ;Going to eat all ^Cs
MOVEI T1,($TOOIN!$TOICL) ;Overrid inhibit for echo
IORM T1,TOFLGS
MOVEI T1,RF.RDD ;Build header for read
PUSHJ P,RSX.BH ;Build header to complete request
SETZ P1, ;Reserved byte
NETOCH P1
PUSH P,OBFPTR ;Save output pointer
NETALC 2 ;Two for the read
PUSHJ P,PUTWRD ;Two for the write
MOVN P2,R.COUNT(P4) ;Get desired count
HRLZI P2,(P2) ;Make AOBJN pointer
JUMPE P2,RX.RDZ ;**Zero length read**
HLRZ P3,R.MOD(P4) ;Get modifiers
RX.RDL: PUSHJ P,INCHR ;Get a character
JRST [HRRZI P2,(P2) ;Flag no break character
MOVSI T1,(<RM.RTM>B15);Set a timeout
IORM T1,@OTPBUF ;...
JRST RX.RDD ] ;Read is done
CAMN T1,ESCCHR ;Escape character?
SOS BRKNUM ;One less break
NETOCH T1
PUSHJ P,CHKBR1 ;Is it a break?
JRST RX.RDD ;yes, read is done
TLNN P4,400000 ;From TTY: service?
TRNE P3,RM.RNE ;No, noecho?
JRST RX.RDF ;From TTY: or noecho
PUSHJ P,OUTTTY ;Output character
RX.RDF: AOBJN P2,RX.RDL ;Continue
RX.RDZ: SETZ T1, ;Make terminator a <NUL>
NETOCH T1
JRST RX.RNB ;No break
RX.RDD: HLRZ T1,BRKCHR
CAIN T1,.CHCNC ;Control-C?
SKIPN T2,XSCREQ ;Any single request?
JRST RX.RDE ;No
HLRZ T2,R.MOD(T2) ;Get modifiers
TRNE T2,RM.OSA ;?
JRST RX.RNB ;Already echoed it
RX.RDE: MOVSI T2,RM.RTC ;Terminate on control?
TDNE T2,R.MOD(P4) ;?
CAIL T1," " ;Is this a control character?
SKIPN R.COUNT(P4) ;Make sure non-zero length request
JRST RX.RNB
CAIE T1,.CHCNZ ;^Z?
CAIN T1,.CHCRT ;<CR>?
TXNE F,F$NEC ;Yes, noecho?
TXZA F,F$CLF ;Don't
TXO F,F$CLF ;Set CLF if all of the above are true
MOVE T4,OSTYPE ;Get OS
CAIN T4,OSIAS ;11M or IAS?
SKIPA T4,[-ISBLEN,,ISBTBL] ;Use IAS table
SKIPA T4,[-RXBLEN,,RXBTBL]
TXZ F,F$CLF ;Skip this stuff if IAS
PUSHJ P,EKOBRK ;Echo if not
RX.RNB: MOVE T1,OBFPTR ;Save real output pointer
EXCH T1,(P) ;Get count pointer
MOVEM T1,OBFPTR ;Point to status word
MOVEI T1,2 ;Was subtracted before
ADDM T1,OBFCTR ;..
MOVEI P1,(P2) ;Character count
PUSHJ P,PUTWRD ;Put it in
POP P,OBFPTR ;Restore real pointer now
RX.RDQ: PUSHJ P,XMTMSS ;Send the message now
TLZN P4,400000 ;From TTY:?
TRNE P3,RM.RNE ;No-echo?
JRST RX.RQ1
PUSHJ P,DOOUT1 ;Force out
SETZM TOFLGS
RX.RQ1: HRRZ T1,R.LINK(P4) ;Point to next request
HRRZM T1,READQ ;which is now current
SKIPN T1,R.PROMPT(P4) ;Prompt block to free?
JRST RX.NPF ;No
HLRE T2,T1 ;Put length in T2
LSHC T2,-2 ;To words
TLNE T3,600000 ;Check remainder
AOJ T2,
HRRZI T1,(T1)
PUSHJ P,CORFRE
RX.NPF: MOVEI T1,(P4) ;Free this block
MOVEI T2,REQSIZ
PUSHJ P,CORFRE ;..
PUSHJ P,XCRUR1 ;...
TXZ F,F$IOQ ;Don't inhibit any more
SKIPE P4,READQ ;New request
JRST RX.NRQ ;New request
SKIPN P4,XSCREQ ;Read single in effect?
TXZA F,F$READ ;No, no read
TXOA F,F$READ ;Be sure it's set
JRST RX.CUN ;See if unsolicited
TXZ F,F$TMR ;Clear timeout
PJRST RX.SCS ;Set it up
;Here to check if an unsolicited request
RX.CUN: SKIPE P4,XUNREQ ;Is there one?
PJRST RX.DUN ;Do setup
PUSHJ P,TTYSST ;Set up TTY:
PJRST FRCTTI ;Look
;Here if a special character was found by SCNSPC, ponder what to do
RX.CSC: SKIPN T1,XSCREQ ;Read single in effect?
JRST RX.DSC ;No
HLRZ T2,R.MOD(T1) ;Get modifiers
CAIE P1,.CHCNC ;Is this the interesting character?
JRST RX.DSC ;No
TRNN T2,RM.OSA ;Want attention characters?
JRST RX.CS2 ;No
SKIPN T2,XSPCNT ;Count of ^C's in buffer
JRST RX.CS5 ;This is the first
PUSH P,T2 ;Save in an interesting place
RX.CS1: PUSHJ P,CONSCN ;Continue the scan
JRST RX.CS3 ;Found one
POP P,(P) ;Clear junk
RX.CS2: MOVEI P1,.CHCNC ;Is the magic character also a break?
PUSHJ P,CHKBRK ;?
TXO F,F$BRK ;Yes, flag it
JRST RX.NSC ;Didn't really see a special character
RX.CS3: CAIE P1,.CHCNC ;The magic character?
JRST [POP P,(P) ;No
JRST RX.DSC] ;Process it
SOSLE (P) ;Yes, notify for it already?
JRST RX.CS1 ;Continue scanning
POP P,(P)
RX.CS5: AOS XSPCNT ;We scanned this one
MOVE P4,XSCREQ ;The unsolicited request
MOVEI T1,RF.RSC ;Function
NETOCH T1
HLRZ T1,R.MOD(P4) ;Get modifiers
ANDI T1,RM.OSA ;Saving only this
NETOCH T1 ;Put in modifiers
SETZ P1,
ASSUME XS.SFC,0
PUSHJ P,PUTWRD ;Completion status and flags
HLRZ T2,R.IDENT(P4) ;Get request ID
NETOCH T2
ASSUME XS.SFC,0 ;From above
NETOCH P1 ;Reserved byte
MOVEI P1,1 ;Number of characters here
PUSHJ P,PUTLWD ;plus zero writes
MOVEI T1,.CHCNC
NETOCH T1
PUSHJ P,XMTMSS ;Send the message
; HLRZ T2,R.MOD(P4) ;Get modifiers
MOVE P4,READQ ;Restore P4 to point to queue block
; TRNE T2,RM.RNE ;Noecho?
; JRST RX.CRQ ;Yes, continue processing
MOVEI T4,[ASCIZ/^C
/]
PUSHJ P,STROUT
PUSHJ P,DOOUT1
JRST RX.CRQ ;Echo before continuing
RX.DSC: PUSHJ P,RX.SPC ;Yes, handle them
JRST RX.DS1 ;Normal return
PUSHJ P,CONSCN ;Continue scan
JRST RX.DSC
JRST RX.NSC ;No special chars at all
RX.DS1: SKIPE P4,READQ ;Still a queued request?
JRST RX.CRQ ;Yes, scan again (must be from TTY:)
PJRST XCRURB ;No, give up now
SUBTTL RSX Support -- Output prompt string
;This routine outputs the prompt string in the RSX digested header block
;pointed to by P4. Uses T1, T3, and T4.
XPROMT: SKIPN T4,R.PROMPT(P4) ;Get the prompt string
POPJ P, ;None to do
MOVEI T3,($TOOIN!$TOICL)
MOVEM T3,TOFLGS
HLRZ T3,T4 ;Get count
HRLI T4,(POINT 8,,) ;Point to data
RX.OPM: ILDB T1,T4
PUSHJ P,OUTTTY
SOJG T3,RX.OPM ;Output all prompt data
PUSHJ P,DOOUT1
SETZM TOFLGS
POPJ P,
SUBTTL RSX Support -- Handle special characters
RX.SPC: CAME P1,ESCCHR ;Escape?
JRST RX.CCC ;No, see if ^C
PUSHJ P,MONITO ;Return to monitor
JRST [PUSHJ P,SPCRMV ;Remove special chracter
PJRST XCRURB ] ;See about this
AOS BRKNUM ;One more break to ignore
PJRST XCRURB ;Check bits
RX.CCC: CAIE P1,.CHCNO
JRST RX.CTC ;Control-C or ^X
PUSHJ P,SPCRMV ;Clear it
PUSHJ P,XCRURB
TXCN F,F$CTO ;Setting ^O?
PUSHJ P,CLRTOQ ;Clear the TO queue
MOVEI T4,[ASCIZ/^O
/] ;How to echo it
PUSHJ P,STROUT
RX.CTO: PUSHJ P,DOOUT1
RX.CO1: MOVEM F,RSXSVF ;Save the current flags
MOVEI T1,RF.ECR
NETOCH T1 ;Tell him to toggle too
SETZ P1,
PUSHJ P,PUTWRD ;No flags or modifiers
MOVEI T1,RE.HAO
NETOCH T1 ;Output reason
PUSHJ P,XMTMSS ;Tell him
TXZ F,F$ICO ;Don't ignore any more
TXNN F,F$CTO ;Set or clear?
PJRST CLRCTO ;Tell the monitor
PUSHJ P,WATOUT ;Wait for it to go out if just set
PJRST SETCTO
RX.CTC: CAIE P1,.CHCNC ;^C?
JRST RX.CTX ;Check ^X if not
PUSHJ P,SPCFLS ;Clear input to ^C
MOVEI T1,RF.ECR ;Request an exception
NETOCH T1
SETZ P1, ;No flags or modifiers
PUSHJ P,PUTWRD
ASSUME RE.SAR,0
NETOCH P1 ;Output the reason
SKIPN P4,READQ ;A request?
PJRST XMTMSS ;Send the message and return
PUSHJ P,XMTMSS ;Send the abort
MOVEI T1,RF.RDD ;Set the request type
PUSHJ P,RSX.BH ;Build it
SETZ P1, ;The reserved byte
NETOCH P1 ;..
PUSHJ P,PUTLWD ;Also the counts
MOVEI P1,.CHCNC ;The terminator
NETOCH P1 ;Output it
PJRST RX.RDQ ;Clean up
RX.CTX: CAIE P1,.CHCNX ;Control-X?
JRST RX.CTU ;Maybe ^U
PUSHJ P,SPCFLS ;Flush input to ^X
SKIPN READQ ;If not inputting
POPJ P, ;Then return
MOVEI T4,[ASCIZ/^U
/]
PUSHJ P,STROUT
PUSHJ P,DOOUT1 ;Force it out
PJRST RX.CU1 ;And check some things
RX.CTU: PUSHJ P,SCNPOS ;Get position
SKIPE T2,READQ ;Read request?
JRST [MOVE T2,R.COUNT(T2) ;Yes, use this count
JRST RX.CCU ] ;Do it
SKIPN T2,XUNREQ ;Get request
JRST CPOPJ1 ;None, ignore these special chars
MOVE T2,R.COUNT(T2) ;Get count
RX.CCU: CAILE T1,(T2)
JRST CPOPJ1 ;Return
CAIE P1,.CHCNU ;Control-U?
JRST RX.CTR ;Maybe ^R
PUSHJ P,DOCTU
RX.CU1: PUSHJ P,RX.CNC ;Count ^Cs
TXNE F,F$PALL ;Shouldn't be here if this is set, but
JRST RX.CU3 ;See about request
SKIPN P4,READQ ;Read request?
JRST RX.CU2
PUSHJ P,XPROMT ;Output the prompt string
PJRST XCRURB ;...
RX.CU2: SKIPN P4,XUNREQ ;No, unsolicited request?
PJRST XCRURB ;No request
PJRST RX.DUN ;Re-set unsolicited stuff
RX.CU3: SKIPN P4,READQ ;Prompt request?
POPJ P,
PJRST XPROMT ;Output and return
RX.CTR: CAIE P1,.CHCNR ;Control-r?
JRST RX.RUB ;Must be rubout
MOVEI T1,RX.CR1 ;For outputting the prompt
PUSHJ P,DOCTR
PJRST XCRURB ;See about flags
RX.CR1: SAVE4 ;Save the Ps
SKIPE P4,READQ ;Request?
PJRST XPROMT ;Finish it
POPJ P,
RX.RUB: PUSHJ P,DORUB ;Do the rubout
PUSHJ P,RX.CNC ;Count ^Cs in buffer
FALL XCRURB ;See about flags
SUBTTL RSX Support -- Check about ^U/^R/<RUB> processing
XCRURB: TDZA T1,T1 ;Flag to set
XCRUR1: SETO T1, ;Don't set
TXNN F,F$READ ;Read pending?
JRST XURURB ;No
TXNN F,F$PALL ;Passall?
SKIPN ICHCNT ;Any chars?
JRST XURURB ;No
XSRURB: JUMPN T1,CPOPJ ;Don't change it
MOVEI T1,<1B<.CHCNR>!1B<.CHCNU>> ;Set to watch them
AND T1,LMASK ;Unless he wanted them
XORI T1,<1B<.CHCNR>!1B<.CHCNU>> ;..
IORM T1,CHRTAB
MOVEI T1,1B31 ;<RUB> in LMASK
TDNE T1,LMASK+3 ;Set there?
TRO T1,1B19 ;Yes, set here
TRC T1,1B19!1B31 ;31 off, 19 as decided
IORM T1,CHRTAB+3
PJRST STRURB ;Set and return
POPJ P, ;Return
XURURB: MOVEI T1,<1B<.CHCNR>!1B<.CHCNU>> ;Clear in CHRTAB
ANDCAM T1,CHRTAB
MOVEI T1,1B19 ;Clear rubout too
ANDCAM T1,CHRTAB+3
MOVE T3,RXDMSK ;Default count
SKIPE T1,READQ ;In case a request
MOVE T3,R.COUNT(T1) ;Get count from there
PJRST UNRURB ;Cancel unless in mask
SUBTTL RSX Support -- Count ^Cs
;Here to set XSPCNT correctly. Uses T1-T4
;Note that no interrupt which can affect XSPCNT should be allowed to happen
RX.CNC: SAVE4 ;Save the Ps
PUSHJ P,SCNINI
SETZM XSPCNT ;Init count
RX.CNL: PUSHJ P,SCNCHR
POPJ P, ;Done if no more characters
CAIN P1,.CHCNC ;Is it the magic character?
AOS XSPCNT ;Count it if so
JRST RX.CNL
SUBTTL RSX Support -- Set TTY: up
;Enter with P4 pointing to header block
;Note this should only be called for "normal" read requests
RX.STT: MOVSI T1,RM.RNE ;No-echo?
TDNN T1,R.MOD(P4) ;?
TXZA F,<F$NEC> ;Echo, clear the bit
TXO F,<F$NEC> ;Set it
HRLI T1,RXDMSK+1 ;Assume default
SKIPE R.MASK(P4) ;Is there?
HRLI T1,R.MASK(P4) ;Yes
HRRI T1,IMASK+1 ;Put it in
BLT T1,ENDMSK
MOVE T1,[IMASK+1,,LMASK] ;Set logical mask
BLT T1,ELMASK ;..
MOVSI T1,RM.RTC ;Terminate on control?
TDNN T1,R.MOD(P4) ;?
JRST RX.ST2 ;No
MOVEI T1,37
ANDM T1,CHRTAB
MOVEI T1,1B19
ANDCAM T1,CHRTAB+3
SETZ T1,
JRST RX.ST3
RX.ST2: MOVX T1,<1B<.CHCNC>!1B<.CHCNO>!1B<.CHCNX>>
IORM T1,CHRTAB
RX.ST3: TXO T1,1B<.CHCNH> ;Be sure see this too
IORM T1,IMASK+1
MOVE T1,R.COUNT(P4) ;Set the default field width
MOVEM T1,IMASK
TXNN F,F$TMR ;See if timeouts are involved
JRST RX.ST4 ;Continue
MOVEI T1,1 ;Then field must be only one
MOVEM T1,IMASK
RX.ST4: SKIPN T1,XSCREQ ;Read single active?
JRST RX.ST6 ;No, skip some
HLRZ T1,R.MOD(T1) ;Get modifiers
TRNN T1,RM.OSA ;Want ^C?
JRST RX.ST6 ;Set TTY:
MOVX T1,1B<.CHCNC> ;Be sure in mask
IORM T1,IMASK+1
RX.ST6: PUSHJ P,TTYSST ;Set up TTY:
PJRST FRCTTI ;And wake up
SUBTTL RSX Support -- handle timed requests
;Call with protocol header pointed to by P4
RX.STM: TXO F,F$TEX ;Be sure it's set
MOVEI T1,RX.TMR ;Routine to handle
MOVEM T1,OSTMR ;Set the routine
HLRZ T1,R.IDENT(P4) ;Get identifier
MOVEM T1,TMRSEQ ;Save to be sure right req
MOVE T1,R.TIME(P4) ;Get the time
PITMR. T1,
JFCL
POPJ P,
;Routine to actually handle requests:
RX.TMR: SKIPN P4,READQ ;Any request
JRST RX.CTS ;See if single-character timeout
HLRZ T1,R.IDENT(P4)
MOVSI T2,RM.RTM ;Check ID and timer flag, in case SSC
CAMN T1,TMRSEQ ;Right sequence number?
TDNN T2,R.MOD(P4) ;Single characters maybe
JRST RX.CTS ;No time-out here, check single chars
PJRST RX.RDS ;Read "satisfied"
RX.CTS: SKIPN P4,XSCREQ ;Single characters request?
POPJ P,
HLRZ T1,R.IDENT(P4) ;Be sure ID matches
CAME T1,TMRSEQ ;?
POPJ P, ;Doesn't match
TXO F,F$TEX ;Timeout expired
JRST RX.SSS ;Single satisfied
SUBTTL RSX Support -- Write data
RX.WRT: PUSHJ P,RSX.EH ;Eat common header
PUSHJ P,CHKCTO ;Check status of ^O
MOVE T1,RSXSVF ;Get old flags
XOR T1,F ;Get difference
TXNE T1,F$CTO ;Has state changed?
PUSHJ P,RX.CO1 ;Yes, inform the host
TXNE F,F$CTO ;Control-O in effect?
JRST RX.WR1 ;Yes
PUSHJ P,GETWRD ;Get read count (should be zero)
PUSHJ P,GETWRD ;Get write count
JUMPE T1,RX.WR1 ;No real bytes
MOVEI T4,(T1) ;Transfer ACs
SETZM TOFLGS ;Assume normal write
MOVSI T1,RM.WBT ;Breakthrough type?
TDNN T1,R.MOD(P4) ;?
JRST RX.WR0 ;No
MOVEI T1,($TOOIN)
MOVEM T1,TOFLGS
RX.WR0: PUSHJ P,RBYTEC ;Else get a byte
CAIL T1," " ;Printing?
TXZA F,F$CLF ;No, cancel line feed
CAIN T1,.CHLFD ;Line feed?
TXZN F,F$CLF ;Supposed to cancel one?
PUSHJ P,OUTTTY ;Output character to TTY:
SOJG T4,RX.WR0 ;For all characters
PUSHJ P,DOOUT1
SKIPN TOFLGS
PUSHJ P,WATDEQ
SETZM TOFLGS
RX.WR1: MOVSI T1,RM.NWC ;Want write complete?
TDNE T1,R.MOD(P4) ;?
JRST RX.WR4 ;No
MOVEI T1,RF.WTD ;Write function
PUSHJ P,RSX.BH ;Build a header
PUSHJ P,XMTMSS ;Send ACK
RX.WR4: MOVEI T1,(P4)
MOVEI T2,REQSIZ
PJRST CORFRE ;Free block and return
SUBTTL RSX Support -- Eat common header
;Returns with digested header block (R.xxxx) pointed to by P4
RSX.EH: MOVEI T1,REQSIZ
PUSHJ P,CORGET
MOVEI P4,(T1) ;Point P4 at it
PUSHJ P,RBYTEC ;Get modifiers
HRLM T1,R.MOD(P4) ;Store them
PUSHJ P,RBYTEC ;Get flags
TRNE T1,RM.CAO ;Cancel ^O?
PUSHJ P,RX.CCO ;Clear ^O
HRRM T1,R.FLAG(P4) ;Also flags
PUSHJ P,GETWRD ;Get status and identifier
LSH T1,-^D8 ;Put ID in low order byte
HRLM T1,R.IDENT(P4) ;Save it
PJRST RBYTEC ;Eat reserved byte and return
SUBTTL RSX Support -- Build header for output message
;Enter with T1=function code to build header for; P4=digested header block
RSX.BH: NETOCH T1 ;Put function in header
HLRZ T1,R.MOD(P4) ;Get modifiers
ANDCMI T1,RM.RTM ;Default didn't time out
NETOCH T1
SETZ T1, ;Flags
NETOCH T1
MOVEI T1,XS.SFC ;Set Normal function
NETOCH T1
HLRZ T1,R.IDENT(P4) ;Get identifier
SOSGE OBFCTR
JRST [PUSHJ P,NETQUE
JRST .-1 ]
IDPB T1,OBFPTR ;Do NETOCH by hand
POPJ P, ;So is a few less instructions
SUBTTL RSX Support -- Queue read request
;Enter with RSX digested header block in P4
XQREAD: MOVEI T1,READQ-R.LINK
MOVEI T2,-1 ;So can check queue
XQLP: TDNN T2,R.LINK(T1) ;Anything there?
JRST XQHAV ;Done
HRRZ T1,R.LINK(T1)
JRST XQLP
XQHAV: HRRM P4,R.LINK(T1)
POPJ P, ;Return
SUBTTL VMS Support -- Protocol definitions
PLM
;+
;.hl 2 VMS Support
; VMS also uses a message protocol. It is perhaps most important
;for VMS that the user understand the internals of the remote operating
;system. This is due to the fact that the program which communicates
;with VMS becomes, in essence, an equivalent of TTDRIVER.
; A further peculiarity of VMS is the "free line feed" logic. This
;is part of VMS such that the user doesn't over-write a just-typed
;out line with echoed characters. The basic rules are:
;.list 1
;.le
;If the last write or broadcast operation ended with a <CR> not followed
;by a <LF> (remember that a VMS "record" is <LF>data<CR>), then the
;next read operation generates a "free" line feed. If there is a leading
;line feed in the prompt, that is the "free" line feed.
;.le
;If the last read operation was terminated by <CR>, then <CR> echoes
;as <CR><LF> and the "free" line feed is "canceled" for the next read
;request (assuming no writing is done in between). This means if
;there is a leading <LF> in the prompt, it is eaten and not displayed.
;.le
;The above is not through for any flavour of physical only I/O (IO$__READPBLK,
;IO$__READALL, PASSALL mode, etc.).
;.end list
; Reference documents:
;.list 1
;.le
;^&VAX/VMS Network Command Terminal Protocol\& - This memo by Scott G. Davis
;describes the pre-release 3.x protocol.
;.le
;^&VMS V3.0 Remote Terminal Protocol\& - This memo by Darrell Duffy
;specifies the updates to the above memo for VMS V3.x.
;.le
;^&VAX/VMS I/O Users' Guide\& - Since the VAX expects NRT to be the equivalent
;of the terminal driver, it is useful to know what is expected of a terminal
;driver.
;.end list
;-
MLP
;Digested header block:
PHASE 0
V.LINK: BLOCK 1 ;Link to next request
V.IDENT:BLOCK 1 ;Identifier for this request
V.MOD: BLOCK 1 ;Modifiers for this request
V.COUNT:BLOCK 1 ;Request byte count for this request
V.TIME: BLOCK 1 ;Timeout for this request
V.PROM: BLOCK 1 ;Pointer to prompt string and size
V.STAT: BLOCK 1 ;Status we want, if request doesn't complete
V.MASK: BLOCK 11 ;One word length + enough for 256 bits
VRQSIZ==.-V.LINK ;Size of digested request block
DEPHASE
; op code modifiers
; READ
CVTLOW==400 ;IO$M_CVTLOW
DISMBX==2000 ;IO$M_DSABLMX
NOECHO==100 ;IO$M_NOECHO
NFILTR==1000 ;IO$M_NOFILTR
PURGE==4000 ;IO$M_PURGE
REFRSH==2000 ;IO$M_REFRESH
TIMER==200 ;IO$M_TIMED
TNOEKO==10000 ;IO$M_TRMNOECHO
ESCAPE==40000 ;IO$M_ESCAPE
TYPAHD==100 ;IO$M_TYPEAHDCNT
;Internal modifiers (left half of V.MOD)
VM.RAL==1B0 ;Readall, MUST BE SIGN BIT
; WRITE
CANCTRLO==100 ;IO$M_CANCTRLO
ENAMBX==200 ;IO$M_ENABLMBX
NFORMT==400 ;IO$M_NOFORMAT
; SETMODE
CC=400 ;IO$M_CTRLCAST
CY==200 ;IO$M_CTRLYAST
HANGUP==1000 ;IO$M_HANGUP
OBAND==2000 ;IO$M_OUTBAND
INCLUDE==10000 ;IO$M_INCLUDE
MODEM==2000 ;IO$M_SET_MODEM
; Status codes returned
NORMAL==1 ;SS$_NORMAL
TIMEOUT==1054 ;SS$TIMEOUT
ABORTS==54 ;SS$_ABORT
PARTES==774 ;SS$_PARTESCAPE
BADESC==74 ;SS$_BADESCAPE
CONTRC==3121 ;SS$_CONTROLC
CONTRY==3021 ;SS$_CONTROLY
CANCEL==4060 ;SS$_CANCEL
HNGUPS==1314 ;SS$_HANGUP
CONTRO==3011 ;SS$_CONTROLO
ILLFNC==364 ;SS$_ILLIOFUNC
; Modifiers for attention code
RA.UNS==0 ;Unsolicited data
RA.HUP==1 ;Modem hangup
RA.CTC==2 ;Control C
RA.CTY==3 ;Control Y
RA.RSV==4 ;Reserved
RA.BRD==5 ;Broadcast mailbox
RA.OUB==6 ;Out-of-band completion
;Miscellaneous constants:
MTMBRD==^D83 ;MSG$_TRMBRDCAST
; VAX Terminal symbols
DC$TERM==102 ;Generic terminals
DT$L120==41 ;LA120
DT$L180==3 ;LA180
DT$L36==40 ;LA36
DT$TTY==0 ;Generic hard copy
DT$V52==100 ;VT52
DT$V100==140 ;VT100
DT$V5X==100 ;Generic CRT
DT$V55==101 ;VT55
DT$101==141 ;VT101
DT$102==142 ;VT102
DT$105==143 ;VT105
DT$V125==144 ;VT125
DT$V131==145 ;VT131
DT$132==146 ;VT132
DT$L100==45 ;LA100
DT$LPQ2==46 ;LPQ02
DT$VT05==1 ;VT05
DT$VK100==2 ;VK100 (GIGI)
; Terminal Definitions
TPSAL==1 ;TT$M_PASSALL
TNEKO==2 ;TT$M_NOECHO
TNTPH==4 ;TT$M_NOTYPEAHEAD
TESCP==10 ;TT$M_ESCAPE
THSYN==20 ;TT$M_HOSTSYNC
TTSYN==40 ;TT$M_TTSYNC
TLOWR==200 ;TT$M_LOWER
TMTAB==400 ;TT$M_MECHTAB
TWRAP==1000 ;TT$M_WRAP
TCRLF==2000 ;TT$M_CRFILL
TLFFL==4000 ;TT$M_LFFILL
TSCOP==10000 ;TT$M_SCOPE
TRMOT==20000 ;TT$M_REMOTE
THSCR==40000 ;TT$M_HOLDSCREEN
T8BIT==100000 ;TT$M_EIGHTBIT
TMDIS==200000 ;TT$M_MBXDSBL
TNBCS==400000 ;TT$M_NOBROADCAST
TRSYN==1,,0 ;TT$M_READSYNC
TMFRM==2,,0 ;TT$M_MECHFORM
THDUP==4,,0 ;TT$M_HALFDUP
;TT2 defs:
T2BCM==20 ;Broadcast mailbox
T2DCRT==4000000000 ;TT2$M_DECCRT
T2ACRT==100000000 ;TT2$M_ANSICRT
; Misc terminal flags
TAPAR==40 ;TT$M_ALTRPAR
TPAR==100 ;TT$M_PARITY
TODD==200 ;TT$M_ODD
TSCRP==100 ;TT$M_SCRIPT
TSPAG==10 ;TT$S_PAGE
TMPAG==37700,,0 ;TT$M_PAGE
;I/O function codes ($IODEF)
VF.WPH==13 ;These are all writes
VF.WLB==40
VF.WVB==60
VF.RPH==14 ;these are all reads
VF.RLB==41
VF.RVB==61
VF.RAL==72 ;READALL
VF.RPR==67 ;Read with prompt
VF.RPA==73 ;READALL with prompt
VF.STC==32 ;Set characteristics
VF.STM==43 ;Set mode
VF.SNC==33 ;Sense characteristics
VF.SNM==47 ;Sense mode
VF.ACC==70 ;ACPcontrol (Kill)
VF.BCS==177777 ;Broadcast
;Return Opcodes
VR.ATT==-1 ;Attention
VR.END==-2 ;I/O complete
VR.ERR==-3 ;Error
SUBTTL VMS Support -- VAX/VMS network input routine
VMS.NT: PUSHJ P,GETWRD ;Get a word (should be there!)
PUSH P,T1 ;Save function
MOVEI T1,VRQSIZ ;Get length of block
PUSHJ P,CORGET ;Get it
MOVEI P4,(T1) ;Copy addr of request block to P4
PUSHJ P,VMS.EH ;Eat common header
POP P,T1 ;Restore function
MOVEI P1,VMSFNC ;Point to QIO table
PUSHJ P,FNDFNC ;Find the function in the table
ERR IVQ,<Illegal VMS QIO function>
VM.ETI: TXZN F,F$NEOM ;If we encountered EOM, then
POPJ P, ;It is OK to return
PUSHJ P,NSPIN ;Else eat to EOM
JRST NSPERR ;Oops
JRST VM.ETI ;Eat all input
SUBTTL VMS Support -- VMS TTY: input routine
VMS.TT:
PUSHJ P,VM.SCT ;Set CHRTAB
JRST VMS.NS ;Nothing is special
PUSHJ P,VM.CHO
PUSHJ P,VMS.OB ;Yes send out of band first
VMS.NS: SKIPE P4,SENSEQ ;Sense pending?
PUSHJ P,VM.SNC ;Finish it up
SKIPE P4,READQ ;Is there a read queued?
JRST [TLO P4,400000 ;Flag here from TTY
PJRST CHKREQ ] ;Check the request
VMS.N1: PUSHJ P,SCNSPC ;Scan for "special" characters
JRST VMS.N5 ;See about treating them
VMS.N3: SKIPE ICHCNT ;Any characters?
PJRST VMS.UN ;Tell him there's data
PJRST VCRURB ;Check setting of F$RUB
VMS.N5: PUSHJ P,VMS.SC ;Treat them
JRST VMS.N1 ;Check again
PUSHJ P,CONSCN ;See if more special chars
JRST VMS.N5 ;Yes
JRST VMS.N3 ;No, ignore the ones we saw
SUBTTL VMS Support -- VMS.DA - Recieve VMS data
VMS.PW: MOVEI T1,NFORMT ;Noformat bit
IORM T1,V.MOD(P4) ;Set it
VMS.DA:
MOVE T1,V.MOD(P4) ;Get modifiers
TRNE T1,CANCTRLO ;Cancel ^O effect?
PUSHJ P,CLRCTO ;Yes
PUSHJ P,CHKCTO ;See what the setting is
TRNE T1,ENAMBX ;Want unsolicited now?
PUSHJ P,VM.SUN ;Set up unsolicited stuff
TXNE F,F$CTO ;Is ^O in effect?
JRST VM.CTO ;Toss the write then
TXNN F,F$PALL ;Passall?
TRNE T1,NFORMT ;Or NOformat?
TXOA F,F$PIM ;Set PIM
JRST VM.DA1 ;OK to use ASCII
PUSHJ P,TTYSST ;Set PIM (wait for pending output to complete)
VM.DA1: PUSHJ P,GETLWD ;Get count
MOVEI P1,(T1) ;Save for later
PUSHJ P,GETWRD ;Get first and second bytes of carcon
ANDI T1,377 ;Save only carcon byte
JUMPN T1,VM.FRT ;FORTRAN carriage control
PUSHJ P,RBYTEC ;Get prefix carcon byte
PUSH P,T1
PUSHJ P,RBYTEC ;Get postfix control
EXCH T1,(P) ;Save postfix, get prefix
VM.DCC: PUSHJ P,VM.CCN ;Do the control
PUSHJ P,VMS.WR ;Write the record out (P1=count)
POP P,T1 ;Get postfix control back
PUSHJ P,VM.CCN ;Do the control
TXZE F,F$PIM ;Clear PIM
PUSHJ P,TTYSST ;Change back
VM.DC2: MOVE T1,V.MOD(P4) ;Get modifiers
TRNE F,REFRSH ;Refresh?
PUSHJ P,VM.CRF ;Need to refresh
PJRST VMS.AK ;ACK the request and return
;Here to interpret a Fortran carriage control character
VM.FRT: DMOVE T3,[ 2 ;2 <LF>s
200!.CHCRT] ;<CR> for postfix
CAIN T1,"0" ;Is it double-space?
JRST VM.FR1 ;Yes, process
DMOVE T3,[200!.CHFFD ;Form-feed prefix
200!.CHCRT] ;<CR> postfix
CAIN T1,"1" ;Eject?
JRST VM.FR1 ;Yes
DMOVE T3,[ Z ;Null prefix
200!.CHCRT] ;<CR> postfix
CAIN T1,"+" ;If overprint control
JRST VM.FR1
DMOVE T3,[ 1 ;1 <LF>
200!.CHCRT] ;<CR> postfix
CAIN T1,"$" ;Unless prompt sequence
DMOVE T3,[ 1 ;1 <LF>
Z ] ;Null postfix
VM.FR1: PUSHJ P,GETWRD ;Eat next two bytes
MOVEI T1,(T3) ;Prefix to T1
PUSH P,T4 ;Postfix to stack
JRST VM.DCC ;Go do it
SUBTTL VMS Support -- Routine to do carriage control
;Call with carriage control byte in T1
VM.CCN: JUMPE T1,CPOPJ ;Nothing to do
TRZE T1,200 ;<LF> count?
JRST [CAIN T1,.CHCRT ;<CR>
TXOA F,F$FLF ;Yes, may need free line feed
TXZ F,F$FLF ;Don't want free <LF>
JRST OUTTTY ] ;...
TXZ F,F$FLF ;Don't need free line feed if already
TXZE F,F$CLF ;Supposed to cancel a line feed?
SOJLE T1,CPOPJ ;Yes, exit if only one to do here
MOVEI T2,(T1) ;Move count to T2
MOVEI T1,.CHCRT ;Do one <CR>
PUSHJ P,OUTTTY ;(don't need more than one)
MOVEI T1,.CHLFD ;Get a line feed
VM.LFS: PUSHJ P,OUTTTY
SOJG T2,VM.LFS ;Do them
POPJ P, ;Then return
SUBTTL VMS Support -- Routine to actually write the record
;Character count in P1, zeroed on return
VMS.WR: JUMPE P1,CPOPJ ;If nothing to do
SETO P2, ;Flag first time through
VM.WR1: PUSHJ P,RBYTEC ;Get a byte from the record
CAIE T1,.CHCRT ;<CR>
TXZA F,F$FLF ;No, don't want free line feed
TXO F,F$FLF ;Flag may want it
AOJG P2,VM.WR2 ;Don't worry about this if not first time
TXNN F,F$CLF ;Cancel on?
JRST VM.WR2 ;No, just ignore
CAIN T1,.CHCRT ;If <CR>...
SOJA P2,VM.WR3 ;Just ignore
CAIN T1,.CHLFD ;A line feed?
TXZA F,F$CLF ;Yes, we already did it
VM.WR2: PUSHJ P,OUTTTY ;Output the character
VM.WR3: SOJG P1,VM.WR1
TXZ F,F$CLF ;Real data, don't cancel any free line feeds
POPJ P, ;Return with characters output
SUBTTL VMS Support -- Check to see if REFRESH needed
VM.CRF: PUSH P,P4
SKIPN P4,READQ ;Is there a request
JRST VM.CF2
PUSHJ P,CHKPRM ;Do the prompt string
MOVE CX,[2,,T1] ;Force out the rescan buffer
MOVE T1,[SIXBIT/.TYPE/]
MOVE T2,TTYUDX
FRCUUO CX,
JFCL ;Ignore; they fail randomly anyway
VM.CF2: POP P,P4
POPJ P,
SUBTTL VMS Support -- Read and Read with prompt
VMS.PA: SKIPA T2,[-1] ;Prompt
VMS.RA: SETZ T2,
MOVSI T1,(VM.RAL) ;Set special mode bit for us
IORM T1,V.MOD(P4) ;Turn it on
JRST VM.RED
VMS.PD: SKIPA T2,[-1]
VMS.RD: SETZ T2,
VM.RED: MOVEM T2,V.PROMPT(P4) ;Set prompt or not flag
PUSHJ P,GETLWD ;Get a longword count for chars
MOVEM T1,V.COUNT(P4) ;Save count
PUSHJ P,GETLWD ;Get time-out
MOVEM T1,V.TIME(P4) ;Save timeout
PUSHJ P,RBYTEC ;Get a byte
JUMPE T1,NOMSK ;No terminator mask
MOVE T4,T1 ;Count of bytes to get
MOVEM T1,V.MASK(P4) ;Flag there is a mask
MOVEI T3,V.MASK+1(P4) ;Point to mask word
HRLI T3,(POINT 8,,) ;Make byte pointer to it
PUSHJ P,CPYMSK ;Set the mask copy
NOMSK: SKIPE V.PROMPT(P4) ;Prompt?
SKIPGE IBFCNT ;Data for one?
JRST NOPMT ;No prompt requested or no data
PUSHJ P,GETWRD ;Get length of string
SKIPN P1,T1 ;Copy to P1 and see if there is any string
JRST NOPMT
CPYPMT: SKIPN P1,T1 ;Copy to P1, is it non-zero?
POPJ P, ;No
LSHC T1,-2
TLNE T2,600000 ;Remainder?
AOJ T1,
PUSHJ P,CORGET ;Get the block
MOVEM T1,V.PROM(P4) ;Point to prompt string
HRLM P1,V.PROM(P4) ;Save number of characters
HRLI T1,(POINT 8,,) ;Byte pointer to data
MOVE T2,T1 ;But don't keep it in T1
PUSHJ P,RBYTEC ;Get a byte
IDPB T1,T2 ;Save
SOJG P1,.-2 ;For all bytes
TRNA ;There really is a prompt
NOPMT: SETZM V.PROMPT(P4) ;There really isn't a prompt
SKIPE READQ ;Read already queued?
JRST VQREAD ;Yes, just queue this request
NVRDRQ: PUSHJ P,CLRCTO ;Clear ^O
MOVX T1,VM.RAL ;Physical type request?
TXNE F,F$PALL ;Physical?
TXZA F,F$FLF ;Skip one useless instruction
TXNN F,F$CLF ;Cancel a free line feed?
TDNE T1,V.MOD(P4) ;(No, physical)?
TXZ F,F$FLF ;Yes, no formatting
MOVE T1,V.MOD(P4) ;Get modifiers
MOVE T2,VMTTCH+1 ;Get terminal characteristics
TRNN T2,TESCP ;Set escape recognition here?
TRNE T1,ESCAPE ;Want escape processing?
TXOA F,F$ESC ;Yes
TXZ F,F$ESC!F$ESA ;Clear all traces
TRNE T1,DISMBX ;Disable unsolicited?
TXZ F,F$UAST ;Yes
TRNE T1,PURGE ;Purge typeahead?
PUSHJ P,FLSTAH ;Flush type-ahead
PUSHJ P,CHKPRM ;See if have to do a prompt
MOVEI T1,NOECHO ;Noecho?
TDNN T1,V.MOD(P4) ;..?
TXNN F,F$FLF ;Echoing, need free line feed?
JRST VM.NFL ;no
MOVEI T1,.CHLFD
PUSHJ P,OUTTTY ;Output
PUSHJ P,DOOUT1 ;...
VM.NFL: HRRZM P4,READQ ;This is the current request
TXO F,F$READ ;Read outstanding
SETOM UNSCNT ;Allow unsolicited messages
MOVEI T1,TIMER ;Timed request?
TDNE T1,V.MOD(P4) ;?
PUSHJ P,VM.STM ;Yes, set a timer request
PUSHJ P,VM.STT ;Set TTY: up
;Enter here on TTY: I/O complete to see if we can now satisfy this request
;Enter with P4 pointing to digested QIO block and sign bit set
;if from TTY: service
CHKREQ:
PUSHJ P,CLRCTO ;Clear ^O
MOVEM P4,READQ ;Store request
CHKRQ1: PUSHJ P,SCNSPC ;Check for special characters
JRST VM.CRS ;See about special characters
CHKRQ2: MOVE P4,READQ ;Get request
MOVE T1,ICHCNT ;Any characters?
TLZN F,(F$BRK) ;Break?
CAML T1,V.COUNT(P4) ;Enough characters input to satisfy?
JRST VM.RDS ;Satisfied
TXZE F,F$TEX ;Timeout expiration?
PJRST FRCTTI ;Give it one more shot
SKIPN V.STAT(P4) ;Set a status?
JRST VQREAD ;Nope, queue the read
VM.RDS: SETOM LICHCT ;Be sure we output ^H next time
MOVEI P2,($TOOIN!$TOICL)
MOVEM P2,TOFLGS
TXZ F,F$ESA ;Be sure zapped
PUSHJ P,VMS.BH ;Build data header
PUSH P,OBFPTR ;Save where iosb goes
NETALC ^D8+2 ;Skip over IOSB and count
MOVN P2,V.COUNT(P4) ;Get character count
HRLZI P2,(P2) ;Make aobjn ptr
MOVE P3,V.MOD(P4) ;Get the modifiers
SETZM BRKSIZ ;Clear size of break string
JUMPE P2,VM.RDZ ;**Zero length read**
JUMPG P2,[MOVE P1,V.STAT(P4) ;Get status desired
JRST VM.RD0 ] ;And complete
VM.RDL: PUSHJ P,INCHR ;Get a character
JRST [SKIPN P1,V.STAT(P4) ;Get status if set (TIMEOUT)
MOVEI P1,TIMEOUT ;?
TLZ P2,400000 ;Be sure don't do terminator stuff
JRST VM.RD0] ;And finish it
CAMN T1,ESCCHR ;Escape character?
SOS BRKNUM ;One less break to ignore
TRNN P3,CVTLOW ;Convert lower case?
JRST VM.NLC ;No, don't bother
CAIL T1,"a" ;Is it lower case?
CAILE T1,"z" ;?
TRNA ;No
TRZ T1,<"a"-"A"> ;Convert if it is
VM.NLC: NETOCH T1
PUSHJ P,CHKBR1 ;See if it's a break character
JRST VM.RDD ;Read done if this is break
TXNE F,F$ESA ;Escape sequence active?
SOJA P2,VM.RDQ ;Yes, don't count as part of string
TLNN P4,400000 ;From TTY: service?
TRNE P3,NOECHO ;No (type-ahead), is this no echo?
TRNA ;Yes or yes, don't echo
PUSHJ P,OUTTTY ;Output character if no
VM.RDQ: AOBJN P2,VM.RDL ;Loop for all chars
VM.RDZ: TXNE F,F$ESA ;Is an escape still active?
SKIPA P1,[PARTES] ;Flag it
VM.RDD: MOVEI P1,NORMAL
TXZE F,F$BAD ;Bad escape sequence?
MOVEI P1,BADESC ;Yes
VM.RD0: MOVE T4,OBFPTR ;Get current output pointer
EXCH T4,(P) ;Get pointer to IOSB
EXCH T4,OBFPTR ;Force PUTWRD to put things in the right place
MOVEI T4,^D8+2 ;Account for stuff already gone
ADDM T4,OBFCTR
PUSHJ P,PUTWRD ;Put it in
MOVEI P1,(P2) ;Number of characters in string
PUSHJ P,PUTWRD ;Put it in
JUMPGE P2,[SETZ P1,
PUSHJ P,PUTLWD ;Put it in
SKIPN V.COUNT(P4) ;Zero character read?
JRST VM.RD2 ;No characters
LDB T1,OBFPTR ;Get last character output
TXZ F,F$CLF!F$FLF ;Clear flags
CAIN T1,.CHCRT ;<CR>
TXO F,F$FLF ;Yes, might need this
JRST VM.RD2 ] ;And finish up
HLRZ T1,BRKCHR ;Break char to T1 for echoing
MOVEI P1,(T1) ;Get the break character
PUSHJ P,PUTWRD ;Put it in
HRRZ P1,BRKSIZ ;Size of the break character
ADDI P2,(P1) ;Include in count
PUSHJ P,PUTWRD ;And it too
TXNE F,F$ESC ;Escape sequence?
CAIG P1,1 ;Yes, was this terminated by such?
JRST VM.RDW ;No
CAIN P1,(P2) ;Only the break?
JRST VM.RD2 ;Yes, don't change F$CLF
VM.RDW: SKIPE V.COUNT(P4) ;If count is non-zero, then
TXZ F,F$FLF!F$CLF ;Clear these too
TRNE P3,TNOEKO!NOECHO ;Various flavour of no-echo?
JRST VM.RD2 ;Yes, observe them
CAIE T1,.CHCNZ ;Cancel free <LF> on ^Z
CAIN T1,.CHCRT ; or <CR>?
TXO F,F$CLF ;Cancel free line feed
MOVE T4,[-VBKLEN,,VBKTAB]
PUSHJ P,EKOBRK ;Try and echo it
VM.RD2: MOVEI P1,(P2) ;Total # of chars in record
PUSHJ P,PUTWRD ;Put it in
POP P,OBFPTR ;Restore old byte pointer
VM.FNR: ;Here to finish a read request
;(^C/^Y also come here)
TXZ F,F$RALL!F$ESC!F$FRC ;No readall, no type-ahead echo
TXZE F,F$IOQ
PUSHJ P,FRCTTO
SETZM TOFLGS ;Clear the buffer flags
PUSHJ P,XMTMSS ;Send the message
MOVE T1,V.LINK(P4) ;Get next
HRRZM T1,READQ ;It is now first
VM.RD3: SKIPN T1,V.PROM(P4) ;Deallocate any prompt block
JRST VM.RD4 ;None
HLRZ T2,T1 ;Get size
LSHC T2,-2 ;Convert to words
TLNE T3,600000 ;Remainder?
AOJ T2,
HRRZI T1,(T1)
PUSHJ P,CORFRE
VM.RD4: MOVEI T1,(P4)
MOVEI T2,VRQSIZ ;Free cor block
PUSHJ P,CORFRE ;Free the core block
PUSHJ P,VCRUR1 ;Check F$RUB
SKIPE P4,READQ ;Is there another request ready?
JRST NVRDRQ ;New VAX read request
TXZ F,F$READ!F$RUB ;No read request outstanding
TXNE F,F$UAST ;Want unsolicited?
PJRST VM.SUN ;Yes
PUSHJ P,TTYSST ;Be sure no-echoed
PJRST FRCTTI ;And a look
VM.CRS: PUSHJ P,VMS.SC ;Handle the special character first
JRST VM.CS4 ;See if still a request
PUSHJ P,CONSCN ;See if more characters
JRST VM.CRS ;Yes, see about them
JRST CHKRQ2 ;Continue processing
VM.CS4: SKIPE P4,READQ ;Is there still a request?
JRST CHKRQ1 ;Yes
JRST VCRURB ;See if need to clear bits
SUBTTL VMS Support -- Routine to output prompt
;Routine to output a prompt string if there is one
CHKPRM: SKIPN T4,V.PROM(P4) ;Is there one?
POPJ P, ;No
PUSHJ P,WATDEQ ;Wait for things to settle
PUSH P,TOFLGS ;Save the flags
MOVEI T3,($TOICL!$TOOIN) ;Form of echo
MOVEM T3,TOFLGS
HLRZ T3,T4 ;Get the character count
TXZ F,F$ESA!F$BAD ;Cancel these
HRLI T4,(POINT 8,,) ;Point to string
OUTPMT: ILDB T1,T4 ;Get character
TXNN F,F$ESC ;Escape processing?
JRST OUTPM1 ;No
TXZ F,F$BAD
PUSH P,T4 ;Gotta save those Ts
PUSH P,T3
PUSH P,T1
MOVEI CX,OUTPM0 ;In case it returns this way
PUSHJ P,CHKESC
TXO F,F$BRK
TRNA
OUTPM0: POP P,(P) ;Fix stack
POP P,T1
POP P,T3
POP P,T4
TXNE F,F$ESA!F$BRK ;Active or done?
JRST NOFLF3 ;Don't bother flags
OUTPM1: TRZE F,F$FLF ;Need to give free LF?
CAIN T1,.CHLFD ;Yes, is this a line feed?
JRST NOFLF2 ;Is <LF> or don't need
CAIE T1,.CHCRT ;Is it a <CR>?
JRST FLFA ;No, give <CR> then
MOVE T2,T4 ;Get byte pointer copy
CHKFLF: ILDB T1,T2 ;Get next character
CAIN T1,.CHLFD ;Is it a <LF>
JRST NOFLFA ;Yes, don't need one then
CAIN T1,.CHCRT ;Is it a <CR>?
JRST CHKFLF ;Yes, scan more
FLFA: MOVEI T1,.CHLFD ;Get a line feed
PUSHJ P,OUTTTY ;Output it
NOFLFA: LDB T1,T4 ;Get old character back
NOFLF2: TXNN F,F$CLF ;Cancel free line feed?
JRST NOFLF3 ;No
CAIN T1,.CHCRT ;Yes, if <CR> just toss
TXZA F,F$CLF ;Set bit to zero
CAIN T1,.CHLFD ;If this is a line feed
TXCA F,F$CLF ;Then clear bit and toss
TXZA F,F$CLF ;Don't cancel except in first
TRNA ;Proceed
NOFLF3: PUSHJ P,OUTTTY ;Output to TTY:
SOJG T3,OUTPMT ;Get next
NOPMT1: PUSHJ P,DOOUT1
POP P,TOFLGS ;Restore the flags
TXO F,F$IOQ ;Read is "active"
POPJ P,
SUBTTL VMS Support -- Break echo string table
VBKTAB: .CHCRT,,[BYTE (7)15,12] ;<CR>
.CHESC,,[ASCIZ/$/] ;<ESC>
.CHCNZ,,[ASCIZ/^Z
/] ;^Z
.CHTAB,,[ASCIZ/ /] ;<TAB>
VBKLEN==.-VBKTAB
SUBTTL VMS Support -- Routine to queue a read request for VMS
VQREAD: SKIPE ICHCNT ;Characters?
TXO F,F$IOQ ;Yes
TXO F,F$READ ;Set read request active
TLNN P4,400000 ;Clear sign bit
JRST VQRD1 ;Do other things
SETZM IMASK ;Go into character mode
PUSHJ P,CHKCTH ;See about ^H stuff
VQRD1: MOVEI T1,READQ-V.LINK ;Find the end of the queue
HRRZI T3,(P4) ;Right half only
FNDENV: SKIPN T2,V.LINK(T1) ;Is it here?
JRST ENVFND ;Found it
CAIN T3,(T2) ;Already queued?
JRST ENVFN1 ;Yes, but be sure TTY: kicked
MOVEI T1,(T2) ;Point ahead
JRST FNDENV ;And look there
ENVFND: HRRZM T3,V.LINK(T1) ;Make this last request
ENVFN1: CAMN T3,READQ ;Adding first request to queue?
PUSHJ P,FRCTTI ;Force TTY: if so
VQRD2: TXNE F,F$RALL!F$PALL!F$LEM ;Need to worry about editing?
JRST VQRD3 ;Nope
PUSHJ P,CHKLED ;Line editing to do?
POPJ P, ;Wait for it to happen then
VQRD3: TLNN P4,400000 ;From TTY: service?
PUSHJ P,EKOTAH ;No, do type-ahead
PUSHJ P,VCRURB ;Check this stuff
SKIPE IMASK ;Need to call TTYSST?
POPJ P,
PUSHJ P,TTYSST
PJRST FRCTTI ;Yes, do it
SUBTTL VMS Support -- Eat and store common header
VMS.EH: PUSHJ P,GETWRD ;Go get a VAX word (16 bits)
MOVE P1,T1 ;Get the word in P1
MOVEM P1,V.MOD(P4) ;Save
PUSHJ P,GETLWD ;Get a long word identifier
MOVEM T1,V.IDENT(P4) ;Save identifier
PJRST GETWRD ;get the unit number which is unimportant
;and return With Modifiers in P1, Ident in P2
SUBTTL VMS Support -- Handle Control-O
VM.CTO: PUSHJ P,VMS.BH ;Build header
MOVEI P1,CONTRO ;Say what happened
JRST VM.AK1 ;AK the message
SUBTTL VMS Support -- VMS.KI - Kill I/O
VMS.KI:
TLZ F,(F$CAST!F$UAST) ;Cancel ^Cs
SKIPN P1,READQ ;Point to queue
PJRST VM.AK2 ;Nothing to do
HRLI P1,READQ-V.LINK ;Predecessor
VM.KIL: MOVE T1,V.IDENT(P4) ;Ident he wants to kill
VM.CKI: CAMN T1,V.IDENT(P1) ;This identifier?
JRST VM.KI1
HRLI P1,(P1) ;Next in queue
HRR P1,V.LINK(P1) ;Link to next
TRNE P1,-1 ;Any more?
JRST VM.AK2 ;Nope
JRST VM.CKI ;Check it out
VM.KI1: MOVEI T1,(P4) ;Get this request
MOVEI T2,VRQSIZ ;Free it
PUSHJ P,CORFRE ;...
HRRZI P4,(P1) ;Point P4 at block
HRR P1,V.LINK(P1) ;Get successor to this
MOVSS P1 ;Predecessor,,successor
HLRM P1,V.LINK(P1) ;De-link from here
HRRZ T1,READQ ;Get the first request in the list
HRRZM P4,READQ ;We are now first
HRRZM T1,V.LINK(P4) ;First is now next
MOVEI P1,ABORTS ;Status
MOVEM P1,V.STAT(P4) ;Status to complete with
SETOM V.COUNT(P4) ;Flag not to complete
PJRST VM.RDS ;Finish it up
SUBTTL VMS Support -- VMS.AK - Write complete and Acknowledge
VMS.AK: ;Acknowledgements
SKIPN V.IDENT(P4) ;Is there an identifier?
JRST VM.AK2 ;No, don't AK then
PUSHJ P,VMS.BH ;Build header
MOVEI P1,NORMAL ;Give good return
;Enter here with P1 header built and P1 containing the I/O status
VM.AK1: PUSHJ P,PUTLWD
SETZ P1, ;Zap high order
PUSHJ P,PUTLWD ;Put it in
PUSHJ P,XMTMSS ;Send completion with no data
VM.AK2: MOVEI T1,(P4) ;Free the core block for the request
MOVEI T2,VRQSIZ
PJRST CORFRE ;Do it
SUBTTL VMS Support -- VMS.BH - Build Header
VMS.BH: SKIPN V.IDENT(P4) ;Get identifier (already shifted)
POPJ P, ;Return
MOVX P1,<BYTE (8) 0,0,377,VR.END> ;MOD,MOD,OP,OP
ROT P1,-4 ;Use the lower 4 bits
PUSHJ P,PUTLWD ;Put long word into buffer
MOVE P1,V.IDENT(P4) ;Get the identifier
SKIPGE P1 ;Do we have one for real?
SETZ P1, ;No, then store a zero
PUSHJ P,PUTLWD ;Put long word in buffer
SETZ P1, ;No unit
PJRST PUTWRD ;Put it in and exit
SUBTTL VMS Support -- VMS.IN - Initialization message
VMS.IN: TXZ F,F$READ ;No outstanding read yet
TXO F,F$NLF!F$UAST ;Don't want <LF>s on <CR>s
SETZM UNSCNT ;We are going to send an unsolicited message
SKIPGE T1,TTYTYP ;Get the type
SKIPA T4,[DT$TTY] ;Set TTY: then
HRRZ T4,VTPTB(T1)
DPB T4,[POINT 8,VMS$CF+3,^D15] ;Set the type
DPB T4,[POINT 8,VMTTCH,^D35-8]
MOVEI T2,20 ;Number of characters in pre-V3
SKIPN PROTMD ;If non-zero, V3 or later
JRST VM.IN0 ;Don't do V3 stuff
MOVEI T2,24 ;Size of characteristics in V3
JUMPL T1,VM.IN0 ;TTY
HLRZ T3,VTPTB(T1) ;Get the DEC/ANSI CRT characteristics
ASSUME T2ACRT,100000000
ASSUME T2DCRT,4000000000
DPB T3,[POINT 8,VMS$CF+5,^D31]
DPB T3,[POINT 8,VMTTCH+2,^D35-<3*8>]
VM.IN0: MOVEM T2,VMS$CF
HLRZ T1,TSVWID ;Get the width
DPB T1,[POINT 16,VMTTCH,^D35-^D16]
DPB T1,[POINT 8,VMS$CF+3,23]
ROT T1,-8 ;High order
DPB T1,[POINT 8,VMS$CF+3,31]
HLRZ T1,TSVLNB ;Get page size
DPB T1,[POINT 8,VMTTCH+1,^D35-^D24]
DPB T1,[POINT 8,VMS$CF+4,31]
HLRZ T1,TSVDIS ;Get the display bit
DPB T1,[POINT 1,VMS$CF+4,<^D35-^L<TSCOP>>/8*8+7-<<^D35-^L<TSCOP>>-<<^D35-^L<TSCOP>>/8*8>>]
LSH T1,<^D35-^L<TSCOP>>
IORM T1,VMTTCH+1 ;Set that here
HLRZ T1,TSVNFC ;Free <CR> bit
TRC T1,1 ;Convert to WRAP bit
DPB T1,[POINT 1,VMS$CF+4,<^D35-^L<TWRAP>>/8*8+7-<<^D35-^L<TWRAP>>-<<^D35-^L<TWRAP>>/8*8>>]
LSH T1,<^D35-^L<TWRAP>>
IORM T1,VMTTCH+1 ;Set it in characteristics
HLRZ T1,TSVXNF ;XON/XOFF
DPB T1,[POINT 1,VMS$CF+4,<^D25-^L<TTSYN>>/8*8+7-<<^D35-^L<TTSYN>>-<<^D35-^L<TTSYN>>/8*8>>]
LSH T1,<^D35-^L<TTSYN>>
IORM T1,VMTTCH+1
VM.IN1: MOVEI T1,VMS$CF ;Return config
PUSHJ P,XMTMSG ;
MOVEI T1,VMS$UN ;Get unsolicited data message
PUSHJ P,XMTMSG ;Send it
MOVE T1,[VXDMSK,,IMASK] ;Set the terminal mask
BLT T1,ENDMSK ;Set it
MOVE T1,[VXDMSK+1,,LMASK] ;Also set logical mask
BLT T1,ELMASK
MOVE T1,[7,,TRMBKS]
TRMOP. T1,
JFCL
PUSHJ P,TTYSST ;Set TTY: up
PJRST FRCTTI
SUBTTL VMS Support -- VM.STM - timed requests
;This routine is called if the request is timed.
;QIO block pointed to by P4.
VM.STM: MOVEI T1,VM.TMR ;Be sure timer trap is set
MOVEM T1,OSTMR ;to go to the right place
MOVE T1,V.IDENT(P4) ;Get the identifier
MOVEM T1,TMRSEQ ;Make it the sequence identifier
MOVE T1,V.TIME(P4) ;Get time request
PITMR. T1,
JFCL ;Oh well
POPJ P,
;VMS routine to actually handle the timer trap
VM.TMR: SKIPN P4,READQ ;Point to queue
POPJ P, ;No entry
MOVE T1,V.IDENT(P4) ;Get the sequence number
CAME T1,TMRSEQ ;Right sequence number?
POPJ P, ;Wrong request
MOVE T1,[2,,T2] ;Find how many chars are in the chunks
MOVEI T2,.TOTTC
MOVE T3,TTYUDX
TRMOP. T1,
PJRST VM.RDS ;Oh well
JUMPE T1,VM.RDS ;If none pending
MOVEM T1,IMASK ;Set that many
MOVEI T1,TIMEOUT ;Set status
MOVEM T1,V.STAT(P4) ;Status for read
TXO F,F$FRC!F$TEX ;Force call to TTYSST
PUSHJ P,FRCTTI ;Force wakeup
PJRST TTYSST ;Set TTY: up and return
SUBTTL VMS Support -- Set TTY: up for this read
VM.STT: TXZ F,<F$NEC!F$PIM!F$LEM> ;Clear some bits
MOVE T1,V.MOD(P4) ;Get modifiers
MOVEI CX,TNEKO ;Check perm chars too
TDNN CX,VMTTCH+1 ;?
TRNE T1,NOECHO ;Or program requested?
TLOA F,(F$NEC) ;Flag to TTY: service
TRNA ;Don't do anything
TRO T1,NOECHO ;Make it say so in request
MOVEM T1,V.MOD(P4) ;Store for when request complete
ASSUME CVTLOW,F$CVL
XOR T1,F ;Get the CVTLOW bit
HLRZ T2,TSVLCT ;Get saved lower case ability
JUMPN T2,VM.SMK ;If TTY: already upper case, no problem
TRNN T1,CVTLOW ;Is it on now?
JRST VM.SMK ;No, no change
TRCE F,F$CVL ;Is it set in F?
TDZA T3,T3 ;Yes, must want to set to upper case
SETO T3, ;If F was zero must want to clear upper case
MOVE T2,TTYUDX
MOVEI T1,.TOLCT+.TOSET
MOVE CX,[3,,T1]
TRMOP. CX, ;Do the right thing
JFCL
VM.SMK: HRRZ CX,V.COUNT(P4) ;Get maximum size
MOVEM CX,IMASK ;Set size of field
SKIPN V.MASK(P4) ;Mask specified?
SKIPA CX,[VXDMSK+1,,] ;Set default mask
HRLI CX,V.MASK+1(P4) ;Set it
HRRI CX,IMASK+1
BLT CX,ENDMSK ;Set the mask
MOVE CX,[IMASK+1,,LMASK] ;Set the "local" mask to this too
BLT CX,ELMASK ;To the end
MOVX T1,<1B<.CHCNH>> ;Must always see ^H
IORM T1,IMASK+1
TXNE F,F$PALL ;If passall, then stop here
JRST VM.NRX ;Set it up
ASSUME VM.RAL,<1B0> ;This must be true
SKIPGE V.MOD(P4) ;If READALL bit is set
TROA F,F$RALL ;Set readall bit
TXZA F,F$RALL ;Set readall
PJRST VM.NRX ;Set TTY: up
VM.NRA: MOVE T1,OBMASK ;Get the out of band mask
IORM T1,IMASK+1
MOVE T1,OBMASK+1 ;Both include and exclude
IORM T1,IMASK+1
SETZ T1, ;Initialize
TLNE F,(F$CAST) ;Want ^C?
TXO T1,<<1B<.CHCNC>>> ;Yes
TLNE F,(F$YAST) ;Want ^Y?
TXO T1,<<1B<.CHCNC>>!<1B<.CHCNY>>>
MOVE T2,V.MOD(P4) ;Get modifiers
MOVEI CX,<1B31> ;Default not NFILTR
TRNE T2,NFILTR ;No filter?
JRST VM.NR1 ;Proceed
TXO F,F$RUB ;In case any snuck in
PUSHJ P,VM.SCT ;Set up CHRTAB (must be after setting F$RUB)
JFCL ;? Shouldn't get here
ANDCAM CX,LMASK+3 ;Clear rubout in appropriate places
ANDCAM CX,IMASK+1+3
MOVX CX,<<1B<.CHCNR>>!<1B<.CHCNU>>!<1B<.CHCNX>>>
ANDCAM CX,LMASK ;These too
TXZ CX,<1B<.CHCNX>> ;We must handle ^X
ANDCM CX,OBMASK
ANDCM CX,OBMASK+1
ANDCAM CX,IMASK+1
IORM T1,IMASK+1 ;Set special bits too
VM.NRX: PUSHJ P,TTYSST ;Do it
PJRST FRCTTI
VM.NR1: TXO F,F$LEM ;Set LEM
PUSHJ P,VM.SCT ;Set up CHRTAB
JFCL ;? Shouldn't get here
TXO T1,<<1B<.CHCNR>>!<1B<.CHCNU>>!<1B<.CHCNX>>>
MOVEI CX,<1B31> ;Also set rubout
IORM CX,IMASK+1+3
IORM T1,IMASK+1 ;Set appropriate bits
SKIPE V.MASK(P4) ;Using default mask?
JRST VM.NRX ;No, change TTY:
IORM T1,LMASK ;Default bits change
IORM CX,LMASK+3 ;..
PUSHJ P,TTYSST
PJRST FRCTTI
SUBTTL VMS Support -- Set Unsolicited mode
;This routine sets the break mask for unsolicited input
VM.SUN: SAVE1
TXO F,F$UAST ;Say we want it
SKIPE READQ ;Is there a read request?
POPJ P, ;No
SETZM IMASK ;TTYSST will set it to 1
SETOM IMASK+1 ;Break on all characters
MOVE P1,[IMASK+1,,IMASK+2] ;Set the whole mask
BLT P1,ENDMSK ;Set it
PUSHJ P,TTYSST
PJRST FRCTTI ;Set up and return
SUBTTL VMS Support -- Set CHRTAB
;This routine is to set up CHRTAB
VM.SCT: PUSHJ P,SAVT ;Save the Ts
TXNE F,F$PALL!F$RALL ;If in a flavour of passall
POPJ P, ;Don't diddle CHRTAB
MOVX T1,<1B<.CHCNO>> ;Set control-O normal
TXNN F,F$LEM ;Editor?
TXO T1,<1B<.CHCNX>> ;No, set ^X
MOVE T4,VMTTCH+1 ;Get characters
TXNE T4,TTSYN ;Paged mode?
TXO T1,<1B<.CHCNS>!1B<.CHCNQ>> ;Yes, we must handle these if they come in
MOVEI T4,1B19 ;Assume don't have to do rubouts
ANDCAM T4,CHRTAB+3 ;..
TXNE F,F$RUB ;Do I have to do rubouts etc.?
TXNE F,F$LEM ;Only if not this
JRST VM.NRU ;No
TXO T1,<1B<.CHCNR>!1B<.CHCNU>>
IORM T4,CHRTAB+3 ;..
VM.NRU: TXNE F,<F$CAST> ;Want ^C?
TXO T1,1B<.CHCNC> ;Yes
TXNE F,<F$YAST> ;And if wants ^Y
TXO T1,<1B<.CHCNC>!1B<.CHCNY>>
MOVEM T1,CHRTAB ;Set special characters
JRST CPOPJ1 ;We changed it
SUBTTL VMS Support -- Handle special characters
;This routine handles ^C, ^Y, and the escape character for VMS
VMS.SC: CAME P1,ESCCHR ;Is it the break character?
JRST VM.NBK ;No
PUSHJ P,MONITO ;Yes, go get response
JRST [PUSHJ P,SPCRMV ;Remove
PJRST VCRURB ] ;See if have to do this
AOS BRKNUM ;One more break
PJRST VCRURB ;Set processing and return
VM.NBK: CAIN P1,.CHCNO ;Control-O?
JRST VM.SCO ;Yes, set it
CAIN P1,.CHCNX ;^X?
JRST VM.SCX ;Yes, handle it
CAIE P1,.CHCNQ ;^Q?
CAIN P1,.CHCNS ;or ^S?
JRST VM.SCQ ;Yes, handle them
CAIE P1,.CHCNC ;Control-C?
JRST VM.NCC ;No
MOVSI T4,(1B<.CHCNC>) ;One time-AST only
ANDCAM T4,CHRTAB ;So isn't special any more
TDNN T4,LMASK ;Want to see ^C as break?
ANDCAM T4,IMASK+1 ;No, clear in IMASK
TLZN F,(F$CAST) ;User want ^C?
JRST VM.SCY ;No, send ^Y then
PUSH P,[RA.CTC,,CONTRC] ;Abort reason and ^C attention
MOVEI T4,[ASCIZ/
^C
/]
JRST VM.CYC ;Send attention interrupt
VM.NCC: CAIE P1,.CHCNY ;Control-Y?
JRST VM.LED ;See about line editing stuff
VM.SCY: MOVEI T4,1B<.CHCNY> ;^Y is one-time also
ANDCAM T4,CHRTAB
TDNN T4,LMASK ;Does he want ^Y as break
ANDCAM T4,IMASK+1 ;No
TLZN F,(F$YAST) ;Want ^Y?
POPJ P, ;Return
PUSH P,[RA.CTY,,CONTRY] ;Control-Y abort and attention
MOVEI T4,[ASCIZ/
^Y
/]
VM.CYC: PUSHJ P,CLRTOQ ;Flush the output queue
PUSHJ P,STROUT ;Output echo
PUSHJ P,DOOUT1 ;Force it out
PUSHJ P,SPCFLS ;Flush input
HLRZ T1,(P)
PUSHJ P,VMS.AT ;Send attention message too
SKIPN P4,READQ ;Anything in input queue?
JRST TPOPJ ;Fix stack and return
PUSHJ P,VMS.BH ;Build header for it
HRRZ P1,(P) ;Get abort reason
PUSHJ P,PUTLWD ;Put the word in
SETZ P1,
PUSHJ P,PUTLWD ;Zap I/O status
NETOCH P1
POP P,(P) ;Attention reason
PJRST VM.FNR ;Read request finished
;Here on control-O
VM.SCO: TXZ F,F$ICO ;Don't ignore monitor any more
PUSHJ P,SPCRMV ;Eat the ^O
PUSHJ P,VCRURB ;Set special processing
TXCN F,F$CTO ;Complement the bit
PUSHJ P,CLRTOQ ;Clear the TO queue
PUSH P,TOFLGS ;Save the flags
MOVEI T4,($TOOIN!$TOICL)
MOVEM T4,TOFLGS
MOVEI T4,[ASCIZ/^O
/]
PUSHJ P,STROUT ;Output
PUSHJ P,DOOUT1 ;Force out
POP P,TOFLGS
TXNN F,F$CTO ;Did we set it?
PJRST CLRCTO ;Inform the monitor
PUSHJ P,WATOUT ;Wait for string to get there
PJRST SETCTO ;Inform the monitor too
VM.SCX: PUSHJ P,SPCFLS ;Eat all type-ahead
SKIPN READQ
POPJ P, ;Return if no outstanding read
MOVEI T1,($TOOIN!$TOICL)
MOVEM T1,TOFLGS
MOVEI T4,[ASCIZ/^U
/] ;Say what we did
PUSHJ P,STROUT
PUSHJ P,DOOUT1
SETZM TOFLGS
POPJ P,
;Here on ^S/^Q
VM.SCQ: MOVE T1,[3,,T2] ;Change the bit
MOVEI T2,.TOSET+.TOSTP ;The output bit
MOVE T3,TTYUDX
CAIE P1,.CHCNS ;^S?
TDZA T4,T4 ;No, ^Q, clear
MOVEI T4,1
TRMOP. T1,
JFCL
PJRST SPCRMV ;Toss character and return
;Here to see about line editing stuff
VM.LED: PUSHJ P,SCNPOS ;Get position of scan
SKIPN T2,READQ ;Get read request
JRST CPOPJ1 ;None?
CAMG T1,V.COUNT(T2) ;Satisfy already?
TXNE F,F$BRK ;Break seen already?
JRST CPOPJ1 ;Yeah, do this later
VM.LD1: CAIN P1,.CHCNU ;Control-U?
JRST VM.SCU ;Do it also
CAIN P1,.CHDEL ;Rubout?
JRST VM.RUB ;Yes
CAIE P1,.CHCNR ;Control-R?
JRST CPOPJ1 ;Ignore it, I guess
;Here to process ^R
VM.SCR: MOVEI T1,VM.CTR ;Routine to call
PUSHJ P,DOCTR ;Handle the ^R
JRST VCRURB ;Check flag
VM.CTR: SAVE4 ;Save the Ps
VM.CUR: SKIPN P4,READQ ;Get current request, if any
POPJ P, ;None
TXO F,F$CLF ;Cancel a line feed
TXZ F,F$FLF ;None
PJRST CHKPRM ;See if need it
;Here to process ^U
VM.SCU: PUSHJ P,DOCTU ;Handle ^U
PUSHJ P,VM.CUR ;See if prompt
JRST VURURB ;Turn off bits
;Here to process rubout
VM.RUB: PUSHJ P,DORUB ;Do the rubout
JRST VCRURB ;Check flag
SUBTTL VMS Support -- VMS.AT - Send Attention
VMS.AT: MOVEI P1,VR.ATT ;Get Attention header
PUSHJ P,PUTWRD ;Put it in
MOVEI P1,(T1) ;Get attention reason
PUSHJ P,PUTWRD
PJRST XMTMSS ;Send the message
SUBTTL VMS Support -- VMS.ST - Set characteristics/mode
VMS.ST: ;'Set Mode' message
MOVE T1,V.MOD(P4) ;Get the modifier
TRNN T1,CC!CY ;One of these?
JRST VM.COB ;No
PUSHJ P,GETLWD ;Get first arg (P1)
MOVX T3,CC ;^C or ^Y?
TDNN T3,V.MOD(P4) ;^C or ^Y?
JRST VM.CCY ;Check ^Y
SKIPN T1 ;Set or clear?
TXZA F,F$CAST ;Clear it
TXO F,F$CAST ;Set it
MOVE T2,CHRTAB+<.CHCNC/36.> ;Set ^C bit
TXNN F,F$CAST!F$YAST ;One of ^C or ^Y set?
TXZA T2,1B<.CHCNC> ;Clear ^C
TXO T2,1B<.CHCNC> ;Set ^C
VM.YAK: MOVEM T2,CHRTAB+<.CHCNC/36.>
PJRST VMS.AK
VM.CCY: ASSUME <<.CHCNC/36.>>,<<.CHCNY/36.>>
MOVE T2,CHRTAB+<.CHCNY/36.>
SKIPN T1 ;Set or clear?
TXZA F,F$YAST ;Clear
TXOA F,F$YAST ;Yes
TXZA T2,1B<.CHCNY> ;Clear ^Y
TXOA T2,<1B<.CHCNC>!1B<.CHCNY>> ;Set both ^C and ^Y
TXNE F,F$CAST ;Affect ^C too?
PJRST VM.YAK ;No
TXZ T2,1B<.CHCNC> ;Clear ^C too
MOVEM T2,CHRTAB+<.CHCNY/36.>
PJRST VMS.AK ;^C/^Y set/clear and ACK
VM.COB: SKIPE PROTMD ;V3+ protocol?
TRNN T1,OBAND ;Want out-of-band AST?
JRST VM.STC ;No
SETO P3, ;Do this twice
MOVE T3,[POINT 8,P1,]
SETZB P1,P2 ;No bits in mask yet
VM.CB1: PUSHJ P,NETICH ;Get character from network
PJRST VMS.AK ;Done if none
MOVEI T4,4 ;Four times each time
PUSHJ P,CPYMSK ;Copy the mask
AOJE P3,VM.CB1
IORM P1,IMASK+1
IORM P2,IMASK+1 ;Both of them
DMOVEM P1,OBMASK ;Save the masks
IOR P1,P2 ;See if ^O is in mask
TXNE P1,1B<.CHCNO> ;?
TXOA F,F$ACO ;Allow it in mask if so
TXZ F,F$ACO ;Not allowed any more
IORM P1,IMASK+1 ;If any significant changes
PUSHJ P,TTYSST ;(just in case)
MOVE T1,V.MOD(P4) ;Get modifier
PJRST VMS.AK
VM.STC: TRNE T1,777700 ;Any modifiers?
PJRST VMS.UM ;Unsupported modifier if so
PUSHJ P,GETLWD ;Get first word of chars
EXCH T1,VMTTCH ;Store it, get old
XOR T1,VMTTCH ;Get differences
TRNN T1,377B<^D35-^D8>;Type change?
JRST VM.ST0 ;No
LDB T1,[POINT 8,VMTTCH,^D35-^D8] ;Get the type
MOVSI T2,-TTPLEN
VM.STL: HRRZ T3,VTPTB(T2)
CAIE T1,(T3) ;This one?
AOBJN T2,VM.STL ;No
JUMPGE T2,VM.ST0 ;Can't find it
HRRZM T2,TTYTYP ;Save it
MOVE T4,TTPTB(T2) ;Get TOPS-10 type
MOVE T3,TTYUDX
MOVEI T2,.TOTRM+.TOSET
MOVE T1,[3,,T2]
TRMOP. T1,
JFCL
VM.ST0: PUSHJ P,GETLWD ;Get second word
TRNN T1,TPSAL ;Check passall
TXZA F,F$PALL
TXO F,F$PALL ;Set or clear as appropriate
EXCH T1,VMTTCH+1 ;Save it too
XOR T1,VMTTCH+1 ;Get changes
MOVE CX,[3,,T2]
MOVE T3,TTYUDX ;Who to change
MOVX T2,TWRAP ;Get the wrap bit
TDNN T1,T2 ;Did it change?
JRST VM.ST1 ;No
TDNE T2,VMTTCH+1 ;On or off?
TDZA T4,T4 ;Off
SETO T4, ;On
MOVEI T2,.TONFC+.TOSET
TRMOP. CX, ;Do it
JFCL
VM.ST1: MOVX T2,TTSYN ;Paged mode?
TDNN T1,T2 ;Change?
JRST VM.ST2 ;No
TDNN T2,VMTTCH+1 ;On or off now?
TDZA T4,T4 ;Off
SETO T4,
MOVEI T2,.TOSET+.TOXNF
MOVE CX,[3,,T2] ;Set as appropriate
TRMOP. CX,
JFCL
VM.ST2: SKIPN PROTMD ;Version 3 or later protocol?
PJRST VMS.AK ;Write the data to the VAX
PUSHJ P,GETLWD ;Version 3, eat speed, fill, and parity
PUSHJ P,GETLWD
PUSHJ P,GETLWD
PUSHJ P,GETLWD ;And get second characteristics word
MOVEM T1,VMTTCH+2 ;Save them away too
CALLRE VMS.AK ;AK the message
SUBTTL VMS Support -- VMS.NI - Unsolicited Data Message
VMS.UN: TXNE F,F$UAST ;Want message?
AOSE UNSCNT ;Send unsolicited message?
POPJ P,
MOVEI T1,VMS$UN ;Tell host about unsolicited data
PJRST XMTMSG ;
SUBTTL VMS Support -- Checkout-of-band character
;Scan input for out-of-band character. If found, then
;return CPOPJ with character. If not found, return CPOPJ1
VM.CHO: SKIPN P4,INPQUE ;Get any input
JRST CPOPJ1 ;None
VM.CHA: SKIPG IBF.LK(P4) ;Another buffer?
JRST VM.CHC ;No, done
HRRZ P4,IBF.LK(P4) ;Point to next
JRST VM.CHA
VM.CHC: MOVE P3,IBF.CT(P4) ;Get count
MOVE P2,IBF.PT(P4) ;And pointer
VM.CH1: PUSHJ P,SCNCHR ;Any?
JRST CPOPJ1 ;None
CAIL P1," " ;Must be a control character
JRST VM.CH1 ;No
MOVEI T1,(P1)
IDIVI T1,^D32 ;Get bit numer
MOVSI T1,400000 ;Get bit 0
MOVNS T2 ;Negate the remainder
LSH T1,(T2) ;Compute mask
TDNN T1,OBMASK ;In include mask?
TDNE T1,OBMASK+1 ;In exclude mask?
TRNA ;In one of them
JRST VM.CH1 ;Check next character
TDNE T1,OBMASK ;In include mask?
JRST VCRURB ;Yes
PUSH P,P1 ;Save character
PUSHJ P,SPCRMV ;Remove the character now
POP P,P1 ;Restore the character
CAMN P1,BRKCHR ;Escape character?
SOS BRKCNT ;Yes
FALL VCRURB ;Check ^R, ^U, <RUB>
;Fall into below
SUBTTL VMS Support -- Check ^R, ^U, and <RUB>
;This routine checks to see if we must do processing for ^R, ^U, or <RUB>
;and sets bits appropriately
VCRURB: TDZA T3,T3 ;Flag to set
VCRUR1: SETO T3, ;Don't set
TXNN F,F$READ ;Read pending?
PJRST VURURB ;No
SKIPE ICHCNT ;Any characters in input?
TXNE F,F$PALL ;Yes, passall?
PJRST VURURB ;Clear if need to
SKIPN T1,READQ
PJRST VCRUR2 ;Set stuff, no request active
MOVX T2,VM.RAL!NFILTR
TDNN T2,V.MOD(T1) ;??
VCRUR2: JUMPE T3,STRURB ;Set
POPJ P,
VURURB: MOVE T3,VXDMSK ;Use default if no request
SKIPE T1,READQ ;Current request
SKIPA T3,V.COUNT(T1) ;Get count from there then
JRST VCKPAL ;Check passall only
HRL T1,V.MOD(T1) ;Get modifiers
TLNN T1,NFILTR ;This no-filter?
VCKPAL: TXNE F,F$PALL ;Passall?
JRST UNRURB ;Conditional based on mask
JUMPE T1,UNRALL ;Always if no request
TXNN F,F$RALL ;Read-all check if a request
JRST UNRALL ;Always then
JRST UNRURB ;Else conditional
SUBTTL VMS Support -- Out-of-band ATTN
VMS.OB: PUSH P,P1 ;Save character
MOVEI P1,VR.ATT ;Get attention reason
PUSHJ P,PUTWRD ;set it
MOVEI P1,RA.OUB ;Modifier
PUSHJ P,PUTWRD ;Also there
SETZ P1,
PUSHJ P,PUTLWD ;Longword
PUSHJ P,PUTWRD
POP P,P1
NETOCH P1 ;Put character in
PJRST XMTMSS ;Send the message
SUBTTL VMS Support -- VMS.BC - Broadcast data
VMS.BC: PUSHJ P,GETLWD ;Get count
SKIPN P3,T1 ;Copy to P1 if any
JRST VMS.AK ;ACK it if no data
SKIPN V.IDENT(P4) ;If no identifier
JRST VM.BNA ;Then just don't ACK this
PUSHJ P,VMS.BH ;ACK the req but don't return the block
MOVEI P1,NORMAL
PUSHJ P,PUTLWD
SETZ P1,
PUSHJ P,PUTLWD
PUSHJ P,XMTMSS ;Send the ACK
VM.BNA: PUSHJ P,GETLWD ;Get junk long-word
PUSH P,TOFLGS ;Save current flags
MOVEI P1,($TOOIN)
MOVEM P1,TOFLGS
PUSH P,F ;Save F
PUSH P,IMASK+1
DMOVE T3,VMTTCH+1 ;Get characteristics
TRNN T3,TNBCS ;No mailbox, is no broadcast set?
TXNE F,F$CTO ;Or is ^O in effect?
JRST [TRNE T4,T2BCM ;Is there a mailbox?
JRST VM.BNB ;Yes
JRST VM.BXD ];No
SKIPN T1,READQ ;Is there a current read request?
JRST VM.BNZ ;No
SKIPE V.PROM(T1) ;Prompt string?
JRST [TXO F,F$FLF ;Yes, set FLF
JRST VM.BNZ ];Continue
TXZ F,F$FLF!F$CLF ;Clear flags
TXNE F,F$NEC ;No-echoed?
JRST VM.BNZ ;Yes
PUSHJ P,SETICH ;Set counts
SKIPE ICHCNT ;Any characters there?
TXOA F,F$FLF ;Yes, flag a line feed
TXO F,F$CLF ;No characters, any line feed taken care of
;The above is not quite accurate.
VM.BNZ: TRNN T4,T2BCM ;Is there also a mailbox?
JRST VM.BCL ;No
VM.BNB: SETO P1,
PUSHJ P,PUTWRD ;Attention request
MOVEI P1,5 ;Completion op code
PUSHJ P,PUTWRD ;...
SETZ P1, ;ID (should be ignored
PUSHJ P,PUTLWD
PUSHJ P,PUTWRD ;Unit
MOVEI P1,^D22(P3) ;Remaining data size
PUSHJ P,PUTWRD
MOVEI P1,MTMBRD ;Code
SETZ P1, ;Just to look nice
PUSHJ P,PUTWRD
PUSHJ P,PUTWRD ;BRDUNIT
PUSHJ P,PUTLWD ;BRDNAME
PUSHJ P,PUTLWD
PUSHJ P,PUTLWD
PUSHJ P,PUTLWD
MOVEI P1,(P3) ;Text size
PUSHJ P,PUTWRD
VM.BCL: PUSHJ P,RBYTEC ;Get a byte
TRNE T4,T2BCM ;Mailbox?
NETOCH T1 ;Ship to network
TXNN F,F$CTO ;Control-O?
TRNE T3,TNBCS ;No broadcast?
JRST VM.BX3 ;Skip all this then
TXNN F,F$FLF ;Supposed to be free line feed?
JRST VM.BX1 ;No
REPEAT 0,< ;For V4
CAIN T1,.CHLFD ;Is this a line feed?
TXZA F,F$FLF ;Yes, clear it
>
CAIGE T1," " ;Printing character?
JRST VM.BX1 ;No
PUSH P,T1
MOVEI T1,.CHCRT ;Preceed with <CR><LF> (for V4)
PUSHJ P,OUTTTY
MOVEI T1,.CHLFD ;Output the <LF>
PUSHJ P,OUTTTY
POP P,T1
TXZ F,F$FLF ;Don't do it any more
VM.BX1: TXNE F,F$CLF ;Cancel line feed?
CAIN T1,.CHLFD ;Yes, is this a line feed?
TXZN F,F$CLF ;Yes, clear
VM.BX2: PUSHJ P,OUTTTY ;Output to TTY:
VM.BX3: SOJG P3,VM.BCL ;For all bytes
CAIN T1,.CHCRT ;Last character a <CR>?
JRST VM.BX4 ;Yes, just proceed
MOVEI T1,.CHCRT ;Append <CR> to message (for V4)
PUSHJ P,OUTTTY ;Do it (V4)
VM.BX4: TXO F,F$FLF ;Now set free <LF>
TXZ F,F$CLF ;Don't cancel any more line feeds
TRNE T4,T2BCM ;Mailbox?
PUSHJ P,XMTMSS ;Send mailbox message now
VM.BXD: MOVEI T1,(P4) ;Point to request block
MOVEI T2,VRQSIZ
PUSHJ P,CORFRE ;Free the block
TXNN F,F$CTO ;^O?
TRNE T3,TNBCS ;Nobroadcast?
JRST VM.BC8 ;Return
SKIPN P4,READQ ;Anything in queue?
JRST VM.BC9
MOVX T1,VM.RAL
TDNE T1,V.MOD(P4) ;Any of the physical stuff?
TXZ F,F$FLF ;Yes
PUSHJ P,CHKPRM ;Output prompt it any
SETZ P3, ;Clear who we're remembering
MOVX T1,F$NEC ;Are we supposed to be noechoed?
TDNE T1,-1(P) ;?
JRST VM.BC8 ;Yes
SKIPN P4,INPQUE
JRST VM.BC5 ;Just do FRCUUO
VM.BC0: SKIPG IBF.LK(P4)
JRST VM.BC1
HRRZ P4,IBF.LK(P4)
SKIPLE IBF.CT(P4) ;Is this one real?
HRRZI P3,(P4) ;Yes, remember it
JRST VM.BC0
VM.BC1: SKIPG IBF.CT(P4) ;If this has a real count then it's the one
MOVEI P4,(P3) ;Else this is the one
JUMPE P4,VM.BC5 ;Nothing, just do frcuuo
MOVE P2,IBF.PT(P4) ;Pointer
SKIPN P3,IBF.CT(P4) ;Get count
JRST VM.BC4 ;It's zero
IBP P2 ;Force normalization
SOJE P3,VM.BC4 ;If just one byte
EXCH P2,P3 ;Set up for ADJBP
ADJBP P2,P3
VM.BC4:
PUSH P,P2
PUSHJ P,SCNLBK ;Point to last character before
VM.BC2: PUSHJ P,SCNCHR
JRST VM.BC3
TXNE F,F$FLF ;Need free line feed?
CAIN P1,.CHLFD ;This a line feed?
JRST VM.BC6 ;Proceed
MOVEI T1,.CHLFD ;Output a line feed
PUSHJ P,OUTTTY ;Output
VM.BC6:
TXZ F,F$FLF
MOVEI T1,(P1)
PUSHJ P,OUTTTY
CAME P2,(P)
JRST VM.BC2
VM.BC3:
POP P,(P) ;Clear junk
VM.BC5: TXZN F,F$FLF ;Still need?
JRST VM.BC7 ;No
TXO F,F$CLF ;Say we gave one
TXNE F,F$NEC ;Currently noechoed?
JRST VM.BC7 ;Yes, no line feed
MOVEI T1,.CHLFD ;Output one
PUSHJ P,OUTTTY
VM.BC7: PUSHJ P,DOOUT1
PUSHJ P,DOFRCU ;Do a FRCUUO
VM.BC8: POP P,T2 ;Restore old value for next time
POP P,T1
POP P,TOFLGS ;Restore output flags
TXNN T1,F$NEC
TXZ F,F$NEC ;Clear no-echo
PUSHJ P,TTYSST
MOVEM T2,IMASK+1
TXZ F,F$ACO
POPJ P,
VM.BC9: PUSHJ P,DOOUT1
PJRST VM.BC8
SUBTTL VMS Support -- VMS.SN - Sense Mode message
VMS.SN: ;'Sense Mode' message received
MOVE T1,V.MOD(P4) ;Get the modifiers
TRNE T1,TYPAHD ;Want typeahead count?
JRST VMS.TA ;Yes
TRNE T1,MODEM ;Want modem status
JRST VM.NMD ;Yes, sense modem
PUSHJ P,VMS.BH ;Build the usual header
MOVEI P1,NORMAL
PUSHJ P,PUTWRD
SETZ P1, ;**TEMP
PUSHJ P,PUTWRD
PUSHJ P,PUTLWD
MOVE P1,VMTTCH ;Get first word of characteristics
PUSHJ P,PUTLWD
MOVE P1,VMTTCH+1
PUSHJ P,PUTLWD
SKIPN PROTMD ;Version 3 protocol?
JRST VM.SN1 ;No
MOVE P1,VMTTCH+2 ;Get char 2
PUSHJ P,PUTLWD
VM.SN1: PUSHJ P,XMTMSS
MOVEI T1,(P4)
MOVEI T2,VRQSIZ
PJRST CORFRE
VMS.TA: PUSHJ P,SETICH ;Set input character count
MOVE T1,[2,,T2] ;Find how many in chunks
MOVEI T2,.TOTTC ;..
MOVE T3,TTYUDX
TRMOP. T1,
SETZ T1,
PUSH P,P4 ;Save P4
PUSHJ P,SCNINI ;Init a scan
PUSHJ P,SCNCHR ;Get the character
JUMPN T1,VM.TA4 ;Figure what's out there
MOVEI P3,(P1) ;Remember character
POP P,P4 ;Restore P4
PUSHJ P,VMS.BH ;Build the usual header
MOVEI P1,NORMAL
PUSHJ P,PUTWRD
SETZ P1, ;**TEMP
PUSHJ P,PUTWRD
PUSHJ P,PUTLWD
MOVE P1,ICHCNT
ADDI P1,(T1) ;Add them in
PUSHJ P,PUTWRD ;Tell him
NETOCH P3 ;Output the character
NETALC 5 ;Rest is reserved
JRST VM.SN1 ;Return
;Here if there are characters in the chunks and none internally. Cheat.
VM.TA4: TXO F,F$FRC ;Force a read
PUSHJ P,FRCTTI ;Force wakeup
SETZM IMASK ;Only want to see first character
POP P,SENSEQ ;Remember the request
PJRST TTYSST ;Set TTY: up and return
;Here at TTY: interrupt level after the read is complete
VM.SNC: TXZ F,F$FRC ;Don't need to force any more
SETZM SENSEQ ;Done here
JRST VMS.TA ;Finish up the sense
;Here if modem modifer is set
VM.NMD: PUSHJ P,VMS.BH ;Build header
MOVEI P1,NORMAL
PUSHJ P,PUTWRD
SETZ P1, ;**TEMP
PUSHJ P,PUTWRD
PUSHJ P,PUTLWD
PUSHJ P,PUTLWD ;Return all zeroes
PUSHJ P,PUTLWD
JRST VM.SN1 ;Finish up
SUBTTL VMS Support -- Return unsupported
;This routine returns an unsupported return for those functions we
;don't know what to do with. Call with request block in P4.
VMS.UM: PUSHJ P,VMS.BH ;Build header
MOVEI P1,ILLFNC ;Say what's wrong
PUSHJ P,PUTWRD ;Put it in
SETZ P1, ;Do the rest
PUSHJ P,PUTWRD
PUSHJ P,PUTLWD ;Of the IOSB
PUSHJ P,XMTMSS ;Send the message
MOVEI T1,(P4) ;Free the block
MOVEI T2,VRQSIZ
PJRST CORFRE
SUBTTL TOPS-10/20 support -- Network service
PLM
;+
;.hl 2 TOPS-10/TOPS-20 Support
; TOPS-10 and TOPS-20 are implemented via a transparent protocol.
;As such, all characters typed by the user are read in PIM mode from
;the terminal and queued immediately for network output. All characters
;sent from the remote host are displayed on the terminal.
;-
MLP
T10.NT:
T20.NT:
UTX.NT: SKIPE OSTMR ;Are we enabled for flush?
TXO F,F$CTO ;Yes, flag it
PUSHJ P,NETCHR ;See if we have a network character
IFN FTPERF,<
DOT204: TXNN F,F$PERF ;Performance flag set?
POPJ P, ;Done
T10.NP: PUSHJ P,GETPRC ;Get a performance character
JRST DOT109 ;Force out the character
T10.EP: PUSHJ P,TSTRET ;Finish
JRST T10.TT ;Get a new character
JRST DOT109 ;Or pass break
> ;End IFN FTPERF
IFE FTPERF,<
POPJ P, ;No, Return (no null messages)
>
SUBTTL TOPS-10/20 support -- TTY: service
T10.TT:
T20.TT:
UTX.TT: TXZE F,F$CTO ;Don't flush anything else
SETZM OSTMR ;No more timer stuff
T10.T1: PUSHJ P,INCHR
JRST T10.T5 ;See if anything to output
IFN FTPERF,<
TXNN F,F$PERF ;All being handled by other stuff
>
JRST DOT107 ;Process
IFN FTPERF,<
CAME T1,ESCCHR ;In case he wants to abort
JRST T10.T1 ;No, just eat
JRST T10.EP ;End performance analysis
>
DOT106: PUSHJ P,INCHR ;Get a character
JRST XMTMSS ;Send the message
DOT107: CAME T1,ESCCHR ;Escape character
JRST DOT109
MOVE T1,TTYUDX ;Get controlling TTY: UDX
CAME T1,CTLTTY ;Same as controlling terminal?
JRST DOT108
TXNE F,F$XPT ;Is he supposed to be an expert?
PUSHJ P,INCHR ;Anything to eat?
DOT108: TDZA T3,T3 ;No character
MOVE T3,T1 ;Put character in T2
T10.MN: PUSHJ P,MONITC ;Go to the monitor
IFN FTPERF,<
JRST [TXNN F,F$PERF ;Now in performace?
JRST T10.T1 ;Loop around if not
JRST T10.NP] ;Start PERF stuff
>
IFE FTPERF,<
JRST T10.T1
>
; SETZM BRKNUM ;(Not really used here anyway)
DOT109: NETOCH T1 ;Output to network
IFN FTPERF,<
TXNN F,F$PERF ;Doing performance stuff
JRST DOT106 ;No, then just continue on normal path
PJRST XMTMSS ;Force out and dismiss
> ;End IFN FTPERF
JRST DOT106 ;Loop for whole message
T10.T5: MOVEI T1,4*OBUFSZ
SUB T1,OBFCTR ;Do anything?
JUMPN T1,XMTMSS ;Yes, force it out
POPJ P,
SUBTTL TOPS-10/20 support -- Timer service
;Timer service is utilized for the "Flush Network Output" command.
;This is implemented so that we can automatically turn off the flush
;command if no network messages are received within the timeout period
T10.TM: TXZN F,F$CTO ;Clear the flush flag
JRST T10.TC ;Clear timer stuff and return
MOVEI T1,1 ;Reset for one second
PITMR. T1, ;Set the timer
JFCL
POPJ P, ;Done
T10.TC: SETZM OSTMR ;Don't come back here
SKIPE T4,NOTICH ;Point to string
TXNN F,F$XPT ;And in some expert mode?
POPJ P,
PUSHJ P,STROUT ;Do it
PJRST DOOUT1 ;Tell him
SUBTTL TOPS-10/20 support -- Initialization
T10.IN:
T20.IN:
UTX.IN: TXO F,<F$PIM!F$READ!F$EOMN>
;No local echo, PIM, always read active
;No EOM except on last buffer
PUSHJ P,SETQUO ;Set link quotas
PJRST TTYSST
SUBTTL Unsupported System support
DOCPM:
DOMSDS:
DOUX11:
DOPS11:
DOELAN:
DORT11:
DOIAS:
DORTS8:
DOOS8:
DOCOPOS:
DORXMP:
DOUNK: ERR USP,<Unsupported Protocol found>
SUBTTL O/S Name table
;PLM
;+
;.Chapter Data Tables
;.hl
MLP
; The rest of the program is concerned with the data tables and
;variables used by the program:
PLM
;.list 1
;.le
MLP
;Table OSNAME is a list of SIXBIT text names indexed by the operating
;system type as returned in the configuration message.
PLM
;-
MLP
OSNAME: 'RSTS-E' ;Old RSTS
'RT-11 '
'RSTS/E'
'RSX11S'
'RSX11M'
'RSX11D'
'IAS '
'VMS '
'TOPS20'
'TOPS10'
'RTS-8 '
'OS-8 '
'RSX-M+'
'COPOS '
'P/OS '
'ELAN '
'CP/M '
'MS-DOS'
'ULTRIX'
'ULTRIX'
SUBTTL Protocal Dispatch Blocks -- RSTS
PLM
;+
;.le
MLP
;The following are the protocol dispatch blocks for each type of operating
;system type. They defined the legal functions for each operating system.
;The format of an entry in a table is "dispatch-address,,function-key-value".
PLM
;.list 1
;.le
MLP
;RSSFNC is the protocol block for RSTS.
PLM
;-
MLP
RSSFNC: RST.CT,,MT$CTL ;Control
RST.DA,,MT$DAT ;Data
Z
SUBTTL Protocal Dispatch Blocks -- RSX
PLM
;+
;.le
MLP
;RSXFNC is the protocol block for RSX.
PLM
;-
MLP
RSXFNC: RX.WRT,,RF.WTD ;Write Data (3)
RX.PRD,,RF.WRD ;Write-then-read (5)
RX.RED,,RF.RDD ;Read Data (4)
RX.NOP,,RF.NOP ;No-op (0)
RX.KIL,,RF.KIL ;Kill I/O (8)
RX.SSC,,RF.RSC ;Single-char input (7)
RX.SUN,,RF.UNS ;Unsolicited input (6)
RX.DIS,,RF.DIS ;Disconnect link
RX.DAT,,RF.ATT ;ATTACH/DETACH
RX.GTC,,RF.GTC ;Get terminal characteristics
RX.STC,,RF.STC ;Set terminal characteristics
Z
SUBTTL Protocal Dispatch Blocks -- VMS
;PLM
;+
;.le
MLP
;VMSFNC is the protocol block for VMS.
PLM
;-
MLP
VMSFNC: VMS.PW,,VF.WPH ;Write
VMS.DA,,VF.WLB ;
VMS.DA,,VF.WVB ;
VMS.RA,,VF.RPH ;Read
VMS.RD,,VF.RLB ;
VMS.RD,,VF.RVB ;
VMS.PD,,VF.RPR ;Read with prompt
VMS.RA,,VF.RAL ;Readall
VMS.PA,,VF.RPA ;Readall with prompt
VMS.KI,,VF.ACC ;Kill I/O
VMS.ST,,VF.STM ;Set mode
VMS.ST,,VF.STC ;
VMS.SN,,VF.SNM ;Sense mode
VMS.SN,,VF.SNC ;
VMS.BC,,VF.BCS ;Broadcast
Z
PLM
;+
;.end list
;-
MLP
SUBTTL Lowseg Initializers Stored in Hiseg
PLM
;+
;.le
MLP
;HILOST is the start of a section of initializing data for the low segment.
;.list 1
PLM
;-
MLP
HILOST: ;This gets BLTted to the Loseg
IFN FTPSECT,<.PSECT .LOW.>
IFE FTPSECT,<RELOC 0>
LOLOST:
IFN FTPSECT,<.PSECT .HIGH.>
IFE FTPSECT,<RELOC>
PHASE LOLOST
SUBTTL NSP. Connect Block
PLM
;+
;.le
MLP
;CONBLK, SRCPDB, DSTPDB, and SRCNAM are the prototype parts of
;NSP. argument blocks.
PLM
;-
MLP
CONBLK: EXP .NSCUD+1 ;ENTER ACTIVE CONNECT BLOCK
EXP ASCNOD ;NODE NAME STRING BLOCK
EXP SRCPDB ;SOURCE PROCESS BLOCK
EXP DSTPDB ;DESTINATION PROCESS BLOCK
EXP USERID ;USERID STRING BLOCK
EXP PASSWD ;PASSWORD STRING BLOCK
EXP ACCOUN ;ACCOUNT STRING BLOCK
EXP USERDA ;USER DATA STRING BLOCK
SRCPDB: .NSDPN+1 ;Length of block
DEC 1 ;Format type
.OBGEN ;Object(=0)
Z ;PPN
SRCNAM ;Pointer to name block
SRCNAM: XWD ^D11,4 ;11 bytes, four words
ASCII8 <TOPS-10 NRT>
PLM
;+
;.le
MLP
;TOBUF is the header for the terminal output buffer.
TOFLGS: BLOCK 1 ;Flags to include when buffer queued
BUFQUO: EXP OUTQUO ;Number of output buffers which can be queued
TOBUF: BLOCK 3 ;Used by us
TOBFH: BLOCK 3 ;Used by OUT UUO
TOQUE: BLOCK 1 ;Output buffer queue
PLM
;-
MLP
PLM
;+
;.le
MLP
;HPSTRM is the argument block for the maintenance of horizontal position data
PLM
;-
MLP
HPSTRM: EXP .TOHPS+.TOSET
HPSUDX: BLOCK 1 ;For fast access
HPOS: EXP Z ;The position
PLM
;+
;.le
MLP
;ECCTRM is for checking if characters are pending to be echoed.
PLM
;-
MLP
ECCTRM: EXP .TOECC
ECCUDX: BLOCK 1
PLM
;+
;.le
MLP
;BKCTRM is for obtaining the count of break characters in the input buffer
PLM
;-
MLP
BKCTRM: EXP .TOBKC
BKCUDX: BLOCK 1
PLM
;+
;.le
MLP
;PAGTRM is for checking the setting of the page bit.
PLM
;-
MLP
PAGTRM: EXP .TOPAG
PAGUDX: BLOCK 1
PLM
;+
;.le
MLP
;CTOTRM is used to check the ^O bit; CTOTRS is for setting the ^O bit.
PLM
;-
MLP
CTOTRM: EXP .TOOSU
CTOUDX: BLOCK 1
CTOTRS: EXP .TOOSU+.TOSET
COSUDX: BLOCK 1
COSVAL: BLOCK 1
PLM
;+
;.le
MLP
;BMASK is the default (TOPS-10) break mask.
PLM
;-
MLP
BMASK: EXP 255 ;Field size
BRKMSK <CGJKLZ[>
PLM
;+
;.le
MLP
;TTYBLK is the OPEN block for device TT:.
PLM
;-
MLP
TTYBLK: Z
SIXBIT 'TT'
TOBFH,,TIBUF
PLM
;+
;.le
MLP
;TTYSAV is the table of TTY: characteristics to be saved on entering NRT
;and restored later.
PLM
;-
MLP
TTYSAV: ;Start of table of saved TTY: chars.
TRMCHR SLV
TRMCHR LCT ;Lower case
TRMCHR NFC ;Free <CR>
TRMCHR LCP
TRMCHR WID ;Width
TRMCHR LNB ;Page size
TRMCHR DIS ;Display bit
TRMCHR BLK ;Blanks
TRMCHR XNF ;XON/XOFF bit
TSVNUM==.-TTYSAV ;Number of characteristics
PLM
;+
;.le
MLP
;TTYSET is a table of terminal characterstics which NRT wishes to
;be set a particular way while it runs. Entries in TTYSET should also
;be in TTYSAV.
PLM
;-
MLP
TTYSET: TRMCHR SLV,-1,ST
TRMCHR BLK,0,ST
TSTNUM==.-TTYSET
SUBTTL Special stuff for VAX
PLM
;+
;.le
MLP
;VMTTCH is storage for VMS terminal characteristics. The default
;type of terminal we set is a TTY:.
PLM
;-
MLP
VMTTCH: <BYTE (8)0,0,DT$TTY,DC$TERM>_-4
Z
Z
SUBTTL Special stuff for RSX
PLM
;+
;.le
MLP
;RXCHTB is storage for the RSX terminal characteristics.
PLM
;-
MLP
RXCHTB: BLOCK RC.MAX ;Terminal characteristics table
PLM
;+
;.LE
MLP
;LEDTRM and LEDUDX are used to check to see if, during type-ahead,
;the user typed some line editing characters.
PLM
;-
MLP
LEDTRM: .TOSBS ;Set break mask
LEDUDX: BLOCK 1 ;UDX
^D255 ;Mask size
EXP <1B<.CHCNU>!1B<.CHCNR>>,0,0,1B31 ;All the interesting bits
PLM
;+
;.end list
;-
MLP
LOLOND:
DEPHASE
SUBTTL Useful break masks
PLM
;+
;.le
MLP
;Default break masks:
PLM
;.list 1
;.le
MLP
;VXDMSK is the VAX default break mask.
PLM
;-
MLP
VXDMSK: ^D255
BRKMSK <ABCDEFGMNOPQRSTUVWXYZ[\]^_>
PLM
;+
;.le
MLP
;RXDMSK is the default RSX break mask.
PLM
;-
MLP
RXDMSK: ^D255
BRKMSK <CGJMNZ[\]^_>
PLM
;+
;.le
MLP
;RSTDMK is the default RSTS break mask
PLM
;-
MLP
RSTDMK: ^D130
BRKMSK <CJMOTYZ[>
PLM
;+
;.end list
;-
MLP
SUBTTL Terminal information tables
PLM
;+
;.le
MLP
;The next set of tables are TTY: type tables. This is so we can
;pass intelligently the type of terminal we are to the remote host.
;The index into each table should yield the corresponding terminal
;type for the appropriate operating system.
PLM
;.list 1
;.le
MLP
;TTPTB is the TOPS-10 version of the table.
PLM
;-
MLP
TTPTB: SIXBIT/VT52/ ;Type VT52
SIXBIT/VT100/ ;Type VT100
SIXBIT/VT61/ ;Type VT61
SIXBIT/VT102/ ;Type VT102
SIXBIT/VT101/ ;Type VT101
SIXBIT/VT132/ ;Type VT132
SIXBIT/VT125/ ;Type VT125
SIXBIT/VT103/ ;Type VT103
SIXBIT/VT180/ ;Type VT180
SIXBIT/VT185/ ;Type VT185
TTPLEN==.-TTPTB
PLM
;+
;.le
MLP
;VTPTB is the VMS terminal type table.
PLM
;-
MLP
;VMS corresponding types (must be same order)
;Left half is the high order byte of the TT2 characteristics, or the
;DEC/ANSI CRT byte
VTPTB: VTTCHR (0,V52) ;VT52
VTTCHR (<T2ACRT!T2DCRT>,V100) ;VT100
VTTCHR (0,V5X) ;VT%x
VTTCHR (<T2ACRT!T2DCRT>,102)
VTTCHR (<T2ACRT!T2DCRT>,101)
VTTCHR (<T2ACRT!T2DCRT>,132)
VTTCHR (<T2ACRT!T2DCRT>,V125)
VTTCHR (<T2ACRT!T2DCRT>,101)
VTTCHR (<T2ACRT!T2DCRT>,V100)
VTTCHR (<T2ACRT!T2DCRT>,V125)
IFN <.-VTPTB-TTPLEN>,<
PRINTX %Incorrect number of VAX terminal types
>
PLM
;+
;.le
MLP
;RTPTB is the RSX terminal type table
PLM
;-
MLP
RTPTB: RXV52 ;VT52
RXV100 ;VT100
RXV61 ;VT61
RXV102 ;VT102
RXV101 ;VT101
RXV132 ;VT132
RXV125 ;VT125
RXV102 ;VT103
RXV100 ;VT180
RXV125 ;VT185
IFN <.-RTPTB-TTPLEN>,<
PRINTX %Incorrect # of RSX terminal types
>
PLM
;+
;.le
MLP
;RXTRMP is the table of TRMOP. functions to do (including .TOSET) for
;SET TERMINAL CHARACTERISTICS messages.
;Bit 0 in the left half indicates that the value should be complemented
;before doing the TRMOP.
PLM
;-
MLP
RXTRMP:
Z ;Zero (undefined)
REPEAT ^D15,<
Z ;1-15 undefined
>
400000,,.TOSET+.TOLCT ;Lower case
.TOSET+.TOFRM ;Form feed
.TOSET+.TOTAB ;Tab
Z ;Handled by F$NEC
Z ;Can't change baud rate
Z ;Can't change baud rate
.TOSET+.TOTRM ;Terminal type
.TOSET+.TODIS ;Display bit
Z ;Handled by F$PALL
.TOSET+.TOSTP ;XON/XOFF done
.TOSET+.TOFLC ;Fill class (horizontal)
.TOSET+.TOFLC ;Fill class (vertical)
.TOSET+.TOPSZ ;Page size
Z ;Enable/disable type-ahead (can't do)
Z ;Handled separately
Z ;Eight bit ascii
Z ;Can't be changed
Z ;Can't be changed
Z ;Control-C flush (always on)
Z ;Full duplex (always on)
Z ;Local GAG (can't do)
Z ;Read type-ahead
Z ;Enable lowercase output
Z ;Force lowercase input
PLM
;+
;.end list
;-
MLP
PLM
;+
;.le
MLP
;QUOTBL is the link quota and percentage goal table, indexed by
;TTY: baud rate. The left half of each entry is the percentage to allocate
;for input; the right half is the goal.
PLM
;-
MLP
QUOTBL: -1 ;Default
-1 ;Assume 50 is really 19.2K
^D7,,0 ;75 BAUD
^D7,,0 ;110 BAUD
^D7,,0 ;134.5 BAUD
^D15,,0 ;150 BAUD
^D15,,1 ;200 BAUD
^D15,,1 ;300 BAUD
^D22,,1 ;600 BAUD
^D22,,2 ;1200 BAUD
^D30,,2 ;1800 BAUD
^D40,,3 ;2400 BAUD
QUOMAX==.-QUOTBL ;4800 and 9600 at MAX
PLM
;+
;.le
MLP
;SEGTBL is the segment size table, also based on baud rate.
PLM
;-
MLP
SEGTBL: 0 ;Default
0 ;Assume 50 is really 19.2K
^D30 ;75
^D30 ;110
^D30 ;134.5
^D30 ;150
^D30 ;200
^D30 ;300
^D60 ;600
^D60 ;1200
^D100 ;1800
^D100 ;2400
SEGMAX==.-SEGTBL ;Above 2400, use default
SUBTTL Terminal strings for <RUB>
PLM
;+
;.le
MLP
;RUBS1 is the rubout string table, indexed by terminal type (same as
;the terminal type tables above).
PLM
;-
MLP
RUBS1: [BYTE (7)^D8,40,^D8] ;VT52: <BSP><SP><BSP>
[BYTE (7)^D8,40,^D8] ;VT100: <BSP><SP><BSP>
[BYTE (7)^D8,40,^D8] ;VT61: <BSP><SP><BSP>
[BYTE (7)^D8,40,^D8] ;VT102: <BSP><SP><BSP>
[BYTE (7)^D8,40,^D8] ;VT101: <BSP><SP><BSP>
[BYTE (7)^D8,40,^D8] ;VT132: <BSP><SP><BSP>
[BYTE (7)^D8,40,^D8] ;VT125: <BSP><SP><BSP>
[BYTE (7)^D8,40,^D8] ;VT103: <BSP><SP><BSP>
[BYTE (7)^D8,40,^D8] ;VT180 <BSP><SP><BSP>
[BYTE (7)^D8,40,^D8] ;VT185 <BSP><SP><BSP>
IFN .-RUBS1-TTPLEN,<
PRINTX %Number of rubout strings doesn't match number of types
>
SUBTTL Literal storage
XLIST
LIT
LIST
PLM
;+
;.end list
;-
MLP
SUBTTL STORAGE
RELOC LOLOND+1 ;THIS STUFF MUST BE IN THE LOW SEG
PLM
;+
MLP
;The rest of the low segment data should be reasonably well documented
;in the comments in the source and hence will not be documented here.
PLM
;-
MLP
FSTZER:!
IBFCNT: BLOCK 1 ;Count of bytes input
IBFPTR: BLOCK 1 ;Byte pointer to data
OBFCTR: BLOCK 1 ;Count of bytes left in buffer
OBFPTR: BLOCK 1 ;Pointer to next byte in buffer
;Here are the volitile NSP. blocks:
ASCNOD: BLOCK 3 ;NODE NAME
USERID: BLOCK 10 ;USER-ID
PASSWD: BLOCK 10 ;PASSWORD
ACCOUN: BLOCK 10 ;ACCOUNT
USERDA: BLOCK 10 ;USER DATA
NSPECD: BLOCK 1 ;ERROR CODE FOR SETNER
FTZER: ;FIRST WORD OF TTY DATA BASE TO ZERO
LSTCHR: BLOCK 1 ;Storage for last character just typed
TRMLEN: BLOCK 1 ;Terminator length
INPCHR: BLOCK 1 ;Saved TTY input Character
TIBUF: BLOCK 3 ;TTY input buffer header
BYTPWD: BLOCK 1 ;Current I/O byte size
CHPBUF: BLOCK 1 ;Number of characters in buffer
BUFCHR: BLOCK 1 ;LH(byte pointer),,#words in buffer
LASTT2: BLOCK 1 ;Pointer to last word in buffer indexed by T2
ICHCNT: BLOCK 1 ;Number of characters available
LICHCT: BLOCK 1 ;Remember value of ICHCNT
INPQUE: BLOCK 1 ;Pointer to input blocks
LTZER==.-1 ;Last word to zero on TTY reset
PROTMD: BLOCK 1 ;Protocol modifier
OSTYPE: BLOCK 1 ;What kind of system is this?
OSTTY: BLOCK 1 ;Routine to handle TTY input for this OS
OSNET: BLOCK 1 ;Routine to handle network input for this OS
;The interrupt level database interlock
INTLVL: BLOCK 1 ;..
SLPFLG: BLOCK 1 ;Flag, set to 1 if we're sleeping
;for output to complete
;The TTY interrupts which have been requested. Zero on exit from TTY: service
;IOR requested conditions in when an interrupt is deferred.
TTYSTS: BLOCK 1
;These are the fake buffers that are used by NSPIN and NSPOUT.
OTPBUF: BLOCK 1 ;Pointer to output buffer
;Note that sign bit set means DON'T set EOM
OUTQUE: BLOCK 1 ;Pointer to the output queue
INPBUF: BLOCK ^D<132/4>+^D10 ;Network Input data
BFLEN==.-INPBUF ;Length of the buffer
IBUFSZ==<.-INPBUF>*4-1 ;LENGTH IN BYTES
IFN FTPMR,<
RNODE: BLOCK MAXPMR+1 ;Remote node ID
NODCNT: BLOCK 1 ;Count of number of nodes in string
PMRCNT: BLOCK 1 ;Storage for length of string
PMRMSG: BLOCK MAXPMR+5 ;For the PMR connect string
> ;End IFN FTPMR
IFE FTPMR,<
RNODE: BLOCK 1 ;Remote node name
>
CHRTAB: BLOCK <^D256/^D36>+1 ;Special character table
TTYTYP: BLOCK 1 ;Index into TTY: type tables
OBMASK: BLOCK 2 ;Out of band include & exclude masks
;(VMS)
XSPCNT: BLOCK 1 ;Count of ^Cs in buffer to skip
XSCREQ: BLOCK 1 ;Pointer to request block for Read Single Characters (RSX)
XUNREQ: BLOCK 1 ;Pointer to request block for Unsolicited input (RSX)
BRKCHR: ;(LH) Char to be considered as "break" char
BRKSIZ: BLOCK 1 ;(RH) Size of break string (VMS escape seq.)
LSTZER==.-1 ;End of Zeroable low segment
NOTICH: BLOCK 1 ;Notification string
;Break mask
TRMBKS: EXP .TOSBS ;Set the break set
TTYUDX: BLOCK 1 ;Storage for UDX of my TTY
FALL IMASK
IMASK: BLOCK 5 ;For break Mask
ENDMSK==.-1
FALL LMASK ;***THESE MUST BE CONTIGUOUS***(RX.SCS)
LMASK: BLOCK 4 ;"Local" or "logical" break mask
ELMASK==.-1
CTLTTY: BLOCK 1 ;IONDX for controlling TTY:
NODBLK: BLOCK .DNNMS+1 ;For DNET. UUO
BRKNUM: BLOCK 1 ;Number of breaks to ignore in input
BRKCNT: BLOCK 1 ;Counter in scanning for above
ESCCHR: BLOCK 1 ;Char to escape from program
ESCBIT: BLOCK 1 ;Bit mask for escape character
ESCWRD: BLOCK 1 ;Word offset for the mask bit
READQ: BLOCK 1 ;Pointer to queued reads for VAX, RSX
SENSEQ: BLOCK 1 ;Queued Sense Request (VAX)
RSXSVF: BLOCK 1 ;Saved F for RSX (Control-O)
UNSCNT: BLOCK 1 ;Unsolicted count (VAX, really full word flag)
RSTFLG: BLOCK 1 ;RESTART flag
RULE: BLOCK 1 ;Current rule number for ANSI escape sequences
TTBAUD: BLOCK 1 ;BAUD rate code for controlling TTY:
DSKHDR: BLOCK .BFCTR+1 ;Block for SWITCH.INI input
SUBTTL NSP. UUO DSTPDB Block
DSTPDB: .NSDOB+1 ;Length of block
DEC 0 ;FORMAT TYPE
.OBHTH ;OBJECT NUMBER OF NRT SERVER
SUBTTL Configuration & Control Messages
;Each of the following messages is preceded by its length
DEFINE NETMSG (LENGTH,STRING)<
EXP LENGTH
BYTE (8) STRING
>
RST$CF: NETMSG ^D10,<MT$CFG,^D10,0,OST10,0,0,0,0,0,0> ;RSTS CONFIG MSG
RST$UN: NETMSG 5,<MT$DAT,5,0,1,.CHCNZ>
RSX$CF: NETMSG ^D42,<RF.SSD,1,0,0,OST10,0,2,0,^D132,0,
RC.VER,1,
RC.TBL,^D255,
RC.CCT,1,
RC.SCI,1,
RC.WBT,1,
RC.CAO,1,
RC.RNE,1,
RC.RTC,1,
RC.CRT,1,
RC.RIL,1,
RC.RWB,1,
RC.UNS,1,
RC.SCX,1,
RC.RTT,1,
RC.RTM,1,
RC.CUR,0> ;No cursor addressing
RSX$UN: NETMSG 4,<RF.ECR,0,0,RE.SAR>
;This defaults to version 3 protocol. It will be changed accordingly
VMS$CF: NETMSG 24,<1,1,1,0,11,0,4,0,DC$TERM,DT$TTY,0,0,200,0,0,0,0,0,0,0>
VMS$UN: NETMSG 4,<VR.ATT,377,RA.UNS,0>
SUBTTL Performance analysis low segment
IFN FTPERF,<
TSTPTR: BLOCK 1 ;Storage for pointer to string
TSTLFT: BLOCK 1 ;Number of characters left to send
COMLEN: BLOCK 1 ;# characters in record
COMREC: BLOCK ^D50 ;250 characters max
TSTREP: BLOCK 1 ;Number of reps to do
TSTBEG: BLOCK 1 ;MSTIME at start
TSTEND: BLOCK 1 ;MSTIME at end
TSTTOT: BLOCK 1 ;Total # of Milliseconds it took
TSTTIM: BLOCK 1 ;UDT time at beginning
FILBLK: BLOCK ^D8 ;FILOP. UUO block
FOBUF: BLOCK 3 ;File output header
FIBUF: BLOCK 3 ;File input header
PRFFIL: SIXBIT /NETRSP/
SIXBIT /DAT/
Z
Z
Z
> ;End IFN FTPERF
SUBTTL Low segment for Interrupt system
VECBAS:
TTYVEC: EXP TTYPSI,0,0,0
NSPVEC: EXP DCNPSI,0,0,0
TMRVEC: EXP TMRPSI,0,0,0 ;Filled in when needed
DATVEC: EXP DATPSI,0,0,0
WAKVEC: EXP WAKPSI,0,0,0
PSYNSP: EXP .PCNSP
NSPVEC-VECBAS,,0
Z
PSYTMR: EXP .PCTMR ;Arg block for TIMER PSIs
TMRVEC-VECBAS,,0
Z
SUBTTL .JBINT stuff
LOC .JBINT
EXP ERRBLK
RELOC
ERRBLK: EXP ERRTRP,ER.ICC!ER.EIJ!ER.TLX!ER.QEX!ER.FUL!ER.OFL,0,0
SUBTTL Data base for timed I/O requests
OSTMR: Z ;Filled in at run time, OS specific
;timer trap processor
TMRSEQ: Z ;Identifier for request being timed
SUBTTL Low segment for core manager
FRELST: BLOCK 1 ;Pointer to linked list of free blocks
HICORE: BLOCK 1 ;Highest location gotten with CORE UUO
SUBTTL Low segment AC blocks and PDLs
PDL: BLOCK PDLLEN ;Non-interrupt PDL
NSPPDL: BLOCK PDLLEN ;NSP interrupt PDL
TTYPDL: BLOCK PDLLEN ;TTY: service PDL
TMRPDL: BLOCK PDLLEN ;Timer service PDL
NSPACS: BLOCK 20 ;For NSP.'s ACs
TTYACS: BLOCK 20 ;TTY: service ACs
TMRACS: BLOCK 20 ;Timer trap ACs
CRSACS: BLOCK 20 ;For crash ACs
CRSPDL: BLOCK 10 ;For resetting things
SUBTTL End of Program
END GO