DIRECTORY Basics USING [DoubleShiftRight, LongMult, bitsPerWord], 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], Process USING [Detach, Pause, MsecToTicks, Priority, GetPriority, priorityBackground, priorityFaultHandlers, priorityRealTime, SecondsToTicks, SetPriority, SetTimeout], PrincOps USING [bitsPerWord, wordsPerPage, BBTableSpace, BBptr], PrincOpsUtils USING [BITBLT, AlignedBBTable, AllocateNakedCondition], RavenDriver, RavenFace, Rope USING [ROPE], VM USING [Allocate, Interval, PageCount, PagesForWords, Pin ]; RavenDriverImpl: MONITOR IMPORTS Basics, CountedVM, FontTune, Imager, ImagerFastShow, ImagerPixelMap, Loader, Process, PrincOpsUtils, RavenFace, VM 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, RavenFace.size[slow], RavenFace.size[fast]]; numBands: NAT = (RavenFace.size[slow]+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: RavenFace.resolution[fast], pixelUnits: TRUE, fontTuner: fontTuner]; Imager.SetPriorityImportant[context, TRUE]; Imager.RotateT[context, -90.0]; Imager.TranslateT[context, [-RavenFace.size[slow], 0]]; Imager.ScaleT[context, RavenFace.resolution[fast]/Imager.metersPerInch]; END; lastPaperFeed: RavenFace.PaperSource _ bottom; 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; RavenFace.SetPageOffsets[ linesFromLeft: registration.short * registrationTabSize, wordTabFromBottom: DivideUp[divident: registration.long * registrationTabSize, divisor: PrincOps.bitsPerWord]]; END; -- SetRegistration 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 [] = BEGIN ENABLE UNWIND => NULL; UNTIL ReadyStatus[currStatus] DO WAIT newStatus ENDLOOP; END; WaitPageSync: ENTRY PROC [] = BEGIN ENABLE UNWIND => NULL; UNTIL currStatus = pageSync OR ErrorStatus[currStatus] DO WAIT newStatus; IF ErrorStatus[currStatus] THEN {error _ TRUE; EXIT}; ENDLOOP; END; WaitBand: ENTRY PROC [band: RavenFace.Index] RETURNS [BOOL] = INLINE BEGIN ENABLE UNWIND => NULL; WHILE RavenFace.BandFull[band] DO WAIT dataCondition^; IF RavenFace.BandFull[band] THEN {Process.SetPriority[old]; RETURN[TRUE]}; EXIT; ENDLOOP; RETURN[FALSE]; END; bbTableSpace: PrincOps.BBTableSpace; bb: PrincOps.BBptr ~ PrincOpsUtils.AlignedBBTable[@bbTableSpace]; band, firstBand: RavenFace.Index; bandAddr: LONG POINTER; totalBands: CARDINAL = pixelMap.refRep.lines/16+1; bandsToGo: CARDINAL _ pixelMap.refRep.lines/16+1; paperTray: RavenFace.PaperSource _ SELECT paperFeed FROM bottom => bottom, top => top, alternating => IF lastPaperFeed = bottom THEN top ELSE bottom, ENDCASE => bottom; dstBpl: INTEGER ~ PrincOps.wordsPerPage*Basics.bitsPerWord; printing _ TRUE; lastPaperFeed _ paperTray; RavenFace.WakeUp[]; WaitReady[]; IF error THEN GOTO OutErr; [firstBand: band, firstBandAddress: bandAddr] _ RavenFace.ResetBands[]; firstBand _ band; FOR i: CARDINAL IN [0 .. RavenFace.MaxBands-2) DO sourceAddr: LONG POINTER _ pixelMap.refRep.pointer + Basics.LongMult[(totalBands - bandsToGo), pixelMap.refRep.rast*sizeEachBand]; bb^ _ [ dst: [word: bandAddr, bit: 0], dstBpl: dstBpl, src: [word: sourceAddr, bit: 0], srcDesc: [srcBpl[pixelMap.refRep.rast*Basics.bitsPerWord]], height: sizeEachBand, width: pixelMap.fSize, flags: [direction: forward, disjoint: TRUE, disjointItems: TRUE, gray: FALSE, srcFunc: null, dstFunc: null] ]; PrincOpsUtils.BITBLT[bb]; [nextBand: band, nextBandAddress: bandAddr] _ RavenFace.AdvanceBand[band]; bandsToGo _ bandsToGo - 1; IF bandsToGo = 0 THEN EXIT; ENDLOOP; BEGIN ENABLE UNWIND => Process.SetPriority[old]; Process.SetPriority[Process.priorityFaultHandlers]; RavenFace.Feed[paperTray, aligned]; WaitPageSync[]; RavenFace.StartImage[firstBand: firstBand]; DO sourceAddr: LONG POINTER _ pixelMap.refRep.pointer + Basics.LongMult[(totalBands - bandsToGo), pixelMap.refRep.rast*sizeEachBand]; bb^ _ [ dst: [word: bandAddr, bit: 0], dstBpl: dstBpl, src: [word: sourceAddr, bit: 0], srcDesc: [srcBpl[pixelMap.refRep.rast*Basics.bitsPerWord]], height: sizeEachBand, width: pixelMap.fSize, flags: [direction: forward, disjoint: TRUE, disjointItems: TRUE, gray: FALSE, srcFunc: null, dstFunc: null] ]; timeout _ WaitBand[band]; IF timeout THEN GOTO Out; PrincOpsUtils.BITBLT[bb]; [nextBand: band, nextBandAddress: bandAddr] _ RavenFace.AdvanceBand[band]; bandsToGo _ bandsToGo - 1; IF bandsToGo = 0 THEN EXIT; ENDLOOP; RavenFace.LastBand[band]; -- indicate that last band has been filled timeout _ WaitBand[band]; IF timeout 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: RavenFace.PrinterStatus _ noStatus; mySP: REF StatusProc _ NIL; printing: BOOL _ FALSE; newStatus: CONDITION; MonitorRavenStatus: PROC [] = BEGIN WaitStatus: ENTRY PROC [] = BEGIN ENABLE UNWIND => NULL; ready: BOOL _ FALSE; UNTIL ready DO WAIT statusCondition^; ready _ TRUE; ENDLOOP; END; Note: ENTRY PROC [] = {ENABLE UNWIND => NULL; BROADCAST newStatus}; messageInternal: Message _ commandStatusFault; Process.SetPriority[Process.priorityRealTime]; DO -- Forever WaitStatus[]; currStatus _ RavenFace.SolicitStatus[]; IF currStatus = pageSync THEN {Note[]; LOOP}; SELECT currStatus FROM onLine, statusOverRun, noStatus, parityError, illegalCharacter, 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, noPaper, 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, noPaper => 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: RavenFace.PrinterStatus] RETURNS [ready: BOOL] = INLINE BEGIN ready _ SELECT status FROM standBy, readyToFeed => TRUE, ENDCASE => FALSE; END; ErrorStatus: PROC [status: RavenFace.PrinterStatus] RETURNS [error: BOOL] = INLINE BEGIN error _ SELECT status FROM feederFault, registrationJam, fuserJam, noExit, interlockOpen, fuserCold, noPaper, 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}; wordsPerBand: CARDINAL = sizeEachBand * PrincOps.wordsPerPage; sizeEachBand: CARDINAL = 16; pagesNeedForBands: VM.PageCount = RavenFace.MaxBands * sizeEachBand + 20; vm: VM.Interval; activeLength: (0..PrincOps.wordsPerPage] _ (RavenFace.size[fast]+15)/16; offset: [0..PrincOps.wordsPerPage) = PrincOps.wordsPerPage - activeLength; 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]; RavenFace.AllocateBands[vm, RavenFace.MaxBands, sizeEachBand]; RavenFace.SetScanLineLength[activeLength]; myPixelMap _ MakePrinterPixelMap[]; secondPixelMap _ MakePrinterPixelMap[]; Loader.MakeProcedureResident[PrintFromPixelMap]; Loader.MakeGlobalFrameResident[PrintFromPixelMap]; [statusCondition, statusMask] _ PrincOpsUtils.AllocateNakedCondition[]; [dataCondition, dataMask] _ PrincOpsUtils.AllocateNakedCondition[]; Process.SetTimeout[dataCondition, Process.SecondsToTicks[20]]; RavenFace.SetInterruptMasks[0, statusMask, dataMask]; RavenFace.WakeUp[]; -- Jump start the Raven Process.Detach[FORK MonitorRavenStatus[]]; END; ropeStatus: ARRAY RavenFace.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[illegalCharacter] _ "illegalCharacter"; ropeStatus[illegalSequence] _ "illegalSequence"; ropeStatus[noPaper] _ "Paper Tray Open or Out of Paper"; ropeStatus[pageSync] _ "pageSync"; ropeStatus[pageAtOutputTray] _ "pageAtOutputTray"; ropeStatus[tonerLow] _ "Toner Low"; ropeStatus[goingOffLine] _ "goingOffLine"; ropeStatus[offLine] _ "offLine"; ropeStatus[onLine] _ "onLine"; ropeStatus[outputTrayFull] _ "outputTrayFull"; ropeStatus[aboutToDozeOff] _ "Low Power Mode"; ropeStatus[statusError] _ "statusError"; ropeStatus[statusOverRun] _ "statusOverRun"; Init[]; END. ΘRavenDriverImpl.mesa Copyright c 1985, 1986 by Xerox Corporation. All rights reserved. Tim Diebert: January 22, 1987 12:18:29 pm 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 WHILE RavenFace.BandFull[band] DO WAIT dataCondition^; ENDLOOP; Refill bands when they have been imaged until input is exhausted set message and broadcast newMessage Κ p˜™Icodešœ Οmœ7™BK™-K™,K™/—K˜šΟk ˜ Kšœžœ+˜7Kšœ žœ˜)Kšœ žœ˜!KšœžœM˜YKšœžœ ˜Kšœžœ1˜EKšœ žœ ˜Kšœžœ2˜>Kšœžœ›˜¨Kšœ žœ2˜@Kšœžœžœ*˜EKšœ ˜ Kšœ ˜ Kšœžœžœ˜Kšžœžœ6˜>—K˜K˜KšΠlnœž˜Kšžœqž˜zKšžœ ˜šœžœžœ ˜K˜Kšœ9žœ˜>Kšœ=žœ˜BK˜Kš Οnœžœžœžœ(žœ˜cK˜š œž œ'ž˜MKšœ\˜\Kšœ žœ!˜.Kšœ žœ˜-Kšœžœ˜!Kšœžœžœ+˜?Kšœžœžœ˜*Kšœ7˜7Kšœ žœ˜$šœžœžœ˜KKšœ.˜.Kšœ9˜9—š žœžœ žœžœΟc ˜SKšžœ$žœ˜CK•StartOfExpansion[Process.Milliseconds]šœ*‘)˜SKšžœ˜—Kšœ˜Kšœ˜Kšœ˜KšœO˜OKšœ˜Kšžœ˜—K˜š  œžœžœ:žœžœžœž˜Kšœ$žœ˜(Kšžœžœžœ6˜RKšœežœ˜Kšœ%žœ˜+K˜Kšœ7˜7KšœH˜HKšžœ˜—K˜K˜.K˜K˜š  œžœž œ%žœž˜SKš œž œžœžœ žœžœžœžœžœ0žœ˜ Kšœ6™6˜Kšœ8˜8Kšœo˜o—Kšžœ‘˜K˜—š  œžœžœ-žœ6žœ3ž˜ΘKšžœžœžœ˜#Kšœžœžœ˜Kšœ.˜.š  œžœžœžœžœžœžœ˜7šžœž˜ Kšžœ žœ˜—Kšžœ˜—š  œžœžœžœžœžœžœ˜:šžœžœž˜9Kšžœ ˜Kš žœžœ žœžœžœ˜>—Kšžœ˜—š  œžœžœžœžœžœž˜JKšžœžœžœ˜Kšžœžœžœžœ™?šžœž˜!Kšžœ˜Kšžœžœžœžœ˜JJšžœ˜Kšžœ˜—Kšžœžœ˜Kšžœ˜K˜—K˜$KšœA˜AKšœ,žœžœ˜9Kšœ žœ˜2Kšœ žœ˜1šœ#žœ ž˜8K˜K˜ Kšœžœžœžœ˜>Kšžœ ˜—Kšœžœ,˜;Kšœ žœ˜Kšœ˜K˜K˜ Kšžœžœžœ˜KšœG˜GKšœ˜šžœžœžœž˜1Kšœ žœžœj˜‚šœ˜Kšœ˜Kšœ˜Kšœ ˜ Kšœ;˜;Kšœ˜Kšœ˜Kšœ&žœžœžœ˜kK˜—Kšœžœ˜KšœJ˜JKšœ˜Kšžœžœžœ˜Kšžœ˜—šžœžœžœ˜0Kšœ3˜3Kšœ#˜#Jšœ˜J˜+Jšœ@™@šž˜Kšœ žœžœj˜‚šœ˜Kšœ˜Kšœ˜Kšœ ˜ Kšœ;˜;Kšœ˜Kšœ˜Kšœ&žœžœžœ˜kK˜—Jšœ˜Jšžœ žœžœ˜Kšœžœ˜KšœJ˜JKšœ˜Jšžœžœžœ˜Jšžœ˜—Jšœ‘*˜EJšœ˜Jšžœ žœžœ˜Kšœ žœ˜Kšžœžœžœ"˜PKšžœ˜—Kšœ˜Kšžœ ˜&Kšžœ žœ!˜7Kšžœ˜K˜—Kšœ/˜/Kšœžœžœ˜Kšœ žœžœ˜Kšœ ž œ˜K˜š œžœž˜#š  œžœžœžœžœžœžœ˜8Kšœžœžœ˜šžœž˜Kšžœžœžœ˜-—Kšžœ˜—Kš œžœžœžœžœžœž œ ˜CKšœ.˜.Kšœ.˜.šžœ‘ ˜ K˜ Kšœ'˜'Kšžœžœ žœ˜-šžœ ž˜šœa‘˜~Kšžœ"žœžœ‘˜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˜š   œžœ#žœ žœžœž˜Xšœž œž˜Kšœžœ˜Kšžœžœ˜—Kšžœ˜—K˜š   œžœ#žœ žœžœž˜Xšœž œž˜Kšœ†žœ˜‹Kšžœžœ˜—Kšžœ˜K˜—Kš  œžœžœžœžœ˜WK˜Kš  œžœžœžœžœ˜HK˜K˜Kšœžœ(˜>Kšœžœ˜Kšœžœ4˜IKšœžœ ˜KšœH˜HKšœJ˜JK˜Kš œžœžœžœž œžœžœ˜GKš œžœžœžœž œžœ žœ˜CK˜š œžœž˜Kšœžœ˜$Kšœ>˜>Kšœ*˜*Kšœ#˜#Kšœ'˜'Kšœ0˜0Kšœ2˜2KšœG˜GKšœC˜CKšœ>˜>Kšœ5˜5Kšœ‘˜,Kšœžœ˜*Kšžœ˜—K˜Kš œ žœžœžœžœ˜FKšœ#˜#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šœ2˜2Kšœ0˜0Kšœ8˜8Kšœ"˜"Kšœ2˜2Kšœ#˜#Kšœ*˜*Kšœ ˜ Kšœ˜Kšœ.˜.Kšœ.˜.Kšœ(˜(Kšœ,˜,K˜—K˜Kšžœ˜—…—/|=΄