+-+-+-+ Beginning of part 3 +-+-+-+ 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 = 340279102 $ 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`009mod 22-oct-1993 wjm: (AXP) split off "zt.h", replace 'long' by 'int' ... 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 X/* ZT definitions (must match ZTDEF.MAR & ZTSERVER.MAR) */ X#include "zt.h" 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`009unsigned short *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 int *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 X`009/* all modifiers ignored */ X`009int sc; X X X`009sc = msgp->media.w[0]; X X`009if(sc == 0) `123 X`009`009do_nop(); X`009`009return; X 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 X#if UNSAFE_AFTER_ERROR X`009`009if(pos_unsafe) return; X#endif 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`009if((set_aftertm() & 1) == 0) `123 X`009`009`009`009ns_iosb.status = SS$_TAPEPOSLOST; X`009`009`009`009ns_iosb.count = 0; X`009`009`009`009pos_unsafe = 1; X`009`009`009`009return; X`009`009`009`125 X#if PRE_V54 X`009`009`125 X#endif X X`009`009ns_req(IO$_SKIPRECORD,sc); X`009`009msgp->record += ns_iosb.count; X X`009`009if((ns_iosb.status & 1) `124`124 X`009`009 ns_iosb.status == SS$_ENDOFTAPE) `123 X`009`009`009aftertm = no; X`009`009`125 else if(ns_iosb.status == SS$_ENDOFFILE) `123 X`009`009`009aftertm = yes; X`009`009`009if( X#if PRE_V54 X`009`009`009 no_acp &&`032 X#endif X`009`009`009`009 (ns_iosb.count == 1)) `123 X`009`009`009`009/* "end of volume recognition" */ X`009`009`009`009set_eov(1); X`009`009`009`125 X`009`009`125 else `123 X`009`009`009aftertm = dunno; X`009`009`009pos_unsafe = 1; X`009`009`125 X X`009`125 else `123`009`009`009`009`009`009/* BACKWARD */ X`009`009ns_req(IO$_SKIPRECORD,sc); X`009`009msgp->record -= ns_iosb.count; X X`009`009aftertm = dunno; X`009`009if(ns_iosb.status == SS$_ENDOFFILE) `123 X`009`009`009`009`009/* o.k. */ X`009`009`125 else if((ns_iosb.status & 1) `124`124 X`009`009`009 ns_iosb.status == SS$_BEGOFTAPE) `123 X`009`009`009if(sc + ns_iosb.count == 0) `123 X`009`009`009`009`009/* o.k. */ X`009`009`009 ns_iosb.status = SS$_NORMAL; X`009`009`009`125 else `123 X`009`009`009`009if(ns_iosb.devdep & MT$M_BOT) `123 X`009`009`009`009`009/* terminated due to B.O.T. */ X`009`009`009`009`009ns_iosb.status = SS$_BEGOFTAPE; X`009`009`009`009`125 else `123 X`009`009`009`009`009/* must not happen! */ X`009`009`009`009`009/* ??? */ X`009`009`009`009`125 X`009`009`009`125 X`009`009`125 else `123`009`009/* error */ X`009`009`009pos_unsafe = 1; X`009`009`125 X`009`125 X`125 X X Xstatic void do_skipfile() X`123 X`009/* all modifiers ignored */ X`009int sc,sca; X`009 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 UNSAFE_AFTER_ERROR X`009`009if(pos_unsafe) return; X#endif 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`009if((set_aftertm() & 1) == 0) `123 X`009`009`009`009ns_iosb.status = SS$_TAPEPOSLOST; X`009`009`009`009pos_unsafe = 1; X`009`009`009`009return; X`009`009`009`125 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`009sca = 0; X`009`009do `123 X`009`009`009do `123 X`009`009`009`009ns_req(IO$_SKIPRECORD,0x7FFF); X`009`009`009`009msgp->record += ns_iosb.count; X`009`009`009`125 while((ns_iosb.status & 1) `124`124 X`009`009`009`009(ns_iosb.status == SS$_ENDOFTAPE)); X X`009`009`009if((ns_iosb.status == SS$_ENDOFFILE)) `123 X`009`009`009`009`009/* o.k. */ X`009`009`009`009sca ++; X`009`009`009`009sc --; X X#if PRE_V54 X`009`009`009`009if(no_acp) `123 X#endif X`009`009`009`009`009if(msgp->record == prevtm+1) `123 X`009`009`009`009`009`009aftertm = yes; X`009`009`009`009`009`009set_eov(sca); X`009`009`009`009`009`009return; X`009`009`009`009`009`125 else `123 X`009`009`009`009`009`009prevtm = msgp->record; X`009`009`009`009`009`125 X#if PRE_V54 X`009`009`009`009`125 X#endif X`009`009`009`125 X`009`009`125 while((sc > 0) && X`009`009`009(ns_iosb.status == SS$_ENDOFFILE)); X X`009`009if(ns_iosb.status == SS$_ENDOFFILE) `123 X`009`009`009`009/* o.k. */ X`009`009`009ns_iosb.status = SS$_NORMAL; X`009`009`125 else `123`009/* error */ X`009`009`009aftertm = dunno; X`009`009`009pos_unsafe = 1; X`009`009`125 X`009`009ns_iosb.count = sca; X X`009`125 else `123`009`009`009`009`009`009/* BACKWARD */ X`009`009`009/* NOTE: It is not clear what status is returned X`009`009`009/* on the attempt to skip backward over B.O.T. X`009`009`009/* We allow for both success and SS$_BEGOFTAPE, and X`009`009`009/* we do return SS$_BEGOFTAPE on skip beyond B.O.T. */ X`009`009int scb;`009/* count of blocks skipped w/i file */ X X`009`009aftertm = dunno; X`009`009sca = 0; X`009`009do `123 X`009`009`009scb = 0; X`009`009`009do `123 X`009`009`009`009ns_req(IO$_SKIPRECORD,-0x7FFF); X`009`009`009`009msgp->record -= ns_iosb.count; X`009`009`009`009scb += ns_iosb.count; X`009`009`009`125 while((ns_iosb.status & 1) && X`009`009`009`009(ns_iosb.count > 0)); X X`009`009`009if((scb > 0) &&`009`009/* anything skipped ? */ X`009`009`009 ((ns_iosb.status & 1) `124`124 X`009`009`009 (ns_iosb.status == SS$_ENDOFFILE) `124`124 X`009`009`009 (ns_iosb.status == SS$_BEGOFTAPE))) `123 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`009`009sca ++; X#else X`009`009`009`009if(!(ns_iosb.devdep & MT$M_BOT)) sca ++; X`009`009`009`009/** don't count BOT (from TMDRIVER) **/ X#endif X`009`009`009`009sc ++; X`009`009`009`125 X`009`009`125 while((sc < 0) && X`009`009`009(scb > 0) &&`009/* stop if nothing was skipped */ X`009`009`009((ns_iosb.status & 1) `124`124 X`009`009`009 (ns_iosb.status == SS$_ENDOFFILE))); X X`009`009if(ns_iosb.status == SS$_ENDOFFILE) `123 X`009`009`009`009`009/* all files skipped */ X`009`009`009ns_iosb.status = SS$_NORMAL; X`009`009`125 else if((ns_iosb.status & 1) `124`124 X`009`009`009 (ns_iosb.status == SS$_BEGOFTAPE)) `123 X`009`009`009if(sc == 0) `123`009/* all files skipped */ X`009`009`009`009ns_iosb.status = SS$_NORMAL; X`009`009`009`125 else if(ns_iosb.devdep & MT$M_BOT) `123 X`009`009`009`009`009/* stopped due to BOT */ X`009`009`009`009ns_iosb.status = SS$_BEGOFTAPE; X`009`009`009`125 else `123 X`009`009`009`009`009/* must not happen! */ X`009`009`009`009`009/* ??? */ X`009`009`009`125 X`009`009`125 else `123`009`009/* error */ X`009`009`009ns_iosb.status = SS$_TAPEPOSLOST; X`009`009`009pos_unsafe = 1; X`009`009`125 X`009`009ns_iosb.count = sca; X`009`125 X`125 X X Xstatic void do_writecheck() X`123 X`009/* modifiers: IO$M_REVERSE rejected, others ignored */ X X X`009if((fmodif & IO$M_REVERSE) != 0) `123`009/* not supported so far */ X`009`009ns_iosb.status = SS$_BADPARAM; X`009`009return; X`009`125 X X#if UNSAFE_AFTER_ERROR X`009if(pos_unsafe) return; X#endif X X`009CHECK(ZT_FRUSER()); X X`009ns_req(IO$_WRITECHECK,msgp->bcnt); X`009if((ns_iosb.status & 1) `124`124 X`009 (ns_iosb.status == SS$_DATAOVERUN) `124`124 X`009 (ns_iosb.status == SS$_ENDOFFILE) `124`124 X`009 (ns_iosb.status == SS$_DATACHECK)) `123 X`009`009`009`009/* tape moved */ X`009`009msgp->record ++; X`009`009aftertm = (ns_iosb.status == SS$_ENDOFFILE) ? yes : no; X`009`125 else `123 X`009`009`009`009/* tape may have moved */ X`009`009pos_unsafe = 1; X`009`009/* msgp->record ++; /* better don't count it */ X`009`009aftertm = dunno; X`009`125 X`125 X X Xstatic void do_read() X`123 X`009/* modifiers: IO$M_REVERSE rejected, X`009`009`009IO$M_DATACHECK o.k., X`009`009`009others ignores */ X X`009if((fmodif & IO$M_REVERSE) != 0) `123`009/* not supported so far */ X`009`009ns_iosb.status = SS$_BADPARAM; X`009`009return; X`009`125 X X#if UNSAFE_AFTER_ERROR X`009if(pos_unsafe) return; X#endif X X`009ns_req(IO$_READLBLK `124 (fmodif & IO$M_DATACHECK),msgp->bcnt); X`009if((ns_iosb.status & 1) `124`124 X`009 (ns_iosb.status == SS$_DATAOVERUN) `124`124 X`009 (ns_iosb.status == SS$_ENDOFFILE)) `123 X`009`009`009`009/* tape moved */ X`009`009msgp->record ++; X`009`009aftertm = (ns_iosb.status == SS$_ENDOFFILE) ? yes : no; X`009`125 else `123 X`009`009`009`009/* tape may have moved */ X`009`009pos_unsafe = 1; X`009`009/* msgp->record ++; /* better don't count it */ X`009`009aftertm = dunno; X`009`125 X X`009*bufbctp = MIN(ns_iosb.count,msgp->bcnt); X`009CHECK(ZT_TOUSER()); X`125 X`009`009 Xstatic void do_writemark() X`123 X`009/* all modifiers ignored */ X X#if UNSAFE_AFTER_ERROR X`009if(pos_unsafe) return; X#endif X X`009ns_req(IO$_WRITEOF,0); X`009if((ns_iosb.status & 1) `124`124 X`009 ns_iosb.status == SS$_ENDOFTAPE) `123 X`009`009msgp->record ++; X`009`009aftertm = yes; X`009`125 else `123 X`009`009/* assume NO tape movement */ X`009`009pos_unsafe = 1; X`009`009aftertm = dunno; X`009`125 X`125 X X Xstatic void do_write() X`123 X`009/* modifiers: IO$M_DATACHECK o.k., others ignored X`009`009(in particular mysterious IO$M_ERASE flag, X`009`009`009and IO$M_NOWAIT ("TU81plus only")) */ X X X#if UNSAFE_AFTER_ERROR X`009if(pos_unsafe) return; X#endif X X`009CHECK(ZT_FRUSER()); X X`009ns_req(IO$_WRITELBLK `124 (fmodif & IO$M_DATACHECK),msgp->bcnt); X`009if((ns_iosb.status & 1) `124`124 X`009 (ns_iosb.status == SS$_ENDOFTAPE)) `123 X`009`009`009/* tape moved */ X`009`009msgp->record ++; X`009`009aftertm = no; X`009`125 else `123 X`009`009`009/* assume NO tape movement */ X`009`009pos_unsafe = 1; X`009`009aftertm = dunno; 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`009/* set defaults */ X`009ns_iosb.count = 0; X`009ns_iosb.status = SS$_UNSAFE; X 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((ns_iosb.status & 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`009ns_iosb.status = SS$_ILLIOFUNC; X`009`009break; X`009`125 X X/* final processing: X`009must copy status & count from ns_iosb to msgp->iosb, X`009`009`009also 5 devdepend bits X`009record`009`009- has been updated (if changed) X`009ucbsts`009`009- v_valid has been modified (if changed) X*/ X X`009/* fake 'LOST' BIT */ X`009if(pos_unsafe `124`124 ns_iosb.status == SS$_TAPEPOSLOST) `123 X`009`009ns_iosb.devdep `124= MT$M_LOST; X`009`125 X X`009if(ns_iosb.devdep & MT$M_BOT) `123`009`009`009/* at "BOT" */ X`009`009ns_iosb.devdep &= `126MT$M_LOST;`009`009/* clear pos. lost */ X`009`009aftertm = no; X`009`009pos_unsafe = 0; X`009`125 X X`009msgp->iosts = ns_iosb.status; X`009msgp->iobct = ns_iosb.count; X`009`123 V`009`009unsigned mask = MT$M_BOT `124 MT$M_EOF `124 MT$M_EOT `124 MT$M_HWL `1 X24 X`009`009`009`009MT$M_LOST; X X`009`009msgp->devdepend = (msgp->devdepend & (`126mask)) `124 X`009`009`009`009 (ns_iosb.devdep & mask); 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(1); 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," iocnt=%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 */ X X X/*****/ X Xstatic short n_chan; Xstatic IOSB n_iosb; X Xstatic int ni_seq = 1; Xstatic int no_seq = 1; X Xstatic ZTNS_MSG n_buf; X X Xstatic void ns_init(void) X`123 X`009char ncb[512]; X`009DESCR ncb_dsc = `1230-0,0,0,ncb`125; X X X/* translate SYS$NET */ X X`009`123 X`009`009$DESCRIPTOR(lnmtabdsc,"LNM$FILE_DEV"); X`009`009$DESCRIPTOR(lognamedsc,"SYS$NET"); X`009`009VMS_ITEM lnmlist[] = X`009`009`009`123`123sizeof(ncb),LNM$_STRING,ncb,&ncb_dsc.dsc$w_length`125, X`009`009`009 `1230,0,NULL,NULL`125`125; X X`009`009CHECK(sys$trnlnm(0,&lnmtabdsc,&lognamedsc,0,lnmlist)); X`009`125 X X/* assign channel to NET */ X X`009`123 X`009`009$DESCRIPTOR(netdsc,"_NET:"); X X`009`009CHECK(sys$assign(&netdsc,&n_chan,0,0)); X`009`125 X X/* accept connection */ X X`009CHECK(sys$qiow(0,n_chan,IO$_ACCESS, X`009`009`009&n_iosb,0,0, X`009`009`0090,(int) (&ncb_dsc),0,0,0,0)); X`009CHECK(n_iosb.status); X X/* setup initial DEVDEPEND */ X X`009ns_iosb.devdep = MT$M_BOT; X`125 X X Xstatic void ns_req(int iofct,int ct) X`123 X`009int dmafct = 0; X`009unsigned dmasts; X`009int datacnt = 0; X`009unsigned char *datap = NULL; X X X/* send IOREQ */ X X`009n_buf.seq = no_seq++; X`009n_buf.func = ZTNS_F_IOREQ; X`009n_buf.count = ct; X`009n_buf.iofunc = iofct; X X`009CHECK(sys$qiow(0,n_chan,IO$_WRITEVBLK, X`009`009&n_iosb,0,0, X`009`009&n_buf,ZTNS_LEN1,0,0,0,0)); X`009CHECK(n_iosb.status); X X/* read msgs, till IOREPLY */ X X while(1) `123 X`009CHECK(sys$qiow(0,n_chan,IO$_READVBLK, X`009`009&n_iosb,0,0, X`009`009&n_buf,sizeof(n_buf),0,0,0,0)); X`009CHECK(n_iosb.status); X X/* check seq# */ X`009if(n_buf.seq != ni_seq++) FEHLER("prot.error: iseq"); X X/* check minimum length */ X`009if(n_iosb.count < ZTNS_LEN1) FEHLER("prot.error: msg too short"); X X/* process low level function */ X`009switch(n_buf.func) `123 X`009 default: X`009`009FEHLER("prot.error: bad func1"); X`009`009return; X X`009 case ZTNS_F_IOREPLY: X`009`009if(datap != NULL) `123 X`009`009`009FEHLER("prot.error: unexpected IOREPLY"); X`009`009`125 X`009`009ns_iosb = n_buf.iosb; X`009`009return; X X`009 case ZTNS_F_R_DATA: X`009`009if(datap != NULL) `123 X`009`009`009FEHLER("prot.error: unexpected R_DATA command"); X`009`009`125 X`009`009*bufbctp = datacnt = (n_buf.count & 0xFFFF); X`009`009datap = bufp; X`009`009dmafct = n_buf.func; X`009`009dmasts = SS$_NORMAL; X`009`009break; X X`009 case ZTNS_F_C_DATA: X`009`009if(datap != NULL) `123 X`009`009`009FEHLER("prot.error: unexpected C_DATA command"); X`009`009`125 X`009`009datacnt = (n_buf.count & 0xFFFF); X`009`009if(*bufbctp < datacnt) `123 X`009`009`009FEHLER("prot.error: C_DATA count too big"); X`009`009`125 X`009`009datap = bufp; X`009`009dmafct = n_buf.func; X`009`009dmasts = SS$_NORMAL; X`009`009break; X X`009 case ZTNS_F_W_DATA: X`009`009if(datap != NULL) `123 X`009`009`009FEHLER("prot.error: unexpected W_DATA command"); X`009`009`125 X`009`009datacnt = (n_buf.count & 0xFFFF); X`009`009if(datacnt <= 0) FEHLER("prot.error: DATA count .le.0"); X`009`009if(*bufbctp < datacnt) `123 X`009`009`009FEHLER("prot.error: W_DATA count too big"); X`009`009`125 X`009`009datap = bufp; X X`009`009/* send data */ X`009`009do `123 X`009`009`009int c; X X`009`009`009n_buf.seq = no_seq++; X`009`009`009n_buf.func = ZTNS_F_DATA; X`009`009`009n_buf.count = c = MIN(datacnt,ZTNS_DATALEN); X`009`009`009datacnt -= c; X`009`009`009memcpy(n_buf.data,datap,c); X`009`009`009datap += c; X X`009`009`009CHECK(sys$qiow(0,n_chan,IO$_WRITEVBLK, X`009`009`009`009&n_iosb,0,0, X`009`009`009`009&n_buf,c + ZTNS_LEN1,0,0,0,0)); X`009`009`009CHECK(n_iosb.status); X`009`009`125 while(datacnt > 0); X X`009`009datap = NULL; X`009`009break; X X`009 case ZTNS_F_DATA: X`009`009if(datap == NULL) `123 X`009`009`009FEHLER("prot.error: unexpected DATA"); X`009`009`125 X`009`009if(n_iosb.count != ZTNS_LEN1 + n_buf.count) `123 X`009`009`009FEHLER("prot.error: bad DATA msg length"); X`009`009`125 X`009`009if(n_buf.count > datacnt) `123 X`009`009`009FEHLER("prot.error: too much data"); X`009`009`125 X X`009`009switch(dmafct) `123 X`009`009 case ZTNS_F_R_DATA: X`009`009`009memcpy(datap,n_buf.data,n_buf.count); -+-+-+-+-+ End of part 3 +-+-+-+-+-