From:	ADVAX::"mcnc!pucc.PRINCETON.EDU!moeller%gwdgv1.dnet.gwdg.de" "GWDGV1::MOELLER" 22-JAN-1991 00:35:31.03
To:	Arisia::Everhart, jim@mango.rsmas.miami.edu, R602MS5U@VB.CC.CMU.EDU, PALTER@UBVMS.BITNET, johnsond@calstate.bitnet, FOX@MSUNSCL.BITNET, awpsys@ultb.isc.rit.edu, ACCESS@KRDC.INT.Alcan.CA, moeller@dgogwdg5
CC:	
Subj:	VMS 5.4 ZTDRIVER part 2 of 4

Received: by ADVAX.DECnet (utk-mail11 v1.5) ; Tue, 22 Jan 91 00:33:19 EST
Received:  from mcnc by ge-dab.GE.COM (5.61/GE-DAB 1.15) with UUCP
	id AA03881 for everhart; Tue, 22 Jan 91 00:32:42 -0500
Received: from pucc.PRINCETON.EDU by mcnc.mcnc.org (5.59/MCNC/6-11-90)
	id AA02585; Mon, 21 Jan 91 23:33:31 -0500
	for Arisia.dnet.ge.com!Everhart
Message-Id: <9101220433.AA02585@mcnc.mcnc.org>
Received: from DGOGWDG1.BITNET by pucc.PRINCETON.EDU (IBM VM SMTP R1.2.2MX) with BSMTP id 1319; Mon, 21 Jan 91 23:33:23 EST
Received: from dnet.gwdg.de by DGOGWDG1.BITNET (Mailer R2.07) with BSMTP id
 7537; Mon, 21 Jan 91 22:18:43 MEZ
Date:    Mon, 21 Jan 1991 22:18:05 +0100
From: "GWDGV1::MOELLER" <mcnc!pucc.PRINCETON.EDU!moeller%gwdgv1.dnet.gwdg.de>
To: Arisia::Everhart, jim@mango.rsmas.miami.edu, R602MS5U@VB.CC.CMU.EDU,
        PALTER@UBVMS.BITNET, johnsond@calstate.bitnet, FOX@MSUNSCL.BITNET,
        awpsys@ultb.isc.rit.edu, ACCESS@KRDC.INT.Alcan.CA, moeller@dgogwdg5
Subject: VMS 5.4 ZTDRIVER part 2 of 4
 
