TITLE[EOMHiTask];
%
Edit by Ed Fiala 23 April 1982: Absorb init from EOMInit.Mc; replace pNWW by
IP[NWW]C; fix bug in NWW code and bum 2 mi.
Edit by rej August 6, 1979 1:49 PM
Edit by srd February 22, 1980 12:58 PM
Real time z-plane bug fixed
Edit by srd February 26, 1980 2:55 PM
Verdi disk hooks added
Edit by srd March 27, 1980 2:17 PM
removed OUTPUT and LOADPAGE Gotchas.
Edit by srd August 12, 1980 1:33 PM
Modified to force start on old list.
Edit by srd March 6, 1981 2:21 PM
Streamlined initial data block processing.
Edit by srd March 12, 1981 1:24 PM
Fixed bugs in initial data block streamlining.
%
SetTask[eomHiTask];

eomHiTaskInit:
LoadPage[eomHiTaskPage], At[eomHiTaskInitLoc];
GoToP[eomHiTaskSleep];

OnPage[eomHiTaskPage];

*Send the IOSTROBE to tell the hardware to consider the request satisfied.
eomHiTaskSleep:
IOSTROBE, CALL[eomHiTaskSwitch];

%High Task Running Code.
Any wakeup at the high task level will come to eomHiRun.
The instruction following eomHiRun tests IOATTEN to decide if the request
is for normal data or for something special, and branches accordingly.
Bump the eomDataTransferOffset assuming that the wakeup is for compressed
data. This will be unbumped if it is not.
%
eomHiRun:
eomDataTransferOffset ← T ← (eomDataTransferOffset) + (20C);
*The IOATTEN test must be in the second instruction. Set up for a slow
*branch on the font/image bit of the eomActiveAttributes. This will be used
*only on the normalXfer branch.
DBLGOTO[eomSpecialXfer,eomNormalXfer,IOATTEN], LU ← LDF[eomActiveAttributes,15,1];

%
********************
Normal Data Transfer Request - - NO IOATTEN
This is where all requests for normal bitmap data come.
(First compressed data request for any object is an IOATTEN request)
%
********************

eomNormalXfer:
*Initiate the data transfer to the device and branch on font/image.
DBLGOTO[eomFont,eomImage,ALU=0],
IOFETCH16[eomDataTransferBaseA,ADD[hiTaskIOoffset,inputChannelBuffer]];

eomFont:
*The font data is a linear list; no ring management is required.
GOTO[eomHiTaskSleep];

eomImage:

*The images are rings. Decrement the blocks remaining to be read
*and check for sector completely read.
DBLGOTO[eomEndSector,eomNoEndSector,R<0], eomBlocksRemaining ← (eomBlocksRemaining) - 1;

