/* @(#)iodev.c 17.1.1.1 (ES0-DMD) 01/25/02 17:35:23 */ /*=========================================================================== Copyright (C) 1995 European Southern Observatory (ESO) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Massachusetss Ave, Cambridge, MA 02139, USA. Corresponding concerning ESO-MIDAS should be addressed as follows: Internet e-mail: midas@eso.org Postal address: European Southern Observatory Data Management Division Karl-Schwarzschild-Strasse 2 D 85748 Garching bei Muenchen GERMANY ===========================================================================*/ /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .COPYRIGHT (c) 1988 European Southern Observatory .IDENT iodev.c .LANGUAGE C .AUTHOR P.Grosbol ESO/IPG .KEYWORDS VMS QIO, tape I/O .ENVIRON VAX/VMS .COMMENT Ref. to VAX/VMS I/O User's Guide Vol.1, Chap.7 for status codes etc. .VERSION 1.0 1988-Nov-28 : Creation, PJG .VERSION 1.1 1988-Dec-08 : Set EOF-status to 0, CGS .VERSION 1.2 1989-Mar-11 : Do not dismount tape, PJG .VERSION 1.3 1989-Oct-11 : Hide everything, FO Also errors correctly retrieved via osmsg() .VERSION 1.4 1989-Dec-20 : 4 parameters for ioinfo .VERSION 1.5 21-May-1990 : 2 parameters for ioclose. Added IO$M_NOASSIST option in MOUNT, such that a clear error message is displayed if the tape unit is not ready ... .VERSION 1.6 17-Aug-1990 : Check (open AND close) that the colon is present... .VERSION 1.7 14-Nov-1990 : Modified oserror values (cf errno.h) .VERSION 1.8 23-Apr-1991 : Check ALL statuses... .VERSION 1.9 20-Aug-1992 : variant_struct not known for GNU. CG. --------------------------------------------------------------------*/ static char class_name[] = "mt"; /* MAgnetic Tape Class */ #include #include #include /* VMS descriptor macro */ #include /* VMS QIO function codes */ #ifndef variant_struct #define variant_struct struct #endif #include /* VMS MOUNT definitions */ #include /* VMS status code definitions */ #include /* Standard Unix error codes */ MID_EXTERN int oserror; /* MIDAS os-error status */ MID_EXTERN int vmserror; /* translated by osmsg() */ #define DMT$M_NOUNLOAD 1 /* take it from */ #define MT$M_DENSITY 7936 /* Density mask (0x1f00) */ #define MT$S_DENSITY 5 /* Length in bits of den. field */ #define MT$V_DENSITY 8 /* Offset in bits of den. field */ #define MT$K_NRZI_800 3 /* Value for 800 bpi */ #define MT$K_PE_1600 4 /* Value for 1600 bpi */ #define MT$K_GCR_6250 5 /* Value for 6250 bpi */ #define MAXDN 64 /* max. length of device name */ static char dname[MAXDN]; /* device name */ static $DESCRIPTOR(src,dname); typedef struct { unsigned short int iostatus; unsigned short int length; unsigned long int info; } IOSB; /*======================================================================*/ static void devname(name) /*+++++++++++++ .PURPOSE Set decriptor with device name .RETURNS Nothing .REMARK Add colon if missing --------------*/ char *name; /* IN: Device name */ { int len; len = strlen(name); /* Add the : if necessary */ if ((name[len-1] != ':') && (len < sizeof(dname))) { oscopy (dname, name, len); dname[len++] = ':'; src.dsc$a_pointer = dname; } else src.dsc$a_pointer = name; src.dsc$w_length = len; return; } static int ioinfo(fd, s, fileno, blkno) /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Retrieve Info concerning an opened device .RETURNS 0 (success) / -1 (error) .REMARKS File position and Block position could be set in SCSI tapes ? Here, these numbers are just set to -1 (unknown) --------------------------------------------------------------------*/ int fd; /* IN: File Descriptor */ struct osustat *s; /* OUT: The filled components */ int *fileno; /* OUT: File position (-1) */ long *blkno; /* OUT: Block position */ { short qio_chan; IOSB iosb; if (fileno) *fileno = -1; if (blkno) *blkno = -1; qio_chan = fd; s->usize = 0; s->blocksize = 0; vmserror = sys$qiow(0,qio_chan,IO$_SENSEMODE,&iosb,0,0,0,0,0,0,0,0); if (vmserror!= SS$_NORMAL) { oserror = EIO; return -1; } s->density = (iosb.info & MT$M_DENSITY)>> MT$V_DENSITY; if (s->density == MT$K_GCR_6250) s->density = 6250; else if (s->density == MT$K_NRZI_800) s->density = 800; else s->density = 1600; s->isda = 0; /* Note: should use getdvi... */ s->istm = 1; /* Note: should use getdvi... */ return 0; } static int ioopen(device,mode,den) /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Assign I/O channel to device .RETURN I/O channel of OK else -1 if assign error --------------------------------------------------------------------*/ char *device; /* IN: pointer to device name */ int mode; /* IN: open mode - NOT used! */ int den; /* IN: tape density */ { int sys$assign(); int sys$mount(); int tden,flag,siz; short qio_chan; struct MNTL { short length; short func; char *buf; int term; } mntl[6]; devname(device); siz = 32000; tden = den; /* setup MOUNT parameters */ flag = MNT$M_FOREIGN | MNT$M_NOLABEL | MNT$M_NOASSIST; mntl[0].length = src.dsc$w_length; mntl[0].func = MNT$_DEVNAM; mntl[0].buf = src.dsc$a_pointer; mntl[0].term = 0; mntl[1].length = 4; mntl[1].func = MNT$_FLAGS; mntl[1].buf = (char *) &flag; mntl[1].term = 0; mntl[2].length = 4; mntl[2].func = MNT$_DENSITY; mntl[2].buf = (char *) &tden; mntl[2].term = 0; mntl[3].length = 4; mntl[3].func = MNT$_BLOCKSIZE; mntl[3].buf = (char *) &siz; mntl[3].term = 0; mntl[4].length = 4; mntl[4].func = MNT$_RECORDSIZ; mntl[4].buf = (char *) &siz; mntl[4].term = 0; mntl[5].length = 0; mntl[5].func = 0; mntl[5].buf = (char *) 0; mntl[5].term = 0; vmserror = sys$mount(mntl); vmserror &= 0xFFFF; /* blank out status level */ if (vmserror != SS$_NORMAL && vmserror != SS$_DEVMOUNT) { oserror = ENXIO; return -1; } /* if (vmserror == SS$_DEVMOUNT) printf("Warning: Device already mounted\n"); */ vmserror = sys$assign(&src,&qio_chan,0,0); if (vmserror != SS$_NORMAL) { oserror = ENXIO; return -1; } return qio_chan; } static int ioclose(fd, option) /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Deassign or close I/O channel to device .RETURN 0: OK ,else -1: error --------------------------------------------------------------------*/ int fd; /* IN: file desc. - I/O-channel */ int option; /* IN: Option OPU_DISMOUNT */ { int sys$dassgn(); int sys$dismou(); short qio_chan; IOSB iosb; char *device; qio_chan = fd; vmserror = sys$qiow(0,qio_chan,IO$_REWIND|IO$M_NOWAIT,&iosb,0,0,0,0,0,0,0,0); vmserror = sys$dassgn(qio_chan); if (vmserror != SS$_NORMAL) { oserror = ENXIO; return -1; } /* Need to get back device name */ device = osuname(-1); devname(device); vmserror = sys$dismou(&src, (option & OPU_DISMOUNT ? 0 :DMT$M_NOUNLOAD)); return 0; } static int ioread(fd,buf,no) /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Read data from a VMS I/O-channel .RETURN no. of bytes read if OK else 0: EOF, -2: QIO error --------------------------------------------------------------------*/ int fd; /* IN: I/O-channel no. */ char *buf; /* IN: pointer to data buffer */ int no; /* IN: no. of bytes to read */ { int sys$qiow(); short qio_chan; IOSB iosb; qio_chan = fd; vmserror = sys$qiow(0,qio_chan,IO$_READLBLK,&iosb,0,0,buf,no,0,0,0,0); if (vmserror != SS$_NORMAL) { oserror = EIO; return -1; } vmserror = iosb.iostatus; if (vmserror & 1) return (iosb.length); if (vmserror == SS$_ENDOFFILE) return (0); oserror = EIO; return(-1); } static int iowrite(fd,buf,no) /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Write data to a VMS I/O-channel .RETURN no. of bytes written if OK else -1: EOT, -2: QIO error, -3: Timeout --------------------------------------------------------------------*/ int fd; /* IN: I/O-channel no. */ char *buf; /* IN: pointer to data buffer */ int no; /* IN: no. of bytes to read */ { int sys$qiow(); short qio_chan; IOSB iosb; qio_chan = fd; vmserror = sys$qiow(0,qio_chan,IO$_WRITELBLK,&iosb,0,0,buf,no,0,0,0,0); if (vmserror != SS$_NORMAL) { oserror = EIO; return -1; } vmserror = iosb.iostatus; if (vmserror & 1) return (iosb.length); if (vmserror == SS$_ENDOFFILE) return (0); oserror = EIO; return(-1); } static int ioweof(fd) /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Write EOF's on tape assigned to a VMS I/O-channel .RETURN 0: OK ,else -1: QIO error, -2: EOT --------------------------------------------------------------------*/ int fd; /* IN: I/O-channel no. */ { int sys$qiow(); int i; short qio_chan; IOSB iosb; qio_chan = fd; vmserror = sys$qiow(0,qio_chan,IO$_WRITEOF,&iosb,0,0,0,0,0,0,0,0); if (vmserror != SS$_NORMAL) { oserror = EIO; return -1; } vmserror = iosb.iostatus; if (vmserror & 1) return (iosb.length); if (vmserror == SS$_ENDOFFILE) return (0); oserror = EIO; return(-1); } static int iorew(fd) /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Rewind tape assigned to a VMS I/O-channel. .RETURN 0: OK , -1: QIO error --------------------------------------------------------------------*/ int fd; /* IN: I/O-channel no. */ { int sys$qiow(); short qio_chan; IOSB iosb; qio_chan = fd; vmserror = sys$qiow(0,qio_chan,IO$_REWIND,&iosb,0,0,0,0,0,0,0,0); if (vmserror != SS$_NORMAL) { oserror = EIO; return -1; } vmserror = iosb.iostatus; if (vmserror & 1) return (iosb.length); if (vmserror == SS$_ENDOFFILE) return (0); oserror = EIO; return(-1); } static int iosf(fd,no) /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Skip files on tape assigned to a VMS I/O-channel .RETURN 0: OK , -1: QIO error --------------------------------------------------------------------*/ int fd; /* IN: I/O-channel no. */ int no; /* IN: no. of files to skip */ { int sys$qiow(); short qio_chan; IOSB iosb; qio_chan = fd; vmserror = sys$qiow(0,qio_chan,IO$_SKIPFILE,&iosb,0,0,no,0,0,0,0,0); if (vmserror != SS$_NORMAL) { oserror = EIO; return -1; } vmserror = iosb.iostatus; if (vmserror & 1) return (iosb.length); if (vmserror == SS$_ENDOFFILE) return (0); oserror = EIO; return(-1); } static int iosr(fd,no) /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Skip files on tape assigned to a VMS I/O-channel .RETURN 0: OK , -1: QIO error --------------------------------------------------------------------*/ int fd; /* IN: I/O-channel no. */ int no; /* IN: no. of files to skip */ { int sys$qiow(); short qio_chan; IOSB iosb; qio_chan = fd; vmserror = sys$qiow(0,qio_chan,IO$_SKIPRECORD,&iosb,0,0,no,0,0,0,0,0); if (vmserror != SS$_NORMAL) { oserror = EIO; return -1; } vmserror = iosb.iostatus; if (vmserror & 1) return (iosb.length); if (vmserror == SS$_ENDOFFILE) return (0); oserror = EIO; return(-1); } static int iofsf(fd,no) /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Forward Skip Files on tape assigned to a VMS I/O-channel .RETURN 0: OK , -1: QIO error --------------------------------------------------------------------*/ int fd; /* IN: I/O-channel no. */ int no; /* IN: no. of files to skip */ { return iosf(fd,no); } static int iobsf(fd,no) /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Backward Skip Files on tape assigned to a VMS I/O-channel .RETURN 0: OK , -1: QIO error --------------------------------------------------------------------*/ int fd; /* IN: I/O-channel no. */ int no; /* IN: no. of files to skip */ { return iosf(fd,-no); } static int iofsr(fd,no) /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Forward Skip Files on tape assigned to a VMS I/O-channel .RETURN 0: OK , -1: QIO error --------------------------------------------------------------------*/ int fd; /* IN: I/O-channel no. */ int no; /* IN: no. of records to skip */ { return iosr(fd,no); } static int iobsr(fd,no) /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Bachward Skip Record on tape assigned to a VMS I/O-channel .RETURN 0: OK , -1: QIO error --------------------------------------------------------------------*/ int fd; /* IN: I/O-channel no. */ int no; /* IN: no. of records to skip */ { return iosr(fd,-no); } /*===================================================================== * Definition of the structure returned to osu *=====================================================================*/ struct iolist *iodev0(); static OPITEM list_of_functions[] = { { U_INFO, ioinfo}, { U_OPEN, ioopen}, { U_CLOSE, ioclose}, { U_READ, ioread}, { U_WRITE, iowrite}, { U_REWIND, iorew}, { U_WEOF, ioweof}, { U_FMF, iofsf}, /* File Move Forward */ { U_FMB, iobsf}, /* File Move Backward */ { U_BMF, iofsr}, /* Block Move Forward */ { U_BMB, iobsr} /* Block Move Backward */ }; static struct iolist this_dev = { iodev0, /* Next iodev in List */ class_name, /* How it's written in DEVCAPFILE */ sizeof(list_of_functions)/sizeof(list_of_functions[0]), list_of_functions }; struct iolist *iodev() /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Get All definitions concerning this class of Devices .RETURNS The iolist .REMARKS Simply returns the local iolist address... ------------------------------------------------------------*/ { return(&this_dev); }