; ******************************************************************** ; .TITLE Disk Driver Programming Example .IDENT /01/ ; ; Define necessary symbols. ; $FIBDEF ;Define file information block Offsets $IODEF ;Define I/O function codes $RMSDEF ;Define RMS-32 Return Status Values ; ; Local storage ; ; Define number of records to be processed. ; NUM_RECS=100 ;One hundred records ; ; Allocate storage for necessary data structures. ; ; Allocate File Access Block. ; ; A file access block is required by RMS-32 to open and close a ; file. ; FAB_BLOCK: ; $FAB ALQ = 100,- ;Initial file size is to be - ;100 blocks FAC = PUT,- ;File Access Type is output FNA = FILE_NAME,- ;File name string address FNS = FILE_SIZE,- ;File name string size FOP = CTG,- ;File is to be contiguous MRS = 512,- ;Maximum record size is 512 - ;bytes NAM = NAM_BLOCK,- ;File name block address ORG = SEQ,- ;File organization is to be - ;sequential REM = FIX ;Record format is fixed length ; ; Allocate file information block. ; ; A file information block is required as an argument in the ; Queue I/O system service call that accesses a file. ; FIB_BLOCK: ; .BLKB FIB$K_LENGTH ; ; ; Allocate file information block descriptor. ; FIB_DESCR: ; .LONG FIB$K_LENGTH ;Length of the file ;information block .LONG FIB_BLOCK ;Address of the file ;information block ; ; Allocate File Name Block ; ; A file name block is required by RMS-32 to return information ; concerning a file (for example, the resultant file name string ; after logical name translation and defaults have been applied). ; NAM_BLOCK: ; $NAM ; ; ; Allocate Record Access Block ; ; A record access block is required by RMS-32 for record ; operations on a file. ; RAB_BLOCK: $RAB FAB = FAB_BLOCK,- ;File access block address RAC = SEQ,- ;Record access is to be - ;sequential RBF = RECORD_BUFFER,- ;Record buffer address RSZ = 512 ;Record buffer size ; ; Allocate direct address buffer ; BLOCK_BUFFER: .BLKB 1024 ;Direct access buffer is 1024 ;bytes ; ; Allocate space to store channel number returned by the $ASSIGN ; Channel system service. ; DEVICE_CHANNEL: ; .BLKW 1 ; ; ; Allocate device name string and descriptor. ; DEVICE_DESCR: ; .LONG 20$-10$ ;Length of device name string .LONG 10$ ;Address of device name string 10$: .ASCII /SYS$DISK/ ;Device on which created file ;will reside 20$: ;Reference label to calculate ;length ; ; Allocate file name string and define string length symbol. ; FILE_NAME: ; .ASCII /SYS$DISK:MYDATAFIL.DAT/ ;File name string FILE_SIZE=.-FILE_NAME ;File name string length ; ; Allocate I/O status quadword storage. ; IO_STATUS: ; .BLKQ 1 ; ; ; Allocate output record buffer. ; RECORD_BUFFER: ; .BLKB 512 ;Record buffer is 512 bytes ; ; ******************************************************************** ; ; Start Program ; ; ******************************************************************** ; ; The purpose of the program is to create a file called MYDATAFIL.DAT ; using RMS-32; store information concerning the file; write 100 ; records, each containing its record number in every byte; ; close the file; and then access, read, and write the file directly, ; using the Queue I/O system service. If any errors are detected, the ; program returns to its caller with the final error status in ; register R0. .ENTRY DISK_EXAMPLE,^M ;Program starting ;address ; ; First create the file and open it, using RMS-32. ; PART_1: ;First part of example $CREATE FAB = FAB_BLOCK ;Create and open file BLBC R0,20$ ;If low bit = 0, creation ;failure ; ; Second, connect the record access block to the created file. ; $CONNECT RAB = RAB_BLOCK ;Connect the record access ;block BLBC R0,30$ ;If low bit = 0, creation ;failure ; ; Now write 100 records, each containing its record number. ; MOVZBL #NUM_RECS,R6 ;Set record write loop count ; ; Fill each byte of the record to be written with its record number. ; 10$: SUBB3 R6,#NUM_RECS+1,R5 ;Calculate record number MOVC5 #0,(R6),R5,#512,RECORD_BUFFER ;Fill record buffer ; ; Now use RMS-32 to write the record into the newly created file. ; $PUT RAB = RAB_BLOCK ;Put record in file BLBC R0,30$ ;If low bit = 0, put failure SOBGTR R6,10$ ;Any more records to write? ; ; The file creation part of the example is almost complete. All that ; remains to be done is to store the file information returned by ; RMS-32 and close the file. ; MOVW NAM_BLOCK+NAM$W_FID,FIB_BLOCK+FIB$W_FID ;Save file ;identification MOVW NAM_BLOCK+NAM$W_FID+2,FIB_BLOCK+FIB$W_FID+2 ;Save ;sequence number MOVW NAM_BLOCK+NAM$W_FID+4,FIB_BLOCK+FIB$W_FID+4 ;Save ;relative volume $CLOSE FAB = FAB_BLOCK ;Close file BLBS R0,PART_2 ;If low bit set, successful ;close 20$ RET ;Return with RMS error status ; ; Record stream connection or put record failure. ; ; Close file and return status. ; 30$: PUSHL R0 ;Save error status $CLOSE FAB = FAB_BLOCK ;Close file POPL R0 ;Retrieve error status RET ;Return with RMS error status ; ; The second part of the example illustrates accessing the previously ; created file directly using the Queue I/O system service, randomly ; reading and writing various parts of the file, and then deaccessing ; the file. ; ; First, assign a channel to the appropriate device and access the ; file. PART_2: ; $ASSIGN_S DEVNAM = DEVICE_DESCR,- ;Assign a channel to file CHAN = DEVICE_CHANNEL ;device BLBC R0,20$ ;If low bit = 0, assign ;failure MOVL #FIB$M_NOWRITE!FIB$M_WRITE,- ;Set for read/write FIB_BLOCK+FIB$L_ACCTL ;access $QIOW_S CHAN = DEVICE_CHANNEL,- ;Access file on device channel FUNC = #IO$_ACCESS!IO$M_ACCESS,- ;I/O function is - ;access file IOSB = IO_STATUS,- ;Address of I/O status - ;quadword P1 = FIB_DESCR ;Address of information block ;descriptor BLBC R0,10$ ;If low bit = 0, access ;failure MOVZWL IO_STATUS,R0 ;Get final I/O completion ;status BLBS R0,30$ ;If low bit set, successful ;I/O function 10$: PUSHL R0 ;Save error status $DASSGN_S CHAN = DEVICE_CHANNEL ;Deassign file device channel POPL R0 ;Retrieve error status 20$: RET ;Return with I/O error status ; ; The file is now ready to be read and written randomly. Since the ; records are fixed length and exactly one block long, the record ; number corresponds to the virtual block number of the record in the ; file. Thus a particular record can be read or written simply by ; specifying its record number in the file. ; ; The following code reads two records at a time and checks to see ; that they contain their respective record numbers in every byte. ; The records are then written back into the file in reverse order. ; This results in record 1 having the old contents of record 2 and ; record 2 having the old contents of record 1, and so forth. After ; the example has been run, it is suggested that the file dump ; utility be used to verify the change in data positioning. ; 30$ MOVZBL #1,R6 ;Set starting record (block) ;number ; ; Read next two records into block buffer. ; 40$: $QIO_S CHAN = DEVICE_CHANNEL,- ;Read next two records from - ;file channel FUNC = #IO$_READVBLK,- ;I/O function is read virtual - ;block IOSB = IO_STATUS,- ;Address of I/O status - ;quadword P1 = BLOCK_BUFFER,- ;Address of I/O buffer P2 = #1024,- ;Size of I/O buffer P3 = R6 ;Starting virtual block of ;transfer BSBB 50$ ;Check I/O completion status ; ; Check each record to make sure it contains the correct data. ; SKPC R6,#512,BLOCK_BUFFER ;Skip over equal record ;numbers in data BNEQ 60$ ;If not equal, data match ;failure ADDL3 #1,R6,R5 ;Calculate even record number SKPC R5,#512,BLOCK_BUFFER+512 ;Skip over equal record ;numbers in data BNEQ 60$ ;If not equal, data match ;failure ; ; Record data matches. ; ; Write records in reverse order in file. ; $QIOW_S CHAN = DEVICE_CHANNEL,- ;Write even-numbered record in - ;odd slot FUNC = #IO$_WRITEVBLK,- ;I/O function is write virtual - ;block IOSB = IO_STATUS,- ;Address of I/O status - ;quadword P1 = BLOCK_BUFFER+512,- ;Address of even record buffer P2 = #512,- ;Length of even record buffer P3 = R6 ;Record number of odd record BSBB 50$ ;Check I/O completion status ADDL3 #1,R6,R5 ;Calculate even record number $QIOW_S CHAN = DEVICE_CHANNEL,- ;Write odd numbered record in - ;even slot FUNC = #IO$_WRITEVBLK,- ;I/O function is write virtual - ;block IOSB = IO_STATUS,- ;Address of I/O status - ;quadword P1 = BLOCK_BUFFER,- ;Address of odd record buffer P2 = #512,- ;Length of odd record buffer P3 = R5 ;Record number of even record BSBB 50$ ;Check I/O completion status ACBB #NUM_RECS-1,#2,R6,40$ ;Any more records to be read? BRB 70$ ; ; ; Check I/O completion status. ; 50$: BLBC R0,70$ ;If low bit = 0, service ;failure MOVZWL IO_STATUS,R0 ;Get final I/O completion ;status BLBC R0,70$ ;If low bit = 0, I/O function RSB ;failure ; ; Record number mismatch in data. ; 60$: MNEGL #4,R0 ;Set dummy error status value ; ; All records have been read, verified, and odd/even pairs inverted ; 70$: PUSHL R0 ;Save final status $QIOW_S CHAN = DEVICE_CHANNEL,- ;Deaccess file FUNC = #IO$_DEACCESS ;I/O function is deaccess file $DASSGN_S CHAN = DEVICE_CHANNEL ;Deassign file device channel POPL R0 ;Retrieve final status RET ; .END DISK_EXAMPLE