IN 181 Version : 1 25-Feb-1988 Transfer rates to various devices under VMS. Penelope Constanta-Fanourakis Margaret E. Votava Donald Petravick Data Acquisition Software Group Fermilab Computing Department Transfer rates from memory to magnetic disk, magnetic tape, optical disk on a VAX 11/780 under VMS V4.4 and/or V4.6 using the QIO system service routines. KEYWORDS:TIMING, VMS Systems Supported: VMS V4.6 CONTENTS ______________________________________________________________________ CHAPTER 1 INTRODUCTION CHAPTER 2 TRANSFER RATES FROM MEMORY TO DEVICE 2.1 MAGNETIC DISK DEVICE RATES . . . . . . . . . . . . 2-2 2.1.1 Digital RA81 Disk Drive . . . . . . . . . . . . 2-2 2.1.2 CDC EMD III 9720/850 Winchester Disk Drive . . . 2-3 2.2 MAGNETIC TAPE DEVICE RATES . . . . . . . . . . . . 2-5 2.3 SREAMING MAGNETIC TAPE DEVICE RATES . . . . . . . 2-6 2.4 OPTICAL DISK DEVICE RATES (EMULEX CONTROLLER) . . 2-7 2.5 OPTICAL DISK DEVICE RATES (KOM CONTROLLER AND DRIVER) . . . . . . . . . . . . . . . . . . . . . 2-8 APPENDIX A SINGLE BUFFER PROGRAM SOURCE CODE APPENDIX B DOUBLE BUFFER PROGRAM SOURCE CODE APPENDIX C SINGLE BUFFER PROGRAM SOURCE CODE (EMULEX CONTROLLER) APPENDIX D DOUBLE BUFFER PROGRAM SOURCE CODE (EMULEX CONTROLLER) iii CHAPTER 1 INTRODUCTION The results given in this document were obtained on a VAX 11/780 running VMS V4.4 for all devices except the streaming magnetic tape for which a microVAX II running VMS V4.4 was used and the AVIV hard disk which also used a microVAX II but under VMS V4.6. Care was taken so that there were no page faults during the execution of the DMA transfers and the timing process was the only process on the system. The rates were obtained using the QIO VMS system service. The FORTRAN programs used both modes of the QIO system service, wait and non-wait. In the non-wait case a QIO was issued, (for a buffer to be written to the device) before the preceding QIO to write a buffer had completed. Transfer rates were obtained for the following devices o Magnetic disk RA81, using the VMS version V4.4 Digital standard DU device class driver with the PU device port driver. o Magnetic tape, initialized at 6250 BPI, 75 IPS start/stop, STC 1921 tape drive with AVIV supplied UNIBUS controller (TFC 805A) and AVIV version V55 MF device driver. o Streaming magnetic tape, initialized at 6250 BPI, 100 IPS streaming, 50 IPS start/stop, STC 2925 tape drive with AVIV supplied QBUS controller (TFC 925B) and Digital standard TS device driver. o Optical disk, written with the OPTIMEM 1000 disk drive, using the EMULEX controller with version D of the EPROM and the VMS version V4.4 Digital standard DU device class driver with the PU device port driver. o Optical disk, written with the OPTIMEM 1000 disk drive, using the KOM UNIBUS controller with version V1.21 of the EPROM and the KOM version V4.1 ZB device driver. 1-1 INTRODUCTION On the OPTIMEM 1000 optical disk drive an interleave of one was selected (sectors read contiguously). This means that physical block i is adjacent to physical block i+1. This setting, according to the OPTIMEM 1000 drive manual, allows for a maximum transfer rate to the optical disk of 480000 Bytes/sec, as opposed to an interleave of three which allows only for a 96000 Bytes/sec. 1-2 CHAPTER 2 TRANSFER RATES FROM MEMORY TO DEVICE Appendices A and B contain the source of the program code using the wait and non-wait mode of the QIO system service respectively, used on all devices but the optical disk device addressed via the EMULEX controller. Execution of the programs results in the creation a contiguous file on the device allocating the appropriate number of blocks using a user open routine. The file is then populated using the QIO system service routines, which do not include the Record Management System (RMS) time overhead. The obtained transfer rates are based on the population of the files and do not include the file creation time. To obtain the elapsed time the LIB$INIT_TIMER and LIB$SHOW_TIMER routines of the VMS RTL services were used. Appendices C and D contain the source of the program code using the wait and non-wait mode of the QIO system service respectively, used on the optical disk device addressed via the EMULEX controller. Execution of the programs result in writing blocks of data to a logical block on the optical disk using the QIO system service routines. The difference between the corresponding source code for the EMULEX controller and the rest of the devices is that there is no VMS file structure on the optical disk when addressed via the EMULEX controller. None of device drivers did read after write data checking thus causing time delays while writing to the device. 2-1 TRANSFER RATES FROM MEMORY TO DEVICE 2.1 MAGNETIC DISK DEVICE RATES 2.1.1 Digital RA81 Disk Drive VAX 11/780 DUA0 (RA81), DIGITAL STANDARD DU DRIVER SINGLE BUFFER (WAIT QIO) +------------+-------------------+--------------+-----------------+ | BLOCK SIZE | NUMBER OF BLOCKS | ELAPSED TIME | RATE IN | | | TRANSFERED | IN SEC | 1000 BYTES/SEC | +------------+-------------------+--------------+-----------------+ | 1024 | 3200 | 55.69 | 58.84 | | 2048 | 1600 | 29.31 | 111.80 | | 4096 | 800 | 16.48 | 198.83 | | 8192 | 400 | 16.00 | 204.80 | | 16384 | 200 | 14.11 | 232.23 | | 16384 | 300 | 20.95 | 234.62 | | | | | | +------------+-------------------+--------------+-----------------+ VAX 11/780 DUA0 (RA81), DIGITAL STANDARD DU DRIVER DOUBLE BUFFER (NON-WAIT QIO) +------------+-------------------+--------------+-----------------+ | BLOCK SIZE | NUMBER OF BLOCKS | ELAPSED TIME | RATE IN | | | TRANSFERED | IN SEC | 1000 BYTES/SEC | +------------+-------------------+--------------+-----------------+ | 1024 | 3200 | 55.49 | 59.05 | | 2048 | 1600 | 29.15 | 112.41 | | 4096 | 800 | 15.87 | 206.48 | | 8192 | 400 | 16.00 | 204.80 | | 16384 | 200 | 12.85 | 255.00 | | 16384 | 300 | 18.84 | 260.89 | | | | | | +------------+-------------------+--------------+-----------------+ 2-2 TRANSFER RATES FROM MEMORY TO DEVICE 2.1.2 CDC EMD III 9720/850 Winchester Disk Drive MicroVAX II CDC EMD III 9720/850 Winchester Disk Drive AVIV DFC 917 SMD/MSCP Compatible Disk Controller DIGITAL DU (RA81) emulator High Water Mark Turned On SINGLE BUFFER (WAIT QIO) +------------+-------------------+--------------+-----------------+ | BLOCK SIZE | NUMBER OF BLOCKS | ELAPSED TIME | RATE IN | | | TRANSFERED | IN SEC | 1000 BYTES/SEC | +------------+-------------------+--------------+-----------------+ | 1024 | 3200 | 55.25 | 59.30 | | 2048 | 1600 | 28.70 | 114.17 | | 4096 | 800 | 15.54 | 210.86 | | 8192 | 400 | 8.99 | 364.49 | | 16384 | 200 | 8.96 | 365.71 | | 16384 | 300 | 13.39 | 367.08 | | | | | | +------------+-------------------+--------------+-----------------+ MicroVAX II CDC EMD III 9720/850 Winchester Disk Drive AVIV DFC 917 SMD/MSCP Compatible Disk Controller DIGITAL DU (RA81) emulator High Water Mark Turned On DOUBLE BUFFER (NON-WAIT QIO) +------------+-------------------+--------------+-----------------+ | BLOCK SIZE | NUMBER OF BLOCKS | ELAPSED TIME | RATE IN | | | TRANSFERED | IN SEC | 1000 BYTES/SEC | +------------+-------------------+--------------+-----------------+ | 1024 | 3200 | 55.24 | 59.32 | | 2048 | 1600 | 28.70 | 114.17 | | 4096 | 800 | 15.50 | 211.41 | | 8192 | 400 | 8.89 | 368.59 | | 16384 | 200 | 8.81 | 371.94 | | 16384 | 300 | 13.18 | 372.93 | | | | | | +------------+-------------------+--------------+-----------------+ 2-3 TRANSFER RATES FROM MEMORY TO DEVICE MicroVAX II CDC EMD III 9720/850 Winchester Disk Drive AVIV DFC 917 SMD/MSCP Compatible Disk Controller DIGITAL DU (RA81) emulator High Water Mark Turned Off DOUBLE BUFFER (NON-WAIT QIO) +------------+-------------------+--------------+-----------------+ | BLOCK SIZE | NUMBER OF BLOCKS | ELAPSED TIME | RATE IN | | | TRANSFERED | IN SEC | 1000 BYTES/SEC | +------------+-------------------+--------------+-----------------+ | 1024 | 3200 | 55.35 | 69.61 | | 2048 | 1600 | 28.70 | 114.17 | | 4096 | 800 | 15.41 | 212.64 | | 8192 | 400 | 9.03 | 362.88 | | 16384 | 200 | 8.77 | 373.64 | | 16384 | 300 | 13.08 | 375.78 | | | | | | +------------+-------------------+--------------+-----------------+ MicroVAX II CDC EMD III 9720/850 Winchester Disk Drive AVIV DFC 917 SMD/MSCP Compatible Disk Controller DIGITAL DU (RA81) emulator High Water Mark Turned Off DOUBLE BUFFER (NON-WAIT QIO) +------------+-------------------+--------------+-----------------+ | BLOCK SIZE | NUMBER OF BLOCKS | ELAPSED TIME | RATE IN | | | READ | IN SEC | 1000 BYTES/SEC | +------------+-------------------+--------------+-----------------+ | 1024 | 3200 | 40.29 | 81.33 | | 2048 | 1600 | 29.82 | 109.89 | | 8192 | 400 | 10.26 | 319.38 | | 16384 | 300 | 10.64 | 461.95 | | | | | | +------------+-------------------+--------------+-----------------+ 2-4 TRANSFER RATES FROM MEMORY TO DEVICE 2.2 MAGNETIC TAPE DEVICE RATES VAX 11/780 MFA0 (DENSITY = 6250 BPI, 75 IPS START/STOP) AVIV CONTROLLER, AVIV DRIVER SINGLE BUFFER (WAIT QIO) +------------+-------------------+--------------+-----------------+ | BLOCK SIZE | NUMBER OF BLOCKS | ELAPSED TIME | RATE IN | | | TRANSFERED | IN SEC | 1000 BYTES/SEC | +------------+-------------------+--------------+-----------------+ | 1024 | 3200 | 34.28 | 95.59 | | 2048 | 1600 | 20.90 | 156.78 | | 4096 | 800 | 14.39 | 227.71 | | 8192 | 400 | 10.69 | 306.53 | | 16384 | 200 | 9.03 | 362.88 | | 16384 | 400 | 18.07 | 362.68 | | 16384 | 2000 | 90.58 | 361.76 | | | | | | +------------+-------------------+--------------+-----------------+ VAX 11/780 MFA0 (DENSITY = 6250 BPI, 75 IPS START/STOP) AVIV CONTROLLER, AVIV DRIVER DOUBLE BUFFER (NON-WAIT QIO) +------------+-------------------+--------------+-----------------+ | BLOCK SIZE | NUMBER OF BLOCKS | ELAPSED TIME | RATE IN | | | TRANSFERED | IN SEC | 1000 BYTES/SEC | +------------+-------------------+--------------+-----------------+ | 1024 | 3200 | 23.23 | 141.06 | | 2048 | 1600 | 15.10 | 217.01 | | 4096 | 800 | 11.38 | 287.94 | | 8192 | 400 | 9.27 | 353.48 | | 16384 | 200 | 8.09 | 405.04 | | 16384 | 400 | 16.40 | 399.61 | | 16384 | 2000 | 81.38 | 402.65 | | | | | | +------------+-------------------+--------------+-----------------+ 2-5 TRANSFER RATES FROM MEMORY TO DEVICE 2.3 SREAMING MAGNETIC TAPE DEVICE RATES MicroVAX II MSA0 (DENSITY = 6250 BPI, 100 IPS STREAMING) AVIV CONTROLLER, DIGITAL STANDARD TS DRIVER SINGLE BUFFER (WAIT QIO) +------------+-------------------+--------------+-----------------+ | BLOCK SIZE | NUMBER OF BLOCKS | ELAPSED TIME | RATE IN | | | TRANSFERED | IN SEC | 1000 BYTES/SEC | +------------+-------------------+--------------+-----------------+ | 1024 | 3200 | 25.45 | 128.75 | | 2048 | 1600 | 15.51 | 211.27 | | 4096 | 800 | 9.53 | 343.84 | | 8192 | 400 | 8.67 | 377.95 | | 16384 | 200 | 6.95 | 471.48 | | 16384 | 2000 | 68.86 | 475.86 | | | | | | +------------+-------------------+--------------+-----------------+ MicroVAX II MSA0 (DENSITY = 6250 BPI, 100 IPS STREAMING) AVIV CONTROLLER, DIGITAL STANDARD TS DRIVER DOUBLE BUFFER (NON-WAIT QIO) +------------+-------------------+--------------+-----------------+ | BLOCK SIZE | NUMBER OF BLOCKS | ELAPSED TIME | RATE IN | | | TRANSFERED | IN SEC | 1000 BYTES/SEC | +------------+-------------------+--------------+-----------------+ | 1024 | 3200 | 25.45 | 128.75 | | 2048 | 1600 | 15.51 | 211.27 | | 4096 | 800 | 9.45 | 346.75 | | 8192 | 400 | 7.63 | 429.46 | | 16384 | 200 | 6.40 | 512.00 | | 16384 | 2000 | 63.82 | 513.44 | | | | | | +------------+-------------------+--------------+-----------------+ 2-6 TRANSFER RATES FROM MEMORY TO DEVICE 2.4 OPTICAL DISK DEVICE RATES (EMULEX CONTROLLER) VAX 11/780 OPTIMEM 1000 OPTICAL DISK DRIVE, INTERLEAVE OF ONE EMULEX CONTROLLER, VMS DU DRIVER SINGLE BUFFER (WAIT QIO) +------------+-------------------+--------------+-----------------+ | BLOCK SIZE | NUMBER OF BLOCKS | ELAPSED TIME | RATE IN | | | TRANSFERED | IN SEC | 1000 BYTES/SEC | +------------+-------------------+--------------+-----------------+ | 1024 | 3200 | 179.98 | 18.21 | | 2048 | 1600 | 94.45 | 34.69 | | 4096 | 800 | 50.35 | 65.08 | | 8192 | 400 | 28.34 | 115.62 | | 16384 | 200 | 17.93 | 182.76 | | 16384 | 300 | 27.65 | 177.76 | | 32768 | 200 | 24.65 | 265.87 | | 32768 | 300 | 36.69 | 267.93 | | | | | | +------------+-------------------+--------------+-----------------+ VAX 11/780 OPTIMEM 1000 OPTICAL DISK DRIVE, INTERLEAVE OF ONE EMULEX CONTROLLER, VMS DU DRIVER DOUBLE BUFFER (NON-WAIT QIO) +------------+-------------------+--------------+-----------------+ | BLOCK SIZE | NUMBER OF BLOCKS | ELAPSED TIME | RATE IN | | | TRANSFERED | IN SEC | 1000 BYTES/SEC | +------------+-------------------+--------------+-----------------+ | 1024 | 3200 | 178.27 | 18.38 | | 2048 | 1600 | 92.39 | 35.47 | | 4096 | 800 | 49.66 | 65.98 | | 8192 | 400 | 28.19 | 116.24 | | 16384 | 200 | 17.52 | 187.03 | | 16384 | 300 | 27.49 | 178.80 | | 32768 | 200 | 24.32 | 269.47 | | 32768 | 300 | 36.55 | 268.96 | | | | | | +------------+-------------------+--------------+-----------------+ 2-7 TRANSFER RATES FROM MEMORY TO DEVICE 2.5 OPTICAL DISK DEVICE RATES (KOM CONTROLLER AND DRIVER) VAX 11/780 OPTIMEM 1000 OPTICAL DISK DRIVE, INTERLEAVE OF ONE KOM CONTROLLER AND DRIVER SINGLE BUFFER (WAIT QIO) +------------+-------------------+--------------+-----------------+ | BLOCK SIZE | NUMBER OF BLOCKS | ELAPSED TIME | RATE IN | | | TRANSFERED | IN SEC | 1000 BYTES/SEC | +------------+-------------------+--------------+-----------------+ | 1024 | 3200 | 352.90 | 9.28 | | 2048 | 1600 | 181.80 | 18.02 | | 4096 | 800 | 92.02 | 35.61 | | 8192 | 400 | 74.85 | 43.78 | | 16384 | 200 | 63.93 | 51.26 | | | | | | +------------+-------------------+--------------+-----------------+ VAX 11/780 OPTIMEM 1000 OPTICAL DISK DRIVE, INTERLEAVE OF ONE KOM CONTROLLER AND DRIVER DOUBLE BUFFER (NON-WAIT QIO) +------------+-------------------+--------------+-----------------+ | BLOCK SIZE | NUMBER OF BLOCKS | ELAPSED TIME | RATE IN | | | TRANSFERED | IN SEC | 1000 BYTES/SEC | +------------+-------------------+--------------+-----------------+ | 1024 | 3200 | 355.68 | 9.21 | | 2048 | 1600 | 181.74 | 18.03 | | 4096 | 800 | 96.02 | 34.13 | | 8192 | 400 | 79.27 | 41.34 | | 16384 | 200 | 63.74 | 51.41 | | | | | | +------------+-------------------+--------------+-----------------+ 2-8 APPENDIX A SINGLE BUFFER PROGRAM SOURCE CODE PROGRAM TIME_QIOW C C This routine handles disks, tapes on a local node. C Benchmark and exercise populating files with the $QIO service. C C DLP 14-oct-1986 FERMI Natl accellerator lab C IMPLICIT NONE INCLUDE '($IODEF)' INCLUDE '($SYSSRVNAM)' INCLUDE '($DVIDEF)' INCLUDE '($DCDEF)' PARAMETER LUN = 1 C INTEGER*4 BLOCK_NUMBER INTEGER*4 QIO_CHANNEL,BLOCK_ALLOCATION INTEGER*2 IOSB(4) INTEGER*4 STATUS COMMON /UFO_COMMON/ QIO_CHANNEL, BLOCK_ALLOCATION C C Global Routines C =============== C EXTERNAL UFOWRITE INTEGER*4 FOR$RAB,LIB$GET_INPUT C C Local Storage C ============= C INTEGER*4 UFO_CHANNEL,I,NIO INTEGER*4 DEVCLASS INTEGER*4 TEMP /0/ INTEGER*4 BLOCK_SIZE, NUMBER_OF_BLOCKS, DEVICE_BLOCKSIZE CHARACTER*255 FILE_NAME CHARACTER*1 TRUNCATE BYTE STRING(66000) /66000*1HA/ C C ========================================================== A-1 SINGLE BUFFER PROGRAM SOURCE CODE C 100 CONTINUE C C Get file name to open C STATUS = LIB$GET_INPUT (FILE_NAME,'FILE to create:') IF (.NOT. STATUS) CALL EXIT (STATUS) C C Check if the file exists C CALL LIB$FIND_FILE (FILE_NAME, FILE_NAME, temp) FILE_NAME = FILE_NAME ( :INDEX (FILE_NAME, ';')) CALL LIB$GETDVI (DVI$_DEVCLASS,,FILE_NAME,DEVCLASS) C C Get the number of bytes to be transfered at each QIO call C TYPE '(A,$)',' Enter bytes in each transfer:' ACCEPT *, BLOCK_SIZE C C Get the total number of transfers C TYPE '(A,$)',' Number of transfers:' ACCEPT *, NIO C C Get the device block size C IF (DEVCLASS .eq. DC$_DISK) THEN TYPE '(A,$)',' Number of bytes in disk block:' ACCEPT *, DEVICE_BLOCKSIZE C C Calculate the number of blocks written at each transfer C NUMBER_OF_BLOCKS = & (BLOCK_SIZE + DEVICE_BLOCKSIZE - 1)/DEVICE_BLOCKSIZE C C Get the number of extra blocks to be allocated for the file C TYPE '(A,$)',' Number of extra blocks to allocate:' ACCEPT *, BLOCK_ALLOCATION C C Calculate the number of blocks to be allocted for the file C BLOCK_ALLOCATION = BLOCK_ALLOCATION + (NIO * NUMBER_OF_BLOCKS) END IF C C Open the file so that the channel number is available in order C to be able to issue QIO C OPEN (UNIT=LUN,FILE=FILE_NAME,FORM='UNFORMATTED', & STATUS='NEW',RECL=(BLOCK_SIZE+3)/4, & ORGANIZATION='SEQUENTIAL', & RECORDTYPE='FIXED',USEROPEN=UFOWRITE) C A-2 SINGLE BUFFER PROGRAM SOURCE CODE C Find the staring block number C IF (DEVCLASS .EQ. DC$_DISK) THEN BLOCK_NUMBER = 1 ELSE BLOCK_NUMBER = 0 END IF C C Initialize the timer C CALL LIB$INIT_TIMER C C Issue the QIOs C DO I = 1,NIO STATUS = SYS$QIOW(,%VAL(QIO_CHANNEL),%VAL(IO$_WRITEVBLK), & IOSB,,,STRING,%VAL(BLOCK_SIZE), & %VAL(BLOCK_NUMBER),,,) IF (STATUS) THEN IF ( IOSB(1)) THEN C C If disk, manually update BLOCK_NUMBER C IF (DEVCLASS .EQ. DC$_DISK) THEN BLOCK_NUMBER = BLOCK_NUMBER + NUMBER_OF_BLOCKS END IF ELSE CALL LIB$SIGNAL(%VAL(ZEXT(IOSB(1)))) END IF ELSE CALL LIB$SIGNAL(%VAL(STATUS)) END IF END DO C C Get the time passed C CALL LIB$SHOW_TIMER C C Initialize variables C IF (STATUS) STATUS = SYS$DASSGN (%val(QIO_CHANNEL)) CALL LIB$SIGNAL (%VAL(STATUS)) TYPE *, ' ' TYPE *, ' ***************' TYPE *, ' ' C C Go and get next file to be opened C GOTO 100 C C Exit C END A-3 SINGLE BUFFER PROGRAM SOURCE CODE C INTEGER*4 FUNCTION UFOWRITE(FAB, RAB, LUN) C IMPLICIT NONE INCLUDE '($RABDEF)' INCLUDE '($FABDEF)' INCLUDE '($SYSSRVNAM)' INTEGER*4 LUN RECORD /FABDEF/FAB RECORD /RABDEF/RAB INTEGER*4 QIO_CHANNEL,BLOCK_ALLOCATION COMMON /UFO_COMMON/ QIO_CHANNEL, BLOCK_ALLOCATION C C The first two bits must be set C FAB.FAB$B_SHR = FAB.FAB$B_SHR .OR. FAB$M_NIL FAB.FAB$L_FOP = FAB.FAB$L_FOP .OR. FAB$M_UFO .OR. FAB$M_CTG C C Need to allocate all disk space now. FAB$W_DEQ inoperable. C Allow block IO access C FAB.FAB$B_FAC = FAB.FAB$B_FAC .OR. FAB$M_BIO FAB.FAB$L_ALQ = BLOCK_ALLOCATION C C Create the file C UFOWRITE = SYS$CREATE(FAB) IF (FAB.FAB$L_STS) THEN C C FAB$L_STV contains condition on failure, otherwise channel number C If FAB$L_STV has value BADATTRIB, then the tape may have been mounted C with too small of a /BLOCKSIZE. C QIO_CHANNEL = FAB.FAB$L_STV ELSE CALL LIB$SIGNAL(%VAL(FAB.FAB$L_STS),,%VAL(FAB.FAB$L_STV)) END IF RETURN END A-4 APPENDIX B DOUBLE BUFFER PROGRAM SOURCE CODE PROGRAM TIME_QIO C C This routine handles disks, tapes on a local node. C Benchmark and exercise populating files with the $QIO service. C C There is always a call to QIO service to be executed by the C driver. C C DLP 14-oct-1986 FERMI Natl accellerator lab C PCF 23-Oct-1986 C IMPLICIT NONE INCLUDE '($IODEF)' INCLUDE '($SYSSRVNAM)' INCLUDE '($DVIDEF)' INCLUDE '($DCDEF)' PARAMETER LUN = 1 C INTEGER*4 BLOCK_NUMBER INTEGER*4 QIO_CHANNEL,BLOCK_ALLOCATION INTEGER*2 IOSB1(4), IOSB2(4) INTEGER*4 STATUS COMMON /UFO_COMMON/ QIO_CHANNEL, BLOCK_ALLOCATION C C Global Routines C =============== C INTEGER*4 LIB$GET_EF, LIB$FREE_EF EXTERNAL UFOWRITE INTEGER*4 FOR$RAB,LIB$GET_INPUT C C Local Storage C ============= C INTEGER*4 UFO_CHANNEL,I,NIO INTEGER*4 DEVCLASS INTEGER*4 TEMP /0/ INTEGER*4 BLOCK_SIZE, NUMBER_OF_BLOCKS B-1 DOUBLE BUFFER PROGRAM SOURCE CODE INTEGER*4 DEVICE_BLOCKSIZE CHARACTER*255 FILE_NAME BYTE STRING(66000) /66000*1hA/ INTEGER*4 EF1, EF2 C C ========================================================== C 100 CONTINUE C STATUS = LIB$GET_INPUT (FILE_NAME,'FILE to create:') IF (.NOT. STATUS) CALL EXIT (STATUS) C C Check if the file exists C CALL LIB$FIND_FILE (FILE_NAME, FILE_NAME, temp) FILE_NAME = FILE_NAME ( :INDEX (FILE_NAME, ';')) CALL LIB$GETDVI (DVI$_DEVCLASS,,FILE_NAME,DEVCLASS) C C Get the number of byte tranfers for each QIO C TYPE '(A,$)',' Enter bytes in each transfer:' ACCEPT *, BLOCK_SIZE C C Get the number of tranfers to be performed C TYPE '(A,$)',' Number of transfers:' ACCEPT *, NIO C C Get the device block size C IF (DEVCLASS .eq. DC$_DISK) THEN TYPE '(A,$)',' Number of bytes in disk block:' ACCEPT *, DEVICE_BLOCKSIZE C C Calculate the number of blocks to be allocated for the file C NUMBER_OF_BLOCKS = & (BLOCK_SIZE + DEVICE_BLOCKSIZE - 1)/DEVICE_BLOCKSIZE C C Get the number of extra blocks to be allocated for the file C TYPE '(A,$)',' Number of extra blocks to allocate:' ACCEPT *, BLOCK_ALLOCATION C C Calculate the total file block size C BLOCK_ALLOCATION = BLOCK_ALLOCATION + (NIO * NUMBER_OF_BLOCKS) END IF C C Open the file, so that the channel is returned in order to be able C to perform QIOs. C OPEN (UNIT=LUN,FILE=FILE_NAME,FORM='UNFORMATTED', B-2 DOUBLE BUFFER PROGRAM SOURCE CODE & STATUS='NEW',RECL=(BLOCK_SIZE+3)/4, & ORGANIZATION='SEQUENTIAL', & RECORDTYPE='FIXED',USEROPEN=UFOWRITE) C C Initialize the first block number to be written C IF (DEVCLASS .EQ. DC$_DISK) THEN BLOCK_NUMBER = 1 ELSE BLOCK_NUMBER = 0 END IF C C Setup the event flags to be used by the SYS$QIO routines C STATUS = LIB$GET_EF(EF1) IF (.NOT.STATUS) CALL EXIT(STATUS) STATUS = LIB$GET_EF(EF2) IF (.NOT.STATUS) CALL EXIT(STATUS) C C Setup the timer C CALL LIB$INIT_TIMER C C Initialize the non wait QIOs C STATUS = SYS$QIO(%VAL(EF1),%VAL(QIO_CHANNEL),%VAL(IO$_WRITEVBLK), & IOSB1,,,STRING,%VAL(BLOCK_SIZE), & %VAL(BLOCK_NUMBER),,,) IF (STATUS) THEN C C If disk, manually update BLOCK_NUMBER C IF (DEVCLASS .EQ. DC$_DISK) THEN BLOCK_NUMBER = BLOCK_NUMBER + NUMBER_OF_BLOCKS END IF ELSE CALL LIB$SIGNAL(%VAL(STATUS)) END IF C C Do the QIOs C DO I = 2, NIO IF (MOD(I,2) .EQ. 0) THEN STATUS = SYS$QIO(%VAL(EF2),%VAL(QIO_CHANNEL), & %VAL(IO$_WRITEVBLK), & IOSB2,,,STRING,%VAL(BLOCK_SIZE), & %VAL(BLOCK_NUMBER),,,) IF (STATUS) THEN C C If disk, manually update BLOCK_NUMBER C IF (DEVCLASS .EQ. DC$_DISK) THEN BLOCK_NUMBER = BLOCK_NUMBER + NUMBER_OF_BLOCKS B-3 DOUBLE BUFFER PROGRAM SOURCE CODE END IF ELSE CALL LIB$SIGNAL(%VAL(STATUS)) END IF C C Wait for previous QIO to finish C STATUS = SYS$SYNCH(%VAL(EF1), IOSB1) IF (STATUS) THEN IF (.NOT. IOSB1(1)) CALL LIB$SIGNAL(%VAL(ZEXT(IOSB1(1)))) ELSE CALL LIB$SIGNAL(%VAL(STATUS)) END IF ELSE STATUS = SYS$QIO(%VAL(EF1),%VAL(QIO_CHANNEL), & %VAL(IO$_WRITEVBLK), & IOSB1,,,STRING,%VAL(BLOCK_SIZE), & %VAL(BLOCK_NUMBER),,,) IF (STATUS) THEN C C If disk, manually update BLOCK_NUMBER C IF (DEVCLASS .EQ. DC$_DISK) THEN BLOCK_NUMBER = BLOCK_NUMBER + NUMBER_OF_BLOCKS END IF ELSE CALL LIB$SIGNAL(%VAL(STATUS)) END IF C C Wait for previous QIO to finish C STATUS = SYS$SYNCH(%VAL(EF2), IOSB2) IF (STATUS) THEN IF (.NOT. IOSB2(1)) CALL LIB$SIGNAL(%VAL(ZEXT(IOSB2(1)))) ELSE CALL LIB$SIGNAL(%VAL(STATUS)) END IF END IF END DO C C Wait for the last QIO to complete C IF (MOD(NIO,2) .EQ. 0) THEN STATUS = SYS$SYNCH(%VAL(EF1), IOSB1) IF (STATUS) THEN IF (.NOT. IOSB1(1)) CALL LIB$SIGNAL(%VAL(ZEXT(IOSB1(1)))) ELSE CALL LIB$SIGNAL(%VAL(STATUS)) END IF ELSE STATUS = SYS$SYNCH(%VAL(EF2), IOSB2) IF (STATUS) THEN IF (.NOT. IOSB2(1)) CALL LIB$SIGNAL(%VAL(ZEXT(IOSB2(1)))) B-4 DOUBLE BUFFER PROGRAM SOURCE CODE ELSE CALL LIB$SIGNAL(%VAL(STATUS)) END IF END IF C C Check the timer C CALL LIB$SHOW_TIMER C C Initialize variables C IF (STATUS) STATUS = SYS$DASSGN (%val(QIO_CHANNEL)) CALL LIB$SIGNAL (%VAL(STATUS)) STATUS = LIB$FREE_EF(EF1) IF (.NOT.STATUS) CALL EXIT(STATUS) STATUS = LIB$FREE_EF(EF2) IF (.NOT.STATUS) CALL EXIT(STATUS) TYPE *, ' ' TYPE *, ' ***************' TYPE *, ' ' C C Check if more files are to be created C GOTO 100 C C Exit C END B-5 DOUBLE BUFFER PROGRAM SOURCE CODE C INTEGER*4 FUNCTION UFOWRITE(FAB, RAB, LUN) C IMPLICIT NONE INCLUDE '($RABDEF)' INCLUDE '($FABDEF)' INCLUDE '($SYSSRVNAM)' INTEGER*4 LUN RECORD /FABDEF/FAB RECORD /RABDEF/RAB INTEGER*4 QIO_CHANNEL,BLOCK_ALLOCATION COMMON /UFO_COMMON/ QIO_CHANNEL, BLOCK_ALLOCATION C C The first two bits must be set C FAB.FAB$B_SHR = FAB.FAB$B_SHR .OR. FAB$M_NIL FAB.FAB$L_FOP = FAB.FAB$L_FOP .OR. FAB$M_UFO .OR. FAB$M_CTG C C Need to allocate all disk space now. FAB$W_DEQ inoperable. C Allow block IO access C FAB.FAB$B_FAC = FAB.FAB$B_FAC .OR. FAB$M_BIO FAB.FAB$L_ALQ = BLOCK_ALLOCATION C C Create the file C UFOWRITE = SYS$CREATE(FAB) IF (FAB.FAB$L_STS) THEN C C FAB$L_STV contains condition on failure, otherwise channel number C If FAB$L_STV has value BADATTRIB, then the tape may have been mounted C with too small of a /BLOCKSIZE. C QIO_CHANNEL = FAB.FAB$L_STV ELSE CALL LIB$SIGNAL(%VAL(FAB.FAB$L_STS),,%VAL(FAB.FAB$L_STV)) END IF RETURN END B-6 APPENDIX C SINGLE BUFFER PROGRAM SOURCE CODE (EMULEX CONTROLLER) PROGRAM EMULEX_TIME_QIOW C C Benchmark and exercise populating an optical disk with the $QIO service. C C There is always a call to QIO service to be executed by the C driver. C C DLP 14-oct-1986 FERMI Natl accellerator lab C PCF 23-Oct-1986 C IMPLICIT NONE INCLUDE '($IODEF)' INCLUDE '($SYSSRVNAM)' C INTEGER*4 BLOCK_NUMBER INTEGER*4 QIO_CHANNEL INTEGER*2 IOSB(4) INTEGER*4 STATUS C C Global Routines C =============== C INTEGER*4 LIB$GET_EF, LIB$FREE_EF INTEGER*4 LIB$GET_INPUT C C Local Storage C ============= C INTEGER*4 I, NIO INTEGER*4 EF1, EF2 INTEGER*4 BLOCK_SIZE, NUMBER_OF_BLOCKS, DEVICE_BLOCKSIZE CHARACTER*255 DEVICE_NAME BYTE STRING(66000) /66000*1hA/ C C ====================================================================== C C C C-1 SINGLE BUFFER PROGRAM SOURCE CODE (EMULEX CONTROLLER) 100 CONTINUE C STATUS = LIB$GET_INPUT (DEVICE_NAME,'DEVICE name:') IF (.NOT. STATUS) CALL EXIT (STATUS) C C Get the starting block number C TYPE '(A,$)', ' Enter starting block number: ' ACCEPT *, BLOCK_NUMBER C C Get the number of byte tranfers for each QIO C TYPE '(A,$)',' Enter bytes in each transfer:' ACCEPT *, BLOCK_SIZE C C Get the number of tranfers to be performed C TYPE '(A,$)',' Number of transfers:' ACCEPT *, NIO C C Get the device block size in order to increment the block number C TYPE '(A,$)',' Number of bytes in disk block:' ACCEPT *, DEVICE_BLOCKSIZE C C Calculate the number of blocks to be allocated for the file C NUMBER_OF_BLOCKS = & (BLOCK_SIZE + DEVICE_BLOCKSIZE - 1)/DEVICE_BLOCKSIZE C C Get a channel for the device C STATUS = SYS$ASSIGN(DEVICE_NAME, QIO_CHANNEL,,) IF (.NOT. STATUS) CALL EXIT(STATUS) C C Setup the timer C CALL LIB$INIT_TIMER C C Do the QIOs C DO I = 1,NIO STATUS = SYS$QIOW(,%VAL(QIO_CHANNEL),%VAL(IO$_WRITELBLK), & IOSB,,,STRING,%VAL(BLOCK_SIZE), & %VAL(BLOCK_NUMBER),,,) IF (STATUS) THEN IF ( IOSB(1)) THEN C C Manually update BLOCK_NUMBER based on C Block_size and block_size of the device C BLOCK_NUMBER = BLOCK_NUMBER + NUMBER_OF_BLOCKS ELSE C-2 SINGLE BUFFER PROGRAM SOURCE CODE (EMULEX CONTROLLER) CALL LIB$SIGNAL(%VAL(ZEXT(IOSB(1)))) END IF ELSE CALL LIB$SIGNAL(%VAL(STATUS)) END IF END DO C C Get the time passed C CALL LIB$SHOW_TIMER C C Initialize variables C IF (STATUS) STATUS = SYS$DASSGN (%val(QIO_CHANNEL)) CALL LIB$SIGNAL (%VAL(STATUS)) C C Display the first availble block C TYPE *, ' First available block number is : ', BLOCK_NUMBER TYPE *, ' ' TYPE *, ' ***************' TYPE *, ' ' C C Check if more blocks are to be written C GOTO 100 C C Exit END C-3 APPENDIX D DOUBLE BUFFER PROGRAM SOURCE CODE (EMULEX CONTROLLER) PROGRAM EMULEX_TIME_QIO C C Benchmark and exercise populating an optical disk with C the $QIO service. C C There is always a call to QIO service to be executed by the C driver. C C DLP 14-oct-1986 FERMI Natl accellerator lab C PCF 23-Oct-1986 C IMPLICIT NONE INCLUDE '($IODEF)' INCLUDE '($SYSSRVNAM)' C INTEGER*4 BLOCK_NUMBER INTEGER*4 QIO_CHANNEL INTEGER*2 IOSB1(4), IOSB2(4) INTEGER*4 STATUS C C Global Routines C =============== C INTEGER*4 LIB$GET_EF, LIB$FREE_EF INTEGER*4 LIB$GET_INPUT C C Local Storage C ============= C INTEGER*4 I, NIO, EF1, EF2 INTEGER*4 BLOCK_SIZE, NUMBER_OF_BLOCKS INTEGER*4 DEVICE_BLOCKSIZE CHARACTER*255 DEVICE_NAME BYTE STRING(66000) /66000*1hA/ C C ========================================================== C C D-1 DOUBLE BUFFER PROGRAM SOURCE CODE (EMULEX CONTROLLER) 100 CONTINUE C STATUS = LIB$GET_INPUT (DEVICE_NAME,'DEVICE name:') IF (.NOT. STATUS) CALL EXIT (STATUS) C C Get the starting block number C TYPE '(A,$)', ' Enter starting block number: ' ACCEPT *, BLOCK_NUMBER C C Get the number of byte tranfers for each QIO C TYPE '(A,$)',' Enter bytes in each transfer:' ACCEPT *, BLOCK_SIZE C C Get the number of tranfers to be performed C TYPE '(A,$)',' Number of transfers:' ACCEPT *, NIO C C Get the device block size in order to increment the block number C TYPE '(A,$)',' Number of bytes in disk block:' ACCEPT *, DEVICE_BLOCKSIZE C C Calculate the number of blocks to be allocated for the file C NUMBER_OF_BLOCKS = & (BLOCK_SIZE + DEVICE_BLOCKSIZE - 1)/DEVICE_BLOCKSIZE C C Get a channel for the device C STATUS = SYS$ASSIGN(DEVICE_NAME, QIO_CHANNEL,,) IF (.NOT. STATUS) CALL EXIT(STATUS) C C Setup the event flags to be used by the SYS$QIO routines C STATUS = LIB$GET_EF(EF1) IF (.NOT.STATUS) CALL EXIT(STATUS) STATUS = LIB$GET_EF(EF2) IF (.NOT.STATUS) CALL EXIT(STATUS) C C Setup the timer C CALL LIB$INIT_TIMER C C Initialize the non wait QIOs C STATUS = SYS$QIO(%VAL(EF1),%VAL(QIO_CHANNEL),%VAL(IO$_WRITELBLK), & IOSB1,,,STRING,%VAL(BLOCK_SIZE), & %VAL(BLOCK_NUMBER),,,) IF (STATUS) THEN C D-2 DOUBLE BUFFER PROGRAM SOURCE CODE (EMULEX CONTROLLER) C Manually update BLOCK_NUMBER based on C Block_size and block_size of the device C BLOCK_NUMBER = BLOCK_NUMBER + NUMBER_OF_BLOCKS ELSE CALL LIB$SIGNAL(%VAL(STATUS)) END IF C C Do the QIOs C DO I = 2, NIO C C Calculate which Event_Flag to use, based uppon the loop number C If loop index is even use EF2 and wait on EF1, C else EF1 and wait on EF2. C IF (MOD(I,2) .EQ. 0) THEN STATUS = SYS$QIO(%VAL(EF2),%VAL(QIO_CHANNEL), & %VAL(IO$_WRITELBLK), & IOSB2,,,STRING,%VAL(BLOCK_SIZE), & %VAL(BLOCK_NUMBER),,,) IF (STATUS) THEN C C Manually update BLOCK_NUMBER based on C Block_size and block_size of the device C BLOCK_NUMBER = BLOCK_NUMBER + NUMBER_OF_BLOCKS ELSE CALL LIB$SIGNAL(%VAL(STATUS)) END IF C C Wait for previous QIO to finish C STATUS = SYS$SYNCH(%VAL(EF1), IOSB1) IF (STATUS) THEN IF (.NOT. IOSB1(1)) CALL LIB$SIGNAL(%VAL(ZEXT(IOSB1(1)))) ELSE CALL LIB$SIGNAL(%VAL(STATUS)) END IF ELSE STATUS = SYS$QIO(%VAL(EF1),%VAL(QIO_CHANNEL), & %VAL(IO$_WRITELBLK), & IOSB1,,,STRING,%VAL(BLOCK_SIZE), & %VAL(BLOCK_NUMBER),,,) IF (STATUS) THEN C C Manually update BLOCK_NUMBER based on block size of the device C BLOCK_NUMBER = BLOCK_NUMBER + NUMBER_OF_BLOCKS ELSE CALL LIB$SIGNAL(%VAL(STATUS)) END IF C D-3 DOUBLE BUFFER PROGRAM SOURCE CODE (EMULEX CONTROLLER) C Wait for previous C STATUS = SYS$SYNCH(%VAL(EF2), IOSB2) IF (STATUS) THEN IF (.NOT. IOSB2(1)) CALL LIB$SIGNAL(%VAL(ZEXT(IOSB2(1)))) ELSE CALL LIB$SIGNAL(%VAL(STATUS)) END IF END IF END DO C C Wait for the last QIO to complete C IF (MOD(NIO,2) .EQ. 0) THEN STATUS = SYS$SYNCH(%VAL(EF1), IOSB1) IF (STATUS) THEN IF (.NOT. IOSB1(1)) CALL LIB$SIGNAL(%VAL(ZEXT(IOSB1(1)))) ELSE CALL LIB$SIGNAL(%VAL(STATUS)) END IF ELSE STATUS = SYS$SYNCH(%VAL(EF2), IOSB2) IF (STATUS) THEN IF (.NOT. IOSB2(1)) CALL LIB$SIGNAL(%VAL(ZEXT(IOSB2(1)))) ELSE CALL LIB$SIGNAL(%VAL(STATUS)) END IF END IF C C Check the timer C CALL LIB$SHOW_TIMER C C Initialize variables C IF (STATUS) STATUS = SYS$DASSGN (%val(QIO_CHANNEL)) CALL LIB$SIGNAL (%VAL(STATUS)) STATUS = LIB$FREE_EF(EF1) IF (.NOT.STATUS) CALL EXIT(STATUS) STATUS = LIB$FREE_EF(EF2) IF (.NOT.STATUS) CALL EXIT(STATUS) C C Display the first availble block C TYPE *, ' First available block number is : ', BLOCK_NUMBER TYPE *, ' ' TYPE *, ' ***************' TYPE *, ' ' C C Check if more blocks are to be written GOTO 100 END D-4