1*3181Swnj /* ht.c 4.13 81/03/10 */ 22961Swnj 32980Swnj #include "tu.h" 41563Sbill #if NHT > 0 522Sbill /* 62926Swnj * TM03/TU?? tape driver 73094Swnj * 83094Swnj * TODO: 93094Swnj * test error handling 103094Swnj * test tape with disk on same mba 113094Swnj * test ioctl's 123094Swnj * see how many rewind interrups we get if we kick when not at BOT 133157Swnj * test writing on write prot tape and error thereby 143157Swnj * check rle error on block tape code 1522Sbill */ 1622Sbill #include "../h/param.h" 1722Sbill #include "../h/systm.h" 1822Sbill #include "../h/buf.h" 1922Sbill #include "../h/conf.h" 2022Sbill #include "../h/dir.h" 2122Sbill #include "../h/file.h" 2222Sbill #include "../h/user.h" 2322Sbill #include "../h/map.h" 24420Sbill #include "../h/pte.h" 252980Swnj #include "../h/mbareg.h" 262980Swnj #include "../h/mbavar.h" 272926Swnj #include "../h/mtio.h" 282926Swnj #include "../h/ioctl.h" 291917Swnj #include "../h/cmap.h" 302961Swnj #include "../h/cpu.h" 3122Sbill 322926Swnj #include "../h/htreg.h" 3322Sbill 342926Swnj struct buf rhtbuf[NHT]; 352926Swnj struct buf chtbuf[NHT]; 3622Sbill 372926Swnj short httypes[] = 38*3181Swnj { MBDT_TM03, MBDT_TE16, MBDT_TU45, MBDT_TU77, 0 }; 392980Swnj struct mba_device *htinfo[NHT]; 403103Swnj int htattach(), htslave(), htustart(), htndtint(), htdtint(); 412926Swnj struct mba_driver htdriver = 422980Swnj { htattach, htslave, htustart, 0, htdtint, htndtint, 432980Swnj httypes, "ht", "tu", htinfo }; 4422Sbill 452926Swnj #define MASKREG(r) ((r) & 0xffff) 4622Sbill 472926Swnj /* bits in minor device */ 482980Swnj #define TUUNIT(dev) (minor(dev)&03) 492926Swnj #define H_NOREWIND 04 502926Swnj #define H_1600BPI 08 5122Sbill 523094Swnj #define HTUNIT(dev) (tutoht[TUUNIT(dev)]) 532980Swnj 542926Swnj #define INF (daddr_t)1000000L /* a block number that wont exist */ 552926Swnj 563094Swnj struct tu_softc { 572926Swnj char sc_openf; 582926Swnj char sc_flags; 592926Swnj daddr_t sc_blkno; 602926Swnj daddr_t sc_nxrec; 612926Swnj u_short sc_erreg; 622926Swnj u_short sc_dsreg; 632926Swnj short sc_resid; 642926Swnj short sc_dens; 652980Swnj struct mba_device *sc_mi; 662980Swnj int sc_slave; 673094Swnj } tu_softc[NTU]; 683094Swnj short tutoht[NTU]; 692926Swnj 702926Swnj /* 712926Swnj * Bits for sc_flags. 722926Swnj */ 732926Swnj #define H_WRITTEN 1 /* last operation was a write */ 742926Swnj #define H_ERASED 2 /* last write retry was an erase gap */ 752926Swnj #define H_REWIND 4 /* last unit start was a rewind */ 7622Sbill 772926Swnj /*ARGSUSED*/ 782980Swnj htattach(mi) 792980Swnj struct mba_device *mi; 802926Swnj { 812926Swnj 822926Swnj } 832926Swnj 842980Swnj htslave(mi, ms) 852980Swnj struct mba_device *mi; 862980Swnj struct mba_slave *ms; 872980Swnj { 883094Swnj register struct tu_softc *sc = &tu_softc[ms->ms_unit]; 892980Swnj 902980Swnj sc->sc_mi = mi; 912980Swnj sc->sc_slave = ms->ms_slave; 923094Swnj tutoht[ms->ms_unit] = mi->mi_unit; 932980Swnj } 942980Swnj 9522Sbill htopen(dev, flag) 962926Swnj dev_t dev; 972926Swnj int flag; 9822Sbill { 993094Swnj register int tuunit; 1002980Swnj register struct mba_device *mi; 1013094Swnj register struct tu_softc *sc; 1023094Swnj int dens; 10322Sbill 1043094Swnj tuunit = TUUNIT(dev); 1053094Swnj if (tuunit >= NTU || (sc = &tu_softc[tuunit])->sc_openf || 1062980Swnj (mi = htinfo[HTUNIT(dev)]) == 0 || mi->mi_alive == 0) { 10722Sbill u.u_error = ENXIO; 10822Sbill return; 10922Sbill } 1102926Swnj htcommand(dev, HT_SENSE, 1); 1113094Swnj dens = 1123094Swnj ((minor(dev)&H_1600BPI)?HTTC_1600BPI:HTTC_800BPI)| 1133094Swnj HTTC_PDP11|sc->sc_slave; 1142926Swnj if ((sc->sc_dsreg & HTDS_MOL) == 0 || 1153157Swnj (flag&FWRITE) && (sc->sc_dsreg&HTDS_WRL) || 1163094Swnj (sc->sc_dsreg & HTDS_BOT) == 0 && (flag&FWRITE) && 1173157Swnj dens != sc->sc_dens) { 1182926Swnj u.u_error = EIO; 1192926Swnj return; 1202926Swnj } 1212926Swnj sc->sc_openf = 1; 1222926Swnj sc->sc_blkno = (daddr_t)0; 1232926Swnj sc->sc_nxrec = INF; 1242926Swnj sc->sc_flags = 0; 1253094Swnj sc->sc_dens = dens; 12622Sbill } 12722Sbill 12822Sbill htclose(dev, flag) 1292926Swnj register dev_t dev; 1302926Swnj register flag; 13122Sbill { 1323094Swnj register struct tu_softc *sc = &tu_softc[TUUNIT(dev)]; 13322Sbill 1342926Swnj if (flag == FWRITE || ((flag&FWRITE) && (sc->sc_flags&H_WRITTEN))) { 1352926Swnj htcommand(dev, HT_WEOF, 1); 1362926Swnj htcommand(dev, HT_WEOF, 1); 1372926Swnj htcommand(dev, HT_SREV, 1); 13822Sbill } 1392926Swnj if ((minor(dev)&H_NOREWIND) == 0) 1402926Swnj htcommand(dev, HT_REW, 0); 1412926Swnj sc->sc_openf = 0; 14222Sbill } 14322Sbill 1442926Swnj htcommand(dev, com, count) 1452926Swnj dev_t dev; 1462926Swnj int com, count; 14722Sbill { 14822Sbill register struct buf *bp; 14922Sbill 1502926Swnj bp = &chtbuf[HTUNIT(dev)]; 151128Sbill (void) spl5(); 1522926Swnj while (bp->b_flags&B_BUSY) { 1533157Swnj if(bp->b_repcnt == 0 && (bp->b_flags&B_DONE)) 1542980Swnj 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 { 1763094Swnj register struct mba_device *mi = htinfo[HTUNIT(bp->b_dev)]; 1772926Swnj register struct buf *dp; 17822Sbill 17922Sbill bp->av_forw = NULL; 1802926Swnj dp = &mi->mi_tab; 181128Sbill (void) spl5(); 1822926Swnj if (dp->b_actf == NULL) 1832926Swnj dp->b_actf = bp; 18422Sbill else 1852926Swnj dp->b_actl->av_forw = bp; 1862926Swnj dp->b_actl = bp; 1872926Swnj if (dp->b_active == 0) 1882926Swnj mbustart(mi); 189128Sbill (void) spl0(); 19022Sbill } 19122Sbill 1922926Swnj htustart(mi) 1932980Swnj register struct mba_device *mi; 19422Sbill { 1952926Swnj register struct htdevice *htaddr = 1962926Swnj (struct htdevice *)mi->mi_drv; 1972926Swnj register struct buf *bp = mi->mi_tab.b_actf; 1983094Swnj register struct tu_softc *sc = &tu_softc[TUUNIT(bp->b_dev)]; 19922Sbill daddr_t blkno; 20022Sbill 2012926Swnj htaddr->httc = sc->sc_dens; 202*3181Swnj if (bp == &chtbuf[HTUNIT(bp->b_dev)] && bp->b_command == HT_SENSE) { 2033157Swnj htaddr->htcs1 = HT_SENSE|HT_GO; 2043157Swnj mbclrattn(mi); 2053157Swnj } 2062926Swnj sc->sc_dsreg = htaddr->htds; 2072926Swnj sc->sc_erreg = htaddr->hter; 2082926Swnj sc->sc_resid = htaddr->htfc; 2092926Swnj sc->sc_flags &= ~(H_WRITTEN|H_REWIND); 2102926Swnj if ((htaddr->htdt & HTDT_SPR) == 0 || (htaddr->htds & HTDS_MOL) == 0) 2112926Swnj if (sc->sc_openf > 0) 2122926Swnj sc->sc_openf = -1; 2132926Swnj if (sc->sc_openf < 0) { 2142926Swnj bp->b_flags |= B_ERROR; 2152926Swnj return (MBU_NEXT); 2162926Swnj } 2173094Swnj if (bp != &chtbuf[HTUNIT(bp->b_dev)]) { 2182926Swnj if (dbtofsb(bp->b_blkno) > sc->sc_nxrec) { 2192926Swnj bp->b_flags |= B_ERROR; 2202926Swnj bp->b_error = ENXIO; 2212961Swnj return (MBU_NEXT); 2223094Swnj } 2233094Swnj if (dbtofsb(bp->b_blkno) == sc->sc_nxrec && 2242926Swnj bp->b_flags&B_READ) { 2252926Swnj bp->b_resid = bp->b_bcount; 2262926Swnj clrbuf(bp); 2272961Swnj return (MBU_NEXT); 2283094Swnj } 2293094Swnj if ((bp->b_flags&B_READ)==0) 2302926Swnj sc->sc_nxrec = dbtofsb(bp->b_blkno) + 1; 2312926Swnj } else { 2322961Swnj if (bp->b_command == HT_SENSE) 2332926Swnj return (MBU_NEXT); 2342926Swnj if (bp->b_command == HT_REW) 2352926Swnj sc->sc_flags |= H_REWIND; 2362926Swnj else 2372926Swnj htaddr->htfc = -bp->b_bcount; 2382926Swnj htaddr->htcs1 = bp->b_command|HT_GO; 2392926Swnj return (MBU_STARTED); 2402926Swnj } 2412926Swnj if ((blkno = sc->sc_blkno) == dbtofsb(bp->b_blkno)) { 2422926Swnj htaddr->htfc = -bp->b_bcount; 2432926Swnj if ((bp->b_flags&B_READ) == 0) { 2443094Swnj if (mi->mi_tab.b_errcnt) { 2453094Swnj if ((sc->sc_flags & H_ERASED) == 0) { 2462926Swnj sc->sc_flags |= H_ERASED; 2472926Swnj htaddr->htcs1 = HT_ERASE | HT_GO; 2482926Swnj return (MBU_STARTED); 2492926Swnj } 2503094Swnj sc->sc_flags &= ~H_ERASED; 2513094Swnj } 2522926Swnj if (htaddr->htds & HTDS_EOT) { 2532926Swnj bp->b_resid = bp->b_bcount; 2542926Swnj return (MBU_NEXT); 2552926Swnj } 25622Sbill } 2572926Swnj return (MBU_DODATA); 25822Sbill } 2592926Swnj if (blkno < dbtofsb(bp->b_blkno)) { 2602926Swnj htaddr->htfc = blkno - dbtofsb(bp->b_blkno); 2612926Swnj htaddr->htcs1 = HT_SFORW|HT_GO; 26222Sbill } else { 2632926Swnj htaddr->htfc = dbtofsb(bp->b_blkno) - blkno; 2642926Swnj htaddr->htcs1 = HT_SREV|HT_GO; 26522Sbill } 2662926Swnj return (MBU_STARTED); 26722Sbill } 26822Sbill 2693094Swnj htdtint(mi, mbsr) 2702980Swnj register struct mba_device *mi; 2713094Swnj int mbsr; 27222Sbill { 2732926Swnj register struct htdevice *htaddr = (struct htdevice *)mi->mi_drv; 2742926Swnj register struct buf *bp = mi->mi_tab.b_actf; 2753094Swnj register struct tu_softc *sc; 2762961Swnj int ds, er, mbs; 27722Sbill 2783094Swnj sc = &tu_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); 2823094Swnj mbs = mbsr; 2832926Swnj sc->sc_blkno++; 2842926Swnj if((bp->b_flags & B_READ) == 0) 2852926Swnj sc->sc_flags |= H_WRITTEN; 2863094Swnj if ((ds&(HTDS_ERR|HTDS_MOL)) != HTDS_MOL || mbs & MBSR_EBITS) { 2872926Swnj htaddr->htcs1 = HT_DCLR|HT_GO; 2882961Swnj mbclrattn(mi); 2892961Swnj if (bp == &rhtbuf[HTUNIT(bp->b_dev)]) { 2902926Swnj er &= ~HTER_FCE; 2913094Swnj mbs &= ~(MBSR_DTABT|MBSR_MBEXC); 2923157Swnj } else 2932926Swnj if (bp->b_flags & B_READ && ds & HTDS_PES) 2942926Swnj er &= ~(HTER_CSITM|HTER_CORCRC); 2953094Swnj if (er&HTER_HARD || mbs&MBSR_EBITS || (ds&HTDS_MOL) == 0 || 2962961Swnj er && ++mi->mi_tab.b_errcnt >= 7) { 2972926Swnj if ((ds & HTDS_MOL) == 0 && sc->sc_openf > 0) 2982926Swnj sc->sc_openf = -1; 2993157Swnj if ((er&HTER_HARD) == HTER_FCE && 3003157Swnj (mbs&MBSR_EBITS) == (MBSR_DTABT|MBSR_MBEXC) && 3013157Swnj (ds&HTDS_MOL)) 3023157Swnj goto noprint; 3033094Swnj printf("tu%d: hard error bn%d mbsr=%b er=%b\n", 3042980Swnj TUUNIT(bp->b_dev), bp->b_blkno, 3053094Swnj mbsr, mbsr_bits, 3062926Swnj MASKREG(htaddr->hter), HTER_BITS); 3073157Swnj noprint: 30822Sbill bp->b_flags |= B_ERROR; 3092926Swnj return (MBD_DONE); 31022Sbill } 3112926Swnj if (er) 3122926Swnj return (MBD_RETRY); 31322Sbill } 3142926Swnj bp->b_resid = 0; 3152926Swnj if (bp->b_flags & B_READ) 3162926Swnj if (ds&HTDS_TM) { /* must be a read, right? */ 3172926Swnj bp->b_resid = bp->b_bcount; 3182926Swnj sc->sc_nxrec = dbtofsb(bp->b_blkno); 3192926Swnj } else if(bp->b_bcount > MASKREG(htaddr->htfc)) 3202926Swnj bp->b_resid = bp->b_bcount - MASKREG(htaddr->htfc); 3212926Swnj return (MBD_DONE); 3222926Swnj } 32322Sbill 3242926Swnj htndtint(mi) 3252980Swnj 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; 3293094Swnj register struct tu_softc *sc; 3302926Swnj int er, ds, fc; 33122Sbill 3323094Swnj ds = MASKREG(htaddr->htds); 3333094Swnj er = MASKREG(htaddr->hter); 3343094Swnj fc = MASKREG(htaddr->htfc); 3353094Swnj if (er) { 3362926Swnj htaddr->htcs1 = HT_DCLR|HT_GO; 3372961Swnj mbclrattn(mi); 3382961Swnj } 3393094Swnj if (bp == 0) 3403094Swnj return (MBN_SKIP); 3413094Swnj sc = &tu_softc[TUUNIT(bp->b_dev)]; 3423094Swnj sc->sc_dsreg = ds; 3433094Swnj sc->sc_erreg = er; 3443094Swnj sc->sc_resid = fc; 3453094Swnj if (bp == &chtbuf[HTUNIT(bp->b_dev)]) { 3463094Swnj switch (bp->b_command) { 3473094Swnj case HT_REWOFFL: 3482926Swnj /* offline is on purpose; don't do anything special */ 3492926Swnj ds |= HTDS_MOL; 3503094Swnj break; 3513094Swnj case HT_SREV: 3523094Swnj /* if backspace file hit bot, its not an error */ 3533094Swnj if (er == (HTER_NEF|HTER_FCE) && ds&HTDS_BOT && 3543094Swnj bp->b_repcnt == INF) 3553094Swnj er &= ~HTER_NEF; 3563094Swnj break; 3573094Swnj } 3582926Swnj er &= ~HTER_FCE; 3592926Swnj if (er == 0) 3602926Swnj ds &= ~HTDS_ERR; 36122Sbill } 3622926Swnj if ((ds & (HTDS_ERR|HTDS_MOL)) != HTDS_MOL) { 3632926Swnj if ((ds & HTDS_MOL) == 0 && sc->sc_openf > 0) 3642926Swnj sc->sc_openf = -1; 3653157Swnj printf("tu%d: hard error bn%d er=%b\n", 3662980Swnj TUUNIT(bp->b_dev), bp->b_blkno, 3673157Swnj sc->sc_erreg, HTER_BITS); 3682926Swnj bp->b_flags |= B_ERROR; 3692926Swnj return (MBN_DONE); 3702926Swnj } 3713094Swnj if (bp == &chtbuf[HTUNIT(bp->b_dev)]) { 3722926Swnj if (sc->sc_flags & H_REWIND) 3732926Swnj return (ds & HTDS_BOT ? MBN_DONE : MBN_RETRY); 3742926Swnj bp->b_resid = -sc->sc_resid; 3752926Swnj return (MBN_DONE); 3762926Swnj } 3772926Swnj if (ds & HTDS_TM) 3783094Swnj if (sc->sc_blkno > dbtofsb(bp->b_blkno)) { 3792926Swnj sc->sc_nxrec = dbtofsb(bp->b_blkno) - fc; 3802926Swnj sc->sc_blkno = sc->sc_nxrec; 3813094Swnj } else { 3822926Swnj sc->sc_blkno = dbtofsb(bp->b_blkno) + fc; 3832926Swnj sc->sc_nxrec = sc->sc_blkno - 1; 3842926Swnj } 3852926Swnj else 3862926Swnj sc->sc_blkno = dbtofsb(bp->b_blkno); 3872926Swnj return (MBN_RETRY); 38822Sbill } 38922Sbill 39022Sbill htread(dev) 3912926Swnj dev_t dev; 39222Sbill { 3932926Swnj 39422Sbill htphys(dev); 3952926Swnj if (u.u_error) 3962926Swnj return; 3972926Swnj physio(htstrategy, &rhtbuf[HTUNIT(dev)], dev, B_READ, minphys); 39822Sbill } 39922Sbill 40022Sbill htwrite(dev) 40122Sbill { 4022926Swnj 40322Sbill htphys(dev); 4042926Swnj if (u.u_error) 4052926Swnj return; 4062926Swnj physio(htstrategy, &rhtbuf[HTUNIT(dev)], dev, B_WRITE, minphys); 40722Sbill } 40822Sbill 40922Sbill htphys(dev) 4102926Swnj dev_t dev; 41122Sbill { 4123094Swnj register int htunit; 4133094Swnj register struct tu_softc *sc; 4143094Swnj register struct mba_device *mi; 41522Sbill daddr_t a; 41622Sbill 4173094Swnj htunit = HTUNIT(dev); 4183094Swnj if (htunit >= NHT || (mi = htinfo[htunit]) == 0 || mi->mi_alive == 0) { 4192926Swnj u.u_error = ENXIO; 4202926Swnj return; 42122Sbill } 4222926Swnj a = u.u_offset >> 9; 4233094Swnj sc = &tu_softc[TUUNIT(dev)]; 4242926Swnj sc->sc_blkno = dbtofsb(a); 4252926Swnj sc->sc_nxrec = dbtofsb(a)+1; 42622Sbill } 4271917Swnj 4282926Swnj /*ARGSUSED*/ 4292926Swnj htioctl(dev, cmd, addr, flag) 4302926Swnj dev_t dev; 4312926Swnj int cmd; 4322926Swnj caddr_t addr; 4332926Swnj int flag; 4342926Swnj { 4353094Swnj register struct tu_softc *sc = &tu_softc[TUUNIT(dev)]; 4363094Swnj register struct buf *bp = &chtbuf[HTUNIT(dev)]; 4372926Swnj register callcount; 4382926Swnj int fcount; 4392926Swnj struct mtop mtop; 4402926Swnj struct mtget mtget; 4412926Swnj /* we depend of the values and order of the MT codes here */ 4422926Swnj static htops[] = 4432926Swnj {HT_WEOF,HT_SFORW,HT_SREV,HT_SFORW,HT_SREV,HT_REW,HT_REWOFFL,HT_SENSE}; 4441917Swnj 4452926Swnj switch (cmd) { 4462926Swnj case MTIOCTOP: /* tape operation */ 4472926Swnj if (copyin((caddr_t)addr, (caddr_t)&mtop, sizeof(mtop))) { 4482926Swnj u.u_error = EFAULT; 4492926Swnj return; 4502926Swnj } 4512926Swnj switch(mtop.mt_op) { 4522926Swnj case MTWEOF: 4532926Swnj callcount = mtop.mt_count; 4542926Swnj fcount = 1; 4552926Swnj break; 4562926Swnj case MTFSF: case MTBSF: 4572926Swnj callcount = mtop.mt_count; 4582926Swnj fcount = INF; 4592926Swnj break; 4602926Swnj case MTFSR: case MTBSR: 4612926Swnj callcount = 1; 4622926Swnj fcount = mtop.mt_count; 4632926Swnj break; 4642926Swnj case MTREW: case MTOFFL: 4652926Swnj callcount = 1; 4662926Swnj fcount = 1; 4672926Swnj break; 4682926Swnj default: 4692926Swnj u.u_error = ENXIO; 4702926Swnj return; 4712926Swnj } 4722926Swnj if (callcount <= 0 || fcount <= 0) { 4732926Swnj u.u_error = ENXIO; 4742926Swnj return; 4752926Swnj } 4762926Swnj while (--callcount >= 0) { 4772926Swnj htcommand(dev, htops[mtop.mt_op], fcount); 4782926Swnj if ((mtop.mt_op == MTFSR || mtop.mt_op == MTBSR) && 4792926Swnj bp->b_resid) { 4802926Swnj u.u_error = EIO; 4812926Swnj break; 4822926Swnj } 4833094Swnj if ((bp->b_flags&B_ERROR) || sc->sc_dsreg&HTDS_BOT) 4842926Swnj break; 4852926Swnj } 4862926Swnj geterror(bp); 4872926Swnj return; 4882926Swnj case MTIOCGET: 4892926Swnj mtget.mt_dsreg = sc->sc_dsreg; 4902926Swnj mtget.mt_erreg = sc->sc_erreg; 4912926Swnj mtget.mt_resid = sc->sc_resid; 4922926Swnj if (copyout((caddr_t)&mtget, addr, sizeof(mtget))) 4932926Swnj u.u_error = EFAULT; 4942926Swnj return; 4952926Swnj default: 4962926Swnj u.u_error = ENXIO; 4972926Swnj } 4982926Swnj } 4992926Swnj 5001917Swnj #define DBSIZE 20 5011917Swnj 5022926Swnj htdump() 5031917Swnj { 5042980Swnj register struct mba_device *mi; 5052926Swnj register struct mba_regs *mp; 5062926Swnj register struct htdevice *htaddr; 5072926Swnj int blk, num; 5082926Swnj int start; 5091917Swnj 5102926Swnj start = 0; 5112926Swnj num = maxfree; 5122926Swnj #define phys(a,b) ((b)((int)(a)&0x7fffffff)) 5132926Swnj if (htinfo[0] == 0) 5142926Swnj return (ENXIO); 5152980Swnj mi = phys(htinfo[0], struct mba_device *); 5162926Swnj mp = phys(mi->mi_hd, struct mba_hd *)->mh_physmba; 5173157Swnj mp->mba_cr = MBCR_IE; 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 } 5273157Swnj hteof(htaddr); 5283157Swnj hteof(htaddr); 5292926Swnj htwait(htaddr); 530*3181Swnj if (htaddr->htds&HTDS_ERR) 5313157Swnj return (EIO); 5322926Swnj htaddr->htcs1 = HT_REW|HT_GO; 5333103Swnj return (0); 5341917Swnj } 5351917Swnj 5362926Swnj htdwrite(dbuf, num, htaddr, mp) 5372926Swnj register dbuf, num; 5382926Swnj register struct htdevice *htaddr; 5392926Swnj struct mba_regs *mp; 5401917Swnj { 5412926Swnj register struct pte *io; 5421917Swnj register int i; 5431917Swnj 5442926Swnj htwait(htaddr); 5452926Swnj io = mp->mba_map; 5461917Swnj for (i = 0; i < num; i++) 5472926Swnj *(int *)io++ = dbuf++ | PG_V; 5482926Swnj htaddr->htfc = -(num*NBPG); 5492926Swnj mp->mba_sr = -1; 5502926Swnj mp->mba_bcr = -(num*NBPG); 5512926Swnj mp->mba_var = 0; 5522926Swnj htaddr->htcs1 = HT_WCOM|HT_GO; 5531917Swnj } 5541917Swnj 5552926Swnj htwait(htaddr) 5562926Swnj struct htdevice *htaddr; 5571917Swnj { 5581917Swnj register s; 5591917Swnj 5601917Swnj do 5612926Swnj s = htaddr->htds; 5622926Swnj while ((s & HTDS_DRY) == 0); 5631917Swnj } 5641917Swnj 5652926Swnj hteof(htaddr) 5662926Swnj struct htdevice *htaddr; 5671917Swnj { 5681917Swnj 5692926Swnj htwait(htaddr); 5702926Swnj htaddr->htcs1 = HT_WEOF|HT_GO; 5711917Swnj } 5721563Sbill #endif 573