LSEPHeadDLion.mesa
Copyright Ó 1981, 1982, 1983, 1985, 1987 by Xerox Corporation. All rights reserved.
Tim Diebert: January 27, 1987 1:13:31 pm 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, ioPageRealAddrLow],
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];
StatusMask: TYPE = WORD;
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: DXGAction: 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.