eomEndSector:
*this code runs if all the blocks in one sector of the ring have been read.
*Check to see if the ring has wrapped. The terminal address is specfied
*in blocks to allow rings up to 4 megabits. Rings larger than 1 megabit are
*not currently supported.
T ← (LSH[eomTerminalBlockAddress,4]) - T;
*decrement the count of sectors filled and make wrap test.
GOTO[eomNoRingWrapA,ALU#0], eomSectorsFilled ← (eomSectorsFilled) - 1;
eomDataTransferOffset ← (ZERO);
eomDataTransferOffset ← (eomDataTransferOffset) - (20C);
eomNoRingWrapA:
*Reset the eomBlocksRemaining value to indicate a full sector.
CALL[eomInitBlocksRemaining];
*Set up the transfer offset for the proper image quad block in the CSB
*and stash the block. Also pick up the wakeup reasons.
T ← (LSH[eomActiveAttributes,2]);
*The wakeup reason bit selection is done in a subroutine so there will be a task
*switch immediately prior to the call on eomHiTaskModifyWakeupReasons, due
*to its length.
DISPATCH[eomActiveAttributes,16,2], CALL[eomSelectWakeupReasonSub];
CALL[eomHiTaskModifyWakeupReasons];
*Check to see if there are any more sectors of data available.
GOTO[eomNoMoreDataAvailable,R<0], A ← eomSectorsFilled;
GOTO[eomHiTaskSleep];
eomNoMoreDataAvailable:
*Send the bit to indicate that we are starting on a non valid data sector.
T ← imageUnderFlow, CALL[eomHiTaskModifyWakeupReasons];
GOTO[eomHiTaskSleep];
eomNoEndSector:
GOTO[eomHiTaskSleep];

%
********************
Special Data Transfer Request - - IOATTEN
This is where all requests for data other than bitmap data come.
%
********************

eomSpecialXfer:
*The special, IOATTEN branch. Get the dispatch field from the hardware.
INPUT[eomDispField,wakeUpType];
*Load the active attributes. This will be used in eomFirstDataBlock
*if that is the branch taken. It fills in time that would otherwise
*be wasted due to the INPUT interlock on the dispatch.
T ← eomActiveAttributes;
*Force the interlock to work and do the dispatch
DISPATCH[eomDispField,14,4], LU ← eomDispField;
*Reset the eomDataTransferOffset to the proper value.
DISP[eomFirstDataBlock], eomDataTransferOffset ← (eomDataTransferOffset) - (20C);

%
********************
SPECIAL TRANSFER BRANCH 0
When the first block of data for a character or image is requested, the transfer
base, and possibly ring control information must be set up. The type of setup
required is indicated by the microcode attributes field in the first word in the
parameter block.
%
********************

eomFirstDataBlock:
*First data block for this image. Set up to test whether the attributes
*have changed since the last item. NOTE - - THIS CODE MAKES THE IMPLICIT
*ASSUMPTION THAT IF THE ATTRIBUTES HAVE NOT CHANGED, THEN NEITHER THE
*PREVIOUS ITEM NOR THIS ONE ARE NOT NON-RESIDENT IMAGES.
*T was initialized with eomActiveAttributes just after the INPUT in the
*specialXfer path.
LU ← (LDF[eomParmBlock0,15,3]) - T, AT[hiTaskWakeupDispatch];
*Set up T with the block pointer value for use if the no change
*path is taken. Mask off the z-Plane information.
T ← (eomBlockPointer) AND NOT (17C),
DBLGOTO[eomNoAttributesChange,eomAttributesChange,ALU=0];
eomNoAttributesChange:
*Do the data transfer of the first data block.
IOFETCH16[eomDataTransferBaseA,ADD[hiTaskIOoffset,inputChannelBuffer]];
IOSTROBE, TASK;
*The IOSTROBE will give T a change to be stored after the IOFETCH16.
eomDataTransferOffset ← T;
*This code assumes that the item MUST be a font item if there was no
*attributes change. Hence, no check for the font/image bit is made,
*no ring checks are made, etc.
GOTO[eomHiRun];
eomAttributesChange:
*Task out here because it is less convenient later.
CALL[eomHiTaskSwitch];
*First, we must check to see if the previous object was an image. If
*so, the eomBlocksRemaining value and the eomDataTransfer value must
*be saved away.
LU ← LDF[eomActiveAttributes,15,1];
*Perform the branch to distinguish between image and not image on the
*previous object. Set up T for use if the branch is not taken.
GOTO[eomPreviousItemNotImage,ALU=0], T ← (eomDataTransferOffset) + (20C);
*Previous item was an image, stash the eomBlocksRemaining and
*eomImageXferOffset values. Active attributes here belongs to the item
*which has just finished printing.
eomImageXferOffset ← T;
T ← (6C);
T ← (LSH[eomActiveAttributes,1]) AND T, CALL[eomHiTaskSwitch];
PSTORE2[eomParameterTransferBaseA,eomBlocksRemaining];

eomPreviousItemNotImage:
*Place the attributes for the current item in T.
T ← (eomParmBlock0) AND (7C);
*Pick up the most significant attribute bit for the character about to begin.
*This differentiates between font bank or image and will always
*come from the parameter block most recently transferred to the hardware.
LU ← LDF[eomParmBlock0,15,1];
*Branch on the font/image bit, and set the active attributes to the values
*for the current item.
DBLGOTO[eomProcessFontBank,eomProcessImageSelect,ALU=0], eomActiveAttributes ← T;

eomProcessFontBank:
*Fetch the base address of font bank 0 into the data transfer offset reg pair.
PFETCH2[eomCsbBaseLo,eomDataTransferBaseA,fontPointerOffset];
CALL[eomHiTaskSwitch];
*Incrementing the font pointer by 0,1,2, or 3 megabits requires the
*high and low byte of the second register in the register pair to have
*0,1,2 or 3 respectively added to both bytes.
*Construct the pointer increment. T already contains the eomActiveAttributes.
T ← (LSH[eomActiveAttributes,10]) OR T;
*Add the increment value to the high half of the register.
eomDataTransferBaseB ← (eomDataTransferBaseB) + T;
T ← (eomBlockPointer) AND NOT (17C);
eomDataTransferOffset ← T, GOTO[eomNoSectorAdjustA];

eomProcessImageSelect:
*ODD BRANCH
*Fabricate the offset to use to fetch the double word pointer to the
*image buffer. Note--eomActiveAttributes bit 15 is always one on this
*dispatch branch, so the lshift 2 will be 0,4,8, or 12 plus 16.
*On the image branch of the dispatch, it is assumed that the attributes
*will always have changed since the last character.
T ← (LSH[eomActiveAttributes,2]);
*Fetch the quadword from the CSB defining this image.
PFETCH4[eomCsbBaseLo,eomDataTransferBaseA];
T ← (6C);
*EomActiveAttributes here belongs to the item which is about to start printing.
T ← (LSH[eomActiveAttributes,1]) AND T, TASK;
*Fetch eomBlocksRemaining and eomImageXferOffset for the image about to begin.
*The task switch after the PFETCH2 will leave volatile state in
*eomImageXferOffset, but since lo task cannot get in while hi task is
*trying to run, this works.
*(eomImageXferOffset is used as a temporary in eomHiTaskModifyWakeupReasons.)
PFETCH2[eomParameterTransferBaseA,eomBlocksRemaining];
*Pick up the count of sectors full.
T ← LDF[eomRingChar,0,sectorsFilledFieldWidth];
*Extract the block pointer information from the "blockPointer" register.
*Result is returned in T.
eomSectorsFilled ← T, USECTASK, CALL[eomExtractBlockPointer];
*Store the masked block pointer in T as the eomDataTransferOffset.
eomDataTransferOffset ← T;
*Put the actual block address in T.
T ← RSH[eomDataTransferOffset,4], CALL[eomHiTaskSwitch];
*Compute the count of blocks prefetched but not used in the previous
*band of thisimage.
T ← (RSH[eomImageXferOffset,4]) - T;
*Check to see if the microcode offset wrapped but the hardware pointer didn’t.
GOTO[eomNoAddTerminalCount, ALU>=0];
*This branch taken if the microcode pointer wrapped but the hardware pointer
*did not. The terminal count (plus one, to account for the full ring size) is
*added into the result to make it positive.
T ← (eomTerminalBlockAddress) + T + 1;
eomNoAddTerminalCount:
*Add this to the number of blocks believed to be remaining, before adjustment
*for the number of blocks prefetched but not used.
*Use eomHiTaskSwitch rather than TASK to be sure that the value actually
*gets stored properly.
eomBlocksRemaining ← T ← (eomBlocksRemaining) + T;
*If the result is larger than a sector, we must back up past a sector
*boundary. Pick up the blocks per sector value from eomRingChar and subtract
*the value computed above.
LU ← (LDF[eomRingChar,blocksPerSectorStartBit,blocksPerSectorFieldWidth]) - T;
*Perform the branch. Also set up T with one plus the number of blocks in a
*sector, in case the branch is not taken. The equal case of this branch means
*that the back up was to, but not past a sector boundary and no adjustment is
*required.
GOTO[eomNoSectorAdjust, ALU>=0],
T ← (LDF[eomRingChar,blocksPerSectorStartBit,blocksPerSectorFieldWidth]) + 1;

*Using T from the previous instruction, load eomBlocksRemaining with (a sector
*size plus 2) less than it had before. The plus 2 is because of the -2 terminal
*count on eomBlocksRemaining.
eomBlocksRemaining ← (eomBlocksRemaining) - T - 1;
*Increment the count of sectors full. The application software is never allowed
*to have overwritten the last sector emptied. Also make the call to
*modify the value of sectors full saved in eomRingChar.
eomSectorsFilled ← (eomSectorsFilled) + 1, CALL[eomInitBlocksRemainingA];
*Set up T with the displacement and store the image ring quad block in the CSB.
T ← LSH[eomActiveAttributes,2];
PSTORE4[eomCsbBaseLo,eomDataTransferBaseA];

eomNoSectorAdjust:
*Pick up the dataTransferOffset in T once again.
T ← eomDataTransferOffset;
eomNoSectorAdjustA:
*Set up for the branch test at eomNormalXfer
LU ← LDF[eomActiveAttributes,15,1], GOTO[eomNormalXfer];

%
********************
SPECIAL TRANSFER BRANCH 1
When the hardware first requests a state save, the code comes here. Additional blocks
of data for the same state save are handled by the COCBRequest branch.
%
********************

eomOCBRequest:
*state save request
eomOldListWrite ← T ← (eomOldListWrite) + (20C), TASK, AT[hiTaskWakeupDispatch,2];
*Bump the eomOldBlocksReturned value to account for the data transfer.
(eomOldBlocksReturned) ← (eomOldBlocksReturned) + 1;
*Overflow condition is indicated by read and write pointers being equal.
LU ← (eomOldListRead) - T;
GOTO[eomOldListOverflow,ALU=0],
IOSTORE16[eomParameterTransferBaseA,ADD[hiTaskIOoffset,outputChannelBuffer]];
*Check for old list ring wrap;
T ← (eomFragments) - (20C);
LU ← (eomOldListWrite) - T;
GOTO[eomOCBRequestSleep,ALU<0], T ← (eomState) AND (newListSizeMask);
*Ring has wrapped, fix the write pointer
eomOldListWrite ← T, GOTO[eomHiTaskSleep];
eomOCBRequestSleep:
GOTO[eomHiTaskSleep];
eomOldListOverFlow:
*There is no recovery from old list overflow. Pause the hi task, but do
*not set the hitask paused status bit. This means that the low task will
*never attempt to restart the hi task. Also, set the bit in the CSB wakeup
*reasons to indicate workspace overflow.
T ← (workSpaceOverflow);
CALL[eomHiTaskSwitch];
CALL[eomHiTaskModifyWakeupReasons];
CALL[eomDropDead];
GOTO[eomHiRun];

%
********************
SPECIAL TRANSFER BRANCH 2
%
********************

eomCOCBRequest:
*continue state save option
GOTO[eomOCBRequest], AT[hiTaskWakeupDispatch,4];

%
********************
SPECIAL TRANSFER BRANCH 3
When the hardware asks for the first block of parameters for a character, this code runs.
It is necessary to check which list, new or old to use, whether z-Planes have changed etc.
The numbered cases following a label indicate the various ways to reach that label.
%
********************

eomIPBRequest:
*check to see which list is being processed
DBLGOTO[eomProcessNewList,eomProcessOldList,R<0], LU ← eomState,
AT[hiTaskWakeupDispatch,6];

eomProcessNewList:
*ODD BRANCH

*1.)Processing new list upon entry (FROM eomIPBRequest).

