/* * COPYRIGHT (C) 1997, 2000 BY * COMPAQ COMPUTER CORPORATION, HOUSTON * TEXAS. ALL RIGHTS RESERVED. * * THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND COPIED * ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE AND WITH THE INCLUSION * OF THE ABOVE COPYRIGHT NOTICE. THIS SOFTWARE OR ANY OTHER COPIES * THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY OTHER * PERSON. NO TITLE TO AND OWNERSHIP OF THE SOFTWARE IS HEREBY TRANSFERRED. * * THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE AND * SHOULD NOT BE CONSTRUED AS A COMMITMENT BY COMPAQ COMPUTER CORPORATION. * * COMPAQ ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY OF ITS * SOFTWARE ON EQUIPMENT THAT IS NOT SUPPLIED BY COMPAQ. * * NO RESPONSIBILITY IS ASSUMED FOR THE USE OR RELIABILITY OF SOFTWARE * ON EQUIPMENT THAT IS NOT SUPPLIED BY COMPAQ COMPUTER CORPORATION. * * SUPPORT FOR THIS SOFTWARE IS NOT COVERED UNDER ANY COMPAQ SOFTWARE * PRODUCT SUPPORT CONTRACT, BUT MAY BE PROVIDED UNDER THE TERMS OF THE * CONSULTING AGREEMENT UNDER WHICH THIS SOFTWARE WAS DEVELOPED. */ #ifdef __VAXC #module DISK_DRIVER "V1.0-002" #endif #ifdef __DECC #pragma module DISK_DRIVER "V1.0-002" #endif /* * Modification history \* V1.0-002, Philippe Vouters, 19, November 1997 * - Compute the startlbn correctly according to ODS file struture * so that IO$_WRITELBLK writes to correct block. * - Suppress the NOSPAN record attribute which prevented a DUMP/RECORD * or a COPY when BYTE > 512 bytes. */ /* This program requires the PSWAPM priviledge and PHY_IO if writing LOGICAL blocks. Compile the program using the following commands: $ CC[/DEFINE=(logical[,byte=n])] Direct_disk_qio +- ALPHA$LIBRARY:SYS$LIB_C/LIBRARY $ LINK Direct_disk_qio $ iodisk :== $disk:[directory]Direct_disk_qio.exe $! Activation: $! iodisk $ exit Increase the compile time constant "nboucle" to avoid an arithmetic exception on the computation of performances. For example; set it up to 100. This will create a bigger file. Define the compilation command "logical" with "byte=n" as 512 multiple if the output file is to be contiguous. This will setup the RMS characteristics of the sequential output file. Using "byte=512" and "nboucle = 1000" creates a 40,000 blocks file. Use "iodisk :== $disk:[directory]" according to the environment. */ #include #include #include #include #include #include time #include #include /* Descriptor Structure and Constant Definitions */ #include /* File Information Block Definitions */ #include /* File identification Definitions */ #include #include /* I/O function code Definitions */ #include /* Library (LIB$) routine definitions */ #include /* All RMS Structure & Return Status Definitions */ #include /* System Service Return Status Value Definitions */ #include /* System routine definitions*/ #include #include #include #include #include #include #include #ifdef LOGICAL /* * Write Logical Block requires PHY_IO priviledge. */ #define IOWRT IO$_WRITELBLK #else #define IOWRT IO$_WRITEVBLK #endif /* ** ** MACRO DEFINITIONS ** */ /* ** The following macro defines a status check which ** occurs numerous times throughout the program. */ #define check_s(status) \ if ( ! (status & 1) ) lib$signal (status) #define BLOCKSIZE 512 #define nboucle 2 #define nb 40 #ifndef BYTE #define byte BLOCKSIZE #else #define byte (BYTE/BLOCKSIZE)*BLOCKSIZE # if (byte > 32767) # error "BYTE cannot have a value greater than 32,767 bytes" # endif #endif #define sizbuf nb*byte /* * The allocation size is setup arbitrarily to the maximum size + * 1,000 blocks. This is to show the effect of the truncate option * used at the end of the file writing. For an actual data collection * and file recording, without knowing either the number of Realtime * I/O collection or the size of each I/O recording, do a $getdvi for * this device, and setup the allocation_size to the number of free * blocks. Note that for getting the maximum disk space, while doing * logical blocks I/Os, initialize the disk with the /INDEX=BEGINNING * qualifier option. */ #define allocation_size (nboucle * sizbuf)/BLOCKSIZE + 1000 char *buffer; static int para1,i; /* ** Declare counters etc. */ unsigned int device_channel; /* Channel Number */ #ifdef __DECC #pragma member_alignment save #pragma nomember_alignment word #endif struct { unsigned short status; unsigned int bytes_count; unsigned short unused; } io_status; /* I/O status block */ typedef struct { unsigned short buflen; unsigned short code; void *buffer; int *retlen; } item_t; #ifdef __DECC #pragma member_alignment restore #endif static FAT fatbuf; static FH2 file_hdr; static FM2 *fm1; static FM2 *map_area; static FM2_1 *retrieval_pointer; static struct atrdef *atr; struct tm datedeb; struct tm *datefin; unsigned long date_valdeb; unsigned long date_valfin; #ifdef __VAXC #define f_i_b_outerl f_i_b.fib$r_fid_overlay.fibSr_fid_fields #define f_i_b_outer2 f_i_b_outerl.fib$r_fid_rvn_overlay #define f_i_b$w_fid_num f_i_b_outerl.fib$w_fid_num #define f_i_bSw_fid_seq f_i_b_outerl.fib$w_fid_seq #define f_i_bSw_fid_rvn f_i_b_outer2.fib$w_fid_rvn #define f_i_b$l_acctl f_i_b.fib$r_acctl_overlay.fib$l_acctl #endif /* Declare RMS control blocks */ static struct FAB f_a_b; /* File Access Block */ static struct fibdef f_i_b; /* File Information Block */ static struct RAB r_a_b; /* Record Access BLock */ static struct NAM n_b; /* Name Block */ /* Declare Bits and Pieces for File Access */ unsigned long int status; /* Status Return */ unsigned long int record_match = SS$_NORMAL; /* Record Number Match */ static unsigned long recnum = 0; /* size of written record */ static int startlbn; struct dsc$descriptor_s device_descr = {0,DSC$K_DTYPE_T,DSC$K_CLASS_S,0}; /* Device descriptor */ struct { /* File Information Block Descriptor */ unsigned short intlength, pad; struct fibdef * addr; } fib_descr = { FIB$K_LENGTH,0,&f_i_b}; int AST_PROC() { int status; check_s (io_status.status); para1++; for(i=0 ; i fm2$v_format == FM2$C_PLACEMENT) fm1 = (FM2 *)((char *)fm1 + 2); else { switch (fm1->fm2$v_format){ case FM2$C_FORMAT1: startlbn = fm1->fm2$w_lowlbn; startlbn += fm1->fm2$v_highlbn << 16; fm1 = (FM2 *)((char *)fm1 + 4); break; case FM2$C_FORMAT2: startlbn = ((FM2_1 *)fm1)->fm2$l_lbn2; fm1 = (FM2 *)((char *)fm1 + 6); break; case FM2$C_FORMAT3: startlbn = ((FM2_2 *)fm1)->fm2$l_lbn3; fm1 = (FM2 *)((char *)fm1 + 8); } }/* end else */ } /* end while */ #else /* * For Virtual I/Os the startlbn is equal to the first file's VBN (1). */ startlbn = 1; #endif /* * Get time of start of collection. */ time(&date_valdeb); date = localtime(&date_valdeb); memcpy(&datedeb,date,sizeof(struct tm)); /* * Initialize number of I/Os counter. */ para1 = 0; /* * Setup the initial buffer content. */ for(i=0 ; i > 16; fatbuf.fat$w_efblkl = recnum & 0xFFFF; f_i_b.fib$v_writethru = 1; f_i_b.fib$v_extend = 0; f_i_b.fib$v_trunc = 1; f_i_b.fib$l_exsz = 0; f_i_b.fib$l_exvbn = recnum; atr[1].atr$w_size = 0; atr[1].atr$w_type = 0; atr[1].atr$l_addr = 0; status = sys$qiow (0, /* No EFN */ device_channel, IO$_DEACCESS, /* Function is deaccess file */ 0, /* No IOSB, AST, P2-P6 */ 0, 0, &fib_descr, /* P1 = address of FIB descriptor*/ 0,0,0, atr, 0); check_s(status); sys$dassgn (device_channel); /* Deassign the device channel */ /* * Get end of collection time. */ datefin = localtime(&date_valfin); printf("end time = %d h %d m %d s\n",datefin->tm_hour,datefin->tm_min, datefin->tm_sec); printf("start time = %d h %d m %d s\n",datedeb.tm_hour,datedeb.tm_min, datedeb.tm_sec); /* * Compute the disk performance (number of bytes/seconds). */ io = (double) (sizbuf * nboucle)/ ((double)(((datefin->tm_hour*60)+datefin->tm_min)*60+datefin->tm_sec)- (double)(((datedeb.tm_hour*60)+datedeb.tm_min)*60+datedeb.tm_sec)); printf("computed i/o rate = %.2lf bytes/sec with sizbuf = %d bytes\n", io,sizbuf); /* ** We begin by using $ASSIGN to assign a channel to the file ** device to read the file using this time virtual blocks. */ status = sys$assign (&device_descr, /* Device descriptor */ &device_channel, /* Channel number */ 0, /* Default access mode */ 0); /* No mailbox */ check_s(status); /* Exit if error */ /* ** To open the file, we use $QIO, specifying the io$access ** function, with read & write access specified. We use the ** file ID information from the first part of the program to ** get access to the file we want. */ /* * Reset the fib's access intention to READ. */ f_i_b.fib$v_write = 0; status = sys$qiow (0, /* No event flag number */ device_channel, /* Channel */ IO$_ACCESS|IO$M_ACCESS, /* Access the file */ &io_status, /* IO status block */ 0, /* No AST completion routine */ 0, /* So no AST routine parameters */ &fib_descr, /* P1 = address of FIB descriptor*/ &dummydsc, 0,0,0,0); /* No P3-P6 */ check_s(status); /* Close and exit if error */ check_s(io_status.status); /* Close and exit if error */ /* * Reread the file using read Virtual Block. */ for(j = 0; j < nboucle; j++) { memset(buffer,0,sizbuf); status = sys$qiow( /* Read record */ 0, /* no EFN */ device_channel, /* Channel */ IO$_READVBLK, /* func = read virtual block */ &io_status, /* IOSB */ 0, /* No AST completion routine */ 0, /* or parameters */ &buffer[0], /* P1 = address of buffer */ sizbuf, /* P2 = length of buffer */ (j*sizbuf)/BLOCKSIZE+1, /* P3 = Record number */ 0, /* No P4-P6 */ 0,0); check_s(status); /* make sure write OK */ /* * Check if records have been correctly written to the disk. */ for(i=0 ; i