jeff@voder.UUCP (Jeff Gilliam) (02/27/88)
Subject: ht driver enhancements/fixes +FIX Index: sys/vaxmba/{htreg.h,ht.c} 4.3BSD Description: Detailed description of the problem, suggestion, or complaint. Repeat-By: Procedure to repeat the problem. Fix: The following patches fix or change the following: 1) SI tri-density drives are completely supported. 2) The MTIOCIEOT and MTIOCEEOT ioctl()s (to ignore and enable EOT errors) are supported. 3) Tape records longer than the buffer passed to read() return ENOMEM. 4) Attempts to write past EOT return ENOSPC unless MTIOCIEOT done. 5) Serious error conditions are logged to the system error log. 6) Simple read and write errors return errors without obnoxious error reports to the user's terminal or system log. 7) Code for handling error reports and for handling control operations is reorganized and fixed. 8) Close no longer hangs onto chtbuf while the slave is rewinding. This allows other slaves on the same formatter to continue operation concurrently. 9) A race condition in htopen() is fixed. 10) The driver is now extensively commented. 11) Errors in existing comments are corrected. 12) The unused sc_mi field in tu_softc[] is eliminated. 13) No longer any reason to keep rhtbuf around. N.B. This depends on changes to the raw I/O system previously posted. If you haven't installed those changes edit the patch so that rhtbuf[] isn't deleted, and the two physio() calls aren't changed. 14) Short tape records no longer return an error. That's what the residual count is for. 15) File spacing operations use a new manifest constant MAXFC for the frame count, instead of INF. Now less likely to fail on huge files written with small records. To apply this patch: cd /sys patch -p1 < thisfile Index: sys/vaxmba/htreg.h RCS file: RCS/htreg.h,v retrieving revision 1.1 retrieving revision 1.2 diff -c -r1.1 -r1.2 *** /tmp/,RCSt1003648 Fri Feb 26 14:30:55 1988 --- /tmp/,RCSt2003648 Fri Feb 26 14:30:56 1988 *************** *** 44,50 **** #define HTDS_MOL 0010000 /* medium on line */ #define HTDS_WRL 0004000 /* write lock */ #define HTDS_EOT 0002000 /* end of tape */ ! /* bit 9 is unused */ #define HTDS_DPR 0000400 /* drive present (always 1) */ #define HTDS_DRY 0000200 /* drive ready */ #define HTDS_SSC 0000100 /* slave status change */ --- 44,50 ---- #define HTDS_MOL 0010000 /* medium on line */ #define HTDS_WRL 0004000 /* write lock */ #define HTDS_EOT 0002000 /* end of tape */ ! #define HTDS_GCR 0001000 /* gcr status */ #define HTDS_DPR 0000400 /* drive present (always 1) */ #define HTDS_DRY 0000200 /* drive ready */ #define HTDS_SSC 0000100 /* slave status change */ *************** *** 56,62 **** #define HTDS_SLA 0000001 /* slave attention */ #define HTDS_BITS \ ! "\10\20ATA\17ERR\16PIP\15MOL\14WRL\13EOT\11DPR\10DRY\ \7SSC\6PES\5SDWN\4IDB\3TM\2BOT\1SLA" /* hter */ --- 56,62 ---- #define HTDS_SLA 0000001 /* slave attention */ #define HTDS_BITS \ ! "\10\20ATA\17ERR\16PIP\15MOL\14WRL\13EOT\12GCR\11DPR\10DRY\ \7SSC\6PES\5SDWN\4IDB\3TM\2BOT\1SLA" /* hter */ *************** *** 101,108 **** #define HTTC_SAC 0020000 /* slave address change */ #define HTTC_EAODTE 0010000 /* enable abort on data xfer errors */ /* bits 8-10 are density select */ ! #define HTTC_800BPI 0001400 /* in bits 8-10, dens=1600 */ ! #define HTTC_1600BPI 0002000 /* in bits 8-10, dens=800 */ /* bits 4-7 are format select */ #define HTTC_PDP11 0000300 /* in bits 4-7, pdp11 normal format */ #define HTTC_EVEN 0000010 /* select even parity */ --- 101,109 ---- #define HTTC_SAC 0020000 /* slave address change */ #define HTTC_EAODTE 0010000 /* enable abort on data xfer errors */ /* bits 8-10 are density select */ ! #define HTTC_800BPI 0001400 /* in bits 8-10, dens=800 */ ! #define HTTC_1600BPI 0002000 /* in bits 8-10, dens=1600 */ ! #define HTTC_6250BPI 0002400 /* in bits 8-10, dens=6250 */ /* bits 4-7 are format select */ #define HTTC_PDP11 0000300 /* in bits 4-7, pdp11 normal format */ #define HTTC_EVEN 0000010 /* select even parity */ Index: sys/vaxmba/ht.c RCS file: RCS/ht.c,v retrieving revision 1.1 retrieving revision 1.9 diff -c -r1.1 -r1.9 *** /tmp/,RCSt1003662 Fri Feb 26 14:31:19 1988 --- /tmp/,RCSt2003662 Fri Feb 26 14:31:20 1988 *************** *** 12,21 **** * TM03/TU?? tape driver * * TODO: - * cleanup messages on errors * test ioctl's - * see how many rewind interrups we get if we kick when not at BOT - * fixup rle error on block tape code */ #include "../machine/pte.h" --- 12,18 ---- *************** *** 31,37 **** --- 28,36 ---- #include "mtio.h" #include "cmap.h" #include "uio.h" + #include "kernel.h" #include "tty.h" + #include "syslog.h" #include "../vax/cpu.h" #include "mbareg.h" *************** *** 38,44 **** #include "mbavar.h" #include "htreg.h" - struct buf rhtbuf[NHT]; struct buf chtbuf[NHT]; short httypes[] = --- 37,42 ---- *************** *** 54,78 **** /* bits in minor device */ #define TUUNIT(dev) (minor(dev)&03) #define H_NOREWIND 04 ! #define H_1600BPI 08 #define HTUNIT(dev) (tutoht[TUUNIT(dev)]) ! #define INF (daddr_t)1000000L /* a block number that wont exist */ struct tu_softc { ! char sc_openf; ! char sc_flags; ! daddr_t sc_blkno; ! daddr_t sc_nxrec; ! u_short sc_erreg; ! u_short sc_dsreg; ! short sc_resid; ! short sc_dens; ! struct mba_device *sc_mi; ! int sc_slave; struct tty *sc_ttyp; /* record user's tty for errors */ } tu_softc[NTU]; short tutoht[NTU]; /* --- 52,78 ---- /* bits in minor device */ #define TUUNIT(dev) (minor(dev)&03) #define H_NOREWIND 04 ! #define H_1600BPI 010 ! #define H_6250BPI 020 #define HTUNIT(dev) (tutoht[TUUNIT(dev)]) ! #define INF (daddr_t)1000000L /* a block number that won't exist */ ! #define MAXFC 32768 /* maximum frame count */ struct tu_softc { ! char sc_openf; /* exclusive open */ ! char sc_flags; /* state flags */ ! daddr_t sc_blkno; /* next block to transfer */ ! daddr_t sc_nxrec; /* next record on tape */ ! u_short sc_erreg; /* image of hter */ ! u_short sc_dsreg; /* image of htds */ ! short sc_resid; /* residual from transfer */ ! short sc_dens; /* sticky selected density */ ! int sc_slave; /* slave number on formatter */ struct tty *sc_ttyp; /* record user's tty for errors */ } tu_softc[NTU]; + /* slave to controller mapping table */ short tutoht[NTU]; /* *************** *** 81,86 **** --- 81,87 ---- #define H_WRITTEN 1 /* last operation was a write */ #define H_ERASED 2 /* last write retry was an erase gap */ #define H_REWIND 4 /* last unit start was a rewind */ + #define H_IEOT 8 /* ignore EOT condition */ char hter_bits[] = HTER_BITS; char htds_bits[] = HTDS_BITS; *************** *** 102,108 **** htaddr->httc = sn; if (htaddr->htdt & HTDT_SPR) { - sc->sc_mi = mi; sc->sc_slave = sn; tutoht[ms->ms_unit] = mi->mi_unit; return (1); --- 103,108 ---- *************** *** 110,115 **** --- 110,122 ---- return (0); } + /* + * Open the device. Tapes are unique open + * devices, so we refuse if it is already open. + * We also check that a tape is available, and + * don't block waiting here; if you want to wait + * for a tape you should timeout in user code. + */ htopen(dev, flag) dev_t dev; int flag; *************** *** 126,150 **** if ((sc = &tu_softc[tuunit])->sc_openf) return (EBUSY); olddens = sc->sc_dens; ! dens = sc->sc_dens = ! ((minor(dev)&H_1600BPI)?HTTC_1600BPI:HTTC_800BPI)| ! HTTC_PDP11|sc->sc_slave; htcommand(dev, HT_SENSE, 1); sc->sc_dens = olddens; if ((sc->sc_dsreg & HTDS_MOL) == 0) { uprintf("tu%d: not online\n", tuunit); return (EIO); } if ((flag&FWRITE) && (sc->sc_dsreg&HTDS_WRL)) { uprintf("tu%d: no write ring\n", tuunit); return (EIO); } if ((sc->sc_dsreg & HTDS_BOT) == 0 && (flag&FWRITE) && dens != sc->sc_dens) { uprintf("tu%d: can't change density in mid-tape\n", tuunit); return (EIO); } - sc->sc_openf = 1; sc->sc_blkno = (daddr_t)0; sc->sc_nxrec = INF; sc->sc_flags = 0; --- 133,168 ---- if ((sc = &tu_softc[tuunit])->sc_openf) return (EBUSY); olddens = sc->sc_dens; ! if (minor(dev) & H_6250BPI) ! dens = sc->sc_dens = HTTC_6250BPI|HTTC_PDP11|sc->sc_slave; ! else if (minor(dev) & H_1600BPI) ! dens = sc->sc_dens = HTTC_1600BPI|HTTC_PDP11|sc->sc_slave; ! else ! dens = sc->sc_dens = HTTC_800BPI|HTTC_PDP11|sc->sc_slave; ! sc->sc_openf = 1; ! get: htcommand(dev, HT_SENSE, 1); + if (sc->sc_dsreg & HTDS_PIP) { + sleep((caddr_t)&lbolt, PZERO+1); + goto get; + } sc->sc_dens = olddens; if ((sc->sc_dsreg & HTDS_MOL) == 0) { uprintf("tu%d: not online\n", tuunit); + sc->sc_openf = 0; return (EIO); } if ((flag&FWRITE) && (sc->sc_dsreg&HTDS_WRL)) { uprintf("tu%d: no write ring\n", tuunit); + sc->sc_openf = 0; return (EIO); } if ((sc->sc_dsreg & HTDS_BOT) == 0 && (flag&FWRITE) && dens != sc->sc_dens) { uprintf("tu%d: can't change density in mid-tape\n", tuunit); + sc->sc_openf = 0; return (EIO); } sc->sc_blkno = (daddr_t)0; sc->sc_nxrec = INF; sc->sc_flags = 0; *************** *** 153,158 **** --- 171,184 ---- return (0); } + /* + * Close tape device. + * + * If tape was open for writing or last operation was + * a write, then write two EOF's and backspace over the last one. + * Unless this is a non-rewinding special file rewind the tape. + * Make the tape available to others. + */ htclose(dev, flag) register dev_t dev; register flag; *************** *** 165,174 **** --- 191,209 ---- htcommand(dev, HT_SREV, 1); } if ((minor(dev)&H_NOREWIND) == 0) + /* + * 0 count means don't hang waiting for rewind complete. + * Further opens are stalled until the rewind completes + * by testing HTDS_PIP (positioning in progress). + */ htcommand(dev, HT_REW, 0); sc->sc_openf = 0; } + /* + * Execute a command on the tape drive + * a specified number of times. + */ htcommand(dev, com, count) dev_t dev; int com, count; *************** *** 179,184 **** --- 214,223 ---- bp = &chtbuf[HTUNIT(dev)]; s = spl5(); while (bp->b_flags&B_BUSY) { + /* + * This special check is because B_BUSY never + * gets cleared in the non-waiting rewind case. + */ if(bp->b_repcnt == 0 && (bp->b_flags&B_DONE)) break; bp->b_flags |= B_WANTED; *************** *** 191,196 **** --- 230,239 ---- bp->b_repcnt = count; bp->b_blkno = 0; htstrategy(bp); + /* + * In case of rewind from close, don't wait. + * This is the only case where count can be 0. + */ if (count == 0) return; iowait(bp); *************** *** 199,204 **** --- 242,250 ---- bp->b_flags &= B_ERROR; } + /* + * Queue a tape operation. + */ htstrategy(bp) register struct buf *bp; { *************** *** 206,211 **** --- 252,260 ---- register struct buf *dp; register int s; + /* + * Put transfer at end of unit queue. + */ bp->av_forw = NULL; dp = &mi->mi_tab; s = spl5(); *************** *** 214,224 **** --- 263,280 ---- else dp->b_actl->av_forw = bp; dp->b_actl = bp; + /* + * If the controller is not busy, get + * it going. + */ if (dp->b_active == 0) mbustart(mi); splx(s); } + /* + * Start activity on an ht controller. + */ htustart(mi) register struct mba_device *mi; { *************** *** 229,267 **** daddr_t blkno; htaddr->httc = sc->sc_dens; ! #ifdef notdef ! /* unneeded, may hang controller */ ! if (bp == &chtbuf[HTUNIT(bp->b_dev)] && bp->b_command == HT_SENSE) { ! htaddr->htcs1 = HT_SENSE|HT_GO; ! mbclrattn(mi); ! } ! #endif sc->sc_dsreg = htaddr->htds; sc->sc_erreg = htaddr->hter; sc->sc_resid = htaddr->htfc; sc->sc_flags &= ~(H_WRITTEN|H_REWIND); if ((htaddr->htdt & HTDT_SPR) == 0 || (htaddr->htds & HTDS_MOL) == 0) if (sc->sc_openf > 0) sc->sc_openf = -1; if (sc->sc_openf < 0) { bp->b_flags |= B_ERROR; return (MBU_NEXT); } ! if (bp != &chtbuf[HTUNIT(bp->b_dev)]) { ! if (bdbtofsb(bp->b_blkno) > sc->sc_nxrec) { ! bp->b_flags |= B_ERROR; ! bp->b_error = ENXIO; ! return (MBU_NEXT); ! } ! if (bdbtofsb(bp->b_blkno) == sc->sc_nxrec && ! bp->b_flags&B_READ) { ! bp->b_resid = bp->b_bcount; ! clrbuf(bp); ! return (MBU_NEXT); ! } ! if ((bp->b_flags&B_READ)==0) ! sc->sc_nxrec = bdbtofsb(bp->b_blkno) + 1; ! } else { if (bp->b_command == HT_SENSE) return (MBU_NEXT); if (bp->b_command == HT_REW) --- 285,317 ---- daddr_t blkno; htaddr->httc = sc->sc_dens; ! /* ! * Record pre-transfer status (e.g. for HT_SENSE) ! */ sc->sc_dsreg = htaddr->htds; sc->sc_erreg = htaddr->hter; sc->sc_resid = htaddr->htfc; + /* + * Default is that last command was NOT a write command; + * if we do a write command we will notice this in htdtint(). + */ sc->sc_flags &= ~(H_WRITTEN|H_REWIND); if ((htaddr->htdt & HTDT_SPR) == 0 || (htaddr->htds & HTDS_MOL) == 0) if (sc->sc_openf > 0) sc->sc_openf = -1; if (sc->sc_openf < 0) { + /* + * Have had a hard error on a non-raw tape + * or the tape unit is now unavailable + * (e.g. taken off line). + */ bp->b_flags |= B_ERROR; return (MBU_NEXT); } ! if (bp == &chtbuf[HTUNIT(bp->b_dev)]) { ! /* ! * Execute control operation with the specified count. ! */ if (bp->b_command == HT_SENSE) return (MBU_NEXT); if (bp->b_command == HT_REW) *************** *** 271,279 **** --- 321,366 ---- htaddr->htcs1 = bp->b_command|HT_GO; return (MBU_STARTED); } + /* + * The following checks handle boundary cases for operation + * on non-raw tapes. On raw tape the initialization of + * sc->sc_nxrec by htphys causes them to be skipped normally + * (except in the case of retries). + */ + if (bdbtofsb(bp->b_blkno) > sc->sc_nxrec) { + /* + * Can't read past known end-of-file. + */ + bp->b_flags |= B_ERROR; + bp->b_error = ENXIO; + return (MBU_NEXT); + } + if (bdbtofsb(bp->b_blkno) == sc->sc_nxrec && bp->b_flags&B_READ) { + /* + * Reading at end of file returns 0 bytes. + */ + bp->b_resid = bp->b_bcount; + clrbuf(bp); + return (MBU_NEXT); + } + if ((bp->b_flags&B_READ)==0) + /* + * Writing sets EOF + */ + sc->sc_nxrec = bdbtofsb(bp->b_blkno) + 1; + /* + * If the data transfer command is in the correct place, + * set up all the registers except the csr, and give + * control over to the MASSBUS adapter routines, to + * wait for resources to start the i/o. + */ if ((blkno = sc->sc_blkno) == bdbtofsb(bp->b_blkno)) { htaddr->htfc = -bp->b_bcount; if ((bp->b_flags&B_READ) == 0) { + /* + * On write error retries erase the + * inter-record gap before rewriting. + */ if (mi->mi_tab.b_errcnt) { if ((sc->sc_flags & H_ERASED) == 0) { sc->sc_flags |= H_ERASED; *************** *** 280,295 **** htaddr->htcs1 = HT_ERASE | HT_GO; return (MBU_STARTED); } sc->sc_flags &= ~H_ERASED; } ! if (htaddr->htds & HTDS_EOT) { bp->b_resid = bp->b_bcount; bp->b_flags |= B_ERROR; return (MBU_NEXT); } } return (MBU_DODATA); } if (blkno < bdbtofsb(bp->b_blkno)) { htaddr->htfc = blkno - bdbtofsb(bp->b_blkno); htaddr->htcs1 = HT_SFORW|HT_GO; --- 367,394 ---- htaddr->htcs1 = HT_ERASE | HT_GO; return (MBU_STARTED); } + /* + * Completed erase of the inter-record gap + * due to a write error; now retry the write + * operation. + */ sc->sc_flags &= ~H_ERASED; } ! if (htaddr->htds & HTDS_EOT && ! (sc->sc_flags & H_IEOT) == 0) { bp->b_resid = bp->b_bcount; bp->b_flags |= B_ERROR; + bp->b_error = ENOSPC; return (MBU_NEXT); } } return (MBU_DODATA); } + /* + * Tape positioned incorrectly; + * set to seek forward or backward to the correct spot. + * This happens for raw tapes only on error retries. + */ if (blkno < bdbtofsb(bp->b_blkno)) { htaddr->htfc = blkno - bdbtofsb(bp->b_blkno); htaddr->htcs1 = HT_SFORW|HT_GO; *************** *** 300,305 **** --- 399,407 ---- return (MBU_STARTED); } + /* + * ht data transfer interrupt routine. + */ htdtint(mi, mbsr) register struct mba_device *mi; int mbsr; *************** *** 310,315 **** --- 412,420 ---- int ds, er, mbs; sc = &tu_softc[TUUNIT(bp->b_dev)]; + /* + * An operation completed... record status + */ ds = sc->sc_dsreg = MASKREG(htaddr->htds); er = sc->sc_erreg = MASKREG(htaddr->hter); sc->sc_resid = MASKREG(htaddr->htfc); *************** *** 317,345 **** sc->sc_blkno++; if((bp->b_flags & B_READ) == 0) sc->sc_flags |= H_WRITTEN; if ((ds&(HTDS_ERR|HTDS_MOL)) != HTDS_MOL || mbs & MBSR_EBITS) { htaddr->htcs1 = HT_DCLR|HT_GO; mbclrattn(mi); ! if (bp == &rhtbuf[HTUNIT(bp->b_dev)]) { ! er &= ~HTER_FCE; ! mbs &= ~(MBSR_DTABT|MBSR_MBEXC); ! } ! if (bp->b_flags & B_READ && ds & HTDS_PES) er &= ~(HTER_CSITM|HTER_CORCRC); ! if (er&HTER_HARD || mbs&MBSR_EBITS || (ds&HTDS_MOL) == 0 || er && ++mi->mi_tab.b_errcnt >= 7) { if ((ds & HTDS_MOL) == 0 && sc->sc_openf > 0) sc->sc_openf = -1; ! if ((er&HTER_HARD) == HTER_FCE && ! (mbs&MBSR_EBITS) == (MBSR_DTABT|MBSR_MBEXC) && ! (ds&HTDS_MOL)) ! goto noprint; ! tprintf(sc->sc_ttyp, "tu%d: hard error bn%d mbsr=%b er=%b ds=%b\n", ! TUUNIT(bp->b_dev), bp->b_blkno, ! mbsr, mbsr_bits, ! sc->sc_erreg, hter_bits, ! sc->sc_dsreg, htds_bits); ! noprint: bp->b_flags |= B_ERROR; return (MBD_DONE); } --- 422,461 ---- sc->sc_blkno++; if((bp->b_flags & B_READ) == 0) sc->sc_flags |= H_WRITTEN; + /* + * Check for errors. + */ if ((ds&(HTDS_ERR|HTDS_MOL)) != HTDS_MOL || mbs & MBSR_EBITS) { htaddr->htcs1 = HT_DCLR|HT_GO; mbclrattn(mi); ! /* ! * Short records will be noticed and handled below. ! */ ! er &= ~HTER_FCE; ! mbs &= ~(MBSR_DTABT|MBSR_MBEXC); ! /* ! * If we were reading at 1600/6250 bpi and the error ! * was corrected, then don't consider this an error. ! */ ! if (bp->b_flags & B_READ && ds & (HTDS_PES|HTDS_GCR)) er &= ~(HTER_CSITM|HTER_CORCRC); ! if (er&HTER_HARD || mbs&MBSR_HARD || (ds&HTDS_MOL) == 0 || er && ++mi->mi_tab.b_errcnt >= 7) { + /* + * Hard or non-i/o errors on non-raw tape + * cause it to close. + */ if ((ds & HTDS_MOL) == 0 && sc->sc_openf > 0) sc->sc_openf = -1; ! if (er&HTER_HARD || mbs&MBSR_EBITS || (ds&HTDS_MOL) == 0) ! /* ! * Couldn't recover error ! */ ! log(LOG_WARNING, "tu%d: hard error bn%d mbsr=%b er=%b ds=%b\n", ! TUUNIT(bp->b_dev), bp->b_blkno, ! mbsr, mbsr_bits, ! sc->sc_erreg, hter_bits, ! sc->sc_dsreg, htds_bits); bp->b_flags |= B_ERROR; return (MBD_DONE); } *************** *** 348,361 **** } bp->b_resid = 0; if (bp->b_flags & B_READ) ! if (ds&HTDS_TM) { /* must be a read, right? */ bp->b_resid = bp->b_bcount; sc->sc_nxrec = bdbtofsb(bp->b_blkno); ! } else if(bp->b_bcount > MASKREG(htaddr->htfc)) ! bp->b_resid = bp->b_bcount - MASKREG(htaddr->htfc); return (MBD_DONE); } htndtint(mi) register struct mba_device *mi; { --- 464,491 ---- } bp->b_resid = 0; if (bp->b_flags & B_READ) ! if (ds&HTDS_TM) { ! /* ! * If we hit a tape mark update our position. ! */ bp->b_resid = bp->b_bcount; sc->sc_nxrec = bdbtofsb(bp->b_blkno); ! } else if (bp->b_bcount < sc->sc_resid) { ! /* ! * The tape record was longer than the buffer passed ! * to read; return ENOMEM. ! */ ! bp->b_error = ENOMEM; ! bp->b_flags |= B_ERROR; ! } else { /* bp->b_bcount >= sc->sc_resid */ ! bp->b_resid = bp->b_bcount - sc->sc_resid; ! } return (MBD_DONE); } + /* + * ht non-data transfer interrupt routine. + */ htndtint(mi) register struct mba_device *mi; { *************** *** 374,379 **** --- 504,512 ---- if (bp == 0) return (MBN_SKIP); sc = &tu_softc[TUUNIT(bp->b_dev)]; + /* + * An operation completed... record status + */ sc->sc_dsreg = ds; sc->sc_erreg = er; sc->sc_resid = fc; *************** *** 384,392 **** ds |= HTDS_MOL; break; case HT_SREV: ! /* if backspace file hit bot, its not an error */ if (er == (HTER_NEF|HTER_FCE) && ds&HTDS_BOT && ! bp->b_repcnt == INF) er &= ~HTER_NEF; break; } --- 517,525 ---- ds |= HTDS_MOL; break; case HT_SREV: ! /* if backspace file hit bot, it's not an error */ if (er == (HTER_NEF|HTER_FCE) && ds&HTDS_BOT && ! bp->b_repcnt == MAXFC) er &= ~HTER_NEF; break; } *************** *** 397,403 **** if ((ds & (HTDS_ERR|HTDS_MOL)) != HTDS_MOL) { if ((ds & HTDS_MOL) == 0 && sc->sc_openf > 0) sc->sc_openf = -1; ! tprintf(sc->sc_ttyp, "tu%d: hard error bn%d er=%b ds=%b\n", TUUNIT(bp->b_dev), bp->b_blkno, sc->sc_erreg, hter_bits, sc->sc_dsreg, htds_bits); bp->b_flags |= B_ERROR; --- 530,536 ---- if ((ds & (HTDS_ERR|HTDS_MOL)) != HTDS_MOL) { if ((ds & HTDS_MOL) == 0 && sc->sc_openf > 0) sc->sc_openf = -1; ! log(LOG_WARNING, "tu%d: hard error bn%d er=%b ds=%b\n", TUUNIT(bp->b_dev), bp->b_blkno, sc->sc_erreg, hter_bits, sc->sc_dsreg, htds_bits); bp->b_flags |= B_ERROR; *************** *** 405,414 **** } if (bp == &chtbuf[HTUNIT(bp->b_dev)]) { if (sc->sc_flags & H_REWIND) ! return (ds & HTDS_BOT ? MBN_DONE : MBN_RETRY); bp->b_resid = -sc->sc_resid; return (MBN_DONE); } if (ds & HTDS_TM) if (sc->sc_blkno > bdbtofsb(bp->b_blkno)) { sc->sc_nxrec = bdbtofsb(bp->b_blkno) - fc; --- 538,550 ---- } if (bp == &chtbuf[HTUNIT(bp->b_dev)]) { if (sc->sc_flags & H_REWIND) ! return (MBN_DONE); bp->b_resid = -sc->sc_resid; return (MBN_DONE); } + /* + * If we hit a tape mark update our position. + */ if (ds & HTDS_TM) if (sc->sc_blkno > bdbtofsb(bp->b_blkno)) { sc->sc_nxrec = bdbtofsb(bp->b_blkno) - fc; *************** *** 422,427 **** --- 558,566 ---- return (MBN_RETRY); } + /* + * Raw interface for a read + */ htread(dev, uio) dev_t dev; struct uio *uio; *************** *** 431,439 **** errno = htphys(dev, uio); if (errno) return (errno); ! return (physio(htstrategy, &rhtbuf[HTUNIT(dev)], dev, B_READ, minphys, uio)); } htwrite(dev, uio) dev_t dev; struct uio *uio; --- 570,581 ---- errno = htphys(dev, uio); if (errno) return (errno); ! return (physio(htstrategy, (struct buf *)NULL, dev, B_READ, minphys, uio)); } + /* + * Raw interface for a write + */ htwrite(dev, uio) dev_t dev; struct uio *uio; *************** *** 443,451 **** errno = htphys(dev, uio); if (errno) return (errno); ! return (physio(htstrategy, &rhtbuf[HTUNIT(dev)], dev, B_WRITE, minphys, uio)); } htphys(dev, uio) dev_t dev; struct uio *uio; --- 585,598 ---- errno = htphys(dev, uio); if (errno) return (errno); ! return (physio(htstrategy, (struct buf *)NULL, dev, B_WRITE, minphys, uio)); } + /* + * Check that a raw device exists. + * If it does, set up sc_blkno and sc_nxrec + * so that the tape will appear positioned correctly. + */ htphys(dev, uio) dev_t dev; struct uio *uio; *************** *** 495,501 **** case MTFSF: case MTBSF: callcount = mtop->mt_count; ! fcount = INF; break; case MTFSR: case MTBSR: --- 642,648 ---- case MTFSF: case MTBSF: callcount = mtop->mt_count; ! fcount = MAXFC; break; case MTFSR: case MTBSR: *************** *** 529,534 **** --- 676,689 ---- mtget->mt_erreg = sc->sc_erreg; mtget->mt_resid = sc->sc_resid; mtget->mt_type = MT_ISHT; + break; + + case MTIOCIEOT: + sc->sc_flags |= H_IEOT; + break; + + case MTIOCEEOT: + sc->sc_flags &= ~H_IEOT; break; default: -- Jeff Gilliam {ucbvax,pyramid,nsc}!voder!jeff