1*2980Swnj /* ht.c 4.8 81/03/07 */ 22961Swnj 3*2980Swnj #include "tu.h" 41563Sbill #if NHT > 0 522Sbill /* 62926Swnj * TM03/TU?? tape driver 722Sbill */ 822Sbill #include "../h/param.h" 922Sbill #include "../h/systm.h" 1022Sbill #include "../h/buf.h" 1122Sbill #include "../h/conf.h" 1222Sbill #include "../h/dir.h" 1322Sbill #include "../h/file.h" 1422Sbill #include "../h/user.h" 1522Sbill #include "../h/map.h" 16420Sbill #include "../h/pte.h" 17*2980Swnj #include "../h/mbareg.h" 18*2980Swnj #include "../h/mbavar.h" 192926Swnj #include "../h/mtio.h" 202926Swnj #include "../h/ioctl.h" 211917Swnj #include "../h/cmap.h" 222961Swnj #include "../h/cpu.h" 2322Sbill 242926Swnj #include "../h/htreg.h" 2522Sbill 262926Swnj struct buf rhtbuf[NHT]; 272926Swnj struct buf chtbuf[NHT]; 2822Sbill 292926Swnj short httypes[] = 302926Swnj { MBDT_TE16, MBDT_TU45, MBDT_TU77, 0 }; 31*2980Swnj struct mba_device *htinfo[NHT]; 32*2980Swnj int htdkinit(), htattach(), htslave(), htustart(), htndtint(), htdtint(); 332926Swnj struct mba_driver htdriver = 34*2980Swnj { htattach, htslave, htustart, 0, htdtint, htndtint, 35*2980Swnj httypes, "ht", "tu", htinfo }; 3622Sbill 372926Swnj #define MASKREG(r) ((r) & 0xffff) 3822Sbill 392926Swnj /* bits in minor device */ 40*2980Swnj #define TUUNIT(dev) (minor(dev)&03) 412926Swnj #define H_NOREWIND 04 422926Swnj #define H_1600BPI 08 4322Sbill 44*2980Swnj #define HTUNIT(dev) (htunit[TUUNIT(dev)]) 45*2980Swnj 462926Swnj #define INF (daddr_t)1000000L /* a block number that wont exist */ 472926Swnj 482926Swnj struct ht_softc { 492926Swnj char sc_openf; 502926Swnj char sc_flags; 512926Swnj daddr_t sc_blkno; 522926Swnj daddr_t sc_nxrec; 532926Swnj u_short sc_erreg; 542926Swnj u_short sc_dsreg; 552926Swnj short sc_resid; 562926Swnj short sc_dens; 57*2980Swnj struct mba_device *sc_mi; 58*2980Swnj int sc_slave; 59*2980Swnj } ht_softc[NTU]; 60*2980Swnj short htunit[NTU]; 612926Swnj 622926Swnj /* 632926Swnj * Bits for sc_flags. 642926Swnj */ 652926Swnj #define H_WRITTEN 1 /* last operation was a write */ 662926Swnj #define H_ERASED 2 /* last write retry was an erase gap */ 672926Swnj #define H_REWIND 4 /* last unit start was a rewind */ 6822Sbill 692926Swnj /*ARGSUSED*/ 70*2980Swnj htattach(mi) 71*2980Swnj struct mba_device *mi; 722926Swnj { 732926Swnj 742926Swnj } 752926Swnj 76*2980Swnj htslave(mi, ms) 77*2980Swnj struct mba_device *mi; 78*2980Swnj struct mba_slave *ms; 79*2980Swnj { 80*2980Swnj register struct ht_softc *sc = &ht_softc[ms->ms_unit]; 81*2980Swnj 82*2980Swnj sc->sc_mi = mi; 83*2980Swnj sc->sc_slave = ms->ms_slave; 84*2980Swnj htunit[ms->ms_unit] = mi->mi_unit; 85*2980Swnj } 86*2980Swnj 8722Sbill htopen(dev, flag) 882926Swnj dev_t dev; 892926Swnj int flag; 9022Sbill { 912926Swnj register int unit; 92*2980Swnj register struct mba_device *mi; 932926Swnj register struct ht_softc *sc; 9422Sbill 95*2980Swnj unit = TUUNIT(dev); 96*2980Swnj if (unit >= NTU || (sc = &ht_softc[unit])->sc_openf || 97*2980Swnj (mi = htinfo[HTUNIT(dev)]) == 0 || mi->mi_alive == 0) { 9822Sbill u.u_error = ENXIO; 9922Sbill return; 10022Sbill } 1012926Swnj /* 1022926Swnj * The NOP below serves two purposes: 1032926Swnj * 1. To get a recent copy of the status registers. 1042926Swnj * 2. To ensure that any outstanding rewinds are truly finished 1052926Swnj */ 1062926Swnj htcommand(dev, HT_SENSE, 1); 1072926Swnj if ((sc->sc_dsreg & HTDS_MOL) == 0 || 1082926Swnj (flag & (FREAD|FWRITE)) == FWRITE && sc->sc_dsreg&HTDS_WRL) { 1092926Swnj u.u_error = EIO; 1102926Swnj return; 1112926Swnj } 1122926Swnj sc->sc_dens = 1132961Swnj ((minor(dev)&H_1600BPI)?HTTC_1600BPI:HTTC_800BPI)| 114*2980Swnj HTTC_PDP11|sc->sc_slave; 1152926Swnj sc->sc_openf = 1; 1162926Swnj sc->sc_blkno = (daddr_t)0; 1172926Swnj sc->sc_nxrec = INF; 1182926Swnj sc->sc_flags = 0; 11922Sbill } 12022Sbill 12122Sbill htclose(dev, flag) 1222926Swnj register dev_t dev; 1232926Swnj register flag; 12422Sbill { 125*2980Swnj register struct ht_softc *sc = &ht_softc[TUUNIT(dev)]; 12622Sbill 1272926Swnj if (flag == FWRITE || ((flag&FWRITE) && (sc->sc_flags&H_WRITTEN))) { 1282926Swnj htcommand(dev, HT_WEOF, 1); 1292926Swnj htcommand(dev, HT_WEOF, 1); 1302926Swnj htcommand(dev, HT_SREV, 1); 13122Sbill } 1322926Swnj if ((minor(dev)&H_NOREWIND) == 0) 1332926Swnj /* 0 as third arg means don't wait */ 1342926Swnj htcommand(dev, HT_REW, 0); 1352926Swnj sc->sc_openf = 0; 13622Sbill } 13722Sbill 1382926Swnj /* 1392926Swnj * Do a non-data-transfer command. 1402926Swnj * 1412926Swnj * N.B.: Count should be zero ONLY for rewind during close. 1422926Swnj */ 1432926Swnj htcommand(dev, com, count) 1442926Swnj dev_t dev; 1452926Swnj int com, count; 14622Sbill { 14722Sbill register struct buf *bp; 14822Sbill 1492926Swnj bp = &chtbuf[HTUNIT(dev)]; 150128Sbill (void) spl5(); 1512926Swnj while (bp->b_flags&B_BUSY) { 152*2980Swnj if (bp->b_command == H_REWIND && bp->b_repcnt == 0 && 153*2980Swnj (bp->b_flags&B_DONE)) 154*2980Swnj break; 15522Sbill bp->b_flags |= B_WANTED; 15622Sbill sleep((caddr_t)bp, PRIBIO); 15722Sbill } 1582943Swnj bp->b_flags = B_BUSY|B_READ; 159128Sbill (void) spl0(); 16022Sbill bp->b_dev = dev; 1612926Swnj bp->b_command = com; 1622926Swnj bp->b_repcnt = count; 16322Sbill bp->b_blkno = 0; 16422Sbill htstrategy(bp); 1652926Swnj if (count == 0) 1662926Swnj return; 16722Sbill iowait(bp); 1682926Swnj if (bp->b_flags&B_WANTED) 16922Sbill wakeup((caddr_t)bp); 1702926Swnj bp->b_flags &= B_ERROR; 17122Sbill } 17222Sbill 17322Sbill htstrategy(bp) 1742926Swnj register struct buf *bp; 17522Sbill { 1762926Swnj register int unit = HTUNIT(bp->b_dev); 177*2980Swnj register struct mba_device *mi = htinfo[unit]; 1782926Swnj register struct buf *dp; 17922Sbill 18022Sbill bp->av_forw = NULL; 1812926Swnj dp = &mi->mi_tab; 182128Sbill (void) spl5(); 1832926Swnj if (dp->b_actf == NULL) 1842926Swnj dp->b_actf = bp; 18522Sbill else 1862926Swnj dp->b_actl->av_forw = bp; 1872926Swnj dp->b_actl = bp; 1882926Swnj if (dp->b_active == 0) 1892926Swnj mbustart(mi); 190128Sbill (void) spl0(); 19122Sbill } 19222Sbill 1932926Swnj htustart(mi) 194*2980Swnj register struct mba_device *mi; 19522Sbill { 1962926Swnj register struct htdevice *htaddr = 1972926Swnj (struct htdevice *)mi->mi_drv; 1982926Swnj register struct buf *bp = mi->mi_tab.b_actf; 199*2980Swnj int unit = TUUNIT(bp->b_dev); 2002926Swnj register struct ht_softc *sc = &ht_softc[unit]; 20122Sbill daddr_t blkno; 20222Sbill 2032926Swnj htaddr->httc = sc->sc_dens; 2042926Swnj sc->sc_dsreg = htaddr->htds; 2052926Swnj sc->sc_erreg = htaddr->hter; 2062926Swnj sc->sc_resid = htaddr->htfc; 2072926Swnj sc->sc_flags &= ~(H_WRITTEN|H_REWIND); 2082926Swnj if ((htaddr->htdt & HTDT_SPR) == 0 || (htaddr->htds & HTDS_MOL) == 0) 2092926Swnj if (sc->sc_openf > 0) 2102926Swnj sc->sc_openf = -1; 2112926Swnj if (sc->sc_openf < 0) { 2122926Swnj bp->b_flags |= B_ERROR; 2132926Swnj return (MBU_NEXT); 2142926Swnj } 2152926Swnj if (bp != &chtbuf[unit]) { 2162926Swnj if (dbtofsb(bp->b_blkno) > sc->sc_nxrec) { 2172926Swnj bp->b_flags |= B_ERROR; 2182926Swnj bp->b_error = ENXIO; 2192961Swnj return (MBU_NEXT); 2202926Swnj } else if (dbtofsb(bp->b_blkno) == sc->sc_nxrec && 2212926Swnj bp->b_flags&B_READ) { 2222926Swnj bp->b_resid = bp->b_bcount; 2232926Swnj clrbuf(bp); 2242961Swnj return (MBU_NEXT); 2252926Swnj } else if ((bp->b_flags&B_READ)==0) 2262926Swnj sc->sc_nxrec = dbtofsb(bp->b_blkno) + 1; 2272926Swnj } else { 2282961Swnj if (bp->b_command == HT_SENSE) 2292926Swnj return (MBU_NEXT); 2302926Swnj if (bp->b_command == HT_REW) 2312926Swnj sc->sc_flags |= H_REWIND; 2322926Swnj else 2332926Swnj htaddr->htfc = -bp->b_bcount; 2342926Swnj htaddr->htcs1 = bp->b_command|HT_GO; 2352926Swnj return (MBU_STARTED); 2362926Swnj } 2372926Swnj if ((blkno = sc->sc_blkno) == dbtofsb(bp->b_blkno)) { 2382926Swnj htaddr->htfc = -bp->b_bcount; 2392926Swnj if ((bp->b_flags&B_READ) == 0) { 2402926Swnj if (mi->mi_tab.b_errcnt) 2412926Swnj if (sc->sc_flags & H_ERASED) 2422926Swnj sc->sc_flags &= ~H_ERASED; 2432926Swnj else { 2442926Swnj sc->sc_flags |= H_ERASED; 2452926Swnj htaddr->htcs1 = HT_ERASE | HT_GO; 2462926Swnj return (MBU_STARTED); 2472926Swnj } 2482926Swnj if (htaddr->htds & HTDS_EOT) { 2492926Swnj bp->b_resid = bp->b_bcount; 2502926Swnj return (MBU_NEXT); 2512926Swnj } 25222Sbill } 2532926Swnj return (MBU_DODATA); 25422Sbill } 2552926Swnj if (blkno < dbtofsb(bp->b_blkno)) { 2562926Swnj htaddr->htfc = blkno - dbtofsb(bp->b_blkno); 2572926Swnj htaddr->htcs1 = HT_SFORW|HT_GO; 25822Sbill } else { 2592926Swnj htaddr->htfc = dbtofsb(bp->b_blkno) - blkno; 2602926Swnj htaddr->htcs1 = HT_SREV|HT_GO; 26122Sbill } 2622926Swnj return (MBU_STARTED); 26322Sbill } 26422Sbill 2652926Swnj /* 2662926Swnj * data transfer interrupt - must be read or write 2672926Swnj */ 26822Sbill /*ARGSUSED*/ 2692926Swnj htdtint(mi, mbasr) 270*2980Swnj register struct mba_device *mi; 2712926Swnj int mbasr; 27222Sbill { 2732926Swnj register struct htdevice *htaddr = (struct htdevice *)mi->mi_drv; 2742926Swnj register struct buf *bp = mi->mi_tab.b_actf; 2752926Swnj register struct ht_softc *sc; 2762961Swnj int ds, er, mbs; 27722Sbill 278*2980Swnj sc = &ht_softc[TUUNIT(bp->b_dev)]; 2792926Swnj ds = sc->sc_dsreg = MASKREG(htaddr->htds); 2802926Swnj er = sc->sc_erreg = MASKREG(htaddr->hter); 2812926Swnj sc->sc_resid = MASKREG(htaddr->htfc); 2822961Swnj mbs = mbasr; 2832926Swnj sc->sc_blkno++; 2842926Swnj if((bp->b_flags & B_READ) == 0) 2852926Swnj sc->sc_flags |= H_WRITTEN; 2862926Swnj if ((ds&(HTDS_ERR|HTDS_MOL)) != HTDS_MOL || 2872961Swnj mbs & MBAEBITS) { 2882926Swnj htaddr->htcs1 = HT_DCLR|HT_GO; 2892961Swnj mbclrattn(mi); 2902961Swnj if (bp == &rhtbuf[HTUNIT(bp->b_dev)]) { 2912926Swnj er &= ~HTER_FCE; 2922961Swnj mbs &= ~(MBS_DTABT|MBS_MBEXC); 2932961Swnj } 2942926Swnj if (bp->b_flags & B_READ && ds & HTDS_PES) 2952926Swnj er &= ~(HTER_CSITM|HTER_CORCRC); 2962926Swnj if (er&HTER_HARD || 2972961Swnj mbs&MBAEBITS || (ds&HTDS_MOL) == 0 || 2982961Swnj er && ++mi->mi_tab.b_errcnt >= 7) { 2992926Swnj if ((ds & HTDS_MOL) == 0 && sc->sc_openf > 0) 3002926Swnj sc->sc_openf = -1; 301*2980Swnj printf("tu%d: hard error bn%d mbasr=%b er=%b\n", 302*2980Swnj TUUNIT(bp->b_dev), bp->b_blkno, 3032926Swnj mbasr, mbasr_bits, 3042926Swnj MASKREG(htaddr->hter), HTER_BITS); 30522Sbill bp->b_flags |= B_ERROR; 3062926Swnj return (MBD_DONE); 30722Sbill } 3082926Swnj if (er) 3092926Swnj return (MBD_RETRY); 31022Sbill } 3112926Swnj bp->b_resid = 0; 3122926Swnj if (bp->b_flags & B_READ) 3132926Swnj if (ds&HTDS_TM) { /* must be a read, right? */ 3142926Swnj bp->b_resid = bp->b_bcount; 3152926Swnj sc->sc_nxrec = dbtofsb(bp->b_blkno); 3162926Swnj } else if(bp->b_bcount > MASKREG(htaddr->htfc)) 3172926Swnj bp->b_resid = bp->b_bcount - MASKREG(htaddr->htfc); 3182926Swnj return (MBD_DONE); 3192926Swnj } 32022Sbill 3212926Swnj /* 3222926Swnj * non-data-transfer interrupt 3232926Swnj */ 3242926Swnj htndtint(mi) 325*2980Swnj register struct mba_device *mi; 3262926Swnj { 3272926Swnj register struct htdevice *htaddr = (struct htdevice *)mi->mi_drv; 3282926Swnj register struct buf *bp = mi->mi_tab.b_actf; 3292926Swnj register struct ht_softc *sc; 3302926Swnj int er, ds, fc; 33122Sbill 332*2980Swnj if (bp == 0) 333*2980Swnj return (MBN_SKIP); 334*2980Swnj sc = &ht_softc[TUUNIT(bp->b_dev)]; 3352926Swnj ds = sc->sc_dsreg = MASKREG(htaddr->htds); 3362926Swnj er = sc->sc_erreg = MASKREG(htaddr->hter); 3372961Swnj fc = sc->sc_resid = MASKREG(htaddr->htfc); 3382961Swnj if (sc->sc_erreg) { 3392926Swnj htaddr->htcs1 = HT_DCLR|HT_GO; 3402961Swnj mbclrattn(mi); 3412961Swnj } 342*2980Swnj if (sc->sc_flags&H_REWIND) { 343*2980Swnj sc->sc_flags &= ~H_REWIND; 344*2980Swnj return (MBN_CONT); 345*2980Swnj } 346*2980Swnj if (bp == &chtbuf[TUUNIT(bp->b_dev)]) { 3472926Swnj if (bp->b_command == HT_REWOFFL) 3482926Swnj /* offline is on purpose; don't do anything special */ 3492926Swnj ds |= HTDS_MOL; 3502926Swnj else if (bp->b_resid == HT_SREV && 3512926Swnj er == (HTER_NEF|HTER_FCE) && 3522926Swnj ds&HTDS_BOT && bp->b_bcount == INF) 3532926Swnj er &= ~HTER_NEF; 3542926Swnj er &= ~HTER_FCE; 3552926Swnj if (er == 0) 3562926Swnj ds &= ~HTDS_ERR; 35722Sbill } 3582926Swnj if ((ds & (HTDS_ERR|HTDS_MOL)) != HTDS_MOL) { 3592926Swnj if ((ds & HTDS_MOL) == 0 && sc->sc_openf > 0) 3602926Swnj sc->sc_openf = -1; 361*2980Swnj printf("tu%d: hard error bn%d er=%b ds=%b\n", 362*2980Swnj TUUNIT(bp->b_dev), bp->b_blkno, 3632926Swnj sc->sc_erreg, HTER_BITS, sc->sc_dsreg, HTDS_BITS); 3642926Swnj bp->b_flags |= B_ERROR; 3652926Swnj return (MBN_DONE); 3662926Swnj } 367*2980Swnj if (bp == &chtbuf[TUUNIT(bp->b_dev)]) { 3682926Swnj if (sc->sc_flags & H_REWIND) 3692926Swnj return (ds & HTDS_BOT ? MBN_DONE : MBN_RETRY); 3702926Swnj bp->b_resid = -sc->sc_resid; 3712926Swnj return (MBN_DONE); 3722926Swnj } 3732926Swnj if (ds & HTDS_TM) 3742926Swnj if (sc->sc_blkno > dbtofsb(bp->b_blkno)) {/* reversing */ 3752926Swnj sc->sc_nxrec = dbtofsb(bp->b_blkno) - fc; 3762926Swnj sc->sc_blkno = sc->sc_nxrec; 3772926Swnj } else { /* spacing forward */ 3782926Swnj sc->sc_blkno = dbtofsb(bp->b_blkno) + fc; 3792926Swnj sc->sc_nxrec = sc->sc_blkno - 1; 3802926Swnj } 3812926Swnj else 3822926Swnj sc->sc_blkno = dbtofsb(bp->b_blkno); 3832926Swnj return (MBN_RETRY); 38422Sbill } 38522Sbill 38622Sbill htread(dev) 3872926Swnj dev_t dev; 38822Sbill { 3892926Swnj 39022Sbill htphys(dev); 3912926Swnj if (u.u_error) 3922926Swnj return; 3932926Swnj physio(htstrategy, &rhtbuf[HTUNIT(dev)], dev, B_READ, minphys); 39422Sbill } 39522Sbill 39622Sbill htwrite(dev) 39722Sbill { 3982926Swnj 39922Sbill htphys(dev); 4002926Swnj if (u.u_error) 4012926Swnj return; 4022926Swnj physio(htstrategy, &rhtbuf[HTUNIT(dev)], dev, B_WRITE, minphys); 40322Sbill } 40422Sbill 40522Sbill htphys(dev) 4062926Swnj dev_t dev; 40722Sbill { 4082926Swnj register int unit; 4092926Swnj register struct ht_softc *sc; 41022Sbill daddr_t a; 41122Sbill 4122926Swnj unit = HTUNIT(dev); 4132926Swnj if (unit >= NHT) { 4142926Swnj u.u_error = ENXIO; 4152926Swnj return; 41622Sbill } 4172926Swnj a = u.u_offset >> 9; 4182926Swnj sc = &ht_softc[unit]; 4192926Swnj sc->sc_blkno = dbtofsb(a); 4202926Swnj sc->sc_nxrec = dbtofsb(a)+1; 42122Sbill } 4221917Swnj 4232926Swnj /*ARGSUSED*/ 4242926Swnj htioctl(dev, cmd, addr, flag) 4252926Swnj dev_t dev; 4262926Swnj int cmd; 4272926Swnj caddr_t addr; 4282926Swnj int flag; 4292926Swnj { 4302926Swnj register unit = HTUNIT(dev); 4312926Swnj register struct ht_softc *sc = &ht_softc[unit]; 4322926Swnj register struct buf *bp = &chtbuf[unit]; 4332926Swnj register callcount; 4342926Swnj int fcount; 4352926Swnj struct mtop mtop; 4362926Swnj struct mtget mtget; 4372926Swnj /* we depend of the values and order of the MT codes here */ 4382926Swnj static htops[] = 4392926Swnj {HT_WEOF,HT_SFORW,HT_SREV,HT_SFORW,HT_SREV,HT_REW,HT_REWOFFL,HT_SENSE}; 4401917Swnj 4412926Swnj switch (cmd) { 4422926Swnj case MTIOCTOP: /* tape operation */ 4432926Swnj if (copyin((caddr_t)addr, (caddr_t)&mtop, sizeof(mtop))) { 4442926Swnj u.u_error = EFAULT; 4452926Swnj return; 4462926Swnj } 4472926Swnj switch(mtop.mt_op) { 4482926Swnj case MTWEOF: 4492926Swnj callcount = mtop.mt_count; 4502926Swnj fcount = 1; 4512926Swnj break; 4522926Swnj case MTFSF: case MTBSF: 4532926Swnj callcount = mtop.mt_count; 4542926Swnj fcount = INF; 4552926Swnj break; 4562926Swnj case MTFSR: case MTBSR: 4572926Swnj callcount = 1; 4582926Swnj fcount = mtop.mt_count; 4592926Swnj break; 4602926Swnj case MTREW: case MTOFFL: 4612926Swnj callcount = 1; 4622926Swnj fcount = 1; 4632926Swnj break; 4642926Swnj default: 4652926Swnj u.u_error = ENXIO; 4662926Swnj return; 4672926Swnj } 4682926Swnj if (callcount <= 0 || fcount <= 0) { 4692926Swnj u.u_error = ENXIO; 4702926Swnj return; 4712926Swnj } 4722926Swnj while (--callcount >= 0) { 4732926Swnj htcommand(dev, htops[mtop.mt_op], fcount); 4742926Swnj if ((mtop.mt_op == MTFSR || mtop.mt_op == MTBSR) && 4752926Swnj bp->b_resid) { 4762926Swnj u.u_error = EIO; 4772926Swnj break; 4782926Swnj } 4792926Swnj if ((chtbuf[HTUNIT(bp->b_dev)].b_flags&B_ERROR) || 4802926Swnj sc->sc_dsreg&HTDS_BOT) 4812926Swnj break; 4822926Swnj } 4832926Swnj geterror(bp); 4842926Swnj return; 4852926Swnj case MTIOCGET: 4862926Swnj mtget.mt_dsreg = sc->sc_dsreg; 4872926Swnj mtget.mt_erreg = sc->sc_erreg; 4882926Swnj mtget.mt_resid = sc->sc_resid; 4892926Swnj if (copyout((caddr_t)&mtget, addr, sizeof(mtget))) 4902926Swnj u.u_error = EFAULT; 4912926Swnj return; 4922926Swnj default: 4932926Swnj u.u_error = ENXIO; 4942926Swnj } 4952926Swnj } 4962926Swnj 4971917Swnj #define DBSIZE 20 4981917Swnj 4992926Swnj htdump() 5001917Swnj { 501*2980Swnj register struct mba_device *mi; 5022926Swnj register struct mba_regs *mp; 5032926Swnj register struct htdevice *htaddr; 5042926Swnj int blk, num; 5052926Swnj int start; 5061917Swnj 5072926Swnj start = 0; 5082926Swnj num = maxfree; 5092926Swnj #define phys(a,b) ((b)((int)(a)&0x7fffffff)) 5102926Swnj if (htinfo[0] == 0) 5112926Swnj return (ENXIO); 512*2980Swnj mi = phys(htinfo[0], struct mba_device *); 5132926Swnj mp = phys(mi->mi_hd, struct mba_hd *)->mh_physmba; 5142926Swnj #if VAX780 5152961Swnj if (cpu == VAX780) 5162961Swnj mbainit(mp); 5172961Swnj #endif 5182926Swnj htaddr = (struct htdevice *)&mp->mba_drv[mi->mi_drive]; 5192926Swnj htaddr->httc = HTTC_PDP11|HTTC_1600BPI; 5202926Swnj htaddr->htcs1 = HT_DCLR|HT_GO; 5211917Swnj while (num > 0) { 5221917Swnj blk = num > DBSIZE ? DBSIZE : num; 5232926Swnj htdwrite(start, blk, htaddr, mp); 5242926Swnj start += blk; 5251917Swnj num -= blk; 5261917Swnj } 5272926Swnj htwait(htaddr); 5282926Swnj htaddr->htcs1 = HT_REW|HT_GO; 5292926Swnj hteof(htaddr); 5302926Swnj hteof(htaddr); 5311917Swnj } 5321917Swnj 5332926Swnj htdwrite(dbuf, num, htaddr, mp) 5342926Swnj register dbuf, num; 5352926Swnj register struct htdevice *htaddr; 5362926Swnj struct mba_regs *mp; 5371917Swnj { 5382926Swnj register struct pte *io; 5391917Swnj register int i; 5401917Swnj 5412926Swnj htwait(htaddr); 5422926Swnj io = mp->mba_map; 5431917Swnj for (i = 0; i < num; i++) 5442926Swnj *(int *)io++ = dbuf++ | PG_V; 5452926Swnj htaddr->htfc = -(num*NBPG); 5462926Swnj mp->mba_sr = -1; 5472926Swnj mp->mba_bcr = -(num*NBPG); 5482926Swnj mp->mba_var = 0; 5492926Swnj htaddr->htcs1 = HT_WCOM|HT_GO; 5501917Swnj } 5511917Swnj 5522926Swnj htwait(htaddr) 5532926Swnj struct htdevice *htaddr; 5541917Swnj { 5551917Swnj register s; 5561917Swnj 5571917Swnj do 5582926Swnj s = htaddr->htds; 5592926Swnj while ((s & HTDS_DRY) == 0); 5601917Swnj } 5611917Swnj 5622926Swnj hteof(htaddr) 5632926Swnj struct htdevice *htaddr; 5641917Swnj { 5651917Swnj 5662926Swnj htwait(htaddr); 5672926Swnj htaddr->htcs1 = HT_WEOF|HT_GO; 5681917Swnj } 5691563Sbill #endif 570