*2.)Processing old list upon entry, AND old list is empty
*(FROM eomOldListEmptyA).

*check if the new list has any blocks in it
DBLGOTO[eomNewListEmpty,eomNewListNotEmpty,R<0], LU ← eomNewBlocksFull;

eomNewListEmpty:
*ODD BRANCH

*1a.)Processing new list upon entry, AND new list is empty
*(FROM eomProcessNewList).

*1b.)Processing old list upon entry, AND old list is empty,
*AND new list is empty (FROM eomProcessNewList).

CALL[eomHiTaskSwitch];
LU ← (eomState) AND (bandDone);
*check if the low task has processed a band end block entry
DBLGOTO[eomLoTaskDone,eomLoTaskNotDone,ALU#0];

eomLoTaskDone:
*ODD BRANCH

*1a.)Processing new list upon entry, AND new list is empty,
*AND lo task is done (FROM eomNewListEmpty).

*1b.)Processing old list upon entry, AND old list is empty,
*AND new list is empty, AND lo task is done (FROM
*eomNewListEmpty).

*low task is done and the new list is empty. Check to see if the
*old list is also empty, by fast branch on eomOldBlocksFull.
*Also load T with the value which will be needed in bandFinished.
DBLGOTO[eomBandFinished,eomBandNotFinished,R<0], A ← eomOldBlocksFull;

eomBandFinished:
*ODD BRANCH

*1a.)Processing new list upon entry, AND new list is empty,
*AND lo task is done, AND old list is empty (FROM eomLoTaskDone).

*1b.)Processing old list upon entry, AND old list is empty,
*AND new list is empty, AND lo task is done, AND [REDUNDANT
*TEST - - old list is empty] (FROM eomLoTaskDone).

*Old and new lists are both empty. Ship the dummy end of band character.
*Load up the first two words of the EOB character for subsequent data
*transfers.

T ← (20C), TASK;
*Force the next band to start processing in the old list.
eomState ← (eomState) AND NOT (workingFromNewList);
PFETCH2[eomParameterTransferBaseA,eomParmBlock0];
*Check to see if this it is real time or parametric mode.
LU ← (eomState) AND (parametricModeFlag);
*Branch, and set up for the test on eob already processed.
DBLGOTO[eomParametricHi,eomRealTimeHi,ALU#0], LU ← (eomState) AND (freezeEOBChar);

eomParametricHi:
*ODD BRANCH

*1a.)Processing new list upon entry, AND new list is empty,
*AND lo task is done, AND old list is empty, AND band
*was parametric (FROM eomBandFinished).

*1b.)Processing old list upon entry, AND old list is empty,
*AND new list is empty, AND lo task is done, AND [REDUNDANT
*TEST - - old list is empty], AND band was parametric (FROM
*eomBandFinished).

*In parametric mode, the low task does not attempt to do any look ahead
*block generation. It will awaken when the band switch indication arrives.
*The high task must send a dummy character to shut down the parameter
*request for the
*first character of the second band, and to allow bitmap data transfer to
*begin. Set new list stuff to dummy in the non-printing character stored
*in the third block of the workspace.
*Branch on EOB character already sent.
*Fake the new list read pointer. This will be incremented by 20B prior to
*the transfer. This points to the first of the two non-printing dummys.
GOTO[eomParametricFreeze, ALU#0], eomNewListRead ← T ← (20C);
*Prohibit zPlane switching on the dummy character. The parameter block
*for the character must indicate zPlane = 0.
eomPreviousZPlane ← (0C);
*Indicate two blocks in new list, both non-printing dummys.
*Send the EOB parameter block. Cannot task out until after the IOSTROBE
*has been sent or the hardware breaks. IOSTROBE must arrive before the
*IOFETCH16 is complete.
*Indicate that a subsequent end of band character must not be sent.
eomNewBlocksFull ← (1C);
eomState ← (eomState) OR (freezeEOBChar);
IOFETCH16[eomParameterTransferBaseA,ADD[hiTaskIOoffset,inputParameterBuffer]],
GOTO[eomHiTaskSleep];
eomParametricFreeze:
*An EOB character has already been sent for this band.
GOTO[eomWaitOnLoTask];

eomRealTimeHi:
*EVEN BRANCH

*1a.)Processing new list upon entry, AND new list is empty,
*AND lo task is done, AND old list is empty, AND band
*was real time (FROM eomBandFinished).

