1*3103Swnj /* ht.c 4.10 81/03/09 */ 22961Swnj 32980Swnj #include "tu.h" 41563Sbill #if NHT > 0 522Sbill /* 62926Swnj * TM03/TU?? tape driver 73094Swnj * 83094Swnj * TODO: 93094Swnj * test tape writing 103094Swnj * test error handling 113094Swnj * test 2 tapes 123094Swnj * test tape with disk on same mba 133094Swnj * test dump code 143094Swnj * try a mounted filesys on tape to check positioning code 153094Swnj * test ioctl's 163094Swnj * see how many rewind interrups we get if we kick when not at BOT 1722Sbill */ 1822Sbill #include "../h/param.h" 1922Sbill #include "../h/systm.h" 2022Sbill #include "../h/buf.h" 2122Sbill #include "../h/conf.h" 2222Sbill #include "../h/dir.h" 2322Sbill #include "../h/file.h" 2422Sbill #include "../h/user.h" 2522Sbill #include "../h/map.h" 26420Sbill #include "../h/pte.h" 272980Swnj #include "../h/mbareg.h" 282980Swnj #include "../h/mbavar.h" 292926Swnj #include "../h/mtio.h" 302926Swnj #include "../h/ioctl.h" 311917Swnj #include "../h/cmap.h" 322961Swnj #include "../h/cpu.h" 3322Sbill 342926Swnj #include "../h/htreg.h" 3522Sbill 362926Swnj struct buf rhtbuf[NHT]; 372926Swnj struct buf chtbuf[NHT]; 3822Sbill 392926Swnj short httypes[] = 402926Swnj { MBDT_TE16, MBDT_TU45, MBDT_TU77, 0 }; 412980Swnj struct mba_device *htinfo[NHT]; 42*3103Swnj int htattach(), htslave(), htustart(), htndtint(), htdtint(); 432926Swnj struct mba_driver htdriver = 442980Swnj { htattach, htslave, htustart, 0, htdtint, htndtint, 452980Swnj httypes, "ht", "tu", htinfo }; 4622Sbill 472926Swnj #define MASKREG(r) ((r) & 0xffff) 4822Sbill 492926Swnj /* bits in minor device */ 502980Swnj #define TUUNIT(dev) (minor(dev)&03) 512926Swnj #define H_NOREWIND 04 522926Swnj #define H_1600BPI 08 5322Sbill 543094Swnj #define HTUNIT(dev) (tutoht[TUUNIT(dev)]) 552980Swnj 562926Swnj #define INF (daddr_t)1000000L /* a block number that wont exist */ 572926Swnj 583094Swnj struct tu_softc { 592926Swnj char sc_openf; 602926Swnj char sc_flags; 612926Swnj daddr_t sc_blkno; 622926Swnj daddr_t sc_nxrec; 632926Swnj u_short sc_erreg; 642926Swnj u_short sc_dsreg; 652926Swnj short sc_resid; 662926Swnj short sc_dens; 672980Swnj struct mba_device *sc_mi; 682980Swnj int sc_slave; 693094Swnj } tu_softc[NTU]; 703094Swnj short tutoht[NTU]; 712926Swnj 722926Swnj /* 732926Swnj * Bits for sc_flags. 742926Swnj */ 752926Swnj #define H_WRITTEN 1 /* last operation was a write */ 762926Swnj #define H_ERASED 2 /* last write retry was an erase gap */ 772926Swnj #define H_REWIND 4 /* last unit start was a rewind */ 7822Sbill 792926Swnj /*ARGSUSED*/ 802980Swnj htattach(mi) 812980Swnj struct mba_device *mi; 822926Swnj { 832926Swnj 842926Swnj } 852926Swnj 862980Swnj htslave(mi, ms) 872980Swnj struct mba_device *mi; 882980Swnj struct mba_slave *ms; 892980Swnj { 903094Swnj register struct tu_softc *sc = &tu_softc[ms->ms_unit]; 912980Swnj 922980Swnj sc->sc_mi = mi; 932980Swnj sc->sc_slave = ms->ms_slave; 943094Swnj tutoht[ms->ms_unit] = mi->mi_unit; 952980Swnj } 962980Swnj 9722Sbill htopen(dev, flag) 982926Swnj dev_t dev; 992926Swnj int flag; 10022Sbill { 1013094Swnj register int tuunit; 1022980Swnj register struct mba_device *mi; 1033094Swnj register struct tu_softc *sc; 1043094Swnj int dens; 10522Sbill 1063094Swnj tuunit = TUUNIT(dev); 1073094Swnj if (tuunit >= NTU || (sc = &tu_softc[tuunit])->sc_openf || 1082980Swnj (mi = htinfo[HTUNIT(dev)]) == 0 || mi->mi_alive == 0) { 10922Sbill u.u_error = ENXIO; 11022Sbill return; 11122Sbill } 1122926Swnj htcommand(dev, HT_SENSE, 1); 1133094Swnj dens = 1143094Swnj ((minor(dev)&H_1600BPI)?HTTC_1600BPI:HTTC_800BPI)| 1153094Swnj HTTC_PDP11|sc->sc_slave; 1162926Swnj if ((sc->sc_dsreg & HTDS_MOL) == 0 || 1173094Swnj (sc->sc_dsreg & HTDS_BOT) == 0 && (flag&FWRITE) && 1183094Swnj dens != sc->sc_dens || 1192926Swnj (flag & (FREAD|FWRITE)) == FWRITE && sc->sc_dsreg&HTDS_WRL) { 1202926Swnj u.u_error = EIO; 1212926Swnj return; 1222926Swnj } 1232926Swnj sc->sc_openf = 1; 1242926Swnj sc->sc_blkno = (daddr_t)0; 1252926Swnj sc->sc_nxrec = INF; 1262926Swnj sc->sc_flags = 0; 1273094Swnj sc->sc_dens = dens; 12822Sbill } 12922Sbill 13022Sbill htclose(dev, flag) 1312926Swnj register dev_t dev; 1322926Swnj register flag; 13322Sbill { 1343094Swnj register struct tu_softc *sc = &tu_softc[TUUNIT(dev)]; 13522Sbill 1362926Swnj if (flag == FWRITE || ((flag&FWRITE) && (sc->sc_flags&H_WRITTEN))) { 1372926Swnj htcommand(dev, HT_WEOF, 1); 1382926Swnj htcommand(dev, HT_WEOF, 1); 1392926Swnj htcommand(dev, HT_SREV, 1); 14022Sbill } 1412926Swnj if ((minor(dev)&H_NOREWIND) == 0) 1422926Swnj htcommand(dev, HT_REW, 0); 1432926Swnj sc->sc_openf = 0; 14422Sbill } 14522Sbill 1462926Swnj htcommand(dev, com, count) 1472926Swnj dev_t dev; 1482926Swnj int com, count; 14922Sbill { 15022Sbill register struct buf *bp; 15122Sbill 1522926Swnj bp = &chtbuf[HTUNIT(dev)]; 153128Sbill (void) spl5(); 1542926Swnj while (bp->b_flags&B_BUSY) { 1552980Swnj if (bp->b_command == H_REWIND && bp->b_repcnt == 0 && 1562980Swnj (bp->b_flags&B_DONE)) 1572980Swnj break; 15822Sbill bp->b_flags |= B_WANTED; 15922Sbill sleep((caddr_t)bp, PRIBIO); 16022Sbill } 1612943Swnj bp->b_flags = B_BUSY|B_READ; 162128Sbill (void) spl0(); 16322Sbill bp->b_dev = dev; 1642926Swnj bp->b_command = com; 1652926Swnj bp->b_repcnt = count; 16622Sbill bp->b_blkno = 0; 16722Sbill htstrategy(bp); 1682926Swnj if (count == 0) 1692926Swnj return; 17022Sbill iowait(bp); 1712926Swnj if (bp->b_flags&B_WANTED) 17222Sbill wakeup((caddr_t)bp); 1732926Swnj bp->b_flags &= B_ERROR; 17422Sbill } 17522Sbill 17622Sbill htstrategy(bp) 1772926Swnj register struct buf *bp; 17822Sbill { 1793094Swnj register struct mba_device *mi = htinfo[HTUNIT(bp->b_dev)]; 1802926Swnj register struct buf *dp; 18122Sbill 18222Sbill bp->av_forw = NULL; 1832926Swnj dp = &mi->mi_tab; 184128Sbill (void) spl5(); 1852926Swnj if (dp->b_actf == NULL) 1862926Swnj dp->b_actf = bp; 18722Sbill else 1882926Swnj dp->b_actl->av_forw = bp; 1892926Swnj dp->b_actl = bp; 1902926Swnj if (dp->b_active == 0) 1912926Swnj mbustart(mi); 192128Sbill (void) spl0(); 19322Sbill } 19422Sbill 1952926Swnj htustart(mi) 1962980Swnj register struct mba_device *mi; 19722Sbill { 1982926Swnj register struct htdevice *htaddr = 1992926Swnj (struct htdevice *)mi->mi_drv; 2002926Swnj register struct buf *bp = mi->mi_tab.b_actf; 2013094Swnj register struct tu_softc *sc = &tu_softc[TUUNIT(bp->b_dev)]; 20222Sbill daddr_t blkno; 20322Sbill 2042926Swnj htaddr->httc = sc->sc_dens; 2052926Swnj sc->sc_dsreg = htaddr->htds; 2062926Swnj sc->sc_erreg = htaddr->hter; 2072926Swnj sc->sc_resid = htaddr->htfc; 2082926Swnj sc->sc_flags &= ~(H_WRITTEN|H_REWIND); 2092926Swnj if ((htaddr->htdt & HTDT_SPR) == 0 || (htaddr->htds & HTDS_MOL) == 0) 2102926Swnj if (sc->sc_openf > 0) 2112926Swnj sc->sc_openf = -1; 2122926Swnj if (sc->sc_openf < 0) { 2132926Swnj bp->b_flags |= B_ERROR; 2142926Swnj return (MBU_NEXT); 2152926Swnj } 2163094Swnj if (bp != &chtbuf[HTUNIT(bp->b_dev)]) { 2172926Swnj if (dbtofsb(bp->b_blkno) > sc->sc_nxrec) { 2182926Swnj bp->b_flags |= B_ERROR; 2192926Swnj bp->b_error = ENXIO; 2202961Swnj return (MBU_NEXT); 2213094Swnj } 2223094Swnj if (dbtofsb(bp->b_blkno) == sc->sc_nxrec && 2232926Swnj bp->b_flags&B_READ) { 2242926Swnj bp->b_resid = bp->b_bcount; 2252926Swnj clrbuf(bp); 2262961Swnj return (MBU_NEXT); 2273094Swnj } 2283094Swnj if ((bp->b_flags&B_READ)==0) 2292926Swnj sc->sc_nxrec = dbtofsb(bp->b_blkno) + 1; 2302926Swnj } else { 2312961Swnj if (bp->b_command == HT_SENSE) 2322926Swnj return (MBU_NEXT); 2332926Swnj if (bp->b_command == HT_REW) 2342926Swnj sc->sc_flags |= H_REWIND; 2352926Swnj else 2362926Swnj htaddr->htfc = -bp->b_bcount; 2372926Swnj htaddr->htcs1 = bp->b_command|HT_GO; 2382926Swnj return (MBU_STARTED); 2392926Swnj } 2402926Swnj if ((blkno = sc->sc_blkno) == dbtofsb(bp->b_blkno)) { 2412926Swnj htaddr->htfc = -bp->b_bcount; 2422926Swnj if ((bp->b_flags&B_READ) == 0) { 2433094Swnj if (mi->mi_tab.b_errcnt) { 2443094Swnj if ((sc->sc_flags & H_ERASED) == 0) { 2452926Swnj sc->sc_flags |= H_ERASED; 2462926Swnj htaddr->htcs1 = HT_ERASE | HT_GO; 2472926Swnj return (MBU_STARTED); 2482926Swnj } 2493094Swnj sc->sc_flags &= ~H_ERASED; 2503094Swnj } 2512926Swnj if (htaddr->htds & HTDS_EOT) { 2522926Swnj bp->b_resid = bp->b_bcount; 2532926Swnj return (MBU_NEXT); 2542926Swnj } 25522Sbill } 2562926Swnj return (MBU_DODATA); 25722Sbill } 2582926Swnj if (blkno < dbtofsb(bp->b_blkno)) { 2592926Swnj htaddr->htfc = blkno - dbtofsb(bp->b_blkno); 2602926Swnj htaddr->htcs1 = HT_SFORW|HT_GO; 26122Sbill } else { 2622926Swnj htaddr->htfc = dbtofsb(bp->b_blkno) - blkno; 2632926Swnj htaddr->htcs1 = HT_SREV|HT_GO; 26422Sbill } 2652926Swnj return (MBU_STARTED); 26622Sbill } 26722Sbill 2683094Swnj htdtint(mi, mbsr) 2692980Swnj register struct mba_device *mi; 2703094Swnj int mbsr; 27122Sbill { 2722926Swnj register struct htdevice *htaddr = (struct htdevice *)mi->mi_drv; 2732926Swnj register struct buf *bp = mi->mi_tab.b_actf; 2743094Swnj register struct tu_softc *sc; 2752961Swnj int ds, er, mbs; 27622Sbill 2773094Swnj sc = &tu_softc[TUUNIT(bp->b_dev)]; 2782926Swnj ds = sc->sc_dsreg = MASKREG(htaddr->htds); 2792926Swnj er = sc->sc_erreg = MASKREG(htaddr->hter); 2802926Swnj sc->sc_resid = MASKREG(htaddr->htfc); 2813094Swnj mbs = mbsr; 2822926Swnj sc->sc_blkno++; 2832926Swnj if((bp->b_flags & B_READ) == 0) 2842926Swnj sc->sc_flags |= H_WRITTEN; 2853094Swnj if ((ds&(HTDS_ERR|HTDS_MOL)) != HTDS_MOL || mbs & MBSR_EBITS) { 2862926Swnj htaddr->htcs1 = HT_DCLR|HT_GO; 2872961Swnj mbclrattn(mi); 2882961Swnj if (bp == &rhtbuf[HTUNIT(bp->b_dev)]) { 2892926Swnj er &= ~HTER_FCE; 2903094Swnj mbs &= ~(MBSR_DTABT|MBSR_MBEXC); 2912961Swnj } 2922926Swnj if (bp->b_flags & B_READ && ds & HTDS_PES) 2932926Swnj er &= ~(HTER_CSITM|HTER_CORCRC); 2943094Swnj if (er&HTER_HARD || mbs&MBSR_EBITS || (ds&HTDS_MOL) == 0 || 2952961Swnj er && ++mi->mi_tab.b_errcnt >= 7) { 2962926Swnj if ((ds & HTDS_MOL) == 0 && sc->sc_openf > 0) 2972926Swnj sc->sc_openf = -1; 2983094Swnj printf("tu%d: hard error bn%d mbsr=%b er=%b\n", 2992980Swnj TUUNIT(bp->b_dev), bp->b_blkno, 3003094Swnj mbsr, mbsr_bits, 3012926Swnj MASKREG(htaddr->hter), HTER_BITS); 30222Sbill bp->b_flags |= B_ERROR; 3032926Swnj return (MBD_DONE); 30422Sbill } 3052926Swnj if (er) 3062926Swnj return (MBD_RETRY); 30722Sbill } 3082926Swnj bp->b_resid = 0; 3092926Swnj if (bp->b_flags & B_READ) 3102926Swnj if (ds&HTDS_TM) { /* must be a read, right? */ 3112926Swnj bp->b_resid = bp->b_bcount; 3122926Swnj sc->sc_nxrec = dbtofsb(bp->b_blkno); 3132926Swnj } else if(bp->b_bcount > MASKREG(htaddr->htfc)) 3142926Swnj bp->b_resid = bp->b_bcount - MASKREG(htaddr->htfc); 3152926Swnj return (MBD_DONE); 3162926Swnj } 31722Sbill 3182926Swnj htndtint(mi) 3192980Swnj register struct mba_device *mi; 3202926Swnj { 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; 3242926Swnj int er, ds, fc; 32522Sbill 3263094Swnj ds = MASKREG(htaddr->htds); 3273094Swnj er = MASKREG(htaddr->hter); 3283094Swnj fc = MASKREG(htaddr->htfc); 3293094Swnj if (er) { 3302926Swnj htaddr->htcs1 = HT_DCLR|HT_GO; 3312961Swnj mbclrattn(mi); 3322961Swnj } 3333094Swnj if (bp == 0) 3343094Swnj return (MBN_SKIP); 3353094Swnj sc = &tu_softc[TUUNIT(bp->b_dev)]; 3363094Swnj sc->sc_dsreg = ds; 3373094Swnj sc->sc_erreg = er; 3383094Swnj sc->sc_resid = fc; 3393094Swnj if (bp == &chtbuf[HTUNIT(bp->b_dev)]) { 3403094Swnj switch (bp->b_command) { 3413094Swnj case HT_REWOFFL: 3422926Swnj /* offline is on purpose; don't do anything special */ 3432926Swnj ds |= HTDS_MOL; 3443094Swnj break; 3453094Swnj case HT_SREV: 3463094Swnj /* if backspace file hit bot, its not an error */ 3473094Swnj if (er == (HTER_NEF|HTER_FCE) && ds&HTDS_BOT && 3483094Swnj bp->b_repcnt == INF) 3493094Swnj er &= ~HTER_NEF; 3503094Swnj break; 3513094Swnj } 3522926Swnj er &= ~HTER_FCE; 3532926Swnj if (er == 0) 3542926Swnj ds &= ~HTDS_ERR; 35522Sbill } 3562926Swnj if ((ds & (HTDS_ERR|HTDS_MOL)) != HTDS_MOL) { 3572926Swnj if ((ds & HTDS_MOL) == 0 && sc->sc_openf > 0) 3582926Swnj sc->sc_openf = -1; 3592980Swnj printf("tu%d: hard error bn%d er=%b ds=%b\n", 3602980Swnj TUUNIT(bp->b_dev), bp->b_blkno, 3612926Swnj sc->sc_erreg, HTER_BITS, sc->sc_dsreg, HTDS_BITS); 3622926Swnj bp->b_flags |= B_ERROR; 3632926Swnj return (MBN_DONE); 3642926Swnj } 3653094Swnj if (bp == &chtbuf[HTUNIT(bp->b_dev)]) { 3662926Swnj if (sc->sc_flags & H_REWIND) 3672926Swnj return (ds & HTDS_BOT ? MBN_DONE : MBN_RETRY); 3682926Swnj bp->b_resid = -sc->sc_resid; 3692926Swnj return (MBN_DONE); 3702926Swnj } 3712926Swnj if (ds & HTDS_TM) 3723094Swnj if (sc->sc_blkno > dbtofsb(bp->b_blkno)) { 3732926Swnj sc->sc_nxrec = dbtofsb(bp->b_blkno) - fc; 3742926Swnj sc->sc_blkno = sc->sc_nxrec; 3753094Swnj } else { 3762926Swnj sc->sc_blkno = dbtofsb(bp->b_blkno) + fc; 3772926Swnj sc->sc_nxrec = sc->sc_blkno - 1; 3782926Swnj } 3792926Swnj else 3802926Swnj sc->sc_blkno = dbtofsb(bp->b_blkno); 3812926Swnj return (MBN_RETRY); 38222Sbill } 38322Sbill 38422Sbill htread(dev) 3852926Swnj dev_t dev; 38622Sbill { 3872926Swnj 38822Sbill htphys(dev); 3892926Swnj if (u.u_error) 3902926Swnj return; 3912926Swnj physio(htstrategy, &rhtbuf[HTUNIT(dev)], dev, B_READ, minphys); 39222Sbill } 39322Sbill 39422Sbill htwrite(dev) 39522Sbill { 3962926Swnj 39722Sbill htphys(dev); 3982926Swnj if (u.u_error) 3992926Swnj return; 4002926Swnj physio(htstrategy, &rhtbuf[HTUNIT(dev)], dev, B_WRITE, minphys); 40122Sbill } 40222Sbill 40322Sbill htphys(dev) 4042926Swnj dev_t dev; 40522Sbill { 4063094Swnj register int htunit; 4073094Swnj register struct tu_softc *sc; 4083094Swnj register struct mba_device *mi; 40922Sbill daddr_t a; 41022Sbill 4113094Swnj htunit = HTUNIT(dev); 4123094Swnj if (htunit >= NHT || (mi = htinfo[htunit]) == 0 || mi->mi_alive == 0) { 4132926Swnj u.u_error = ENXIO; 4142926Swnj return; 41522Sbill } 4162926Swnj a = u.u_offset >> 9; 4173094Swnj sc = &tu_softc[TUUNIT(dev)]; 4182926Swnj sc->sc_blkno = dbtofsb(a); 4192926Swnj sc->sc_nxrec = dbtofsb(a)+1; 42022Sbill } 4211917Swnj 4222926Swnj /*ARGSUSED*/ 4232926Swnj htioctl(dev, cmd, addr, flag) 4242926Swnj dev_t dev; 4252926Swnj int cmd; 4262926Swnj caddr_t addr; 4272926Swnj int flag; 4282926Swnj { 4293094Swnj register struct tu_softc *sc = &tu_softc[TUUNIT(dev)]; 4303094Swnj register struct buf *bp = &chtbuf[HTUNIT(dev)]; 4312926Swnj register callcount; 4322926Swnj int fcount; 4332926Swnj struct mtop mtop; 4342926Swnj struct mtget mtget; 4352926Swnj /* we depend of the values and order of the MT codes here */ 4362926Swnj static htops[] = 4372926Swnj {HT_WEOF,HT_SFORW,HT_SREV,HT_SFORW,HT_SREV,HT_REW,HT_REWOFFL,HT_SENSE}; 4381917Swnj 4392926Swnj switch (cmd) { 4402926Swnj case MTIOCTOP: /* tape operation */ 4412926Swnj if (copyin((caddr_t)addr, (caddr_t)&mtop, sizeof(mtop))) { 4422926Swnj u.u_error = EFAULT; 4432926Swnj return; 4442926Swnj } 4452926Swnj switch(mtop.mt_op) { 4462926Swnj case MTWEOF: 4472926Swnj callcount = mtop.mt_count; 4482926Swnj fcount = 1; 4492926Swnj break; 4502926Swnj case MTFSF: case MTBSF: 4512926Swnj callcount = mtop.mt_count; 4522926Swnj fcount = INF; 4532926Swnj break; 4542926Swnj case MTFSR: case MTBSR: 4552926Swnj callcount = 1; 4562926Swnj fcount = mtop.mt_count; 4572926Swnj break; 4582926Swnj case MTREW: case MTOFFL: 4592926Swnj callcount = 1; 4602926Swnj fcount = 1; 4612926Swnj break; 4622926Swnj default: 4632926Swnj u.u_error = ENXIO; 4642926Swnj return; 4652926Swnj } 4662926Swnj if (callcount <= 0 || fcount <= 0) { 4672926Swnj u.u_error = ENXIO; 4682926Swnj return; 4692926Swnj } 4702926Swnj while (--callcount >= 0) { 4712926Swnj htcommand(dev, htops[mtop.mt_op], fcount); 4722926Swnj if ((mtop.mt_op == MTFSR || mtop.mt_op == MTBSR) && 4732926Swnj bp->b_resid) { 4742926Swnj u.u_error = EIO; 4752926Swnj break; 4762926Swnj } 4773094Swnj if ((bp->b_flags&B_ERROR) || sc->sc_dsreg&HTDS_BOT) 4782926Swnj break; 4792926Swnj } 4802926Swnj geterror(bp); 4812926Swnj return; 4822926Swnj case MTIOCGET: 4832926Swnj mtget.mt_dsreg = sc->sc_dsreg; 4842926Swnj mtget.mt_erreg = sc->sc_erreg; 4852926Swnj mtget.mt_resid = sc->sc_resid; 4862926Swnj if (copyout((caddr_t)&mtget, addr, sizeof(mtget))) 4872926Swnj u.u_error = EFAULT; 4882926Swnj return; 4892926Swnj default: 4902926Swnj u.u_error = ENXIO; 4912926Swnj } 4922926Swnj } 4932926Swnj 4941917Swnj #define DBSIZE 20 4951917Swnj 4962926Swnj htdump() 4971917Swnj { 4982980Swnj register struct mba_device *mi; 4992926Swnj register struct mba_regs *mp; 5002926Swnj register struct htdevice *htaddr; 5012926Swnj int blk, num; 5022926Swnj int start; 5031917Swnj 5042926Swnj start = 0; 5052926Swnj num = maxfree; 5062926Swnj #define phys(a,b) ((b)((int)(a)&0x7fffffff)) 5072926Swnj if (htinfo[0] == 0) 5082926Swnj return (ENXIO); 5092980Swnj mi = phys(htinfo[0], struct mba_device *); 5102926Swnj mp = phys(mi->mi_hd, struct mba_hd *)->mh_physmba; 5113094Swnj mbainit(mp); 5122926Swnj htaddr = (struct htdevice *)&mp->mba_drv[mi->mi_drive]; 5132926Swnj htaddr->httc = HTTC_PDP11|HTTC_1600BPI; 5142926Swnj htaddr->htcs1 = HT_DCLR|HT_GO; 5151917Swnj while (num > 0) { 5161917Swnj blk = num > DBSIZE ? DBSIZE : num; 5172926Swnj htdwrite(start, blk, htaddr, mp); 5182926Swnj start += blk; 5191917Swnj num -= blk; 5201917Swnj } 5212926Swnj htwait(htaddr); 5222926Swnj htaddr->htcs1 = HT_REW|HT_GO; 5232926Swnj hteof(htaddr); 5242926Swnj hteof(htaddr); 525*3103Swnj return (0); 5261917Swnj } 5271917Swnj 5282926Swnj htdwrite(dbuf, num, htaddr, mp) 5292926Swnj register dbuf, num; 5302926Swnj register struct htdevice *htaddr; 5312926Swnj struct mba_regs *mp; 5321917Swnj { 5332926Swnj register struct pte *io; 5341917Swnj register int i; 5351917Swnj 5362926Swnj htwait(htaddr); 5372926Swnj io = mp->mba_map; 5381917Swnj for (i = 0; i < num; i++) 5392926Swnj *(int *)io++ = dbuf++ | PG_V; 5402926Swnj htaddr->htfc = -(num*NBPG); 5412926Swnj mp->mba_sr = -1; 5422926Swnj mp->mba_bcr = -(num*NBPG); 5432926Swnj mp->mba_var = 0; 5442926Swnj htaddr->htcs1 = HT_WCOM|HT_GO; 5451917Swnj } 5461917Swnj 5472926Swnj htwait(htaddr) 5482926Swnj struct htdevice *htaddr; 5491917Swnj { 5501917Swnj register s; 5511917Swnj 5521917Swnj do 5532926Swnj s = htaddr->htds; 5542926Swnj while ((s & HTDS_DRY) == 0); 5551917Swnj } 5561917Swnj 5572926Swnj hteof(htaddr) 5582926Swnj struct htdevice *htaddr; 5591917Swnj { 5601917Swnj 5612926Swnj htwait(htaddr); 5622926Swnj htaddr->htcs1 = HT_WEOF|HT_GO; 5631917Swnj } 5641563Sbill #endif 565