--last edit by Govvel on February 4, 1981 2:50 PM
--last edit by Jarvis on July 30, 1980 1:47 PM
--ast edit by Olmstead on October 31, 1980 9:07 AM
--last edit by Forrect on December 1, 1980 1:52 PM
-- To do: bury ImageCSB.lineSize into the microcode. Re-arrange ImageCSB to make
-- fields the microcode cares about contiguous.
DIRECTORY
DeviceCleanup USING [Item, Reason, Await],
DLionInputOutput USING [ firstReservedPage, IOPage, ioPageRealAddrLow, SetReservedMemoryUse],
Environment USING [PageCount, PageNumber, wordsPerPage],
PageMap USING [Assoc, flagsClean, RealPageNumber, Value, valueVacant],
RavenFace,
System USING [Pulses, MicrosecondsToPulses, Microseconds, GetClockPulses],
Utilities USING [LongPointerFromPage];
RavenHeadDLion: PROGRAM
IMPORT DLionInputOutput, DeviceCleanup, PageMap, System, Utilities
EXPORTS RavenFace
SHARES PageMap =
BEGIN OPEN RavenFace;
-- 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];
-- raven occupies from 10x through 38x on the IOPage
imageLoc: LONG POINTER TO ImageCSB = LOOPHOLE[DLionInputOutput.IOPage + 20B]; -- FF10'x
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, -- used by device cleanup to wait for printer to stop
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
BandRecord: TYPE = MACHINE DEPENDENT RECORD [
band(0): Band, next(1): Index, status(2): INTEGER];
firstBandRecord: Index =
LOOPHOLE [DLionInputOutput.ioPageRealAddrLow + 20B + SIZE[ImageCSB]];
bandRecordLimit: Index = firstBandRecord + MaxBands*SIZE[BandRecord];
bandRecordBase: BandRecordBase =
LOOPHOLE[imageLoc + SIZE[ImageCSB] - LOOPHOLE[firstBandRecord, CARDINAL]];
controlLoc: LONG POINTER TO CCSB = LOOPHOLE[DLionInputOutput.IOPage + 60B]; -- FF30'x
CCSB: TYPE = MACHINE DEPENDENT RECORD [
unused(0): WORD, mask(1): WORD, data(2): WORD, status(3): WORD];
statusLoc: 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
pagesCurrentlyInBands: Environment.PageCount ← 0;
bandBufferBase: BandBufferBase;
bandBufferBasePage: Environment.PageNumber;
nullIndex: Index = LOOPHOLE[0];
IthIndex: PROC [i:CARDINAL [0..MaxBands)] RETURNS [Index] = {
RETURN[firstBandRecord + (i*SIZE[BandRecord])]};
AllocateBands: PUBLIC PROC [
bandVirtualPageNumber: Environment.PageNumber, nBands: (0..MaxBands],
sizeEachBand: Environment.PageCount] =
BEGIN
bandBufferBase ← Utilities.LongPointerFromPage[
bandVirtualPageNumber - DLionInputOutput.firstReservedPage];
bandBufferBasePage ← bandVirtualPageNumber;
pagesCurrentlyInBands ← sizeEachBand*nBands;
DLionInputOutput.SetReservedMemoryUse[Raven, pagesCurrentlyInBands];
FOR i: CARDINAL IN [0..pagesCurrentlyInBands) DO
PageMap.Assoc[
bandVirtualPageNumber + i, [
FALSE, PageMap.flagsClean, DLionInputOutput.firstReservedPgae + i]];
LOOPHOLE[Utilities.LongPointerFromPage[bandVirtualPageNumber + i], LONG
POINTER TO ARRAY [0..Environment.wordsPerPage) OF WORD]↑← ALL[0];
ENDLOOP;
FOR i: CARDINAL IN [0..nBands) DO
bandRecordBase[IthIndex[i]] ← [
band:
LOOPHOLE[(DLionInputOutput.firstReservedPage +
i*sizeEachBand)*Environment.wordsPerPage],
next: IthIndex[(i+1) MOD nBands], status: 0];
ENDLOOP;
imageLoc.bandSize ← sizeEachBand;
imageLoc.lastStartedBand ← nullIndex;
imageLoc.lineSize ← Environment.wordsPerPage;
END;
SetInteruptMasks: PUBLIC PROC [control, status, data: WORD] = {
controlLoc.mask ← control; statusLoc.mask ← status; imageLoc.mask ← data};
DeallocateBands: PUBLIC PROC =
BEGIN
imageLoc.lastStartedBand ← nullIndex;
FOR i: CARDINAL IN [0..pagesCurrentlyInBands) DO
PageMap.Assoc[bandBufferBasePage + i, PageMap.valueVacant] ENDLOOP;
pagesCurrentlyInBands ← 0;
DLionInputOutput.SetreservedMemoryUse[notBusy];
END;
Display: PUBLIC PROC [chat: CionsoleCharacter] = {
Send[60B + LOOPHOLE[char, WORD]]};
Feed: PUBLIC PROC [paperSource: PaperSource, paperStacking: PaperStacking] =
BEGIN
Send[
100B + (IF paperSource = botton THEN 0 ELSE 20B) +
(IF paperStacking = aligned THEN 0 ELSE 1)]
END;
SolicitStatus: PUBLIC PROC RETURNS [s: PrinterStatus] =
BEGIN
If statusLoc.overrun # 0 THEN {
statusLoc.status ← 0; statusLoc.overrun ← 0; s ← statusOverRun}
ELSE
IF statusLoc.status # 0 then {
s ← LOOPHOLE[Inline.BITAND[statusLoc.data, 177B]]; statusLoc.status ← 0}
ELSE s ← noStatus;
END;
SetScanLineLength: PUBLIC PROC [
activeWordsEachScanLine: [0..Environment.wordsPerPage]] =
BEGIN
offset: [0..Environment.wordsPerPage) =
Environments.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 [linesFromLeft, wordTabFromBottom: CARDINAL] = {
imageLoc.scans ← linesFromLeft; imageLoc.tab ← wordTabFromBottom};
ResetBands: PUBLIC PROC RETURNS [Index, LONG POINTER] =
BEGIN
imageLoc.lastStartedBand ← null Index;
FOR i: Index ← firstBandRecord, i + SIZE[BandRecord] WHILE i < bandRecordLimit
DO bandRecordBase[i].status ← 0 ENDLOOP;
RETURN[fistBandRecord, @bandBufferBase[bandRecordBase[firstBandRecord].band]]
END;
StartImage: PUBLIC PROC [band: Index] = {
imageLoc.overrun ← 0; imageLoc.run ← band};
BandOverrun: PUBLIC PROC RETURNS [BOOLEAN] = {RETURN[imageLoc.overrun # 0]};
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] = {
RETURN[bandRecordBase[band].status # 0]};
LastBand: PUBLIC PROC [band: Index] = {
bandRecordBase[band].status ← -1; imageLoc.lastStartedBand ← band};
-- send off a control word
Send: PROC [w: WORD] =
BEGIN
UNTIL controlLoc.status = 0 DO --GORP??-- ENDLOOP;
controlLoc.data ← w;
controlLoc.status ← LAST[WORD]
END;
InitializeCleanUp: PUBLIC PROC =
BEGIn
item: DeviceCleanup.item;
saveCSB; ImageCSB;
maxWaitTime: System.Microseconds = LONG[27500]*(2*MaxBands);
waitTime: System.Pulses = System.MicrosecondsToPulses[m: maxWaitTime];
DO
reason: DeviceCleanup.Reason = DeviceCleanup.Await[@item];
SELECT reason FROM
turnOff =>
BEGIN
then: System.Pulses = System.GetclockPulses[];
If imageLoc.lastStartedBand # nullIndex THEN
WHILE (System.GetClockPulses[] - then) < waitTime
AND bandRecordBase[imageLoc.lastStartedBand].status # 0 DO ENDLOOP;
saveCSB ← imageLoc↑;
END;
turnOn => --restore csb; client will have to redo page.
{saveCSB.lastStartedBand ← nullIndex; imageLoc ↑ ← saveCSB};
disconnect =>
FOR i: CARDINAL IN [0..pagesCurrentlyInBands) DO
PageMap.Assoc[bandBufferBasePage + i, PageMap.valueVacant] ENDLOOP;
ENDCASE;
ENDLOOP;
END;
END...