1*8478Sroot /* rk.c 4.46 82/10/10 */ 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 */ 211899Swnj #include "../h/param.h" 221899Swnj #include "../h/systm.h" 231899Swnj #include "../h/buf.h" 241899Swnj #include "../h/conf.h" 251899Swnj #include "../h/dir.h" 261899Swnj #include "../h/user.h" 271899Swnj #include "../h/pte.h" 281899Swnj #include "../h/map.h" 292618Swnj #include "../h/vm.h" 301899Swnj #include "../h/dk.h" 312618Swnj #include "../h/cmap.h" 323709Sroot #include "../h/dkbad.h" 337731Sroot #include "../h/uio.h" 341899Swnj 35*8478Sroot #include "../vax/cpu.h" 36*8478Sroot #include "../vaxuba/ubareg.h" 37*8478Sroot #include "../vaxuba/ubavar.h" 38*8478Sroot #include "../vaxuba/rkreg.h" 391899Swnj 402618Swnj struct rk_softc { 412618Swnj int sc_softas; 422618Swnj int sc_ndrive; 432618Swnj int sc_wticks; 442618Swnj int sc_recal; 452648Swnj } rk_softc[NHK]; 461899Swnj 472618Swnj /* THIS SHOULD BE READ OFF THE PACK, PER DRIVE */ 482787Swnj struct size { 492618Swnj daddr_t nblocks; 502618Swnj int cyloff; 513709Sroot } rk7_sizes[8] ={ 522618Swnj 15884, 0, /* A=cyl 0 thru 240 */ 532665Swnj 10032, 241, /* B=cyl 241 thru 392 */ 542665Swnj 53790, 0, /* C=cyl 0 thru 814 */ 552618Swnj 0, 0, 562618Swnj 0, 0, 572618Swnj 0, 0, 582618Swnj 27786, 393, /* G=cyl 393 thru 813 */ 592618Swnj 0, 0, 603709Sroot }, rk6_sizes[8] ={ 613709Sroot 15884, 0, /* A=cyl 0 thru 240 */ 623709Sroot 11154, 241, /* B=cyl 241 thru 409 */ 633709Sroot 27126, 0, /* C=cyl 0 thru 410 */ 643709Sroot 0, 0, 653709Sroot 0, 0, 663709Sroot 0, 0, 673709Sroot 0, 0, 683709Sroot 0, 0, 692618Swnj }; 702618Swnj /* END OF STUFF WHICH SHOULD BE READ IN PER DISK */ 711899Swnj 723709Sroot short rktypes[] = { RK_CDT, 0 }; 733709Sroot 742618Swnj int rkprobe(), rkslave(), rkattach(), rkdgo(), rkintr(); 752981Swnj struct uba_ctlr *rkminfo[NHK]; 762981Swnj struct uba_device *rkdinfo[NRK]; 772981Swnj struct uba_device *rkip[NHK][4]; 781899Swnj 792618Swnj u_short rkstd[] = { 0777440, 0 }; 802618Swnj struct uba_driver hkdriver = 812622Swnj { rkprobe, rkslave, rkattach, rkdgo, rkstd, "rk", rkdinfo, "hk", rkminfo, 1 }; 822648Swnj struct buf rkutab[NRK]; 832648Swnj short rkcyl[NRK]; 843727Sroot #ifndef NOBADSECT 853709Sroot struct dkbad rkbad[NRK]; 863709Sroot struct buf brkbuf[NRK]; 873709Sroot #endif 881899Swnj 892618Swnj struct rkst { 902618Swnj short nsect; 912618Swnj short ntrak; 922618Swnj short nspc; 932618Swnj short ncyl; 942618Swnj struct size *sizes; 952618Swnj } rkst[] = { 962618Swnj NRKSECT, NRKTRK, NRKSECT*NRKTRK, NRK7CYL, rk7_sizes, 973709Sroot NRKSECT, NRKTRK, NRKSECT*NRKTRK, NRK6CYL, rk6_sizes, 982618Swnj }; 991899Swnj 1002618Swnj u_char rk_offset[16] = 1013293Swnj { RKAS_P400,RKAS_M400,RKAS_P400,RKAS_M400,RKAS_P800,RKAS_M800,RKAS_P800, 1023293Swnj RKAS_M800,RKAS_P1200,RKAS_M1200,RKAS_P1200,RKAS_M1200,0,0,0,0 1033293Swnj }; 1041899Swnj 1052648Swnj struct buf rrkbuf[NRK]; 1062618Swnj 1072618Swnj #define b_cylin b_resid 1082618Swnj 1092618Swnj #ifdef INTRLVE 1102618Swnj daddr_t dkblock(); 1112618Swnj #endif 1122618Swnj 1132618Swnj int rkwstart, rkwatch(); 1142618Swnj 1152618Swnj rkprobe(reg) 1162618Swnj caddr_t reg; 1171899Swnj { 1182618Swnj register int br, cvec; 1191899Swnj 1202618Swnj #ifdef lint 1212618Swnj br = 0; cvec = br; br = cvec; 1224935Swnj rkintr(0); 1232618Swnj #endif 1242618Swnj ((struct rkdevice *)reg)->rkcs1 = RK_CDT|RK_IE|RK_CRDY; 1252618Swnj DELAY(10); 1262618Swnj ((struct rkdevice *)reg)->rkcs1 = RK_CDT; 1277416Skre return (sizeof (struct rkdevice)); 1282618Swnj } 1291899Swnj 1302618Swnj rkslave(ui, reg) 1312981Swnj struct uba_device *ui; 1322618Swnj caddr_t reg; 1332618Swnj { 1342618Swnj register struct rkdevice *rkaddr = (struct rkdevice *)reg; 1351899Swnj 1363709Sroot ui->ui_type = 0; 1373709Sroot rkaddr->rkcs1 = RK_CCLR; 1382618Swnj rkaddr->rkcs2 = ui->ui_slave; 1392957Swnj rkaddr->rkcs1 = RK_CDT|RK_DCLR|RK_GO; 1402622Swnj rkwait(rkaddr); 1412894Swnj DELAY(50); 1423293Swnj if (rkaddr->rkcs2&RKCS2_NED || (rkaddr->rkds&RKDS_SVAL) == 0) { 1433709Sroot rkaddr->rkcs1 = RK_CCLR; 1442618Swnj return (0); 1452618Swnj } 1463709Sroot if (rkaddr->rkcs1&RK_CERR && rkaddr->rker&RKER_DTYE) { 1473709Sroot ui->ui_type = 1; 1483709Sroot rkaddr->rkcs1 = RK_CCLR; 1493709Sroot } 1502618Swnj return (1); 1512618Swnj } 1522618Swnj 1532618Swnj rkattach(ui) 1542981Swnj register struct uba_device *ui; 1552618Swnj { 1562618Swnj 1572618Swnj if (rkwstart == 0) { 1582758Swnj timeout(rkwatch, (caddr_t)0, hz); 1592618Swnj rkwstart++; 1602618Swnj } 1612618Swnj if (ui->ui_dk >= 0) 1622758Swnj dk_mspw[ui->ui_dk] = 1.0 / (60 * NRKSECT * 256); 1632618Swnj rkip[ui->ui_ctlr][ui->ui_slave] = ui; 1642618Swnj rk_softc[ui->ui_ctlr].sc_ndrive++; 1652618Swnj rkcyl[ui->ui_unit] = -1; 1663709Sroot ui->ui_flags = 0; 1672618Swnj } 1682618Swnj 1691899Swnj rkstrategy(bp) 1702618Swnj register struct buf *bp; 1711899Swnj { 1722981Swnj register struct uba_device *ui; 1732618Swnj register struct rkst *st; 1742618Swnj register int unit; 1752618Swnj register struct buf *dp; 1762618Swnj int xunit = minor(bp->b_dev) & 07; 1772618Swnj long bn, sz; 1785433Sroot int s; 1791899Swnj 1802618Swnj sz = (bp->b_bcount+511) >> 9; 1812618Swnj unit = dkunit(bp); 1822648Swnj if (unit >= NRK) 1832618Swnj goto bad; 1842618Swnj ui = rkdinfo[unit]; 1852618Swnj if (ui == 0 || ui->ui_alive == 0) 1862618Swnj goto bad; 1872618Swnj st = &rkst[ui->ui_type]; 1882618Swnj if (bp->b_blkno < 0 || 1892618Swnj (bn = dkblock(bp))+sz > st->sizes[xunit].nblocks) 1902618Swnj goto bad; 1912618Swnj bp->b_cylin = bn/st->nspc + st->sizes[xunit].cyloff; 1925433Sroot s = spl5(); 1932618Swnj dp = &rkutab[ui->ui_unit]; 1942618Swnj disksort(dp, bp); 1952618Swnj if (dp->b_active == 0) { 1962618Swnj (void) rkustart(ui); 1972618Swnj bp = &ui->ui_mi->um_tab; 1982618Swnj if (bp->b_actf && bp->b_active == 0) 1992618Swnj (void) rkstart(ui->ui_mi); 2001899Swnj } 2015433Sroot splx(s); 2022618Swnj return; 2032618Swnj 2042618Swnj bad: 2052618Swnj bp->b_flags |= B_ERROR; 2062618Swnj iodone(bp); 2072618Swnj return; 2081899Swnj } 2091899Swnj 2102618Swnj rkustart(ui) 2112981Swnj register struct uba_device *ui; 2122618Swnj { 2132618Swnj register struct buf *bp, *dp; 2142981Swnj register struct uba_ctlr *um; 2152618Swnj register struct rkdevice *rkaddr; 2161899Swnj 2172618Swnj if (ui == 0) 2186347Swnj return; 2192618Swnj dk_busy &= ~(1<<ui->ui_dk); 2202618Swnj dp = &rkutab[ui->ui_unit]; 2212618Swnj um = ui->ui_mi; 2222894Swnj rkaddr = (struct rkdevice *)um->um_addr; 2232618Swnj if (um->um_tab.b_active) { 2242618Swnj rk_softc[um->um_ctlr].sc_softas |= 1<<ui->ui_slave; 2256347Swnj return; 2262618Swnj } 2276347Swnj if ((bp = dp->b_actf) == NULL) 2286347Swnj return; 2293709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_CERR; 2302618Swnj rkaddr->rkcs2 = ui->ui_slave; 2313709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO; 2322618Swnj rkwait(rkaddr); 2333709Sroot if ((rkaddr->rkds & RKDS_VV) == 0 || ui->ui_flags == 0) { 2342618Swnj /* SHOULD WARN SYSTEM THAT THIS HAPPENED */ 2353727Sroot #ifndef NOBADSECT 2363709Sroot struct rkst *st = &rkst[ui->ui_type]; 2373709Sroot struct buf *bbp = &brkbuf[ui->ui_unit]; 2383709Sroot #endif 2393709Sroot 2403709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_PACK|RK_GO; 2413709Sroot ui->ui_flags = 1; 2423727Sroot #ifndef NOBADSECT 2433709Sroot bbp->b_flags = B_READ|B_BUSY; 2443709Sroot bbp->b_dev = bp->b_dev; 2453709Sroot bbp->b_bcount = 512; 2463709Sroot bbp->b_un.b_addr = (caddr_t)&rkbad[ui->ui_unit]; 2473709Sroot bbp->b_blkno = st->ncyl*st->nspc - st->nsect; 2483709Sroot bbp->b_cylin = st->ncyl - 1; 2493709Sroot dp->b_actf = bbp; 2503709Sroot bbp->av_forw = bp; 2513709Sroot bp = bbp; 2523709Sroot #endif 2532618Swnj rkwait(rkaddr); 2542618Swnj } 2552903Swnj if (dp->b_active) 2562903Swnj goto done; 2572903Swnj dp->b_active = 1; 2583293Swnj if ((rkaddr->rkds & RKDS_DREADY) != RKDS_DREADY) 2592894Swnj goto done; 2602618Swnj if (rk_softc[um->um_ctlr].sc_ndrive == 1) 2612618Swnj goto done; 2622618Swnj if (bp->b_cylin == rkcyl[ui->ui_unit]) 2632618Swnj goto done; 2642618Swnj rkaddr->rkcyl = bp->b_cylin; 2652618Swnj rkcyl[ui->ui_unit] = bp->b_cylin; 2663709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_IE|RK_SEEK|RK_GO; 2672618Swnj if (ui->ui_dk >= 0) { 2682618Swnj dk_busy |= 1<<ui->ui_dk; 2692618Swnj dk_seek[ui->ui_dk]++; 2702618Swnj } 2712618Swnj goto out; 2722618Swnj done: 2732618Swnj if (dp->b_active != 2) { 2742618Swnj dp->b_forw = NULL; 2752618Swnj if (um->um_tab.b_actf == NULL) 2762618Swnj um->um_tab.b_actf = dp; 2772618Swnj else 2782618Swnj um->um_tab.b_actl->b_forw = dp; 2792618Swnj um->um_tab.b_actl = dp; 2802618Swnj dp->b_active = 2; 2812618Swnj } 2822618Swnj out: 2836347Swnj return; 2842618Swnj } 2852618Swnj 2862618Swnj rkstart(um) 2872981Swnj register struct uba_ctlr *um; 2881899Swnj { 2892618Swnj register struct buf *bp, *dp; 2902981Swnj register struct uba_device *ui; 2912618Swnj register struct rkdevice *rkaddr; 2922618Swnj struct rkst *st; 2931899Swnj daddr_t bn; 2942618Swnj int sn, tn, cmd; 2951899Swnj 2962618Swnj loop: 2972618Swnj if ((dp = um->um_tab.b_actf) == NULL) 2986347Swnj return; 2992618Swnj if ((bp = dp->b_actf) == NULL) { 3002618Swnj um->um_tab.b_actf = dp->b_forw; 3012618Swnj goto loop; 3021899Swnj } 3032618Swnj um->um_tab.b_active++; 3042618Swnj ui = rkdinfo[dkunit(bp)]; 3052618Swnj bn = dkblock(bp); 3062618Swnj st = &rkst[ui->ui_type]; 3072618Swnj sn = bn%st->nspc; 3082618Swnj tn = sn/st->nsect; 3092618Swnj sn %= st->nsect; 3102618Swnj rkaddr = (struct rkdevice *)ui->ui_addr; 3112957Swnj retry: 3123709Sroot rkaddr->rkcs1 = RK_CCLR; 3132618Swnj rkaddr->rkcs2 = ui->ui_slave; 3143709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO; 3152618Swnj rkwait(rkaddr); 3163293Swnj if ((rkaddr->rkds&RKDS_SVAL) == 0) { 3172957Swnj rknosval++; 3182957Swnj goto nosval; 3192894Swnj } 3203293Swnj if (rkaddr->rkds&RKDS_PIP) { 3212957Swnj rkpip++; 3222957Swnj goto retry; 3232957Swnj } 3243293Swnj if ((rkaddr->rkds&RKDS_DREADY) != RKDS_DREADY) { 3252927Swnj printf("rk%d: not ready", dkunit(bp)); 3263293Swnj if ((rkaddr->rkds&RKDS_DREADY) != RKDS_DREADY) { 3272894Swnj printf("\n"); 3283709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO; 3292894Swnj rkwait(rkaddr); 3303709Sroot rkaddr->rkcs1 = RK_CCLR; 3312894Swnj rkwait(rkaddr); 3322894Swnj um->um_tab.b_active = 0; 3332894Swnj um->um_tab.b_errcnt = 0; 3342894Swnj dp->b_actf = bp->av_forw; 3352894Swnj dp->b_active = 0; 3362894Swnj bp->b_flags |= B_ERROR; 3372894Swnj iodone(bp); 3382894Swnj goto loop; 3392894Swnj } 3402894Swnj printf(" (came back!)\n"); 3412894Swnj } 3422957Swnj nosval: 3432618Swnj rkaddr->rkcyl = bp->b_cylin; 3442618Swnj rkcyl[ui->ui_unit] = bp->b_cylin; 3452618Swnj rkaddr->rkda = (tn << 8) + sn; 3462618Swnj rkaddr->rkwc = -bp->b_bcount / sizeof (short); 3472618Swnj if (bp->b_flags & B_READ) 3483709Sroot cmd = rktypes[ui->ui_type]|RK_IE|RK_READ|RK_GO; 3492618Swnj else 3503709Sroot cmd = rktypes[ui->ui_type]|RK_IE|RK_WRITE|RK_GO; 3512618Swnj um->um_cmd = cmd; 3523104Swnj (void) ubago(ui); 3531899Swnj } 3541899Swnj 3552618Swnj rkdgo(um) 3562981Swnj register struct uba_ctlr *um; 3571899Swnj { 3582618Swnj register struct rkdevice *rkaddr = (struct rkdevice *)um->um_addr; 3591899Swnj 3607031Swnj um->um_tab.b_active = 2; /* should now be 2 */ 3612618Swnj rkaddr->rkba = um->um_ubinfo; 3622618Swnj rkaddr->rkcs1 = um->um_cmd|((um->um_ubinfo>>8)&0x300); 3632618Swnj } 3642618Swnj 3652710Swnj rkintr(rk11) 3662618Swnj int rk11; 3672618Swnj { 3682981Swnj register struct uba_ctlr *um = rkminfo[rk11]; 3692981Swnj register struct uba_device *ui; 3702618Swnj register struct rkdevice *rkaddr = (struct rkdevice *)um->um_addr; 3712618Swnj register struct buf *bp, *dp; 3722618Swnj int unit; 3732618Swnj struct rk_softc *sc = &rk_softc[um->um_ctlr]; 3742618Swnj int as = (rkaddr->rkatt >> 8) | sc->sc_softas; 3752618Swnj int needie = 1; 3762618Swnj 3772618Swnj sc->sc_wticks = 0; 3782618Swnj sc->sc_softas = 0; 3796347Swnj if (um->um_tab.b_active == 2 || sc->sc_recal) { 3807031Swnj um->um_tab.b_active = 1; 3812618Swnj dp = um->um_tab.b_actf; 3822618Swnj bp = dp->b_actf; 3832618Swnj ui = rkdinfo[dkunit(bp)]; 3842618Swnj dk_busy &= ~(1 << ui->ui_dk); 3853727Sroot #ifndef NOBADSECT 3863709Sroot if (bp->b_flags&B_BAD) 3873709Sroot if (rkecc(ui, CONT)) 3883709Sroot return; 3893709Sroot #endif 3902618Swnj if (rkaddr->rkcs1 & RK_CERR) { 3912618Swnj int recal; 3922618Swnj u_short ds = rkaddr->rkds; 3932618Swnj u_short cs2 = rkaddr->rkcs2; 3942618Swnj u_short er = rkaddr->rker; 3953709Sroot #ifdef RKDEBUG 3963293Swnj if (rkdebug) { 3973293Swnj printf("cs2=%b ds=%b er=%b\n", 3983293Swnj cs2, RKCS2_BITS, ds, 3993293Swnj RKDS_BITS, er, RKER_BITS); 4003293Swnj } 4013709Sroot #endif 4023293Swnj if (er & RKER_WLE) { 4032927Swnj printf("rk%d: write locked\n", dkunit(bp)); 4042685Swnj bp->b_flags |= B_ERROR; 4052685Swnj } else if (++um->um_tab.b_errcnt > 28 || 4062676Swnj ds&RKDS_HARD || er&RKER_HARD || cs2&RKCS2_HARD) { 4073709Sroot hard: 4082927Swnj harderr(bp, "rk"); 4092927Swnj printf("cs2=%b ds=%b er=%b\n", 4102894Swnj cs2, RKCS2_BITS, ds, 4112676Swnj RKDS_BITS, er, RKER_BITS); 4123145Swnj bp->b_flags |= B_ERROR; 4133145Swnj sc->sc_recal = 0; 4143709Sroot } else if (er & RKER_BSE) { 4153727Sroot #ifndef NOBADSECT 4163709Sroot if (rkecc(ui, BSE)) 4173709Sroot return; 4183709Sroot else 4193709Sroot #endif 4203709Sroot goto hard; 4217182Sroot } else { 4227182Sroot if ((er & (RKER_DCK|RKER_ECH)) == RKER_DCK) { 4237182Sroot if (rkecc(ui, ECC)) 4247182Sroot return; 4257182Sroot } else 4267182Sroot um->um_tab.b_active = 0; 4277182Sroot } 4283293Swnj if (cs2&RKCS2_MDS) { 4293293Swnj rkaddr->rkcs2 = RKCS2_SCLR; 4302618Swnj goto retry; 4311899Swnj } 4322618Swnj recal = 0; 4333293Swnj if (ds&RKDS_DROT || er&(RKER_OPI|RKER_SKI|RKER_UNS) || 4342618Swnj (um->um_tab.b_errcnt&07) == 4) 4352618Swnj recal = 1; 4363709Sroot rkaddr->rkcs1 = RK_CCLR; 4372618Swnj rkaddr->rkcs2 = ui->ui_slave; 4383709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO; 4392618Swnj rkwait(rkaddr); 4402618Swnj if (recal && um->um_tab.b_active == 0) { 4413709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_IE|RK_RECAL|RK_GO; 4422618Swnj rkcyl[ui->ui_unit] = -1; 4432957Swnj sc->sc_recal = 0; 4442957Swnj goto nextrecal; 4452618Swnj } 4461899Swnj } 4472618Swnj retry: 4482957Swnj switch (sc->sc_recal) { 4492957Swnj 4502957Swnj case 1: 4512957Swnj rkaddr->rkcyl = bp->b_cylin; 4522957Swnj rkcyl[ui->ui_unit] = bp->b_cylin; 4533709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_IE|RK_SEEK|RK_GO; 4542957Swnj goto nextrecal; 4552957Swnj case 2: 4562957Swnj if (um->um_tab.b_errcnt < 16 || 4573290Swnj (bp->b_flags&B_READ) == 0) 4583159Swnj goto donerecal; 4592957Swnj rkaddr->rkatt = rk_offset[um->um_tab.b_errcnt & 017]; 4603709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_IE|RK_OFFSET|RK_GO; 4612957Swnj /* fall into ... */ 4622957Swnj nextrecal: 4632957Swnj sc->sc_recal++; 4642957Swnj rkwait(rkaddr); 4652957Swnj um->um_tab.b_active = 1; 4662957Swnj return; 4673159Swnj donerecal: 4682957Swnj case 3: 4692618Swnj sc->sc_recal = 0; 4702618Swnj um->um_tab.b_active = 0; 4712957Swnj break; 4721899Swnj } 4733709Sroot ubadone(um); 4742618Swnj if (um->um_tab.b_active) { 4752618Swnj um->um_tab.b_active = 0; 4762618Swnj um->um_tab.b_errcnt = 0; 4772618Swnj um->um_tab.b_actf = dp->b_forw; 4782618Swnj dp->b_active = 0; 4792618Swnj dp->b_errcnt = 0; 4802618Swnj dp->b_actf = bp->av_forw; 4812618Swnj bp->b_resid = -rkaddr->rkwc * sizeof(short); 4822618Swnj iodone(bp); 4832618Swnj if (dp->b_actf) 4846347Swnj rkustart(ui); 4851899Swnj } 4862618Swnj as &= ~(1<<ui->ui_slave); 4871899Swnj } 4882618Swnj for (unit = 0; as; as >>= 1, unit++) 4892981Swnj if (as & 1) { 4902981Swnj ui = rkip[rk11][unit]; 4912981Swnj if (ui) { 4926347Swnj rkustart(rkip[rk11][unit]); 4932981Swnj } else { 4943709Sroot rkaddr->rkcs1 = RK_CCLR; 4952981Swnj rkaddr->rkcs2 = unit; 4963709Sroot rkaddr->rkcs1 = RK_DCLR|RK_GO; 4972981Swnj rkwait(rkaddr); 4983709Sroot rkaddr->rkcs1 = RK_CCLR; 4992981Swnj } 5002981Swnj } 5012618Swnj if (um->um_tab.b_actf && um->um_tab.b_active == 0) 5026347Swnj rkstart(um); 5036347Swnj if (((needie = rkaddr->rkcs1) & RK_IE) == 0) 5043709Sroot rkaddr->rkcs1 = RK_IE; 5051899Swnj } 5061899Swnj 5072618Swnj rkwait(addr) 5082618Swnj register struct rkdevice *addr; 5092618Swnj { 5101899Swnj 5112618Swnj while ((addr->rkcs1 & RK_CRDY) == 0) 5122618Swnj ; 5132618Swnj } 5142618Swnj 5157731Sroot rkread(dev, uio) 5162618Swnj dev_t dev; 5177731Sroot struct uio *uio; 5181899Swnj { 5192618Swnj register int unit = minor(dev) >> 3; 5202618Swnj 5212648Swnj if (unit >= NRK) 5228162Sroot return (ENXIO); 5238162Sroot return (physio(rkstrategy, &rrkbuf[unit], dev, B_READ, minphys, uio)); 5241899Swnj } 5251899Swnj 5267836Sroot rkwrite(dev, uio) 5272618Swnj dev_t dev; 5287836Sroot struct uio *uio; 5291899Swnj { 5302618Swnj register int unit = minor(dev) >> 3; 5311899Swnj 5322648Swnj if (unit >= NRK) 5332618Swnj u.u_error = ENXIO; 5342618Swnj else 5357836Sroot physio(rkstrategy, &rrkbuf[unit], dev, B_WRITE, minphys, uio); 5361899Swnj } 5371899Swnj 5383709Sroot rkecc(ui, flag) 5392981Swnj register struct uba_device *ui; 5401899Swnj { 5412618Swnj register struct rkdevice *rk = (struct rkdevice *)ui->ui_addr; 5422618Swnj register struct buf *bp = rkutab[ui->ui_unit].b_actf; 5432981Swnj register struct uba_ctlr *um = ui->ui_mi; 5442618Swnj register struct rkst *st; 5452618Swnj struct uba_regs *ubp = ui->ui_hd->uh_uba; 5462618Swnj caddr_t addr; 5473709Sroot int reg, npf, o, cmd, ubaddr; 5482618Swnj int bn, cn, tn, sn; 5491899Swnj 5503727Sroot #ifndef NOBADSECT 5513709Sroot if (flag == CONT) 5523709Sroot npf = bp->b_error; 5533709Sroot else 5543709Sroot #endif 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--; 5753709Sroot printf("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 5993727Sroot #ifndef NOBADSECT 6003709Sroot case BSE: 6013709Sroot #ifdef RKBDEBUG 6023709Sroot if (rkbdebug) 6033709Sroot printf("rkecc, BSE: bn %d cn %d tn %d sn %d\n", bn, cn, tn, sn); 6043709Sroot #endif 6053709Sroot if ((bn = isbad(&rkbad[ui->ui_unit], cn, tn, sn)) < 0) 6063709Sroot return(0); 6073709Sroot bp->b_flags |= B_BAD; 6083709Sroot bp->b_error = npf + 1; 6093709Sroot bn = st->ncyl*st->nspc - st->nsect - 1 - bn; 6103709Sroot cn = bn/st->nspc; 6113709Sroot sn = bn%st->nspc; 6123709Sroot tn = sn/st->nsect; 6133709Sroot sn %= st->nsect; 6143709Sroot #ifdef RKBDEBUG 6153709Sroot if (rkbdebug) 6163709Sroot printf("revector to cn %d tn %d sn %d\n", cn, tn, sn); 6173709Sroot #endif 6183709Sroot rk->rkwc = -(512 / sizeof (short)); 6193709Sroot break; 6203709Sroot 6213709Sroot case CONT: 6223709Sroot #ifdef RKBDEBUG 6233709Sroot if (rkbdebug) 6243709Sroot printf("rkecc, CONT: bn %d cn %d tn %d sn %d\n", bn,cn,tn,sn); 6253709Sroot #endif 6263709Sroot bp->b_flags &= ~B_BAD; 6273709Sroot rk->rkwc = -((bp->b_bcount - (int)ptob(npf)) / sizeof (short)); 6287182Sroot if (rk->rkwc == 0) { 6297182Sroot um->um_tab.b_active = 0; 6307182Sroot return (0); 6317182Sroot } 6323709Sroot break; 6333709Sroot #endif 6343709Sroot } 6353709Sroot rk->rkcs1 = RK_CCLR; 6363709Sroot rk->rkcs2 = ui->ui_slave; 6373709Sroot rk->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO; 6383709Sroot rkwait(rk); 6392618Swnj rk->rkcyl = cn; 6402618Swnj rk->rkda = (tn << 8) | sn; 6413709Sroot ubaddr = (int)ptob(reg) + o; 6422618Swnj rk->rkba = ubaddr; 6433709Sroot cmd = (bp->b_flags&B_READ ? RK_READ : RK_WRITE)|RK_IE|RK_GO; 6443709Sroot cmd |= (ubaddr >> 8) & 0x300; 6453709Sroot cmd |= rktypes[ui->ui_type]; 6462618Swnj rk->rkcs1 = cmd; 6477031Swnj um->um_tab.b_active = 2; /* continuing */ 6483709Sroot um->um_tab.b_errcnt = 0; /* error has been corrected */ 6492618Swnj return (1); 6501899Swnj } 6511899Swnj 6522618Swnj rkreset(uban) 6532927Swnj int uban; 6541899Swnj { 6552981Swnj register struct uba_ctlr *um; 6562981Swnj register struct uba_device *ui; 6572618Swnj register rk11, unit; 6581899Swnj 6592648Swnj for (rk11 = 0; rk11 < NHK; rk11++) { 6602618Swnj if ((um = rkminfo[rk11]) == 0 || um->um_ubanum != uban || 6612618Swnj um->um_alive == 0) 6622618Swnj continue; 6632927Swnj printf(" hk%d", rk11); 6642618Swnj um->um_tab.b_active = 0; 6652618Swnj um->um_tab.b_actf = um->um_tab.b_actl = 0; 6662618Swnj rk_softc[um->um_ctlr].sc_recal = 0; 6676347Swnj rk_softc[um->um_ctlr].sc_wticks = 0; 6682618Swnj if (um->um_ubinfo) { 6692618Swnj printf("<%d>", (um->um_ubinfo>>28)&0xf); 6702618Swnj ubadone(um); 6712618Swnj } 6724039Swnj for (unit = 0; unit < NRK; unit++) { 6732618Swnj if ((ui = rkdinfo[unit]) == 0) 6742618Swnj continue; 6754039Swnj if (ui->ui_alive == 0 || ui->ui_mi != um) 6762618Swnj continue; 6772618Swnj rkutab[unit].b_active = 0; 6782618Swnj (void) rkustart(ui); 6792618Swnj } 6802618Swnj (void) rkstart(um); 6812618Swnj } 6821899Swnj } 6832380Swnj 6842618Swnj rkwatch() 6852380Swnj { 6862981Swnj register struct uba_ctlr *um; 6872618Swnj register rk11, unit; 6882618Swnj register struct rk_softc *sc; 6892380Swnj 6902758Swnj timeout(rkwatch, (caddr_t)0, hz); 6912648Swnj for (rk11 = 0; rk11 < NHK; rk11++) { 6922618Swnj um = rkminfo[rk11]; 6932618Swnj if (um == 0 || um->um_alive == 0) 6942618Swnj continue; 6952618Swnj sc = &rk_softc[rk11]; 6962618Swnj if (um->um_tab.b_active == 0) { 6972648Swnj for (unit = 0; unit < NRK; unit++) 6982622Swnj if (rkutab[unit].b_active && 6992622Swnj rkdinfo[unit]->ui_mi == um) 7002618Swnj goto active; 7012618Swnj sc->sc_wticks = 0; 7022618Swnj continue; 7032618Swnj } 7042618Swnj active: 7052618Swnj sc->sc_wticks++; 7062618Swnj if (sc->sc_wticks >= 20) { 7072618Swnj sc->sc_wticks = 0; 7082927Swnj printf("hk%d: lost interrupt\n", rk11); 7092648Swnj ubareset(um->um_ubanum); 7102618Swnj } 7112618Swnj } 7122380Swnj } 7132618Swnj 7142618Swnj #define DBSIZE 20 7152618Swnj 7162618Swnj rkdump(dev) 7172618Swnj dev_t dev; 7182618Swnj { 7192618Swnj struct rkdevice *rkaddr; 7202618Swnj char *start; 7212618Swnj int num, blk, unit; 7222618Swnj struct size *sizes; 7232618Swnj register struct uba_regs *uba; 7242981Swnj register struct uba_device *ui; 7252618Swnj register short *rp; 7262618Swnj struct rkst *st; 7272618Swnj 7282618Swnj unit = minor(dev) >> 3; 7292885Swnj if (unit >= NRK) 7302885Swnj return (ENXIO); 7312618Swnj #define phys(cast, addr) ((cast)((int)addr & 0x7fffffff)) 7322981Swnj ui = phys(struct uba_device *, rkdinfo[unit]); 7332885Swnj if (ui->ui_alive == 0) 7342885Swnj return (ENXIO); 7352618Swnj uba = phys(struct uba_hd *, ui->ui_hd)->uh_physuba; 7363329Swnj ubainit(uba); 7372618Swnj rkaddr = (struct rkdevice *)ui->ui_physaddr; 7382618Swnj num = maxfree; 7392618Swnj start = 0; 7403709Sroot rkaddr->rkcs1 = RK_CCLR; 7412618Swnj rkaddr->rkcs2 = unit; 7423709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO; 7432618Swnj rkwait(rkaddr); 7443293Swnj if ((rkaddr->rkds & RKDS_VV) == 0) { 7453709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_IE|RK_PACK|RK_GO; 7462618Swnj rkwait(rkaddr); 7472618Swnj } 7482618Swnj st = &rkst[ui->ui_type]; 7492618Swnj sizes = phys(struct size *, st->sizes); 7502885Swnj if (dumplo < 0 || dumplo + num >= sizes[minor(dev)&07].nblocks) 7512885Swnj return (EINVAL); 7522618Swnj while (num > 0) { 7532618Swnj register struct pte *io; 7542618Swnj register int i; 7552618Swnj int cn, sn, tn; 7562618Swnj daddr_t bn; 7572618Swnj 7582618Swnj blk = num > DBSIZE ? DBSIZE : num; 7592618Swnj io = uba->uba_map; 7602618Swnj for (i = 0; i < blk; i++) 7612981Swnj *(int *)io++ = (btop(start)+i) | (1<<21) | UBAMR_MRV; 7622618Swnj *(int *)io = 0; 7632618Swnj bn = dumplo + btop(start); 7642618Swnj cn = bn/st->nspc + sizes[minor(dev)&07].cyloff; 7652618Swnj sn = bn%st->nspc; 7662618Swnj tn = sn/st->nsect; 7672618Swnj sn = sn%st->nsect; 7682618Swnj rkaddr->rkcyl = cn; 7692618Swnj rp = (short *) &rkaddr->rkda; 7702618Swnj *rp = (tn << 8) + sn; 7712618Swnj *--rp = 0; 7722618Swnj *--rp = -blk*NBPG / sizeof (short); 7733709Sroot *--rp = rktypes[ui->ui_type]|RK_GO|RK_WRITE; 7742618Swnj rkwait(rkaddr); 7752885Swnj if (rkaddr->rkcs1 & RK_CERR) 7762885Swnj return (EIO); 7772618Swnj start += blk*NBPG; 7782618Swnj num -= blk; 7792618Swnj } 7802618Swnj return (0); 7812618Swnj } 7822618Swnj #endif 783