This is the file containing the INFO-ized version of PCNET;INTRO >.
See REM, or say :INFO NET PCNET PRO LOW QUICK <cr>

<<This file is very new (1983.Feb.23) and at present represents only a
  single level of indexing. But even this should permit answering
  queries via electronic mail, sending just the major levels desired.>>

                Introduction to PCNet, now treeified starting 1983.Feb.23
                by John Gilmore, 29 September 1981
                File MC:PCNET;INTRO > before treeification

    Very toplevel layers of software...
  Overall topology and organization of network:: (not yet included...)
  Offline processing such as headers of electronic mail:: (not yet included)

    Layers of communication protocol while in packet mode, top to bottom...
  Application programs:: (not yet included in this document)

    Also not yet included in this document: establishing and breaking
    connections (HELLO and BYE).

	added 1982.Sept to the original 1981 online document

[DRAFT VERSION -- Several parts not yet included here. See later
 for a list of these missing parts.]
** WARNING -- A new draft is now written, which includes many of the
missing parts. It is not yet online here. It is better than this
draft, so please don't make listings of this draft because it is
already obsolete. -- There are still several changes/improvements we
want to make in this document, thus the current draft probably won't
be put online here at all, rather a later draft, one that we're
satisfied with, will be put online here after it's ready. Meanwhile,
please just be patient. If you want to volunteer to be a proofreader,
contact REM@MIT-MC and also G.Harris@SU-SCORE, and we might send a
draft for review. **

[DRAFT VERSION - The following parts haven't yet been included here:
  Mail/FTP protocol, both at the level of opcodes&messages between
    application programs, and the header that begins each message --
    Fylstra.TSCA@SRU-UNIX is working on this. Meanwhile consult
    PCNET;SERPRO TTY for header format and see REM;APPPRG > for
    server-level protocol, both now in new draft.
  Change to method by which application programs are started up,
    by ASCII name instead of 6-bit number -- REM;APPPRG > inc'l in new draft.
  Latest change to format of validating block -- included in new draft.
  Examples of protocol updated to new protocol -- PCNET;EXAMPL WRU
  Rewording of part about application programs (called "server processes"
    in this current draft) -- REM looked at this and decided there was
    no easy way to reword it. See REM;APPPRG > for current terminology.
  Listing of test nodes is now in PCNET;TEST NODES.
  Listing of software available and how to get it -- PCNET;SOURCE INDEX]

  Copyright (c) by John C. Gilmore.  Permission granted to reproduce
  for the purpose of making PCNet freely available to the public.  For
  other purposes, explicit written permission must be obtained first.
  This copyright notice must be included in all copies.

PCNet stands for Personal Computer Network.  It is a way for two
personal computers to communicate with each other.  When hundreds or
thousands of people are communicating with each other via their
personal computers, a network is formed.

The PCNet Project started in 1977 when (who?) saw that the technology
to allow personal computers to talk existed but was not being used.
The existing and planned projects at that time had all been designed
for particular computers or particular operating systems.  It was not
possible for an Apple to talk to a Pet, or a TRS-80 to talk to a CP/M
system.  This is still largely true today.

These people formed the PCNet Committee as a volunteer, non-profit
organization.  They wanted to define and implement a protocol (a
well-defined method for communicating) that would work with almost any
type of equipment, from the smallest to the largest.  They didn't want
the project to be sponsored or funded by a partisan organization, so
that these goals would be preserved.  And they wanted their products
to be in the public domain, freely available to everyone, to encourage
their use and permit even the smallest users to communicate with
everyone else.  This is still true now, although the informal "PCNet
Committee" became a formal Project under the sponsorship of People's
Computer Company, the non-profit publishers of Dr. Dobb's Journal.

There are many problems inherent in building a network out of a large,
unorganized set of small, personally-controlled computers connected to
the normal telephone network.  Part of the problems have to do with
the reliability of the communications lines and of the computers and
their storage media.  Other problems arise from the lack of
centralized control over the network.  We have done our best to solve
these problems using what we know now.  In a few years, when use of
networks like PCNet is widespread, we will know much more about the
process of making a network where once there was Chaos.

Note that the lack of centralized control is by no means totally a
liability.  It enables new users to join the network simply by calling
other network users.  It also creates a network that cannot "go down"
due to central difficulties, cannot be damaged by any local action,
cannot be traced, cannot be stopped -- without stopping, damaging, or
tracing the entire world telephone network.  This is important to many
of us who believe that centralized government control is not always a
good thing.  (Note, however, that since large parts of the world phone
network are now being traced by "intelligence" agency computers -- in
particular, by the NSA -- this advantage has practically disappeared.
Perhaps illicit packet radio can save us from Uncle Sam's snooping
ears.)

The PCNet protocol solves the reliability problems inherent in using
the normal phone network by using an error-checking and retransmission
scheme.

The first versions of PCNet to be released will implement the basic
protocol and two applications -- mail transfer and file transfer.  An
application is a program that accomplishes useful work, "applying" the
power of the cr to satisfy some want or need.  Applications are
distinct from the PCNet protocol, which exists only to satisfy
technical constraints and not to provide a service that people desire.
Other applications can and will be written for use with the PCNet
protocol -- for example, two-player game programs.  These applications
can be written by anyone; they call on the protocol as required, but
do not themselves get involved in the messy details.  Full source will
be provided for all PCNet code; and after the first release, new
updates can of course be distributed over the network.

