1*3293Swnj /* rk.c 4.31 81/03/17 */ 21899Swnj 31942Swnj #include "rk.h" 42648Swnj #if NHK > 0 53104Swnj int rkpip; /* DEBUG */ 63104Swnj int rknosval; /* DEBUG */ 7*3293Swnj int rkdebug; 81899Swnj /* 9*3293Swnj * RK611/RK0[67] disk driver 102622Swnj * 112622Swnj * This driver mimics up.c; see it for an explanation of common code. 122685Swnj * 132885Swnj * TODO: 143208Swnj * Learn why we lose an interrupt sometime when spinning drives down 15*3293Swnj * Support rk06 161899Swnj */ 171899Swnj #include "../h/param.h" 181899Swnj #include "../h/systm.h" 191899Swnj #include "../h/buf.h" 201899Swnj #include "../h/conf.h" 211899Swnj #include "../h/dir.h" 221899Swnj #include "../h/user.h" 231899Swnj #include "../h/pte.h" 241899Swnj #include "../h/map.h" 252618Swnj #include "../h/vm.h" 262981Swnj #include "../h/ubareg.h" 272981Swnj #include "../h/ubavar.h" 281899Swnj #include "../h/dk.h" 292618Swnj #include "../h/cpu.h" 302618Swnj #include "../h/cmap.h" 311899Swnj 322618Swnj #include "../h/rkreg.h" 331899Swnj 342618Swnj struct rk_softc { 352618Swnj int sc_softas; 362618Swnj int sc_ndrive; 372618Swnj int sc_wticks; 382618Swnj int sc_recal; 392648Swnj } rk_softc[NHK]; 401899Swnj 412618Swnj /* THIS SHOULD BE READ OFF THE PACK, PER DRIVE */ 422787Swnj struct size { 432618Swnj daddr_t nblocks; 442618Swnj int cyloff; 452618Swnj } rk7_sizes[] ={ 462618Swnj 15884, 0, /* A=cyl 0 thru 240 */ 472665Swnj 10032, 241, /* B=cyl 241 thru 392 */ 482665Swnj 53790, 0, /* C=cyl 0 thru 814 */ 492618Swnj 0, 0, 502618Swnj 0, 0, 512618Swnj 0, 0, 522618Swnj 27786, 393, /* G=cyl 393 thru 813 */ 532618Swnj 0, 0, 542618Swnj }; 552618Swnj /* END OF STUFF WHICH SHOULD BE READ IN PER DISK */ 561899Swnj 572618Swnj int rkprobe(), rkslave(), rkattach(), rkdgo(), rkintr(); 582981Swnj struct uba_ctlr *rkminfo[NHK]; 592981Swnj struct uba_device *rkdinfo[NRK]; 602981Swnj struct uba_device *rkip[NHK][4]; 611899Swnj 622618Swnj u_short rkstd[] = { 0777440, 0 }; 632618Swnj struct uba_driver hkdriver = 642622Swnj { rkprobe, rkslave, rkattach, rkdgo, rkstd, "rk", rkdinfo, "hk", rkminfo, 1 }; 652648Swnj struct buf rkutab[NRK]; 662648Swnj short rkcyl[NRK]; 671899Swnj 682618Swnj struct rkst { 692618Swnj short nsect; 702618Swnj short ntrak; 712618Swnj short nspc; 722618Swnj short ncyl; 732618Swnj struct size *sizes; 742618Swnj } rkst[] = { 752618Swnj NRKSECT, NRKTRK, NRKSECT*NRKTRK, NRK7CYL, rk7_sizes, 762618Swnj }; 771899Swnj 782618Swnj u_char rk_offset[16] = 79*3293Swnj { RKAS_P400,RKAS_M400,RKAS_P400,RKAS_M400,RKAS_P800,RKAS_M800,RKAS_P800, 80*3293Swnj RKAS_M800,RKAS_P1200,RKAS_M1200,RKAS_P1200,RKAS_M1200,0,0,0,0 81*3293Swnj }; 821899Swnj 832648Swnj struct buf rrkbuf[NRK]; 842618Swnj 852618Swnj #define b_cylin b_resid 862618Swnj 872618Swnj #ifdef INTRLVE 882618Swnj daddr_t dkblock(); 892618Swnj #endif 902618Swnj 912618Swnj int rkwstart, rkwatch(); 922618Swnj 932618Swnj rkprobe(reg) 942618Swnj caddr_t reg; 951899Swnj { 962618Swnj register int br, cvec; 971899Swnj 982618Swnj #ifdef lint 992618Swnj br = 0; cvec = br; br = cvec; 1002618Swnj #endif 1012618Swnj ((struct rkdevice *)reg)->rkcs1 = RK_CDT|RK_IE|RK_CRDY; 1022618Swnj DELAY(10); 1032618Swnj ((struct rkdevice *)reg)->rkcs1 = RK_CDT; 1042618Swnj return (1); 1052618Swnj } 1061899Swnj 1072618Swnj rkslave(ui, reg) 1082981Swnj struct uba_device *ui; 1092618Swnj caddr_t reg; 1102618Swnj { 1112618Swnj register struct rkdevice *rkaddr = (struct rkdevice *)reg; 1121899Swnj 1132894Swnj rkaddr->rkcs1 = RK_CDT|RK_CCLR; 1142618Swnj rkaddr->rkcs2 = ui->ui_slave; 1152957Swnj rkaddr->rkcs1 = RK_CDT|RK_DCLR|RK_GO; 1162622Swnj rkwait(rkaddr); 1172894Swnj DELAY(50); 118*3293Swnj if (rkaddr->rkcs2&RKCS2_NED || (rkaddr->rkds&RKDS_SVAL) == 0) { 1192618Swnj rkaddr->rkcs1 = RK_CDT|RK_CCLR; 1202618Swnj return (0); 1212618Swnj } 1222618Swnj return (1); 1232618Swnj } 1242618Swnj 1252618Swnj rkattach(ui) 1262981Swnj register struct uba_device *ui; 1272618Swnj { 1282618Swnj 1292618Swnj if (rkwstart == 0) { 1302758Swnj timeout(rkwatch, (caddr_t)0, hz); 1312618Swnj rkwstart++; 1322618Swnj } 1332618Swnj if (ui->ui_dk >= 0) 1342758Swnj dk_mspw[ui->ui_dk] = 1.0 / (60 * NRKSECT * 256); 1352618Swnj rkip[ui->ui_ctlr][ui->ui_slave] = ui; 1362618Swnj rk_softc[ui->ui_ctlr].sc_ndrive++; 1372618Swnj rkcyl[ui->ui_unit] = -1; 1382618Swnj } 1392618Swnj 1401899Swnj rkstrategy(bp) 1412618Swnj register struct buf *bp; 1421899Swnj { 1432981Swnj register struct uba_device *ui; 1442618Swnj register struct rkst *st; 1452618Swnj register int unit; 1462618Swnj register struct buf *dp; 1472618Swnj int xunit = minor(bp->b_dev) & 07; 1482618Swnj long bn, sz; 1491899Swnj 1502618Swnj sz = (bp->b_bcount+511) >> 9; 1512618Swnj unit = dkunit(bp); 1522648Swnj if (unit >= NRK) 1532618Swnj goto bad; 1542618Swnj ui = rkdinfo[unit]; 1552618Swnj if (ui == 0 || ui->ui_alive == 0) 1562618Swnj goto bad; 1572618Swnj st = &rkst[ui->ui_type]; 1582618Swnj if (bp->b_blkno < 0 || 1592618Swnj (bn = dkblock(bp))+sz > st->sizes[xunit].nblocks) 1602618Swnj goto bad; 1612618Swnj bp->b_cylin = bn/st->nspc + st->sizes[xunit].cyloff; 1622618Swnj (void) spl5(); 1632618Swnj dp = &rkutab[ui->ui_unit]; 1642618Swnj disksort(dp, bp); 1652618Swnj if (dp->b_active == 0) { 1662618Swnj (void) rkustart(ui); 1672618Swnj bp = &ui->ui_mi->um_tab; 1682618Swnj if (bp->b_actf && bp->b_active == 0) 1692618Swnj (void) rkstart(ui->ui_mi); 1701899Swnj } 1712618Swnj (void) spl0(); 1722618Swnj return; 1732618Swnj 1742618Swnj bad: 1752618Swnj bp->b_flags |= B_ERROR; 1762618Swnj iodone(bp); 1772618Swnj return; 1781899Swnj } 1791899Swnj 1802618Swnj rkustart(ui) 1812981Swnj register struct uba_device *ui; 1822618Swnj { 1832618Swnj register struct buf *bp, *dp; 1842981Swnj register struct uba_ctlr *um; 1852618Swnj register struct rkdevice *rkaddr; 1862618Swnj int didie = 0; 1871899Swnj 1882618Swnj if (ui == 0) 1892618Swnj return (0); 1902618Swnj dk_busy &= ~(1<<ui->ui_dk); 1912618Swnj dp = &rkutab[ui->ui_unit]; 1922618Swnj um = ui->ui_mi; 1932894Swnj rkaddr = (struct rkdevice *)um->um_addr; 1942618Swnj if (um->um_tab.b_active) { 1952618Swnj rk_softc[um->um_ctlr].sc_softas |= 1<<ui->ui_slave; 1962618Swnj return (0); 1972618Swnj } 1982618Swnj rkaddr->rkcs1 = RK_CDT|RK_CERR; 1992618Swnj rkaddr->rkcs2 = ui->ui_slave; 2002957Swnj rkaddr->rkcs1 = RK_CDT|RK_DCLR|RK_GO; 2012618Swnj rkwait(rkaddr); 2022903Swnj if ((bp = dp->b_actf) == NULL) { 2032903Swnj rkaddr->rkcs1 = RK_CDT|RK_DCLR|RK_GO; 2042903Swnj rkwait(rkaddr); 2052903Swnj return (0); 2062903Swnj } 207*3293Swnj if ((rkaddr->rkds & RKDS_VV) == 0) { 2082618Swnj /* SHOULD WARN SYSTEM THAT THIS HAPPENED */ 2092894Swnj rkaddr->rkcs1 = RK_CDT|RK_PACK|RK_GO; 2102618Swnj rkwait(rkaddr); 2112618Swnj } 2122903Swnj if (dp->b_active) 2132903Swnj goto done; 2142903Swnj dp->b_active = 1; 215*3293Swnj if ((rkaddr->rkds & RKDS_DREADY) != RKDS_DREADY) 2162894Swnj goto done; 2172618Swnj if (rk_softc[um->um_ctlr].sc_ndrive == 1) 2182618Swnj goto done; 2192618Swnj if (bp->b_cylin == rkcyl[ui->ui_unit]) 2202618Swnj goto done; 2212618Swnj rkaddr->rkcyl = bp->b_cylin; 2222618Swnj rkcyl[ui->ui_unit] = bp->b_cylin; 2232618Swnj rkaddr->rkcs1 = RK_CDT|RK_IE|RK_SEEK|RK_GO; 2242618Swnj didie = 1; 2252618Swnj if (ui->ui_dk >= 0) { 2262618Swnj dk_busy |= 1<<ui->ui_dk; 2272618Swnj dk_seek[ui->ui_dk]++; 2282618Swnj } 2292618Swnj goto out; 2302618Swnj done: 2312618Swnj if (dp->b_active != 2) { 2322618Swnj dp->b_forw = NULL; 2332618Swnj if (um->um_tab.b_actf == NULL) 2342618Swnj um->um_tab.b_actf = dp; 2352618Swnj else 2362618Swnj um->um_tab.b_actl->b_forw = dp; 2372618Swnj um->um_tab.b_actl = dp; 2382618Swnj dp->b_active = 2; 2392618Swnj } 2402618Swnj out: 2412618Swnj return (didie); 2422618Swnj } 2432618Swnj 2442618Swnj rkstart(um) 2452981Swnj register struct uba_ctlr *um; 2461899Swnj { 2472618Swnj register struct buf *bp, *dp; 2482981Swnj register struct uba_device *ui; 2492618Swnj register struct rkdevice *rkaddr; 2502618Swnj struct rkst *st; 2511899Swnj daddr_t bn; 2522618Swnj int sn, tn, cmd; 2531899Swnj 2542618Swnj loop: 2552618Swnj if ((dp = um->um_tab.b_actf) == NULL) 2562618Swnj return (0); 2572618Swnj if ((bp = dp->b_actf) == NULL) { 2582618Swnj um->um_tab.b_actf = dp->b_forw; 2592618Swnj goto loop; 2601899Swnj } 2612618Swnj um->um_tab.b_active++; 2622618Swnj ui = rkdinfo[dkunit(bp)]; 2632618Swnj bn = dkblock(bp); 2642618Swnj st = &rkst[ui->ui_type]; 2652618Swnj sn = bn%st->nspc; 2662618Swnj tn = sn/st->nsect; 2672618Swnj sn %= st->nsect; 2682618Swnj rkaddr = (struct rkdevice *)ui->ui_addr; 2692957Swnj retry: 2702618Swnj rkaddr->rkcs1 = RK_CDT|RK_CERR; 2712618Swnj rkaddr->rkcs2 = ui->ui_slave; 2722957Swnj rkaddr->rkcs1 = RK_CDT|RK_DCLR|RK_GO; 2732618Swnj rkwait(rkaddr); 274*3293Swnj if ((rkaddr->rkds&RKDS_SVAL) == 0) { 2752957Swnj rknosval++; 2762957Swnj goto nosval; 2772894Swnj } 278*3293Swnj if (rkaddr->rkds&RKDS_PIP) { 2792957Swnj rkpip++; 2802957Swnj goto retry; 2812957Swnj } 282*3293Swnj if ((rkaddr->rkds&RKDS_DREADY) != RKDS_DREADY) { 2832927Swnj printf("rk%d: not ready", dkunit(bp)); 284*3293Swnj if ((rkaddr->rkds&RKDS_DREADY) != RKDS_DREADY) { 2852894Swnj printf("\n"); 2862894Swnj rkaddr->rkcs1 = RK_CDT|RK_DCLR|RK_GO; 2872894Swnj rkwait(rkaddr); 2882894Swnj rkaddr->rkcs1 = RK_CDT|RK_CERR; 2892894Swnj rkwait(rkaddr); 2902894Swnj um->um_tab.b_active = 0; 2912894Swnj um->um_tab.b_errcnt = 0; 2922894Swnj dp->b_actf = bp->av_forw; 2932894Swnj dp->b_active = 0; 2942894Swnj bp->b_flags |= B_ERROR; 2952894Swnj iodone(bp); 2962894Swnj goto loop; 2972894Swnj } 2982894Swnj printf(" (came back!)\n"); 2992894Swnj } 3002957Swnj nosval: 3012618Swnj rkaddr->rkcyl = bp->b_cylin; 3022618Swnj rkcyl[ui->ui_unit] = bp->b_cylin; 3032618Swnj rkaddr->rkda = (tn << 8) + sn; 3042618Swnj rkaddr->rkwc = -bp->b_bcount / sizeof (short); 3052618Swnj if (bp->b_flags & B_READ) 3062618Swnj cmd = RK_CDT|RK_IE|RK_READ|RK_GO; 3072618Swnj else 3082618Swnj cmd = RK_CDT|RK_IE|RK_WRITE|RK_GO; 3092618Swnj um->um_cmd = cmd; 3103104Swnj (void) ubago(ui); 3112618Swnj return (1); 3121899Swnj } 3131899Swnj 3142618Swnj rkdgo(um) 3152981Swnj register struct uba_ctlr *um; 3161899Swnj { 3172618Swnj register struct rkdevice *rkaddr = (struct rkdevice *)um->um_addr; 3181899Swnj 3192618Swnj rkaddr->rkba = um->um_ubinfo; 3202618Swnj rkaddr->rkcs1 = um->um_cmd|((um->um_ubinfo>>8)&0x300); 3212618Swnj } 3222618Swnj 3232710Swnj rkintr(rk11) 3242618Swnj int rk11; 3252618Swnj { 3262981Swnj register struct uba_ctlr *um = rkminfo[rk11]; 3272981Swnj register struct uba_device *ui; 3282618Swnj register struct rkdevice *rkaddr = (struct rkdevice *)um->um_addr; 3292618Swnj register struct buf *bp, *dp; 3302618Swnj int unit; 3312618Swnj struct rk_softc *sc = &rk_softc[um->um_ctlr]; 3322618Swnj int as = (rkaddr->rkatt >> 8) | sc->sc_softas; 3332618Swnj int needie = 1; 3342618Swnj 3352618Swnj sc->sc_wticks = 0; 3362618Swnj sc->sc_softas = 0; 3372618Swnj if (um->um_tab.b_active) { 3382957Swnj ubadone(um); 3392618Swnj dp = um->um_tab.b_actf; 3402618Swnj bp = dp->b_actf; 3412618Swnj ui = rkdinfo[dkunit(bp)]; 3422618Swnj dk_busy &= ~(1 << ui->ui_dk); 3432618Swnj if (rkaddr->rkcs1 & RK_CERR) { 3442618Swnj int recal; 3452618Swnj u_short ds = rkaddr->rkds; 3462618Swnj u_short cs2 = rkaddr->rkcs2; 3472618Swnj u_short er = rkaddr->rker; 348*3293Swnj if (rkdebug) { 349*3293Swnj printf("cs2=%b ds=%b er=%b\n", 350*3293Swnj cs2, RKCS2_BITS, ds, 351*3293Swnj RKDS_BITS, er, RKER_BITS); 352*3293Swnj } 353*3293Swnj if (er & RKER_WLE) { 3542927Swnj printf("rk%d: write locked\n", dkunit(bp)); 3552685Swnj bp->b_flags |= B_ERROR; 3562685Swnj } else if (++um->um_tab.b_errcnt > 28 || 3572676Swnj ds&RKDS_HARD || er&RKER_HARD || cs2&RKCS2_HARD) { 3582927Swnj harderr(bp, "rk"); 3592927Swnj printf("cs2=%b ds=%b er=%b\n", 3602894Swnj cs2, RKCS2_BITS, ds, 3612676Swnj RKDS_BITS, er, RKER_BITS); 3623145Swnj bp->b_flags |= B_ERROR; 3633145Swnj sc->sc_recal = 0; 3642676Swnj } else 3652618Swnj um->um_tab.b_active = 0; 366*3293Swnj if (cs2&RKCS2_MDS) { 367*3293Swnj rkaddr->rkcs2 = RKCS2_SCLR; 3682618Swnj goto retry; 3691899Swnj } 3702618Swnj recal = 0; 371*3293Swnj if (ds&RKDS_DROT || er&(RKER_OPI|RKER_SKI|RKER_UNS) || 3722618Swnj (um->um_tab.b_errcnt&07) == 4) 3732618Swnj recal = 1; 374*3293Swnj if ((er & (RKER_DCK|RKER_ECH)) == RKER_DCK) 3752618Swnj if (rkecc(ui)) 3762618Swnj return; 3772618Swnj rkaddr->rkcs1 = RK_CDT|RK_CCLR; 3782618Swnj rkaddr->rkcs2 = ui->ui_slave; 3792618Swnj rkaddr->rkcs1 = RK_CDT|RK_DCLR|RK_GO; 3802618Swnj rkwait(rkaddr); 3812618Swnj if (recal && um->um_tab.b_active == 0) { 3822618Swnj rkaddr->rkcs1 = RK_CDT|RK_IE|RK_RECAL|RK_GO; 3832618Swnj rkcyl[ui->ui_unit] = -1; 3842957Swnj sc->sc_recal = 0; 3852957Swnj goto nextrecal; 3862618Swnj } 3871899Swnj } 3882618Swnj retry: 3892957Swnj switch (sc->sc_recal) { 3902957Swnj 3912957Swnj case 1: 3922957Swnj rkaddr->rkcyl = bp->b_cylin; 3932957Swnj rkcyl[ui->ui_unit] = bp->b_cylin; 3942957Swnj rkaddr->rkcs1 = RK_CDT|RK_IE|RK_SEEK|RK_GO; 3952957Swnj goto nextrecal; 3962957Swnj case 2: 3972957Swnj if (um->um_tab.b_errcnt < 16 || 3983290Swnj (bp->b_flags&B_READ) == 0) 3993159Swnj goto donerecal; 4002957Swnj rkaddr->rkatt = rk_offset[um->um_tab.b_errcnt & 017]; 4012957Swnj rkaddr->rkcs1 = RK_CDT|RK_IE|RK_OFFSET|RK_GO; 4022957Swnj /* fall into ... */ 4032957Swnj nextrecal: 4042957Swnj sc->sc_recal++; 4052957Swnj rkwait(rkaddr); 4062957Swnj um->um_tab.b_active = 1; 4072957Swnj return; 4083159Swnj donerecal: 4092957Swnj case 3: 4102618Swnj sc->sc_recal = 0; 4112618Swnj um->um_tab.b_active = 0; 4122957Swnj break; 4131899Swnj } 4142618Swnj if (um->um_tab.b_active) { 4152618Swnj um->um_tab.b_active = 0; 4162618Swnj um->um_tab.b_errcnt = 0; 4172618Swnj um->um_tab.b_actf = dp->b_forw; 4182618Swnj dp->b_active = 0; 4192618Swnj dp->b_errcnt = 0; 4202618Swnj dp->b_actf = bp->av_forw; 4212618Swnj bp->b_resid = -rkaddr->rkwc * sizeof(short); 4222618Swnj iodone(bp); 4232618Swnj if (dp->b_actf) 4242618Swnj if (rkustart(ui)) 4252618Swnj needie = 0; 4261899Swnj } 4272618Swnj as &= ~(1<<ui->ui_slave); 4281899Swnj } 4292618Swnj for (unit = 0; as; as >>= 1, unit++) 4302981Swnj if (as & 1) { 4312981Swnj ui = rkip[rk11][unit]; 4322981Swnj if (ui) { 4332981Swnj if (rkustart(rkip[rk11][unit])) 4342981Swnj needie = 0; 4352981Swnj } else { 4362981Swnj rkaddr->rkcs1 = RK_CERR|RK_CDT; 4372981Swnj rkaddr->rkcs2 = unit; 4382981Swnj rkaddr->rkcs1 = RK_CDT|RK_DCLR|RK_GO; 4392981Swnj rkwait(rkaddr); 4402981Swnj } 4412981Swnj } 4422618Swnj if (um->um_tab.b_actf && um->um_tab.b_active == 0) 4432618Swnj if (rkstart(um)) 4442618Swnj needie = 0; 4452618Swnj if (needie) 4462618Swnj rkaddr->rkcs1 = RK_CDT|RK_IE; 4471899Swnj } 4481899Swnj 4492618Swnj rkwait(addr) 4502618Swnj register struct rkdevice *addr; 4512618Swnj { 4521899Swnj 4532618Swnj while ((addr->rkcs1 & RK_CRDY) == 0) 4542618Swnj ; 4552618Swnj } 4562618Swnj 4572618Swnj rkread(dev) 4582618Swnj dev_t dev; 4591899Swnj { 4602618Swnj register int unit = minor(dev) >> 3; 4612618Swnj 4622648Swnj if (unit >= NRK) 4632618Swnj u.u_error = ENXIO; 4642618Swnj else 4652618Swnj physio(rkstrategy, &rrkbuf[unit], dev, B_READ, minphys); 4661899Swnj } 4671899Swnj 4682618Swnj rkwrite(dev) 4692618Swnj dev_t dev; 4701899Swnj { 4712618Swnj register int unit = minor(dev) >> 3; 4721899Swnj 4732648Swnj if (unit >= NRK) 4742618Swnj u.u_error = ENXIO; 4752618Swnj else 4762618Swnj physio(rkstrategy, &rrkbuf[unit], dev, B_WRITE, minphys); 4771899Swnj } 4781899Swnj 4792618Swnj rkecc(ui) 4802981Swnj register struct uba_device *ui; 4811899Swnj { 4822618Swnj register struct rkdevice *rk = (struct rkdevice *)ui->ui_addr; 4832618Swnj register struct buf *bp = rkutab[ui->ui_unit].b_actf; 4842981Swnj register struct uba_ctlr *um = ui->ui_mi; 4852618Swnj register struct rkst *st; 4862618Swnj struct uba_regs *ubp = ui->ui_hd->uh_uba; 4872618Swnj register int i; 4882618Swnj caddr_t addr; 4892618Swnj int reg, bit, byte, npf, mask, o, cmd, ubaddr; 4902618Swnj int bn, cn, tn, sn; 4911899Swnj 4922618Swnj npf = btop((rk->rkwc * sizeof(short)) + bp->b_bcount) - 1; 4932618Swnj reg = btop(um->um_ubinfo&0x3ffff) + npf; 4942618Swnj o = (int)bp->b_un.b_addr & PGOFSET; 4952940Swnj printf("rk%d%c: soft ecc sn%d\n", dkunit(bp), 4962885Swnj 'a'+(minor(bp->b_dev)&07), bp->b_blkno + npf); 4972618Swnj mask = rk->rkec2; 4982724Swnj ubapurge(um); 4992618Swnj i = rk->rkec1 - 1; /* -1 makes 0 origin */ 5002618Swnj bit = i&07; 5012618Swnj i = (i&~07)>>3; 5022618Swnj byte = i + o; 5032618Swnj while (i < 512 && (int)ptob(npf)+i < bp->b_bcount && bit > -11) { 5042618Swnj addr = ptob(ubp->uba_map[reg+btop(byte)].pg_pfnum)+ 5052618Swnj (byte & PGOFSET); 5062618Swnj putmemc(addr, getmemc(addr)^(mask<<bit)); 5072618Swnj byte++; 5082618Swnj i++; 5092618Swnj bit -= 8; 5102618Swnj } 5112618Swnj um->um_tab.b_active++; /* Either complete or continuing... */ 5122618Swnj if (rk->rkwc == 0) 5132618Swnj return (0); 5142622Swnj #ifdef notdef 5152622Swnj rk->rkcs1 |= RK_GO; 5162622Swnj #else 5172618Swnj rk->rkcs1 = RK_CDT|RK_CCLR; 5182618Swnj rk->rkcs2 = ui->ui_slave; 5192618Swnj rk->rkcs1 = RK_CDT|RK_DCLR|RK_GO; 5202618Swnj rkwait(rk); 5212618Swnj bn = dkblock(bp); 5222618Swnj st = &rkst[ui->ui_type]; 5232618Swnj cn = bp->b_cylin; 5242618Swnj sn = bn%st->nspc + npf + 1; 5252618Swnj tn = sn/st->nsect; 5262618Swnj sn %= st->nsect; 5272618Swnj cn += tn/st->ntrak; 5282618Swnj tn %= st->ntrak; 5292618Swnj rk->rkcyl = cn; 5302618Swnj rk->rkda = (tn << 8) | sn; 5312618Swnj ubaddr = (int)ptob(reg+1) + o; 5322618Swnj rk->rkba = ubaddr; 5332618Swnj cmd = (ubaddr >> 8) & 0x300; 5342618Swnj cmd |= RK_CDT|RK_IE|RK_GO|RK_READ; 5352618Swnj rk->rkcs1 = cmd; 5362622Swnj #endif 5372618Swnj return (1); 5381899Swnj } 5391899Swnj 5402618Swnj rkreset(uban) 5412927Swnj int uban; 5421899Swnj { 5432981Swnj register struct uba_ctlr *um; 5442981Swnj register struct uba_device *ui; 5452618Swnj register rk11, unit; 5461899Swnj 5472648Swnj for (rk11 = 0; rk11 < NHK; rk11++) { 5482618Swnj if ((um = rkminfo[rk11]) == 0 || um->um_ubanum != uban || 5492618Swnj um->um_alive == 0) 5502618Swnj continue; 5512927Swnj printf(" hk%d", rk11); 5522618Swnj um->um_tab.b_active = 0; 5532618Swnj um->um_tab.b_actf = um->um_tab.b_actl = 0; 5542618Swnj rk_softc[um->um_ctlr].sc_recal = 0; 5552618Swnj if (um->um_ubinfo) { 5562618Swnj printf("<%d>", (um->um_ubinfo>>28)&0xf); 5572618Swnj ubadone(um); 5582618Swnj } 5592648Swnj for (unit = 0; unit < NHK; unit++) { 5602618Swnj if ((ui = rkdinfo[unit]) == 0) 5612618Swnj continue; 5622618Swnj if (ui->ui_alive == 0) 5632618Swnj continue; 5642618Swnj rkutab[unit].b_active = 0; 5652618Swnj (void) rkustart(ui); 5662618Swnj } 5672618Swnj (void) rkstart(um); 5682618Swnj } 5691899Swnj } 5702380Swnj 5712618Swnj rkwatch() 5722380Swnj { 5732981Swnj register struct uba_ctlr *um; 5742618Swnj register rk11, unit; 5752618Swnj register struct rk_softc *sc; 5762380Swnj 5772758Swnj timeout(rkwatch, (caddr_t)0, hz); 5782648Swnj for (rk11 = 0; rk11 < NHK; rk11++) { 5792618Swnj um = rkminfo[rk11]; 5802618Swnj if (um == 0 || um->um_alive == 0) 5812618Swnj continue; 5822618Swnj sc = &rk_softc[rk11]; 5832618Swnj if (um->um_tab.b_active == 0) { 5842648Swnj for (unit = 0; unit < NRK; unit++) 5852622Swnj if (rkutab[unit].b_active && 5862622Swnj rkdinfo[unit]->ui_mi == um) 5872618Swnj goto active; 5882618Swnj sc->sc_wticks = 0; 5892618Swnj continue; 5902618Swnj } 5912618Swnj active: 5922618Swnj sc->sc_wticks++; 5932618Swnj if (sc->sc_wticks >= 20) { 5942618Swnj sc->sc_wticks = 0; 5952927Swnj printf("hk%d: lost interrupt\n", rk11); 5962648Swnj ubareset(um->um_ubanum); 5972618Swnj } 5982618Swnj } 5992380Swnj } 6002618Swnj 6012618Swnj #define DBSIZE 20 6022618Swnj 6032618Swnj rkdump(dev) 6042618Swnj dev_t dev; 6052618Swnj { 6062618Swnj struct rkdevice *rkaddr; 6072618Swnj char *start; 6082618Swnj int num, blk, unit; 6092618Swnj struct size *sizes; 6102618Swnj register struct uba_regs *uba; 6112981Swnj register struct uba_device *ui; 6122618Swnj register short *rp; 6132618Swnj struct rkst *st; 6142618Swnj 6152618Swnj unit = minor(dev) >> 3; 6162885Swnj if (unit >= NRK) 6172885Swnj return (ENXIO); 6182618Swnj #define phys(cast, addr) ((cast)((int)addr & 0x7fffffff)) 6192981Swnj ui = phys(struct uba_device *, rkdinfo[unit]); 6202885Swnj if (ui->ui_alive == 0) 6212885Swnj return (ENXIO); 6222618Swnj uba = phys(struct uba_hd *, ui->ui_hd)->uh_physuba; 6232618Swnj #if VAX780 6242618Swnj if (cpu == VAX_780) 6252618Swnj ubainit(uba); 6261899Swnj #endif 6272618Swnj rkaddr = (struct rkdevice *)ui->ui_physaddr; 6282618Swnj num = maxfree; 6292618Swnj start = 0; 6302618Swnj rkaddr->rkcs1 = RK_CDT|RK_CERR; 6312618Swnj rkaddr->rkcs2 = unit; 6322618Swnj rkaddr->rkcs1 = RK_CDT|RK_DCLR|RK_GO; 6332618Swnj rkwait(rkaddr); 634*3293Swnj if ((rkaddr->rkds & RKDS_VV) == 0) { 6352618Swnj rkaddr->rkcs1 = RK_CDT|RK_IE|RK_PACK|RK_GO; 6362618Swnj rkwait(rkaddr); 6372618Swnj } 6382618Swnj st = &rkst[ui->ui_type]; 6392618Swnj sizes = phys(struct size *, st->sizes); 6402885Swnj if (dumplo < 0 || dumplo + num >= sizes[minor(dev)&07].nblocks) 6412885Swnj return (EINVAL); 6422618Swnj while (num > 0) { 6432618Swnj register struct pte *io; 6442618Swnj register int i; 6452618Swnj int cn, sn, tn; 6462618Swnj daddr_t bn; 6472618Swnj 6482618Swnj blk = num > DBSIZE ? DBSIZE : num; 6492618Swnj io = uba->uba_map; 6502618Swnj for (i = 0; i < blk; i++) 6512981Swnj *(int *)io++ = (btop(start)+i) | (1<<21) | UBAMR_MRV; 6522618Swnj *(int *)io = 0; 6532618Swnj bn = dumplo + btop(start); 6542618Swnj cn = bn/st->nspc + sizes[minor(dev)&07].cyloff; 6552618Swnj sn = bn%st->nspc; 6562618Swnj tn = sn/st->nsect; 6572618Swnj sn = sn%st->nsect; 6582618Swnj rkaddr->rkcyl = cn; 6592618Swnj rp = (short *) &rkaddr->rkda; 6602618Swnj *rp = (tn << 8) + sn; 6612618Swnj *--rp = 0; 6622618Swnj *--rp = -blk*NBPG / sizeof (short); 6632618Swnj *--rp = RK_CDT|RK_GO|RK_WRITE; 6642618Swnj rkwait(rkaddr); 6652885Swnj if (rkaddr->rkcs1 & RK_CERR) 6662885Swnj return (EIO); 6672618Swnj start += blk*NBPG; 6682618Swnj num -= blk; 6692618Swnj } 6702618Swnj return (0); 6712618Swnj } 6722618Swnj #endif 673