1*18315Sralph /* rk.c 6.4 85/03/12 */ 21899Swnj 31942Swnj #include "rk.h" 42648Swnj #if NHK > 0 53104Swnj int rkpip; /* DEBUG */ 63104Swnj int rknosval; /* DEBUG */ 73709Sroot #ifdef RKDEBUG 83293Swnj int rkdebug; 93709Sroot #endif 103709Sroot #ifdef RKBDEBUG 113709Sroot int rkbdebug; 123709Sroot #endif 131899Swnj /* 143293Swnj * RK611/RK0[67] disk driver 152622Swnj * 162622Swnj * This driver mimics up.c; see it for an explanation of common code. 172685Swnj * 182885Swnj * TODO: 193208Swnj * Learn why we lose an interrupt sometime when spinning drives down 201899Swnj */ 219777Ssam #include "../machine/pte.h" 229777Ssam 2317076Sbloom #include "param.h" 2417076Sbloom #include "systm.h" 2517076Sbloom #include "buf.h" 2617076Sbloom #include "conf.h" 2717076Sbloom #include "dir.h" 2817076Sbloom #include "user.h" 2917076Sbloom #include "map.h" 3017076Sbloom #include "vm.h" 3117076Sbloom #include "dk.h" 3217076Sbloom #include "cmap.h" 3317076Sbloom #include "dkbad.h" 3417076Sbloom #include "uio.h" 3517076Sbloom #include "kernel.h" 36*18315Sralph #include "syslog.h" 371899Swnj 388478Sroot #include "../vax/cpu.h" 3917076Sbloom #include "ubareg.h" 4017076Sbloom #include "ubavar.h" 4117076Sbloom #include "rkreg.h" 421899Swnj 432618Swnj struct rk_softc { 442618Swnj int sc_softas; 452618Swnj int sc_ndrive; 462618Swnj int sc_wticks; 472618Swnj int sc_recal; 482648Swnj } rk_softc[NHK]; 491899Swnj 502618Swnj /* THIS SHOULD BE READ OFF THE PACK, PER DRIVE */ 512787Swnj struct size { 522618Swnj daddr_t nblocks; 532618Swnj int cyloff; 543709Sroot } rk7_sizes[8] ={ 552618Swnj 15884, 0, /* A=cyl 0 thru 240 */ 562665Swnj 10032, 241, /* B=cyl 241 thru 392 */ 572665Swnj 53790, 0, /* C=cyl 0 thru 814 */ 582618Swnj 0, 0, 592618Swnj 0, 0, 602618Swnj 0, 0, 612618Swnj 27786, 393, /* G=cyl 393 thru 813 */ 622618Swnj 0, 0, 633709Sroot }, rk6_sizes[8] ={ 643709Sroot 15884, 0, /* A=cyl 0 thru 240 */ 653709Sroot 11154, 241, /* B=cyl 241 thru 409 */ 663709Sroot 27126, 0, /* C=cyl 0 thru 410 */ 673709Sroot 0, 0, 683709Sroot 0, 0, 693709Sroot 0, 0, 703709Sroot 0, 0, 713709Sroot 0, 0, 722618Swnj }; 732618Swnj /* END OF STUFF WHICH SHOULD BE READ IN PER DISK */ 741899Swnj 753709Sroot short rktypes[] = { RK_CDT, 0 }; 763709Sroot 772618Swnj int rkprobe(), rkslave(), rkattach(), rkdgo(), rkintr(); 782981Swnj struct uba_ctlr *rkminfo[NHK]; 792981Swnj struct uba_device *rkdinfo[NRK]; 802981Swnj struct uba_device *rkip[NHK][4]; 811899Swnj 822618Swnj u_short rkstd[] = { 0777440, 0 }; 832618Swnj struct uba_driver hkdriver = 842622Swnj { rkprobe, rkslave, rkattach, rkdgo, rkstd, "rk", rkdinfo, "hk", rkminfo, 1 }; 852648Swnj struct buf rkutab[NRK]; 862648Swnj short rkcyl[NRK]; 873709Sroot struct dkbad rkbad[NRK]; 883709Sroot struct buf brkbuf[NRK]; 891899Swnj 902618Swnj struct rkst { 912618Swnj short nsect; 922618Swnj short ntrak; 932618Swnj short nspc; 942618Swnj short ncyl; 952618Swnj struct size *sizes; 962618Swnj } rkst[] = { 972618Swnj NRKSECT, NRKTRK, NRKSECT*NRKTRK, NRK7CYL, rk7_sizes, 983709Sroot NRKSECT, NRKTRK, NRKSECT*NRKTRK, NRK6CYL, rk6_sizes, 992618Swnj }; 1001899Swnj 1012618Swnj u_char rk_offset[16] = 1023293Swnj { RKAS_P400,RKAS_M400,RKAS_P400,RKAS_M400,RKAS_P800,RKAS_M800,RKAS_P800, 1033293Swnj RKAS_M800,RKAS_P1200,RKAS_M1200,RKAS_P1200,RKAS_M1200,0,0,0,0 1043293Swnj }; 1051899Swnj 1062648Swnj struct buf rrkbuf[NRK]; 1072618Swnj 1082618Swnj #define b_cylin b_resid 1092618Swnj 1102618Swnj #ifdef INTRLVE 1112618Swnj daddr_t dkblock(); 1122618Swnj #endif 1132618Swnj 1142618Swnj int rkwstart, rkwatch(); 1152618Swnj 1162618Swnj rkprobe(reg) 1172618Swnj caddr_t reg; 1181899Swnj { 1192618Swnj register int br, cvec; 1201899Swnj 1212618Swnj #ifdef lint 1222618Swnj br = 0; cvec = br; br = cvec; 1234935Swnj rkintr(0); 1242618Swnj #endif 1252618Swnj ((struct rkdevice *)reg)->rkcs1 = RK_CDT|RK_IE|RK_CRDY; 1262618Swnj DELAY(10); 1272618Swnj ((struct rkdevice *)reg)->rkcs1 = RK_CDT; 1287416Skre return (sizeof (struct rkdevice)); 1292618Swnj } 1301899Swnj 1312618Swnj rkslave(ui, reg) 1322981Swnj struct uba_device *ui; 1332618Swnj caddr_t reg; 1342618Swnj { 1352618Swnj register struct rkdevice *rkaddr = (struct rkdevice *)reg; 1361899Swnj 1373709Sroot ui->ui_type = 0; 1383709Sroot rkaddr->rkcs1 = RK_CCLR; 1392618Swnj rkaddr->rkcs2 = ui->ui_slave; 1402957Swnj rkaddr->rkcs1 = RK_CDT|RK_DCLR|RK_GO; 1412622Swnj rkwait(rkaddr); 1422894Swnj DELAY(50); 1433293Swnj if (rkaddr->rkcs2&RKCS2_NED || (rkaddr->rkds&RKDS_SVAL) == 0) { 1443709Sroot rkaddr->rkcs1 = RK_CCLR; 1452618Swnj return (0); 1462618Swnj } 1473709Sroot if (rkaddr->rkcs1&RK_CERR && rkaddr->rker&RKER_DTYE) { 1483709Sroot ui->ui_type = 1; 1493709Sroot rkaddr->rkcs1 = RK_CCLR; 1503709Sroot } 1512618Swnj return (1); 1522618Swnj } 1532618Swnj 1542618Swnj rkattach(ui) 1552981Swnj register struct uba_device *ui; 1562618Swnj { 1572618Swnj 1582618Swnj if (rkwstart == 0) { 1592758Swnj timeout(rkwatch, (caddr_t)0, hz); 1602618Swnj rkwstart++; 1612618Swnj } 1622618Swnj if (ui->ui_dk >= 0) 1632758Swnj dk_mspw[ui->ui_dk] = 1.0 / (60 * NRKSECT * 256); 1642618Swnj rkip[ui->ui_ctlr][ui->ui_slave] = ui; 1652618Swnj rk_softc[ui->ui_ctlr].sc_ndrive++; 1662618Swnj rkcyl[ui->ui_unit] = -1; 1673709Sroot ui->ui_flags = 0; 1682618Swnj } 1692618Swnj 1708573Sroot rkopen(dev) 1718573Sroot dev_t dev; 1728573Sroot { 1738573Sroot register int unit = minor(dev) >> 3; 1748573Sroot register struct uba_device *ui; 1758573Sroot 1768573Sroot if (unit >= NRK || (ui = rkdinfo[unit]) == 0 || ui->ui_alive == 0) 1778573Sroot return (ENXIO); 1788573Sroot return (0); 1798573Sroot } 1808573Sroot 1811899Swnj rkstrategy(bp) 1822618Swnj register struct buf *bp; 1831899Swnj { 1842981Swnj register struct uba_device *ui; 1852618Swnj register struct rkst *st; 1862618Swnj register int unit; 1872618Swnj register struct buf *dp; 1882618Swnj int xunit = minor(bp->b_dev) & 07; 1892618Swnj long bn, sz; 1905433Sroot int s; 1911899Swnj 1922618Swnj sz = (bp->b_bcount+511) >> 9; 1932618Swnj unit = dkunit(bp); 1942648Swnj if (unit >= NRK) 1952618Swnj goto bad; 1962618Swnj ui = rkdinfo[unit]; 1972618Swnj if (ui == 0 || ui->ui_alive == 0) 1982618Swnj goto bad; 1992618Swnj st = &rkst[ui->ui_type]; 2002618Swnj if (bp->b_blkno < 0 || 2012618Swnj (bn = dkblock(bp))+sz > st->sizes[xunit].nblocks) 2022618Swnj goto bad; 2032618Swnj bp->b_cylin = bn/st->nspc + st->sizes[xunit].cyloff; 2045433Sroot s = spl5(); 2052618Swnj dp = &rkutab[ui->ui_unit]; 2062618Swnj disksort(dp, bp); 2072618Swnj if (dp->b_active == 0) { 2082618Swnj (void) rkustart(ui); 2092618Swnj bp = &ui->ui_mi->um_tab; 2102618Swnj if (bp->b_actf && bp->b_active == 0) 2112618Swnj (void) rkstart(ui->ui_mi); 2121899Swnj } 2135433Sroot splx(s); 2142618Swnj return; 2152618Swnj 2162618Swnj bad: 2172618Swnj bp->b_flags |= B_ERROR; 2182618Swnj iodone(bp); 2192618Swnj return; 2201899Swnj } 2211899Swnj 2222618Swnj rkustart(ui) 2232981Swnj register struct uba_device *ui; 2242618Swnj { 2252618Swnj register struct buf *bp, *dp; 2262981Swnj register struct uba_ctlr *um; 2272618Swnj register struct rkdevice *rkaddr; 2281899Swnj 2292618Swnj if (ui == 0) 2306347Swnj return; 2312618Swnj dk_busy &= ~(1<<ui->ui_dk); 2322618Swnj dp = &rkutab[ui->ui_unit]; 2332618Swnj um = ui->ui_mi; 2342894Swnj rkaddr = (struct rkdevice *)um->um_addr; 2352618Swnj if (um->um_tab.b_active) { 2362618Swnj rk_softc[um->um_ctlr].sc_softas |= 1<<ui->ui_slave; 2376347Swnj return; 2382618Swnj } 2396347Swnj if ((bp = dp->b_actf) == NULL) 2406347Swnj return; 2413709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_CERR; 2422618Swnj rkaddr->rkcs2 = ui->ui_slave; 2433709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO; 2442618Swnj rkwait(rkaddr); 2453709Sroot if ((rkaddr->rkds & RKDS_VV) == 0 || ui->ui_flags == 0) { 2462618Swnj /* SHOULD WARN SYSTEM THAT THIS HAPPENED */ 2473709Sroot struct rkst *st = &rkst[ui->ui_type]; 2483709Sroot struct buf *bbp = &brkbuf[ui->ui_unit]; 2493709Sroot 2503709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_PACK|RK_GO; 2513709Sroot ui->ui_flags = 1; 2523709Sroot bbp->b_flags = B_READ|B_BUSY; 2533709Sroot bbp->b_dev = bp->b_dev; 2543709Sroot bbp->b_bcount = 512; 2553709Sroot bbp->b_un.b_addr = (caddr_t)&rkbad[ui->ui_unit]; 2563709Sroot bbp->b_blkno = st->ncyl*st->nspc - st->nsect; 2573709Sroot bbp->b_cylin = st->ncyl - 1; 2583709Sroot dp->b_actf = bbp; 2593709Sroot bbp->av_forw = bp; 2603709Sroot bp = bbp; 2612618Swnj rkwait(rkaddr); 2622618Swnj } 2632903Swnj if (dp->b_active) 2642903Swnj goto done; 2652903Swnj dp->b_active = 1; 2663293Swnj if ((rkaddr->rkds & RKDS_DREADY) != RKDS_DREADY) 2672894Swnj goto done; 2682618Swnj if (rk_softc[um->um_ctlr].sc_ndrive == 1) 2692618Swnj goto done; 2702618Swnj if (bp->b_cylin == rkcyl[ui->ui_unit]) 2712618Swnj goto done; 2722618Swnj rkaddr->rkcyl = bp->b_cylin; 2732618Swnj rkcyl[ui->ui_unit] = bp->b_cylin; 2743709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_IE|RK_SEEK|RK_GO; 2752618Swnj if (ui->ui_dk >= 0) { 2762618Swnj dk_busy |= 1<<ui->ui_dk; 2772618Swnj dk_seek[ui->ui_dk]++; 2782618Swnj } 2792618Swnj goto out; 2802618Swnj done: 2812618Swnj if (dp->b_active != 2) { 2822618Swnj dp->b_forw = NULL; 2832618Swnj if (um->um_tab.b_actf == NULL) 2842618Swnj um->um_tab.b_actf = dp; 2852618Swnj else 2862618Swnj um->um_tab.b_actl->b_forw = dp; 2872618Swnj um->um_tab.b_actl = dp; 2882618Swnj dp->b_active = 2; 2892618Swnj } 2902618Swnj out: 2916347Swnj return; 2922618Swnj } 2932618Swnj 2942618Swnj rkstart(um) 2952981Swnj register struct uba_ctlr *um; 2961899Swnj { 2972618Swnj register struct buf *bp, *dp; 2982981Swnj register struct uba_device *ui; 2992618Swnj register struct rkdevice *rkaddr; 3002618Swnj struct rkst *st; 3011899Swnj daddr_t bn; 3022618Swnj int sn, tn, cmd; 3031899Swnj 3042618Swnj loop: 3052618Swnj if ((dp = um->um_tab.b_actf) == NULL) 3066347Swnj return; 3072618Swnj if ((bp = dp->b_actf) == NULL) { 3082618Swnj um->um_tab.b_actf = dp->b_forw; 3092618Swnj goto loop; 3101899Swnj } 3112618Swnj um->um_tab.b_active++; 3122618Swnj ui = rkdinfo[dkunit(bp)]; 3132618Swnj bn = dkblock(bp); 3142618Swnj st = &rkst[ui->ui_type]; 3152618Swnj sn = bn%st->nspc; 3162618Swnj tn = sn/st->nsect; 3172618Swnj sn %= st->nsect; 3182618Swnj rkaddr = (struct rkdevice *)ui->ui_addr; 3192957Swnj retry: 3203709Sroot rkaddr->rkcs1 = RK_CCLR; 3212618Swnj rkaddr->rkcs2 = ui->ui_slave; 3223709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO; 3232618Swnj rkwait(rkaddr); 3243293Swnj if ((rkaddr->rkds&RKDS_SVAL) == 0) { 3252957Swnj rknosval++; 3262957Swnj goto nosval; 3272894Swnj } 3283293Swnj if (rkaddr->rkds&RKDS_PIP) { 3292957Swnj rkpip++; 3302957Swnj goto retry; 3312957Swnj } 3323293Swnj if ((rkaddr->rkds&RKDS_DREADY) != RKDS_DREADY) { 3332927Swnj printf("rk%d: not ready", dkunit(bp)); 3343293Swnj if ((rkaddr->rkds&RKDS_DREADY) != RKDS_DREADY) { 3352894Swnj printf("\n"); 3363709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO; 3372894Swnj rkwait(rkaddr); 3383709Sroot rkaddr->rkcs1 = RK_CCLR; 3392894Swnj rkwait(rkaddr); 3402894Swnj um->um_tab.b_active = 0; 3412894Swnj um->um_tab.b_errcnt = 0; 3422894Swnj dp->b_actf = bp->av_forw; 3432894Swnj dp->b_active = 0; 3442894Swnj bp->b_flags |= B_ERROR; 3452894Swnj iodone(bp); 3462894Swnj goto loop; 3472894Swnj } 3482894Swnj printf(" (came back!)\n"); 3492894Swnj } 3502957Swnj nosval: 3512618Swnj rkaddr->rkcyl = bp->b_cylin; 3522618Swnj rkcyl[ui->ui_unit] = bp->b_cylin; 3532618Swnj rkaddr->rkda = (tn << 8) + sn; 3542618Swnj rkaddr->rkwc = -bp->b_bcount / sizeof (short); 3552618Swnj if (bp->b_flags & B_READ) 3563709Sroot cmd = rktypes[ui->ui_type]|RK_IE|RK_READ|RK_GO; 3572618Swnj else 3583709Sroot cmd = rktypes[ui->ui_type]|RK_IE|RK_WRITE|RK_GO; 3592618Swnj um->um_cmd = cmd; 3603104Swnj (void) ubago(ui); 3611899Swnj } 3621899Swnj 3632618Swnj rkdgo(um) 3642981Swnj register struct uba_ctlr *um; 3651899Swnj { 3662618Swnj register struct rkdevice *rkaddr = (struct rkdevice *)um->um_addr; 3671899Swnj 3687031Swnj um->um_tab.b_active = 2; /* should now be 2 */ 3692618Swnj rkaddr->rkba = um->um_ubinfo; 3702618Swnj rkaddr->rkcs1 = um->um_cmd|((um->um_ubinfo>>8)&0x300); 3712618Swnj } 3722618Swnj 3732710Swnj rkintr(rk11) 3742618Swnj int rk11; 3752618Swnj { 3762981Swnj register struct uba_ctlr *um = rkminfo[rk11]; 3772981Swnj register struct uba_device *ui; 3782618Swnj register struct rkdevice *rkaddr = (struct rkdevice *)um->um_addr; 3792618Swnj register struct buf *bp, *dp; 3802618Swnj int unit; 3812618Swnj struct rk_softc *sc = &rk_softc[um->um_ctlr]; 3822618Swnj int as = (rkaddr->rkatt >> 8) | sc->sc_softas; 3832618Swnj 3842618Swnj sc->sc_wticks = 0; 3852618Swnj sc->sc_softas = 0; 3866347Swnj if (um->um_tab.b_active == 2 || sc->sc_recal) { 3877031Swnj um->um_tab.b_active = 1; 3882618Swnj dp = um->um_tab.b_actf; 3892618Swnj bp = dp->b_actf; 3902618Swnj ui = rkdinfo[dkunit(bp)]; 3912618Swnj dk_busy &= ~(1 << ui->ui_dk); 3923709Sroot if (bp->b_flags&B_BAD) 3933709Sroot if (rkecc(ui, CONT)) 3943709Sroot return; 3952618Swnj if (rkaddr->rkcs1 & RK_CERR) { 3962618Swnj int recal; 3972618Swnj u_short ds = rkaddr->rkds; 3982618Swnj u_short cs2 = rkaddr->rkcs2; 3992618Swnj u_short er = rkaddr->rker; 4003709Sroot #ifdef RKDEBUG 4013293Swnj if (rkdebug) { 4023293Swnj printf("cs2=%b ds=%b er=%b\n", 4033293Swnj cs2, RKCS2_BITS, ds, 4043293Swnj RKDS_BITS, er, RKER_BITS); 4053293Swnj } 4063709Sroot #endif 4073293Swnj if (er & RKER_WLE) { 4082927Swnj printf("rk%d: write locked\n", dkunit(bp)); 4092685Swnj bp->b_flags |= B_ERROR; 4102685Swnj } else if (++um->um_tab.b_errcnt > 28 || 4112676Swnj ds&RKDS_HARD || er&RKER_HARD || cs2&RKCS2_HARD) { 4123709Sroot hard: 4132927Swnj harderr(bp, "rk"); 4142927Swnj printf("cs2=%b ds=%b er=%b\n", 4152894Swnj cs2, RKCS2_BITS, ds, 4162676Swnj RKDS_BITS, er, RKER_BITS); 4173145Swnj bp->b_flags |= B_ERROR; 4183145Swnj sc->sc_recal = 0; 4193709Sroot } else if (er & RKER_BSE) { 4203709Sroot if (rkecc(ui, BSE)) 4213709Sroot return; 4223709Sroot else 4233709Sroot goto hard; 4247182Sroot } else { 4257182Sroot if ((er & (RKER_DCK|RKER_ECH)) == RKER_DCK) { 4267182Sroot if (rkecc(ui, ECC)) 4277182Sroot return; 4287182Sroot } else 4297182Sroot um->um_tab.b_active = 0; 4307182Sroot } 4313293Swnj if (cs2&RKCS2_MDS) { 4323293Swnj rkaddr->rkcs2 = RKCS2_SCLR; 4332618Swnj goto retry; 4341899Swnj } 4352618Swnj recal = 0; 4363293Swnj if (ds&RKDS_DROT || er&(RKER_OPI|RKER_SKI|RKER_UNS) || 4372618Swnj (um->um_tab.b_errcnt&07) == 4) 4382618Swnj recal = 1; 4393709Sroot rkaddr->rkcs1 = RK_CCLR; 4402618Swnj rkaddr->rkcs2 = ui->ui_slave; 4413709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO; 4422618Swnj rkwait(rkaddr); 4432618Swnj if (recal && um->um_tab.b_active == 0) { 4443709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_IE|RK_RECAL|RK_GO; 4452618Swnj rkcyl[ui->ui_unit] = -1; 4462957Swnj sc->sc_recal = 0; 4472957Swnj goto nextrecal; 4482618Swnj } 4491899Swnj } 4502618Swnj retry: 4512957Swnj switch (sc->sc_recal) { 4522957Swnj 4532957Swnj case 1: 4542957Swnj rkaddr->rkcyl = bp->b_cylin; 4552957Swnj rkcyl[ui->ui_unit] = bp->b_cylin; 4563709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_IE|RK_SEEK|RK_GO; 4572957Swnj goto nextrecal; 4582957Swnj case 2: 4592957Swnj if (um->um_tab.b_errcnt < 16 || 4603290Swnj (bp->b_flags&B_READ) == 0) 4613159Swnj goto donerecal; 4622957Swnj rkaddr->rkatt = rk_offset[um->um_tab.b_errcnt & 017]; 4633709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_IE|RK_OFFSET|RK_GO; 4642957Swnj /* fall into ... */ 4652957Swnj nextrecal: 4662957Swnj sc->sc_recal++; 4672957Swnj rkwait(rkaddr); 4682957Swnj um->um_tab.b_active = 1; 4692957Swnj return; 4703159Swnj donerecal: 4712957Swnj case 3: 4722618Swnj sc->sc_recal = 0; 4732618Swnj um->um_tab.b_active = 0; 4742957Swnj break; 4751899Swnj } 4763709Sroot ubadone(um); 4772618Swnj if (um->um_tab.b_active) { 4782618Swnj um->um_tab.b_active = 0; 4792618Swnj um->um_tab.b_errcnt = 0; 4802618Swnj um->um_tab.b_actf = dp->b_forw; 4812618Swnj dp->b_active = 0; 4822618Swnj dp->b_errcnt = 0; 4832618Swnj dp->b_actf = bp->av_forw; 4842618Swnj bp->b_resid = -rkaddr->rkwc * sizeof(short); 4852618Swnj iodone(bp); 4862618Swnj if (dp->b_actf) 4876347Swnj rkustart(ui); 4881899Swnj } 4892618Swnj as &= ~(1<<ui->ui_slave); 4901899Swnj } 4912618Swnj for (unit = 0; as; as >>= 1, unit++) 4922981Swnj if (as & 1) { 4932981Swnj ui = rkip[rk11][unit]; 4942981Swnj if (ui) { 4956347Swnj rkustart(rkip[rk11][unit]); 4962981Swnj } else { 4973709Sroot rkaddr->rkcs1 = RK_CCLR; 4982981Swnj rkaddr->rkcs2 = unit; 4993709Sroot rkaddr->rkcs1 = RK_DCLR|RK_GO; 5002981Swnj rkwait(rkaddr); 5013709Sroot rkaddr->rkcs1 = RK_CCLR; 5022981Swnj } 5032981Swnj } 5042618Swnj if (um->um_tab.b_actf && um->um_tab.b_active == 0) 5056347Swnj rkstart(um); 5068609Sroot if (((rkaddr->rkcs1) & RK_IE) == 0) 5073709Sroot rkaddr->rkcs1 = RK_IE; 5081899Swnj } 5091899Swnj 5102618Swnj rkwait(addr) 5112618Swnj register struct rkdevice *addr; 5122618Swnj { 5131899Swnj 5142618Swnj while ((addr->rkcs1 & RK_CRDY) == 0) 5152618Swnj ; 5162618Swnj } 5172618Swnj 5187731Sroot rkread(dev, uio) 5192618Swnj dev_t dev; 5207731Sroot struct uio *uio; 5211899Swnj { 5222618Swnj register int unit = minor(dev) >> 3; 5232618Swnj 5242648Swnj if (unit >= NRK) 5258162Sroot return (ENXIO); 5268162Sroot return (physio(rkstrategy, &rrkbuf[unit], dev, B_READ, minphys, uio)); 5271899Swnj } 5281899Swnj 5297836Sroot rkwrite(dev, uio) 5302618Swnj dev_t dev; 5317836Sroot struct uio *uio; 5321899Swnj { 5332618Swnj register int unit = minor(dev) >> 3; 5341899Swnj 5352648Swnj if (unit >= NRK) 5368493Sroot return (ENXIO); 5378493Sroot return (physio(rkstrategy, &rrkbuf[unit], dev, B_WRITE, minphys, uio)); 5381899Swnj } 5391899Swnj 5403709Sroot rkecc(ui, flag) 5412981Swnj register struct uba_device *ui; 5421899Swnj { 5432618Swnj register struct rkdevice *rk = (struct rkdevice *)ui->ui_addr; 5442618Swnj register struct buf *bp = rkutab[ui->ui_unit].b_actf; 5452981Swnj register struct uba_ctlr *um = ui->ui_mi; 5462618Swnj register struct rkst *st; 5472618Swnj struct uba_regs *ubp = ui->ui_hd->uh_uba; 5482618Swnj caddr_t addr; 5493709Sroot int reg, npf, o, cmd, ubaddr; 5502618Swnj int bn, cn, tn, sn; 5511899Swnj 5523709Sroot if (flag == CONT) 5533709Sroot npf = bp->b_error; 5543709Sroot else 5553709Sroot npf = btop((rk->rkwc * sizeof(short)) + bp->b_bcount); 5562618Swnj reg = btop(um->um_ubinfo&0x3ffff) + npf; 5572618Swnj o = (int)bp->b_un.b_addr & PGOFSET; 5582618Swnj bn = dkblock(bp); 5592618Swnj st = &rkst[ui->ui_type]; 5602618Swnj cn = bp->b_cylin; 5613709Sroot sn = bn%st->nspc + npf; 5622618Swnj tn = sn/st->nsect; 5632618Swnj sn %= st->nsect; 5642618Swnj cn += tn/st->ntrak; 5652618Swnj tn %= st->ntrak; 5663709Sroot ubapurge(um); 5673709Sroot switch (flag) { 5683709Sroot case ECC: 5693709Sroot { 5703709Sroot register int i; 5713709Sroot int bit, byte, mask; 5723709Sroot 5733709Sroot npf--; 5743709Sroot reg--; 575*18315Sralph log(KERN_RECOV, "rk%d%c: soft ecc sn%d\n", dkunit(bp), 5763709Sroot 'a'+(minor(bp->b_dev)&07), bp->b_blkno + npf); 5773709Sroot mask = rk->rkec2; 5783709Sroot i = rk->rkec1 - 1; /* -1 makes 0 origin */ 5793709Sroot bit = i&07; 5803709Sroot i = (i&~07)>>3; 5813709Sroot byte = i + o; 5823709Sroot while (i < 512 && (int)ptob(npf)+i < bp->b_bcount && bit > -11) { 5833709Sroot addr = ptob(ubp->uba_map[reg+btop(byte)].pg_pfnum)+ 5843709Sroot (byte & PGOFSET); 5853709Sroot putmemc(addr, getmemc(addr)^(mask<<bit)); 5863709Sroot byte++; 5873709Sroot i++; 5883709Sroot bit -= 8; 5893709Sroot } 5907182Sroot if (rk->rkwc == 0) { 5917182Sroot um->um_tab.b_active = 0; 5923709Sroot return (0); 5937182Sroot } 5943709Sroot npf++; 5953709Sroot reg++; 5963709Sroot break; 5973709Sroot } 5983709Sroot 5993709Sroot case BSE: 6003709Sroot #ifdef RKBDEBUG 6013709Sroot if (rkbdebug) 6023709Sroot printf("rkecc, BSE: bn %d cn %d tn %d sn %d\n", bn, cn, tn, sn); 6033709Sroot #endif 6043709Sroot if ((bn = isbad(&rkbad[ui->ui_unit], cn, tn, sn)) < 0) 6053709Sroot return(0); 6063709Sroot bp->b_flags |= B_BAD; 6073709Sroot bp->b_error = npf + 1; 6083709Sroot bn = st->ncyl*st->nspc - st->nsect - 1 - bn; 6093709Sroot cn = bn/st->nspc; 6103709Sroot sn = bn%st->nspc; 6113709Sroot tn = sn/st->nsect; 6123709Sroot sn %= st->nsect; 6133709Sroot #ifdef RKBDEBUG 6143709Sroot if (rkbdebug) 6153709Sroot printf("revector to cn %d tn %d sn %d\n", cn, tn, sn); 6163709Sroot #endif 6173709Sroot rk->rkwc = -(512 / sizeof (short)); 6183709Sroot break; 6193709Sroot 6203709Sroot case CONT: 6213709Sroot #ifdef RKBDEBUG 6223709Sroot if (rkbdebug) 6233709Sroot printf("rkecc, CONT: bn %d cn %d tn %d sn %d\n", bn,cn,tn,sn); 6243709Sroot #endif 6253709Sroot bp->b_flags &= ~B_BAD; 6263709Sroot rk->rkwc = -((bp->b_bcount - (int)ptob(npf)) / sizeof (short)); 62715213Skarels if (rk->rkwc == 0) 6287182Sroot return (0); 6293709Sroot break; 6303709Sroot } 6313709Sroot rk->rkcs1 = RK_CCLR; 6323709Sroot rk->rkcs2 = ui->ui_slave; 6333709Sroot rk->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO; 6343709Sroot rkwait(rk); 6352618Swnj rk->rkcyl = cn; 6362618Swnj rk->rkda = (tn << 8) | sn; 6373709Sroot ubaddr = (int)ptob(reg) + o; 6382618Swnj rk->rkba = ubaddr; 6393709Sroot cmd = (bp->b_flags&B_READ ? RK_READ : RK_WRITE)|RK_IE|RK_GO; 6403709Sroot cmd |= (ubaddr >> 8) & 0x300; 6413709Sroot cmd |= rktypes[ui->ui_type]; 6422618Swnj rk->rkcs1 = cmd; 6437031Swnj um->um_tab.b_active = 2; /* continuing */ 6443709Sroot um->um_tab.b_errcnt = 0; /* error has been corrected */ 6452618Swnj return (1); 6461899Swnj } 6471899Swnj 6482618Swnj rkreset(uban) 6492927Swnj int uban; 6501899Swnj { 6512981Swnj register struct uba_ctlr *um; 6522981Swnj register struct uba_device *ui; 6532618Swnj register rk11, unit; 6541899Swnj 6552648Swnj for (rk11 = 0; rk11 < NHK; rk11++) { 6562618Swnj if ((um = rkminfo[rk11]) == 0 || um->um_ubanum != uban || 6572618Swnj um->um_alive == 0) 6582618Swnj continue; 6592927Swnj printf(" hk%d", rk11); 6602618Swnj um->um_tab.b_active = 0; 6612618Swnj um->um_tab.b_actf = um->um_tab.b_actl = 0; 6622618Swnj rk_softc[um->um_ctlr].sc_recal = 0; 6636347Swnj rk_softc[um->um_ctlr].sc_wticks = 0; 6642618Swnj if (um->um_ubinfo) { 6652618Swnj printf("<%d>", (um->um_ubinfo>>28)&0xf); 6669354Ssam um->um_ubinfo = 0; 6672618Swnj } 6684039Swnj for (unit = 0; unit < NRK; unit++) { 6692618Swnj if ((ui = rkdinfo[unit]) == 0) 6702618Swnj continue; 6714039Swnj if (ui->ui_alive == 0 || ui->ui_mi != um) 6722618Swnj continue; 6732618Swnj rkutab[unit].b_active = 0; 6742618Swnj (void) rkustart(ui); 6752618Swnj } 6762618Swnj (void) rkstart(um); 6772618Swnj } 6781899Swnj } 6792380Swnj 6802618Swnj rkwatch() 6812380Swnj { 6822981Swnj register struct uba_ctlr *um; 6832618Swnj register rk11, unit; 6842618Swnj register struct rk_softc *sc; 6852380Swnj 6862758Swnj timeout(rkwatch, (caddr_t)0, hz); 6872648Swnj for (rk11 = 0; rk11 < NHK; rk11++) { 6882618Swnj um = rkminfo[rk11]; 6892618Swnj if (um == 0 || um->um_alive == 0) 6902618Swnj continue; 6912618Swnj sc = &rk_softc[rk11]; 6922618Swnj if (um->um_tab.b_active == 0) { 6932648Swnj for (unit = 0; unit < NRK; unit++) 6942622Swnj if (rkutab[unit].b_active && 6952622Swnj rkdinfo[unit]->ui_mi == um) 6962618Swnj goto active; 6972618Swnj sc->sc_wticks = 0; 6982618Swnj continue; 6992618Swnj } 7002618Swnj active: 7012618Swnj sc->sc_wticks++; 7022618Swnj if (sc->sc_wticks >= 20) { 7032618Swnj sc->sc_wticks = 0; 7042927Swnj printf("hk%d: lost interrupt\n", rk11); 7052648Swnj ubareset(um->um_ubanum); 7062618Swnj } 7072618Swnj } 7082380Swnj } 7092618Swnj 7102618Swnj #define DBSIZE 20 7112618Swnj 7122618Swnj rkdump(dev) 7132618Swnj dev_t dev; 7142618Swnj { 7152618Swnj struct rkdevice *rkaddr; 7162618Swnj char *start; 7172618Swnj int num, blk, unit; 7182618Swnj struct size *sizes; 7192618Swnj register struct uba_regs *uba; 7202981Swnj register struct uba_device *ui; 7212618Swnj register short *rp; 7222618Swnj struct rkst *st; 7232618Swnj 7242618Swnj unit = minor(dev) >> 3; 7252885Swnj if (unit >= NRK) 7262885Swnj return (ENXIO); 7272618Swnj #define phys(cast, addr) ((cast)((int)addr & 0x7fffffff)) 7282981Swnj ui = phys(struct uba_device *, rkdinfo[unit]); 7292885Swnj if (ui->ui_alive == 0) 7302885Swnj return (ENXIO); 7312618Swnj uba = phys(struct uba_hd *, ui->ui_hd)->uh_physuba; 7323329Swnj ubainit(uba); 7332618Swnj rkaddr = (struct rkdevice *)ui->ui_physaddr; 7342618Swnj num = maxfree; 7352618Swnj start = 0; 7363709Sroot rkaddr->rkcs1 = RK_CCLR; 7372618Swnj rkaddr->rkcs2 = unit; 7383709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO; 7392618Swnj rkwait(rkaddr); 7403293Swnj if ((rkaddr->rkds & RKDS_VV) == 0) { 7413709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_IE|RK_PACK|RK_GO; 7422618Swnj rkwait(rkaddr); 7432618Swnj } 7442618Swnj st = &rkst[ui->ui_type]; 7452618Swnj sizes = phys(struct size *, st->sizes); 7462885Swnj if (dumplo < 0 || dumplo + num >= sizes[minor(dev)&07].nblocks) 7472885Swnj return (EINVAL); 7482618Swnj while (num > 0) { 7492618Swnj register struct pte *io; 7502618Swnj register int i; 7512618Swnj int cn, sn, tn; 7522618Swnj daddr_t bn; 7532618Swnj 7542618Swnj blk = num > DBSIZE ? DBSIZE : num; 7552618Swnj io = uba->uba_map; 7562618Swnj for (i = 0; i < blk; i++) 7572981Swnj *(int *)io++ = (btop(start)+i) | (1<<21) | UBAMR_MRV; 7582618Swnj *(int *)io = 0; 7592618Swnj bn = dumplo + btop(start); 7602618Swnj cn = bn/st->nspc + sizes[minor(dev)&07].cyloff; 7612618Swnj sn = bn%st->nspc; 7622618Swnj tn = sn/st->nsect; 7632618Swnj sn = sn%st->nsect; 7642618Swnj rkaddr->rkcyl = cn; 7652618Swnj rp = (short *) &rkaddr->rkda; 7662618Swnj *rp = (tn << 8) + sn; 7672618Swnj *--rp = 0; 7682618Swnj *--rp = -blk*NBPG / sizeof (short); 7693709Sroot *--rp = rktypes[ui->ui_type]|RK_GO|RK_WRITE; 7702618Swnj rkwait(rkaddr); 7712885Swnj if (rkaddr->rkcs1 & RK_CERR) 7722885Swnj return (EIO); 7732618Swnj start += blk*NBPG; 7742618Swnj num -= blk; 7752618Swnj } 7762618Swnj return (0); 7772618Swnj } 77812503Ssam 77912503Ssam rksize(dev) 78012503Ssam dev_t dev; 78112503Ssam { 78212503Ssam int unit = minor(dev) >> 3; 78312503Ssam struct uba_device *ui; 78412503Ssam struct rkst *st; 78512503Ssam 78612503Ssam if (unit >= NRK || (ui = rkdinfo[unit]) == 0 || ui->ui_alive == 0) 78712503Ssam return (-1); 78812503Ssam st = &rkst[ui->ui_type]; 78912503Ssam return (st->sizes[minor(dev) & 07].nblocks); 79012503Ssam } 7912618Swnj #endif 792