; ********************************************************************
;
.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,R3,R4,R5,R6> ;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 |