The mail transfer application will accomplish the moving of short
messages (a few thousand characters, typically) thru the network.
Messages can be typed in and edited on the sender's home computer, and
delivered immediately by telephone to the receivers' home computers,
or can be delivered late at night to take advantage of the 60%
discount rate; or they can be delivered to other PCNet nodes (other
peoples' computers that use PCNet protocols) and be forwarded to their
true destinations.  In large metropolitan areas, many such forwarding
centers will probably exist to move mail for free despite "message
unit" or "zoned" call billing.  These forwarders can also provide
long-distance forwarding service to subscribers -- for example, a New
York computer club could call a San Francisco computer club each night
with high-speed equipment, forwarding all messages from its members to
destinations in the West.  Anyone who found that their average
long-distance mail-forwarding bill was more expensive than their share
of the cost of such a shared system could join.  Furthermore, as local
and transcontinental packet radio links become operational,
non-commercial PCNet mail can be forwarded thru them without cost.

The file transfer application will move data files from one computer
to another.  The files can contain any data -- text, programs, machine
code, graphics images -- anything that a computer can represent.  This
application does not support forwarding and only acts point-to-point
-- you must call the node that contains the file you want.  (You can
send files as messages, too; but this is only practical for small
files.)

When a node's computer is not in use for anything else, PCNet can be
running, waiting for the phone to ring.  When it does, the appropriate
application(s) will be run and mail or files can be received without a
human having to be there.  The messages will be stored on disk or
other media and will await the owner next time she returns.  In this
way PCNet mail is like Post Office mail, but it also has the
advantages of instant or overnight delivery, and the ability to send
to multiple people with a single command.

                        PCNet Communication Protocols

This section describes the protocols used to communicate between
applications.

An application can send a block of information to another application,
or can receive such a block.

Because more than one application might be running at once, and
because a single application might want to send several different
types of data (and have the recipient be able to distinguish them),
PCNet provides multiple "streams" of data to and from an application.
With each block of data the application sends, it also indicates which
"stream" the data is to travel along.  The receiving application is
told which stream each block of data was received on.

PCNet also provides the ability to transmit an "end" marker in a
stream.  This tells the receiver that whatever was being transmitted
is complete.  For example, this marker shows the end of a message in
the mail application.  Further data coming along that stream could be
commands, or other messages.  Having this "end" marker independent of
the data being sent means that all possible bytes can be transmitted
and received in messages, without reserving one for "end of message"
or requiring more elaborate schemes.

Calls PWRITE&PREAD to send&receive data, just like application
programs, except it uses stream 0 instead of nonzero stream numbers.

* CONtrol messages::	Opens&closes applications, changes parameters

	Opens&closes applications, changes parameters

Control Messages
----------------

PREAD and PWRITE are the only primitives needed to communicate with
another application, but we still haven't mentioned how an application
starts.

One of the applications will be started by some means external to
PCNet, such as a user running the mail application with a console
command because s/he wants to send a message.  PCNet provides
facilities for that application to connect itself, over some
communications link, to the second PCNet node, and to tell the second
node which application(s) it should run.

The details of how an application makes a physical (eg telephone or
packet radio) connection to another computer are beyond the scope of
this document.  A PCALL procedure takes whatever arguments are
required to specify hardware and addressing parameters (line speed,
modem type, telephone number, logon sequence, radio frequency, compass
direction of receiver, etc.) and returns an indication of whether the
connection was successfully initiated.

Once PCALL indicates that a connection has been made, it remains to
select the application to run on the called computer.  This is done
with a control message.

Control messages are just like normal directing blocks, except that
they are sent on "stream 0" -- the control stream.  Their End-of-Data
bit is always set, because each control message is complete in itself.
(At some future point, it might be possible to send "continued"
control messages with the End-of-Data bit set only in the last one.)

Each control message has a one-byte operation code followed by
variable-length arguments.

The operation codes come in four variations.  Each code refers to some
particular option or application or action, and the four variations
are "Please do xxxxx", "Please don't xxxxx", "I will xxxxx", and "I
won't xxxxx".  For example, the operation code for "hang up" can be
sent as "Please do hang up".  If the other node has further
applications that it wants to run, it will send "I won't hang up".  If
it has nothing better to do, it will send "I will hang up" -- and then
hang up its phone.

The variations (also called "flavors" a la Raskin-Flakkers) are
encoded into the top 2 bits of the operation code.  They go like this:

	00-- ----	I won't
	01-- ----	I will
	10-- ----	Please don't
	11-- ----	Please do

This encoding has the advantage (which is actually the purpose of this
whole Please-do, I-will scheme) that if a PCNet node receives a
control message that it doesn't understand, it can just invert the top
2 bits and send the message back.  This turns Please Do into I Won't,
I Will into Please Don't, etc., which is usually the right thing to
do.  This means that a newer PCNet node can safely talk to an older
node -- if the new one requests something that the old one was never
designed to do, it will automatically reject the request.

The variable-length arguments in each control message vary depending
on the operation code.  The codes, and their arguments, are:

*** *** THIS TABLE IS COMPLETELY OBSOLETE, SINCE THE BEGINNING OF 1982
*** *** I WISH DAVID HARRIS WOULD UPLOAD THE NEW DRAFT OF THIS DOCUMENT!!!
      Code	Won't	Don't	Will	Do	Meaning and arguments
    --00 0000	00	40	80	C0	Unassigned
    --00 0001	01	41	81	C1	Hang up.
    --00 0010	02	42	82	C2	Echo.
    --00 0011	03	43	83	C3	Accept mail
    --00 0100	04	44	84	C4	Return mail
    --00 0101	05	45	84	C5	Accept file
    --00 0110	06	46	86	C6	Return file
    --00 0111	07	47	87	C7	Node ID; argument is ID
    --00 1000	08	48	88	C8	Return DIALOG file (*)

(*) Specific to the DIALOG/PET implementation of PCNet; do not use.
*** END OF OBSOLETE PART *** NOW THOSE INDIVIDUAL CODES FOR SENDING
AND RECEIVING MAIL ARE INSIDE THE MAIL1 APPLICATION PROGRAM. THE
CONTROL MESSAGE MERELY ACTIVATES THE APPLICATION PROGRAM AND ASSIGNS
(OPENS) LOGICAL STREAMS TO IT. ***

Where arguments are not defined in the table, received arguments should
be ignored.

[This text is from PCNET;INTRO > written by John Gilmore.]

	Interface between service levels and application program

To send a block of data, an application calls on PCNET-WRITE, which
from here on will be abbreviated to PWRITE.  The actual details of how
the call is made are totally dependent on the language and operating
system involved; from a high-level language like C or Pascal, PWRITE
would probably be a procedure call; from BASIC or assembler language,
a lower-level interface would be used, like USR() or JSR.  In some
systems, PWRITE could be invoked by doing output to the usual output
device, with PRINT statements.

PWRITE takes three arguments and produces one result.  The arguments
are the data to be sent, the stream number on which to send it, and
whether to send an "end" marker after the data.  PWRITE calls on lower
levels of the protocol to format and error-check the transmission, and
returns to the application once the data has been transmitted and
acknowledged (the other application has received it correctly and told
us so).

The result of PWRITE indicates what happened.  If everything went
smoothly, it reports whether the other application sent any data to us
along with the acknowledgement.  (If it did, we can read the data with
PCNET-READ.)  If there were problems with the phone line, but they
were circumvented by retransmitting the data, the application never
hears about it, but just gets the indication that the data was
(eventually) properly received.  If there was a permanent problem,
however, the error is indicated in PWRITE's result.  Such things as
the remote end hanging up the phone are reported in this way.

An application can receive data from the other application by calling
PCNET-READ, hereafter abbreviated to PREAD.  If data is already
waiting from the last PWRITE transaction, it just returns that data.
If not, it sends a short acknowledgement to the other application to
see if it has anything to transmit.  It then returns the new data, or
reports that there is no data to be read.

PREAD takes no arguments, and returns four results.  The first result
indicates what happened -- there is data, there is no data, or there
is an error.  The other results are the received data, its stream
number, and whether an "end marker" was found after the data.

When one application does a PREAD and then the other does a PWRITE,
the effect of the PCNet protocol is to move the arguments of the
PWRITE over as the results of the PREAD.  If the second application
does a PREAD instead of a PWRITE, the first PREAD will return an
indication that no data was received.  If both applications had done
PWRITEs, the first PWRITE would return an indication that there is
data waiting to be read.  (Note that a PREAD or PWRITE doesn't usually
return to the caller until it has transmitted and then received.  This
means that when one application is in control, the other one is inside
a PREAD or PWRITE call awaiting a response from the first application.
That's why in the above description, the first PREAD/PWRITE got the
indications, instead of the second one -- the first one returned after
the second one transmitted to it, but the second one is still waiting
for a response before it can return.  This doesn't have to be true
when running with more complicated software or protocol variations,
but for PCNet Simple protocol it's true.)

One restriction in PREAD and PWRITE was made to make them easier and
cheaper to write.  If an application does a PWRITE and the result
indicates that data was received along with the acknowledgement, it
must PREAD that data before it can do another PWRITE.  (The second
PWRITE will return an error if this is violated.)  This is because
PWRITE only has one place to put data received with acknowledgements.
If this area was full and PWRITE sent some data, and the other
application sent us more data along with its acknowledgement of our
data, either its old data or its new data would have to be thrown
away.  Rather than make that decision, PWRITE forces the application
to read the data and either use it or throw it away -- but the
application gets to choose.

    Middle layer of protocol

    Lower layer, divided into micro-layers, from nearest the middle layer...

[This text is from PCNET;INTRO > written by John Gilmore]

The Directing Layer
-------------------

The directing layer handles PREADs and PWRITEs from the applications.
It takes the arguments of a PWRITE and packs them into a "directing
block", which it then sends to the directing layer in the other PCNet
node.

Here's what a directing block looks like:

	|-1 byte-|

	+--------+	The flags look like this:
	| flags	 |	X--- ----	End-of-Data flag from PWRITE call
	+--------+	-1-- ----	This bit is reserved and must be 1.
	|  data  |	--XX XXXX	Stream number from PWRITE call
	|  from  |
	| PWRITE |	Data may be 0-128 bytes unless a larger size is
	+--------+	negotiated between the PCNet nodes.

As you can see, except for one reserved bit, this is just the
information that the application passed to PWRITE.

For a PWRITE, the directing layer creates this block and passes it on
to the validating layer, which takes care of transmitting it
error-free to the other PCNet node.  For a PREAD, the directing layer
calls the validating layer, and if any data has been received, it
decodes the End-Of-Data bit and the stream number, and returns the
block to the application.

In a system with multiple applications running at the same time, the
directing layer would have to look at the stream number in each
incoming block and give it to the proper application, so the two (or
more) applications would not receive blocks meant for each other.  In
simple PCNet nodes, only one application can be running at once, so it
just gets all the blocks that arrive.

The Validating Layer [sic, really two different layers]
--------------------

The purpose of the validating layer [sic] is to provide error-free
transmission of data.

It does this by breaking data into blocks; detecting errors in blocks;
and retransmitting blocks that were not received error-free.
[ERRATA - The data is already broken into blocks before these layers
receive it, and no additional or different blocking is done by these layers.]

The validating layer [sic] is called by the directing layer when PWRITE
wants to send some data, or PREAD wants to receive some (and there's
none in the buffer).  It returns with an indication of whether new
data has been received error-free, and whether a timeout or serious
error (such as loss of carrier on the phone line) occured.

In PCNet Simple, the validating layer is called when we are in control
of the phone line (it has been "turned around" to us).  It transmits,
turns the line around to the other system, then receives and awaits
turnaround to us.  It does not return until the block we sent has been
acknowledged and we once again have control of the line.  (This
prevents data from arriving as we are bashing the disk from inside an
application, for example.)  If our block was not acknowledged, we
ignore any data received from the other node (because we have no place
to keep it), retransmit our block, and go 'round once again.

In FDX (full-duplex) or with an acknowledgement window greater than 1
(I'll explain this terminology later), the Validating Layer returns as
soon as the Directing Layer's data has been queued for sending.  This
allows the Directing Layer (and thus, applications that call it) to
give the Validating Layer several blocks of data to transmit while
awaiting the acknowledgement of the first block.  Since at the moment
a maximum of four blocks can be outstanding (queued for transmission
but not yet acknowledged) at once, if the Validating Layer already has
four blocks queued, it waits until one has been acknowledged before
returning to the Directing Layer, so that no additional outgoing data
can possibly be queued until there is room for it in the queue.  If
any data is waiting in the receive queue, a PWRITE will get a
data-available status passed up to it, while a PREAD will get the
first such block.  (Note that if the Directing Layer gives it an empty
block to send, it is not even queued.  The Validating Layer takes care
of inserting empty blocks where required in FDX, even though the
Directing Layer has an HDX mentality.)

Data coming into the Validating Layer is already broken into blocks
(in the current design), so it need not worry about achieving that
goal.

Errors are detected by appending a checksum to each transmitted block,
and checking it upon reception.

Retransmissions are explained below. [In the section on sequencing]

Validating Layer Sequence Numbers
---------------------------------

Sequence numbers in the validating blocks are used to ensure that all
blocks have been received correctly.  Their use corresponds roughly to
the "acknowledgements" used in some other protocols.

Two 3-bit fields in each block's header are used for this purpose.  In
Simple (HDX, 1 block transmitted per turnaround) mode, only one such
field is really needed, but two are used to retain compatability with
Extended Simple and Advanced nodes, which will appear rapidly after a
few Simple nodes appear.  The algorithm used by the Simple nodes is
much easier to understand and implement than the one used by the more
advanced nodes.

The Advanced algorithm uses three variables to keep track of
acknowledgements.

WEGIVE contains the number of the next block to be transmitted.  As
blocks are passed from the directing layer to the validating layer,
the current value of WEGIVE is placed in them, and then WEGIVE is
incremented.  When a block is received from the other node, WEGIVE is
checked to see if our last transmission has been acknowledged.

WEWANT contains the number of the next block that we want to receive.
In Simple mode, this is always the number of the block after the last
one we correctly received.  When a block is received correctly, its
number is compared to WEWANT to see if it was (1) the previous block,
retransmitted; (2) the block that we want, or (3) some other block --
a violation of protocol.  WEWANT is copied into all transmitted
blocks, to let the other node know which block we are awaiting.

SHEWANTS corresponds to WEWANT, but from the other node.  It contains
the number of the next block that the other node wants to receive from
us, as best we know it.  It is set from each correctly received
block's Want field.  It is compared to WEGIVE to see if she has
correctly received the block we just sent to her -- i.e. if she has
acknowledged the block.

-----------------------------

The receive side of the validating layer is always looking for a
particular block from the other side.  Each block is identified by a
sequence number, called "Give", which runs from 0 to 7 and back to 0.
(It's Give because it's the number of a block given to the receiver.)
The Give that the receive validating layer (RVL) wants to see is
remembered in the variable WEWANT.

Each block that the RVL sees, that has already passed the other tests
(checksum, etc.) is tested to see if it is the block the RVL wants to
see (its Give = WEWANT).  If not, the RVL ignores the block.  If
it matches, tho, the RVL passes the block to the Directing Layer and
remembers to look for the next block (next Give) next time.

The Transmit side of the Validating Layer (TVL) puts the RVL's
WEWANT value into each block it transmits.  This tells the other
node which block the RVL is waiting for.  Corrspondingly, the RVL gets
this field (called "Want") out of each block it receives, and
leaves it around for the TVL in the variable SHEWANTS.

-----------------------------

The TVL is always transmitting a particular block to the other side.
It remembers the block's Give in a variable called WEGIVE.  Every time
the TVL gets a chance to transmit a block, it compares SHEWANTS with
WEGIVE.  If they're equal, she wants the block we're sending, so TVL
sends it.  If on the other hand, SHEWANTS = 1+WEGIVE, then she has
already received this block from us, and we should send her a newer
one.  The TVL returns to the Directing Layer, passing it whatever data
we might have received, and asking for some data to transmit.  If on
the third hand, SHEWANTS has some other value, there is an error in
somebody's PCNet program, and the TVL throws up its hands and
complains.

Here's an example:

              .                                  .
              .                                  .
              .                                  .
          Give 3, Want 3           ---->         OK
              OK                  <----      Give 3, Want 4
          Give 4, Want 4           ---->         OK
              Checksum error   <--garble--   Give 4, Want 5
(retran)  Give 4, Want 4           ---->         Give <> Wewant
              OK                  <----      Give 4, Want 5       (retran)
          Give 5, Want 5        --garble-->      Invalid length
              Give <> Wewant    <----      Give 4, Want 5       (retran)
(retran)  Give 5, Want 5        --garble-->      Checksum error
              Give <> Wewant    <----      Give 4, Want 5       (retran)
(retran)  Give 5, Want 5           ---->         OK
              OK                  <----      Give 5, Want 6
              .                                  .
              .                                  .
              .                                  .

Notice that anytime an error occurs in one direction, and no error
occurs in the other direction, a "Give <> Wewant" error occurs,
because the node that received the error retransmitted its previous
block, because it never received the acknowledgement that the other
side had seen it.

Note also that one node's Give and Want are always the same,
and the other's were always off by 1.  This is always true in HDX
1-of-8 (half-duplex, when only one packet is sent per turnaround), and
can be used to simplify the programming.

Since the Originate node (the one that dialed the phone call, if
phones are being used) transmits the first block, it will send a block
with the Give same as the Want -- both zeros.  The Answer node
will send Give+1=Want blocks -- starting with give 0, want
1.  Simple mode Originate nodes must check that blocks they receive
have this offset, because of a glitch that could occur on the very
first block.

If the first block does not get thru error-free, the Answer node must
send a block with Give 0 (since this is its first block) and Want 0
(since it is awaiting block 0 from the originate node).  If the
Originate node accepted that block, it would have to send a block with
Give 0 (since its previous message was not acknowledged), Want 1
(since it accepted block 0 already).  This would result in Originate
sending the "unequal" numbers and Answer having the "equal"s.

Since we always want the Originate node to send the "equal" numbers,
the Originate node must reject the Answer node's Give 0 Want 0 block
(i.e., pretend to have received it in error) and retransmit its
previous block, which also had Give 0, Want 0.  Once the Originate
Give 0 Want 0 block gets thru, Answer will send a Give 0 Want 1 block,
and things will be properly synchronized.

-------------------------

Given that we have assured that Originate always transmits "equal"
blocks, and Answer always sends "unequal"s, each node only needs one
variable to keep track of its acknowldgements.  That number
corresponds to WEGIVE.

When a block is received, its Want and its Give are compared.
If they are not in the proper relationship (either equal, or Give
+ 1 = Want), the block is invalid.  Next, its Want is compared
to WEGIVE.  (Its Give is ignored, except for the comparison to
its Want.)  If its Want is the same as WEGIVE, our block has
been received and acknowledged, and we can return the current block to
the Directing Layer and send a new block next time.

If its Want is 1 less than WEGIVE, our block has not been
received, and we must retransmit it.

If no correct block is received before it's our turn to transmit, we
must also retransmit our block, since it has not been acknowledged.

This exhausts the cases possible in HDX 1-of-8 protocol.

The first-block problem is taken care of by starting up the Answer
node with a Give 0, Want 0 block in its retransmission buffer.  Of
course, all blocks that its software builds will have Give+1=Want --
but this block was never built by its software, and is only used if
the first block received is in error.  (The software is already set up
to retransmit its block if it receives a block in error; all that
needs to be done is to put this dummy message in the retransmission
buffer before starting, and the rest works.)

Validating Blocks look like this:

        |-1 byte-|

        +--------+      The Flags byte looks like this:
        | direct-|      0--- ----       Originate node sent this block
        |   ing  |      1--- ----       Answer node sent this block
        |  block |      -0-- ----       Reserved, must be zero
        +--------+      --XX X---       Give sequence number
        | flags  |      ---- -XXX	Want acknowledgement number
        +--------+
        | check- |
        +--------+
        |  sum   |
        +--------+
        | [pad]  |
        +--------+

When a Validating Block is received (returned from the Translation and
Framing layer), its length, flags, and data are checksummed, and the
result is compared to the supplied checksums.  If they are different,
the block is ignored.  The length is a 2-byte binary value which
counts the number of data bytes in the block, not including the header
and checksums.

	  ____________Checksummed______________
	 /				       \
	+++++++++++++++++-------+-------+-------+-------+-------+
	| ... data ...  | flags | len H | len L | cks 1 | cks 2 |
	+++++++++++++++++-------+-------+-------+-------+-------+
				\Not transmitted/

The receiver checksums the data bytes, flags, and physical length (the
two bytes of lengths are generated locally, everything else was in
the block as received), and compares them to the checksum (also in
the block as received).  If the checksum is the same, the data
is valid; if not, either some data was corrupted or some was inserted
or deleted (i.e. the length was corrupted).

In one case this does not work.  The Translating Layer (which we
haven't gotten to yet) can only send even numbers of bytes when
translating to and from Radix-41.  If we try to send an odd-length
Validating Block, it will stick an extra byte of zeros on the end of
the block and transmit it that way.  Since this is a "corruption" of
the data, the received block will not pass the checksum test.

We deal with this by cursing at the Translating Layer and putting a
special kludge in the Validating Layer.  If a block fails the checksum
test, we look at its last byte.  If that byte is zero, we remove it,
and decrement the length of the block, then recompute the checksum.
(Note that this changes the length bytes, and causes us to use
different bytes as the "desired checksum".)  If the new checksum
matches, all is well; if not, a real error occurred.

Note that this method uses the physical block length to imply the
true length, then checks it; just as it uses the physical data to
imply the true data, and then checks it.

Validating Layer Checksums
--------------------------

There are two checksum algorithms used by PCNet.  The first is used
when the Translating Layer is translating to and from Radix-41
(because it's simple and sufficient); the other is used when
translating to and from Transparent Binary (for more muscle).

The first algorithm consists of simply adding up the bytes of the
block and ignoring any overflow out of the 8-bit sum.  We add up the
even-numbered bytes separately from the odd-numbered bytes.  The two's
complement of these two 8-bit sums form the 16 bits of checksum
information.  (The negated sum of the even bytes goes to the even
checksum location; the negated sum of the odd bytes to the odd
location.  The checksums will be a different order depending on the
evenness of the block length.

To see if a blocks's checksum and data match, we simply add up all the
bytes of the block, including the checksum bytes.  (Again we keep
separate even and odd sums and ignore overflows.)  If the resulting
sums are both zero, the block is correct.  This simple method works
because Radix-41 translation mixes up the bits of the block so much
that a 1-bit transmission error would mess up a bunch of bits of the
block, and get detected easily.

The second algorithm is called CRC for Cyclic Redundancy Check.  It is
a method based on mathematical theories that I do not understand well,
but it is much better at detecting errors than the simple addition
checksum.  There are many different CRC algorithms.  The one used in
PCNet is the same one that is used in "SDLC" or "X.25" protocols.  It
is a 16-bit CRC and uses the formula (X^16)+(X^12)+(X^5)+1.  When
computing this CRC checksum, the checksum is initialized to FFFF hex,
then each byte of the length, block, and flags are passed thru the
algorithm.  The complement of the resulting checksum is transmitted.
The receiver does the same, but also runs the received checksum bytes
thru the algorithm.  If the final checksum is F0B8 hex after the
second checksum byte has been processed, the block is correct.

Once the checksums have been validated, the block is assumed to be
good (uncorrupted by phone noise -- that is, we received exactly what
the sender sent).  However, the block may get ignored for other
reasons, such as: we've already received this block, or it fails some
further checks because it was sent by buggy software.

If the -X-- ---- bit in the packet is on, the packet is in error.
This bit is reserved for extensions to the existing PCNet protocol --
if it is set, anything in the packet could have a different meaning,
and we must ignore it.

If the X--- ---- bit indicates that we sent this block, we ignore it.
Either the other system is echoing each character it receives
(thinking, perhaps, that we are a FDX, non-local-copy terminal); or we
have called a test node which is echoing at the Framing Layer --
waiting to see turnaround, and then sending everything it receives.

The Translating and Framing Layer [sic, really three layers]
---------------------------------

This layer determines where blocks start and end in the data passing
over the phone line.  It also allows all 8-bit combinations to be used
in blocks, even though the node might not be able to read all possible
8-bit bytes from the phone line.  It further determines which node is
allowed to transmit, when Half Duplex is in use.

The T/FL (Translating/Framing Layer) transmits and receives 7-bit or
8-bit characters over the phone line, and uses and returns binary data
blocks to the higher layers.  In the "Radix-41" translation method, 7
bits of data are used, with "mark" parity, one start bit, and one stop
bit.  (Systems that can't transmit "mark" parity can still be used,
but will not recover as well from framing errors.  Received parity is
not checked.)  In the "Binary" translation method, 8 bits of data, one
start bit, and one stop bit are used.

Four possible T/FLs exist:
        HDX, R41 - Used in Simple mode
        HDX, Bin - Used in Enhanced Simple mode
        FDX, R41   (not likely to get any use)
        FDX, Bin - Used in Advanced mode

Translation
-----------

Any 8-bit bytes can be passed to the T/FL by the higher layers.  T/FL
uses some 8-bit values for special things like framing and turnaround
("@", "]", "[") and would get very confused if these were sent as part
of a data block.  Furthermore, many computers cannot use all 8 bits
from a phone-line as data; their hardware takes one bit for parity, or
their operating system translates lowercase to uppercase, or
intervenes if particular control characters are received.  The T/FL
must therefore TRANSLATE data blocks to a form which can be sent and
received without confusion.

For computers which can send or receive all 8 bits of data over the
phone, Binary translation is used.  Here we only have to worry about
the 8-bit values that T/FL uses for other things.  Therefore we encode
such values as 2-byte sequences instead.  Here are all the 8-bit
values that the T/FL has to deal with specially in Binary translation:

 Hex   Octal      ASCII                        Means
-----  -------  -----------  -----------------------------------------
C0     300      @  +top      Start/end of block; *turnaround ack
DB     333      [  +top     *The originate node has finished sending
DD     335      ]  +top     *The answer node has finished sending
90     220      DLE+top      The next character is encoded data
90 40  220 100  DLE+top @    The data character C0/240/@+top
90 5B  220 133  DLE+top [   *The data character DB/333/[+top from orig
90 5D  220 135  DLE+top ]   *The data character DD/335/]+top from ans
90 10  220 020  DLE+top DLE  The data character 82/202/DLE+top

Note that the bracket RECEIVED by a particular node need not be
translated when sent in a data block (we can assume it will NOT be
echoed back; we don't use binary mode when talking to a computer that
insists on echoing).  For example, the Originate node may send ]+top
with impunity.  When running FDX, neither bracket need be translated.
This leaves the only char needing translation as @+top (and DLE+top
since it is needed to translate @+top).

This convention makes it very simple to do binary mode translation;
receiving code must look for @ and brackets with the top bit on (the
top bit is ignored in R41); and if a DLE+top is seen, the next byte
must have hex 80 (octal 200) OR-ed in to it.  The next byte should be
checked for validity at least to the extent that a DLE+top followed by
another "flag" should cause a translation error and then correctly
interpret the second flag (eg @+top).  Any other bytes received are
just passed thru as-is.

For computers which cannot receive all 8-bit values, we use Radix-41
encoding.  Each pair of data bytes is transmitted and received as
three characters from a restricted subset of ASCII -- uppercase
letters, numbers, and a few punctuation marks.  These characters, plus
"@[]" and CR, are the only ones used by PCNet in Radix-41, and they
can be sent or received by virtually all computer systems.

        +-------+-------+-------+-------+-------+-------
Data    |Byte 0 |Byte 1 |Byte 2 |Byte 3 |Byte 4 | etc...
        +-------+-------+-------+-------+-------+-------
        |                \_____          \_____________
        |                      \                       \
        +-------+-------+-------+-------+-------+-------+-------+-------+
Encoded |Char 0 |Char 1 |Char 2 |Char 3 |Char 3 |Char 5 |Char 6 | etc...
        +-------+-------+-------+-------+-------+-------+-------+-------+

This translation is done by taking a pair of data bytes as a 16-bit
unsigned integer, and dividing it by 41.  The remainder is the "ones"
digit of the base-41 representation of the 16-bit quantity.  The
quotient is again divided by 41, and the remainder and quotient are
the "41s" and "1681s" digits.

	                +-------+-------+
	        Data    |Byte 0 |Byte 1 |
	                +-------+-------+
	                        |
		        +---------------+
		        | 16-bit number |
		        +---------------+
	                Divide by 41
	          Quotient     Remainder
	        +----------+   +-------+
	        |          |   |  1's  |
	        +----------+   +-------+
	    Divide by 41            |
	Quotient    Remainder       |
	+-------+   +-------+       |
	| 1681's|   |  41's |       |
	+-------+   +-------+       |
	   |            |           |
	   |            |           |
	 ----------Table Look-Up--------
	   |            |           |
	+-------+   +-------+   +-------+
Encoded |Char 0 |   |Char 1 |   |Char 2 |
        +-------+   +-------+   +-------+

What we are really doing is finding the base-41 representation of the
16-bit number, just as you find a base-16 representation (hexadecimal)
by successive divisions by 16.  The "digits" of hexadecimal are
"0123456789ABCDEF"; the "digits" of our base-41 representation are

        "0123456789:;<=>ABCDEFGHIJKLMNOPQRSTUVWXYZ"

Thus the pair of bytes 00 00 hex would turn into 16-bit number 0000,
base 41 number 0,0,0, and would be sent as Radix-41 "000".  Or bytes
02 00 hex would be decimal 512, base 41 0,12,10, or Radix-41 "0<:".

Since the largest 16-digit base 2 number is 65536, and the largest
3-digit base 41 number is 68921, all possible 2-byte values will fit
into 3 base-41 digits.  In fact, there are a few left over, which we
might want to use as flags at some point.

Each pair of bytes in the data block given to T/FL is translated and
sent this way.  The validating layer always gives T/FL an even number
of bytes (adding a pad byte if necessary), so we don't have to worry
about dangling bytes.

When receiving a data block in Radix-41, each character is examined to
see if it is one of the Radix-41 characters ("digits").  If not, it is
ignored; this removes assorted control characters sent by some host
systems.  It also allows a node to send debugging messages using
lowercase letters, space, control characters, and symbols other than
":;<=>".  This can be invaluable when debugging PCNet software; you
can call a node which pulls apart your packets and gives detailed
messages when something is wrong, and these messages won't interfere
with the protocol at all. (Numbers can be spelled out in lower case,
such as "want number is four, received packet six, you blew it.")

If a received character is a Radix-41 digit, it is saved until 3
such characters have been collected.  Then each is translated to its
corresponding numeric value, and the digits are multiplied by 41 and
added to produce the original 16-bit number.  (If an overflow occurs,
a character was garbled or lost, and the data block is in error.)

If an "@" or a bracket is received and some Radix-41 characters have
been received since the last group of 3, the data block is in error;
it has an invalid length. [Note, this is actually determined in a
different way; The packet-framing layer just below this translating
layer passes up a block of data that was received between atsigns.
This layer then notices the block doesn't contain a multiple of three
bytes, and thus rejects it.]

If all data translated without errors, the block is passed to the Validating
Layer; otherwise an empty block is passed.  The Validating Layer will decide
whether and what to retransmit and/or pass on to the upper layers.

Framing of Data Blocks
----------------------

"@"s are also sent before and after a data block, to encourage the
receiver to be synchronized, and to indicate the end of the block.

Each byte received (after turnaround has been sent and acknowledged
with five "@"s) could be part of a data block.  Such a block begins
with the first non-"@" received, and ends with the following "@" or
bracket.  In Pcnet Simple, only one data block is sent before
turnaround, but due to garbling it may appear that several data blocks
have been received.  Each must be translated, if possible, and then
passed to the validating layer for checking.  The first block that
passes the checks should be used, and anything between that and
turnaround ignored.  The following illustrates some possible framing
situations and how they are handled.  (Note that "ABCDEFGHI"
isn't a valid Radix-41 block, but you get the idea.)

        Transmitted     @@@@@   @ABCDEFGHI@]]]]]
        Received        @@@@@ Y @ABCDEFGHI@]]]]]
        Interpretation  1st block = Y           invalid length
                        2nd block = ABCDEFGHI   OK

        Transmitted     @@@@@   @ABCDEFGHI@]]]]]
        Received        @XXX@   @ABCDEFGHI@]]]]]
        Interpretation  1st block = XXX         invalid length
                        2nd block = ABCDEFGHI   OK

        Transmitted     @@@@@   @ABCDEFGHI@]]]]]
        Received        @@@@@   @ABCDEF@HI@]]]]]
        Interpretation  1st block = ABCDEF      bad checksum
                        2nd block = HI          bad length
                        No valid block received, request retransmission.

        Transmitted     @@@@@   @ABCDEFGHI@]]]]]
        Received        @@@@@   @ABCDEFGHI@]XX]]
        Interpretation  1st block = ABCDEFGHI   OK
                        2nd block = XX		ignored; 1st was good