*1b.)Processing old list upon entry, AND old list is empty,
*AND new list is empty, AND lo task is done, AND [REDUNDANT
*TEST - - old list is empty], AND band was real time (FROM
*eomBandFinished).

*Reinitialize the new list parameters. This is required following the use of
*the end of band character.
LOADPAGE[eomLoTaskPage];
*Set up the lo task activation flag.
eomDispField ← (setLoTaskRun), CALL[eomInitNewList];
*Output the lo task activation.
OUTPUT[eomDispField,loTaskCommandReg];
*Reset the previous z-plane reference.
eomPreviousZPlane ← (0C);
*Stop the hi task by writing 0 to the start bit and reinitialize the
*new list ring parameters.
T ← (20C), TASK;
*This instruction serves to interlock the OUTPUT, as well as setting up the
*zero value for later use.
eomDispField ← (0C);
eomXferEOBBlock:
IOFETCH16[eomParameterTransferBaseA,ADD[hiTaskIOoffset,inputParameterBuffer]];
IOSTROBE;
*Stop the hi task by writing 0 to the start bit.
OUTPUT[eomDispField,opcStartupOut];
*Clear the band done indication.
eomState ← (eomState) AND NOT (bandDone), TASK;
*Interlock the OUTPUT.
eomDispField ← eomDispField;
GOTO[eomHiRun];

eomBandNotFinished:
*EVEN BRANCH

*1a.)Processing new list upon entry, AND new list is empty,
*AND lo task is done, AND old list is not empty (FROM eomLoTaskDone).

*1b.)ABSURD CASE - - CAN NEVER OCCUR
*Processing old list upon entry, AND old list is empty,
*AND new list is empty, AND lo task is done, AND old list
*is not empty (FROM eomLoTaskDone).

*new list is empty but old list is not. Send parameter block from old list.
*Can jump into the middle because we know already that the old list is not
*empty and the z-Plane change check is not necessary, since only the old
*list remains, and it is sorted. It is necessary to fetch the first two
*words of the parameter block before doing the GOTO.
T ← (eomOldListRead) + (20C);
PFETCH2[eomParameterTransferBaseA,eomParmBlock0], CALL[eomHiTaskSwitch];
GOTO[eomOldListTransfer];

eomLoTaskNotDone:
*EVEN BRANCH

*1a.)Processing new list upon entry, AND new list is empty,
*AND lo task is not done (FROM eomNewListEmpty).

*1b.)Processing old list upon entry, AND old list is empty,
*AND new list is empty, AND lo task is not done (FROM
*eomNewListEmpty).

*new list is empty because the low task fell behind. It is not done yet.
*Check if a switch to the old list is allowable. The condition for this
*is if the z-Plane for the first block on the old list is the same as the
*most recently transferred block.
*First, check to see whether the old list is empty.
DBLGOTO[eomWaitOnLoTask,eomSwitchToOldList,R<0], LU ← eomOldBlocksFull;

eomWaitOnLoTask:
*ODD BRANCH

*1a.)Processing new list upon entry, AND new list is empty,
*AND lo task is not done processing the band, AND old list
*is empty (FROM eomLoTaskNotDone).

*1b.)Processing old list upon entry, AND old list is empty,
*AND new list is empty, AND lo task is not done, AND
*[REDUNDANT TEST - - old list is empty] (FROM eomLoTaskNotDone).

*2.)Processing new list upon entry, AND new list is empty,
*AND lo task is not done processing the band, AND old list
*is not empty, AND current old list z-Plane does not match
*previous z-Plane (FROM eomNoSwitchList).

*3.)Processing old list upon entry, AND old list is not empty,
*AND old list z-Plane > previous z-Plane, AND new list is
*empty, AND lo task is not done (FROM eomLoTaskNotDoneA).

*4a.)Processing new list upon entry, AND new list is empty,
*AND lo task is done, AND freezeEOB character condition
*is set (FROM eomBandFrozen). This occurs only in parametric
*mode, and then only when the second request for an EOB
*character for the band is made.

*4b.)Processing old list upon entry, AND old list is empty,
*AND new list is empty, AND lo task is done, AND freezeEOB
*character condition is set (FROM eomBandFrozen). This occurs only
*in parametric mode, and then only when the second request for an EOB
*character for the band is made.

*the old list is empty, we must wait on the low task to put a block in the
*new list. Set the hi Task pause. Low task will remove the pause when it
*puts a block in the new list.
CALL[eomPauseHiTask];
*Must not go to eomHiTaskSleep, because no IOSTROBE should be issued. The
*request is not yet satisfied.
GOTO[eomHiRun];

eomSwitchToOldList:
*EVEN BRANCH

*1a.)Processing new list upon entry, AND new list is empty,
*AND lo task is not done processing the band, AND old list
*is not empty (FROM eomLoTaskNotDone).

*1b.)ABSURD CASE - - CAN NEVER OCCUR
*Processing old list upon entry, AND old list is empty,
*AND new list is empty, AND lo task is not done, AND
*{ABSURD - - old list is not empty} (FROM eomLoTaskNotDone).

*the old list is not empty. Now check the z-Plane to see if a switch is
*possible.
*load T with the offset of the word with the z-Plane info.
T ← (eomOldListRead) + (20C);
PFETCH2[eomParameterTransferBaseA,eomParmBlock0], CALL[eomHiTaskSwitch];
T ← LDF[eomBlockPointer,14,4];
LU ← (eomPreviousZPlane) - T;
DBLGOTO[eomSwitchList,eomNoSwitchList,ALU=0];

eomSwitchList:
*EVEN BRANCH

*1.)Processing new list upon entry, AND new list is empty,
*AND lo task is not done processing the band, AND old list
*is not empty, AND current old list z-Plane matches previous
*z-Plane (FROM eomSwitchToOldList).

*actually switch to the old list and resume processing.
*set hi task status to indicate old list processing. We can branch into the
*middle of the old list processing because we know that the old list is not
*empty, and there is no change in the z-Plane information.
eomState ← (eomState) AND NOT (workingFromNewList), GOTO[eomOldListTransfer];

eomNoSwitchList:
*ODD BRANCH

*1.)Processing new list upon entry, AND new list is empty,
*AND lo task is not done processing the band, AND old list
*is not empty, AND current old list z-Plane does not match
*previous z-Plane (FROM eomSwitchToOldList).

*z-Plane will not allow the switch.
GOTO[eomWaitOnLoTask];

eomNewListNotEmpty:
*EVEN BRANCH

*1a.)Processing new list upon entry, AND new list is not empty
*(FROM eomProcessNewList).

*1b.)Processing old list upon entry, AND old list is empty,
*AND new list is not empty (FROM eomProcessNewList).

