/* IO_PERFORM.C - is a program to demonstrate the use of Fast I/O system services. The program creates a buffer object and fandle and then reads the text file TEST.TXT in the local directory. The file is read one block at a time and the first text string in each block is displayed. You can hit enter to read successive blocks of the file. Since the entire file is read, it is best if TEST.TXT is a small text file. The first pass of the file issues $IO_PERFORMs using AST completion. Once the EOF of TEST.TXT is reached, the file is read on a second pass using $IO_PERFORMWs. Since we only have one fandle, a completion AST is also used on the second pass although it is not neceesary. Once the EOF is reached on the second pass, cleanup of the fandle and buffer object occurs. Since $IO_PERFORM requires that the data buffer be aligned to a 512 byte boundary, the program allocates a 3 512-byte block of memory for IOSAs and data buffer. A 3 512-byte block is used to guarantee space for an aligned 2 512-byte block which is made into a buffer object. The IOSA/data buffer object is aligned to the first 512-byte boundary within the 3 512-byte block. The first 512 bytes of the buffer object are used for IOSAs and the second 512 bytes are used for the 512 byte data buffer. This program is intended for use on both VAX and Alpha systems. Note that the RTL capability routines on VAX in STARLET, do not require that buffer objects be used. So system mamagenent for buffer objects can be saved on VAX. */ #ifdef __ALPHA #include /* Omit this if for VAX */ #endif #include #include #include #include #include #include static int retadr[2]; /* Beginning and end address of buffer object */ static volatile int didit = 0; /* Flag indicating if AST has fired or not */ static volatile int astps, pfsts; /* PS when AST fired; and Status from Prntf done in AST */ int ast(int **p) /* Completion AST that fires when I/O is done */ { iosa *i = (iosa *) p; pfsts = printf("\nAST fired! Parameter 0x%08X\n\n", i->iosa$ih_context); didit = 1; #ifdef __ALPHA astps = __PAL_RD_PS(); /* Omit this if for VAX */ #endif return 1; } int fastio(int argc, char ** argv[]) MAIN_PROGRAM { static iosa *iostat; static fandle fan; static int chan; static char *Pbuf; int status, inadr[2], handle[2]; struct FAB fab; static char *filename = "TEST.TXT"; char * rec1; char nothing[200]; int i,diskblocksize; int addr; /* Where the data will be read into (really a pointer) */ /* Perform Setup: Open the file Allocate memory for buffer object and align to next 512-byte boundary Create the buffer object Create a Fandle */ printf("\n\n\n>>>>>>>> DO SETUP <<<<<<<<\n\n\n"); fab = cc$rms_fab; fab.fab$l_fna = filename; fab.fab$b_fns = strlen(fab.fab$l_fna); fab.fab$l_dna = "TEST.TXT;"; fab.fab$b_dns = strlen(fab.fab$l_dna); fab.fab$b_fac = FAB$M_GET; fab.fab$b_shr = FAB$M_NIL; fab.fab$l_fop = FAB$M_UFO; status = SYS$OPEN(&fab); if (!(status&1)) exit (status); chan = fab.fab$l_stv; printf("\nOpen %s, status %X, STV value %X\n\n", filename, status, chan); diskblocksize = 512; Pbuf = malloc(3 * diskblocksize); printf("Buffer Memory allocated starting at VA %X, ending at %X\n\n", (int) Pbuf, (int) Pbuf+3*diskblocksize-1); Pbuf = (char *) ((int)Pbuf + diskblocksize); /* Align buffer pool to 512 byte boundary for $IO_PERFORM */ Pbuf = (char *) ((int)Pbuf & (0xFFFFFFFF ^ (diskblocksize-1))); inadr[0] = (int) Pbuf; /* Setup starting address of buffer object */ inadr[1] = inadr[0] + ((2*diskblocksize)-1); /* Setup ending address of buffer object that is 2 disk blocks in length */ status = SYS$CREATE_BUFOBJ(inadr, retadr, 0, 0, handle); printf("Buffer object inadr %X,%X\n", inadr[0], inadr[1]); printf("status %X; retadr = %X,%X and Buffer Object handle = %X,%X\n\n", status, retadr[0], retadr[1], handle[0], handle[1]); if (!(status&1)) exit (status); iostat = (iosa *)inadr[0]; /* The IOSA resides in first 512 byte chunk of buffer object */ iostat->iosa$l_status = 1; /* Used in loop control, below */ iostat->iosa$ih_context = 0xFEEDBEEF; /* Pointer to user thread context, since only have one thread, set it to unique value */ printf("Calling $IO_SETUP(%X,%X,%X)\n",IO$_READVBLK, fan); status = SYS$IO_SETUP(IO$_READVBLK, handle, handle, &ast, 0, &fan); printf("$IO_SETUP status %X fandle %X %08X\n\n", status, fan>>32, fan); if (!(status&1)) exit (status); addr = inadr[0] + diskblocksize; /* The data buffer resides in second 512 byte chunk of buffer object */ rec1 = (char *) addr; /* Loop reading the entire file a block at a time using $IO_PERFORMs */ printf("\n\n>>>>>>>> ISSUE $IO_PERFORMs <<<<<<<<\n\n"); for(i=1; (iostat->iosa$l_status & 1); i++) /* Loop over all blocks of file until EOF returned */ { astps = didit = 0; printf("\n\nAST flag = %d\n", didit); printf("Calling $IO_PERFORM(%X%08X, %X, %X, %X, %X, %d)\n", fan>>32, fan, chan, iostat, addr, diskblocksize, i); status = SYS$IO_PERFORM(fan, chan, iostat, addr, diskblocksize, i); printf("$IO_PERFORM service call status %X\n", status); if (!(status&1)) exit (status); while (didit==0); /* Loop until AST fires */ printf("AST flag = %X, ast PS was %X, printf returned %d\n", didit, astps, pfsts); printf("$IO_PERFORM IOSA completion status %X, data length %X\n", iostat->iosa$l_status, iostat->iosa$ih_count); if (iostat->iosa$l_status & 1) printf("First string in data block #%d: \"%s\"\n", i, &rec1[2]); printf("\n Hit enter for another $IO_PERFORM:"); gets(nothing); } /* Now loop reading the entire file a block at a time using $IO_PERFORMWs */ printf("\n\n\n\n>>>>>>>> ISSUE $IO_PERFORMWs <<<<<<<<\n\n"); iostat->iosa$l_status = 1; /* Used in loop control, below */ iostat->iosa$ih_context = 0xBEEFBEEF; for(i=1; (iostat->iosa$l_status & 1); i++) /* Loop over all blocks of file until EOF returned */ { astps = didit = 0; printf("\n\nAST flag = %d\n", didit); printf("Calling $IO_PERFORMW(%X%08X, %X, %X, %X, %X, %d)\n", fan>>32, fan, chan, iostat, addr, diskblocksize, i); status = SYS$IO_PERFORMW(fan, chan, iostat, addr, diskblocksize, i); printf("$IO_PERFORMW service call status %X\n", status); if (!(status&1)) exit (status); while (didit==0); /* Loop until AST fires */ printf("AST flag = %X, ast PS was %X, printf returned %d\n", didit, astps, pfsts); printf("$IO_PERFORMW IOSA completion status %X, data length %X\n", iostat->iosa$l_status, iostat->iosa$ih_count); if (iostat->iosa$l_status & 1) printf("First string in data block #%d: \"%s\"\n", i, &rec1[2]); printf("\n Hit enter for another $IO_PERFORMW:"); gets(nothing); } /* All done, so do proper cleanup of fandle and buffer object */ printf("\n\n\n\n>>>>>>>> DO CLEANUP <<<<<<<<\n\n\n"); printf("\nCalling $IO_CLEANUP(%X%08X)\n", fan>>32, fan); status = SYS$IO_CLEANUP(fan); printf("$IO_CLEANUP status %X\n", status); if (!(status&1)) exit (status); printf("\nCalling $DELETE_BUFOBJ(%X%08X)\n", handle[0], handle[1]); status = SYS$DELETE_BUFOBJ(handle); printf("$DELETE_BUFOBJ status %X\n", status); if (!(status&1)) exit (status); SYS$DASSGN(chan); if (!(status&1)) exit (status); }