In FDX, each block is preceded by "@" and followed by "@".  No blocks
are ignored due to already having received a good block, since there
are no turnarounds to wait for.  If three good blocks come in, and the
receiver has space to keep them in, they can be accepted and
acknowledged.  If a bad block comes in, it will not be acknowledged,
and the sending node will retransmit it when it notices the lack of
acknowledgement.

When running HDX, the T/FL must always be aware of which node is in
control of the phone line.  It cannot return any received data to the
higher layers until the other node has "turned the phone line around"
by sending brackets.  It must follow each transmission with brackets
to turn the line back to the other node.

The Originate node always sends "]" brackets, and listens for "["
brackets.  The answer node does the opposite.  (I remember this by
noting that the answers are outside the brackets, unlike typical
questions.)  They send different brackets because their transmissions
might get echoed by the other node.  Receiving its own turnaround
brackets would confuse a node if it couldn't tell its brackets from
the other node's.

Sending a single bracket to indicate turnaround will cause problems if
we get errors on the phone line, though.  In particular,

      - a data character could get turned into a bracket

      - a bracket could get turned into a non-bracket

      - the receiving hardware could be out of synchronization with
the data -- that is, looking for the beginnings of characters
elsewhere than where we're transmitting them.

We solve the first problem by looking for three brackets, close
together, as the turnaround signal.  If too many other characters are
in between the brackets, they do not cause a turnaround.  This is
implemented with a counter that goes up by 3 for each received bracket
and goes down by 1 for each non-bracket.  If the counter goes below
zero, it is reset to zero.  If it ever goes above 7, we have turned
around.  This was derived by:

        M = 3   How many brackets we must see
        P = 2   How many extra characters in between are OK.
