<> <> <> <> <> DIRECTORY Basics USING [BITAND, BITXOR, bitsPerWord], DoradoInputOutput USING [InputNoPE, Output], PrincOps USING [zMISC, NoTimeout], PrincOpsUtils USING [AllocateNakedCondition, ConditionPointer], Process USING [Detach, InitializeCondition, priorityRealTime, SetPriority], RasterControllerDorado, RasterControllerFace; RasterControllerHeadDorado: CEDAR MONITOR IMPORTS Basics, DoradoInputOutput, PrincOpsUtils, Process, RasterControllerDorado, RasterControllerFace EXPORTS RasterControllerFace ~ BEGIN OPEN RasterControllerDorado, RasterControllerFace; <> hardwareScanlineWords: PUBLIC NAT _ 4096; hardwareScanlinePages: PUBLIC NAT _ hardwareScanlineWords / wordsPerPage; hardwareScanlineBits: NAT _ hardwareScanlineWords * Basics.bitsPerWord; interruptMask: WORD; ltMicrocodeCondition: PrincOpsUtils.ConditionPointer; channelProcs: ARRAY ExtendedChannel OF ChannelProc _ ALL[NIL]; mrbInUse: MRBPointer _ NIL; -- This is what we are really monitoring RegisterChannelProc: PUBLIC ENTRY PROC [channel: ExtendedChannel, proc: ChannelProc] ~ { ENABLE UNWIND => NULL; channelProcs[channel] _ proc; }; <<>> <> <<>> StartMicrocode: PUBLIC ENTRY PROC [mrb: MRBPointer] RETURNS [ok: BOOL] ~ TRUSTED { ENABLE UNWIND => NULL; CallMicrocode: PROC [MRBPointer] RETURNS [ok: BOOL] ~ TRUSTED MACHINE CODE {PrincOps.zMISC, 245B}; mrb.status _ nullLTStatus; IF ok _ CallMicrocode[mrb] THEN { mrbInUse _ mrb; Process.Detach[FORK WatchMicrocodeCondition[]]; }; RETURN[ok]; }; WatchMicrocodeCondition: ENTRY PROC ~ TRUSTED { ENABLE UNWIND => NULL; Xor: PROC [arg1, arg2: LTStatus] RETURNS [LTStatus] ~ TRUSTED INLINE { RETURN[LOOPHOLE[Basics.BITXOR[LOOPHOLE[arg1], LOOPHOLE[arg2]]]]; }; oldStatus, newStatus, status: LTStatus _ nullLTStatus; Process.SetPriority[Process.priorityRealTime]; UNTIL newStatus.microcodeDone DO oldStatus _ newStatus; WHILE mrbInUse#NIL AND oldStatus = (newStatus _ mrbInUse.status) DO WAIT ltMicrocodeCondition; ENDLOOP; IF mrbInUse=NIL THEN EXIT; status _ Xor[oldStatus, newStatus]; -- isolate only what changed FOR chan: ExtendedChannel IN ExtendedChannel DO proc: ChannelProc _ channelProcs[chan]; IF proc#NIL AND (status.channels[chan]#nullChannelStatus OR newStatus.microcodeDone) THEN proc[chan, status, newStatus]; ENDLOOP; ENDLOOP; mrbInUse _ NIL; }; KillMicrocodeWatcher: ENTRY PROC ~ TRUSTED { ENABLE UNWIND => NULL; IF mrbInUse#NIL THEN { mrbInUse.status.microcodeDone _ TRUE; NOTIFY ltMicrocodeCondition^; }; }; <> ResetMicrocode: PUBLIC PROC [] = TRUSTED BEGIN resetAll: WORD ~ 400B; DoradoInputOutput.Output[resetAll, taskCmd]; KillMicrocodeWatcher[]; END; ShutupMicrocode: PUBLIC PROC [] = TRUSTED BEGIN shutupAll: WORD ~ 140000B; DoradoInputOutput.Output[shutupAll, taskCmd]; KillMicrocodeWatcher[]; END; config0: Config0 _ [FALSE, 0, TRUE, FALSE, 0, FALSE, 0]; -- On_AHSync'dly SetUpForRealLineSync: PUBLIC PROC ~ TRUSTED { config0.AHSyncGetsROSSync _ TRUE; DoradoInputOutput.Output[LOOPHOLE[config0], config0Cmd]; }; SetUpForFakeLineSync: PUBLIC PROC ~ TRUSTED { config0.AHSyncGetsROSSync _ FALSE; DoradoInputOutput.Output[LOOPHOLE[config0], config0Cmd]; }; SetUpForRosClock: PUBLIC PROC ~ TRUSTED { config0.ABGetsAEdgeClk _ TRUE; config0.ABGetsTestClk _ FALSE; DoradoInputOutput.Output[LOOPHOLE[config0], config0Cmd]; }; SetUpForFakeClock: PUBLIC PROC ~ TRUSTED { config0.ABGetsAEdgeClk _ FALSE; config0.ABGetsTestClk _ FALSE; DoradoInputOutput.Output[LOOPHOLE[config0], config0Cmd]; }; SetUpForTestClock: PUBLIC PROC ~ TRUSTED { config0.ABGetsAEdgeClk _ FALSE; config0.ABGetsTestClk _ TRUE; DoradoInputOutput.Output[LOOPHOLE[config0], config0Cmd]; }; LineSync: PUBLIC PROC ~ TRUSTED { DoradoInputOutput.Output[2000B, taskCmd]; }; FakePixelClock: PUBLIC PROC ~ TRUSTED { DoradoInputOutput.Output[1000B, taskCmd]; }; CheckConfig: PUBLIC PROC RETURNS [HardwareConfig] ~ TRUSTED { RETURN[LOOPHOLE[DoradoInputOutput.InputNoPE[config1Cmd], HardwareConfig]]; }; <> InitializeMRB: PUBLIC PROC [mrb: MRBPointer, stb: STBPointer _ NIL, aRCB, bRCB, cRCB: RCBPointer _ NIL, ccb: CCBPointer _ NIL, flags: CARDINAL _ 0 ] ~ TRUSTED { mrb.seal _ goodMRBSeal; mrb.stb _ stb; mrb.rcb[A] _ aRCB; mrb.rcb[B] _ bRCB; mrb.rcb[C] _ cRCB; mrb.ccb _ ccb; mrb.flags _ flags; mrb.interruptMask _ interruptMask; mrb.status _ nullLTStatus; }; InitializeRCB: PUBLIC PROC [ rcb, next: RCBPointer _ NIL, bitmap: LONG POINTER _ NIL, activeWordsPerLine: CARDINAL _ 0, wordsPerLine: CARDINAL _ 0, lines: INTEGER _ 0, --Total number of scans to read fMargin: CARDINAL _ 0, sRepeat, fRepeat: INTEGER _ 0, sReverse, fReverse: BOOL _ FALSE, mosaic: BOOL _ FALSE, bitsPerSample: [0..bitsPerWord] _ 1] ~ TRUSTED { samplesPerWord: CARDINAL ~ 16/bitsPerSample; indexMask: CARDINAL ~ SELECT bitsPerSample FROM 1 => 177777B, 2 => 177776B, 4 => 177774B, 8 => 177770B, 10, 12, 16 => 177760B, ENDCASE => ERROR; -- BadItemSize[bitsPerSample]; bmValid: BOOL ~ bitmap#NIL; munches: INTEGER _ (activeWordsPerLine+15)/16; --Picks up an extra realBPS: [0..bitsPerWord] _ SELECT bitsPerSample FROM 1 => 1, 2 => 2, 4 => 4, 8 => 8, 10, 12, 16 => 16, ENDCASE => ERROR; packedFMargin: CARDINAL _ fMargin*realBPS; --align it for the hardware wordsPerLine _ RoundUpC[wordsPerLine, 16]; --Actually should generate ERROR if wordsPerLine#words rcb^ _ [ seal: goodRCBSeal, next: next, extraLines: lines-2, repeatCnt: sRepeat-1, ccr: [ itemClockRes: 15-fRepeat, reverse: fReverse, mosaic: mosaic, itemIs10Bit: bitsPerSample >= 10, itemIs12Bit: bitsPerSample >= 12, itemSize: SELECT bitsPerSample FROM 1 => b1, 2 => b2, 4 => b4, 8 => b8, 10 => b10, 12 => b12, 16 => b12, -- hardware can handle at most 12 bits ENDCASE => ERROR ], handshake: [bmValid, 0], bitmap: IF sReverse THEN bitmap+(LONG[lines-1]*LONG[wordsPerLine]) ELSE bitmap, activeMunches: munches-1, wordsPerLine: IF sReverse THEN -wordsPerLine ELSE wordsPerLine, indexIntoBuffer: Basics.BITAND[(IF fReverse THEN (activeWordsPerLine*16)+packedFMargin-1 ELSE hardwareScanlineBits-packedFMargin), indexMask], status: [ bitmapAddrValid: FALSE, ws: 0, rcbComplete: FALSE ] ]; }; InitializeCCB: PUBLIC PROC [ ccb, next: CCBPointer _ NIL, bitmap: LONG POINTER _ NIL, words: CARDINAL _ 0, lines: INTEGER _ 0, --Total number of scans to read fMargin: CARDINAL _ 0, sRepeat, fRepeat: INTEGER _ 0, sReverse, fReverse: BOOL _ FALSE, bitsPerSample: [0..bitsPerWord] _ 1, cursorCtl: CursorCtl _ defaultCursorCtl, modeCtl: ModeCtl _ defaultModeCtl, halftoneCtl: HalftoneCtl _ defaultHalftoneCtl, selCtl: SelCtl _ defaultSelCtl] ~ TRUSTED { samplesPerWord: CARDINAL ~ 16/bitsPerSample; alignedFMargin: CARDINAL ~ RoundUpC[fMargin, samplesPerWord]; fMarginWords: CARDINAL ~ alignedFMargin/samplesPerWord; bmValid: BOOL ~ bitmap#NIL; munches: INTEGER _ (fMarginWords+words+15)/16; --Picks up an extra wordsPerLine: CARDINAL _ RoundUpC[words, 16]; --Actually should generate ERROR if wordsPerLine#words ccb^ _ [ seal: goodRCBSeal, next: next, extraLines: lines-2, repeatCnt: sRepeat-1, ccr: [ itemClockRes: 15-fRepeat, reverse: fReverse, itemIs10Bit: bitsPerSample >= 10, itemIs12Bit: bitsPerSample >= 12, itemSize: SELECT bitsPerSample FROM 1 => b1, 2 => b2, 4 => b4, 8 => b8, 10 => b10, 12 => b12, 16 => b12, -- hardware can handle at most 12 bits ENDCASE => ERROR ], handshake: [bmValid, 0], bitmap: IF sReverse THEN bitmap+(LONG[lines-1]*LONG[wordsPerLine]) ELSE bitmap, activeMunches: munches-1, wordsPerLine: IF sReverse THEN -wordsPerLine ELSE wordsPerLine, indexIntoBuffer: IF fReverse THEN (wordsPerLine+fMarginWords)*16-1 ELSE 0, status: [ bitmapAddrValid: FALSE, ws: 0, rcbComplete: FALSE ], cursorCtl: cursorCtl, modeCtl: modeCtl, halftoneCtl: halftoneCtl, selCtl: selCtl ]; }; BitsPerSample: PUBLIC PROC [lgBitsPerPixel: [0..4]] RETURNS [[0..bitsPerWord]] ~ { RETURN [SELECT lgBitsPerPixel FROM 0 => 1, 1 => 2, 2 => 4, 3 => 8, 4 => 16, ENDCASE => ERROR]; }; PixelsPerWord: PROC [lgBitsPerPixel: [0..4]] RETURNS [[0..bitsPerWord]] ~ { RETURN [SELECT lgBitsPerPixel FROM 0 => 16, 1 => 8, 2 => 4, 3 => 2, 4 => 1, ENDCASE => ERROR]; }; Init: PROC ~ TRUSTED { [ltMicrocodeCondition, interruptMask] _ PrincOpsUtils.AllocateNakedCondition[]; Process.InitializeCondition[ltMicrocodeCondition, PrincOps.NoTimeout]; }; Init[]; END.