*2.)Processing old list upon entry, AND old list is not empty,
*AND old list z-Plane > previous z-Plane, AND new list is not
*empty, AND old list z-Plane > new list z-Plane. The previous
*z-Plane value has been adjusted to the current value. (FROM
*eomOldToNewSwitch).

*the new list has blocks in it. Check for a Z-plane switch.
*first, bump the offset. Cannot save the bumpped offset until we are sure
*which list the block is really going to be sent from.
T ← (eomNewListRead) + (20C);
PFETCH2[eomParameterTransferBaseA,eomParmBlock0], CALL[eomHiTaskSwitch];
*extract the z-Plane info
T ← LDF[eomBlockPointer,14,4];
LU ← (eomPreviousZPlane) - T;
DBLGOTO[eomNewListTransfer,eomZPlaneSwitch,ALU=0];

eomNewListTransfer:
*EVEN BRANCH

*1a.)Processing new list upon entry, AND new list is not empty
*AND no z-Plane switch since last block (FROM eomNewListNotEmpty).

*1b.)Processing old list upon entry, AND old list is empty,
*AND new list is not empty, AND no z-Plane switch since
*last block (FROM eomNewListNotEmpty).

*1c.)Processing old list upon entry, AND old list is not empty,
*AND old list z-Plane > previous z-Plane, AND new list is not
*empty, AND old list z-Plane > new list z-Plane. The previous
*z-Plane value has been adjusted to the current value. (FROM
*eomNewListNotEmpty).

*2a.)Processing new list upon entry, AND new list is not empty
*AND there is a z-Plane switch since last block, AND the
*old list is empty (FROM eomOldListEmpty).

*2b.)Processing old list upon entry, AND old list is empty,
*AND new list is not empty, AND there is a z-Plane switch
*since last block, AND [REDUNDANT TEST - - the old list is
*empty] (FROM eomOldListEmpty).

*3.)Processing new list upon entry, AND new list is not empty
*AND there is a z-Plane switch since last block, AND the
*old list is not empty, AND the new list z-Plane value is
*<= the old list z-Plane value (FROM eomNoNewToOldSwitch).

*OK to send the block.
eomNewListRead ← T ← (eomNewListRead) + (20C);*reload the offset
IOFETCH16[eomParameterTransferBaseA,ADD[hiTaskIOoffset,inputParameterBuffer]];
*Log the removal of the block from the new list.
eomNewBlocksFull ← (eomNewBlocksFull) - 1, GOTO[eomHiTaskSleep];

eomZPlaneSwitch:
*ODD BRANCH

*1a.)Processing new list upon entry, AND new list is not empty
*AND there is a z-Plane switch since last block (FROM
*eomNewListNotEmpty).

*1b.)Processing old list upon entry, AND old list is empty,
*AND new list is not empty, AND there is a z-Plane switch
*since last block (FROM eomNewListNotEmpty).

*there has been a z-Plane switch, must check the old list.
*First, check whether the old list is empty
DBLGOTO[eomOldListEmpty,eomOldListNotEmpty,R<0], LU ← eomOldBlocksFull;

eomOldListEmpty:
*ODD BRANCH

*1a.)Processing new list upon entry, AND new list is not empty
*AND there is a z-Plane switch since last block, AND the
*old list is empty (FROM eomZPlaneSwitch).

*1b.)Processing old list upon entry, AND old list is empty,
*AND new list is not empty, AND there is a z-Plane switch
*since last block, AND [REDUNDANT TEST - - the old list is
*empty] (FROM eomZPlaneSwitch).

*If the old list is empty, the transfer must come from the new list,
*regardless of a z-Plane switch. T contains the current z-Plane value,
*so stash this changed value as the new previous value.
eomPreviousZPlane ← T, GOTO[eomNewListTransfer];

eomOldListNotEmpty:
*EVEN BRANCH

*1a.)Processing new list upon entry, AND new list is not empty
*AND there is a z-Plane switch since last block, AND the
*old list is not empty (FROM eomZPlaneSwitch).

*1b.)ABSURD CASE - - CAN NEVER OCCUR
*Processing old list upon entry, AND old list is empty,
*AND new list is not empty, AND there is a z-Plane switch
*since last block, AND {the old list is not empty} (FROM
*eomZPlaneSwitch).

*fetch the z-Plane info from the next block in the old list.
T ← (eomOldListRead) + (21C);
PFETCH1[eomParameterTransferBaseA,eomAlternateZPlane], CALL[eomExtractZPlane];
*LU = 0 implies the z-Planes are the same, so don’t change lists
*LU < 0 implies new list z-Plane > old list z-Plane, so do change lists
*LU > 0 implies new list z-Plane < old list z-Plane, so don’t change lists
LU ← (LDF[eomAlternateZPlane,14,4]) - T;
*Perform the branch and save away the eomPreviousZPlane value;
DBLGOTO[eomNoNewToOldSwitch,eomNewToOldSwitch,ALU>=0], T ← LDF[eomAlternateZPlane,14,4];

eomNoNewToOldSwitch:
*EVEN BRANCH

*1.)Processing new list upon entry, AND new list is not empty
*AND there is a z-Plane switch since last block, AND the
*old list is not empty, AND the new list z-Plane value is
*<= the old list z-Plane value (FROM eomOldListNotEmpty).

*Stash the new z-Plane value as the previous value.
T ← LDF[eomBlockPointer,14,4];
eomPreviousZPlane ← T, GOTO[eomNewListTransfer];

eomNewToOldSwitch:
*ODD BRANCH

*1.)Processing new list upon entry, AND new list is not empty
*AND there is a z-Plane switch since last block, AND the
*old list is not empty, AND the new list z-Plane value is
*> the old list z-Plane value (FROM eomOldListNotEmpty).

*Stash the eomPreviousZPlane value. This need only be done when a
*change occurs.
eomPreviousZPlane ← T;
*Perform the z-Plane switch. It is necessary to refetch the first 2 words of
*this parameter block. The zPlane check made is superfluous, but easier than
*trying to avoid it.
eomState ← (eomState) AND NOT (workingFromNewList), GOTO[eomOldListNotEmptyA];

eomProcessOldList:
*EVEN BRANCH

*1.)Processing old list upon entry.

*check if the old list has any blocks in it
DBLGOTO[eomOldListEmptyA,eomOldListNotEmptyA,R<0], LU ← eomOldBlocksFull;

eomOldListEmptyA:
*ODD BRANCH

*1.)Processing old list upon entry, AND old list is empty
*(FROM eomProcessOldList).

