// PrintSlot.bcpl - SLOT printing code // last modified by Ramshaw, November 29, 1983 10:27 AM // - Added RavenPowerOnFlag hack // last modified by Butterfield, October 6, 1980 5:10 PM // - SetSCB, add .invert = InvertMode - 10/6/80 get "PressInternals.df" get "PressParams.df" get "SlotDefs.d" //outgoing procedures external [ PSlot;SLOTInit ] //outgoing statics external [ SLOTScanLength //To give to 3100 interface SLOTScanMarginAdjust //Adjustments to add to user input SLOTBitMarginAdjust SLOTDouble SLOTTimeOut ] static [ SLOTScanLength=384*11+48 SLOTScanMarginAdjust=36 SLOTBitMarginAdjust=12 SLOTDouble SLOTTimeOut=10 ] //incoming procedures external [ //PRESSML Ugt //OS Zero;MoveBlock;Timer;StartIO //PRINT PrintError //WINDOW FileVDA //PRINTDISKTRIDENT SetDA ] //incoming statics external [ BitsFile Report InvertMode RavenPowerOnFlag ] //internal statics static [ bufferEmpty=0; PrintFail=0; IllegalState=0; readErrors=0 vDA ReadNext; PrintNext readCount; printCount SectorsPerBuff ] // S L O T Definitions: structure RS [ blank byte Spare2 bit Wait bit //complement signal PaperJam bit //complement signal AddPaper bit //complement signal SelectB bit Ready bit LineSync bit PageSync bit //complement signal ] manifest NormalizeStatus = #161 //use to uncomplement above signals structure SCB [ blank bit 14 COM bit 2 // Command Beam On #0 // Command Status #1 // Command Reset #2 // Command Print #3 BlowUp bit // Make-one-bit-into-four; true select option LastPage bit // Marks this command as the last page if true invert bit // inverts the page bitsPerLine bit 13 // Servo Count for number of bits per line bitMargin word // Bottom Margin (bits) scanLineWc word // Double Word Count scanMargin word // Left Margin (bits before print in portrait) scansPerPage word // Total number of Scan Lines per page bufferPtr word // Print Buffer Base Address (first loc.) scanLineWcInc word // Print Buffer Scan Line Increment scansPerBuff word // Print-mode Buffer Length currentBuff word // Current Buffer Address currentLine word // Current Scan Address SW word = @RS // Return Status Word ] manifest lSCB = size SCB/16 manifest [ SCBloc=#720 slotSIObit=4 BeamOnCommand=0 StatusCommand=1 ResetCommand=2 PrintCommand=3 ] // T R I D E N T D I S K defintions structure DCB [ diskAddress word 2 //DCB+0 & DCB+1 drive word //DCB+2 nextDC word //DCB+3 ID word //DCB+4 CommH word //DCB+5 CountH word //DCB+6 AddrH word //DCB+7 ECC0H word //DCB+8 ECC1H word //DCB+9 StatusH word //DCB+10 CommL word //DCB+11 CountL word //DCB+12 AddrL word //DCB+13 ECC0L word //DCB+14 ECC1L word //DCB+15 StatusL word //DCB+16 CommD word //DCB+17 CountD word //DCB+18 AddrD word //DCB+19 ECC0D word //DCB+20 ECC1D word //DCB+21 StatusD word //DCB+22 endWord word //DCB+23 ] manifest lDCB = size DCB/16 manifest [ KBLK = #640; diskWordsPerPage=1024 diskCheck = #4104; diskRead = #104; DCBseal = #122645 diskSIOStart=#40 RTC=#430 Active=#453 parityInterruptBit=1 WakeupsWaiting=#452 ] let SLOTInit() be [ SLOTCommand(Reset) SLOTCommand(BeamOn) SlotReady() ] and PSlot(pg, numBands, last, firstAdr, lastAdr) be [ let oldActive=@Active @Active=oldActive&(not parityInterruptBit) let firstBuff=(firstAdr+2)&(-2) let buffLen=nil let da=nil // Make an effort to print blank pages. Otherwise, color sync // on 6500 will be screwed up. test numBands gr 0 then [ buffLen=1024*((pg>>PageG.BitWc*BANDWidth+1023)/1024)+2 da=FileVDA(BitsFile, pg>>PageG.BitPage) ] or [ buffLen=1024 da=-1 pg>>PageG.FirstBand=10 pg>>PageG.BitMargin=16*10 pg>>PageG.BitWc=4 numBands=1 ] let buff=firstBuff for i=1 to 20 do [ if Ugt(buff+buffLen, lastAdr) then break let nb=buff+buffLen if da eq -1 then Zero(buff, buffLen) buff!-1=nb buff=nb ] buff!(-buffLen-1)=firstBuff //On exit from loop, buff is just after last legal buffer let v=vec lSlotStatus [Retry SLOTPrint( (last? LastPage,NormalPage), pg>>PageG.FirstBand*BANDWidth, pg>>PageG.BitMargin, pg>>PageG.BitWc*16, numBands*BANDWidth, BANDWidth, da, firstBuff, v) let SlotError=(v!Ready eq 0)&((v!Wait % v!PaperJam % v!PaperOut % v!Illegal % v!PageNotPrinted) ne 0) //Only worry about clearing or cleaning up Slot Errors (not disk errors) test SlotError then [ SLOTCommand(Reset) SlotReady(v) ] or break ]Retry repeat @WakeupsWaiting=@WakeupsWaiting&(not parityInterruptBit) @Active=oldActive ] and SlotReady(v; numargs n) be [ let vv=vec 10 if n eq 0 then [ v=vv; SLOTStatus(v) ] [checkStatus if v!Ready then return SLOTCommand(Reset) //Kill print request let i=0 if v!PaperOut then [ i=1 compileif ReportSw then [ Report>>REP.PaperOut=true ] ] if v!PaperJam then [ i=2 compileif ReportSw then [ Report>>REP.Jams=Report>>REP.Jams+1 ] ] test ((RavenPowerOnFlag ne 0) & (i eq 2)) ifso PrintError(2, 15000) //Signal error, wait for CR or timeout ifnot PrintError(i) //Signal error, wait for fix... SLOTCommand(Reset) SLOTCommand(BeamOn) SLOTStatus(v) ]checkStatus repeat ] // SLOT Procedures and SLOTStatus(v) be [ let scb=vec lSCB scb=SetSCB(scb) scb>>SCB.COM = StatusCommand scb>>SCB.SW = NormalizeStatus @SCBloc = scb StartIO(slotSIObit) MsWait(20) //give microcode long enough to see the new command if scb>>SCB.SW eq NormalizeStatus then IllegalState = true scb>>SCB.SW = scb>>SCB.SW xor NormalizeStatus v!Wait = scb>>SCB.Wait v!PaperJam = scb>>SCB.PaperJam v!PaperOut = scb>>SCB.AddPaper v!Illegal = IllegalState v!PageNotPrinted = PrintFail v!Overrun = bufferEmpty v!DiskError = readErrors v!Ready = scb>>SCB.Ready & ((v!Wait % v!PaperJam % v!PaperOut % v!Illegal % v!PageNotPrinted % v!Overrun % v!DiskError) eq 0) ] and SLOTCommand(comm) be [ let scb=vec lSCB scb=SetSCB(scb) switchon comm into [ case SetDensity: case BeamOn: [ scb>>SCB.COM = BeamOnCommand; endcase ] case Reset: [ IllegalState = false PrintFail = false bufferEmpty = false readErrors = 0 ] //!!! no endcase case StopPrint: case BeamOff: [ scb>>SCB.COM = ResetCommand; endcase ] default: [ IllegalState = true;return ] ] @ SCBloc = scb StartIO(slotSIObit) for i = 0 to 30000 do if scb>>SCB.SW then break if scb>>SCB.SW eq 0 then IllegalState=true if comm eq BeamOn then MsWait(1000) ] and SLOTPrint(lastPage, scanMargin, bitMargin, scanLength, numScans, scansPerBuffer, DA, bufferList, V) be [ vDA = DA let useDisk = DA ne -1 readErrors = 0; PrintFail=0 let scb=vec lSCB scb=SetSCB(scb) scb>>SCB.COM = PrintCommand scb>>SCB.LastPage = lastPage scb>>SCB.bitMargin = bitMargin + SLOTBitMarginAdjust scb>>SCB.scanLineWc = scanLength rshift 5 scb>>SCB.scanMargin = scanMargin + SLOTScanMarginAdjust scb>>SCB.scansPerPage = numScans let currentBuff = bufferList scb>>SCB.bufferPtr = currentBuff scb>>SCB.currentBuff = currentBuff let numWords = scanLength rshift 4 scb>>SCB.scanLineWcInc = numWords scb>>SCB.scansPerBuff = scansPerBuffer rv SCBloc = scb // Compute how many buffers to process before done let BufferCount = (numScans+scansPerBuffer-1)/scansPerBuffer printCount = BufferCount readCount = BufferCount //Now get the disk spinning: SectorsPerBuff = (scansPerBuffer*numWords+1023)/1024 let labelBuff = vec 10 let dcbTable = vec 64*lDCB //Enough for all of memory! dcbTable=(dcbTable+1)&(-2) let dcb = dcbTable let buff = bufferList [ ReadNext = dcb for cnt = 0 to SectorsPerBuff-1 do [ Zero(dcb,lDCB) dcb>>DCB.nextDC = dcb + lDCB dcb>>DCB.CommH = diskCheck dcb>>DCB.CountH = 2 dcb>>DCB.AddrH = lv dcb>>DCB.diskAddress dcb>>DCB.CommL = diskRead dcb>>DCB.AddrL = labelBuff dcb>>DCB.CountL = 10 dcb>>DCB.CommD = diskRead dcb>>DCB.CountD = diskWordsPerPage dcb>>DCB.AddrD = buff + cnt*diskWordsPerPage unless useDisk then dcb>>DCB.StatusD = 1 dcb = dcb>>DCB.nextDC ] ReadBuffer(false) buff=buff!-1 ] repeatuntil buff eq bufferList (dcb-lDCB)>>DCB.nextDC = dcbTable ReadNext = dcbTable PrintNext = dcbTable if useDisk then [ StartIO(diskSIOStart) KBLK!2=-1; KBLK!3=-1 //Reset track memory @KBLK = dcbTable ] Start: //wait up to 10 seconds -- 2 page times for 'slow-to-grab' 3100's let timeOut = @RTC + SLOTTimeOut*27 //Read in the first load from the disk: until PrintBuffer() do if @RTC ge timeOut then [ readErrors=-1; PrintFail=-1; break ] bufferEmpty=0 //Now spin the Slot: unless PrintFail then [ml StartIO(slotSIObit) [ if scb>>SCB.currentBuff ne currentBuff then //started next buff [ currentBuff = scb>>SCB.currentBuff if useDisk then [ unless PrintBuffer() then break //must be full ReadBuffer(true) //read into emptied buff ] ] if scb>>SCB.SW then break if @RTC ge timeOut then [ PrintFail=1; break ] ] repeat ]ml @ KBLK = 0 //make sure disk wont start up SLOTStatus(V) if lastPage then [ MsWait(6000); SLOTCommand(Reset) ] ] and PrintBuffer() = valof [ if printCount eq 0 then resultis true printCount = printCount-1 let dcb = PrintNext for i = 1 to SectorsPerBuff do [ unless dcb>>DCB.StatusD then [ bufferEmpty = true; resultis false ] let status=dcb>>DCB.StatusH % dcb>>DCB.StatusL % dcb>>DCB.StatusD if status ne 1 then [ // if status ne #11 then [ readErrors=-1; resultis 0 ] readErrors = readErrors + 1 ] dcb = dcb>>DCB.nextDC ] PrintNext = dcb resultis true ] and ReadBuffer(startUp) be if readCount then [ readCount = readCount-1 let StartNext = ReadNext for i = 1 to SectorsPerBuff do [ SetDA(ReadNext, vDA); vDA=vDA+1 ReadNext>>DCB.StatusD = 0 ReadNext>>DCB.ID = DCBseal ReadNext = ReadNext>>DCB.nextDC ] if startUp ne 0 & @KBLK eq 0 then @KBLK = StartNext ] and SetSCB(scb) = valof [ Zero(scb, lSCB+1) let p=(scb+1)&(-2) p>>SCB.invert = InvertMode; p>>SCB.bitsPerLine=SLOTScanLength p>>SCB.BlowUp=SLOTDouble resultis p ] and MsWait(ms) be [ let timeOut = @RTC + ms/37 until @RTC ge timeOut do loop ] (1800)\39f1 199f0