.TITLE C2I .ENABL LC .IDENT /RICE01/ .MCALL QIO$S,QIOW$S,QIO$,DIR$,ASTX$S,DSAR$S,ENAR$S .MCALL EXIT$S,WSIG$S .LIST MEB .PSECT SW.SYS,D,RW,OVR,GBL .BLKW 1 INCRUN: .BLKW 2 ZERDAT: .BLKW 4 MTDIS: .BLKW 1 .PSECT ; ; C2 HEADERS (FIXED) ; C2.BHQ:: .WORD 0 ; POINTS TO FIRST BUFFER HEADER C2.BOQ:: .WORD 0 ; FIRST BUFFER OUTPUT BLOCK C2.BAQ:: .WORD 0 ; FIRST BUFFER STATUS BLOCK IN ANALYSIS C2.BAE: .WORD C2.BAQ ; LAST IN ANALYSIS C2.ACT:: .WORD 0 ; NUMBER OF BUFFS ANALYZED C2.OER:: .WORD 0 ; NUMBER OF BAD OUTPUTS C2.RUN:: .WORD 0 ; RUN # TERINI:: .WORD 0 ; STATUS INDICATOR ENDCNT: .WORD 0 ; COUNTS FLUSHED INPUT BUFFS ; 0 = END RUN (NON 0 = RUN) ; ; SUBROUTINE WITH COROUTINE TO SAVE R5-R0+ SET UP R5-R3 ; R5 = HEADER ; R4 = STATUS BUFFER ; R3 = DATA BUFFER ; C2SAV: MOV R3,-(SP) ; SAVE R3-R0 MOV R2,-(SP) MOV R1,-(SP) MOV R0,-(SP) MOV 10(SP),-(SP) ; SET UP RETURN ADDRESS MOV R4,12(SP) ; SAVE R4 MOV 14(SP),R4 ; R4 = STATUS BUFF. MOV R5,14(SP) ; SAVE R5 MOV BS.BHQ(R4),R5 ; R5 = BUFF HEADER MOV BS.ADD(R4),R3 ; R3 = DATA BUFFER JSR PC,@(SP)+ ; RETURN TO CALLER, THEN HERE MOV (SP)+,R0 ; RESTORE R0 TO R5 MOV (SP)+,R1 MOV (SP)+,R2 MOV (SP)+,R3 MOV (SP)+,R4 MOV (SP)+,R5 ASTX$S ; RETURN FROM AST ENAR$S ; IF REJECTED RETURN TO HERE RTS PC ; IF NOT AST NORMAL RETURN ; ; AST ENTRY WHEN DATA BUFFER INPUT DONE ; C2I:: JSR PC,C2SAV ; SET UP R5 TO R3 BITB #2,BH.EFG(R5) ; Is MAX buffer size requested ? BEQ 1$ ; No MOV BH.QIO+Q.IOPL+2(R5),BS.CNT(R4) ; Input size=MAX size 1$: DECB BH.ICT(R5) ; DECREMENT INPUT COUNT INC BH.CNT(R5) ; INCREMENT # OF BUFFERS INPUT MOV BH.CNT(R5),BF.ICT(R3) ; AND PUT INTO BUFFER MOV BS.CNT(R4),BF.CNT(R3) ; PUT INTO DATA BUFFER MOVB BS.STS(R4),BF.TYP+1(R3) ; SAVE ERROR TYPE FOR USER ; ;**** INSERT ERROR MESSAGES HERE LATER ; CMPB BH.AOP(R5),#1 ; CHECK ANALYSIS OPTION BLT OUTTST ; NO ANALYSIS BEQ ANAL ; MUST ANALYZE CMPB BH.ICT(R5),#1 ; CHECK STAT OF INPUT QUE BGT 2$ ; IT IS GOOD WITH 2 ENTRIES INCB BH.IMN(R5) ; NOT GOOD, REQUIRE MORE BUFFS IN QUE CMPB BH.IMN(R5),BH.BCT(R5) ; COMPARE REQUIRED #INPUT WITH TOT#BUFFS BLT 2$ ; IT IS LESS DECB BH.IMN(R5) ; NOW IS MAX - 1 2$: CMPB BH.ICT(R5),BH.IMN(R5) ; CHECK IF ENOUGH IN INPUT TO ANALYZE BLT NOANAL ANAL: CLR BS.ANQ(R4) ; THIS IS LAST IN ANALYSIS QUE MOV R4,@C2.BAE ; INSERT STATUS BUFFER INTO END OF QUE MOV R4,C2.BAE ; NOW IS LAST ENTRY ADD #BS.ANQ,C2.BAE ; POINTS TO LAST ENTRY QUE INC C2.ACT ; NUMBER ANALYZED MOV C2.ACT,BF.ACT(R3) ; ANALYSIS NUMBER TO BUFFER INCB BH.ACT(R5) ; ANALYSIS COUNT CLRB BS.ANL(R4) ; IN ANALYSIS QUE BR OUTTST NOANAL: CLR BF.ACT(R3) ; NO ANALYSIS TSTB BH.ACT(R5) ; TEST IF ANY IN ANALYSIS NOW BNE OUTTST ; YES DECB BH.IMN(R5) ; NO, LOWER MINIMUM BGT OUTTST INCB BH.IMN(R5) ; IS NOW 1 OUTTST: CMPB BH.OOP(R5),#1 ; TEST OUTPUT OPTION BLT NOOUT ; NO OUTPUT TST MTDIS ; DISABLED? BNE NOOUT ; YES BEQ OUT ; MUST OUTPUT TSTB BS.ANL(R4) ; TEST ANALYSIS STAT BEQ NOOUT ; IN ANALYSIS SO NO OUTPUT OUT: INCB BH.OCT(R5) ; INCRMENT OUTPUT COUNT MOV BH.BOQ(R5),R2 ; OUTPUT QUE ADDRESS INC BO.OCT(R2) ; INCREMENT OUTPUT COUNT MOV BO.OCT(R2),BF.OCT(R3) ; AND PUT IN BUFFER MOV BS.CNT(R4),R0 ; BUFFER SIZE LESS HEADER ADD #BF.DAT,R0 ; TOTAL BUFFER SIZE CMP R0,#14. ; IS IT MINIMUM SIZE? BGE 1$ ; YES MOV #14.,R0 ; NO, MAKE IT MIN. 1$: QIO$S #IO.WLB,BO.OLN(R2),,,R4,#C2OUT, RETN: RTS PC NOOUT: CLR BF.OCT(R3) ; NO OUTPUT TST BS.ANL(R4) ; IS BUFF IN ANALYSIS BEQ RETN ; YES, DO NOT RESTART INPUT ; ; SECTION TO QUE BUFFERS FOR INPUT ; C2STRT: TST TERINI ; ARE WE IN END MODE BEQ RUNDWN ; YES,DO NOT CONTINUE MOV R5,R1 ; WILL BE QIO ADD #BH.QIO,R1 ; POINTS TO QIO TST (R1) ; $QIO exists ? BEQ 2$ ; No, skip it INCB BH.ICT(R5) ; INCREMENT INPUT COUNT CLR BF.ICT(R3) ; NO INPUT COUNT TILL INPUT MOV R4,Q.IOSB(R1) ; IN/OUT STATUS MOV R3,Q.IOPL(R1) ; BUFFER ADDRESS ADD #BF.DAT,Q.IOPL(R1) ; NOW POINTS TO DATA DIR$ R1,ERROR ; EXECUTE QIO 2$: RTS PC RUNDWN: DEC ENDCNT ; DECREMENT RUNDOWN COUNT BNE 10$ ; NOT ZERO YET MOV #C2.BOQ,R2 ; Output que MOV #ENDBUF,R0 ; Buffer to write 1$: MOV (R2),R2 ; Done yet ? BEQ 10$ ; Yes CALL BEGWRT ; Write it BR 1$ ; Continue for more 10$: RETURN ; ; AST ENTRY WHEN OUTPUT DONE ; C2OUT: JSR PC,C2SAV ; SET UP R3-R5 ; ; **** HERE ISSUE ERROR MESSAGES LATER ; CMPB (R4),#IS.SUC ; WAS IT SUCCESS? BEQ 1$ ; YES CMPB (R4),#IE.EOT ; END OF TAPE? BEQ 2$ ; YES INC C2.OER ; INCREMENT OUTPUT ERROR COUNT BR 1$ 2$: MOV R5,-(SP) ; SAVE CHAN POINTER CALL KILLER ; KILL THIS RUN MOV (SP)+,R5 ; THIS CHAN 1$: DECB BH.OCT(R5) ; DECREMENT # OF BUFFS IN OUTPUT TSTB BS.ANL(R4) ; STILL IN ANALYSIS? BEQ RETN ; YES BR C2STRT ; NO, INSERT INTO INPUT QUE ; ; SUBROUTINE TO DECLARE ANALYSIS OF CURRENT BUFFER DONE ; RBTS:: DSAR$S ; DISABLE AST RECOGNITION MOV C2.BAQ,-(SP) ; CURRENT ANALYSIS BUFFER BNE 1$ ; BUFFER IS IN ANALYSIS ENAR$S ; REENABLE AST RECOGNITION TST (SP)+ ; POP STACK RTS PC 1$: JSR PC,C2SAV ; SIMULATE AST + REMOVE FROM INPUT QUE DECB BH.ACT(R5) ; ONE FEWER BUFF IN ANAL. INCB BS.ANL(R4) ; SET ANAL STAT TO ENDED OK MOV BS.ANQ(R4),C2.BAQ ; MOVE NEXT BUFFER UP IN ANAL QUE BNE 2$ ; NOT LAST ONE MOV #C2.BAQ,C2.BAE ; SET TO POINT TO LAST ENTRY IN LIST 2$: TSTB BS.STS(R4) ; IS IT OUT OF OUTPUT QUE? BNE C2STRT ; YES, PUT INTO INPUT QUE RTS PC ; NO, EXIT ; ; REJECTION ERROR ROUTINE ; ERROR: MOV $DSW,R0 ; PUT ERROR CODE IN R0 BPT RTS PC ; ; ROUTINE TO END C2 DATA ACQUISITION ; C2MESS: CLR -(SP) ; 2'ND WORD OF MESSAGE BLOCK MOV R0,-(SP) ; ADDRESS IF ASCIZ TEXT MOV SP,R0 ; POINTS TO MESSAGE BLOCK CLR R1 ; NON ERROR TYPE JSR PC,$ERRLG ; OUTPUT MESSAGE CMP (SP)+,(SP)+ ; POP STACK RETURN ENDMES: .ASCIZ /END run/ BEGMES: .ASCIZ /BEGIN run/ RUNMES: .ASCIZ /Continue RUN/ STPMES: .ASCIZ /STOP run/ .EVEN KILLER: TST TERINI ; Run already ended? BEQ 10$ ; Yes, do not kill CLR TERINI ; MAKE SURE WE ARE IN END MODE MOV #C2.BHQ,R5 ; GET FIRST BUFFER HEADER ADDRESS CLR ENDCNT ; NOW CLEAR END COUNTER 1$: MOV (R5),R5 ; GET FIRST HEADER BNE 2$ ; YES, MORE 10$: RETURN ; No more 2$: MOVB BH.QIO+Q.IOLU(R5),R0 ; LUN FOR INPUT QIO$S #IO.KIL,R0 ; KILL MIOP CHANNEL MOV BH.END(R5),R0 ; End command list CALL BEGCLS ; Execute END CLIST 3$: MOVB BH.BCT(R5),R0 ; NUMBER OF BUFFS THIS CHAN ADD R0,ENDCNT ; TOTAL NUMBER OF BUFFS BR 1$ ; CONTINUE ENDBUF: .WORD -1,-1,-1,-1,-1,-1,-1 CRUD: .WORD 0 ; ; ; C2END:: DSAR$S ; DISABLE AST RECOGNITION TST TERINI ; TEST IF RUN IN PROGRESS BNE 13$ ; YES, WE CAN END IT JMP FAILUR ; NO, DO NOT END 13$: CALL KILLER ; KILL ALL CHANS 4$: MOV #ENDMES,R0 ; END RUN MESSAGE CALL C2MESS ; OUTPUT BR SUCCES ; GIVE SUCCESSFUL END ; ; ROUTINE TO BEGIN C2 DATA ACQUISITION ; C2BEG:: DSAR$S ; DISABLE AST RECOGNITION TST TERINI ; TEST STATUS BNE FAILUR ; SKIP BEGIN TST ENDCNT ; BUFFS STILL IN USE? BNE FAILUR ; YES MOV #BEGMES,R0 ; BEGIN MESSAGE TO OUTPUT CALL C2MESS ; OUTPUT IT DEC TERINI ; ENABLE START MODE CLR C2.ACT ; CLEAR ANALYSIS COUNT TST INCRUN ; DO WE INCREMENT RUN#? BNE 1$ ; NO INC C2.RUN ; YES 1$: MOV C2.RUN,BEGBUF+2 ; Run number into buffer MOV #BEGBUF,R0 ; Buffer to write MOV #C2.BOQ,R2 ; GET OUTPUT QUE 2$: MOV (R2),R2 ; GET OUTPUT HEADER BEQ 3$ ; NO MORE TO DO CLR BO.OCT(R2) ; CLEAR OUTPUT COUNT CALL BEGWRT ; Write it BR 2$ 3$: MOV #C2.BHQ,R5 ; AGAIN GO DOWN LIST TO START THEM ; ; This section executes all begin command lists ; 4$: MOV (R5),R5 ; GET HEADER BEQ 11$ ; NO MORE MOV BH.BEG(R5),R0 ; START CLIST CALL BEGCLS ; Start the CLIST BITB #1,BH.BFG(R5) ; Is cleared buffer requested ? BEQ 4$ ; No TST ZERDAT ; Is clearing inhibited ? BNE 4$ ; Yes MOV BH.QIO+Q.IOPL+2(R5),R1 ; Size of data buffer (less header) CLC ASR R1 ; Now is word count MOV BH.BSQ(R5),R4 ; Find start of buffer status que 5$: MOV BS.ADD(R4),R0 ; Start of data buffer BEQ 4$ ; None ADD #BF.DAT,R0 ; Points to data 6$: CLR (R0)+ SOB R1,6$ MOV BS.QUE(R4),R4 ; Last buffer ? BNE 5$ BR 4$ 11$: MOV #C2.BHQ,R5 ; AGAIN GO DOWN LIST TO START THEM 12$: MOV (R5),R5 ; GET HEADER BEQ SUCCES ; Done with begin CLR BH.CNT(R5) ; CLEAR INPUT COUNT MOV BH.BSQ(R5),R4 ; GET FIRST STATUS BUFFER 13$: MOV BS.ADD(R4),R3 ; BUFFER ADDRESS JSR PC,C2STRT ; START INPUT MOV BS.QUE(R4),R4 ; GET NEXT STATUS BNE 13$ ; CONTINUE TILL ALL BUFFS IN INPUT BR 12$ ; NEXT HEADER SUCCES: ENAR$S ; REENABLE AST CLC ; SUCCESS RETURN C2RUN:: MOV #RUNMES,R0 CALL C2MESS RETURN C2STP:: MOV #STPMES,R0 CALL C2MESS RETURN FAILUR: ENAR$S SEC ; FAILURE RETURN ; ; This section executes all BEGIN or END command lists ; BEGCLS: TST R0 ; Does clist exist ? BEQ 4$ ; No MOVB BH.QIO+Q.IOLU(R5),R1 ; LUN MOV R0,R2 ; Will be CLIST address ADD #CL.BEG,R2 ; CLIST execution address QIO$S #IO.RBC,R1,,,#BSTS,, 4$: RETURN BSTS: .BLKW 2 ; ; Write BEGIN or END buffers to tape ; BEGWRT: TST MTDIS ; TAPE DISABLED? BNE 1$ ; YES TSTB BO.OOP(R2) ; THIS UNIT DISABLED? BEQ 1$ ; YES QIO$S #IO.WLB,BO.OLN(R2),,,,,,ERROR ; WRITE BEGIN BUFFER 1$: RETURN BEGBUF: .ASCII 'C2' .WORD 0,0,0,0,0,0 ; ; ROUTINE TO TEST STATUS OF DATA ACQUISITION ; ; CALL ASTAT(ISTAT) ; ISTAT = 0 BUFFER READY ; ISTAT = 1 NO BUFFER TO ANALYZE ; ISTAT = 4 RUN ENDED ; ISTAT = 5 RUN ENDED NO BUFFERS TO ANALYZE ; ASTAT:: MOV #1,R0 CALL R5CHEK ; CHECK THE PARAMETERS CLR @(R5) TST TERINI ; CHECK IF END DATA BNE 1$ ; NO BIS #4,@(R5) ; 4 INDICATES END DATA 1$: TST C2.BAQ ; CHECK IF ANY IN ANAL QUE BNE 2$ ; YES BIS #1,@(R5) ; SET BIT TO SAY NO WSIG$S ; Wait for 1 significant event 2$: CALL KBYES ; ALLOW INPUT RETURN ; ; CALL BTRAN(IARRAY,IWORD,ISIZE) ; TRANSFER DATA FROM DATA BUFFER TO IARRAY STARTING FROM ; IWORD, TRANSFER ISIZE # OF WORDS. ; IWORD = 1 IS FIRST DATA WORD ; = 0 IS THE DATA LENGTH ; = -1 IS THE OUTPUT COUNT ; = -2 IS THE ANALYSIS COUNT ; = -3 IS THE INPUT COUNT ; = -4 IS THE BUFFER TYPE ; BTRAN:: MOV #^RAN ,-(SP) ; SET UP FOR TRACEBACK MOV #^RBTR,R4 JSR R4,NAM$ MOV #3,R0 ; 3 PARAM IN CALL JSR PC,R5CHEK ; CHEK EM MOV C2.BAQ,R1 ; ANALYSIS QUE BEQ 2$ ; NONE, SO EXIT MOV BS.ADD(R1),R0 ; BUFFER ADDRESS MOV (R5)+,R2 ; ARRAY ADDRESS MOV @(R5)+,R3 ; WORD# REQUESTED ASL R3 ; NOW IS BYTE NUMBER BVS 2$ ; BAD WORD # MOV R3,R1 ; SAVE IT ADD #BF.DAT-2,R3 ; WORD IN BUFFER BLT 2$ ; R3 IS TOO SMALL!! MOV @(R5),R4 ; NUMBER OF WORDS REQUESTED DEC R4 BLT 2$ ; BAD COUNT ASL R4 ; NOW IS BYTE NUMBER BVS 2$ ADD R4,R1 ; LAST WORD IN BUFFER BCS 2$ ; BAD # OF WORDS + WORD # CMP R1,BF.CNT(R0) ; IS FINAL WORD TOO BIG? BGT 2$ ; YES ADD R3,R0 ; STARTING ADDRESS MOV @(R5),R4 ; COUNT 1$: MOV (R0)+,(R2)+ ; MOVE 1 WORD SOB R4,1$ ; CONTINUE TILL DONE RTS PC 2$: MOV #BTRMES,R0 ; Message to output JMP C2MESS ; Give error message, no action BTRMES: .ASCIZ /IBR or BTRAN - Reference outside of buffer/ .EVEN ; ; IDATA = IBR(IWORD) GETS 1 WORD FROM DATA BUFFER ; IBR:: MOV #^R ,-(SP) ; SET UP FOR TRACEBACK MOV #^RIBR,R4 JSR R4,NAM$ MOV #1,R0 JSR PC,R5CHEK ; CHECK NUMBER OF PARAM MOV C2.BAQ,R1 ; GET BUFFER HEADER BEQ 2$ ; NO BUFFERS IN ANALYSIS MOV BS.ADD(R1),R0 ; BUFFER ADDRESS MOV @(R5),R3 ; WORD # REQUESTED ASL R3 ; NOW IS BYTE # BVS 2$ ; BAD # CMP R3,BF.CNT(R0) ; TOO BIG? BGT 2$ ; YES ADD #BF.DAT-2,R3 ; POINTS TO DATUM BLT 2$ ; TOO SMALL ADD R3,R0 ; BYTE # IN DATA BUFFER MOV (R0),R0 ; GET WORD RTS PC ; RETURN 2$: MOV #BTRMES,R0 ; Error message CALL C2MESS CLR R0 ; No output RETURN ; ; CALL FLUSH ; THIS FLUSHES OUT UNUSED ANALYSIS BUFFFERS ; FLUSH:: TST TERINI ; TEST IF IN END RUN MODE BNE 10$ ; NO, DO NOT FLUSH 5$: CALL RBTS ; FLUSH OUT 1 BUFFER TST C2.BAQ ; ARE THERE ANY MORE? BNE 5$ ; YES, CONTINUE TILL DONE 10$: TST MTDIS ; TAPING DISABLED? BEQ 11$ ; NO RETURN 11$: MOV #C2.BOQ,R2 ; GET HEADER 12$: MOV (R2),R2 ; GET OUTPUT HEADER BNE 13$ ; INPUT AVAILABLE RETURN 13$: MOV BO.OLN(R2),R0 ; LOGICAL UNIT # TSTB BO.OOP(R2) ; UNIT DISABLED? BEQ 12$ ; YES MOV #3,R1 ; NUMBER OF EOF 14$: QIOW$S #IO.EOF,R0,#1,,#ISTAT ; WRITE AN EOF SOB R1,14$ ; CONTINUE TILL DONE MOV #2,R1 ; NO OF EOF TO SPACE OVER CMPB ISTAT,#IE.EOT ; Was it end of tape? BNE 15$ ; No QIO$S #IO.RWU,R0 ; Rewind the tape + offline BR 12$ 15$: QIOW$S #IO.SPB,R0,#1,,,,<#-1> ; SPACE BACK OVER EOF SOB R1,15$ BR 12$ ISTAT: .BLKW 2 ; I/O status .END