.TITLE RDTAP -- READ TAPE PROGRAM .IDENT /V03.00/ ; ; Copyright (c) 2011 by Oleg Safiullin ; ; Permission to use, copy, modify, and distribute this software for any ; purpose with or without fee is hereby granted, provided that the above ; copyright notice and this permission notice appear in all copies. ; ; THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ; WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ; MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ; ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ; WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ; ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ; OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ; ; 14-SEP-2011 FORM REWRITE ; $JSX == 4 ;EXTENDED JOB STATUS WORD ALL64$ == 20 ;USE 64KB OF MEMORY UNDER VBGEXE VBGEX$ == 200 ;VBGEXE SUPPORT $USRSP == 42 ;USER STACK POINTER $USRTO == 50 ;USER TOP ADDRESS $ERRBY == 52 ;EMT ERROR BYTE $USRRB == 53 ;USER ERROR BYTE WARN$ == 2 ;WARNING STATUS FATAL$ == 10 ;FATAL STATUS OPT.N == 100000 ;NO REWIND OPTION OPT.T == 400 ;TEST OPTION OPT.U == 200 ;UNLOAD OPTION FCHAN == 0 ;FILE CHANNEL TCHAN == 1 ;TAPE CHANNEL SF.MRD == 370 ;READ MAGTAPE BLOCK FUNCTION SF.MOR == 372 ;REWIND AND OFFLINE FUNCTION .ASECT .=$JSX .WORD ALL64$!VBGEX$ .PSECT .MCALL .ASSUME,.CLOSE,.CSISPC,.DSTAT .MCALL .ENTER,.FETCH,.LOOKUP,.PRINT .MCALL .SETTOP,.SPFUN,.SRESET,.WRITW RDTAP:: MOV @#$USRTO,BUF ;INITIALIZE BUFFER ADDRESS ADD #2,BUF ; .SETTOP #-2 ;EXTEND JOB TO MAXIMUM SIZE MOV R0,TOP ;SAVE TOP ADDRESS 10$: MOV #OBUF,R1 ;POINT TO LINE BUFFER .CSISPC #OUTSP,#DFEXT,,R1 ;PARSE CSI STRING TSTB @R1 ;EMPTY STRING? BNE 20$ ;NO .PRINT #IDENT ;YES. PRINT IDENT STRING 15$: MOV @#$USRSP,SP ;RESTORE STACK POINTER BR 10$ ;PROCESS NEXT CSI STRING 20$: CMPB #<',>,(R1)+ ;FILE SEPARATOR USED? BEQ 55$ ;YES. SYNTAX ERROR TSTB @R1 ;NO. END OF LINE? BNE 20$ ;NO CLR OPTS ;INITIALIZE OPTIONS MOV (SP)+,R1 ;GET OPTION COUNT BEQ 50$ ;NO OPTIONS SPECIFIED 30$: MOV (SP)+,R0 ;GET CURRENT OPTION BMI 55$ ;VALUE SPECIFIED. SYNTAX ERROR MOV #OPT.N,R2 ;ASSUME /N SPECIFIED CMPB #'N,R0 ;/N? BEQ 40$ ;YES SWAB R2 ;ASSUME /U SPECIFIED CMPB #'U,R0 ;/U? BEQ 40$ ;YES ASL R2 ;ASSUME T SPECIFIED CMPB #'T,R0 ;/T? BNE 55$ ;NO. SYNTAX ERROR 40$: BIS R2,OPTS ;UPDATE OPTIONS DEC R1 ;MORE OPTIONS SPECIFIED? BNE 30$ ;YES 50$: TST OUTSP+2 ;OUTPUT FILE SPECIFIED? BNE 60$ ;YES BIT #OPT.T,OPTS ;/T SPECIFIED? BNE 60$ ;YES 55$: .PRINT #ERR1 ;NO. SYNTAX ERROR 56$: BISB #FATAL$,@#$USRRB ;SET FATAL STATUS .SRESET ;SOFT RESET BR 15$ ;LOOP 60$: TST INPSP+2 ;INPUT FILE SPECIFIED? BNE 55$ ;YES. SYNTAX ERROR MOV BUF,R0 ;SET BUFFER ADDRESS BIT #OPT.T,OPTS ;/T SPECIFIED? BNE 70$ ;YES. IGNORE OUTPUT FILE .FETCH BUF,#OUTSP ;FETCH OUTPUT HANDLER BCC 70$ ;OK .PRINT #ERR2 ;FAILED TO FETCH OUTPUT HANDLER BR 56$ ; 70$: MOV R0,R1 ;SET BUFFER ADDRESS .FETCH R1,#INPSP ;FETCH INPUT HANDLER BCC 80$ ;OK .PRINT #ERR3 ;FAILED TO FETCH INPUT HANDLER BR 56$ ; 80$: MOV R0,R4 ;SET BUFFER ADDRESS .DSTAT #STAT,#INPSP ;CHECK INPUT DEVICE STATUS TST STAT ;FILE STRUCTURE DEVICE? BPL 81$ ;NO. .PRINT #ERR11 ;BAD INPUT DEVICE BR 56$ ; 81$: MOV TOP,R5 ;CALCULATE BUFFER SIZE SUB R4,R5 ; ROR R5 ;CONVERT TO WORD COUNT CMP #256.,R5 ;LESS THAN 256. WORDS? BLE 85$ ;NO .PRINT #ERR6 ;NOT ENOUGH MEMORY BR 56$ ; 85$: CMP #16384.,R5 ;GREATER THAN 16384. WORDS? BGE 86$ ;NO MOV #16384.,R5 ;LIMIT BUFFER TO 16384. WORDS 86$: BIT #OPT.T,OPTS ;/T SPECIFIED? BNE 95$ ;YES. IGNORE OUTPUT FILE .ENTER #AREA,#FCHAN,#OUTSP,OUTSP+10 ;ENTER OUTPUT FILE BCC 90$ ;OK .PRINT #ERR4 ;FAILED TO ENTER OUTPUT FILE BR 56$ ; 90$: MOV R0,OUTSP+10 ;SAVE ALLOCATED SIZE MOV R0,R1 ;PRINT MESSAGE MOV #INFO2V,R0 ; MOV PC,R2 ; CALL $CBDMG ; .PRINT #INFO2 ; BR 96$ ; 95$: MOV #-1,OUTSP+10 ;INITIALIZE FILE LENGTH 96$: CLR R1 ;ASSUME REWIND LOOKUP TST OPTS ;/N SPECIFIED? BPL 100$ ;NO DEC R1 ;SET NOREWIND FLAG 100$: .LOOKUP #AREA,#TCHAN,#INPSP,R1 ;LOOKUP TAPE DEVICE BCC 110$ ;OK .PRINT #ERR5 ;FAILED TO LOOKUP TAPE DEVICE 105$: BR 56$ ; 110$: MOV #INFO1V,R0 ;PRINT MAX BLOCK SIZE MOV R5,R1 ; MOV PC,R2 ; CALL $CBDMG ; .PRINT #INFO1 ; MOV #STAT,R3 ;POINT TO SPFUN STATUS BLOCK CLR EOFCT ;CLEAR EOF COUNTER CLR OBLKN ;CLEAR FILE BLOCK NUMBER MOV #OBUF,OBUFP ;CLEAR OUTPUT BUFFER POINTER CLR FCNT ;CLEAR FILE COUNTER 120$: MOV R5,R1 ;INITIALIZE BLOCK LENGTH .SPFUN #AREA,#TCHAN,#SF.MRD,R4,R1,R3 ;READ PHYSICAL BLOCK BCC 140$ ;OK TSTB @#$ERRBY ;END OF FILE/TAPE? BEQ 160$ ;YES CMP #6,@R3 ;SHORT BLOCK READ? BEQ 130$ ;YES CMP #5,@R3 ;BLOCK LARGER THAN BUFFER? BEQ 150$ ;YES .PRINT #ERR7 ;TAPE READ ERROR BR 105$ ; 130$: SUB 2(R3),R1 ;CALCULATE TAPE BLOCK SIZE BEQ 170$ ;EMPTY BLOCK DETECTED 140$: CLR EOFCT ;CLEAR EOF COUNTER CALL WRBLK ;WRITE TAPE BLOCK TO FILE BCC 120$ ;OK. LOOP 145$: MOV #ERR8,R0 ;ASSUME FILE WRITE ERROR CMP OBLKN,OUTSP+10 ;ALLOCATED SPACE FULL? BLO 146$ ;NO MOV #ERR10,R0 ;TAPE TOO LARGE 146$: .PRINT ;FILE WRITE ERROR/TAPE TOO LARGE BR 105$ ; 150$: .PRINT #ERR9 ;TAPE BLOCK TOO LARGE BR 105$ ; 160$: CMP #2,@R3 ;UNEXPECTED END OF TAPE? BEQ 170$ ;YES CMP #1,@R3 ;EOF ONLY? BNE 175$ ;NO. END OF TAPE INC EOFCT ;INCREASE EOF COUNT CMP #2,EOFCT ;TWO EOFS FOUND? BEQ 175$ ;YES. END OF TAPE INC FCNT ;INCREASE FILE COUNT CALL WREOF ;WRITE EOF TO FILE BCS 145$ ;OUTPUT ERROR BR 120$ ;LOOP 170$: .PRINT #WARN1 ;UNEXPECTED END OF TAPE BISB #WARN$,@#$USRRB ;SET WARNING STATE 175$: TST EOFCT ;JUST REACHED EOF? BNE 190$ ;NO INC FCNT ;INCREASE FILE COUNT 180$: CALL WREOF ;WRITE EOF TO FILE BCS 145$ ;ERROR 190$: CALL WREOF ;WRITE EOF TO FILE BCS 145$ ;ERROR CALL FLUSH ;FLUSH OUTPUT BUFFER BCS 145$ ;ERROR MOV #INFO3V,R0 ;PRINT TAPE FILE COUNT MOV FCNT,R1 ; MOV PC,R2 ; CALL $CBDMG ; .PRINT #INFO3 ; BIT #OPT.T,OPTS ;/T SPECIFIED? BNE 195$ ;YES .CLOSE #FCHAN ;CLOSE OUTPUT FILE MOV #INFO4V,R0 ;PRINT DISK BLOCK COUNT MOV OBLKN,R1 ; MOV PC,R2 ; CALL $CBDMG ; .PRINT #INFO4 ; BR 196$ ; 195$: MOV #INFO5V,R0 ;PRINT DISK BLOCK COUNT MOV OBLKN,R1 ; MOV PC,R2 ; CALL $CBDMG ; .PRINT #INFO5 ; 196$: TSTB OPTS ;UNLOAD TAPE? BPL 200$ ;NO .SPFUN #AREA,#TCHAN,#SF.MOR,,,R3 ;REWIND AND OFFLINE BCC 200$ ;OK .PRINT #WARN2 ;REWIND FAILED BISB #WARN$,@#$USRRB ;SET WARNING STATE 200$: .CLOSE #TCHAN ;CLOSE TAPE .SRESET ;SOFT RESET JMP 10$ ;LOOP ;+ ;WRBLK -- WRITE TAPE BLOCK TO FILE ; ;INPUT: ; R1 - BLOCK WORD COUNT ; R4 - BUFFER ADDRESS ; ;OUTPUT: ; CARRY - WRITE ERROR FLAG ; R2 - MODIFIED ;- WRBLK: CALL WRLEN ;WRITE BLOCK LENGTH BCS 10$ ;ERROR MOV R4,R2 ;SET BUFFER ADDRESS CALL WRITE ;WRITE BLOCK BCS 10$ ;ERROR BR WRLEN ;WRITE TRAILER 10$: RETURN ;RETURN ;+ ;WREOF -- WRITE EOF TO FILE ; ;INPUT: ; NONE ; ;OUTPUT: ; CARRY - WRITE ERROR FLAG ; R1, R2 - MODIFIED ;- WREOF: CLR R1 ;CLEAR BLOCK LENGTH ;+ ;WRLEN -- WRITE TAPE BLOCK LENGTH TO FILE ; ;INPUT: ; R1 - BLOCK WORD COUNT ; ;OUTPUT: ; CARRY - WRITE ERROR FLAG ; R2 - MODIFIED ;- WRLEN: MOV R1,-(SP) ;SAVE R1 MOV #BKLEN,R2 ;CALCULATE BLOCK LENGTH MOV R1,@R2 ; ASL @R2 ; MOV #2,R1 ;SET WORD COUNT CALL WRITE ;WRITE DATA TO FILE MOV (SP)+,R1 ;RESTORE R1 RETURN ;RETURN ;+ ;WRITE -- WRITE DATA TO FILE ; ;INPUT: ; R1 - WORD COUNT ; R2 - BUFFER ADDRESS ;- WRITE: MOV R1,-(SP) ;SAVE R1 MOV R3,-(SP) ;SAVE R3 MOV OBUFP,R3 ;GET BUFFER POINTER 10$: MOV (R2)+,(R3)+ ;MOVE WORD TO BUFFER CMP #OBUF+512.,R3 ;BUFFER IS FULL? BNE 20$ ;NO MOV #OBUF,R3 ;RESET BUFFER ADDRESS BIT #OPT.T,OPTS ;/T SPECIFIED? BNE 15$ ;YES. SKIP WRITE .WRITW #AREA,#FCHAN,R3,#256.,OBLKN ;WRITE DATA TO FILE BCS 30$ ;ERROR 15$: INC OBLKN ;INCREASE BLOCK NUMBER BNE 20$ ;OK SUB #1,OBLKN ;BLOCK NUMBER OVERFLOW BR 30$ ; 20$: DEC R1 ;MORE WORDS TO MOVE? BNE 10$ ;YES MOV R3,OBUFP ;SAVE BUFFER POINTER 30$: MOV (SP)+,R3 ;RESTORE R3 MOV (SP)+,R1 ;RESTORE R1 RETURN ;RETURN ;+ ;FLUSH -- FLUSH OUTPUT BUFFER ; ;INPUT: ; R4 - BUFFER ADDRESS ; ;OUTPUT: ; R1 - MODIFIED ; CARRY - WRITE ERROR ;- FLUSH: MOV OBUFP,R1 ;GET BUFFER POINTER SUB #OBUF,R1 ;CALCULATE DATA LENGTH BEQ 20$ ;NO DATA IN BUFFER BIT #OPT.T,OPTS ;/T SPECIFIED? BNE 10$ ;YES. SKIP WRITE ASR R1 ;CONVERT TO WORDS .WRITW #AREA,#FCHAN,#OBUF,R1,OBLKN ;WRITE DATA TO FILE BCS 20$ ;ERROR 10$: INC OBLKN ;INCREASE BLOCK BUMBER BNE 20$ ;OK SUB #1,OBLKN ;BLOCK NUMBER OVERFLOW 20$: RETURN DFEXT:: .WORD 0,^RTAP,0,0 ;DEFAULT EXTENSIONS OUTSP:: .BLKW 5 ;OUTPUT FILE DESCRIPTOR AREA:: .BLKW 10. ;EMT AREA INPSP:: .BLKW 4 ;INPUT FILE DESCRIPTOR OPTS:: .BLKW 1 ;OPTIONS EOFCT:: .WORD 0 ;EOF COUNTER OBLKN:: .WORD 0 ;CURRENT OUTPUT FILE BLOCK OBUFP:: .WORD 0 ;OUTPUT BUFFER POINTER FCNT:: .WORD 0 ;NUMBER OF TAPE FILES STAT:: .BLKW 4 ;SPFUN STATUS BLOCK .BLKW 11. ;PAD CSI BLOCK .ASSUME .-OUTSP EQ 39.*2,MESSAGE=<;Incorrect CSI block length> BKLEN:: .WORD 0,0 ;TAPE BLOCK LENGTH BUFFER BUF:: .WORD 0 ;INPUT BUFFER ADDRESS TOP:: .WORD 0 ;TOP ADDRESS OBUF:: .BLKW 256. ;OUTPUT BUFFER IDENT: .ASCIZ /RDTAP V03.00/ ERR1: .ASCIZ /?RDTAP-F-Syntax error/ ERR2: .ASCIZ /?RDTAP-F-Failed to fetch output handler/ ERR3: .ASCIZ /?RDTAP-F-Failed to fetch input handler/ ERR4: .ASCIZ /?RDTAP-F-Failed to enter output file/ ERR5: .ASCIZ /?RDTAP-F-Failed to lookup tape device/ ERR6: .ASCIZ /?RDTAP-F-Not enough memory/ ERR7: .ASCIZ /?RDTAP-F-Tape read error/ ERR8: .ASCIZ /?RDTAP-F-Output file write error/ ERR9: .ASCIZ /?RDTAP-F-Tape block too large/ ERR10: .ASCIZ /?RDTAP-F-Tape too large/ ERR11: .ASCIZ /?RDTAP-F-Bad input device/ WARN1: .ASCIZ /?RDTAP-W-Unexpected end of tape/ WARN2: .ASCIZ /?RDTAP-W-Rewind failed/ INFO1: .ASCII /?RDTAP-I-/ INFO1V: .ASCIZ /XXXXX. word(s) allocated for tape block buffer/ INFO2: .ASCII /?RDTAP-I-/ INFO2V: .ASCIZ /XXXXX. block(s) allocated for tape image file/ INFO3: .ASCII /?RDTAP-I-/ INFO3V: .ASCIZ /XXXXX. file(s) read from tape/ INFO4: .ASCII /?RDTAP-I-/ INFO4V: .ASCIZ /XXXXX. disk block(s) used/ INFO5: .ASCII /?RDTAP-I-/ INFO5V: .ASCIZ /XXXXX. disk block(s) required/ .END RDTAP