1*2574Swnj /* tm.c 4.13 02/19/81 */ 21919Swnj 31940Swnj #include "tm.h" 42471Swnj #if NTM03 > 0 51919Swnj /* 61919Swnj * TM tape driver 72471Swnj * 82471Swnj * THIS HANDLES ONLY ONE DRIVE ON ONE CONTROLER, AS WE HAVE NO 92471Swnj * WAY TO TEST MULTIPLE TRANSPORTS. 101919Swnj */ 112471Swnj #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" 20*2574Swnj #include "../h/vm.h" 211919Swnj #include "../h/uba.h" 221919Swnj #include "../h/mtio.h" 231919Swnj #include "../h/ioctl.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(); 332471Swnj struct uba_minfo *tmminfo[NTM03]; 342471Swnj struct uba_dinfo *tmdinfo[NTM11]; 352458Swnj u_short tmstd[] = { 0772520, 0 }; 362396Swnj struct uba_driver tmdriver = 37*2574Swnj { tmcntrlr, tmslave, tmdgo, 0, tmstd, "mt", tmdinfo, "tm", 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 452471Swnj struct tm_softc { 462471Swnj char sc_openf; 472471Swnj char sc_flags; 482471Swnj daddr_t sc_blkno; 492471Swnj daddr_t sc_nxrec; 502471Swnj u_short sc_erreg; 512471Swnj u_short sc_dsreg; 522471Swnj short sc_resid; 532471Swnj } tm_softc[NTM03]; 541919Swnj 551919Swnj #define SSEEK 1 /* seeking */ 561919Swnj #define SIO 2 /* doing seq i/o */ 571919Swnj #define SCOM 3 /* sending control command */ 581919Swnj 591919Swnj #define LASTIOW 1 /* last op was a write */ 601919Swnj #define WAITREW 2 /* someone is waiting for a rewind */ 611919Swnj 622426Skre /* 632426Skre * Determine if there is a controller for 642426Skre * a tm at address reg. Our goal is to make the 652426Skre * device interrupt. 662426Skre */ 672458Swnj tmcntrlr(um, reg) 682458Swnj struct uba_minfo *um; 692396Swnj caddr_t reg; 702396Swnj { 712458Swnj register int br, cvec; 722426Skre 732396Swnj ((struct device *)reg)->tmcs = IENABLE; 742396Swnj /* 752396Swnj * If this is a tm03/tc11, it ought to have interrupted 762396Swnj * by now, if it isn't (ie: it is a ts04) then we just 772458Swnj * hope that it didn't interrupt, so autoconf will ignore it. 782458Swnj * Just in case, we will reference one 792396Swnj * of the more distant registers, and hope for a machine 802458Swnj * check, or similar disaster if this is a ts. 812471Swnj * 822471Swnj * Note: on an 11/780, badaddr will just generate 832471Swnj * a uba error for a ts; but our caller will notice that 842471Swnj * so we won't check for it. 852396Swnj */ 862396Swnj if (badaddr(&((struct device *)reg)->tmrd, 2)) 872458Swnj return (0); 882458Swnj return (1); 892396Swnj } 902396Swnj 91*2574Swnj tmslave(ui, reg) 922396Swnj struct uba_dinfo *ui; 932396Swnj caddr_t reg; 942396Swnj { 952458Swnj 962396Swnj /* 972396Swnj * Due to a design flaw, we cannot ascertain if the tape 982396Swnj * exists or not unless it is on line - ie: unless a tape is 992396Swnj * mounted. This is too servere a restriction to bear. 1002396Swnj * As we can only handle one tape, we might just as well insist 1012396Swnj * that it be slave #0, and just assume that it exists. 1022396Swnj * Something better will have to be done if you have two 1032396Swnj * tapes on one controller, or two controllers 1042396Swnj */ 105*2574Swnj if (ui->ui_slave != 0 || tmdinfo[0]) 1062396Swnj return(0); 1072458Swnj return (1); 1082396Swnj } 1092396Swnj 1101919Swnj tmopen(dev, flag) 1111919Swnj dev_t dev; 1121919Swnj int flag; 1131919Swnj { 1141919Swnj register ds, unit; 1152396Swnj register struct uba_dinfo *ui; 1162471Swnj register struct tm_softc *sc = &tm_softc[0]; 1171919Swnj 1182458Swnj tmminfo[0]->um_tab.b_flags |= B_TAPE; 1191919Swnj unit = minor(dev)&03; 1202471Swnj if (unit>=NTM11 || sc->sc_openf || (ui = tmdinfo[0]) == 0 || ui->ui_alive==0) { 1211919Swnj u.u_error = ENXIO; /* out of range or open */ 1221919Swnj return; 1231919Swnj } 124*2574Swnj tmcommand(dev, NOP, 1); 1252471Swnj if ((sc->sc_erreg&SELR) == 0) { 1262471Swnj u.u_error = EIO; 1272471Swnj goto eio; 1281919Swnj } 1292471Swnj sc->sc_openf = 1; 1302471Swnj if (sc->sc_erreg&RWS) 1311919Swnj tmwaitrws(dev); /* wait for rewind complete */ 1322471Swnj while (sc->sc_erreg&SDWN) 133*2574Swnj tmcommand(dev, NOP, 1); /* await settle down */ 1342471Swnj if ((sc->sc_erreg&TUR)==0 || 1352471Swnj ((flag&(FREAD|FWRITE)) == FWRITE && (sc->sc_erreg&WRL))) { 1362396Swnj ((struct device *)ui->ui_addr)->tmcs = DCLR|GO; 1371919Swnj u.u_error = EIO; /* offline or write protect */ 1381919Swnj } 1391919Swnj if (u.u_error != 0) { 1402471Swnj sc->sc_openf = 0; 1412471Swnj if (u.u_error == EIO) 1422471Swnj eio: 1432471Swnj uprintf("tape offline or protected\n"); 1441919Swnj return; 1451919Swnj } 1462471Swnj sc->sc_blkno = (daddr_t)0; 1472471Swnj sc->sc_nxrec = INF; 1482471Swnj sc->sc_flags = 0; 1492471Swnj sc->sc_openf = 1; 1501919Swnj } 1511919Swnj 1521919Swnj tmwaitrws(dev) 1531919Swnj register dev; 1541919Swnj { 1552396Swnj register struct device *addr = 1562471Swnj (struct device *)tmdinfo[0]->ui_addr; 1572471Swnj register struct tm_softc *sc = &tm_softc[0]; 1581919Swnj 1591919Swnj spl5(); 1601919Swnj for (;;) { 1612396Swnj if ((addr->tmer&RWS) == 0) { 1621919Swnj spl0(); /* rewind complete */ 1631919Swnj return; 1641919Swnj } 1652471Swnj sc->sc_flags |= WAITREW; 1662471Swnj sleep((caddr_t)&sc->sc_flags, PRIBIO); 1671919Swnj } 1681919Swnj } 1691919Swnj 1701919Swnj tmclose(dev, flag) 1711919Swnj register dev_t dev; 1721919Swnj register flag; 1731919Swnj { 1742471Swnj register struct tm_softc *sc = &tm_softc[0]; 1751919Swnj 1762471Swnj if (flag == FWRITE || ((flag&FWRITE) && (sc->sc_flags&LASTIOW))) { 177*2574Swnj tmcommand(dev, WEOF, 1); 178*2574Swnj tmcommand(dev, WEOF, 1); 179*2574Swnj tmcommand(dev, SREV, 1); 1801919Swnj } 1811919Swnj if ((minor(dev)&T_NOREWIND) == 0) 182*2574Swnj tmcommand(dev, REW, 1); 1832471Swnj sc->sc_openf = 0; 1841919Swnj } 1851919Swnj 186*2574Swnj tmcommand(dev, com, count) 1871919Swnj dev_t dev; 1881919Swnj int com, count; 1891919Swnj { 1901919Swnj register struct buf *bp; 1911919Swnj 1921919Swnj bp = &ctmbuf; 1931919Swnj (void) spl5(); 1941919Swnj while (bp->b_flags&B_BUSY) { 1951919Swnj bp->b_flags |= B_WANTED; 1961919Swnj sleep((caddr_t)bp, PRIBIO); 1971919Swnj } 1981919Swnj bp->b_flags = B_BUSY|B_READ; 1991919Swnj (void) spl0(); 2001919Swnj bp->b_dev = dev; 2011919Swnj bp->b_repcnt = -count; 2021919Swnj bp->b_command = com; 2031919Swnj bp->b_blkno = 0; 2041919Swnj tmstrategy(bp); 2051919Swnj iowait(bp); 2061919Swnj if (bp->b_flags&B_WANTED) 2071919Swnj wakeup((caddr_t)bp); 2081919Swnj bp->b_flags &= B_ERROR; 2091919Swnj } 2101919Swnj 2111919Swnj tmstrategy(bp) 2121919Swnj register struct buf *bp; 2131919Swnj { 2141919Swnj register daddr_t *p; 2152458Swnj register struct buf *tmi; 2161919Swnj 2171928Swnj tmwaitrws(bp->b_dev); 2181919Swnj if (bp != &ctmbuf) { 2192471Swnj p = &tm_softc[0].sc_nxrec; 2201919Swnj if (dbtofsb(bp->b_blkno) > *p) { 2211919Swnj bp->b_flags |= B_ERROR; 2221919Swnj bp->b_error = ENXIO; /* past EOF */ 2231919Swnj iodone(bp); 2241919Swnj return; 2251919Swnj } else if (dbtofsb(bp->b_blkno) == *p && bp->b_flags&B_READ) { 2261919Swnj bp->b_resid = bp->b_bcount; 2271919Swnj clrbuf(bp); /* at EOF */ 2281919Swnj iodone(bp); 2291919Swnj return; 2301919Swnj } else if ((bp->b_flags&B_READ) == 0) 2311919Swnj *p = dbtofsb(bp->b_blkno) + 1; /* write sets EOF */ 2321919Swnj } 2331919Swnj bp->av_forw = NULL; 2341919Swnj (void) spl5(); 2352458Swnj tmi = &tmminfo[0]->um_tab; 2362458Swnj if (tmi->b_actf == NULL) 2372458Swnj tmi->b_actf = bp; 2381919Swnj else 2392458Swnj tmi->b_actl->av_forw = bp; 2402458Swnj tmi->b_actl = bp; 2412458Swnj if (tmi->b_active == 0) 2421919Swnj tmstart(); 2431919Swnj (void) spl0(); 2441919Swnj } 2451919Swnj 2461919Swnj tmstart() 2471919Swnj { 2481919Swnj register struct buf *bp; 2492471Swnj register struct uba_minfo *um = tmminfo[0]; 2502396Swnj register struct uba_dinfo *ui; 2512396Swnj register struct device *addr; 2522471Swnj register struct tm_softc *sc = &tm_softc[0]; 2532471Swnj int cmd, s; 2542471Swnj daddr_t blkno; 2551919Swnj 2561919Swnj loop: 2572471Swnj if ((bp = um->um_tab.b_actf) == 0) 2581919Swnj return; 2592471Swnj ui = tmdinfo[0]; 2602396Swnj addr = (struct device *)ui->ui_addr; 2612471Swnj sc->sc_dsreg = addr->tmcs; 2622471Swnj sc->sc_erreg = addr->tmer; 2632471Swnj sc->sc_resid = addr->tmbc; 2642471Swnj sc->sc_flags &= ~LASTIOW; 2652471Swnj if (sc->sc_openf < 0 || (addr->tmcs&CUR) == 0) { 2662471Swnj /* sc->sc_openf = -1; ??? */ 2671919Swnj bp->b_flags |= B_ERROR; /* hard error'ed or !SELR */ 2681919Swnj goto next; 2691919Swnj } 2701919Swnj cmd = IENABLE | GO; 2711919Swnj if ((minor(bp->b_dev) & T_1600BPI) == 0) 2721919Swnj cmd |= D800; 2731919Swnj if (bp == &ctmbuf) { 2741919Swnj if (bp->b_command == NOP) 2751919Swnj goto next; /* just get status */ 2761919Swnj else { 2771919Swnj cmd |= bp->b_command; 2782471Swnj um->um_tab.b_active = SCOM; 2791919Swnj if (bp->b_command == SFORW || bp->b_command == SREV) 2802396Swnj addr->tmbc = bp->b_repcnt; 2812396Swnj addr->tmcs = cmd; 2821919Swnj return; 2831919Swnj } 2841919Swnj } 2852471Swnj if ((blkno = sc->sc_blkno) == dbtofsb(bp->b_blkno)) { 2862396Swnj addr->tmbc = -bp->b_bcount; 2871919Swnj if ((bp->b_flags&B_READ) == 0) { 2882471Swnj if (um->um_tab.b_errcnt) 2891919Swnj cmd |= WIRG; 2901919Swnj else 2911919Swnj cmd |= WCOM; 2921919Swnj } else 2931919Swnj cmd |= RCOM; 2942471Swnj um->um_tab.b_active = SIO; 295*2574Swnj if (um->um_ubinfo) 296*2574Swnj panic("tmstart"); 297*2574Swnj um->um_cmd = cmd; 298*2574Swnj ubago(ui); 299*2574Swnj splx(s); 3001919Swnj return; 3011919Swnj } 3022471Swnj um->um_tab.b_active = SSEEK; 3031919Swnj if (blkno < dbtofsb(bp->b_blkno)) { 3041919Swnj cmd |= SFORW; 3052396Swnj addr->tmbc = blkno - dbtofsb(bp->b_blkno); 3061919Swnj } else { 3071919Swnj cmd |= SREV; 3082396Swnj addr->tmbc = dbtofsb(bp->b_blkno) - blkno; 3091919Swnj } 3102396Swnj addr->tmcs = cmd; 3111919Swnj return; 3121919Swnj 3131919Swnj next: 314*2574Swnj ubarelse(um->um_ubanum, &um->um_ubinfo); 3152471Swnj um->um_tab.b_actf = bp->av_forw; 3161919Swnj iodone(bp); 3171919Swnj goto loop; 3181919Swnj } 3191919Swnj 320*2574Swnj tmdgo(um) 321*2574Swnj register struct uba_minfo *um; 3221919Swnj { 323*2574Swnj register struct device *addr = (struct device *)um->um_addr; 3242471Swnj 325*2574Swnj printf("tmdgo %x %x\n", um->um_ubinfo, um->um_cmd); 326*2574Swnj addr->tmba = um->um_ubinfo; 327*2574Swnj addr->tmcs = um->um_cmd | ((um->um_ubinfo >> 12) & 0x30); 3282396Swnj } 3292396Swnj 3302471Swnj /*ARGSUSED*/ 3312396Swnj tmintr(d) 3322471Swnj int d; 3332396Swnj { 3341919Swnj register struct buf *bp; 3352471Swnj register struct uba_minfo *um = tmminfo[0]; 3362471Swnj register struct device *addr = (struct device *)tmdinfo[0]->ui_addr; 3372471Swnj register struct tm_softc *sc = &tm_softc[0]; 3381919Swnj register state; 3391919Swnj 340*2574Swnj printf("tmintr %x %x\n", um->um_tab.b_actf, um->um_tab.b_active); 3412471Swnj if (sc->sc_flags&WAITREW && (addr->tmer&RWS) == 0) { 3422471Swnj sc->sc_flags &= ~WAITREW; 3432471Swnj wakeup((caddr_t)&sc->sc_flags); 3441919Swnj } 3452471Swnj if ((bp = um->um_tab.b_actf) == NULL) 3461919Swnj return; 3472471Swnj sc->sc_dsreg = addr->tmcs; 3482471Swnj sc->sc_erreg = addr->tmer; 3492471Swnj sc->sc_resid = addr->tmbc; 3501919Swnj if ((bp->b_flags & B_READ) == 0) 3512471Swnj sc->sc_flags |= LASTIOW; 3522471Swnj state = um->um_tab.b_active; 3532471Swnj um->um_tab.b_active = 0; 3542396Swnj if (addr->tmcs&ERROR) { 3552396Swnj while(addr->tmer & SDWN) 3561919Swnj ; /* await settle down */ 3572396Swnj if (addr->tmer&EOF) { 3581919Swnj tmseteof(bp); /* set blkno and nxrec */ 3591919Swnj state = SCOM; 3602396Swnj addr->tmbc = -bp->b_bcount; 3611919Swnj goto errout; 3621919Swnj } 3632396Swnj if ((bp->b_flags&B_READ) && (addr->tmer&(HARD|SOFT)) == RLE) 3641919Swnj goto out; 3652396Swnj if ((addr->tmer&HARD)==0 && state==SIO) { 3662471Swnj if (++um->um_tab.b_errcnt < 7) { 3672396Swnj if((addr->tmer&SOFT) == NXM) 3681919Swnj printf("TM UBA late error\n"); 3692471Swnj sc->sc_blkno++; 370*2574Swnj ubarelse(um->um_ubanum, &um->um_ubinfo); 3711919Swnj tmstart(); 3721919Swnj return; 3731919Swnj } 3742471Swnj } else if (sc->sc_openf>0 && bp != &rtmbuf) 3752471Swnj sc->sc_openf = -1; 3762471Swnj deverror(bp, sc->sc_erreg, sc->sc_dsreg); 3771919Swnj bp->b_flags |= B_ERROR; 3781919Swnj state = SIO; 3791919Swnj } 3801919Swnj out: 3811919Swnj switch (state) { 3821919Swnj 3831919Swnj case SIO: 3842471Swnj sc->sc_blkno++; 3851919Swnj /* fall into ... */ 3861919Swnj 3871919Swnj case SCOM: 3881919Swnj if (bp == &ctmbuf) { 3891919Swnj switch (bp->b_command) { 3901919Swnj case SFORW: 3912471Swnj sc->sc_blkno -= bp->b_repcnt; 3921919Swnj break; 3931919Swnj 3941919Swnj case SREV: 3952471Swnj sc->sc_blkno += bp->b_repcnt; 3961919Swnj break; 3971919Swnj 3981919Swnj default: 3991919Swnj if (++bp->b_repcnt < 0) { 4001919Swnj tmstart(); /* continue */ 4011919Swnj return; 4021919Swnj } 4031919Swnj } 4041919Swnj } 4051919Swnj errout: 4062471Swnj um->um_tab.b_errcnt = 0; 4072471Swnj um->um_tab.b_actf = bp->av_forw; 4082396Swnj bp->b_resid = -addr->tmbc; 409*2574Swnj ubarelse(um->um_ubanum, &um->um_ubinfo); 4101919Swnj iodone(bp); 4111919Swnj break; 4121919Swnj 4131919Swnj case SSEEK: 4142471Swnj sc->sc_blkno = dbtofsb(bp->b_blkno); 4151919Swnj break; 4161919Swnj 4171919Swnj default: 4181919Swnj return; 4191919Swnj } 4201919Swnj tmstart(); 4211919Swnj } 4221919Swnj 4231919Swnj tmseteof(bp) 4241919Swnj register struct buf *bp; 4251919Swnj { 4262396Swnj register struct device *addr = 4272471Swnj (struct device *)tmdinfo[0]->ui_addr; 4282471Swnj register struct tm_softc *sc = &tm_softc[0]; 4291919Swnj 4301919Swnj if (bp == &ctmbuf) { 4312471Swnj if (sc->sc_blkno > dbtofsb(bp->b_blkno)) { 4321919Swnj /* reversing */ 4332471Swnj sc->sc_nxrec = dbtofsb(bp->b_blkno) - addr->tmbc; 4342471Swnj sc->sc_blkno = sc->sc_nxrec; 4351919Swnj } else { 4361919Swnj /* spacing forward */ 4372471Swnj sc->sc_blkno = dbtofsb(bp->b_blkno) + addr->tmbc; 4382471Swnj sc->sc_nxrec = sc->sc_blkno - 1; 4391919Swnj } 4401919Swnj return; 4411919Swnj } 4421919Swnj /* eof on read */ 4432471Swnj sc->sc_nxrec = dbtofsb(bp->b_blkno); 4441919Swnj } 4451919Swnj 4461919Swnj tmread(dev) 4471919Swnj { 4481919Swnj 4491919Swnj tmphys(dev); 4501919Swnj physio(tmstrategy, &rtmbuf, dev, B_READ, minphys); 4511919Swnj } 4521919Swnj 4531919Swnj tmwrite(dev) 4541919Swnj { 4551919Swnj 4561919Swnj tmphys(dev); 4571919Swnj physio(tmstrategy, &rtmbuf, dev, B_WRITE, minphys); 4581919Swnj } 4591919Swnj 4601919Swnj tmphys(dev) 4611919Swnj { 4621919Swnj register daddr_t a; 4632471Swnj register struct tm_softc *sc = &tm_softc[0]; 4641919Swnj 4651919Swnj a = dbtofsb(u.u_offset >> 9); 4662471Swnj sc->sc_blkno = a; 4672471Swnj sc->sc_nxrec = a + 1; 4681919Swnj } 4691919Swnj 4701919Swnj /*ARGSUSED*/ 4711919Swnj tmioctl(dev, cmd, addr, flag) 4721919Swnj caddr_t addr; 4731919Swnj dev_t dev; 4741919Swnj { 4751919Swnj register callcount; 4762471Swnj register struct tm_softc *sc = &tm_softc[0]; 4771919Swnj int fcount; 4781919Swnj struct mtop mtop; 4791919Swnj struct mtget mtget; 4801919Swnj /* we depend of the values and order of the MT codes here */ 4812324Skre static tmops[] = {WEOF, SFORW, SREV, SFORW, SREV, REW, OFFL, NOP}; 4821919Swnj 4831919Swnj switch(cmd) { 4841919Swnj case MTIOCTOP: /* tape operation */ 4851919Swnj if (copyin((caddr_t)addr, (caddr_t)&mtop, sizeof(mtop))) { 4861919Swnj u.u_error = EFAULT; 4871919Swnj return; 4881919Swnj } 4891919Swnj switch(mtop.mt_op) { 4901919Swnj case MTWEOF: case MTFSF: case MTBSF: 4911919Swnj callcount = mtop.mt_count; 4921919Swnj fcount = INF; 4931919Swnj break; 4941919Swnj case MTFSR: case MTBSR: 4951919Swnj callcount = 1; 4961919Swnj fcount = mtop.mt_count; 4971919Swnj break; 4982324Skre case MTREW: case MTOFFL: case MTNOP: 4991919Swnj callcount = 1; 5001919Swnj fcount = 1; 5011919Swnj break; 5021919Swnj default: 5031919Swnj u.u_error = ENXIO; 5041919Swnj return; 5051919Swnj } 5061919Swnj if (callcount <= 0 || fcount <= 0) 5071919Swnj u.u_error = ENXIO; 5081919Swnj else while (--callcount >= 0) { 509*2574Swnj tmcommand(dev, tmops[mtop.mt_op], fcount); 5101919Swnj if ((mtop.mt_op == MTFSR || mtop.mt_op == MTBSR) && 5111919Swnj ctmbuf.b_resid) { 5121919Swnj u.u_error = EIO; 5131919Swnj break; 5141919Swnj } 5152471Swnj if ((ctmbuf.b_flags&B_ERROR) || 5162471Swnj sc->sc_erreg&BOT) 5171919Swnj break; 5181919Swnj } 5191919Swnj geterror(&ctmbuf); 5201919Swnj return; 5211919Swnj case MTIOCGET: 5222471Swnj mtget.mt_dsreg = sc->sc_dsreg; 5232471Swnj mtget.mt_erreg = sc->sc_erreg; 5242471Swnj mtget.mt_resid = sc->sc_resid; 5251919Swnj if (copyout((caddr_t)&mtget, addr, sizeof(mtget))) 5261919Swnj u.u_error = EFAULT; 5271919Swnj return; 5281919Swnj default: 5291919Swnj u.u_error = ENXIO; 5301919Swnj } 5311919Swnj } 5321919Swnj 5331919Swnj #define DBSIZE 20 5341919Swnj 5352363Swnj tmdump() 5362363Swnj { 5372396Swnj register struct uba_dinfo *ui; 5382396Swnj register struct uba_regs *up; 5392396Swnj register struct device *addr; 5402426Skre int blk, num; 5412426Skre int start; 5421919Swnj 5432426Skre start = 0; 5442426Skre num = maxfree; 5452426Skre #define phys(a,b) ((b)((int)(a)&0x7fffffff)) 5462458Swnj if (tmdinfo[0] == 0) { 5472396Swnj printf("dna\n"); 5482396Swnj return (-1); 5492396Swnj } 5502458Swnj ui = phys(tmdinfo[0], struct uba_dinfo *); 5512396Swnj up = phys(ui->ui_hd, struct uba_hd *)->uh_physuba; 5522396Swnj #if VAX780 5532396Swnj if (cpu == VAX_780) 5542396Swnj ubainit(up); 5551919Swnj #endif 5562324Skre DELAY(1000000); 5572396Swnj addr = (struct device *)ui->ui_physaddr; 5582396Swnj tmwait(addr); 5592396Swnj addr->tmcs = DCLR | GO; 5601919Swnj while (num > 0) { 5611919Swnj blk = num > DBSIZE ? DBSIZE : num; 5622396Swnj tmdwrite(start, blk, addr, up); 5631919Swnj start += blk; 5641919Swnj num -= blk; 5651919Swnj } 5662426Skre tmeof(addr); 5672426Skre tmeof(addr); 5682426Skre tmwait(addr); 5692471Swnj addr->tmcs = REW | GO; 5702471Swnj tmwait(addr); 5712363Swnj return (0); 5721919Swnj } 5731919Swnj 5742396Swnj tmdwrite(buf, num, addr, up) 5752396Swnj register buf, num; 5762396Swnj register struct device *addr; 5772396Swnj struct uba_regs *up; 5781919Swnj { 5792396Swnj register struct pte *io; 5802396Swnj register int npf; 5811928Swnj 5822396Swnj tmwait(addr); 5832396Swnj io = up->uba_map; 5841919Swnj npf = num+1; 5851928Swnj while (--npf != 0) 5862396Swnj *(int *)io++ = (buf++ | (1<<UBA_DPSHIFT) | UBA_MRV); 5872396Swnj *(int *)io = 0; 5882396Swnj addr->tmbc = -(num*NBPG); 5892396Swnj addr->tmba = 0; 5902396Swnj addr->tmcs = WCOM | GO; 5911919Swnj } 5921919Swnj 5932396Swnj tmwait(addr) 5942396Swnj register struct device *addr; 5951919Swnj { 5961928Swnj register s; 5971919Swnj 5981919Swnj do 5992396Swnj s = addr->tmcs; 6001919Swnj while ((s & CUR) == 0); 6011919Swnj } 6021919Swnj 6032396Swnj tmeof(addr) 6042396Swnj struct device *addr; 6051919Swnj { 6061919Swnj 6072396Swnj tmwait(addr); 6082396Swnj addr->tmcs = WEOF | GO; 6091919Swnj } 6101919Swnj #endif 611