DIRECTORY Basics USING [bitsPerWord, DoubleShiftRight, LongMult], CountedVM USING [Handle, SimpleAllocate], FontTune USING [CreateFontTuner], Imager USING [Context, metersPerInch, RotateT, ScaleT, SetPriorityImportant, TranslateT], ImagerFastShow USING [Create], ImagerPixelMap USING [DeviceRectangle, PixelMap, PixelMapRep, Clear], ImagerRaster USING [FontTuner], Loader USING [MakeProcedureResident, MakeGlobalFrameResident], LSEPFace, Process USING [Detach, Pause, MsecToTicks, Priority, GetPriority, priorityBackground, priorityFaultHandlers, priorityRealTime, SetPriority], PrincOps USING [bitsPerWord, wordsPerPage, BBTableSpace, BBptr, PageCount], PrincOpsUtils USING [AllocateNakedCondition, BITBLT, AlignedBBTable, GetClockPulses --, LongCopy --], RavenCodes, RavenDriver, Rope USING [ROPE], VM USING [Allocate, Interval, PageCount, PagesForWords, Pin ], VMSideDoor USING [AssignSpecialRealMemory]; RavenDriverImpl: MONITOR IMPORTS Basics, CountedVM, FontTune, Imager, ImagerFastShow, ImagerPixelMap, Loader, LSEPFace, Process, PrincOpsUtils, VM, VMSideDoor EXPORTS RavenDriver ~ BEGIN OPEN RavenDriver; myPixelMap: ImagerPixelMap.PixelMap _ [0, 0, 0, 0, 0, 0, NIL]; secondPixelMap: ImagerPixelMap.PixelMap _ [0, 0, 0, 0, 0, 0, NIL]; GetPrinterPixelMap: PUBLIC PROC RETURNS [pixelMap: ImagerPixelMap.PixelMap] = {RETURN[myPixelMap]}; MakePrinterPixelMap: PROC RETURNS [pixelMap: ImagerPixelMap.PixelMap] = BEGIN bounds: ImagerPixelMap.DeviceRectangle _ [0, 0, (8*300+300/2), (11*300)]; numBands: NAT = ((8*300+300/2)+15)/16; numLines: CARDINAL = numBands * sizeEachBand; wordsPerLine: NAT ~ activeLength; words: LONG CARDINAL ~ Basics.LongMult[wordsPerLine, numLines]; pages: CARDINAL = VM.PagesForWords[words]; vm: CountedVM.Handle _ CountedVM.SimpleAllocate[words]; interval: VM.Interval ~ vm.interval; refRep: REF ImagerPixelMap.PixelMapRep _ NEW[ImagerPixelMap.PixelMapRep _ [ ref: vm, pointer: vm.pointer, words: vm.words, lgBitsPerPixel: 0, rast: wordsPerLine, lines: numLines]]; FOR i: INT _ 0, i+400 UNTIL i >= interval.count DO -- only pin about 100K each time VM.Pin[[page: interval.page+i, count: MIN[interval.count-i, 400]]]; Process.Pause[Process.MsecToTicks[500]]; -- wait a half second for Laundry process ENDLOOP; pixelMap.refRep _ refRep; pixelMap.sMin _ 0; pixelMap.fMin _ 0; [pixelMap.sOrigin, pixelMap.fOrigin, pixelMap.sSize, pixelMap.fSize] _ bounds; ImagerPixelMap.Clear[pixelMap]; END; ContextFromPixelMap: PUBLIC PROC [pixelMap: ImagerPixelMap.PixelMap, fontTunerParms: Rope.ROPE _ NIL] RETURNS [context: Imager.Context] = BEGIN fontTuner: ImagerRaster.FontTuner _ NIL; IF fontTunerParms # NIL THEN fontTuner _ FontTune.CreateFontTuner[fontTunerParms]; context _ ImagerFastShow.Create[pm: pixelMap, pixelsPerInch: RavenCodes.resolution[fast], pixelUnits: TRUE, fontTuner: fontTuner]; Imager.SetPriorityImportant[context, TRUE]; Imager.RotateT[context, -90.0]; Imager.TranslateT[context, [-(8*300+300/2), 0]]; Imager.ScaleT[context, RavenCodes.resolution[fast]/Imager.metersPerInch]; END; lastPaperFeed: RavenCodes.PrinterCommand _ feed; SetRegistration: PUBLIC PROCEDURE [registration: RavenRegistration] = TRUSTED BEGIN DivideUp: PROCEDURE [divident, divisor: CARDINAL] RETURNS [quotient: CARDINAL] = TRUSTED INLINE BEGIN RETURN[quotient: (divident + divisor - 1) / divisor]; END; LSEPFace.SetPageOffsets[ wordsFast: DivideUp[divident: registration.long * registrationTabSize, divisor: PrincOps.bitsPerWord], linesSlow: registration.short * registrationTabSize]; END; -- SetRegistration lastBand: BOOL; pageBufferIndex: CARDINAL; -- index to current band in page buffer pageBufferIndexLast: CARDINAL; -- last meaningful band in page buffer pageBufferBandBuffer: LONG POINTER; -- band buffer virtual address bandBufferSize: PrincOps.PageCount = 16; -- From BandBLT ScanLine: TYPE = [0..bandBufferSize); -- scan line index into a band bandLast, band, firstBand: LSEPFace.Index; bbTableSpace: PrincOps.BBTableSpace; bb: PrincOps.BBptr ~ PrincOpsUtils.AlignedBBTable[@bbTableSpace]; dstBpl: INTEGER ~ PrincOps.wordsPerPage*Basics.bitsPerWord; BandCopyInternal: PROCEDURE [pixelMap: ImagerPixelMap.PixelMap, pm: REF ImagerPixelMap.PixelMapRep] = INLINE BEGIN sourceAddr: LONG POINTER _ pm.pointer + Basics.LongMult[pageBufferIndex, pm.rast*sizeEachBand]; bb^ _ [ dst: [word: pageBufferBandBuffer, bit: 0], dstBpl: dstBpl, src: [word: sourceAddr, bit: 0], srcDesc: [srcBpl[pm.rast*Basics.bitsPerWord]], height: sizeEachBand, width: pixelMap.fSize, flags: [direction: forward, disjoint: TRUE, disjointItems: TRUE, gray: FALSE, srcFunc: null, dstFunc: null] ]; PrincOpsUtils.BITBLT[bb]; IF (pageBufferIndex _ pageBufferIndex + 1) > pageBufferIndexLast THEN {lastBand _ TRUE; bandLast _ band}; [nextBand: band, nextBandAddress: pageBufferBandBuffer] _ LSEPFace.AdvanceBand[currentBand: band]; END; -- BandCopyInternal dataOnPulses: ARRAY [0 .. 256) OF CARD _ ALL[0]; PrintFromPixelMap: PUBLIC PROC [pixelMap: ImagerPixelMap.PixelMap, copies: CARDINAL _ 1, paperFeed: RavenDriver.PaperFeed _ alternating] RETURNS [endingStatus: PrinterStatus, type: StatusType] = BEGIN ENABLE ABORTED => printing _ FALSE; timeout, error: BOOL _ FALSE; old: Process.Priority _ Process.GetPriority[]; WaitReady: ENTRY PROC [] = INLINE BEGIN ENABLE UNWIND => NULL; UNTIL ReadyStatus[currStatus] DO WAIT newStatus ENDLOOP; END; WaitPageSync: ENTRY PROC [] = INLINE BEGIN ENABLE UNWIND => NULL; UNTIL currStatus = pageSync OR ErrorStatus[currStatus] DO WAIT newStatus; IF ErrorStatus[currStatus] THEN {error _ TRUE; EXIT}; ENDLOOP; END; WaitBandEmpty: ENTRY PROC [band: LSEPFace.Index] = INLINE BEGIN ENABLE UNWIND => NULL; WHILE LSEPFace.BandFull[band] DO WAIT dataCondition^; ENDLOOP; END; paperTray: RavenCodes.PrinterCommand _ SELECT paperFeed FROM bottom => feed, top => feedTop, alternating => IF lastPaperFeed = feed THEN feedTop ELSE feed, ENDCASE => feed; printing _ TRUE; lastPaperFeed _ paperTray; pageBufferIndexLast _ pixelMap.refRep.lines/16-1; LSEPFace.PutCommand[LOOPHOLE[RavenCodes.PrinterCommand[solicitStatus]]]; WaitReady[]; IF error THEN GOTO OutErr; [firstBand: band, firstBandAddress: pageBufferBandBuffer] _ LSEPFace.ResetBands[]; firstBand _ band; pageBufferIndex _ 0; lastBand _ FALSE; THROUGH [0..bandBufferCount) UNTIL lastBand DO BandCopyInternal[pixelMap, pixelMap.refRep]; dataOnPulses[pageBufferIndex] _ PrincOpsUtils.GetClockPulses[]; ENDLOOP; BEGIN ENABLE UNWIND => Process.SetPriority[old]; Process.SetPriority[Process.priorityFaultHandlers]; LSEPFace.PutCommand[LOOPHOLE[paperTray]]; WaitPageSync[]; LSEPFace.StartImage[firstBand: firstBand]; UNTIL lastBand DO WaitBandEmpty[band]; BandCopyInternal[pixelMap, pixelMap.refRep]; dataOnPulses[pageBufferIndex] _ PrincOpsUtils.GetClockPulses[]; ENDLOOP; LSEPFace.LastBand[bandLast]; -- indicate that last band has been filled WaitBandEmpty[bandLast]; IF LSEPFace.BandOverrun[] THEN GOTO Out; printing _ FALSE; EXITS Out => {Process.SetPriority[old]; RETURN [ropeStatus[currStatus], error]}; END; Process.SetPriority[old]; RETURN [ropeStatus[noStatus], normal]; EXITS OutErr => {RETURN [ropeStatus[currStatus], error]}; END; currStatus: RavenCodes.PrinterStatus _ noStatus; mySP: REF StatusProc _ NIL; printing: BOOL _ FALSE; newStatus: CONDITION; SetScanLineLength: PUBLIC SAFE PROCEDURE [scanLineLength: (0..PrincOps.wordsPerPage]] = TRUSTED BEGIN LSEPFace.SetScanLineLength[scanLineLength]; END; MonitorRavenStatus: PROC [] = BEGIN WaitStatus: ENTRY PROC [] = INLINE BEGIN ENABLE UNWIND => NULL; ready: BOOL _ FALSE; UNTIL ready DO WAIT statusCondition^; ready _ TRUE; ENDLOOP; END; Note: ENTRY PROC [] = INLINE {ENABLE UNWIND => NULL; BROADCAST newStatus}; messageInternal: Message _ commandStatusFault; Process.SetPriority[Process.priorityRealTime]; DO -- Forever WaitStatus[]; currStatus _ LOOPHOLE[LSEPFace.GetStatus[]]; IF currStatus = pageSync THEN {Note[]; LOOP}; SELECT currStatus FROM statusOverRun, noStatus, parityError, unrecognizedCommand, illegalSequence, statusError => -- read status and try again IF messageInternal = aboutToDozeOff THEN LOOP; -- ignore death throes IN [key0..keyOffLine] => LOOP; warming, standBy, feederFault, registrationJam, fuserJam, noExit, interlockOpen, fuserCold, feedTraysNotEngaged, tonerLow, goingOffLine, offLine, outputTrayFull, aboutToDozeOff => BEGIN messageInternal _ SELECT currStatus FROM warming, fuserCold => fuserUnderTemperature, standBy => ok, feederFault => preRegistrationFault, registrationJam => postRegistrationJam, fuserJam => preExitJam, noExit => postExitJam, interlockOpen => doorOpen, feedTraysNotEngaged => traysUnlatched, tonerLow => tonerLow, goingOffLine, offLine => offLine, outputTrayFull => outputTrayFull, ENDCASE => aboutToDozeOff; END; ENDCASE => {Note[]; LOOP}; IF NOT printing AND mySP # NIL THEN Process.Detach[FORK Send[]]; Note[]; ENDLOOP; END; Send: PROC [] = BEGIN Process.SetPriority[Process.priorityBackground]; mySP[ropeStatus[currStatus], normal]; END; Message: TYPE = {traysUnlatched, preRegistrationFault, postRegistrationJam, preExitJam, postExitJam, doorOpen, outputTrayFull, tonerLow, aboutToDozeOff, fuserUnderTemperature, imageFault, commandStatusFault, offLine, ok}; ReadyStatus: PROC [status: RavenCodes.PrinterStatus] RETURNS [ready: BOOL] = INLINE BEGIN ready _ SELECT status FROM standBy, readyToFeed => TRUE, ENDCASE => FALSE; END; ErrorStatus: PROC [status: RavenCodes.PrinterStatus] RETURNS [error: BOOL] = INLINE BEGIN error _ SELECT status FROM feederFault, registrationJam, fuserJam, noExit, interlockOpen, fuserCold, feedTraysNotEngaged, tonerLow, goingOffLine, offLine, aboutToDozeOff => TRUE, ENDCASE => FALSE; END; RegisterStatusProc: PUBLIC ENTRY PROC [sp: StatusProc] = {mySP _ NEW[StatusProc _ sp]}; UnRegisterStatusProc: PUBLIC ENTRY PROC [sp: StatusProc] = {mySP _ NIL}; WakeUp: PUBLIC PROCEDURE[] = BEGIN LSEPFace.PutCommand[LOOPHOLE[RavenCodes.PrinterCommand[solicitStatus]]]; -- Jump start the Raven END; bandBufferCount: LSEPFace.BandBufferCount _ 3; wordsPerBand: CARDINAL = sizeEachBand * PrincOps.wordsPerPage; sizeEachBand: CARDINAL = 16; pagesNeedForBands: VM.PageCount = LSEPFace.MaxBands * sizeEachBand + 20; vm: VM.Interval; activeLength: (0..PrincOps.wordsPerPage] _ ((11*300)+15)/16; statusCondition: LONG POINTER TO CONDITION _ NIL; statusMask: WORD _ 0; dataCondition: LONG POINTER TO CONDITION _ NIL; dataMask: WORD _ 0; Init: PROC [] = BEGIN vm _ VM.Allocate[pagesNeedForBands]; VMSideDoor.AssignSpecialRealMemory[vm]; -- Move to low core and Pin LSEPFace.AllocateBands[vm.page, bandBufferCount, sizeEachBand, 1]; SetScanLineLength[activeLength]; myPixelMap _ MakePrinterPixelMap[]; Loader.MakeProcedureResident[PrintFromPixelMap]; Loader.MakeGlobalFrameResident[PrintFromPixelMap]; [statusCondition, statusMask] _ PrincOpsUtils.AllocateNakedCondition[]; [dataCondition, dataMask] _ PrincOpsUtils.AllocateNakedCondition[]; LSEPFace.SetInterruptMasks[0, statusMask, dataMask]; LSEPFace.PutCommand[LOOPHOLE[RavenCodes.PrinterCommand[solicitStatus]]]; -- Jump start the Raven Process.Detach[FORK MonitorRavenStatus[]]; -- Up to realTime END; ropeStatus: ARRAY RavenCodes.PrinterStatus OF PrinterStatus _ ALL[NIL]; ropeStatus[noStatus] _ "No status"; ropeStatus[key0] _ "key0"; ropeStatus[key1] _ "key1"; ropeStatus[key2] _ "key2"; ropeStatus[key3] _ "key3"; ropeStatus[key4] _ "key4"; ropeStatus[key5] _ "key5"; ropeStatus[key6] _ "key6"; ropeStatus[key7] _ "key7"; ropeStatus[key8] _ "key8"; ropeStatus[key9] _ "key9"; ropeStatus[keyClear] _ "keyClear"; ropeStatus[keyTest] _ "keyTest"; ropeStatus[keyOnLine] _ "keyOnLine"; ropeStatus[keyOffLine] _ "keyOffLine"; ropeStatus[warming] _ "Warming"; ropeStatus[standBy] _ "Ready"; ropeStatus[feederFault] _ "Feeder Fault"; ropeStatus[registrationJam] _ "Registration Jam"; ropeStatus[fuserJam] _ "Fuser Jam"; ropeStatus[noExit] _ "No Exit"; ropeStatus[interlockOpen] _ "Interlock Open"; ropeStatus[fuserCold] _ "Fuser Cold"; ropeStatus[feeding] _ "Feeding"; ropeStatus[readyToFeed] _ "Ready To Feed"; ropeStatus[displayAcknowledge] _ "displayAcknowledge"; ropeStatus[parityError] _ "parityError"; ropeStatus[unrecognizedCommand] _ "illegalCharacter"; ropeStatus[illegalSequence] _ "illegalSequence"; ropeStatus[feedTraysNotEngaged] _ "Paper Tray Open or Out of Paper"; ropeStatus[pageSync] _ "pageSync"; ropeStatus[pageAtOutputTray] _ "pageAtOutputTray"; ropeStatus[tonerLow] _ "Toner Low"; ropeStatus[goingOffLine] _ "goingOffLine"; ropeStatus[offLine] _ "offLine"; ropeStatus[outputTrayFull] _ "outputTrayFull"; ropeStatus[aboutToDozeOff] _ "Low Power Mode"; ropeStatus[statusError] _ "statusError"; ropeStatus[statusOverRun] _ "statusOverRun"; Init[]; END. θRavenDriverImpl.mesa Copyright Σ 1985, 1986, 1987 by Xerox Corporation. All rights reserved. Tim Diebert: January 28, 1987 10:39:29 am PST Rick Beach, November 25, 1985 8:18:04 am PST Michael Plass, November 26, 1985 2:44:23 pm PST sets up arguments for call which will set page offsets copy from page buffer to imaging band, by scan line scan lines in the buffer are each wordsPerScanLine words scan lines in the imaging band are each 256 words, offset ahead by 256 words-wordsPerScanLine bandOffset: CARD _ LONG[pageBufferIndex] * LONG[pm.rast] * LONG[LAST[ScanLine]]; FOR scanIndex: ScanLine IN [FIRST[ScanLine]..LAST[ScanLine]] DO PrincOpsUtils.LongCopy[ from: PageBufferAddress[base, pageBufferIndex, scanIndex], from: LOOPHOLE[pm.pointer + bandOffset + (scanIndex * LONG[pm.rast])], nwords: activeLength, to: LOOPHOLE[LOOPHOLE[pageBufferBandBuffer, LONG CARDINAL] + scanIndex * 256]]; ENDLOOP; mark current band ready for imaging and get address and index of next Refill bands when they have been imaged until input is exhausted LSEPFace.PutCommand[LOOPHOLE[RavenCodes.PrinterCommand[solicitStatus]]]; set message and broadcast newMessage secondPixelMap _ MakePrinterPixelMap[]; Process.SetTimeout[dataCondition, Process.SecondsToTicks[20]]; Κ J˜™IcodešœH™HK™-K™,K™/—K˜šΟk ˜ Kšœœ+˜7Kšœ œ˜)Kšœ œ˜!KšœœM˜YKšœœ ˜Kšœœ1˜EKšœ œ ˜Kšœœ2˜>Kšœ ˜ Kšœœ˜ŒKšœ œ=˜KKšœœœ!Οcœ˜eK˜ Kšœ ˜ Kšœœœ˜Kšœœ6˜>Kšœ œ˜+—K˜K˜KšΠlnœ˜Kšœpœ ˜…Kšœ ˜šœœœ ˜K˜Kšœ9œ˜>Kšœ=œ˜BK˜Kš Οnœœœœ(œ˜cK˜š œ œ'˜MKšœI˜IKšœ œ˜'Kšœ œ˜-Kšœœ˜!Kšœœœ+˜?Kšœœœ˜*Kšœ7˜7Kšœ œ˜$šœœœ˜KKšœ.˜.Kšœ9˜9—š œœ œœž ˜SKšœ$œ˜CK•StartOfExpansion[Process.Milliseconds]šœ*ž)˜SKšœ˜—Kšœ˜Kšœ˜Kšœ˜KšœO˜OKšœ˜Kšœ˜—K˜š  œœœ:œœœ˜Kšœ$œ˜(Kšœœœ6˜RKšœfœ˜‚Kšœ%œ˜+K˜Kšœ0˜0KšœI˜IKšœ˜—K˜Kšœ0˜0K˜K˜š  œœ œ%œ˜SKš œ œœœ œœœœœ0œ˜ Kšœ6™6˜Kšœf˜fKšœ5˜5—Kšœž˜—K˜Kšœ œ˜Kšœœž'˜CKšœœž&˜FKšœœœž˜CKšœ)ž˜8Kšœ œž˜EKšœ*˜*K˜$KšœA˜AKšœœ,˜;K˜š  œ œ)œœ˜rKšœΚ™ΚKš œ œœœ œœ ™PKšœ œœG˜_šœ˜Kšœ*˜*Kšœ˜Kšœ ˜ Kšœ.˜.Kšœ˜Kšœ˜Kšœ&œœœ˜kK˜—Kšœœ˜š œœœ œ ™?™K™:Kšœœ(œ ™FKšœ™Kš œ œœœœ™O—Kšœ™—šœ>˜EKšœ œ˜#—KšœE™EK˜bKšœž˜—K˜K˜Kš œœ œœœ˜0š  œœœ-œ6œ3˜ΘKšœœœ˜#Kšœœœ˜Kšœ.˜.š  œœœœœœœœ˜>šœ˜ Kšœ œ˜—Kšœ˜—š  œœœœœœœœ˜Ašœœ˜9Kšœ ˜Kš œœ œœœ˜>—Kšœ˜—š   œœœœ˜?Kšœœœ˜Kšœœœœ˜>Kšœ˜K˜—šœ'œ ˜Kšœ ˜—Kšœ œ˜Kšœ˜Kšœ1˜1Kšœœ,˜HK˜ Kšœœœ˜KšœR˜RKšœ˜K˜Kšœ œ˜šœœ ˜.Kšœ,˜,Kšœ?˜?Kšœ˜—šœœœ˜0Kšœ3˜3Kšœœ ˜)Jšœ˜Jšœ*˜*Jšœ@™@šœ ˜Kšœ˜Kšœ,˜,Kšœ?˜?Kšœ˜—Jšœž*˜HJšœ˜Jšœœœ˜(Kšœ œ˜Kšœœœ"˜PKšœ˜—Kšœ˜Kšœ ˜&Kšœ œ"˜9Kšœ˜K˜—Kšœ0˜0Kšœœœ˜Kšœ œœ˜Kšœ  œ˜K˜š  œœœ œ0œ˜eK˜+Kšœ˜—K˜š œœ˜#š  œœœœœœœœ˜?Kšœœœ˜šœ˜Kšœœœ˜-—Kšœ˜—Kš œœœœœœœ œ ˜JKšœ.˜.Kšœ.˜.šœž ˜ K˜ Kšœœ,™HKšœ œ˜,Kšœœ œ˜-šœ ˜šœ\ž˜yKšœ"œœž˜F—Kšœœ˜šœ³˜ΉKšœ%™%šœœ ˜(K˜,K˜K˜$K˜'K˜K˜K˜Kšœ&˜&K˜K˜!K˜!Kšœ˜—Kšœ˜—Kšœ œ˜—Kš œœ œœœœ ˜@K˜Kšœ˜—Kšœ˜—K˜š œœ˜Kšœ0˜0Kšœ%˜%Kšœ˜K˜—Kšœ œΠ˜έK˜š   œœ$œ œœ˜Yšœ œ˜Kšœœ˜Kšœœ˜—Kšœ˜—K˜š   œœ$œ œœ˜Yšœ œ˜Kšœ’œ˜—Kšœœ˜—Kšœ˜K˜—Kš  œœœœœ˜WK˜Kš  œœœœœ˜HK˜š œœ œ˜"Kšœœ.ž˜aKšœ˜—K˜K˜K˜.Kšœœ(˜>Kšœœ˜Kšœœ3˜HKšœœ ˜Kšœ<˜™>Kšœ4˜4Kšœœ.ž˜aKšœœž˜=Kšœ˜—K˜Kš œ œœœœ˜GKšœ#˜#Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ"˜"Kšœ ˜ Kšœ$˜$Kšœ&˜&Kšœ ˜ Kšœ˜Kšœ)˜)Kšœ1˜1Kšœ#˜#Kšœ˜Kšœ-˜-Kšœ%˜%Kšœ ˜ Kšœ*˜*Kšœ6˜6Kšœ(˜(Kšœ5˜5Kšœ0˜0KšœD˜DKšœ"˜"Kšœ2˜2Kšœ#˜#Kšœ*˜*Kšœ ˜ Kšœ.˜.Kšœ.˜.Kšœ(˜(Kšœ,˜,K˜—K˜Kšœ˜—…—1‚C΄