HP OpenVMS I/O User’s Reference Manual: OpenVMS Version 8.4 > Chapter 3 Magnetic Tape Drivers
3.5 Magnetic Tape Drive Programming Examples
This section
presents magnetic tape driver programming examples. Example 3-2 shows the recommended sequence for changing a device characteristic.
It retrieves the current characteristics using an IO$_SENSEMODE request,
sets the new characteristics bits, and then uses IO$_SETMODE to set
the new characteristics. Example 3-3 shows ways of specifying sense mode and set mode, both with and
without a user buffer specified, and with user buffers of different
lengths. In addition, Example 3-4 shows how data is written to and read from magnetic
tape through the magnetic tape ACP. Example 3-2 Device Characteristic Program Example $QIOW_S - ; Get current characteristics.
FUNC = #IO$_SENSEMODE,- ; - Sense mode
CHAN = CHANNEL,- ; - Channel
IOSB = IO_STATUS,- ; - IOSB
P1 = BUFFER,- ; - User buffer supplied
P2 = #12 ; - Buffer length = 12
.
.
.
(Check for errors)
.
.
.
(Set desired characteristics bits)
.
.
.
$QIOW_S - ; Set new characteristics.
FUNC = #IO$_SETMODE,- ; - Set Mode
CHAN = CHANNEL,- ; - Channel
IOSB = IO_STATUS,- ; - IOSB
P1 = BUFFER,- ; - User buffer address
P2 = #12 ; - Buffer length = 12
.
.
.
(Check for errors)
.
.
.
|
Example 3-3 Set Mode and Sense Mode Program Example .PSECT IMPURE, NOEXE, NOSHR
$IODEF
DEVICE_NAME: ; Name of device
.ASCID /MUA0/ ;
CHANNEL: ; Channel to device
.WORD 0 ;
BUFFER: .BLKL 3 ; Set/Sense characteristics
; buffer
IO_STATUS: ; Final I/O status
.QUAD 0 ;
.PSECT CODE, RD, NOWRT, EXE
.ENTRY MAIN,^M
|
|
|
$ASSIGN_S - ; Assign a channel to device
DEVNAM = DEVICE_NAME,- ;
CHAN = CHANNEL ;
BSBW ERR_CHECK2 ; Check for errors
$QIOW_S - ; Get current characteristics
FUNC = #IO$_SENSEMODE,-; No user buffer supplied
CHAN = CHANNEL,- ;
IOSB = IO_STATUS ;
BSBW ERR_CHECK ; Check for errors
$QIOW_S - ; Get current characteristics
FUNC = #IO$_SENSEMODE,-; User buffer supplied, length
CHAN = CHANNEL,- ; defaulted
IOSB = IO_STATUS,- ;
P1 = BUFFER ;
BSBW ERR_CHECK ; Check for errors
$QIOW_S - ; Get current characteristics
FUNC = #IO$_SENSEMODE,-; User buffer supplied, length
CHAN = CHANNEL,- ; = 8
IOSB = IO_STATUS,- ;
P1 = BUFFER,- ;
P2 = #8 ;
BSBW ERR_CHECK ; Check for errors
$QIOW_S - ; Get extended characteristics
FUNC = #IO$_SENSEMODE,-; User buffer supplied, length
CHAN = CHANNEL,- ; = 12
IOSB = IO_STATUS,- ;
P1 = BUFFER,- ;
P2 = #12 ;
BSBW ERR_CHECK ; Check for errors
$QIOW_S
|
|
|
FUNC = #IO$_SETMODE,- ; Length defaulted
CHAN = CHANNEL,- ;
IOSB = IO_STATUS,- ;
P1 = BUFFER ;
BSBW ERR_CHECK ; Check for errors
$QIOW_S - ; Set new characteristics
FUNC = #IO$_SETMODE,- ; Length = 8
CHAN = CHANNEL,- ;
IOSB = IO_STATUS,- ;
P1 = BUFFER,- ;
P2 = #8 ;
BSBW ERR_CHECK ; Check for errors
$QIOW_S - ; Set extended characteristics
FUNC = #IO$_SETMODE,- ; Length = 12
CHAN = CHANNEL,- ;
IOSB = IO_STATUS,- ;
P1 = BUFFER,- ;
P2 = #12 ;
BSBW ERR_CHECK ; Check for errors
RET
.ENABLE LSB
ERR_CHECK:
BLBS IO_STATUS,ERR_CHECK2 ; Continue if good IOSB
MOVZWL IO_STATUS,-(SP) ; Otherwise, set up for stop
BRB 10$ ; Branch to common code
ERR_CHECK2:
BLBS R0,20$ ; Continue if good status
PUSHL R0 ; Otherwise, set up for stop
10$: CALLS #1,G^LIB$STOP ; Stop execution
20$: RSB
.DISABLE LSB
.END MAIN
|
Example 3-4 MAGNETIC_TAPE.MAR Device Characteristic Program Example |
; *********************************************************************
;
.TITLE MAGTAPE PROGRAMMING EXAMPLE
.IDENT /01/
;
; Define necessary symbols.
;
$FIBDEF ;Define file information block
;symbols
$IODEF ;Define I/O function codes
;
; Allocate storage for the necessary data structures.
;
;
; Allocate magtape device name string and descriptor.
;
TAPENAME: ;
.LONG 20$-10$ ;Length of name string
.LONG 10$ ;Address of name string
10$: .ASCII /TAPE/ ;Name string
20$: ;Reference label
;
; Allocate space to store assigned channel number.
;
TAPECHAN: ;
.BLKW 1 ;Tape channel number
;
; Allocate space for the I/O status quadword.
;
IOSTATUS: ;
.BLKQ 1 ;I/O status quadword
;
; Allocate storage for the input/output buffer.
;
BUFFER: ;
.REPT 256 ;Initialize buffer to
.ASCII /A/ ;contain 'A'
.ENDR ;
;
; Now define the file information block (FIB), which the ACP uses
; in accessing and deaccessing the file. Both the user and the ACP
; supply the information required in the FIB to perform these
; functions.
;
FIB_DESCR: ;Start of FIB
.LONG ENDFIB-FIB ;Length of FIB
.LONG FIB ;Address of FIB
FIB: .LONG FIB$M_WRITE!FIB$M_NOWRITE ;Read/write access allowed
.WORD 0,0,0 ;File ID
.WORD 0,0,0 ;Directory ID
.LONG 0 ;Context
.WORD 0 ;Name flags
.WORD 0 ;Extend control
ENDFIB: ;Reference label
;
; Now define the file name string and descriptor.
;
NAME_DESCR: ;
.LONG END_NAME-NAME ;File name descriptor
.LONG NAME ;Address of name string
NAME: .ASCII "MYDATA.DAT;1" ;File name string
END_NAME: ;Reference label
;
; *********************************************************************
;
; Start Program
;
; *********************************************************************
;
; The program first assigns a channel to the magnetic tape unit and
; then performs an access function to create and access a file called
; MYDATA.DAT. Next, the program writes 26 blocks of data (the letters
; of the alphabet) to the tape. The first block contains all A's, the
; next, all B's, and so forth. The program starts by writing a block of
; 256 bytes, that is, the block of A's. Each subsequent block is reduced
; in size by two bytes so that by the time the block of Z's is written,
; the size is only 206 bytes. The magtape ACP does not allow the reading
; of a file that has been written until one of three events occurs:
; 1. The file is deaccessed.
; 2. The file is rewound.
; 3. The file is backspaced.
; In this example the file is backspaced zero blocks and then read in
; reverse (incrementing the block size every block); the data is
; checked against the data that is supposed to be there. If no data
; errors are detected, the file is deaccessed and the program exits.
;
.ENTRY MAGTAPE_EXAMPLE,^M,R4,R5,R6,R7,R8>
;
; First, assign a channel to the tape unit.
;
$ASSIGN_S TAPENAME,TAPECHAN ;Assign tape unit
CMPW #SS$_NORMAL,R0 ;Success?
BSBW ERRCHECK ;Find out
;
; Now create and access the file MYDATA.DAT.
;
$QIOW_S CHAN=TAPECHAN,- ;Channel is magtape
FUNC=#IO$_CREATE!IO$M_ACCESS!IO$M_CREATE,-;Function
- ;is create
IOSB=IOSTATUS,- ;Address of I/O status
- ;word
P1=FIB_DESCR,- ;FIB descriptor
P2=#NAME_DESCR ;Name descriptor
CMPW #SS$_NORMAL,R0 ;Success?
BSBW ERRCHECK ;Find out
;
; LOOP1 consists of writing the alphabet to the tape (see previous
; description).
;
MOVL #26,R5 ;Set up loop count
MOVL #256,R3 ;Set up initial byte count
;in R3
LOOP1: ;Start of loop
$QIOW_S CHAN=TAPECHAN,- ;Perform QIOW to tape channel
FUNC=#IO$_WRITEVBLK,- ;Function is write virtual
- ;block
P1=BUFFER,- ;Buffer address
P2=R3 ;Byte count
CMPW #SS$_NORMAL,R0 ;Success?
BSBW ERRCHECK ;Find out
;
; Now decrement the byte count in preparation for the next write
; operation and set up a loop count for updating the character
; written; LOOP2 performs the update.
SUBL2 #2,R3 ;Decrement byte count for
;next write
MOVL R3,R8 ;Copy byte count to R8 for
;LOOP2 count
MOVAL BUFFER,R7 ;Get buffer address in R7
LOOP2: INCB (R7)+ ;Increment character
SOBGTR R8,LOOP2 ;Until finished
SOBGTR R5,LOOP1 ;Repeat LOOP1 until alphabet
;complete
;
; The alphabet is now complete. Fall through LOOP1 and update the
; byte count so that it reflects the actual size of the last block
; written to tape.
;
ADDL2 #2,R3 ;Update byte count
;
; The tape is now read, but first the program must perform one of
; the three functions described previously before the ACP allows
; read access. The program performs an ACP control function,
; specifying skip zero blocks. This is a special case of skip reverse
; and causes the ACP to allow read access.
;
CLRL FIB+FIB$L_CNTRLVAL ;Set up to space zero blocks
MOVW #FIB$C_SPACE,FIB+FIB$W_CNTRLFUNC ;Set up for space
;function
$QIOW_S CHAN=TAPECHAN,- ;Perform QIOW to tape channel
FUNC=#IO$_ACPCONTROL,- ;Perform an ACP control
- ;function
P1=FIB_DESCR ;Define the FIB
CMPW #SS$_NORMAL,R0 ;Success?
BSBW ERRCHECK ;Find out
;
; Read the file in reverse.
;
MOVL #26,R5 ;Set up loop count
MOVB #^A/Z/,R6 ;Get first character in R6
LOOP3: ;
MOVAL BUFFER,R7 ;And buffer address to R7
$QIOW_S CHAN=TAPECHAN,- ;Channel is magtape
FUNC=#IO$_READVBLK!IO$M_REVERSE,- ;Function is read
- ;reverse
IOSB=IOSTATUS,- ;Define I/O status quadword
P1=BUFFER,- ;And buffer address
P2=R3 ;R3 bytes
CMPW #SS$_NORMAL,R0 ;Success?
BSBW ERRCHECK ;Find out
;
; Check the data read to verify that it matches the data written.
;
MOVL R3,R4 ;Copy R3 to R4 for loop count
CHECKDATA: ;
CMPB (R7)+,R6 ;Check each character
BNEQ MISMATCH ;If error, print message
SOBGTR R4,CHECKDATA ;Continue until finished
DECB R6 ;Go through alphabet in reverse
ADDL2 #2,R3 ;Update byte count by 2 for
;next block
SOBGTR R5,LOOP3 ;Read next block
;
; Now deaccess the file.
;
$QIOW_S CHAN=TAPECHAN,- ;Channel is magtape
FUNC=#IO$_DEACCESS,- ;Deaccess function
P1=FIB_DESCR,- ;File information block (required)
IOSB=IOSTATUS ;I/O status
;
; Deassign the channel and exit.
;
EXIT: $DASSGN_S CHAN=TAPECHAN ;Deassign channel
RET ;Exit
;
; If an error had been detected, a program would normally
; generate an error message here. But for this example the
; program simply exits.
;
MISMATCH: ;
BRB EXIT ;Exit
ERRCHECK: ;
BNEQ EXIT ;If not success, exit
RSB ;Otherwise, return
.END MAGTAPE_EXAMPLE
|
|
|