17031Swnj #define RKDEBUG 2*7182Sroot #define RKBDEBUG 3*7182Sroot /* rk.c 4.41 82/06/14 */ 41899Swnj 51942Swnj #include "rk.h" 62648Swnj #if NHK > 0 73104Swnj int rkpip; /* DEBUG */ 83104Swnj int rknosval; /* DEBUG */ 93709Sroot #ifdef RKDEBUG 103293Swnj int rkdebug; 113709Sroot #endif 123709Sroot #ifdef RKBDEBUG 133709Sroot int rkbdebug; 143709Sroot #endif 151899Swnj /* 163293Swnj * RK611/RK0[67] disk driver 172622Swnj * 182622Swnj * This driver mimics up.c; see it for an explanation of common code. 192685Swnj * 202885Swnj * TODO: 213208Swnj * Learn why we lose an interrupt sometime when spinning drives down 221899Swnj */ 231899Swnj #include "../h/param.h" 241899Swnj #include "../h/systm.h" 251899Swnj #include "../h/buf.h" 261899Swnj #include "../h/conf.h" 271899Swnj #include "../h/dir.h" 281899Swnj #include "../h/user.h" 291899Swnj #include "../h/pte.h" 301899Swnj #include "../h/map.h" 312618Swnj #include "../h/vm.h" 322981Swnj #include "../h/ubareg.h" 332981Swnj #include "../h/ubavar.h" 341899Swnj #include "../h/dk.h" 352618Swnj #include "../h/cpu.h" 362618Swnj #include "../h/cmap.h" 373709Sroot #include "../h/dkbad.h" 381899Swnj 392618Swnj #include "../h/rkreg.h" 401899Swnj 412618Swnj struct rk_softc { 422618Swnj int sc_softas; 432618Swnj int sc_ndrive; 442618Swnj int sc_wticks; 452618Swnj int sc_recal; 462648Swnj } rk_softc[NHK]; 471899Swnj 482618Swnj /* THIS SHOULD BE READ OFF THE PACK, PER DRIVE */ 492787Swnj struct size { 502618Swnj daddr_t nblocks; 512618Swnj int cyloff; 523709Sroot } rk7_sizes[8] ={ 532618Swnj 15884, 0, /* A=cyl 0 thru 240 */ 542665Swnj 10032, 241, /* B=cyl 241 thru 392 */ 552665Swnj 53790, 0, /* C=cyl 0 thru 814 */ 562618Swnj 0, 0, 572618Swnj 0, 0, 582618Swnj 0, 0, 592618Swnj 27786, 393, /* G=cyl 393 thru 813 */ 602618Swnj 0, 0, 613709Sroot }, rk6_sizes[8] ={ 623709Sroot 15884, 0, /* A=cyl 0 thru 240 */ 633709Sroot 11154, 241, /* B=cyl 241 thru 409 */ 643709Sroot 27126, 0, /* C=cyl 0 thru 410 */ 653709Sroot 0, 0, 663709Sroot 0, 0, 673709Sroot 0, 0, 683709Sroot 0, 0, 693709Sroot 0, 0, 702618Swnj }; 712618Swnj /* END OF STUFF WHICH SHOULD BE READ IN PER DISK */ 721899Swnj 733709Sroot short rktypes[] = { RK_CDT, 0 }; 743709Sroot 752618Swnj int rkprobe(), rkslave(), rkattach(), rkdgo(), rkintr(); 762981Swnj struct uba_ctlr *rkminfo[NHK]; 772981Swnj struct uba_device *rkdinfo[NRK]; 782981Swnj struct uba_device *rkip[NHK][4]; 791899Swnj 802618Swnj u_short rkstd[] = { 0777440, 0 }; 812618Swnj struct uba_driver hkdriver = 822622Swnj { rkprobe, rkslave, rkattach, rkdgo, rkstd, "rk", rkdinfo, "hk", rkminfo, 1 }; 832648Swnj struct buf rkutab[NRK]; 842648Swnj short rkcyl[NRK]; 853727Sroot #ifndef NOBADSECT 863709Sroot struct dkbad rkbad[NRK]; 873709Sroot struct buf brkbuf[NRK]; 883709Sroot #endif 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; 1282618Swnj return (1); 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 1701899Swnj rkstrategy(bp) 1712618Swnj register struct buf *bp; 1721899Swnj { 1732981Swnj register struct uba_device *ui; 1742618Swnj register struct rkst *st; 1752618Swnj register int unit; 1762618Swnj register struct buf *dp; 1772618Swnj int xunit = minor(bp->b_dev) & 07; 1782618Swnj long bn, sz; 1795433Sroot int s; 1801899Swnj 1812618Swnj sz = (bp->b_bcount+511) >> 9; 1822618Swnj unit = dkunit(bp); 1832648Swnj if (unit >= NRK) 1842618Swnj goto bad; 1852618Swnj ui = rkdinfo[unit]; 1862618Swnj if (ui == 0 || ui->ui_alive == 0) 1872618Swnj goto bad; 1882618Swnj st = &rkst[ui->ui_type]; 1892618Swnj if (bp->b_blkno < 0 || 1902618Swnj (bn = dkblock(bp))+sz > st->sizes[xunit].nblocks) 1912618Swnj goto bad; 1922618Swnj bp->b_cylin = bn/st->nspc + st->sizes[xunit].cyloff; 1935433Sroot s = spl5(); 1942618Swnj dp = &rkutab[ui->ui_unit]; 1952618Swnj disksort(dp, bp); 1962618Swnj if (dp->b_active == 0) { 1972618Swnj (void) rkustart(ui); 1982618Swnj bp = &ui->ui_mi->um_tab; 1992618Swnj if (bp->b_actf && bp->b_active == 0) 2002618Swnj (void) rkstart(ui->ui_mi); 2011899Swnj } 2025433Sroot splx(s); 2032618Swnj return; 2042618Swnj 2052618Swnj bad: 2062618Swnj bp->b_flags |= B_ERROR; 2072618Swnj iodone(bp); 2082618Swnj return; 2091899Swnj } 2101899Swnj 2112618Swnj rkustart(ui) 2122981Swnj register struct uba_device *ui; 2132618Swnj { 2142618Swnj register struct buf *bp, *dp; 2152981Swnj register struct uba_ctlr *um; 2162618Swnj register struct rkdevice *rkaddr; 2171899Swnj 2182618Swnj if (ui == 0) 2196347Swnj return; 2202618Swnj dk_busy &= ~(1<<ui->ui_dk); 2212618Swnj dp = &rkutab[ui->ui_unit]; 2222618Swnj um = ui->ui_mi; 2232894Swnj rkaddr = (struct rkdevice *)um->um_addr; 2242618Swnj if (um->um_tab.b_active) { 2252618Swnj rk_softc[um->um_ctlr].sc_softas |= 1<<ui->ui_slave; 2266347Swnj return; 2272618Swnj } 2286347Swnj if ((bp = dp->b_actf) == NULL) 2296347Swnj return; 2303709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_CERR; 2312618Swnj rkaddr->rkcs2 = ui->ui_slave; 2323709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO; 2332618Swnj rkwait(rkaddr); 2343709Sroot if ((rkaddr->rkds & RKDS_VV) == 0 || ui->ui_flags == 0) { 2352618Swnj /* SHOULD WARN SYSTEM THAT THIS HAPPENED */ 2363727Sroot #ifndef NOBADSECT 2373709Sroot struct rkst *st = &rkst[ui->ui_type]; 2383709Sroot struct buf *bbp = &brkbuf[ui->ui_unit]; 2393709Sroot #endif 2403709Sroot 2413709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_PACK|RK_GO; 2423709Sroot ui->ui_flags = 1; 2433727Sroot #ifndef NOBADSECT 2443709Sroot bbp->b_flags = B_READ|B_BUSY; 2453709Sroot bbp->b_dev = bp->b_dev; 2463709Sroot bbp->b_bcount = 512; 2473709Sroot bbp->b_un.b_addr = (caddr_t)&rkbad[ui->ui_unit]; 2483709Sroot bbp->b_blkno = st->ncyl*st->nspc - st->nsect; 2493709Sroot bbp->b_cylin = st->ncyl - 1; 2503709Sroot dp->b_actf = bbp; 2513709Sroot bbp->av_forw = bp; 2523709Sroot bp = bbp; 2533709Sroot #endif 2542618Swnj rkwait(rkaddr); 2552618Swnj } 2562903Swnj if (dp->b_active) 2572903Swnj goto done; 2582903Swnj dp->b_active = 1; 2593293Swnj if ((rkaddr->rkds & RKDS_DREADY) != RKDS_DREADY) 2602894Swnj goto done; 2612618Swnj if (rk_softc[um->um_ctlr].sc_ndrive == 1) 2622618Swnj goto done; 2632618Swnj if (bp->b_cylin == rkcyl[ui->ui_unit]) 2642618Swnj goto done; 2652618Swnj rkaddr->rkcyl = bp->b_cylin; 2662618Swnj rkcyl[ui->ui_unit] = bp->b_cylin; 2673709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_IE|RK_SEEK|RK_GO; 2682618Swnj if (ui->ui_dk >= 0) { 2692618Swnj dk_busy |= 1<<ui->ui_dk; 2702618Swnj dk_seek[ui->ui_dk]++; 2712618Swnj } 2722618Swnj goto out; 2732618Swnj done: 2742618Swnj if (dp->b_active != 2) { 2752618Swnj dp->b_forw = NULL; 2762618Swnj if (um->um_tab.b_actf == NULL) 2772618Swnj um->um_tab.b_actf = dp; 2782618Swnj else 2792618Swnj um->um_tab.b_actl->b_forw = dp; 2802618Swnj um->um_tab.b_actl = dp; 2812618Swnj dp->b_active = 2; 2822618Swnj } 2832618Swnj out: 2846347Swnj return; 2852618Swnj } 2862618Swnj 2872618Swnj rkstart(um) 2882981Swnj register struct uba_ctlr *um; 2891899Swnj { 2902618Swnj register struct buf *bp, *dp; 2912981Swnj register struct uba_device *ui; 2922618Swnj register struct rkdevice *rkaddr; 2932618Swnj struct rkst *st; 2941899Swnj daddr_t bn; 2952618Swnj int sn, tn, cmd; 2961899Swnj 2972618Swnj loop: 2982618Swnj if ((dp = um->um_tab.b_actf) == NULL) 2996347Swnj return; 3002618Swnj if ((bp = dp->b_actf) == NULL) { 3012618Swnj um->um_tab.b_actf = dp->b_forw; 3022618Swnj goto loop; 3031899Swnj } 3042618Swnj um->um_tab.b_active++; 3052618Swnj ui = rkdinfo[dkunit(bp)]; 3062618Swnj bn = dkblock(bp); 3072618Swnj st = &rkst[ui->ui_type]; 3082618Swnj sn = bn%st->nspc; 3092618Swnj tn = sn/st->nsect; 3102618Swnj sn %= st->nsect; 3112618Swnj rkaddr = (struct rkdevice *)ui->ui_addr; 3122957Swnj retry: 3133709Sroot rkaddr->rkcs1 = RK_CCLR; 3142618Swnj rkaddr->rkcs2 = ui->ui_slave; 3153709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO; 3162618Swnj rkwait(rkaddr); 3173293Swnj if ((rkaddr->rkds&RKDS_SVAL) == 0) { 3182957Swnj rknosval++; 3192957Swnj goto nosval; 3202894Swnj } 3213293Swnj if (rkaddr->rkds&RKDS_PIP) { 3222957Swnj rkpip++; 3232957Swnj goto retry; 3242957Swnj } 3253293Swnj if ((rkaddr->rkds&RKDS_DREADY) != RKDS_DREADY) { 3262927Swnj printf("rk%d: not ready", dkunit(bp)); 3273293Swnj if ((rkaddr->rkds&RKDS_DREADY) != RKDS_DREADY) { 3282894Swnj printf("\n"); 3293709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO; 3302894Swnj rkwait(rkaddr); 3313709Sroot rkaddr->rkcs1 = RK_CCLR; 3322894Swnj rkwait(rkaddr); 3332894Swnj um->um_tab.b_active = 0; 3342894Swnj um->um_tab.b_errcnt = 0; 3352894Swnj dp->b_actf = bp->av_forw; 3362894Swnj dp->b_active = 0; 3372894Swnj bp->b_flags |= B_ERROR; 3382894Swnj iodone(bp); 3392894Swnj goto loop; 3402894Swnj } 3412894Swnj printf(" (came back!)\n"); 3422894Swnj } 3432957Swnj nosval: 3442618Swnj rkaddr->rkcyl = bp->b_cylin; 3452618Swnj rkcyl[ui->ui_unit] = bp->b_cylin; 3462618Swnj rkaddr->rkda = (tn << 8) + sn; 3472618Swnj rkaddr->rkwc = -bp->b_bcount / sizeof (short); 3482618Swnj if (bp->b_flags & B_READ) 3493709Sroot cmd = rktypes[ui->ui_type]|RK_IE|RK_READ|RK_GO; 3502618Swnj else 3513709Sroot cmd = rktypes[ui->ui_type]|RK_IE|RK_WRITE|RK_GO; 3522618Swnj um->um_cmd = cmd; 3533104Swnj (void) ubago(ui); 3541899Swnj } 3551899Swnj 3562618Swnj rkdgo(um) 3572981Swnj register struct uba_ctlr *um; 3581899Swnj { 3592618Swnj register struct rkdevice *rkaddr = (struct rkdevice *)um->um_addr; 3601899Swnj 3617031Swnj um->um_tab.b_active = 2; /* should now be 2 */ 3622618Swnj rkaddr->rkba = um->um_ubinfo; 3632618Swnj rkaddr->rkcs1 = um->um_cmd|((um->um_ubinfo>>8)&0x300); 3642618Swnj } 3652618Swnj 3662710Swnj rkintr(rk11) 3672618Swnj int rk11; 3682618Swnj { 3692981Swnj register struct uba_ctlr *um = rkminfo[rk11]; 3702981Swnj register struct uba_device *ui; 3712618Swnj register struct rkdevice *rkaddr = (struct rkdevice *)um->um_addr; 3722618Swnj register struct buf *bp, *dp; 3732618Swnj int unit; 3742618Swnj struct rk_softc *sc = &rk_softc[um->um_ctlr]; 3752618Swnj int as = (rkaddr->rkatt >> 8) | sc->sc_softas; 3762618Swnj int needie = 1; 3772618Swnj 3782618Swnj sc->sc_wticks = 0; 3792618Swnj sc->sc_softas = 0; 3806347Swnj if (um->um_tab.b_active == 2 || sc->sc_recal) { 3817031Swnj um->um_tab.b_active = 1; 3822618Swnj dp = um->um_tab.b_actf; 3832618Swnj bp = dp->b_actf; 3842618Swnj ui = rkdinfo[dkunit(bp)]; 3852618Swnj dk_busy &= ~(1 << ui->ui_dk); 3863727Sroot #ifndef NOBADSECT 3873709Sroot if (bp->b_flags&B_BAD) 3883709Sroot if (rkecc(ui, CONT)) 3893709Sroot return; 3903709Sroot #endif 3912618Swnj if (rkaddr->rkcs1 & RK_CERR) { 3922618Swnj int recal; 3932618Swnj u_short ds = rkaddr->rkds; 3942618Swnj u_short cs2 = rkaddr->rkcs2; 3952618Swnj u_short er = rkaddr->rker; 3963709Sroot #ifdef RKDEBUG 3973293Swnj if (rkdebug) { 3983293Swnj printf("cs2=%b ds=%b er=%b\n", 3993293Swnj cs2, RKCS2_BITS, ds, 4003293Swnj RKDS_BITS, er, RKER_BITS); 4013293Swnj } 4023709Sroot #endif 4033293Swnj if (er & RKER_WLE) { 4042927Swnj printf("rk%d: write locked\n", dkunit(bp)); 4052685Swnj bp->b_flags |= B_ERROR; 4062685Swnj } else if (++um->um_tab.b_errcnt > 28 || 4072676Swnj ds&RKDS_HARD || er&RKER_HARD || cs2&RKCS2_HARD) { 4083709Sroot hard: 4092927Swnj harderr(bp, "rk"); 4102927Swnj printf("cs2=%b ds=%b er=%b\n", 4112894Swnj cs2, RKCS2_BITS, ds, 4122676Swnj RKDS_BITS, er, RKER_BITS); 4133145Swnj bp->b_flags |= B_ERROR; 4143145Swnj sc->sc_recal = 0; 4153709Sroot } else if (er & RKER_BSE) { 4163727Sroot #ifndef NOBADSECT 4173709Sroot if (rkecc(ui, BSE)) 4183709Sroot return; 4193709Sroot else 4203709Sroot #endif 4213709Sroot goto hard; 422*7182Sroot } else { 423*7182Sroot if ((er & (RKER_DCK|RKER_ECH)) == RKER_DCK) { 424*7182Sroot if (rkecc(ui, ECC)) 425*7182Sroot return; 426*7182Sroot } else 427*7182Sroot um->um_tab.b_active = 0; 428*7182Sroot } 4293293Swnj if (cs2&RKCS2_MDS) { 4303293Swnj rkaddr->rkcs2 = RKCS2_SCLR; 4312618Swnj goto retry; 4321899Swnj } 4332618Swnj recal = 0; 4343293Swnj if (ds&RKDS_DROT || er&(RKER_OPI|RKER_SKI|RKER_UNS) || 4352618Swnj (um->um_tab.b_errcnt&07) == 4) 4362618Swnj recal = 1; 4373709Sroot rkaddr->rkcs1 = RK_CCLR; 4382618Swnj rkaddr->rkcs2 = ui->ui_slave; 4393709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO; 4402618Swnj rkwait(rkaddr); 4412618Swnj if (recal && um->um_tab.b_active == 0) { 4423709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_IE|RK_RECAL|RK_GO; 4432618Swnj rkcyl[ui->ui_unit] = -1; 4442957Swnj sc->sc_recal = 0; 4452957Swnj goto nextrecal; 4462618Swnj } 4471899Swnj } 4482618Swnj retry: 4492957Swnj switch (sc->sc_recal) { 4502957Swnj 4512957Swnj case 1: 4522957Swnj rkaddr->rkcyl = bp->b_cylin; 4532957Swnj rkcyl[ui->ui_unit] = bp->b_cylin; 4543709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_IE|RK_SEEK|RK_GO; 4552957Swnj goto nextrecal; 4562957Swnj case 2: 4572957Swnj if (um->um_tab.b_errcnt < 16 || 4583290Swnj (bp->b_flags&B_READ) == 0) 4593159Swnj goto donerecal; 4602957Swnj rkaddr->rkatt = rk_offset[um->um_tab.b_errcnt & 017]; 4613709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_IE|RK_OFFSET|RK_GO; 4622957Swnj /* fall into ... */ 4632957Swnj nextrecal: 4642957Swnj sc->sc_recal++; 4652957Swnj rkwait(rkaddr); 4662957Swnj um->um_tab.b_active = 1; 4672957Swnj return; 4683159Swnj donerecal: 4692957Swnj case 3: 4702618Swnj sc->sc_recal = 0; 4712618Swnj um->um_tab.b_active = 0; 4722957Swnj break; 4731899Swnj } 4743709Sroot ubadone(um); 4752618Swnj if (um->um_tab.b_active) { 4762618Swnj um->um_tab.b_active = 0; 4772618Swnj um->um_tab.b_errcnt = 0; 4782618Swnj um->um_tab.b_actf = dp->b_forw; 4792618Swnj dp->b_active = 0; 4802618Swnj dp->b_errcnt = 0; 4812618Swnj dp->b_actf = bp->av_forw; 4822618Swnj bp->b_resid = -rkaddr->rkwc * sizeof(short); 4832618Swnj iodone(bp); 4842618Swnj if (dp->b_actf) 4856347Swnj rkustart(ui); 4861899Swnj } 4872618Swnj as &= ~(1<<ui->ui_slave); 4881899Swnj } 4892618Swnj for (unit = 0; as; as >>= 1, unit++) 4902981Swnj if (as & 1) { 4912981Swnj ui = rkip[rk11][unit]; 4922981Swnj if (ui) { 4936347Swnj rkustart(rkip[rk11][unit]); 4942981Swnj } else { 4953709Sroot rkaddr->rkcs1 = RK_CCLR; 4962981Swnj rkaddr->rkcs2 = unit; 4973709Sroot rkaddr->rkcs1 = RK_DCLR|RK_GO; 4982981Swnj rkwait(rkaddr); 4993709Sroot rkaddr->rkcs1 = RK_CCLR; 5002981Swnj } 5012981Swnj } 5022618Swnj if (um->um_tab.b_actf && um->um_tab.b_active == 0) 5036347Swnj rkstart(um); 5046347Swnj if (((needie = rkaddr->rkcs1) & RK_IE) == 0) 5053709Sroot rkaddr->rkcs1 = RK_IE; 5061899Swnj } 5071899Swnj 5082618Swnj rkwait(addr) 5092618Swnj register struct rkdevice *addr; 5102618Swnj { 5111899Swnj 5122618Swnj while ((addr->rkcs1 & RK_CRDY) == 0) 5132618Swnj ; 5142618Swnj } 5152618Swnj 5162618Swnj rkread(dev) 5172618Swnj dev_t dev; 5181899Swnj { 5192618Swnj register int unit = minor(dev) >> 3; 5202618Swnj 5212648Swnj if (unit >= NRK) 5222618Swnj u.u_error = ENXIO; 5232618Swnj else 5242618Swnj physio(rkstrategy, &rrkbuf[unit], dev, B_READ, minphys); 5251899Swnj } 5261899Swnj 5272618Swnj rkwrite(dev) 5282618Swnj dev_t dev; 5291899Swnj { 5302618Swnj register int unit = minor(dev) >> 3; 5311899Swnj 5322648Swnj if (unit >= NRK) 5332618Swnj u.u_error = ENXIO; 5342618Swnj else 5352618Swnj physio(rkstrategy, &rrkbuf[unit], dev, B_WRITE, minphys); 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 } 590*7182Sroot if (rk->rkwc == 0) { 591*7182Sroot um->um_tab.b_active = 0; 5923709Sroot return (0); 593*7182Sroot } 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)); 628*7182Sroot if (rk->rkwc == 0) { 629*7182Sroot um->um_tab.b_active = 0; 630*7182Sroot return (0); 631*7182Sroot } 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