1*2981Swnj /* rk.c 4.24 03/07/81 */ 21899Swnj 32957Swnj int rkpip; 42957Swnj int rknosval; 51942Swnj #include "rk.h" 62648Swnj #if NHK > 0 71899Swnj /* 82618Swnj * RK11/RK07 disk driver 92622Swnj * 102622Swnj * This driver mimics up.c; see it for an explanation of common code. 112685Swnj * 122885Swnj * TODO: 132885Swnj * Add reading of bad sector information and disk layout from sector 1 142885Swnj * Add bad sector forwarding code 152903Swnj * Why do we lose an interrupt sometime when spinning drives down? 161899Swnj */ 172618Swnj #define DELAY(i) { register int j; j = i; while (--j > 0); } 181899Swnj #include "../h/param.h" 191899Swnj #include "../h/systm.h" 201899Swnj #include "../h/buf.h" 211899Swnj #include "../h/conf.h" 221899Swnj #include "../h/dir.h" 231899Swnj #include "../h/user.h" 241899Swnj #include "../h/pte.h" 251899Swnj #include "../h/map.h" 262618Swnj #include "../h/vm.h" 27*2981Swnj #include "../h/ubareg.h" 28*2981Swnj #include "../h/ubavar.h" 291899Swnj #include "../h/dk.h" 302618Swnj #include "../h/cpu.h" 312618Swnj #include "../h/cmap.h" 321899Swnj 332618Swnj #include "../h/rkreg.h" 341899Swnj 352618Swnj struct rk_softc { 362618Swnj int sc_softas; 372618Swnj int sc_ndrive; 382618Swnj int sc_wticks; 392618Swnj int sc_recal; 402648Swnj } rk_softc[NHK]; 411899Swnj 422618Swnj /* THIS SHOULD BE READ OFF THE PACK, PER DRIVE */ 432787Swnj struct size { 442618Swnj daddr_t nblocks; 452618Swnj int cyloff; 462618Swnj } rk7_sizes[] ={ 472618Swnj 15884, 0, /* A=cyl 0 thru 240 */ 482665Swnj 10032, 241, /* B=cyl 241 thru 392 */ 492665Swnj 53790, 0, /* C=cyl 0 thru 814 */ 502618Swnj 0, 0, 512618Swnj 0, 0, 522618Swnj 0, 0, 532618Swnj 27786, 393, /* G=cyl 393 thru 813 */ 542618Swnj 0, 0, 552618Swnj }; 562618Swnj /* END OF STUFF WHICH SHOULD BE READ IN PER DISK */ 571899Swnj 582618Swnj int rkprobe(), rkslave(), rkattach(), rkdgo(), rkintr(); 59*2981Swnj struct uba_ctlr *rkminfo[NHK]; 60*2981Swnj struct uba_device *rkdinfo[NRK]; 61*2981Swnj struct uba_device *rkip[NHK][4]; 621899Swnj 632618Swnj u_short rkstd[] = { 0777440, 0 }; 642618Swnj struct uba_driver hkdriver = 652622Swnj { rkprobe, rkslave, rkattach, rkdgo, rkstd, "rk", rkdinfo, "hk", rkminfo, 1 }; 662648Swnj struct buf rkutab[NRK]; 672648Swnj short rkcyl[NRK]; 681899Swnj 692618Swnj struct rkst { 702618Swnj short nsect; 712618Swnj short ntrak; 722618Swnj short nspc; 732618Swnj short ncyl; 742618Swnj struct size *sizes; 752618Swnj } rkst[] = { 762618Swnj NRKSECT, NRKTRK, NRKSECT*NRKTRK, NRK7CYL, rk7_sizes, 772618Swnj }; 781899Swnj 792618Swnj u_char rk_offset[16] = 802618Swnj { P400,M400,P400,M400,P800,M800,P800,M800,P1200,M1200,P1200,M1200,0,0,0,0 }; 811899Swnj 822648Swnj struct buf rrkbuf[NRK]; 832618Swnj 842618Swnj #define b_cylin b_resid 852618Swnj 862618Swnj #ifdef INTRLVE 872618Swnj daddr_t dkblock(); 882618Swnj #endif 892618Swnj 902618Swnj int rkwstart, rkwatch(); 912618Swnj 922618Swnj rkprobe(reg) 932618Swnj caddr_t reg; 941899Swnj { 952618Swnj register int br, cvec; 961899Swnj 972618Swnj #ifdef lint 982618Swnj br = 0; cvec = br; br = cvec; 992618Swnj #endif 1002618Swnj ((struct rkdevice *)reg)->rkcs1 = RK_CDT|RK_IE|RK_CRDY; 1012618Swnj DELAY(10); 1022618Swnj ((struct rkdevice *)reg)->rkcs1 = RK_CDT; 1032618Swnj return (1); 1042618Swnj } 1051899Swnj 1062618Swnj rkslave(ui, reg) 107*2981Swnj struct uba_device *ui; 1082618Swnj caddr_t reg; 1092618Swnj { 1102618Swnj register struct rkdevice *rkaddr = (struct rkdevice *)reg; 1111899Swnj 1122894Swnj rkaddr->rkcs1 = RK_CDT|RK_CCLR; 1132618Swnj rkaddr->rkcs2 = ui->ui_slave; 1142957Swnj rkaddr->rkcs1 = RK_CDT|RK_DCLR|RK_GO; 1152622Swnj rkwait(rkaddr); 1162894Swnj DELAY(50); 1172894Swnj if (rkaddr->rkcs2&RK_NED || (rkaddr->rkds&RK_SVAL) == 0) { 1182618Swnj rkaddr->rkcs1 = RK_CDT|RK_CCLR; 1192618Swnj return (0); 1202618Swnj } 1212618Swnj return (1); 1222618Swnj } 1232618Swnj 1242618Swnj rkattach(ui) 125*2981Swnj register struct uba_device *ui; 1262618Swnj { 1272618Swnj 1282618Swnj if (rkwstart == 0) { 1292758Swnj timeout(rkwatch, (caddr_t)0, hz); 1302618Swnj rkwstart++; 1312618Swnj } 1322618Swnj if (ui->ui_dk >= 0) 1332758Swnj dk_mspw[ui->ui_dk] = 1.0 / (60 * NRKSECT * 256); 1342618Swnj rkip[ui->ui_ctlr][ui->ui_slave] = ui; 1352618Swnj rk_softc[ui->ui_ctlr].sc_ndrive++; 1362618Swnj rkcyl[ui->ui_unit] = -1; 1372618Swnj } 1382618Swnj 1391899Swnj rkstrategy(bp) 1402618Swnj register struct buf *bp; 1411899Swnj { 142*2981Swnj register struct uba_device *ui; 1432618Swnj register struct rkst *st; 1442618Swnj register int unit; 1452618Swnj register struct buf *dp; 1462618Swnj int xunit = minor(bp->b_dev) & 07; 1472618Swnj long bn, sz; 1481899Swnj 1492618Swnj sz = (bp->b_bcount+511) >> 9; 1502618Swnj unit = dkunit(bp); 1512648Swnj if (unit >= NRK) 1522618Swnj goto bad; 1532618Swnj ui = rkdinfo[unit]; 1542618Swnj if (ui == 0 || ui->ui_alive == 0) 1552618Swnj goto bad; 1562618Swnj st = &rkst[ui->ui_type]; 1572618Swnj if (bp->b_blkno < 0 || 1582618Swnj (bn = dkblock(bp))+sz > st->sizes[xunit].nblocks) 1592618Swnj goto bad; 1602618Swnj bp->b_cylin = bn/st->nspc + st->sizes[xunit].cyloff; 1612618Swnj (void) spl5(); 1622618Swnj dp = &rkutab[ui->ui_unit]; 1632618Swnj disksort(dp, bp); 1642618Swnj if (dp->b_active == 0) { 1652618Swnj (void) rkustart(ui); 1662618Swnj bp = &ui->ui_mi->um_tab; 1672618Swnj if (bp->b_actf && bp->b_active == 0) 1682618Swnj (void) rkstart(ui->ui_mi); 1691899Swnj } 1702618Swnj (void) spl0(); 1712618Swnj return; 1722618Swnj 1732618Swnj bad: 1742618Swnj bp->b_flags |= B_ERROR; 1752618Swnj iodone(bp); 1762618Swnj return; 1771899Swnj } 1781899Swnj 1792618Swnj rkustart(ui) 180*2981Swnj register struct uba_device *ui; 1812618Swnj { 1822618Swnj register struct buf *bp, *dp; 183*2981Swnj register struct uba_ctlr *um; 1842618Swnj register struct rkdevice *rkaddr; 1852618Swnj register struct rkst *st; 1862618Swnj daddr_t bn; 1872618Swnj int sn, csn; 1882618Swnj int didie = 0; 1891899Swnj 1902618Swnj if (ui == 0) 1912618Swnj return (0); 1922618Swnj dk_busy &= ~(1<<ui->ui_dk); 1932618Swnj dp = &rkutab[ui->ui_unit]; 1942618Swnj um = ui->ui_mi; 1952894Swnj rkaddr = (struct rkdevice *)um->um_addr; 1962618Swnj if (um->um_tab.b_active) { 1972618Swnj rk_softc[um->um_ctlr].sc_softas |= 1<<ui->ui_slave; 1982618Swnj return (0); 1992618Swnj } 2002618Swnj rkaddr->rkcs1 = RK_CDT|RK_CERR; 2012618Swnj rkaddr->rkcs2 = ui->ui_slave; 2022957Swnj rkaddr->rkcs1 = RK_CDT|RK_DCLR|RK_GO; 2032618Swnj rkwait(rkaddr); 2042903Swnj if ((bp = dp->b_actf) == NULL) { 2052903Swnj rkaddr->rkcs1 = RK_CDT|RK_DCLR|RK_GO; 2062903Swnj rkwait(rkaddr); 2072903Swnj return (0); 2082903Swnj } 2092618Swnj if ((rkaddr->rkds & RK_VV) == 0) { 2102618Swnj /* SHOULD WARN SYSTEM THAT THIS HAPPENED */ 2112894Swnj rkaddr->rkcs1 = RK_CDT|RK_PACK|RK_GO; 2122618Swnj rkwait(rkaddr); 2132618Swnj } 2142903Swnj if (dp->b_active) 2152903Swnj goto done; 2162903Swnj dp->b_active = 1; 2172894Swnj if ((rkaddr->rkds & RK_DREADY) != RK_DREADY) 2182894Swnj goto done; 2192618Swnj if (rk_softc[um->um_ctlr].sc_ndrive == 1) 2202618Swnj goto done; 2212618Swnj if (bp->b_cylin == rkcyl[ui->ui_unit]) 2222618Swnj goto done; 2232618Swnj rkaddr->rkcyl = bp->b_cylin; 2242618Swnj rkcyl[ui->ui_unit] = bp->b_cylin; 2252618Swnj rkaddr->rkcs1 = RK_CDT|RK_IE|RK_SEEK|RK_GO; 2262618Swnj didie = 1; 2272618Swnj if (ui->ui_dk >= 0) { 2282618Swnj dk_busy |= 1<<ui->ui_dk; 2292618Swnj dk_seek[ui->ui_dk]++; 2302618Swnj } 2312618Swnj goto out; 2322618Swnj done: 2332618Swnj if (dp->b_active != 2) { 2342618Swnj dp->b_forw = NULL; 2352618Swnj if (um->um_tab.b_actf == NULL) 2362618Swnj um->um_tab.b_actf = dp; 2372618Swnj else 2382618Swnj um->um_tab.b_actl->b_forw = dp; 2392618Swnj um->um_tab.b_actl = dp; 2402618Swnj dp->b_active = 2; 2412618Swnj } 2422618Swnj out: 2432618Swnj return (didie); 2442618Swnj } 2452618Swnj 2462618Swnj rkstart(um) 247*2981Swnj register struct uba_ctlr *um; 2481899Swnj { 2492618Swnj register struct buf *bp, *dp; 250*2981Swnj register struct uba_device *ui; 2512618Swnj register struct rkdevice *rkaddr; 2522618Swnj struct rkst *st; 2531899Swnj daddr_t bn; 2542618Swnj int sn, tn, cmd; 2551899Swnj 2562618Swnj loop: 2572618Swnj if ((dp = um->um_tab.b_actf) == NULL) 2582618Swnj return (0); 2592618Swnj if ((bp = dp->b_actf) == NULL) { 2602618Swnj um->um_tab.b_actf = dp->b_forw; 2612618Swnj goto loop; 2621899Swnj } 2632618Swnj um->um_tab.b_active++; 2642618Swnj ui = rkdinfo[dkunit(bp)]; 2652618Swnj bn = dkblock(bp); 2662618Swnj st = &rkst[ui->ui_type]; 2672618Swnj sn = bn%st->nspc; 2682618Swnj tn = sn/st->nsect; 2692618Swnj sn %= st->nsect; 2702618Swnj rkaddr = (struct rkdevice *)ui->ui_addr; 2712957Swnj retry: 2722618Swnj rkaddr->rkcs1 = RK_CDT|RK_CERR; 2732618Swnj rkaddr->rkcs2 = ui->ui_slave; 2742957Swnj rkaddr->rkcs1 = RK_CDT|RK_DCLR|RK_GO; 2752618Swnj rkwait(rkaddr); 2762957Swnj if ((rkaddr->rkds&RK_SVAL) == 0) { 2772957Swnj rknosval++; 2782957Swnj goto nosval; 2792894Swnj } 2802957Swnj if (rkaddr->rkds&RK_PIP) { 2812957Swnj rkpip++; 2822957Swnj goto retry; 2832957Swnj } 2842894Swnj if ((rkaddr->rkds&RK_DREADY) != RK_DREADY) { 2852927Swnj printf("rk%d: not ready", dkunit(bp)); 2862894Swnj if ((rkaddr->rkds&RK_DREADY) != RK_DREADY) { 2872894Swnj printf("\n"); 2882894Swnj rkaddr->rkcs1 = RK_CDT|RK_DCLR|RK_GO; 2892894Swnj rkwait(rkaddr); 2902894Swnj rkaddr->rkcs1 = RK_CDT|RK_CERR; 2912894Swnj rkwait(rkaddr); 2922894Swnj um->um_tab.b_active = 0; 2932894Swnj um->um_tab.b_errcnt = 0; 2942894Swnj dp->b_actf = bp->av_forw; 2952894Swnj dp->b_active = 0; 2962894Swnj bp->b_flags |= B_ERROR; 2972894Swnj iodone(bp); 2982894Swnj goto loop; 2992894Swnj } 3002894Swnj printf(" (came back!)\n"); 3012894Swnj } 3022957Swnj nosval: 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) 317*2981Swnj register struct uba_ctlr *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 { 328*2981Swnj register struct uba_ctlr *um = rkminfo[rk11]; 329*2981Swnj register struct uba_device *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) { 3402957Swnj ubadone(um); 3412618Swnj dp = um->um_tab.b_actf; 3422618Swnj bp = dp->b_actf; 3432618Swnj ui = rkdinfo[dkunit(bp)]; 3442618Swnj dk_busy &= ~(1 << ui->ui_dk); 3452618Swnj if (rkaddr->rkcs1 & RK_CERR) { 3462618Swnj int recal; 3472618Swnj u_short ds = rkaddr->rkds; 3482618Swnj u_short cs2 = rkaddr->rkcs2; 3492618Swnj u_short er = rkaddr->rker; 3502685Swnj if (ds & RK_WLE) { 3512927Swnj printf("rk%d: write locked\n", dkunit(bp)); 3522685Swnj bp->b_flags |= B_ERROR; 3532685Swnj } else if (++um->um_tab.b_errcnt > 28 || 3542676Swnj ds&RKDS_HARD || er&RKER_HARD || cs2&RKCS2_HARD) { 3552618Swnj bp->b_flags |= B_ERROR; 3562927Swnj harderr(bp, "rk"); 3572927Swnj printf("cs2=%b ds=%b er=%b\n", 3582894Swnj cs2, RKCS2_BITS, ds, 3592676Swnj RKDS_BITS, er, RKER_BITS); 3602676Swnj } else 3612618Swnj um->um_tab.b_active = 0; 3622618Swnj if (cs2&RK_MDS) { 3632618Swnj rkaddr->rkcs2 = RK_SCLR; 3642618Swnj goto retry; 3651899Swnj } 3662618Swnj recal = 0; 3672618Swnj if (ds&RK_DROT || er&(RK_OPI|RK_SKI|RK_UNS) || 3682618Swnj (um->um_tab.b_errcnt&07) == 4) 3692618Swnj recal = 1; 3702618Swnj if ((er & (RK_DCK|RK_ECH)) == RK_DCK) 3712618Swnj if (rkecc(ui)) 3722618Swnj return; 3732618Swnj rkaddr->rkcs1 = RK_CDT|RK_CCLR; 3742618Swnj rkaddr->rkcs2 = ui->ui_slave; 3752618Swnj rkaddr->rkcs1 = RK_CDT|RK_DCLR|RK_GO; 3762618Swnj rkwait(rkaddr); 3772618Swnj if (recal && um->um_tab.b_active == 0) { 3782618Swnj rkaddr->rkcs1 = RK_CDT|RK_IE|RK_RECAL|RK_GO; 3792618Swnj rkcyl[ui->ui_unit] = -1; 3802957Swnj sc->sc_recal = 0; 3812957Swnj goto nextrecal; 3822618Swnj } 3831899Swnj } 3842618Swnj retry: 3852957Swnj switch (sc->sc_recal) { 3862957Swnj 3872957Swnj case 1: 3882957Swnj rkaddr->rkcyl = bp->b_cylin; 3892957Swnj rkcyl[ui->ui_unit] = bp->b_cylin; 3902957Swnj rkaddr->rkcs1 = RK_CDT|RK_IE|RK_SEEK|RK_GO; 3912957Swnj goto nextrecal; 3922957Swnj 3932957Swnj case 2: 3942957Swnj if (um->um_tab.b_errcnt < 16 || 3952957Swnj (bp->b_flags&B_READ) != 0) 3962957Swnj break; 3972957Swnj rkaddr->rkatt = rk_offset[um->um_tab.b_errcnt & 017]; 3982957Swnj rkaddr->rkcs1 = RK_CDT|RK_IE|RK_OFFSET|RK_GO; 3992957Swnj /* fall into ... */ 4002957Swnj nextrecal: 4012957Swnj sc->sc_recal++; 4022957Swnj rkwait(rkaddr); 4032957Swnj um->um_tab.b_active = 1; 4042957Swnj return; 4052957Swnj 4062957Swnj case 3: 4072618Swnj sc->sc_recal = 0; 4082618Swnj um->um_tab.b_active = 0; 4092957Swnj break; 4101899Swnj } 4112618Swnj if (um->um_tab.b_active) { 4122618Swnj um->um_tab.b_active = 0; 4132618Swnj um->um_tab.b_errcnt = 0; 4142618Swnj um->um_tab.b_actf = dp->b_forw; 4152618Swnj dp->b_active = 0; 4162618Swnj dp->b_errcnt = 0; 4172618Swnj dp->b_actf = bp->av_forw; 4182618Swnj bp->b_resid = -rkaddr->rkwc * sizeof(short); 4192618Swnj iodone(bp); 4202618Swnj if (dp->b_actf) 4212618Swnj if (rkustart(ui)) 4222618Swnj needie = 0; 4231899Swnj } 4242618Swnj as &= ~(1<<ui->ui_slave); 4251899Swnj } 4262618Swnj for (unit = 0; as; as >>= 1, unit++) 427*2981Swnj if (as & 1) { 428*2981Swnj ui = rkip[rk11][unit]; 429*2981Swnj if (ui) { 430*2981Swnj if (rkustart(rkip[rk11][unit])) 431*2981Swnj needie = 0; 432*2981Swnj } else { 433*2981Swnj rkaddr->rkcs1 = RK_CERR|RK_CDT; 434*2981Swnj rkaddr->rkcs2 = unit; 435*2981Swnj rkaddr->rkcs1 = RK_CDT|RK_DCLR|RK_GO; 436*2981Swnj rkwait(rkaddr); 437*2981Swnj } 438*2981Swnj } 4392618Swnj if (um->um_tab.b_actf && um->um_tab.b_active == 0) 4402618Swnj if (rkstart(um)) 4412618Swnj needie = 0; 4422618Swnj if (needie) 4432618Swnj rkaddr->rkcs1 = RK_CDT|RK_IE; 4441899Swnj } 4451899Swnj 4462618Swnj rkwait(addr) 4472618Swnj register struct rkdevice *addr; 4482618Swnj { 4491899Swnj 4502618Swnj while ((addr->rkcs1 & RK_CRDY) == 0) 4512618Swnj ; 4522618Swnj } 4532618Swnj 4542618Swnj rkread(dev) 4552618Swnj dev_t dev; 4561899Swnj { 4572618Swnj register int unit = minor(dev) >> 3; 4582618Swnj 4592648Swnj if (unit >= NRK) 4602618Swnj u.u_error = ENXIO; 4612618Swnj else 4622618Swnj physio(rkstrategy, &rrkbuf[unit], dev, B_READ, minphys); 4631899Swnj } 4641899Swnj 4652618Swnj rkwrite(dev) 4662618Swnj dev_t dev; 4671899Swnj { 4682618Swnj register int unit = minor(dev) >> 3; 4691899Swnj 4702648Swnj if (unit >= NRK) 4712618Swnj u.u_error = ENXIO; 4722618Swnj else 4732618Swnj physio(rkstrategy, &rrkbuf[unit], dev, B_WRITE, minphys); 4741899Swnj } 4751899Swnj 4762618Swnj rkecc(ui) 477*2981Swnj register struct uba_device *ui; 4781899Swnj { 4792618Swnj register struct rkdevice *rk = (struct rkdevice *)ui->ui_addr; 4802618Swnj register struct buf *bp = rkutab[ui->ui_unit].b_actf; 481*2981Swnj register struct uba_ctlr *um = ui->ui_mi; 4822618Swnj register struct rkst *st; 4832618Swnj struct uba_regs *ubp = ui->ui_hd->uh_uba; 4842618Swnj register int i; 4852618Swnj caddr_t addr; 4862618Swnj int reg, bit, byte, npf, mask, o, cmd, ubaddr; 4872618Swnj int bn, cn, tn, sn; 4881899Swnj 4892618Swnj npf = btop((rk->rkwc * sizeof(short)) + bp->b_bcount) - 1; 4902618Swnj reg = btop(um->um_ubinfo&0x3ffff) + npf; 4912618Swnj o = (int)bp->b_un.b_addr & PGOFSET; 4922940Swnj printf("rk%d%c: soft ecc sn%d\n", dkunit(bp), 4932885Swnj 'a'+(minor(bp->b_dev)&07), bp->b_blkno + npf); 4942618Swnj mask = rk->rkec2; 4952724Swnj ubapurge(um); 4962618Swnj i = rk->rkec1 - 1; /* -1 makes 0 origin */ 4972618Swnj bit = i&07; 4982618Swnj i = (i&~07)>>3; 4992618Swnj byte = i + o; 5002618Swnj while (i < 512 && (int)ptob(npf)+i < bp->b_bcount && bit > -11) { 5012618Swnj addr = ptob(ubp->uba_map[reg+btop(byte)].pg_pfnum)+ 5022618Swnj (byte & PGOFSET); 5032618Swnj putmemc(addr, getmemc(addr)^(mask<<bit)); 5042618Swnj byte++; 5052618Swnj i++; 5062618Swnj bit -= 8; 5072618Swnj } 5082618Swnj um->um_tab.b_active++; /* Either complete or continuing... */ 5092618Swnj if (rk->rkwc == 0) 5102618Swnj return (0); 5112622Swnj #ifdef notdef 5122622Swnj rk->rkcs1 |= RK_GO; 5132622Swnj #else 5142618Swnj rk->rkcs1 = RK_CDT|RK_CCLR; 5152618Swnj rk->rkcs2 = ui->ui_slave; 5162618Swnj rk->rkcs1 = RK_CDT|RK_DCLR|RK_GO; 5172618Swnj rkwait(rk); 5182618Swnj bn = dkblock(bp); 5192618Swnj st = &rkst[ui->ui_type]; 5202618Swnj cn = bp->b_cylin; 5212618Swnj sn = bn%st->nspc + npf + 1; 5222618Swnj tn = sn/st->nsect; 5232618Swnj sn %= st->nsect; 5242618Swnj cn += tn/st->ntrak; 5252618Swnj tn %= st->ntrak; 5262618Swnj rk->rkcyl = cn; 5272618Swnj rk->rkda = (tn << 8) | sn; 5282618Swnj ubaddr = (int)ptob(reg+1) + o; 5292618Swnj rk->rkba = ubaddr; 5302618Swnj cmd = (ubaddr >> 8) & 0x300; 5312618Swnj cmd |= RK_CDT|RK_IE|RK_GO|RK_READ; 5322618Swnj rk->rkcs1 = cmd; 5332622Swnj #endif 5342618Swnj return (1); 5351899Swnj } 5361899Swnj 5372618Swnj rkreset(uban) 5382927Swnj int uban; 5391899Swnj { 540*2981Swnj register struct uba_ctlr *um; 541*2981Swnj register struct uba_device *ui; 5422618Swnj register rk11, unit; 5431899Swnj 5442648Swnj for (rk11 = 0; rk11 < NHK; rk11++) { 5452618Swnj if ((um = rkminfo[rk11]) == 0 || um->um_ubanum != uban || 5462618Swnj um->um_alive == 0) 5472618Swnj continue; 5482927Swnj printf(" hk%d", rk11); 5492618Swnj um->um_tab.b_active = 0; 5502618Swnj um->um_tab.b_actf = um->um_tab.b_actl = 0; 5512618Swnj rk_softc[um->um_ctlr].sc_recal = 0; 5522618Swnj if (um->um_ubinfo) { 5532618Swnj printf("<%d>", (um->um_ubinfo>>28)&0xf); 5542618Swnj ubadone(um); 5552618Swnj } 5562648Swnj for (unit = 0; unit < NHK; unit++) { 5572618Swnj if ((ui = rkdinfo[unit]) == 0) 5582618Swnj continue; 5592618Swnj if (ui->ui_alive == 0) 5602618Swnj continue; 5612618Swnj rkutab[unit].b_active = 0; 5622618Swnj (void) rkustart(ui); 5632618Swnj } 5642618Swnj (void) rkstart(um); 5652618Swnj } 5661899Swnj } 5672380Swnj 5682618Swnj rkwatch() 5692380Swnj { 570*2981Swnj register struct uba_ctlr *um; 5712618Swnj register rk11, unit; 5722618Swnj register struct rk_softc *sc; 5732380Swnj 5742758Swnj timeout(rkwatch, (caddr_t)0, hz); 5752648Swnj for (rk11 = 0; rk11 < NHK; rk11++) { 5762618Swnj um = rkminfo[rk11]; 5772618Swnj if (um == 0 || um->um_alive == 0) 5782618Swnj continue; 5792618Swnj sc = &rk_softc[rk11]; 5802618Swnj if (um->um_tab.b_active == 0) { 5812648Swnj for (unit = 0; unit < NRK; unit++) 5822622Swnj if (rkutab[unit].b_active && 5832622Swnj rkdinfo[unit]->ui_mi == um) 5842618Swnj goto active; 5852618Swnj sc->sc_wticks = 0; 5862618Swnj continue; 5872618Swnj } 5882618Swnj active: 5892618Swnj sc->sc_wticks++; 5902618Swnj if (sc->sc_wticks >= 20) { 5912618Swnj sc->sc_wticks = 0; 5922927Swnj printf("hk%d: lost interrupt\n", rk11); 5932648Swnj ubareset(um->um_ubanum); 5942618Swnj } 5952618Swnj } 5962380Swnj } 5972618Swnj 5982618Swnj #define DBSIZE 20 5992618Swnj 6002618Swnj rkdump(dev) 6012618Swnj dev_t dev; 6022618Swnj { 6032618Swnj struct rkdevice *rkaddr; 6042618Swnj char *start; 6052618Swnj int num, blk, unit; 6062618Swnj struct size *sizes; 6072618Swnj register struct uba_regs *uba; 608*2981Swnj register struct uba_device *ui; 6092618Swnj register short *rp; 6102618Swnj struct rkst *st; 6112618Swnj 6122618Swnj unit = minor(dev) >> 3; 6132885Swnj if (unit >= NRK) 6142885Swnj return (ENXIO); 6152618Swnj #define phys(cast, addr) ((cast)((int)addr & 0x7fffffff)) 616*2981Swnj ui = phys(struct uba_device *, rkdinfo[unit]); 6172885Swnj if (ui->ui_alive == 0) 6182885Swnj return (ENXIO); 6192618Swnj uba = phys(struct uba_hd *, ui->ui_hd)->uh_physuba; 6202618Swnj #if VAX780 6212618Swnj if (cpu == VAX_780) 6222618Swnj ubainit(uba); 6231899Swnj #endif 6242618Swnj rkaddr = (struct rkdevice *)ui->ui_physaddr; 6252618Swnj num = maxfree; 6262618Swnj start = 0; 6272618Swnj rkaddr->rkcs1 = RK_CDT|RK_CERR; 6282618Swnj rkaddr->rkcs2 = unit; 6292618Swnj rkaddr->rkcs1 = RK_CDT|RK_DCLR|RK_GO; 6302618Swnj rkwait(rkaddr); 6312618Swnj if ((rkaddr->rkds & RK_VV) == 0) { 6322618Swnj rkaddr->rkcs1 = RK_CDT|RK_IE|RK_PACK|RK_GO; 6332618Swnj rkwait(rkaddr); 6342618Swnj } 6352618Swnj st = &rkst[ui->ui_type]; 6362618Swnj sizes = phys(struct size *, st->sizes); 6372885Swnj if (dumplo < 0 || dumplo + num >= sizes[minor(dev)&07].nblocks) 6382885Swnj return (EINVAL); 6392618Swnj while (num > 0) { 6402618Swnj register struct pte *io; 6412618Swnj register int i; 6422618Swnj int cn, sn, tn; 6432618Swnj daddr_t bn; 6442618Swnj 6452618Swnj blk = num > DBSIZE ? DBSIZE : num; 6462618Swnj io = uba->uba_map; 6472618Swnj for (i = 0; i < blk; i++) 648*2981Swnj *(int *)io++ = (btop(start)+i) | (1<<21) | UBAMR_MRV; 6492618Swnj *(int *)io = 0; 6502618Swnj bn = dumplo + btop(start); 6512618Swnj cn = bn/st->nspc + sizes[minor(dev)&07].cyloff; 6522618Swnj sn = bn%st->nspc; 6532618Swnj tn = sn/st->nsect; 6542618Swnj sn = sn%st->nsect; 6552618Swnj rkaddr->rkcyl = cn; 6562618Swnj rp = (short *) &rkaddr->rkda; 6572618Swnj *rp = (tn << 8) + sn; 6582618Swnj *--rp = 0; 6592618Swnj *--rp = -blk*NBPG / sizeof (short); 6602618Swnj *--rp = RK_CDT|RK_GO|RK_WRITE; 6612618Swnj rkwait(rkaddr); 6622885Swnj if (rkaddr->rkcs1 & RK_CERR) 6632885Swnj return (EIO); 6642618Swnj start += blk*NBPG; 6652618Swnj num -= blk; 6662618Swnj } 6672618Swnj return (0); 6682618Swnj } 6692618Swnj #endif 670