RavenDriverImpl.mesa
Copyright Ó 1987 by Xerox Corporation. All rights reserved.
Tim Diebert: April 27, 1987 3:03:16 pm PDT
DIRECTORY
ImagerSample USING [RasterSampleMap],
LSEPFace USING [BandBufferCount, Index],
PrincOps USING [PageCount, wordsPerPage],
RavenDriver USING [PaperTray],
VM USING [Interval];
RavenDriverImpl: CEDAR MONITOR
IMPORTS ImportsList
EXPORTS ExportsList
~ BEGIN
TYPEs:
Band: TYPE = ARRAY [0 .. bandBufferSize * PrincOps.wordsPerPage) OF WORD;
Constants:
bandBufferSize: PrincOps.PageCount = 16; -- From BandBLT
maxBands: CARDINAL = 160; -- 8.5" * 300BitsPer" / 16BitsPerWord
activeLength: (0..PrincOps.wordsPerPage] ← ((11*300)+15)/16;
bandBufferPadding: PrincOps.PageCount = 1; -- to allow for overwrite when copying due to offset of short scan lines
Variables:
paperTrayLast: RavenControl.PaperTray ← bottom; -- last tray fed from
abortImaging: BOOLEANFALSE;
lastBand: BOOLEAN;
imagingActive: BOOLEANFALSE;
loopbackMode: BOOLEANFALSE; -- server Loop Back diagnostic test
band, bandFirst, bandLast: LSEPFace.Index;
bandBufferCount: LSEPFace.BandBufferCount;
bandLowCore: VM.Interval;
wordsPerScanLine: (0..PrincOps.wordsPerPage]; -- current words per scan line
pageBufferIndex: CARDINAL; -- index to current band in page buffer
pageBufferIndexLast: CARDINAL; -- last meaningful band in page buffer
pageBufferBandBuffer: LONG POINTER; -- band buffer virtual address
sampleMap: ImagerSample.RasterSampleMap;
controlCondition, imageCondition, statusCondition: CONDITION;
newStatus: PUBLIC CONDITION;
commandQ: Queue.Handle;
Public Procedures:
Initialize: PUBLIC SAFE PROCEDURE [bufferSize: PrincOps.PageCount] = TRUSTED BEGIN
controlMask, imageMask, statusMask: WORD;
[controlCondition, controlMask] ← PrincOpsUtils.AllocateNakedCondition[];
[imageCondition, imageMask] ← PrincOpsUtils.AllocateNakedCondition[];
[statusCondition, statusMask] ← PrincOpsUtils.AllocateNakedCondition[];
Process.Detach[FORK LSEPFace.InitializeCleanUp]; -- start the cleanup proc
LSEPFace.SetInterruptMasks[control: controlMask, status: statusMask, data: imageMask];
set up band buffers, etc.
bandBufferCount ← bufferSize / bandBufferSize; -- the number of bands in low core
bandLowCore ← VM.Allocate[bufferSize + bandBufferPadding];
VMSideDoor.AssignSpecialRealMemory[bandLowCore]; -- Move to low core and Pin
LSEPFace.AllocateBands[bandVirtualPageNumber: bandLowCore.page,
nBands: bandBufferCount, sizeEachBand: bandBufferSize, slop: 1];
sampleMap ← MakePrinterSampleMap[]; -- create the full page buffer SampleMap
commandQ ← NEW[Queue.QueueRep];
Queue.Initialize[commandQ];
END; -- Initialize
SendEngineCommand: PUBLIC PROCEDURE [cmd: RavenCodes.PrinterCommand] =
{Queue.Push[commandQ, cmd]};
HandleCommand: PROCEDURE = BEGIN
Pops a command and acts on it, and notifies WatchCommandStatus that command has been sent if a response is expected.
cmd: RavenCodes.PrinterCommand;
Process.SetPriority[Process.priorityRealTime];
DO -- forever
cmd ← LOOPHOLE[Queue.Pop[commandQ]]; -- waits till queue is non-empty
IF loopbackMode
THEN NULL -- Synchronizer.Notify[@commandSent]
ELSE BEGIN
SELECT cmd FROM
beepShort, beepLong => NULL; -- no response
goToSleep => BEGIN
Queue.Push[@consoleQ, RavenCodes.PrinterStatus.key1];
Queue.Push[@consoleQ, RavenCodes.PrinterStatus.key2];
Queue.Push[@consoleQ, RavenCodes.PrinterStatus.keyTest];
SetEngineStatus[lowPowerMode]; -- no response, post new status
END;
ENDCASE => NULL;
SELECT cmd FROM
solicitStatus => statusQuery ← TRUE;
feed, feedOffset => paperTrayLast ← bottom;
feedTop, feedTopOffset => paperTrayLast ← top;
solicitPaperSize => paperSizeInternal ← LOOPHOLE[0]; -- set paper size to unknown
ENDCASE => NULL;
END;
LSEPFace.PutCommand[LOOPHOLE[cmd]]; -- send the command
Interrupt.Wait[controlInt]; -- wait for IOP to send
IF NOT loopbackMode THEN Process.Pause[Process.MsecToTicks[100]]; -- let IOT settle
ENDLOOP; -- forever
END; -- HandleCommand
HandleStatus: PROCEDURE = BEGIN -- wait for status to be set and act accordingly
sts: RavenCodes.PrinterStatus;
loopbackPlug: BOOLEANFALSE; -- to avoid trashing loopback test
Process.SetPriority[Process.priorityRealTime];
DO -- forever
Interrupt.Wait[statusInt]; -- wait for status from IOT
sts ← LOOPHOLE[LSEPFace.GetStatus[]]; -- get received status
IF loopbackMode THEN BEGIN
Synchronizer.Notify[statusReceived]; -- something was received
Queue.Push[@turnaroundQ, sts];
LOOP;
END;
SELECT sts FROM
noStatus, statusError, statusOverRun => -- not legit status
IF statusInternal = lowPowerMode THEN LOOP; -- ignore completely if printer is off
LOOPHOLE[RavenCodes.PrinterCommand[solicitStatus]] => loopbackPlug ← TRUE;
IN [key0..LOOPHOLE[RavenCodes.PrinterCommand[displayBlank]]] => NULL; -- not responses to commands
ENDCASE => Synchronizer.Notify[statusReceived]; -- WatchCommandStatus waiting on it
IF NOT statusQuery THEN -- events are only if we didn't ask
SELECT sts FROM
pageSync => BEGIN -- handle this status first for better performance
Synchronizer.Broadcast[pageSync];
BroadcastEngineEvent[feeding]; -- also used as the feeding status
IF imagingActive AND transferStatus = ready THEN BEGIN -- band overrun, still imaging
BroadcastEngineEvent[pageSyncMiss];
Queue.Push[@logQ, RavenControl.LogItem[plateStatus[pageSyncMiss]]];
END;
END;
standBy => BEGIN -- printer is okay or after last page
BroadcastEngineEvent[idle];
IF engineState = error THEN -- state was error, now okay
SendEngineCommand[solicitPaperSize]; -- get paper size
engineState ← okay; -- set to error in BroadcastEngineEvent
END;
readyToFeed => BroadcastEngineEvent[readyToFeed];
pageAtOutputTray => BroadcastEngineEvent[pageDelivery];
feederFault => BEGIN
IF imagingActive THEN abortImaging ← TRUE;
paperTrayOk[paperTrayLast] ← FALSE;
BroadcastEngineEvent[feedError];
END;
fuserCold, goingOffLine, outputTrayFull => BroadcastEngineEvent[softError];
registrationJam, fuserJam, noExit, interlockOpen, aboutToDozeOff => BEGIN
IF imagingActive THEN abortImaging ← TRUE;
BroadcastEngineEvent[hardError];
END;
feedTraysNotEngaged => BroadcastEngineEvent[softError];
ENDCASE => NULL;
SELECT sts FROM
noStatus, keyOnLine, parityError, unrecognizedCommand, illegalSequence,
LOOPHOLE
[57H], -- B1 online
statusError, statusOverRun => -- read status and try again
SendEngineCommand[solicitStatus];
standBy => BEGIN-- printer is okay or after last page
IF imagingActive THEN BEGIN -- flush required to finish imaging
abortImaging ← TRUE;
flushPrinter ← TRUE;
END;
END;
interlockOpen, feedTraysNotEngaged => paperTrayOk ← ALL[TRUE];
IN [paperSmallSmall..paperLargeLarge] => paperSizeInternal ← sts;
IN [key0..keyOffLine] => IF NOT loopbackPlug THEN Queue.Push[@consoleQ, sts];
ENDCASE => NULL;
log the status
Queue.Push[@logQ, RavenControl.LogItem[printerStatus[sts]]];
SELECT sts FROM
warming, standBy, feederFault, registrationJam, fuserJam, noExit, interlockOpen, fuserCold, feedTraysNotEngaged, tonerLow, goingOffLine, offLine, outputTrayFull, aboutToDozeOff => BEGIN
meaningful engine statuses
loopbackPlug ← FALSE; -- not from loopback plug
IF statusInternal = communicationFault THEN SendEngineCommand[displayBlank];
IF sts = aboutToDozeOff THEN BEGIN -- force engine out of repair mode
Queue.Push[@consoleQ, RavenCodes.PrinterStatus.key1];
Queue.Push[@consoleQ, RavenCodes.PrinterStatus.key2];
Queue.Push[@consoleQ, RavenCodes.PrinterStatus.keyTest];
END; -- ADP AR 4030
SetEngineStatus[
SELECT sts FROM
warming => warming,
standBy => okay,
feederFault => preRegistrationFault,
registrationJam => postRegistrationJam,
fuserJam => preExitJam,
noExit => postExitJam,
interlockOpen => doorOpen,
fuserCold => warming,
feedTraysNotEngaged => traysUnlatched,
tonerLow => tonerLow,
goingOffLine, offLine => offline,
outputTrayFull => outputTrayFull,
aboutToDozeOff => lowPowerMode,
ENDCASE => ERROR];
END;
ENDCASE => NULL;
statusQuery ← FALSE;
ENDLOOP; -- forever
END; -- HandleStatus
END.