1*2903Swnj /* rk.c 4.20 03/05/81 */ 21899Swnj 31942Swnj #include "rk.h" 42648Swnj #if NHK > 0 52894Swnj int rkwaitdry; 61899Swnj /* 72618Swnj * RK11/RK07 disk driver 82622Swnj * 92622Swnj * This driver mimics up.c; see it for an explanation of common code. 102685Swnj * 112885Swnj * TODO: 122885Swnj * Add reading of bad sector information and disk layout from sector 1 132885Swnj * Add bad sector forwarding code 14*2903Swnj * Why do we lose an interrupt sometime when spinning drives down? 151899Swnj */ 162618Swnj #define DELAY(i) { register int j; j = i; while (--j > 0); } 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" 261899Swnj #include "../h/uba.h" 271899Swnj #include "../h/dk.h" 282618Swnj #include "../h/cpu.h" 292618Swnj #include "../h/cmap.h" 301899Swnj 312618Swnj #include "../h/rkreg.h" 321899Swnj 332618Swnj struct rk_softc { 342618Swnj int sc_softas; 352618Swnj int sc_ndrive; 362618Swnj int sc_wticks; 372618Swnj int sc_recal; 382648Swnj } rk_softc[NHK]; 391899Swnj 402618Swnj /* THIS SHOULD BE READ OFF THE PACK, PER DRIVE */ 412787Swnj struct size { 422618Swnj daddr_t nblocks; 432618Swnj int cyloff; 442618Swnj } rk7_sizes[] ={ 452618Swnj 15884, 0, /* A=cyl 0 thru 240 */ 462665Swnj 10032, 241, /* B=cyl 241 thru 392 */ 472665Swnj 53790, 0, /* C=cyl 0 thru 814 */ 482618Swnj 0, 0, 492618Swnj 0, 0, 502618Swnj 0, 0, 512618Swnj 27786, 393, /* G=cyl 393 thru 813 */ 522618Swnj 0, 0, 532618Swnj }; 542618Swnj /* END OF STUFF WHICH SHOULD BE READ IN PER DISK */ 551899Swnj 562618Swnj int rkprobe(), rkslave(), rkattach(), rkdgo(), rkintr(); 572648Swnj struct uba_minfo *rkminfo[NHK]; 582648Swnj struct uba_dinfo *rkdinfo[NRK]; 592648Swnj struct uba_dinfo *rkip[NHK][4]; 601899Swnj 612618Swnj u_short rkstd[] = { 0777440, 0 }; 622618Swnj struct uba_driver hkdriver = 632622Swnj { rkprobe, rkslave, rkattach, rkdgo, rkstd, "rk", rkdinfo, "hk", rkminfo, 1 }; 642648Swnj struct buf rkutab[NRK]; 652648Swnj short rkcyl[NRK]; 661899Swnj 672618Swnj struct rkst { 682618Swnj short nsect; 692618Swnj short ntrak; 702618Swnj short nspc; 712618Swnj short ncyl; 722618Swnj struct size *sizes; 732618Swnj } rkst[] = { 742618Swnj NRKSECT, NRKTRK, NRKSECT*NRKTRK, NRK7CYL, rk7_sizes, 752618Swnj }; 761899Swnj 772618Swnj u_char rk_offset[16] = 782618Swnj { P400,M400,P400,M400,P800,M800,P800,M800,P1200,M1200,P1200,M1200,0,0,0,0 }; 791899Swnj 802648Swnj struct buf rrkbuf[NRK]; 812618Swnj 822618Swnj #define b_cylin b_resid 832618Swnj 842618Swnj #ifdef INTRLVE 852618Swnj daddr_t dkblock(); 862618Swnj #endif 872618Swnj 882618Swnj int rkwstart, rkwatch(); 892618Swnj 902618Swnj rkprobe(reg) 912618Swnj caddr_t reg; 921899Swnj { 932618Swnj register int br, cvec; 941899Swnj 952618Swnj #ifdef lint 962618Swnj br = 0; cvec = br; br = cvec; 972618Swnj #endif 982618Swnj ((struct rkdevice *)reg)->rkcs1 = RK_CDT|RK_IE|RK_CRDY; 992618Swnj DELAY(10); 1002618Swnj ((struct rkdevice *)reg)->rkcs1 = RK_CDT; 1012618Swnj return (1); 1022618Swnj } 1031899Swnj 1042618Swnj rkslave(ui, reg) 1052618Swnj struct uba_dinfo *ui; 1062618Swnj caddr_t reg; 1072618Swnj { 1082618Swnj register struct rkdevice *rkaddr = (struct rkdevice *)reg; 1091899Swnj 1102894Swnj rkaddr->rkcs1 = RK_CDT|RK_CCLR; 1112618Swnj rkaddr->rkcs2 = ui->ui_slave; 1122894Swnj rkaddr->rkcs1 = RK_CDT|RK_SELECT|RK_GO; 1132622Swnj rkwait(rkaddr); 1142894Swnj DELAY(50); 1152894Swnj if (rkaddr->rkcs2&RK_NED || (rkaddr->rkds&RK_SVAL) == 0) { 1162618Swnj rkaddr->rkcs1 = RK_CDT|RK_CCLR; 1172618Swnj return (0); 1182618Swnj } 1192618Swnj return (1); 1202618Swnj } 1212618Swnj 1222618Swnj rkattach(ui) 1232618Swnj register struct uba_dinfo *ui; 1242618Swnj { 1252618Swnj 1262618Swnj if (rkwstart == 0) { 1272758Swnj timeout(rkwatch, (caddr_t)0, hz); 1282618Swnj rkwstart++; 1292618Swnj } 1302618Swnj if (ui->ui_dk >= 0) 1312758Swnj dk_mspw[ui->ui_dk] = 1.0 / (60 * NRKSECT * 256); 1322618Swnj rkip[ui->ui_ctlr][ui->ui_slave] = ui; 1332618Swnj rk_softc[ui->ui_ctlr].sc_ndrive++; 1342618Swnj rkcyl[ui->ui_unit] = -1; 1352618Swnj } 1362618Swnj 1371899Swnj rkstrategy(bp) 1382618Swnj register struct buf *bp; 1391899Swnj { 1402618Swnj register struct uba_dinfo *ui; 1412618Swnj register struct rkst *st; 1422618Swnj register int unit; 1432618Swnj register struct buf *dp; 1442618Swnj int xunit = minor(bp->b_dev) & 07; 1452618Swnj long bn, sz; 1461899Swnj 1472618Swnj sz = (bp->b_bcount+511) >> 9; 1482618Swnj unit = dkunit(bp); 1492648Swnj if (unit >= NRK) 1502618Swnj goto bad; 1512618Swnj ui = rkdinfo[unit]; 1522618Swnj if (ui == 0 || ui->ui_alive == 0) 1532618Swnj goto bad; 1542618Swnj st = &rkst[ui->ui_type]; 1552618Swnj if (bp->b_blkno < 0 || 1562618Swnj (bn = dkblock(bp))+sz > st->sizes[xunit].nblocks) 1572618Swnj goto bad; 1582618Swnj bp->b_cylin = bn/st->nspc + st->sizes[xunit].cyloff; 1592618Swnj (void) spl5(); 1602618Swnj dp = &rkutab[ui->ui_unit]; 1612618Swnj disksort(dp, bp); 1622618Swnj if (dp->b_active == 0) { 1632618Swnj (void) rkustart(ui); 1642618Swnj bp = &ui->ui_mi->um_tab; 1652618Swnj if (bp->b_actf && bp->b_active == 0) 1662618Swnj (void) rkstart(ui->ui_mi); 1671899Swnj } 1682618Swnj (void) spl0(); 1692618Swnj return; 1702618Swnj 1712618Swnj bad: 1722618Swnj bp->b_flags |= B_ERROR; 1732618Swnj iodone(bp); 1742618Swnj return; 1751899Swnj } 1761899Swnj 1772618Swnj rkustart(ui) 1782618Swnj register struct uba_dinfo *ui; 1792618Swnj { 1802618Swnj register struct buf *bp, *dp; 1812618Swnj register struct uba_minfo *um; 1822618Swnj register struct rkdevice *rkaddr; 1832618Swnj register struct rkst *st; 1842618Swnj daddr_t bn; 1852618Swnj int sn, csn; 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; 2002618Swnj rkaddr->rkcs1 = RK_CDT|RK_SELECT|RK_GO; 2012618Swnj rkwait(rkaddr); 202*2903Swnj if ((bp = dp->b_actf) == NULL) { 203*2903Swnj rkaddr->rkcs1 = RK_CDT|RK_DCLR|RK_GO; 204*2903Swnj rkwait(rkaddr); 205*2903Swnj return (0); 206*2903Swnj } 2072618Swnj if ((rkaddr->rkds & RK_VV) == 0) { 2082618Swnj /* SHOULD WARN SYSTEM THAT THIS HAPPENED */ 2092894Swnj rkaddr->rkcs1 = RK_CDT|RK_PACK|RK_GO; 2102618Swnj rkwait(rkaddr); 2112618Swnj } 212*2903Swnj if (dp->b_active) 213*2903Swnj goto done; 214*2903Swnj dp->b_active = 1; 2152894Swnj if ((rkaddr->rkds & RK_DREADY) != RK_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) 2452618Swnj register struct uba_minfo *um; 2461899Swnj { 2472618Swnj register struct buf *bp, *dp; 2482618Swnj register struct uba_dinfo *ui; 2492618Swnj register struct rkdevice *rkaddr; 2502618Swnj struct rkst *st; 2511899Swnj daddr_t bn; 2522618Swnj int sn, tn, cmd; 2532894Swnj int waitdry; 2541899Swnj 2552618Swnj loop: 2562618Swnj if ((dp = um->um_tab.b_actf) == NULL) 2572618Swnj return (0); 2582618Swnj if ((bp = dp->b_actf) == NULL) { 2592618Swnj um->um_tab.b_actf = dp->b_forw; 2602618Swnj goto loop; 2611899Swnj } 2622618Swnj um->um_tab.b_active++; 2632618Swnj ui = rkdinfo[dkunit(bp)]; 2642618Swnj bn = dkblock(bp); 2652618Swnj st = &rkst[ui->ui_type]; 2662618Swnj sn = bn%st->nspc; 2672618Swnj tn = sn/st->nsect; 2682618Swnj sn %= st->nsect; 2692618Swnj rkaddr = (struct rkdevice *)ui->ui_addr; 2702618Swnj rkaddr->rkcs1 = RK_CDT|RK_CERR; 2712618Swnj rkaddr->rkcs2 = ui->ui_slave; 2722618Swnj rkaddr->rkcs1 = RK_CDT|RK_SELECT|RK_GO; 2732618Swnj rkwait(rkaddr); 2742894Swnj waitdry = 0; 2752894Swnj while ((rkaddr->rkds&RK_SVAL) == 0) { 2762894Swnj if (++waitdry > 32) 2772894Swnj break; 2782894Swnj rkwaitdry++; 2792894Swnj } 2802894Swnj if ((rkaddr->rkds&RK_DREADY) != RK_DREADY) { 2812894Swnj printf("rk%d not ready", dkunit(bp)); 2822894Swnj if ((rkaddr->rkds&RK_DREADY) != RK_DREADY) { 2832894Swnj printf("\n"); 2842894Swnj rkaddr->rkcs1 = RK_CDT|RK_DCLR|RK_GO; 2852894Swnj rkwait(rkaddr); 2862894Swnj rkaddr->rkcs1 = RK_CDT|RK_CERR; 2872894Swnj rkwait(rkaddr); 2882894Swnj um->um_tab.b_active = 0; 2892894Swnj um->um_tab.b_errcnt = 0; 2902894Swnj dp->b_actf = bp->av_forw; 2912894Swnj dp->b_active = 0; 2922894Swnj bp->b_flags |= B_ERROR; 2932894Swnj iodone(bp); 2942894Swnj goto loop; 2952894Swnj } 2962894Swnj printf(" (came back!)\n"); 2972894Swnj } 2982618Swnj if (um->um_tab.b_errcnt >= 16 && (bp->b_flags&B_READ) != 0) { 2992618Swnj rkaddr->rkatt = rk_offset[um->um_tab.b_errcnt & 017]; 3002618Swnj rkaddr->rkcs1 = RK_CDT|RK_OFFSET|RK_GO; 3012618Swnj rkwait(rkaddr); 3021899Swnj } 3032618Swnj rkaddr->rkcyl = bp->b_cylin; 3042618Swnj rkcyl[ui->ui_unit] = bp->b_cylin; 3052618Swnj rkaddr->rkda = (tn << 8) + sn; 3062618Swnj rkaddr->rkwc = -bp->b_bcount / sizeof (short); 3072618Swnj if (bp->b_flags & B_READ) 3082618Swnj cmd = RK_CDT|RK_IE|RK_READ|RK_GO; 3092618Swnj else 3102618Swnj cmd = RK_CDT|RK_IE|RK_WRITE|RK_GO; 3112618Swnj um->um_cmd = cmd; 3122618Swnj ubago(ui); 3132618Swnj return (1); 3141899Swnj } 3151899Swnj 3162618Swnj rkdgo(um) 3172618Swnj register struct uba_minfo *um; 3181899Swnj { 3192618Swnj register struct rkdevice *rkaddr = (struct rkdevice *)um->um_addr; 3201899Swnj 3212618Swnj rkaddr->rkba = um->um_ubinfo; 3222618Swnj rkaddr->rkcs1 = um->um_cmd|((um->um_ubinfo>>8)&0x300); 3232618Swnj } 3242618Swnj 3252710Swnj rkintr(rk11) 3262618Swnj int rk11; 3272618Swnj { 3282618Swnj register struct uba_minfo *um = rkminfo[rk11]; 3292618Swnj register struct uba_dinfo *ui; 3302618Swnj register struct rkdevice *rkaddr = (struct rkdevice *)um->um_addr; 3312618Swnj register struct buf *bp, *dp; 3322618Swnj int unit; 3332618Swnj struct rk_softc *sc = &rk_softc[um->um_ctlr]; 3342618Swnj int as = (rkaddr->rkatt >> 8) | sc->sc_softas; 3352618Swnj int needie = 1; 3362618Swnj 3372618Swnj sc->sc_wticks = 0; 3382618Swnj sc->sc_softas = 0; 3392618Swnj if (um->um_tab.b_active) { 3402618Swnj dp = um->um_tab.b_actf; 3412618Swnj bp = dp->b_actf; 3422618Swnj ui = rkdinfo[dkunit(bp)]; 3432618Swnj dk_busy &= ~(1 << ui->ui_dk); 3442618Swnj if (rkaddr->rkcs1 & RK_CERR) { 3452618Swnj int recal; 3462618Swnj u_short ds = rkaddr->rkds; 3472618Swnj u_short cs2 = rkaddr->rkcs2; 3482618Swnj u_short er = rkaddr->rker; 3492618Swnj if (sc->sc_recal) 3502618Swnj printf("recal CERR\n"); 3512685Swnj if (ds & RK_WLE) { 3522618Swnj printf("rk%d is write locked\n", dkunit(bp)); 3532685Swnj bp->b_flags |= B_ERROR; 3542685Swnj } else if (++um->um_tab.b_errcnt > 28 || 3552676Swnj ds&RKDS_HARD || er&RKER_HARD || cs2&RKCS2_HARD) { 3562618Swnj bp->b_flags |= B_ERROR; 3572676Swnj harderr(bp); 3582894Swnj printf("rk%d%c cs2=%b ds=%b er=%b\n", 3592894Swnj dkunit(bp), 'a'+(minor(bp->b_dev)&07), 3602894Swnj cs2, RKCS2_BITS, ds, 3612676Swnj RKDS_BITS, er, RKER_BITS); 3622676Swnj } else 3632618Swnj um->um_tab.b_active = 0; 3642618Swnj if (cs2&RK_MDS) { 3652618Swnj rkaddr->rkcs2 = RK_SCLR; 3662618Swnj goto retry; 3671899Swnj } 3682618Swnj recal = 0; 3692618Swnj if (ds&RK_DROT || er&(RK_OPI|RK_SKI|RK_UNS) || 3702618Swnj (um->um_tab.b_errcnt&07) == 4) 3712618Swnj recal = 1; 3722618Swnj if ((er & (RK_DCK|RK_ECH)) == RK_DCK) 3732618Swnj if (rkecc(ui)) 3742618Swnj return; 3752618Swnj rkaddr->rkcs1 = RK_CDT|RK_CCLR; 3762618Swnj rkaddr->rkcs2 = ui->ui_slave; 3772618Swnj rkaddr->rkcs1 = RK_CDT|RK_DCLR|RK_GO; 3782618Swnj rkwait(rkaddr); 3792618Swnj if (recal && um->um_tab.b_active == 0) { 3802618Swnj rkaddr->rkcs1 = RK_CDT|RK_IE|RK_RECAL|RK_GO; 3812618Swnj rkcyl[ui->ui_unit] = -1; 3822618Swnj rkwait(rkaddr); 3832618Swnj um->um_tab.b_active = 1; 3842618Swnj sc->sc_recal = 1; 3852618Swnj return; 3862618Swnj } 3871899Swnj } 3882618Swnj retry: 3892618Swnj if (sc->sc_recal) { 3902618Swnj sc->sc_recal = 0; 3912618Swnj um->um_tab.b_active = 0; 3921899Swnj } 3932618Swnj ubadone(um); 3942618Swnj if (um->um_tab.b_active) { 3952618Swnj um->um_tab.b_active = 0; 3962618Swnj um->um_tab.b_errcnt = 0; 3972618Swnj um->um_tab.b_actf = dp->b_forw; 3982618Swnj dp->b_active = 0; 3992618Swnj dp->b_errcnt = 0; 4002618Swnj dp->b_actf = bp->av_forw; 4012618Swnj bp->b_resid = -rkaddr->rkwc * sizeof(short); 4022618Swnj iodone(bp); 4032618Swnj if (dp->b_actf) 4042618Swnj if (rkustart(ui)) 4052618Swnj needie = 0; 4061899Swnj } 4072618Swnj as &= ~(1<<ui->ui_slave); 4081899Swnj } 4092894Swnj att: 4102618Swnj for (unit = 0; as; as >>= 1, unit++) 4112618Swnj if (as & 1) 4122618Swnj if (rkustart(rkip[rk11][unit])) 4132618Swnj needie = 0; 4142618Swnj if (um->um_tab.b_actf && um->um_tab.b_active == 0) 4152618Swnj if (rkstart(um)) 4162618Swnj needie = 0; 4172618Swnj if (needie) 4182618Swnj rkaddr->rkcs1 = RK_CDT|RK_IE; 4191899Swnj } 4201899Swnj 4212618Swnj rkwait(addr) 4222618Swnj register struct rkdevice *addr; 4232618Swnj { 4241899Swnj 4252618Swnj while ((addr->rkcs1 & RK_CRDY) == 0) 4262618Swnj ; 4272618Swnj } 4282618Swnj 4292618Swnj rkread(dev) 4302618Swnj dev_t dev; 4311899Swnj { 4322618Swnj register int unit = minor(dev) >> 3; 4332618Swnj 4342648Swnj if (unit >= NRK) 4352618Swnj u.u_error = ENXIO; 4362618Swnj else 4372618Swnj physio(rkstrategy, &rrkbuf[unit], dev, B_READ, minphys); 4381899Swnj } 4391899Swnj 4402618Swnj rkwrite(dev) 4412618Swnj dev_t dev; 4421899Swnj { 4432618Swnj register int unit = minor(dev) >> 3; 4441899Swnj 4452648Swnj if (unit >= NRK) 4462618Swnj u.u_error = ENXIO; 4472618Swnj else 4482618Swnj physio(rkstrategy, &rrkbuf[unit], dev, B_WRITE, minphys); 4491899Swnj } 4501899Swnj 4512618Swnj rkecc(ui) 4522618Swnj register struct uba_dinfo *ui; 4531899Swnj { 4542618Swnj register struct rkdevice *rk = (struct rkdevice *)ui->ui_addr; 4552618Swnj register struct buf *bp = rkutab[ui->ui_unit].b_actf; 4562618Swnj register struct uba_minfo *um = ui->ui_mi; 4572618Swnj register struct rkst *st; 4582618Swnj struct uba_regs *ubp = ui->ui_hd->uh_uba; 4592618Swnj register int i; 4602618Swnj caddr_t addr; 4612618Swnj int reg, bit, byte, npf, mask, o, cmd, ubaddr; 4622618Swnj int bn, cn, tn, sn; 4631899Swnj 4642618Swnj npf = btop((rk->rkwc * sizeof(short)) + bp->b_bcount) - 1; 4652618Swnj reg = btop(um->um_ubinfo&0x3ffff) + npf; 4662618Swnj o = (int)bp->b_un.b_addr & PGOFSET; 4672894Swnj printf("soft ecc rk%d%c bn%d\n", dkunit(bp), 4682885Swnj 'a'+(minor(bp->b_dev)&07), bp->b_blkno + npf); 4692618Swnj mask = rk->rkec2; 4702724Swnj ubapurge(um); 4712618Swnj i = rk->rkec1 - 1; /* -1 makes 0 origin */ 4722618Swnj bit = i&07; 4732618Swnj i = (i&~07)>>3; 4742618Swnj byte = i + o; 4752618Swnj while (i < 512 && (int)ptob(npf)+i < bp->b_bcount && bit > -11) { 4762618Swnj addr = ptob(ubp->uba_map[reg+btop(byte)].pg_pfnum)+ 4772618Swnj (byte & PGOFSET); 4782618Swnj putmemc(addr, getmemc(addr)^(mask<<bit)); 4792618Swnj byte++; 4802618Swnj i++; 4812618Swnj bit -= 8; 4822618Swnj } 4832618Swnj um->um_tab.b_active++; /* Either complete or continuing... */ 4842618Swnj if (rk->rkwc == 0) 4852618Swnj return (0); 4862622Swnj #ifdef notdef 4872622Swnj rk->rkcs1 |= RK_GO; 4882622Swnj #else 4892618Swnj rk->rkcs1 = RK_CDT|RK_CCLR; 4902618Swnj rk->rkcs2 = ui->ui_slave; 4912618Swnj rk->rkcs1 = RK_CDT|RK_DCLR|RK_GO; 4922618Swnj rkwait(rk); 4932618Swnj bn = dkblock(bp); 4942618Swnj st = &rkst[ui->ui_type]; 4952618Swnj cn = bp->b_cylin; 4962618Swnj sn = bn%st->nspc + npf + 1; 4972618Swnj tn = sn/st->nsect; 4982618Swnj sn %= st->nsect; 4992618Swnj cn += tn/st->ntrak; 5002618Swnj tn %= st->ntrak; 5012618Swnj rk->rkcyl = cn; 5022618Swnj rk->rkda = (tn << 8) | sn; 5032618Swnj ubaddr = (int)ptob(reg+1) + o; 5042618Swnj rk->rkba = ubaddr; 5052618Swnj cmd = (ubaddr >> 8) & 0x300; 5062618Swnj cmd |= RK_CDT|RK_IE|RK_GO|RK_READ; 5072618Swnj rk->rkcs1 = cmd; 5082622Swnj #endif 5092618Swnj return (1); 5101899Swnj } 5111899Swnj 5122618Swnj rkreset(uban) 5131899Swnj { 5142618Swnj register struct uba_minfo *um; 5152618Swnj register struct uba_dinfo *ui; 5162618Swnj register rk11, unit; 5172618Swnj int any = 0; 5181899Swnj 5192648Swnj for (rk11 = 0; rk11 < NHK; rk11++) { 5202618Swnj if ((um = rkminfo[rk11]) == 0 || um->um_ubanum != uban || 5212618Swnj um->um_alive == 0) 5222618Swnj continue; 5232618Swnj if (any == 0) { 5242618Swnj printf(" rk"); 5252618Swnj any++; 5262618Swnj } 5272618Swnj um->um_tab.b_active = 0; 5282618Swnj um->um_tab.b_actf = um->um_tab.b_actl = 0; 5292618Swnj rk_softc[um->um_ctlr].sc_recal = 0; 5302618Swnj if (um->um_ubinfo) { 5312618Swnj printf("<%d>", (um->um_ubinfo>>28)&0xf); 5322618Swnj ubadone(um); 5332618Swnj } 5342648Swnj for (unit = 0; unit < NHK; unit++) { 5352618Swnj if ((ui = rkdinfo[unit]) == 0) 5362618Swnj continue; 5372618Swnj if (ui->ui_alive == 0) 5382618Swnj continue; 5392618Swnj rkutab[unit].b_active = 0; 5402618Swnj (void) rkustart(ui); 5412618Swnj } 5422618Swnj (void) rkstart(um); 5432618Swnj } 5441899Swnj } 5452380Swnj 5462618Swnj rkwatch() 5472380Swnj { 5482618Swnj register struct uba_minfo *um; 5492618Swnj register rk11, unit; 5502618Swnj register struct rk_softc *sc; 5512380Swnj 5522758Swnj timeout(rkwatch, (caddr_t)0, hz); 5532648Swnj for (rk11 = 0; rk11 < NHK; rk11++) { 5542618Swnj um = rkminfo[rk11]; 5552618Swnj if (um == 0 || um->um_alive == 0) 5562618Swnj continue; 5572618Swnj sc = &rk_softc[rk11]; 5582618Swnj if (um->um_tab.b_active == 0) { 5592648Swnj for (unit = 0; unit < NRK; unit++) 5602622Swnj if (rkutab[unit].b_active && 5612622Swnj rkdinfo[unit]->ui_mi == um) 5622618Swnj goto active; 5632618Swnj sc->sc_wticks = 0; 5642618Swnj continue; 5652618Swnj } 5662618Swnj active: 5672618Swnj sc->sc_wticks++; 5682618Swnj if (sc->sc_wticks >= 20) { 5692618Swnj sc->sc_wticks = 0; 5702894Swnj printf("lost rkintr "); 5712648Swnj ubareset(um->um_ubanum); 5722618Swnj } 5732618Swnj } 5742380Swnj } 5752618Swnj 5762618Swnj #define DBSIZE 20 5772618Swnj 5782618Swnj rkdump(dev) 5792618Swnj dev_t dev; 5802618Swnj { 5812618Swnj struct rkdevice *rkaddr; 5822618Swnj char *start; 5832618Swnj int num, blk, unit; 5842618Swnj struct size *sizes; 5852618Swnj register struct uba_regs *uba; 5862618Swnj register struct uba_dinfo *ui; 5872618Swnj register short *rp; 5882618Swnj struct rkst *st; 5892618Swnj 5902618Swnj unit = minor(dev) >> 3; 5912885Swnj if (unit >= NRK) 5922885Swnj return (ENXIO); 5932618Swnj #define phys(cast, addr) ((cast)((int)addr & 0x7fffffff)) 5942618Swnj ui = phys(struct uba_dinfo *, rkdinfo[unit]); 5952885Swnj if (ui->ui_alive == 0) 5962885Swnj return (ENXIO); 5972618Swnj uba = phys(struct uba_hd *, ui->ui_hd)->uh_physuba; 5982618Swnj #if VAX780 5992618Swnj if (cpu == VAX_780) 6002618Swnj ubainit(uba); 6011899Swnj #endif 6022618Swnj rkaddr = (struct rkdevice *)ui->ui_physaddr; 6032618Swnj num = maxfree; 6042618Swnj start = 0; 6052618Swnj rkaddr->rkcs1 = RK_CDT|RK_CERR; 6062618Swnj rkaddr->rkcs2 = unit; 6072618Swnj rkaddr->rkcs1 = RK_CDT|RK_DCLR|RK_GO; 6082618Swnj rkwait(rkaddr); 6092618Swnj if ((rkaddr->rkds & RK_VV) == 0) { 6102618Swnj rkaddr->rkcs1 = RK_CDT|RK_IE|RK_PACK|RK_GO; 6112618Swnj rkwait(rkaddr); 6122618Swnj } 6132618Swnj st = &rkst[ui->ui_type]; 6142618Swnj sizes = phys(struct size *, st->sizes); 6152885Swnj if (dumplo < 0 || dumplo + num >= sizes[minor(dev)&07].nblocks) 6162885Swnj return (EINVAL); 6172618Swnj while (num > 0) { 6182618Swnj register struct pte *io; 6192618Swnj register int i; 6202618Swnj int cn, sn, tn; 6212618Swnj daddr_t bn; 6222618Swnj 6232618Swnj blk = num > DBSIZE ? DBSIZE : num; 6242618Swnj io = uba->uba_map; 6252618Swnj for (i = 0; i < blk; i++) 6262618Swnj *(int *)io++ = (btop(start)+i) | (1<<21) | UBA_MRV; 6272618Swnj *(int *)io = 0; 6282618Swnj bn = dumplo + btop(start); 6292618Swnj cn = bn/st->nspc + sizes[minor(dev)&07].cyloff; 6302618Swnj sn = bn%st->nspc; 6312618Swnj tn = sn/st->nsect; 6322618Swnj sn = sn%st->nsect; 6332618Swnj rkaddr->rkcyl = cn; 6342618Swnj rp = (short *) &rkaddr->rkda; 6352618Swnj *rp = (tn << 8) + sn; 6362618Swnj *--rp = 0; 6372618Swnj *--rp = -blk*NBPG / sizeof (short); 6382618Swnj *--rp = RK_CDT|RK_GO|RK_WRITE; 6392618Swnj rkwait(rkaddr); 6402885Swnj if (rkaddr->rkcs1 & RK_CERR) 6412885Swnj return (EIO); 6422618Swnj start += blk*NBPG; 6432618Swnj num -= blk; 6442618Swnj } 6452618Swnj return (0); 6462618Swnj } 6472618Swnj #endif 648