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*40909Ssklower * @(#)ht.c 7.11 (Berkeley) 04/12/90 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 "file.h" 2517118Sbloom #include "user.h" 2640898Ssklower #include "proc.h" 2717118Sbloom #include "map.h" 2817118Sbloom #include "ioctl.h" 2917118Sbloom #include "mtio.h" 3017118Sbloom #include "cmap.h" 3118325Sralph #include "tty.h" 3231036Skarels #include "syslog.h" 3322Sbill 3437509Smckusick #include "machine/pte.h" 358469Sroot #include "../vax/cpu.h" 3617118Sbloom #include "mbareg.h" 3717118Sbloom #include "mbavar.h" 3817118Sbloom #include "htreg.h" 3922Sbill 402926Swnj struct buf chtbuf[NHT]; 4122Sbill 422926Swnj short httypes[] = 433181Swnj { MBDT_TM03, MBDT_TE16, MBDT_TU45, MBDT_TU77, 0 }; 442980Swnj struct mba_device *htinfo[NHT]; 4531552Skarels struct mba_slave *tuinfo[NTU]; 463103Swnj int htattach(), htslave(), htustart(), htndtint(), htdtint(); 472926Swnj struct mba_driver htdriver = 482980Swnj { htattach, htslave, htustart, 0, htdtint, htndtint, 492980Swnj httypes, "ht", "tu", htinfo }; 5022Sbill 512926Swnj #define MASKREG(r) ((r) & 0xffff) 5222Sbill 532926Swnj /* bits in minor device */ 542980Swnj #define TUUNIT(dev) (minor(dev)&03) 552926Swnj #define H_NOREWIND 04 5631094Skarels #define H_DENS(dev) ((minor(dev) >> 3) & 03) 5722Sbill 5834220Sbostic #define HTUNIT(dev) (tuinfo[TUUNIT(dev)]->ms_ctlr) 592980Swnj 602926Swnj #define INF (daddr_t)1000000L /* a block number that wont exist */ 612926Swnj 623094Swnj struct tu_softc { 632926Swnj char sc_openf; 642926Swnj char sc_flags; 652926Swnj daddr_t sc_blkno; 662926Swnj daddr_t sc_nxrec; 672926Swnj u_short sc_erreg; 682926Swnj u_short sc_dsreg; 692926Swnj short sc_resid; 702926Swnj short sc_dens; 7140898Ssklower caddr_t sc_ctty; /* record user's tty for errors */ 7230918Skarels int sc_blks; /* number of I/O operations since open */ 7330918Skarels int sc_softerrs; /* number of soft I/O errors since open */ 743094Swnj } tu_softc[NTU]; 752926Swnj 762926Swnj /* 772926Swnj * Bits for sc_flags. 782926Swnj */ 792926Swnj #define H_WRITTEN 1 /* last operation was a write */ 802926Swnj #define H_ERASED 2 /* last write retry was an erase gap */ 812926Swnj #define H_REWIND 4 /* last unit start was a rewind */ 8222Sbill 833204Swnj char hter_bits[] = HTER_BITS; 843204Swnj char htds_bits[] = HTDS_BITS; 853204Swnj 862926Swnj /*ARGSUSED*/ 872980Swnj htattach(mi) 882980Swnj struct mba_device *mi; 892926Swnj { 902926Swnj 912926Swnj } 922926Swnj 937430Skre htslave(mi, ms, sn) 942980Swnj struct mba_device *mi; 952980Swnj struct mba_slave *ms; 967430Skre int sn; 972980Swnj { 984756Swnj register struct htdevice *htaddr = (struct htdevice *)mi->mi_drv; 992980Swnj 1007430Skre htaddr->httc = sn; 1014756Swnj if (htaddr->htdt & HTDT_SPR) { 10231552Skarels tuinfo[ms->ms_unit] = ms; 1034756Swnj return (1); 1044756Swnj } else 1054756Swnj return (0); 1062980Swnj } 1072980Swnj 10831094Skarels int htdens[4] = { HTTC_800BPI, HTTC_1600BPI, HTTC_6250BPI, HTTC_800BPI }; 10931094Skarels 11022Sbill htopen(dev, flag) 1112926Swnj dev_t dev; 1122926Swnj int flag; 11322Sbill { 1143094Swnj register int tuunit; 1153094Swnj register struct tu_softc *sc; 11634220Sbostic register struct mba_slave *ms; 1173203Swnj int olddens, dens; 11822Sbill 1193094Swnj tuunit = TUUNIT(dev); 12034220Sbostic if (tuunit >= NTU || (ms = tuinfo[tuunit]) == NULL || 12134220Sbostic ms->ms_alive == 0 || htinfo[ms->ms_ctlr]->mi_alive == 0) 1228580Sroot return (ENXIO); 12325052Skarels if ((sc = &tu_softc[tuunit])->sc_openf) 12425052Skarels return (EBUSY); 12530918Skarels sc->sc_openf = 1; 1263203Swnj olddens = sc->sc_dens; 12734220Sbostic dens = sc->sc_dens = htdens[H_DENS(dev)] | HTTC_PDP11 | ms->ms_slave; 1283203Swnj htcommand(dev, HT_SENSE, 1); 1293203Swnj sc->sc_dens = olddens; 1303707Sroot if ((sc->sc_dsreg & HTDS_MOL) == 0) { 13130918Skarels sc->sc_openf = 0; 1323717Sroot uprintf("tu%d: not online\n", tuunit); 1338580Sroot return (EIO); 1342926Swnj } 1353707Sroot if ((flag&FWRITE) && (sc->sc_dsreg&HTDS_WRL)) { 13630918Skarels sc->sc_openf = 0; 1373717Sroot uprintf("tu%d: no write ring\n", tuunit); 1388580Sroot return (EIO); 1393707Sroot } 1403707Sroot if ((sc->sc_dsreg & HTDS_BOT) == 0 && (flag&FWRITE) && 1413707Sroot dens != sc->sc_dens) { 14230918Skarels sc->sc_openf = 0; 1433717Sroot uprintf("tu%d: can't change density in mid-tape\n", tuunit); 1448580Sroot return (EIO); 1453707Sroot } 1462926Swnj sc->sc_blkno = (daddr_t)0; 1472926Swnj sc->sc_nxrec = INF; 1482926Swnj sc->sc_flags = 0; 1493094Swnj sc->sc_dens = dens; 15030918Skarels sc->sc_blks = 0; 15130918Skarels sc->sc_softerrs = 0; 15240898Ssklower sc->sc_ctty = (caddr_t)(u.u_procp->p_flag&SCTTY ? 15340898Ssklower u.u_procp->p_session->s_ttyp : 0); 1548580Sroot return (0); 15522Sbill } 15622Sbill 15722Sbill htclose(dev, flag) 1582926Swnj register dev_t dev; 1592926Swnj register flag; 16022Sbill { 1613094Swnj register struct tu_softc *sc = &tu_softc[TUUNIT(dev)]; 16222Sbill 1632926Swnj if (flag == FWRITE || ((flag&FWRITE) && (sc->sc_flags&H_WRITTEN))) { 1642926Swnj htcommand(dev, HT_WEOF, 1); 1652926Swnj htcommand(dev, HT_WEOF, 1); 1662926Swnj htcommand(dev, HT_SREV, 1); 16722Sbill } 1682926Swnj if ((minor(dev)&H_NOREWIND) == 0) 1692926Swnj htcommand(dev, HT_REW, 0); 17030918Skarels if (sc->sc_blks > 100 && sc->sc_softerrs > sc->sc_blks / 100) 17130918Skarels log(LOG_INFO, "tu%d: %d soft errors in %d blocks\n", 17230918Skarels TUUNIT(dev), sc->sc_softerrs, sc->sc_blks); 1732926Swnj sc->sc_openf = 0; 17440733Skarels return (0); 17522Sbill } 17622Sbill 1772926Swnj htcommand(dev, com, count) 1782926Swnj dev_t dev; 1792926Swnj int com, count; 18022Sbill { 18122Sbill register struct buf *bp; 1825436Sroot register int s; 18322Sbill 1842926Swnj bp = &chtbuf[HTUNIT(dev)]; 1855436Sroot s = spl5(); 1862926Swnj while (bp->b_flags&B_BUSY) { 1873157Swnj if(bp->b_repcnt == 0 && (bp->b_flags&B_DONE)) 1882980Swnj break; 18922Sbill bp->b_flags |= B_WANTED; 19022Sbill sleep((caddr_t)bp, PRIBIO); 19122Sbill } 1922943Swnj bp->b_flags = B_BUSY|B_READ; 1935436Sroot splx(s); 19422Sbill bp->b_dev = dev; 1952926Swnj bp->b_command = com; 1962926Swnj bp->b_repcnt = count; 19722Sbill bp->b_blkno = 0; 19822Sbill htstrategy(bp); 1992926Swnj if (count == 0) 2002926Swnj return; 20122Sbill iowait(bp); 2022926Swnj if (bp->b_flags&B_WANTED) 20322Sbill wakeup((caddr_t)bp); 2042926Swnj bp->b_flags &= B_ERROR; 20522Sbill } 20622Sbill 20722Sbill htstrategy(bp) 2082926Swnj register struct buf *bp; 20922Sbill { 2103094Swnj register struct mba_device *mi = htinfo[HTUNIT(bp->b_dev)]; 2112926Swnj register struct buf *dp; 2125436Sroot register int s; 21322Sbill 21422Sbill bp->av_forw = NULL; 2152926Swnj dp = &mi->mi_tab; 2165436Sroot s = spl5(); 2172926Swnj if (dp->b_actf == NULL) 2182926Swnj dp->b_actf = bp; 21922Sbill else 2202926Swnj dp->b_actl->av_forw = bp; 2212926Swnj dp->b_actl = bp; 2222926Swnj if (dp->b_active == 0) 2232926Swnj mbustart(mi); 2245436Sroot splx(s); 22522Sbill } 22622Sbill 2272926Swnj htustart(mi) 2282980Swnj register struct mba_device *mi; 22922Sbill { 2302926Swnj register struct htdevice *htaddr = 2312926Swnj (struct htdevice *)mi->mi_drv; 2322926Swnj register struct buf *bp = mi->mi_tab.b_actf; 2333094Swnj register struct tu_softc *sc = &tu_softc[TUUNIT(bp->b_dev)]; 23422Sbill daddr_t blkno; 23522Sbill 2362926Swnj htaddr->httc = sc->sc_dens; 23715108Skarels #ifdef notdef 23815108Skarels /* unneeded, may hang controller */ 2393181Swnj if (bp == &chtbuf[HTUNIT(bp->b_dev)] && bp->b_command == HT_SENSE) { 2403157Swnj htaddr->htcs1 = HT_SENSE|HT_GO; 2413157Swnj mbclrattn(mi); 2423157Swnj } 24315108Skarels #endif 2442926Swnj sc->sc_dsreg = htaddr->htds; 2452926Swnj sc->sc_erreg = htaddr->hter; 2462926Swnj sc->sc_resid = htaddr->htfc; 2472926Swnj sc->sc_flags &= ~(H_WRITTEN|H_REWIND); 2482926Swnj if ((htaddr->htdt & HTDT_SPR) == 0 || (htaddr->htds & HTDS_MOL) == 0) 2492926Swnj if (sc->sc_openf > 0) 2502926Swnj sc->sc_openf = -1; 2512926Swnj if (sc->sc_openf < 0) { 2522926Swnj bp->b_flags |= B_ERROR; 2532926Swnj return (MBU_NEXT); 2542926Swnj } 2553094Swnj if (bp != &chtbuf[HTUNIT(bp->b_dev)]) { 25634220Sbostic /* transfer: check positioning */ 25734220Sbostic if (bp->b_flags & B_RAW) { 25834220Sbostic /* raw transfer: record position for retry */ 25934220Sbostic if (mi->mi_tab.b_errcnt == 0) { 26034220Sbostic sc->sc_blkno = bdbtofsb(bp->b_blkno); 26134220Sbostic sc->sc_nxrec = sc->sc_blkno + 1; 26234220Sbostic } 26334220Sbostic } else { 26434220Sbostic if (bdbtofsb(bp->b_blkno) > sc->sc_nxrec) { 26534220Sbostic bp->b_flags |= B_ERROR; 26634220Sbostic bp->b_error = ENXIO; 26734220Sbostic return (MBU_NEXT); 26834220Sbostic } 26934220Sbostic if (bdbtofsb(bp->b_blkno) == sc->sc_nxrec && 27034220Sbostic bp->b_flags&B_READ) { 27134220Sbostic bp->b_resid = bp->b_bcount; 27234220Sbostic clrbuf(bp); 27334220Sbostic return (MBU_NEXT); 27434220Sbostic } 27534220Sbostic if ((bp->b_flags&B_READ)==0) 27634220Sbostic sc->sc_nxrec = bdbtofsb(bp->b_blkno) + 1; 2773094Swnj } 2782926Swnj } else { 2792961Swnj if (bp->b_command == HT_SENSE) 2802926Swnj return (MBU_NEXT); 2812926Swnj if (bp->b_command == HT_REW) 2822926Swnj sc->sc_flags |= H_REWIND; 2832926Swnj else 2842926Swnj htaddr->htfc = -bp->b_bcount; 2852926Swnj htaddr->htcs1 = bp->b_command|HT_GO; 2862926Swnj return (MBU_STARTED); 2872926Swnj } 2887379Ssam if ((blkno = sc->sc_blkno) == bdbtofsb(bp->b_blkno)) { 2892926Swnj htaddr->htfc = -bp->b_bcount; 2902926Swnj if ((bp->b_flags&B_READ) == 0) { 2913094Swnj if (mi->mi_tab.b_errcnt) { 2923094Swnj if ((sc->sc_flags & H_ERASED) == 0) { 2932926Swnj sc->sc_flags |= H_ERASED; 2942926Swnj htaddr->htcs1 = HT_ERASE | HT_GO; 2952926Swnj return (MBU_STARTED); 2962926Swnj } 2973094Swnj sc->sc_flags &= ~H_ERASED; 2983094Swnj } 2992926Swnj if (htaddr->htds & HTDS_EOT) { 3002926Swnj bp->b_resid = bp->b_bcount; 3016812Swnj bp->b_flags |= B_ERROR; 3022926Swnj return (MBU_NEXT); 3032926Swnj } 30422Sbill } 3052926Swnj return (MBU_DODATA); 30622Sbill } 3077379Ssam if (blkno < bdbtofsb(bp->b_blkno)) { 3087379Ssam htaddr->htfc = blkno - bdbtofsb(bp->b_blkno); 3092926Swnj htaddr->htcs1 = HT_SFORW|HT_GO; 31022Sbill } else { 3117379Ssam htaddr->htfc = bdbtofsb(bp->b_blkno) - blkno; 3122926Swnj htaddr->htcs1 = HT_SREV|HT_GO; 31322Sbill } 3142926Swnj return (MBU_STARTED); 31522Sbill } 31622Sbill 3173094Swnj htdtint(mi, mbsr) 3182980Swnj register struct mba_device *mi; 3193094Swnj int mbsr; 32022Sbill { 3212926Swnj register struct htdevice *htaddr = (struct htdevice *)mi->mi_drv; 3222926Swnj register struct buf *bp = mi->mi_tab.b_actf; 3233094Swnj register struct tu_softc *sc; 3242961Swnj int ds, er, mbs; 32522Sbill 3263094Swnj sc = &tu_softc[TUUNIT(bp->b_dev)]; 3272926Swnj ds = sc->sc_dsreg = MASKREG(htaddr->htds); 3282926Swnj er = sc->sc_erreg = MASKREG(htaddr->hter); 3292926Swnj sc->sc_resid = MASKREG(htaddr->htfc); 3303094Swnj mbs = mbsr; 3312926Swnj sc->sc_blkno++; 3322926Swnj if((bp->b_flags & B_READ) == 0) 3332926Swnj sc->sc_flags |= H_WRITTEN; 3343094Swnj if ((ds&(HTDS_ERR|HTDS_MOL)) != HTDS_MOL || mbs & MBSR_EBITS) { 3352926Swnj htaddr->htcs1 = HT_DCLR|HT_GO; 3362961Swnj mbclrattn(mi); 33734220Sbostic if (bp->b_flags & B_RAW) { 3382926Swnj er &= ~HTER_FCE; 3393094Swnj mbs &= ~(MBSR_DTABT|MBSR_MBEXC); 3404276Sroot } 3412926Swnj if (bp->b_flags & B_READ && ds & HTDS_PES) 3422926Swnj er &= ~(HTER_CSITM|HTER_CORCRC); 3433094Swnj if (er&HTER_HARD || mbs&MBSR_EBITS || (ds&HTDS_MOL) == 0 || 3442961Swnj er && ++mi->mi_tab.b_errcnt >= 7) { 3452926Swnj if ((ds & HTDS_MOL) == 0 && sc->sc_openf > 0) 3462926Swnj sc->sc_openf = -1; 3473157Swnj if ((er&HTER_HARD) == HTER_FCE && 3483157Swnj (mbs&MBSR_EBITS) == (MBSR_DTABT|MBSR_MBEXC) && 3493157Swnj (ds&HTDS_MOL)) 3503157Swnj goto noprint; 35140898Ssklower tprintf(sc->sc_ctty, "tu%d: hard error bn%d mbsr=%b er=%b ds=%b\n", 3522980Swnj TUUNIT(bp->b_dev), bp->b_blkno, 3533094Swnj mbsr, mbsr_bits, 3543204Swnj sc->sc_erreg, hter_bits, 3553204Swnj sc->sc_dsreg, htds_bits); 3563157Swnj noprint: 35722Sbill bp->b_flags |= B_ERROR; 3582926Swnj return (MBD_DONE); 35922Sbill } 3602926Swnj if (er) 3612926Swnj return (MBD_RETRY); 36222Sbill } 3632926Swnj bp->b_resid = 0; 36430918Skarels sc->sc_blks++; 36530918Skarels if (mi->mi_tab.b_errcnt) 36630918Skarels sc->sc_softerrs++; 3672926Swnj if (bp->b_flags & B_READ) 3682926Swnj if (ds&HTDS_TM) { /* must be a read, right? */ 3692926Swnj bp->b_resid = bp->b_bcount; 3707379Ssam sc->sc_nxrec = bdbtofsb(bp->b_blkno); 3712926Swnj } else if(bp->b_bcount > MASKREG(htaddr->htfc)) 3722926Swnj bp->b_resid = bp->b_bcount - MASKREG(htaddr->htfc); 3732926Swnj return (MBD_DONE); 3742926Swnj } 37522Sbill 3762926Swnj htndtint(mi) 3772980Swnj register struct mba_device *mi; 3782926Swnj { 3792926Swnj register struct htdevice *htaddr = (struct htdevice *)mi->mi_drv; 3802926Swnj register struct buf *bp = mi->mi_tab.b_actf; 3813094Swnj register struct tu_softc *sc; 3822926Swnj int er, ds, fc; 38322Sbill 3843094Swnj ds = MASKREG(htaddr->htds); 3853094Swnj er = MASKREG(htaddr->hter); 3863094Swnj fc = MASKREG(htaddr->htfc); 3873094Swnj if (er) { 3882926Swnj htaddr->htcs1 = HT_DCLR|HT_GO; 3892961Swnj mbclrattn(mi); 3902961Swnj } 3913094Swnj if (bp == 0) 3923094Swnj return (MBN_SKIP); 3933094Swnj sc = &tu_softc[TUUNIT(bp->b_dev)]; 3943094Swnj sc->sc_dsreg = ds; 3953094Swnj sc->sc_erreg = er; 3963094Swnj sc->sc_resid = fc; 3973094Swnj if (bp == &chtbuf[HTUNIT(bp->b_dev)]) { 39826290Skarels switch ((int)bp->b_command) { 3993094Swnj case HT_REWOFFL: 4002926Swnj /* offline is on purpose; don't do anything special */ 4012926Swnj ds |= HTDS_MOL; 4023094Swnj break; 4033094Swnj case HT_SREV: 4043094Swnj /* if backspace file hit bot, its not an error */ 4053094Swnj if (er == (HTER_NEF|HTER_FCE) && ds&HTDS_BOT && 4063094Swnj bp->b_repcnt == INF) 4073094Swnj er &= ~HTER_NEF; 4083094Swnj break; 4093094Swnj } 4102926Swnj er &= ~HTER_FCE; 4112926Swnj if (er == 0) 4122926Swnj ds &= ~HTDS_ERR; 41322Sbill } 4142926Swnj if ((ds & (HTDS_ERR|HTDS_MOL)) != HTDS_MOL) { 4152926Swnj if ((ds & HTDS_MOL) == 0 && sc->sc_openf > 0) 4162926Swnj sc->sc_openf = -1; 41740898Ssklower tprintf(sc->sc_ctty, "tu%d: hard error bn%d er=%b ds=%b\n", 4182980Swnj TUUNIT(bp->b_dev), bp->b_blkno, 4193204Swnj sc->sc_erreg, hter_bits, sc->sc_dsreg, htds_bits); 4202926Swnj bp->b_flags |= B_ERROR; 4212926Swnj return (MBN_DONE); 4222926Swnj } 4233094Swnj if (bp == &chtbuf[HTUNIT(bp->b_dev)]) { 4242926Swnj if (sc->sc_flags & H_REWIND) 4252926Swnj return (ds & HTDS_BOT ? MBN_DONE : MBN_RETRY); 4262926Swnj bp->b_resid = -sc->sc_resid; 4272926Swnj return (MBN_DONE); 4282926Swnj } 4292926Swnj if (ds & HTDS_TM) 4307379Ssam if (sc->sc_blkno > bdbtofsb(bp->b_blkno)) { 4317379Ssam sc->sc_nxrec = bdbtofsb(bp->b_blkno) - fc; 4322926Swnj sc->sc_blkno = sc->sc_nxrec; 4333094Swnj } else { 4347379Ssam sc->sc_blkno = bdbtofsb(bp->b_blkno) + fc; 4352926Swnj sc->sc_nxrec = sc->sc_blkno - 1; 4362926Swnj } 4372926Swnj else 4387379Ssam sc->sc_blkno = bdbtofsb(bp->b_blkno); 4392926Swnj return (MBN_RETRY); 44022Sbill } 44122Sbill 4422926Swnj /*ARGSUSED*/ 4437636Ssam htioctl(dev, cmd, data, flag) 4442926Swnj dev_t dev; 4452926Swnj int cmd; 4467636Ssam caddr_t data; 4472926Swnj int flag; 4482926Swnj { 4493094Swnj register struct tu_softc *sc = &tu_softc[TUUNIT(dev)]; 4503094Swnj register struct buf *bp = &chtbuf[HTUNIT(dev)]; 4512926Swnj register callcount; 452*40909Ssklower int fcount, error = 0; 4537636Ssam struct mtop *mtop; 4547636Ssam struct mtget *mtget; 4552926Swnj /* we depend of the values and order of the MT codes here */ 4562926Swnj static htops[] = 4572926Swnj {HT_WEOF,HT_SFORW,HT_SREV,HT_SFORW,HT_SREV,HT_REW,HT_REWOFFL,HT_SENSE}; 4581917Swnj 4592926Swnj switch (cmd) { 4607636Ssam 4617636Ssam case MTIOCTOP: /* tape operation */ 4627636Ssam mtop = (struct mtop *)data; 4637636Ssam switch (mtop->mt_op) { 4647636Ssam 4652926Swnj case MTWEOF: 4667636Ssam callcount = mtop->mt_count; 4672926Swnj fcount = 1; 4682926Swnj break; 4697636Ssam 4702926Swnj case MTFSF: case MTBSF: 4717636Ssam callcount = mtop->mt_count; 4722926Swnj fcount = INF; 4732926Swnj break; 4747636Ssam 4752926Swnj case MTFSR: case MTBSR: 4762926Swnj callcount = 1; 4777636Ssam fcount = mtop->mt_count; 4782926Swnj break; 4797636Ssam 4802926Swnj case MTREW: case MTOFFL: 4812926Swnj callcount = 1; 4822926Swnj fcount = 1; 4832926Swnj break; 4847636Ssam 4852926Swnj default: 4868580Sroot return (ENXIO); 4872926Swnj } 4888580Sroot if (callcount <= 0 || fcount <= 0) 4898580Sroot return (EINVAL); 4902926Swnj while (--callcount >= 0) { 4917636Ssam htcommand(dev, htops[mtop->mt_op], fcount); 4927636Ssam if ((mtop->mt_op == MTFSR || mtop->mt_op == MTBSR) && 4938580Sroot bp->b_resid) 4948580Sroot return (EIO); 4953094Swnj if ((bp->b_flags&B_ERROR) || sc->sc_dsreg&HTDS_BOT) 4962926Swnj break; 4972926Swnj } 498*40909Ssklower if (bp->b_flags&B_ERROR) 499*40909Ssklower if ((error = bp->b_error)==0) 500*40909Ssklower return (EIO); 501*40909Ssklower return (error); 5027636Ssam 5032926Swnj case MTIOCGET: 5047636Ssam mtget = (struct mtget *)data; 5057636Ssam mtget->mt_dsreg = sc->sc_dsreg; 5067636Ssam mtget->mt_erreg = sc->sc_erreg; 5077636Ssam mtget->mt_resid = sc->sc_resid; 5087636Ssam mtget->mt_type = MT_ISHT; 5098580Sroot break; 5107636Ssam 5112926Swnj default: 5128580Sroot return (ENXIO); 5132926Swnj } 5148580Sroot return (0); 5152926Swnj } 5162926Swnj 5171917Swnj #define DBSIZE 20 5181917Swnj 5192926Swnj htdump() 5201917Swnj { 5212980Swnj register struct mba_device *mi; 5222926Swnj register struct mba_regs *mp; 5232926Swnj register struct htdevice *htaddr; 5242926Swnj int blk, num; 5252926Swnj int start; 5261917Swnj 5272926Swnj start = 0; 5282926Swnj num = maxfree; 5292926Swnj #define phys(a,b) ((b)((int)(a)&0x7fffffff)) 5302926Swnj if (htinfo[0] == 0) 5312926Swnj return (ENXIO); 5322980Swnj mi = phys(htinfo[0], struct mba_device *); 5332926Swnj mp = phys(mi->mi_hd, struct mba_hd *)->mh_physmba; 5343157Swnj mp->mba_cr = MBCR_IE; 5352926Swnj htaddr = (struct htdevice *)&mp->mba_drv[mi->mi_drive]; 5362926Swnj htaddr->httc = HTTC_PDP11|HTTC_1600BPI; 5372926Swnj htaddr->htcs1 = HT_DCLR|HT_GO; 5381917Swnj while (num > 0) { 5391917Swnj blk = num > DBSIZE ? DBSIZE : num; 5402926Swnj htdwrite(start, blk, htaddr, mp); 5412926Swnj start += blk; 5421917Swnj num -= blk; 5431917Swnj } 5443157Swnj hteof(htaddr); 5453157Swnj hteof(htaddr); 5462926Swnj htwait(htaddr); 5473181Swnj if (htaddr->htds&HTDS_ERR) 5483157Swnj return (EIO); 5492926Swnj htaddr->htcs1 = HT_REW|HT_GO; 5503103Swnj return (0); 5511917Swnj } 5521917Swnj 5532926Swnj htdwrite(dbuf, num, htaddr, mp) 5542926Swnj register dbuf, num; 5552926Swnj register struct htdevice *htaddr; 5562926Swnj struct mba_regs *mp; 5571917Swnj { 5582926Swnj register struct pte *io; 5591917Swnj register int i; 5601917Swnj 5612926Swnj htwait(htaddr); 5622926Swnj io = mp->mba_map; 5631917Swnj for (i = 0; i < num; i++) 5642926Swnj *(int *)io++ = dbuf++ | PG_V; 5652926Swnj htaddr->htfc = -(num*NBPG); 5662926Swnj mp->mba_sr = -1; 5672926Swnj mp->mba_bcr = -(num*NBPG); 5682926Swnj mp->mba_var = 0; 5692926Swnj htaddr->htcs1 = HT_WCOM|HT_GO; 5701917Swnj } 5711917Swnj 5722926Swnj htwait(htaddr) 5732926Swnj struct htdevice *htaddr; 5741917Swnj { 5751917Swnj register s; 5761917Swnj 5771917Swnj do 5782926Swnj s = htaddr->htds; 5792926Swnj while ((s & HTDS_DRY) == 0); 5801917Swnj } 5811917Swnj 5822926Swnj hteof(htaddr) 5832926Swnj struct htdevice *htaddr; 5841917Swnj { 5851917Swnj 5862926Swnj htwait(htaddr); 5872926Swnj htaddr->htcs1 = HT_WEOF|HT_GO; 5881917Swnj } 5891563Sbill #endif 590