/* @(#)iodev1.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 ===========================================================================*/ /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .TYPE Module .NAME iodev1 .LANGUAGE C .AUTHOR IPG-ESO Garching .CATEGORY Basic disk i/o .COMMENTS Class is made for Disks / OD .VERSION 0.0 12-Oct-1989: Design, F. Ochsenbein, C. Guirao .VERSION 1.0 11-Jan-1990: Implementation. .VERSION 1.1 18-May-1990: 2 parameterse for ioclose .VERSION 1.2 17-Aug-1990: Correct order: 1) Mount 2) Assign .VERSION 1.3 17-Oct-1990: Removed GNU-nonunderstandable code... .VERSION 1.4 20-Aug-1992: variant_struct not known for GNU. CG. .ENVIRONMENT VMS ------------------------------------------------------------*/ static char class_name[] = "disk"; #include #include #include /* Contains definitions of READ / WRITE, etc... */ struct iolist *iodev2(); /* Next io routines in list */ #ifndef variant_struct #define variant_struct struct #endif #include /* VMS MOUNT definitions */ #define DMT$M_NOUNLOAD 1 /* take it from */ #include /* VMS QIO function codes */ #include /* VMS status code definitions */ #include /* VMS descriptor macro */ #include /* VMS for GetDVI */ #include /* VMS classes of devices */ #include #define SECTOR_SIZE 512 /* The VMS standard */ MID_EXTERN int oserror; MID_EXTERN int vmserror; /* translated by osmsg() */ typedef struct dsc$descriptor_s SDV; /* Set address & length of a string */ static short chan; static struct { unsigned short iostatus; unsigned short length; unsigned long info; } iosb = {0, 0, 0}; /* The i/o status block */ typedef struct item { /* Specification for System Services */ unsigned short len; unsigned short item_code; char *addr; long *return_len; } ITEM; #define if_VMSerror if (!(vmserror&1)) /*======================================================================*/ static SDV *devname(name) /*+++++++++++++ .PURPOSE Set sdv with device name .RETURNS Nothing .REMARK Add colon if missing --------------*/ char *name; /* IN: Device name */ { static SDV sdv = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0}; static char aName[20]; int len; len = strlen(name); /* Add the : if necessary */ if ((name[len-1] != ':') && (len < sizeof(aName))) { oscopy (aName, name, len); aName[len++] = ':'; sdv.dsc$a_pointer = aName; } else sdv.dsc$a_pointer = name; sdv.dsc$w_length = len; return (&sdv); } /*======================================================================*/ static int io1 (op, buffer, length, block) /*+++++++++++++ .PURPOSE Interface to SYS$QIOW, with test of main returned status .RETURNS Byte count / -1 .REMARK No tracing in this routine, only called from other osu routines --------------*/ int op; /* IN: The operation to perform */ char *buffer; /* OUT: Buffer address */ int length; /* IN: Buffer length */ int block; /* IN: Sector number */ { register int l; if (oserror) return(-1); iosb.iostatus = 0, iosb.length = 0; vmserror = SYS$QIOW (0,chan,op,&iosb,0,0,buffer,length,block,0,0,0); l = iosb.length; if (!(vmserror & 1)) oserror = EIO, l = -1; return(l); } /*======================================================================*/ static int io2 (op, buffer, length, block) /*+++++++++++++ .PURPOSE Interface to SYS$QIOW, with test of 2 returned codes .RETURNS Length / -1 if error / 0 for EOF or Virgin Sectors .REMARK --------------*/ int op; /* IN: The operation to perform */ char *buffer; /* OUT: Buffer address */ int length; /* IN: Buffer length */ int block; /* IN: Sector number */ { register int l; l = io1(op, buffer, length, block); if (oserror == 0) { switch(iosb.iostatus) { case SS$_NORMAL: break; #if 0 /* Following cases ignored here */ case SS$_DATAOVERUN: if (l == length) l++; break; case SS$_ENDOFTAPE: oserrmsg = "Physical End reached"; oserror = -1; break; #endif case SS$_FORCEDERROR: case SS$_FORMAT: /* This happens with virgin sectors on ODs. */ break; case SS$_ENDOFVOLUME: case SS$_ENDOFFILE: l = 0; break; /* No error */ default: oserror = EIO; vmserror = iosb.iostatus; break; } } return (oserror ? -1 : l); } /*======================================================================*/ static int iorew(fd) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Go to sector #0 .RETURNS 0 (success) / -1 (error) ------------------------------------------------------------*/ int fd; /* IN: File Descriptor */ { return(0); } static int ioinfo(fd, s, fileno, blkno) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Retrieve Info concerning an opened device .RETURNS 0 (success) / -1 (error) ------------------------------------------------------------*/ int fd; /* IN: File Descriptor */ struct osustat *s; /* OUT: The filled components */ int *fileno; /* OUT: Where we are */ long *blkno; /* OUT: Where we are */ { SDV *sdv; /* Need the device name to get info */ static int dev_class; /* The VMS device class */ static struct { struct item item_1; long end;} getdvi = { { sizeof(dev_class),DVI$_DEVCLASS,(char *)&dev_class,(long *)0}, 0}; oserror = 0; if (fileno) *fileno = *blkno = -1; /* Unknown ... */ s->usize = 0; s->blocksize = 0; s->density = 0; sdv = devname(osuname(-1)); /* Check if Tape or Disk via GETDVI */ getdvi.item_1.item_code = DVI$_DEVCLASS; vmserror = SYS$GETDVIW(0,0,sdv, &getdvi, &iosb,0,0,0); if_VMSerror { oserror = EIO; return(-1);} s->isda = (dev_class == DC$_DISK); /* For Disks, get relevant device info */ if (s->isda){ getdvi.item_1.item_code = DVI$_MAXBLOCK; vmserror = SYS$GETDVIW(0,0, sdv,&getdvi,&iosb,0,0,0); if_VMSerror { oserror = EIO; return(-1);} s->blocksize = SECTOR_SIZE; /* Unit used for usize */ s->usize = dev_class; /* Number of sectors in 512-bytes */ } return(0); } static int ioopen(name, mode, den) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Open Raw Disk Tape .RETURNS File descriptor / -1 (error) .REMARKS ------------------------------------------------------------*/ char *name; /* IN: Physical name of tape device */ int mode; /* IN: Open mode */ int den; /* IN: Density. Not used */ { SDV *sdv; /* Device name to get info */ int l; static unsigned long mount_option = /* MNT$M_NOASSIST|MNT$M_FOREIGN|MNT$M_MESSAGE; */ MNT$M_NOASSIST|MNT$M_FOREIGN; static struct { /* Mount service */ ITEM item_1; ITEM item_2; long end;} mount = { { 0, MNT$_DEVNAM, 0, 0}, /* Device Name */ { sizeof(mount_option),MNT$_FLAGS, (char *)&mount_option,(long *)0}, 0}; oserror = 0; /* Mount the Disk */ sdv = devname(name); mount.item_1.len = sdv->dsc$w_length; mount.item_1.addr = sdv->dsc$a_pointer; vmserror = SYS$MOUNT(&mount); if_VMSerror /* Some error, but take only 16 bits */ switch(vmserror&0xffff) { case SS$_DEVMOUNT: break; /* Already mounted, not an error */ default: oserror = EINTR; return(-1); } /* Assign the device */ vmserror = SYS$ASSIGN(sdv, &chan, 0,0); if_VMSerror { oserror = EIO; return(-1);} return(chan); } static int ioclose(fd, option) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Close the Device .RETURNS 0 (success) / -1 (failure) ------------------------------------------------------------*/ int fd; /* IN: Tape file descriptor */ int option; /* IN: Option OPU_DISMOUNT */ { SDV *sdv; oserror=0; vmserror = SYS$DASSGN(fd); if_VMSerror { oserror = EIO; return(-1);} sdv = devname(osuname(-1)); vmserror = SYS$DISMOU(sdv, (option & OPU_DISMOUNT ? 0 :DMT$M_NOUNLOAD)); if_VMSerror { oserror = EIO; return(-1);} return(0); } static int iosread(fd, sno, ssize, buffer, size) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Read a buffer from a DA device .RETURNS Bytes read / -1 if error .REMARKS 0 Bytes read, means ??? ------------------------------------------------------------*/ int fd; /* IN: Tape device file descriptor */ long sno; /* IN: Starting sector to read */ int ssize; /* IN: Size on one sector */ char *buffer; /* OUT: Buffer for reading */ int size; /* IN: Length of bytes to be read */ { long block; oserror = 0, chan = fd; block = sno*(ssize/SECTOR_SIZE); return (io2(IO$_READLBLK, buffer, size, block)); } static int ioswrite(fd, sno, ssize, buffer, size) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Write a block to a DA device .RETURNS Bytes written / -1 if error .REMARKS 0 Bytes read, means ??? ------------------------------------------------------------*/ int fd; /* IN: Tape device file descriptor */ long sno; /* IN: Starting sector to write */ int ssize; /* IN: Size on one sector */ char *buffer; /* IN: Buffer to write */ int size; /* IN: Numberof bytes to write */ { long block; oserror = 0, chan = fd; block = sno*(ssize/SECTOR_SIZE); return (io2(IO$_WRITELBLK, buffer, size, block)); } /*===================================================================== * Definition of the structure returned to osu *=====================================================================*/ static OPITEM list_of_functions[] = { { U_OPEN, ioopen}, /* Open (name, mode) */ { U_CLOSE, ioclose}, { U_INFO, ioinfo}, { U_SREAD, iosread}, /* Sector Read (fd,sno,ssize,buf,bsize)*/ { U_SWRITE, ioswrite}, /* Sector Write(fd,sno,ssize,buf,bsize)*/ { U_REWIND, iorew} }; static struct iolist this_dev = { iodev2, /* 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 *iodev1() /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Get All definitions concerning this class of Devices .RETURNS The iolist .REMARKS ------------------------------------------------------------*/ { return(&this_dev); }