+-+-+-+ Beginning of part 2 +-+-+-+ 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`009if(argc > 2) `123 X`009`009do_init(argv[2]); X`009`125 else `123 X`009`009do_init(NULL); X`009`125 X`009if(argc > 1 && strlen(argv[1]) > 0) `123 X`009`009DESCR ztdsc = `123strlen(argv[1]),0,0,argv[1]`125; X X`009`009CHECK(ZT_INIT(&ztdsc)); X`009`125 else `123 X`009`009CHECK(ZT_INIT()); X`009`125 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 = "ZT1D.C" $ CHECKSUM_IS = 706038384 $ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY X/*`009ZT1 'tape' routines using a disk file and "unix I/O" ... X`009w.j.m. feb 1994, after ZT1T (ZT1 assumed to pass filename to tape_init) X*/ X X#ifndef TRACE X#define TRACE 1 X#endif X X#include ssdef X X#include stdio X#include stdlib X#include string X#include errno X X#include unixio X#include file X X#include descrip Xtypedef struct dsc$descriptor DESCR; X Xextern void LIB$STOP(),Fehler(); 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 int *bufbctp; X Xextern int /*logical*/ hw_online,hw_medonline,hw_bot,hw_eof,hw_eot,hw_hwl; X X/* forward */ Xvoid tape_init(char * /*disk file name*/); 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/* 'disk tape' structure (STREAM-LF file assumed): X *`009int l0; char [l0]; int l0; int l1; char [l1]; int l1; ... X *`009`009l=0 stands for end of written area, X *`009`009l=1 stands for tape mark X * "int" is to mean INTEGER*4 X * X * This is compatible with a unix [little-endian] FORTRAN BINARY file X * (checked for ULTRIX & DEC OSF/1). X * X * the very first "record" always contains the fixed string "ZT1 " X * X * NOTE: I/O errors considered fatal. X * NOTE: no EOT handling (yet)! X */ X X#define T_MAXBLOCK 0xFFFF X X`009/* room for tape block & 2 length fields */ Xstatic unsigned char tbuf[4 + 4 + T_MAXBLOCK]; X`009/* current byte offset in file (point between 'prev' & 'next' record) */ Xstatic int tp; X`009/* file descriptor */ Xstatic int tfd; X`009/* read-only flag */ Xstatic int/*logical*/ t_ro; X X#define T_EOM 0 X#define T_MARK 1 X Xstatic const struct T_magic `123 X`009int l0_1; X`009char magic[4]; X`009int l0_2; X`125 t_magic = `123 4, `123'Z', 'T', '1', ' '`125, 4`125; X Xstatic int t_nextlen,t_prevlen; X X#define T_nextlen t_nextlen X#define T_prevlen t_prevlen X#define T_data tbuf`009`009`009/* tape block from TOP_read() */ X X#define T_prevpos (tp - (T_prevlen + 8)) X#define T_nextpos (tp + (T_nextlen + 8)) X X#define T_bot (tp == sizeof(t_magic)) X#define T_eom (T_nextlen == T_EOM) X#define T_eot 0`009`009`009`009/* always false for now */ X X#define I4(bp) (*((int *)(bp))) X X#define T_abort() do `123\ X`009fprintf(stderr,"Aborting ...\n");\ X`009abort();\ X`125 while(0) X X#define T_checklen(i) do `123\ X`009if(i < 0 `124`124 i > T_MAXBLOCK) `123\ X`009`009fprintf(stderr,"Bad block length: %d\n",i);\ X`009`009T_abort();\ X`009`125\ X`125 while(0) X X/*****/ X Xstatic long diskpos;`009`009/* current file position (byte offset) */ Xstatic int diskeof = -1;`009/* new EOF position to be set, or -1 */ X X Xstatic void disk_seek(int p) X`123 X#if 1 X`009`123 X`009`009static void disk_write();`009/*forward*/ X`009`009static int teom = T_EOM; X X`009`009if(diskeof > 0 && p < diskeof) `123 X`009`009`009disk_write(diskeof,4,(unsigned char *)&teom); X`009`009`009diskeof = -1; X`009`009`125 X`009`125 X#endif X`009diskpos = p; X`009if(lseek(tfd,diskpos,SEEK_SET) < 0) `123 X`009`009perror("lseek"); X`009`009T_abort(); X`009`125 X`125 X Xstatic void disk_truncate(int p) X`123 X#if 0 X`009if(p != diskpos) disk_seek(p); X#endif X`009diskeof = p; X`125 X Xstatic void disk_write(int p, int l, unsigned char *b) X`123 X`009int k; X`009int ll = l; X`009unsigned char *bb = b; X X X`009if(p != diskpos) disk_seek(p); X X`009while(ll > 0) `123 X`009`009if((k = write(tfd,bb,ll)) < 0) `123 X`009`009`009perror("write"); X`009`009`009T_abort(); X`009`009`125 X`009`009ll -= k; X`009`009bb += k; X`009`125 X`009diskpos = diskeof = p + l; X`125 X Vstatic void disk_read(int p, int l, unsigned char *b)`009/* ggf. fill in T_EO XM */ X`123 X`009int k; X`009int ll = l; X`009unsigned char *bb = b; X X X`009if(p != diskpos) disk_seek(p); X X`009while(ll > 0) `123 X`009`009k = read(tfd,bb,ll); X`009`009if(k < 0) `123 X`009`009`009perror("read"); X`009`009`009T_abort(); X`009`009`125 X`009`009if(k == 0) `123`009`009`009/* EOF */ X`009`009`009if(ll == 4) `123`009`009/* 4 bytes remain => ok */ X`009`009`009`009*((int *)bb) = T_EOM;`009/* provide sentinel */ X`009`009`009`009diskpos = p + (l - 4); X`009`009`009`009return;`009`009`009/* success */ X`009`009`009`125 else `123 X`009`009`009`009fprintf(stderr,"read() EOF at %d\n",p + l - ll); X`009`009`009`009T_abort(); X`009`009`009`125 X`009`009`125 else `123 X`009`009`009ll -= k; X`009`009`009bb += k; X`009`009`125 X`009`125 X X`009diskpos = p + l; X`125 X`009 X/*****/ X Xstatic void TOP_rewind()`009/* permitted to occur at BOT, verify magic */ X`123 X`009if(T_bot) return; X X`009tp = sizeof(t_magic); X`009disk_read(0,sizeof(t_magic) + 4,tbuf); X`009T_nextlen = I4(tbuf + sizeof(t_magic)); X`009T_checklen(T_nextlen); X`009if(memcmp(&t_magic,tbuf,sizeof(t_magic))) T_abort(); X X`009T_prevlen = T_EOM; X`125 X Xstatic void TOP_bsr()`009`009/* must not occur at BOT */ X`123 X`009tp = T_prevpos; X`009if(T_bot) `123 X`009`009int oldprevlen = T_prevlen; X X`009`009TOP_rewind(); X`009`009if(T_nextlen != oldprevlen) T_abort(); X`009`125 else `123 X`009`009disk_read(tp - 4,2*4,tbuf); X`009`009if(I4(tbuf + 4) != T_prevlen) T_abort(); X`009`009T_nextlen = T_prevlen; X`009`009T_prevlen = I4(tbuf); X`009`009T_checklen(T_prevlen); X`009`125 X`125 X Xstatic void TOP_fsr()`009`009/* must not occur at EOM */ X`123 X`009tp = T_nextpos; X`009disk_read(tp - 4,2*4,tbuf); X`009if(I4(tbuf) != T_nextlen) T_abort(); X`009T_prevlen = T_nextlen; X`009T_nextlen = I4(tbuf + 4); X`009T_checklen(T_nextlen); X`125 X Xstatic void TOP_read()`009`009/* must not occur at EOM */ X`123 X`009disk_read(tp + 4,T_nextlen + 2*4,tbuf); X `009tp = T_nextpos; X`009if(I4(tbuf + T_nextlen) != T_nextlen) T_abort(); X`009T_prevlen = T_nextlen; X`009T_nextlen = I4(tbuf + T_nextlen + 4); X`009T_checklen(T_nextlen); X`125 X Vstatic void TOP_write(int l, unsigned char *b)`009/* also used for writemark X */ X`123 X`009T_checklen(l); X X`009if(!T_eom) disk_truncate(tp); X X`009T_nextlen = l; X`009disk_write(tp,4,(unsigned char *)&T_nextlen); X`009disk_write(tp + 4,T_nextlen,b); X`009disk_write(tp + 4 + T_nextlen,4,(unsigned char *)&T_nextlen); X`009tp = T_nextpos; X X`009T_prevlen = l; X`009T_nextlen = T_EOM; X`125 X`009`009 X/*****/ X Xvoid tape_init(char *fn) X`123 X`009char *mp; X`009char fnbuf[256]; X X X`009diskpos = 0; X X`009if(!fn) fn = "ZT_DISK_TAPE";`009/* could be a logical name */ X X`009fprintf(stderr,"Going to open %s ...\n",fn); X#if 0 X`009if((tfd = open(fn,O_RDWR,0,"ctx=stm","mbc=16")) >= 0) `123 X#else X`009if((tfd = open(fn,O_RDWR,0)) >= 0) `123 X#endif X`009`009mp = "opened r/w"; X`009`009t_ro = 0; X#if 0 X`009`125 else if((tfd = open(fn,O_RDONLY,0,"ctx=stm","mbc=16")) >= 0) `123 X#else X`009`125 else if((tfd = open(fn,O_RDONLY,0)) >= 0) `123 X#endif X`009`009mp = "opened r/o"; X`009`009t_ro = 1; X#if 0 X`009`125 else if((tfd = creat(fn,0,"ctx=stm","mbc=16")) >= 0) `123 X#else X`009`125 else if((tfd = creat(fn,0)) >= 0) `123 X#endif X`009`009mp = "created"; X`009`009t_ro = 0; X`009`009disk_write(0,sizeof(t_magic),(unsigned char *)&t_magic); X`009`125 else `123 X`009`009perror("open/creat"); X`009`009T_abort(); X`009`125 X`009fprintf(stderr,"File %s %s\n",getname(tfd,fnbuf),mp); X X`009TOP_rewind(); X X#if TRACE X`009tpos = 0; X#endif X X`009hw_online = 1; X`009hw_medonline = 1; X`009hw_hwl = t_ro; X X`009hw_eof = 0; X`009hw_bot = T_bot; X`009hw_eot = T_eot; X`125 X X/*****/ 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`009if(hw_hwl) return SS$_WRITLCK; X X`009TOP_write(T_MARK,(unsigned char *)"\026"); 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`009TOP_rewind(); 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_eom) `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`009TOP_fsr(); 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`009TOP_bsr(); 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_eom) `123 X`009`009xstat = SS$_TAPEPOSLOST; X`009`125 else `123 X`009`009TOP_read(); X`009`009hw_eof = (T_prevlen == 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_prevlen `124`124 X`009`009`009 memcmp(T_data,bufp,T_prevlen)) `123 X`009`009`009`009xstat = SS$_DATACHECK; X`009`009`009`125 X`009`009`009*bufbctp = T_prevlen; X`009`009`125 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_eom) return SS$_TAPEPOSLOST; X X`009TOP_read(); X`009hw_eof = (T_prevlen == T_MARK); X`009if(hw_eof) `123 X`009`009*bufbctp = 0; X`009`125 else `123 X`009`009*bufbctp = T_prevlen; X`009`009memcpy(bufp,T_data,T_prevlen); X`009`125 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`009if(hw_hwl) return SS$_WRITLCK; X X`009TOP_write(*bufbctp,bufp); 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 = "ZT1T.C" $ CHECKSUM_IS = 58552466 $ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY X/*`009memory-'tape' routines for first test of ZTDRIVER ... X`009w.j.m. jun 1989 X`009mod 22-oct-1993 wjm: (AXP) replace 'long' by 'int' 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 int *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); -+-+-+-+-+ End of part 2 +-+-+-+-+-