*if the old list is empty, all that can be done is to switch back to the
*new list and continue processing
eomState ← (eomState) OR (workingFromNewList), CALL[eomHiTaskSwitch];
GOTO[eomProcessNewList];

eomOldListNotEmptyA:
*EVEN BRANCH

*1.)Processing new list upon entry, AND new list is not empty
*AND there is a z-Plane switch since last block, AND the
*old list is not empty, AND the new list z-Plane value is
*> the old list z-Plane value (FROM eomNewToOldSwitch).

*2.)Processing old list upon entry, AND old list is not empty
*(FROM eomProcessOldList).

*if the old list is not empty, we must check for a z-Plane change
T ← (eomOldListRead) + (20C);
PFETCH2[eomParameterTransferBaseA,eomParmBlock0], CALL[eomHiTaskSwitch];
*extract the z-Plane info
T ← LDF[eomBlockPointer,14,4];
LU ← (eomPreviousZPlane) - T;
DBLGOTO[eomOldListTransfer,eomZPlaneSwitchA,ALU=0];

eomOldListTransfer:
*EVEN BRANCH

*1.)Processing new list upon entry, AND new list is empty,
*AND lo task is done, AND old list is not empty. (FROM
*eomBandNotFinished)

*2.)Processing new list upon entry, AND new list is empty,
*AND lo task is not done processing the band, AND old list
*is not empty, AND current old list z-Plane matches previous
*z-Plane (FROM eomSwitchList).


*3a.)Processing new list upon entry, AND new list is not empty
*AND there is a z-Plane switch since last block, AND the
*old list is not empty, AND the new list z-Plane value is
*> the old list z-Plane value, AND [REDUNDANT CHECK - - the
*old list z-Plane value is <= the new list z-Plane value]
*(FROM eomOldListNotEmptyA).

*3b.)Processing old list upon entry, AND old list is not empty,
*AND old list z-Plane = previous z-Plane (FROM eomOldListNotEmptyA).

*4.)Processing old list upon entry, AND old list is not empty,
*AND old list z-Plane > previous z-Plane, AND new list is
*empty, AND the lo task is done (FROM eomLoTaskDoneA).

*5.)Processing old list upon entry, AND old list is not empty,
*AND old list z-Plane > previous z-Plane, AND new list is not
*empty, AND old list z-Plane <= new list z-Plane (FROM
*eomNoOldToNewSwitch).

*OK to send the block.
*We must check to see if the block being sent is an image, and if so, whether
*the block pointer in the parameter block requires adjustment due to an
*imaginal input ring wrap during the last band. If an adjustment is required,
*do it.
LU ← LDF[eomParmBlock0,15,1];*pick up the font/image bit.
*If the block is not for an image, branch. Also, set up T in case the
*branch is not taken.
GOTO[eomNoImageWrap,ALU=0], T ← (eomParmBlock0) AND (7C);
*
*The ring wrap computation must be done here as a part of the parameter block
*transfer because the block pointer must be adjusted (unwrapped) before the
*parameter block is sent to the hardware.
*
*Construct a pointer to the terminal count for this image in the CSB.
*This automatically comes out in the high CSB because of the 1 bit in position
*15B which indicates image.
eomTemp ← T, CALL[eomHiTaskSwitch];
eomTemp ← (LSH[eomTemp,2]);
eomTemp ← T ← (eomTemp) + (2C);
*Fetch the terminal count into eomDispField.
PFETCH1[eomCsbBaseLo,eomDispField];
*Now fetch the microcode transfer offset (eomImageXferOffset) from location
*1,3,5, or 7 of the junk area depending upon which image.
T ← (7C);
T ← (RSH[eomTemp,1]) AND T, TASK;
PFETCH1[eomParameterTransferBaseA,eomImageXferOffset];
*Load T with the terminal count (which is one block less than the actual size of
*the ring. Add one block to this value.
T ← (eomDispField) + 1;
*EomBlockPointer contains words, not blocks, and must be shifted.
T ← (RSH[eomBlockPointer,4]) - T;
*If the result is negative, the block pointer had not really gone beyond
*the end of the ring buffer. If the branch is not taken, the result was
*positive and the block pointer needs unwrapping. Stash T in eomDispField
*so it can be shifted if the branch is not taken.
GOTO[eomHardwarePointerInBounds, ALU<0], eomTemp1 ← T;
eomProcessWrap:
*The result was positive; the block pointer needs unwrapping.
*Shift the modified block pointer into the high 12 bits.
T ← LSH[eomTemp1,4];
*Get the Z-Plane value and OR it into its slot in the word.
eomBlockPointer ← (LDF[eomBlockPointer,14,4]) OR T;
T ← (eomOldListRead) + (20C);
*Store the first 2 words of the parameter block to effect the modification of
*the block pointer.
PSTORE2[eomParameterTransferBaseA,eomParmBlock0], GOTO[eomNoImageWrap];
eomHardwarePointerInBounds:
*The hardware pointer was within the bounds of the data ring. It is still
*possible that the hardware pointer wrapped. Check this by looking at the
*separation between the hardware pointer and the saved value of the microcode
*pointer.
*
*Get the block pointer down to a block value.
T ← RSH[eomBlockPointer,4];
*Convert the microcode pointer to a block value and obtain the difference
*between microcode pointer and hardware pointer.
eomImageXferOffset ← (RSH[eomImageXferOffset,4]) - T;
*If the result is less than 0, the hardware pointer is within the ring
*(from the preceeding test) and above the microcode pointer. This is legal,
*indicating that the microcode pointer wrapped but the hardware pointer has
*not.
GOTO[eomNotReallyWrapped, ALU<0], LU ← (eomImageXferOffset) - (22C);
*The result of the preceeding ALU operation will be greater than zero only if
*the separation of the microcode and hardware pointers is 16 blocks or greater.
*If this occurs, the hardware pointer has wrapped and must be adjusted.
GOTO[eomNotReallyWrappedA, ALU<0], T ← (eomDispField) OR (170000C);
*This instruction loads T with the count of blocks between the top end of the
*ring and the megabit boundary. This value must be added to the hardware value
*to achieve a correct pointer.
T ← (ZERO) OR NOT T;
T ← (RSH[eomBlockPointer,4]) + T, CALL[eomHiTaskSwitch];
*Load eomDispField with the correct block value of the pointer, and go process
*the actual wrap adjustment and storage of the modified value.
eomTemp1 ← T, GOTO[eomProcessWrap];
eomNotReallyWrapped:
GOTO[eomNoImageWrap];
eomNotReallyWrappedA:
GOTO[eomNoImageWrap];
eomNoImageWrap:
*This is the entry point from eomCIPBRequest - - IOATTEN branch 4.
eomOldListRead ← T ← (eomOldListRead) + (20C);*reload the offset
eomNoImageWrapA:
*log the removal of the block from the old list
eomOldBlocksFull ← (eomOldBlocksFull) - 1, CALL[eomHiTaskSwitch];
*CANNOT task out after this IOFETCH because the IOSTROBE must
*arrive at the hardware before the transfer completes.
IOFETCH16[eomParameterTransferBaseA,ADD[hiTaskIOoffset,inputParameterBuffer]];
*check for an old list ring wrap
T ← (eomFragments) - (20C);
LU ← (eomOldListRead) - T;
GOTO[eomOldListTransferSleep,ALU<0], T ← (eomState) AND (newListSizeMask);
*reset the read pointer if there is a wrap.
eomOldListRead ← T, GOTO[eomHiTaskSleep];
eomOldListTransferSleep:
GOTO[eomHiTaskSleep];

eomZPlaneSwitchA:
*ODD BRANCH

*1a.)ABSURD CASE - - CAN NEVER OCCUR
*Processing new list upon entry, AND new list is not empty
*AND there is a z-Plane switch since last block, AND the
*old list is not empty, AND the new list z-Plane value is
*> the old list z-Plane value, AND {the old list z-Plane value is >
*the new list z-Plane value} (FROM eomOldListNotEmptyA).

