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*31552Skarels * @(#)ht.c 7.5 (Berkeley) 06/18/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" 3331036Skarels #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]; 47*31552Skarels struct mba_slave *tuinfo[NTU]; 483103Swnj int htattach(), htslave(), htustart(), htndtint(), htdtint(); 492926Swnj struct mba_driver htdriver = 502980Swnj { htattach, htslave, htustart, 0, htdtint, htndtint, 512980Swnj httypes, "ht", "tu", htinfo }; 5222Sbill 532926Swnj #define MASKREG(r) ((r) & 0xffff) 5422Sbill 552926Swnj /* bits in minor device */ 562980Swnj #define TUUNIT(dev) (minor(dev)&03) 572926Swnj #define H_NOREWIND 04 5831094Skarels #define H_DENS(dev) ((minor(dev) >> 3) & 03) 5922Sbill 603094Swnj #define HTUNIT(dev) (tutoht[TUUNIT(dev)]) 612980Swnj 622926Swnj #define INF (daddr_t)1000000L /* a block number that wont exist */ 632926Swnj 643094Swnj struct tu_softc { 652926Swnj char sc_openf; 662926Swnj char sc_flags; 672926Swnj daddr_t sc_blkno; 682926Swnj daddr_t sc_nxrec; 692926Swnj u_short sc_erreg; 702926Swnj u_short sc_dsreg; 712926Swnj short sc_resid; 722926Swnj short sc_dens; 732980Swnj struct mba_device *sc_mi; 742980Swnj int sc_slave; 7518325Sralph struct tty *sc_ttyp; /* record user's tty for errors */ 7630918Skarels int sc_blks; /* number of I/O operations since open */ 7730918Skarels int sc_softerrs; /* number of soft I/O errors since open */ 783094Swnj } tu_softc[NTU]; 793094Swnj short tutoht[NTU]; 802926Swnj 812926Swnj /* 822926Swnj * Bits for sc_flags. 832926Swnj */ 842926Swnj #define H_WRITTEN 1 /* last operation was a write */ 852926Swnj #define H_ERASED 2 /* last write retry was an erase gap */ 862926Swnj #define H_REWIND 4 /* last unit start was a rewind */ 8722Sbill 883204Swnj char hter_bits[] = HTER_BITS; 893204Swnj char htds_bits[] = HTDS_BITS; 903204Swnj 912926Swnj /*ARGSUSED*/ 922980Swnj htattach(mi) 932980Swnj struct mba_device *mi; 942926Swnj { 952926Swnj 962926Swnj } 972926Swnj 987430Skre htslave(mi, ms, sn) 992980Swnj struct mba_device *mi; 1002980Swnj struct mba_slave *ms; 1017430Skre int sn; 1022980Swnj { 1033094Swnj register struct tu_softc *sc = &tu_softc[ms->ms_unit]; 1044756Swnj register struct htdevice *htaddr = (struct htdevice *)mi->mi_drv; 1052980Swnj 1067430Skre htaddr->httc = sn; 1074756Swnj if (htaddr->htdt & HTDT_SPR) { 1084756Swnj sc->sc_mi = mi; 1097430Skre sc->sc_slave = sn; 110*31552Skarels tuinfo[ms->ms_unit] = ms; 1114756Swnj tutoht[ms->ms_unit] = mi->mi_unit; 1124756Swnj return (1); 1134756Swnj } else 1144756Swnj return (0); 1152980Swnj } 1162980Swnj 11731094Skarels int htdens[4] = { HTTC_800BPI, HTTC_1600BPI, HTTC_6250BPI, HTTC_800BPI }; 11831094Skarels 11922Sbill htopen(dev, flag) 1202926Swnj dev_t dev; 1212926Swnj int flag; 12222Sbill { 1233094Swnj register int tuunit; 1242980Swnj register struct mba_device *mi; 1253094Swnj register struct tu_softc *sc; 1263203Swnj int olddens, dens; 12722Sbill 1283094Swnj tuunit = TUUNIT(dev); 129*31552Skarels if (tuunit >= NTU || tuinfo[tuunit]->ms_alive == 0 || 130*31552Skarels (mi = htinfo[HTUNIT(dev)]) == 0 || mi->mi_alive == 0) 1318580Sroot return (ENXIO); 13225052Skarels if ((sc = &tu_softc[tuunit])->sc_openf) 13325052Skarels return (EBUSY); 13430918Skarels sc->sc_openf = 1; 1353203Swnj olddens = sc->sc_dens; 13631094Skarels dens = sc->sc_dens = htdens[H_DENS(dev)] | HTTC_PDP11 | sc->sc_slave; 1373203Swnj htcommand(dev, HT_SENSE, 1); 1383203Swnj sc->sc_dens = olddens; 1393707Sroot if ((sc->sc_dsreg & HTDS_MOL) == 0) { 14030918Skarels sc->sc_openf = 0; 1413717Sroot uprintf("tu%d: not online\n", tuunit); 1428580Sroot return (EIO); 1432926Swnj } 1443707Sroot if ((flag&FWRITE) && (sc->sc_dsreg&HTDS_WRL)) { 14530918Skarels sc->sc_openf = 0; 1463717Sroot uprintf("tu%d: no write ring\n", tuunit); 1478580Sroot return (EIO); 1483707Sroot } 1493707Sroot if ((sc->sc_dsreg & HTDS_BOT) == 0 && (flag&FWRITE) && 1503707Sroot dens != sc->sc_dens) { 15130918Skarels sc->sc_openf = 0; 1523717Sroot uprintf("tu%d: can't change density in mid-tape\n", tuunit); 1538580Sroot return (EIO); 1543707Sroot } 1552926Swnj sc->sc_blkno = (daddr_t)0; 1562926Swnj sc->sc_nxrec = INF; 1572926Swnj sc->sc_flags = 0; 1583094Swnj sc->sc_dens = dens; 15930918Skarels sc->sc_blks = 0; 16030918Skarels sc->sc_softerrs = 0; 16118325Sralph sc->sc_ttyp = u.u_ttyp; 1628580Sroot return (0); 16322Sbill } 16422Sbill 16522Sbill htclose(dev, flag) 1662926Swnj register dev_t dev; 1672926Swnj register flag; 16822Sbill { 1693094Swnj register struct tu_softc *sc = &tu_softc[TUUNIT(dev)]; 17022Sbill 1712926Swnj if (flag == FWRITE || ((flag&FWRITE) && (sc->sc_flags&H_WRITTEN))) { 1722926Swnj htcommand(dev, HT_WEOF, 1); 1732926Swnj htcommand(dev, HT_WEOF, 1); 1742926Swnj htcommand(dev, HT_SREV, 1); 17522Sbill } 1762926Swnj if ((minor(dev)&H_NOREWIND) == 0) 1772926Swnj htcommand(dev, HT_REW, 0); 17830918Skarels if (sc->sc_blks > 100 && sc->sc_softerrs > sc->sc_blks / 100) 17930918Skarels log(LOG_INFO, "tu%d: %d soft errors in %d blocks\n", 18030918Skarels TUUNIT(dev), sc->sc_softerrs, sc->sc_blks); 1812926Swnj sc->sc_openf = 0; 18222Sbill } 18322Sbill 1842926Swnj htcommand(dev, com, count) 1852926Swnj dev_t dev; 1862926Swnj int com, count; 18722Sbill { 18822Sbill register struct buf *bp; 1895436Sroot register int s; 19022Sbill 1912926Swnj bp = &chtbuf[HTUNIT(dev)]; 1925436Sroot s = spl5(); 1932926Swnj while (bp->b_flags&B_BUSY) { 1943157Swnj if(bp->b_repcnt == 0 && (bp->b_flags&B_DONE)) 1952980Swnj break; 19622Sbill bp->b_flags |= B_WANTED; 19722Sbill sleep((caddr_t)bp, PRIBIO); 19822Sbill } 1992943Swnj bp->b_flags = B_BUSY|B_READ; 2005436Sroot splx(s); 20122Sbill bp->b_dev = dev; 2022926Swnj bp->b_command = com; 2032926Swnj bp->b_repcnt = count; 20422Sbill bp->b_blkno = 0; 20522Sbill htstrategy(bp); 2062926Swnj if (count == 0) 2072926Swnj return; 20822Sbill iowait(bp); 2092926Swnj if (bp->b_flags&B_WANTED) 21022Sbill wakeup((caddr_t)bp); 2112926Swnj bp->b_flags &= B_ERROR; 21222Sbill } 21322Sbill 21422Sbill htstrategy(bp) 2152926Swnj register struct buf *bp; 21622Sbill { 2173094Swnj register struct mba_device *mi = htinfo[HTUNIT(bp->b_dev)]; 2182926Swnj register struct buf *dp; 2195436Sroot register int s; 22022Sbill 22122Sbill bp->av_forw = NULL; 2222926Swnj dp = &mi->mi_tab; 2235436Sroot s = spl5(); 2242926Swnj if (dp->b_actf == NULL) 2252926Swnj dp->b_actf = bp; 22622Sbill else 2272926Swnj dp->b_actl->av_forw = bp; 2282926Swnj dp->b_actl = bp; 2292926Swnj if (dp->b_active == 0) 2302926Swnj mbustart(mi); 2315436Sroot splx(s); 23222Sbill } 23322Sbill 2342926Swnj htustart(mi) 2352980Swnj register struct mba_device *mi; 23622Sbill { 2372926Swnj register struct htdevice *htaddr = 2382926Swnj (struct htdevice *)mi->mi_drv; 2392926Swnj register struct buf *bp = mi->mi_tab.b_actf; 2403094Swnj register struct tu_softc *sc = &tu_softc[TUUNIT(bp->b_dev)]; 24122Sbill daddr_t blkno; 24222Sbill 2432926Swnj htaddr->httc = sc->sc_dens; 24415108Skarels #ifdef notdef 24515108Skarels /* unneeded, may hang controller */ 2463181Swnj if (bp == &chtbuf[HTUNIT(bp->b_dev)] && bp->b_command == HT_SENSE) { 2473157Swnj htaddr->htcs1 = HT_SENSE|HT_GO; 2483157Swnj mbclrattn(mi); 2493157Swnj } 25015108Skarels #endif 2512926Swnj sc->sc_dsreg = htaddr->htds; 2522926Swnj sc->sc_erreg = htaddr->hter; 2532926Swnj sc->sc_resid = htaddr->htfc; 2542926Swnj sc->sc_flags &= ~(H_WRITTEN|H_REWIND); 2552926Swnj if ((htaddr->htdt & HTDT_SPR) == 0 || (htaddr->htds & HTDS_MOL) == 0) 2562926Swnj if (sc->sc_openf > 0) 2572926Swnj sc->sc_openf = -1; 2582926Swnj if (sc->sc_openf < 0) { 2592926Swnj bp->b_flags |= B_ERROR; 2602926Swnj return (MBU_NEXT); 2612926Swnj } 2623094Swnj if (bp != &chtbuf[HTUNIT(bp->b_dev)]) { 2637379Ssam if (bdbtofsb(bp->b_blkno) > sc->sc_nxrec) { 2642926Swnj bp->b_flags |= B_ERROR; 2652926Swnj bp->b_error = ENXIO; 2662961Swnj return (MBU_NEXT); 2673094Swnj } 2687379Ssam if (bdbtofsb(bp->b_blkno) == sc->sc_nxrec && 2692926Swnj bp->b_flags&B_READ) { 2702926Swnj bp->b_resid = bp->b_bcount; 2712926Swnj clrbuf(bp); 2722961Swnj return (MBU_NEXT); 2733094Swnj } 2743094Swnj if ((bp->b_flags&B_READ)==0) 2757379Ssam sc->sc_nxrec = bdbtofsb(bp->b_blkno) + 1; 2762926Swnj } else { 2772961Swnj if (bp->b_command == HT_SENSE) 2782926Swnj return (MBU_NEXT); 2792926Swnj if (bp->b_command == HT_REW) 2802926Swnj sc->sc_flags |= H_REWIND; 2812926Swnj else 2822926Swnj htaddr->htfc = -bp->b_bcount; 2832926Swnj htaddr->htcs1 = bp->b_command|HT_GO; 2842926Swnj return (MBU_STARTED); 2852926Swnj } 2867379Ssam if ((blkno = sc->sc_blkno) == bdbtofsb(bp->b_blkno)) { 2872926Swnj htaddr->htfc = -bp->b_bcount; 2882926Swnj if ((bp->b_flags&B_READ) == 0) { 2893094Swnj if (mi->mi_tab.b_errcnt) { 2903094Swnj if ((sc->sc_flags & H_ERASED) == 0) { 2912926Swnj sc->sc_flags |= H_ERASED; 2922926Swnj htaddr->htcs1 = HT_ERASE | HT_GO; 2932926Swnj return (MBU_STARTED); 2942926Swnj } 2953094Swnj sc->sc_flags &= ~H_ERASED; 2963094Swnj } 2972926Swnj if (htaddr->htds & HTDS_EOT) { 2982926Swnj bp->b_resid = bp->b_bcount; 2996812Swnj bp->b_flags |= B_ERROR; 3002926Swnj return (MBU_NEXT); 3012926Swnj } 30222Sbill } 3032926Swnj return (MBU_DODATA); 30422Sbill } 3057379Ssam if (blkno < bdbtofsb(bp->b_blkno)) { 3067379Ssam htaddr->htfc = blkno - bdbtofsb(bp->b_blkno); 3072926Swnj htaddr->htcs1 = HT_SFORW|HT_GO; 30822Sbill } else { 3097379Ssam htaddr->htfc = bdbtofsb(bp->b_blkno) - blkno; 3102926Swnj htaddr->htcs1 = HT_SREV|HT_GO; 31122Sbill } 3122926Swnj return (MBU_STARTED); 31322Sbill } 31422Sbill 3153094Swnj htdtint(mi, mbsr) 3162980Swnj register struct mba_device *mi; 3173094Swnj int mbsr; 31822Sbill { 3192926Swnj register struct htdevice *htaddr = (struct htdevice *)mi->mi_drv; 3202926Swnj register struct buf *bp = mi->mi_tab.b_actf; 3213094Swnj register struct tu_softc *sc; 3222961Swnj int ds, er, mbs; 32322Sbill 3243094Swnj sc = &tu_softc[TUUNIT(bp->b_dev)]; 3252926Swnj ds = sc->sc_dsreg = MASKREG(htaddr->htds); 3262926Swnj er = sc->sc_erreg = MASKREG(htaddr->hter); 3272926Swnj sc->sc_resid = MASKREG(htaddr->htfc); 3283094Swnj mbs = mbsr; 3292926Swnj sc->sc_blkno++; 3302926Swnj if((bp->b_flags & B_READ) == 0) 3312926Swnj sc->sc_flags |= H_WRITTEN; 3323094Swnj if ((ds&(HTDS_ERR|HTDS_MOL)) != HTDS_MOL || mbs & MBSR_EBITS) { 3332926Swnj htaddr->htcs1 = HT_DCLR|HT_GO; 3342961Swnj mbclrattn(mi); 3352961Swnj if (bp == &rhtbuf[HTUNIT(bp->b_dev)]) { 3362926Swnj er &= ~HTER_FCE; 3373094Swnj mbs &= ~(MBSR_DTABT|MBSR_MBEXC); 3384276Sroot } 3392926Swnj if (bp->b_flags & B_READ && ds & HTDS_PES) 3402926Swnj er &= ~(HTER_CSITM|HTER_CORCRC); 3413094Swnj if (er&HTER_HARD || mbs&MBSR_EBITS || (ds&HTDS_MOL) == 0 || 3422961Swnj er && ++mi->mi_tab.b_errcnt >= 7) { 3432926Swnj if ((ds & HTDS_MOL) == 0 && sc->sc_openf > 0) 3442926Swnj sc->sc_openf = -1; 3453157Swnj if ((er&HTER_HARD) == HTER_FCE && 3463157Swnj (mbs&MBSR_EBITS) == (MBSR_DTABT|MBSR_MBEXC) && 3473157Swnj (ds&HTDS_MOL)) 3483157Swnj goto noprint; 34918325Sralph tprintf(sc->sc_ttyp, "tu%d: hard error bn%d mbsr=%b er=%b ds=%b\n", 3502980Swnj TUUNIT(bp->b_dev), bp->b_blkno, 3513094Swnj mbsr, mbsr_bits, 3523204Swnj sc->sc_erreg, hter_bits, 3533204Swnj sc->sc_dsreg, htds_bits); 3543157Swnj noprint: 35522Sbill bp->b_flags |= B_ERROR; 3562926Swnj return (MBD_DONE); 35722Sbill } 3582926Swnj if (er) 3592926Swnj return (MBD_RETRY); 36022Sbill } 3612926Swnj bp->b_resid = 0; 36230918Skarels sc->sc_blks++; 36330918Skarels if (mi->mi_tab.b_errcnt) 36430918Skarels sc->sc_softerrs++; 3652926Swnj if (bp->b_flags & B_READ) 3662926Swnj if (ds&HTDS_TM) { /* must be a read, right? */ 3672926Swnj bp->b_resid = bp->b_bcount; 3687379Ssam sc->sc_nxrec = bdbtofsb(bp->b_blkno); 3692926Swnj } else if(bp->b_bcount > MASKREG(htaddr->htfc)) 3702926Swnj bp->b_resid = bp->b_bcount - MASKREG(htaddr->htfc); 3712926Swnj return (MBD_DONE); 3722926Swnj } 37322Sbill 3742926Swnj htndtint(mi) 3752980Swnj register struct mba_device *mi; 3762926Swnj { 3772926Swnj register struct htdevice *htaddr = (struct htdevice *)mi->mi_drv; 3782926Swnj register struct buf *bp = mi->mi_tab.b_actf; 3793094Swnj register struct tu_softc *sc; 3802926Swnj int er, ds, fc; 38122Sbill 3823094Swnj ds = MASKREG(htaddr->htds); 3833094Swnj er = MASKREG(htaddr->hter); 3843094Swnj fc = MASKREG(htaddr->htfc); 3853094Swnj if (er) { 3862926Swnj htaddr->htcs1 = HT_DCLR|HT_GO; 3872961Swnj mbclrattn(mi); 3882961Swnj } 3893094Swnj if (bp == 0) 3903094Swnj return (MBN_SKIP); 3913094Swnj sc = &tu_softc[TUUNIT(bp->b_dev)]; 3923094Swnj sc->sc_dsreg = ds; 3933094Swnj sc->sc_erreg = er; 3943094Swnj sc->sc_resid = fc; 3953094Swnj if (bp == &chtbuf[HTUNIT(bp->b_dev)]) { 39626290Skarels switch ((int)bp->b_command) { 3973094Swnj case HT_REWOFFL: 3982926Swnj /* offline is on purpose; don't do anything special */ 3992926Swnj ds |= HTDS_MOL; 4003094Swnj break; 4013094Swnj case HT_SREV: 4023094Swnj /* if backspace file hit bot, its not an error */ 4033094Swnj if (er == (HTER_NEF|HTER_FCE) && ds&HTDS_BOT && 4043094Swnj bp->b_repcnt == INF) 4053094Swnj er &= ~HTER_NEF; 4063094Swnj break; 4073094Swnj } 4082926Swnj er &= ~HTER_FCE; 4092926Swnj if (er == 0) 4102926Swnj ds &= ~HTDS_ERR; 41122Sbill } 4122926Swnj if ((ds & (HTDS_ERR|HTDS_MOL)) != HTDS_MOL) { 4132926Swnj if ((ds & HTDS_MOL) == 0 && sc->sc_openf > 0) 4142926Swnj sc->sc_openf = -1; 41518325Sralph tprintf(sc->sc_ttyp, "tu%d: hard error bn%d er=%b ds=%b\n", 4162980Swnj TUUNIT(bp->b_dev), bp->b_blkno, 4173204Swnj sc->sc_erreg, hter_bits, sc->sc_dsreg, htds_bits); 4182926Swnj bp->b_flags |= B_ERROR; 4192926Swnj return (MBN_DONE); 4202926Swnj } 4213094Swnj if (bp == &chtbuf[HTUNIT(bp->b_dev)]) { 4222926Swnj if (sc->sc_flags & H_REWIND) 4232926Swnj return (ds & HTDS_BOT ? MBN_DONE : MBN_RETRY); 4242926Swnj bp->b_resid = -sc->sc_resid; 4252926Swnj return (MBN_DONE); 4262926Swnj } 4272926Swnj if (ds & HTDS_TM) 4287379Ssam if (sc->sc_blkno > bdbtofsb(bp->b_blkno)) { 4297379Ssam sc->sc_nxrec = bdbtofsb(bp->b_blkno) - fc; 4302926Swnj sc->sc_blkno = sc->sc_nxrec; 4313094Swnj } else { 4327379Ssam sc->sc_blkno = bdbtofsb(bp->b_blkno) + fc; 4332926Swnj sc->sc_nxrec = sc->sc_blkno - 1; 4342926Swnj } 4352926Swnj else 4367379Ssam sc->sc_blkno = bdbtofsb(bp->b_blkno); 4372926Swnj return (MBN_RETRY); 43822Sbill } 43922Sbill 4407739Sroot htread(dev, uio) 4412926Swnj dev_t dev; 4427739Sroot struct uio *uio; 44322Sbill { 4448157Sroot int errno; 4452926Swnj 4468157Sroot errno = htphys(dev, uio); 4478157Sroot if (errno) 4488157Sroot return (errno); 4498157Sroot return (physio(htstrategy, &rhtbuf[HTUNIT(dev)], dev, B_READ, minphys, uio)); 45022Sbill } 45122Sbill 4528605Sroot htwrite(dev, uio) 4538605Sroot dev_t dev; 4548688Sroot struct uio *uio; 45522Sbill { 4568157Sroot int errno; 4572926Swnj 4588157Sroot errno = htphys(dev, uio); 4598157Sroot if (errno) 4608157Sroot return (errno); 4618157Sroot return (physio(htstrategy, &rhtbuf[HTUNIT(dev)], dev, B_WRITE, minphys, uio)); 46222Sbill } 46322Sbill 4647739Sroot htphys(dev, uio) 4652926Swnj dev_t dev; 4667739Sroot struct uio *uio; 46722Sbill { 4683094Swnj register int htunit; 4693094Swnj register struct tu_softc *sc; 4703094Swnj register struct mba_device *mi; 47122Sbill daddr_t a; 47222Sbill 4733094Swnj htunit = HTUNIT(dev); 4747832Sroot if (htunit >= NHT || (mi = htinfo[htunit]) == 0 || mi->mi_alive == 0) 4757739Sroot return (ENXIO); 4767832Sroot a = uio->uio_offset >> 9; 4773094Swnj sc = &tu_softc[TUUNIT(dev)]; 4787379Ssam sc->sc_blkno = bdbtofsb(a); 4797379Ssam sc->sc_nxrec = bdbtofsb(a)+1; 4807739Sroot return (0); 48122Sbill } 4821917Swnj 4832926Swnj /*ARGSUSED*/ 4847636Ssam htioctl(dev, cmd, data, flag) 4852926Swnj dev_t dev; 4862926Swnj int cmd; 4877636Ssam caddr_t data; 4882926Swnj int flag; 4892926Swnj { 4903094Swnj register struct tu_softc *sc = &tu_softc[TUUNIT(dev)]; 4913094Swnj register struct buf *bp = &chtbuf[HTUNIT(dev)]; 4922926Swnj register callcount; 4932926Swnj int fcount; 4947636Ssam struct mtop *mtop; 4957636Ssam struct mtget *mtget; 4962926Swnj /* we depend of the values and order of the MT codes here */ 4972926Swnj static htops[] = 4982926Swnj {HT_WEOF,HT_SFORW,HT_SREV,HT_SFORW,HT_SREV,HT_REW,HT_REWOFFL,HT_SENSE}; 4991917Swnj 5002926Swnj switch (cmd) { 5017636Ssam 5027636Ssam case MTIOCTOP: /* tape operation */ 5037636Ssam mtop = (struct mtop *)data; 5047636Ssam switch (mtop->mt_op) { 5057636Ssam 5062926Swnj case MTWEOF: 5077636Ssam callcount = mtop->mt_count; 5082926Swnj fcount = 1; 5092926Swnj break; 5107636Ssam 5112926Swnj case MTFSF: case MTBSF: 5127636Ssam callcount = mtop->mt_count; 5132926Swnj fcount = INF; 5142926Swnj break; 5157636Ssam 5162926Swnj case MTFSR: case MTBSR: 5172926Swnj callcount = 1; 5187636Ssam fcount = mtop->mt_count; 5192926Swnj break; 5207636Ssam 5212926Swnj case MTREW: case MTOFFL: 5222926Swnj callcount = 1; 5232926Swnj fcount = 1; 5242926Swnj break; 5257636Ssam 5262926Swnj default: 5278580Sroot return (ENXIO); 5282926Swnj } 5298580Sroot if (callcount <= 0 || fcount <= 0) 5308580Sroot return (EINVAL); 5312926Swnj while (--callcount >= 0) { 5327636Ssam htcommand(dev, htops[mtop->mt_op], fcount); 5337636Ssam if ((mtop->mt_op == MTFSR || mtop->mt_op == MTBSR) && 5348580Sroot bp->b_resid) 5358580Sroot return (EIO); 5363094Swnj if ((bp->b_flags&B_ERROR) || sc->sc_dsreg&HTDS_BOT) 5372926Swnj break; 5382926Swnj } 5398711Sroot return (geterror(bp)); 5407636Ssam 5412926Swnj case MTIOCGET: 5427636Ssam mtget = (struct mtget *)data; 5437636Ssam mtget->mt_dsreg = sc->sc_dsreg; 5447636Ssam mtget->mt_erreg = sc->sc_erreg; 5457636Ssam mtget->mt_resid = sc->sc_resid; 5467636Ssam mtget->mt_type = MT_ISHT; 5478580Sroot break; 5487636Ssam 5492926Swnj default: 5508580Sroot return (ENXIO); 5512926Swnj } 5528580Sroot return (0); 5532926Swnj } 5542926Swnj 5551917Swnj #define DBSIZE 20 5561917Swnj 5572926Swnj htdump() 5581917Swnj { 5592980Swnj register struct mba_device *mi; 5602926Swnj register struct mba_regs *mp; 5612926Swnj register struct htdevice *htaddr; 5622926Swnj int blk, num; 5632926Swnj int start; 5641917Swnj 5652926Swnj start = 0; 5662926Swnj num = maxfree; 5672926Swnj #define phys(a,b) ((b)((int)(a)&0x7fffffff)) 5682926Swnj if (htinfo[0] == 0) 5692926Swnj return (ENXIO); 5702980Swnj mi = phys(htinfo[0], struct mba_device *); 5712926Swnj mp = phys(mi->mi_hd, struct mba_hd *)->mh_physmba; 5723157Swnj mp->mba_cr = MBCR_IE; 5732926Swnj htaddr = (struct htdevice *)&mp->mba_drv[mi->mi_drive]; 5742926Swnj htaddr->httc = HTTC_PDP11|HTTC_1600BPI; 5752926Swnj htaddr->htcs1 = HT_DCLR|HT_GO; 5761917Swnj while (num > 0) { 5771917Swnj blk = num > DBSIZE ? DBSIZE : num; 5782926Swnj htdwrite(start, blk, htaddr, mp); 5792926Swnj start += blk; 5801917Swnj num -= blk; 5811917Swnj } 5823157Swnj hteof(htaddr); 5833157Swnj hteof(htaddr); 5842926Swnj htwait(htaddr); 5853181Swnj if (htaddr->htds&HTDS_ERR) 5863157Swnj return (EIO); 5872926Swnj htaddr->htcs1 = HT_REW|HT_GO; 5883103Swnj return (0); 5891917Swnj } 5901917Swnj 5912926Swnj htdwrite(dbuf, num, htaddr, mp) 5922926Swnj register dbuf, num; 5932926Swnj register struct htdevice *htaddr; 5942926Swnj struct mba_regs *mp; 5951917Swnj { 5962926Swnj register struct pte *io; 5971917Swnj register int i; 5981917Swnj 5992926Swnj htwait(htaddr); 6002926Swnj io = mp->mba_map; 6011917Swnj for (i = 0; i < num; i++) 6022926Swnj *(int *)io++ = dbuf++ | PG_V; 6032926Swnj htaddr->htfc = -(num*NBPG); 6042926Swnj mp->mba_sr = -1; 6052926Swnj mp->mba_bcr = -(num*NBPG); 6062926Swnj mp->mba_var = 0; 6072926Swnj htaddr->htcs1 = HT_WCOM|HT_GO; 6081917Swnj } 6091917Swnj 6102926Swnj htwait(htaddr) 6112926Swnj struct htdevice *htaddr; 6121917Swnj { 6131917Swnj register s; 6141917Swnj 6151917Swnj do 6162926Swnj s = htaddr->htds; 6172926Swnj while ((s & HTDS_DRY) == 0); 6181917Swnj } 6191917Swnj 6202926Swnj hteof(htaddr) 6212926Swnj struct htdevice *htaddr; 6221917Swnj { 6231917Swnj 6242926Swnj htwait(htaddr); 6252926Swnj htaddr->htcs1 = HT_WEOF|HT_GO; 6261917Swnj } 6271563Sbill #endif 628