amiga-request@abcfd20.larc.nasa.gov (Amiga Sources/Binaries Moderator) (10/05/90)
Submitted-by: <DrBob@cup.portal.com> Posting-number: Volume 90, Issue 262 Archive-name: devices/btntape-1.0/part01 BTNtape is a "Better Than Nothing" SCSI tape device handler. It provides flat-file access to a SCSI tape drive from application programs using simple DOS calls to Read() and Write(). It can also be used with the Amiga TAR utility for disk backups. Files may span multiple tape volumes and may start at any tape block. This handler requires a "SCSI-direct" compatible hard disk driver. It is known to work with a 3-M MCD-40 tape drive on the CBM 2091 controller, the CBM 2090A with an ST506 hard drive, and the Supra 4x4, and may also work with others (refer to the docs). Included is a monitoring program which prints useful information about handler activities, including error sense data. Includes ANSI C source code. #!/bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of archive 1 (of 2)." # Contents: MakeFile formattape lmkfile mountlist pktstuff.c # sense.codes tape-handle.uu tape.c tape.h tapeio.c tapemon # tapemon/tapemon.c tapemon/tapemon.doc tapemon/tapemon.lmk # tapemon/tapemon.uu tplink.h # Wrapped by tadguy@abcfd20 on Thu Oct 4 19:41:24 1990 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'MakeFile' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'MakeFile'\" else echo shar: Extracting \"'MakeFile'\" \(192 characters\) sed "s/^X//" >'MakeFile' <<'END_OF_FILE' X# Aztec C makefile XOBJECT = tape.o tapeio.o pktstuff.o X Xtape-handler: $(OBJECT) X ln +Q -o tape-handler -w +a -g +s $(OBJECT) -lc X X$(OBJECT): tape.h X cc -m0b -so -sb -we -bs $*.c X X X X END_OF_FILE if test 192 -ne `wc -c <'MakeFile'`; then echo shar: \"'MakeFile'\" unpacked with wrong size! fi # end of 'MakeFile' fi if test -f 'formattape' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'formattape'\" else echo shar: Extracting \"'formattape'\" \(618 characters\) sed "s/^X//" >'formattape' <<'END_OF_FILE' X04 80 20 00 03 80 X XThis is the raw command string for formatting cartridges with a 3M MCD-40. XTo start a format operation, enter this from the CLI: X X type formattape to tape:$$RAWCMD$$ X XThe $$RAWCMD$$ must be in upper case. This file must be smaller than Xa tape block. Everything in the file after the first line is ignored. X XThe bytes have the following meanings: X Xbyte 0 = 04 = the SCSI Format_Unit command Xbyte 1 = 80 = immediate command execution Xbyte 2 = 20 = condition tape before format Xbyte 3 = 00 = reserved Xbyte 4 = 00 = interleave (00,02-07 are valid values) Xbyte 5 = 80 = no retries, 80 = retries X END_OF_FILE if test 618 -ne `wc -c <'formattape'`; then echo shar: \"'formattape'\" unpacked with wrong size! fi # end of 'formattape' fi if test -f 'lmkfile' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'lmkfile'\" else echo shar: Extracting \"'lmkfile'\" \(455 characters\) sed "s/^X//" >'lmkfile' <<'END_OF_FILE' X# LATTICE MAKEFILE FOR BTN-TAPE X X# Compile with -d to create the window version X#FLAGS= -v -y -b1 -mat -cakfsu -d XCFLAGS= -v -y -b1 -mat -cakfsu X XLIBS=LIB:lc.lib+LIB:amiga.lib X Xtape-handler: tape.o tapeio.o pktstuff.o X blink FROM tape.o+tapeio.o+pktstuff.o TO $@ SC SD LIB $(LIBS) X Xtape.o : tape.c tape.h tplink.h X LC $(CFLAGS) tape.c X Xtapeio.o : tapeio.c tape.h X LC $(CFLAGS) tapeio.c X Xpktstuff.o : pktstuff.c tape.h X LC $(CFLAGS) pktstuff.c X END_OF_FILE if test 455 -ne `wc -c <'lmkfile'`; then echo shar: \"'lmkfile'\" unpacked with wrong size! fi # end of 'lmkfile' fi if test -f 'mountlist' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'mountlist'\" else echo shar: Extracting \"'mountlist'\" \(222 characters\) sed "s/^X//" >'mountlist' <<'END_OF_FILE' XTAPE: Handler = L:tape-handler X Startup = "4/1/8192/1/0/yourscsi.device" /* change for yours! */ X Stacksize = 4000 X Priority = 5 X GlobVec = -1 X Mount = 1 /* optional */ X# END_OF_FILE if test 222 -ne `wc -c <'mountlist'`; then echo shar: \"'mountlist'\" unpacked with wrong size! fi # end of 'mountlist' fi if test -f 'pktstuff.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'pktstuff.c'\" else echo shar: Extracting \"'pktstuff.c'\" \(1768 characters\) sed "s/^X//" >'pktstuff.c' <<'END_OF_FILE' X/* misc.c - support routines - Phillip Lindsay (C) Commodore 1986 X * You may freely distribute this source and use it for Amiga Development - X * as long as the Copyright notice is left intact. X * X * 30-SEP-86 X */ X X#include <exec/types.h> X#include <exec/nodes.h> X#include <exec/lists.h> X#include <exec/ports.h> X#include <libraries/dos.h> X#include <libraries/dosextens.h> X#include "tape.h" X X#if defined AZTEC_C X #include <functions.h> X#elif defined LATTICE X #include <proto/exec.h> X#endif X X X/* returnpkt() - packet support routine X * here is the guy who sends the packet back to the sender... X * (I modeled this just like the BCPL routine [so its a little redundant] ) X */ X Xvoid returnpkt( X struct DosPacket *packet, X ULONG res1, X ULONG res2) X{ X struct Message *mess; X struct MsgPort *replyport; X struct Process *myproc; X X packet->dp_Res1 = res1; X packet->dp_Res2 = res2; X replyport = packet->dp_Port; X mess = packet->dp_Link; X myproc = (struct Process *) FindTask(0L); X packet->dp_Port = &myproc->pr_MsgPort; X mess->mn_Node.ln_Name = (char *) packet; X mess->mn_Node.ln_Succ = NULL; X mess->mn_Node.ln_Pred = NULL; X X PutMsg(replyport,mess); X} X X X/* X * taskwait() ... Waits for a message to arrive at your port and X * extracts the packet address which is returned to you. X */ X Xstruct DosPacket *taskwait(void) X{ X struct Process *myproc; X struct MsgPort *myport; X struct Message *mymess; X X myproc = (struct Process *) FindTask(0L); X myport = &myproc->pr_MsgPort; X X WaitPort(myport); /* wait for packet */ X mymess = (struct Message *) GetMsg(myport); X X/* give them the pointer to the packet */ Xreturn((struct DosPacket *) mymess->mn_Node.ln_Name); X} X X/* end of misc.c */ END_OF_FILE if test 1768 -ne `wc -c <'pktstuff.c'`; then echo shar: \"'pktstuff.c'\" unpacked with wrong size! fi # end of 'pktstuff.c' fi if test -f 'sense.codes' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'sense.codes'\" else echo shar: Extracting \"'sense.codes'\" \(1279 characters\) sed "s/^X//" >'sense.codes' <<'END_OF_FILE' X/* Extended Sense codes provided by the 3-M MCD-403 drive X X 1 - RECOVERED ERROR X X 2 - NOT READY X 04 Drive Not Ready X A7 Logical Load Failure X A8 Cartridge Autoloading X B0 No Cartridge in Drive X X 3 - MEDIUM ERROR X 10 ID CRC X 11 Unrecovered Read error of data blocks X 15 Seek Positioning error X 19 Defect List error X 31 Medium Format corrupted X 32 No Defect Spare Location Available X X 4 - HARDWARE ERROR X 08 Logical Unit Communication Failure X 10 ID CRC X 15 Seek Positioning error X 42 Power On Diagnostic Failure X X 5 - ILLEGAL REQUEST X 20 Invalid Command Operation Code X 21 Illegal Logical Block Address X 24 Illegal field in CDB X 26 Invalid field in Parameter List X X 6 - UNIT ATTENTION X 28 Medium Changed X 29 Power On or Reset or Bus Device Reset occured X 2A Mode Select Parameters changed X X 7 - DATA PROTECT X 27 Write Protected X X 8 - BLANK CHECK (unformatted tape) X X 9 - VENDOR UNIQUE X X B - ABORTED COMMAND X 47 Message Parity Error Message X 48 Initiator Detected Error X*/ END_OF_FILE if test 1279 -ne `wc -c <'sense.codes'`; then echo shar: \"'sense.codes'\" unpacked with wrong size! fi # end of 'sense.codes' fi if test -f 'tape-handle.uu' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'tape-handle.uu'\" else echo shar: Extracting \"'tape-handle.uu'\" \(10238 characters\) sed "s/^X//" >'tape-handle.uu' <<'END_OF_FILE' Xbegin 644 tape-handler XM```#\P`````````"``````````$```9^````>````^D```9^3E7_B$CG!SI)( XM^0````!P`#M`_XX[0/^00_H'GG``+'@`!$ZN_=@I0`%0D\E.KO[:)D!.N@\<) XM)$`@*@`<(@#E@2X`0?H'ABM(_]I!^@>**TC_WBM!_^9![`%^*TC_[D'M_\(KG XM2/_J0>W_VBE(`60G2`!8("H`&.6`($!#Z``!*4D!>A`1*T'_SG(BL`%F'E*LV XM`7H@;`%Z2AAF_%.(D>P!>B`((FP!>M/`0BG__T*G80`([BM`_\)(>``!80`(< XMXBP`2'@``6$`"-@J`$AX``%A``C.*4`!;$AX``%A``C".4`!>$AX__]A``BV# XM3^\`&"M`_[(@+`%L(@5.NA%:*4`!<"M`_[8@;?^R$!!R)+`!9@XI?`$`````^ XM"%*M_[)@#G(KL`%F"$*L`7!2K?^R*VW_LO_B(`8`@``!```O0``<(#P```%6` XM(B\`'"QX``1.KO\Z*T#_QDJ`9AQ(>`!G0J<O"DZZ#8XB;`%0+'@`!$ZN_F)@U XM``8\(&W_QBE(`51#Z``@*4D!6$/H`$`I20%<0J="ITZZ$:9(>``P+P!.NA)H< XM3^\`$"E``6`@;?^R("W_PB)L`6!R`"QX``1.KOY$2H!G*DAX`-)"IR\*3KH-/ XM)B)L`5`L>``$3J[^8B)M_\8@/````59.KO\N8``%QD'K`%PB;?_.(T@`""\J4 XM`!!(>/__+PI.N@SN3^\`#'#_+'@`!$ZN_K8;0/^-#```_V<,<@`2`'`!XZ`KB XM0/_R0J=A``9@6$].N@T>)$`@*@`(7X!G``4*4X!G``467X!G``4F<D.0@6<`Y XM`RY;@&<`!`0$@````Y9G#E.`9PI3@&<``G)@``482FW_D&<22'@`RD*G+PI.U XMN@QP3^\`#&"H(`8`@``!```O0``<("W_MB(O`!PL>``$3J[_.BE````@!@"`5 XM``$``"]``!P@+?^V(B\`'$ZN_SHI0``$2JP``&<$2H!F+"\M_[9A``9L2'@`^ XM9T*G+PI.N@P02'H%$$AL`7Y.N@\N80`&_$_O`!A@`/\X<``B*@`<Y8$@04/H6 XM``$I20%Z.T#_ECM`_Y([0/^4(&P!>A`0<CJP`6<&4JP!>F#N(&P!>E*(<`E#M XM^@3D$ABR&5;(__IF#'`!.T#_ECM`_Y)@1"!L`7H0*``!<BJP`68(.WP``?^25 XM8"YR`!(`0>P`30@P``(8`&<>(&P!>E*(0J="IR\(3KH5!$_O``PI0`%H.WP`! XM`?^20J=A``3X6$]*;?^29PAP`"M`_YI@%G``+P`O`$AX``-.N@:23^\`#"M`& XM_YI*@&<B+P!A``3(+JW_MF$`!71(>`#:0J<O"DZZ"QA/[P`08`#^4'``+P`OC XM`$AX``5.N@963^\`#$J`9P@@/'____]@%G``(&P!6!`H``+A@'(`$B@``X"!: XM4H`I0`%T(@5.N@XV+P`O!2\L`71(>@/Z2&P!?DZZ#>AA``6V3^\`%#M\``'_J XMD'``.4``#$*M_Z(K;?^V_YX[0/^8.T#_CDIM_Y)F"C`L`7A(P"E``6@O+`%H$ XM2'H#PDAL`7Y.N@VB80`%<$_O``P,J@```^T`"&8Z.WP``?^4<``O`"\`2'@`X XM`4ZZ!:9/[P`,(BP!;-.L`6@K0/^:9A1P`2\`+P`O`$ZZ!8A/[P`,*T#_FB\J9 XM`!!(>/__+PI.N@H>3^\`#&``_59*;?^09V)*;?^.9S9*;?^69Q@P+?^82,!"M XMIR\`2'@`!$ZZ!49/[P`,8#`P+?^82,!"IR\`2'@``DZZ!2Y/[P`,8!A*;``,< XM9Q)P`"\`+P!(>``&3KH%%$_O``Q";?^0+RW_MF$`!`!83R\J`!!(>/__+PI.! XMN@F@3^\`#$IM_Y1F""`L`6S1K`%H+RP!:$AZ`MQ(;`%^3KH,J&$`!'9/[P`,\ XM8`#\LDJM_YIG%"\M_YIA``,`6$]P_R5``!Q@``"N*VH`&/^N*VH`'/^J2JW_! XMJF<``)I*K?^>9D@@+`%LT:P!:#`M_YA(P'(!+P$O`"\!3KH$>$_O``PK0/^:< XM9Q`O`&$``K!83W#_)4``'&!>"&T``/^9("W_MG(`*T#_GBM!_Z(@+?^>(BW_< XMJK*`;@(@`3(M_YA(P>6!0>P``"!P&`#1[?^B*T#_IB)M_ZY@`A+84X!D^B`M< XM_Z:1K?^JT:W_HI&M_Y[1K?^N8`#_8B\J`!@O*@`<+PI.N@B>3^\`#&``^]8KE XM:@`8_ZXK:@`<_ZI*K?^J9P``Q"`M_YXB+?^JLH!M?#(M_YA(P>6!0>P``"!PS XM&`#1[?^B(FW_KF`"$-E3@&3Z,"W_F$C`2'@``2\`2'@``DZZ`Y9/[P`,*T#_R XMFF<0+P!A``'.6$]P_R5``!Q@:"`L`6S1K`%H("W_GI&M_ZK1K?^N<``K;?^VG XM_YX(;0``_YE";?^.*T#_HF``_W(P+?^82,#E@$'L```@<`@`T>W_HB)M_ZY@D XM`A#94X%D^B`M_ZJ1K?^>T:W_HD*M_ZH[?``!_XY@`/\X+RH`$"\J`!PO"DZZ@ XM![)/[P`,8`#ZZD*G+P<O"DZZ!Z!/[P`,8`#ZV"\J`!`O*@`4+PI.N@>*3^\`P XM#&``^L(O*@`02'C__R\*3KH'=$_O``Q@`/JL2'@`T4*G+PI.N@=@+JH`"$AZ? XM`,)(;`%^3KH*>F$``DA/[P`48`#ZA$SM7.#_;$Y=3G5I;G1U:71I;VXN;&EBR XM<F%R>0!487!E2&%N9&QE<@`M0E1.5$%012!6,2XP(%)!4BU397`@,3`@,3DYD XM,`!#86XG="!G970@;65M;W)Y(&9O<B!T87!E(&)U9F9E<G,*```D)%)!5T--` XM1"0D```E9"`J("5D(#T@)60*`$]P96YE9"!A="!B;&]C:R`E9`H`0VQO<V5D@ XM(&%T(&)L;V-K("5D"@!5;G-U<'!O<G1E9%]0:W0])60*`&EO7T5R<F]R/25DA XM("!396YS93TE6"PE,#)8"@`O`$CG`0A)^0`````N+P`,<``@;`%8$4``#"!L= XM`5@10``"X(=F$G``+P`O`"\`3KH!BD_O``Q@3G`MOH!F2'``+P`O`"\`3KH!B XM<D_O``P@;`%8$!`B``(!`'!*`68,`@``#R!L`5@10``"$"@``B!L`6010``D\ XM(&P!6!`H``P@;`%D$4``)7``(&P!6!`H``)R`!(H``PO`2\`+P=(>O]&2&P!H XM?DZZ".IA``"X3^\`%$S?$(!.=4CG`0I)^0`````N+P`02FP`#&<2<``O`"\`3 XM2'@`!DZZ`.1/[P`,2JP``&<.(FP``"`'+'@`!$ZN_RY*K``$9PXB;``$(`<L! XM>``$3J[_+I'(*4@`!"E(``!,WU"`3G5(YP$82?D`````/B\`$DI'9P1P`&`$[ XM("P!>B9`2'K^SB\+3KH&"E!/*4`!>G#_OD!F!B`L`7I@$$*G0J<O+`%Z3KH.> XMI$_O``Q,WQB`3G5(YP`*2?D`````(&P!9$JH`"!G/")H`"`@*``<+'@`!$ZN' XM_KP@;`%D("@`&$ZN_L(B;`%D(FD`("!L`60@*``<3J[^O"!L`60@*``83J[^[ XMPDS?4`!.=0``3E7_]$CG+PI)^0`````N+0`(+"T`#!HM`!-*;``,9S8B;`%@P XM+'@`!$ZN_B9P`#E```P@;`%@2B@`'V<:<@`2*``?X8%T`")L`5P4*0`5TH(@. XM`6```U!P!KZ`9@9P`&```T0@;`%<(6P!5``,(&P!7#%\``8`$'``(&P!7!%`8 XM`!4B;`%@,WP`'``<(&P!8"%L`5P`*'(6(&P!8"%!`"0@;`%@$4``'Q%\``$`0 XM'G@`<`:X0&P,(&P!5-#$0A!21&#N(`<,@`````9D``)PT$`P.P`&3OL`!`%LQ XM``H`F@$N`>@!L"`L`6C0K`%LL*P!=&4$80`#5"!L`500O``(("P!:"(`X(ETF XM`$8"PH(@;`%4$4$``G``1@#`K`%H(&P!5!%```,@+`%L(&P!5!%```0@!N6`[ XM0>P``")L`5PBL`@`(&P!7"%L`7``!"!L`5P1?``!`!0O+`%L+RP!:$AZ`E!(0 XM;`%^3KH&<DZZ_D!/[P`08``!RB`L`6C0K`%LL*P!=&4$80`"Q"!L`500O``*@ XM("P!:"(`X(ET`!0!<@!&`<2!(&P!5!%"``)P`$8`P*P!:"!L`5010``#("P!* XM;"!L`5010``$(`;E@$'L```B,`@`@JP`""!L`5P@@2%L`7``!"!L`5Q"*``4= XM+RP!;"\L`6A(>@'42&P!?DZZ!=Y.NOVL3^\`$&```38@;`%4$+P``2`&Y8!!1 XM[```(FP!7"*P"``@;`%<0J@`!"!L`5Q"*``42'H!K$AL`7Y.N@6>3KK];%!/, XM8```^"!L`500O``#(&P!5!%\`!P`!'`<(&P!7"%```0@;`%<(*P!6"!L`5P1X XM?``!`!1(>@%T2&P!?DZZ!5I.NOTH4$]@``"T(&P!5!"\`"5P""!L`5PA0``$: XM(&P!7""L`5@@;`%<$7P``0`42'H!0DAL`7Y.N@4@3KK\[E!/8'IX`"`&Y8!!M XM[```*W`(`/_\(&W__!`0<@JP`6<T<""X0&PN(`121")L`532P$AX`!!(;?_\+ XM+P@O20`H3KH+1$_O``QR`$8!P($@;P`<$(!@P"!L`5P@K`%8(&P!7$*H``0@2 XM;`%<0B@`%$AZ`-!(;`%^3KH$I$ZZ_')03TH%9B8B;`%@+'@`!$ZN_CAP`"!LQ XM`6`0*``?X8!R`")L`5P2*0`5T(%@0"\L`6!.N@PV6$\@;`%@2B@`'V<6<``0? XM*``?X8!R`"!L`5P2*``5T(%@%B!L`6`0*``>"````&8&.7P``0`,<`!,WU#TQ XM3EU.=5)E861I;F<@8FQO8VL@)60@*B`E9`H``%=R:71I;F<@8FQO8VL@)60@1 XM*B`E9`H``%)E=VEN9&EN9PH``%-E;G-E.@``0V%P86-I='DZ`%)A=R!C;VUMD XM86YD"@``("!%3U0Z($EN<V5R="!N97AT('1A<&4`0V]N=&EN=64``%%U:70`% XM`%1I;64@9F]R(&$@;F5W('1A<&4*```O#$GY`````'``+P`O`$AX``9A`/NF( XM2'K_TDAL`7Y.N@-P3KK[/DAX`#)(>`#Z<``O`"\`2&P`.$AL`"1(;``00J=.[ XMN@3Z3^\`-$J`9Q(P+`%X2,`I0`%H0J=.NOFF6$\H7TYU``!.5?_T2.<#.DGYA XM`````"9M``@N+0`,+"T`$"='``PG1@`0*VL`!/_X)%.3R2QX``1.KO[:($!#E XMZ`!<)TD`!"5+``J3R22))4D`!"M`__0@;?_X(DI.KOZ23-]<P$Y=3G5.5?_T2 XM2.<`.DGY`````)/)+'@`!$ZN_MHF0$7K`%P@2DZN_H`@2DZN_HP@0"`H``I,' XMWUP`3EU.=4CG(#`F;P`0)$M*$F<D<``0$D'L`$T(,``!"`!G"G(`$@!T()*"- XM8`1R`!(`%(%2BF#8(`M,WPP$3G4``````````'!A3E7_]$CG`3`F;P`@(`MG( XM(B!++RT`#"\(*4@!T$ZZ`9)03RX`(&P!T")(T\<K2?_X8!`@;`'02A!F!'``C XM8$(K2/_X)&W_^"\M``PO"DZZ`7Y03RX`2C)X`&<:0C)X`"!*T<=%Z``!+RT`V XM#"\*3KH!0E!/+@`@2M''*4@!T"`M__A,WPR`3EU.=2`O``@@;P`$3E7_]")/[ XM<@I.N@)`!D$`,!+!2H!F\"`)$.&_R6;Z0A"0CTY=3G4``"`O``@@;P`$3E7_= XM]")/(@`"00`'!D$`,!+!YHAF\"`)$.&_R6;Z0A"0CTY=3G4``#`Q,C,T-38W< XM.#EA8F-D968@+P`((&\`!$/O``0R``)!``\2^Q#<Z(AF\B`)(@]8@1#ALHEFP XM^D(0D(%.=4Y5__A(YP$P)F\`'"1O`"!^`$H39RHK2O_\(&W__$H09PP0$+`32 XM9P92K?_\8.P@;?_\2A!F!"`'8`A2AU*+8-(@!TS?#(!.74YU3E7_^$CG`3`FB XM;P`<)&\`('X`2A-G(BM*__P@;?_\2A!G$!`0L!-F!"`'8`Y2K?_\8.A2AU*+% XM8-H@!TS?#(!.74YU2.<`,"9O``PD;P`0+PHO"V$`_V)03TS?#`!.=4CG`#`F\ XM;P`,)&\`$"\*+PMAD%!/3-\,`$YU```@;P`$(DAR`'``+P(,$``K9P8,$``MH XM9@)22!`8!```,&T2#```"6X,)`'E@=*"TH'2@&#F#!$`+68"1($D'R`(4X`@+ XM;P`(((&0B4YU+P<N+P`(4JP!V"`'(&P!U!#`*4@!U"X?3G5.50``2.<`,"9OK XM`!`D;P`40JP!V"E+`=1(;0`0+PI(>O_&3KH%Q"!L`=1"$"`L`=A,[0P`__A._ XM74YU2.<P`"0`)@%(0DA#Q,'&P,#!U$-(0D)"T(),WP`,3G5*@&H``!Y$@$J!] XM:@``#$2!80``($2!3G5A```81(!$@4YU2H%J```,1(%A```&1(!.=2\"2$$TK XM`68``")(0$A!2$(T`&<```:$P3`"2$`T`(3!,`)(0C(")!].=2\#=A`,00"`X XM9```!N&944,,00@`9```!NF964,,02``9```!N6954-*06L```;CF5-#-`#FJ XMJ$A"0D+FJDA#@,$V`#`"-`-(0<3!D()D```(4T/0@63^<@`R`TA#Y[A(0,%!A XM)A\D'TYU2.<#,B9O`!@N+P`<</\L>``$3J[^MBP`#`8`_V8$<`!@9G`B(CP`I XM`0`!3J[_.B1`(`IF"G``$`9.KOZP8$@E2P`*(`<50``)%7P`!``(0BH`#A5&^ XM``^3R4ZN_MHE0``0(`MG"")*3J[^GF`:0>H`&"5(`!1!Z@`4)4@`'$*J`!@5Q XM?``"`"`@"DS?3,!.=0``2.<P,BQL`5`@;P`8(F\`'"1O`"`F;P`D("\`*"(O$ XM`"PD+P`P)B\`-$ZN_J1,WTP,3G4``````````'!A2.<!,B9O`!0N+P`8(`MF^ XM!'``8"P@!R(\``$``2QX``1.KO\Z)$`@"F<4%7P`!0`(0BH`"25+``X@!S5`: XM`!(@"DS?3(!.=0``3E7_Q$CG)S`F;P!<)&\`8'X`?`!Z`'``&WP`(/_[<@`KX XM0?_V=/\K0O_R0>W_T!M`__$;0/_\*T'_Y"M!_^@K2/_,2A-G+'``$!,$0``@L XM9Q170&<444!G"%5`9A9^`6`.?`%@"GH!8`8;?``!__Q2BV#0$!-R,+`!9@92G XMBQM!__MP*K`39@P@4EB2*U#_]E*+8`Y(;?_V+PM.NOS.4$_7P!`3<BZP`68BO XM4HMP*K`39@P@4EB2*U#_\E*+8`Y(;?_R+PM.NORD4$_7P!`3<FRP`68*&WP`V XM`?_Q4HM@"')HL`%F`E*+$!MR`!(`&T#_\`1!`%AG``%^!$$`"V<``@I306<DD XM!$$`"V<``1)306<``5!706<``;I506<``.1706<``5)@``'X2BW_\6<((%)8\ XMDB`08`8@4EB2(!`K0/_L;`IR`42M_^PK0?_H2JW_Z&<$<"U@"DH&9P1P*V`"J XM<"`;0/_0<``0!B(M_^B"@'``$`6"@&<(4JW_S%*M_^0O+?_L+RW_S$ZZ^H)0< XM3RM`_\@@+?_R2H!J!G(!*T'_\B`M_\@B+?_RDH!([0`"_\1O-"!M_\PB2-/!B XM+P`O"2\(3KH"4D_O``QP`!`M__LB+?_$(&W_S&`"$,!3@63Z("W_\BM`_\C1Z XMK?_D0>W_T"M(_\Q*!V<``3`;?``@__M@``$F2BW_\6<((%)8DB`08`8@4EB20 XM(!`K0/_L8`#_9$HM__%G""!26)(@$&`&(%)8DB`0*T#_[$HM__QG$B!M_\P0& XM_``P<@$K0?_D*TC_S"\`+RW_S$ZZ^>903RM`_\A@`/\R&WP`,/_[("W_\DJ`4 XM:@9P""M`__)*+?_Q9P@@4EB2(!!@!B!26)(@$"M`_^Q*+?_\9Q8@;?_,$/P`! XM,!#\`'AR`BM!_^0K2/_,+P`O+?_,3KKYRE!/*T#_R'!8L"W_\&8`_M!(;?_0S XM3KKX=EA/8`#^PB!26)(B4"M)_\QF"$'Z`-@K2/_,(&W_S$H89OQ3B)'M_\PKT XM2/_D("W_\DJ`:R:QP&\B*T#_Y&`<<`$K0/_D(%)8DB`0&T#_T$(M_]%@!G``: XM8```C"`M_^0B+?_VLH!L"'0`*T+_]F`$D:W_]DH'9S93K?_D;1AP`"!M_\P0A XM&"\`*TC_S"!M`!!.D%A/8.)3K?_V;4AP`!`M__LO`"!M`!!.D%A/8.A3K?_V( XM;1)P`!`M__LO`"!M`!!.D%A/8.A3K?_D;1AP`"!M_\P0&"\`*TC_S"!M`!!.O XMD%A/8.(@"TS?#.1.74YU``!.5?_T2.<!,"9O`"`D;P`D*VT`$/_V'AI*!V<T0 XM<"6^`&8BL!)F!%**8!HO"TAM__8O"F$`_!9/[P`,*T#_^F<$)$!@TG``$`<O2 XM`$Z36$]@QDS?#(!.74YU```@;P`$(F\`""`O``QO%K/(90S1P-/`$R!3@&;Z5 XM3G42V%.`9OI.=0``+SP`````2.=X,"!O`"`B;P`D("\`*"E\``````'<)$@,Z XM$``@9@122&#V)D@,````;0P,```D;@8,```!9@9P`&```/@,$``M9@A2+P`8R XM4DA@"`P0`"MF`E)(#````&8><`H,$``P9CAP"%)(#!``6&<&#!``>&8H<!!2F XM2&`B#```$&8<#!``,&86#"@`>``!9@142&`*#"@`6``!9@)42$*!0H(,$```! XM9P``7!00#`(`,&U2#`(`.6X&!`(`,&`."((`!0P"`$%M/`0"`#>T`&XT*`%GM XM("8!QL!(1,C`2$1K#@Q$``!F"-:$900B`V`&'WP``0`9TH)D```('WP``0`9< XM4DA@G@@O````&&<"1($(+P```!EG```B*7P````B`=P(+P```!AF```*(CQ_N XM____8`8B/(````"S_`````!G"K?(9@0BBF`"(H@@`4S?#!Y8CTYU````````B XM``!P82)O``0O#BQI`!1.KO_B+%].=0`````#[`````D````!```/6@``#OH`A XM``Z.```*3@``"?(```FD```)1@``")(````*`````````_`````"7T)E9VEN( XM24\``!GD`````````_(```/J````>````````````````````````0$```8`W XM`P````````Y,```````!`0``!@`#````````#F0```````$!```&``,`````E XM```.;@``````("`@("`@("`@*"@H*"@@("`@("`@("`@("`@("`@("!($!`0< XM$!`0$!`0$!`0$!`0A(2$A(2$A(2$A!`0$!`0$!"!@8&!@8$!`0$!`0$!`0$!H XM`0$!`0$!`0$!`1`0$!`0$(*"@H*"@@("`@("`@("`@("`@("`@("`@("$!`0. XM$"`@("`@("`@("`H*"@H*"`@("`@("`@("`@("`@("`@($@0$!`0$!`0$!`0` XM$!`0$!"$A(2$A(2$A(2$$!`0$!`0$(&!@8&!@0$!`0$!`0$!`0$!`0$!`0$!_ XM`0$!$!`0$!`0@H*"@H*"`@("`@("`@("`@("`@("`@("`@(0$!`0(```````W XM````````````````````````````````````````````````````````````` XM````````````````````````````````````````````````````````````` XM````````````````````````````````````````````````````````````` XG`````````````^P````#`````````$0````P````'`````````/RW X`` Xend Xsize 7284 END_OF_FILE if test 10238 -ne `wc -c <'tape-handle.uu'`; then echo shar: \"'tape-handle.uu'\" unpacked with wrong size! fi # end of 'tape-handle.uu' fi if test -f 'tape.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'tape.c'\" else echo shar: Extracting \"'tape.c'\" \(16555 characters\) sed "s/^X//" >'tape.c' <<'END_OF_FILE' X/**** BTNtape Handler for SCSI tape drives ****/ X/**** Author: Bob Rethemeyer (DrBob@cup.portal.com) ****/ X X#define TVERSION "-BTNTAPE V1.0 RAR-" ## __DATE__ X X/* (c) Copyright 1990, Robert Rethemeyer. X * This software may be freely distributed and redistributed, X * for non-commercial purposes, provided this notice is included. X *----------------------------------------------------------------------- X * BTNtape is an AmigaDOS device handler to make a simple DOS TAPE: device. X * It converts DOS packets for the device into I/O requests to a X * "SCSI-direct" compatible device driver. It is based on "my.handler" X * by Phillip Lindsay and a SCSI-direct program by Robert Mitchell. X * Source is ANSI C compliant. Compile with Lattice v5 or Manx v5. X * X * This handler works in conjunction with the accompanying TapeMon program. X *---------------------------------------------------------------------------- X * Install this handler in your L: directory. X * Make a devs:mountlist entry similar to this: X * X * TAPE: Handler = L:tape-handler X * Stacksize = 4000 X * Priority = 5 (use 11 for Supra) X * GlobVec = -1 X * Startup = "4/5/8192/1/0/yourscsi.device" X * ( unit/BufMemType/blocksize/Buffers/Reserved/Driver ) X * # X * Then use "MOUNT TAPE:" to make the device known to DOS. X * X * This handler can circumvent the "write phase" problem in the CBM 2090A X * driver. To invoke the circumvention, prefix the name of the driver X * in the Startup mountlist parameter with a dollar sign ("$"). X * Example: Startup = "4/5/8192/1/0/$hddisk.device" X * X * This handler can circumvent a byte count problem in the Supra v1.10 X * driver. To invoke the circumvention, prefix the name of the driver X * in the Startup mountlist parameter with a plus sign ("+"). X * Example: Startup = "4/5/8192/1/0/+supradirect.device" X * X * ---------------------------------------------------------------------------- X */ X X#include <exec/types.h> X#include <exec/nodes.h> X#include <exec/lists.h> X#include <exec/ports.h> X#include <exec/tasks.h> X#include <exec/libraries.h> X#include <exec/io.h> X#include <exec/memory.h> X#include <devices/scsidisk.h> X#include <libraries/dos.h> X#include <libraries/dosextens.h> X#include <libraries/filehandler.h> X#include <stdio.h> X#include <string.h> X#include <ctype.h> X#include <limits.h> X X#if defined AZTEC_C X #include <functions.h> X#elif defined LATTICE X #include <proto/exec.h> X#endif X X#include "tape.h" X#include "tplink.h" X Xstruct things { /* a collection of things we will have to alloc */ X UBYTE cmdbuff[32]; X UBYTE snsarea[32]; X struct SCSICmd scsicmd; X UBYTE pad[256]; /* SCSICmd may be larger than include? */ X } ; X X/*======== Global data */ X Xstruct IntuitionBase *IntuitionBase; XUBYTE *cdb; /* pointer to tape command buffer */ XUBYTE *sns; /* pointer to sense data buffer */ Xstruct SCSICmd *cmd; /* pointer to scsidirect command */ Xstruct IOStdReq *ior; /* pointer to io request structure*/ XUBYTE *TapeBuff[2] /* pointers to 2 tape buffers */ X ={NULL,NULL}; Xstruct tplink *linktp; /* pointer to link structure */ XULONG blknum; /* block number for io operation */ XULONG numblks; /* number of blocks per io operation */ XULONG rwlen; /* bytes in a tape read/write */ XULONG bugmask = 0; /* 2090A bug circumvention */ Xlong tpsize; /* tape size in blocks */ Xshort reserved; /* number of reserved blocks at BOT */ Xshort inprog = FALSE; /* io operation in progress flag */ Xchar *z; /* scratch */ Xchar dbb[80]; /* buffer for monitor messages */ X X#define RAWNAME "$$RAWCMD$$" X#define RAWLEN 10 X X/*********************** Main program ********************************/ X#ifdef AZTEC_C X #pragma intfunc(_main()) X#endif Xvoid _main(void) X{ X struct tplink tpl; /* structure to link hndlr & mon */ X struct Process *myproc; /* ptr to handler's process struct */ X struct DosPacket *mypkt; /* ptr to dos packet sent */ X struct DeviceNode *mynode; /* ptr to devnode passed in pkt Arg3 */ X ULONG dvnode; /* ptr to devnode passed in pkt Arg3 */ X struct things *xarea; /* ptr to dynamic misc. areas */ X ULONG unit; /* device SCSI unit address */ X ULONG bufmemtype; /* type of mem for dynamic buffers */ X ULONG blksize; /* bytes per tape block */ X ULONG TBSize; /* bytes in a tape buffer */ X char *driver; /* name of SCSI device driver */ X UBYTE *dptr; /* ptr to next byte in dos buffer */ X long dcnt; /* count of dos packet bytes to move */ X long mcnt; /* count of bytes to move */ X long Boff; /* current offset in tape buffer */ X long rem; /* bytes remaining in tape buffer */ X long x; /* scratch */ X short Bn; /* current buffer number, 0 or 1 */ X short raw; /* raw command mode flag */ X short rdmode; /* flag indicating open for reading */ X short norw; /* no-rewind flag */ X short open= FALSE; /* tape file open flag */ X short dirty=FALSE; /* buffer has unwritten data in it */ X BYTE acksig; /* monitor acknowledge signal number */ X X/*======== Startup */ X X IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",0); X myproc = (struct Process *) FindTask(0L); /* find this process */ X mypkt = taskwait(); /* wait for startup packet */ X /* packet: Arg1=BSTR to name, Arg2=BSTR to startup string, Arg3=BPTR devnode*/ X mynode = (struct DeviceNode *) BADDR(mypkt->dp_Arg3); X dvnode = (ULONG) mypkt->dp_Arg3; X X/*======== Create linkage for the tape monitor: install pointer to tplink X ======== structure in the free pointer of the task block, so the tape X ======== monitor can find it after FindTask(). X*/ X tpl.keyword = "TapeHandler"; X tpl.version = TVERSION; X tpl.devnode = (void *)mynode; X tpl.dbb = dbb; X tpl.unit = &unit; X linktp = &tpl; X ((struct Task *)myproc)->tc_UserData = (APTR) linktp; X X/*======== Extract info from mountlist Startup parameter. It may be X ======== enclosed in quotes, and each item is separated by a single '/' X*/ X z = (char *)BADDR(mypkt->dp_Arg2)+1 ; /* Arg2= BSTR to mountlist 'Startup'*/ X if(z[0]=='\"') { /* remove quotes if any */ X z++; X z[strlen(z)-1]= '\0' ; X } X unit = Nextnum(0); X bufmemtype = Nextnum(1); X blksize = Nextnum(1); X numblks = Nextnum(1); X reserved = Nextnum(1); X driver = (char *) Nextnum(-1); X rwlen = TBSize = numblks * blksize; /* size of a tape buffer */ X X/*======== Kludges to work around various SCSIdirect driver software problems */ X X if (driver[0] == '$') { /* Activate 2090A bug circumvention */ X bugmask = 0x01000000; /* if driver name starts with '$' */ X driver++ ; X } X else if (driver[0] == '+') { /* Activate Supra bug circumvention */ X rwlen = 0; /* if driver name starts with '+' */ X driver++ ; X } X tpl.driver = driver; X X/*======== Allocate some memory for non-data buffers */ X X if( !(xarea = (struct things *) X AllocMem(sizeof(struct things), bufmemtype | MEMF_CLEAR) )) X { returnpkt(mypkt,DOSFALSE,ERROR_NO_FREE_STORE); X CloseLibrary((struct Library *)IntuitionBase); X return; X } X cdb = &xarea->cmdbuff[0]; X sns = &xarea->snsarea[0]; X cmd = &xarea->scsicmd; X ior = (struct IOStdReq *) CreateExtIO( CreatePort(0,0), X sizeof(struct IOStdReq)); X X/*======== Open the SCSIdirect device */ X X if ( OpenDevice(driver,unit,(struct IORequest *)ior,0L) ) { X returnpkt(mypkt,DOSFALSE,ERROR_INVALID_COMPONENT_NAME); X CloseLibrary((struct Library *)IntuitionBase); X FreeMem(xarea,sizeof(struct things)); X return; X } X mynode->dn_Task = &myproc->pr_MsgPort; /* install handler taskid */ X returnpkt(mypkt,DOSTRUE,mypkt->dp_Res2); /* reply to initial packet */ X X/*======== Allocate the signal that TapeMon will X ======== use to acknowledge MPR requests. X*/ X acksig = AllocSignal(-1); X if(acksig != -1) tpl.handsig = 1UL << acksig; X /* else { monitor will not attempt to signal us } */ X X DoSense(0); X X/* =========== The main packet processing loop =============== */ X X for (;;) { X mypkt = taskwait(); /* wait for a packet */ X switch(mypkt->dp_Type) { X X case ACTION_FINDINPUT: /*----------- Open() ------------*/ X case ACTION_FINDOUTPUT: X if(open) returnpkt(mypkt,DOSFALSE,ERROR_OBJECT_IN_USE); X else { X TapeBuff[0] = (UBYTE *) AllocMem(TBSize, bufmemtype | MEMF_CLEAR); X TapeBuff[1] = (UBYTE *) AllocMem(TBSize, bufmemtype | MEMF_CLEAR); X if (!TapeBuff[0] || !TapeBuff[1]) { X FreeStuff(TBSize); X returnpkt(mypkt,DOSFALSE,ERROR_NO_FREE_STORE); X MPR0("Can't get memory for tape buffers\n") X } X else { X /* Detect open modes: raw command, continue, goto-block */ X raw=norw=rdmode=FALSE; X for( z=(char *)BADDR(mypkt->dp_Arg3)+1 ; z[0]!=':' ; z++ ); X if(!memcmp(z+1,RAWNAME,RAWLEN)) raw=norw=TRUE; X else if( z[1] == '*' ) norw=TRUE; X else if( isdigit((int)z[1]) ) { X blknum = (ULONG) strtol(z+1,NULL,0); X norw=TRUE; X } X X DoSense(0); /* eat tape-change status */ X if(norw) x=0; X else x=TapeIO(TREWIND,0,CTLWAIT); X if(x) { X DoSense(x); X FreeStuff(TBSize); X returnpkt(mypkt,DOSFALSE,ERROR_DEVICE_NOT_MOUNTED); X } X else { X tpsize = TapeIO(RDCAP,0,CTLWAIT) ? /* get tape capacity in sns */ X LONG_MAX : ((sns[2] << 8) | sns[3]) + 1; X MPR3("%d * %d = %d\n", tpsize,blksize,tpsize*blksize) X open=TRUE; X dirty=FALSE; X inprog=FALSE; X Boff=0; X Bn=0; X rem = TBSize; X if(!norw) blknum = reserved; X MPR1("Opened at block %d\n",blknum) X if (mypkt->dp_Type==ACTION_FINDINPUT) { X rdmode=TRUE; X x= TapeIO(TREAD,0,CTLWAIT); /* fill 1st buffer */ X blknum += numblks; X if(!x) x=TapeIO(TREAD,1,CTLIMM); /* start reading 2nd */ X } X returnpkt(mypkt,DOSTRUE,mypkt->dp_Res2); X } X } X } X break; X X case ACTION_END: /*----------- Close() -----------*/ X if(open) { X if(dirty) { X if(raw) TapeIO(RAWCMD,Bn,CTLWAIT); /* send user command */ X else TapeIO(TWRITE,Bn,CTLWAIT); /* write last block */ X } X else if(inprog) TapeIO(TFINISH,0,CTLWAIT); /* wait for last one */ X open=FALSE; X FreeStuff(TBSize); X } X returnpkt(mypkt,DOSTRUE,mypkt->dp_Res2); X if(!rdmode) blknum += numblks; X MPR1("Closed at block %d\n",blknum) X break; X X case ACTION_READ: /*----------- Read() ------------*/ X if(x) { X DoSense(x); X mypkt->dp_Arg3 = -1; X goto RDERR; X } X dptr = (UBYTE *) mypkt->dp_Arg2; X dcnt = mypkt->dp_Arg3; X while(dcnt) { X if(!rem) { X blknum += numblks; /* start reading next buffer */ X if(x=TapeIO(TREAD,Bn,CTLIMM)) { X DoSense(x); X mypkt->dp_Arg3 = -1; X goto RDERR; X } X Bn ^= 1; /* switch to other (filled) buffer */ X rem = TBSize; X Boff = 0; X } X mcnt = (dcnt>rem) ? rem : dcnt; X memcpy (dptr, &TapeBuff[Bn][Boff], mcnt); X dcnt -= mcnt ; X Boff += mcnt ; X rem -= mcnt ; X dptr += mcnt ; X } X RDERR: X returnpkt(mypkt,mypkt->dp_Arg3,mypkt->dp_Arg2); X break; X X case ACTION_WRITE: /*----------- Write() -----------*/ X dptr = (UBYTE *) mypkt->dp_Arg2; X dcnt = mypkt->dp_Arg3; X while (dcnt) { X if (dcnt >= rem) { X memcpy (&TapeBuff[Bn][Boff], dptr, rem); X if( x=TapeIO(TWRITE,Bn,CTLIMM) ) { X DoSense(x); X mypkt->dp_Arg3 = -1; X goto WRTERR; X } X blknum += numblks; X dcnt -= rem; X dptr += rem; X Boff = 0; X rem = TBSize; X Bn ^= 1; X dirty = FALSE; X } X else { X memcpy (&TapeBuff[Bn][Boff], dptr, dcnt); X rem -= dcnt; X Boff += dcnt; X dcnt = 0; X dirty = TRUE; X } X } X WRTERR: X returnpkt(mypkt,mypkt->dp_Arg3,mypkt->dp_Res2); X break; X X case ACTION_CURRENT_VOLUME: X returnpkt(mypkt,dvnode,DOSFALSE); X break; X X case ACTION_LOCATE_OBJECT: /* lock */ X returnpkt(mypkt,mypkt->dp_Arg1,mypkt->dp_Res2); X break; X X case ACTION_FREE_LOCK: /* unlock */ X returnpkt(mypkt,DOSTRUE,mypkt->dp_Res2); X break; X X default: /* say what? */ X returnpkt(mypkt,DOSFALSE,ERROR_ACTION_NOT_KNOWN); X MPR1("Unsupported_Pkt=%d\n",mypkt->dp_Type) X X } /* end of switch */ X } /* end of loop */ X} /* end of _main() */ X X/**************************************************************************/ X Xvoid DoSense(long x) X{ X sns[2] = sns[12] = 0; X x=x>>8; X if(x==0) TapeIO(TSENSE,0,CTLWAIT); X else if(x==HFERR_BadStatus) { X TapeIO(TSENSE,0,CTLWAIT); X if(!(sns[0] & 0x70)) sns[2]=sns[0] & 0x0f; /* non-extended sense */ X linktp->sense = sns[2]; /* keep last error info */ X linktp->xsense = sns[12]; X } X MPR3("io_Error=%d Sense=%X,%02X\n", x, sns[2], sns[12]) X return; X} X X/**************************************************************************/ X Xvoid FreeStuff(ULONG bs) X{ X if(inprog) TapeIO(TFINISH,0,CTLWAIT); /* just in case */ X if(TapeBuff[0]) FreeMem(TapeBuff[0],bs); X if(TapeBuff[1]) FreeMem(TapeBuff[1],bs); X TapeBuff[0] = TapeBuff[1] = NULL; X return; X} X X/**************************************************************************/ X/* Nextnum parses and returns the next number in the startup string */ X XULONG Nextnum(short kk) /* kk=0 for first number */ X{ /* kk=1 for other numbers */ Xchar *zz; /* kk=-1 for pointer to last token */ X zz = (kk) ? NULL : z; X z = strtok(zz,"/"); X if(kk==-1) return( (ULONG) z); X else return( (ULONG) strtol(z,NULL,0) ); X} X X/************************************************************************** X MonPrint requests that the TapeMon program print the message in 'dbb'. X Since this handler cannot do DOS I/O, it must beg the TapeMon program, X possibly running in a CLI somewhere, to do the printf for it. If the X TapeMon is running, it will have installed a pointer to its task in X the link structure, and we can Signal() it. X*/ X Xvoid MonPrint(void) X{ X if(linktp->montask) { X Signal(linktp->montask, linktp->monsig); X Wait (linktp->handsig); X Signal(linktp->montask, linktp->monsig); X Wait (linktp->handsig); X } X return; X} X END_OF_FILE if test 16555 -ne `wc -c <'tape.c'`; then echo shar: \"'tape.c'\" unpacked with wrong size! fi # end of 'tape.c' fi if test -f 'tape.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'tape.h'\" else echo shar: Extracting \"'tape.h'\" \(1152 characters\) sed "s/^X//" >'tape.h' <<'END_OF_FILE' X/* BTNtape include file, version 1.0 */ X X/* Operations supported by TapeIO */ X#define TSENSE 0 /* issue sense */ X#define TREAD 1 /* read blocks */ X#define TWRITE 2 /* write blocks */ X#define TREWIND 3 /* rewind (rezero) tape */ X#define RAWCMD 4 /* send user scsi command to tape */ X#define RDCAP 5 /* read capacity */ X#define TFINISH 6 /* wait for last operation to finish */ X X/* these control how fast TapeIO returns to the caller */ X#define CTLWAIT 0 /* return when operation is done */ X#define CTLIMM 1 /* return immediately */ X X/* inline message print functions */ X#define MPR0(XYZ) sprintf(dbb,XYZ); MonPrint(); X#define MPR1(XYZ,V1) sprintf(dbb,XYZ,V1); MonPrint(); X#define MPR2(XYZ,V1,V2) sprintf(dbb,XYZ,V1,V2); MonPrint(); X#define MPR3(XYZ,V1,V2,V3) sprintf(dbb,XYZ,V1,V2,V3); MonPrint(); X X/* function prototypes */ Xvoid _main(void); Xvoid DoSense(long); Xvoid FreeStuff(ULONG); XULONG Nextnum(short); Xvoid MonPrint(void); Xlong TapeIO(int,int,UBYTE); Xvoid NewTape(void); Xvoid returnpkt(struct DosPacket *, ULONG, ULONG); Xstruct DosPacket *taskwait(void); END_OF_FILE if test 1152 -ne `wc -c <'tape.h'`; then echo shar: \"'tape.h'\" unpacked with wrong size! fi # end of 'tape.h' fi if test -f 'tapeio.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'tapeio.c'\" else echo shar: Extracting \"'tapeio.c'\" \(6492 characters\) sed "s/^X//" >'tapeio.c' <<'END_OF_FILE' X/* X** TapeIO: performs operations to the tape unit via SCSI-direct for BTNtape X** Version 1.0 09/10/90 X** X** (c) Copyright 1990 Robert Rethemeyer. X** This code is freely distributable and redistributable, X** for non-commercial purposes, provided this notice is included. X** X** This code was derived from programs written by Robert Mitchell. X*/ X X#include <exec/types.h> X#include <exec/io.h> X#include <libraries/dos.h> X#include <libraries/dosextens.h> X#include <devices/scsidisk.h> X#include <intuition/intuition.h> X#include <stdio.h> X#include <string.h> X X#if defined AZTEC_C X #include <functions.h> X#elif defined LATTICE X #include <proto/exec.h> X #include <proto/intuition.h> X#endif X X#include "tape.h" X#include "tplink.h" X X/* the following SCSI commands are defined for the 3M MCD-403 tape unit */ X#define CMD_TEST_UNIT_READY 0x00 X#define CMD_REZERO 0x01 X#define CMD_REQUEST_SENSE 0x03 X#define CMD_FORMAT_UNIT 0x04 X#define CMD_SEND_SYSTEM_DATA 0x05 X#define CMD_RECEIVE_SYSTEM_DATA 0x06 X#define CMD_REASSIGN_BLOCKS 0x07 X#define CMD_SCSI_READ 0x08 X#define CMD_VERIFY_UNIT 0x09 X#define CMD_SCSI_WRITE 0x0a X#define CMD_SEEK 0x0b X#define CMD_READ_SCSI_DEFECT 0x0d X#define CMD_READ_CONTROLLER_INFO 0x0e X#define CMD_WRITE_CONTROLLER_INFO 0x0f X#define CMD_DRIVE_PASS_THRU 0x10 X#define CMD_READ_DRIVE_LINES 0x11 X#define CMD_INQUIRY 0x12 X#define CMD_READ_QIC100_INFO 0x13 X#define CMD_WRITE_QIC100_INFO 0x14 X#define CMD_MODE_SELECT 0x15 X#define CMD_RESERVE 0x16 X#define CMD_RELEASE 0x17 X#define CMD_READ_QIC100_DEFECT 0x19 X#define CMD_MODE_SENSE 0x1a X#define CMD_LOAD_UNLOAD 0x1b X#define CMD_READ_DIAG_RESULT 0x1c X#define CMD_SEND_DIAG 0x1d X#define CMD_READ_CAPACITY 0x25 X#define CMD_READ_EXTENDED 0x28 X#define CMD_WRITE_EXTENDED 0x2a X#define CMD_SEEK_EXTENDED 0x2b X#define CMD_READ_SCSI_DEFECT_DATA 0x37 X#define CMD_WRITE_BUFFER 0x3b X#define CMD_READ_BUFFER 0x3c X X#define CBLEN 6 Xextern UBYTE *cdb; Xextern UBYTE *sns; Xextern struct SCSICmd *cmd; Xextern UBYTE *TapeBuff[2]; Xextern struct IOStdReq *ior; Xextern ULONG blknum; Xextern ULONG numblks; Xextern ULONG rwlen; Xextern ULONG bugmask; Xextern long tpsize; Xextern struct tplink *linktp; Xextern short inprog; Xextern char dbb[80]; X X Xlong TapeIO(int toper, int bn, UBYTE ctl) X{ X char *z; X short i; X X if(inprog) { WaitIO((struct IORequest *)ior); X inprog = FALSE; X if(ior->io_Error) X return((long)((ior->io_Error << 8) + cmd->scsi_Status)); X } X if(toper == TFINISH) return(0L); X cmd->scsi_Command = cdb; X cmd->scsi_CmdLength = CBLEN; X cmd->scsi_Status = 0; X ior->io_Command = HD_SCSICMD; X ior->io_Data = (APTR) cmd; X ior->io_Length = sizeof(struct SCSICmd); X ior->io_Error = 0; X ior->io_Flags = IOF_QUICK; X for (i=0 ; i<CBLEN; i++) cdb[i] = 0x00; X X switch(toper) { X case TREAD: X if((blknum+numblks)>=tpsize) NewTape(); X cdb[0] = CMD_SCSI_READ; X cdb[2] = (UBYTE) ( (blknum >> 8) & 0x00ff); X cdb[3] = (UBYTE) (blknum & 0x00ff); X cdb[4] = (UBYTE) numblks ; X cmd->scsi_Data = (UWORD *) TapeBuff[bn]; X cmd->scsi_Length = rwlen; X cmd->scsi_Flags = SCSIF_READ; X MPR2("Reading block %d * %d\n",blknum,numblks) X break; X X case TWRITE: X if((blknum+numblks)>=tpsize) NewTape(); X cdb[0] = CMD_SCSI_WRITE; X cdb[2] = (UBYTE)(blknum >> 8) & 0x00ff; X cdb[3] = (UBYTE)(blknum & 0x00ff); X cdb[4] = (UBYTE) numblks ; X /* cmd->scsi_Data = (UWORD *) TapeBuff[bn]; */ /* 2090A bug fix */ X cmd->scsi_Data = (UWORD *) ((ULONG) TapeBuff[bn] | bugmask); X cmd->scsi_Length = rwlen; X cmd->scsi_Flags = SCSIF_WRITE; X MPR2("Writing block %d * %d\n",blknum,numblks) X break; X X case TREWIND: X cdb[0] = CMD_REZERO; X cmd->scsi_Data = (UWORD *) TapeBuff[bn]; X cmd->scsi_Length = 0; X cmd->scsi_Flags = 0; X MPR0("Rewinding\n") X break; X X case TSENSE: X cdb[0] = CMD_REQUEST_SENSE; X cdb[4] = 28; /* extended sense */ X cmd->scsi_Length = 28; X cmd->scsi_Data = (UWORD *) sns; X cmd->scsi_Flags = SCSIF_READ; X MPR0("Sense:") X break; X X case RDCAP: X cdb[0] = CMD_READ_CAPACITY; X cmd->scsi_Length = 8; X cmd->scsi_Data = (UWORD *) sns; X cmd->scsi_Flags = SCSIF_READ; X MPR0("Capacity:") X break; X X case RAWCMD: /* Convert hex in tape buffer to bytes in command buffer. */ X i = 0; /* Bytes are specified by hex digit pairs sep. by blanks */ X z = (char *)TapeBuff[bn]; /* terminated by newline */ X while(z[0]!='\n' && i<32) cdb[i++] = (UBYTE) 0xff & strtol(z,&z,16); X cmd->scsi_Data = (UWORD *) sns; X cmd->scsi_Length = 0; X cmd->scsi_Flags = 0; X MPR0("Raw command\n") X break; X X } X if(ctl == CTLWAIT) { X DoIO ((struct IORequest *)ior); /* start sync io */ X return((long)((ior->io_Error << 8) + cmd->scsi_Status)); X } X else { X BeginIO((struct IORequest *)ior); /* start async io */ X if(ior->io_Error) X return((long)((ior->io_Error << 8) + cmd->scsi_Status)); X if( !(ior->io_Flags & IOF_QUICK) ) inprog = TRUE; X return(0L); X } X} X X/************************************************************************** X* NewTape() Displays a requester asking user to insert a new tape. X*/ X Xvoid NewTape(void) X{ X extern ULONG blknum; X extern short reserved; X extern void DoSense(); X X static struct IntuiText reqtext[] = { X { AUTOFRONTPEN,AUTOBACKPEN,AUTODRAWMODE,AUTOLEFTEDGE,AUTOTOPEDGE,AUTOITEXTFONT, X " EOT: Insert next tape", AUTONEXTTEXT }, X { AUTOFRONTPEN,AUTOBACKPEN,AUTODRAWMODE,AUTOLEFTEDGE,AUTOTOPEDGE,AUTOITEXTFONT, X "Continue", AUTONEXTTEXT }, X { AUTOFRONTPEN,AUTOBACKPEN,AUTODRAWMODE,AUTOLEFTEDGE,AUTOTOPEDGE,AUTOITEXTFONT, X "Quit", AUTONEXTTEXT } X }; X X TapeIO(TFINISH,0,CTLWAIT); /* yeeks, recursion! */ X MPR0("Time for a new tape\n") X if( AutoRequest(NULL,&reqtext[0],&reqtext[1],&reqtext[2],NULL,NULL,250,50) ) { X blknum=reserved; /* reset block number for new tape */ X DoSense(0); /* eat tape change status (recursion again) */ X } X return; X} END_OF_FILE if test 6492 -ne `wc -c <'tapeio.c'`; then echo shar: \"'tapeio.c'\" unpacked with wrong size! fi # end of 'tapeio.c' fi if test ! -d 'tapemon' ; then echo shar: Creating directory \"'tapemon'\" mkdir 'tapemon' fi if test -f 'tapemon/tapemon.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'tapemon/tapemon.c'\" else echo shar: Extracting \"'tapemon/tapemon.c'\" \(3861 characters\) sed "s/^X//" >'tapemon/tapemon.c' <<'END_OF_FILE' X/** X * TapeMon: a monitor program for the BTNtape handler. X */ X#define MVERSION "TapeMon V1.0" X/* X * (c) Copyright 1990 Robert Rethemeyer X * This software may be freely distributed and redistributed, X * for non-commercial purposes, provided this notice is included. X *------------------------------------------------------------ X * Run TapeMon from a CLI to receive informational messages X * from the BTN-Tape handler process. To terminate the X * monitor program, break the CLI using control-C or BREAK. X */ X#include <exec/types.h> X#include <exec/nodes.h> X#include <exec/lists.h> X#include <exec/ports.h> X#include <exec/tasks.h> X#include <exec/execbase.h> X#include <libraries/dos.h> X#include <stdlib.h> X#include <stdio.h> X#include <string.h> X#include "/tplink.h" X X#if defined AZTEC_C X #include <functions.h> X#elif defined LATTICE X #include <proto/exec.h> X #include <proto/dos.h> X#endif X Xextern struct DosLibrary *DOSBase; X Xvoid main(int,char *[]); Xvoid main(int argc, char *argv[]) X{ X struct Task *tapeproc; X struct tplink *linktp; X char *tapename; X ULONG x; X short run = 1; X BYTE signum; X BYTE oldpri; X X printf("*** BTN-Tape Handler & Monitor ***\n(c) Copyright 1990 Robert Rethemeyer\n"); X X if(argc > 1) tapename = argv[1]; X else tapename = "TAPE"; X if (!(tapeproc = FindTask(tapename))) { X printf("Process %s not found...\n (be sure to use caps, no ':')\n",tapename); X exit(30); X } X if (!(linktp = (struct tplink *) tapeproc->tc_UserData)) { X printf("No linkage structure...\n wrong process, or\n handler not active yet?\n"); X exit(31); X } X printf("%s: Proc %X DevNode %X\n",tapename,tapeproc,linktp->devnode); X X if (strcmp(linktp->keyword,"TapeHandler")) { X printf("Process %s doesn't look like BTN-Tape\n",tapename); X exit(32); X } X X if (linktp->montask) { X printf("There is already a TapeMon running\n"); X exit(33); X } X X if (!linktp->handsig) { X printf("Handler has no signal\n"); X exit(34); X } X X signum = AllocSignal(-1); X if (signum == -1) { X printf("Unable to allocate signal for TapeMon\n"); X exit(35); X } X linktp->monsig = 1UL << signum; /* give mask to tape handler */ X linktp->montask = FindTask(0); /* tell it where I am also */ X printf("%s Unit %X\n",linktp->driver,*(linktp->unit)); X if(linktp->sense) X printf("Last sense= %X,%02X\n",linktp->sense,linktp->xsense); X printf("Use ^C to terminate TapeMon\n%s\n",linktp->version); X X /* Set the monitor priority to the same as that of the handler */ X oldpri = SetTaskPri (linktp->montask, (long)tapeproc->tc_Node.ln_Pri); X X /* The main loop. Wait for a signal from the handler, then print the X contents of dbb. Some extra handshaking must then be done to sync X the two processes and prevent races. If a control-C occurs during X a Wait, then finish whatever was in progress before ending the loop. X */ X X while(run) { X x=Wait(linktp->monsig | SIGBREAKF_CTRL_C); /* Wait for req from hndlr */ X if (x & SIGBREAKF_CTRL_C) run = 0; X if(!(x & linktp->monsig) ) continue; X X printf(" %s",linktp->dbb); /* print handler's message */ X Signal(tapeproc, linktp->handsig); /* tell it we are 'done' */ X X x=Wait(linktp->monsig | SIGBREAKF_CTRL_C); /* Wait for ack of 'done' */ X if (x & SIGBREAKF_CTRL_C) run = 0; X if(!(x & linktp->monsig) ) Wait(linktp->monsig); X X Signal(tapeproc, linktp->handsig); /* Ack his ack */ X } X X /* Clean up and exit */ X X SetTaskPri(linktp->montask, (long) oldpri); /* restore priority */ X linktp->montask = NULL; /* break link with handler */ X linktp->monsig = 0; X FreeSignal((ULONG)signum); X printf("TapeMon terminated\n"); X exit(0); X} END_OF_FILE if test 3861 -ne `wc -c <'tapemon/tapemon.c'`; then echo shar: \"'tapemon/tapemon.c'\" unpacked with wrong size! fi # end of 'tapemon/tapemon.c' fi if test -f 'tapemon/tapemon.doc' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'tapemon/tapemon.doc'\" else echo shar: Extracting \"'tapemon/tapemon.doc'\" \(3964 characters\) sed "s/^X//" >'tapemon/tapemon.doc' <<'END_OF_FILE' X**** TapeMon: a monitor program for BTNtape handler **** X**** Version 1.0 09/10/90 **** X**** Freeware by Bob Rethemeyer (DrBob@cup.portal.com) **** X**** (c) Copyright 1990 Robert Rethemeyer **** X XTapeMon is an optional companion program to the BTNtape SCSIdirect Xtape handler. Since the handler cannot directly inform you of what Xit is doing, TapeMon, running in a separate CLI, communicates with Xthe handler and prints information for you. Think of it as a window Xinto the handler. X XTo run TapeMon, bring up a separate CLI window. Enter "TapeMon" or X"TapeMon name", where name is the name of the handler device process. XIf you do not enter the name, the monitor will default to using "TAPE". XIf you do enter the name, it must be in uppercase letters, and must Xnot have an ending colon. X XThe handler must be loaded and running for TapeMon to work. Otherwise Xit prints a message and immediately quits. If you have mounted the Xtape handler but not accessed the tape yet, the handler is not yet loaded, Xand TapeMon will give up. To avoid this, invoke TapeMon after starting Xtape access, or use "Mount = 1" in your mountlist entry. X XOnce the handler is loaded and running, you may invoke or terminate Xthe monitor at any time (but only one TapeMon may run at a time). XTo terminate the monitor, enter control-C from the TapeMon CLI window, Xor send a BREAK command from another CLI. X XIf the handler encounters a tape error, it remembers the data returned Xby SENSE. When TapeMon is started, it prints the retained sense data. XSo if you weren't running TapeMon at the time an error occurs, you can Xstill see the sense data by starting TapeMon after the fact. X XThe following summarizes the messages from the handler/monitor: X X Opened at block x printed when the TAPE: file is opened by DOS. X x is the first block number of the file. X X Closed at block x printed when the TAPE: file is closed by DOS. X x is the next available block. X X Writing block x * n printed when a tape write is started by the X handler. x = starting block, n = number of blocks X X Reading block x * n printed when a tape read is started by the handler. X X Unsupported_pkt= x printed when DOS sends a packet which the handler X rejects. Example: 25 for the INFO command. X X Rewinding printed when handler starts a tape rewind X X Raw command printed when handler receives a raw command request X X Last sense= x,yy retained sense data printed at TapeMon startup X X Sense: io_Error= z Sense= x,yy printed when the handler issues SENSE X to the tape drive. z is the Amiga X error code returned by the scsi driver, X n is the basic sense code returned by X the drive, and yy is the extended sense. X X Capacity: xxxx * yyyy = zzzzzzzz prints the capacity of the tape volume. X x is the number of blocks on the tape, X y is the size of a block, and z is the X total volume capacity in bytes. X X Can't get memory for tape buffers printed for Open() attempts when not X enough memory is available for buffers. X X Time for a new tape printed when EOT requester displayed X X XHOW IT WORKS X XTapeMon works by finding the tape handler process and locating a common Xdata structure attached to it. The monitor waits for signals from the Xhandler. The handler detects the presence of the monitor and signals Xit when a message needs to be printed. A break signal causes the monitor Xto disconnect itself from the handler and terminate. X END_OF_FILE if test 3964 -ne `wc -c <'tapemon/tapemon.doc'`; then echo shar: \"'tapemon/tapemon.doc'\" unpacked with wrong size! fi # end of 'tapemon/tapemon.doc' fi if test -f 'tapemon/tapemon.lmk' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'tapemon/tapemon.lmk'\" else echo shar: Extracting \"'tapemon/tapemon.lmk'\" \(231 characters\) sed "s/^X//" >'tapemon/tapemon.lmk' <<'END_OF_FILE' X# LATTICE MAKEFILE FOR TAPE MONITOR X XCFLAGS= -b1 -mat -cakfsu X XLIBS=LIB:lc.lib+LIB:amiga.lib X Xtapemon : tapemon.o X blink FROM LIB:c.o+tapemon.o TO $@ SC SD LIB $(LIBS) X Xtapemon.o : tapemon.c /tplink.h X LC $(CFLAGS) tapemon.c X END_OF_FILE if test 231 -ne `wc -c <'tapemon/tapemon.lmk'`; then echo shar: \"'tapemon/tapemon.lmk'\" unpacked with wrong size! fi # end of 'tapemon/tapemon.lmk' fi if test -f 'tapemon/tapemon.uu' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'tapemon/tapemon.uu'\" else echo shar: Extracting \"'tapemon/tapemon.uu'\" \(10953 characters\) sed "s/^X//" >'tapemon/tapemon.uu' <<'END_OF_FILE' Xbegin 644 tapemon XM```#\P`````````"``````````$```;T```!(0```^D```;T2.=^_B1()`!)_ XM^0`````L>``$1_D```(<<@`@/````)I@`B;!4<C__"E/`EPI3@)40JP"6'``? XM(CP``#``3J[^SD/Z`5IP`$ZN_=@I0`.P9@9P9&```/PF;@$4*6L`F`)02JL`# XMK&=H(`^0KP`X!H````"`*4`"("!K`*S1R-'((F@`$-/)T\D@`G(`$ADI20)D$ XMT(%2@$)G4H`"0/_^G\!5@$)W"``@`E.`U($?L@``(`!3@E'(__8?O``@(`!3> XM@A^Q(``@`%'*__@B3R\)8'(I:P`Z`B!P?U*`T:P"($'K`%Q.KOZ`0>L`7$ZNU XM_HPI0`)8+P`D0"`J`"1G$BQL`[`@0"(H```I00)03J[_@B(J`"!G&B0\```#% XM[4ZN_^(I0`)@9PKEB"!`)V@`"`"D(&P"6"\(2&P"'"!H`"0I:``$`F1.N@1RB XM3KH3VG``8`0@+P`$+P`@+`)(9P0@0$Z03KH.LBQX``0B;`.P3J[^8DZZ!$A*U XMK`)89QHB+`)@9P1.KO_<+'@`!$ZN_WPB;`)83J[^AB`?+FP"7$S??WY.=61OU XM<RYL:6)R87)Y`$Y5_^R_[`(@90`(9DCG#S(N+0`(>@%(>@(>3KH#]%A/<`&^) XM@&\,(&T`#"MH``3_]&`(0?H"2BM(__0B;?_T+'@`!$ZN_MHF0"`+9A@O+?_T/ XM2'H",DZZ!"9(>``>3KH+/D_O``PD:P!8(`IF$DAZ`DY.N@.>2'@`'TZZ"R)0) XM3R\J``PO"R\M__1(>@)X3KH)P$_O`!`@4D/Z`H(0&+`99@9*`&;V9Q@O+?_T< XM2'H">DZZ`\Q(>``@3KH*Y$_O``Q*J@`@9Q)(>@*(3KH#1DAX`"%.N@K*4$]*% XMJ@`89A)(>@*43KH#+DAX`").N@JR4$]P_RQX``1.KOZV*``,!`#_9A)(>@*(2 XM3KH#"DAX`"-.N@J.4$]P`!`$<@'AH25!`!R3R2QX``1.KO[:)4``("!J`!`O8 XM$"\J``A(>@)Z3KH)$D_O``Q**@`D9QQP`!`J`"1R`!(J`"4O`2\`2'H"9$ZZG XM"/!/[P`,+RH`!$AZ`FI.N@,.4$]P`!`K``DB:@`@+'@`!$ZN_M0;0/_L2D5G7 XM<"`J`!P`0!``+'@`!$ZN_L(L``@&``QG`GH`(`;`J@`<9]HO*@`42'H"0$ZZ9 XM`L103R)+("H`&"QX``1.KOZ\("H`'`!`$`!.KO["+``(!@`,9P)Z`"`&(BH`? XM',"!9@8@`4ZN_L(B2R`J`!A.KOZ\8(QP`!`M_^PB:@`@+'@`!$ZN_M1"J@`@= XM0JH`''``$`1.KOZP2'H!V$ZZ`>Q"ETZZ"7),[4SP_]!.74YU*BHJ($)43BU47 XM87!E($AA;F1L97(@)B!-;VYI=&]R("HJ*@JI($-O<'ER:6=H="`Q.3DP(%)O@ XM8F5R="!2971H96UE>65R"@``5$%010``4')O8V5S<R`E<R!N;W0@9F]U;F0N- XM+BX*("AB92!S=7)E('1O('5S92!C87!S+"!N;R`G.B<I"@!.;R!L:6YK86=E' XM('-T<G5C='5R92XN+@H@=W)O;F<@<')O8V5S<RP@;W(*(&AA;F1L97(@;F]TW XM(&%C=&EV92!Y970_"@``)7,Z(%!R;V,@)5@@1&5V3F]D92`E6`H`5&%P94AA9 XM;F1L97(`4')O8V5S<R`E<R!D;V5S;B=T(&QO;VL@;&EK92!"5$XM5&%P90H`? XM`%1H97)E(&ES(&%L<F5A9'D@82!487!E36]N(')U;FYI;F<*`$AA;F1L97(@4 XM:&%S(&YO('-I9VYA;`H``%5N86)L92!T;R!A;&QO8V%T92!S:6=N86P@9F]RE XM(%1A<&5-;VX*```E<R!5;FET("58"@!,87-T('-E;G-E/2`E6"PE,#)8"@``> XM57-E(%Y#('1O('1E<FUI;F%T92!487!E36]N"B5S"@`@)7,`5&%P94UO;B!T: XM97)M:6YA=&5D"@!.=4YU2.<#$"9O`!`@2TH89OQ3B)'++`A^`!X;2H=G,E.LJ XM`$9M%B!L`#Y#Z``!*4D`/B`'$(!R`!(`8-P@!W(`$@!(;``Z+P%.N@%V4$\BO XM`&#&2&P`.DAX__].N@%D4$\@!DS?",!.=0```````'!A3E7_W$CG#S`F;P!$0 XM?`!![0`,*TC_\AX;2@=G``$*<"6^`&8``,P>&W``$`=R&%U!:P``B+![$`AF? XM]$[[$`0`9&```%``>&```!H`<&```!0`<V````(@;?_R)%@K2/_R8$H@;?_R6 XM*!@K2/_R1>W_['H'2H5K%B`$<@_`@4'Z`,#1P!204XKHA%.%8.9"+?_M8!H@$ XM;?_R*!@K2/_R+P1(;?_E3KH1.%!/1>W_Y2\*3KK^Y%A/W(!@`/]>4H93K`!&4 XM;1@@;``^0^@``2E)`#X@!Q"`<@`2`&``_SYP`!`'2&P`.B\`3KH`:E!/(@!@Z XM`/\H4H93K`!&;1@@;``^0^@``2E)`#X@!Q"`<@`2`&``_PAP`!`'2&P`.B\`U XM3KH`-%!/(@!@`/[R2&P`.DAX__].N@`@(`9,[0SP_\1.74YU,#$R,S0U-C<X! XM.4%#1$5&````3E7_[$CG+Q`N+P`T)F\`."@'<#'`JP`89P9P_V```G`(*P`'A XM`!I6P$0`2(!(P"P`2JL`%&8``(0(*P`"`!MF>G``)T``#'+_OH%G``)"+PM.9 XMN@^*6$]*@&<,".L`!0`;</]@``(J".L``0`;2@9G#B`K`!0B`$2!)T$`#&`([ XM("L`%"=```Q3JP`,;18@:P`$0^@``2=)``0@!Q"`<@`2`&`2(`=R`!(`+PLO/ XM`6$`_U)03R(`(`%@``'6""L``@`;9UAP_[Z`9@9P`&```<(@!QM`__]*!F<B@ XM<@J^@68<<@(O`4AZ`;(O*P`<*T'_\$ZZ"$Q/[P`,*@!@&G(!+P%(;?__+RL`A XM'"M!__!.N@@P3^\`#"H`?O]@``#@".L``0`;2@9G4G#_OH!G3%2K``QR"KZ!F XM9B8@:P`$0^@``2=)``00O``-(BL`#$J!:PHO"R\`80#^KE!/4JL`#"!K``1#= XMZ``!)TD`!"`'$(`B*P`,2H%K``$<?O\@*P`$D*L`$"M`__!G<@@K``8`&F=26 XM2'@``D*G+RL`'$ZZ`R!/[P`,*T#_[$H&9SA3K?_L;3)"IR\M_^PO*P`<3KH#6 XM`$AX``%(;?_]+RL`'$ZZ#^Q/[P`82JP"-&8*$"W__7(:L`%GR"\M__`O*P`0W XM+RL`'$ZZ!U!/[P`,*@!@`GH`</^Z@&8(".L`!0`;8`RZK?_P9P8(ZP`$`!M*: XM!F<.(BL`%"0!1((G0@`,8!@(*P`"`!MG"'(`)T$`#&`((BL`%"=!``P@:P`0Q XM)T@`!+Z`9RY3JP`,;18@:P`$0^@``2=)``0@!Q"`<@`2`&`2(`=R`!(`+PLO# XM`6$`_9!03R(`<##`JP`89P1P_V`,</^X@&8$<`!@`B`$3-\(]$Y=3G4-"@``, XM``````````!P82YL`EQ.N@]Z2'D````43KH#'```````````<&%(YR`P)F\`[ XM$"1+2A)G)'``$!)![`")"#```0@`9PIR`!(`=""2@F`$<@`2`!2!4HI@V"`+( XM3-\,!$YU``````````!P84Y5__A(YP,P)F\`("1O`"0N+P`H($I*&&;\4XB16 XMRBP(($M*&&;\4XB1RR`((DO3P"M)__B\AV,"+`<@!B!*8`(2V%.`9/H@;?_XC XM0C!H`"`+3-\,P$Y=3G4@+P`((&\`!$Y5__0B3W(*3KH$4`9!`#`2P4J`9O`@] XM"1#AO\EF^D(0D(].74YU```@+P`((&\`!$Y5__0B3R(``D$`!P9!`#`2P>:(6 XM9O`@"1#AO\EF^D(0D(].74YU```P,3(S-#4V-S@Y86)C9&5F("\`""!O``1#& XM[P`$,@`"00`/$OL0W.B(9O(@"2(/6($0X;*)9OI"$)"!3G4@;P`$(DAR`'``\ XM+P(,$``K9P8,$``M9@)22!`8!```,&T2#```"6X,)`'E@=*"TH'2@&#F#!$`! XM+68"1($D'R`(4X`@;P`(((&0B4YU+P<N+P`(4JP#J%.L`$9M%B!L`#Y#Z``!N XM*4D`/B`'$(!R`!(`8!0@!W(`$@!(;``Z+P%.NON(4$\B`"X?3G5.50``+PLF' XM;P`,0JP#J$AM``PO"TAZ_ZQ.N@BV2&P`.DAX__].NOM8("P#J"9M__Q.74YU\ XM``!(YP\0+B\`&"PO`!PJ+P`@+P=.N@.$6$\F0"`+9@1P_V`>+P4O!B\K``1.< XMN@&@3^\`#"@`2JP"-&<$</]@`B`$3-\(\$YU``````````!P84CG`S`N+P`4C XM2H=N!G``8```I'`(OH!D`BX`(`=6@"X``D?__$7L`!`F4B`+9T`@*P`$L(=MP XM,K"'9@P@4R2(GZP`%"`+8&X@*P`$D(=R"+"!918@2]'')(@D2"23)4``!)^LD XM`!0@"V!,)$LF4V"\(`<B+`"$T(%3@$ZZ`@HB+`"$3KH!XBP`4(8@!E:`+``") XM1O_\+P9.N@,N6$\F0"`+9Q(O!B\+3KH+%BZ'80#_5%!/8`)P`$S?#,!.=0``, XM````````````````2.<#$"XO`!!'[``8(`MG-`@K``(`&V8H""L``0`;9R`@4 XM*P`$D*L`$"P`2H9G$B\&+RL`$"\K`!Q.N@,R3^\`#"938,@O!TZZ"B!83TS?F XM",!.=0``2.<W$"XO`!PF;P`@+"\`)$JL`DQG!$ZZ#=A"K`(T(@<D"R8&+&P#- XML$ZN_]`J`'#_NH!F#DZN_WPI0`(T<`4I0`.L(`5,WPCL3G4`````````````L XM`````````````'!A2.<_`"XO`!PL+P`@*B\`)$JL`DQG!$ZZ#7A"K`(T(`53( XM@"(')`8F`"QL`[!.KO^^*`!P_[B`9@Y.KO]\*4`"-'`6*4`#K"`%#(`````"G XM9Q8,@`````%G"$J`9A@@!F`4(`30AF`.(@=T`'8`+&P#L$ZN_[Y,WP#\3G4`$ XM`$CG-Q`N+P`<)F\`("PO`"1*K`),9P1.N@S\0JP"-"(')`LF!BQL`[!.KO_6F XM*@!P_[J`9@Y.KO]\*4`"-'`%*4`#K"`%3-\([$YU```O!RXO``A*K`),9P1.) XMN@RZ(@<L;`.P3J[_W'``+A].=4CG,``D`"8!2$)(0\3!QL#`P=1#2$)"0M""- XM3-\`#$YU2H!J```>1(!*@6H```Q$@6$``"!$@4YU80``&$2`1(%.=4J!:@``9 XM#$2!80``!D2`3G4O`DA!-`%F```B2$!(04A"-`!G```&A,$P`DA`-`"$P3`"< XM2$(R`B0?3G4O`W80#$$`@&0```;AF5%##$$(`&0```;IF5E##$$@`&0```;E: XMF55#2D%K```&XYE30S0`YJA(0D)"YJI(0X#!-@`P`C0#2$'$P9""9```"%-#L XMT(%D_G(`,@-(0^>X2$#!028?)!].=2\'+B\`"'``*4`"-$J':R*^K```;!P@S XM!^>`0>P":$JP"`!G#B`'YX!![`)HT<`@"&`(<`DI0`.L<``N'TYU````````3 XM``````````!(YP`R)FP#M"`+9Q0D4R)+("L`""QX``1.KO\N)DI@Z)'(*4@#= XMN"E(`[1,WTP`3G5(YP$R+B\`%'`,WH`@!W(`+'@`!$ZN_SHF0"`+9@1P`&`Z" XM)T<`"$7L`[0@:@`$)T@`!)'()HA*DF8")(M*J@`$9P8B:@`$(HLE2P`$2JP`E XM!&8$*4L`!$'K``P@"$S?3(!.=0``````````````````2.<',"XO`!@F;P`<, XM+"\`("\'3KK_`%A/)$`@"F8$</]@-@@J``,``V<02'@``D*G+P=.NOM(3^\`U XM#"\&+PLO*@`$3KK\I$_O``PJ`$JL`C1G!'#_8`(@!4S?#.!.=0``3E7_Q$CGP XM)S`F;P!<)&\`8'X`?`!Z`'``&WP`(/_[<@`K0?_V=/\K0O_R0>W_T!M`__$;7 XM0/_\*T'_Y"M!_^@K2/_,2A-G+'``$!,$0``@9Q170&<444!G"%5`9A9^`6`.- XM?`%@"GH!8`8;?``!__Q2BV#0$!-R,+`!9@92BQM!__MP*K`39@P@4EB2*U#_B XM]E*+8`Y(;?_V+PM.NOG"4$_7P!`3<BZP`68B4HMP*K`39@P@4EB2*U#_\E*+K XM8`Y(;?_R+PM.NOF84$_7P!`3<FRP`68*&WP``?_Q4HM@"')HL`%F`E*+$!MRY XM`!(`&T#_\`1!`%AG``%^!$$`"V<``@I306<D!$$`"V<``1)306<``5!706<`6 XM`;I506<``.1706<``5)@``'X2BW_\6<((%)8DB`08`8@4EB2(!`K0/_L;`IR9 XM`42M_^PK0?_H2JW_Z&<$<"U@"DH&9P1P*V`"<"`;0/_0<``0!B(M_^B"@'``@ XM$`6"@&<(4JW_S%*M_^0O+?_L+RW_S$ZZ^#I03RM`_\@@+?_R2H!J!G(!*T'_! XM\B`M_\@B+?_RDH!([0`"_\1O-"!M_\PB2-/!+P`O"2\(3KH&HD_O``QP`!`M0 XM__LB+?_$(&W_S&`"$,!3@63Z("W_\BM`_\C1K?_D0>W_T"M(_\Q*!V<``3`;8 XM?``@__M@``$F2BW_\6<((%)8DB`08`8@4EB2(!`K0/_L8`#_9$HM__%G""!22 XM6)(@$&`&(%)8DB`0*T#_[$HM__QG$B!M_\P0_``P<@$K0?_D*TC_S"\`+RW_K XMS$ZZ]YY03RM`_\A@`/\R&WP`,/_[("W_\DJ`:@9P""M`__)*+?_Q9P@@4EB2* XM(!!@!B!26)(@$"M`_^Q*+?_\9Q8@;?_,$/P`,!#\`'AR`BM!_^0K2/_,+P`O> XM+?_,3KKW@E!/*T#_R'!8L"W_\&8`_M!(;?_03KKV7EA/8`#^PB!26)(B4"M)[ XM_\QF"$'Z`-@K2/_,(&W_S$H89OQ3B)'M_\PK2/_D("W_\DJ`:R:QP&\B*T#_E XMY&`<<`$K0/_D(%)8DB`0&T#_T$(M_]%@!G``8```C"`M_^0B+?_VLH!L"'0`D XM*T+_]F`$D:W_]DH'9S93K?_D;1AP`"!M_\P0&"\`*TC_S"!M`!!.D%A/8.)3C XMK?_V;4AP`!`M__LO`"!M`!!.D%A/8.A3K?_V;1)P`!`M__LO`"!M`!!.D%A/# XM8.A3K?_D;1AP`"!M_\P0&"\`*TC_S"!M`!!.D%A/8.(@"TS?#.1.74YU``!.S XM5?_T2.<!,"9O`"`D;P`D*VT`$/_V'AI*!V<T<"6^`&8BL!)F!%**8!HO"TAMA XM__8O"F$`_!9/[P`,*T#_^F<$)$!@TG``$`<O`$Z36$]@QDS?#(!.74YU``!.G XM5?_P2.<A,B9O`"P,K````"`#^FP``(80$W(@L`%G#'()L`%G!G(*L`%F!%*+T XM8.A*$V=H("P#^N6`4JP#^D'L!`+1P"1(<"*P$V8F4HLDBTH39PIP(K`39P12: XMBV#R2A-F#$AX``%.N@(D6$]@GD(;8)HDBTH39Q@0$W(@L`%G$'()L`%G"G(*8 XML`%G!%*+8.1*$V8"8`9"&V``_W)*K`/Z9@8@;`)88`1![`0"*4@#_DJL`_IF] XM?$/Z`21-[`/`+-DLV2S9+-D\D2)L`E@@:0`D2'@`*"\H``1(;`/`3KKT>D_O^ XM``PL;`.P0>P#P"(()#P```/N3J[_XBE``FPI0`)T<A`I00)P*4`"?"E!`GCEC XM@"M`__`L>``$D\E.KO[:(&W_\")`(V@`"`"D?@`K0/_T8"HL;`.P3J[_RBE`F XM`FQ.KO_$*4`"=$'Z`*8B""0\```#[4ZN_^(I0`)\?A`@!P!`@`&!K`)H(`<`? XM0(`"@:P"<`"L``"``P)X2JP`@&<$<`!@!B`\``"``"X`0JP`-"`'`$```2E`^ XM`#!P`2E``%8@!P!```(I0`!2<`(I0`!X(`<`0`"`*4``=$'Z`W8I2`),+RP#L XM_B\L`_I.NNJ^0I=.NO943.U,A/_<3EU.=6-O;CHQ,"\Q,"\S,C`O.#`O`"H`B XM````````````````2.<P,BQO`#@@;P`8(F\`'"1O`"`F;P`D("\`*"(O`"PD\ XM+P`P)B\`-$ZN_J1,WTP,3G4``"\+)F\`"$JK`!1G#`@K``,`&V8$<`!@-B\L[ XM`8Q.NO4.6$\G0``$)T``$$J`9@IP#"E``ZQP_V`6)VP!C``4<//!JP`8<``G& XM0``,)T``""9?3G4``````````'!A2.<'`"XO`!`@+```4X`L`$I&:S`@!DC`; XMYX!![`)H*C`(`$H%9QH(!0`$9A0@!DC`YX!![`)H+S`(!$ZZ]MA83U-&8,PO# XM!TZZZ5A83TS?`.!.=0``("\`""!O``1.5?_T(D]L!A#\`"U$@'(*3KKW&`9!_ XM`#`2P4J`9O`0X;_)9OI"$"`(3EV0KP`$3G5.5?_H2.<!,BXO`#1*AVX&</]@X XM``#2<`B^@&0"+@`@!U:`+@`"1__\)&T`""`M``C0A]^L`!1![``0)E`K0/_P\ XM*TC_]"`+9P``D"!+("L`!-'`*TC_[")M__"WR6,0)(LE1P`$+&W_]"R*<`!@3 XM>+?)9AHL4R2.("L`!"(`TH<E00`$+&W_]"R*<`!@6K7(9`B?K``4</]@3K7(K XM9BQ*DV<.(%.SR&,(GZP`%'#_8#C?JP`$2I-G#K/39@H@*0`$T:L`!":1<`!@- XM'BM+__0K;?_L_^@F4V``_VX@;?_T((I"DB5'``1P`$S?3(!.74YU``!(YP<P@ XM+B\`&"9O`!PL+P`@+P=.NO:(6$\D0"`*9@1P_V`>+P8O"R\J``1.NO4@3^\`0 XM#"H`2JP"-&<$</]@`B`%3-\,X$YU```@;P`$(F\`""`O``QO%K/(90S1P-/`Y XM$R!3@&;Z3G42V%.`9OI.=0``3E7_J$CG`0(L>``$0_H`CG``3J[]V"M`_ZAFQ XM"DAX`!1.NOWR6$]^`"!L`F0>*/__(`=#[?^P8`(2V%.`9/I"-7BP0>W_L"E(@ XM`9PO+?^H2'@`*$AX`/IP`"\`+P!(;`&X<@`O`4AL`:0O`4ZZ_1A(>``43KK]> XMH$SM0(#_H$Y=3G4J*B!3=&%C:R!/=F5R9FQO=R`J*@``15A)5```:6YT=6ET/ XM:6]N+FQI8G)A<GD```````````!P84Y5_YA(YS,"?@`@;`)D'BC__W!/OH!OX XM`BX`(`=#[?^O8`(2V%.`9/I"-7BO+'@`!)/)3J[^VBM`_Z8@0$JH`*QG4B(HY XM`*SE@2)!+"D`.$CM``+_GDJ&9@0L*`"@2H9G-"QL`[`B!D'Z`+(D"'8+3J[_W XMT"!'4H<@"!N\``H(KRQL`[`B!B8'0>W_KR0(3J[_T'#_8%(L>``$0_H`C'``% XM3J[]V"M`_YIF!'#_8#I![?^O*4@!["\M_YI(>``\2'@`^G``+P`O`$AL`@A(! XM;`'T2&P!X$*G3KK[]D_O`"13@&<$</]@`G``3-]`S$Y=3G4J*B!5<V5R($%BT XM;W)T(%)E<75E<W1E9"`J*@``0T].5$E.544``$%"3U)4`"HJ*B!"<F5A:SH@5 XM`&EN='5I=&EO;BYL:6)R87)Y`"\'<``B/```,``L>``$3J[^SBX``H<``#``1 XM2H=G($JL`DQG&B!L`DQ.D$J`9@)@#D*L`DQ(>``43KK[ZEA/+A].=6&\3G4`) XM`````^P````"`````0```!0````*`````````_(```/J````AP```"@`````A XM`````````````````````````#H`````````````````````````````````Z XM``````````!<````````````````````````````````````````````````< XM``````````````````````````````````````````"`````!```("`@("`@$ XM("`@*"@H*"@@("`@("`@("`@("`@("`@("!($!`0$!`0$!`0$!`0$!`0A(2$L XMA(2$A(2$A!`0$!`0$!"!@8&!@8$!`0$!`0$!`0$!`0$!`0$!`0$!`1`0$!`0V XM$(*"@H*"@@("`@("`@("`@("`@("`@("`@("$!`0$"`@("`@("`@("`H*"@HD XM*"`@("`@("`@("`@("`@("`@($@0$!`0$!`0$!`0$!`0$!"$A(2$A(2$A(2$( XM$!`0$!`0$(&!@8&!@0$!`0$!`0$!`0$!`0$!`0$!`0$!$!`0$!`0@H*"@H*"V XM`@("`@("`@("`@("`@("`@("`@(0$!`0(````````@#__P````X`#@``````D XM`````````/__````!``$````````&A@```&0__\````$``0````````:+@``7 XM``#__P````X`#@```````!L^`````/__````!``$``````````````',__\`$ XM```$``0````````;6@````#__P````0`!````````!MD`````````^P````%V XM`````````A0```(````!V````<0```&P````!`````$```'P```!M````#H`, X+```8`````````_(`- X`` Xend Xsize 7796 END_OF_FILE if test 10953 -ne `wc -c <'tapemon/tapemon.uu'`; then echo shar: \"'tapemon/tapemon.uu'\" unpacked with wrong size! fi # end of 'tapemon/tapemon.uu' fi if test -f 'tplink.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'tplink.h'\" else echo shar: Extracting \"'tplink.h'\" \(771 characters\) sed "s/^X//" >'tplink.h' <<'END_OF_FILE' X/* Structure shared by BTNtape and TapeMon. Version 1.0 */ X Xstruct tplink { X char *keyword; /* name "TapeHandler" */ X char *version; /* version string */ X char *driver; /* scsi driver name */ X void *devnode; /* device node address*/ X ULONG *unit; /* scsi unit number */ X char *dbb; /* message from handler */ X ULONG handsig; /* handler sig mask */ X ULONG monsig; /* monitor sig mask */ X struct Task *montask; /* monitor task ptr */ X UBYTE sense; /* last sense */ X UBYTE xsense; /* last extended sense*/ X }; END_OF_FILE if test 771 -ne `wc -c <'tplink.h'`; then echo shar: \"'tplink.h'\" unpacked with wrong size! fi # end of 'tplink.h' fi echo shar: End of archive 1 \(of 2\). cp /dev/null ark1isdone MISSING="" for I in 1 2 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked both archives. rm -f ark[1-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0 -- Mail submissions (sources or binaries) to <amiga@uunet.uu.net>. Mail comments to the moderator at <amiga-request@uunet.uu.net>. Post requests for sources, and general discussion to comp.sys.amiga.