Heading:
Alto Gateway Microcode Package
Page Numbers: Yes X: 527 Y: 10.5"
Inter-Office Memorandum
ToAlto Gateway ProjectDateFebruary 10, 1980
FromEd TaftLocationPalo Alto
SubjectAlto Gateway Microcode PackageOrganizationPARC/CSL
XEROX
Filed on: [Ivy]<Portola>GatewayMicrocode.press
The Gateway Microcode package provides facilities by means of which Mesa or Bcpl programs may conveniently and efficiently control either of two communication interfaces: the XEOS Alto EIA board or the ASD Communication Processor. It also includes various other pieces of microcode useful in Alto Gateways.
The microcode package has the following properties.
It permits operating communication lines at relatively high speeds: many lines at 9.6 KB, or a few (probably not more than two) lines at 56 KB, full-duplex.
It provides a framework making it possible to control individual lines independently of each other. That is, the microcode may provide independent software interfaces to each line.
The present microcode implements the complete finite state automata for reception and transmission of data frames (packets) using a subset of the BiSync protocol. The software specifies packet reception and transmission by means of queues of Line Command Blocks. The software is notified (by an interrupt) when reception or transmission of a packet has been completed.
Other software interfaces presently implemented are character-at-a-time reception and transmission via ring buffers and uninterpreted block-at-a-time transmission.
Separate versions of the microcode exist for the EIA board and the CommProc. While the two pieces of hardware are quite different, the software interfaces and overall organization of the driver are virtually identical. The only intentional differences have to do with initialization, exception handling, and interpretation of control and status words. Note, however, that simultaneous operation of an EIA board and a CommProc in the same Alto is not supported.
The microcode is usable by both Mesa and Bcpl programs. Slightly different versions of the microcode are required for the two languages.
This document describes the software interface to the Gateway microcode package. Information available from the hardware documentation for the EIA board and the CommProc is not duplicated here. Reference is made to the one-page command and status word format summary provided by XEOS, and to the CommProc Functional Specification (hardware) provided by ASD.
All information applies to both interfaces and to both Bcpl and Mesa programming unless otherwise specified. All numbers are decimal unless suffixed with ’B’, in which case they are octal.
Hardware requirements
The microcode runs only on an Alto-II with the Extended Memory option (though there is no necessity for more than 64K of memory actually to be installed).
The microcode is usable by Mesa programs only if the Alto has a 2K Control board, with the Mesa microcode blown into ROM1.
EIA board
One or more EIA boards should be installed as described in the documentation accompanying them. The XEOS wire-wrap interface requires several modifications before it may be used with the EIA microcode. These modifications will be detailed in a separate memo. If the IC in location D2 is a 74LS174, the modifications have already been made; if it is a 74LS175, they have not. The ASD printed-circuit interface is expected to incorporate these changes.
A modification is required to make the Memory Refresh Task be RAM-related. This involves adding a single wire to the backplane: MRTACTIVE’ (slot 11, pin 109) to either TASKA’ (slot 10, pin 13) or TASKB’ (pin 14), whichever isn’t being used by other devices. If both an EIA board and a CommProc are installed in the same Alto, TASKB’ must be used, because the CommProc uses TASKA’.
CommProc
The CommProc installation instructions should be followed. No other modifications are required.
Exception: if two additional Ethernet interfaces are also installed in the same Alto, the CommProc interval timer must be disabled because the task which it uses (task 1) is needed for the second extra Ethernet. To do this, while installing the CommProc omit the connection of WAKE1’ to pin 114 and 1ACT’ to pin 119 of slot 16.
Organization and data structures
The EIA microcode runs as part of the Memory Refresh Task. Every 38 microseconds, it checks to see whether any EIA line is requesting service, and if so performs all processing required. The CommProc microcode runs as a dedicated task that wakes up only when service is required for data transfers.
In either case, the microcode requires the presence of several data structures in main memory. These data structures are used both for maintaining line state and for communication with software.
Line table
All line state is maintained in a table in main memory, pointed to by an S-register called LINTAB. Five other S-registers are used for scratch; all six must be dedicated to the Gateway microcode. The S-registers presently assigned are 71 through 75 and 77, which have been chosen not to conflict with the Mesa emulator.
Associated with each line is a six-word Line Table Entry (LTE), whose first word lies at LINTAB + 6*line, where line is the communication line number (in the range 0 to 7 for EIA boards, 0 to 15 for CommProc). LTEs must lie on even-word boundaries. The structure of an LTE is:
Word 0Unused.
Word 1EIA board only: Hardware status is stored here every time the EIA line requests service, for whatever reason. See the "Status Word Format" in the EIA interface documentation. The microcode interprets the INTP flag as a request for service.
Word 2Pointer to current input Line Command Block (LCB), or zero if no LCB is set up.
Word 3Current input state (described below).
Word 4Pointer to current output LCB, or zero if no LCB is set up.
Word 5Current output state.
Additionally, a few words below the beginning of the line table are reserved for various purposes, as will be described later. Here is a summary:
Word -4CommProc only: Interval Timer interrupt bit mask.
Word -3CommProc only: Interval Timer interval.
Word -2CommProc only: Interval Timer counter.
Word -1Pointer to CRC table.
Line states
The state word is a small integer representing the state of the microcode with respect to a given line and direction. When a line requests service, the microcode uses the state to dispatch to the appropriate stretch of microcode for handling the line at that point. The microcode updates the state when appropriate.
Associated with the finite state automaton for each software interface is a set of states. Each set is closed; i.e., the microcode will transition only to other states in the same set. The software is expected to initialize the input and output state words of each line to the initial states of the software interfaces being used. Thereafter, the microcode maintains the states automatically. The initial states presently defined are:
0Throwaway mode. Input data is thrown away and output requests are ignored (EIA board) or cause Send Enable to be reset (CommProc). Unused lines should have their states initialized to this value.
1BiSync data frame input.
2BiSync data frame output.
3Character-at-a-time input via a ring buffer.
4Character-at-a-time output via a ring buffer.
5Uninterpreted block output.
When additional software interfaces are implemented, their initial states will be added to this list.
Line Command Blocks
Input and output data transfers are specified by separate chains of Line Command Blocks (LCBs). The LTE contains pointers to the first LCB in each chain. When a complete packet transfer has taken place, the microcode stores ending status in the LCB, issues an interrupt (if the software so desires), and begins processing the next LCB in the same chain. Exception: the Character-at-a-time software interfaces use only a single LCB, which describes a ring buffer that is used indefinitely.
An LCB must be aligned on an even-word boundary. The first four words of every LCB have a standard format, regardless of the software interface; additional words are interface-dependent. Words marked ’*’ are modified by the microcode and must therefore be reinitialized before every use of the LCB; other words are never stored into by the microcode.
Word 0Link to next LCB, or zero if none.
Word 1Bit mask indicating channel(s) on which an interrupt is to be initiated when processing of the LCB has been completed.
Word 2*Ending microcode status (see below). The software must initialize this to zero before appending the LCB to a chain.
Word 3*Ending hardware status.
The microcode indicates that it has completed processing an LCB by setting bit 0 of the microcode status word (word 2), storing an error code in bits 1-15 of the same word, and storing hardware status in word 3. The microcode may store an error code and hardware status prior to the end of the transfer, so the software should look only at bit 0 of the microcode status to determine whether LCB processing has completed.
The following error codes are independent of the software interface in use on the line. Other codes are defined by specific software interfaces.
0No error.
1A fatal hardware status was reported. The hardware status word stored in the LCB will show what the error was. The microcode will post this code in preference to a software interface-dependent error if both occur during processing of the same LCB.
During input, the status bits treated as fatal errors are the following:
RPE (Receive Parity Error): Can occur only if parity checking has been enabled.
ROR (Receive Overflow Error): Input data late, characters lost.
RFE (Receive Framing Error): Can occur only when the line is in asynchronous mode.
During output, the fatal error status bits are:
FCT (Fill Character Transmitted): EIA board only. Can occur only when the line is in synchronous mode. Indicates that the USRT transmitted a fill character because a new data character was not supplied within one character time after a request. Note that this is a perfectly normal condition between frames, when there is no data to be sent. It is an error only if it occurs within a frame. The microcode for block-mode transmission is careful to ignore FCT status at the beginning of a frame. However, during character-at-a-time transmission, the software must make this distinction.
Transmit Overrun: CommProc only.
Emulator-level subroutine calls
The Mesa or Bcpl software communicates with the microcode by three means: manipulating the shared data structures, directly manipulating the hardware interface registers, and calling Ram subroutines that have been included in the microcode. Ram subroutine calls are accomplished somewhat differently in Mesa and Bcpl.
The following examples show how to call the SilentBoot subroutine, which takes a single argument and sets the Boot Locus Vector to it, then boots the Alto. Other Ram subroutines are declared and called similarly.
In the Mesa version of the microcode, subroutine entry points are at fixed locations in the Ram and are intended to be called directly by means of the JRAM Mesa opcode, with argument and result values passed through the Mesa stack in the usual fashion. The entry point to the SilentBoot subroutine is Ram location 1400B. The subroutine is declared and called as follows. This is valid only in Mesa versions 4.0 and later.
silentBootAddr: CARDINAL = 1400B; -- Ram entry point for SilentBoot
SilentBoot:
PROCEDURE[bootLocusVector: WORD] =
MACHINE CODE BEGIN
Mopcodes.zLIW, silentBootAddr/256, silentBootAddr MOD 256;
Mopcodes.zJRAM;
END;
SilentBoot[177376B]; -- the call --
Ram subroutine calls must be complete Mesa statements, not nested expressions. When a Ram subroutine returns a value, a call to it must be a statement of the form "simpleVariable ← Routine[arguments]".
In the Bcpl version of the microcode, subroutines are called by executing undefined opcodes that trap into the Ram. For example, the opcode for SilentBoot is 63000B. Arguments are passed in accumulators 0, 1, and 3, and the result (if any) is returned in AC0.
A Bcpl-callable procedure is available to do this. It is contained in the file CallRam.asm, and is called as follows:
result = CallRam(opcode, ac0, ac1, ac3)
For example:
CallRam(63000B, 177376B) // equivalent to Mesa’s SilentBoot[177376B]
The following table summarizes the Ram subroutine names and the corresponding Mesa Ram entry points and Bcpl trap opcodes for all the routines presently defined in the microcode.
NameMesa entry pointBcpl opcode
SilentBoot1400B63000B
EnableEIA
(EIA board)1401B63400B
SetLineTab
(CommProc)1401B63400B
PupChecksum
1402B64000B
ProcessEIA
(EIA emulator version only)-----65400B
ChangeControlReg
(CommProc)1403B65400B
SetConPtr
(1822 version only)1420B-----
PREncrypt
(1822 version only)1421B-----
Initialization
Prior to operating the communication hardware or Gateway microcode, the software must perform a great deal of initialization.
Microcode initialization
First, the microcode must be loaded. There are a large number of possible microcode configurations, depending on whether Mesa or Bcpl is being used, what devices are to be controlled, and how they are to be operated. Packed Ram images for seven standard configurations are available in the following files, to be found on [Ivy]<Portola>. Other configurations can easily be constructed; see the "Packaging and other facilities" section for information.
MesaGateEIA.brMesa, EIA board.
MesaGateEIAChain.brMesa, EIA board, and up to 3 Ethernet board to be operated with chained input buffers.
BcplGateEIA.brBcpl, EIA board.
BcplEmuEIA.brBcpl, EIA board, emulator-level processing. (See the "Timing information" section for an explanation of the circumstances under which this version is required.)
MesaGateCP.brMesa, CommProc
MesaGateCPChain1822.brMesa, EIA board, up to 3 Ethernets with input chaining, and an Alto-1822 interface.
BcplGateCP.brBcpl, CommProc
The Boot Locus Vector should be set to a value that will cause the appropriate tasks to be run in the Ram, and the Alto should be "silently" booted. This may be accomplished using the SilentBoot Ram subroutine, presented previously. The correct Boot Locus Vector value for each Ram image is contained in word zero of that Ram image; see the "Packed Ram" and "LoadRam" package documentation for further details on the format of Ram images. The Bcpl LoadRam procedure obtains the Boot Locus Vector from the Ram image automatically (if the boot argument is true).
Caution: the silent boot causes an extended memory Alto’s bank registers to be reset to zero. Therefore, the code that executes the silent boot had better be running in bank zero, or else it will perform an unexpected non-local goto. If any other tasks (e.g., the display) are running in extended memory, their bank registers will need to be reset also. XMesa programmers beware.
Determining which lines exist
To determine whether any EIA boards exist, simply store 140000B into location 177700B and then read location 177704B. If the result is nonzero, at least one EIA board exists. After reading 177704B, you should read 177703B once; otherwise, you may leave the EIA board in a bad state. You must do all this before enabling the EIA microcode. Note that the EIA board for line zero must be present in order for any other line to work.
In order to determine which EIA lines are present, it is necessary to complete the initialization of the Line Table (below) and enable the EIA microcode. Then zero the hardware status word in each LTE and poke each line by storing 14x000B into location 177700B, for x=0 to 7. Within a maximum of 608 (=2*8*38) microseconds, the status word for every line that exists will have become nonzero.
To determine which CommProc lines exist, store some nonzero value into location 177300B + 4*line, for line=0 to 15. If the same nonzero value can be read back, the line exists. The nonzero value chosen should not cause Receive Enable (bit 8) or Send Enable (bit 9) to be set, since that would cause the CommProc microcode to be awakened.
Data structure initialization
Next, the main memory data structures must be initialized. LINTAB should be set up as documented previously, with initial states appropriate to the software interfaces to be used on each line.
The word at LINTAB-1 must contain a pointer to a 256-word table, CRCTAB, that assists in CRC computation. The software must initialize this table using the algorithm presented by the following Bcpl program:
for i = 0 to 255 do
[
let crc = 0
let val = i
for power = 0 to 7 do
test (val & 1) eq 0
ifso
val = val rshift 1
ifnot
[
crc = crc xor (120001
B rshift (7 - power))
val = (val rshift 1) xor 120001
B
]
CRCTAB ! i = crc
]
This table is usable by software as well as microcode. The following procedure, given a partial CRC and a new data character, returns the updated CRC:
let UpdateCRC(oldCRC, data) =
(oldCRC rshift 8) xor CRCTAB ! ((oldCRC xor data) & 377B)
Hardware initialization
Next, the hardware for each line must be put into the correct initial state. For the EIA board, this is accomplished by storing a sequence of command words into main memory location 177700B, as described under "Control Word Formats" in the EIA interface documentation. For the CommProc, the control words at addresses 177300B + 4*line + n (n=0, 1, 2) must be initialized as appropriate. The CommProc Receive Enable and Send Enable flags must not be set until after SetLineTab has been called (below).
The exact command words required depend on how the line is to be used and what software interface is to be employed. Typical command sequences are suggested later in the descriptions of specific software interfaces.
Enabling and disabling the microcode
EIA board: The microcode is controlled by bit 15 of the R-register R37: if this bit is set, the EIA microcode is permitted to run.
The microcode is enabled and disabled by a Ram subroutine, EnableEIA[LINTAB]. If LINTAB is nonzero, the microcode is enabled and LINTAB establishes the address of the Line Table. If LINTAB is zero, the microcode is disabled.
The software must turn the EIA off when quitting and when entering the debugger, and back on again when leaving the debugger. When quitting, it is necessary to execute SilentBoot[177776B] in order to get MRT out of the Ram.
CommProc: The Line Table address is established by calling the Ram subroutine SetLineTab[LINTAB], which has the same entry point as EnableEIA but does not perform the additional function of enabling or disabling the microcode.
Unfortunately, the CommProc provides no way to enable and disable the microcode as a whole in a manner that doesn’t disturb the state of the hardware. Probably the best method of shutting off wakeups when entering the debugger is to execute the following for each line:
Read and save the contents of control word 0 (by fetching 177300B + 4*line).
Turn off Send Enable and Receive Enable by executing ChangeControlReg[4*line, 300B].
When leaving the debugger, restore the saved value of control word 0 by storing it directly into 177300B + 4*line.
Of course, executing SilentBoot[177776B] still suffices to reset everything when quitting.
Additional initialization for Emulator-level EIA processing
There is a special version of the Bcpl EIA microcode that is functionally equivalent to the standard one but performs EIA processing in the Emulator task rather than the Memory Refresh Task. The justification for this variant is described later in the "Timing information" section. Here we describe the additional initialization that this microcode requires.
When the Memory Refresh Task discovers that EIA service is required, it initiates an interrupt on channel 16B, which has highest priority except for the parity error channel. The interrupt routine for this channel (pointed to directly by the channel’s dispatch word, which is location 502B) is expected to consist entirely of the following two instructions:
ProcessEIA; opcode 65400B
bri; 61002B
The ProcessEIA instruction calls a Ram subroutine that performs the necessary EIA processing. ProcessEIA takes no arguments and returns no results.
Before enabling the EIA microcode, it is necessary to set up this interrupt routine and to turn on channel 16B (by "or"ing 2 into Active = 453B). This may not be done using the Bcpl Interrupt package, since that package performs a context switch and a Bcpl procedure call on every interrupt, which is definitely not what you want. Also, the software must reserve channel 16B early enough during initialization so that it will not be usurped by other uses of the Interrupt package.
General operation
EIA board
The EIA interface requests service whenever the INTP condition is true (see "Status Word Format" in the EIA documentation). The microcode examines the status word of the requesting line to determine what to do. If the RDA (Receive Data Available) flag is set, it performs input processing on the line (i.e., it dispatches on the line’s input state). Similarly, if TBMT (Transmit Buffer Empty) is set, it does output processing.
Regardless of whether or not RDA or TBMT is set, the microcode stores the hardware status in word 1 of the Line Table Entry. This permits the software to monitor the status of an otherwise idle line (e.g., to notice Send Indicator). Note, however, that not all changes in status cause the EIA interface to request service. In particular, the dropping of SI or CD causes a request but the raising of those signals does not. Therefore, to guarantee that the status is up-to-date, the software should poke the interface using the command that forces a line to request a wakeup, then wait at least 38 microseconds before reading the status word. Poking the interface is accomplished by storing the command 14x000B (where x is the line number) into location 177700B.
CommProc
Service requests in the CommProc cause a dedicated task to be awakened. Requests are generated only for transmission or reception of data bytes, not by changes of control or status levels. The CommProc task dispatches on line number, I/O direction, and line state in a manner similar to the EIA microcode.
Unlike the EIA microcode, the CommProc microcode does not store hardware status into word 1 of the Line Table Entry, since the hardware status register may be interrogated directly by software. At any time, the status word for line may be read from memory location 177300B + 4*line + 3.
A Ram subroutine is provided by means of which the software may change selected bits in a control register without disturbing the other bits. This operation is atomic with respect to CommProc task execution.
ChangeControlReg: PROCEDURE[lineTimes4: CARDINAL, changeMask: WORD]
LineTimes4 should be four times the line number to be affected. The low-order two bits identify the control word to be manipulated. Control word zero is the only one for which this operation is likely to be useful. The control register bits corresponding to ones in bits 1 through 15 of changeMask are set to the value in bit 0 of changeMask. The remaining bits are not disturbed. Note that bit 0 is not used in any control register.
General
In general, the microcode performs only data transfer operations between a line and memory, and does not touch the interface control registers. This means that it is the software’s responsibility to initialize the interface appropriately (synchronous or asynchronous, full- or half-duplex, baud rate, etc.) and to monitor status bits as required.
In the descriptions of the block-mode software interfaces, references are made to the operation of appending an LCB to a chain. Care must be taken to do this in a race-free fashion. The following Bcpl procedure accepts head, a pointer to the head of an LCB chain (within a Line Table Entry), and lcb, a pointer to an LCB to be appended to the chain.
let AppendLCB(head, lcb) be
[
lcb ! 0 = 0
let p = head
while p ! 0 ne 0 do p = p ! 0
p ! 0 = lcb
if head ! 0 eq 0 then if lcb ! 2 ge 0 then head ! 0 = lcb
]
Note that it is the software’s responsibility to keep track of LCBs it has put on queues, since the microcode does not hand back pointers to the LCBs that it is finished with.
To reset a line that has timed out or is otherwise in need of reinitialization (e.g., when switching to a different software interface), the following procedure is offered:
Set the line state to zero.
Remove the LCB, set the LCB pointer to zero, and reset control registers as required.
Set the line state to the initial state of the appropriate software interface.
Restart the hardware.