(P+1)xM-P = 7   Value of counter that signals turnaround.

**** Clarify this a lot!!!! *******

We solve the second problem by transmitting five brackets.  Even if
two of them get garbled, the above method will correctly turn the line
around.

We solve the third problem by transmitting an "@" before the five
brackets.  The "@" character, with mark parity, goes down the phone
line as 7 bits of space and 3 bits of mark, in that order.  The
receiving hardware is looking for a place where "mark" turns to
"space" to signal the start of a character.  If the receiving hardware
thinks it's in mid-character when it receives the first bit of the
"@", it won't see the start-of-character transition until the "@" ends
and the first bit of bracket comes thru.  It will therefore receive
the first bracket even if framing errors lose the "@".

There are some other aspects of turnaround that increase its
robustness.  First, if Radix-41 translation is in use, a Carriage
Return (ASCII CR) is sent after the last bracket; this allows nodes on
large and/or stupid computers to act as limited PCNet nodes.  Such
systems cannot look for three brackets to turn them around, but are
locked-in to using CR to end a series of input characters.  Since we
only send one CR, these systems will have the same kind of problems
that were described for sending just one bracket; but the PCNet
protocol is mainly designed for micros, and is not very concerned with
the problems of IBM (and IBM-like) nodes.  The CR is a concession that
allows limited use of such machines with the protocol.