*1b.)Processing old list upon entry, AND old list is not empty,
*AND old list z-Plane > previous z-Plane (FROM eomOldListNotEmptyA).

*there has been a z-Plane switch, must check the new list.
*First, check whether the new list is empty
DBLGOTO[eomNewListEmptyA,eomNewListNotEmptyA,R<0], LU ← eomNewBlocksFull;

eomNewListEmptyA:
*ODD BRANCH

*1.)Processing old list upon entry, AND old list is not empty,
*AND old list z-Plane > previous z-Plane, AND new list is
*empty (FROM eomZPlaneSwitchA).

*if the new list is empty, we must check to see if the low task is done.
LU ← (eomState) AND (bandDone);
DBLGOTO[eomLoTaskDoneA,eomLoTaskNotDoneA,ALU#0];

eomLoTaskDoneA:
*ODD BRANCH

*1.)Processing old list upon entry, AND old list is not empty,
*AND old list z-Plane > previous z-Plane, AND new list is
*empty, AND the lo task is done (FROM eomNewListEmptyA).

*The low task is done. The transfer must come from the old list. T
*contains the new z-Plane value. Stash this as the new previous value.
eomPreviousZPlane ← T, GOTO[eomOldListTransfer];

eomLoTaskNotDoneA:
*EVEN BRANCH

*1.)Processing old list upon entry, AND old list is not empty,
*AND old list z-Plane > previous z-Plane, AND new list is
*empty, AND lo task is not done (FROM eomNewListEmptyA).

*the low task is not done. The transfer cannot proceed until there is
*a block in the new list to compare z-Planes with the current old list
*entry.
GOTO[eomWaitOnLoTask];

eomNewListNotEmptyA:
*EVEN BRANCH

*1.)Processing old list upon entry, AND old list is not empty,
*AND old list z-Plane > previous z-Plane, AND new list is not
*empty (FROM eomZPlaneSwitchA).

*fetch the z-Plane info from the next block in the new list.
T ← (eomNewListRead) + (21C);
PFETCH1[eomParameterTransferBaseA,eomAlternateZPlane], CALL[eomExtractZPlane];
*LU = 0 implies the z-Planes are the same, so don’t change lists
*LU < 0 implies old list z-Plane > new list z-Plane, so do change lists
*LU > 0 implies old list z-Plane < new list z-Plane, so don’t change lists
LU ← (LDF[eomAlternateZPlane,14,4]) - T;
*Pick up the alternate z-Plane value for use in the old to new switch branch.
DBLGOTO[eomNoOldToNewSwitch,eomOldToNewSwitch,ALU>=0], T ← LDF[eomAlternateZPlane,14,4];

eomNoOldToNewSwitch:
*EVEN BRANCH

*1.)Processing old list upon entry, AND old list is not empty,
*AND old list z-Plane > previous z-Plane, AND new list is not
*empty, AND old list z-Plane <= new list z-Plane (FROM
*eomNewListNotEmptyA).

*Stash the new z-Plane value as the previous value.
T ← LDF[eomBlockPointer,14,4];
eomPreviousZPlane ← T, GOTO[eomOldListTransfer];

eomOldToNewSwitch:
*ODD BRANCH

*1.)Processing old list upon entry, AND old list is not empty,
*AND old list z-Plane > previous z-Plane, AND new list is not
*empty, AND old list z-Plane > new list z-Plane (FROM
*eomNewListNotEmptyA).

*Stash the eomPreviousZPlane value. This need only be done when a
*change occurs.
eomPreviousZPlane ← T;
*Perform the z-Plane switch.
*We can branch into the middle of the new list processing because we know
*that the new list is not empty, and it is the lowest current z-Plane number.
*The first two words of the parameter block must be acquired however, so
*go to the new list processing which does the fetch. The z-Plane check there
*will show a match since we have modified the previous value here.
eomState ← (eomState) OR (workingFromNewList), GOTO[eomNewListNotEmpty];

%
********************
SPECIAL TRANSFER BRANCH 4
%
********************

eomCIPBRequest:
*Continue state restore option.
*This option must always come out of the old list, and the z-plane information
*doesn’t exist. In addition, unless something is badly broken, the old list
*will always have enough data to satisfy these requests.
GOTO[eomNoImageWrap], AT[hiTaskWakeupDispatch,10];

%
********************
SPECIAL TRANSFER BRANCH 5
This wakeup indicates that the EOM is ready with a band of data and the IOT can
request it any time.
%
********************

eomBBReadyRequest:
T ← (firstBandReady), CALL[eomHiTaskSwitch], AT[hiTaskWakeupDispatch,12];
GOTO[eomBBBehindRequestPlusTwo];

%
********************
SPECIAL TRANSFER BRANCH 6
This wakeup indicates that the hardware had not processed an end of band character
before the IOT caused a band switch. It means the page is damaged to some degree.
%
********************

eomBBBehindRequest:
T ← (bandBufferBehind), CALL[eomHiTaskSwitch], AT[hiTaskWakeupDispatch,14];
*This NOP is necessary to prevent the call on eomHiTaskModifyWakeupReasons
*from trying to return to hiTaskWakeupDispatch + 16, which is not an
*available location since eomBitMapRequest is already there.
NOP;
eomBBBehindRequestPlusTwo:
CALL[eomHiTaskModifyWakeupReasons];
GOTO[eomHiTaskSleep];

