Page Numbers: Yes X: 527 Y: -.5" First Page: 85
Heading:
Dorado Hardware ManualSlow IO14 September 1981
Slow IO
The slow io facility allows data transfers between the processor and any of up to 256 independently addressed io registers. It is intended that the slow io facility will be used to load and read control information associated with high speed io devices (> 20 x 106 bits/sec), which will then use the fast io system for their data transfers. Low speed devices (< 20 x 106 bits/sec) will use the slow io bus for all phases of their operation. Very slow or polled devices may be driven directly from an emulator.
Device controllers for Dorado interact with the processor by exchanging data over a 16-bit bidirectional bus IOB ("Input/Output Bus"). There may be a total of up to 256 io registers in all controllers connected to a single system. The unique 8-bit device numbers assigned to particular devices or uses that appear in every system are discussed in subsequent chapters and summarized in the table below.
Table 21: IO Register Addresses
NumberNameComment
󈋆DiskControlDisk control register
󈋇
DiskMuffDisk muffler control
󈋈
DiskDataDisk FIFO data
󈋉
DiskRamDisk format RAM
󈋊
DiskTagDisk tag register
󈋋
EDataEthernet input or output data
󈋌
EControlEthernet control and status
360
PixelClockDDC pixel clock
361
MixerDDC mixer
362
CMapDDC CMap
363
DWTFlag* (DispM analog of DWTFlag)
364
DHTFlag* (DispM analog of DHTFlag)
365
BMapDDC BMap
366
NLCB* (DispM analog of NLCB)
367
Statics* (DispM analog of Statics)
370
StatusDDC muffler and OIS data
372
MiniMixerDDC MiniMixer
373
DWTFlagDDC word task control
374
DHTFlagDDC horizontal task control
375
HRamDDC horizontal waveform control
376
NLCBDDC next line control block
377
StaticsDDC debugging control
Input/Output Functions
In most cases, a task will need to do many sequential io operations to the same io register. The 8-bit task-specific register TIOA holds the device address being referenced by each task.
TIOA is loaded at t2 from B[0:7] by the TIOA←B function, or TIOA[5:7] can be loaded from FF[5:7] while preserving TIOA[0:4] by the TIOA←small constant function. Pd←Input, Pd←InputNoPE, or Output←B functions can be issued in the instruction immediately following the one that loads TIOA.
Most input registers include odd byte parity with IOB data. The Pd←Input function reads IOB data and checks parity. The Pd←InputNoPE function reads IOB data without a parity check; this is useful when determining whether a device exists (IOB has bad parity if a nonexistent register is selected). The enabling and timing of parity error halts is discussed in the "Errors" chapter.
The Output←B function sends 16 bits of data with parity to the io register selected by TIOA. Many controllers check the parity and report parity errors as part of their status.
The tasks reserved for standard peripherals are given in the table below.
Table 22: Task Assignments
NumberNameComment
𔁆EMUThe emulator
𔁇
CONSpecial task for restarting emulator after faults
𔁈
JNKJunk task (awakened every 32 ms)
𔁉
DHTDisplay horizontal task
𔁊
AHTDispM terminal interface horizontal task
𔁌
EOTEthernet output task
𔁍
EITEthernet input task
11
8AWTDispM terminal interface word task
12
8SIMTask simulator
13
8DWTDisplay word task
14
8DSKDisk io
17
8FLTThe fault task
IO Opcodes
The Mesa instruction set has two opcodes for dealing with the slow io system:
INPUT:
TIOA←a;
Stkp←Stkp+1;
Stack←Input, IFUJump[0];
OUTPUT:
TIOA←a;
Output←Stack&−1, IFUJump[0];
These opcodes allow a Mesa program to have full access to the io system. The intent is that these instructions will be used to set up registers in firmware-driven devices, and do all the service required by polled slow devices. In many cases, the use of an INPUT or OUTPUT instruction is not sensible (doing io to a device normally driven by firmware, for example), but the capability should prove useful for testing and diagnostics.
Wakeup, Block, and Next
The "Control Section" chapter discussed task switching, and the material which follows is an elaboration of that discussion.
Note that a task for which a wakeup request is issued at t0 cannot commence its next instruction until t4; i.e., at least two cycles elapse after a wakeup before the next instruction is executed. The task then runs until it does a Block; in order to avoid an erroneous extra wakeup, the task must lower its wakeup request at least one cycle before issuing Block.
Consequently, an io device may turn off its wakeup request according to one of three strategies:
The first is to turn off the request when Next becomes equal to its task number; in this case the wakeup request is lowered at t0 of the first instruction executed for the task, and it must not block until the second instruction to prevent an erroneous second wakeup. The special situation in which Next is invalid ("Next Lies") must be dealt with by device controllers that do this. This situation occurs as follows:
Suppose that a task blocks with the following instruction:
Branch[Loop], Fetch←Address, Block;*Fetch next word
This generates Switch and the task in Bnt is broadcast over the Next bus. If the Fetch← causes hold and Bnt < Ctask, then no task switch will occur. However, the Next bus is incorrectly broadcasting Bnt. Since hold occurs after t1, there is insufficient time to change the Next bus back to Ctask in this case.
Consequently, controllers using Next detect "Next Lies" and disable any actions that would otherwise be performed when it occurs.
A pathological lockout problem should be noted: Since task T’s wakeup request was lowered at t2 when Next=T was noted at t0, the Next Lies condition will (correctly) result in repeating the held instruction at t2; however, some task of lower priority than T may erroneously execute at t4. This might be a problem if some high demand task of higher priority is coded so that it always creates Next Lies (say, by doing Block and immediate ←Md in the instruction after a Fetch←).
Another consequence of "Next Lies" is that IOAtten may be incorrect when "Next Lies" is occurring. Consequently, branch on IOAtten is illegal during an instruction that blocks and might cause hold.
The second strategy monitors TIOA becoming equal to a particular device value. In this case the wakeup request is lowered at t0 of the second instruction following a wakeup, and the task must not block until the third instruction. The disk controller has used this strategy, which has the draw back that if TIOA inadvertently assumes the particular device value for any other task, the hardware will malfunction. A consequence of any device using this strategy is that all tasks must be careful to initialize TIOA properly when first awakened.
The third strategy waits for some Output←B or Pd←Input operation to reset the wakeup condition. This would reset the condition at t3 or t5 of the Output←B instruction, and the wakeup would be lowered at t4 or t6; in this case the task must not block until the third or fourth instruction after the Output←B or Pd←Input to avoid an erroneous wakeup. The exact requirement depends upon the io controller—the disk controller, for example, lowers its wakeup request at t4 and can block in the third instruction after Output←B, while the display controller horizontal task lowers its wakeup request at t5 and can block in the fourth instruction.
If loops naturally run for at least three instructions, use of TIOA is more economical than use of Next because TIOA decoding is mandatory in any case, while Next is needed only for short loop devices, devices that use the fast io system, and devices that drive the SubTask lines.
SubTasks
When an io device sees Next becoming equal to its task, it can (optionally) present a two-bit SubTask number as well.
The processor, control, and memory sections clock SubTask into flipflops at t0. The processor OR’s SubTask [0:1] into RBase[2:3] and into MemBase[2:3]. This allows the same firmware to control several identical io devices concurrently—each device, represented by a SubTask, gets its own RM region with 16 RM locations and its own pair of MemBase registers; if only SubTask[0] is driven, then two RM regions and four MemBase registers are available to each subtask. Note that the 16 change-RBase-for-write functions do not OR SubTask into the changed address, so they cannot be used; also, if RBase is read by the processor the value read out has SubTask OR’ed in. However, the 16 change-RSTK-for-write functions do work.
Note also that when the debugging processor (Baseboard microcomputer or Alto running Midas) asserts the Freeze signal, the affect of the subtask on RBase[2:3] is disabled, but subtask continues to affect MemBase[2:3].
In the memory section, the task and SubTask that issued an IOFetch← is bussed to fast output devices with data from storage. The device receiving the data identifies itself by means of this information. IOStore←’s are handled similarly.
A task presenting SubTask signals generally must Block at the same location each iteration since there is only a single TPC value for all of the SubTasks. Hence, the full generality of tasking is unavailable—the microcode for these tasks must be coded as though the wakeup mechanism were a priority interrupt.
Illegal Things IO Tasks Must Not Do
(1) It is illegal to Block in an instruction that does B←ExternalSource, where ExternalSource is anything except one of the sources on the IFU board. This restriction is needed so that the emulator will be able to do arithmetic on B←PCX’.
(2) The IOAtten branch condition is illegal in an instruction that Blocks and might be held, because NextLies might occur, as discussed above.
(3) A task may not Block on an instruction that might be held, if its wakeup request might be dropped at t0 of the instruction. If this occurred, the instruction might inadvertently be repeated before the Block took effect.
(4) It is illegal to Block with TaskingOff in force.
(5) A task must not Block until one cycle after its wakeup request is turned off.
(6)It is illegal to issue Wakeup[n] if task n might run in the next cycle. Wakeup[n] must be executed with TaskingOff in such circumstances.