.TITLE RMSBLKIO .IDENT /2.1/ ;+ ; ; Do block I/O through RMS ; ; This routine pprovides for OPEN, CLOSE, READ and Write ; ; Fortran calls ; OPEN_BLKIO ! USROPN routine ; GET_RABADR (IRABADR) ; CALL READ_BLOCK (ARRAY, BLOCK, NUMBER_OF_BYTES) ; CALL WRITE_BLOCK(ARRAY, BLOCK, NUMBER_OF_BYTES) ; ; Define the offsets from AP fo the different parameters ; in the Fortran call statement. ; ; Written by: James G. Downward 28-April-1982 ; KMS Fusion, Inc ; P.O. Box 1567 ; Ann Arbor, Mich 48104 ; (313)-769-8500 ; ; Modified by: James G. Downward 29-April-1982 ; Do not truncate file if record put ; in middle. Use Fortran defaults ; (ie $PUT), Allow 'READONLY' in OPEN ; statement. ; Buffer_Address = 4 Block_Number = 8 Byte_Count = 12 $RMSDEF $fabdef $RABDEF .PSECT RMS_TABLES NOEXE, RD, WRT RABADR::.LONG 0,0 .PSECT CODE PIC,REL,LCL,NOSHR,EXE,RD,NOWRT ;+ ; Open_Blkio ; ; called during Fortran OPEN processing. In the OPEN statement ; USEROPEN = Open_Blkio is defined. ; ; If more than one block I/O file is to be used at one time ; immediately prior to any I/O to this LUN, a call to ; Get_RABadr must be made so the RAB address can be stored for ; later use. ; ; Here to open the file that was specified in the $FAB macro ; .ENTRY OPEN_BLKIO, ^M<> MOVL 4(AP),R0 ; Get Address of our FAB BISB #FAB$M_BIO,FAB$B_FAC(R0); Allow block I/O ; BISB #FAB$M_PUT,FAB$B_FAC(R0); Allow $PUT & $WRITE BISB #FAB$M_GET,FAB$B_FAC(R0); Allow $GET and $READ INSV #1,#FAB$V_CBT,#1,FAB$L_FOP(R0); Contiguous best try ; Set up the RAB MOVL 8(AP),R0 ; Get the RAB address MOVL R0,RABADR ; Save address for later INSV #1,#RAB$V_BIO,#1,RAB$L_ROP(R0); Set up as Block I/O file INSV #0,#RAB$V_TPT,#1,RAB$L_ROP(R0); Do not set EOF on put $OPEN FAB=@4(AP) ; First, try opening old file BLBS R0,20$ ; Open worked, go connect ; open failed, try and create file $CREATE FAB=@4(AP) ; Create the file BLBC R0,30$ ; If create fails just give up 20$: $CONNECT RAB=@8(AP) ; Connect to the file BLBC R0,30$ ; give up if connect fails MOVL #1,R0 ; Force simple success 30$: RET ;+ ; GET_RABADR ; ; CALL Get_RABadr (IRAB_Address) ; ; where IRAB_Address is an I*4 word to store the address of the RAB ; using the LUN for block I/O. ; ; Retrieves from internal one long word storage the address of the RAB ; used by the last Open_Blkio call. Since, each call to Open_Blkio ; will erase the previous RABADR, this way the RAB addresses can be ; stored in the Fortran program untill needed by the another call. ;- .ENTRY GET_RABADR,^M<> MOVL RABADR,@4(AP) ; Retrieve the RAB address RET ; There, wasn't that simple? ;+ ; SET_RABADR ; ; CALL Set_RABadr (IRAB_Address) ; ; where IRAB_Address is an I*4 word to store the address of the RAB ; using the LUN for block I/O. ; ; Restore the address of the RAB to the internal storage word so that ; Read_Block and Write_Block can use it. ;- .ENTRY SET_RABADR,^M<> MOVL @4(AP),RABADR ; Reset the address of the block I/O RAB RET ; ; ;+ ; WRITE_BLOCK ; ; CALL Write_Block (Ibuffer,Iblock_Number,Ibyte_Count) ; or ; Istatus = Write_Block (Ibuffer,Iblock_Number,Ibyte_Count) ; ; Write a block on the disk. The routine assumes that it was ; called with three parameters: ; ; Iblock_Number = Starting block number on the disk I*2 ; Ibuffer = Memory buffer to write from I*2 ; Ibyte_Count = Number of bytes to transfer I*2 ; Istatus = IO status code from RMS I*4 ; ; If more than one block I/O file is in use, the RAB address must ; be set with a call to SET_RABADR each time a block I/O is done to ; a different LUN. ; ;- .entry WRITE_BLOCK, ^M<> ; ; Move calling arguments into the RAB to do the write ; MOVL RABADR,R0 ; Get RAB address MOVZWL @Block_Number(AP),RAB$L_BKT(R0) ; Block # to start at MOVL Buffer_Address(AP),RAB$L_RBF(R0); set Buffer address MOVW @Byte_Count(AP),RAB$W_RSZ(R0) ; $WRITE RAB=R0 ; Write out to disk BLBC R0, 20$ ; MOVL #1,R0 ; 20$: RET ; .ENTRY BLKIO_ERR,0 ; MOVL 4(AP),R0 ; ; PUSHL RAB$L_STV(R0) ; ; PUSHL RAB$L_STS(R0) ; ; CALLS #2, LIB$SIGNAL ; Report error type ; RET ;+ ; READ_BLOCK ; ; CALL Read_Block (Ibuffer,Iblock_Number,Ibyte_Count) ; or ; Istatus = Read_Block (Ibuffer,Iblock_Number,Ibyte_Count) ; ; Write a block on the disk. The routine assumes that it was ; called with three parameters: ; ; Iblock_Number = Starting block number on the disk I*2 ; Ibuffer = Memory buffer to write from I*2 ; Ibyte_Count = Number of bytes to transfer I*2 ; Istatus = IO status code from RMS I*4 ; ; If more than one block I/O file is in use, the RAB address must ; be set with a call to SET_RABADR each time a block I/O is done to ; a different LUN. ; ; The parameters the routine was called with are the same as for ; Write_Blodk. Notice however, that the location in the RAB which ; gets the buffer address and the number of bytes are different ; than for the write. ; .Entry READ_BLOCK, ^M<> ; ; Move calling arguments into the RAB to do the read ; MOVL RABADR,R0 ; Get RAB address MOVZWL @Block_Number(AP),RAB$L_BKT(R0) ; Set the block # MOVL Buffer_Address(AP),RAB$L_UBF(R0); Set the buffer address MOVW @Byte_Count(AP),RAB$W_USZ(R0) ; Set byte count $READ RAB=R0 ; Do the read BLBC R0,30$ ; Return error code MOVL #1,R0 ; Show simple success 30$: RET .END