Secondly, a node must transmit five "@"s as soon as it recognizes a
line turnaround.  If the node that sent the turnaround has not seen
these "@"s within ***10*** seconds, it retransmits the turnaround, so
that severe errors on the phone line will not bring things to a total
standstill.  (Current implementations just look for the first "@", is
this a good idea?  If so, let's standardize it.)

Thirdly, if no character has been received for ***50*** seconds, we
assume the other node has gone off into never-never land and we give
up.  It's not clear that this qualifies as "robustness", but it does
keep the long-distance phone bills down.

When running FDX, no brackets or turnarounds are used.  Either node
can transmit at any time -- but also must be prepared to receive at
any time.  In practice, occasional lapses in reception are tolerable;
if any data is missed, (for example, while interrupts are disabled for
some reason), the Validation Layer will see to retransmitting it.  Of
course, such retransmissions cost because they increase the length of
the phone call.  These "lapses" could occur if interrupts are disabled
due to critically timed operations, in an interrupt-driven machine, or
would occur anytime a non-interrupt-driven machine did not poll the
received data before two characters came in, the second clobbering the
first.  An FDX node should send a character at least every 10 or 20
seconds, to avoid missing the 50-second "never-never land" timeout.
An atsign or two will do.

[All the sections of text are from PCNET;INTRO > -- this part
 originally trnscribed by REM as MODEMI WRU, from a proposal by one
 of the tiger-team members at the first workshop session.]

Interfacing to Hardware
-----------------------

To make software easier to document and to make it easier to patch
together parts written by different people, we've defined a set of
procedure calls for handling the telephone interface (modem and UART).

Modems are notorious for being unable to tell the difference between
(a) a dial tone (b) a dead line (c) somebody on the line (d) the
remote phone ringing, (e) the remote phone being busy, or (f) the
remote phone answering but not putting up modem carrier.  The only
signals these modems can reliably decode are (aa) before picking up
phone, if this phone is ringing from an incoming call (bb) after
picking up phone and dialing blind and waiting a few seconds, if
carrier comes up from the remote modem, and (cc) during a call if
remote carrier drops either because the phone has hung up or because
the phone is still connected but the remote modem has been disabled
(these two cases are indistinguishable).  These two signals (aa is
ring-detect, bb is carrier-detect, cc is just the opposite of bb) are
sufficient for programming the PCNet protocol, but must be programmed
separately for each combination of modem and language, whereas the
other parts of software can be done once in each language without
regard for differences in modem.

We decided upon a systematic way to name the low-level routines and
some of the intermediate-level routines for operating these modems.
By sticking to these conventions it will be easier to exchange
subroutines, to know exactly which subroutine is being discussed, and
to switch to another modem without changing the rest of the software.
Our convention uses a 5-letter name for each subroutine, the first
three letters having the role of a verb and the last two letters being
an abbreviation for some object (signal, data, mode) being operated
upon.

Verbs --
	SET (boolean, TRUE means set, FALSE means not-set i.e. clear)
	IST (is it true?, returns boolean)
	DIL (dial)
	SND (send, assuming we've already checked for ready)
	RCV (receive, assuming we've already checked for ready)
	SDW (send after wait for ready)
	RCW (receive after wait for ready)

Nouns --
	RG (ring; boolean)
	CA (carrier; boolean)
	OH (off-hook; TRUE means line open, FALSE means we've hung up)
	SP (speed in chars per second; integer such as 10,11,30,45,60,120)
	AN (answer mode; TRUE means answer, FALSE means originate)
	BT (byte of UART/ACIA data; integer)
	TR (transmitter ready, preceding character finished; boolean)
	RR (receiver ready, new data has arrived; boolean)
	TN (telephone number; string of digits with possible pause-characters
		if needed; implemented as list, vector, array, pipe, etc.)

Below where actual subroutines are defined, each description begins
with the name of the subroutine and its arguments and returned
value(s).  For example:

SNDBT: BT --> status

means that SNDBT is the subroutine; it takes one argument which is
a BT (byte of data), and returns one value which is status info.

RCVBT: --> BT, status

means that RCVBT is the name, it takes no arguments, but it returns
two values, one a BT and the other a status.  Arguments and results
may be passed with whatever convenion is appropriate for the
implementation language.

INITM:
	Initialize modem after power-up or non-PCNET use.  This
	routine does whatever system-specific stuff may be needed
	before the other routines will work correctly.

SETSP: SP --> status
	Set speed of UART/ACIA.  If you use Bell-103 modem protocol at
	all speeds, this won't affect the modem, but for nonstandard
	implementations at 1200 baud or faster this may also select
	the carrier frequencies of the modem.

ISTRG: --> RG
	Is telephone ringing (from incoming call we haven't yet
	answered)?

DILTN: TN --> status
	Dial a number blindly (assumes you have dial tone, but you
	can't check for that with most $400 modems currently
	available).

ISTCA: --> CA
	Test for remote carrier being heard and recognized here.  What
	frequency carrier is recognized depends on originate/answer
	mode which must have been set earlier.

SETAN: AN --> status
	Set originate/answer mode of carriers in modem and anything
	else in modem/DAA that is needed to correspond.

SETOH: OH --> status
	Set off/on hook.  If OH is TRUE this answers the phone or
	picks up phone in preparation to dial.  If OH is FALSE this
	hangs up.

SETCA: CA --> status
	If CA is true, turn on my carrier (frequency transmitted
	depends on originate/answer mode which must have been set
	earlier).  If CA is false, turn off my carrier.

ISTTR: --> TR
	Check to see if transmitter is ready so that we can send more
	data.  TRUE means safe to send next byte, FALSE means still
	busy with the preceding byte.

SNDBT: BT --> status
	(ISTTR must return TRUE before it is safe to call this
	routine.)  Send one 8-bit byte of data in 10-bit
	start+data+stop frame.

ISTRR: --> RR
	Check to see if receiver is ready.  TRUE means a byte of data
	has completely arrived and we'd better get it before another
	byte arrives.  FALSE means no new data has arrived.

RCVBT: --> BT, status
	(ISTRR must return TRUE before it is safe to call this
	routine.)  Receive the 8-bit byte of data that has arrived and
	has been waiting for us to get it.  Status indicates whether a
	valid byte was received, or framing and/or overrun errors
	occurred.

DELAY: time --> status
	Delay for a specified interval of realtime.  Some modems (PMMI
	for example) permit use of the baudrate clock for program
	timing, but if this feature isn't available the DELAY may be
	implemented as a program loop since it won't be used except
	when the whole machine is waiting for it to be safe to proceed
	with the next step.  DELAY is needed because some modems don't
	work unless you pause between certain operations, and for
	things like awaiting a dial tone.  The meaning of its argument
	may be defined by each programmer since it isn't used by
	higher-level software.

These routines call the preceding as subroutines, and do not access
the hardware directly themselves.  They may therefore be written
either in a high-level language or in machine language.  These
routines perform almost all the functions called directly by the
higher-level protocols, thus provide an interface between the atomic
hardware operations defined in the preceding section and the useful
hardware-related functions required by the PCNet software.  These
routines, together with INITM and ISTRG, are the only routines ever
needed to be called from high-level half-duplex software such as PCNet
(checking ISTCA is implicit in the failure-return from various of
these routines).

ORICL: SP, TN --> success?
	Initiate an outgoing (originate-mode) call.
	* Call SETSP and SETAN as needed to put modem in correct mode.
	* Call SETOH(TRUE).
	* DELAY about 3 seconds to give the local telephone exchange
	time to give you a dial tone.
	* Call DILTN(TN).
	* DELAY about 30 seconds to give the remote telephone exchange
	time to make the connection, the remote modem time to answer
	the phone and put up carrier, and the local carrier time to
	see the remote carrier and sense it long enough to decide it
	is really there.  Periodically call ISTCA and continue as soon
	as it's true.  If after 30 seconds you don't have carrier,
	something went wrong, you'll have to try again later or give
	up.  You may want to keep testing for carrier for a while just
	in case it was really there and phone noise obliterated it.
	* Call SETCA(TRUE).
	* Possibly DELAY about a half-second to give your modem time
	to stabilize (some modems drop carrier if you have just turned
	it on and you immediately try to do something else with the
	modem, a design bug we have to live with presently).

ANSCL: SP --> success?
	Answer an incoming call.  Normally another routine will loop
	testing for ISTRG.  After seeing ISTRG return TRUE, indicating
	at last that someone has dialed this number and our phone is
	ringing, this ANSWER-CALL routine is called.  It does:
	*  Call SETSP to set the modem speed.
	*  Call SETOH(TRUE) to answer the call.
	*  Call SETAN(TRUE).
	*  Call SETCA(TRUE).
	*  Loop waiting for ISTCA to return TRUE.  If this doesn't
	happen in a reasonable time (say 15 seconds), something is
	wrong.

ENDCL: --> success?
	Terminate the call that is in progress.
	*  Call SETCA(FALSE) to turn off carrier.
	*  Call SETOH(FALSE) to hang up.
	*  Call other routines as needed to establish the correct
	inactive state.

SDWBT: BT --> status
	This routine waits until the UART/ACIA is ready for the next
	outgoing character (by seeing ISTTR return TRUE), then calls
	SNDBT(BT).  It also calls ISTCA and if it returns FALSE
	then this routine returns an error.

RCWBT: time --> BT, status
	This routine loops, calling ISTRR repeatedly for a few
	seconds.  At any point in this loop, if ISTRR returns TRUE,
	RCWBT immediately terminates the loop, calls RCVBT to get a
	BT, and returns it up the line.  If ISTRR remains FALSE for
	the full time, this routine gives up and returns a timeout
	signal.  It also calls ISTCA inside the loop, and if it
	returns FALSE then this routine returns an error.

*** *** *** This section is completely obsolete, but is included in
case somebody has an old version of the software and wants to know
whether it is totally broken or merely performs an old obsolete
protocol such as shown here ***

Examples
--------

(THESE ARE IN THE OLD PROTOCOL!!!)

The format used to describe the blocks is that of the Apple debug
trace.
The fields shown are the originate/answer bit, Give, Want, Length,
Stream number (with "Z" indicating End-of-Data").  If the block is a
control message (stream 0 with end-of-data), the opcode byte
is shown.  The remainder of the block is shown in ASCII.

Orig G0 W0 L7 S00Z 87 "FOO"
	@S10OQJ)1BIE463(@]]]]]

