123310Smckusick /* 229266Smckusick * Copyright (c) 1982, 1986 Regents of the University of California. 323310Smckusick * All rights reserved. The Berkeley software License Agreement 423310Smckusick * specifies the terms and conditions for redistribution. 523310Smckusick * 6*31036Skarels * @(#)ht.c 7.3 (Berkeley) 05/07/87 723310Smckusick */ 82961Swnj 92980Swnj #include "tu.h" 101563Sbill #if NHT > 0 1122Sbill /* 122926Swnj * TM03/TU?? tape driver 133094Swnj * 143094Swnj * TODO: 153204Swnj * cleanup messages on errors 163094Swnj * test ioctl's 173094Swnj * see how many rewind interrups we get if we kick when not at BOT 183204Swnj * fixup rle error on block tape code 1922Sbill */ 2017118Sbloom #include "param.h" 2117118Sbloom #include "systm.h" 2217118Sbloom #include "buf.h" 2317118Sbloom #include "conf.h" 2417118Sbloom #include "dir.h" 2517118Sbloom #include "file.h" 2617118Sbloom #include "user.h" 2717118Sbloom #include "map.h" 2817118Sbloom #include "ioctl.h" 2917118Sbloom #include "mtio.h" 3017118Sbloom #include "cmap.h" 3117118Sbloom #include "uio.h" 3218325Sralph #include "tty.h" 33*31036Skarels #include "syslog.h" 3422Sbill 3530918Skarels #include "../machine/pte.h" 368469Sroot #include "../vax/cpu.h" 3717118Sbloom #include "mbareg.h" 3817118Sbloom #include "mbavar.h" 3917118Sbloom #include "htreg.h" 4022Sbill 412926Swnj struct buf rhtbuf[NHT]; 422926Swnj struct buf chtbuf[NHT]; 4322Sbill 442926Swnj short httypes[] = 453181Swnj { MBDT_TM03, MBDT_TE16, MBDT_TU45, MBDT_TU77, 0 }; 462980Swnj struct mba_device *htinfo[NHT]; 473103Swnj int htattach(), htslave(), htustart(), htndtint(), htdtint(); 482926Swnj struct mba_driver htdriver = 492980Swnj { htattach, htslave, htustart, 0, htdtint, htndtint, 502980Swnj httypes, "ht", "tu", htinfo }; 5122Sbill 522926Swnj #define MASKREG(r) ((r) & 0xffff) 5322Sbill 542926Swnj /* bits in minor device */ 552980Swnj #define TUUNIT(dev) (minor(dev)&03) 562926Swnj #define H_NOREWIND 04 572926Swnj #define H_1600BPI 08 5822Sbill 593094Swnj #define HTUNIT(dev) (tutoht[TUUNIT(dev)]) 602980Swnj 612926Swnj #define INF (daddr_t)1000000L /* a block number that wont exist */ 622926Swnj 633094Swnj struct tu_softc { 642926Swnj char sc_openf; 652926Swnj char sc_flags; 662926Swnj daddr_t sc_blkno; 672926Swnj daddr_t sc_nxrec; 682926Swnj u_short sc_erreg; 692926Swnj u_short sc_dsreg; 702926Swnj short sc_resid; 712926Swnj short sc_dens; 722980Swnj struct mba_device *sc_mi; 732980Swnj int sc_slave; 7418325Sralph struct tty *sc_ttyp; /* record user's tty for errors */ 7530918Skarels int sc_blks; /* number of I/O operations since open */ 7630918Skarels int sc_softerrs; /* number of soft I/O errors since open */ 773094Swnj } tu_softc[NTU]; 783094Swnj short tutoht[NTU]; 792926Swnj 802926Swnj /* 812926Swnj * Bits for sc_flags. 822926Swnj */ 832926Swnj #define H_WRITTEN 1 /* last operation was a write */ 842926Swnj #define H_ERASED 2 /* last write retry was an erase gap */ 852926Swnj #define H_REWIND 4 /* last unit start was a rewind */ 8622Sbill 873204Swnj char hter_bits[] = HTER_BITS; 883204Swnj char htds_bits[] = HTDS_BITS; 893204Swnj 902926Swnj /*ARGSUSED*/ 912980Swnj htattach(mi) 922980Swnj struct mba_device *mi; 932926Swnj { 942926Swnj 952926Swnj } 962926Swnj 977430Skre htslave(mi, ms, sn) 982980Swnj struct mba_device *mi; 992980Swnj struct mba_slave *ms; 1007430Skre int sn; 1012980Swnj { 1023094Swnj register struct tu_softc *sc = &tu_softc[ms->ms_unit]; 1034756Swnj register struct htdevice *htaddr = (struct htdevice *)mi->mi_drv; 1042980Swnj 1057430Skre htaddr->httc = sn; 1064756Swnj if (htaddr->htdt & HTDT_SPR) { 1074756Swnj sc->sc_mi = mi; 1087430Skre sc->sc_slave = sn; 1094756Swnj tutoht[ms->ms_unit] = mi->mi_unit; 1104756Swnj return (1); 1114756Swnj } else 1124756Swnj return (0); 1132980Swnj } 1142980Swnj 11522Sbill htopen(dev, flag) 1162926Swnj dev_t dev; 1172926Swnj int flag; 11822Sbill { 1193094Swnj register int tuunit; 1202980Swnj register struct mba_device *mi; 1213094Swnj register struct tu_softc *sc; 1223203Swnj int olddens, dens; 12322Sbill 1243094Swnj tuunit = TUUNIT(dev); 12525052Skarels if (tuunit >= NTU || (mi = htinfo[HTUNIT(dev)]) == 0 || 12625052Skarels mi->mi_alive == 0) 1278580Sroot return (ENXIO); 12825052Skarels if ((sc = &tu_softc[tuunit])->sc_openf) 12925052Skarels return (EBUSY); 13030918Skarels sc->sc_openf = 1; 1313203Swnj olddens = sc->sc_dens; 1323204Swnj dens = sc->sc_dens = 1333094Swnj ((minor(dev)&H_1600BPI)?HTTC_1600BPI:HTTC_800BPI)| 1343094Swnj HTTC_PDP11|sc->sc_slave; 1353203Swnj htcommand(dev, HT_SENSE, 1); 1363203Swnj sc->sc_dens = olddens; 1373707Sroot if ((sc->sc_dsreg & HTDS_MOL) == 0) { 13830918Skarels sc->sc_openf = 0; 1393717Sroot uprintf("tu%d: not online\n", tuunit); 1408580Sroot return (EIO); 1412926Swnj } 1423707Sroot if ((flag&FWRITE) && (sc->sc_dsreg&HTDS_WRL)) { 14330918Skarels sc->sc_openf = 0; 1443717Sroot uprintf("tu%d: no write ring\n", tuunit); 1458580Sroot return (EIO); 1463707Sroot } 1473707Sroot if ((sc->sc_dsreg & HTDS_BOT) == 0 && (flag&FWRITE) && 1483707Sroot dens != sc->sc_dens) { 14930918Skarels sc->sc_openf = 0; 1503717Sroot uprintf("tu%d: can't change density in mid-tape\n", tuunit); 1518580Sroot return (EIO); 1523707Sroot } 1532926Swnj sc->sc_blkno = (daddr_t)0; 1542926Swnj sc->sc_nxrec = INF; 1552926Swnj sc->sc_flags = 0; 1563094Swnj sc->sc_dens = dens; 15730918Skarels sc->sc_blks = 0; 15830918Skarels sc->sc_softerrs = 0; 15918325Sralph sc->sc_ttyp = u.u_ttyp; 1608580Sroot return (0); 16122Sbill } 16222Sbill 16322Sbill htclose(dev, flag) 1642926Swnj register dev_t dev; 1652926Swnj register flag; 16622Sbill { 1673094Swnj register struct tu_softc *sc = &tu_softc[TUUNIT(dev)]; 16822Sbill 1692926Swnj if (flag == FWRITE || ((flag&FWRITE) && (sc->sc_flags&H_WRITTEN))) { 1702926Swnj htcommand(dev, HT_WEOF, 1); 1712926Swnj htcommand(dev, HT_WEOF, 1); 1722926Swnj htcommand(dev, HT_SREV, 1); 17322Sbill } 1742926Swnj if ((minor(dev)&H_NOREWIND) == 0) 1752926Swnj htcommand(dev, HT_REW, 0); 17630918Skarels if (sc->sc_blks > 100 && sc->sc_softerrs > sc->sc_blks / 100) 17730918Skarels log(LOG_INFO, "tu%d: %d soft errors in %d blocks\n", 17830918Skarels TUUNIT(dev), sc->sc_softerrs, sc->sc_blks); 1792926Swnj sc->sc_openf = 0; 18022Sbill } 18122Sbill 1822926Swnj htcommand(dev, com, count) 1832926Swnj dev_t dev; 1842926Swnj int com, count; 18522Sbill { 18622Sbill register struct buf *bp; 1875436Sroot register int s; 18822Sbill 1892926Swnj bp = &chtbuf[HTUNIT(dev)]; 1905436Sroot s = spl5(); 1912926Swnj while (bp->b_flags&B_BUSY) { 1923157Swnj if(bp->b_repcnt == 0 && (bp->b_flags&B_DONE)) 1932980Swnj break; 19422Sbill bp->b_flags |= B_WANTED; 19522Sbill sleep((caddr_t)bp, PRIBIO); 19622Sbill } 1972943Swnj bp->b_flags = B_BUSY|B_READ; 1985436Sroot splx(s); 19922Sbill bp->b_dev = dev; 2002926Swnj bp->b_command = com; 2012926Swnj bp->b_repcnt = count; 20222Sbill bp->b_blkno = 0; 20322Sbill htstrategy(bp); 2042926Swnj if (count == 0) 2052926Swnj return; 20622Sbill iowait(bp); 2072926Swnj if (bp->b_flags&B_WANTED) 20822Sbill wakeup((caddr_t)bp); 2092926Swnj bp->b_flags &= B_ERROR; 21022Sbill } 21122Sbill 21222Sbill htstrategy(bp) 2132926Swnj register struct buf *bp; 21422Sbill { 2153094Swnj register struct mba_device *mi = htinfo[HTUNIT(bp->b_dev)]; 2162926Swnj register struct buf *dp; 2175436Sroot register int s; 21822Sbill 21922Sbill bp->av_forw = NULL; 2202926Swnj dp = &mi->mi_tab; 2215436Sroot s = spl5(); 2222926Swnj if (dp->b_actf == NULL) 2232926Swnj dp->b_actf = bp; 22422Sbill else 2252926Swnj dp->b_actl->av_forw = bp; 2262926Swnj dp->b_actl = bp; 2272926Swnj if (dp->b_active == 0) 2282926Swnj mbustart(mi); 2295436Sroot splx(s); 23022Sbill } 23122Sbill 2322926Swnj htustart(mi) 2332980Swnj register struct mba_device *mi; 23422Sbill { 2352926Swnj register struct htdevice *htaddr = 2362926Swnj (struct htdevice *)mi->mi_drv; 2372926Swnj register struct buf *bp = mi->mi_tab.b_actf; 2383094Swnj register struct tu_softc *sc = &tu_softc[TUUNIT(bp->b_dev)]; 23922Sbill daddr_t blkno; 24022Sbill 2412926Swnj htaddr->httc = sc->sc_dens; 24215108Skarels #ifdef notdef 24315108Skarels /* unneeded, may hang controller */ 2443181Swnj if (bp == &chtbuf[HTUNIT(bp->b_dev)] && bp->b_command == HT_SENSE) { 2453157Swnj htaddr->htcs1 = HT_SENSE|HT_GO; 2463157Swnj mbclrattn(mi); 2473157Swnj } 24815108Skarels #endif 2492926Swnj sc->sc_dsreg = htaddr->htds; 2502926Swnj sc->sc_erreg = htaddr->hter; 2512926Swnj sc->sc_resid = htaddr->htfc; 2522926Swnj sc->sc_flags &= ~(H_WRITTEN|H_REWIND); 2532926Swnj if ((htaddr->htdt & HTDT_SPR) == 0 || (htaddr->htds & HTDS_MOL) == 0) 2542926Swnj if (sc->sc_openf > 0) 2552926Swnj sc->sc_openf = -1; 2562926Swnj if (sc->sc_openf < 0) { 2572926Swnj bp->b_flags |= B_ERROR; 2582926Swnj return (MBU_NEXT); 2592926Swnj } 2603094Swnj if (bp != &chtbuf[HTUNIT(bp->b_dev)]) { 2617379Ssam if (bdbtofsb(bp->b_blkno) > sc->sc_nxrec) { 2622926Swnj bp->b_flags |= B_ERROR; 2632926Swnj bp->b_error = ENXIO; 2642961Swnj return (MBU_NEXT); 2653094Swnj } 2667379Ssam if (bdbtofsb(bp->b_blkno) == sc->sc_nxrec && 2672926Swnj bp->b_flags&B_READ) { 2682926Swnj bp->b_resid = bp->b_bcount; 2692926Swnj clrbuf(bp); 2702961Swnj return (MBU_NEXT); 2713094Swnj } 2723094Swnj if ((bp->b_flags&B_READ)==0) 2737379Ssam sc->sc_nxrec = bdbtofsb(bp->b_blkno) + 1; 2742926Swnj } else { 2752961Swnj if (bp->b_command == HT_SENSE) 2762926Swnj return (MBU_NEXT); 2772926Swnj if (bp->b_command == HT_REW) 2782926Swnj sc->sc_flags |= H_REWIND; 2792926Swnj else 2802926Swnj htaddr->htfc = -bp->b_bcount; 2812926Swnj htaddr->htcs1 = bp->b_command|HT_GO; 2822926Swnj return (MBU_STARTED); 2832926Swnj } 2847379Ssam if ((blkno = sc->sc_blkno) == bdbtofsb(bp->b_blkno)) { 2852926Swnj htaddr->htfc = -bp->b_bcount; 2862926Swnj if ((bp->b_flags&B_READ) == 0) { 2873094Swnj if (mi->mi_tab.b_errcnt) { 2883094Swnj if ((sc->sc_flags & H_ERASED) == 0) { 2892926Swnj sc->sc_flags |= H_ERASED; 2902926Swnj htaddr->htcs1 = HT_ERASE | HT_GO; 2912926Swnj return (MBU_STARTED); 2922926Swnj } 2933094Swnj sc->sc_flags &= ~H_ERASED; 2943094Swnj } 2952926Swnj if (htaddr->htds & HTDS_EOT) { 2962926Swnj bp->b_resid = bp->b_bcount; 2976812Swnj bp->b_flags |= B_ERROR; 2982926Swnj return (MBU_NEXT); 2992926Swnj } 30022Sbill } 3012926Swnj return (MBU_DODATA); 30222Sbill } 3037379Ssam if (blkno < bdbtofsb(bp->b_blkno)) { 3047379Ssam htaddr->htfc = blkno - bdbtofsb(bp->b_blkno); 3052926Swnj htaddr->htcs1 = HT_SFORW|HT_GO; 30622Sbill } else { 3077379Ssam htaddr->htfc = bdbtofsb(bp->b_blkno) - blkno; 3082926Swnj htaddr->htcs1 = HT_SREV|HT_GO; 30922Sbill } 3102926Swnj return (MBU_STARTED); 31122Sbill } 31222Sbill 3133094Swnj htdtint(mi, mbsr) 3142980Swnj register struct mba_device *mi; 3153094Swnj int mbsr; 31622Sbill { 3172926Swnj register struct htdevice *htaddr = (struct htdevice *)mi->mi_drv; 3182926Swnj register struct buf *bp = mi->mi_tab.b_actf; 3193094Swnj register struct tu_softc *sc; 3202961Swnj int ds, er, mbs; 32122Sbill 3223094Swnj sc = &tu_softc[TUUNIT(bp->b_dev)]; 3232926Swnj ds = sc->sc_dsreg = MASKREG(htaddr->htds); 3242926Swnj er = sc->sc_erreg = MASKREG(htaddr->hter); 3252926Swnj sc->sc_resid = MASKREG(htaddr->htfc); 3263094Swnj mbs = mbsr; 3272926Swnj sc->sc_blkno++; 3282926Swnj if((bp->b_flags & B_READ) == 0) 3292926Swnj sc->sc_flags |= H_WRITTEN; 3303094Swnj if ((ds&(HTDS_ERR|HTDS_MOL)) != HTDS_MOL || mbs & MBSR_EBITS) { 3312926Swnj htaddr->htcs1 = HT_DCLR|HT_GO; 3322961Swnj mbclrattn(mi); 3332961Swnj if (bp == &rhtbuf[HTUNIT(bp->b_dev)]) { 3342926Swnj er &= ~HTER_FCE; 3353094Swnj mbs &= ~(MBSR_DTABT|MBSR_MBEXC); 3364276Sroot } 3372926Swnj if (bp->b_flags & B_READ && ds & HTDS_PES) 3382926Swnj er &= ~(HTER_CSITM|HTER_CORCRC); 3393094Swnj if (er&HTER_HARD || mbs&MBSR_EBITS || (ds&HTDS_MOL) == 0 || 3402961Swnj er && ++mi->mi_tab.b_errcnt >= 7) { 3412926Swnj if ((ds & HTDS_MOL) == 0 && sc->sc_openf > 0) 3422926Swnj sc->sc_openf = -1; 3433157Swnj if ((er&HTER_HARD) == HTER_FCE && 3443157Swnj (mbs&MBSR_EBITS) == (MBSR_DTABT|MBSR_MBEXC) && 3453157Swnj (ds&HTDS_MOL)) 3463157Swnj goto noprint; 34718325Sralph tprintf(sc->sc_ttyp, "tu%d: hard error bn%d mbsr=%b er=%b ds=%b\n", 3482980Swnj TUUNIT(bp->b_dev), bp->b_blkno, 3493094Swnj mbsr, mbsr_bits, 3503204Swnj sc->sc_erreg, hter_bits, 3513204Swnj sc->sc_dsreg, htds_bits); 3523157Swnj noprint: 35322Sbill bp->b_flags |= B_ERROR; 3542926Swnj return (MBD_DONE); 35522Sbill } 3562926Swnj if (er) 3572926Swnj return (MBD_RETRY); 35822Sbill } 3592926Swnj bp->b_resid = 0; 36030918Skarels sc->sc_blks++; 36130918Skarels if (mi->mi_tab.b_errcnt) 36230918Skarels sc->sc_softerrs++; 3632926Swnj if (bp->b_flags & B_READ) 3642926Swnj if (ds&HTDS_TM) { /* must be a read, right? */ 3652926Swnj bp->b_resid = bp->b_bcount; 3667379Ssam sc->sc_nxrec = bdbtofsb(bp->b_blkno); 3672926Swnj } else if(bp->b_bcount > MASKREG(htaddr->htfc)) 3682926Swnj bp->b_resid = bp->b_bcount - MASKREG(htaddr->htfc); 3692926Swnj return (MBD_DONE); 3702926Swnj } 37122Sbill 3722926Swnj htndtint(mi) 3732980Swnj register struct mba_device *mi; 3742926Swnj { 3752926Swnj register struct htdevice *htaddr = (struct htdevice *)mi->mi_drv; 3762926Swnj register struct buf *bp = mi->mi_tab.b_actf; 3773094Swnj register struct tu_softc *sc; 3782926Swnj int er, ds, fc; 37922Sbill 3803094Swnj ds = MASKREG(htaddr->htds); 3813094Swnj er = MASKREG(htaddr->hter); 3823094Swnj fc = MASKREG(htaddr->htfc); 3833094Swnj if (er) { 3842926Swnj htaddr->htcs1 = HT_DCLR|HT_GO; 3852961Swnj mbclrattn(mi); 3862961Swnj } 3873094Swnj if (bp == 0) 3883094Swnj return (MBN_SKIP); 3893094Swnj sc = &tu_softc[TUUNIT(bp->b_dev)]; 3903094Swnj sc->sc_dsreg = ds; 3913094Swnj sc->sc_erreg = er; 3923094Swnj sc->sc_resid = fc; 3933094Swnj if (bp == &chtbuf[HTUNIT(bp->b_dev)]) { 39426290Skarels switch ((int)bp->b_command) { 3953094Swnj case HT_REWOFFL: 3962926Swnj /* offline is on purpose; don't do anything special */ 3972926Swnj ds |= HTDS_MOL; 3983094Swnj break; 3993094Swnj case HT_SREV: 4003094Swnj /* if backspace file hit bot, its not an error */ 4013094Swnj if (er == (HTER_NEF|HTER_FCE) && ds&HTDS_BOT && 4023094Swnj bp->b_repcnt == INF) 4033094Swnj er &= ~HTER_NEF; 4043094Swnj break; 4053094Swnj } 4062926Swnj er &= ~HTER_FCE; 4072926Swnj if (er == 0) 4082926Swnj ds &= ~HTDS_ERR; 40922Sbill } 4102926Swnj if ((ds & (HTDS_ERR|HTDS_MOL)) != HTDS_MOL) { 4112926Swnj if ((ds & HTDS_MOL) == 0 && sc->sc_openf > 0) 4122926Swnj sc->sc_openf = -1; 41318325Sralph tprintf(sc->sc_ttyp, "tu%d: hard error bn%d er=%b ds=%b\n", 4142980Swnj TUUNIT(bp->b_dev), bp->b_blkno, 4153204Swnj sc->sc_erreg, hter_bits, sc->sc_dsreg, htds_bits); 4162926Swnj bp->b_flags |= B_ERROR; 4172926Swnj return (MBN_DONE); 4182926Swnj } 4193094Swnj if (bp == &chtbuf[HTUNIT(bp->b_dev)]) { 4202926Swnj if (sc->sc_flags & H_REWIND) 4212926Swnj return (ds & HTDS_BOT ? MBN_DONE : MBN_RETRY); 4222926Swnj bp->b_resid = -sc->sc_resid; 4232926Swnj return (MBN_DONE); 4242926Swnj } 4252926Swnj if (ds & HTDS_TM) 4267379Ssam if (sc->sc_blkno > bdbtofsb(bp->b_blkno)) { 4277379Ssam sc->sc_nxrec = bdbtofsb(bp->b_blkno) - fc; 4282926Swnj sc->sc_blkno = sc->sc_nxrec; 4293094Swnj } else { 4307379Ssam sc->sc_blkno = bdbtofsb(bp->b_blkno) + fc; 4312926Swnj sc->sc_nxrec = sc->sc_blkno - 1; 4322926Swnj } 4332926Swnj else 4347379Ssam sc->sc_blkno = bdbtofsb(bp->b_blkno); 4352926Swnj return (MBN_RETRY); 43622Sbill } 43722Sbill 4387739Sroot htread(dev, uio) 4392926Swnj dev_t dev; 4407739Sroot struct uio *uio; 44122Sbill { 4428157Sroot int errno; 4432926Swnj 4448157Sroot errno = htphys(dev, uio); 4458157Sroot if (errno) 4468157Sroot return (errno); 4478157Sroot return (physio(htstrategy, &rhtbuf[HTUNIT(dev)], dev, B_READ, minphys, uio)); 44822Sbill } 44922Sbill 4508605Sroot htwrite(dev, uio) 4518605Sroot dev_t dev; 4528688Sroot struct uio *uio; 45322Sbill { 4548157Sroot int errno; 4552926Swnj 4568157Sroot errno = htphys(dev, uio); 4578157Sroot if (errno) 4588157Sroot return (errno); 4598157Sroot return (physio(htstrategy, &rhtbuf[HTUNIT(dev)], dev, B_WRITE, minphys, uio)); 46022Sbill } 46122Sbill 4627739Sroot htphys(dev, uio) 4632926Swnj dev_t dev; 4647739Sroot struct uio *uio; 46522Sbill { 4663094Swnj register int htunit; 4673094Swnj register struct tu_softc *sc; 4683094Swnj register struct mba_device *mi; 46922Sbill daddr_t a; 47022Sbill 4713094Swnj htunit = HTUNIT(dev); 4727832Sroot if (htunit >= NHT || (mi = htinfo[htunit]) == 0 || mi->mi_alive == 0) 4737739Sroot return (ENXIO); 4747832Sroot a = uio->uio_offset >> 9; 4753094Swnj sc = &tu_softc[TUUNIT(dev)]; 4767379Ssam sc->sc_blkno = bdbtofsb(a); 4777379Ssam sc->sc_nxrec = bdbtofsb(a)+1; 4787739Sroot return (0); 47922Sbill } 4801917Swnj 4812926Swnj /*ARGSUSED*/ 4827636Ssam htioctl(dev, cmd, data, flag) 4832926Swnj dev_t dev; 4842926Swnj int cmd; 4857636Ssam caddr_t data; 4862926Swnj int flag; 4872926Swnj { 4883094Swnj register struct tu_softc *sc = &tu_softc[TUUNIT(dev)]; 4893094Swnj register struct buf *bp = &chtbuf[HTUNIT(dev)]; 4902926Swnj register callcount; 4912926Swnj int fcount; 4927636Ssam struct mtop *mtop; 4937636Ssam struct mtget *mtget; 4942926Swnj /* we depend of the values and order of the MT codes here */ 4952926Swnj static htops[] = 4962926Swnj {HT_WEOF,HT_SFORW,HT_SREV,HT_SFORW,HT_SREV,HT_REW,HT_REWOFFL,HT_SENSE}; 4971917Swnj 4982926Swnj switch (cmd) { 4997636Ssam 5007636Ssam case MTIOCTOP: /* tape operation */ 5017636Ssam mtop = (struct mtop *)data; 5027636Ssam switch (mtop->mt_op) { 5037636Ssam 5042926Swnj case MTWEOF: 5057636Ssam callcount = mtop->mt_count; 5062926Swnj fcount = 1; 5072926Swnj break; 5087636Ssam 5092926Swnj case MTFSF: case MTBSF: 5107636Ssam callcount = mtop->mt_count; 5112926Swnj fcount = INF; 5122926Swnj break; 5137636Ssam 5142926Swnj case MTFSR: case MTBSR: 5152926Swnj callcount = 1; 5167636Ssam fcount = mtop->mt_count; 5172926Swnj break; 5187636Ssam 5192926Swnj case MTREW: case MTOFFL: 5202926Swnj callcount = 1; 5212926Swnj fcount = 1; 5222926Swnj break; 5237636Ssam 5242926Swnj default: 5258580Sroot return (ENXIO); 5262926Swnj } 5278580Sroot if (callcount <= 0 || fcount <= 0) 5288580Sroot return (EINVAL); 5292926Swnj while (--callcount >= 0) { 5307636Ssam htcommand(dev, htops[mtop->mt_op], fcount); 5317636Ssam if ((mtop->mt_op == MTFSR || mtop->mt_op == MTBSR) && 5328580Sroot bp->b_resid) 5338580Sroot return (EIO); 5343094Swnj if ((bp->b_flags&B_ERROR) || sc->sc_dsreg&HTDS_BOT) 5352926Swnj break; 5362926Swnj } 5378711Sroot return (geterror(bp)); 5387636Ssam 5392926Swnj case MTIOCGET: 5407636Ssam mtget = (struct mtget *)data; 5417636Ssam mtget->mt_dsreg = sc->sc_dsreg; 5427636Ssam mtget->mt_erreg = sc->sc_erreg; 5437636Ssam mtget->mt_resid = sc->sc_resid; 5447636Ssam mtget->mt_type = MT_ISHT; 5458580Sroot break; 5467636Ssam 5472926Swnj default: 5488580Sroot return (ENXIO); 5492926Swnj } 5508580Sroot return (0); 5512926Swnj } 5522926Swnj 5531917Swnj #define DBSIZE 20 5541917Swnj 5552926Swnj htdump() 5561917Swnj { 5572980Swnj register struct mba_device *mi; 5582926Swnj register struct mba_regs *mp; 5592926Swnj register struct htdevice *htaddr; 5602926Swnj int blk, num; 5612926Swnj int start; 5621917Swnj 5632926Swnj start = 0; 5642926Swnj num = maxfree; 5652926Swnj #define phys(a,b) ((b)((int)(a)&0x7fffffff)) 5662926Swnj if (htinfo[0] == 0) 5672926Swnj return (ENXIO); 5682980Swnj mi = phys(htinfo[0], struct mba_device *); 5692926Swnj mp = phys(mi->mi_hd, struct mba_hd *)->mh_physmba; 5703157Swnj mp->mba_cr = MBCR_IE; 5712926Swnj htaddr = (struct htdevice *)&mp->mba_drv[mi->mi_drive]; 5722926Swnj htaddr->httc = HTTC_PDP11|HTTC_1600BPI; 5732926Swnj htaddr->htcs1 = HT_DCLR|HT_GO; 5741917Swnj while (num > 0) { 5751917Swnj blk = num > DBSIZE ? DBSIZE : num; 5762926Swnj htdwrite(start, blk, htaddr, mp); 5772926Swnj start += blk; 5781917Swnj num -= blk; 5791917Swnj } 5803157Swnj hteof(htaddr); 5813157Swnj hteof(htaddr); 5822926Swnj htwait(htaddr); 5833181Swnj if (htaddr->htds&HTDS_ERR) 5843157Swnj return (EIO); 5852926Swnj htaddr->htcs1 = HT_REW|HT_GO; 5863103Swnj return (0); 5871917Swnj } 5881917Swnj 5892926Swnj htdwrite(dbuf, num, htaddr, mp) 5902926Swnj register dbuf, num; 5912926Swnj register struct htdevice *htaddr; 5922926Swnj struct mba_regs *mp; 5931917Swnj { 5942926Swnj register struct pte *io; 5951917Swnj register int i; 5961917Swnj 5972926Swnj htwait(htaddr); 5982926Swnj io = mp->mba_map; 5991917Swnj for (i = 0; i < num; i++) 6002926Swnj *(int *)io++ = dbuf++ | PG_V; 6012926Swnj htaddr->htfc = -(num*NBPG); 6022926Swnj mp->mba_sr = -1; 6032926Swnj mp->mba_bcr = -(num*NBPG); 6042926Swnj mp->mba_var = 0; 6052926Swnj htaddr->htcs1 = HT_WCOM|HT_GO; 6061917Swnj } 6071917Swnj 6082926Swnj htwait(htaddr) 6092926Swnj struct htdevice *htaddr; 6101917Swnj { 6111917Swnj register s; 6121917Swnj 6131917Swnj do 6142926Swnj s = htaddr->htds; 6152926Swnj while ((s & HTDS_DRY) == 0); 6161917Swnj } 6171917Swnj 6182926Swnj hteof(htaddr) 6192926Swnj struct htdevice *htaddr; 6201917Swnj { 6211917Swnj 6222926Swnj htwait(htaddr); 6232926Swnj htaddr->htcs1 = HT_WEOF|HT_GO; 6241917Swnj } 6251563Sbill #endif 626