11936Swnj #include "ht.h" 21563Sbill #if NHT > 0 322Sbill /* 4*2926Swnj * TM03/TU?? tape driver 522Sbill */ 622Sbill #include "../h/param.h" 722Sbill #include "../h/systm.h" 822Sbill #include "../h/buf.h" 922Sbill #include "../h/conf.h" 1022Sbill #include "../h/dir.h" 1122Sbill #include "../h/file.h" 1222Sbill #include "../h/user.h" 1322Sbill #include "../h/map.h" 14420Sbill #include "../h/pte.h" 1522Sbill #include "../h/mba.h" 16*2926Swnj #include "../h/mtio.h" 17*2926Swnj #include "../h/ioctl.h" 181917Swnj #include "../h/cmap.h" 1922Sbill 20*2926Swnj #include "../h/htreg.h" 2122Sbill 22*2926Swnj struct buf rhtbuf[NHT]; 23*2926Swnj struct buf chtbuf[NHT]; 2422Sbill 25*2926Swnj short httypes[] = 26*2926Swnj { MBDT_TE16, MBDT_TU45, MBDT_TU77, 0 }; 27*2926Swnj struct mba_info *htinfo[NHT]; 28*2926Swnj int htdkinit(), htustart(), htndtint(), htdtint(); 29*2926Swnj struct mba_driver htdriver = 30*2926Swnj { htdkinit, htustart, 0, htdtint, htndtint, httypes, htinfo }; 3122Sbill 32*2926Swnj #define MASKREG(r) ((r) & 0xffff) 3322Sbill 34*2926Swnj /* bits in minor device */ 35*2926Swnj #define HTUNIT(dev) (minor(dev)&03) 36*2926Swnj #define H_NOREWIND 04 37*2926Swnj #define H_1600BPI 08 3822Sbill 39*2926Swnj #define INF (daddr_t)1000000L /* a block number that wont exist */ 40*2926Swnj 41*2926Swnj struct ht_softc { 42*2926Swnj char sc_openf; 43*2926Swnj char sc_flags; 44*2926Swnj daddr_t sc_blkno; 45*2926Swnj daddr_t sc_nxrec; 46*2926Swnj u_short sc_erreg; 47*2926Swnj u_short sc_dsreg; 48*2926Swnj short sc_resid; 49*2926Swnj short sc_dens; 50*2926Swnj } ht_softc[NHT]; 51*2926Swnj 52*2926Swnj /* 53*2926Swnj * States for b_active for device. 54*2926Swnj */ 5522Sbill #define SIO 1 5622Sbill #define SSFOR 2 5722Sbill #define SSREV 3 5822Sbill #define SRETRY 4 5922Sbill #define SCOM 5 6022Sbill #define SOK 6 61*2926Swnj #define SEOF 7 6222Sbill 63*2926Swnj /* 64*2926Swnj * Bits for sc_flags. 65*2926Swnj */ 66*2926Swnj #define H_WRITTEN 1 /* last operation was a write */ 67*2926Swnj #define H_ERASED 2 /* last write retry was an erase gap */ 68*2926Swnj #define H_REWIND 4 /* last unit start was a rewind */ 6922Sbill 70*2926Swnj /*ARGSUSED*/ 71*2926Swnj htdkinit(mi) 72*2926Swnj struct mba_info *mi; 73*2926Swnj { 74*2926Swnj 75*2926Swnj } 76*2926Swnj 7722Sbill htopen(dev, flag) 78*2926Swnj dev_t dev; 79*2926Swnj int flag; 8022Sbill { 81*2926Swnj register int unit; 82*2926Swnj register struct mba_info *mi; 83*2926Swnj register struct ht_softc *sc; 8422Sbill 85*2926Swnj unit = HTUNIT(dev); 86*2926Swnj if (unit >= NHT || (sc = &ht_softc[unit])->sc_openf || 87*2926Swnj (mi = htinfo[unit]) == 0 || mi->mi_alive == 0) { 8822Sbill u.u_error = ENXIO; 8922Sbill return; 9022Sbill } 91*2926Swnj /* 92*2926Swnj * The NOP below serves two purposes: 93*2926Swnj * 1. To get a recent copy of the status registers. 94*2926Swnj * 2. To ensure that any outstanding rewinds are truly finished 95*2926Swnj * so that the test for BOT is valid. 96*2926Swnj */ 97*2926Swnj htcommand(dev, HT_SENSE, 1); 98*2926Swnj if ((sc->sc_dsreg & HTDS_MOL) == 0 || 99*2926Swnj (flag & (FREAD|FWRITE)) == FWRITE && sc->sc_dsreg&HTDS_WRL) { 100*2926Swnj u.u_error = EIO; 101*2926Swnj return; 102*2926Swnj } 103*2926Swnj sc->sc_dens = 104*2926Swnj ((minor(dev)&H_1600BPI)?HTTC_1600BPI:HTTC_800BPI)|HTTC_PDP11|unit; 105*2926Swnj sc->sc_openf = 1; 106*2926Swnj sc->sc_blkno = (daddr_t)0; 107*2926Swnj sc->sc_nxrec = INF; 108*2926Swnj sc->sc_flags = 0; 10922Sbill } 11022Sbill 11122Sbill htclose(dev, flag) 112*2926Swnj register dev_t dev; 113*2926Swnj register flag; 11422Sbill { 115*2926Swnj register struct ht_softc *sc = &ht_softc[HTUNIT(dev)]; 11622Sbill 117*2926Swnj if (flag == FWRITE || ((flag&FWRITE) && (sc->sc_flags&H_WRITTEN))) { 118*2926Swnj htcommand(dev, HT_WEOF, 1); 119*2926Swnj htcommand(dev, HT_WEOF, 1); 120*2926Swnj htcommand(dev, HT_SREV, 1); 12122Sbill } 122*2926Swnj if ((minor(dev)&H_NOREWIND) == 0) 123*2926Swnj /* 0 as third arg means don't wait */ 124*2926Swnj htcommand(dev, HT_REW, 0); 125*2926Swnj sc->sc_openf = 0; 12622Sbill } 12722Sbill 128*2926Swnj /* 129*2926Swnj * Do a non-data-transfer command. 130*2926Swnj * 131*2926Swnj * N.B.: Count should be zero ONLY for rewind during close. 132*2926Swnj */ 133*2926Swnj htcommand(dev, com, count) 134*2926Swnj dev_t dev; 135*2926Swnj int com, count; 13622Sbill { 13722Sbill register struct buf *bp; 13822Sbill 139*2926Swnj bp = &chtbuf[HTUNIT(dev)]; 140128Sbill (void) spl5(); 141*2926Swnj /* 142*2926Swnj * The B_DONE test is to allow the rewind on close not to wait at 143*2926Swnj * all. We just must make sure that it was an asynchronous rewind, 144*2926Swnj * otherwise if it isn't we might wake up before the process 145*2926Swnj * waiting for the command (we are waiting for the buffer here). 146*2926Swnj */ 147*2926Swnj while (bp->b_flags&B_BUSY) { 148*2926Swnj if (bp->b_flags&B_DONE && bp->b_repcnt == 0) 149*2926Swnj break; 15022Sbill bp->b_flags |= B_WANTED; 15122Sbill sleep((caddr_t)bp, PRIBIO); 15222Sbill } 153*2926Swnj bp->b_flags = B_BUSY; 154128Sbill (void) spl0(); 15522Sbill bp->b_dev = dev; 156*2926Swnj bp->b_command = com; 157*2926Swnj bp->b_repcnt = count; 15822Sbill bp->b_blkno = 0; 15922Sbill htstrategy(bp); 160*2926Swnj if (count == 0) 161*2926Swnj return; 16222Sbill iowait(bp); 163*2926Swnj if (bp->b_flags&B_WANTED) 16422Sbill wakeup((caddr_t)bp); 165*2926Swnj bp->b_flags &= B_ERROR; 16622Sbill } 16722Sbill 16822Sbill htstrategy(bp) 169*2926Swnj register struct buf *bp; 17022Sbill { 171*2926Swnj register int unit = HTUNIT(bp->b_dev); 172*2926Swnj register struct mba_info *mi; 173*2926Swnj register struct buf *dp; 174*2926Swnj register struct ht_softc *sc = &ht_softc[unit]; 17522Sbill 17622Sbill bp->av_forw = NULL; 177*2926Swnj dp = &mi->mi_tab; 178128Sbill (void) spl5(); 179*2926Swnj if (dp->b_actf == NULL) 180*2926Swnj dp->b_actf = bp; 18122Sbill else 182*2926Swnj dp->b_actl->av_forw = bp; 183*2926Swnj dp->b_actl = bp; 184*2926Swnj if (dp->b_active == 0) 185*2926Swnj mbustart(mi); 186128Sbill (void) spl0(); 18722Sbill } 18822Sbill 189*2926Swnj htustart(mi) 190*2926Swnj register struct mba_info *mi; 19122Sbill { 192*2926Swnj register struct htdevice *htaddr = 193*2926Swnj (struct htdevice *)mi->mi_drv; 194*2926Swnj register struct buf *bp = mi->mi_tab.b_actf; 195*2926Swnj int unit = HTUNIT(bp->b_dev); 196*2926Swnj register struct ht_softc *sc = &ht_softc[unit]; 19722Sbill daddr_t blkno; 19822Sbill 199*2926Swnj htaddr->httc = sc->sc_dens; 200*2926Swnj sc->sc_dsreg = htaddr->htds; 201*2926Swnj sc->sc_erreg = htaddr->hter; 202*2926Swnj sc->sc_resid = htaddr->htfc; 203*2926Swnj sc->sc_flags &= ~(H_WRITTEN|H_REWIND); 204*2926Swnj if ((htaddr->htdt & HTDT_SPR) == 0 || (htaddr->htds & HTDS_MOL) == 0) 205*2926Swnj if (sc->sc_openf > 0) 206*2926Swnj sc->sc_openf = -1; 207*2926Swnj if (sc->sc_openf < 0) { 208*2926Swnj bp->b_flags |= B_ERROR; 209*2926Swnj return (MBU_NEXT); 210*2926Swnj } 211*2926Swnj if (bp != &chtbuf[unit]) { 212*2926Swnj if (dbtofsb(bp->b_blkno) > sc->sc_nxrec) { 213*2926Swnj bp->b_flags |= B_ERROR; 214*2926Swnj bp->b_error = ENXIO; 21522Sbill goto next; 216*2926Swnj } else if (dbtofsb(bp->b_blkno) == sc->sc_nxrec && 217*2926Swnj bp->b_flags&B_READ) { 218*2926Swnj bp->b_resid = bp->b_bcount; 219*2926Swnj clrbuf(bp); 220*2926Swnj goto next; 221*2926Swnj } else if ((bp->b_flags&B_READ)==0) 222*2926Swnj sc->sc_nxrec = dbtofsb(bp->b_blkno) + 1; 223*2926Swnj } else { 224*2926Swnj if (bp->b_command == HT_SENSE) 225*2926Swnj return (MBU_NEXT); 226*2926Swnj if (bp->b_command == HT_REW) 227*2926Swnj sc->sc_flags |= H_REWIND; 228*2926Swnj else 229*2926Swnj htaddr->htfc = -bp->b_bcount; 230*2926Swnj htaddr->htcs1 = bp->b_command|HT_GO; 231*2926Swnj return (MBU_STARTED); 232*2926Swnj } 233*2926Swnj if ((blkno = sc->sc_blkno) == dbtofsb(bp->b_blkno)) { 234*2926Swnj htaddr->htfc = -bp->b_bcount; 235*2926Swnj if ((bp->b_flags&B_READ) == 0) { 236*2926Swnj if (mi->mi_tab.b_errcnt) 237*2926Swnj if (sc->sc_flags & H_ERASED) 238*2926Swnj sc->sc_flags &= ~H_ERASED; 239*2926Swnj else { 240*2926Swnj sc->sc_flags |= H_ERASED; 241*2926Swnj htaddr->htcs1 = HT_ERASE | HT_GO; 242*2926Swnj return (MBU_STARTED); 243*2926Swnj } 244*2926Swnj if (htaddr->htds & HTDS_EOT) { 245*2926Swnj bp->b_resid = bp->b_bcount; 246*2926Swnj return (MBU_NEXT); 247*2926Swnj } 24822Sbill } 249*2926Swnj return (MBU_DODATA); 25022Sbill } 251*2926Swnj if (blkno < dbtofsb(bp->b_blkno)) { 252*2926Swnj htaddr->htfc = blkno - dbtofsb(bp->b_blkno); 253*2926Swnj htaddr->htcs1 = HT_SFORW|HT_GO; 25422Sbill } else { 255*2926Swnj htaddr->htfc = dbtofsb(bp->b_blkno) - blkno; 256*2926Swnj htaddr->htcs1 = HT_SREV|HT_GO; 25722Sbill } 258*2926Swnj return (MBU_STARTED); 259*2926Swnj next: 26022Sbill iodone(bp); 261*2926Swnj return (MBU_NEXT); 26222Sbill } 26322Sbill 264*2926Swnj /* 265*2926Swnj * data transfer interrupt - must be read or write 266*2926Swnj */ 26722Sbill /*ARGSUSED*/ 268*2926Swnj htdtint(mi, mbasr) 269*2926Swnj register struct mba_info *mi; 270*2926Swnj int mbasr; 27122Sbill { 272*2926Swnj register struct htdevice *htaddr = (struct htdevice *)mi->mi_drv; 273*2926Swnj register struct buf *bp = mi->mi_tab.b_actf; 274*2926Swnj register struct ht_softc *sc; 275*2926Swnj int ds, er; 27622Sbill 277*2926Swnj if (bp == NULL) 27822Sbill return; 279*2926Swnj sc = &ht_softc[HTUNIT(bp->b_dev)]; 280*2926Swnj ds = sc->sc_dsreg = MASKREG(htaddr->htds); 281*2926Swnj er = sc->sc_erreg = MASKREG(htaddr->hter); 282*2926Swnj sc->sc_resid = MASKREG(htaddr->htfc); 283*2926Swnj sc->sc_blkno++; 284*2926Swnj if((bp->b_flags & B_READ) == 0) 285*2926Swnj sc->sc_flags |= H_WRITTEN; 286*2926Swnj if ((ds&(HTDS_ERR|HTDS_MOL)) != HTDS_MOL || 287*2926Swnj mbasr & MBAEBITS) { 288*2926Swnj htaddr->htcs1 = HT_DCLR|HT_GO; 289*2926Swnj if (bp == &rhtbuf[HTUNIT(bp->b_dev)]) 290*2926Swnj er &= ~HTER_FCE; 291*2926Swnj if (bp->b_flags & B_READ && ds & HTDS_PES) 292*2926Swnj er &= ~(HTER_CSITM|HTER_CORCRC); 293*2926Swnj if (er&HTER_HARD || 294*2926Swnj mbasr&MBAEBITS || (ds&HTDS_MOL) == 0 || 295*2926Swnj sc->sc_erreg && ++mi->mi_tab.b_errcnt >= 7) { 296*2926Swnj if ((ds & HTDS_MOL) == 0 && sc->sc_openf > 0) 297*2926Swnj sc->sc_openf = -1; 298*2926Swnj printf("ht%d: hard error bn%d mbasr=%b er=%b\n", 299*2926Swnj HTUNIT(bp->b_dev), bp->b_blkno, 300*2926Swnj mbasr, mbasr_bits, 301*2926Swnj MASKREG(htaddr->hter), HTER_BITS); 30222Sbill bp->b_flags |= B_ERROR; 303*2926Swnj return (MBD_DONE); 30422Sbill } 305*2926Swnj if (er) 306*2926Swnj return (MBD_RETRY); 30722Sbill } 308*2926Swnj bp->b_resid = 0; 309*2926Swnj if (bp->b_flags & B_READ) 310*2926Swnj if (ds&HTDS_TM) { /* must be a read, right? */ 311*2926Swnj bp->b_resid = bp->b_bcount; 312*2926Swnj sc->sc_nxrec = dbtofsb(bp->b_blkno); 313*2926Swnj } else if(bp->b_bcount > MASKREG(htaddr->htfc)) 314*2926Swnj bp->b_resid = bp->b_bcount - MASKREG(htaddr->htfc); 315*2926Swnj return (MBD_DONE); 316*2926Swnj } 31722Sbill 318*2926Swnj /* 319*2926Swnj * non-data-transfer interrupt 320*2926Swnj */ 321*2926Swnj htndtint(mi) 322*2926Swnj register struct mba_info *mi; 323*2926Swnj { 324*2926Swnj register struct htdevice *htaddr = (struct htdevice *)mi->mi_drv; 325*2926Swnj register struct buf *bp = mi->mi_tab.b_actf; 326*2926Swnj register struct ht_softc *sc; 327*2926Swnj int er, ds, fc; 32822Sbill 329*2926Swnj if (bp == NULL) 33022Sbill return; 331*2926Swnj sc = &ht_softc[HTUNIT(bp->b_dev)]; 332*2926Swnj ds = sc->sc_dsreg = MASKREG(htaddr->htds); 333*2926Swnj er = sc->sc_erreg = MASKREG(htaddr->hter); 334*2926Swnj sc->sc_resid = MASKREG(htaddr->htfc); 335*2926Swnj if (sc->sc_erreg) 336*2926Swnj htaddr->htcs1 = HT_DCLR|HT_GO; 337*2926Swnj if (bp == &chtbuf[HTUNIT(bp->b_dev)]) { 338*2926Swnj if (bp->b_command == HT_REWOFFL) 339*2926Swnj /* offline is on purpose; don't do anything special */ 340*2926Swnj ds |= HTDS_MOL; 341*2926Swnj else if (bp->b_resid == HT_SREV && 342*2926Swnj er == (HTER_NEF|HTER_FCE) && 343*2926Swnj ds&HTDS_BOT && bp->b_bcount == INF) 344*2926Swnj er &= ~HTER_NEF; 345*2926Swnj er &= ~HTER_FCE; 346*2926Swnj if (er == 0) 347*2926Swnj ds &= ~HTDS_ERR; 34822Sbill } 349*2926Swnj if ((ds & (HTDS_ERR|HTDS_MOL)) != HTDS_MOL) { 350*2926Swnj if ((ds & HTDS_MOL) == 0 && sc->sc_openf > 0) 351*2926Swnj sc->sc_openf = -1; 352*2926Swnj printf("ht%d: hard error bn%d er=%b ds=%b\n", 353*2926Swnj HTUNIT(bp->b_dev), bp->b_blkno, 354*2926Swnj sc->sc_erreg, HTER_BITS, sc->sc_dsreg, HTDS_BITS); 355*2926Swnj bp->b_flags |= B_ERROR; 356*2926Swnj return (MBN_DONE); 357*2926Swnj } 358*2926Swnj if (bp == &chtbuf[HTUNIT(bp->b_dev)]) { 359*2926Swnj if (sc->sc_flags & H_REWIND) 360*2926Swnj return (ds & HTDS_BOT ? MBN_DONE : MBN_RETRY); 361*2926Swnj bp->b_resid = -sc->sc_resid; 362*2926Swnj return (MBN_DONE); 363*2926Swnj } 364*2926Swnj if (ds & HTDS_TM) 365*2926Swnj if (sc->sc_blkno > dbtofsb(bp->b_blkno)) {/* reversing */ 366*2926Swnj sc->sc_nxrec = dbtofsb(bp->b_blkno) - fc; 367*2926Swnj sc->sc_blkno = sc->sc_nxrec; 368*2926Swnj } else { /* spacing forward */ 369*2926Swnj sc->sc_blkno = dbtofsb(bp->b_blkno) + fc; 370*2926Swnj sc->sc_nxrec = sc->sc_blkno - 1; 371*2926Swnj } 372*2926Swnj else 373*2926Swnj sc->sc_blkno = dbtofsb(bp->b_blkno); 374*2926Swnj return (MBN_RETRY); 37522Sbill } 37622Sbill 37722Sbill htread(dev) 378*2926Swnj dev_t dev; 37922Sbill { 380*2926Swnj 38122Sbill htphys(dev); 382*2926Swnj if (u.u_error) 383*2926Swnj return; 384*2926Swnj physio(htstrategy, &rhtbuf[HTUNIT(dev)], dev, B_READ, minphys); 38522Sbill } 38622Sbill 38722Sbill htwrite(dev) 38822Sbill { 389*2926Swnj 39022Sbill htphys(dev); 391*2926Swnj if (u.u_error) 392*2926Swnj return; 393*2926Swnj physio(htstrategy, &rhtbuf[HTUNIT(dev)], dev, B_WRITE, minphys); 39422Sbill } 39522Sbill 39622Sbill htphys(dev) 397*2926Swnj dev_t dev; 39822Sbill { 399*2926Swnj register int unit; 400*2926Swnj register struct ht_softc *sc; 40122Sbill daddr_t a; 40222Sbill 403*2926Swnj unit = HTUNIT(dev); 404*2926Swnj if (unit >= NHT) { 405*2926Swnj u.u_error = ENXIO; 406*2926Swnj return; 40722Sbill } 408*2926Swnj a = u.u_offset >> 9; 409*2926Swnj sc = &ht_softc[unit]; 410*2926Swnj sc->sc_blkno = dbtofsb(a); 411*2926Swnj sc->sc_nxrec = dbtofsb(a)+1; 41222Sbill } 4131917Swnj 414*2926Swnj /*ARGSUSED*/ 415*2926Swnj htioctl(dev, cmd, addr, flag) 416*2926Swnj dev_t dev; 417*2926Swnj int cmd; 418*2926Swnj caddr_t addr; 419*2926Swnj int flag; 420*2926Swnj { 421*2926Swnj register unit = HTUNIT(dev); 422*2926Swnj register struct ht_softc *sc = &ht_softc[unit]; 423*2926Swnj register struct buf *bp = &chtbuf[unit]; 424*2926Swnj register callcount; 425*2926Swnj int fcount; 426*2926Swnj struct mtop mtop; 427*2926Swnj struct mtget mtget; 428*2926Swnj /* we depend of the values and order of the MT codes here */ 429*2926Swnj static htops[] = 430*2926Swnj {HT_WEOF,HT_SFORW,HT_SREV,HT_SFORW,HT_SREV,HT_REW,HT_REWOFFL,HT_SENSE}; 4311917Swnj 432*2926Swnj switch (cmd) { 433*2926Swnj case MTIOCTOP: /* tape operation */ 434*2926Swnj if (copyin((caddr_t)addr, (caddr_t)&mtop, sizeof(mtop))) { 435*2926Swnj u.u_error = EFAULT; 436*2926Swnj return; 437*2926Swnj } 438*2926Swnj switch(mtop.mt_op) { 439*2926Swnj case MTWEOF: 440*2926Swnj callcount = mtop.mt_count; 441*2926Swnj fcount = 1; 442*2926Swnj break; 443*2926Swnj case MTFSF: case MTBSF: 444*2926Swnj callcount = mtop.mt_count; 445*2926Swnj fcount = INF; 446*2926Swnj break; 447*2926Swnj case MTFSR: case MTBSR: 448*2926Swnj callcount = 1; 449*2926Swnj fcount = mtop.mt_count; 450*2926Swnj break; 451*2926Swnj case MTREW: case MTOFFL: 452*2926Swnj callcount = 1; 453*2926Swnj fcount = 1; 454*2926Swnj break; 455*2926Swnj default: 456*2926Swnj u.u_error = ENXIO; 457*2926Swnj return; 458*2926Swnj } 459*2926Swnj if (callcount <= 0 || fcount <= 0) { 460*2926Swnj u.u_error = ENXIO; 461*2926Swnj return; 462*2926Swnj } 463*2926Swnj while (--callcount >= 0) { 464*2926Swnj htcommand(dev, htops[mtop.mt_op], fcount); 465*2926Swnj if ((mtop.mt_op == MTFSR || mtop.mt_op == MTBSR) && 466*2926Swnj bp->b_resid) { 467*2926Swnj u.u_error = EIO; 468*2926Swnj break; 469*2926Swnj } 470*2926Swnj if ((chtbuf[HTUNIT(bp->b_dev)].b_flags&B_ERROR) || 471*2926Swnj sc->sc_dsreg&HTDS_BOT) 472*2926Swnj break; 473*2926Swnj } 474*2926Swnj geterror(bp); 475*2926Swnj return; 476*2926Swnj case MTIOCGET: 477*2926Swnj mtget.mt_dsreg = sc->sc_dsreg; 478*2926Swnj mtget.mt_erreg = sc->sc_erreg; 479*2926Swnj mtget.mt_resid = sc->sc_resid; 480*2926Swnj if (copyout((caddr_t)&mtget, addr, sizeof(mtget))) 481*2926Swnj u.u_error = EFAULT; 482*2926Swnj return; 483*2926Swnj default: 484*2926Swnj u.u_error = ENXIO; 485*2926Swnj } 486*2926Swnj } 487*2926Swnj 4881917Swnj #define DBSIZE 20 4891917Swnj 490*2926Swnj htdump() 4911917Swnj { 492*2926Swnj register struct mba_info *mi; 493*2926Swnj register struct mba_regs *mp; 494*2926Swnj register struct htdevice *htaddr; 495*2926Swnj int blk, num; 496*2926Swnj int start; 4971917Swnj 498*2926Swnj start = 0; 499*2926Swnj num = maxfree; 500*2926Swnj #define phys(a,b) ((b)((int)(a)&0x7fffffff)) 501*2926Swnj if (htinfo[0] == 0) 502*2926Swnj return (ENXIO); 503*2926Swnj mi = phys(htinfo[0], struct mba_info *); 504*2926Swnj mp = phys(mi->mi_hd, struct mba_hd *)->mh_physmba; 505*2926Swnj #if VAX780 506*2926Swnj mbainit(mp); 507*2926Swnj htaddr = (struct htdevice *)&mp->mba_drv[mi->mi_drive]; 508*2926Swnj htaddr->httc = HTTC_PDP11|HTTC_1600BPI; 509*2926Swnj htaddr->htcs1 = HT_DCLR|HT_GO; 5101917Swnj while (num > 0) { 5111917Swnj blk = num > DBSIZE ? DBSIZE : num; 512*2926Swnj htdwrite(start, blk, htaddr, mp); 513*2926Swnj start += blk; 5141917Swnj num -= blk; 5151917Swnj } 516*2926Swnj htwait(htaddr); 517*2926Swnj htaddr->htcs1 = HT_REW|HT_GO; 518*2926Swnj hteof(htaddr); 519*2926Swnj hteof(htaddr); 5201917Swnj } 5211917Swnj 522*2926Swnj htdwrite(dbuf, num, htaddr, mp) 523*2926Swnj register dbuf, num; 524*2926Swnj register struct htdevice *htaddr; 525*2926Swnj struct mba_regs *mp; 5261917Swnj { 527*2926Swnj register struct pte *io; 5281917Swnj register int i; 5291917Swnj 530*2926Swnj htwait(htaddr); 531*2926Swnj io = mp->mba_map; 5321917Swnj for (i = 0; i < num; i++) 533*2926Swnj *(int *)io++ = dbuf++ | PG_V; 534*2926Swnj htaddr->htfc = -(num*NBPG); 535*2926Swnj mp->mba_sr = -1; 536*2926Swnj mp->mba_bcr = -(num*NBPG); 537*2926Swnj mp->mba_var = 0; 538*2926Swnj htaddr->htcs1 = HT_WCOM|HT_GO; 5391917Swnj } 5401917Swnj 541*2926Swnj htwait(htaddr) 542*2926Swnj struct htdevice *htaddr; 5431917Swnj { 5441917Swnj register s; 5451917Swnj 5461917Swnj do 547*2926Swnj s = htaddr->htds; 548*2926Swnj while ((s & HTDS_DRY) == 0); 5491917Swnj } 5501917Swnj 551*2926Swnj hteof(htaddr) 552*2926Swnj struct htdevice *htaddr; 5531917Swnj { 5541917Swnj 555*2926Swnj htwait(htaddr); 556*2926Swnj htaddr->htcs1 = HT_WEOF|HT_GO; 5571917Swnj } 5581563Sbill #endif 559