--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...