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