1*3208Swnj /* rk.c 4.29 81/03/11 */ 21899Swnj 31942Swnj #include "rk.h" 42648Swnj #if NHK > 0 53104Swnj int rkpip; /* DEBUG */ 63104Swnj int rknosval; /* DEBUG */ 71899Swnj /* 82618Swnj * RK11/RK07 disk driver 92622Swnj * 102622Swnj * This driver mimics up.c; see it for an explanation of common code. 112685Swnj * 122885Swnj * TODO: 13*3208Swnj * Learn why we lose an interrupt sometime when spinning drives down 141899Swnj */ 151899Swnj #include "../h/param.h" 161899Swnj #include "../h/systm.h" 171899Swnj #include "../h/buf.h" 181899Swnj #include "../h/conf.h" 191899Swnj #include "../h/dir.h" 201899Swnj #include "../h/user.h" 211899Swnj #include "../h/pte.h" 221899Swnj #include "../h/map.h" 232618Swnj #include "../h/vm.h" 242981Swnj #include "../h/ubareg.h" 252981Swnj #include "../h/ubavar.h" 261899Swnj #include "../h/dk.h" 272618Swnj #include "../h/cpu.h" 282618Swnj #include "../h/cmap.h" 291899Swnj 302618Swnj #include "../h/rkreg.h" 311899Swnj 322618Swnj struct rk_softc { 332618Swnj int sc_softas; 342618Swnj int sc_ndrive; 352618Swnj int sc_wticks; 362618Swnj int sc_recal; 372648Swnj } rk_softc[NHK]; 381899Swnj 392618Swnj /* THIS SHOULD BE READ OFF THE PACK, PER DRIVE */ 402787Swnj struct size { 412618Swnj daddr_t nblocks; 422618Swnj int cyloff; 432618Swnj } rk7_sizes[] ={ 442618Swnj 15884, 0, /* A=cyl 0 thru 240 */ 452665Swnj 10032, 241, /* B=cyl 241 thru 392 */ 462665Swnj 53790, 0, /* C=cyl 0 thru 814 */ 472618Swnj 0, 0, 482618Swnj 0, 0, 492618Swnj 0, 0, 502618Swnj 27786, 393, /* G=cyl 393 thru 813 */ 512618Swnj 0, 0, 522618Swnj }; 532618Swnj /* END OF STUFF WHICH SHOULD BE READ IN PER DISK */ 541899Swnj 552618Swnj int rkprobe(), rkslave(), rkattach(), rkdgo(), rkintr(); 562981Swnj struct uba_ctlr *rkminfo[NHK]; 572981Swnj struct uba_device *rkdinfo[NRK]; 582981Swnj struct uba_device *rkip[NHK][4]; 591899Swnj 602618Swnj u_short rkstd[] = { 0777440, 0 }; 612618Swnj struct uba_driver hkdriver = 622622Swnj { rkprobe, rkslave, rkattach, rkdgo, rkstd, "rk", rkdinfo, "hk", rkminfo, 1 }; 632648Swnj struct buf rkutab[NRK]; 642648Swnj short rkcyl[NRK]; 651899Swnj 662618Swnj struct rkst { 672618Swnj short nsect; 682618Swnj short ntrak; 692618Swnj short nspc; 702618Swnj short ncyl; 712618Swnj struct size *sizes; 722618Swnj } rkst[] = { 732618Swnj NRKSECT, NRKTRK, NRKSECT*NRKTRK, NRK7CYL, rk7_sizes, 742618Swnj }; 751899Swnj 762618Swnj u_char rk_offset[16] = 772618Swnj { P400,M400,P400,M400,P800,M800,P800,M800,P1200,M1200,P1200,M1200,0,0,0,0 }; 781899Swnj 792648Swnj struct buf rrkbuf[NRK]; 802618Swnj 812618Swnj #define b_cylin b_resid 822618Swnj 832618Swnj #ifdef INTRLVE 842618Swnj daddr_t dkblock(); 852618Swnj #endif 862618Swnj 872618Swnj int rkwstart, rkwatch(); 882618Swnj 892618Swnj rkprobe(reg) 902618Swnj caddr_t reg; 911899Swnj { 922618Swnj register int br, cvec; 931899Swnj 942618Swnj #ifdef lint 952618Swnj br = 0; cvec = br; br = cvec; 962618Swnj #endif 972618Swnj ((struct rkdevice *)reg)->rkcs1 = RK_CDT|RK_IE|RK_CRDY; 982618Swnj DELAY(10); 992618Swnj ((struct rkdevice *)reg)->rkcs1 = RK_CDT; 1002618Swnj return (1); 1012618Swnj } 1021899Swnj 1032618Swnj rkslave(ui, reg) 1042981Swnj struct uba_device *ui; 1052618Swnj caddr_t reg; 1062618Swnj { 1072618Swnj register struct rkdevice *rkaddr = (struct rkdevice *)reg; 1081899Swnj 1092894Swnj rkaddr->rkcs1 = RK_CDT|RK_CCLR; 1102618Swnj rkaddr->rkcs2 = ui->ui_slave; 1112957Swnj rkaddr->rkcs1 = RK_CDT|RK_DCLR|RK_GO; 1122622Swnj rkwait(rkaddr); 1132894Swnj DELAY(50); 1142894Swnj if (rkaddr->rkcs2&RK_NED || (rkaddr->rkds&RK_SVAL) == 0) { 1152618Swnj rkaddr->rkcs1 = RK_CDT|RK_CCLR; 1162618Swnj return (0); 1172618Swnj } 1182618Swnj return (1); 1192618Swnj } 1202618Swnj 1212618Swnj rkattach(ui) 1222981Swnj register struct uba_device *ui; 1232618Swnj { 1242618Swnj 1252618Swnj if (rkwstart == 0) { 1262758Swnj timeout(rkwatch, (caddr_t)0, hz); 1272618Swnj rkwstart++; 1282618Swnj } 1292618Swnj if (ui->ui_dk >= 0) 1302758Swnj dk_mspw[ui->ui_dk] = 1.0 / (60 * NRKSECT * 256); 1312618Swnj rkip[ui->ui_ctlr][ui->ui_slave] = ui; 1322618Swnj rk_softc[ui->ui_ctlr].sc_ndrive++; 1332618Swnj rkcyl[ui->ui_unit] = -1; 1342618Swnj } 1352618Swnj 1361899Swnj rkstrategy(bp) 1372618Swnj register struct buf *bp; 1381899Swnj { 1392981Swnj register struct uba_device *ui; 1402618Swnj register struct rkst *st; 1412618Swnj register int unit; 1422618Swnj register struct buf *dp; 1432618Swnj int xunit = minor(bp->b_dev) & 07; 1442618Swnj long bn, sz; 1451899Swnj 1462618Swnj sz = (bp->b_bcount+511) >> 9; 1472618Swnj unit = dkunit(bp); 1482648Swnj if (unit >= NRK) 1492618Swnj goto bad; 1502618Swnj ui = rkdinfo[unit]; 1512618Swnj if (ui == 0 || ui->ui_alive == 0) 1522618Swnj goto bad; 1532618Swnj st = &rkst[ui->ui_type]; 1542618Swnj if (bp->b_blkno < 0 || 1552618Swnj (bn = dkblock(bp))+sz > st->sizes[xunit].nblocks) 1562618Swnj goto bad; 1572618Swnj bp->b_cylin = bn/st->nspc + st->sizes[xunit].cyloff; 1582618Swnj (void) spl5(); 1592618Swnj dp = &rkutab[ui->ui_unit]; 1602618Swnj disksort(dp, bp); 1612618Swnj if (dp->b_active == 0) { 1622618Swnj (void) rkustart(ui); 1632618Swnj bp = &ui->ui_mi->um_tab; 1642618Swnj if (bp->b_actf && bp->b_active == 0) 1652618Swnj (void) rkstart(ui->ui_mi); 1661899Swnj } 1672618Swnj (void) spl0(); 1682618Swnj return; 1692618Swnj 1702618Swnj bad: 1712618Swnj bp->b_flags |= B_ERROR; 1722618Swnj iodone(bp); 1732618Swnj return; 1741899Swnj } 1751899Swnj 1762618Swnj rkustart(ui) 1772981Swnj register struct uba_device *ui; 1782618Swnj { 1792618Swnj register struct buf *bp, *dp; 1802981Swnj register struct uba_ctlr *um; 1812618Swnj register struct rkdevice *rkaddr; 1822618Swnj int didie = 0; 1831899Swnj 1842618Swnj if (ui == 0) 1852618Swnj return (0); 1862618Swnj dk_busy &= ~(1<<ui->ui_dk); 1872618Swnj dp = &rkutab[ui->ui_unit]; 1882618Swnj um = ui->ui_mi; 1892894Swnj rkaddr = (struct rkdevice *)um->um_addr; 1902618Swnj if (um->um_tab.b_active) { 1912618Swnj rk_softc[um->um_ctlr].sc_softas |= 1<<ui->ui_slave; 1922618Swnj return (0); 1932618Swnj } 1942618Swnj rkaddr->rkcs1 = RK_CDT|RK_CERR; 1952618Swnj rkaddr->rkcs2 = ui->ui_slave; 1962957Swnj rkaddr->rkcs1 = RK_CDT|RK_DCLR|RK_GO; 1972618Swnj rkwait(rkaddr); 1982903Swnj if ((bp = dp->b_actf) == NULL) { 1992903Swnj rkaddr->rkcs1 = RK_CDT|RK_DCLR|RK_GO; 2002903Swnj rkwait(rkaddr); 2012903Swnj return (0); 2022903Swnj } 2032618Swnj if ((rkaddr->rkds & RK_VV) == 0) { 2042618Swnj /* SHOULD WARN SYSTEM THAT THIS HAPPENED */ 2052894Swnj rkaddr->rkcs1 = RK_CDT|RK_PACK|RK_GO; 2062618Swnj rkwait(rkaddr); 2072618Swnj } 2082903Swnj if (dp->b_active) 2092903Swnj goto done; 2102903Swnj dp->b_active = 1; 2112894Swnj if ((rkaddr->rkds & RK_DREADY) != RK_DREADY) 2122894Swnj goto done; 2132618Swnj if (rk_softc[um->um_ctlr].sc_ndrive == 1) 2142618Swnj goto done; 2152618Swnj if (bp->b_cylin == rkcyl[ui->ui_unit]) 2162618Swnj goto done; 2172618Swnj rkaddr->rkcyl = bp->b_cylin; 2182618Swnj rkcyl[ui->ui_unit] = bp->b_cylin; 2192618Swnj rkaddr->rkcs1 = RK_CDT|RK_IE|RK_SEEK|RK_GO; 2202618Swnj didie = 1; 2212618Swnj if (ui->ui_dk >= 0) { 2222618Swnj dk_busy |= 1<<ui->ui_dk; 2232618Swnj dk_seek[ui->ui_dk]++; 2242618Swnj } 2252618Swnj goto out; 2262618Swnj done: 2272618Swnj if (dp->b_active != 2) { 2282618Swnj dp->b_forw = NULL; 2292618Swnj if (um->um_tab.b_actf == NULL) 2302618Swnj um->um_tab.b_actf = dp; 2312618Swnj else 2322618Swnj um->um_tab.b_actl->b_forw = dp; 2332618Swnj um->um_tab.b_actl = dp; 2342618Swnj dp->b_active = 2; 2352618Swnj } 2362618Swnj out: 2372618Swnj return (didie); 2382618Swnj } 2392618Swnj 2402618Swnj rkstart(um) 2412981Swnj register struct uba_ctlr *um; 2421899Swnj { 2432618Swnj register struct buf *bp, *dp; 2442981Swnj register struct uba_device *ui; 2452618Swnj register struct rkdevice *rkaddr; 2462618Swnj struct rkst *st; 2471899Swnj daddr_t bn; 2482618Swnj int sn, tn, cmd; 2491899Swnj 2502618Swnj loop: 2512618Swnj if ((dp = um->um_tab.b_actf) == NULL) 2522618Swnj return (0); 2532618Swnj if ((bp = dp->b_actf) == NULL) { 2542618Swnj um->um_tab.b_actf = dp->b_forw; 2552618Swnj goto loop; 2561899Swnj } 2572618Swnj um->um_tab.b_active++; 2582618Swnj ui = rkdinfo[dkunit(bp)]; 2592618Swnj bn = dkblock(bp); 2602618Swnj st = &rkst[ui->ui_type]; 2612618Swnj sn = bn%st->nspc; 2622618Swnj tn = sn/st->nsect; 2632618Swnj sn %= st->nsect; 2642618Swnj rkaddr = (struct rkdevice *)ui->ui_addr; 2652957Swnj retry: 2662618Swnj rkaddr->rkcs1 = RK_CDT|RK_CERR; 2672618Swnj rkaddr->rkcs2 = ui->ui_slave; 2682957Swnj rkaddr->rkcs1 = RK_CDT|RK_DCLR|RK_GO; 2692618Swnj rkwait(rkaddr); 2702957Swnj if ((rkaddr->rkds&RK_SVAL) == 0) { 2712957Swnj rknosval++; 2722957Swnj goto nosval; 2732894Swnj } 2742957Swnj if (rkaddr->rkds&RK_PIP) { 2752957Swnj rkpip++; 2762957Swnj goto retry; 2772957Swnj } 2782894Swnj if ((rkaddr->rkds&RK_DREADY) != RK_DREADY) { 2792927Swnj printf("rk%d: not ready", dkunit(bp)); 2802894Swnj if ((rkaddr->rkds&RK_DREADY) != RK_DREADY) { 2812894Swnj printf("\n"); 2822894Swnj rkaddr->rkcs1 = RK_CDT|RK_DCLR|RK_GO; 2832894Swnj rkwait(rkaddr); 2842894Swnj rkaddr->rkcs1 = RK_CDT|RK_CERR; 2852894Swnj rkwait(rkaddr); 2862894Swnj um->um_tab.b_active = 0; 2872894Swnj um->um_tab.b_errcnt = 0; 2882894Swnj dp->b_actf = bp->av_forw; 2892894Swnj dp->b_active = 0; 2902894Swnj bp->b_flags |= B_ERROR; 2912894Swnj iodone(bp); 2922894Swnj goto loop; 2932894Swnj } 2942894Swnj printf(" (came back!)\n"); 2952894Swnj } 2962957Swnj nosval: 2972618Swnj rkaddr->rkcyl = bp->b_cylin; 2982618Swnj rkcyl[ui->ui_unit] = bp->b_cylin; 2992618Swnj rkaddr->rkda = (tn << 8) + sn; 3002618Swnj rkaddr->rkwc = -bp->b_bcount / sizeof (short); 3012618Swnj if (bp->b_flags & B_READ) 3022618Swnj cmd = RK_CDT|RK_IE|RK_READ|RK_GO; 3032618Swnj else 3042618Swnj cmd = RK_CDT|RK_IE|RK_WRITE|RK_GO; 3052618Swnj um->um_cmd = cmd; 3063104Swnj (void) ubago(ui); 3072618Swnj return (1); 3081899Swnj } 3091899Swnj 3102618Swnj rkdgo(um) 3112981Swnj register struct uba_ctlr *um; 3121899Swnj { 3132618Swnj register struct rkdevice *rkaddr = (struct rkdevice *)um->um_addr; 3141899Swnj 3152618Swnj rkaddr->rkba = um->um_ubinfo; 3162618Swnj rkaddr->rkcs1 = um->um_cmd|((um->um_ubinfo>>8)&0x300); 3172618Swnj } 3182618Swnj 3192710Swnj rkintr(rk11) 3202618Swnj int rk11; 3212618Swnj { 3222981Swnj register struct uba_ctlr *um = rkminfo[rk11]; 3232981Swnj register struct uba_device *ui; 3242618Swnj register struct rkdevice *rkaddr = (struct rkdevice *)um->um_addr; 3252618Swnj register struct buf *bp, *dp; 3262618Swnj int unit; 3272618Swnj struct rk_softc *sc = &rk_softc[um->um_ctlr]; 3282618Swnj int as = (rkaddr->rkatt >> 8) | sc->sc_softas; 3292618Swnj int needie = 1; 3302618Swnj 3312618Swnj sc->sc_wticks = 0; 3322618Swnj sc->sc_softas = 0; 3332618Swnj if (um->um_tab.b_active) { 3342957Swnj ubadone(um); 3352618Swnj dp = um->um_tab.b_actf; 3362618Swnj bp = dp->b_actf; 3372618Swnj ui = rkdinfo[dkunit(bp)]; 3382618Swnj dk_busy &= ~(1 << ui->ui_dk); 3392618Swnj if (rkaddr->rkcs1 & RK_CERR) { 3402618Swnj int recal; 3412618Swnj u_short ds = rkaddr->rkds; 3422618Swnj u_short cs2 = rkaddr->rkcs2; 3432618Swnj u_short er = rkaddr->rker; 3442685Swnj if (ds & RK_WLE) { 3452927Swnj printf("rk%d: write locked\n", dkunit(bp)); 3462685Swnj bp->b_flags |= B_ERROR; 3472685Swnj } else if (++um->um_tab.b_errcnt > 28 || 3482676Swnj ds&RKDS_HARD || er&RKER_HARD || cs2&RKCS2_HARD) { 3492927Swnj harderr(bp, "rk"); 3502927Swnj printf("cs2=%b ds=%b er=%b\n", 3512894Swnj cs2, RKCS2_BITS, ds, 3522676Swnj RKDS_BITS, er, RKER_BITS); 3533145Swnj bp->b_flags |= B_ERROR; 3543145Swnj sc->sc_recal = 0; 3552676Swnj } else 3562618Swnj um->um_tab.b_active = 0; 3572618Swnj if (cs2&RK_MDS) { 3582618Swnj rkaddr->rkcs2 = RK_SCLR; 3592618Swnj goto retry; 3601899Swnj } 3612618Swnj recal = 0; 3622618Swnj if (ds&RK_DROT || er&(RK_OPI|RK_SKI|RK_UNS) || 3632618Swnj (um->um_tab.b_errcnt&07) == 4) 3642618Swnj recal = 1; 3652618Swnj if ((er & (RK_DCK|RK_ECH)) == RK_DCK) 3662618Swnj if (rkecc(ui)) 3672618Swnj return; 3682618Swnj rkaddr->rkcs1 = RK_CDT|RK_CCLR; 3692618Swnj rkaddr->rkcs2 = ui->ui_slave; 3702618Swnj rkaddr->rkcs1 = RK_CDT|RK_DCLR|RK_GO; 3712618Swnj rkwait(rkaddr); 3722618Swnj if (recal && um->um_tab.b_active == 0) { 3732618Swnj rkaddr->rkcs1 = RK_CDT|RK_IE|RK_RECAL|RK_GO; 3742618Swnj rkcyl[ui->ui_unit] = -1; 3752957Swnj sc->sc_recal = 0; 3762957Swnj goto nextrecal; 3772618Swnj } 3781899Swnj } 3792618Swnj retry: 3802957Swnj switch (sc->sc_recal) { 3812957Swnj 3822957Swnj case 1: 3832957Swnj rkaddr->rkcyl = bp->b_cylin; 3842957Swnj rkcyl[ui->ui_unit] = bp->b_cylin; 3852957Swnj rkaddr->rkcs1 = RK_CDT|RK_IE|RK_SEEK|RK_GO; 3862957Swnj goto nextrecal; 3872957Swnj case 2: 3882957Swnj if (um->um_tab.b_errcnt < 16 || 3892957Swnj (bp->b_flags&B_READ) != 0) 3903159Swnj goto donerecal; 3912957Swnj rkaddr->rkatt = rk_offset[um->um_tab.b_errcnt & 017]; 3922957Swnj rkaddr->rkcs1 = RK_CDT|RK_IE|RK_OFFSET|RK_GO; 3932957Swnj /* fall into ... */ 3942957Swnj nextrecal: 3952957Swnj sc->sc_recal++; 3962957Swnj rkwait(rkaddr); 3972957Swnj um->um_tab.b_active = 1; 3982957Swnj return; 3993159Swnj donerecal: 4002957Swnj case 3: 4012618Swnj sc->sc_recal = 0; 4022618Swnj um->um_tab.b_active = 0; 4032957Swnj break; 4041899Swnj } 4052618Swnj if (um->um_tab.b_active) { 4062618Swnj um->um_tab.b_active = 0; 4072618Swnj um->um_tab.b_errcnt = 0; 4082618Swnj um->um_tab.b_actf = dp->b_forw; 4092618Swnj dp->b_active = 0; 4102618Swnj dp->b_errcnt = 0; 4112618Swnj dp->b_actf = bp->av_forw; 4122618Swnj bp->b_resid = -rkaddr->rkwc * sizeof(short); 4132618Swnj iodone(bp); 4142618Swnj if (dp->b_actf) 4152618Swnj if (rkustart(ui)) 4162618Swnj needie = 0; 4171899Swnj } 4182618Swnj as &= ~(1<<ui->ui_slave); 4191899Swnj } 4202618Swnj for (unit = 0; as; as >>= 1, unit++) 4212981Swnj if (as & 1) { 4222981Swnj ui = rkip[rk11][unit]; 4232981Swnj if (ui) { 4242981Swnj if (rkustart(rkip[rk11][unit])) 4252981Swnj needie = 0; 4262981Swnj } else { 4272981Swnj rkaddr->rkcs1 = RK_CERR|RK_CDT; 4282981Swnj rkaddr->rkcs2 = unit; 4292981Swnj rkaddr->rkcs1 = RK_CDT|RK_DCLR|RK_GO; 4302981Swnj rkwait(rkaddr); 4312981Swnj } 4322981Swnj } 4332618Swnj if (um->um_tab.b_actf && um->um_tab.b_active == 0) 4342618Swnj if (rkstart(um)) 4352618Swnj needie = 0; 4362618Swnj if (needie) 4372618Swnj rkaddr->rkcs1 = RK_CDT|RK_IE; 4381899Swnj } 4391899Swnj 4402618Swnj rkwait(addr) 4412618Swnj register struct rkdevice *addr; 4422618Swnj { 4431899Swnj 4442618Swnj while ((addr->rkcs1 & RK_CRDY) == 0) 4452618Swnj ; 4462618Swnj } 4472618Swnj 4482618Swnj rkread(dev) 4492618Swnj dev_t dev; 4501899Swnj { 4512618Swnj register int unit = minor(dev) >> 3; 4522618Swnj 4532648Swnj if (unit >= NRK) 4542618Swnj u.u_error = ENXIO; 4552618Swnj else 4562618Swnj physio(rkstrategy, &rrkbuf[unit], dev, B_READ, minphys); 4571899Swnj } 4581899Swnj 4592618Swnj rkwrite(dev) 4602618Swnj dev_t dev; 4611899Swnj { 4622618Swnj register int unit = minor(dev) >> 3; 4631899Swnj 4642648Swnj if (unit >= NRK) 4652618Swnj u.u_error = ENXIO; 4662618Swnj else 4672618Swnj physio(rkstrategy, &rrkbuf[unit], dev, B_WRITE, minphys); 4681899Swnj } 4691899Swnj 4702618Swnj rkecc(ui) 4712981Swnj register struct uba_device *ui; 4721899Swnj { 4732618Swnj register struct rkdevice *rk = (struct rkdevice *)ui->ui_addr; 4742618Swnj register struct buf *bp = rkutab[ui->ui_unit].b_actf; 4752981Swnj register struct uba_ctlr *um = ui->ui_mi; 4762618Swnj register struct rkst *st; 4772618Swnj struct uba_regs *ubp = ui->ui_hd->uh_uba; 4782618Swnj register int i; 4792618Swnj caddr_t addr; 4802618Swnj int reg, bit, byte, npf, mask, o, cmd, ubaddr; 4812618Swnj int bn, cn, tn, sn; 4821899Swnj 4832618Swnj npf = btop((rk->rkwc * sizeof(short)) + bp->b_bcount) - 1; 4842618Swnj reg = btop(um->um_ubinfo&0x3ffff) + npf; 4852618Swnj o = (int)bp->b_un.b_addr & PGOFSET; 4862940Swnj printf("rk%d%c: soft ecc sn%d\n", dkunit(bp), 4872885Swnj 'a'+(minor(bp->b_dev)&07), bp->b_blkno + npf); 4882618Swnj mask = rk->rkec2; 4892724Swnj ubapurge(um); 4902618Swnj i = rk->rkec1 - 1; /* -1 makes 0 origin */ 4912618Swnj bit = i&07; 4922618Swnj i = (i&~07)>>3; 4932618Swnj byte = i + o; 4942618Swnj while (i < 512 && (int)ptob(npf)+i < bp->b_bcount && bit > -11) { 4952618Swnj addr = ptob(ubp->uba_map[reg+btop(byte)].pg_pfnum)+ 4962618Swnj (byte & PGOFSET); 4972618Swnj putmemc(addr, getmemc(addr)^(mask<<bit)); 4982618Swnj byte++; 4992618Swnj i++; 5002618Swnj bit -= 8; 5012618Swnj } 5022618Swnj um->um_tab.b_active++; /* Either complete or continuing... */ 5032618Swnj if (rk->rkwc == 0) 5042618Swnj return (0); 5052622Swnj #ifdef notdef 5062622Swnj rk->rkcs1 |= RK_GO; 5072622Swnj #else 5082618Swnj rk->rkcs1 = RK_CDT|RK_CCLR; 5092618Swnj rk->rkcs2 = ui->ui_slave; 5102618Swnj rk->rkcs1 = RK_CDT|RK_DCLR|RK_GO; 5112618Swnj rkwait(rk); 5122618Swnj bn = dkblock(bp); 5132618Swnj st = &rkst[ui->ui_type]; 5142618Swnj cn = bp->b_cylin; 5152618Swnj sn = bn%st->nspc + npf + 1; 5162618Swnj tn = sn/st->nsect; 5172618Swnj sn %= st->nsect; 5182618Swnj cn += tn/st->ntrak; 5192618Swnj tn %= st->ntrak; 5202618Swnj rk->rkcyl = cn; 5212618Swnj rk->rkda = (tn << 8) | sn; 5222618Swnj ubaddr = (int)ptob(reg+1) + o; 5232618Swnj rk->rkba = ubaddr; 5242618Swnj cmd = (ubaddr >> 8) & 0x300; 5252618Swnj cmd |= RK_CDT|RK_IE|RK_GO|RK_READ; 5262618Swnj rk->rkcs1 = cmd; 5272622Swnj #endif 5282618Swnj return (1); 5291899Swnj } 5301899Swnj 5312618Swnj rkreset(uban) 5322927Swnj int uban; 5331899Swnj { 5342981Swnj register struct uba_ctlr *um; 5352981Swnj register struct uba_device *ui; 5362618Swnj register rk11, unit; 5371899Swnj 5382648Swnj for (rk11 = 0; rk11 < NHK; rk11++) { 5392618Swnj if ((um = rkminfo[rk11]) == 0 || um->um_ubanum != uban || 5402618Swnj um->um_alive == 0) 5412618Swnj continue; 5422927Swnj printf(" hk%d", rk11); 5432618Swnj um->um_tab.b_active = 0; 5442618Swnj um->um_tab.b_actf = um->um_tab.b_actl = 0; 5452618Swnj rk_softc[um->um_ctlr].sc_recal = 0; 5462618Swnj if (um->um_ubinfo) { 5472618Swnj printf("<%d>", (um->um_ubinfo>>28)&0xf); 5482618Swnj ubadone(um); 5492618Swnj } 5502648Swnj for (unit = 0; unit < NHK; unit++) { 5512618Swnj if ((ui = rkdinfo[unit]) == 0) 5522618Swnj continue; 5532618Swnj if (ui->ui_alive == 0) 5542618Swnj continue; 5552618Swnj rkutab[unit].b_active = 0; 5562618Swnj (void) rkustart(ui); 5572618Swnj } 5582618Swnj (void) rkstart(um); 5592618Swnj } 5601899Swnj } 5612380Swnj 5622618Swnj rkwatch() 5632380Swnj { 5642981Swnj register struct uba_ctlr *um; 5652618Swnj register rk11, unit; 5662618Swnj register struct rk_softc *sc; 5672380Swnj 5682758Swnj timeout(rkwatch, (caddr_t)0, hz); 5692648Swnj for (rk11 = 0; rk11 < NHK; rk11++) { 5702618Swnj um = rkminfo[rk11]; 5712618Swnj if (um == 0 || um->um_alive == 0) 5722618Swnj continue; 5732618Swnj sc = &rk_softc[rk11]; 5742618Swnj if (um->um_tab.b_active == 0) { 5752648Swnj for (unit = 0; unit < NRK; unit++) 5762622Swnj if (rkutab[unit].b_active && 5772622Swnj rkdinfo[unit]->ui_mi == um) 5782618Swnj goto active; 5792618Swnj sc->sc_wticks = 0; 5802618Swnj continue; 5812618Swnj } 5822618Swnj active: 5832618Swnj sc->sc_wticks++; 5842618Swnj if (sc->sc_wticks >= 20) { 5852618Swnj sc->sc_wticks = 0; 5862927Swnj printf("hk%d: lost interrupt\n", rk11); 5872648Swnj ubareset(um->um_ubanum); 5882618Swnj } 5892618Swnj } 5902380Swnj } 5912618Swnj 5922618Swnj #define DBSIZE 20 5932618Swnj 5942618Swnj rkdump(dev) 5952618Swnj dev_t dev; 5962618Swnj { 5972618Swnj struct rkdevice *rkaddr; 5982618Swnj char *start; 5992618Swnj int num, blk, unit; 6002618Swnj struct size *sizes; 6012618Swnj register struct uba_regs *uba; 6022981Swnj register struct uba_device *ui; 6032618Swnj register short *rp; 6042618Swnj struct rkst *st; 6052618Swnj 6062618Swnj unit = minor(dev) >> 3; 6072885Swnj if (unit >= NRK) 6082885Swnj return (ENXIO); 6092618Swnj #define phys(cast, addr) ((cast)((int)addr & 0x7fffffff)) 6102981Swnj ui = phys(struct uba_device *, rkdinfo[unit]); 6112885Swnj if (ui->ui_alive == 0) 6122885Swnj return (ENXIO); 6132618Swnj uba = phys(struct uba_hd *, ui->ui_hd)->uh_physuba; 6142618Swnj #if VAX780 6152618Swnj if (cpu == VAX_780) 6162618Swnj ubainit(uba); 6171899Swnj #endif 6182618Swnj rkaddr = (struct rkdevice *)ui->ui_physaddr; 6192618Swnj num = maxfree; 6202618Swnj start = 0; 6212618Swnj rkaddr->rkcs1 = RK_CDT|RK_CERR; 6222618Swnj rkaddr->rkcs2 = unit; 6232618Swnj rkaddr->rkcs1 = RK_CDT|RK_DCLR|RK_GO; 6242618Swnj rkwait(rkaddr); 6252618Swnj if ((rkaddr->rkds & RK_VV) == 0) { 6262618Swnj rkaddr->rkcs1 = RK_CDT|RK_IE|RK_PACK|RK_GO; 6272618Swnj rkwait(rkaddr); 6282618Swnj } 6292618Swnj st = &rkst[ui->ui_type]; 6302618Swnj sizes = phys(struct size *, st->sizes); 6312885Swnj if (dumplo < 0 || dumplo + num >= sizes[minor(dev)&07].nblocks) 6322885Swnj return (EINVAL); 6332618Swnj while (num > 0) { 6342618Swnj register struct pte *io; 6352618Swnj register int i; 6362618Swnj int cn, sn, tn; 6372618Swnj daddr_t bn; 6382618Swnj 6392618Swnj blk = num > DBSIZE ? DBSIZE : num; 6402618Swnj io = uba->uba_map; 6412618Swnj for (i = 0; i < blk; i++) 6422981Swnj *(int *)io++ = (btop(start)+i) | (1<<21) | UBAMR_MRV; 6432618Swnj *(int *)io = 0; 6442618Swnj bn = dumplo + btop(start); 6452618Swnj cn = bn/st->nspc + sizes[minor(dev)&07].cyloff; 6462618Swnj sn = bn%st->nspc; 6472618Swnj tn = sn/st->nsect; 6482618Swnj sn = sn%st->nsect; 6492618Swnj rkaddr->rkcyl = cn; 6502618Swnj rp = (short *) &rkaddr->rkda; 6512618Swnj *rp = (tn << 8) + sn; 6522618Swnj *--rp = 0; 6532618Swnj *--rp = -blk*NBPG / sizeof (short); 6542618Swnj *--rp = RK_CDT|RK_GO|RK_WRITE; 6552618Swnj rkwait(rkaddr); 6562885Swnj if (rkaddr->rkcs1 & RK_CERR) 6572885Swnj return (EIO); 6582618Swnj start += blk*NBPG; 6592618Swnj num -= blk; 6602618Swnj } 6612618Swnj return (0); 6622618Swnj } 6632618Swnj #endif 664