LSEPHeadDLion.mesa
Copyright Ó 1981, 1982, 1983, 1985, 1987 by Xerox Corporation. All rights reserved.
Tim Diebert: March 4, 1987 10:49:10 am PST
To do: bury ImageCSB.lineSize into the microcode.
Re-arrrange ImageCSB to make fields the microcode cares about contiguous.
DIRECTORY
BasicTime USING [Pulses, MicrosecondsToPulses],
DeviceCleanup USING [Item, Reason, Await],
DLionInputOutput USING [firstReservedPage, IOPage],
DLionInputOutput USING [
firstReservedPage, IOPage, ioPageRealAddrLow, lsepControlDataOffset,
lsepControlDataMax, lsepControlMaskOffset, lsepControlMaskMax,
lsepImageCSBOffset, lsepImageCSBMax, lsepStatusMaskOffset, lsepStatusMaskMax,
lsepStatusOffset, lsepStatusMax, SetReservedMemoryUse],
Loader USING [MakeProcedureResident, MakeGlobalFrameResident],
LSEPFace,
PrincOps USING [PageCount, PageNumber, wordsPerPage],
PrincOpsUtils USING [BITAND, GetClockPulses],
VM USING [AddressForPageNumber];
LSEPHeadDLion:
PROGRAM
IMPORTS BasicTime, DeviceCleanup, DLionInputOutput, Loader, PrincOpsUtils, VM
EXPORTS LSEPFace =
BEGIN OPEN LSEPFace;
There is a game going on that the relative pointers "work" in relation BOTH to Physical 10000x and some virtual Base addresses.
Index: PUBLIC TYPE = BandRecordBase RELATIVE ORDERED POINTER TO BandRecord;
BandRecordBase: TYPE = LONG BASE POINTER TO RECORD [UNSPECIFIED];
Band: TYPE = BandBufferBase RELATIVE POINTER; -- real AND virtual relative pointer
BandBufferBase: TYPE = LONG BASE POINTER TO RECORD [UNSPECIFIED];
BandRecord:
TYPE =
MACHINE
DEPENDENT
RECORD [
band(0): Band,
next(1): Index,
status(2): INTEGER];
imageLoc:
LONG
POINTER
TO ImageCSB =
LOOPHOLE[DLionInputOutput.IOPage + 20B];
LOOPHOLE[DLionInputOutput.IOPage + DLionInputOutput.lsepImageCSBOffset];
ImageCSB:
TYPE =
MACHINE
DEPENDENT
RECORD [
run(0): Index,
overrun(1): WORD, --zero=> ok, nonzero => overrun
mask(2): CARDINAL, --band empty wakeup mask
bandSize(3): CARDINAL, --number of lines (pages) in band
lastStartedBand(4): Index, --for deviceCleanup to stop printer
lineSize(5): CARDINAL, --constant = 256
tab(6): CARDINAL, --words of pixels to skip before starting scan
scans(7): CARDINAL]; --number of blank lines after page sync
compileCheckLSEPSize: BOOLEAN [TRUE..TRUE] = (DLionInputOutput.lsepImageCSBMax >= (SIZE[BandRecord] * MaxBands + SIZE[ImageCSB]));
firstBandRecord: Index = LOOPHOLE[40000B + 20B + 10B];
firstBandRecord: Index = LOOPHOLE[DLionInputOutput.ioPageRealAddrLow + 20B + SIZE[ImageCSB], BandRecordBase RELATIVE ORDERED POINTER TO BandRecord];
LOOPHOLE[DLionInputOutput.ioPageRealAddrLow + DLionInputOutput.lsepImageCSBOffset + SIZE[ImageCSB]];
bandRecordLimit: Index = firstBandRecord + MaxBands * SIZE[BandRecord];
bandRecordBase: BandRecordBase =
LOOPHOLE[imageLoc + SIZE[ImageCSB] - LOOPHOLE[firstBandRecord, CARDINAL]];
controlMaskLoc:
LONG
POINTER
TO ControlMask =
LOOPHOLE[DLionInputOutput.IOPage + 61B];
LOOPHOLE[DLionInputOutput.IOPage + DLionInputOutput.lsepControlMaskOffset];
ControlMask: TYPE = WORD;
compileCheckControlMaskSize: BOOLEAN [TRUE..TRUE] = (DLionInputOutput.lsepControlMaskMax >= SIZE[ControlMask]);
controlDataLoc:
LONG
POINTER
TO ControlData =
LOOPHOLE[DLionInputOutput.IOPage + 62B];
LOOPHOLE[DLionInputOutput.IOPage + DLionInputOutput.lsepControlDataOffset];
ControlData: TYPE = WORD;
compileCheckControlDataSize: BOOLEAN [TRUE..TRUE] =
(DLionInputOutput.lsepControlDataMax >= SIZE[ControlData]);
statusMaskLoc:
LONG
POINTER
TO StatusMask =
LOOPHOLE[DLionInputOutput.IOPage + 65B];
LOOPHOLE[DLionInputOutput.IOPage + DLionInputOutput.lsepStatusMaskOffset];
compileCheckStatusMaskSize: BOOLEAN [TRUE..TRUE] =
(DLionInputOutput.lsepStatusMaskMax >= SIZE[StatusMask]);
statusLoc:
LONG
POINTER
TO
BYTE =
LOOPHOLE[DLionInputOutput.IOPage + 66B];
LOOPHOLE[DLionInputOutput.IOPage + DLionInputOutput.lsepStatusOffset];
compileCheckStatusSize: BOOLEAN [TRUE..TRUE] =
(DLionInputOutput.lsepStatusMax >= SIZE[BYTE]);
pagesCurrentlyInBands: PrincOps.PageCount ← 0;
bandBufferBase: BandBufferBase;
bandBufferBasePage: PrincOps.PageNumber;
nullIndex: Index = LOOPHOLE[0];
IthIndex:
PROC [i:
CARDINAL [0..MaxBands)]
RETURNS [Index] =
INLINE
BEGIN RETURN[firstBandRecord + (i * SIZE[BandRecord])]; END;
AllocateBands:
PUBLIC
PROC [bandVirtualPageNumber: PrincOps.PageNumber,
nBands: BandBufferCount, sizeEachBand: PrincOps.PageCount,
slop: PrincOps.PageCount] =
BEGIN
bandBufferBase ← VM.AddressForPageNumber[bandVirtualPageNumber - DLionInputOutput.firstReservedPage];
bandBufferBasePage ← bandVirtualPageNumber;
pagesCurrentlyInBands ← sizeEachBand * nBands + slop;
DLionInputOutput.SetReservedMemoryUse[Raven, pagesCurrentlyInBands];
FOR i: PrincOps.PageCount
IN [0..pagesCurrentlyInBands)
DO
-- Clear Memory
PageMap.SetMapFlags[
virtual: bandVirtualPageNumber + i,
real: DLionInputOutput.firstReservedPage + i, flags: PageMap.flagsClean];
LOOPHOLE[VM.AddressForPageNumber[bandVirtualPageNumber + i],
LONG POINTER TO ARRAY [0..PrincOps.wordsPerPage) OF WORD]^ ← ALL[0];
IF bandVirtualPageNumber + i # DLionInputOutput.firstReservedPage + i THEN ERROR;
ENDLOOP;
FOR i:
CARDINAL
IN [0..nBands)
DO
bandRecordBase[IthIndex[i]] ← [
band:
LOOPHOLE[(DLionInputOutput.firstReservedPage + i *
CARDINAL[sizeEachBand])
* PrincOps.wordsPerPage], next: IthIndex[(i + 1) MOD nBands],
status: 0];
ENDLOOP;
imageLoc.bandSize ← CARDINAL[sizeEachBand];
imageLoc.lastStartedBand ← nullIndex;
imageLoc.lineSize ← PrincOps.wordsPerPage;
END;
DeallocateBands:
PUBLIC
PROC =
BEGIN
imageLoc.lastStartedBand ← nullIndex;
FOR i: PrincOps.PageCount IN [0..pagesCurrentlyInBands) DO
PageMap.SetMapFlags[
virtual: bandBufferBasePage + i, real: 0, flags: PageMap.flagsVacant]
ENDLOOP;
pagesCurrentlyInBands ← 0;
DLionInputOutput.SetReservedMemoryUse[notBusy];
END;
SetInterruptMasks:
PUBLIC
PROC [control, status, data:
WORD] =
BEGIN
controlMaskLoc^ ← control;
statusMaskLoc^ ← status;
imageLoc.mask ← data;
END;
InitializeCleanUp:
PUBLIC
PROC =
BEGIN
item: DeviceCleanup.Item;
saveCSB: ImageCSB;
maxWaitTime: LONG CARDINAL = LONG[27500] * (2 * MaxBands);
waitTime: BasicTime.Pulses = BasicTime.MicrosecondsToPulses[maxWaitTime];
DO
reason: DeviceCleanup.Reason = DeviceCleanup.Await[@item];
SELECT reason
FROM
turnOff =>
BEGIN
then: BasicTime.Pulses = PrincOpsUtils.GetClockPulses[];
IF imageLoc.lastStartedBand # nullIndex
THEN
WHILE (PrincOpsUtils.GetClockPulses[] - then) < waitTime
AND bandRecordBase[imageLoc.lastStartedBand].status # 0 DO ENDLOOP;
saveCSB ← imageLoc^;
END;
turnOn =>
BEGIN
-- restore csb; client will have to redo page.
saveCSB.lastStartedBand ← nullIndex;
imageLoc^ ← saveCSB;
END;
disconnect => {};
FOR i: LONG CARDINAL IN [0..pagesCurrentlyInBands) DO
PageMap.SetMapFlags[
virtual: bandBufferBasePage + i, real: 0,
flags: PageMap.flagsVacant];
ENDLOOP;
ENDCASE;
ENDLOOP;
END;
SetScanLineLength:
PUBLIC
PROC [activeWordsEachScanLine: (0..PrincOps.wordsPerPage]] =
BEGIN
offset: [0..PrincOps.wordsPerPage) = PrincOps.wordsPerPage - activeWordsEachScanLine;
FOR i: Index ← firstBandRecord, i +
SIZE[BandRecord]
WHILE i < bandRecordLimit
DO
pageOffset: TYPE = MACHINE DEPENDENT RECORD [page(0:0..7): [0..377B), offset(0:8..15): [0..377B)];
LOOPHOLE[bandRecordBase[i].band, pageOffset].offset ← offset;
ENDLOOP;
END;
SetPageOffsets:
PUBLIC
PROC [wordsFast:
CARDINAL, linesSlow:
CARDINAL] =
BEGIN imageLoc.tab ← wordsFast; imageLoc.scans ← linesSlow; END;
ResetBands:
PUBLIC
PROC
RETURNS [Index,
LONG
POINTER] =
BEGIN
imageLoc.lastStartedBand ← nullIndex;
FOR i: Index ← firstBandRecord, i +
SIZE[BandRecord]
WHILE i < bandRecordLimit
DO bandRecordBase[i].status ← 0; ENDLOOP;
RETURN[firstBandRecord, @bandBufferBase[bandRecordBase[firstBandRecord].band]];
END;
ZeroBands:
PUBLIC
PROC =
BEGIN
FOR i: PrincOps.PageCount
IN [0..pagesCurrentlyInBands)
DO
LOOPHOLE[VM.AddressForPageNumber[bandBufferBasePage + i],
LONG POINTER TO ARRAY [0..PrincOps.wordsPerPage) OF WORD]^ ← ALL[0];
ENDLOOP;
END;
StartImage:
PUBLIC
PROC [band: Index] =
BEGIN imageLoc.overrun ← 0; imageLoc.run ← band; END;
BandOverrun:
PUBLIC
PROC
RETURNS [
BOOLEAN] =
BEGIN RETURN[imageLoc.overrun # 0]; END;
AdvanceBand:
PUBLIC
PROC [currentBand: Index]
RETURNS [Index,
LONG
POINTER] =
BEGIN
b: LONG POINTER TO BandRecord = @bandRecordBase[currentBand];
b.status ← LAST[INTEGER];
imageLoc.lastStartedBand ← currentBand;
RETURN[b.next, @bandBufferBase[bandRecordBase[b.next].band]];
END;
BandFull:
PUBLIC
PROC [band: Index]
RETURNS [
BOOLEAN] =
BEGIN RETURN[bandRecordBase[band].status # 0]; END;
LastBand:
PUBLIC
PROC [band: Index] =
BEGIN bandRecordBase[band].status ← -1; imageLoc.lastStartedBand ← band; END;
PutCommand:
PUBLIC
PROC [command:
BYTE] =
BEGIN
UNTIL controlDataLoc^ = 0 DO ENDLOOP;
controlDataLoc^ ← command + 80H; -- send off a command byte
(controlDataLoc+1)^ ← LAST[WORD]; -- For the Pilot 6 version of Domino
controlLocal: LONG POINTER TO CCSB = LOOPHOLE[DLionInputOutput.IOPage + 60B];
CCSB: TYPE = MACHINE DEPENDENT RECORD [unused(0): WORD, mask(1): WORD, data(2): WORD, status(3): WORD];
UNTIL controlLocal.status = 0 DO --GORP??-- ENDLOOP;
controlLocal.data ← command + 80H;
controlLocal.status ← LAST[WORD]
END;
GetStatus:
PUBLIC
PROC
RETURNS [status:
BYTE] =
BEGIN
status ← statusLoc^; -- pick up previously recieved status byte
statusLoc^ ← 0;
Old Pilot 6 head stuff......
statusLocal: LONG POINTER TO SCSB = LOOPHOLE[DLionInputOutput.IOPage + 64B]; -- FF34'x
SCSB: TYPE = MACHINE DEPENDENT RECORD [overrun(0): WORD, mask(1): WORD, data(2): WORD, status(3): CARDINAL]; -- actually PrinterStatus
IF statusLocal.overrun # 0
THEN {statusLocal.status ← 0; statusLocal.overrun ← 0; status ← 177B}
ELSE
IF statusLocal.status # 0
THEN {status ← LOOPHOLE[PrincOpsUtils.BITAND[statusLocal.data, 177B]];
statusLocal.status ← 0}
ELSE status ← 0;
END;
Loader.MakeProcedureResident[AllocateBands];
Loader.MakeGlobalFrameResident[AllocateBands];
Loader.MakeProcedureResident[DeallocateBands];
Loader.MakeGlobalFrameResident[DeallocateBands];
Loader.MakeProcedureResident[SetInterruptMasks];
Loader.MakeGlobalFrameResident[SetInterruptMasks];
Loader.MakeProcedureResident[InitializeCleanUp];
Loader.MakeGlobalFrameResident[InitializeCleanUp];
Loader.MakeProcedureResident[SetScanLineLength];
Loader.MakeGlobalFrameResident[SetScanLineLength];
Loader.MakeProcedureResident[SetPageOffsets];
Loader.MakeGlobalFrameResident[SetPageOffsets];
Loader.MakeProcedureResident[ResetBands];
Loader.MakeGlobalFrameResident[ResetBands];
Loader.MakeProcedureResident[ZeroBands];
Loader.MakeGlobalFrameResident[ZeroBands];
Loader.MakeProcedureResident[StartImage];
Loader.MakeGlobalFrameResident[StartImage];
Loader.MakeProcedureResident[BandOverrun];
Loader.MakeGlobalFrameResident[BandOverrun];
Loader.MakeProcedureResident[AdvanceBand];
Loader.MakeGlobalFrameResident[AdvanceBand];
Loader.MakeProcedureResident[BandFull];
Loader.MakeGlobalFrameResident[BandFull];
Loader.MakeProcedureResident[LastBand];
Loader.MakeGlobalFrameResident[LastBand];
Loader.MakeProcedureResident[PutCommand];
Loader.MakeGlobalFrameResident[PutCommand];
Loader.MakeProcedureResident[GetStatus];
Loader.MakeGlobalFrameResident[GetStatus];
END......
Log:
XXP /July 23, 1981 11:07 AM/Modified "PutCommand".
XXP /August 12, 1981 8:53 PM/Implemented "DozeOff" and "WakeUp" PROCEDUREs.
XXP /August 18, 1981 11:35 AM/Cleaned-up DIRECTORY.
XXP /September 26, 1981 6:31
PM/
1. Modified "AllocateBands" as follows:
(a) call to "SpecialSpace.CreateForCode";
(b) call to "DLionInputOutput.DonateReservedMemory".
2. Modified "DeallocateBands" as follows:
(a) call to "Space.Delete".
Those changes were made to allow hiding the fact that SOME space MUST
be reserved ("bandBufferPadding" pages) beyond the actually used BandBuffer area
due to the possibility of BandBLT writing beyond that BandBuffer area.
I also took this opportunity to move DLionInputOutput.DonateReservedMemory into AllocateBands,
where it seems to belong.
Question: is InitializeCleanUp now doing ALL it is supposed to do?
FXH ? merged Claude's changes into Pilot version, except for the head creating/destroying the space and calling DonateReservedMemory.
14-Nov-81 15:06:15
JXP
fold in changes made by JGS for bootstrap
15-Feb-82 9:03:01
FXH
add lost edit for resolution pair
2-Mar-82 13:40:35
CRF and
FXH
Add special BitBlt-independent implementations of BYTBLTR and BLTLR so that they
may be used with JLSEPMesa.db.
16-Mar-82 13:22:22
FXH
Change Display to allow for display of 'F.
25-Mar-82 10:53:05
CRF
Add special BitBlt-independent implementation of BYTBLT so that it may be used
with RavenMesa.db (which used to be called JLSEPMesa.db).
26-Mar-82 15:12:52
CRF
Deleted BYTBLT, BYTBLTR, and BLTLR implementations (they were merged into the ProcessorHeadDLion implementations).
28-Jul-82 10:17:04
AEF
New IOPage layout.
9-Apr-83 14:47:56
AEF
Don't use Utilities.
11-Apr-83 11:29:09
AEF
Change use of PageMap.
Time: 26-Sep-84 10:17:42
By:
DXG
Action: Added copyright notice and rebuild for 11.1 release.
7-Jun-85 11:50:38: NXS Created device independant version, changed name from RavenHeadDLion to LSEPHeadDLion for 12.0, fix PutCommand to allow send of 0.