home *** CD-ROM | disk | FTP | other *** search
- It's been tape drive weekend here at hack central.
-
- I've had two problems using my A3070 drive with NetBSD -- the
- first is that I couldn't work with multiple files on a single tape.
- Every command after doing a 'mt -f /dev/nrst0 fsf 1' resulted in an
- error. That kinda sucks. The problem appears to be that the SCSI tape
- driver (.../amiga/dev/st.c) will send a mode-select command to the
- driver every time you open the device and the Caliper CP150 (what's
- inside the A3070) doesn't like that very much. It only seems to take
- mode-select when the tape is fully rewound. (The mode-select chooses
- between 120M and 150M operation, and probably does some other stuff,
- too). Here are the patches I used (613 source base). The second
- problem is described after this:
-
- ------------------------------------------------------------------------
- *** arch/amiga/dev/st.c-orig Thu Aug 12 14:49:01 1993
- --- arch/amiga/dev/st.c Sun Sep 5 21:48:40 1993
- ***************
- *** 111,117 ****
- extern int sterror (int unit, struct st_softc *sc, int stat);
- extern int stxsense (int ctlr, int slave, int unit, struct st_softc *sc);
- extern int prtkey (int unit, struct st_softc *sc);
- ! extern int dumpxsense (struct st_xsense *sensebuf);
- extern int prtmodsel (struct mode_select_data *msd, int modlen);
- extern int prtmodstat (struct mode_sense *mode);
-
- --- 111,117 ----
- extern int sterror (int unit, struct st_softc *sc, int stat);
- extern int stxsense (int ctlr, int slave, int unit, struct st_softc *sc);
- extern int prtkey (int unit, struct st_softc *sc);
- ! extern int dumpxsense (struct st_xsense *sensebuf, struct st_softc *sc);
- extern int prtmodsel (struct mode_select_data *msd, int modlen);
- extern int prtmodstat (struct mode_sense *mode);
-
- ***************
- *** 156,163 ****
- */
- static struct st_xsense {
- struct scsi_xsense sc_xsense; /* data from sense */
- ! struct exb_xsense exb_xsense; /* additional info from exabyte */
- } st_xsense[NST];
-
- static struct scsi_fmt_cdb stcmd[NST];
-
- --- 156,168 ----
- */
- static struct st_xsense {
- struct scsi_xsense sc_xsense; /* data from sense */
- ! union {
- ! struct exb_xsense uexb_xsense; /* additional info from exabyte */
- ! struct cpr_xsense ucpr_xsense; /* additional info from caliper */
- ! } u;
- } st_xsense[NST];
- + #define exb_xsense u.uexb_xsense
- + #define cpr_xsense u.ucpr_xsense
-
- static struct scsi_fmt_cdb stcmd[NST];
-
- ***************
- *** 316,325 ****
- if (idstr[i] != ' ')
- break;
- idstr[i+1] = 0;
- ! printf("st%d: %s >%s< rev %s\n", ad->amiga_unit, idstr, &idstr[8],
- &idstr[24]);
- } else if (inqlen == 5)
- ! /* great it's a stupid device, doesn't know it's know name */
- idstr[0] = idstr[8] = '\0';
- else
- idstr[8] = '\0';
- --- 321,330 ----
- if (idstr[i] != ' ')
- break;
- idstr[i+1] = 0;
- ! printf("st%d: %s %s rev %s\n", ad->amiga_unit, idstr, &idstr[8],
- &idstr[24]);
- } else if (inqlen == 5)
- ! /* great it's a stupid device, doesn't know it's own name */
- idstr[0] = idstr[8] = '\0';
- else
- idstr[8] = '\0';
- ***************
- *** 362,367 ****
- --- 367,378 ----
- sc->sc_datalen[CMD_INQUIRY] = 36;
- sc->sc_datalen[CMD_MODE_SELECT] = 12;
- sc->sc_datalen[CMD_MODE_SENSE] = 12;
- + } else if (bcmp("CP150", &idstr[8], 5) == 0) {
- + sc->sc_tapeid = MT_ISCALIPER;
- + sc->sc_datalen[CMD_REQUEST_SENSE] = 14;
- + sc->sc_datalen[CMD_INQUIRY] = 36;
- + sc->sc_datalen[CMD_MODE_SELECT] = 12;
- + sc->sc_datalen[CMD_MODE_SENSE] = 12;
- } else {
- if (idstr[8] == '\0')
- printf("st%d: No ID, assuming Archive\n", ad->amiga_unit);
- ***************
- *** 414,419 ****
- --- 425,431 ----
- struct mode_select_data msd;
- struct mode_sense mode;
- int modlen;
- + int skip_modsel = 0;
- static struct scsi_fmt_cdb modsel = {
- 6,
- CMD_MODE_SELECT, 0, 0, 0, sizeof(msd), 0
- ***************
- *** 471,476 ****
- --- 483,497 ----
- sc->sc_blklen = 512;
- break;
- #endif
- + case MT_ISCALIPER:
- + sc->sc_blklen = 512;
- + stxsense(ctlr, slave, unit, sc);
- + /* Calipers can't handle a mode-select if the tape
- + * isn't rewound.
- + */
- + if (xsense->cpr_xsense.b11)
- + skip_modsel = 1;
- + break;
- case MT_ISWANGTEK:
- sc->sc_blklen = 512;
- break;
- ***************
- *** 485,490 ****
- --- 506,514 ----
- sc->sc_blklen = 512;
- }
-
- + if (skip_modsel)
- + goto mode_selected;
- +
- /* setup for mode select */
- msd.rsvd1 = 0;
- msd.rsvd2 = 0;
- ***************
- *** 513,518 ****
- --- 537,543 ----
- msd.density = 0x4;
- }
- break;
- + case MT_ISCALIPER:
- case MT_ISWANGTEK:
- if (minor (dev) & STDEV_HIDENSITY)
- msd.density = 0x10;
- ***************
- *** 586,591 ****
- --- 611,617 ----
- goto retryselect;
- }
-
- + mode_selected:
- /* drive ready ? */
- stat = scsi_test_unit_rdy(ctlr, slave, unit);
-
- ***************
- *** 622,627 ****
- --- 648,654 ----
- case MT_ISHPDAT:
- case MT_ISVIPER1:
- case MT_ISPYTHON:
- + case MT_ISCALIPER:
- case MT_ISWANGTEK:
- if (xsense->sc_xsense.key == XSK_UNTATTEN)
- stat = scsi_test_unit_rdy(ctlr, slave, unit);
- ***************
- *** 654,660 ****
- stxsense(ctlr, slave, unit, sc);
- #ifdef DEBUG
- if (st_debug & ST_OPEN)
- ! dumpxsense(xsense);
- #endif
- }
- if (stat)
- --- 681,687 ----
- stxsense(ctlr, slave, unit, sc);
- #ifdef DEBUG
- if (st_debug & ST_OPEN)
- ! dumpxsense(xsense, sc);
- #endif
- }
- if (stat)
- ***************
- *** 1387,1394 ****
-
- #ifdef DEBUG
-
- ! dumpxsense(sensebuf)
- struct st_xsense *sensebuf;
- {
- struct st_xsense *xp = sensebuf;
-
- --- 1414,1422 ----
-
- #ifdef DEBUG
-
- ! dumpxsense(sensebuf, sc)
- struct st_xsense *sensebuf;
- + struct st_softc *sc;
- {
- struct st_xsense *xp = sensebuf;
-
- ***************
- *** 1404,1432 ****
- (xp->sc_xsense.info3<<8)|(xp->sc_xsense.info4)) );
- printf("ASenseL 0x%x\n", xp->sc_xsense.len);
-
- ! if (xp->sc_xsense.len != 0x12) /* MT_ISEXB Exabyte only ?? */
- ! return; /* What about others */
-
- ! printf("ASenseC 0x%x\n", xp->exb_xsense.addsens);
- ! printf("AsenseQ 0x%x\n", xp->exb_xsense.addsensq);
- ! printf("R/W Errors 0x%lx\n",
- ! (u_long)((xp->exb_xsense.rwerrcnt2<<16)|
- ! (xp->exb_xsense.rwerrcnt1<<8)|
- ! (xp->exb_xsense.rwerrcnt1)) );
- ! printf("PF 0x%x BPE 0x%x FPE 0x%x ME 0x%x ECO 0x%x TME 0x%x TNP 0x%x BOT 0x%x\n",
- ! xp->exb_xsense.pf, xp->exb_xsense.bpe, xp->exb_xsense.fpe,
- ! xp->exb_xsense.me, xp->exb_xsense.eco, xp->exb_xsense.tme,
- ! xp->exb_xsense.tnp, xp->exb_xsense.bot);
- ! printf("XFR 0x%x TMD 0x%x WP 0x%x FMKE 0x%x URE 0x%x WE1 0x%x SSE 0x%x FE 0x%x\n",
- ! xp->exb_xsense.xfr, xp->exb_xsense.tmd, xp->exb_xsense.wp,
- ! xp->exb_xsense.fmke, xp->exb_xsense.ure, xp->exb_xsense.we1,
- ! xp->exb_xsense.sse, xp->exb_xsense.fe);
- ! printf("WSEB 0x%x WSEO 0x%x\n",
- ! xp->exb_xsense.wseb, xp->exb_xsense.wseo);
- ! printf("Remaining Tape 0x%lx\n",
- ! (u_long)((xp->exb_xsense.tplft2<<16)|
- ! (xp->exb_xsense.tplft1<<8)|
- ! (xp->exb_xsense.tplft0)) );
- }
-
- prtmodsel(msd, modlen)
- --- 1432,1474 ----
- (xp->sc_xsense.info3<<8)|(xp->sc_xsense.info4)) );
- printf("ASenseL 0x%x\n", xp->sc_xsense.len);
-
- ! switch (sc->sc_tapeid) {
- ! case MT_ISEXABYTE:
- ! printf("ASenseC 0x%x\n", xp->exb_xsense.addsens);
- ! printf("AsenseQ 0x%x\n", xp->exb_xsense.addsensq);
- ! printf("R/W Errors 0x%lx\n",
- ! (u_long)((xp->exb_xsense.rwerrcnt2<<16)|
- ! (xp->exb_xsense.rwerrcnt1<<8)|
- ! (xp->exb_xsense.rwerrcnt1)) );
- ! printf("PF 0x%x BPE 0x%x FPE 0x%x ME 0x%x ECO 0x%x TME 0x%x TNP 0x%x BOT 0x%x\n",
- ! xp->exb_xsense.pf, xp->exb_xsense.bpe,
- ! xp->exb_xsense.fpe, xp->exb_xsense.me,
- ! xp->exb_xsense.eco, xp->exb_xsense.tme,
- ! xp->exb_xsense.tnp, xp->exb_xsense.bot);
- ! printf("XFR 0x%x TMD 0x%x WP 0x%x FMKE 0x%x URE 0x%x WE1 0x%x SSE 0x%x FE 0x%x\n",
- ! xp->exb_xsense.xfr, xp->exb_xsense.tmd,
- ! xp->exb_xsense.wp, xp->exb_xsense.fmke,
- ! xp->exb_xsense.ure, xp->exb_xsense.we1,
- ! xp->exb_xsense.sse, xp->exb_xsense.fe);
- ! printf("WSEB 0x%x WSEO 0x%x\n",
- ! xp->exb_xsense.wseb, xp->exb_xsense.wseo);
- ! printf("Remaining Tape 0x%lx\n",
- ! (u_long)((xp->exb_xsense.tplft2<<16)|
- ! (xp->exb_xsense.tplft1<<8)|
- ! (xp->exb_xsense.tplft0)) );
- ! break;
- !
- ! case MT_ISCALIPER:
- ! printf("b8 0x%x (wp 0x%x) b9 0x%x b10 0x%x b11 0x%x b12 0x%x b13 0x%x\n",
- ! xp->cpr_xsense.b8, xp->cpr_xsense.b8 & CPR_WP,
- ! xp->cpr_xsense.b9, xp->cpr_xsense.b10,
- ! xp->cpr_xsense.b11, xp->cpr_xsense.b12,
- ! xp->cpr_xsense.b13);
- ! break;
-
- ! default:
- ! break;
- ! }
- }
-
- prtmodsel(msd, modlen)
- *** arch/amiga/dev/stvar.h-orig Sat May 15 06:45:00 1993
- --- arch/amiga/dev/stvar.h Sun Sep 5 00:05:41 1993
- ***************
- *** 101,106 ****
- --- 101,116 ----
- char venderunique[16];
- };
-
- + struct cpr_xsense {
- + u_char b8;
- + #define CPR_WP 0x10
- + u_char b9;
- + u_char b10;
- + u_char b11;
- + u_char b12;
- + u_char b13;
- + };
- +
- struct st_mode {
- u_char sdl;
- u_char medtype;
- *** sys/mtio.h-orig Sat Jun 19 09:45:39 1993
- --- sys/mtio.h Sat Sep 4 16:42:02 1993
- ***************
- *** 96,101 ****
- --- 96,102 ----
- #define MT_ISPYTHON 0x0f /* Archive Python (DAT) */
- #define MT_ISHPDAT 0x10 /* HP 35450A DAT drive */
- #define MT_ISWANGTEK 0x11 /* WANGTEK 5150ES */
- + #define MT_ISCALIPER 0x12 /* Caliper CP150 */
-
- /* mag tape io control commands */
- #define MTIOCTOP _IOW('m', 1, struct mtop) /* do a mag tape op */
-
- ------------------------------------------------------------------------
-
- The other problem I had was that a tape error would crash the
- kernel -- woo hoo! My specific test case was putting a fresh tape in
- the drive and doing a 'mt -f /dev/rst0 fsf 1'. The problem goes
- something like this: When an I/O operation is done and hasn't failed
- early because something like a mode-select failed, the tape driver
- calls stfinish(), which then calls biodone() on the I/O buffer which
- was being used for the I/O operation. biodone() wakes up anyone who
- was waiting on the buffer; someone (probably the tape driver but I
- haven't checked) is stuck in biowait() sleeping on that buffer.
- biowait() wakes up, looks at the buffer, sees that its error flag is
- set, and proceeds to remove it from its hash queue and put it somewhere
- else. Unfortunately, that buffer was never on a hash queue -- it was
- an element in an array of buffers defined inside st.c. Wa ha ha ha!
- What a good joke! The b_back and b_forw pointers are 0! Here's what I
- did to fix that:
-
- ------------------------------------------------------------------------
- *** kern/vfs_bio.c-orig Sun Aug 8 05:47:13 1993
- --- kern/vfs_bio.c Sun Sep 5 21:48:07 1993
- ***************
- *** 653,660 ****
- * and i believe it's wrong to let bp->b_error override B_ERROR
- * but it certainly appears to work OK this way...
- */
- ! bremhash(bp);
- ! binshash(bp, bfreelist + BQ_AGE);
- }
- if (!bp->b_error)
- bp->b_error = EIO;
- --- 653,663 ----
- * and i believe it's wrong to let bp->b_error override B_ERROR
- * but it certainly appears to work OK this way...
- */
- ! /* Some bufs aren't in the buffer cache, you fool. */
- ! if (bp->b_back && bp->b_forw) {
- ! bremhash(bp);
- ! binshash(bp, bfreelist + BQ_AGE);
- ! }
- }
- if (!bp->b_error)
- bp->b_error = EIO;
- ------------------------------------------------------------------------
-
- --
- ------------------------------------------------------------------------
- Andy Heffernan ahh@netcom.com
-
-