TITLE[EOMStarLoTask];
%
The low task constructs parameter blocks, handles Mesa requests, and
processes various error conditions.
Ed Fiala 3 June 1983: Interlock Output below the label "eomMesaCommandBaseA".
Edited by Tom Henning January 25, 1982 moved some BuildRulette code from eomLoTaskPage2 to eomHiTaskPage
Edited by Tom Henning January 13, 1982 modify nibble pointer so that for a 16x1 ruleload it starts on nibble 00, for a 16x16 ruleload it starts on the correct nibble xx to merge inks without borders
Edited by Tom Henning December 14, 1982 added Trapezoid support in inkwellRule
Edited by Tom Henning December 14, 1982 fix bug in Rulette Mode on height and inkwell
Edited by Tom Henning November 18, 1982 moved some BuildRulette code to eomLoTaskPage2, added some code to BuildRule to figure out the starting nibble of the ruleLoad
Edited by Tom Henning Sept 30, 1982 set Rulette width to zero to print a width of one
Edited by Tom Henning August 19, 1982 enable Inkwell and Rulette code
Edited by Tom Henning August 17, 1982 enable z-marker code
Edited by Tom Henning August 17, 1982 restored AT[type6Dispatch,6] command with eomType6Link&ZPlane command
Edited by Tom Henning August 17, 1982 modified eomBuildRule code tasking structure
Edited by Tom Henning August 16, 1982 deleted Star graphics features
Edited by Tom Henning July 23, 1982 added Rulette Mode Rulette Block generation
Edited by Tom Henning July 21, 1982 added InkwellRule Information Block and Rulette Skeleton Block generation
Edited by Tom Henning June 30, 1982 deleted commands 6,7,10,11
Edited by Tom Henning June 30, 1982 make z-plane changes
From EOMLoTask.mc Rubicon version 6/30/82, to be extended for Star graphics
Previously edited by Steve Dashiell, Ron Joiner, and Ed Fiala
Originally written by Steve Dashiell
%
SetTask[eomLoTask];
eomLoTaskInit:
eomCsbBaseLo ← (eomLhLoCsbBase), At[eomLoTaskInitLoc];
eomCsbBaseLo ← (eomCsbBaseLo) OR (eomRhLoCsbBase);
eomRulettesLeft ← (0C); * indicate not Rulette Mode
eomCsbBaseHi ← (eomLhHiCSBbase);
LoadPage[eomLoTaskPage];
eomCsbBaseHi ← (eomCsbBaseHi) or (eomRhHiCSBbase), GoToP[.+1];
OnPage[eomLoTaskPage];
eomLoSleep:
Call[eomLoTaskSwitch];
*Assume that the wakeup is to process a band list entry, and in fact assume
*that the entry is a type 1 character entry. Pick up the low 3 bits of the
*font number and the character code. Shift the data so it will point to a
*quadword address. The masking of the low two bits will be done later.
eomLoRun:
T ← RSH[eomBListEntryB,4];
*Stash the result prepratory to picking up the high two font bits and
*concatenating them. Also, test for special wakeup.
*This must be the second instruction for the IOATTEN to work properly.
eomTemp ← T, DBLGOTO[eomSpecialReason,eomBuildBlock,IOATTEN];
%********************
This is the normal low task activity. The code comes here if there is no IOATTEN
present at eomLoRun+1.
%********************
eomBuildBlock:
*Set up mask for high two font bits. This penalizes all band list
*entries except for character blocks, which it speeds up slightly.
lu ← (eomRulettesLeft), goto[eomBuildRulette,R Odd];
* Rulette Mode ?
T ← (highFontBitsMask);
*Check to see if the band list entry is a character type or something else.
DBLGOTO[eomGenFontParmBlock,eomHandleOtherType, R>=0], T ← (RSH[eomBlistEntryA,1]) AND T;
eomHandleOtherType:
*The band list entry is not for a character.
*Perform the dispatch on the band list entry type code.
DISPATCH[eomBListEntryA,1,2];
DISP[eomBuildRule];
%********************
BLOCK BUILDER TRANSFER BRANCH 4
This branch processes type 2 band list entries (Rules).
%********************
eomBuildRule:
*This is a 4 word band list entry, fetch the other 2 words and stash in
*eomFragA and eomFragB which will not be used otherwise. Note that eomFragC and
*eomFragD do not contain any information, and may be used as temps.
eomBandListPointer ← T ← (eomBandListPointer) + (2C), AT[loTaskBlockBldDispatch];
*Pick up the rule load block number.
*(most significant 6 bits of the rule load number)
PFETCH2[eomBandListA,eomFragA];
eomTemp ← 0C;
eomBuildRuleContinue:
T ← LDF[eomBListEntryB,0,6], Task;
*Fetch a double word from the junk area. This has been initialized by the
*application software to contain a skeleton of a rule parameter block.
*The words at 10 and 11 contain word 0 and a font bank relative pointer
*to the beginning of the rule loads.
PFETCH2[eomParameterTransferBaseA,eomFragC,10];
*Stash the rule load block number in eomTemp1 for shifting.
eomTemp1 ← T;
*Construct partial parameter word 2 to indicate
*blocks to request = 0, rule = true, save partial state,
*previous line not present, line buffer position = 0.
eomParmC ← (ruleParmWord2);
*Pick up the word pointer from the low 4
*bits of the rule load number field in the second band list entry word and
*shift to the proper field.
T ← (170000C);
T ← (LSH[eomBListEntryB,6]) AND T;
*Stash away the completed word 2 of the parameter block.
eomParmC ← (eomParmC) OR T;
*Fetch the short base pointer which was obtained from the junk area.
T ← eomFragD;
*Multiply the rule number by 16 and add to the base.
*Store the result in eomParmB (rule parameter word 1).
T ← (LSH[eomTemp1,4]) + T, CALL[eomStashTInParmB];
T ← (eomFragC);
eomParmA ← T, CALL[eomParmWordD];
*Stash away parameter word 3 and output the quad word to the new list.
eomParmD ← T, CALL[eomRuleStashSub];
* obtain word D, derived from eomFragB
*Parameter block word 4 need not be initialized in this case because of the
*rule being forced raw data.
*Pick up the width from the band list entry. The subroutine stashes it in
*eomParmB.
T ← eomFragA, USECTASK, CALL[eomStashTInParmB];
*set up the X and Y values
T ← LDF[eomBListEntryB,12,6];*stash the X value
eomParmC ← T;
T ← LDF[eomBListEntryA,3,15];
*stash the Y value and output the quadWord to the new list
eomParmD ← T, CALL[eomRuleStashSub];
*construct word 8 of the parameter block
*eomFragD already contains the low byte of word 8, except for the ink setting,
*from the rule setup dispatch above.
T ← (eomFragD) OR (partialStateSave);*indicate partial state save
*The sign bit of the eomInkSetting, which is used as a fast branch
*flag to indicate abnormal ink must be masked out. Stash the third quadword
*of the parameter block.
T ← (RHMASK[eomInkSetting]) OR T;
eomParmA ← T, CALL[eomRuleStashSub];
eomNewListWrite ← (eomNewListWrite) + (4C), GOTO[eomActivateHiTask];
eomBuildRulette:
eomRulettesLeft ← (eomRulettesLeft)-(10C), skip[R>=0]; * any Rulettes left?
eomRulettesLeft ← (0C), goto[eomLoSleep];
* no, reset flag, and go process present Band Entries
T ← (eomBListEntryB)AND Not(160000C);
*move height to word 3, go to a different page
LoadPage[eomHiTaskPage];
eomFragB ← T, gotoP[.+1];* obtain height
OnPage[eomHiTaskPage];
eomFragA ← (0C);
* set to Rulette size of one scanline wide
* figure out contents of word 1
T ← LDF[eomBListEntryA,0,3], CALL[eomHiTaskSwitch]; * extract X coordinate
eomTemp ← T;
T ← LDF[eomBListEntryB,0,3];
eomTemp ← T ← (Lsh[eomTemp,3])OR(T);
* X coordinate is in T and eomTemp
* figure out correct Rule Load of a 16x16 inkwell
* X for Inkwell pointer
LoadPage[eomLoTaskPage];
eomTemp ← LDF[eomTemp,14,4], gotoP[.+1]; * LSB 4 bits
OnPage[eomLoTaskPage];
eomTemp ← (Lsh[eomTemp,6])OR(T);
T ← (eomBListEntryA)AND(3C);
eomBListEntryB ← T;
T ← Lsh[eomBListEntryB,12]; * Y for Inkwell pointer
T ← (eomTemp) OR (T), Task;
T ← (eomRuletteInkPointer) OR (T); * merge inkwell pointer
eomBListEntryB ← T;
*figure out the starting nibble of the ruleLoad
T ← LDF[eomBListEntryA,14,2];
eomTemp ← T, goto[eomBuildRuleContinue];
%********************
BLOCK BUILDER TRANSFER BRANCH 5
This branch processes type 3 band list entries (Command Codes).
%********************
*dispatch on the low 3 bits of command
DISPATCH[eomBListEntryA,7,3], AT[loTaskBlockBldDispatch,1];
DISP[eomType6NOP];
eomType6NOP:
*this is the nop command
GOTO[eomPrefetchBandListEntry], AT[type6Dispatch];
eomType6EOP:
*This is the end of page command. This is faked by setting the flag to indicate
*end of band processed, and backing up the band list pointer to point once again
*to the end of page entry.
*Set up for the branch on EOP already sent.
LU ← (eomState) AND (eopAlreadySent), AT[type6Dispatch,1];
*Do the branch, and set up eomFragB in case the branch is taken.
GOTO[eomFirstEOPencounter,ALU=0], eomState ← (eomState) OR (eopAlreadySent);
*Go and pause the low task. Also back up the band list pointer.
eomBandListPointer ← (eomBandListPointer) - (2C), GOTO[eomType6EOB];
eomFirstEOPencounter:
*Change the band list base registers to point to the workspace.
T ← eomParameterTransferBaseA;
eomBandListA ← T;
T ← eomParameterTransferBaseB;
eomBandListB ← T, CALL[eomLoTaskSwitch];
*Set up the band list offset to point to the dummy EOP in the workspace.
eomBandListPointer ← (bandListEOPpointerMinusTwo);
*Task out due to length of modify wakeup reasons subroutine.
*Store the modified wakeup reasons.
T ← (EOPProcessed), CALL[eomModifyWakeupReasons];
*Go to pause the low task.
GOTO[eomType6EOB];
eomType6EOB:
*Check for new list overflow. First, pick up the maximum allowable new
*list pointer value (the start of old list).
T ← (eomState) AND (newListSizeMask), AT[type6Dispatch,2];
CALL[eomLoTaskSwitch];
*Subtract this from the current end of new list.
LU ← (eomNewListWrite) - T;
DBLGOTO[eomNewListOverflow,eomNoNewListOverflow,ALU>=0];
eomNewListOverflow:
*The new list has overflowed, send the error notify.
T ← (newListOverflow);
CALL[eomModifyWakeupReasons];
NOP;
eomNoNewListOverflow:
*This is the end of band command. This simply sets the band done flag,
*and pauses the low task.
eomState ← (eomState) OR (bandDone);
*Output the command for the low task automaton to pause. Also, activate the
*high task if it needs it. It could be paused waiting for the band done
*indication before sending out the end of band character.
INPUT[eomTemp,resetLoTaskRun];
LU ← eomTemp, CALL[eomActivateHiTaskFromLoTask];
GOTO[eomPrefetchBandListEntry];
eomType6ZPlane:
*build a Z-Plane Information Block
* write the z-plane value into word 0
LoadPage[eomLoTaskPage2], AT[type6Dispatch,3];
T ← Lsh[eomBListEntryB,10], gotoP[eomBuildZMarker];
OnPage[eomLoTaskPage2];
eomBuildZMarker:
eomParmA ← T;
eomParmA ← (eomParmA) OR (10C);
*Fetch a double word from the junk area.
*The words at 10 and 11 contain word 0 and a font bank relative pointer
*to the beginning of the rule loads.
PFETCH2[eomParameterTransferBaseA,eomFragC,10];
eomParmB ← (2C); * mark this as a ZMarker
eomParmC ← (120C);
*Fetch the short base pointer which was obtained from the junk area.
T ← (eomFragD)AND Not(17C);
*OR the result in eomParmB (rule parameter word 1).
eomParmB ← (eomParmB) OR (T);
*Construct the mask for use in building the height. This mask has zero
*bits (which will be complemented to one bits) in the positions where
*the raw data flag and the fresh start bit must go.
eomParmD ← (143400C);
*construct parameter word 3 to indicate fresh start, raw data, nibble
*pointer = 0, font, and height from band list entry. Set height to 1
* eomFragC now has ones in bits 5-15 and a 1 in bit positions 1 and 0.
eomParmD ← (eomParmD) OR (376C), CALL[eomRuleStashSubPaged];
eomParmB ← (5000C); * set width to guarantee State Save for 40 Bands
eomParmC ← (77C); * set x displacement to last scanline
eomParmD ← (0C), CALL[eomRuleStashSubPaged];
* force the X value to start on the last scanline of Band Buffer
*construct word 8 of the parameter block
eomParmA ← (10C);
eomParmA ← (eomParmA) OR (400C), CALL[eomRuleStashSubPaged];
*indicate partial state save, use invisible ink
eomNewListWrite ← (eomNewListWrite) + (4C);
*Pick up the ink setting, shift and mask to place it in the field where
*it is used.
T ← (14C);
T ← (RSH[eomBlistEntryA,10]) AND T;
*Stash the ink setting, and check for abnormal ink.
*Abnormal ink is anything except visible black.
DBLGOTO[eomNormalInk,eomAbnormalInk,ALU=0], eomInkSetting ← T;
eomAbnormalInk:
*abnormal ink. Set the sign bit to be used as a fast branch flag
*to indicate the abnormality
eomInkSetting ← (eomInkSetting) OR (abnormalInkIndication);
eomNormalInk:
*Normal ink; don’t do anything funny.
LoadPage[eomLoTaskPage];
gotoP[eomActivateHiTask];
OnPage[eomLoTaskPage];
eomType6Link:
*This is the link format
*It is required that 2 be subtracted because the bandlist prefetch
*increments the band list pointer prior to performing the fetch.
T ← (eomBListEntryB) - (2C), AT[type6Dispatch,4];
eomBandListPointer ← T, GOTO[eomPrefetchBandListEntry];
eomType6Link&EOB:
*this combines link format with end of band. Perform the link
*here, then branch to the EOB code.
*It is required that 2 be subtracted because the bandlist prefetch
*increments the band list pointer prior to performing the fetch.
T ← (eomBListEntryB) - (2C), AT[type6Dispatch,5];
eomBandListPointer ← T, GOTO[eomType6EOB];
eomType6Link&ZPlane:
*this combines link format with z-plane change. Perform the link here,
*then branch to the z-Plane change code.
*It is required that 2 be subtracted because the bandlist prefetch
*increments the band list pointer prior to performing the fetch.
T ← (eomBListEntryB) - (2C), AT[type6Dispatch,6];
eomBandListPointer ← T, GOTO[eomType6ZPlane];
* set Rulette Mode command
eomType6RuletteMode:
LoadPage[eomLoTaskPage3], AT[type6Dispatch,7];
T ← (eomBListEntryB)AND(170000C), gotoP[eomSetupRuletteMode];
* mask out lower 6 bits, and the next 6 higher bits
OnPage[eomLoTaskPage3];
eomSetupRuletteMode:
eomRuletteInkPointer ← T; * store inkwell pointer
T ← LDF[eomBListEntryA,12,6]; * high 6 bits of number of Rulettes
eomRulettesLeft ← T, Task;
T ← LDF[eomBListEntryB,12,6]; * low 6 bits of number of Rulettes
eomRulettesLeft ← (Lsh[eomRulettesLeft,6])OR(T);
* merge to get 12 bit number of Rulettes
eomRulettesLeft ← (Lsh[eomRulettesLeft,3])+1;
* set LSB to indicate Rulette Mode
eomRulettesLeft ← (eomRulettesLeft)-(10C); * precompensate for count
LoadPage[eomLoTaskPage];
gotoP[eomPrefetchBandListEntry];
OnPage[eomLoTaskPage];
eomPrefetchBandListEntry:
*Fetch the next band list entry prior to tasking out.
eomBandListPointer ← T ← (eomBandListPointer) + (2C);
PFETCH2[eomBandListA,eomBListEntryA], GOTO[eomLoSleep];
%********************
BLOCK BUILDER TRANSFER BRANCH 6
This branch builds InkwellRules.
%********************
eomBuildInkwellRule:
LoadPage[eomLoTaskPage2], AT[loTaskBlockBldDispatch,2];
*This is a 4 word band list entry, fetch the other 2 words and stash in
*eomFragA and eomFragB which will not be used otherwise.
*Note that eomFragC and eomFragD do not contain any information,
*and may be used as temps.
eomBandListPointer ← T ← (eomBandListPointer) + (2C), gotop[.+1];
OnPage[eomLoTaskPage2];
PFETCH2[eomBandListA,eomFragA], Task;
*This is a 4 word band list entry, fetch the other 2 words and stash in
*eomFragA and eomFragB which will not be used otherwise.
* output the InkwellRule Information Block to the New List
T ← (eomBListEntryB) AND (77C);
eomTemp ← T;
T ← (Lsh[eomTemp,11])+1; * x-coordinate
eomParmB ← T;
T ← eomFragA, goto[eomTrapezoidInfoBlock,R Odd];
eomParmA ← T, goto[eomInkwellRule];
eomTrapezoidInfoBlock:
eomParmA ← T;
T ← LDF[eomBListEntryA,3,15];
eomParmC ← T; * initial Y coordinate
T ← LDF[eomFragB,3,15]; * initial height
eomParmD ← T, CALL[eomRuleStashSubPaged];
eomBandListPointer ← T ← (eomBandListPointer) + (2C), CALL[eomGetTrapezoidParm];
eomParmC ← eomParmC, CALL[eomRuleStashSubPaged];
eomBandListPointer ← T ← (eomBandListPointer) + (2C), CALL[eomGetTrapezoidParm];
eomParmC ← eomParmC, CALL[eomRuleStashSubPaged];
eomNewListWrite ← (eomNewListWrite) + (4C), goto[eomInkwellRuletteBlock];
eomInkwellRule:
CALL[eomRuleStashSubPaged];
eomNewListWrite ← (eomNewListWrite) + (14C), goto[eomInkwellRuletteBlock];
eomInkwellRuletteBlock:
eomNewBlocksFull ← (eomNewBlocksFull) + 1;
eomFragA ← (0C); * set to Rulette size of one scanline wide
* figure out the correct rule load
T ← (eomBListEntryA) AND (3C);
eomTemp ← (T);
T ← Lsh[eomTemp,12];
eomBListEntryB ← (eomBListEntryB)+(T);
T ← LDF[eomBListEntryA,14,2];
LoadPage[eomLoTaskPage];
eomTemp ← T, gotop[eomBuildRuleContinue];
OnPage[eomLoTaskPage];
%********************
BLOCK BUILDER TRANSFER BRANCH 7
This branch processes type 4 band list entries (Images).
%********************
eomBuildType2:
T ← eomBListEntryB, AT[loTaskBlockBldDispatch,3];
PFETCH4[eomBandListA,eomParmA];
eomParmB ← (eomParmB) AND Not (17C), CALL[eomRuleStashSub];
*force the interlock, zero out z-plane field, then write the Parameter Block
T ← (eomBListEntryB) + (4C), CALL[eomBuildType4Sub];
T ← (eomBListEntryB) + (10C), CALL[eomBuildType4Sub];
*increment the write pointer to take account of the last quadword, which
*is not transferred. Go and remove the hi task pause, if one is in effect.
eomNewListWrite ← (eomNewListWrite) + (4C), GOTO[eomActivateHiTask];
%********************
This is the exceptional low task activity. The code comes here if there is an IOATTEN
present at eomLoRun+1.
%********************
eomSpecialReason:
*Get the wakeup reason from the hardware. NOTE-- this value in eomFragc
*is also used in the eomMesaCommand dispatch if the special reason is a
*mesa command.
INPUT[eomFragC,loTaskStatus];
CALL[eomLoTaskSwitch];
*dispatch on the reason
DISPATCH[eomFragC,16,2], LU ← eomFragC;*force the interlock to work;
*Load up a 1 for use if the branch is band switch.
eomFragB ← (1C), DISP[eomNoStatus];
%********************
SPECIAL TRANSFER BRANCH 0
This branch is an error. Status zero should never occur with the IOATTEN line
raised.
%********************
eomNoStatus:
*GOTO[eomLoSleep], AT[loTaskMainDispatch];
eomLoTaskResetInterlock:
LU ← eomTemp, GOTO[eomLoSleep], AT[loTaskMainDispatch];
%********************
SPECIAL TRANSFER BRANCH 1
This code is run if a parity error was detected.
%********************
eomParityError:
*Merge the parity error wakeup reason in with whatever else is already
*there.
T ← (parityError), AT[loTaskMainDispatch,1];
CALL[eomLoTaskSwitch];
*This subroutine is so long, must task right before calling it.
CALL[eomModifyWakeupReasons];
*INPUT[eomTemp,resetParityError];
*eomLoTaskResetInterlock:
*LU ← eomTemp, GOTO[eomLoSleep];
INPUT[eomTemp,resetParityError], GOTO[eomNoStatus];
%********************
SPECIAL TRANSFER BRANCH 2
The code comes here to handle a mesa request.
%********************
eomMesaCommand:
*Pick up the mesa command field and dispatch on it.
DISPATCH[eomFragC,11,3], AT[loTaskMainDispatch,2];
DISP[eomMesaCommandBase];
%********************
MESA COMMAND TRANSFER BRANCH 0 - - SECOND LEVEL DISPATCH
Parametric Page Generation Startup
The code comes here to handle a type 0 Mesa request: set up internal registers
from the CSB and start generating parameter blocks. This is the normal parametric
page printing start.
%********************
eomMesaCommandBase:
*Clear the bitMapFirst indication, and indicate parametric time
*operation starting from the new list
eomState ← (newListAndParametricMode), AT[loTaskMesaDispatch];
eomMesaCommandBaseA:
*This is the entry point from the real time page print option.
*Fetch the long pointer to the working storage. Also activate the low
*task wakeup automaton.
PFETCH2[eomCsbBaseLo,eomParameterTransferBaseA,workingStorageOffset],
CALL[eomActivateLoTask];
*Fetch the skeleton for the band buffer command word.
*This skeleton will be in word 12B of the junk area. Also, initialize the
*new list ring.
PFETCH1[eomParameterTransferBaseA,eomFragA,12], CALL[eomInitNewList];
*Fetch the word to be sent to the OPC startup register, and the indication
*of how large the new list should be.
PFETCH2[eomCsbBaseLo,eomFragC,mesaCommandOffset], CALL[eomLoTaskSwitch];
*eomFragD contains the new list size in the 5 low order bits.
eomFragD ← LSH[eomFragD,12];
*Be paranoid, mask the field in case Mesa is being bad.
T ← (eomFragD) AND (newListSizeMask);
eomState ← (eomState) OR T;
*Initialize active attributes to zero and load transfer base with the
*beginning address of the font storage.
eomRulettesLeft ← (0C); * indicate not Rulette Mode
eomActiveAttributes ← (ZERO);
PFETCH2[eomCsbBaseLo,eomDataTransferBaseA,fontPointerOffset];
*initialize the workspace. The low 16 words of the workspace are reserved
*for misc. junk.
eomOldListRead ← T;
eomOldListWrite ← T;
*fetch the long pointer to the band list
PFETCH2[eomCsbBaseLo,eomBandListA,bandListOffset], TASK;
*initialize the offset from the band list base
eomBandListPointer ← (0C);
*Fetch the short pointer to the parameter block fragments. Note that this
*pointer is relative to the working storage long pointer
PFETCH1[eomCsbBaseLo,eomFragments,fragmentsOffset];
*indicate no parameter blocks in either list
*empty is indicated by the sign bit set, that is, -1.
eomOldBlocksFull ← (ZERO) - 1;
eomOldBlocksReturned ← (ZERO) - 1;
*Output the band buffer command fetched from word 12B in the junk area.
OUTPUT[eomFragA,bandBufferCmndReg];
*Initialize to hi task not paused.
eomState ← (eomState) OR (hiTaskRunning);
*Perform the OUTPUT to start the EOM.
OUTPUT[eomFragC,opcStartupOut];
*Set up the EOP for the workspace.
eomFragA ← (hiEOPcode);
*Initialize the previous z-Plane value to zero.
eomOldZNewZ ← (0C), TASK;
eomFragA ← (eomFragA) OR (loEOPcode);
*Fetch the first band list entry.
T ← eomBandListPointer;
PFETCH2[eomBandListA,eomBListEntryA], TASK;
*Store the EOP in the workspace.
PSTORE1[eomParameterTransferBaseA,eomFragA,endOfPageCodeLoc];
eomResetMesaRequestCode:
*reset the Mesa request
*This is the location to branch to when the mesa request needs resetting.
INPUT[eomTemp,resetMesaCommand], GOTO[eomLoTaskResetInterlock];
%********************
MESA COMMAND TRANSFER BRANCH 1 - - SECOND LEVEL DISPATCH
Reset Wakeup Reason
%********************
eomResetWakeupReason:
*ALL CODE BETWEEN THE PFETCH4 AND THE PSTORE4 MUST BE DONE WITHOUT A TASK
*SWITCH, OTHERWISE THE HIGH TASK COULD MODIFY THE WAKEUP REASON AFTER THE
*PFETCH AND BEFORE THE PSTORE AND THAT MODIFICATION WOULD BE DESTROYED
*WHEN LO TASK DID THE PSTORE4
*Pick up the current wakeup reason word in eomParmB and the mesa command
*in eomParmC.
PFETCH4[eomCsbBaseLo,eomParmA,wakeupMaskOffset], AT[loTaskMesaDispatch,1];
*Load T with the mask to use (from mesa command).
T ← eomParmC;
*The usectask call is manditory to allow time for eomFragB to be properly
*stored prior to the start of the PSTORE.
eomParmB ← (eomParmB) AND T, USECTASK, CALL[eomLoTaskSwitch];
*Store the masked reasons word back in the CSB.
PSTORE4[eomCsbBaseLo,eomParmA,wakeupMaskOffset], CALL[eomLoTaskSwitch];
GOTO[eomResetMesaRequestCode];
%********************
MESA COMMAND TRANSFER BRANCH 2 - - SECOND LEVEL DISPATCH
Continue Parametric Page Print
%********************
eomContinueParaPrint:
*Clear the bitMapFirst indication. The parametric operation flag is still
*set. Also indicate no freezeEOBChar state.
eomState ← (eomState) AND NOT (firstParametricAndBandDone), AT[loTaskMesaDispatch,2];
eomState ← (eomState) AND NOT (freezeEOBChar);
*Activate the low task. This subroutine does not use T.
T ← eomOldBlocksReturned, CALL[eomActivateLoTask];
*Set the old blocks full value for the upcoming band to the number of blocks
*returned in the previous band. Also, initialize the new list parameters.
eomOldBlocksFull ← T, CALL[eomInitNewList];
*Initialize the active attributes to image, to force a setup for the first
*data block of the next band. Without this, the data transfer base can be
*left pointing to the bitmap return buffer. The sign bit set means that the
*initial data block handler in the hi task will not attempt to save any
*parameters about image 3 away in the junk area. (eomActiveAttributes = 7
*implies image # 3)
eomActiveAttributes ← (ZERO) - 1;
*Set the old blocks returned value to its initial value to indicate no blocks
*returned. Also, activate the hi task.
eomOldBlocksReturned ← (ZERO) - 1, CALL[eomActivateHiTaskFromLoTask];
*Reset the mesa request wakeup for the lo task.
GOTO[eomResetMesaRequestCode];
%********************
MESA COMMAND TRANSFER BRANCH 3 - - SECOND LEVEL DISPATCH
Increment Image Sector Value
%********************
eomIncrementImSectVal:
*Pick up the image number to increment the sector count from.
*eomFragA will contain the image number (0,1,2, or 3).
PFETCH1[eomCsbBaseLo,eomFragA,mesaCommandOffset], AT[loTaskMesaDispatch,3];
*Set up the offset for fetching the sector count
T ← (20C);
T ← (LSH[eomFragA,2]) + T, CALL[eomLoTaskSwitch];
*
*ALL THE CODE BETWEEN THE FOLLOWING "LU ←" UP TO THE PSTORE4 MUST BE DONE
*WITHOUT A TASK SWITCH, OR THE HIGH TASK CAN COME IN IN THE MIDDLE AND MODIFY
*THE COUNT OF SECTORS AVAILABLE WITHOUT THE KNOWLEDGE OF LO TASK.
*THIS IS TRUE WHETHER THE IMAGE IS ACTIVE OR NOT (it could become active
*after the PFETCH4 but before the PSTORE4).
*
LU ← (LSH[eomActiveAttributes,2]) - T;
DBLGOTO[eomImageActive,eomImageNotActive,ALU=0];
eomImageActive:
*The image data is already present in the quad block starting at
*eomDataTransferBaseA, so no fetch is required.
eomRingChar ← (eomRingChar) + (incSectorsFilledByOne);
eomSectorsFilled ← (eomSectorsFilled) + 1, TASK;
PSTORE4[eomCsbBaseLo,eomDataTransferBaseA];
GOTO[eomResetMesaRequestCode];
eomImageNotActive:
PFETCH4[eomCsbBaseLo,eomParmA];
eomParmD ← (eomParmD) + (incSectorsFilledByOne);
*The NOP is manditory to insure that eomParmD is stored prior to the
*start of the PSTORE4.
NOP, TASK;
PSTORE4[eomCsbBaseLo,eomParmA];
*Go and reset the Mesa request.
GOTO[eomResetMesaRequestCode];
%********************
MESA COMMAND TRANSFER BRANCH 4 - - SECOND LEVEL DISPATCH
Dump 64 CPU registers to main memory.
%********************
eomDiagnosticRegDump:
*Pick up the microcode long pointer from the mesa command and the word
*following.
PFETCH2[eomCsbBaseLo,eomFragA,mesaCommandOffset], AT[loTaskMesaDispatch,4];
*Initialize eomFragC to be an offset.
eomFragC ← (100C), CALL[eomLoTaskSwitch];
NOP;
eomRegDumpLoopHead:
T ← STKP;
*Use eomFragD to save the stack pointer.
eomFragD ← T;
*Load the stack pointer for the current quad block.
STKP ← eomFragC;
*Set up the offset from the double word base.
T ← (eomFragC) - (100C);
PSTORE4[eomFragA,STACK];
*Retreive the actual stack pointer.
eomFragD ← (eomFragD) XOR (377C);
*Restore the stack pointer.
STKP ← eomFragD, CALL[eomLoTaskSwitch];
eomFragC ← (eomFragC) + (4C);
*Check for completion.
LU ← (eomFragC) - (200C);
DBLGOTO[eomRegDumpLoopHead,eomRegDumpDone,ALU<0];
eomRegDumpDone:
GOTO[eomResetMesaRequestCode];
%********************
MESA COMMAND TRANSFER BRANCH 5 - - SECOND LEVEL DISPATCH
Show Revision Level.
%********************
eomShowRevLevel:
eomTemp ← (revisionLevel), AT[loTaskMesaDispatch,5];
PSTORE1[eomCsbBaseLo,eomTemp,statusOffset], CALL[eomLoTaskSwitch];
GOTO[eomResetMesaRequestCode];
%********************
MESA COMMAND TRANSFER BRANCH 6 - - SECOND LEVEL DISPATCH
Terminate Page Print
%********************
eomTerminatePagePrint:
*Zero the wakeup reasons word;
eomFragB ← 0C, AT[loTaskMesaDispatch,6];
CALL[eomLoTaskSwitch];
*Output garbage to register 0 to do the IORESET. The output must be done
*twice for the hardware to completely reset.
OUTPUT[eomFragA,0];
OUTPUT[eomFragA,0];
*The store is done here to allow eomFragB to be stored;
PSTORE1[eomCsbBaseLo,eomFragB,wakeupReasonOffset], GOTO[eomResetMesaRequestCode];
%********************
MESA COMMAND TRANSFER BRANCH 7 - - SECOND LEVEL DISPATCH
This option handles the startup of a real time page print.
%********************
eomStartRealTimePage:
*Intialize the eomHiTaskState value to indicate real time page print and
*working from new list. Then go and set up as in a parametric page print.
eomState ← (workingFromNewList), GOTO[eomMesaCommandBaseA],
AT[loTaskMesaDispatch,7];
%********************
SPECIAL TRANSFER BRANCH 3
The code comes here to handle a band switch.
%********************
eomBandSwitch:
*Fetch the count of bands processed. The count will be in eomParmD.
PFETCH4[eomParameterTransferBaseA,eomParmA,thirdJunkQuad],
AT[loTaskMainDispatch,3];
*Set up to send the notification of band switch;
T ← (bandSwitch), CALL[eomLoTaskSwitch];
*Increment the bands processed count.
eomParmD ← (eomParmD) + 1, CALL[eomModifyWakeupReasons];
*Check to see if we are in parametric or real time mode.
LU ← (eomState) AND (parametricModeFlag);
*Check for parametric band switch. If it is real time band switch, update
*the old list full values. Also, store the count of bands processed.
GOTO[eomParametricBandSwitch,ALU#0],
PSTORE4[eomParameterTransferBaseA,eomParmA,thirdJunkQuad];
*Output the start bit, set up in the DISP instruction. This is required
*in real time operation. Also, send the band switch notification.
OUTPUT[eomFragB,opcStartupOut];
T ← eomOldBlocksReturned;
eomOldBlocksFull ← T;
eomOldBlocksReturned ← (ZERO) - 1;
eomParametricBandSwitch:
*Reset the wakeup condition.
INPUT[eomTemp,resetBandSwitch], GOTO[eomLoTaskResetInterlock];
eomGenFontParmBlock:
*THE NEW LIST WRITE POINTER POINTS TO THE QUADWORD LOCATION ONE POSITION PRIOR
*TO THE TRUE WRITING POSITION BECAUSE THE RULE AND IMAGINAL ENTRIES PERFORM
*THEIR WRITING INTO NEW LIST VIA A SUBROUTINE CALL WHICH PERFORMS A PRE-
*INCREMENT OF THIS POINTER. FOR THIS REASON, THE
*OFFSETS FROM THE WRITE POINTER ARE 4 LARGER THAN IT APPEARS THEY SHOULD BE.
*Finish assembling the offset from the fragments base.
eomTemp ← (eomTemp) AND NOT (3C);
T ← (eomTemp) OR T;
*Add in the base.
T ← (eomFragments) + T;
*Fetch the fragment.
PFETCH4[eomParameterTransferBaseA,eomFragA];
*set up the Y value
T ← LDF[eomBListEntryA,3,15], TASK;
eomParmD ← T;
*set up the X value
T ← LDF[eomBListEntryB,12,6];
eomParmC ← T;
*Create the run length and terminator word and stash it. The run length
*must be initialized to maximum, all ones. The terminator doesn’t matter.
eomParmA ← (ZERO) -1;
*Now pick up the width information from the fragment.
T ← eomFragD;
eomParmB ← T;
*Check for abnormal ink.
GOTO[eomNormalInkB,R>=0], A ← eomInkSetting;
*The ink color is abnormal (not black visible). Must diddle the force word 8
*to zero bit in eomParmB and also generate word 8 of the parameter block.
eomParmB ← (eomParmB) AND NOT (forceWord8ToZero);
*Stash the second quadword of the parameter block.
T ← (eomNewListWrite) + (10C);
PSTORE4[eomParameterTransferBaseA,eomParmA];
*Generate word 8.
T ← RHMASK[eomInkSetting], TASK;
eomParmA ← T;
*Stash the third quadword of the parameter block.
T ← (eomNewListWrite) + (14C);
PSTORE4[eomParameterTransferBaseA,eomParmA], GOTO[eomEndInkBranch];
eomNormalInkB:
*Stash the second quadword of the parameter block.
T ← (eomNewListWrite) + (10C);
PSTORE4[eomParameterTransferBaseA,eomParmA], GOTO[eomEndInkBranch];
eomEndInkBranch:
*Move the first word of the first quadword of the parameter block out of
*the fragment.
T ← (eomFragA), TASK;
eomParmA ← T;
*Zero out the z-plane field of the second parameter word.
T ← (eomFragB) AND NOT (17C);
eomParmB ← T;
*Construct the third parameter word and stash it. This word is
*all zero for a startup font character, except for the word pointer
*and the previous line present bit.
*Pick up the word pointer and shift it to the proper location.
T ← LSH[eomFragB,14];
eomParmC ← T;
*OR in the bit to indicate previous line not present.
eomParmC ← (eomParmC) OR (previousLineNotPresent);
*move the fourth word
T ← eomFragC, TASK;
eomParmD ← T;
*output the first parameter quad
T ← (eomNewListWrite) + (4C);
PSTORE4[eomParameterTransferBaseA,eomParmA];
*Increment the new list write pointer to account for the block just added.
eomNewListWrite ← (eomNewListWrite) + (20C), GOTO[eomActivateHiTask];
eomActivateHiTask:
*Fetch the next band list entry.
eomBandListPointer ← T ← (eomBandListPointer) + (2C);
PFETCH2[eomBandListA,eomBListEntryA];
*Indicate the addition of another block to the new list.
*Also, activate the hi task if it needs it.
eomNewBlocksFull ← (eomNewBlocksFull) + 1, CALL[eomActivateHiTaskFromLoTask];
GOTO[eomLoRun];
********************
*LOW TASK SUBROUTINES
********************
*eomSnarfZPlaneInfo:
*pick up the default z-Plane information
*T ← (RHMASK[eomZPlane]) OR T;
eomStashTInParmB:
*Stash the second parameter
eomParmB ← T, RETURN;
% SUBROUTINE eomRuleStashSub AND eomBuildType4Sub ********************
This subroutine stashes parameter blocks into the new list and bumps the new list
write pointer.
% ********************
eomBuildType4Sub:
*Fetch the quadblock from the parameter block
PFETCH4[eomBandListA,eomParmA];
LU ← eomParmD;*force the interlock
eomRuleStashSub:
eomNewListWrite ← T ← (eomNewListWrite) + (4C);
PSTORE4[eomParameterTransferBaseA,eomParmA], RETURN;
% SUBROUTINE eomRuleStashSubPaged ********************
This subroutine stashes parameter blocks into the new list and bumps the new list
write pointer.
% ********************
OnPage[eomLoTaskPage2];
eomRuleStashSubPaged:
eomNewListWrite ← T ← (eomNewListWrite) + (4C);
PSTORE4[eomParameterTransferBaseA,eomParmA], RETURN;
% SUBROUTINE eomGetTrapezoidParm ********************
This subroutine gets parameter blocks into the new list and bumps the new list
write pointer.
% ********************
eomGetTrapezoidParm:
PFETCH2[eomBandListA,eomParmA];
eomParmA ← eomParmA;
eomBandListPointer ← T ← (eomBandListPointer) + (2C);
PFETCH2[eomBandListA,eomParmC], RETURN;
OnPage[eomLoTaskPage];
% SUBROUTINE eomActivateLoTask ********************
This subroutine sends the command to the hardware to activate the low task wakeup
automaton.
% ********************
eomActivateLoTask:
eomFragA ← setLoTaskRun;
OUTPUT[eomFragA,loTaskCommandReg];
eomInterlockOUTPUT:
*Interlock to force completion of the OUTPUT;
eomFragA ←eomFragA, RETURN;
% SUBROUTINE eomModifyWakeupReasons ********************
This subroutine gets the current wakeup reasons word from the CSB and OR’s into it the
value in T, then puts it back.
% ********************
eomModifyWakeupReasons:
*Fetch the wakeup mask and wakeup reasons into eomTemp and eomTemp1
*respectively.
PFETCH2[eomCsbBaseLo,eomTemp,wakeupMaskOffset];
*Use eomImageXferOffset as a temporary and load it with the register
*address in emulator space where the naked notify needs to go.
eomImageXferOffset ← IP[NWW]C;
*Or the new wakeup reason into the current wakeup reasons word.
eomTemp1 ← (eomTemp1) OR T, LoadPage[eomHiTaskPage];
*Save the current stack pointer in T. This is actually the ones complement
*of the 8 bit value. Branch to high task page.
T ← STKP, GOTO[eomLoEntryModifyWakeupReasons];
% SUBROUTINE eomActivateHiTaskFromLoTask ********************
This subroutine checks to see if the hi task is active, and if not it activates it.
% ********************
eomActivateHiTaskFromLoTask:
*Check if the high task is already active and if not, activate it.
GOTO[eomHiTaskActive, R ODD], eomState ← (eomState) OR (hiTaskRunning);
*Set up the pause remove command word.
eomFragA ← (hiTaskUnPause);
*Send the pause remove.
OUTPUT[eomFragA,loTaskCommandReg], GOTO[eomInterlockOUTPUT];
eomHiTaskActive:
eomLoTaskSwitch:
NOP, RETURN;
% SUBROUTINE eomInitNewList ********************
This subroutine initializes the new list ring parameters.
% ********************
eomInitNewList:
*lowest read transfer will be at 60B (increments by 20B)
eomNewListRead ← (newListReadRingBase);
*lowest write transfer will be at 60B (increments by 4)
eomNewListWrite ← (newListWriteRingBase);
*Indicate no parameter blocks in the new list (-1).
eomNewBlocksFull ← (ZERO) - 1, RETURN;
% SUBROUTINE eomParmWordD ********************
This subroutine obtains word D of the parameter block.
% ********************
eomParmWordD:
*Construct the mask for use in building the height. This mask has zero
*bits (which will be complemented to one bits) in the positions where
*the raw data flag and the fresh start bit must go.
T ← (34000C);
*construct parameter word 3 to indicate fresh start, raw data, nibble
*pointer = 0, font, and height from band list entry. Also compute
*adjustment to height, and compute rule mask.
*Dispatch on the 2 least significant bits of the height.
DISPATCH[eomFragB,16,2];
*eomFragC now has ones in bits 5-15 and a 1 in bit position 1.
eomFragC ← (ZERO) OR NOT T, DISP[eomSetUpRuleMask0];
*eomFragD is no longer significant, so it is used here as a temp
eomSetUpRuleMask0:*set up T to indicate no adjustment to height
T ← (1C), AT[ruleMaskDispatch];
*set up eomFragD to provide 000 for the rule mask and indicate rule
eomFragD ← (200C), GOTO[eomMergeHeight];
eomSetUpRuleMask1:
*set up eomFragD to provide 111 for the rule mask and indicate rule
eomFragD ← (360C), GOTO[eomMergeHeightSetT], AT[ruleMaskDispatch,1];
eomSetUpRuleMask2:
*set up eomFragD to provide 011 for the rule mask and indicate rule
eomFragD ← (260C), GOTO[eomMergeHeightSetT], AT[ruleMaskDispatch,2];
eomSetUpRuleMask3:
*set up eomFragD to provide 001 for the rule mask and indicate rule
eomFragD ← (220C), GOTO[eomMergeHeightSetT], AT[ruleMaskDispatch,3];
eomMergeHeightSetT:
*Set T to indicate a +1 adjustment to the height.
T ← (0C);
eomMergeHeight:
*pick up the 11 most significant bits of the height from the band list entry
*and subtract the increment value. This increment value will be either 0 or 1.
*The value supplied to the hardware must be one less than the value in the
*band list entry. Therefore, if the increment value is one, subtract 0 and if
*it is zero, subtract 1.
T ← (LDF[eomFragB,3,13]) - T;
*Take the ones complement of the height, and mask off the most significant
*bits to restrict the value to only the height field. The FRD bit is
*automatically generated at this point, since the most significant bits of
*NOT T will be ones.
T ← (eomFragC) AND NOT T;
*OR in the starting nibble of the ruleLoad
T ← (Lsh[eomTemp,14])OR(T), Return;
*Stash away parameter word 3 and output the quad word to the new list.
END;