+-+-+-+ Beginning of part 2 +-+-+-+
X
V/* NOTE: following ZT definitions must match ZTDEF.MAR & ZTSERVER.MAR *******
X**/
X
Xtypedef struct ZTmsg `123
X`009unsigned short iosts;
X`009unsigned short iobct;
X`009unsigned long devdepend;
X`009long record;
X`009unsigned short ucbsts;
X`009unsigned short fill1;
X`009unsigned long devchar;
X`009unsigned short func;
X`009unsigned short bcnt;
X`009union `123
X`009`009short w[4];
X`009`009unsigned short uw[4];
X`009`009unsigned long ul[2];
X`009`125 media;
X`125 ZTmsg;
Xglobalref struct `123
X`009unsigned short l;
X`009unsigned short fill1;
X`009ZTmsg *p;
X`125 ZT_MSGDSC;
X
Xglobalref struct `123
X`009unsigned long bct;
X`009unsigned char *addr;
X`125 ZT_BUFDSC;
X
Xextern unsigned ZT_INIT(),ZT_WAIT(),ZT_TOUSER(),ZT_FRUSER(),ZT_REQCOM();
X
V/******* end of ZT definitions **********************************************
X**/
X
X
X#include ssdef
X
X#include "mtdef.h"
X#include "iodef.h"`009/* my own! */
X#include "ucbdef.h"`009/* note VMS version dependency */
X#if PRE_V54
X#include devdef
X#endif
X
X#include stdio
X#include stddef
X#include string
X#include descrip
Xtypedef struct dsc$descriptor DESCR;
X
X#define CHECK(x) do `123unsigned s=x; if(!(s&1)) LIB$STOP(s);`125 while(0)
X#define FEHLER(m) do `123$DESCRIPTOR(d,m); Fehler(&d);`125 while(0)
X
Xvoid tape_init(void);
Xunsigned tape_writemark(void),
X`009tape_nop(void),
X`009tape_rewind(int/*logical*/ /*unload*/),
X`009tape_skiprec(int /*+-#blocks*/,int * /*#blocks skipped*/),
X`009tape_compare(int/*logical*/ /*reverse*/),
X`009tape_read(int/*logical*/ /*reverse*/,int/*logical*/ /*check*/),
X`009tape_write(int/*logical*/ /*check*/);
X
X/* data shared with 'tape' routines */
Xunsigned char *bufp;
Xunsigned long *bufbctp;
Xint /*logical*/ hw_online,hw_medonline,hw_bot,hw_eof,hw_eot,hw_hwl;
X
X
Xstatic ZTmsg *msgp;
X
Xstatic unsigned short fcode;
Xstatic unsigned short fmodif;
Xstatic enum `123no,yes,dunno`125 aftertm;`009/* tape positioned after mark? -
X`009`009`009`009`009shortcut to save tape movement */
X
X/*****/
X
Xstatic void do_init()
X`123
X`009tape_init();
X`009if(hw_bot) `123
X`009`009aftertm = no;
X`009`125 else `123
X`009`009aftertm = dunno;
X`009`125
X`125
X
Xstatic void do_writemark()
X`123
X`009/* fmodif: ... */
X
X`009msgp->iosts = tape_writemark();
X`009if(msgp->iosts & 1) `123
X`009`009msgp->record ++;
X`009`009aftertm = yes;
X`009`125
X`125
X
Xstatic void do_nop()
X`123
X`009/* give 'tape' a chance to update the state */
X`009msgp->iosts = tape_nop();
X
X`009/* 'aftertm' did not change, I hope ... */
X`125
X
Xstatic void do_rewind(int unload)
X`123
X`009/* fmodif: IO$M_NOWAIT ignored */
X
X`009msgp->iosts = tape_rewind(unload);
X`009msgp->record = 0;
X
X#if 0`009/* this works together with a VMS V.5 addition:
X`009   if tape is mounted foreign & MT$M_ENAUTOPACK is set,
X`009   then set UCB$M_VALID on "medium online" interrupt */
X`009/*...................................................*/
X`009if(!hw_medonline) `123
X`009`009msgp->ucbsts &= `126UCB$M_VALID;
X`009`125
X#endif`009/*...................................................*/
X`125
X
Xstatic unsigned set_aftertm()`009/* ggf. find out if tape is positioned
X`009`009`009`009`009after a tape mark */
X`123
X`009unsigned status;
X`009int sca;
X
X
X`009if(aftertm != dunno) return SS$_NORMAL;`009/* nothing to be done */
X
X`009status = tape_skiprec(-1,&sca);
X`009msgp->record -= sca;
X`009if(sca != 1) `123
X`009`009if(!hw_bot) `123
X`009`009`009return SS$_TAPEPOSLOST;
X`009`009`125 else `123
X`009`009`009aftertm = no;
X`009`009`009return SS$_NORMAL;
X`009`009`125
X`009`125
X`009status = tape_skiprec(1,&sca);
X`009msgp->record += sca;
X`009if(sca != 1) `123
X`009`009return SS$_TAPEPOSLOST;
X`009`125
X`009aftertm = hw_eof;
X`009return SS$_NORMAL;
X`125
X
Xstatic void`009/* "end of volume" recognized */
Xset_eov()`009/* backspace over 2nd eof mark, decrement spacing count etc. */
X`123
X`009unsigned status;
X`009int sca;
X
X
X`009status = tape_skiprec(-1,&sca);
X`009msgp->record -= sca;
X`009msgp->iobct --;
X`009if(!(status & 1) `124`124 !hw_eof `124`124 sca != 1) `123
X`009`009msgp->iosts = SS$_TAPEPOSLOST;
X`009`009aftertm = dunno;
X`009`125 else `123
X`009`009/* aftertm remains == yes */
X`009`009msgp->iosts = SS$_ENDOFVOLUME;
X`009`125
X`125
X
Xstatic void do_skiprec()
X`123
X`009int sc,sca;
X`009
X
X`009/* fmodif: ... */
X
X`009sc = msgp->media.w[0];
X`009if(sc == 0) `123
X`009`009do_nop();
X`009`009return;
X`009`125 else if(sc > 0) `123`009`009`009`009`009/* FORWARD */
X#if PRE_V54
X`009`009int/*logical*/ no_acp;
X
X
X`009`009no_acp =`009/* not mounted, or mounted foreign */
X`009`009`009((msgp->devchar & DEV$M_MNT) == 0) `124`124
X`009`009`009((msgp->devchar & DEV$M_FOR) != 0);
X`009`009if(no_acp) `123
X#endif
X`009`009`009msgp->iosts = set_aftertm();
X`009`009`009if(!(msgp->iosts & 1)) return;`009/* ... tapeposlost */
X#if PRE_V54
X`009`009`125
X#endif
X
X`009`009msgp->iosts = tape_skiprec(sc,&sca);
X`009`009msgp->record += sca;
X`009`009msgp->iobct = sca;
X
X`009`009if(!(msgp->iosts & 1)) `123
X`009`009`009aftertm = dunno;
X`009`009`125 else if(hw_eof) `123
X`009`009`009aftertm = yes;
X`009`009`009if(
X#if PRE_V54
X`009`009`009   no_acp &&
X#endif
X`009`009`009`009     (sca == 1)) `123
X`009`009`009`009/* "end of volume recognition" */
X`009`009`009`009set_eov();
X`009`009`009`125 else `123
X`009`009`009`009msgp->iosts = SS$_ENDOFFILE;
X`009`009`009`125
X`009`009`125 else `123
X`009`009`009aftertm = no;
X`009`009`125
X`009`125 else `123`009`009`009`009`009`009/* BACKWARD */
X`009`009msgp->iosts = tape_skiprec(sc,&sca);
X`009`009msgp->record -= sca;
X`009`009msgp->iobct = sca;
X
X`009`009aftertm = dunno;
X`009`009if((msgp->iosts & 1) && hw_eof) `123
X`009`009`009msgp->iosts = SS$_ENDOFFILE;
X`009`009`125
X`009`125
X`125
X
Xstatic void do_skipfile()
X`123
X`009int sc,sca;
X`009
X`009/* fmodif: ... */
X
X`009sc = msgp->media.w[0];
X`009if(sc == 0) `123
X`009`009do_nop();
X`009`009return;
X`009`125 else if(sc > 0) `123`009`009`009`009`009/* FORWARD */
X#if PRE_V54
X`009`009int/*logical*/ no_acp;
X#endif
X`009`009int prevtm;`009`009/* 'record' after tape mark, or -2 */
X
X#if PRE_V54
X`009`009no_acp =`009/* not mounted, or mounted foreign */
X`009`009`009((msgp->devchar & DEV$M_MNT) == 0) `124`124
X`009`009`009((msgp->devchar & DEV$M_FOR) != 0);
X`009`009if(no_acp) `123
X#endif
X`009`009`009msgp->iosts = set_aftertm();
X`009`009`009if(!(msgp->iosts & 1)) return;`009/* ... tapeposlost */
X`009`009`009if(aftertm == yes) `123
X`009`009`009`009prevtm = msgp->record;
X`009`009`009`125 else `123
X`009`009`009`009prevtm = -2;
X`009`009`009`125
X#if PRE_V54
X`009`009`125
X#endif
X
X`009`009msgp->iobct = 0;
X`009`009do `123
X`009`009`009do `123
X`009`009`009`009msgp->iosts = tape_skiprec(0x7FFF,&sca);
X`009`009`009`009msgp->record += sca;
X`009`009`009`009if(!(msgp->iosts & 1)) `123
X`009`009`009`009`009aftertm = dunno;
X`009`009`009`009`009return;
X`009`009`009`009`125
X`009`009`009`125 while(!hw_eof);
X
X`009`009`009msgp->iobct ++;
X`009`009`009sc --;
X
X#if PRE_V54
X`009`009`009if(no_acp) `123
X#endif
X`009`009`009`009if(msgp->record == prevtm+1) `123
X`009`009`009`009`009aftertm = yes;
X`009`009`009`009`009set_eov();
X`009`009`009`009`009return;
X`009`009`009`009`125 else `123
X`009`009`009`009`009prevtm = msgp->record;
X`009`009`009`009`125
X#if PRE_V54
X`009`009`009`125
X#endif
X`009`009`125 while(sc > 0);
X`009`009aftertm = yes;
X`009`125 else `123`009`009`009`009`009`009/* BACKWARD */
X`009`009msgp->iobct = 0;
X`009`009do `123
X`009`009`009do `123
X`009`009`009`009msgp->iosts = tape_skiprec(-0x7FFF,&sca);
X`009`009`009`009msgp->record -= sca;
X`009`009`009`009if(!(msgp->iosts & 1)) `123
X`009`009`009`009`009aftertm = dunno;
X`009`009`009`009`009return;
X`009`009`009`009`125
X`009`009`009`125 while(!hw_eof && !hw_bot);
X
X#if 0`009/* I had this in the pre-5.4 version, `009`009*/
X`009/* but TMDRIVER has always counted differently`009*/
X`009`009`009msgp->iobct ++;
X#else
X`009`009`009if(hw_bot) break;`009`009/** don't count BOT **/
X`009`009`009msgp->iobct ++;`009`009`009/** (from TMDRIVER) **/
X#endif
X`009`009`009sc ++;
X
X`009`009`125 while(sc < 0 && !hw_bot);
X`009`009aftertm = dunno;
X`009`125
X`125
X
Xstatic void do_writecheck()
X`123
X`009int /*logical*/ reverse;
X
X
X`009/* fmodif: ... */
X`009reverse = ((fmodif & IO$M_REVERSE) != 0);
X`009if(reverse) `123`009`009`009`009/* not supported so far */
X`009`009msgp->iosts = SS$_BADPARAM;
X`009`009return;
X`009`125
X
X`009CHECK(ZT_FRUSER());
X
X`009msgp->iosts = tape_compare(reverse);`009/* 'updates' *bufbctp`009*/
X`009if((msgp->iosts & 1) `124`124
X`009   (msgp->iosts == SS$_PARITY) `124`124
X`009   (msgp->iosts == SS$_DATACHECK)) `123`009/*** assume tape moved ***/
X`009`009if(reverse) `123
X`009`009`009msgp->record --;
X`009`009`009aftertm = dunno;
X`009`009`125 else `123
X`009`009`009msgp->record ++;
X`009`009`009aftertm = hw_eof;
X`009`009`125
X`009`125
X`009if(msgp->iosts & 1) `123
X`009`009if(hw_eof) `123
X`009`009`009msgp->iosts = SS$_ENDOFFILE;
X`009`009`125 else `123
X`009`009`009msgp->iobct = *bufbctp;
X`009`009`009if(*bufbctp > msgp->bcnt) `123
X`009`009`009`009msgp->iosts = SS$_DATAOVERUN;
X`009`009`009`125
X`009`009`125
X`009`125
X`125
X
Xstatic void do_read()
X`123
X`009int /*logical*/ reverse, check;
X
X
X`009/* fmodif: ... */
X`009reverse = ((fmodif & IO$M_REVERSE) != 0);
X`009if(reverse) `123`009`009`009`009/* not supported so far */
X`009`009msgp->iosts = SS$_BADPARAM;
X`009`009return;
X`009`125
X`009check = ((fmodif & IO$M_DATACHECK) != 0);
X
X`009msgp->iosts = tape_read(reverse,check);`009/* fills in *bufbctp`009*/
X`009if((msgp->iosts & 1) `124`124
X`009   (msgp->iosts == SS$_PARITY) `124`124
X`009   (msgp->iosts == SS$_DATACHECK)) `123`009/*** assume tape moved ***/
X`009`009if(reverse) `123
X`009`009`009msgp->record --;
X`009`009`009aftertm = dunno;
X`009`009`125 else `123
X`009`009`009msgp->record ++;
X`009`009`009aftertm = hw_eof;
X`009`009`125
X`009`125
X`009if(msgp->iosts & 1) `123
X`009`009if(hw_eof) `123
X`009`009`009msgp->iosts = SS$_ENDOFFILE;
X`009`009`125 else `123
X`009`009`009msgp->iobct = *bufbctp;
X`009`009`009if(*bufbctp > msgp->bcnt) `123
X`009`009`009`009msgp->iosts = SS$_DATAOVERUN;
X`009`009`009`009*bufbctp = msgp->bcnt;
X`009`009`009`125
X`009`009`009CHECK(ZT_TOUSER());
X`009`009`125
X`009`125
X`125
X`009`009
Xstatic void do_write()
X`123
X`009int/*logical*/ check;
X
X
X`009/* fmodif: the mysterious IO$M_ERASE flag is simply ignored,
X`009`009`009ditto IO$M_NOWAIT ("TU81plus only") ... */
X`009check = ((fmodif & IO$M_DATACHECK) != 0);
X
X`009CHECK(ZT_FRUSER());
X`009msgp->iosts = tape_write(check);
X`009if(msgp->iosts & 1) `123
X`009`009msgp->record ++;
X`009`009msgp->iobct = *bufbctp;
X`009`009aftertm = no;
X`009`125
X`125
X
X
X/*****/
X
X#if TRACE
Xstatic void trace_func();`009/* forward */
Xstatic void trace_result();`009/* forward */
X#endif
X
Xstatic void dispatch()
X`123
X`009fcode = msgp->func & IO$M_FCODE;
X`009fmodif = msgp->func & IO$M_FMODIFIERS;
X
X#if TRACE
X`009trace_func();
X#endif
X
X`009switch(fcode) `123
X
X`009  case IO$_WRITEMARK:
X`009  case IO$_WRITEOF:
X`009`009do_writemark();
X`009`009break;
X
X`009  case IO$_UNLOAD:
X`009  case IO$_REWINDOFF:
X`009`009do_rewind(1);
X`009`009break;
X
X`009  case IO$_RECAL:
X`009  case IO$_REWIND:
X`009  case IO$_AVAILABLE:`009`009/* NOTE: driver cleared VALID */
X`009`009do_rewind(0);
X`009`009break;
X`009`009
X`009  case IO$_PACKACK:
X`009`009do_nop();
X`009`009if((msgp->iosts & 1)) `123
X`009`009`009msgp->ucbsts `124= UCB$M_VALID;
X`009`009`125
X`009`009break;
X`009`009
X`009  case IO$_SPACEFILE:
X`009  case IO$_SKIPFILE:
X`009`009do_skipfile();
X`009`009break;
X
X`009  case IO$_SPACERECORD:
X`009  case IO$_SKIPRECORD:
X`009`009do_skiprec();
X`009`009break;
X
X`009  case IO$_WRITECHECK:
X`009`009do_writecheck();
X`009`009break;
X
X`009  case IO$_WRITEPBLK:
X`009  case IO$_WRITELBLK:
X`009`009do_write();
X`009`009break;
X
X`009  case IO$_READPBLK:
X`009  case IO$_READLBLK:
X`009`009do_read();
X`009`009break;
X
X`009  case IO$_NOP:
X`009  case IO$_SENSECHAR:
X`009  case IO$_SENSEMODE:
X`009  case IO$_SETCHAR:`009`009/* treat as no-op */
X`009  case IO$_SETMODE:`009`009/* treat as no-op */
X`009  case IO$_DRVCLR:`009`009/* treat as no-op */
X`009  case IO$_ERASETAPE:`009`009/* treat as no-op */
Xnoop:
X`009`009do_nop();
X`009`009break;
X
X`009  default:
X`009`009msgp->iosts = SS$_ILLIOFUNC;
X`009`009break;
X`009`125
X
X/* final processing:
X`009iosts`009`009- has been set
X`009iobct`009`009- has been set (or defaulted to 0)
X`009devdepend`009- to be set here
X`009record`009`009- has been updated (if changed)
X`009ucbsts`009`009- v_valid has been modified (if changed)
X*/
X
V`009if(msgp->iosts == SS$_TAPEPOSLOST) `123`009/* set 'LOST' BIT from status
X */
X`009`009msgp->devdepend `124= MT$M_LOST;
X`009`125
X
X`009if(hw_bot) `123`009`009`009/* "BOT" */
X`009`009msgp->devdepend `124= MT$M_BOT;`009`009/* set BOT */
X`009`009msgp->devdepend &= `126MT$M_LOST;`009`009/* clear pos. lost */
X`009`009aftertm = no;
X`009`125 else `123
X`009`009msgp->devdepend &= `126MT$M_BOT;`009`009/* clear BOT */
X`009`125
X
X`009if(hw_eof) `123`009`009`009/* "EOF" */
X`009`009msgp->devdepend `124= MT$M_EOF;`009`009/* set EOF */
X`009`125 else `123
X`009`009msgp->devdepend &= `126MT$M_EOF;`009`009/* clear EOF */
X`009`125
X
X`009if(hw_eot) `123`009`009`009/* "EOT" */
X`009`009msgp->devdepend `124= MT$M_EOT;`009`009/* set EOT */
X
X`009`009switch(fcode) `123`009`009`009/* usually set iosts=EOT */
X`009`009  case IO$_SPACEFILE:
X`009`009  case IO$_SKIPFILE:
X`009`009  case IO$_SPACERECORD:
X`009`009  case IO$_SKIPRECORD:
X`009`009`009if(msgp->media.w[0] >= 0) goto eotsts;
X`009`009`009break;`009`009`009/* not for space reverse */
X
X`009`009  case IO$_WRITECHECK:
X`009`009`009if(!(fmodif & IO$M_REVERSE)) goto eotsts;
X`009`009`009break;`009`009`009/* not for writecheck reverse */
X
X`009`009  case IO$_READPBLK:
X`009`009  case IO$_READVBLK:
X`009`009`009break;`009`009`009/* not for read */
X
X`009`009  default:
Xeotsts:
X`009`009`009if(msgp->iosts & 1) `123
X`009`009`009`009msgp->iosts = SS$_ENDOFTAPE;
X`009`009`009`125
X`009`009`009break;
X`009`009`125
X`009`125 else `123
X`009`009msgp->devdepend &= `126MT$M_EOT;`009`009/* clear EOT */
X`009`125
X
X`009if(hw_hwl) `123`009`009`009/* write lock */
X`009`009msgp->devdepend `124= MT$M_HWL;`009`009/* set HWL */
X`009`125 else `123
X`009`009msgp->devdepend &= `126MT$M_HWL;`009`009/* clear HWL */
X`009`125
X
X#if TRACE
X`009trace_result();
X#endif
X`125
X
X
X/*****/
X
Xmain(argc,argv)
Xint argc; char **argv;
X`123
X
X#ifdef VAXC
X`009redirect(&argc,&argv);
X#endif
X
X`009bufp = ZT_BUFDSC.addr;
X`009bufbctp = &(ZT_BUFDSC.bct);
X
X`009if(ZT_MSGDSC.l != sizeof(ZTmsg)) FEHLER("bad MSGDSC.len");
X`009msgp = ZT_MSGDSC.p;
X
X
X`009do_init();
X`009CHECK(ZT_INIT());
X
X
X`009do `123
X`009`009CHECK(ZT_WAIT());
X
X`009`009dispatch();
X
X`009`009CHECK(ZT_REQCOM());
X`009`125 while(hw_online);
X`125
X
X
X/*****/
X
X#if TRACE
X
Xtypedef enum `123zeroparm,oneparm,transfer,setchar`125 TRACE_FTYPE;
X
Xstatic void trace_f(char *fname,TRACE_FTYPE ftype)
X`123
X`009int i,fm;
X
X`009fprintf(stdout,"***** %s",fname);
X
X`009for(fm = fmodif>>IO$V_FMODIFIERS, i = IO$V_FMODIFIERS;
X`009    (fm != 0) && i < 16;
X`009    fm >>= 1, i++) `123
X`009`009if(fm & 1) switch(i) `123
X`009`009  case IO$V_REVERSE:
X`009`009`009fprintf(stdout,",REVERSE"); break;
X`009`009  case IO$V_NOWAIT:
X`009`009`009fprintf(stdout,",NOWAIT"); break;
X`009`009  case IO$V_ERASE:
X`009`009`009fprintf(stdout,",ERASE"); break;
X`009`009  case IO$V_INHERLOG:
X`009`009`009fprintf(stdout,",INHERLOG"); break;
X`009`009  case IO$V_INHEXTGAP:
X`009`009`009fprintf(stdout,",INHEXTGAP"); break;
X`009`009  case IO$V_DATACHECK:
X`009`009`009fprintf(stdout,",DATACHECK"); break;
X`009`009  case IO$V_INHRETRY:
X`009`009`009fprintf(stdout,",INHRETRY"); break;
X`009`009  default:
X`009`009`009fprintf(stdout,",1@%d",i);
X`009`009`009break;
X`009`009`125
X`009`125
X
X`009switch(ftype) `123
X`009  case zeroparm:
X`009`009break;
X`009  case oneparm:
X`009`009fprintf(stdout," media=%d",msgp->media.w[0]);
X`009`009break;
X`009  case transfer:
X`009`009fprintf(stdout," bcnt=%d",msgp->bcnt);
X`009`009break;
X`009  case setchar:
X`009`009fprintf(stdout," media: %04X %04X %04X",
X`009`009`009`009msgp->media.uw[0],
X`009`009`009`009msgp->media.uw[1],
X`009`009`009`009msgp->media.uw[2]);
X`009`009break;
X`009`125
X`009fprintf(stdout," record=%d\n",msgp->record);`009 `032
X`125
X
Xstatic void trace_func()
X`123
X`009switch(fcode) `123
X`009  case IO$_NOP:
X`009`009trace_f("IO$_NOP",zeroparm); break;
X`009  case IO$_UNLOAD:
X`009`009trace_f("IO$_UNLOAD",zeroparm); break;
X`009  case IO$_RECAL:
X`009`009trace_f("IO$_RECAL",zeroparm); break;
X`009  case IO$_DRVCLR:
X`009`009trace_f("IO$_DRVCLR",zeroparm); break;
X`009  case IO$_ERASETAPE:
X`009`009trace_f("IO$_ERASETAPE",zeroparm); break;
X`009  case IO$_PACKACK:
X`009`009trace_f("IO$_PACKACK",zeroparm); break;
X`009  case IO$_AVAILABLE:
X`009`009trace_f("IO$_AVAILABLE",zeroparm); break;
X`009  case IO$_WRITEMARK:
X`009`009trace_f("IO$_WRITEMARK",zeroparm); break;
X`009  case IO$_REWINDOFF:
X`009`009trace_f("IO$_REWINDOFF",zeroparm); break;
X`009  case IO$_REWIND:
X`009`009trace_f("IO$_REWIND",zeroparm); break;
X`009  case IO$_WRITEOF:
X`009`009trace_f("IO$_WRITEOF",zeroparm); break;
X`009  case IO$_SPACEFILE:
X`009`009trace_f("IO$_SPACEFILE",oneparm); break;
X`009  case IO$_SPACERECORD:
X`009`009trace_f("IO$_SPACERECORD",oneparm); break;
X`009  case IO$_SKIPFILE:
X`009`009trace_f("IO$_SKIPFILE",oneparm); break;
X`009  case IO$_SKIPRECORD:
X`009`009trace_f("IO$_SKIPRECORD",oneparm); break;
X`009  case IO$_SENSECHAR:
X`009`009trace_f("IO$_SENSECHAR",zeroparm); break;
X`009  case IO$_SENSEMODE:
X`009`009trace_f("IO$_SENSEMODE",zeroparm); break;
X`009  case IO$_SETCHAR:
X`009`009trace_f("IO$_SETCHAR",setchar); break;
X`009  case IO$_SETMODE:
X`009`009trace_f("IO$_SETMODE",setchar); break;
X`009  case IO$_WRITECHECK:
X`009`009trace_f("IO$_WRITECHECK",transfer); break;
X`009  case IO$_WRITEPBLK:
X`009`009trace_f("IO$_WRITEPBLK",transfer); break;
X`009  case IO$_READPBLK:
X`009`009trace_f("IO$_READPBLK",transfer); break;
X`009  case IO$_WRITELBLK:
X`009`009trace_f("IO$_WRITELBLK",transfer); break;
X`009  case IO$_READLBLK:
X`009`009trace_f("IO$_READLBLK",transfer); break;
X`009  default:
X`009`009`123`009char name[16];
X
X`009`009`009sprintf(name,"?%d?",fcode);
X`009`009`009trace_f(name,zeroparm);
X`009`009`125
X`009`009break;
X`009`125
X`125
X
Xstatic void trace_result()
X`123
X`009fprintf(stdout,"\tiosts=");
X`009switch(msgp->iosts) `123
X`009  case SS$_NORMAL:
X`009`009fprintf(stdout,"SS$_NORMAL"); break;
X`009  case SS$_BADPARAM:
X`009`009fprintf(stdout,"SS$_BADPARAM"); break;
X`009  case SS$_CTRLERR:
X`009`009fprintf(stdout,"SS$_CTRLERR"); break;
X`009  case SS$_DATACHECK:
X`009`009fprintf(stdout,"SS$_DATACHECK"); break;
X`009  case SS$_DEVOFFLINE:
X`009`009fprintf(stdout,"SS$_DEVOFFLINE"); break;
X`009  case SS$_DRVERR:
X`009`009fprintf(stdout,"SS$_DRVERR"); break;
X`009  case SS$_FORMAT:
X`009`009fprintf(stdout,"SS$_FORMAT"); break;
X`009  case SS$_ILLIOFUNC:
X`009`009fprintf(stdout,"SS$_ILLIOFUNC"); break;
X`009  case SS$_MEDOFL:
X`009`009fprintf(stdout,"SS$_MEDOFL"); break;
X`009  case SS$_NONEXDRV:
X`009`009fprintf(stdout,"SS$_NONEXDRV"); break;
X`009  case SS$_PARITY:
X`009`009fprintf(stdout,"SS$_PARITY"); break;
X`009  case SS$_TAPEPOSLOST:
X`009`009fprintf(stdout,"SS$_TAPEPOSLOST"); break;
X`009  case SS$_TIMEOUT:
X`009`009fprintf(stdout,"SS$_TIMEOUT"); break;
X`009  case SS$_UNSAFE:
X`009`009fprintf(stdout,"SS$_UNSAFE"); break;
X`009  case SS$_VOLINV:
X`009`009fprintf(stdout,"SS$_VOLINV"); break;
X`009  case SS$_WRITLCK:
X`009`009fprintf(stdout,"SS$_WRITLCK"); break;
X`009  case SS$_DATAOVERUN:
X`009`009fprintf(stdout,"SS$_DATAOVERUN"); break;
X`009  case SS$_ENDOFFILE:
X`009`009fprintf(stdout,"SS$_ENDOFFILE"); break;
X`009  case SS$_ENDOFTAPE:
X`009`009fprintf(stdout,"SS$_ENDOFTAPE"); break;
X`009  case SS$_ENDOFVOLUME:
X`009`009fprintf(stdout,"SS$_ENDOFVOLUME"); break;
X`009  case SS$_BEGOFTAPE:
X`009`009fprintf(stdout,"SS$_BEGOFTAPE"); break;
X`009  default:
X`009`009fprintf(stdout,"%04X",msgp->iosts);
X`009`009break;
X`009`125
X
X`009if(msgp->devdepend & MT$M_BOT) fprintf(stdout,",M_BOT");
X`009if(msgp->devdepend & MT$M_EOF) fprintf(stdout,",M_EOF");
X`009if(msgp->devdepend & MT$M_EOT) fprintf(stdout,",M_EOT");
X`009if(msgp->devdepend & MT$M_HWL) fprintf(stdout,",M_HWL");
X`009if(msgp->devdepend & MT$M_LOST) fprintf(stdout,",M_LOST");
X
X`009if(msgp->iobct != 0) `123
X`009`009fprintf(stdout," iobct=%d",msgp->iobct);
X`009`125
X
X`009fprintf(stdout," atm=%c",(aftertm == yes) ? '1' :
X`009`009`009`009`009(aftertm == no) ? '0' : '?');
X`009 `032
X`009fprintf(stdout," record=%d\n",msgp->record);`009 `032
X`125
X
X#endif /* TRACE */
$ GOSUB UNPACK_FILE
 