Ans  G0 W1 L2 S00Z 87 "FOO"
	@Y40OQJ)1BIE400(@[[[[[

Orig G1 W1 L4 S00Z C3
	@7O(9WS9S7@]]]]]

Ans  G1 W2 L4 S00Z 83
	@DR(P1J-KH@[[[[[

Orig G2 W2 L19 S02Z "MAIL: REM^M^J^M^JFOO TEST^M^J"
	@LW2KXAF5A(Z7XL9101G)0CQ972BAWB+QB801C*FC4(@]]]]]

Ans  G2 W3 L0F S03Z "GOOD: THANKS"
	@9E12+972BWY7AWB0+87IAZ+8D((@[[[[[

	Differences between old (pre-1981) and new protocol

Note: The Appendix on the 1980 protocol should go here.  I haven't
retyped it yet.  DO NOT DELETE MC:PCNET;GNU INTRO until I do.  This
means YOU, REM!!!

"APPENDIX A" ON 1980 PROTOCOL IS NOW INSERTED HERE -- WARNING, NOBODY HAS
 READ IT TO SEE IF IT'S CORRECT -- REPORT ERRATA TO Robert Maas, 415-323-0720

		Appendix A -- Older Versions of the Protocol
		Retyped by Robert Elton Maas

Older versions of the PCNet protocol included a length byte in the
Validating Block, and used different orderings of characters that
represent the Radix-41 digits.

----------------

There were two reasons for the length-byte change.  First, one byte
of overhead per block was saved.  Second, it permitted two nodes
to negotiate lengths longer than 255 bytes while remaining compatible
with the PCNET Simple protocol. Without the change, the maximum length
that a Validating Block could accomodate was 253 bytes of data. With the
change, up to 65534 bytes of data can be used.  (This would allow values
in the hundreds or low thousands, which we think would be reasonable.)

(In the following, the "physical block" is the received block passed to
the validating layer by the translating layer.  The "physical length"
is the length of this block; that is the number of bytes it contains.)

The current (new) layout of a Validating Block is:

	 /-Length of--\	  /--- Physical block -----------------\
	/  phys.blk.   \ /					\
	+-------+-------+-------+++++++++++++++++-------+-------+
	| len H | len L | header| ... data ...  | cks 1 | cks 2 |
	+-------+-------+-------+++++++++++++++++-------+-------+
	\					/
	 \---- checksum all of this -----------/

When transmitting, the physical length (length of data plus 1 for
the header byte and 2 for the checksum bytes that will be added later)
is temporarily put at the front of the block as two extra bytes.
This augmented block (lenH, lenL, header, data) is then checksummed.
The two length bytes are then thrown away from the beginning, and
the two checksum bytes are appended at the end.  What actually gets
transmitted then are the header byte, the data, and the two checksum bytes.

When receiving, the physical length is measured from the arrived data
(whatever number of bytes were received, that's the physical length we use)
and as before the physical length is temporarily put at the front of
the block and used to compute the checksum.  This time the computed checksum
is compared with the two checksum bytes that were received, and if they agree
we accept the block as good.

When using Radix-41 (Simple Mode), there is one special case that must be
handled.  If the physical block to be transmitted has an odd length, an
extra zero byte is added after the second checksum byte so that the block
will then be of even length. (This is necessary because Radix-41 translation
can't handle an odd byte; it handles only pairs of bytes.)  On receipt of
the block, the first attempt to validate the block won't succeed because
the zero byte won't have been thrown away.  Checksum will be computed on
lenH and lenL which are one higher than they are supposed to be, and
the first checksum byte transmitted will be received as a data byte to
be included in the checksum, and the second checksum byte will be treated
as the first checksum byte, and the zero byte will be treated as the
second checksum byte. The computed checksum will surely not match the
checksum and zero bytes so the block will be rejected. [Can anybody prove
there dosn't exist a valid block which just happens to have a zero
second-checksum and just happens to match another block one shorter?]
The simplest solution is that after finding the computed checksum doesn't
match the checksum as received, if the second checksum byte is zero then
remove it and try again.  Note that the physical length bytes stuck on
at the start of the block will have to be adjusted before computing the
checksum.  If after this second attempt the checksum bytes still don't
agree, then the block really is bad and should be rejected.

By contrast, the old validating block looked like this:

	 /--- Physical block, all of this transmitted--\
	/						\
	+-------+-------+++++++++++++++++-------+-------+
	| header| length| ... data ...  | cks 1 | cks 2 |
	+-------+-------+++++++++++++++++-------+-------+
	\				/
	 \--------Checksum this--------/

The header byte occured at the start instead of at the end, then
the single length-byte (maximum value 255).  Everything (except
of course the checksums) is checksummed. But the length byte was
transmitted along with everything else instead of being dropped.

The receiver had to compute the checksum only once, even in the
case of an odd-length block with zero byte appended since the length
byte is part of the data as received rather than being guessed two
different ways depending on the zero byte. If the length was odd
and the last byte was zero then the last byte was dropped. An extra
validity check could then be performed, comparing the actual length
(after dropping the zero byte if it was dropped) with the length byte
and rejecting the block if they were different. However this extra
check could be omitted since the preceding tests were sufficient to
achieve the desired level of assurance that only good blocks were
accepted.

----------------

The ordering of Radix-41 "digits" (ASCII characters used to represent
numeric digits) was changed to make it easier to convert the
"digits" to and from values 0 thru 40.  The current ordering is:

	0123456789:;<=>ABCDEFGHIJKLMNOPQRSTUVWXYZ

which consists of two contiguous sets in ASCII, 0 thru >, and A thru Z.
The old ordering was:

	(0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ*+-)

Note that neither is a direct extension of IBM hexadecimal notation:

	0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ.....

but the new method can be implemented as a single test for the two
contiguous sections (0 thru >, and A thru Z) followed by a different
offset in the two cases (hexadecimal 30 and 32 respectively),
whereas the old method has to be implemented as a table-lookup to
avoid a whole bunch of tests.

----------------

The arithmetic mapping that converts pairs of 8-bit values (2^16=65536
different possible 16-bit values, i.e. values 0 thru 65535) into triples
of base-41 values (41^3=68921 possible values, i.e. values 0 thru 68920,
except only 0 thru 65535 are actually used) when transmitting, and
then converts them back again when receiving, is the same.  However the
sequence in which pairs of 8-bit values are assembled to make 16-bit
values, and the sequence in which triples of base-41 values are
transmitted after the arithmetic is done, have been reversed.

The old method took the first byte of the pair as the low-order byte
(times 1) and the second as the high-order byte (times 256),
just like 8080 and 6502 opcodes take their 16-bit addresses.
This is backwards from normal mathematical notation, sort of like
"four and twenty blackbirds".  The new method takes the first byte
as the high-order byte and the second as the low-order byte, just
like normal notation "twenty-four".

The old method transmitted the low-order base-41 digit (1) first,
then the middle (41) and lastly the high-order (1681). This was
backwards, like "four and twenty and a hundred". The new method
transmits the high-order digit (1681) first, then the middle (41),
then the low-order (1) last, like "a hundred and twenty-four".

This is a dummy node for copying when making new nodes.