1*2471Swnj /* tm.c 4.12 02/17/81 */ 21919Swnj 31940Swnj #include "tm.h" 4*2471Swnj #if NTM03 > 0 51919Swnj /* 61919Swnj * TM tape driver 7*2471Swnj * 8*2471Swnj * THIS HANDLES ONLY ONE DRIVE ON ONE CONTROLER, AS WE HAVE NO 9*2471Swnj * WAY TO TEST MULTIPLE TRANSPORTS. 101919Swnj */ 11*2471Swnj #define DELAY(N) { register int d = N; while (--d > 0); } 121919Swnj #include "../h/param.h" 131919Swnj #include "../h/buf.h" 141919Swnj #include "../h/dir.h" 151919Swnj #include "../h/conf.h" 161919Swnj #include "../h/user.h" 171919Swnj #include "../h/file.h" 181919Swnj #include "../h/map.h" 191919Swnj #include "../h/pte.h" 201919Swnj #include "../h/uba.h" 211919Swnj #include "../h/mtio.h" 221919Swnj #include "../h/ioctl.h" 231919Swnj #include "../h/vm.h" 242363Swnj #include "../h/cmap.h" 252396Swnj #include "../h/cpu.h" 261919Swnj 272396Swnj #include "../h/tmreg.h" 281919Swnj 291919Swnj struct buf ctmbuf; 301919Swnj struct buf rtmbuf; 311919Swnj 322396Swnj int tmcntrlr(), tmslave(), tmdgo(), tmintr(); 33*2471Swnj struct uba_minfo *tmminfo[NTM03]; 34*2471Swnj struct uba_dinfo *tmdinfo[NTM11]; 352458Swnj u_short tmstd[] = { 0772520, 0 }; 362396Swnj struct uba_driver tmdriver = 372458Swnj { tmcntrlr, tmslave, tmdgo, 0, tmstd, "tm", tmdinfo, tmminfo }; 381919Swnj 391919Swnj /* bits in minor device */ 401919Swnj #define T_NOREWIND 04 411919Swnj #define T_1600BPI 08 421919Swnj 431919Swnj #define INF (daddr_t)1000000L 441919Swnj 45*2471Swnj struct tm_softc { 46*2471Swnj char sc_openf; 47*2471Swnj char sc_flags; 48*2471Swnj daddr_t sc_blkno; 49*2471Swnj daddr_t sc_nxrec; 50*2471Swnj u_short sc_erreg; 51*2471Swnj u_short sc_dsreg; 52*2471Swnj short sc_resid; 53*2471Swnj int sc_ubinfo; 54*2471Swnj } tm_softc[NTM03]; 551919Swnj 561919Swnj #define SSEEK 1 /* seeking */ 571919Swnj #define SIO 2 /* doing seq i/o */ 581919Swnj #define SCOM 3 /* sending control command */ 591919Swnj 601919Swnj #define LASTIOW 1 /* last op was a write */ 611919Swnj #define WAITREW 2 /* someone is waiting for a rewind */ 621919Swnj 632426Skre /* 642426Skre * Determine if there is a controller for 652426Skre * a tm at address reg. Our goal is to make the 662426Skre * device interrupt. 672426Skre */ 682458Swnj tmcntrlr(um, reg) 692458Swnj struct uba_minfo *um; 702396Swnj caddr_t reg; 712396Swnj { 722458Swnj register int br, cvec; 732426Skre 742396Swnj ((struct device *)reg)->tmcs = IENABLE; 752396Swnj /* 762396Swnj * If this is a tm03/tc11, it ought to have interrupted 772396Swnj * by now, if it isn't (ie: it is a ts04) then we just 782458Swnj * hope that it didn't interrupt, so autoconf will ignore it. 792458Swnj * Just in case, we will reference one 802396Swnj * of the more distant registers, and hope for a machine 812458Swnj * check, or similar disaster if this is a ts. 82*2471Swnj * 83*2471Swnj * Note: on an 11/780, badaddr will just generate 84*2471Swnj * a uba error for a ts; but our caller will notice that 85*2471Swnj * so we won't check for it. 862396Swnj */ 872396Swnj if (badaddr(&((struct device *)reg)->tmrd, 2)) 882458Swnj return (0); 892458Swnj return (1); 902396Swnj } 912396Swnj 922396Swnj tmslave(ui, reg, slaveno) 932396Swnj struct uba_dinfo *ui; 942396Swnj caddr_t reg; 952396Swnj { 962458Swnj 972396Swnj /* 982396Swnj * Due to a design flaw, we cannot ascertain if the tape 992396Swnj * exists or not unless it is on line - ie: unless a tape is 1002396Swnj * mounted. This is too servere a restriction to bear. 1012396Swnj * As we can only handle one tape, we might just as well insist 1022396Swnj * that it be slave #0, and just assume that it exists. 1032396Swnj * Something better will have to be done if you have two 1042396Swnj * tapes on one controller, or two controllers 1052396Swnj */ 1062458Swnj if (slaveno != 0 || tmdinfo[0]) 1072396Swnj return(0); 1082458Swnj return (1); 1092396Swnj } 1102396Swnj 1111919Swnj tmopen(dev, flag) 1121919Swnj dev_t dev; 1131919Swnj int flag; 1141919Swnj { 1151919Swnj register ds, unit; 1162396Swnj register struct uba_dinfo *ui; 117*2471Swnj register struct tm_softc *sc = &tm_softc[0]; 1181919Swnj 1192458Swnj tmminfo[0]->um_tab.b_flags |= B_TAPE; 1201919Swnj unit = minor(dev)&03; 121*2471Swnj if (unit>=NTM11 || sc->sc_openf || (ui = tmdinfo[0]) == 0 || ui->ui_alive==0) { 1221919Swnj u.u_error = ENXIO; /* out of range or open */ 1231919Swnj return; 1241919Swnj } 1251919Swnj tcommand(dev, NOP, 1); 126*2471Swnj if ((sc->sc_erreg&SELR) == 0) { 127*2471Swnj u.u_error = EIO; 128*2471Swnj goto eio; 1291919Swnj } 130*2471Swnj sc->sc_openf = 1; 131*2471Swnj if (sc->sc_erreg&RWS) 1321919Swnj tmwaitrws(dev); /* wait for rewind complete */ 133*2471Swnj while (sc->sc_erreg&SDWN) 1341919Swnj tcommand(dev, NOP, 1); /* await settle down */ 135*2471Swnj if ((sc->sc_erreg&TUR)==0 || 136*2471Swnj ((flag&(FREAD|FWRITE)) == FWRITE && (sc->sc_erreg&WRL))) { 1372396Swnj ((struct device *)ui->ui_addr)->tmcs = DCLR|GO; 1381919Swnj u.u_error = EIO; /* offline or write protect */ 1391919Swnj } 1401919Swnj if (u.u_error != 0) { 141*2471Swnj sc->sc_openf = 0; 142*2471Swnj if (u.u_error == EIO) 143*2471Swnj eio: 144*2471Swnj uprintf("tape offline or protected\n"); 1451919Swnj return; 1461919Swnj } 147*2471Swnj sc->sc_blkno = (daddr_t)0; 148*2471Swnj sc->sc_nxrec = INF; 149*2471Swnj sc->sc_flags = 0; 150*2471Swnj sc->sc_openf = 1; 1511919Swnj } 1521919Swnj 1531919Swnj tmwaitrws(dev) 1541919Swnj register dev; 1551919Swnj { 1562396Swnj register struct device *addr = 157*2471Swnj (struct device *)tmdinfo[0]->ui_addr; 158*2471Swnj register struct tm_softc *sc = &tm_softc[0]; 1591919Swnj 1601919Swnj spl5(); 1611919Swnj for (;;) { 1622396Swnj if ((addr->tmer&RWS) == 0) { 1631919Swnj spl0(); /* rewind complete */ 1641919Swnj return; 1651919Swnj } 166*2471Swnj sc->sc_flags |= WAITREW; 167*2471Swnj sleep((caddr_t)&sc->sc_flags, PRIBIO); 1681919Swnj } 1691919Swnj } 1701919Swnj 1711919Swnj tmclose(dev, flag) 1721919Swnj register dev_t dev; 1731919Swnj register flag; 1741919Swnj { 175*2471Swnj register struct tm_softc *sc = &tm_softc[0]; 1761919Swnj 177*2471Swnj if (flag == FWRITE || ((flag&FWRITE) && (sc->sc_flags&LASTIOW))) { 1781919Swnj tcommand(dev, WEOF, 1); 1791919Swnj tcommand(dev, WEOF, 1); 1801919Swnj tcommand(dev, SREV, 1); 1811919Swnj } 1821919Swnj if ((minor(dev)&T_NOREWIND) == 0) 1831919Swnj tcommand(dev, REW, 1); 184*2471Swnj sc->sc_openf = 0; 1851919Swnj } 1861919Swnj 1871919Swnj tcommand(dev, com, count) 1881919Swnj dev_t dev; 1891919Swnj int com, count; 1901919Swnj { 1911919Swnj register struct buf *bp; 1921919Swnj 1931919Swnj bp = &ctmbuf; 1941919Swnj (void) spl5(); 1951919Swnj while (bp->b_flags&B_BUSY) { 1961919Swnj bp->b_flags |= B_WANTED; 1971919Swnj sleep((caddr_t)bp, PRIBIO); 1981919Swnj } 1991919Swnj bp->b_flags = B_BUSY|B_READ; 2001919Swnj (void) spl0(); 2011919Swnj bp->b_dev = dev; 2021919Swnj bp->b_repcnt = -count; 2031919Swnj bp->b_command = com; 2041919Swnj bp->b_blkno = 0; 2051919Swnj tmstrategy(bp); 2061919Swnj iowait(bp); 2071919Swnj if (bp->b_flags&B_WANTED) 2081919Swnj wakeup((caddr_t)bp); 2091919Swnj bp->b_flags &= B_ERROR; 2101919Swnj } 2111919Swnj 2121919Swnj tmstrategy(bp) 2131919Swnj register struct buf *bp; 2141919Swnj { 2151919Swnj register daddr_t *p; 2162458Swnj register struct buf *tmi; 2171919Swnj 2181928Swnj tmwaitrws(bp->b_dev); 2191919Swnj if (bp != &ctmbuf) { 220*2471Swnj p = &tm_softc[0].sc_nxrec; 2211919Swnj if (dbtofsb(bp->b_blkno) > *p) { 2221919Swnj bp->b_flags |= B_ERROR; 2231919Swnj bp->b_error = ENXIO; /* past EOF */ 2241919Swnj iodone(bp); 2251919Swnj return; 2261919Swnj } else if (dbtofsb(bp->b_blkno) == *p && bp->b_flags&B_READ) { 2271919Swnj bp->b_resid = bp->b_bcount; 2281919Swnj clrbuf(bp); /* at EOF */ 2291919Swnj iodone(bp); 2301919Swnj return; 2311919Swnj } else if ((bp->b_flags&B_READ) == 0) 2321919Swnj *p = dbtofsb(bp->b_blkno) + 1; /* write sets EOF */ 2331919Swnj } 2341919Swnj bp->av_forw = NULL; 2351919Swnj (void) spl5(); 2362458Swnj tmi = &tmminfo[0]->um_tab; 2372458Swnj if (tmi->b_actf == NULL) 2382458Swnj tmi->b_actf = bp; 2391919Swnj else 2402458Swnj tmi->b_actl->av_forw = bp; 2412458Swnj tmi->b_actl = bp; 2422458Swnj if (tmi->b_active == 0) 2431919Swnj tmstart(); 2441919Swnj (void) spl0(); 2451919Swnj } 2461919Swnj 2471919Swnj tmstart() 2481919Swnj { 2491919Swnj register struct buf *bp; 250*2471Swnj register struct uba_minfo *um = tmminfo[0]; 2512396Swnj register struct uba_dinfo *ui; 2522396Swnj register struct device *addr; 253*2471Swnj register struct tm_softc *sc = &tm_softc[0]; 254*2471Swnj int cmd, s; 255*2471Swnj daddr_t blkno; 2561919Swnj 2571919Swnj loop: 258*2471Swnj if ((bp = um->um_tab.b_actf) == 0) 2591919Swnj return; 260*2471Swnj ui = tmdinfo[0]; 2612396Swnj addr = (struct device *)ui->ui_addr; 262*2471Swnj sc->sc_dsreg = addr->tmcs; 263*2471Swnj sc->sc_erreg = addr->tmer; 264*2471Swnj sc->sc_resid = addr->tmbc; 265*2471Swnj sc->sc_flags &= ~LASTIOW; 266*2471Swnj if (sc->sc_openf < 0 || (addr->tmcs&CUR) == 0) { 267*2471Swnj /* sc->sc_openf = -1; ??? */ 2681919Swnj bp->b_flags |= B_ERROR; /* hard error'ed or !SELR */ 2691919Swnj goto next; 2701919Swnj } 2711919Swnj cmd = IENABLE | GO; 2721919Swnj if ((minor(bp->b_dev) & T_1600BPI) == 0) 2731919Swnj cmd |= D800; 2741919Swnj if (bp == &ctmbuf) { 2751919Swnj if (bp->b_command == NOP) 2761919Swnj goto next; /* just get status */ 2771919Swnj else { 2781919Swnj cmd |= bp->b_command; 279*2471Swnj um->um_tab.b_active = SCOM; 2801919Swnj if (bp->b_command == SFORW || bp->b_command == SREV) 2812396Swnj addr->tmbc = bp->b_repcnt; 2822396Swnj addr->tmcs = cmd; 2831919Swnj return; 2841919Swnj } 2851919Swnj } 286*2471Swnj if ((blkno = sc->sc_blkno) == dbtofsb(bp->b_blkno)) { 2872396Swnj addr->tmbc = -bp->b_bcount; 2882054Swnj s = spl6(); 289*2471Swnj if (sc->sc_ubinfo == 0) 290*2471Swnj sc->sc_ubinfo = ubasetup(ui->ui_ubanum, bp, 1); 2912054Swnj splx(s); 2921919Swnj if ((bp->b_flags&B_READ) == 0) { 293*2471Swnj if (um->um_tab.b_errcnt) 2941919Swnj cmd |= WIRG; 2951919Swnj else 2961919Swnj cmd |= WCOM; 2971919Swnj } else 2981919Swnj cmd |= RCOM; 299*2471Swnj cmd |= (sc->sc_ubinfo >> 12) & 0x30; 300*2471Swnj um->um_tab.b_active = SIO; 301*2471Swnj addr->tmba = sc->sc_ubinfo; 3022396Swnj addr->tmcs = cmd; 3031919Swnj return; 3041919Swnj } 305*2471Swnj um->um_tab.b_active = SSEEK; 3061919Swnj if (blkno < dbtofsb(bp->b_blkno)) { 3071919Swnj cmd |= SFORW; 3082396Swnj addr->tmbc = blkno - dbtofsb(bp->b_blkno); 3091919Swnj } else { 3101919Swnj cmd |= SREV; 3112396Swnj addr->tmbc = dbtofsb(bp->b_blkno) - blkno; 3121919Swnj } 3132396Swnj addr->tmcs = cmd; 3141919Swnj return; 3151919Swnj 3161919Swnj next: 317*2471Swnj ubarelse(ui->ui_ubanum, &sc->sc_ubinfo); 318*2471Swnj um->um_tab.b_actf = bp->av_forw; 3191919Swnj iodone(bp); 3201919Swnj goto loop; 3211919Swnj } 3221919Swnj 3232396Swnj tmdgo() 3241919Swnj { 325*2471Swnj 3262396Swnj } 3272396Swnj 328*2471Swnj /*ARGSUSED*/ 3292396Swnj tmintr(d) 330*2471Swnj int d; 3312396Swnj { 3321919Swnj register struct buf *bp; 333*2471Swnj register struct uba_minfo *um = tmminfo[0]; 334*2471Swnj register struct device *addr = (struct device *)tmdinfo[0]->ui_addr; 335*2471Swnj register struct tm_softc *sc = &tm_softc[0]; 3361919Swnj register state; 3371919Swnj 338*2471Swnj if (sc->sc_flags&WAITREW && (addr->tmer&RWS) == 0) { 339*2471Swnj sc->sc_flags &= ~WAITREW; 340*2471Swnj wakeup((caddr_t)&sc->sc_flags); 3411919Swnj } 342*2471Swnj if ((bp = um->um_tab.b_actf) == NULL) 3431919Swnj return; 344*2471Swnj sc->sc_dsreg = addr->tmcs; 345*2471Swnj sc->sc_erreg = addr->tmer; 346*2471Swnj sc->sc_resid = addr->tmbc; 3471919Swnj if ((bp->b_flags & B_READ) == 0) 348*2471Swnj sc->sc_flags |= LASTIOW; 349*2471Swnj state = um->um_tab.b_active; 350*2471Swnj um->um_tab.b_active = 0; 3512396Swnj if (addr->tmcs&ERROR) { 3522396Swnj while(addr->tmer & SDWN) 3531919Swnj ; /* await settle down */ 3542396Swnj if (addr->tmer&EOF) { 3551919Swnj tmseteof(bp); /* set blkno and nxrec */ 3561919Swnj state = SCOM; 3572396Swnj addr->tmbc = -bp->b_bcount; 3581919Swnj goto errout; 3591919Swnj } 3602396Swnj if ((bp->b_flags&B_READ) && (addr->tmer&(HARD|SOFT)) == RLE) 3611919Swnj goto out; 3622396Swnj if ((addr->tmer&HARD)==0 && state==SIO) { 363*2471Swnj if (++um->um_tab.b_errcnt < 7) { 3642396Swnj if((addr->tmer&SOFT) == NXM) 3651919Swnj printf("TM UBA late error\n"); 366*2471Swnj sc->sc_blkno++; 367*2471Swnj ubarelse(um->um_ubanum, &sc->sc_ubinfo); 3681919Swnj tmstart(); 3691919Swnj return; 3701919Swnj } 371*2471Swnj } else if (sc->sc_openf>0 && bp != &rtmbuf) 372*2471Swnj sc->sc_openf = -1; 373*2471Swnj deverror(bp, sc->sc_erreg, sc->sc_dsreg); 3741919Swnj bp->b_flags |= B_ERROR; 3751919Swnj state = SIO; 3761919Swnj } 3771919Swnj out: 3781919Swnj switch (state) { 3791919Swnj 3801919Swnj case SIO: 381*2471Swnj sc->sc_blkno++; 3821919Swnj /* fall into ... */ 3831919Swnj 3841919Swnj case SCOM: 3851919Swnj if (bp == &ctmbuf) { 3861919Swnj switch (bp->b_command) { 3871919Swnj case SFORW: 388*2471Swnj sc->sc_blkno -= bp->b_repcnt; 3891919Swnj break; 3901919Swnj 3911919Swnj case SREV: 392*2471Swnj sc->sc_blkno += bp->b_repcnt; 3931919Swnj break; 3941919Swnj 3951919Swnj default: 3961919Swnj if (++bp->b_repcnt < 0) { 3971919Swnj tmstart(); /* continue */ 3981919Swnj return; 3991919Swnj } 4001919Swnj } 4011919Swnj } 4021919Swnj errout: 403*2471Swnj um->um_tab.b_errcnt = 0; 404*2471Swnj um->um_tab.b_actf = bp->av_forw; 4052396Swnj bp->b_resid = -addr->tmbc; 406*2471Swnj ubarelse(um->um_ubanum, &sc->sc_ubinfo); 4071919Swnj iodone(bp); 4081919Swnj break; 4091919Swnj 4101919Swnj case SSEEK: 411*2471Swnj sc->sc_blkno = dbtofsb(bp->b_blkno); 4121919Swnj break; 4131919Swnj 4141919Swnj default: 4151919Swnj return; 4161919Swnj } 4171919Swnj tmstart(); 4181919Swnj } 4191919Swnj 4201919Swnj tmseteof(bp) 4211919Swnj register struct buf *bp; 4221919Swnj { 4232396Swnj register struct device *addr = 424*2471Swnj (struct device *)tmdinfo[0]->ui_addr; 425*2471Swnj register struct tm_softc *sc = &tm_softc[0]; 4261919Swnj 4271919Swnj if (bp == &ctmbuf) { 428*2471Swnj if (sc->sc_blkno > dbtofsb(bp->b_blkno)) { 4291919Swnj /* reversing */ 430*2471Swnj sc->sc_nxrec = dbtofsb(bp->b_blkno) - addr->tmbc; 431*2471Swnj sc->sc_blkno = sc->sc_nxrec; 4321919Swnj } else { 4331919Swnj /* spacing forward */ 434*2471Swnj sc->sc_blkno = dbtofsb(bp->b_blkno) + addr->tmbc; 435*2471Swnj sc->sc_nxrec = sc->sc_blkno - 1; 4361919Swnj } 4371919Swnj return; 4381919Swnj } 4391919Swnj /* eof on read */ 440*2471Swnj sc->sc_nxrec = dbtofsb(bp->b_blkno); 4411919Swnj } 4421919Swnj 4431919Swnj tmread(dev) 4441919Swnj { 4451919Swnj 4461919Swnj tmphys(dev); 4471919Swnj physio(tmstrategy, &rtmbuf, dev, B_READ, minphys); 4481919Swnj } 4491919Swnj 4501919Swnj tmwrite(dev) 4511919Swnj { 4521919Swnj 4531919Swnj tmphys(dev); 4541919Swnj physio(tmstrategy, &rtmbuf, dev, B_WRITE, minphys); 4551919Swnj } 4561919Swnj 4571919Swnj tmphys(dev) 4581919Swnj { 4591919Swnj register daddr_t a; 460*2471Swnj register struct tm_softc *sc = &tm_softc[0]; 4611919Swnj 4621919Swnj a = dbtofsb(u.u_offset >> 9); 463*2471Swnj sc->sc_blkno = a; 464*2471Swnj sc->sc_nxrec = a + 1; 4651919Swnj } 4661919Swnj 4671919Swnj /*ARGSUSED*/ 4681919Swnj tmioctl(dev, cmd, addr, flag) 4691919Swnj caddr_t addr; 4701919Swnj dev_t dev; 4711919Swnj { 4721919Swnj register callcount; 473*2471Swnj register struct tm_softc *sc = &tm_softc[0]; 4741919Swnj int fcount; 4751919Swnj struct mtop mtop; 4761919Swnj struct mtget mtget; 4771919Swnj /* we depend of the values and order of the MT codes here */ 4782324Skre static tmops[] = {WEOF, SFORW, SREV, SFORW, SREV, REW, OFFL, NOP}; 4791919Swnj 4801919Swnj switch(cmd) { 4811919Swnj case MTIOCTOP: /* tape operation */ 4821919Swnj if (copyin((caddr_t)addr, (caddr_t)&mtop, sizeof(mtop))) { 4831919Swnj u.u_error = EFAULT; 4841919Swnj return; 4851919Swnj } 4861919Swnj switch(mtop.mt_op) { 4871919Swnj case MTWEOF: case MTFSF: case MTBSF: 4881919Swnj callcount = mtop.mt_count; 4891919Swnj fcount = INF; 4901919Swnj break; 4911919Swnj case MTFSR: case MTBSR: 4921919Swnj callcount = 1; 4931919Swnj fcount = mtop.mt_count; 4941919Swnj break; 4952324Skre case MTREW: case MTOFFL: case MTNOP: 4961919Swnj callcount = 1; 4971919Swnj fcount = 1; 4981919Swnj break; 4991919Swnj default: 5001919Swnj u.u_error = ENXIO; 5011919Swnj return; 5021919Swnj } 5031919Swnj if (callcount <= 0 || fcount <= 0) 5041919Swnj u.u_error = ENXIO; 5051919Swnj else while (--callcount >= 0) { 5061919Swnj tcommand(dev, tmops[mtop.mt_op], fcount); 5071919Swnj if ((mtop.mt_op == MTFSR || mtop.mt_op == MTBSR) && 5081919Swnj ctmbuf.b_resid) { 5091919Swnj u.u_error = EIO; 5101919Swnj break; 5111919Swnj } 512*2471Swnj if ((ctmbuf.b_flags&B_ERROR) || 513*2471Swnj sc->sc_erreg&BOT) 5141919Swnj break; 5151919Swnj } 5161919Swnj geterror(&ctmbuf); 5171919Swnj return; 5181919Swnj case MTIOCGET: 519*2471Swnj mtget.mt_dsreg = sc->sc_dsreg; 520*2471Swnj mtget.mt_erreg = sc->sc_erreg; 521*2471Swnj mtget.mt_resid = sc->sc_resid; 5221919Swnj if (copyout((caddr_t)&mtget, addr, sizeof(mtget))) 5231919Swnj u.u_error = EFAULT; 5241919Swnj return; 5251919Swnj default: 5261919Swnj u.u_error = ENXIO; 5271919Swnj } 5281919Swnj } 5291919Swnj 5301919Swnj #define DBSIZE 20 5311919Swnj 5322363Swnj tmdump() 5332363Swnj { 5342396Swnj register struct uba_dinfo *ui; 5352396Swnj register struct uba_regs *up; 5362396Swnj register struct device *addr; 5372426Skre int blk, num; 5382426Skre int start; 5391919Swnj 5402426Skre start = 0; 5412426Skre num = maxfree; 5422426Skre #define phys(a,b) ((b)((int)(a)&0x7fffffff)) 5432458Swnj if (tmdinfo[0] == 0) { 5442396Swnj printf("dna\n"); 5452396Swnj return (-1); 5462396Swnj } 5472458Swnj ui = phys(tmdinfo[0], struct uba_dinfo *); 5482396Swnj up = phys(ui->ui_hd, struct uba_hd *)->uh_physuba; 5492396Swnj #if VAX780 5502396Swnj if (cpu == VAX_780) 5512396Swnj ubainit(up); 5521919Swnj #endif 5532324Skre DELAY(1000000); 5542396Swnj addr = (struct device *)ui->ui_physaddr; 5552396Swnj tmwait(addr); 5562396Swnj addr->tmcs = DCLR | GO; 5571919Swnj while (num > 0) { 5581919Swnj blk = num > DBSIZE ? DBSIZE : num; 5592396Swnj tmdwrite(start, blk, addr, up); 5601919Swnj start += blk; 5611919Swnj num -= blk; 5621919Swnj } 5632426Skre tmeof(addr); 5642426Skre tmeof(addr); 5652426Skre tmwait(addr); 566*2471Swnj addr->tmcs = REW | GO; 567*2471Swnj tmwait(addr); 5682363Swnj return (0); 5691919Swnj } 5701919Swnj 5712396Swnj tmdwrite(buf, num, addr, up) 5722396Swnj register buf, num; 5732396Swnj register struct device *addr; 5742396Swnj struct uba_regs *up; 5751919Swnj { 5762396Swnj register struct pte *io; 5772396Swnj register int npf; 5781928Swnj 5792396Swnj tmwait(addr); 5802396Swnj io = up->uba_map; 5811919Swnj npf = num+1; 5821928Swnj while (--npf != 0) 5832396Swnj *(int *)io++ = (buf++ | (1<<UBA_DPSHIFT) | UBA_MRV); 5842396Swnj *(int *)io = 0; 5852396Swnj addr->tmbc = -(num*NBPG); 5862396Swnj addr->tmba = 0; 5872396Swnj addr->tmcs = WCOM | GO; 5881919Swnj } 5891919Swnj 5902396Swnj tmwait(addr) 5912396Swnj register struct device *addr; 5921919Swnj { 5931928Swnj register s; 5941919Swnj 5951919Swnj do 5962396Swnj s = addr->tmcs; 5971919Swnj while ((s & CUR) == 0); 5981919Swnj } 5991919Swnj 6002396Swnj tmeof(addr) 6012396Swnj struct device *addr; 6021919Swnj { 6031919Swnj 6042396Swnj tmwait(addr); 6052396Swnj addr->tmcs = WEOF | GO; 6061919Swnj } 6071919Swnj #endif 608