.TITLE TAPEIO Tape block I/O and supporting functions ; ; Substantially modified from previous versions ; 1982-SEP-16 -- JWB -- Revision 0 ; $RMSDEF $SSDEF ; CLOSED = 0 ; File status = CLOSED GETSW = 1 ; File status = OPEN FOR INPUT PUTSW = 2 ; File status = OPEN FOR OUTPUT OK = 1 ; STATUS return = 1 for OK EOF = 2 ; STATUS return = 2 for END OF FILE OPERR = 3 ; STATUS return = 3 for OPEN ERROR IOERR = 4 ; STATUS return = 4 for I/O ERROR ; ; REGISTER USAGE: ; R0 - System status value ; R1 - FAB or RAB base addresses ; R2 - DEVICE descriptor address ; R3 - ; R4 - STATUS address ; R5 - SYSTAT address ; ; ------------- READ-ONLY DATA SECTION ---------------- ; .PSECT TPDATR,RD,NOWRT,NOEXE,LONG ; ONEFILE:.LONG 1 ; ; ------------- READ/WRITE DATA SECTION --------------- ; .PSECT TPDATW,RD,WRT,NOEXE,LONG ; GETFAB: $FAB FAC=, - ; input only ORG=SEQ, - RFM=UDF ; GETRAB: $RAB FAB=GETFAB, - ; link to input FAB RAC=SEQ ; READ access is sequential ; PUTFAB: $FAB FAC=, - ; output only ORG=SEQ, - RFM=UDF ; PUTRAB: $RAB FAB=PUTFAB, - ; link to output FAB RAC=SEQ ; WRITE access is sequential ; INSTAT: .WORD CLOSED ; 0 = not open, 1 = open for input OUSTAT: .WORD CLOSED ; 0 = not open, 2 = open for output ; IOSB: ; I/O status block for control funcs only IOSBST: .BLKW ; status IOSBBC: .BLKW ; byte count IOSBDD: .BLKL ; device-dependent data DEVDESC: .BLKQ ; local copy of DEVICE descriptor TAPECHAN: .BLKL ; channel number for control functions .PAGE ; ; ----------------- CODE ----------------------------- ; .PSECT TAPEIO,EXE,NOWRT ; ; SUBROUTINE TOPENR(DEVICE,MAXLBK, STATUS,SYSTAT) ; ; Open a tape device for reading ; ; INPUTS: DEVICE - CHAR*(*) - Logical or physical device name ; MAXBLK - INTEGER - Maximum number of bytes in a block ; ; OUTPUT: STATUS - INTEGER - 1 = ok, ; - 3 = error opening file ; - 4 = error connecting record stream ; SYSTAT - INTEGER - System status code ; .ENTRY TOPENR,^M MOVL 12(AP),R4 ;Address of STATUS MOVL 16(AP),R5 ;Address of SYSTAT MOVL #SS$_NORMAL,R0 MOVL #OK,(R4) ;Set STATUS = OK CMPW INSTAT,#GETSW BEQL 40$ ;Skip if already open MOVAL GETFAB,R1 MOVL 4(AP),R2 ;Address of DEVICE descriptor MOVW (R2),FAB$B_FNS(R1) ;Filename string size MOVL 4(R2),FAB$L_FNA(R1) ;Filename string address MOVW @8(AP),FAB$W_BLS(R1) ;Put MAXBLK in GETFAB BLS $OPEN FAB=GETFAB ;Open for reading BLBC R0,30$ ;Error? $CONNECT RAB=GETRAB ;Connect for reading BLBC R0,28$ ;Error? MOVW #GETSW,INSTAT ;Indicate open for input BRB 40$ 28$: MOVL #IOERR,(R4) ;Set STATUS = CONNECT error (4) BRB 32$ 30$: MOVL #OPERR,(R4) ;Set STATUS = OPEN error (3) 32$: MOVW #CLOSED,INSTAT ;Indicate file is not open 40$: JSB SET_SYSTAT ;Set SYSTAT return RET ; ; --------- Internal Subroutine SET_SYSTAT --------- ; Assumes value is in R0, address of SYSTAT is in R5 ; SET_SYSTAT: CMPL R0,#RMS$_NORMAL ;If STATUS is RMS$_NORMAL, BNEQU 50$ MOVL #SS$_NORMAL,R0 ;then change it to SS$_NORMAL 50$: MOVL R0,(R5) ;Set SYSTAT RSB ;Internal RETURN .PAGE ; ; SUBROUTINE TOPENW(DEVICE,MAXLBK, STATUS,SYSTAT) ; ; Open a tape device for writing ; ; INPUTS: DEVICE - CHAR*(*) - Logical or physical device name ; MAXBLK - INTEGER - Maximum number of bytes in a block ; ; OUTPUT: STATUS - INTEGER - 1 = ok, ; - 3 = error opening file ; - 4 = error connecting record stream ; SYSTAT - INTEGER - System status code ; .ENTRY TOPENW,^M MOVL 12(AP),R4 ;Address of STATUS MOVL 16(AP),R5 ;Address of SYSTAT MOVL #SS$_NORMAL,R0 MOVL #OK,(R4) ;Set STATUS = OK CMPW OUSTAT,#PUTSW BEQL 40$ ;Skip if already open MOVAL PUTFAB,R1 MOVL 4(AP),R2 ;Address of DEVICE descriptor MOVW (R2),FAB$B_FNS(R1) ;Filename string size MOVL 4(R2),FAB$L_FNA(R1) ;Filename string address MOVW @8(AP),FAB$W_BLS(R1) ;Put MAXBLK in PUTFAB BLS $OPEN FAB=PUTFAB ;Open for writing BLBC R0,30$ ;Error? $CONNECT RAB=PUTRAB ;Connect for writing BLBC R0,28$ ;Error? MOVW #PUTSW,OUSTAT ;Indicate open for output BRB 40$ 28$: MOVL #IOERR,(R4) ;Set STATUS = connect error (4) BRB 32$ 30$: MOVL #OPERR,(R4) ;Set STATUS = open error (3) 32$: MOVW #CLOSED,OUSTAT ;Indicate file is not open 40$: JSB SET_SYSTAT ;Set SYSTAT return RET .PAGE ; ; SUBROUTINE TCLOSR(DEVICE, STATUS,SYSTAT) ; ; Close tape file that was opened by TOPENR ; ; INPUT: DEVICE - CHAR*(*) - Logical or physical device name ; ; OUTPUT: STATUS - INTEGER - 1 = ok ; SYSTAT - INTEGER - System status code ; .ENTRY TCLOSR,^M MOVL 8(AP),R4 ;Address of STATUS MOVL 12(AP),R5 ;Address of SYSTAT MOVL #OK,(R4) ;Set STATUS = OK $CLOSE FAB=GETFAB MOVW #CLOSED,INSTAT JSB SET_SYSTAT RET ; ; SUBROUTINE TCLOSW(DEVICE, STATUS,SYSTAT) ; ; Close tape file that was opened by TOPENW ; ; INPUT: DEVICE - CHAR*(*) - Logical or physical device name ; ; OUTPUT: STATUS - INTEGER - 1 = ok ; SYSTAT - INTEGER - System status code ; .ENTRY TCLOSW,^M MOVL 8(AP),R4 ;Address of STATUS MOVL 12(AP),R5 ;Address of SYSTAT MOVL #OK,(R4) ;Set STATUS = OK $CLOSE FAB=PUTFAB MOVW #CLOSED,OUSTAT JSB SET_SYSTAT RET .PAGE ; ; SUBROUTINE TPREAD(BUFSIZ, BUFFER,LENGTH,STATUS,SYSTAT) ; ; Read a tape block into BUFFER ; ; INPUT: BUFSIZ - INTEGER - Size of BUFFER, bytes ; ; OUTPUTS:BUFFER - INTEGER(BUFSIZ/4) - Input buffer ; - or BYTE(BUFSIZ) ; LENGTH - INTEGER - Block length read, in bytes ; STATUS - INTEGER - 1 = ok, ; - 2 = end of file ; - 3 = error - file not open for input ; - 4 = error - read failure - see systat ; SYSTAT - INTEGER - System status code ; .ENTRY TPREAD,^M MOVL 16(AP),R4 ;Address of STATUS MOVL 20(AP),R5 ;Address of SYSTAT MOVL #OK,(R4) ;Set STATUS to OK CMPW INSTAT,#GETSW ;Open for input? BEQL 10$ ;Proceed if OK MOVL #OPERR,(R4) ;Set STATUS = open error CLRL R0 ;Return warning in R0 JSB SET_SYSTAT ;Set SYSTAT value RET 10$: ;;; $RAB_STORE RAB=GETRAB,UBF=BUFFER,USZ=BUFSIZ MOVAL GETRAB,R1 MOVW @4(AP),RAB$W_USZ(R1) ;USZ=BUFSIZ (value) MOVL 8(AP),RAB$L_UBF(R1) ;UBF=BUFFER (address) ; $READ RAB=GETRAB ; MOVAL GETRAB,R1 ;Reset in case clobbered MOVW RAB$W_RSZ(R1),@12(AP) ;Set LENGTH BLBS R0,20$ ;GET ok? MOVL #EOF,(R4) ;Set STATUS = EOF CMPL R0,#RMS$_EOF ;End of file? BEQL 20$ ;Yes MOVL #IOERR,(R4) ;Set STATUS = ERROR 20$: JSB SET_SYSTAT ;Set SYSTAT = R0 RET .PAGE ; ; SUBROUTINE TPWRIT(BUFSIZ,BUFFER,LENGTH, STATUS,SYSTAT) ; ; Write a tape block from BUFFER ; ; INPUT: BUFSIZ - INTEGER - Size of BUFFER, bytes (not used) ; BUFFER - INTEGER(BUFSIZ/4) - Output buffer ; - or BYTE(BUFSIZ) ; LENGTH - INTEGER - Block length to write, in bytes ; ; OUTPUT: STATUS - INTEGER - 1 = ok, ; - 2 = end of file / end of medium ; - 3 = error - file not open for output ; - 4 = error - write failure - see SYSTAT ; SYSTAT - INTEGER - System status code ; .ENTRY TPWRIT,^M MOVL 16(AP),R4 ;Address of STATUS MOVL 20(AP),R5 ;Address of SYSTAT MOVL #OK,(R4) ;Set STATUS to OK CMPW OUSTAT,#PUTSW ;Open for output? BEQL 10$ ;Proceed if OK MOVL #OPERR,(R4) ;Set STATUS = OPEN error CLRL R0 ;Return warning in R0 JSB SET_SYSTAT ;Set SYSTAT value RET 10$: ;;; $RAB_STORE RAB=PUTRAB,RBF=BUFFER,RSZ=LENGTH MOVAL PUTRAB,R1 MOVW @12(AP),RAB$W_RSZ(R1) ;RSZ=LENGTH (value) MOVL 8(AP),RAB$L_RBF(R1) ;RBF=BUFFER (address) ; $WRITE RAB=PUTRAB ; BLBS R0,20$ ;WRITE ok? MOVL #EOF,(R4) ;Set STATUS = EOF CMPL R0,#RMS$_EOF ;End of file? BEQL 20$ ;Yes MOVL #IOERR,(R4) ;Set STATUS = ERROR 20$: JSB SET_SYSTAT ;Set SYSTAT = R0 RET .PAGE ; ; SUBROUTINE TPSKPF(DEVICE, STATUS,SYSTAT) ; ; Skip forward to next end of file ; ; INPUT: DEVICE - CHAR*(*) - Device name descriptor ; OUTPUT: STATUS - INTEGER - 1 = ok, ; 3 = channel assignment error ; 4 = I/O error ; SYSTAT - INTEGER - System status code ; .ENTRY TPSKPF,^M MOVL 4(AP),R2 ;Address of DEVICE descriptor MOVL 8(AP),R4 ;Address of STATUS MOVL 12(AP),R5 ;Address of SYSTAT MOVL (R2),DEVDESC ;Make copy so macro will work MOVL 4(R2),DEVDESC+4 MOVL #OK,(R4) $ASSIGN_S DEVNAM=DEVDESC,CHAN=TAPECHAN BLBS R0,10$ ;Continue if OK MOVL #OPERR,(R4) ;Set STATUS = open error JSB SET_SYSTAT RET 10$: $QIOW_S CHAN=TAPECHAN,FUNC=#IO$_SKIPFILE,IOSB=IOSB,P1=1 CMPL R0,#SS$_NORMAL ;Check status from QIOW BNEQ 20$ MOVZWL IOSBST,R0 ;Check status in IOSB 20$: JSB SET_SYSTAT ;Return SYSTAT value BLBS R0,30$ ;Any error? MOVL #IOERR,(R4) ;Set STATUS = IOERR 30$: $DASSGN_S CHAN=TAPECHAN RET .PAGE ; ; SUBROUTINE TPREWD(DEVICE, STATUS,SYSTAT) ; ; Rewind a tape device ; ; INPUT: DEVICE - CHAR*(*) - Device descriptor ; ; OUTPUT: STATUS - INTEGER - 1 = ok, ; 3 = channel assignment error, ; 4 = I/O error ; SYSTAT - INTEGER - System status code ; .ENTRY TPREWD,^M MOVL 4(AP),R2 ;Address of DEVICE descriptor MOVL 8(AP),R4 ;Address of STATUS MOVL 12(AP),R5 ;Address of SYSTAT MOVL (R2),DEVDESC ;Make copy so macro will work MOVL 4(R2),DEVDESC+4 MOVL #OK,(R4) $ASSIGN_S DEVNAM=DEVDESC,CHAN=TAPECHAN BLBS R0,10$ ;Continue if OK MOVL #OPERR,(R4) ;Set STATUS = open error JSB SET_SYSTAT RET 10$: $QIOW_S CHAN=TAPECHAN,IOSB=IOSB,- FUNC=#IO$_REWIND CMPL R0,#SS$_NORMAL ;Check status from QIOW BNEQ 20$ MOVZWL IOSBST,R0 ;Check status in IOSB 20$: JSB SET_SYSTAT ;Return SYSTAT value BLBS R0,30$ ;Any error? MOVL #IOERR,(R4) ;Set STATUS = IOERR 30$: $DASSGN_S CHAN=TAPECHAN RET .PAGE ; ; SUBROUTINE TPREWO(DEVICE, STATUS,SYSTAT) ; ; Rewind a tape device, and put it offline ; ; INPUT: DEVICE - CHAR*(*) - Device descriptor ; ; OUTPUT: STATUS - INTEGER - 1 = ok, ; 3 = channel assignment error, ; 4 = I/O error ; SYSTAT - INTEGER - System status code ; .ENTRY TPREWO,^M MOVL 4(AP),R2 ;Address of DEVICE descriptor MOVL 8(AP),R4 ;Address of STATUS MOVL 12(AP),R5 ;Address of SYSTAT MOVL (R2),DEVDESC ;Make copy so macro will work MOVL 4(R2),DEVDESC+4 MOVL #OK,(R4) $ASSIGN_S DEVNAM=DEVDESC,CHAN=TAPECHAN BLBS R0,10$ ;Continue if OK MOVL #OPERR,(R4) ;Set STATUS = open error JSB SET_SYSTAT RET 10$: $QIOW_S CHAN=TAPECHAN,IOSB=IOSB,- FUNC=# CMPL R0,#SS$_NORMAL ;Check status from QIOW BNEQ 20$ MOVZWL IOSBST,R0 ;Check status in IOSB 20$: JSB SET_SYSTAT ;Return SYSTAT value BLBS R0,30$ ;Any error? MOVL #IOERR,(R4) ;Set STATUS = IOERR 30$: $DASSGN_S CHAN=TAPECHAN RET ; .END