DIRECTORY BasicTime USING [Pulses, MicrosecondsToPulses], DeviceCleanup USING [Item, Reason, Await], DLionInputOutput USING [GetRealPage, IOPage, ioPageRealAddrLow], Loader USING [MakeProcedureResident, MakeGlobalFrameResident], PrincOps USING [PageCount, PageNumber, wordsPerPage], PrincOpsUtils USING [BITAND, GetClockPulses, LongZero], RavenFace, VM USING [AddressForPageNumber, Interval, nullInterval, Pin], VMSideDoor USING [AssignSpecialRealMemory, ReleaseSpecialRealMemory]; RavenHeadDLion: PROGRAM IMPORTS BasicTime, DeviceCleanup, DLionInputOutput, Loader, PrincOpsUtils, VM, VMSideDoor EXPORTS RavenFace = BEGIN OPEN RavenFace; resolution: PUBLIC ResolutionPair _ [300, 300]; size: PUBLIC SizePair _ [300*11, 8*300+300/2]; IOPage: LONG POINTER = DLionInputOutput.IOPage; imageLoc: LONG POINTER TO ImageCSB = LOOPHOLE[IOPage + 20B]; firstBandRecord: Index = LOOPHOLE [DLionInputOutput.ioPageRealAddrLow + 20B + SIZE[ImageCSB]]; BandRecordBase: TYPE = LONG BASE POINTER TO RECORD [UNSPECIFIED]; -- base to BandRecord bandRecordBase: BandRecordBase = LOOPHOLE[imageLoc + SIZE[ImageCSB] - LOOPHOLE[firstBandRecord, CARDINAL]]; -- The IO page address Index: PUBLIC TYPE = BandRecordBase RELATIVE ORDERED POINTER TO BandRecord; BandRecord: TYPE = MACHINE DEPENDENT RECORD [ band(0): Band, -- Relative to Real page 0 next(1): Index, -- This is relative to the start of the IOPage!!! status(2): INTEGER]; bandRecordLimit: Index = firstBandRecord + MaxBands*SIZE[BandRecord]; BandBufferBase: TYPE = LONG BASE POINTER TO RECORD [UNSPECIFIED]; -- Band memory as defined by the band records. bandBufferBase: BandBufferBase; -- Set by AllocateBands as a real address for the uCode. Band: TYPE = BandBufferBase RELATIVE POINTER; -- real relative pointer VBandBufferBase: TYPE = LONG BASE POINTER TO RECORD [UNSPECIFIED]; -- Virtual band memory as defined by the band records. This is so we keep track of the mapping between the real address of the bands and the virtual addresses. vBandBufferBase: VBandBufferBase; -- Set by AllocateBands as the original virtual address of the band. VBand: TYPE = VBandBufferBase RELATIVE POINTER; -- Virtual relative pointer. Band[bandBufferBase] should be the real address = Band[vBandBufferBase]. 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 controlLoc: LONG POINTER TO CCSB = LOOPHOLE[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[IOPage + 64B]; -- FF34'x SCSB: TYPE = MACHINE DEPENDENT RECORD [overrun(0): WORD, mask(1): WORD, data(2): WORD, status(3): CARDINAL]; -- actually PrinterStatus pagesCurrentlyInBands: PrincOps.PageCount _ 0; -- How many are used. nullIndex: Index = LOOPHOLE[0]; heldBandVM: VM.Interval _ VM.nullInterval; IthIndex: PROC [i:CARDINAL [0..MaxBands)] RETURNS [Index] = { RETURN[firstBandRecord + (i*SIZE[BandRecord])]}; AllocateBands: PUBLIC PROC [bandVM: VM.Interval, nBands: (0..MaxBands], sizeEachBand: CARDINAL] = BEGIN realPage: CARDINAL; words: INT; IF heldBandVM # VM.nullInterval THEN ERROR; -- Storage already allocated. IF bandVM.count < (nBands*sizeEachBand) THEN ERROR; VMSideDoor.AssignSpecialRealMemory[bandVM]; -- Move to low core and Pin bandBufferBase _ VM.AddressForPageNumber[DLionInputOutput.GetRealPage[bandVM.page]]; vBandBufferBase _ VM.AddressForPageNumber[bandVM.page]; -- Make the virtual LP pagesCurrentlyInBands _ sizeEachBand*nBands; words _ LONG[nBands] * LONG[sizeEachBand] * LONG[PrincOps.wordsPerPage]; realPage _ LOOPHOLE[DLionInputOutput.GetRealPage[bandVM.page]]; ClearCore[VM.AddressForPageNumber[bandVM.page], words]; FOR i: CARDINAL IN [0..nBands) DO bandRecordBase[IthIndex[i]] _ [band: LOOPHOLE[(realPage + i * sizeEachBand) * PrincOps.wordsPerPage], next: IthIndex[(i+1) MOD nBands], status: 0]; ENDLOOP; imageLoc.bandSize _ sizeEachBand; imageLoc.lastStartedBand _ nullIndex; imageLoc.lineSize _ PrincOps.wordsPerPage; heldBandVM _ bandVM; END; ClearCore: PROC [pointer: LONG POINTER, words: INT] = BEGIN WHILE words > 32768 DO PrincOpsUtils.LongZero[pointer, 32768]; pointer _ pointer + 32768; words _ words - 32768; ENDLOOP; PrincOpsUtils.LongZero[pointer, words]; END; SetInterruptMasks: PUBLIC PROC [control, status, data: WORD] = { controlLoc.mask _ control; statusLoc.mask _ status; imageLoc.mask _ data}; DeallocateBands: PUBLIC PROC = BEGIN imageLoc.lastStartedBand _ nullIndex; IF heldBandVM = VM.nullInterval THEN ERROR; -- Storage not allocated. VMSideDoor.ReleaseSpecialRealMemory[heldBandVM]; pagesCurrentlyInBands _ 0; heldBandVM _ VM.nullInterval; END; Display: PUBLIC PROC [char: ConsoleCharacter] = { Send[LOOPHOLE[char, WORD]]}; Feed: PUBLIC PROC [paperSource: PaperSource, paperStacking: PaperStacking] = BEGIN Send[100B + (IF paperSource = bottom THEN 0 ELSE 20B) + (IF paperStacking = aligned THEN 0 ELSE 1)] END; WakeUp: PUBLIC PROC = {Send[40B]}; DozeOff: PUBLIC PROC = {Send[132B]}; ReadStatus: PUBLIC PROC RETURNS [status: PrinterStatus] = { Send[40B]; RETURN [SolicitStatus[]]}; 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[PrincOpsUtils.BITAND[statusLoc.data, 177B]]; statusLoc.status _ 0} ELSE s _ noStatus; 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 [linesFromLeft, wordTabFromBottom: CARDINAL] = { imageLoc.tab _ wordTabFromBottom; imageLoc.scans _ linesFromLeft}; 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, @vBandBufferBase[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, @vBandBufferBase[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: 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: 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 => --restore csb; client will have to redo page. {saveCSB.lastStartedBand _ nullIndex; imageLoc ^ _ saveCSB}; disconnect => {IF heldBandVM = VM.nullInterval THEN ERROR; -- Storage not allocated. VMSideDoor.ReleaseSpecialRealMemory[heldBandVM]; heldBandVM _ VM.nullInterval}; ENDCASE; ENDLOOP; END; Loader.MakeProcedureResident[AllocateBands]; Loader.MakeGlobalFrameResident[AllocateBands]; END... RavenHeadDLion.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. 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 Tim Diebert: January 22, 1987 12:26:09 pm PST To do: bury ImageCSB.lineSize into the microcode. Re-arrange ImageCSB to make fields the microcode cares about contiguous. Reconstructed from the Pilot 6 listing. RavenStuff There is a game going on that the relative pointers "work" in relation BOTH to Physical 10000x and some virtual Base addresses. Raven occupies from 10x through 38x on the IOPage This stuff is hear for the sake of the compiler. This is an offset into the table of BandRecords loacated in the IOPage. firstBandRecord: Index = LOOPHOLE [20B + SIZE[ImageCSB]]; This is a real mess. I think that the effective address of bandRecordBase[firstBandRecord] = IOPage + 20B + SIZE[ImageCSB] and bandRecordBase[firstBandRecord.NEXT] = IOPage + 20B + SIZE[ImageCSB] + SIZE[BandRecord] and so on. imageLoc: LONG POINTER TO ImageCSB = LOOPHOLE[IOPage + 20B]; DLionInputOutput.SetReservedMemoryUse[Raven, pagesCurrentlyInBands]; DLionInputOutput.SetReservedMemoryUse[notBusy]; send off a control word Κ ˜code™Kšœ Οmœ1™Kšœ žœ'˜5Kšœžœžœ˜7K˜ Kšžœžœ5˜=Kšœ žœ5˜EK˜—šΠlnœž˜KšžœDžœ ˜YKšžœ ˜Kšžœžœ ˜K˜Kšœ žœ˜/Kšœžœ"˜.K˜K˜—šΠbl ™ K™Kšœ™K™Kšœ1™1K˜K™0Kšœžœžœ˜/Kš œ žœžœžœ žœ˜