$ FILE_IS = "ZT1T.C"
$ CHECKSUM_IS = 560051951
$ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY
X/*`009memory-'tape' routines for first test of ZTDRIVER ...
X`009w.j.m. jun 1989
X*/
X
X#ifndef TRACE
X#define TRACE 1
X#endif
X
X#include ssdef
X
X#include stdio
X#include stddef
X#include string
X#include descrip
Xtypedef struct dsc$descriptor DESCR;
X
X#define CHECK(x) do `123unsigned s=x; if(!(s&1)) LIB$STOP(s);`125 while(0)
X#define FEHLER(m) do `123$DESCRIPTOR(d,m); Fehler(&d);`125 while(0)
X
X/* data & entries used by "main" program */
X
Xextern unsigned char *bufp;
Xextern unsigned long *bufbctp;
X
Xextern int /*logical*/ hw_online,hw_medonline,hw_bot,hw_eof,hw_eot,hw_hwl;
X
X/* forward */
Xvoid tape_init(void);
Xunsigned tape_writemark(void),
X`009tape_nop(void),
X`009tape_rewind(int/*logical*/ /*unload*/),
X`009tape_skiprec(int /*+-#blocks*/,int * /*#blocks skipped*/),
X`009tape_compare(int/*logical*/ /*reverse*/),
X`009tape_read(int/*logical*/ /*reverse*/,int/*logical*/ /*check*/),
X`009tape_write(int/*logical*/ /*check*/);
X
X#if TRACE
Xstatic void trace_tape(char *,int,int,int);`009/* forward */
Xstatic int tpos;`009/* true position (in blocks) */
X#endif
X
X/* the 'memory tape' */
X/* structure:
X`009short l1; char [l1]; short l1; short l2; char [l2]; short l1; ...
X`009`009l=0 stands for end of written area,
X`009`009l=1 stands for tape mark
X*/
X
X#define TAPELEN 2000000`009`009`009/* bytes */
X#define TAPEEOT (TAPELEN-200000)`009/* room after EOT */
Xstatic unsigned char tm[TAPELEN], *tp;
X
X#define T_eotape 0
X#define T_mark 1
X
X#define T_nextlen (*((unsigned short *) tp))
X#define T_prevlen (*(((unsigned short *) tp) - 1))
X#define T_data (tp + sizeof(unsigned short))
X
X#define T_bot (tp == tm)
X#define T_eot (tp >= (tm + TAPEEOT))
X
X#define T_toomuch(l) (tp >= (tm + TAPELEN - 3*sizeof(unsigned short) - l))
X
X#define T_prevpos (tp - (T_prevlen + 2*sizeof(unsigned short)))
X#define T_nextpos (tp + (T_nextlen + 2*sizeof(unsigned short)))
X
X
X/*****/
X
Xvoid tape_init(void)
X`123
X
X`009tp = tm;
X`009T_nextlen = T_eotape;
X#if TRACE
X`009tpos = 0;
X#endif
X
X`009hw_online = 1;
X`009hw_medonline = 1;
X`009hw_hwl = 0;
X
X`009hw_eof = 0;
X`009hw_bot = T_bot;
X`009hw_eot = T_eot;
X`125
X
Xunsigned tape_writemark(void)
X`123
X#if TRACE
X`009trace_tape("WRITEMARK",0,0,0);
X#endif
X`009if(!hw_online) return SS$_DEVOFFLINE;
X`009if(!hw_medonline) return SS$_MEDOFL;
X
X`009if(T_toomuch(T_mark)) return SS$_UNSAFE;
X
X`009T_nextlen = T_mark;
X`009tp = T_nextpos;
X`009T_prevlen = T_mark;
X`009T_nextlen = T_eotape;
X#if TRACE
X`009tpos ++;
X#endif
X
X`009hw_eof = 1; `009`009/* ??? */
X`009hw_bot = T_bot;
X`009hw_eot = T_eot;
X
X`009return SS$_NORMAL;
X`125
X
Xunsigned tape_nop(void)
X`123
X#if TRACE
X`009trace_tape("NOP",0,0,0);
X#endif
X`009/* tape status does not change ... */
X`009if(!hw_online) return SS$_DEVOFFLINE;
X`009if(!hw_medonline) return SS$_MEDOFL;
X`009return SS$_NORMAL;
X`125
X
Xunsigned tape_rewind(int/*logical*/ unload)
X`123
X#if TRACE
X`009trace_tape("REWIND",1,unload,0);
X#endif
X`009if(!hw_online) return SS$_DEVOFFLINE;
X`009if(!hw_medonline) return SS$_MEDOFL;
X
X`009/* leave (mysteriously) medium online in spite of unload */
X`009/* i.e. 'unload' is ignored(!) */
X
X`009tp = tm;
X#if TRACE
X`009tpos = 0;
X#endif
X
X`009hw_eof = 0;
X`009hw_bot = T_bot;
X`009hw_eot = T_eot;
X
X`009return SS$_NORMAL;
X`125
X
Xunsigned tape_skiprec(int sb,int *sap)
X/* sb = (signed) # blocks to be skipped
X   sap = pointer to return value: absolute # blocks skipped */
X/* terminate after EOF mark, or at BOT */
X`123
X`009unsigned xstat;
X
X
X#if TRACE
X`009trace_tape("SKIPREC",1,sb,0);
X#endif
X`009if(!hw_online) return SS$_DEVOFFLINE;
X`009if(!hw_medonline) return SS$_MEDOFL;
X
X`009*sap = 0;
X
X`009xstat = SS$_NORMAL;`009/* assume success,`032
X`009`009`009`009this includes EOF & BOT termination */
X`009if(sb > 0) `123
X`009`009do `123
X`009`009`009if(T_nextlen == T_eotape) `123
X`009`009`009`009xstat = SS$_TAPEPOSLOST;
X`009`009`009`009break;
X`009`009`009`125
X`009`009`009hw_eof = (T_nextlen == T_mark);
X`009`009`009tp = T_nextpos;
X#if TRACE
X`009`009`009tpos ++;
X#endif
X`009`009`009(*sap) ++;
X`009`009`125 while(!hw_eof && (*sap < sb));
X`009`125 else if(sb < 0) `123
X`009`009do `123
X`009`009`009if(T_bot) break;
X`009`009`009hw_eof = (T_prevlen == T_mark);
X`009`009`009tp = T_prevpos;
X#if TRACE
X`009`009`009tpos --;
X#endif
X`009`009`009(*sap) ++;
X`009`009`125 while(!hw_eof && ((*sap + sb) < 0));
X`009`125
X
X`009hw_bot = T_bot;
X`009hw_eot = T_eot;
X
X`009return xstat;
X`125
X
Xunsigned tape_compare(int/*logical*/ reverse)
X/* (buffer,bufbct) has memory data.
X`009compare to tape block,
X`009return length of tape block in bufbct */
X`123
X`009unsigned xstat;
X
X
X#if TRACE
X`009trace_tape("COMPARE",1,reverse,0);
X#endif
X`009if(!hw_online) return SS$_DEVOFFLINE;
X`009if(!hw_medonline) return SS$_MEDOFL;
X
X`009if(reverse) return SS$_BADPARAM;`009/* reverse not supported */
X
X
X`009xstat = SS$_NORMAL;`009/* assume success, includes EOF read */
X
X`009if(T_nextlen == T_eotape) `123
X`009`009xstat = SS$_TAPEPOSLOST;
X`009`125 else `123
X`009`009hw_eof = (T_nextlen == T_mark);
X`009`009if(hw_eof) `123
X`009`009`009*bufbctp = 0;
X`009`009`125 else `123
X`009`009`009if(*bufbctp < T_nextlen `124`124
X`009`009`009   memcmp(T_data,bufp,T_nextlen)) `123
X`009`009`009`009xstat = SS$_DATACHECK;
X`009`009`009`125
X`009`009`009*bufbctp = T_nextlen;
X`009`009`125
X`009`009tp = T_nextpos;
X#if TRACE
X`009`009tpos ++;
X#endif
X`009`125
X
X`009hw_bot = T_bot;
X`009hw_eot = T_eot;
X
X`009return xstat;
X`125
X
X
Xunsigned tape_read(int/*logical*/ reverse, int/*logical*/ check)
X/* put data into (buffer,bufbct) */
X/* 'check' (ignored) requests data checking */
X`123
X#if TRACE
X`009trace_tape("READ",2,reverse,check);
X#endif
X`009if(!hw_online) return SS$_DEVOFFLINE;
X`009if(!hw_medonline) return SS$_MEDOFL;
X
X`009if(reverse) return SS$_BADPARAM;`009/* reverse not supported */
X
X`009if(T_nextlen == T_eotape) return SS$_TAPEPOSLOST;
X
X`009hw_eof = (T_nextlen == T_mark);
X`009if(hw_eof) `123
X`009`009*bufbctp = 0;
X`009`125 else `123
X`009`009*bufbctp = T_nextlen;
X`009`009memcpy(bufp,T_data,T_nextlen);
X`009`125
X`009tp = T_nextpos;
X#if TRACE
X`009tpos ++;
X#endif
X
X`009hw_bot = T_bot;
X`009hw_eot = T_eot;
X
X`009return SS$_NORMAL;
X`125
X
Xunsigned tape_write(int/*logical*/ check)
X/* process data from (buffer,bufbct) */
X/* 'check' (ignored) requests data checking */
X`123
X#if TRACE
X`009trace_tape("WRITE",1,check,0);
X#endif
X`009if(!hw_online) return SS$_DEVOFFLINE;
X`009if(!hw_medonline) return SS$_MEDOFL;
X
X`009if(T_toomuch(*bufbctp)) return SS$_UNSAFE;
X
X`009T_nextlen = *bufbctp;
X`009memcpy(T_data,bufp,*bufbctp);
X`009tp = T_nextpos;
X`009T_prevlen = *bufbctp;
X`009T_nextlen = T_eotape;
X#if TRACE
X`009tpos ++;
X#endif
X
X`009hw_eof = 0;
X`009hw_bot = T_bot;
X`009hw_eot = T_eot;
X
X`009return SS$_NORMAL;
X`125
X
X
X/*****/
X
X#if TRACE
X
Xstatic void trace_tape(char *fname,int ac,int a1,int a2)
X`123
X`009fprintf(stdout,"\tTAPE_%s(",fname);
X`009if(ac > 0) `123
X`009`009fprintf(stdout,"%d",a1);
X`009`009if(ac > 1) `123
X`009`009`009fprintf(stdout,",%d",a2);
X`009`009`125
X`009`125
X`009fprintf(stdout,") tpos=%d\n",tpos);
X`125
X
X#endif
$ GOSUB UNPACK_FILE
 
$ FILE_IS = "ZT2.C"
$ CHECKSUM_IS = 554597599
$ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY
X/*`009ZTserver (network object) for ZTNS & ZTDRIVER ...
X`009w.j.m. jun 1989
X`009mod 3-jul-1989 wjm: unless UNSAFE_AFTER_ERROR is defined as 1,
X`009`009`009don't take unknown position that serious,
X`009`009`009just set MT$M_LOST bit.
X`009fix 19-sep-1989 wjm: properly set/clear MT$M_LOST in ZT's iosb
X`009mod 28-dec-1990 wjm: VMS V5.4 *always* does end-of-volume recognition,
X`009`009`009`009no longer dependent upon FOREIGN MOUNT.
X`009`009`009     Old behaviour now only with PRE_V54 defined.
X`009fix 14-jan-1991 wjm: fix(?) file count returned when reverse
X`009`009`009`009SKIPFILE hits BOT (required for 5.4 MTAAACP)
X*/
X
X#ifndef TRACE
X#define TRACE 1
X#endif
X
X#ifndef UNSAFE_AFTER_ERROR
X#define UNSAFE_AFTER_ERROR 0
X#endif
X
X#ifndef PRE_V54`009`009/* might be conditional on UCBDEF or IODEF;`009   */
X#define PRE_V54 0`009/* e.g. UCB$L_SHAD & IO$V_MOVEFILE are new in V5.4 */
X#endif
X
X#include "ztns.h"`009/* includes IOSB */
X
V/* NOTE: following ZT definitions must match ZTDEF.MAR & ZTSERVER.MAR *******
X**/
X
Xtypedef struct ZTmsg `123
X`009IOSB iosb;`009/* i.e. status, count, devdep */
X`009long record;
X`009unsigned short ucbsts;
X`009unsigned short fill1;
X`009unsigned long devchar;
X`009unsigned short func;
X`009unsigned short bcnt;
X`009union `123
X`009`009short w[4];
X`009`009unsigned short uw[4];
X`009`009unsigned long ul[2];
X`009`125 media;
X`125 ZTmsg;
Xglobalref struct `123
X`009unsigned short l;
X`009unsigned short fill1;
X`009ZTmsg *p;
X`125 ZT_MSGDSC;
X
Xglobalref struct `123
X`009unsigned long bct;
X`009unsigned char *addr;
X`125 ZT_BUFDSC;
X
Xextern unsigned ZT_INIT(),ZT_WAIT(),ZT_TOUSER(),ZT_FRUSER(),ZT_REQCOM();
X
V/******* end of ZT definitions **********************************************
X**/
X
X
X#include ssdef
X#include lnmdef
X
X#include "mtdef.h"
X#include "iodef.h"`009/* my own! */
X#include "ucbdef.h"`009/* note VMS version dependency */
X#if PRE_V54
X#include devdef
X#endif
X
X#include stdio
X#include stddef
X#include string
X#include descrip
Xtypedef struct dsc$descriptor DESCR;
X
Xtypedef struct VMS_ITEM `123
X`009unsigned short size;
X`009unsigned short code;
X`009void *bufp;
X`009int *lenp;
X`125 VMS_ITEM;
X
X#define CHECK(x) do `123unsigned s=x; if(!(s&1)) lib$stop(s);`125 while(0)
X#define FEHLER(m) do `123$DESCRIPTOR(d,m); Fehler(&d);`125 while(0)
X#define MIN(a,b) ((a) < (b)) ? (a) : (b)
X
Xextern void lib$stop();
Xextern unsigned sys$assign(),sys$trnlnm();
Xextern unsigned sys$qiow(int,int,int,
X`009`009`009IOSB*,void*,int,
X`009`009`009void*,int,int,int,int,int);
X
X
Xstatic void ns_init(void);`009/* forward */
Xstatic void ns_req(int,int);`009/* forward */
Xstatic IOSB ns_iosb;
X
Xstatic unsigned char *bufp;
Xstatic unsigned long *bufbctp;
X
Xstatic ZTmsg *msgp;
X
Xstatic unsigned short fcode;
Xstatic unsigned short fmodif;
X
Xstatic enum `123no,yes,dunno`125 aftertm;`009/* tape positioned after mark? -
X`009`009`009`009`009shortcut to save tape movement */
X
Xstatic int/*logical*/ pos_unsafe;`009/* set after (hard) error,
X`009`009`009`009`009/* #if UNSAFE_AFTER_ERROR:
X`009`009`009`009`009/*     inhibits all operations
X`009`009`009`009`009/*     that move the tape forward,
X`009`009`009`009`009/*     since UCB$L_RECORD may be wrong*/
X
X/*****/
X
Xstatic void do_init()
X`123
X`009ns_init();`009/* must set up  ns_iosb.devdep */
X
X`009aftertm = (ns_iosb.devdep & MT$M_BOT) ? no: dunno;
X`009pos_unsafe = !(ns_iosb.devdep & MT$M_BOT);
X`125
X
X
Xstatic void do_nop()
X`123
X`009/* all modifiers ignored */
X
X`009/* give 'ns' a chance to update 'devdep' */
X`009ns_req(IO$_SKIPRECORD,0);`009/* skip 0 blocks */
X`009if((ns_iosb.status & 1) `124`124
X`009   (ns_iosb.status == SS$_ENDOFTAPE) `124`124
X`009   (ns_iosb.status == SS$_BEGOFTAPE)) `123
X`009`009`009/* o.k. */
X`009`125 else `123
X`009`009pos_unsafe = 1;
X`009`125
X`009/* 'aftertm' did not change, I hope ... */
X`125
X
X
Xstatic void do_rewind(int unload)
X`123
X`009/* fmodif: IO$M_NOWAIT, others ignored */
X`009unsigned short nsfct;
X
X
X`009if(unload) `123
X`009`009nsfct = IO$_REWINDOFF;
X`009`125 else `123
X`009`009nsfct = IO$_REWIND;
X`009`125
X`009nsfct `124= (fmodif & IO$M_NOWAIT);
X`009ns_req(nsfct,0);
X`009
X`009msgp->record = 0;`009/* always */
X`009aftertm = no;
X
X`009if((ns_iosb.status & 1) `124`124
X`009   (ns_iosb.status == SS$_BEGOFTAPE)) `123
X`009`009/* o.k. */
X`009`125 else `123
X`009`009pos_unsafe = 1;
X`009`125
X
X#if 0`009/* this works together with a VMS V.5 addition:
X`009   if tape is mounted foreign & MT$M_ENAUTOPACK is set,
X`009   then set UCB$M_VALID on "medium online" interrupt */
X`009/*...................................................*/
X`009if(!hw_medonline) `123
X`009`009msgp->ucbsts &= `126UCB$M_VALID;
X`009`125
X#endif`009/*...................................................*/
X`125
X
X
Xstatic unsigned set_aftertm()`009/* ggf. find out if tape is positioned
X`009`009`009`009`009after a tape mark */
X`123
X`009if(aftertm != dunno) return SS$_NORMAL;`009/* nothing to be done */
X
X`009ns_req(IO$_SKIPRECORD,-1);
X`009msgp->record -= ns_iosb.count;
X`009if(ns_iosb.count != 1) `123
X`009`009if((ns_iosb.devdep & MT$M_BOT) == 0) `123
X`009`009`009pos_unsafe = 1;
X`009`009`009return SS$_TAPEPOSLOST;
X`009`009`125 else `123
X`009`009`009pos_unsafe = 0;`009/* we're at BOT! */
X`009`009`009aftertm = no;
X`009`009`009return SS$_NORMAL;
X`009`009`125
X`009`125
X`009aftertm = (ns_iosb.status == SS$_ENDOFFILE) ? yes : no;
X
X`009ns_req(IO$_SKIPRECORD,1);
X`009msgp->record += ns_iosb.count;
X`009if(ns_iosb.count != 1) `123
X`009`009pos_unsafe = 1;
X`009`009return SS$_TAPEPOSLOST;
X`009`125
X`009return SS$_NORMAL;
X`125
X
Xstatic void`009/* "end of volume" recognized */
Vset_eov(sca)`009/* backspace over 2nd eof mark, decrement spacing count etc.
X */
Xint sca;`009`009/* spacing count so far (>0) */
X`123
X`009ns_req(IO$_SKIPRECORD,-1);
X`009if(ns_iosb.count == 1 && ns_iosb.status == SS$_ENDOFFILE) `123 /* o.k. */
X`009`009msgp->record --;
X`009`009ns_iosb.status = SS$_ENDOFVOLUME;
X`009`009/* aftertm remains == yes */
X`009`125 else `123
X`009`009pos_unsafe = 1;
X`009`009ns_iosb.status = SS$_TAPEPOSLOST;
X`009`009aftertm = dunno;
X`009`125
X`009ns_iosb.count = sca - 1;`009/* final count */
X`125
X
X
Xstatic void do_skiprec()
X`123
-+-+-+-+-+ End of part 2 +-+-+-+-+-