%
********************
SPECIAL TRANSFER BRANCH 7
This wakeup requests a transfer of bitmap data from the EOM back to processor
main memory.
%
********************

eomBitMapRequest:
*it is assumed that there will never be any input data transfers during
*a bitmap output sequence. This means that the same quadblock of ring
*information can be used for transfers going out.
*If it is not the first transfer, do not initialize the stuff.
*Set the branch flag to indicate that the bitmap transfer
*structure has been initialized.
LU ← (eomState) AND (firstParametricReturnBlock), AT[hiTaskWakeupDispatch,16];
GOTO[eomNotFirstBitmap, ALU#0], eomState ← (eomState) OR
(firstParametricReturnBlock);
*Fetch the output buffer information.
PFETCH4[eomCsbBaseLo,eomDataTransferBaseA,outputBufferOffset];
CALL[eomHiTaskSwitch];
*Compute the total number of blocks which will be transferred.
*Get the number of blocks of data per band.
PFETCH1[eomParameterTransferBaseA,eomParmBlock0,parametricBlockCount];

eomNotFirstBitmap:
*NOTE-- IN THIS MODE, eomRingChar CONTAINS THE TRANSFER OFFSET
eomRingChar ← T ← (eomRingChar) + (20C), CALL[eomHiTaskSwitch];
*Check for a ring wrap
LU ← (LSH[eomTerminalBlockAddress,4]) - T;
GOTO[eomNoOutputRingWrap,ALU#0];
*Ring has wrapped, reset the transfer offset.
eomRingChar ← T ← ZERO;

eomNoOutputRingWrap:
*Decrement the count of blocks of data to be transferred.
GOTO[eomThisIsFinalBlock,R<0], eomParmBlock0 ← (eomParmBlock0) - 1;

eomNoOutputRingWrapA:
IOSTORE16[eomDataTransferBaseA,ADD[hiTaskIOoffset,outputChannelBuffer]],
GOTO[eomHiTaskSleep];
eomThisIsFinalBlock:
*The ring data must be saved away now.
PSTORE4[eomCsbBaseLo,eomDataTransferBaseA,outputBufferOffset], CALL[eomHiTaskSwitch];
*Indicate band all returned in the CSB wakeup reasons.
T ← (bandAllReturned), CALL[eomHiTaskModifyWakeupReasons];
T ← eomRingChar, GOTO[eomNoOutputRingWrapA];


********************

*HIGH TASK SUBROUTINES

********************

% SUBROUTINE eomSelectWakeupReasonSub ********************
This subroutine sets up the proper wakeup reason bit in T for the image currently
being processed, then returns. The value in T should not be used on the first
instruction after restarting, due to possible interlock problems.
%

eomSelectWakeupReasonSub:
*Store the image ring quad block for the current image in the hi Csb. This
*is done following an update of the number of sectors of data available.
PSTORE4[eomCsbBaseLo,eomDataTransferBaseA], DISP[eomSelectWakeupReason];
eomSelectWakeupReason:
T ← (image0SectorEmpty), RETURN, AT[hiTaskWakeupReasonDisp];
T ← (image1SectorEmpty), RETURN, AT[hiTaskWakeupReasonDisp,1];
T ← (image2SectorEmpty), RETURN, AT[hiTaskWakeupReasonDisp,2];
T ← (image3SectorEmpty), RETURN, AT[hiTaskWakeupReasonDisp,3];

% SUBROUTINE eomInitBlocksRemaining ********************
This subroutine initializes the blocks remaining in sector value, and modifies the
sectors full (empty) value in the resident ring quad block.
%

eomInitBlocksRemaining:
*Reset the eomBlocksRemaining value to indicate a full sector.
*The CSB contains the actual number of blocks per sector so we must
*subtract 2 to initialize properly.
T ← (LDF[eomRingChar,blocksPerSectorStartBit,blocksPerSectorFieldWidth]);
eomBlocksRemaining ← T;

eomInitBlocksRemainingA:
*Shift the sectors empty value to the high byte
T ← LSH[eomSectorsFilled,blocksPerSectorFieldWidth];
*merge into the proper word in the quad block.
eomRingChar ← (LDF[eomRingChar,blocksPerSectorStartBit,blocksPerSectorFieldWidth]) OR T,
RETURN;


% SUBROUTINE ExtractBlockPointer ********************
This subroutine extracts the block pointer information from the second word of
the most recently sent parameter block. This result is returned in T.
% ********************

eomExtractBlockPointer:
*Mask out the z-plane information.
T ← (eomBlockPointer) AND NOT (17C), RETURN;


% SUBROUTINE PauseHiTask (also DropDead) ********************
This subroutine pauses the high task. Optionally, by entering at DropDead, the
high task status bit which is normally set to indicate the pause, can be
left in the run position. This will prevent the low task from restarting
the high task.
% ********************

eomPauseHiTask:
*indicate pause in status
eomState ← (eomState) AND NOT (hiTaskRunning);
eomDropDead:
INPUT[eomTemp,hiTaskPause];
LU ← eomTemp, RETURN;


% SUBROUTINE eomHiTaskModifyWakeupReasons ********************
This subroutine gets the current wakeup reasons word from the CSB and OR’s into it the
value in T, then puts it back.
% ********************

eomHiTaskModifyWakeupReasons:
*Fetch the wakeup mask and wakeup reasons into eomTemp and eomTemp1
*respectively.
PFETCH2[eomCsbBaseLo,eomTemp,wakeupMaskOffset];
*Use eomImageXferOffset as a temporary for the register
*address 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;
T ← (SStkP&NStkP) xor (377C);*Save StkP in T.
*Entry here from EOMLoTask.Mc
eomLoEntryModifyWakeupReasons:
*Put IP[NWW] in StkP and save StkP in eomImageXferOffset.
StkP ← eomImageXferOffset, eomImageXferOffset ← T, NoRegILockOK;
*Save the modified wakeup reason back into the CSB.
PStore1[eomCsbBaseLo,eomTemp1,wakeupReasonOffset];
*Put the naked notify mask into T.
T ← eomTemp;
Stack ← (Stack) or T, Skip[ALU#0];
LU ← StkP ← eomImageXferOffset, Return;
Stack&-1;
T ← Stack ← (Stack) or (IntPendingBit);
*Restore StkP to its original value and return.
LU ← StkP ← eomImageXferOffset, RS232 ← T, Return;

% SUBROUTINE eomExtractZPlane ********************
This subroutine returns the z-Plane value in T.
% ********************

eomExtractZPlane:
T ← LdF[eomBlockPointer,14,4];
eomHiTaskSwitch:
Return;


END[EOMHiTask];