Heading:
Alto Gateway Microcode Package
Page Numbers: Yes X: 527 Y: 10.5" First Page: 10
BiSync software interface
The microcode implements a subset of the standard BiSync protocol, namely the part dealing with transparent transmission of data frames. Such frames are used to encapsulate Pups transmitted over synchronous lines among Nova and Alto Gateways. The microcode does not implement control messages, ACKs, or other aspects of full BiSync. Indeed, it is not presently usable as part of a software implementation of full BiSync, though it could be made so with some effort.
LCB format
The standard 4-word LCB is extended to contain the following additional information:
Word 4*Byte count and half-word selection. Bit 0 = 0 if the next byte to be transferred is the left byte in a word, 1 if the right byte. Bits 1-15 contain the number of bytes remaining.
Word 5*Address of word containing next byte to be transferred.
Word 6*Partial CRC. The software must initialize this to zero before appending the LCB to a chain.
Data bytes are packed two per word, left-to-right, consistent with Mesa, Bcpl, and Pup conventions.
Hardware initialization: EIA board
The following control sequences are suggested to initialize the EIA line appropriately for synchronous communication. These are precisely the settings required for the Pup Gateway application.
10x400B(where x is the line number) INITIF with DS=1 (communicating with Data Set), HD=0 (full-duplex), STD=0 (no secondary channel). The Baud rate is normally irrelevant when operating in synchronous mode because the clock is provided by the modem. If it is desired to connect two Altos with a direct synchronous line (no modems), exactly one of the Altos should set DS=0 (communicating with Data Terminal) and select an appropriate Baud rate. When operating in half-duplex mode, it is the software’s responsibility to manage the S (sending) bit appropriately.
13x200BRESET with RRT=1 (reset the USRT chip).
11x700BINITRT with NDB=3 (8 data bits per character), NPB=1 (no parity bit), A/S=0 (synchronous). POE and NSB are irrelevant.
12x026BINITRG with F/S=0, Data=26B (SYN byte for receiver sync character register).
12x777BINITRG with F/S=1, Data=377B (all-ones byte for transmitter fill character register).
After the hardware and data structures are initialized and the EIA microcode enabled, synchronous input should be initiated (just once) by issuing a "Restart Receiver" command (store 13x100B in location 177700B). Thereafter, the EIA microcode tracks the incoming data stream, regardless of whether or not an LCB has been provided by the software.
Hardware initialization: CommProc
CommProc control word n is initialized by storing into location 177300B + 4*line + n, for n=0, 1, 2.
word 0 ← 60BData Terminal Ready, Request to Send. For test purposes, setting Wrap Enable (bit 13) may be useful.
word 1 ← 302BWord Select 3 (8-bit bytes), Clock Select 0, Mode Select 2 (synchronous). Clock Select is relevant only when running in asynchronous mode or when Wrap Enable is true. The baud rate selected by any of the four values of Clock Select is determined by jumpers on the backplane.
word 2 ← 26BSYN byte for receiver sync character recognition.
After the hardware and data structures have been completely initialized, input should be initiated (just once) by setting the Receive Enable bit in control word 0. This is most easily accomplished by ChangeControlReg[4*line, 100200B]. Thereafter, the CommProc microcode tracks the incoming data stream, regardless of whether or not an LCB has been provided by the software.
Input
To enable reception of a packet, the software should set up an LCB as described previously. Word 5 should be initialized with a pointer to a buffer and word 4 with its length in bytes. Note that words 2 (ending microcode status) and 6 (partial CRC) must be initialized to zero. The LCB should then be appended to the line’s input LCB chain.
When a packet has been received, the microcode stores status as described previously, requests interrupts as specified by word 1 of the LCB, and removes the LCB from the chain. Bits 1-15 of word 4 (byte count) indicate the number of unused bytes remaining in the input buffer.
Microcode status codes peculiar to BiSync input are:
3Input line control error (byte after first DLE wasn’t STX).
4Input buffer overflowed. Assuming the buffer really was large enough for the largest expected packet, an overflow most likely means that the receiver lost character sync with the incoming data. Therefore, the microcode drops sync and restarts the receiver when this happens.
5Input line control error (in body of packet, byte after DLE wasn’t DLE, SYN, or ETX).
6Input CRC error.
The receiver is then restarted (searching for character sync), regardless of whether or not there is another LCB on the chain. If a packet starts to arrive and no LCB is set up, the microcode throws the data bytes away but still maintains packet frame sync. If a new LCB is provided by the software while the microcode is in the middle of receiving a packet, the remainder of the packet is stored in the buffer. The ending status will most likely indicate a CRC error in this case, since the CRC is computed only over the data actually stored in the buffer.
To assure correct reception of every incoming packet, therefore, it is advisable that the software attempt to maintain at least two LCBs on the input chain at all times.
Output
To transmit a packet, the software should set up an LCB as described previously and append it to the line’s output LCB chain. It should then initiate transmission in one of the following ways:
EIA board: Poke the interface by storing 14x000B into location 177700B.
CommProc: Set Send Enable by calling ChangeControlReg[4*line, 100100B].
This ensures that the microcode will wake up and notice that a new LCB has been set up. Note that it is OK to poke the interface in this way even when it is already running; ongoing data transfers are not disturbed.
When the packet has been transmitted, the microcode stores status and requests interrupts as described previously and removes the LCB from the chain. If there is another LCB on the chain, transmission of that packet begins immediately. Otherwise, the transmitter becomes idle (the EIA board transmits continuous fill characters; the CommProc’s Send Enable flag is reset).
BiSync data frame format
A frame consists of the following sequence of bytes:
SYN SYN ... SYN DLE STX ... transparent data ... DLE ETX CRC CRC
The frame begins with at least two SYN bytes, which the receiver searches for in order to establish byte synchronization. The sequence DLE STX signals the start of the data portion of the frame.
Within the data portion, all bytes are treated as literal data except DLE, which is an escape character. A literal data byte whose code corresponds to DLE is transmitted by doubling it, i.e., by sending DLE DLE. If the sequence DLE SYN appears, both bytes are ignored. Some synchronous interfaces, though not the Alto EIA, automatically transmit DLE SYN when a transmit data-late condition occurs.
The end of the data packet is indicated by the sequence DLE ETX. Following this are two bytes containing the 16-bit CRC, transmitted low-order byte first. The algorithm used is the industry-standard CRC-16, computed over the transparent data bytes and the ETX. When the sequence DLE DLE appears, only one of the DLEs contributes to the CRC. When DLE SYN appears, neither byte is included.
While no frame is in progress, continuous fill characters (all ones) are transmitted.
Uninterpreted block transmission interface
This software interface permits transmission of arbitrary blocks of characters, with the microcode performing no interpretation whatever. It is useful primarily in conjunction with software implementation of more elaborate synchronous protocols, such as full BiSync.
Note that there is no corresponding interface for reception of uninterpreted blocks, since there is no way for the microcode to determine when a frame ends without interpreting the protocol. For input, the character-at-a-time (ring buffer) interface is probably the most appropriate.
This software interface is not included in the MesaGateCPChain1822 and MesaGateEIAChain configurations.
LCB format
Three words are added to the basic 4-word LCB:
Word 4*Byte count and half-word selection. Bit 0 = 0 if the next byte to be transferred is the left byte in a word, 1 if the right byte. Bits 1-15 contain the number of bytes remaining.
Word 5*Address of word containing next byte to be transmitted.
Word 6Control command to be issued after transmission of block has been completed.
The block pointed to by the LCB is expected to contain two data bytes per word, packed left-to-right.
Operation
To transmit a packet, the software should set up an LCB and append it to the line’s output LCB chain. It should then poke the interface in the manner described above under "BiSync Software Interface: Output".
When the packet has been transmitted, the microcode first issues the control command in word 6 of the LCB by storing it in location 177700B (EIA board) or 177300 + 4*line (CommProc). The intended use of this feature is to turn around a half-duplex synchronous line at the end of transmission. This word should be zero if no control command is to be issued.
The microcode then stores status and requests interrupts as described previously and removes the LCB from the chain. If there is another LCB on the chain, transmission of that packet begins immediately; otherwise, the transmitter becomes idle.
Note that the microcode does not add any SYN characters or other framing at either the beginning or the end of the block. If such characters are required, the software must include them in the data block.
Character-at-a-time software interface
This interface implements character-at-a-time reception and transmission via ring buffers. This is the most suitable interface for asynchronous lines. It can also be used for synchronous lines when it is desired to implement the synchronous line protocol in software.
This software interface is not included in the MesaGateCPChain1822 and MesaGateEIAChain configurations.
LCB format
Unlike the block-oriented software interfaces described previously, this interface requires a single LCB that is used indefinitely. The standard 4-word LCB is extended by an additional 4 words that describe a ring buffer. The LCB link (word 0) must contain a pointer to itself.
Word 4Address of first word of ring buffer.
Word 5Address of last word of ring buffer +1 (i.e., the first address plus the length of the buffer).
Word 6*Address of next word to be read from the buffer.
Word 7*Address of next word to be written in the buffer.
Data is stored in the buffer one byte per word, right-justified. The input microcode returns status in the left byte (EIA only), and the output microcode expects the left byte to be zero.
The reader and writer of the ring buffer must obey certain conventions to ensure race-free operation:
There must be only one reader and one writer, though the reader and writer need not be interlocked in any fashion.
An empty buffer is represented by read pointer equal to write pointer. A full buffer is represented by read pointer equal to write pointer +1 (modulo wrap-around). Note that under these conditions, the word pointed to by the write pointer is not being used.
The reader should read the data from the buffer before incrementing the read pointer.
The writer should write the data into the buffer before incrementing the write pointer.
These conventions are used by the microcode. The ring buffer format and conventions just described are also the ones used by the Bcpl Ring Buffer package (word version).
Input
If an EIA board is operating in synchronous mode, input must first be initiated (just once) by issuing a "Restart Receiver" command (store 13x100B in location 177700B). A CommProc line must be started by ChangeControlReg[4*line, 100200B], whether it is running in synchronous or asynchronous mode.
Whenever a character arrives, the microcode attempts to write the data into the input ring buffer. It then initiates an interrupt as specified by the interrupt mask in the LCB (if it is nonzero). EIA only: the microcode stores the rightmost 8 bits of the current hardware status into the left byte of each word at the same time it stores the data into the right byte.
If the ring buffer is full when a new character arrives, the microcode posts an error code of 2 in the LCB and throws the character away. Hardware error conditions will cause an error code of 1 to be posted, as described previously. The microcode never zeroes the microcode status word. It is the software’s responsibility to sample the status occasionally and zero it after noticing an error. Note that there is no way to determine which character caused the error.
To read the next character, the software should first wait until the ring buffer is not empty (the RingBufferEmpty procedure in the Bcpl Ring Buffer package is usable for this purpose). It should then read the data byte from the buffer and increment the read pointer. The following Bcpl code illustrates the required operations, which are similar to the ones used by the Bcpl Ring Buffer package.
let readPointer = lcb ! 6
while readPointer eq lcb ! 7 do [ ... ] // buffer empty
let data = readPointer ! 0
readPointer = readPointer+1
if readPointer eq lcb ! 5 then readPointer = lcb ! 4 // wrap around
lcb ! 6 = readPointer
Output
To transmit a new character, the software should first wait until the ring buffer is not full (the RingBufferFull procedure in the Bcpl Ring Buffer package is usable for this purpose). It should then store the data byte in the word pointed to by the write pointer, then increment the write pointer. Finally, it should poke the line (to ensure that the microcode wakes up and notices the new character), as described previously under "BiSync Software Interface: Output". It is actually necessary to poke the line only if it was idle at the moment the new character was written into the buffer. This may be determined by checking to see if, after writing the new character, there is exactly one character in the buffer. However, the cost of servicing an unnecessary wakeup is only 4 microseconds, whereas the cost of deciding whether or not to issue the wakeup is undoubtedly much greater, so in practice it is probably better just to poke the interface every time.
Whenever the microcode finishes transmitting a character, it initiates an interrupt as specified by the interrupt mask in the LCB (if it is nonzero).
The following Bcpl code illustrates the operation of writing a new character into the ring buffer:
let writePointer = lcb ! 7
writePointer ! 0 = data
writePointer = writePointer+1
if writePointer eq lcb ! 5 then writePointer = lcb ! 4 // wrap around
while writePointer eq lcb ! 6 do [ ... ] // buffer full
lcb ! 7 = writePointer
Note (CommProc only): When the microcode discovers the ring buffer to be empty, it resets Send Enable to dismiss the data request. A consequence of this is that there is no way to detect a transmit underflow condition for a line being operated in synchronous mode.
Timing information
The following rough calculations attempt to estimate the fraction of the Alto consumed by the Gateway microcode when driving lines at various data rates.
EIA microcode timing
BiSyncUninterpretedCharacter-
blockat-a-time
Alto cycles/byte906573
Microseconds/byte
151112
Fraction of Alto cycles consumed
running one line, one direction, at
9.6
KB1.8%1.3%1.4%
19.2
KB3.6%2.6%2.9%
56
KB10.5%7.7%8.4%
Remember, of course, that the percentage figures refer to the raw Alto microinstruction execution rate, with no other overhead. A full-screen display consumes about 60% of the Alto’s cycles.
An orthogonal problem is that of MRT task latency and overrun. If the EIA microcode runs for longer than the MRT wakeup interval (38 microseconds), the next wakeup will be missed. The loss of MRT wakeups has several noticeable effects, the most serious of which are that the cursor jiggles vertically and the real-time clock loses time.
The EIA microcode is careful to service at most one character per run of MRT, even if several lines are requesting service simultaneously. The worst-case running time of the EIA microcode is about 20 microseconds. Therefore, in the absence of interference from higher-priority tasks, MRT should never overrun its next wakeup.
Unfortunately, when the display is running, it consumes approximately 60% of the Alto’s cycles, at a priority level higher than MRT. The MRT wakeup interval is the same as the display horizontal scan interval. Therefore, if the Alto provides data for the entire scan line, 60% of the machine during that interval is taken up by the display and only 40% is left for MRT and lower-priority tasks. This can cause the EIA microcode’s worst-case running time of 20 microseconds to be stretched to nearly 50 microseconds, easily overrunning the MRT wakeup interval.
Therefore, to prevent MRT overruns, it is advisable either to turn off the display entirely or to limit the width of the display bit map. For example, a half-width display will consume only 30% of the Alto during each scan line, probably leaving enough cycles for MRT and the EIA microcode. Note that use of the horizontal tab feature is nearly as costly in Alto cycles as is providing real data for the same portion of the scan line.
The disk word task is also higher-priority than MRT, but it consumes only about 15% of the Alto so is less likely to cause MRT overruns. The Ethernet task is lower-priority than MRT so will not interfere with it at all.
For applications in which it is unacceptable to turn off the display, a special version of the EIA microcode exists in which MRT, rather than doing EIA processing itself, initiates an interrupt on a high-priority channel and lets the Emulator task do the work. This eliminates the MRT overrun problem entirely, but at a cost of nearly 100 additional microinstructions executed per byte. Only a Bcpl version of this special microcode is provided at present. The software must set up an interrupt routine, as described under "Initialization".
CommProc microcode timing
BiSyncUninterpretedCharacter-
blockat-a-time
Alto cycles724246
Microseconds/byte
1278
Fraction of Alto cycles consumed
running one line, one direction, at
9.6
KB1.4%0.8%1.0%
19.2
KB2.9%1.7%1.9%
56
KB8.4%4.9%5.6%
The CommProc task is lower-priority than MRT and other tasks sensitive to latency, so the latency considerations presented above do not apply.
Packaging and other facilities
The Gateway microcode is packaged to include all the microcode services required by Alto Gateways. However, the microcode source consists of a number of more-or-less independent modules, stored in a single dump-format file [Ivy]<Portola>GatewayMc.dm.
All the standard Ram images are obtained by compiling one of the top-level Mu source files, which inserts (using the "#" facility) various assortments of the other files to produce a given configuration. New configurations can easily be constructed, subject to Ram space limitations and R- and S-register availability. (The MesaCPChain1822 configuration fills the entire Ram and uses all the registers.)
All the Mesa Ram images include the Ram portion of the XMesa (extended memory) microcode. Therefore, if Rom1 contains XMesa microcode also, it is possible to run XMesa-based software. The presence of the XMesa microcode in the Ram does not interfere with operation of standard Mesa software in machines with the standard Mesa microcode in Rom1.
MesaGateEIA.muTop-level source for Mesa, EIA board.
MesaGateEIAChain.muTop-level source for Mesa, EIA board, and up to 3 Ethernet boards with chained input buffers (see below).
BcplGateEIA.muTop-level source for Bcpl, EIA board.
BcplEmuEIA.muTop-level source for Bcpl, EIA board, emulator-level processing.
MesaGateCP.muTop-level source for Mesa, CommProc.
MesaGateCPChain1822.muTop-level source for Mesa, CommProc, up to 3 Ethernet boards with chained input buffers, and an Alto-1822 interface (see below).
BcplGateCP.muTop-level source for Bcpl, CommProc.
AltoEIA1.muMain EIA board driver, EIA subroutines, and BiSync software interface.
AltoEIA2.muUninterpreted and character-at-a-time EIA software interfaces.
CommProc1.muMain CommProc driver, CommProc subroutines, and BiSync software interface.
CommProc2.muUninterpreted and character-at-a-time CommProc software interfaces, and CommProc interval timer.
EIAMRT.muModified version of the Memory Refresh Task, required for the EIA microcode.
EIADispMRT.muVersion of EIAMRT.mu required when GateDisplay.mu is included (see below).
EmuEIAMRT.muVersion of EIAMRT.mu required when using BcplEmuEIA.mu.
CPMRT.muModified version of the Memory Refresh Task, to accompany the CommProc microcode. The CPMRT changes are a subset of the EIAMRT changes, including abolition of the software Interval Timer and elimination of the wasteful use of R-register CLOCKTEMP. The CommProc microcode itself does not require MRT to be modified. CPMRT is so named simply to distinguish it from EIAMRT.
CPDispMRT.muVersion of CPMRT.mu required when GateDisplay.mu is included (see below).
GateDisplay.muMicrocode for the Alto display and cursor, rewritten to use two fewer R-registers than the standard microcode. This is required when using Mesa and controlling extra devices requiring R-registers, such as additional Ethernet controllers. The registers saved are 21B and 26B. All the display-related tasks (MRT, DWT, CURT, DHT, and DVT, tasks 10B through 14B respectively) must be started in the Ram, and special variants of the MRT microcode (EIADispMRT.mu, CPDispMRT.mu) are required.
ExtraEther1.muMicrocode for one additional Ethernet interface (see below).
ExtraEther2.muMicrocode for a second additional Ethernet interface. This is not presently assembled in any of the standard Ram images.
ExtraEther.muA top-level source file demonstrating the use of ExtraEther1.mu and ExtraEther2.mu. This file itself is not used in the Gateway microcode package.
ChainEther0.muMicrocode for controlling the standard Ethernet interface using chained input buffers (see below).
ChainEther1.muChained input microcode for the first additional Ethernet interface.
ChainEther2.muChained input microcode for the second additional Ethernet interface.
Mesa1822.muMicrocode for controlling an Alto-1822 interface (used for connecting to the Arpanet or the Arpa Packet Radio network). Documentation may be obtained from Larry Stewart (user LStewart).
PREncrypt.muMicrocode for encrypting data to be sent through the Packet Radio network.
Pup checksum computation
A Ram subroutine is included for efficient computation of the Pup software checksum:
PupChecksum:
PROCEDURE[initialSum: WORD, address: POINTER, count: CARDINAL]
RETURNS[resultSum: WORD]
The address should be a pointer to the first word of a Pup and the count the number of words in the Pup, exclusive of the checksum word (i.e., (Pup.length-1)/2). initialSum must be zero.
Timing for this subroutine is 9 Alto cycles per word, or about 425 microseconds for a maximum-length Pup.
Interval timer (CommProc only)
The CommProc hardware includes a task-driven interval timer. The Gateway microcode package supports this; however, the interval timer is not required by present Pup Gateway applications.
If the interval timer is to be used, the software must reserve and initialize three additional words just below the beginning of the Line Table. These are:
Word -4Interrupt bit mask. An interrupt is initiated on the designated channel(s) each time the interval timer expires.
Word -3Timer interval, in units of 625 microseconds.
Word -2Interval Timer counter. This should be initialized to the timer interval minus one, and is thereafter maintained by the microcode.
The interval timer is enabled by storing 100000B in location 177400B, and disabled by storing 0 into the same word. While the hardware is enabled, the microcode issues one interrupt per timer interval.
If the interval timer is being used, one should take care to disable it before entering the debugger.
Note: the interval timer microcode is not included in the MesaGateCPChain1822 configuration.
Additional Ethernet controllers
The Gateway microcode package includes microcode for controlling up to two additional Ethernet interfaces. For details, consult the memo How to install extra Ethernet interfaces in an Alto. The task number, SIO control bit, and control block address assignments are as follows:
ControllerTaskSIO bitsControl block
Standard Ethernet714, 15600B - 611B
First extra Ethernet212, 13630B - 641B
Second extra Ethernet110, 11642B - 653B
Source files ExtraEther1.mu and ExtraEther2.mu contain microcode for controlling the first and second additional Ethernets. This microcode operates identically to the standard Ethernet microcode except for task number, SIO bits, and control block address. All the standard Ram images except MesaGateEIAChain and MesaGateCPChain1822 include ExtraEther1 but not ExtraEther2.
In order to operate a second extra Ethernet interface in conjunction with Mesa (which uses nearly every available R- and S-register), it is necessary to free up two additional R-registers. This may be done by replacing the standard display and cursor microcode by the code contained in GateDisplay.mu, which uses two fewer R-registers.
The second Ethernet interface conflicts with the CommProc interval timer over use of task 1. Since the interval timer is not used in the Pup Gateway application, it suffices to disconnect the interval timer task wakeup and active signals (see "Hardware requirements" at the beginning of this document).
Another version of the Ethernet microcode exists that provides a somewhat different software interface to the Ethernet. The major difference is that input is specified by means of chains of command blocks that are followed automatically by the microcode, and the microcode also handles most of the decisions about switching between input and output. This permits the software to keep the Ethernet receiver turned on a greater fraction of the time than with the standard microcode (which requires the software to restart the interface after every packet sent or received); we expect this to improve the performance of Alto Gateways.
Files ChainEther0.mu, ChainEther1.mu, and ChainEther2.mu contain the microcode for the standard Ethernet interface and the first and second extra interfaces, respectively. The standard configurations MesaGateEIAChain and MesaGateCPChain1822 include all three. Programming information may be obtained from Hal Murray.
Due to Ram space limitations, the MesaGateEIAChain and MesaGateCPChain1822 configurations do not include the uninterpreted block and character-at-a-time software interfaces or the microcode for controlling the CommProc interval timer. These are not required in the Pup Gateway application.