1*2458Swnj /* tm.c 4.11 02/16/81 */ 21919Swnj 31940Swnj #include "tm.h" 41919Swnj #if NTM > 0 51919Swnj /* 61919Swnj * TM tape driver 71919Swnj */ 82324Skre #define DELAY(N) { register int d; d = N; while (--d > 0); } 91919Swnj #include "../h/param.h" 101919Swnj #include "../h/buf.h" 111919Swnj #include "../h/dir.h" 121919Swnj #include "../h/conf.h" 131919Swnj #include "../h/user.h" 141919Swnj #include "../h/file.h" 151919Swnj #include "../h/map.h" 161919Swnj #include "../h/pte.h" 171919Swnj #include "../h/uba.h" 181919Swnj #include "../h/mtio.h" 191919Swnj #include "../h/ioctl.h" 201919Swnj #include "../h/vm.h" 212363Swnj #include "../h/cmap.h" 222396Swnj #include "../h/cpu.h" 231919Swnj 242396Swnj #include "../h/tmreg.h" 251919Swnj 261919Swnj struct buf ctmbuf; 271919Swnj struct buf rtmbuf; 281919Swnj 292396Swnj int tmcntrlr(), tmslave(), tmdgo(), tmintr(); 30*2458Swnj struct uba_dinfo *tmdinfo[NTM]; 31*2458Swnj struct uba_minfo *tmminfo[NTM]; 32*2458Swnj u_short tmstd[] = { 0772520, 0 }; 332396Swnj struct uba_driver tmdriver = 34*2458Swnj { tmcntrlr, tmslave, tmdgo, 0, tmstd, "tm", tmdinfo, tmminfo }; 351919Swnj int tm_ubinfo; 361919Swnj 371919Swnj /* bits in minor device */ 381919Swnj #define T_NOREWIND 04 391919Swnj #define T_1600BPI 08 401919Swnj 411919Swnj #define INF (daddr_t)1000000L 421919Swnj 431919Swnj /* 441919Swnj * Really only handle one tape drive... if you have more than one, 452396Swnj * you can put all these (and some of the above) in a structure, 462396Swnj * change the obvious things, and make tmslave smarter, but 471919Swnj * it is not clear what happens when some drives are transferring while 481919Swnj * others rewind, so we don't pretend that this driver handles multiple 491919Swnj * tape drives. 501919Swnj */ 511919Swnj char t_openf; 521919Swnj daddr_t t_blkno; 531919Swnj char t_flags; 541919Swnj daddr_t t_nxrec; 551919Swnj u_short t_erreg; 561919Swnj u_short t_dsreg; 571919Swnj short t_resid; 581919Swnj 591919Swnj #define SSEEK 1 /* seeking */ 601919Swnj #define SIO 2 /* doing seq i/o */ 611919Swnj #define SCOM 3 /* sending control command */ 621919Swnj 631919Swnj #define LASTIOW 1 /* last op was a write */ 641919Swnj #define WAITREW 2 /* someone is waiting for a rewind */ 651919Swnj 662426Skre /* 672426Skre * Determine if there is a controller for 682426Skre * a tm at address reg. Our goal is to make the 692426Skre * device interrupt. 702426Skre */ 71*2458Swnj tmcntrlr(um, reg) 72*2458Swnj struct uba_minfo *um; 732396Swnj caddr_t reg; 742396Swnj { 75*2458Swnj register int br, cvec; 762426Skre 772396Swnj ((struct device *)reg)->tmcs = IENABLE; 782396Swnj /* 792396Swnj * If this is a tm03/tc11, it ought to have interrupted 802396Swnj * by now, if it isn't (ie: it is a ts04) then we just 81*2458Swnj * hope that it didn't interrupt, so autoconf will ignore it. 82*2458Swnj * Just in case, we will reference one 832396Swnj * of the more distant registers, and hope for a machine 84*2458Swnj * check, or similar disaster if this is a ts. 852396Swnj */ 862396Swnj if (badaddr(&((struct device *)reg)->tmrd, 2)) 87*2458Swnj return (0); 88*2458Swnj return (1); 892396Swnj } 902396Swnj 912396Swnj tmslave(ui, reg, slaveno) 922396Swnj struct uba_dinfo *ui; 932396Swnj caddr_t reg; 942396Swnj { 95*2458Swnj 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*2458Swnj if (slaveno != 0 || tmdinfo[0]) 1062396Swnj return(0); 107*2458Swnj 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; 1161919Swnj 117*2458Swnj tmminfo[0]->um_tab.b_flags |= B_TAPE; 1181919Swnj unit = minor(dev)&03; 119*2458Swnj if (unit>=NTM || t_openf || !(ui = tmdinfo[minor(dev)&03])->ui_alive) { 1201919Swnj u.u_error = ENXIO; /* out of range or open */ 1211919Swnj return; 1221919Swnj } 1231919Swnj tcommand(dev, NOP, 1); 1241919Swnj if ((t_erreg&SELR) == 0) { 1251919Swnj u.u_error = EIO; /* offline */ 1261919Swnj return; 1271919Swnj } 1281919Swnj t_openf = 1; 1291919Swnj if (t_erreg&RWS) 1301919Swnj tmwaitrws(dev); /* wait for rewind complete */ 1311919Swnj while (t_erreg&SDWN) 1321919Swnj tcommand(dev, NOP, 1); /* await settle down */ 1331919Swnj if ((t_erreg&TUR)==0 || 1341919Swnj ((flag&(FREAD|FWRITE)) == FWRITE && (t_erreg&WRL))) { 1352396Swnj ((struct device *)ui->ui_addr)->tmcs = DCLR|GO; 1361919Swnj u.u_error = EIO; /* offline or write protect */ 1371919Swnj } 1381919Swnj if (u.u_error != 0) { 1391919Swnj t_openf = 0; 1401919Swnj return; 1411919Swnj } 1421919Swnj t_blkno = (daddr_t)0; 1431919Swnj t_nxrec = INF; 1441919Swnj t_flags = 0; 1451919Swnj t_openf = 1; 1461919Swnj } 1471919Swnj 1481919Swnj tmwaitrws(dev) 1491919Swnj register dev; 1501919Swnj { 1512396Swnj register struct device *addr = 152*2458Swnj (struct device *)tmdinfo[minor(dev)&03]->ui_addr; 1531919Swnj 1541919Swnj spl5(); 1551919Swnj for (;;) { 1562396Swnj if ((addr->tmer&RWS) == 0) { 1571919Swnj spl0(); /* rewind complete */ 1581919Swnj return; 1591919Swnj } 1601919Swnj t_flags |= WAITREW; 1611919Swnj sleep((caddr_t)&t_flags, PRIBIO); 1621919Swnj } 1631919Swnj } 1641919Swnj 1651919Swnj tmclose(dev, flag) 1661919Swnj register dev_t dev; 1671919Swnj register flag; 1681919Swnj { 1691919Swnj 1701919Swnj if (flag == FWRITE || ((flag&FWRITE) && (t_flags&LASTIOW))) { 1711919Swnj tcommand(dev, WEOF, 1); 1721919Swnj tcommand(dev, WEOF, 1); 1731919Swnj tcommand(dev, SREV, 1); 1741919Swnj } 1751919Swnj if ((minor(dev)&T_NOREWIND) == 0) 1761919Swnj tcommand(dev, REW, 1); 1771919Swnj t_openf = 0; 1781919Swnj } 1791919Swnj 1801919Swnj tcommand(dev, com, count) 1811919Swnj dev_t dev; 1821919Swnj int com, count; 1831919Swnj { 1841919Swnj register struct buf *bp; 1851919Swnj 1861919Swnj bp = &ctmbuf; 1871919Swnj (void) spl5(); 1881919Swnj while (bp->b_flags&B_BUSY) { 1891919Swnj bp->b_flags |= B_WANTED; 1901919Swnj sleep((caddr_t)bp, PRIBIO); 1911919Swnj } 1921919Swnj bp->b_flags = B_BUSY|B_READ; 1931919Swnj (void) spl0(); 1941919Swnj bp->b_dev = dev; 1951919Swnj bp->b_repcnt = -count; 1961919Swnj bp->b_command = com; 1971919Swnj bp->b_blkno = 0; 1981919Swnj tmstrategy(bp); 1991919Swnj iowait(bp); 2001919Swnj if (bp->b_flags&B_WANTED) 2011919Swnj wakeup((caddr_t)bp); 2021919Swnj bp->b_flags &= B_ERROR; 2031919Swnj } 2041919Swnj 2051919Swnj tmstrategy(bp) 2061919Swnj register struct buf *bp; 2071919Swnj { 2081919Swnj register daddr_t *p; 209*2458Swnj register struct buf *tmi; 2101919Swnj 2111928Swnj tmwaitrws(bp->b_dev); 2121919Swnj if (bp != &ctmbuf) { 2131919Swnj p = &t_nxrec; 2141919Swnj if (dbtofsb(bp->b_blkno) > *p) { 2151919Swnj bp->b_flags |= B_ERROR; 2161919Swnj bp->b_error = ENXIO; /* past EOF */ 2171919Swnj iodone(bp); 2181919Swnj return; 2191919Swnj } else if (dbtofsb(bp->b_blkno) == *p && bp->b_flags&B_READ) { 2201919Swnj bp->b_resid = bp->b_bcount; 2211919Swnj clrbuf(bp); /* at EOF */ 2221919Swnj iodone(bp); 2231919Swnj return; 2241919Swnj } else if ((bp->b_flags&B_READ) == 0) 2251919Swnj *p = dbtofsb(bp->b_blkno) + 1; /* write sets EOF */ 2261919Swnj } 2271919Swnj bp->av_forw = NULL; 2281919Swnj (void) spl5(); 229*2458Swnj tmi = &tmminfo[0]->um_tab; 230*2458Swnj if (tmi->b_actf == NULL) 231*2458Swnj tmi->b_actf = bp; 2321919Swnj else 233*2458Swnj tmi->b_actl->av_forw = bp; 234*2458Swnj tmi->b_actl = bp; 235*2458Swnj if (tmi->b_active == 0) 2361919Swnj tmstart(); 2371919Swnj (void) spl0(); 2381919Swnj } 2391919Swnj 2401919Swnj tmstart() 2411919Swnj { 2421919Swnj register struct buf *bp; 2432396Swnj register struct uba_dinfo *ui; 2442396Swnj register struct device *addr; 2451919Swnj register cmd; 2461919Swnj register daddr_t blkno; 2472054Swnj int s; 2481919Swnj 2491919Swnj loop: 250*2458Swnj if ((bp = tmminfo[0]->um_tab.b_actf) == 0) 2511919Swnj return; 252*2458Swnj ui = tmdinfo[minor(bp->b_dev)&03]; 2532396Swnj addr = (struct device *)ui->ui_addr; 2542396Swnj t_dsreg = addr->tmcs; 2552396Swnj t_erreg = addr->tmer; 2562396Swnj t_resid = addr->tmbc; 2571919Swnj t_flags &= ~LASTIOW; 2582396Swnj if (t_openf < 0 || (addr->tmcs&CUR) == 0) { 2591919Swnj /* t_openf = -1; ??? */ 2601919Swnj bp->b_flags |= B_ERROR; /* hard error'ed or !SELR */ 2611919Swnj goto next; 2621919Swnj } 2631919Swnj cmd = IENABLE | GO; 2641919Swnj if ((minor(bp->b_dev) & T_1600BPI) == 0) 2651919Swnj cmd |= D800; 2661919Swnj if (bp == &ctmbuf) { 2671919Swnj if (bp->b_command == NOP) 2681919Swnj goto next; /* just get status */ 2691919Swnj else { 2701919Swnj cmd |= bp->b_command; 271*2458Swnj tmminfo[0]->um_tab.b_active = SCOM; 2721919Swnj if (bp->b_command == SFORW || bp->b_command == SREV) 2732396Swnj addr->tmbc = bp->b_repcnt; 2742396Swnj addr->tmcs = cmd; 2751919Swnj return; 2761919Swnj } 2771919Swnj } 2781919Swnj if ((blkno = t_blkno) == dbtofsb(bp->b_blkno)) { 2792396Swnj addr->tmbc = -bp->b_bcount; 2802054Swnj s = spl6(); 2811919Swnj if (tm_ubinfo == 0) 2822396Swnj tm_ubinfo = ubasetup(ui->ui_ubanum, bp, 1); 2832054Swnj splx(s); 2841919Swnj if ((bp->b_flags&B_READ) == 0) { 285*2458Swnj if (tmminfo[0]->um_tab.b_errcnt) 2861919Swnj cmd |= WIRG; 2871919Swnj else 2881919Swnj cmd |= WCOM; 2891919Swnj } else 2901919Swnj cmd |= RCOM; 2911919Swnj cmd |= (tm_ubinfo >> 12) & 0x30; 292*2458Swnj tmminfo[0]->um_tab.b_active = SIO; 2932396Swnj addr->tmba = tm_ubinfo; 2942396Swnj addr->tmcs = cmd; 2951919Swnj return; 2961919Swnj } 297*2458Swnj tmminfo[0]->um_tab.b_active = SSEEK; 2981919Swnj if (blkno < dbtofsb(bp->b_blkno)) { 2991919Swnj cmd |= SFORW; 3002396Swnj addr->tmbc = blkno - dbtofsb(bp->b_blkno); 3011919Swnj } else { 3021919Swnj cmd |= SREV; 3032396Swnj addr->tmbc = dbtofsb(bp->b_blkno) - blkno; 3041919Swnj } 3052396Swnj addr->tmcs = cmd; 3061919Swnj return; 3071919Swnj 3081919Swnj next: 3092396Swnj ubarelse(ui->ui_ubanum, &tm_ubinfo); 310*2458Swnj tmminfo[0]->um_tab.b_actf = bp->av_forw; 3111919Swnj iodone(bp); 3121919Swnj goto loop; 3131919Swnj } 3141919Swnj 3152396Swnj tmdgo() 3161919Swnj { 3172396Swnj } 3182396Swnj 3192396Swnj tmintr(d) 3202396Swnj { 3211919Swnj register struct buf *bp; 322*2458Swnj register struct device *addr = (struct device *)tmdinfo[d]->ui_addr; 3231919Swnj register state; 3241919Swnj 3252396Swnj if (t_flags&WAITREW && (addr->tmer&RWS) == 0) { 3261919Swnj t_flags &= ~WAITREW; 3271919Swnj wakeup((caddr_t)&t_flags); 3281919Swnj } 329*2458Swnj if ((bp = tmminfo[0]->um_tab.b_actf) == NULL) 3301919Swnj return; 3312396Swnj t_dsreg = addr->tmcs; 3322396Swnj t_erreg = addr->tmer; 3332396Swnj t_resid = addr->tmbc; 3341919Swnj if ((bp->b_flags & B_READ) == 0) 3351919Swnj t_flags |= LASTIOW; 336*2458Swnj state = tmminfo[0]->um_tab.b_active; 337*2458Swnj tmminfo[0]->um_tab.b_active = 0; 3382396Swnj if (addr->tmcs&ERROR) { 3392396Swnj while(addr->tmer & SDWN) 3401919Swnj ; /* await settle down */ 3412396Swnj if (addr->tmer&EOF) { 3421919Swnj tmseteof(bp); /* set blkno and nxrec */ 3431919Swnj state = SCOM; 3442396Swnj addr->tmbc = -bp->b_bcount; 3451919Swnj goto errout; 3461919Swnj } 3472396Swnj if ((bp->b_flags&B_READ) && (addr->tmer&(HARD|SOFT)) == RLE) 3481919Swnj goto out; 3492396Swnj if ((addr->tmer&HARD)==0 && state==SIO) { 350*2458Swnj if (++tmminfo[0]->um_tab.b_errcnt < 7) { 3512396Swnj if((addr->tmer&SOFT) == NXM) 3521919Swnj printf("TM UBA late error\n"); 3532426Skre t_blkno++; 354*2458Swnj ubarelse(tmdinfo[d]->ui_ubanum, &tm_ubinfo); 3551919Swnj tmstart(); 3561919Swnj return; 3571919Swnj } 3581919Swnj } else if (t_openf>0 && bp != &rtmbuf) 3591919Swnj t_openf = -1; 3601928Swnj deverror(bp, t_erreg, t_dsreg); 3611919Swnj bp->b_flags |= B_ERROR; 3621919Swnj state = SIO; 3631919Swnj } 3641919Swnj out: 3651919Swnj switch (state) { 3661919Swnj 3671919Swnj case SIO: 3681919Swnj t_blkno++; 3691919Swnj /* fall into ... */ 3701919Swnj 3711919Swnj case SCOM: 3721919Swnj if (bp == &ctmbuf) { 3731919Swnj switch (bp->b_command) { 3741919Swnj case SFORW: 3751919Swnj t_blkno -= bp->b_repcnt; 3761919Swnj break; 3771919Swnj 3781919Swnj case SREV: 3791919Swnj t_blkno += bp->b_repcnt; 3801919Swnj break; 3811919Swnj 3821919Swnj default: 3831919Swnj if (++bp->b_repcnt < 0) { 3841919Swnj tmstart(); /* continue */ 3851919Swnj return; 3861919Swnj } 3871919Swnj } 3881919Swnj } 3891919Swnj errout: 390*2458Swnj tmminfo[0]->um_tab.b_errcnt = 0; 391*2458Swnj tmminfo[0]->um_tab.b_actf = bp->av_forw; 3922396Swnj bp->b_resid = -addr->tmbc; 393*2458Swnj ubarelse(tmdinfo[d]->ui_ubanum, &tm_ubinfo); 3941919Swnj iodone(bp); 3951919Swnj break; 3961919Swnj 3971919Swnj case SSEEK: 3981919Swnj t_blkno = dbtofsb(bp->b_blkno); 3991919Swnj break; 4001919Swnj 4011919Swnj default: 4021919Swnj return; 4031919Swnj } 4041919Swnj tmstart(); 4051919Swnj } 4061919Swnj 4071919Swnj tmseteof(bp) 4081919Swnj register struct buf *bp; 4091919Swnj { 4102396Swnj register struct device *addr = 411*2458Swnj (struct device *)tmdinfo[minor(bp->b_dev)&03]->ui_addr; 4121919Swnj 4131919Swnj if (bp == &ctmbuf) { 4141919Swnj if (t_blkno > dbtofsb(bp->b_blkno)) { 4151919Swnj /* reversing */ 4162396Swnj t_nxrec = dbtofsb(bp->b_blkno) - addr->tmbc; 4171919Swnj t_blkno = t_nxrec; 4181919Swnj } else { 4191919Swnj /* spacing forward */ 4202396Swnj t_blkno = dbtofsb(bp->b_blkno) + addr->tmbc; 4211919Swnj t_nxrec = t_blkno - 1; 4221919Swnj } 4231919Swnj return; 4241919Swnj } 4251919Swnj /* eof on read */ 4261919Swnj t_nxrec = dbtofsb(bp->b_blkno); 4271919Swnj } 4281919Swnj 4291919Swnj tmread(dev) 4301919Swnj { 4311919Swnj 4321919Swnj tmphys(dev); 4331919Swnj physio(tmstrategy, &rtmbuf, dev, B_READ, minphys); 4341919Swnj } 4351919Swnj 4361919Swnj tmwrite(dev) 4371919Swnj { 4381919Swnj 4391919Swnj tmphys(dev); 4401919Swnj physio(tmstrategy, &rtmbuf, dev, B_WRITE, minphys); 4411919Swnj } 4421919Swnj 4431919Swnj tmphys(dev) 4441919Swnj { 4451919Swnj register daddr_t a; 4461919Swnj 4471919Swnj a = dbtofsb(u.u_offset >> 9); 4481919Swnj t_blkno = a; 4491919Swnj t_nxrec = a + 1; 4501919Swnj } 4511919Swnj 4521919Swnj /*ARGSUSED*/ 4531919Swnj tmioctl(dev, cmd, addr, flag) 4541919Swnj caddr_t addr; 4551919Swnj dev_t dev; 4561919Swnj { 4571919Swnj register callcount; 4581919Swnj int fcount; 4591919Swnj struct mtop mtop; 4601919Swnj struct mtget mtget; 4611919Swnj /* we depend of the values and order of the MT codes here */ 4622324Skre static tmops[] = {WEOF, SFORW, SREV, SFORW, SREV, REW, OFFL, NOP}; 4631919Swnj 4641919Swnj switch(cmd) { 4651919Swnj case MTIOCTOP: /* tape operation */ 4661919Swnj if (copyin((caddr_t)addr, (caddr_t)&mtop, sizeof(mtop))) { 4671919Swnj u.u_error = EFAULT; 4681919Swnj return; 4691919Swnj } 4701919Swnj switch(mtop.mt_op) { 4711919Swnj case MTWEOF: case MTFSF: case MTBSF: 4721919Swnj callcount = mtop.mt_count; 4731919Swnj fcount = INF; 4741919Swnj break; 4751919Swnj case MTFSR: case MTBSR: 4761919Swnj callcount = 1; 4771919Swnj fcount = mtop.mt_count; 4781919Swnj break; 4792324Skre case MTREW: case MTOFFL: case MTNOP: 4801919Swnj callcount = 1; 4811919Swnj fcount = 1; 4821919Swnj break; 4831919Swnj default: 4841919Swnj u.u_error = ENXIO; 4851919Swnj return; 4861919Swnj } 4871919Swnj if (callcount <= 0 || fcount <= 0) 4881919Swnj u.u_error = ENXIO; 4891919Swnj else while (--callcount >= 0) { 4901919Swnj tcommand(dev, tmops[mtop.mt_op], fcount); 4911919Swnj if ((mtop.mt_op == MTFSR || mtop.mt_op == MTBSR) && 4921919Swnj ctmbuf.b_resid) { 4931919Swnj u.u_error = EIO; 4941919Swnj break; 4951919Swnj } 4961919Swnj if ((ctmbuf.b_flags&B_ERROR) || t_erreg&BOT) 4971919Swnj break; 4981919Swnj } 4991919Swnj geterror(&ctmbuf); 5001919Swnj return; 5011919Swnj case MTIOCGET: 5021919Swnj mtget.mt_dsreg = t_dsreg; 5031919Swnj mtget.mt_erreg = t_erreg; 5041919Swnj mtget.mt_resid = t_resid; 5051919Swnj if (copyout((caddr_t)&mtget, addr, sizeof(mtget))) 5061919Swnj u.u_error = EFAULT; 5071919Swnj return; 5081919Swnj default: 5091919Swnj u.u_error = ENXIO; 5101919Swnj } 5111919Swnj } 5121919Swnj 5131919Swnj #define DBSIZE 20 5141919Swnj 5152363Swnj tmdump() 5162363Swnj { 5172396Swnj register struct uba_dinfo *ui; 5182396Swnj register struct uba_regs *up; 5192396Swnj register struct device *addr; 5202426Skre int blk, num; 5212426Skre int start; 5221919Swnj 5232426Skre start = 0; 5242426Skre num = maxfree; 5252426Skre #define phys(a,b) ((b)((int)(a)&0x7fffffff)) 526*2458Swnj if (tmdinfo[0] == 0) { 5272396Swnj printf("dna\n"); 5282396Swnj return (-1); 5292396Swnj } 530*2458Swnj ui = phys(tmdinfo[0], struct uba_dinfo *); 5312396Swnj up = phys(ui->ui_hd, struct uba_hd *)->uh_physuba; 5322396Swnj #if VAX780 5332396Swnj if (cpu == VAX_780) 5342396Swnj ubainit(up); 5351919Swnj #endif 5362324Skre DELAY(1000000); 5372396Swnj addr = (struct device *)ui->ui_physaddr; 5382396Swnj tmwait(addr); 5392396Swnj addr->tmcs = DCLR | GO; 5401919Swnj while (num > 0) { 5411919Swnj blk = num > DBSIZE ? DBSIZE : num; 5422396Swnj tmdwrite(start, blk, addr, up); 5431919Swnj start += blk; 5441919Swnj num -= blk; 5451919Swnj } 5462426Skre tmwait(addr); 5472426Skre tmeof(addr); 5482426Skre tmeof(addr); 5492426Skre tmrewind(addr); 5502426Skre tmwait(addr); 5512363Swnj return (0); 5521919Swnj } 5531919Swnj 5542396Swnj tmdwrite(buf, num, addr, up) 5552396Swnj register buf, num; 5562396Swnj register struct device *addr; 5572396Swnj struct uba_regs *up; 5581919Swnj { 5592396Swnj register struct pte *io; 5602396Swnj register int npf; 5611928Swnj 5622396Swnj tmwait(addr); 5632396Swnj io = up->uba_map; 5641919Swnj npf = num+1; 5651928Swnj while (--npf != 0) 5662396Swnj *(int *)io++ = (buf++ | (1<<UBA_DPSHIFT) | UBA_MRV); 5672396Swnj *(int *)io = 0; 5682396Swnj addr->tmbc = -(num*NBPG); 5692396Swnj addr->tmba = 0; 5702396Swnj addr->tmcs = WCOM | GO; 5711919Swnj } 5721919Swnj 5732396Swnj tmwait(addr) 5742396Swnj register struct device *addr; 5751919Swnj { 5761928Swnj register s; 5771919Swnj 5781919Swnj do 5792396Swnj s = addr->tmcs; 5801919Swnj while ((s & CUR) == 0); 5811919Swnj } 5821919Swnj 5832396Swnj tmrewind(addr) 5842396Swnj struct device *addr; 5851919Swnj { 5861919Swnj 5872396Swnj tmwait(addr); 5882396Swnj addr->tmcs = REW | GO; 5891919Swnj } 5901919Swnj 5912396Swnj tmeof(addr) 5922396Swnj struct device *addr; 5931919Swnj { 5941919Swnj 5952396Swnj tmwait(addr); 5962396Swnj addr->tmcs = WEOF | GO; 5971919Swnj } 5981919Swnj #endif 599