mirror of
https://github.com/PDP-10/its.git
synced 2026-04-03 04:37:53 +00:00
Add most missing SYSDOC files.
This commit is contained in:
committed by
Eric Swenson
parent
596237d05e
commit
196263051c
118
doc/info/netwrk.1
Executable file
118
doc/info/netwrk.1
Executable file
@@ -0,0 +1,118 @@
|
||||
-*-Mode:Text-*-
|
||||
|
||||
File: NETWRK Node: Top Up: (DIR)
|
||||
|
||||
This file attempts to describe various computer networks of two types --
|
||||
those to which ITS systems are directly connected, and those which are of
|
||||
interest to the ITS user community because they link up personal computers or
|
||||
research institutions that are not accessible by the first kind of network.
|
||||
There are two networks to which ITS machines are connected: the ARPANet and
|
||||
the Chaosnet. These networks support file transfer, mail, remote login, and
|
||||
other services -- they may appear to be quite similar to the user, but have
|
||||
differing implementations. All the other networks documented herein are
|
||||
mostly for mail and file transfer.
|
||||
|
||||
* Menu:
|
||||
|
||||
* ARPANet: (Internet) The Arpanet
|
||||
|
||||
* Chaosnet: (CHAOS) The Chaosnet
|
||||
|
||||
* User programs for either of the above
|
||||
|
||||
* Internet: (Internet) The Internet
|
||||
|
||||
* CSNET: (CSNET) The NSF CSnet.
|
||||
|
||||
* PCNET: (MC:PCNET;PCNET INFO) Personal Computer Network
|
||||
|
||||
Internet
|
||||
|
||||
The Internet is a very large computer network that connects various
|
||||
educational, military, and commericial establishments, all involved in some
|
||||
way in computer science research. It is actually a ``catenet'' of many
|
||||
computer networks that run a protocol, the Internet Protocol, to allow
|
||||
packets to be sent from one host to another, possibly through several other
|
||||
networks. An accompanying protocol called TCP provides a reliable byte
|
||||
stream that programs can use, thus ignoring data errors and all the other
|
||||
nitty-gritty details involved in getting a packet from here to there.
|
||||
|
||||
The ARPANet is perhaps the most famous of the Internet networks. It
|
||||
stretches from Massachusetts to Stanford. Before the days of Internet, it
|
||||
ran a protocol called NCP, which, unfortunately, was beginning to show its
|
||||
age. (The ARPANet is at least ten years old.) Because the net had ceased to
|
||||
become a research project, turning into a heavily-used resource, it was
|
||||
decided that it would be interesting, now that a long-haul network was shown
|
||||
feasible, to try to connect various networks together. Then the hosts on
|
||||
these networks, all differing in one characteristic or another, could talk to
|
||||
each other without having to contact special hosts that would translate one
|
||||
high-level protocol into another. IP came out of this desire. (In a false
|
||||
start, all the internetwork issues were going to be resolved in the TCP
|
||||
layer, but the details were wisely factored out.) So the ARPANet become
|
||||
``just another'' network in the Internet, although it still carries most of
|
||||
the long-distance traffic.
|
||||
|
||||
When the switch from ARPAnet to Internet in software was made, it was a
|
||||
cataclysm underneath, but the user could not notice much. Most of the
|
||||
high-level protocols used in the NCP days were simply carried over: Telnet,
|
||||
SUPDUP (where it was implemented), FTP, and SMTP. Some ITS user programs
|
||||
contain commands to switch from TCP to NCP mode, though this is not usually
|
||||
required.
|
||||
|
||||
At MIT, Internet appears in a variety of ways. First, there is the ARPANet.
|
||||
The second type of network to embrace IP was the LCS/Pronet Ring net. The
|
||||
main users of these networks are the LCS VAXes and many of the Athena
|
||||
machines. Thirdly, there are Ethernets at Tech Square who run IP, usually
|
||||
along with Chaosnet. The users of this mode include some VAXes at the AI
|
||||
Lab, and some LCS machines. And last, but not least, the Chaosnet can also
|
||||
support Internet (after much heated discussion). A few Unix machines have
|
||||
taken this option.
|
||||
|
||||
As for the ITS machines, they all connect to the Internet through their
|
||||
ARPANet IMPs. The Internet host tables can be found in SYSENG; HSTNIC >
|
||||
ITS implements both server and user programs for FTP, TELNET, and SUPDUP.
|
||||
The MLDEV is also supported. There is also an SMTP (mail) server. Sources
|
||||
for various TCP-related programs can be found in the TCP; directory on MC.
|
||||
For programmers, there is a quick rundown of the ITS TCP interface (and
|
||||
documentation that applies to network system calls in general) in
|
||||
TCP;TCPDOC > The network status can be checked with the PEEK program.
|
||||
|
||||
CHAOS
|
||||
|
||||
The Chaosnet was developed at the MIT AI lab as a local network to allows
|
||||
Lisp Machines (CADRs, specifically) to access files on AI and MC. Its
|
||||
success caused it to become the most widely used local network at MIT. The
|
||||
following operation systems have support Chaosnet: LispM, ITS, Twenex, Tenex,
|
||||
Unix, Multics, VMS, Seconds, MINITS, and MOS. The last three are used
|
||||
mainly in terminal concentrators and bridges. Chaosnet has also been used at
|
||||
Yale, TI, and many other Lisp Machine installations. The definitive Chaosnet
|
||||
documentation can be found in AI Memo 628, ``Chaosnet,'' by David Moon.
|
||||
|
||||
Chaosnet started out being supported by special Chaosnet hardware, but is now
|
||||
mostly used with Ethernet II hardware. Leased serial lines and microwave
|
||||
links have also been used to run Chaosnet. It is stressed that Chaosnet is
|
||||
local network, but it has been used with some success transcontinentally.
|
||||
|
||||
On ITS, most programs (except FINGER) will automatically chose to use the
|
||||
Chaosnet. Here is a list of current user and server programs:
|
||||
|
||||
Service Protocol User Server
|
||||
--------------------------------------------------------------
|
||||
Remote Login TELNET :TELNET yes
|
||||
SUPDUP :SUPDUP yes
|
||||
File Access FILE :CFTP yes
|
||||
Mail MAIL (COMSAT) yes
|
||||
SMTP (COMSAT) yes
|
||||
TTY send SEND :SEND yes
|
||||
CONVERSE
|
||||
|
||||
There are also the usual servers for HOSTAB, TIME, UPTIME, and STATUS. All
|
||||
ITS machines offer a TCP server as well -- it allows Chaosnet hosts to
|
||||
contact Internet hosts at a specified port number. There is also a GMSGS
|
||||
server and a LIMERICK server.
|
||||
|
||||
For contacting a host at an arbitary contact name, use
|
||||
|
||||
:MOON;CHARFC host contact
|
||||
|
||||
The K PEEK mode will show that status of the Chaosnet.
|
||||
1
doc/sysdoc/-read-.-this-
Executable file
1
doc/sysdoc/-read-.-this-
Executable file
@@ -0,0 +1 @@
|
||||
This directory (SYSDOC) contains system documentation for ITS.
|
||||
2184
doc/sysdoc/chaord.57
Executable file
2184
doc/sysdoc/chaord.57
Executable file
File diff suppressed because it is too large
Load Diff
760
doc/sysdoc/chaos.file
Executable file
760
doc/sysdoc/chaos.file
Executable file
@@ -0,0 +1,760 @@
|
||||
-*- Mode:Text -*-
|
||||
|
||||
Description of the CHAOS FILE protocol designed by HIC.
|
||||
|
||||
The CHAOS FILE protocol is a protocol used to give access to the
|
||||
file systems of remote hosts on the CHAOS net. Provided that the
|
||||
foreign host has a CHAOS FILE server, one can read and write files,
|
||||
delete, rename, etc. The protocol was originally designed to give LISP
|
||||
machines access to the file systems of our PDP/10's, but is general
|
||||
enough to support file transfer between 10's, and other purposes.
|
||||
|
||||
We will describe the protocol from the point of view of the
|
||||
user, i.e., the implementor of a user program communicating to a foreign
|
||||
server. Hence, terms such as "receive", "send", "input", and "output"
|
||||
are from a user's point of view, unless explicitly indicated. The first
|
||||
step in using the protocol is to open what is called a CONTROL
|
||||
connection to the server on the foreign host. A CONTROL connection is
|
||||
simply a standard CHAOS net connection to the contact name "FILE" on the
|
||||
foreign host. The CONTROL connection is used to send commands, and
|
||||
receive responses and most error message.
|
||||
|
||||
When reading or writing files, actual data is sent over separate
|
||||
CHAOS net connections called DATA connections. DATA connections are
|
||||
opened in conjunction with the foreign host, using commands on the
|
||||
CONTROL connection. Hence, the CONTROL connection must be opened first.
|
||||
We will present the details below; but here are some preliminary facts
|
||||
about DATA connections. Like CONTROL connections, DATA connections are
|
||||
bidirectional. Each half (send and receive) of a DATA connection is
|
||||
used independently, so two file transfers may be active on a DATA
|
||||
connection at the same time (but they must be in opposite directions).
|
||||
There may be more than one DATA connection per CONTROL connection, but
|
||||
each DATA connection is associated with a particular CONTROL connection.
|
||||
This is because each CONTROL connection deals with a separate
|
||||
incarnation of the server at the foreign host. We also note that DATA
|
||||
connections are re-usable, i.e., can be used for many file transfers.
|
||||
Simple programs might very well get by with a single DATA connection,
|
||||
but it is possible to have several (the actual limit depends on
|
||||
resources of the foreign host, and is 3 for ITS servers, and 8 for
|
||||
TOPS-20 servers).
|
||||
|
||||
The protocol is organized so that commands and responses have a
|
||||
fairly uniform syntax. Further, each command (response) is sent
|
||||
(received) in a single packet. Each command has a field for a unique
|
||||
identifier, called the transaction id, or "tid" for short, which
|
||||
identifies it. This is because the protocol permits asynchronous
|
||||
processing of commands and responses, i.e., you can send a new command
|
||||
without waiting for the response to the previous one. However, it is a
|
||||
good idea to read the responses as they come in, so the server will not
|
||||
block trying to send responses to you. The server is coded so that it
|
||||
will not block if DATA connection packets back up.
|
||||
|
||||
Let us now discuss the details of command and response packets.
|
||||
We will discuss error processing later. Each command must be sent in a
|
||||
separate packet on the CONTROL connection. The packet must have the
|
||||
packet opcode for ASCII data (%CODAT = 200). When you are done with the
|
||||
CONTROL connection and wish to disconnect from the foreign host, you
|
||||
should send an EOF packet (%COEOF = 014) on the CONTROL connection.
|
||||
This will cause the server to abort any transfers in progress, close all
|
||||
DATA connections pertaining to this CONTROL connection, and close the
|
||||
CONTROL connection.
|
||||
|
||||
Responses to commands, successful or not, will come as data
|
||||
packets (i.e., opcode %CODAT) on the CONTROL connection. The only other
|
||||
kind of packet you should see on the CONTROL connection (unless there
|
||||
are network problems) and asynchronous mark packets, which will be
|
||||
discussed later.
|
||||
|
||||
The contents of a command or response packet is simply the
|
||||
sequence of ASCII bytes in the data portion of the packet. Fields are
|
||||
generally separated by either spaces (040) or LISP machine newline
|
||||
characters (NL = 215). We remark now that certain parts of the protocol
|
||||
are oriented towards the LISP machine character set, which consists of
|
||||
256 characters. This is in contrast to the 128 character set standard
|
||||
on PDP/10's. The printing characters generally have the same
|
||||
interpretation, though. Later we will explain the character set
|
||||
translation features provided by the protocol in detail.
|
||||
|
||||
Here is the format of command and response packets:
|
||||
|
||||
command: tid <sp> [ fh ] <sp> cmd [ args ]
|
||||
response: tid <sp> [ fh ] <sp> cmd [ <sp> results ]
|
||||
|
||||
<sp> means a space character (040), and brackets surround
|
||||
optional fields. Each field is a sequence of printing characters. Here
|
||||
is the interpretation and format of the common fields:
|
||||
|
||||
tid: Transaction identifier, used only to help the user program sort
|
||||
out replies. Only the first 5 characters are significant; the
|
||||
rest are discarded, and will not appear in a response. Tid's
|
||||
may vary or be the same, as you wish.
|
||||
|
||||
fh: File handle, used to identify a DATA connection, and a direction
|
||||
(in/out). That is, each DATA connection has two file handles
|
||||
associated with it, one for indicating input (transfer to you
|
||||
from the foreign host), and one for output (transfer from you to
|
||||
the foreign host). Like tid's, file handles are also unique
|
||||
only in the first 5 characters.
|
||||
|
||||
cmd: A command name. Only the first 5 characters are actually read
|
||||
at the current time, but this should not be depended upon. The
|
||||
full name of the command always appears in the response.
|
||||
Command names must be presented in upper case.
|
||||
|
||||
The "args" and "results" fields vary depending on the command,
|
||||
and will be described with each command below. The response to a
|
||||
particular command will have the same tid as the command, and also the
|
||||
same file-handle (if relevant), and the same command name. The only
|
||||
differences are that the tid and file handle in the response will be
|
||||
truncated to 5 characters, and the command name will always appear in
|
||||
full.
|
||||
|
||||
Conventions used in the descriptions:
|
||||
|
||||
Numbers we write (e.g., packet opcodes, ASCII codes, etc.) are
|
||||
in octal, unless followed by a decimal point, in which case they are
|
||||
decimal. Byte sizes are an exception to this rule: they are always in
|
||||
decimal, even if not followed by a decimal point.
|
||||
<none> means an empty field in a packet.
|
||||
<num> means a sequence of ASCII characters that are all digits
|
||||
(codes 060 through 071, i.e., '0' through '9'). Such numbers are always
|
||||
expressed in decimal. These numbers are unsigned, but may have leading
|
||||
zeroes. (The server may possibly send a negative <num> to you, e.g.,
|
||||
the "-1" of the version field of an OPEN response, but you should never
|
||||
send a negative <num> to it.)
|
||||
Some syntax was too long to be presented on a single line here;
|
||||
we note that there is no CRLF or newline in the packet when we continue
|
||||
syntax on a second line. That is, all characters in every command or
|
||||
response are written down explicitly.
|
||||
A reminder: the end of a command or response is not marked by a
|
||||
special character, because the length field of the CHAOS net packet
|
||||
determines where the data ends.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
DATA-CONNECTION
|
||||
args = <sp> ifh <sp> ofh
|
||||
results = <none>
|
||||
|
||||
This is used to open a new DATA connection. The "ifh" and "ofh"
|
||||
fields are the input and output file handles to associate with this data
|
||||
connection. Each should be distinct from all other file handles of
|
||||
other DATA connections pertaining to the same CONTROL. Since this
|
||||
command does not pertain to any existing file handles, the file handle
|
||||
field of the command must be omitted. As would be expected, the input
|
||||
file handle is used to describe the receive half of the DATA connection
|
||||
and the output file handle is use to describe the send half.
|
||||
|
||||
When the server receives a valid (well-formed, etc.)
|
||||
DATA-CONNECTION packet, it will attempt to open a new CHAOS net
|
||||
connection to your host, using "ofh" (the output file handle you
|
||||
supplied in the command packet) as the contact name. Hence, you should
|
||||
listen for such a connection. The server will respond to the
|
||||
DATA-CONNECTION command immediately, even though the new DATA connection
|
||||
may not yet be open. Of course, you cannot use the connection until it
|
||||
is open, but you will know that, because you had to open it.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
UNDATA-CONNECTION
|
||||
args = <none>
|
||||
results = <none>
|
||||
|
||||
This command is used to close a DATA connection when you are
|
||||
finished with it. There is probably little occasion to use this, since
|
||||
any DATA connections will be closed when the CONTROL connection is
|
||||
closed, and a DATA connection can be re-used for multiple file
|
||||
transfers. The DATA connection closed is the one whose input or output
|
||||
file handle appears in the file handle field of the UNDATA-CONNECTION
|
||||
command. UNDATA-CONNECTION implies a CLOSE on each file handle of the
|
||||
DATA connection for which there is a file transfer in progress.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
OPEN
|
||||
args = [ options ] <NL> filename <NL>
|
||||
options = <sp> option1 <sp> option2 ... <sp> optionN
|
||||
results = <sp> version <sp> date <sp> len <sp> qfasl
|
||||
<NL> realname <NL>
|
||||
|
||||
This command is used to open a file for reading or writing at
|
||||
the foreign host. The "filename" part is the filename to use at the
|
||||
foreign host. It is always expressed in the foreign host's file name
|
||||
syntax. The "options" field will be explained momentarily. If an input
|
||||
file handle is given in the file handle field of the command, then the
|
||||
file is to be opened for reading. If an output file handle is given,
|
||||
then the file is to be opened for writing. In either case the file
|
||||
handle serves to indicate not only the direction of transfer, but also
|
||||
the DATA connection to be used for the transfer. A file handle must be
|
||||
supplied, unless a PROBE is being done. PROBE will be explained below,
|
||||
but breifly, it permits you to find out information about a file (i.e.,
|
||||
the "results" information of an OPEN response) without actually opening
|
||||
it.
|
||||
|
||||
The "options" field of the OPEN command consists of a number of
|
||||
options (most of them are simple ASCII strings), always in upper case,
|
||||
each preceded by a space (to separate them from the "OPEN" and from each
|
||||
other). The options permit you to specify whether the transfer is to be
|
||||
BINARY or CHARACTER, and a number of other things. Some options apply
|
||||
only to BINARY transfers, and others (character set translations in
|
||||
particular) only to CHARACTER transfers. Here is a list of the options
|
||||
and their meaning.
|
||||
|
||||
READ - Indicates that we will be reading a file. This is
|
||||
redundant, and is checked for consistency (i.e., we must have
|
||||
given OPEN an input file handle).
|
||||
|
||||
WRITE - Analogous to READ.
|
||||
|
||||
CHARACTER - Specifies that we will be transferring character
|
||||
data as opposed to binary. This affects the mode in which the
|
||||
server will open a file, as well as whether or not character set
|
||||
translations are performed. CHARACTER is the default, so it
|
||||
need never be specified. The check for QFASL files is not
|
||||
performed (see below).
|
||||
|
||||
BINARY - Specifies that we will be transferring binary data. A
|
||||
check is made for QFASL files when reading (the result of the
|
||||
test is supplied in the response to the OPEN; see below). The
|
||||
default byte size is 16 bits (see the discussion of byte sizes
|
||||
below).
|
||||
|
||||
PROBE - This is used to check the existence of a file, and find
|
||||
out information about it if it exists. The file is not actually
|
||||
opened. This option is implied if no file handle is given in
|
||||
the OPEN command. You should not supply a file handle when
|
||||
doing a PROBE. The response packet will contain the same
|
||||
information as a response to OPEN'ing the file for reading.
|
||||
BINARY vs. CHARACTER makes a difference in a probe, as described
|
||||
in the discussion of the response to OPEN.
|
||||
|
||||
Options pertaining to BINARY transfers only:
|
||||
|
||||
BYTE-SIZE <sp> <num> - Specifies to use bytes with <num> bits
|
||||
each. The interpretation is explained below.
|
||||
|
||||
Options pertaining to CHARACTER transfers only:
|
||||
|
||||
RAW - Suppresses character set translation (see below).
|
||||
|
||||
SUPER-IMAGE - Suppresses rubout quoting (this pertains to
|
||||
character set translation, see below).
|
||||
|
||||
Options specific to particular foriegn hosts:
|
||||
|
||||
At present there are only two kinds of servers: ITS servers
|
||||
(e.g., AI and MC) and TOPS-20 servers (e.g., XX, EE, and SPEECH). There
|
||||
are two options that are specific to TOPS-20 servers (i.e., they do not
|
||||
work for ITS servers, and should not be presented to them):
|
||||
|
||||
TEMPORARY - TOPS-20 server only: says to use GJ%TMP in the
|
||||
GTJFN. This is useful mainly when writing files, and indicates
|
||||
that the foreign operating system is to treat the file as
|
||||
temporary. See TOPS-20 documentation for more about the
|
||||
implications of this option.
|
||||
|
||||
DELETED - TOPS-20 server only: says to set GJ%DEL in the GTJFN.
|
||||
This is useful mainly for READ'ing or in PROBE's, and indicates
|
||||
that deleted files should be considered when looking for a file.
|
||||
See TOPS-20 documentation for information about this.
|
||||
|
||||
Details for ITS servers:
|
||||
|
||||
A CHARACTER OPEN will be in .UAI (.UAO) mode when reading
|
||||
(writing). Similarly, a BINARY OPEN will be in .UII (.UIO)
|
||||
mode. An OPEN for writing always opens _LSPM_ OUTPUT in the
|
||||
spcified directory, but does a RENMWO just before the CLOSE, to
|
||||
the appropriate file names. The server takes care of the
|
||||
traditional screws associated with the last word of text files,
|
||||
i.e., you don't have to worry about it -- you will never see the
|
||||
extra characters.
|
||||
|
||||
Details for TOPS-20 servers:
|
||||
|
||||
GTJFN's - When OPEN'ing for READ or PROBE, GJ%OLD is always set.
|
||||
When OPEN'ing for WRITE, GJ%FOU and GJ%NEW will be set. These
|
||||
are independent of the setting of GJ%DEL and GJ%TMP (see the
|
||||
TEMPORARY and DELETED options, above).
|
||||
|
||||
OPENF's - CHARACTER mode does a 7-bit OPENF, normal mode, with
|
||||
line number checking off when reading. BINARY mode does a
|
||||
36-bit DUMP mode OPENF -- the server handles the packing and
|
||||
unpacking of bytes within words.
|
||||
|
||||
Open results:
|
||||
|
||||
results = <sp> version <sp> date <sp> len <sp> qfasl
|
||||
<NL> realname <NL>
|
||||
|
||||
version = a <num>, expressing the version number of the file.
|
||||
On ITS server, this will be the numeric second name, or the
|
||||
leading numeric characters of the second name. If the name has
|
||||
no numerics, the field will be "-1". On TOPS-20 this will be
|
||||
the generation number of the file.
|
||||
|
||||
date = The creation date of the file, expressed in the form
|
||||
"mm/dd/yy hh:mm:ss". (That is a real <sp> between the date and
|
||||
the time.)
|
||||
|
||||
len = ASCII digits for the length of the file in the byte size
|
||||
being read. This will always be 0 when writing.
|
||||
|
||||
qfasl = "T" if we are doing a BINARY READ, and the first word
|
||||
of the file is "QFASL" in sixbit. "NIL" otherwise. This is
|
||||
clearly oriented towards LISP machines!
|
||||
|
||||
realname = the full name of the file, e.g., what RFNAME (on ITS)
|
||||
or JFNS (on TOPS-20) will tell you, when asking for all the
|
||||
usual fields (device, directory, first name, second name,
|
||||
generation number).
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
CLOSE
|
||||
args = <none>
|
||||
results = <sp> version <sp> date <sp> len
|
||||
<NL> realname <NL>
|
||||
|
||||
A file handle must be given, and a transfer must be active on
|
||||
that handle. A synchronous mark will be sent or awaited accordingly,
|
||||
and the file will be closed (but not the DATA connection). See the
|
||||
discussion of data transfer protocol, below, for more details.
|
||||
|
||||
The results are mostly as for OPEN. However, the "len" field is
|
||||
computed differently. For ASCII input, it will be the number of
|
||||
characters, as returned by FILLEN on ITS. On TOPS-20, it will be the
|
||||
number of bytes in the file, if it was written using 7-bit bytes,
|
||||
otherwise, 5 times the number of words. For binary input, it is the
|
||||
number of words in the file times 2. For ASCII output, "len" is the
|
||||
exact number of characters written, and for binary output, it is the
|
||||
number of words times the number of bytes per word for the current byte
|
||||
size. [This stuff may be buggy anyway.]
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
FILEPOS, args = <sp> <num>
|
||||
|
||||
This must have a file handle, and it must be an input file
|
||||
handle. It requests the foreign host to reset its file access pointer
|
||||
to byte <num> of the file currently open, according to the current byte
|
||||
size being used. As explained below, this sends a synchronous mark
|
||||
before starting to send more data. FILEPOS is ILLEGAL for files being
|
||||
written.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
DELETE
|
||||
args = <none> or <sp> filename <NL>
|
||||
results = <none>
|
||||
|
||||
If a file handle is given the file being read or written on the
|
||||
specified DATA connection will be deleted after we close it (regardless
|
||||
of direction). The file handle must refer to an open DATA connection,
|
||||
and the direction must be correspond to the current transfer. This is
|
||||
called a "delete while open", or DELEWO. In such a case, DELETE should
|
||||
have no argument.
|
||||
|
||||
If no file handle is given, then the optional argument must be
|
||||
present, and specifies a file to be deleted immediately.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
RENAME
|
||||
args = <NL> filename1 [ <NL> filename2 ] <NL>
|
||||
results = <none>
|
||||
|
||||
If a file handle is given, only the first filename should be
|
||||
present, and the file will be renamed to filename1 sometime. This is
|
||||
called a "rename while open", or RENMWO. On ITS, a RENMWO call is done
|
||||
immediately. On TOPS-20, a GTJFN is done to filename1, and when we do a
|
||||
CLOSE on the file handle, the CLOSF is done with CO%NRJ set, and then an
|
||||
RNAMF is done to the previously obtained jfn.
|
||||
|
||||
If no file handle is given, then both filenames must be present,
|
||||
and the effect is to rename filename1 to be filename2. Don't forget
|
||||
that on ITS renaming can only be done within a directory. The server
|
||||
simply ignores the device and directory parts of filename2, so be
|
||||
careful. On TOPS-20, renaming from one pack to another will fail.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
CONTINUE
|
||||
args = <none>
|
||||
results = <none>
|
||||
|
||||
This must have a file handle, and the indicated channel must be
|
||||
in the asynchronously marked state. That is, an error of some kind
|
||||
occurred. If the error might be recoverable, then CONTINUE will try to
|
||||
resume from it. If the error is non-recoverable, you will get an error
|
||||
response. See the discussion of marks below.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
SET-BYTE-SIZE
|
||||
args = <sp> nbs <sp> [ npos ]
|
||||
results = <none>
|
||||
|
||||
This must have a file handle, which must refer to a file open in
|
||||
BINARY mode. Both nbs and npos are <num>'s. "nbs" is the new byte
|
||||
size, and must be in the range 1 to 16. "npos" is the new position in
|
||||
the file IN TERMS OF THE OLD BYTE SIZE. The npos part may be omitted
|
||||
for output files, and is ignored if present (but the second <sp> MUST be
|
||||
there). If npos is omitted for input files, it defaults to 0. This
|
||||
command sends or awaits a synchronous mark.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
LOGIN
|
||||
args = <NL> userid [ <NL> password [ <NL> account ]]
|
||||
results from ITS = <sp> uname <sp> hsname
|
||||
<NL> persname <NL>
|
||||
results from TOPS-20 = <none>
|
||||
|
||||
This command is for logging in at the foreign host. You must
|
||||
log in before any OPEN commands will be accepted. Logging in to ITS is
|
||||
simple: you just give the desired UNAME, which may even legally be
|
||||
blank. On TOPS-20, the userid must correspond to a real directory
|
||||
(RCUSR is used), and the password and account are passed to a LOGIN
|
||||
jsys. For most of our TOPS-20's, userid = ANONYMOUS and password =
|
||||
ANONYMOUS will give you a login of low privilege. If the first character
|
||||
in the password is an asterisk, capabilities will be enabled.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
DIRECTORY
|
||||
args = options <NL> pathname
|
||||
results = same as for OPEN
|
||||
|
||||
The only option currently allowed is DELETED, which says to include deleted
|
||||
files (TOPS20) or "*" files (ITS).
|
||||
|
||||
The DIRECTORY command is like opening an input file. The possible responses
|
||||
are the same as for OPEN, except that the affirmative response says DIRECTORY
|
||||
rather than OPEN.
|
||||
|
||||
The input file that you read consists of a series of records; first a
|
||||
header and then the name and properties of each file that matches the
|
||||
pathname, which may contain wildcards in system-dependent fashion. Each
|
||||
record read consists of a pathname, <NL>, a set of properties separated by
|
||||
<NL>, and an extra <NL> to separate it from the next record. Each property
|
||||
consists of the name of the property, optionally followed by a space and
|
||||
the value. (If no value is present, the property is a yes/no property and
|
||||
the value is yes). The header record is in the same format; it has a blank
|
||||
pathname and has the properties for the file system as a whole rather than
|
||||
for a particular file.
|
||||
|
||||
The properties are not documented here; consult the Lisp machine manual for
|
||||
a list of the most useful ones.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
COMPLETE
|
||||
args = options <NL> default-pathname <NL> string
|
||||
results = status <NL> new-string <NL>
|
||||
|
||||
This does filename completion. String is a filename typed in by the user
|
||||
amd default-pathname is the default name against which it is being typed.
|
||||
The filename is completed according to the files present in the file system
|
||||
and the possibly-expanded string is returned.
|
||||
|
||||
Allowed options are DELETED, READ, WRITE, OLD, NEW-OK. DELETED means not
|
||||
to ignore deleted files; this applies to Tenex and TOPS-20 only. READ
|
||||
means the file is going to be read (this is the default). WRITE means the
|
||||
file is going to be written, and affects version number defaulting. OLD
|
||||
means an existent file is required (this is the default). NEW-OK means that
|
||||
it is permissible for the string to complete to the name of a file that does
|
||||
not exist.
|
||||
|
||||
The returned status is NIL, OLD, or NEW. NIL means that an error occured,
|
||||
OLD means that the string completed to the name of an existent file, NEW
|
||||
means that the string completed to a legal filename which is not the name
|
||||
of an existent file.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
CHANGE-PROPERTIES
|
||||
args = filename <NL> property-name <SP> new-value <NL> ...
|
||||
results = <none>
|
||||
|
||||
This allows you to change one or more properties of a file. The properties which
|
||||
are legal to change are those in the SETTABLE-PROPERTIES property of the header
|
||||
record returned by the DIRECTORY command. The legal values for yes/no
|
||||
properties are T and NIL.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
About character set translations:
|
||||
|
||||
As mentioned somewhere above, the protocol was originally
|
||||
designed to provide access to PDP/10 file systems for LISP machines.
|
||||
LISP machines support 8-bit characters, and hence have 256 characters in
|
||||
their character set. This results in minor difficulties when conversing
|
||||
with PDP/10's, which prefer 7-bit characters. Translations apply ONLY
|
||||
to CHARACTER transfers, not BINARY transfers. Below is a table showing
|
||||
the "normal" (i.e., default) correspondence between LISP machine and
|
||||
PDP/10 characters. Some LISP machine characters expand to more than one
|
||||
PDP/10 character. The notation "x in <c1, c2>" means "for all
|
||||
character codes x such that c1 <= x <= c2."
|
||||
|
||||
LISP machine character PDP/10 character(s)
|
||||
|
||||
x in <000, 007> x
|
||||
x in <010, 012> 177 x
|
||||
013 013
|
||||
x in <014, 015> 177 x
|
||||
x in <016, 176> x
|
||||
177 177 177
|
||||
x in <200, 207> 177 <x - 200>
|
||||
x in <210, 212> <x - 200>
|
||||
213 177 013
|
||||
214 014
|
||||
215 015 012
|
||||
x in <216, 376> 177 <x - 200>
|
||||
377 no corresponding code
|
||||
|
||||
This table may seem confusing at first, but there ARE some
|
||||
general rules about it that should make it appear more sensible. First,
|
||||
LISP machine characters in the range <000, 177> are generally
|
||||
represented as themselves, and x in <200, 377> is generally represented
|
||||
as 177 followed by <x - 200>. That is, 177 is used to quote LISP
|
||||
machine characters with the high bit on. It was deemed that 177 is more
|
||||
important than 377, so 177 177 means 177, and there is no way to
|
||||
describe 377 with PDP/10 characters. On the LISP machine, the
|
||||
formatting control characters appear shifted up by 200. This explains
|
||||
why the preferred mode of expressing 210 (backspace) is 010, and 010
|
||||
turns into 177 010. The same reasoning applies to 211 (tab), 212
|
||||
(linefeed), 214 (formfeed), and 215 (newline). However, newline has an
|
||||
added twist -- it is supposed to start at the beginning of a new line,
|
||||
so it is deemed equivalent to 015 012 (CRLF) in PDP/10 characters. When
|
||||
converting PDP/10 characters to LISP machine characters, an 015 always
|
||||
turns into a 215; however, if it is followed by an 012, the 012 is
|
||||
skipped.
|
||||
|
||||
The above table applies in the case of NORMAL translation, i.e.
|
||||
the default translation mode. Note that the server ASSUMES the user is
|
||||
a LISP machine, and that all our servers are PDP/10's, so the labellings
|
||||
"LISP machine" and "PDP/10" can be thought of as "user" and "server".
|
||||
|
||||
The other translation modes available are:
|
||||
|
||||
RAW - perform no translation (PDP/10 characters simply discard
|
||||
the high order bit of LISP machine characters, and LISP machine
|
||||
characters supplied by a server will always be in the range
|
||||
<000, 177>.
|
||||
|
||||
SUPER-IMAGE - This suppresses the use of rubout for quoting.
|
||||
That is, each entry beginning with a 177 in the PDP/10 column of
|
||||
the translation table presented above, has the 177 removed. The
|
||||
PDP/10 character 015 always maps to the LISP machine character
|
||||
215, as in normal translation. Here is the corrected table:
|
||||
|
||||
LISP machine character PDP/10 character(s)
|
||||
|
||||
x in <000, 177> x
|
||||
x in <200, 214> <x - 200>
|
||||
215 015 012
|
||||
x in <216, 376> <x - 200>
|
||||
377 no corresponding code
|
||||
|
||||
User programs written for PDP/10's probably do not wish to have
|
||||
any of the above translations performed, since they are using the PDP/10
|
||||
7-bit character set. Hence, RAW is probably what you want. It is also
|
||||
the most efficient method of transferring ASCII data using the protocol.
|
||||
|
||||
----------------------------------------------------------------
|
||||
|
||||
Data transfer and byte packing issues:
|
||||
|
||||
Once a DATA connection has been established, and an OPEN has
|
||||
succeeded, data transfer proceeds by sending/receiving packets on the
|
||||
appropriate DATA connection. CHARACTER data is always in packets with
|
||||
opcode %CODAT (200), and BINARY data in packets with opcode 300 octal.
|
||||
Consider the data portion of a packet as a sequence of 8-bit bytes, in
|
||||
the fashion usual for the CHAOS net. Then CHARACTER data is always
|
||||
packed one character per packet byte. The organization is such that a
|
||||
standard PDP/10 byte pointer of size 8-bits can be used to load or store
|
||||
characters into a packet sequentially. (As usual, the low 4 bits of
|
||||
each 36-bit word is ignored, and not even transmitted on the CHAOS net.)
|
||||
There are no particular restrictions on the minimum or maximum sizes of
|
||||
data packets, other than hardware or operating system limits. The
|
||||
server will always send the largest packets it can.
|
||||
|
||||
The situation with BINARY data is slightly more complicated. We
|
||||
must consider the data portion of a packet as a sequence of 16-bit
|
||||
bytes. Each 16-bit byte consists of two 8-bit bytes, with the first of
|
||||
the two 8-bit bytes being the high-order half of the 16-bit byte. (This
|
||||
corresponds to PDP/10 conventions, but is the opposite of PDP/11
|
||||
conventions regarding byte packing.) Each byte of binary data sent is
|
||||
stored in one 16-bit byte in the packet. If the byte size is less than
|
||||
16-bits, then the byte is right-justified within the 16-bits, with the
|
||||
remaining high order bits set to unpredictable values. The organization
|
||||
is such that loading or storing sequential bytes in a packet can be done
|
||||
with a standard PDP/10 byte pointer of byte size 16 bits, and transfer
|
||||
of the bytes so obtained to or from words of files can be done with a
|
||||
byte pointer of the size in use for the transfer.
|
||||
|
||||
Each packet of BINARY data should contain an integral number of
|
||||
16-bit bytes, i.e., it should have an even nmber of 8-bit bytes. If it
|
||||
does not, the odd byte is discarded. The server always sends binary
|
||||
packets with an even number of 8-bit bytes.
|
||||
|
||||
For transferring all 36 bits of a PDP/10 word to another 36 bit
|
||||
machine, the byte size must divide 36. The most efficient value is 12,
|
||||
since it is the largest divisor of 36 that is not greater than 16, which
|
||||
is the largest byte size supported by the protocol.
|
||||
|
||||
----------------------------------------------------------------
|
||||
|
||||
Protocol issues in data transfer:
|
||||
|
||||
In addition to just data packets, some other kinds of
|
||||
informative packets are sent or received on the DATA connection.
|
||||
|
||||
EOF packets (opcode 014) are used to mark end of file when
|
||||
reading or writing. That is, when you are writing a file and come to
|
||||
the end of what you wish to write, you will send an EOF packet to tell
|
||||
the server it has reached the end. Similarly, you will receive an EOF
|
||||
packet at the end of a file when reading. EOF packets are always empty
|
||||
(i.e., contain no data). There are additional details about closing a
|
||||
file, however; read on.
|
||||
|
||||
In addition to EOF packets, SYNCHRONOUS MARKS (opcode 201) are
|
||||
used to separate groups of packets in the transfer, mainly for purposes
|
||||
of matching up with FILEPOS and SET-BYTE-SIZE commands. You will
|
||||
receive a synchronous mark on the DATA connection sometime after each
|
||||
successful FILEPOS and SET-BYTE-SIZE command. These marks indicate the
|
||||
place in the data stream where the command actually occurred. They are
|
||||
necessary because the server may be several packets ahead of you in
|
||||
sending data, and without the marks there would be no easy way to tell
|
||||
where the previous information ended and the new information starts. A
|
||||
synchronous mark is also sent in response to a CLOSE command when
|
||||
reading, and expected after an EOF when writing. The mark after a CLOSE
|
||||
when reading allows you to find the end of the data packets for that
|
||||
transfer, if you decide to stop the transfer in the middle. The mark
|
||||
after EOF when writing performs a similar function for the server if you
|
||||
terminate the transfer in the middle.
|
||||
|
||||
When writing, you should send a synchronous mark on the DATA
|
||||
connection whenever you perform a successful SET-BYTE-SIZE command, and
|
||||
also as part of a CLOSE, as described above. All other synchronous
|
||||
marks are ones that you will receive.
|
||||
|
||||
Examples:
|
||||
|
||||
1) Reading a file. Assume you have a CONTROL connection and an idle
|
||||
DATA connection. Send an OPEN command, and await the response. Then
|
||||
start reading data packets from the data channel. The transfer will
|
||||
continue unless you stop it. Suppose you have read all the file. Then
|
||||
you will see an EOF packet. Send your CLOSE command, to order the file
|
||||
closed, and await a SYNC mark on the DATA connection, indicating that
|
||||
the close is in fact done, and the DATA connection can be re-used for
|
||||
some other purpose. If you decide to quit in the middle, send a CLOSE
|
||||
command, and get the response, and read packets from the DATA connection
|
||||
until you see a SYNC mark. (This assumes that there would be no other
|
||||
SYNC marks in transit because of, say, a previous FILEPOS command, etc.
|
||||
If there were any of those, you will have to wait through the
|
||||
appropriate number of SYNC marks.)
|
||||
|
||||
2) Writing a file. Again assume you have established a CONTROL and DATA
|
||||
connection. Send the OPEN command and await the reponse. Then start
|
||||
writing packets on the DATA connection. Assuming there are no problems,
|
||||
send an EOF. WAIT FOR THE EOF TO BE ACKNOWLEDGED BY THE SERVER. (That
|
||||
is, a CHAOS net acknowledgement indicating that the server has actually
|
||||
read the EOF packet.) Now send a SYNC mark on the DATA connection and a
|
||||
CLOSE on the CONTROL connection (in either order). If you do not wait
|
||||
for the EOF to be acknowledged, and you send a CLOSE anyway, the file
|
||||
may be truncated because some data packets may not have been processed
|
||||
by the server.
|
||||
|
||||
----------------------------------------------------------------
|
||||
|
||||
Errors and Ansynchronous marks:
|
||||
|
||||
ASYNCHRONOUS MARK packets (opcode 202) indicate error conditions
|
||||
in the transfer, such as running out of disk space or allocation. Some
|
||||
of these may be recoverable, some not. When reading, an asynchronous
|
||||
mark will come in over the appropriate DATA connection. When writing,
|
||||
it will come in on the CONTROL connection. (The DATA connection is not
|
||||
used in this case because the receive half might be in use for another
|
||||
transfer). Here is the format of an asynchronous mark packet:
|
||||
|
||||
tid <sp> fh <sp> ERROR <sp> erc <sp> c <sp> message
|
||||
|
||||
That is, it looks like a regular error response packet, except that it
|
||||
has a different opcode (responses are data packets, opcode 200). The
|
||||
tid should be ignored -- it will be somewhat random (whatever happens to
|
||||
to be lying around). The file handle, fh, is useful when writing, to
|
||||
see which DATA connection the error happened to. The "erc" part is a 3
|
||||
character error code (a table of them is presented below, subject to
|
||||
change without notice). The single character "c" will be either "R"
|
||||
(for recoverable) or "F" (for fatal). A recoverable error can be
|
||||
restarted from by sending an appropriate CONTINUE command. A fatal
|
||||
error cannot be recovered from, and an appropriate CLOSE should be
|
||||
performed. The "message" part is an ASCII error message, possibly
|
||||
obtained from the host operating system.
|
||||
|
||||
Error codes:
|
||||
|
||||
Flag codes:
|
||||
C = command error (comes in data packet with cmd = "ERROR", on
|
||||
the CONTROL connection).
|
||||
F = fatal asynchronous error.
|
||||
R = restartable asynchronous error.
|
||||
|
||||
Flag Code Message, Causes, Possible Diagnosis
|
||||
|
||||
C CCC - CHANNEL CANNOT CONTINUE
|
||||
CONTINUE not possible.
|
||||
C CNO - CHANNEL NOT OPEN
|
||||
CLOSE on non-open channel.
|
||||
C CRF - CANNOT RENAME OUTPUT FILE TO REAL NAMES
|
||||
Final RENMWO for CLOSE on ITS failed.
|
||||
F CSP - CANNOT SET POINTER
|
||||
Response to this failure in FILEPOS or SET-BYTE-SIZE.
|
||||
C FNF - message varies, depending on reason (FILE NOT FOUND).
|
||||
Failing OPEN.
|
||||
C IBS - ILLEGAL BYTE SIZE
|
||||
Response to byte size not in range 1 - 16.
|
||||
F IDO - ILLEGAL DATA OPCODE
|
||||
Bad packet opcode in the range 200 - 377 (you should use
|
||||
200 for CHARACTER data, and 300 for BINARY)
|
||||
C IFH - ILLEGAL FILE HANDLE FOR FILEPOS
|
||||
Only input file handles are legal.
|
||||
R IOC - message varies (INPUT OUTPUT CONDITION).
|
||||
Generic code for possibly recoverable failures. This
|
||||
will be sent in an ASYNC mark packet.
|
||||
F IPO - ILLEGAL PACKET OPCODE
|
||||
Received a packet with an illegal opcode, or a SYNC or
|
||||
ASYNC mark when not expected.
|
||||
C IRF - ILLEGAL REQUEST FORMAT
|
||||
Generic response to ill-formed command.
|
||||
C ISC - ILLEGAL CHANNEL FOR SET-BYTE-SIZE
|
||||
SET-BYTE-SIZE may only be done on BINARY channels.
|
||||
C NCN - NULL COMMAND NAME
|
||||
Particular case of a bad command.
|
||||
C NER - NOT ENOUGH RESOURCES
|
||||
Possible causes are: no more I/O channels/jfns available
|
||||
for new DATA connections, system failure to open a new
|
||||
CHAOSnet channel, and inability to lookup a user's info
|
||||
in LOGIN.
|
||||
C NLI - NOT LOGGED IN
|
||||
OPEN cannot be done until you are logged in.
|
||||
C TMI - TOO MUCH INFORMATION
|
||||
This happens if a response or error packet overflows.
|
||||
C UFH - UNKNOWN FILE HANDLE
|
||||
Particular case of an ill-formed command.
|
||||
C UKC - UNKNOWN COMMAND
|
||||
Particular case of an ill-formed command.
|
||||
C UNK - USER NOT KNOWN
|
||||
Bad LOGIN (TOPS-20 only).
|
||||
C UOO - UNKNOWN OPEN OPTION
|
||||
Obvious problem.
|
||||
F xxx - ??? When a file system or other operating system call
|
||||
fails, which is not covered in the above, then another code is
|
||||
used. These are taken from a table for ITS, with the message
|
||||
read from the ERR: device, and on TOPS-20, the letters are the
|
||||
first letters of the first three words of the error message
|
||||
returned by an ERSTR call. The only exception is code FNF,
|
||||
special cased if the error is GJFX24 ("file not found") or OPNX2
|
||||
("file does not exist") on TOPS-20. No other FNF's will come
|
||||
from TOPS-20, even by "accidient" -- a special check is made.
|
||||
169
doc/sysdoc/clo.100
Executable file
169
doc/sysdoc/clo.100
Executable file
@@ -0,0 +1,169 @@
|
||||
-*-Text-*- Alan 12/31/83
|
||||
|
||||
Here is what I know about the core link device(s).
|
||||
|
||||
The core link device is a primitive mechanism for connecting two jobs
|
||||
together with a uni-directional stream. The basic idea is very simple:
|
||||
suppose job A opens CLO:FOO;BAR BAZ for input and job B opens
|
||||
CLO:FOO;BAR BAZ for output, then by virtue of the fact that they used the
|
||||
same name (FOO;BAR BAZ) they are connected together and anything job B
|
||||
happens to output to its channel will be what job A reads from its channel.
|
||||
For many simple hacks, that's all you really need to know about it!
|
||||
|
||||
The core link device is not a random access device. Only the most basic
|
||||
system calls are supported (like OPEN, IOT, SIOT, STATUS, RFNAME, and
|
||||
CLOSE). There is no way for either job to cause the other to receive a
|
||||
second word interrupt. For more advanced applications where a more
|
||||
complicated interface is desired the JOB device can be used. See
|
||||
.INFO.;ITS JOBONL (or .INFO.;ITS JOB).
|
||||
|
||||
ITS keeps an I/O buffer for each core link, so the two jobs will not
|
||||
actually be kept running in lock-step. The outputting job will wait when
|
||||
it tries to output only if the buffer becomes full, and the inputting job
|
||||
will wait when it tries to input only if the buffer becomes empty. The
|
||||
buffer is about 100. words long. Because of this buffering it is not
|
||||
necessary for both jobs to open their channels in identical modes, one job
|
||||
can read (write) 36-bit words while the other is writing (reading) 7-bit
|
||||
characters. [This should be contrasted with the JOB device, where ITS
|
||||
cannot keep any internal state for the JOB/BOJ connection because of
|
||||
PCLSRing considerations.]
|
||||
|
||||
If the reading job closes its input channel, the writing job's output
|
||||
channel acts like the NUL device. All output is simply discarded. If the
|
||||
writing job closes its output channel, the reading job's input channel acts
|
||||
like it has reached end of file (after it has read whatever remained in the
|
||||
buffer of course). [Actually, in .UII mode if you IOT beyond end of file
|
||||
it starts returning random 36-bit words. It should be fixed to generate an
|
||||
IOC interrupt like other devices do at EOF in .UII mode. I guess it really
|
||||
doesn't matter much since you don't open things in image mode unless you
|
||||
know exactly what they are anyway...]
|
||||
|
||||
There are actually 4 core link devices: CLO (Core Link Open), CLU (Core
|
||||
Link Use), CLI (Core Link Interrupt), and CLA (Core Link Answer). The
|
||||
differences between them all have to do with what happens when you open
|
||||
them. In fact, after you have completed the process of opening a channel
|
||||
with any of these devices, an RFNAME call on that channel will always
|
||||
report that it is the CLO device, since from that point on they all behave
|
||||
identically.
|
||||
|
||||
In order match up jobs that desire to use the core link device, ITS
|
||||
maintains a table called the "core link directory". At any given time the
|
||||
core link directory contains a number of "core links". Each core link has
|
||||
three names: an SNAME, a first name, and a second name (SNAME;NAME1 NAME2).
|
||||
|
||||
When a job tries to open CLO:FOO;BAR BAZ, ITS searches the core link
|
||||
directory for a core link named FOO;BAR BAZ. If no core link is found with
|
||||
that name, then a new core link is created with that name and entered in
|
||||
the directory. (If the core link directory gets full a %EFLDR error can be
|
||||
returned at this point.)
|
||||
|
||||
The CLU device behaves identically to the CLO device, except that if no
|
||||
existing core link has the proper name then instead of creating a new one,
|
||||
a file not found error is returned (%ENSFL). Thus you should use the CLU
|
||||
device when you are certain that some other job has already created a core
|
||||
link of a given name.
|
||||
|
||||
Also potentially associated with each core link is a pair of jobs. One for
|
||||
reading, and one for writing. After an appropriately named core link has
|
||||
been located or created, ITS checks to see whether some other job already
|
||||
has this core link open in the same direction. If so, a file locked error
|
||||
is returned (%ENAFL), otherwise this job is recorded as the one reading or
|
||||
writing the core link, and the channel is successfully opened.
|
||||
|
||||
You can list the core link directory. Opening CLO:.FILE. (DIR) will
|
||||
allow you to read a table like the following:
|
||||
|
||||
SNAME NAME1 NAME2 ALAN A -> ALAN B
|
||||
SPAZM FOOBAR 259 CLOSED-> ALAN A
|
||||
QAZWSX FOOBAR 259 ALAN FOOBAR-> CLOSED
|
||||
FOO BAR BAZ CLOSED-> CLOSED
|
||||
|
||||
(Try typing CLO^F to DDT. Probably the core link directory will be empty,
|
||||
so you won't seen anything interesting.)
|
||||
|
||||
This table is interpreted as follows:
|
||||
|
||||
SNAME NAME1 NAME2 ALAN A -> ALAN B
|
||||
^ ^ ^ ^ ^ ^ ^
|
||||
| | | | | | | UNAME and JNAME of
|
||||
| | | | | +------+--- job reading from
|
||||
| | | | | this core link.
|
||||
| | | | |
|
||||
| | | | | UNAME and JNAME of
|
||||
| | | +------+---job writing into
|
||||
| | | this core link.
|
||||
| | |
|
||||
| | | SNAME and first and
|
||||
+------+------+---second names for
|
||||
this core link.
|
||||
|
||||
If no job is reading from the core link, the word CLOSED will appear after
|
||||
the arrow instead of a UNAME/JNAME pair. Similarly if no job is writing
|
||||
into the core link, CLOSED appears before the arrow.
|
||||
|
||||
If you are trying to debug something that uses the core link device, a
|
||||
listing of the core link directory is a valuable debugging aid.
|
||||
|
||||
In the core link directory listing above, the core link named FOO;BAR BAZ
|
||||
has neither an associated reading nor writing job. You might think that
|
||||
such a core link would be worthless, but this is not necessarily the case!
|
||||
Suppose that job A opens CLO:FOO;BAR BAZ for output intending to only
|
||||
transmit 100. ascii characters through the link. Since 100. characters can
|
||||
easily fit in the core link's buffer, job A can output all 100. characters
|
||||
and close its channel before the reading job even gets as far as opening
|
||||
its channel. Thus for a brief time the core link has no associated jobs.
|
||||
|
||||
Unfortunately there is no way to guarantee that any job will ever open the
|
||||
core link FOO;BAR BAZ for input to pick up those 100. characters. For this
|
||||
reason ITS will garbage collect any core link that has not had any
|
||||
associated jobs for several minutes (about 5 minutes).
|
||||
|
||||
You can also delete core links from the core link directory yourself. Thus
|
||||
from DDT you can type "^O CLO:FOO;BAR BAZ" to get rid of a garbage core
|
||||
link. Normally there is no need to do this, since ITS will flush them
|
||||
eventually anyway. [Indeed, it is a BAD idea to use this feature currently
|
||||
because there is a bug such that instead of deleting the core link, you
|
||||
sometimes cause it to become permanently locked down. Since there are a
|
||||
finite number of core links (12. currently), if you do this often enough
|
||||
you will render the core link device unusable.]
|
||||
|
||||
A reasonable person might wonder what happens if some job tries to re-open
|
||||
the core link FOO;BAR BAZ for output and write more characters into it.
|
||||
Well, each core link actually acts as a SEQUENCE of files separated by
|
||||
end-of-file markers. If a second job opens CLO:FOO;BAR BAZ and writes more
|
||||
data into it, that data will be available to the SECOND job that opens that
|
||||
core link for input. Thus if one job is in a loop opening the core link
|
||||
named FOO;BAR BAZ, outputting a single character, and then closing it
|
||||
again, and a second job is in a loop opening that core link, reading
|
||||
characters until end of file, and then closing it again, then the second
|
||||
job will see a sequence of single character length files.
|
||||
|
||||
We haven't yet mentioned the CLI and CLA devices. These two devices enable
|
||||
one job to interrupt another job indicating that it wishes to send a
|
||||
message through a core link. This is how interactive messages work on ITS.
|
||||
|
||||
The sending job opens the CLI device with first and second filenames equal
|
||||
to the UNAME and JNAME of the job that it wishes to interrupt. For
|
||||
example, a job might try to open CLI:CSTACY HACTRN (any SNAME supplied will
|
||||
be ignored). ITS then checks to see that a job named CSTACY HACTRN really
|
||||
does exist. If it does, ITS checks to see that that job has enabled the
|
||||
%PICLI interrupt. If it is not the case that both conditions are met, the
|
||||
open returns an illegal file name error (%EBDFN). If both conditions are
|
||||
met, then we proceed as if we were opening CLO:_CLI_;CSTACY HACTRN. If
|
||||
that succeeds, then we actually give the job CSTACY HACTRN the %PICLI
|
||||
interrupt, and the open succeeds.
|
||||
|
||||
The UNAME and JNAME of the sending job are now placed in the core link's
|
||||
I/O buffer so that the receiving job will be able to read them out before
|
||||
any additional data that the sender might wish to transmit. (Note that you
|
||||
can only open the CLI device for output.)
|
||||
|
||||
In order to handle the %PICLI interrupt the job CSTACY HACTRN opens CLA:
|
||||
(any additional names supplied will be ignored). This is like opening
|
||||
CLU:_CLI_;CSTACY HACTRN, except that it saves the interrupted job from
|
||||
having to figure out its own name. The receiving job can now read the
|
||||
UNAME and JNAME of its interrupter by inputting the first two 36-bit words
|
||||
from the newly opened channel.
|
||||
|
||||
The jobs are now talking through an ordinary core link named
|
||||
_CLI_;CSTACY HACTRN.
|
||||
108
doc/sysdoc/devdoc.5
Executable file
108
doc/sysdoc/devdoc.5
Executable file
@@ -0,0 +1,108 @@
|
||||
|
||||
SUBTTL I/O DEVICE DISPATCH TABLES
|
||||
|
||||
COMMENT |
|
||||
This page tries to document the ITS I/O device dispatch tables and
|
||||
dispatch environment. It is not completed yet.
|
||||
|
||||
The tables use several different indices, which are:
|
||||
opnidx - result of device name lookup in DEVTAB
|
||||
ioidx - result of OPEN; has symbolic values. This is the index
|
||||
stored in RH of IOCHNM (per-job channel table)
|
||||
sidx - secondary index from DCHSTB(ioidx)
|
||||
ridx - secondary index from RSTB(ioidx)
|
||||
|
||||
The following system calls are dispatched through these tables.
|
||||
There are 11 dispatch routines that each device must specify.
|
||||
The format is "CALL [table name(index-used) -> device-routine]"
|
||||
Unless otherwise noted, context for all routines has
|
||||
U/ User index
|
||||
R/ addr of IOCHNM word for specified channel
|
||||
and the phrase "all ACs can be used" excludes P and U, of course.
|
||||
and routines can hang (u.o.n.)
|
||||
|
||||
OPEN [DEVADR(opnidx) -> devO]
|
||||
"opnidx" is looked up from DEVTAB which holds the device names.
|
||||
The device's OPEN routine is in the RH of DEVADR.
|
||||
It must set up the user's IOCHNM word for the channel,
|
||||
by setting the RH to the right "ioidx" and the LH to whatever
|
||||
the device wants.
|
||||
|
||||
Context:
|
||||
A/ FN1
|
||||
B/ FN2
|
||||
C/ <mode bits>,,<device name>
|
||||
D/ <mode bits rotated -1>
|
||||
E/ <device name>
|
||||
TT/ DEVADR word <bits>,,<routine>
|
||||
W/ "open" command (0= Normal R/W open, 1= Write-over mode,
|
||||
2= Make link, 4= Delete or rename)
|
||||
SRN3(U),SRN4(U),SRN5(U) - args 4,5,6 (if present)
|
||||
|
||||
Routine is JRST'd to, and must return via POPJ1 for success.
|
||||
Errors should JRST to the appropriate OPNLnn label.
|
||||
All ACs can be smashed.
|
||||
|
||||
CLOSE [CLSTB(ioidx) -> devCLS]
|
||||
The device's CLOSE routine is in the RH of CLSTB.
|
||||
|
||||
Context:
|
||||
A/ 0,,<LH of IOCHNM word>
|
||||
B/ 0,,<RH of IOCHNM word>
|
||||
C/ CLSTB entry, <bits>,,<rtn addr>
|
||||
R/ addr of IOCHNM word
|
||||
Called via PUSHJ, must return via POPJ (IOCHNM and IOCHST will
|
||||
be cleared immediately after return).
|
||||
Can smash all ACs including R.
|
||||
Must NOT hang!
|
||||
|
||||
IOT, SIOT [IOTTB(ioidx) -> devVarious]
|
||||
These routines do I/O transfers. The main reason "ioidx"
|
||||
has so many possible values (causing IOTTB to be large) is
|
||||
because lots of devices specify different ioidx's for different
|
||||
modes - input/output, block/unit, image/ascii, etc - in order
|
||||
to speed up actual I/O transfers, which are probably the most
|
||||
common device-related system calls.
|
||||
|
||||
Context:
|
||||
Boy is this complicated.
|
||||
|
||||
STATUS [LH(DSTSTB(sidx)) -> devSTA]
|
||||
Context:
|
||||
R/ addr of IOCHNM word
|
||||
Called by PUSHJ, must return by POPJ
|
||||
Must return in RH(D) some device-dependent status stuff.
|
||||
Calling routine (NSTATUS) fills in the LH from IOCHST.
|
||||
Must not smash C,R! Probably should not smash other
|
||||
stuff either, depending on what USRVAR/USET need.
|
||||
|
||||
WHYINT [RH(DSTSTB(sidx)) -> devWHY]
|
||||
|
||||
RCHST, RFNAME [LH(DRFNTB(sidx)) -> devRCH]
|
||||
|
||||
RFPNTR [RH(DRFNTB(sidx)) -> devRFP]
|
||||
|
||||
IOPUSH, IOPOP [LH(RSTB1(ridx)) -> devIOP]
|
||||
|
||||
RESET [RH(RSTB1(ridx)) -> devRST]
|
||||
Context:
|
||||
R/ addr of IOCHNM wd
|
||||
Called by JRST from NRESET/ARESET/AIOPP1, must return by POPJ.
|
||||
Can clobber all ACs. Must not hang.
|
||||
|
||||
FORCE [LH(DFRCTB(ridx)) -> devFRC]
|
||||
Context:
|
||||
A/ LH of IOCHNM word, in RH.
|
||||
H/ IOCHNM word
|
||||
R/ <LH of CLSTB entry>,,<addr of IOCHNM word>
|
||||
Called by JRST from NFORCE. Returns by POPJ1 for win,
|
||||
POPJ if fail. Should not clobber context that FINISH routine
|
||||
may need.
|
||||
|
||||
FINISH [RH(DFRCTB(ridx)) -> devFIN]
|
||||
Same as FORCE, except that FORCE is called first, thus
|
||||
context is whatever FORCE leaves behind. This routine
|
||||
must do the actual waiting for FORCE's actions to be
|
||||
finished.
|
||||
|
||||
|
|
||||
638
doc/sysdoc/grphcs.21
Executable file
638
doc/sysdoc/grphcs.21
Executable file
@@ -0,0 +1,638 @@
|
||||
This file was moved to MIT-MC from
|
||||
MIT-AI by David C. Plummer on 6 June
|
||||
1981, and may be up to date.
|
||||
|
||||
|
||||
NWG/RFC# 746 RMS 17-MAR-78 43976
|
||||
SUPDUP Graphics Extension
|
||||
|
||||
|
||||
|
||||
Network Working Group Richard Stallman
|
||||
Request for Comments 746 MIT-AI
|
||||
NIC 43976 17 March 1978
|
||||
|
||||
|
||||
The SUPDUP Graphics Extension
|
||||
|
||||
... extends SUPDUP to permit the display of drawings on the
|
||||
screen of the terminal, as well as text. We refer constantly to the
|
||||
documentation of the SUPDUP protocol, described by Crispin in RFC 734
|
||||
"SUPDUP Protocol".
|
||||
|
||||
Since this extension has never been implemented, it presumably
|
||||
has some problems. It is being published to ask for suggestions, and
|
||||
to encourage someone to try to bring it up.
|
||||
|
||||
The major accomplishments are these:
|
||||
|
||||
* It is easy to do simple things.
|
||||
|
||||
* Any program on the server host can at any time begin
|
||||
outputting pictures. No special preparations are needed.
|
||||
|
||||
* No additional network connections are needed. Graphics
|
||||
commands go through the normal text output connection.
|
||||
|
||||
* It has nothing really to do with the network. It is suitable
|
||||
for use with locally connected intelligent display terminals
|
||||
in a terminal-independent manner, by programs which need not
|
||||
know whether they are being used locally or remotely. It can be
|
||||
used as the universal means of expression of graphics output, for
|
||||
whatever destination. Programs can be written to use it for
|
||||
non-network terminals, with little loss of convenience, and
|
||||
automatically be usable over the ARPA network.
|
||||
|
||||
* Loss of output (due, perhaps, to a "silence" command typed
|
||||
by the user) does not leave the user host confused.
|
||||
|
||||
* The terminal does not need to be able to remember the
|
||||
internal "semantic" structure of the picture being
|
||||
displayed, but just the lines and points, or even just bits
|
||||
in a bit matrix.
|
||||
|
||||
* The server host need not be able to invoke arbitrary
|
||||
terminal-dependent software to convert a standard language
|
||||
into one that a terminal can use. Instead, a standard
|
||||
language is defined which all programmable terminals can
|
||||
interpret easily. Major differences between terminals are
|
||||
catered to by conventions for including enough redundant
|
||||
information in the output stream that all types of terminals
|
||||
will have the necessary information available when it is
|
||||
needed, even if they are not able to remember it in usable
|
||||
form from one command to another.
|
||||
|
||||
Those interested in network graphics should read about the
|
||||
Multics Graphics System, whose fundamental purpose is the same, but
|
||||
whose particular assumptions are very different (although it did
|
||||
inspire a few of the features of this proposal).
|
||||
|
||||
NWG/RFC# 746 RMS 17-MAR-78 43976
|
||||
SUPDUP Graphics Extension
|
||||
|
||||
|
||||
SUPDUP Initial Negotiation:
|
||||
|
||||
One new optional variable, the SMARTS variable, is defined. It
|
||||
should follow the other variables sent by the SUPDUP user process to
|
||||
the SUPDUP server process. Bits and fields in the left half-word of
|
||||
this variable are given names starting with "%TQ". Bits and fields in
|
||||
the right half are given names starting with "%TR". Not all of the
|
||||
SMARTS variable has to do with the graphics protocol, but most of it
|
||||
does. The %TQGRF bit should be 1 if the terminal supports graphics
|
||||
output at all.
|
||||
|
||||
|
||||
Invoking the Graphics Protocol:
|
||||
|
||||
Graphics mode is entered by a %TDGRF (octal 231) code in the
|
||||
output stream. Following characters in the range 0 - 177 are
|
||||
interpreted according to the graphics protocol. Any character 200 or
|
||||
larger (a %TD code) leaves graphics mode, and then has its normal
|
||||
interpretation. Thus, if the server forgets that the terminal in
|
||||
graphics mode, the terminal will not long remain confused.
|
||||
|
||||
Once in graphics mode, the output stream should contain a
|
||||
sequence of graphics protocol commands, each followed by its
|
||||
arguments. A zero as a command is a no-op. To leave graphics mode
|
||||
deliberately, it is best to use a %TDNOP.
|
||||
|
||||
NWG/RFC# 746 RMS 17-MAR-78 43976
|
||||
SUPDUP Graphics Extension
|
||||
|
||||
|
||||
Co-ordinates:
|
||||
|
||||
Graphics mode uses a cursor position which is remembered from one
|
||||
graphics command to the next while in graphics mode. The graphics
|
||||
mode cursor is not the same one used by normal type-out: Graphics
|
||||
protocol commands have no effect on the normal type-out cursor, and
|
||||
normal type-out has no effect on the graphics mode cursor. In
|
||||
addition, the graphics cursor's position is measured in dots rather
|
||||
than in characters. The relationship between the two units (dots, and
|
||||
characters) is recorded by the %TQHGT and %TQWID fields of the SMARTS
|
||||
variable of the terminal, which contain the height and width in dots
|
||||
of the box occupied by a character. The size of the screen in either
|
||||
dimension is assumed to be the length of a character box times the
|
||||
number of characters in that direction on the screen. If the screen
|
||||
is actually bigger than that, the excess may or may not be part of
|
||||
the visible area; the program will not know that it exists, in any
|
||||
case.
|
||||
|
||||
Each co-ordinate of the cursor position is a 14-bit signed
|
||||
number, where zero is at the center of the screen (if the screen
|
||||
dimension is an even number of dots, then the visible negative points
|
||||
extend one unit farther than the positive ones, in proper two's
|
||||
complement fashion). Excessively large values of the co-ordinates
|
||||
will be off the screen, but are still meaningful.
|
||||
|
||||
An alternate mode is defined, which some terminals may support,
|
||||
in which virtual co-ordinates are used. The specified co-ordinates
|
||||
are still 14-bit signed numbers, but instead of being in units of
|
||||
physical dots on the terminal, it is assumed that +4000 octal is the
|
||||
top of the screen or the right edge, while -4000 octal is the bottom
|
||||
of the screen or the left edge. The terminal is responsible for
|
||||
scaling these virtual co-ordinates into units of screen dots. Not all
|
||||
terminals need have this capability; the %TQVIR bit in the SMARTS
|
||||
variable indicates that it exists. To use virtual co-ordinates, the
|
||||
server should send a %GOVIR; to use physical co-ordinates again, it
|
||||
should send a %GOPHY. These should be repeated at intervals, such as
|
||||
when graphics mode is entered, even though the terminal must attempt
|
||||
to remember the state of the switch anyway. This repetition is so
|
||||
that a loss of some output will not cause unbounded confusion.
|
||||
|
||||
The virtual co-ordinates are based on a square. If the visible
|
||||
area on the terminal is not a square, then the standard virtual range
|
||||
should correspond to a square around the center of the screen, and the
|
||||
rest of the visible area should correspond to virtual co-ordinates
|
||||
just beyond the normally visible range.
|
||||
|
||||
Graphics protocol commands take two types of cursor position
|
||||
arguments, absolute ones and relative ones. Commands that take
|
||||
address arguments generally have two forms, one for each type of
|
||||
address. A relative address consists of two offsets, delta-X and
|
||||
delta-Y, from the old cursor position. Each offset is a 7-bit two's
|
||||
complement number occupying one character. An absolute address
|
||||
consists of two co-ordinates, each 14 bits long, occupying two
|
||||
characters, each of which conveys 7 bits. The X co-ordinate or offset
|
||||
precedes the Y. Both types of address set the running cursor position
|
||||
which will be used by the next address, if it is relative. It is
|
||||
perfectly legitimate for parts of objects to go off the screen. What
|
||||
happens to them is not terribly important, as long as it is not
|
||||
disastrous, does not interfere with the reckoning of the cursor
|
||||
position, and does not cause later objects, drawn after the cursor
|
||||
moves back onto the screen, to be misdrawn.
|
||||
|
||||
Whether a particular spot on the screen is specified with an
|
||||
absolute or a relative address is of no consequence. The sequence in
|
||||
which they are drawn is of no consequence. Each object is independent
|
||||
of all others, and exists at the place which was specified, in one way
|
||||
or other, by the command that created it. Relative addresses are
|
||||
provided for the sake of data compression. They are not an attempt to
|
||||
spare programs the need for the meagre intelligence required to
|
||||
convert between absolute and relative addresses; more intelligence
|
||||
than that will surely be required for other aspects of the graphics
|
||||
protocol. Nor are relative addresses intended to cause several
|
||||
objects to relocate together if one is "moved" or erased. Terminals
|
||||
are not expected to remember any relation between objects once they
|
||||
are drawn. Most will not be able to.
|
||||
|
||||
Although the cursor position on entry to graphics mode remains
|
||||
set from the last exit, it is wise to reinitialize it with a %GOMVA
|
||||
command before any long transfer, to limit the effects of lost output.
|
||||
|
||||
NWG/RFC# 746 RMS 17-MAR-78 43976
|
||||
SUPDUP Graphics Extension
|
||||
|
||||
|
||||
Commands:
|
||||
|
||||
Commands to draw an object always have counterparts which erase
|
||||
the same object. On a bit matrix terminal, erasure and drawing are
|
||||
almost identical operations. On a display list terminal, erasure
|
||||
involves searching the display list for an object with the specified
|
||||
characteristics and deleting it from the list. Thus, on such
|
||||
terminals you can erase an object only if precisely that object was
|
||||
drawn, and was specified the same way when drawn as when erased.
|
||||
(presumably; a very hairy program might allow more). Any terminal
|
||||
whose %TOERS bit is set must be able to erase to at least that extent.
|
||||
|
||||
The commands to draw objects run from 100 to 137, while those to
|
||||
erase run in a parallel sequence from 140 to 177. Other sorts of
|
||||
operations have command codes below 100. Meanwhile, the 20 bit in the
|
||||
command code says which type of addresses are used as arguments: if
|
||||
the 20 bit is set, absolute addresses are used. Graphics commands are
|
||||
given names starting with "%GO".
|
||||
|
||||
Graphics often uses characters. The %GODCH command is followed
|
||||
by a string of characters to be output, terminated by a zero. The
|
||||
characters must be single-position printing characters. On most
|
||||
terminals, this limits them to ASCII graphic characters. Terminals
|
||||
with %TOSAI set in the TTYOPT variable allow all characters 0-177.
|
||||
The characters are output at the current graphics cursor position (the
|
||||
lower left hand corner of the first character's rectangle being placed
|
||||
there), which is moved as the characters are drawn. The normal
|
||||
type-out cursor is not relevant and its position is not changed. The
|
||||
cursor position at which the characters are drawn may be in between
|
||||
the lines and columns used for normal type-out. The %GOECH command is
|
||||
similar to %GODCH but erases the characters specified in it. To clear
|
||||
out a row of character positions on a bit matrix terminal without
|
||||
having to respecify the text, a rectangle command may be used.
|
||||
|
||||
|
||||
Example:
|
||||
|
||||
The way to send a simple line drawing is this:
|
||||
|
||||
%TDRST ;Reset all graphics modes.
|
||||
%TDGRF ;Enter graphics.
|
||||
%GOCLR ;Clear the screen.
|
||||
%GOMVA xx yy ;Set cursor.
|
||||
%GODLA xx yy ;Draw line from there.
|
||||
<< repeat last two commands for each line >>
|
||||
%TDNOP ;Exit graphics.
|
||||
|
||||
NWG/RFC# 746 RMS 17-MAR-78 43976
|
||||
SUPDUP Graphics Extension
|
||||
|
||||
|
||||
Graphics Input:
|
||||
|
||||
The %TRGIN bit in the right half of the SMARTS variable indicates
|
||||
that the terminal can supply a graphic input in the form of a cursor
|
||||
position on request. Sending a %GOGIN command to the terminal asks to
|
||||
read the cursor position. It should be followed by an argument
|
||||
character that will be included in the reply, and serve to associate
|
||||
the reply with the particular request for input that elicited it. The
|
||||
reply should have the form of a Top-Y character (code 4131), followed
|
||||
by the reply code character as just described, followed by an absolute
|
||||
cursor position. Since Top-Y is not normally meaningful as input,
|
||||
%GOGIN replies can be distinguished reliably from keyboard input.
|
||||
Unsolicited graphic input should be sent using a Top-X instead of a
|
||||
Top-Y, so that the program can distinguish them. Instead of a reply
|
||||
code, for which there is no need, the terminal should send an encoding
|
||||
of the buttons pressed by the user on his input device, if it has more
|
||||
than one.
|
||||
|
||||
|
||||
Sets:
|
||||
|
||||
Terminals may define the concept of a "set" of objects. There
|
||||
are up to 200 different sets, each of which can contain arbitrarily
|
||||
many objects. At any time, one set is selected; objects drawn become
|
||||
part of that set, and objects erased are removed from it. Objects in
|
||||
a set other than the selected one cannot be erased without switching
|
||||
to the sets that contain them. A set can be made temporarily
|
||||
invisible, as a whole, without being erased or its contents forgotten;
|
||||
and it can then be made instantly visible again. Also, a whole set
|
||||
can be moved. A set has at all times a point identified as its
|
||||
"center", and all objects in it are actually remembered relative to
|
||||
that center, which can be moved arbitrarily, thus moving all the
|
||||
objects in the set at once. Before beginning to use a set, therefore,
|
||||
one should "move" its center to some absolute location. Set center
|
||||
motion can easily cause objects in the set to move off screen. When
|
||||
this happens, it does not matter what happens temporarily to those
|
||||
objects, but their "positions" must not be forgotten, so that undoing
|
||||
the set center motion will restore them to visibility in their
|
||||
previous positions. Sets are not easily implemented on bit matrix
|
||||
terminals, which should therefore ignore all set operations (except,
|
||||
for a degenerate interpretation in connection with blinking, if that
|
||||
is implemented). The %TQSET bit in the SMARTS variable of the
|
||||
terminal indicates that the terminal implements multiple sets of
|
||||
objects.
|
||||
|
||||
On a terminal which supports multiple sets, the %GOCLR command
|
||||
should empty all sets and mark all sets "visible" (perform a %GOVIS on
|
||||
each one). So should a %TDCLR SUPDUP command. Thus, any program
|
||||
which starts by clearing the screen will not have to worry about
|
||||
initializing the states of all sets.
|
||||
|
||||
NWG/RFC# 746 RMS 17-MAR-78 43976
|
||||
SUPDUP Graphics Extension
|
||||
|
||||
|
||||
Blinking:
|
||||
|
||||
Some terminals have the ability to blink objects on the screen.
|
||||
The command %GOBNK meaning make the current set blink. All objects in
|
||||
it already begin blinking, and any new objects also blink. %GOVIS or
|
||||
%TOINV cancels the effect of a %GOBNK, making the objects of the set
|
||||
permanently visible or invisible. %TQBNK indicates that the terminal
|
||||
supports blinking on the screen.
|
||||
|
||||
However, there is a problem: some intelligent bit matrix
|
||||
terminals may be able to implement blinking a few objects, if they are
|
||||
told in advance, before the objects are drawn. They will be unable to
|
||||
support arbitrary use of %GOBNK, however.
|
||||
|
||||
The solution to the problem is a convention for the use of %TOBNK
|
||||
which, together with degenerate definitions for set operations, makes
|
||||
it possible to give commands which reliably work on any terminal which
|
||||
supports blinking.
|
||||
|
||||
On a terminal which sets %TQBNK but not %TQSET, %GOBNK is defined
|
||||
to cause objects which are drawn after it to be drawn blinking.
|
||||
%GOSET cancels this, so following objects will be drawn unblinking.
|
||||
This is regardless of the argument to the %GOSET.
|
||||
|
||||
Thus, the way for a program to work on all terminals with %TQBNK,
|
||||
whether they know about sets or not, is: to write a bliniking
|
||||
picture, select some set other than your normal one (set 1 will do),
|
||||
do %GOBNK, output the picture, and reselect set 0. The picture will
|
||||
blink, while you draw things in set 0. To draw more blinking objects,
|
||||
you must reselect set 1 and do another %GOBNK. Simply reselecting set
|
||||
1 will not work on terminals which don't really support sets, since
|
||||
they don't remember that the blinking objects are "in set 1" and not
|
||||
"in set 0".
|
||||
|
||||
Erasing a blinking object should make it disappear, on any
|
||||
terminal which implements blinking. On bit matrix terminals, blinking
|
||||
MUST always be done by XORing, so that the non-blinking background
|
||||
is not destroyed.
|
||||
|
||||
%GOCLS, on a terminal which supports blinking but not sets,
|
||||
should delete all blinking objects. Then, the convention for deleting
|
||||
all blinking objects is to select set 1, do a %GOCLS, and reselect set
|
||||
0. This has the desired effect on all terminals. This definition of
|
||||
%GOCLS causes no trouble on non-set terminals, since %GOCLS would
|
||||
otherwise be meaningless to them.
|
||||
|
||||
To make blinking objects stop blinking but remain visible is
|
||||
possible with a %GOVIS on a terminal which supports sets. But in
|
||||
general the only way to do it is to delete them and redraw them as
|
||||
permanent.
|
||||
|
||||
NWG/RFC# 746 RMS 17-MAR-78 43976
|
||||
SUPDUP Graphics Extension
|
||||
|
||||
|
||||
Rectangles and XOR Mode:
|
||||
|
||||
Bit matrix terminals have their own operations that display list
|
||||
terminals cannot duplicate. First of all, they have XOR mode, in
|
||||
which objects drawn cancel existing objects when they overlap. In
|
||||
this mode, drawing an object and erasing it are identical operations.
|
||||
All %GOD.. commands act IDENTICALLY to the corresponding %GOE..'s.
|
||||
XOR mode is entered with a %GOXOR and left with a %GOIOR. Display
|
||||
list terminals will ignore both commands. For that reason, the
|
||||
program should continue to distinguish draw commands from erase
|
||||
commands even in XOR mode. %TQXOR indicates a terminal which
|
||||
implements XOR mode. XOR mode, when set, remains set even if graphics
|
||||
mode is left and re-entered. However, it is wise to re-specify it
|
||||
from time to time, in case output is lost.
|
||||
|
||||
Bit matrix terminals can also draw solid rectangles. They can
|
||||
thus implement the commands %GODRR, %GODRA, %GOERR, and %GOERA. A
|
||||
rectangle is specified by taking the current cursor position to be one
|
||||
corner, and providing the address of the opposite corner. That can be
|
||||
done with either a relative address or an absolute one. The %TQREC
|
||||
bit indicates that the terminal implements rectangle commands.
|
||||
|
||||
Of course, a sufficiently intelligent bit matrix terminal can
|
||||
provide all the features of a display list terminal by remembering
|
||||
display lists which are redundant with the bit matrix, and using them
|
||||
to update the matrix when a %GOMSR or %GOVIS is done. However, most
|
||||
bit matrix terminals are not expected to go to such lengths.
|
||||
|
||||
NWG/RFC# 746 RMS 17-MAR-78 43976
|
||||
SUPDUP Graphics Extension
|
||||
|
||||
|
||||
How Several Process Can Draw On One Terminal Without Interfering With
|
||||
Each Other:
|
||||
|
||||
If we define "input-stream state" information to be whatever
|
||||
information which can affect the action of any command, other than
|
||||
what is contained in the command, then each of the several processes
|
||||
must have its own set of input-stream state variables.
|
||||
|
||||
This is accomplished by providing the %GOPSH command. The %GOPSH
|
||||
command saves all such input-stream information, to be restored when
|
||||
graphics mode is exited. If the processes can arrange to output
|
||||
blocks of characters uninterruptibly, they can begin each block with a
|
||||
%GOPSH followed by commands to initialize the input-stream state
|
||||
information as they desire. Each block of graphics output should be
|
||||
ended by a %TDNOP, leaving the terminal in its "normal" state for all
|
||||
the other processes, and at the same time popping the what the %GOPSH
|
||||
pushed.
|
||||
|
||||
The input-stream state information consists of:
|
||||
The cursor position
|
||||
the state of XOR mode (default is OFF)
|
||||
the selected set (default is 0)
|
||||
the co-ordinate unit in use (physical dots, or virtual)
|
||||
(default is physical)
|
||||
whether output is going to the display screen or to a hardcopy
|
||||
device (default is to the screen)
|
||||
what portion of the screen is in use
|
||||
(see "Using Only Part of the Screen")
|
||||
(default is all)
|
||||
|
||||
Each unit of input-stream status has a default value for the sake
|
||||
of programs that do not know that the information exists; the
|
||||
exception is the cursor position, since all programs must know that it
|
||||
exists. A %TDINI or %TDRST command should set all of the variables to
|
||||
their default values.
|
||||
|
||||
The state of the current set (whether it is visible, and where
|
||||
its center is) is not part of the input-stream state information,
|
||||
since it would be hard to say what it would mean if it were. Besides,
|
||||
the current set number is part of the input-stream state information,
|
||||
so different processes can use different sets. The allocation of sets
|
||||
to processes is the server host's own business.
|
||||
|
||||
NWG/RFC# 746 RMS 17-MAR-78 43976
|
||||
SUPDUP Graphics Extension
|
||||
|
||||
|
||||
Using Only Part of the Screen:
|
||||
|
||||
It is sometimes desirable to use part of the screen for picture
|
||||
and part for text. Then one may wish to clear the picture without
|
||||
clearing the text. On display list terminals, %GOCLR should do this.
|
||||
On bit matrix terminals, however, %GOCLR can't tell which bits were
|
||||
set by graphics and which by text display. For their sake, the %GOLMT
|
||||
command is provided. This command takes two cursor positions as
|
||||
arguments, specifying a rectangle. It declares that graphics will be
|
||||
limited to that rectangle, so %GOCLR should clear only that part of
|
||||
the screen. %GOLMT need not do anything on a terminal which can
|
||||
remember graphics output as distinct from text output and clear the
|
||||
former selectively, although it would be a desirable feature to
|
||||
process it even on those terminals.
|
||||
|
||||
%GOLMT can be used to enable one of several processes which
|
||||
divide up the screen among themselves to clear only the picture that
|
||||
it has drawn, on a bit matrix terminal. By using both %GOLMT and
|
||||
distinct sets, it is possible to deal successfully with almost any
|
||||
terminal, since bit matrix terminals will implement %GOLMT and display
|
||||
list terminals almost always implement sets.
|
||||
|
||||
The %TDCLR command should clear the whole screen, including
|
||||
graphics output, ignoring %GOLMT.
|
||||
|
||||
|
||||
Errors:
|
||||
|
||||
In general, errors in graphics commands should be ignored.
|
||||
|
||||
Since the output and input streams are not synchronized unless
|
||||
trouble is taken, there is no simple way to report an error well
|
||||
enough for the program that caused it to identify just which command
|
||||
was invalid. So it is better not to try.
|
||||
|
||||
Errors which are not the fault of any individual command, such as
|
||||
running out of memory for display lists, should also be ignored as
|
||||
much as possible. This does NOT mean completely ignoring the commands
|
||||
that cannot be followed; it means following them as much as possible:
|
||||
moving the cursor, selecting sets, etc. as they specify, so that any
|
||||
subsequent commands which can be executed are executed as intended.
|
||||
|
||||
NWG/RFC# 746 RMS 17-MAR-78 43976
|
||||
SUPDUP Graphics Extension
|
||||
|
||||
|
||||
Extensions:
|
||||
|
||||
This protocol does not attempt to specify commands for dealing
|
||||
with every imaginable feature which a picture-drawing device can have.
|
||||
Additional features should be left until they are needed and well
|
||||
understood, so that they can be done right.
|
||||
|
||||
|
||||
Storage of Graphics Commands in Files:
|
||||
|
||||
This can certainly be done. Since graphics commands are composed
|
||||
exclusively of the ASCII characters 0 - 177, any file that can hold
|
||||
ASCII text can hold the commands to draw a picture. This is less
|
||||
useful than you might think, however. Any program for editing, in
|
||||
whatever loose sense, a picture, will have its own internal data which
|
||||
determine the relationships between the objects depicted, and control
|
||||
the interpretation of the programs commands, and this data will all be
|
||||
lost in the SUPDUP graphics commands for displaying the picture.
|
||||
Thus, each such program will need to have its own format for storing
|
||||
pictures in files, suitable for that program's internal data
|
||||
structure. Inclusion of actual graphics commands in a file will be
|
||||
useful only when the sole purpose of the file is to be displayed.
|
||||
|
||||
NWG/RFC# 746 RMS 17-MAR-78 43976
|
||||
SUPDUP Graphics Extension
|
||||
|
||||
|
||||
Note: the values of these commands are represented as 8.-bit octal
|
||||
bytes. Arguments to the commands are in lower case inside angle
|
||||
brackets.
|
||||
|
||||
The Draw commands are:
|
||||
|
||||
Value Name Arguments
|
||||
|
||||
101 %GODLR <p>
|
||||
Draw line relative, from the cursor to <p>.
|
||||
102 %GODPR <p>
|
||||
Draw point relative, at <p>.
|
||||
103 %GODRR <p>
|
||||
Draw rectangle relative, corners at <p> and at the
|
||||
current cursor position.
|
||||
104 %GODCH <string> <0>
|
||||
Display the chars of <string> starting at the current
|
||||
graphics cursor position.
|
||||
121 %GODLA <p>
|
||||
Draw line absolute, from the cursor to <p>.
|
||||
The same effect as %GODLR, but the arg is an absolute
|
||||
address.
|
||||
122 %GODPA <p>
|
||||
Draw point absolute, at <p>.
|
||||
123 %GODRA <p>
|
||||
Draw rectangle absolute, corners at <p> and at the
|
||||
current cursor position.
|
||||
|
||||
The Erase commands are:
|
||||
|
||||
Value Name Arguments
|
||||
|
||||
141 %GOELR <p>
|
||||
Erase line relative, from the cursor to <p>.
|
||||
142 %GOEPR <p>
|
||||
Erase point relative, at <p>.
|
||||
143 %GOERR <p>
|
||||
Erase rectangle relative, corners at <p> and at the
|
||||
current cursor position.
|
||||
144 %GOECH <string> <0>
|
||||
Erase the chars of <string> starting at the current
|
||||
graphics cursor position.
|
||||
161 %GOELA <p>
|
||||
Erase line absolute, from the cursor to <p>.
|
||||
162 %GOEPA <p>
|
||||
Erase point absolute, at <p>.
|
||||
163 %GOERA <p>
|
||||
Erase rectangle absolute, corners at <p> and at the
|
||||
current cursor position.
|
||||
|
||||
NWG/RFC# 746 RMS 17-MAR-78 43976
|
||||
SUPDUP Graphics Extension
|
||||
|
||||
|
||||
The miscellaneous commands are:
|
||||
|
||||
Value Name Arguments
|
||||
|
||||
001 %GOMVR <p>
|
||||
Move cursor to point <p>
|
||||
021 %GOMVA <p>
|
||||
Move cursor to point <p>, absolute address.
|
||||
002 %GOXOR
|
||||
Turn on XOR mode. Bit matrix terminals only.
|
||||
022 %GOIOR
|
||||
Turn off XOR mode.
|
||||
003 %GOSET <n>
|
||||
Select set. <n> is a 1-character set number, 0 - 177.
|
||||
004 %GOMSR <p>
|
||||
Move set origin to <p>. Display list terminals only.
|
||||
024 %GOMSA <p>
|
||||
Move set origin to <p>, absolute address.
|
||||
006 %GOINV
|
||||
Make current set invisible.
|
||||
026 %GOVIS
|
||||
Make current set visible.
|
||||
007 %GOBNK
|
||||
Make current set blink. Canceled by %GOINV or %GOVIS.
|
||||
010 %GOCLR
|
||||
Erase whole screen.
|
||||
030 %GOCLS
|
||||
Erase entire current set (display list terminals).
|
||||
011 %GOPSH
|
||||
Push all input-stream status information, to be
|
||||
restored when graphics mode is exited.
|
||||
012 %GOVIR
|
||||
Start using virtual co-ordinates
|
||||
032 %GOPHY
|
||||
Resume giving co-ordinates in units of dots.
|
||||
013 %GOHRD <n>
|
||||
Divert output to output subdevice <n>.
|
||||
<n>=0 reselects the main display screen.
|
||||
014 %GOGIN <n>
|
||||
Request graphics input (mouse, tablet, etc).
|
||||
<n> is the reply code to include in the answer.
|
||||
015 %GOLMT <p1> <p2>
|
||||
Limits graphics to a subrectangle of the screen.
|
||||
%GOCLR will clear only that area. This is for those
|
||||
who would use the rest for text.
|
||||
|
||||
NWG/RFC# 746 RMS 17-MAR-78 43976
|
||||
SUPDUP Graphics Extension
|
||||
|
||||
|
||||
Bits in the SMARTS Variable Related to Graphics:
|
||||
|
||||
Note: the values of these bits are represented as octal 36.-bit words,
|
||||
with the left and right 18.-bit halfword separated by two commas as in
|
||||
the normal PDP-10 convention.
|
||||
|
||||
Name Value Description
|
||||
|
||||
%TQGRF 000001,,0 terminal understands graphics protocol.
|
||||
|
||||
%TQSET 000002,,0 terminal supports multiple sets.
|
||||
|
||||
%TQREC 000004,,0 terminal implements rectangle commands.
|
||||
|
||||
%TQXOR 000010,,0 terminal implements XOR mode.
|
||||
|
||||
%TQBNK 000020,,0 terminal implements blinking.
|
||||
|
||||
%TQVIR 000040,,0 terminal implements virtual co-ordinates.
|
||||
|
||||
%TQWID 001700,,0 character width, in dots.
|
||||
|
||||
%TQHGT 076000,,0 character height, in dots.
|
||||
|
||||
%TRGIN 0,,400000 terminal can provide graphics input.
|
||||
|
||||
%TRGHC 0,,200000 terminal has a hard-copy device to which output
|
||||
can be diverted.
|
||||
|
||||
;;;Local Modes:
|
||||
;;;Mode:Text
|
||||
;;;Auto Fill Mode:1
|
||||
;;;Fill Column:70
|
||||
;;;End:
|
||||
562
doc/sysdoc/intrup.108
Executable file
562
doc/sysdoc/intrup.108
Executable file
@@ -0,0 +1,562 @@
|
||||
Overview of ITS User Interrupts
|
||||
|
||||
When ITS wishes to signal a user program of the existence of an
|
||||
unusual interesting condition or occurrence, it does so via
|
||||
the "user interrupt" mechanism. This mechanism essentially
|
||||
causes the user program to call an interrupt handling subroutine
|
||||
in the middle of what it had been doing. The interrupt handler has
|
||||
enough information to be able to return to the interrupted code
|
||||
without any effects on it if desired, and to determine the cause
|
||||
of the interrupt so as to take appropriate action. The program
|
||||
can specify which interrupt conditions it wishes to handle, and
|
||||
what their priority order should be; un-handled interrupts are
|
||||
either ignored or fatal depending on the condition. Some interrupt
|
||||
conditions represent errors in the execution of the job; some
|
||||
indicate the occurrence of asynchronous events such as I/O operation
|
||||
completion; some exist for debugging and are always fatal.
|
||||
|
||||
The noun "interrupt" may mean either the event of interrupting
|
||||
a program (causing it to call the handler), or a condition which
|
||||
can cause a program to be interrupted. Also, the distinction
|
||||
between an interrupt condition and the bit which is 1 when the
|
||||
condition is present is often blurred.
|
||||
|
||||
Unlike TENEX, ITS never gives the user an interrupt "in the middle
|
||||
of a system call". The PC saved by an interrupt is always a user-mode PC.
|
||||
This is a great advantage when it comes to having the interrupt handler
|
||||
understand what the interrupted code was doing and fix it up.
|
||||
System calls will either be finished or backed out of (to be redone)
|
||||
when it is necessary for the job to be interrupted. To avoid having to
|
||||
do a lot of work twice, all ITS system calls that take a long time to
|
||||
complete are designed so that if restarted they will continue from
|
||||
where they left off. They do this by updating their arguments to
|
||||
indicate how much progress they have made, just like the BLT instruction.
|
||||
Now you know why SIOT and block-mode IOT update their pointer and
|
||||
byte count as they go.
|
||||
|
||||
Section A describes how interrupts are signaled and enabled, etc.
|
||||
Section B describes what is actually done to a job when it is
|
||||
interrupted, if it uses the older simple interrupt mechanism.
|
||||
Section C gives an example of an old-style interrupt handler.
|
||||
Section D describes what is actually done to a job when it is
|
||||
interrupted, if it uses the newer vectored interrupt mechanism.
|
||||
Section E describes the individual interrupt conditions in the
|
||||
first interrupt request word (.PIRQC).
|
||||
Section F describes the individual interrupt conditions in the
|
||||
second interrupt request word (.IFPIR).
|
||||
|
||||
A. The ITS Interrupt Mechanism
|
||||
|
||||
Each ITS job has two "interrupt request words", called .PIRQC
|
||||
and .IFPIR, and readable with .SUSET. Each distinct interrupt
|
||||
condition is assigned one of the bits in one of the words.
|
||||
The interrupt is "pending" when the bit is 1.
|
||||
.PIRQC is called the "first interrupt word" and interrupts in it
|
||||
are "first word interrupts". .IFPIR is the "second interrupt word"
|
||||
and its interrupts are "second word interrupts".
|
||||
|
||||
Interrupt conditions are divided by the system into three severity classes.
|
||||
Class 1 interrupts are always fatal. They are genarally conditions caused
|
||||
by the user or the superior, for debugging purposes; for example,
|
||||
breakpoints, ^Z typed, and single-instruction-proceed interrupts are
|
||||
of class 1. Class 2 interrupts are fatal unless the program is set up
|
||||
to handle the interrupt. Most error conditions are class 2; for example,
|
||||
MPV (memory protect violation), ILOPR (illegal operation), IOCERR
|
||||
(I/O channel error). All class 1 and 2 interrupts are first word
|
||||
interrupts. Class 3 interrupts are never fatal unless the user
|
||||
explicitly makes them so; either the program is eventually interrupted
|
||||
or nothing happens. Most asynchronous conditions are class 3.
|
||||
|
||||
When a job receives a fatal interrupt, that job is not interrupted
|
||||
itself; instead, it is stopped, as if its superior had stopped it,
|
||||
and an "inferior got a fatal interrupt" interrupt is signaled for the
|
||||
superior. If a top level job receives a fatal interrupt, then it will
|
||||
be stopped and detached (see the symbolic system call DETACH).
|
||||
|
||||
Each interrupt word has a corresponding mask word: .MASK for .PIRQC,
|
||||
and .MSK2 for .IFPIR. An interrupt is enabled if the appropriate bit in
|
||||
the mask word is 1. A program will not receive an interrupt which is
|
||||
disabled, but if the interrupt condition is in class 2 it
|
||||
will be fatal if it is not enabled. Class 3 interrupts will not even
|
||||
be signaled if they are disabled. Class 1 interrupts are not allowed
|
||||
to be enabled, the idea being that the job which gets an always-fatal
|
||||
interrupt is not allowed to handle the interrupt itself.
|
||||
|
||||
Each interrupt word also has a defer word: .DF1 for .PIRQC, and
|
||||
.DF2 for .IFPIR. If the appropriate bit in the defer word is set,
|
||||
the interrupt is "deferred". For a class 2 interrupt, deferment has
|
||||
the same effect as disablement: the interrupt becomes fatal.
|
||||
For a class 1 interrupt, deferment has no effect. For a class 3
|
||||
interrupt, deferment differs from disablement in that a deferred
|
||||
interrupt will still be signaled; it will then remain pending until
|
||||
it is no longer deferred, when it will be given to the user.
|
||||
The system makes it easy to defer a specified set of interrupts while
|
||||
processing an interrupt. That is how different priorities of
|
||||
interrupts may exist.
|
||||
|
||||
Slightly obsolete but still useful is the variable .PICLR, which is
|
||||
normally -1. If this variable is set to 0, all interrupts are deferred.
|
||||
The actual values of the defer words are unaltered. .PICLR was
|
||||
the original way to defer interrupts, before the defer words existed.
|
||||
The older style of interrupt handling on ITS sets .PICLR to 0 while
|
||||
an interrupt is being processed; thus, there is only one interrupt
|
||||
priority level.
|
||||
|
||||
To help eliminate timing errors, the six variables .PIRQC, .IFPIR,
|
||||
.MASK, .MSK2, .DF1 and .DF2 have aliases which have the same value
|
||||
when read, but when written either IORM or ANDCAM into the variable
|
||||
instead of setting all the bits in it. These aliases are called
|
||||
.IPIRQC, .IIFPIR, .IMASK, .IMSK2, .IDF1 and .IDF2 for IORM'ing,
|
||||
and .APIRQC, .AIFPIR, .AMASK, .AMSK2, .ADF1 and .ADF2 for ANDCAM'ing.
|
||||
Thus, depositing 20 in .APIRQC will clear the 20 bit in .PIRQC.
|
||||
|
||||
Error-condition interrupts (MPV, ILOPR, IOCERR, WIRO, DTTY and some others)
|
||||
usually abort the instruction that causes them. When this happens,
|
||||
the old convention (still the default) is to leave the PC pointing
|
||||
AFTER the aborted instruction. This is very bad since it is hard
|
||||
for the user's interrupt handler to tell whether to decrement the PC.
|
||||
The new convention, selected by setting bit %OPOPC in the LH of the
|
||||
.OPTION variable to 1, is for the system to decrement the PC when
|
||||
a fatal interrupt happens, so that if the interrupt handler fixes
|
||||
the problem (e.g. creates the nonexistent page of core) and dismisses,
|
||||
the instruction will be retried. All new programs should use the
|
||||
new convention; it would be nice to flush the old one entirely.
|
||||
|
||||
B. How Jobs Are Informed about Their Interrupts (Old Style)
|
||||
|
||||
There are two ways for a program to receive interrupts from the
|
||||
system: the old way, and the new way. The old scheme always stores
|
||||
the PC in the same place, making recursive interrupts difficult.
|
||||
It also makes all interrupts have the same priority level.
|
||||
The new scheme pushes the interrupt information on a stack. It also
|
||||
has the ability to decode the interrupts for the user, whereas with the
|
||||
old mechanism the program must decode the interrupts. Nevertheless,
|
||||
the old mechanism is not considered obsolete, since it is easier to use.
|
||||
|
||||
Both mechanisms have the user's interrupt handler information pointed
|
||||
to by location 42. More generally, the address of the interrupt pointer
|
||||
is 2 plus the rh of the .40ADDR variable; since .40ADDR usually holds
|
||||
40, the interrupt pointer usually lives in 42.
|
||||
|
||||
The two mechanisms are selected by the %OPINT bit of the .OPTION
|
||||
variable: the new mode is used if the bit is 1.
|
||||
|
||||
In the old mode, 42 is expected to contain the address of the
|
||||
interrupt handler itself. Let that address be called "TSINT"
|
||||
(every program should use that label, for the sake of humans).
|
||||
If TSINT is 0, or addresses nonexistent or pure storage,
|
||||
when the system attempts to interrupt the job, an always-fatal
|
||||
BADPI (%PIB42) interrupt is signaled and the program does not
|
||||
receive the original interrupts. If the superior, handling the BADPI,
|
||||
fixes up 42 and restarts the job, it will then be properly interrupted.
|
||||
|
||||
When an interrupt happens, all the
|
||||
pending enabled undeferred first word interrupts will be given to
|
||||
the user at once if there are any; otherwise, all the pending
|
||||
enabled undeferred second word interrupts will be given. The
|
||||
interrupts which are given will be cleared in the request word.
|
||||
Whichever interrupt request word is being given will be stored in TSINT.
|
||||
If the interrupts being handled are second-word interrupts, the sign
|
||||
of TSINT will be set. The PC is stored in TSINT+1. The job is then
|
||||
started at TSINT+2, with all PC flags except user and user-i/o zeroed.
|
||||
The job's .PICLR will be set to 0, preventing further interrupts while
|
||||
the interrupt handler is running. Because more than one interrupt
|
||||
may be given to the user at once, the interrupt routine should check
|
||||
all of the interrupt bits, and after handling one interrupt should
|
||||
return to check the remaining bits.
|
||||
|
||||
The normal way for the interrupt handler
|
||||
to exit is with the .DISMIS uuo, which should address a word containing
|
||||
the desired new PC. .DISMIS jumps to that PC, restoring flags, and also
|
||||
sets .PICLR to -1 to allow interrupts again. To restart the program
|
||||
where it was interrupted, .DISMIS TSINT+1 should be used. The program
|
||||
may desire to restore the saved PC flags but a different PC; in that
|
||||
case, it should probably clear the byte-interrupt flag (%PCFPD) before
|
||||
restoring the flags.
|
||||
|
||||
C. An Example of an Old Style Interrupt Handler
|
||||
|
||||
TSINT:
|
||||
LOC 42
|
||||
TSINT ;this is the interrupt pointer. -> int handler.
|
||||
LOC TSINT
|
||||
0 ;first word of handler gets the bits for the interrupts
|
||||
0 ;second gets the PC
|
||||
EXCH A,TSINT
|
||||
JUMPL A,TSINT2 ;sign of int word set => second word interrupts;
|
||||
TLNE A,%PJRLT ;otherwise, they are first word interrupts.
|
||||
PUSHJ P,TIMINT ;if we got an alarm clock int, handle that.
|
||||
TRNE A,%PIMPV
|
||||
PUSHJ P,MPVINT ;if we got an MPV, handle that.
|
||||
TRNE A,%PIIOC
|
||||
PUSHJ P,IOCINT ;if we got an IOCERR, handle that.
|
||||
TSINTX: EXCH A,TSINT
|
||||
.DISMIS TSINT+1 ;then restore the saved PC and zero .PICLR.
|
||||
|
||||
TSINT2: TRNE A,1_TYIC
|
||||
PUSHJ P,INPUTI ;handle characters typed on the tty (assuming
|
||||
;that tty input is open on channel TYIC)
|
||||
TDNE A,INFBIT
|
||||
PUSHJ P,INFINT ;handle interrupts from one of our inferiors,
|
||||
;assuming the inferior's .INTB variable was
|
||||
;read into INFBIT.
|
||||
JRST TSINTX
|
||||
|
||||
;if the program can't recover from MPV's well, it might do this:
|
||||
MPVINT: <TYPE ERROR MESSAGE SOMEHOW>
|
||||
.DISMIS [RESTART] ;re-initialize the program.
|
||||
|
||||
;if it wanted to create the referenced page, it might do this:
|
||||
MPVINT: PUSH P,B
|
||||
.SUSET [.RMPVA,,B]
|
||||
LSH B,-10. ;get the referenced page's number.
|
||||
.CALL [ SETZ ? 'CORBLK
|
||||
MOVEI 400000 ? MOVEI -1 ? B ? SETZI 400001]
|
||||
.VALUE ; ^ get a fresh page into page w/ number in B.
|
||||
POP P,B
|
||||
POPJ P,
|
||||
|
||||
D. How Jobs Are Informed about Their Interrupts (New Style)
|
||||
|
||||
When using the newer interrupt mechanism, the program must divide
|
||||
the interrupts that it handles into some number of groups (there
|
||||
may be as few as one interrupt in a group, or all the interrupts
|
||||
may be in one group). The interrupts in a group are all handled
|
||||
the same way; they have the same relative priority to all other
|
||||
interrupts, and have the same handler address. For each group,
|
||||
the user must specify to the system which interrupts are in it,
|
||||
which interrupts are considered to have a lower priority than
|
||||
those in the group, and where the handler for the group is located.
|
||||
This is done with the "interrupt table", which should be 5n+1 words
|
||||
long where n is the number of groups. The interrupt table should
|
||||
be identified to the system by means of an AOBJN pointer in 42.
|
||||
|
||||
The first word of the interrupt table should hold the address
|
||||
of the interrupt stack (which may be an accumulator - P will work!).
|
||||
The LH of this word specifies extra information to be pushed on
|
||||
the interrupt stack at each interrupt, beyond the necessary minimum:
|
||||
bits 3.5-3.1 # of ACs to push. 0 => don't push any ACs.
|
||||
bits 3.7-4.1 # of first AC to push.
|
||||
bit 4.9 1 => push the .JPC and .SUUOH variables, and the LSPCL
|
||||
(an internal ITS variable), after the ACs if any.
|
||||
|
||||
Then come five words for each interrupt group. Their meanings are:
|
||||
wd 1 The 1st word interrupts that are in this group.
|
||||
If a bit is set in this word, the corresponding interrupt is
|
||||
in this group.
|
||||
wd 2 The 2nd word interrupts which are in this group.
|
||||
wd 3 The 1st word interrupts that are of priority less than or equal to
|
||||
this group's. Give the bits for the appropriate interrupts.
|
||||
When interrupts in this group happen, these bits will be
|
||||
set in .DF1 to prevent the lower-priority interrupts from
|
||||
happening. Note that it is not obligatory to include the
|
||||
interrupts of the group itself in this word; if they are not
|
||||
included, they will be able to interrupt recursively. That is
|
||||
sometimes desirable for recoverable synchronous conditions.
|
||||
wd 4 The 2nd word interrupts that are ofthe same or lower priority.
|
||||
wd 5 The address of the handler for this group.
|
||||
|
||||
Note that the priority-relation between interrupts, specified by the
|
||||
second and third words of the groups in the interrupt table, need not
|
||||
be even a partial order: it is permissible for interrupt A to defer
|
||||
only B, B to defer only C, and C to defer only A, although not very
|
||||
useful. Often, a synchronous interrupt is left incomparable with all
|
||||
other interrupts - it defers only itself, or nothing.
|
||||
|
||||
Synchronous interrupts should come before asynchronous ones
|
||||
in the table. The only time an exception to that is safe is when
|
||||
the asynchronous interrupt defers the synchronous one. The reason for
|
||||
this rule is that when a synchronous interrupt and an asynchronous one
|
||||
are signalled at the same time, if the asynchronous interrupt comes
|
||||
earlier in the table it will happen first; if the synchronous one is
|
||||
not then deferred, it will interrupt saving a PC pointing at the first
|
||||
word of the asynchronous interrupt's handler - which is not the address
|
||||
of the instruction that actually caused the synchronous interrupt. If
|
||||
the synchronous interrupt's handler looks at the PC, as many do, it will
|
||||
be confused.
|
||||
|
||||
This is an example of an interrupt table (taken from DDT).
|
||||
|
||||
TSINT: LOC 42
|
||||
-TSINTL,,TSINT
|
||||
LOC TSINT
|
||||
|
||||
P ;interrupt pdl pointer address.
|
||||
%PIWRO ? 0 ? 0 ? 0 ? PURBR1
|
||||
;pure-page violations don't inhibit anything.
|
||||
;DDT wants to type out ":UNPURE", and doesn't
|
||||
;like to type out with any interrupts inhibited.
|
||||
%PITTY ? 0 ? %PITTY ? 0 ? TTYINT
|
||||
;Don't-have-tty interrupts defer themselves
|
||||
;so that they become fatal while one is being
|
||||
;processed. If DDT decides that the one
|
||||
;that happened should have been fatal, it
|
||||
;signals another by depositing in .IPIRQC, and
|
||||
;that one IS fatal since it is deferred.
|
||||
%PIIOC\%PIILO\%PIMPV\%PIOOB ? 0 ? #%PITTY ? -1 ? TSIN0
|
||||
;Error interrupts inhibit asynchronous ints for
|
||||
;safety's sake, and themselves so an error in
|
||||
;the handler will be fatal.
|
||||
#%PIIOC#%PIILO#%PIMPV#%PIOOB#%PIWRO#%PICLI#%PITTY ? #<1_TYOC>#1_TYOBC
|
||||
#%PIIOC#%PIILO#%PIMPV#%PIOOB#%PIWRO#%PICLI#%PITTY ? -1 ? TSIN0
|
||||
;Miscellaneous interrupts have the same handler
|
||||
;as the errors - for historical reasons - but
|
||||
;don't defer the errors, so that DDT can recover
|
||||
;if an error happens in a miscellaneous int.
|
||||
0 ? 1_TYOC+1_TYOBC ? 0 ? 0 ? MORINT
|
||||
;Bottom-of-screen-on-terminal interrupts defer nothing,
|
||||
;so they can exit by simply jumping if they wish.
|
||||
%PICLI ? 0 ? %PICLI ? 0 ? CLIBRK
|
||||
;Core-link interrupts (someone is :SEND'ing to me).
|
||||
TSINTL==.-TSINT
|
||||
|
||||
The algorithm for giving a set of interrupts is:
|
||||
Look through the interrupt block one group at a time.
|
||||
If a group is found that applies to any of the interupts that
|
||||
are to be given, all the interrupts that it applies to and that are
|
||||
to be given are pushed, together, onto the interrupt stack
|
||||
at once. The words pushed are:
|
||||
First, two words containing the interrupts being pushed.
|
||||
The first word interrupt bits are pushed first.
|
||||
Next, two words containing the old settings of .DF1 and .DF2.
|
||||
The old .DF1 is pushed first.
|
||||
Next, a word containing the PC before the interrupt.
|
||||
Last, any AC's or debugging variables specified by the LH of
|
||||
the first word of the interrupt table. These are pushed in the
|
||||
order: AC's first, then .JPC, then .SUUOH, and finally LSPCL.
|
||||
If pdl overflow is enabled, it will be detected properly when the
|
||||
interrupt data is pushed.
|
||||
After the necessary information has been saved and the interrupt pdl
|
||||
updated, the defer words and the PC will be set as specified
|
||||
in the the interrupt table.
|
||||
At this point, if there still remain any pending enabled undeferred
|
||||
interrupts, the whole process is repeated, scanning through all the
|
||||
groups from the beginning. Note that giving one interrupt may cause
|
||||
other previously undeferred interrupts to be deferred. It may also
|
||||
set the pdl overflow interrupt, in which case that interrupt will
|
||||
be given immediately if not deferred.
|
||||
|
||||
If there are pending enabled undeferred interrupts not included
|
||||
in any group, and they do not become deferred by the giving of other
|
||||
interrupts, then they are considered immediately fatal. Thus, the
|
||||
user can make a nonfatal interrupt be fatal by enabling it but not
|
||||
including it in any group.
|
||||
|
||||
The interrupt routine may conveniently
|
||||
exit with the DISMIS Symbolic System Call.
|
||||
The first arg, if not immediate, should point at the interrupt stack:
|
||||
.CALL [SETZ ? 'DISMIS ? SETZ P]
|
||||
The defer words and PC will be restored from the top 3
|
||||
words on the stack and 5 words will be popped. Stack overflow
|
||||
will be detected. You may specify that extra things should be popped
|
||||
using the control bit argument; bit 2.9 specifies that three words
|
||||
should be discarded, while <m>*100+<n> specifies that ACs <m> through
|
||||
<m>+<n>-1 should be popped. Thus, it is a win to give, as the control
|
||||
bit argument (in the RH) whatever was put in the LH of the first word
|
||||
of the interrupt table - that will cause the DISMIS to pop exactly
|
||||
what interrupts push.
|
||||
|
||||
If the first arg is immediate, clearly nothing can be popped:
|
||||
.CALL [SETZ ? 'DISMIS ? SETZI 2+[DF1 ? DF2 ? PC] ]
|
||||
In this case the control-bit argument is ignored.
|
||||
If a second argument is given, it is used as the new PC
|
||||
instead of what is found on the interrupt stack.
|
||||
Similarly, optional third and fourth arguments specify the new
|
||||
contents of the defer words, overriding what was saved on the stack.
|
||||
Thus, if four arguments are given and the first is immediate,
|
||||
the first argument is effectively ignored.
|
||||
|
||||
E. The Interrupt Bits in the First Interrupt Word.
|
||||
|
||||
The interrupt classes are:
|
||||
[1] stops job and interrupts superior (fatal intr)
|
||||
[2] stops job and interrupts superior unless enabled and undeferred
|
||||
[3] does nothing unless enabled; waits if deferred.
|
||||
Bits in the lh have two names: %PI... as a bit in the word,
|
||||
and %PJ... shifted down by 18. bits.
|
||||
|
||||
The following interrupts abort the instruction, and leave the PC pointing
|
||||
before the instruction if %OPOPC is 1 (as is winning), or after it if
|
||||
%OPOPC is 0: %PIMPV, %PIOOB, %PIIOC, %PIILO, %PJTTY, %PJWRO, %PJFET, %PJTRP.
|
||||
|
||||
"(S)" indicates a synchronous interrupt; "(A)", an asynchronous one.
|
||||
An interrupt is synchronous if its occurrence is always directly related
|
||||
to the instruction that is being executed when it is signaled.
|
||||
|
||||
;RH bits
|
||||
%PICLI==400000 ;CLI interrupt [3] (A)
|
||||
;Some job opened the CLI device with filenames equal
|
||||
;to the uname and jname of this job.
|
||||
%PIPDL==200000 ;PDL overflow [3] (S)
|
||||
%PILTP==100000 ;340 or E&S light pen hit [3] (A)
|
||||
%PIMAR==40000 ;MAR hit. [2] (S)
|
||||
;The MAR is a hardware feature that allows
|
||||
;references to a specific memory location to
|
||||
;be trapped. This is the interrupt that happens
|
||||
;when such a reference is detected. The guilty
|
||||
;instuction is usually not aborted; if it is, the
|
||||
;PC is SOS'ed regardless of the setting of %OPOPC.
|
||||
;See the .MARA and .MARPC variables.
|
||||
%PIMPV==20000 ;MPV (memory protect violation) [2] (S)
|
||||
;The job referenced a non-existent memory location.
|
||||
;The address of that location (roundd down to
|
||||
;a page boundary on KA-10's) may be found in .MPVA.
|
||||
;The guilty instruction was aborted, and the PC was
|
||||
;left set according to %OPOPC.
|
||||
%PICLK==10000 ;Slow (1/2 sec) clock [3] (A)
|
||||
%PI1PR==4000 ;Single-instruction proceed [1] (S)
|
||||
;If a job is started with the one-proceed flag
|
||||
;(%PC1PR on KA-10's) set, after one instruction
|
||||
;is completed a %PI1PR interrupt will occur.
|
||||
;DDT's ^N command uses this feature.
|
||||
%PIBRK==2000 ;.BREAK instruction executed. [1] (S)
|
||||
;.BREAK is used for DDT breakpoints, and for explicit
|
||||
;program requests to DDT.
|
||||
%PIOOB==1000 ;Address out of bounds [2] (S)
|
||||
;This is an obscure condition that used to
|
||||
;happen on USR device IOT's, when an attempt
|
||||
;was made to refer to a nonexistent location in the
|
||||
;other job. Now this always causes an MPV.
|
||||
;The guilty instruction was aborted, and the PC was
|
||||
;left set according to %OPOPC.
|
||||
%PIIOC==400 ;IOCERR (I/O channel error) [2] (S)
|
||||
;This indicates the failure of an I/O system
|
||||
;call. The channel that was being operated on is
|
||||
;in .BCHN, and its .IOS word should contain, in
|
||||
;bits 4.5 - 4.1, an error code.
|
||||
;The guilty instruction was aborted, and the PC was
|
||||
;left set according to %OPOPC.
|
||||
%PIVAL==200 ;.VALUE instruction executed [1] (S)
|
||||
%PIDWN==100 ;System-going-down status change [3] (A)
|
||||
;If the system changes its mind about whether
|
||||
;or when it is scheduled to go down, this interrupt
|
||||
;is signaled.
|
||||
%PIILO==40 ;ILOPR, ILUUO (illegal operation) [2] (S)
|
||||
;This can be caused by a returnable uuo when the
|
||||
;program's 41 doesn't seem suitable for handling one
|
||||
;(see ITS UUOS). It can also be used to report
|
||||
;the failure of certain more archaic system calls.
|
||||
;The guilty instruction was aborted, and the PC was
|
||||
;left set according to %OPOPC.
|
||||
%PIDIS==20 ;Display memory protect [2] (A)
|
||||
;The 340 or E&S display got an MPV.
|
||||
;This is now obsolete since the 340 and E&S
|
||||
;no longer work.
|
||||
%PIARO==10 ;Arithmetic overflow [3] (S)
|
||||
;The PDP-10's built-in arithmetic overflow
|
||||
;condition was detected by the hardware.
|
||||
;In fact, overflow occurs so often
|
||||
;that enabling this interrupt causes the
|
||||
;machine to slow down considerably,
|
||||
;and it should be avoided.
|
||||
%PIB42==4 ;BADPI (Bad location 42) [1] (S)
|
||||
;If in attempting to interrupt a job it turns out
|
||||
;to be necessary to refer to nonexistent memory
|
||||
;or write in read-only memory, this interrupt
|
||||
;is signaled, instead of MPV or WIRO.
|
||||
;This is so that the program will return to DDT
|
||||
;instead of mysteriously looping.
|
||||
%PIC.Z==2 ;^Z or CALL typed on terminal [1] (A)
|
||||
%PITYI==1 ;TTY input (obsolete) [3] (A)
|
||||
|
||||
;LH bits
|
||||
%PJRLT==200000 ;Real-time timer went off [3] (A)
|
||||
;These interrupts are controlled by the .REALT
|
||||
;uuo. See ITS UUOS.
|
||||
%PJRUN==100000 ;Run-time timer went off [3] (A)
|
||||
;This interrupt is requested (in advance)
|
||||
;by setting .RTMR.
|
||||
%PJNXI==40000 ;Non-existent IO register [2] (S)
|
||||
;A Job in User IOT mode referenced a non-existent IO
|
||||
;register on the KS10 Unibus. The PC is left pointing
|
||||
;before the guilty instruction. The address of the
|
||||
;non-existant register may be found in .MPVA.
|
||||
%PJJST==20000 ;Job Status display request. [3] (A)
|
||||
;The sequence ^_J was typed on the
|
||||
;console owned by this process or some inferior.
|
||||
%PJDCL==10000 ;Deferred call. [1] (S)
|
||||
;An attempt was made to read TTY input
|
||||
;and the next character was a deferred-call
|
||||
;character (^_D or Control-CALL).
|
||||
;This deferred-call character is never seen
|
||||
;by the program; it just causes the interrupt.
|
||||
;It differs from ordinary CALL or ^Z
|
||||
;in that it takes effect when the program
|
||||
;gets around to reading it, not immediately.
|
||||
%PJATY==4000 ;TTY returned. [3] (A)
|
||||
;This interrupt happens when the TTY is
|
||||
;returned by the superior, after having
|
||||
;been taken away. TECO uses this to know
|
||||
;that it must redisplay the entire screen.
|
||||
%PJTTY==2000 ;Don't have TTY [2] (S)
|
||||
;This results from an attempt to use the job's
|
||||
;console tty when the job does not own it, if
|
||||
;%TBINT is 1 and %TBWAT is 0. See ITS TTY.
|
||||
;The guilty instruction is aborted, and the PC is
|
||||
;left set according to %OPOPC.
|
||||
%PJPAR==1000 ;Memory parity error [2] (A)
|
||||
;Programs are not intended to try to recover
|
||||
;from parity errors, on the assumption that they
|
||||
;are probably permanently screwed up.
|
||||
;This interrupt is asynchronous because it can
|
||||
;be caused by a parity error in another job
|
||||
;which destroys data in a page shared with this job.
|
||||
%PJFOV==400 ;ARFOV (Floating overflow) [3] (S)
|
||||
;This is a non-aborting PDP-10 hardware condition.
|
||||
%PJWRO==200 ;WIRO (Write in read-only page) [2] (S)
|
||||
;The guilty instruction was aborted, and the PC was
|
||||
;left set according to %OPOPC. The address of read
|
||||
;only location (rounded down to a page boundary on
|
||||
;KA-10's) may be found in .MPVA.
|
||||
%PJFET==100 ;Fetched insn from impure page [2] (S)
|
||||
;On KA-10's, if bit %PCPUR of the PC flags is 1,
|
||||
;fetching an instruction from an impure page
|
||||
;will cause this interrupt. This is supposed to
|
||||
;facilitate catching jumps to randomness.
|
||||
;The guilty instruction is aborted, and the PC is
|
||||
;left set according to %OPOPC.
|
||||
%PJTRP==40 ;SYSUUO (System uuo in trap mode) [2] (S)
|
||||
;A job whose .UTRAP variable was nonzero either
|
||||
;attempted to execute an instruction that trapped
|
||||
;to the system, or was about to be interrupted.
|
||||
;This feature is intended to be used by the superior
|
||||
;to provide a non-ITS environment for the inferior.
|
||||
;For that purpose, this interrupt should not be
|
||||
;enabled for the inferior, so that it will be fatal.
|
||||
;The guilty instruction was aborted, and the PC was
|
||||
;left set according to %OPOPC.
|
||||
%PJDBG==2 ;System being debugged state change [3] (A)
|
||||
;When the system enters or leaves "debugging mode",
|
||||
;this interrupt is signaled.
|
||||
%PJLOS==1 ;A .LOSE UUO or a LOSE system call [2] (S)
|
||||
;was executed.
|
||||
|
||||
F. The Interrupt Bits in the Second Word
|
||||
|
||||
The right half of the second word (.IFPIR) is used for I/O channel
|
||||
interrupts that signal the arrival of or need for data.
|
||||
They should not be confused with I/O channel error interrupts
|
||||
or IOCERRors. Each channel has its own bit: 1.1 is for channel
|
||||
0; 1.2, for channel 1; ... 2.7, for channel 17 .
|
||||
They are all class 3, and their significance depends on the device
|
||||
open on the channel.
|
||||
|
||||
The left half of the second word (.IFPIR) is used for
|
||||
"inferior got a fatal interrupt" interrupts. Each of a job's
|
||||
inferiors is assigned its own interrupt bit from among the
|
||||
bottom 8 bits of the left half. When an inferior job is created,
|
||||
its interrupt bit should be read and remembered by reading the
|
||||
.INTB variable with a .USET. Every time that inferior gets a fatal
|
||||
interrupt, it will be stopped and the superior will receive an
|
||||
interrupt on that inferior's bit in .IFPIR. The inferior may
|
||||
be restarted by zeroing its .USTP variable, but if the fatal
|
||||
interrupts remain and are still fatal the inferior will simply
|
||||
stop and interrupt the superior again. "Inferior got a fatal
|
||||
interrupt" interrupts are all class 3.
|
||||
|
||||
The reason that inferiors interrupt through a special set of bits
|
||||
instead of using I/O channel interrupts is that it makes it possible
|
||||
to receive interrupts from all one's inferiors without having them
|
||||
all open on I/O channels at all times. DDT normally keeps only
|
||||
its current job open, and when it receives an interrupt from some
|
||||
other job it opens that job temporarily.
|
||||
3571
doc/sysdoc/itstty.41
Executable file
3571
doc/sysdoc/itstty.41
Executable file
File diff suppressed because it is too large
Load Diff
782
doc/sysdoc/job.100
Executable file
782
doc/sysdoc/job.100
Executable file
@@ -0,0 +1,782 @@
|
||||
PROGRAMMING TECHNOLOGY DIVISION DOCUMENT SYS.xx.yy
|
||||
|
||||
|
||||
IDENTIFICATIONî______________
|
||||
|
||||
The JOB/BOJ Device: A Mechanism for Implementing
|
||||
Non-standard Devices
|
||||
|
||||
Marc S. Seriff, Jack Haverty, Richard Stallman (MIT-AI)
|
||||
|
||||
September 18, 1974
|
||||
|
||||
|
||||
INTRODUCTIONî____________
|
||||
|
||||
It is occasionally desirable to extend the ITS system to allow
|
||||
|
||||
for the use of non-standard I/O devices. A very desirable feature
|
||||
|
||||
would be to allow user-level programs to make use of the newly defined
|
||||
|
||||
devices with out modification of the user-level programs. For this
|
||||
|
||||
reason the JOB/BOJ device was implemented.
|
||||
|
||||
When a job (call it the user) attempts an OPEN for a file whose
|
||||
|
||||
name is "JOB: <-dir>-; <-fn1>- <-fn2>-", the system creates a
|
||||
|
||||
new job, called the BOJ device handler, or BDH (this is a terrible
|
||||
|
||||
name; it USES the BOJ device and HANDLES the JOB device), and attempts
|
||||
|
||||
to load the file "DSK: <-dir>-; <-fn1>- <-fn2>-" into that job.
|
||||
|
||||
If the load fails, the OPEN will fail. If this load succeeds, the
|
||||
|
||||
OPEN, as well as all further I/O operations on the user's JOB channel
|
||||
|
||||
will be referred to the BDH for execution. At that point, it will be
|
||||
|
||||
up to the BDH to decide whether or not the open should fail. In order
|
||||
|
||||
to get a handle on information about the user's open, The BDH opens
|
||||
|
||||
one or more channels to the "BOJ" device. The system will insure that
|
||||
|
||||
the BDH's BOJ channel is logically linked to the user's JOB channel.
|
||||
|
||||
The following diagram illustrates what happens:
|
||||
PTDD 2 SYS.xx.yy
|
||||
|
||||
|
||||
|
||||
__________ _________
|
||||
| | | |
|
||||
| User |------v__________------>| BDH |
|
||||
|__________| | | ---XO--- | | |_________|
|
||||
| | Sys|tem | |
|
||||
____| |_____|_____| |____
|
||||
|v | |v
|
||||
The JOB channel | The BOJ channel
|
||||
|
|
||||
|v
|
||||
System mediates
|
||||
|
||||
|
||||
Once the BDH has successfully opened the BOJ channel, it will be
|
||||
|
||||
notified (via an I/O channel interrupt) every time the user attempts
|
||||
|
||||
an I/O operation on the JOB channel. The BDH may then examine the
|
||||
|
||||
data that is made available to it about the I/O operation and may
|
||||
|
||||
simulate the operation for the user. In this way, BDHs can be written
|
||||
|
||||
to give anything the appearance of a disk, tape or other specific type
|
||||
|
||||
of I/O device.
|
||||
|
||||
USING THE JOB DEVICEî_____ ___ ___ ______
|
||||
|
||||
Programs that use the JOB device should not be required to make
|
||||
|
||||
special provisions. A BDH should, in general, be written so that the
|
||||
|
||||
non-standard device will behave exactly like some standard device. In
|
||||
|
||||
other words, a user program may open a JOB device using a standard
|
||||
|
||||
open and may then execute any legal I/O operation.
|
||||
|
||||
A file name with something other than "JOB" for a device code can
|
||||
|
||||
be made to act like a JOB device in one of two ways. The first way
|
||||
|
||||
should be used for devices that are not generally applicable or are
|
||||
|
||||
expected to be used only for a short time. To use this method simply
|
||||
|
||||
use translates (using MONIT, DDT or directly via system calls) to
|
||||
|
||||
inform the system which file should be used as a BDH. For instance,
|
||||
|
||||
if we translate all file names of the form "XXX:" into the file name
|
||||
PTDD 3 SYS.xx.yy
|
||||
|
||||
|
||||
"JOB:ABC;TS RUNXXX", then the system will use the file "DSK:ABC;TS
|
||||
|
||||
RUNXXX" as the BDH for any file name whose device code is "XXX".
|
||||
|
||||
The other method is much simpler and is designed for non-standard
|
||||
|
||||
devices that are to be made available to the entire user community.
|
||||
|
||||
When an OPEN is attempted on a device whose name the system does not
|
||||
|
||||
recognize, the system will examine the "DEVICE;" directory for a file
|
||||
|
||||
whose first name is "JOBDEV" and whose second name is the unrecognized
|
||||
|
||||
device name. If such a file exists, then the contents of that file
|
||||
|
||||
will be loaded by the system and used as the BDH for the user's OPEN.
|
||||
|
||||
USING THE BOJ DEVICE - THE BOJ DEVICE HANDLERî_____ ___ ___ ______ _ ___ ___ ______ _______
|
||||
|
||||
The BDH is the workhorse in the JOB/BOJ device scheme. It is
|
||||
|
||||
required to interpret all of the user's I/O operations. It must do
|
||||
|
||||
everything to make the non-standard device that it represents appear
|
||||
|
||||
standard. The system provides five .CALLs to give the BDH some of the
|
||||
|
||||
required communcation with the user.
|
||||
|
||||
The first thing that the BDH should do when he is loaded and
|
||||
|
||||
started by the system is to execute an OPEN on the BOJ device. This
|
||||
|
||||
establishs a logical link between the user and the BDH. The BDH may
|
||||
|
||||
enable a channel interrupt on the BOJ channel, in order to be informed
|
||||
|
||||
whenever the user attempts an I/O operation.
|
||||
|
||||
It should be noted that the ITS system allows for the possibility
|
||||
|
||||
of a full duplex connection between the user and the BDH (i.e. a
|
||||
|
||||
channel in each direction). If a user attempts an open for reading
|
||||
|
||||
and an open for writing on the same device, then the system will
|
||||
|
||||
present both opens to the same activation of the BDH. Should this be
|
||||
|
||||
undesirable for a particular BDH, that BDH should use an open mode
|
||||
|
||||
with the 3.4 bit set (10 in the left half) each time it attempts to
|
||||
|
||||
open the BOJ device.
|
||||
PTDD 4 SYS.xx.yy
|
||||
|
||||
|
||||
JOBCAL SYSTEM CALLî______ ______ ____
|
||||
|
||||
The first .CALL that will be discussed is the JOBCAL. This call
|
||||
|
||||
enables the BDH to find out what I/O operation the user has attempted
|
||||
|
||||
to execute. It has the following calling sequence:
|
||||
|
||||
.CALL JOBCAL
|
||||
... ; Error return
|
||||
... ; Success return
|
||||
|
||||
JOBCAL: SETZ
|
||||
SIXBIT/JOBCAL/
|
||||
[<-BOJ channel number>-]
|
||||
2000,,<-opcode>-
|
||||
SETZ [-<-n>-,,<-data>-]
|
||||
|
||||
|
||||
This .CALL, as well as the other three discussed below, will fail to
|
||||
|
||||
skip if any of the following conditions hold:
|
||||
|
||||
1. <-BOJ channel number>- is an illegal channel number.
|
||||
|
||||
2. <-BOJ channel number>- is not open on the BOJ device.
|
||||
|
||||
3. the user job does not exist or as has closed his channel.
|
||||
|
||||
4. the user job is no longer attempting to execute the I/O
|
||||
operation.
|
||||
|
||||
<-opcode>- should be an address into which information about
|
||||
|
||||
the I/O operation requested will be placed. This word contains three
|
||||
|
||||
sections. The right half of the word contains an integer indicating
|
||||
|
||||
which operation was attempted. The following table indicates what the
|
||||
|
||||
various integers mean:
|
||||
PTDD 5 SYS.xx.yy
|
||||
|
||||
|
||||
|
||||
CODE OPERATIONî ____ _________
|
||||
|
||||
0 OPEN
|
||||
|
||||
1 IOT (transfer)
|
||||
|
||||
2 STATUS (currently unused)
|
||||
|
||||
3 RESET
|
||||
|
||||
4 RCHST (complete status)
|
||||
|
||||
5 ACCESS
|
||||
|
||||
6 FDELE (for delete or rename while not open)
|
||||
|
||||
7 FDELE (for rename while open)
|
||||
|
||||
8 CALL (see below)
|
||||
|
||||
It is up to the BDH to insure that these I/O operations perform as
|
||||
|
||||
they would for standard ITS devices.
|
||||
|
||||
The top three bits (4.9-4.7) of the op-code word contain the mode
|
||||
|
||||
in which user is attempting to open his channel. This is only
|
||||
|
||||
meaningful for op-code 0, OPEN. If either of the next two bits (4.6
|
||||
|
||||
and 4.5) are non-zero, then the user is requesting that a channel be
|
||||
|
||||
closed. As was mentioned above, the system allows the connection
|
||||
|
||||
between user and BDH to be full dumplex. If the 4.6 bit of the opcode
|
||||
|
||||
is set, then the user is requesting that his input channel be closed,
|
||||
|
||||
while the 4.5 bit requests a close of the user's output channel. It
|
||||
|
||||
is possible to get an opcode in which both bits are set. In the case
|
||||
|
||||
the BDH should perform the obvious task of closing both channels.
|
||||
|
||||
Most I/O operations require more information than just the name
|
||||
|
||||
of the operation. The third argument to JOBCAL tells the system where
|
||||
|
||||
any additional information that is available should be placed.
|
||||
|
||||
<-n>- is the largest number of words that the BDH is willing to
|
||||
PTDD 6 SYS.xx.yy
|
||||
|
||||
|
||||
accept (it should normally be 12). <-data>- is the address where
|
||||
|
||||
the first word of the information should be placed. What information
|
||||
|
||||
is placed in this buffer is determined by the I/O operation being
|
||||
|
||||
attempted.
|
||||
|
||||
If the op-code (in the right half of the op-code word) is less
|
||||
|
||||
than 8, then five words will be written into the buffer (beginning at
|
||||
|
||||
<-data>-) in response to the JOBCAL. The meanings of the words are
|
||||
|
||||
given in the following table:
|
||||
PTDD 7 SYS.xx.yy
|
||||
|
||||
|
||||
|
||||
WORD OPERATIONS MEANINGî____ __________ _______
|
||||
|
||||
1 IOT (1) Meaningful only for block IOTs.
|
||||
This word will contain the user's
|
||||
IOT pointer. The left half of this
|
||||
word will be the negative of the
|
||||
number of words that the user wants.
|
||||
|
||||
1 ACCESS (5) The address within the virtual file
|
||||
that is open from (or to) which the
|
||||
next IOT should be done. The first
|
||||
word of the virtual file is word
|
||||
zero.
|
||||
|
||||
1 FDELE (6 or 7) Zero implies delete requested.
|
||||
Non-zero means that a rename is
|
||||
requested. This word is the name
|
||||
(in sixbit) to be used as the new
|
||||
first file name.
|
||||
|
||||
2 OPEN (0) or FDELE (6) First name of the file that the user
|
||||
is attempting to open, rename or
|
||||
delete.
|
||||
|
||||
3 OPEN (0) or FDELE (6) Second name of the file that the
|
||||
user is attempting to open, rename
|
||||
or delete.
|
||||
|
||||
4 OPEN (0) or FDELE (6) Name of directory to be used for
|
||||
open, rename or delete.
|
||||
|
||||
5 OPEN (0) or FDELE (6) Name of device to be used for open,
|
||||
rename or delete.
|
||||
|
||||
6 OPEN (0) The full 18 bit open mode (right
|
||||
justified).
|
||||
|
||||
6 FDELE (6 or 7) Zero implies delete. Non-zero means
|
||||
that a rename is requested. This
|
||||
word is the name (in sixbit) to be
|
||||
used as the new second file name.
|
||||
|
||||
If the op-code returned by JOBCAL is 8, then the user has
|
||||
|
||||
attempted some I/O operation not recognized by the systems JOB/BOJ
|
||||
|
||||
device code (this does not mean that the operation is illegal). Inî ___
|
||||
|
||||
this case, more information is written into the BDH's buffer (up to
|
||||
|
||||
twelve words). The first of the data words will be the SIXBIT name of
|
||||
PTDD 8 SYS.xx.yy
|
||||
|
||||
|
||||
the operation being performed. (This will normally be the name of the
|
||||
|
||||
.CALL executed by the user - see Appendix 1 for a list of
|
||||
|
||||
possiblities.) The second word will contain all of the flags that the
|
||||
|
||||
user has set using the "flag" feature of the .CALL UUO. The third
|
||||
|
||||
word will be an integer indicating how many input (to the system)
|
||||
|
||||
arguments the user supplied in his .CALL. It should be noted that if
|
||||
|
||||
this integer is larger than <-n>-+3, then some information will be
|
||||
|
||||
lost. The values of the input arguments will appear in the remainder
|
||||
|
||||
of the words in the buffer. Remember that, in almost all cases, the
|
||||
|
||||
first of the input arguments will be the user's channel number.
|
||||
|
||||
JOBRET SYSTEM CALLî______ ______ ____
|
||||
|
||||
Once the BDH has interpreted the user's request for execution of
|
||||
|
||||
an I/O operation, the BDH must have some way of responding to the
|
||||
|
||||
user. This is provided with the JOBRET .CALL. This .CALL serves
|
||||
|
||||
three purposes:
|
||||
|
||||
1. to unblock the user who is waiting for completion of his
|
||||
I/O request (possibly causing the request to skip)
|
||||
|
||||
2. to set lossage codes in the user's status words (e.g. for
|
||||
failed opens).
|
||||
|
||||
3. to return information requested by the user's I/O
|
||||
operation.
|
||||
|
||||
The format of this CALL is as follows:
|
||||
|
||||
.CALL JOBRET
|
||||
... ; error return
|
||||
... ; success return
|
||||
|
||||
JOBRET: SETZ
|
||||
SIXBIT /JOBRET/
|
||||
[<-BOJ channel number>-]
|
||||
[<-return>-]
|
||||
SETZ [-<-n>-,,<-data>-]
|
||||
|
||||
|
||||
where <-return>- satisfies requirements 1 and 2 above. If
|
||||
PTDD 9 SYS.xx.yy
|
||||
|
||||
|
||||
<-return>- is zero, then the user's I/O call will not skip or set
|
||||
|
||||
status bits. If <-return>- is of the form <-i>-,,<-j>- , then
|
||||
|
||||
<-i>- will be placed in the "open-loss" field of the status word for
|
||||
|
||||
the user's channel and the user's I/O call will skip <-j>- times. A
|
||||
|
||||
list of all currently recognized open loss codes can be found in
|
||||
|
||||
Appendix 2.
|
||||
|
||||
If the user's I/O call requested data, then the BDH can supply
|
||||
|
||||
this data by supplying the third argument to the JOBRET call. The
|
||||
|
||||
system will use the <-n>- words beginning at location <-data>- as
|
||||
|
||||
the values for the return arguments in the user's call.
|
||||
|
||||
SETIOC AND JOBINT -- INTERRUPT SYSTEM CALLSî______ ___ ______ __ _________ ______ _____
|
||||
|
||||
There are two interrupt oriented functions that the BDH must
|
||||
|
||||
perform and there are CALLs available to perform them. The first is
|
||||
|
||||
to notify the user when he has done something catastrophic. The user
|
||||
|
||||
should be notified of his error by causing the system to awaken him
|
||||
|
||||
with an I/O channel error. This done with the SETIOC call, as
|
||||
|
||||
follows:
|
||||
|
||||
.CALL SETIOC
|
||||
... ; error return (standard reasons
|
||||
+ illegal IOCERR code)
|
||||
... ; success return
|
||||
|
||||
SETIOC: SETZ
|
||||
SIXBIT/SETIOC/
|
||||
[<-BOJ channel number>-]
|
||||
SETZ [<-IOCERR code>-]
|
||||
|
||||
|
||||
where <-IOCERR code>- is an integer identifying the reason for the
|
||||
|
||||
error. This integer should be chosen from the list that can be found
|
||||
|
||||
in Appendix 2. Since BDHs are written to handle non-standard devices,
|
||||
|
||||
these error codes will quite often not apply. Simply choose the code
|
||||
|
||||
that comes closest.
|
||||
PTDD 10 SYS.xx.yy
|
||||
|
||||
|
||||
Occassionally, the BDH must notify the user of a non-catastrophic
|
||||
|
||||
situation (e.g. the arrival of data). The JOBINT call allows the BDH
|
||||
|
||||
to give the user a second-word I/O channel interrupt, as follows:
|
||||
|
||||
.CALL JOBINT
|
||||
... ; error return
|
||||
... ; success return
|
||||
|
||||
JOBINT: SETZ
|
||||
SIXBIT /JOBINT/
|
||||
SETZ [<-BOJ channel number>-]
|
||||
|
||||
|
||||
JOBSTS SYSTEM CALLî______ ______ ____
|
||||
|
||||
Finally, the BDH must have some way to notify the system what the
|
||||
|
||||
status of the pseudo-device is. For this purpose, the JOBSTS call is
|
||||
|
||||
available. Its calling sequence is as follows:
|
||||
|
||||
.CALL JOBSTS
|
||||
... ; error return
|
||||
... ; success return
|
||||
|
||||
JOBSTS: SETZ
|
||||
SIXBIT /JOBSTS/
|
||||
[<-BOJ channel number>-]
|
||||
SETZ [<-new status>-]
|
||||
|
||||
|
||||
The right half of <-new status>- will be given to anyone requesting
|
||||
|
||||
the status of the user's channel until another JOBSTS is done. It
|
||||
|
||||
should be remembered that the low order six bits (1.1-1.6) should
|
||||
|
||||
contain the device code of the pseudo-device. Unless, you know what
|
||||
|
||||
you are doing, this should always be 22 octal.
|
||||
|
||||
DATA TRANSFERS - HOW TO IOTî____ _________ _ ___ __ ___
|
||||
|
||||
Since the main purposes of I/O devices is transfer of
|
||||
|
||||
information, let us look at how the BDH manages to respond to the
|
||||
|
||||
user's IOTs. The method for doing this is very simply. If we think
|
||||
|
||||
back to the diagram presented early in this memo, we will remember
|
||||
PTDD 11 SYS.xx.yy
|
||||
|
||||
|
||||
that the BOJ and JOB channels (i.e. the channels belonging to the BDH
|
||||
|
||||
and the user, respectively) are logically connected. The full meaning
|
||||
|
||||
of this now becomes clear. If the JOB channel is open for input and
|
||||
|
||||
the BOJ channel is open for output, then anything that BDH outputs on
|
||||
|
||||
the BOJ channel will be available to the user as input on the JOB
|
||||
|
||||
channel. (For this reason, the BDH must insure that he opens the BOJî ____
|
||||
|
||||
channel in the opposite direction from the user's JOB channel even if
|
||||
|
||||
this requires opening the BOJ channel a second time in the correct
|
||||
|
||||
mode.)
|
||||
|
||||
There are two features of which the BDH implementer should be
|
||||
|
||||
aware when writing the I/O sections of the BDH. Let us assume for the
|
||||
|
||||
discussion here, that the user has the JOB channel open for reading
|
||||
|
||||
and that the BDH has the BOJ channel open for writing. Let us also
|
||||
|
||||
assume that the user is currently hung attempting to read 100 words on
|
||||
|
||||
his JOB channel.
|
||||
|
||||
First it should be noted that the BDH does not have to respond toî ___
|
||||
|
||||
this request with a single transfer of 100 words. The system will act
|
||||
|
||||
as an mediator between different transfer sizes. The BDH can respond
|
||||
|
||||
to the user's request for 100 words in several ways:
|
||||
|
||||
1. He can send all 100 words in small pieces (e.g. 10
|
||||
|
||||
transfers of 10 words each.
|
||||
|
||||
2. He can send all 100 words in a single transfer.
|
||||
|
||||
3. He can send more than 100 words. In this case, the BDH
|
||||
|
||||
will remain hung in his IOT until the user has read all of
|
||||
|
||||
the data that the BDH is attempting to send. (If this is
|
||||
|
||||
undesirable, set the 3.5 in the BOJ open mode. This will
|
||||
|
||||
cause BOJ IOTs to unhang whenever the user's IOT is
|
||||
PTDD 12 SYS.xx.yy
|
||||
|
||||
|
||||
satisfied. When that happens, the BOJ IOT pointer will
|
||||
|
||||
have been counted out only partially; the RH will point to
|
||||
|
||||
the first word not transfered)
|
||||
|
||||
4. He may send less than 100 words. In this case, the BDH
|
||||
|
||||
must manually awaken the user as described below.
|
||||
|
||||
The user, who is hung awaiting his 100 words, will stay hung until he
|
||||
|
||||
has received all 100 words. Suppose, however, that the BDH only
|
||||
|
||||
wishes to send 50 words (e.g. the last 50 words of the virtual file).
|
||||
|
||||
To do this, he can send the 50 words normally, but must then use the
|
||||
|
||||
JOBRET call (described above) to awaken the user. JOBRET should be
|
||||
|
||||
called with the BOJ channel number as the first argument, zero as the
|
||||
|
||||
second argument and no third argument. Secondly, the BDH implementer
|
||||
|
||||
must be aware that the ITS system guarantees that IOTs to a channel
|
||||
|
||||
open in block mode, will never generate an I/O channel error. In
|
||||
|
||||
other words, the following algorithm should be followed:
|
||||
|
||||
1. If the user requests n words and there are n words or more
|
||||
|
||||
left in the "file", give him n words.
|
||||
|
||||
2. If the user requests n words and there are only m words
|
||||
|
||||
(n>m), give him m words and manually awaken him (using
|
||||
|
||||
JOBRET).
|
||||
|
||||
3. If the user requests n words and there are no words left,
|
||||
|
||||
then give him nothing and manually awaken him (using
|
||||
|
||||
JOBRET).
|
||||
|
||||
HINTS TO BDH IMPLEMENTERSî_____ __ ___ ____________
|
||||
|
||||
The following hints should ease the task of BDH implementers a
|
||||
|
||||
little. It is hoped that anyone who attempts to a BDH implementation
|
||||
|
||||
will add his harshly acquired knowledge to this section of this memo.
|
||||
PTDD 13 SYS.xx.yy
|
||||
|
||||
|
||||
1. Remember that the BDH is essentially a disowned job and should
|
||||
|
||||
attempt to log out after a close has been requested.
|
||||
|
||||
2. Be very leery of logging out for any reason other than a requested
|
||||
|
||||
CLOSE. In particular:
|
||||
|
||||
a. if a JOBCAL fails, only log out if a request for OPEN has not
|
||||
|
||||
yet been received.
|
||||
|
||||
b. when you generate an I/O channel error for the user, only log
|
||||
|
||||
out if the error is irrecoverable. Remember that he can
|
||||
|
||||
correct an access beyond end-of-file by doing an access before
|
||||
|
||||
attempting another IOT.
|
||||
|
||||
c. if he requests an I/O operation that you do not recognize,
|
||||
|
||||
generate a "mode not available" error (via JOBRET) and wait
|
||||
|
||||
for his next request.
|
||||
|
||||
d. if you decide, for your own reasons, to make the initial open
|
||||
|
||||
fail, you should log out.
|
||||
|
||||
THE OJB DEVICE -- AN AID FOR DEBUGGING THE BDHî___ ___ ______ __ __ ___ ___ _________ ___ ___
|
||||
|
||||
One of the problems with debugging BDH programs is that when the
|
||||
|
||||
JOB device is used, it is loaded into a newly created job. That job is
|
||||
|
||||
not inferior to any DDT, and there is no way to put breakpoints in it
|
||||
|
||||
before it starts. The OJB device makes it possible to run the BDH
|
||||
|
||||
program under DDT.
|
||||
|
||||
The OJB device acts just like the JOB device except during the
|
||||
|
||||
initial open. When the JOB device would be creating and loading a new
|
||||
|
||||
job, the OJB device is looking for an existing job whose UNAME and
|
||||
|
||||
JNAME are the same as the filenames specified in the open. If such a
|
||||
|
||||
job is found, it is connected to the job opening the OJB device
|
||||
|
||||
through a standard JOB-BOJ pipeline. If such a job does not exist,
|
||||
PTDD 14 SYS.xx.yy
|
||||
|
||||
|
||||
the open of the OJB device fails. In order to protect innocent jobs
|
||||
|
||||
from being hacked in this matter, the job opened on the OJB device is
|
||||
|
||||
required to have set its OPTOJB bit (this is bit 4.2 in the .OPTION
|
||||
|
||||
varisble, settable with .SUSET). Also, it must not already be a BDH,
|
||||
|
||||
for the system cannot consider one job to be a BDH through two
|
||||
|
||||
connections at once. If either of those conditions is not met, the
|
||||
|
||||
OJB open WAITS until they are.
|
||||
|
||||
To remove a possible timing screw, a BOJ device open by a job
|
||||
|
||||
that is not a BDH, which usually fails, will wait instead for the job
|
||||
|
||||
to become a BDH if the job's OPTOJB bit is set.
|
||||
|
||||
The procedure for using the OJB device for debugging is:
|
||||
|
||||
|
||||
1. create a job to use for the BDH (call it J, in this example).
|
||||
|
||||
2. run (in another job) the program which would normally open
|
||||
|
||||
the JOB device, but tell it (perhaps by means of a translation) to use
|
||||
|
||||
the OJB device instead. This program's function is to issue system
|
||||
|
||||
calls so that the BDH's responses to them can be tested.
|
||||
|
||||
Since the OPTOJB bit of job J is now 0, when this program reaches
|
||||
|
||||
the OJB open it will hang.
|
||||
|
||||
3. ^Z that program, and ^P it. it will go back to hanging in the
|
||||
|
||||
open of the OJB device.
|
||||
|
||||
4. switch to job J, load in the BDH program. This RESET's the
|
||||
|
||||
job so that if it had been a BDH before, it will not be one now.
|
||||
|
||||
5. turn on the OPTOJB bit by depositing from DDT in .OPTION.
|
||||
|
||||
The conditions for a successful OJB open by job JJ have now been met,
|
||||
|
||||
so that job will make some headway, turning job J into a BDH and
|
||||
|
||||
waiting for job J to issue a JOBRET.
|
||||
PTDD 15 SYS.xx.yy
|
||||
|
||||
|
||||
6. it is now possible to start running job J, with breakpoints
|
||||
|
||||
as desired, to step through the code for handling the initial open.
|
||||
|
||||
It is unlikely, but theoretically possible, for J to execute its BOJ
|
||||
|
||||
open before JJ gets around to turning J into a BDH. In this case, J
|
||||
|
||||
will wait for JJ to do so.
|
||||
|
||||
7. if it becomes necessary to try again after discovering a bug,
|
||||
|
||||
go back to step 2. The OJB open will hang up this time not because
|
||||
|
||||
the OPTOJB bit is off (since it is still 1) but because J is already a
|
||||
|
||||
BDH. Loading J in step 4 will make J cease to be a BDH but also turn
|
||||
|
||||
off the OPTOJB bit, so JJ will still be waiting.
|
||||
|
||||
8. it is possible for job JJ to be "PCLSR'ed" or backed up out
|
||||
|
||||
of its open while job J is being traced through the handling of the
|
||||
|
||||
initial open. For example, job JJ might receive a real-time
|
||||
|
||||
interrupt. If that happens, J will cease to be a BDH. This will not
|
||||
|
||||
interfere with the tracing of J until the next BOJ device system call
|
||||
|
||||
is executed; that call will probably fail. It is impossible to
|
||||
|
||||
continue after such an occurrence, so the jobs must be restarted by
|
||||
|
||||
returning to step 2. Of course, if there are no breakpoints before
|
||||
|
||||
the first JOBRET, this is very unlikely to happen.
|
||||
|
||||
9. if the initial open has been handled successfully, to go on
|
||||
|
||||
to debug handling of other system calls, simply tell JJ to execute
|
||||
|
||||
them with J stopped while JJ is being told, then ^Z^P JJ and go back
|
||||
|
||||
to J.
|
||||
|
||||
10. the usual .LOGOUT in the BDH program will be a no-op when the
|
||||
|
||||
program is run as an inferior in this manner, so it should be followed
|
||||
|
||||
by a .VALUE.
|
||||
| ||||