123310Smckusick /* 223310Smckusick * Copyright (c) 1982 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*25052Skarels * @(#)ht.c 6.6 (Berkeley) 10/01/85 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 */ 209787Ssam #include "../machine/pte.h" 219787Ssam 2217118Sbloom #include "param.h" 2317118Sbloom #include "systm.h" 2417118Sbloom #include "buf.h" 2517118Sbloom #include "conf.h" 2617118Sbloom #include "dir.h" 2717118Sbloom #include "file.h" 2817118Sbloom #include "user.h" 2917118Sbloom #include "map.h" 3017118Sbloom #include "ioctl.h" 3117118Sbloom #include "mtio.h" 3217118Sbloom #include "cmap.h" 3317118Sbloom #include "uio.h" 3418325Sralph #include "tty.h" 3522Sbill 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 */ 753094Swnj } tu_softc[NTU]; 763094Swnj short tutoht[NTU]; 772926Swnj 782926Swnj /* 792926Swnj * Bits for sc_flags. 802926Swnj */ 812926Swnj #define H_WRITTEN 1 /* last operation was a write */ 822926Swnj #define H_ERASED 2 /* last write retry was an erase gap */ 832926Swnj #define H_REWIND 4 /* last unit start was a rewind */ 8422Sbill 853204Swnj char hter_bits[] = HTER_BITS; 863204Swnj char htds_bits[] = HTDS_BITS; 873204Swnj 882926Swnj /*ARGSUSED*/ 892980Swnj htattach(mi) 902980Swnj struct mba_device *mi; 912926Swnj { 922926Swnj 932926Swnj } 942926Swnj 957430Skre htslave(mi, ms, sn) 962980Swnj struct mba_device *mi; 972980Swnj struct mba_slave *ms; 987430Skre int sn; 992980Swnj { 1003094Swnj register struct tu_softc *sc = &tu_softc[ms->ms_unit]; 1014756Swnj register struct htdevice *htaddr = (struct htdevice *)mi->mi_drv; 1022980Swnj 1037430Skre htaddr->httc = sn; 1044756Swnj if (htaddr->htdt & HTDT_SPR) { 1054756Swnj sc->sc_mi = mi; 1067430Skre sc->sc_slave = sn; 1074756Swnj tutoht[ms->ms_unit] = mi->mi_unit; 1084756Swnj return (1); 1094756Swnj } else 1104756Swnj return (0); 1112980Swnj } 1122980Swnj 11322Sbill htopen(dev, flag) 1142926Swnj dev_t dev; 1152926Swnj int flag; 11622Sbill { 1173094Swnj register int tuunit; 1182980Swnj register struct mba_device *mi; 1193094Swnj register struct tu_softc *sc; 1203203Swnj int olddens, dens; 12122Sbill 1223094Swnj tuunit = TUUNIT(dev); 123*25052Skarels if (tuunit >= NTU || (mi = htinfo[HTUNIT(dev)]) == 0 || 124*25052Skarels mi->mi_alive == 0) 1258580Sroot return (ENXIO); 126*25052Skarels if ((sc = &tu_softc[tuunit])->sc_openf) 127*25052Skarels return (EBUSY); 1283203Swnj olddens = sc->sc_dens; 1293204Swnj dens = sc->sc_dens = 1303094Swnj ((minor(dev)&H_1600BPI)?HTTC_1600BPI:HTTC_800BPI)| 1313094Swnj HTTC_PDP11|sc->sc_slave; 1323203Swnj htcommand(dev, HT_SENSE, 1); 1333203Swnj sc->sc_dens = olddens; 1343707Sroot if ((sc->sc_dsreg & HTDS_MOL) == 0) { 1353717Sroot uprintf("tu%d: not online\n", tuunit); 1368580Sroot return (EIO); 1372926Swnj } 1383707Sroot if ((flag&FWRITE) && (sc->sc_dsreg&HTDS_WRL)) { 1393717Sroot uprintf("tu%d: no write ring\n", tuunit); 1408580Sroot return (EIO); 1413707Sroot } 1423707Sroot if ((sc->sc_dsreg & HTDS_BOT) == 0 && (flag&FWRITE) && 1433707Sroot dens != sc->sc_dens) { 1443717Sroot uprintf("tu%d: can't change density in mid-tape\n", tuunit); 1458580Sroot return (EIO); 1463707Sroot } 1472926Swnj sc->sc_openf = 1; 1482926Swnj sc->sc_blkno = (daddr_t)0; 1492926Swnj sc->sc_nxrec = INF; 1502926Swnj sc->sc_flags = 0; 1513094Swnj sc->sc_dens = dens; 15218325Sralph sc->sc_ttyp = u.u_ttyp; 1538580Sroot return (0); 15422Sbill } 15522Sbill 15622Sbill htclose(dev, flag) 1572926Swnj register dev_t dev; 1582926Swnj register flag; 15922Sbill { 1603094Swnj register struct tu_softc *sc = &tu_softc[TUUNIT(dev)]; 16122Sbill 1622926Swnj if (flag == FWRITE || ((flag&FWRITE) && (sc->sc_flags&H_WRITTEN))) { 1632926Swnj htcommand(dev, HT_WEOF, 1); 1642926Swnj htcommand(dev, HT_WEOF, 1); 1652926Swnj htcommand(dev, HT_SREV, 1); 16622Sbill } 1672926Swnj if ((minor(dev)&H_NOREWIND) == 0) 1682926Swnj htcommand(dev, HT_REW, 0); 1692926Swnj sc->sc_openf = 0; 17022Sbill } 17122Sbill 1722926Swnj htcommand(dev, com, count) 1732926Swnj dev_t dev; 1742926Swnj int com, count; 17522Sbill { 17622Sbill register struct buf *bp; 1775436Sroot register int s; 17822Sbill 1792926Swnj bp = &chtbuf[HTUNIT(dev)]; 1805436Sroot s = spl5(); 1812926Swnj while (bp->b_flags&B_BUSY) { 1823157Swnj if(bp->b_repcnt == 0 && (bp->b_flags&B_DONE)) 1832980Swnj break; 18422Sbill bp->b_flags |= B_WANTED; 18522Sbill sleep((caddr_t)bp, PRIBIO); 18622Sbill } 1872943Swnj bp->b_flags = B_BUSY|B_READ; 1885436Sroot splx(s); 18922Sbill bp->b_dev = dev; 1902926Swnj bp->b_command = com; 1912926Swnj bp->b_repcnt = count; 19222Sbill bp->b_blkno = 0; 19322Sbill htstrategy(bp); 1942926Swnj if (count == 0) 1952926Swnj return; 19622Sbill iowait(bp); 1972926Swnj if (bp->b_flags&B_WANTED) 19822Sbill wakeup((caddr_t)bp); 1992926Swnj bp->b_flags &= B_ERROR; 20022Sbill } 20122Sbill 20222Sbill htstrategy(bp) 2032926Swnj register struct buf *bp; 20422Sbill { 2053094Swnj register struct mba_device *mi = htinfo[HTUNIT(bp->b_dev)]; 2062926Swnj register struct buf *dp; 2075436Sroot register int s; 20822Sbill 20922Sbill bp->av_forw = NULL; 2102926Swnj dp = &mi->mi_tab; 2115436Sroot s = spl5(); 2122926Swnj if (dp->b_actf == NULL) 2132926Swnj dp->b_actf = bp; 21422Sbill else 2152926Swnj dp->b_actl->av_forw = bp; 2162926Swnj dp->b_actl = bp; 2172926Swnj if (dp->b_active == 0) 2182926Swnj mbustart(mi); 2195436Sroot splx(s); 22022Sbill } 22122Sbill 2222926Swnj htustart(mi) 2232980Swnj register struct mba_device *mi; 22422Sbill { 2252926Swnj register struct htdevice *htaddr = 2262926Swnj (struct htdevice *)mi->mi_drv; 2272926Swnj register struct buf *bp = mi->mi_tab.b_actf; 2283094Swnj register struct tu_softc *sc = &tu_softc[TUUNIT(bp->b_dev)]; 22922Sbill daddr_t blkno; 23022Sbill 2312926Swnj htaddr->httc = sc->sc_dens; 23215108Skarels #ifdef notdef 23315108Skarels /* unneeded, may hang controller */ 2343181Swnj if (bp == &chtbuf[HTUNIT(bp->b_dev)] && bp->b_command == HT_SENSE) { 2353157Swnj htaddr->htcs1 = HT_SENSE|HT_GO; 2363157Swnj mbclrattn(mi); 2373157Swnj } 23815108Skarels #endif 2392926Swnj sc->sc_dsreg = htaddr->htds; 2402926Swnj sc->sc_erreg = htaddr->hter; 2412926Swnj sc->sc_resid = htaddr->htfc; 2422926Swnj sc->sc_flags &= ~(H_WRITTEN|H_REWIND); 2432926Swnj if ((htaddr->htdt & HTDT_SPR) == 0 || (htaddr->htds & HTDS_MOL) == 0) 2442926Swnj if (sc->sc_openf > 0) 2452926Swnj sc->sc_openf = -1; 2462926Swnj if (sc->sc_openf < 0) { 2472926Swnj bp->b_flags |= B_ERROR; 2482926Swnj return (MBU_NEXT); 2492926Swnj } 2503094Swnj if (bp != &chtbuf[HTUNIT(bp->b_dev)]) { 2517379Ssam if (bdbtofsb(bp->b_blkno) > sc->sc_nxrec) { 2522926Swnj bp->b_flags |= B_ERROR; 2532926Swnj bp->b_error = ENXIO; 2542961Swnj return (MBU_NEXT); 2553094Swnj } 2567379Ssam if (bdbtofsb(bp->b_blkno) == sc->sc_nxrec && 2572926Swnj bp->b_flags&B_READ) { 2582926Swnj bp->b_resid = bp->b_bcount; 2592926Swnj clrbuf(bp); 2602961Swnj return (MBU_NEXT); 2613094Swnj } 2623094Swnj if ((bp->b_flags&B_READ)==0) 2637379Ssam sc->sc_nxrec = bdbtofsb(bp->b_blkno) + 1; 2642926Swnj } else { 2652961Swnj if (bp->b_command == HT_SENSE) 2662926Swnj return (MBU_NEXT); 2672926Swnj if (bp->b_command == HT_REW) 2682926Swnj sc->sc_flags |= H_REWIND; 2692926Swnj else 2702926Swnj htaddr->htfc = -bp->b_bcount; 2712926Swnj htaddr->htcs1 = bp->b_command|HT_GO; 2722926Swnj return (MBU_STARTED); 2732926Swnj } 2747379Ssam if ((blkno = sc->sc_blkno) == bdbtofsb(bp->b_blkno)) { 2752926Swnj htaddr->htfc = -bp->b_bcount; 2762926Swnj if ((bp->b_flags&B_READ) == 0) { 2773094Swnj if (mi->mi_tab.b_errcnt) { 2783094Swnj if ((sc->sc_flags & H_ERASED) == 0) { 2792926Swnj sc->sc_flags |= H_ERASED; 2802926Swnj htaddr->htcs1 = HT_ERASE | HT_GO; 2812926Swnj return (MBU_STARTED); 2822926Swnj } 2833094Swnj sc->sc_flags &= ~H_ERASED; 2843094Swnj } 2852926Swnj if (htaddr->htds & HTDS_EOT) { 2862926Swnj bp->b_resid = bp->b_bcount; 2876812Swnj bp->b_flags |= B_ERROR; 2882926Swnj return (MBU_NEXT); 2892926Swnj } 29022Sbill } 2912926Swnj return (MBU_DODATA); 29222Sbill } 2937379Ssam if (blkno < bdbtofsb(bp->b_blkno)) { 2947379Ssam htaddr->htfc = blkno - bdbtofsb(bp->b_blkno); 2952926Swnj htaddr->htcs1 = HT_SFORW|HT_GO; 29622Sbill } else { 2977379Ssam htaddr->htfc = bdbtofsb(bp->b_blkno) - blkno; 2982926Swnj htaddr->htcs1 = HT_SREV|HT_GO; 29922Sbill } 3002926Swnj return (MBU_STARTED); 30122Sbill } 30222Sbill 3033094Swnj htdtint(mi, mbsr) 3042980Swnj register struct mba_device *mi; 3053094Swnj int mbsr; 30622Sbill { 3072926Swnj register struct htdevice *htaddr = (struct htdevice *)mi->mi_drv; 3082926Swnj register struct buf *bp = mi->mi_tab.b_actf; 3093094Swnj register struct tu_softc *sc; 3102961Swnj int ds, er, mbs; 31122Sbill 3123094Swnj sc = &tu_softc[TUUNIT(bp->b_dev)]; 3132926Swnj ds = sc->sc_dsreg = MASKREG(htaddr->htds); 3142926Swnj er = sc->sc_erreg = MASKREG(htaddr->hter); 3152926Swnj sc->sc_resid = MASKREG(htaddr->htfc); 3163094Swnj mbs = mbsr; 3172926Swnj sc->sc_blkno++; 3182926Swnj if((bp->b_flags & B_READ) == 0) 3192926Swnj sc->sc_flags |= H_WRITTEN; 3203094Swnj if ((ds&(HTDS_ERR|HTDS_MOL)) != HTDS_MOL || mbs & MBSR_EBITS) { 3212926Swnj htaddr->htcs1 = HT_DCLR|HT_GO; 3222961Swnj mbclrattn(mi); 3232961Swnj if (bp == &rhtbuf[HTUNIT(bp->b_dev)]) { 3242926Swnj er &= ~HTER_FCE; 3253094Swnj mbs &= ~(MBSR_DTABT|MBSR_MBEXC); 3264276Sroot } 3272926Swnj if (bp->b_flags & B_READ && ds & HTDS_PES) 3282926Swnj er &= ~(HTER_CSITM|HTER_CORCRC); 3293094Swnj if (er&HTER_HARD || mbs&MBSR_EBITS || (ds&HTDS_MOL) == 0 || 3302961Swnj er && ++mi->mi_tab.b_errcnt >= 7) { 3312926Swnj if ((ds & HTDS_MOL) == 0 && sc->sc_openf > 0) 3322926Swnj sc->sc_openf = -1; 3333157Swnj if ((er&HTER_HARD) == HTER_FCE && 3343157Swnj (mbs&MBSR_EBITS) == (MBSR_DTABT|MBSR_MBEXC) && 3353157Swnj (ds&HTDS_MOL)) 3363157Swnj goto noprint; 33718325Sralph tprintf(sc->sc_ttyp, "tu%d: hard error bn%d mbsr=%b er=%b ds=%b\n", 3382980Swnj TUUNIT(bp->b_dev), bp->b_blkno, 3393094Swnj mbsr, mbsr_bits, 3403204Swnj sc->sc_erreg, hter_bits, 3413204Swnj sc->sc_dsreg, htds_bits); 3423157Swnj noprint: 34322Sbill bp->b_flags |= B_ERROR; 3442926Swnj return (MBD_DONE); 34522Sbill } 3462926Swnj if (er) 3472926Swnj return (MBD_RETRY); 34822Sbill } 3492926Swnj bp->b_resid = 0; 3502926Swnj if (bp->b_flags & B_READ) 3512926Swnj if (ds&HTDS_TM) { /* must be a read, right? */ 3522926Swnj bp->b_resid = bp->b_bcount; 3537379Ssam sc->sc_nxrec = bdbtofsb(bp->b_blkno); 3542926Swnj } else if(bp->b_bcount > MASKREG(htaddr->htfc)) 3552926Swnj bp->b_resid = bp->b_bcount - MASKREG(htaddr->htfc); 3562926Swnj return (MBD_DONE); 3572926Swnj } 35822Sbill 3592926Swnj htndtint(mi) 3602980Swnj register struct mba_device *mi; 3612926Swnj { 3622926Swnj register struct htdevice *htaddr = (struct htdevice *)mi->mi_drv; 3632926Swnj register struct buf *bp = mi->mi_tab.b_actf; 3643094Swnj register struct tu_softc *sc; 3652926Swnj int er, ds, fc; 36622Sbill 3673094Swnj ds = MASKREG(htaddr->htds); 3683094Swnj er = MASKREG(htaddr->hter); 3693094Swnj fc = MASKREG(htaddr->htfc); 3703094Swnj if (er) { 3712926Swnj htaddr->htcs1 = HT_DCLR|HT_GO; 3722961Swnj mbclrattn(mi); 3732961Swnj } 3743094Swnj if (bp == 0) 3753094Swnj return (MBN_SKIP); 3763094Swnj sc = &tu_softc[TUUNIT(bp->b_dev)]; 3773094Swnj sc->sc_dsreg = ds; 3783094Swnj sc->sc_erreg = er; 3793094Swnj sc->sc_resid = fc; 3803094Swnj if (bp == &chtbuf[HTUNIT(bp->b_dev)]) { 3813094Swnj switch (bp->b_command) { 3823094Swnj case HT_REWOFFL: 3832926Swnj /* offline is on purpose; don't do anything special */ 3842926Swnj ds |= HTDS_MOL; 3853094Swnj break; 3863094Swnj case HT_SREV: 3873094Swnj /* if backspace file hit bot, its not an error */ 3883094Swnj if (er == (HTER_NEF|HTER_FCE) && ds&HTDS_BOT && 3893094Swnj bp->b_repcnt == INF) 3903094Swnj er &= ~HTER_NEF; 3913094Swnj break; 3923094Swnj } 3932926Swnj er &= ~HTER_FCE; 3942926Swnj if (er == 0) 3952926Swnj ds &= ~HTDS_ERR; 39622Sbill } 3972926Swnj if ((ds & (HTDS_ERR|HTDS_MOL)) != HTDS_MOL) { 3982926Swnj if ((ds & HTDS_MOL) == 0 && sc->sc_openf > 0) 3992926Swnj sc->sc_openf = -1; 40018325Sralph tprintf(sc->sc_ttyp, "tu%d: hard error bn%d er=%b ds=%b\n", 4012980Swnj TUUNIT(bp->b_dev), bp->b_blkno, 4023204Swnj sc->sc_erreg, hter_bits, sc->sc_dsreg, htds_bits); 4032926Swnj bp->b_flags |= B_ERROR; 4042926Swnj return (MBN_DONE); 4052926Swnj } 4063094Swnj if (bp == &chtbuf[HTUNIT(bp->b_dev)]) { 4072926Swnj if (sc->sc_flags & H_REWIND) 4082926Swnj return (ds & HTDS_BOT ? MBN_DONE : MBN_RETRY); 4092926Swnj bp->b_resid = -sc->sc_resid; 4102926Swnj return (MBN_DONE); 4112926Swnj } 4122926Swnj if (ds & HTDS_TM) 4137379Ssam if (sc->sc_blkno > bdbtofsb(bp->b_blkno)) { 4147379Ssam sc->sc_nxrec = bdbtofsb(bp->b_blkno) - fc; 4152926Swnj sc->sc_blkno = sc->sc_nxrec; 4163094Swnj } else { 4177379Ssam sc->sc_blkno = bdbtofsb(bp->b_blkno) + fc; 4182926Swnj sc->sc_nxrec = sc->sc_blkno - 1; 4192926Swnj } 4202926Swnj else 4217379Ssam sc->sc_blkno = bdbtofsb(bp->b_blkno); 4222926Swnj return (MBN_RETRY); 42322Sbill } 42422Sbill 4257739Sroot htread(dev, uio) 4262926Swnj dev_t dev; 4277739Sroot struct uio *uio; 42822Sbill { 4298157Sroot int errno; 4302926Swnj 4318157Sroot errno = htphys(dev, uio); 4328157Sroot if (errno) 4338157Sroot return (errno); 4348157Sroot return (physio(htstrategy, &rhtbuf[HTUNIT(dev)], dev, B_READ, minphys, uio)); 43522Sbill } 43622Sbill 4378605Sroot htwrite(dev, uio) 4388605Sroot dev_t dev; 4398688Sroot struct uio *uio; 44022Sbill { 4418157Sroot int errno; 4422926Swnj 4438157Sroot errno = htphys(dev, uio); 4448157Sroot if (errno) 4458157Sroot return (errno); 4468157Sroot return (physio(htstrategy, &rhtbuf[HTUNIT(dev)], dev, B_WRITE, minphys, uio)); 44722Sbill } 44822Sbill 4497739Sroot htphys(dev, uio) 4502926Swnj dev_t dev; 4517739Sroot struct uio *uio; 45222Sbill { 4533094Swnj register int htunit; 4543094Swnj register struct tu_softc *sc; 4553094Swnj register struct mba_device *mi; 45622Sbill daddr_t a; 45722Sbill 4583094Swnj htunit = HTUNIT(dev); 4597832Sroot if (htunit >= NHT || (mi = htinfo[htunit]) == 0 || mi->mi_alive == 0) 4607739Sroot return (ENXIO); 4617832Sroot a = uio->uio_offset >> 9; 4623094Swnj sc = &tu_softc[TUUNIT(dev)]; 4637379Ssam sc->sc_blkno = bdbtofsb(a); 4647379Ssam sc->sc_nxrec = bdbtofsb(a)+1; 4657739Sroot return (0); 46622Sbill } 4671917Swnj 4682926Swnj /*ARGSUSED*/ 4697636Ssam htioctl(dev, cmd, data, flag) 4702926Swnj dev_t dev; 4712926Swnj int cmd; 4727636Ssam caddr_t data; 4732926Swnj int flag; 4742926Swnj { 4753094Swnj register struct tu_softc *sc = &tu_softc[TUUNIT(dev)]; 4763094Swnj register struct buf *bp = &chtbuf[HTUNIT(dev)]; 4772926Swnj register callcount; 4782926Swnj int fcount; 4797636Ssam struct mtop *mtop; 4807636Ssam struct mtget *mtget; 4812926Swnj /* we depend of the values and order of the MT codes here */ 4822926Swnj static htops[] = 4832926Swnj {HT_WEOF,HT_SFORW,HT_SREV,HT_SFORW,HT_SREV,HT_REW,HT_REWOFFL,HT_SENSE}; 4841917Swnj 4852926Swnj switch (cmd) { 4867636Ssam 4877636Ssam case MTIOCTOP: /* tape operation */ 4887636Ssam mtop = (struct mtop *)data; 4897636Ssam switch (mtop->mt_op) { 4907636Ssam 4912926Swnj case MTWEOF: 4927636Ssam callcount = mtop->mt_count; 4932926Swnj fcount = 1; 4942926Swnj break; 4957636Ssam 4962926Swnj case MTFSF: case MTBSF: 4977636Ssam callcount = mtop->mt_count; 4982926Swnj fcount = INF; 4992926Swnj break; 5007636Ssam 5012926Swnj case MTFSR: case MTBSR: 5022926Swnj callcount = 1; 5037636Ssam fcount = mtop->mt_count; 5042926Swnj break; 5057636Ssam 5062926Swnj case MTREW: case MTOFFL: 5072926Swnj callcount = 1; 5082926Swnj fcount = 1; 5092926Swnj break; 5107636Ssam 5112926Swnj default: 5128580Sroot return (ENXIO); 5132926Swnj } 5148580Sroot if (callcount <= 0 || fcount <= 0) 5158580Sroot return (EINVAL); 5162926Swnj while (--callcount >= 0) { 5177636Ssam htcommand(dev, htops[mtop->mt_op], fcount); 5187636Ssam if ((mtop->mt_op == MTFSR || mtop->mt_op == MTBSR) && 5198580Sroot bp->b_resid) 5208580Sroot return (EIO); 5213094Swnj if ((bp->b_flags&B_ERROR) || sc->sc_dsreg&HTDS_BOT) 5222926Swnj break; 5232926Swnj } 5248711Sroot return (geterror(bp)); 5257636Ssam 5262926Swnj case MTIOCGET: 5277636Ssam mtget = (struct mtget *)data; 5287636Ssam mtget->mt_dsreg = sc->sc_dsreg; 5297636Ssam mtget->mt_erreg = sc->sc_erreg; 5307636Ssam mtget->mt_resid = sc->sc_resid; 5317636Ssam mtget->mt_type = MT_ISHT; 5328580Sroot break; 5337636Ssam 5342926Swnj default: 5358580Sroot return (ENXIO); 5362926Swnj } 5378580Sroot return (0); 5382926Swnj } 5392926Swnj 5401917Swnj #define DBSIZE 20 5411917Swnj 5422926Swnj htdump() 5431917Swnj { 5442980Swnj register struct mba_device *mi; 5452926Swnj register struct mba_regs *mp; 5462926Swnj register struct htdevice *htaddr; 5472926Swnj int blk, num; 5482926Swnj int start; 5491917Swnj 5502926Swnj start = 0; 5512926Swnj num = maxfree; 5522926Swnj #define phys(a,b) ((b)((int)(a)&0x7fffffff)) 5532926Swnj if (htinfo[0] == 0) 5542926Swnj return (ENXIO); 5552980Swnj mi = phys(htinfo[0], struct mba_device *); 5562926Swnj mp = phys(mi->mi_hd, struct mba_hd *)->mh_physmba; 5573157Swnj mp->mba_cr = MBCR_IE; 5582926Swnj htaddr = (struct htdevice *)&mp->mba_drv[mi->mi_drive]; 5592926Swnj htaddr->httc = HTTC_PDP11|HTTC_1600BPI; 5602926Swnj htaddr->htcs1 = HT_DCLR|HT_GO; 5611917Swnj while (num > 0) { 5621917Swnj blk = num > DBSIZE ? DBSIZE : num; 5632926Swnj htdwrite(start, blk, htaddr, mp); 5642926Swnj start += blk; 5651917Swnj num -= blk; 5661917Swnj } 5673157Swnj hteof(htaddr); 5683157Swnj hteof(htaddr); 5692926Swnj htwait(htaddr); 5703181Swnj if (htaddr->htds&HTDS_ERR) 5713157Swnj return (EIO); 5722926Swnj htaddr->htcs1 = HT_REW|HT_GO; 5733103Swnj return (0); 5741917Swnj } 5751917Swnj 5762926Swnj htdwrite(dbuf, num, htaddr, mp) 5772926Swnj register dbuf, num; 5782926Swnj register struct htdevice *htaddr; 5792926Swnj struct mba_regs *mp; 5801917Swnj { 5812926Swnj register struct pte *io; 5821917Swnj register int i; 5831917Swnj 5842926Swnj htwait(htaddr); 5852926Swnj io = mp->mba_map; 5861917Swnj for (i = 0; i < num; i++) 5872926Swnj *(int *)io++ = dbuf++ | PG_V; 5882926Swnj htaddr->htfc = -(num*NBPG); 5892926Swnj mp->mba_sr = -1; 5902926Swnj mp->mba_bcr = -(num*NBPG); 5912926Swnj mp->mba_var = 0; 5922926Swnj htaddr->htcs1 = HT_WCOM|HT_GO; 5931917Swnj } 5941917Swnj 5952926Swnj htwait(htaddr) 5962926Swnj struct htdevice *htaddr; 5971917Swnj { 5981917Swnj register s; 5991917Swnj 6001917Swnj do 6012926Swnj s = htaddr->htds; 6022926Swnj while ((s & HTDS_DRY) == 0); 6031917Swnj } 6041917Swnj 6052926Swnj hteof(htaddr) 6062926Swnj struct htdevice *htaddr; 6071917Swnj { 6081917Swnj 6092926Swnj htwait(htaddr); 6102926Swnj htaddr->htcs1 = HT_WEOF|HT_GO; 6111917Swnj } 6121563Sbill #endif 613