1*8573Sroot /* rk.c 4.48 82/10/17 */ 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 358478Sroot #include "../vax/cpu.h" 368478Sroot #include "../vaxuba/ubareg.h" 378478Sroot #include "../vaxuba/ubavar.h" 388478Sroot #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 169*8573Sroot rkopen(dev) 170*8573Sroot dev_t dev; 171*8573Sroot { 172*8573Sroot register int unit = minor(dev) >> 3; 173*8573Sroot register struct uba_device *ui; 174*8573Sroot 175*8573Sroot if (unit >= NRK || (ui = rkdinfo[unit]) == 0 || ui->ui_alive == 0) 176*8573Sroot return (ENXIO); 177*8573Sroot return (0); 178*8573Sroot } 179*8573Sroot 1801899Swnj rkstrategy(bp) 1812618Swnj register struct buf *bp; 1821899Swnj { 1832981Swnj register struct uba_device *ui; 1842618Swnj register struct rkst *st; 1852618Swnj register int unit; 1862618Swnj register struct buf *dp; 1872618Swnj int xunit = minor(bp->b_dev) & 07; 1882618Swnj long bn, sz; 1895433Sroot int s; 1901899Swnj 1912618Swnj sz = (bp->b_bcount+511) >> 9; 1922618Swnj unit = dkunit(bp); 1932648Swnj if (unit >= NRK) 1942618Swnj goto bad; 1952618Swnj ui = rkdinfo[unit]; 1962618Swnj if (ui == 0 || ui->ui_alive == 0) 1972618Swnj goto bad; 1982618Swnj st = &rkst[ui->ui_type]; 1992618Swnj if (bp->b_blkno < 0 || 2002618Swnj (bn = dkblock(bp))+sz > st->sizes[xunit].nblocks) 2012618Swnj goto bad; 2022618Swnj bp->b_cylin = bn/st->nspc + st->sizes[xunit].cyloff; 2035433Sroot s = spl5(); 2042618Swnj dp = &rkutab[ui->ui_unit]; 2052618Swnj disksort(dp, bp); 2062618Swnj if (dp->b_active == 0) { 2072618Swnj (void) rkustart(ui); 2082618Swnj bp = &ui->ui_mi->um_tab; 2092618Swnj if (bp->b_actf && bp->b_active == 0) 2102618Swnj (void) rkstart(ui->ui_mi); 2111899Swnj } 2125433Sroot splx(s); 2132618Swnj return; 2142618Swnj 2152618Swnj bad: 2162618Swnj bp->b_flags |= B_ERROR; 2172618Swnj iodone(bp); 2182618Swnj return; 2191899Swnj } 2201899Swnj 2212618Swnj rkustart(ui) 2222981Swnj register struct uba_device *ui; 2232618Swnj { 2242618Swnj register struct buf *bp, *dp; 2252981Swnj register struct uba_ctlr *um; 2262618Swnj register struct rkdevice *rkaddr; 2271899Swnj 2282618Swnj if (ui == 0) 2296347Swnj return; 2302618Swnj dk_busy &= ~(1<<ui->ui_dk); 2312618Swnj dp = &rkutab[ui->ui_unit]; 2322618Swnj um = ui->ui_mi; 2332894Swnj rkaddr = (struct rkdevice *)um->um_addr; 2342618Swnj if (um->um_tab.b_active) { 2352618Swnj rk_softc[um->um_ctlr].sc_softas |= 1<<ui->ui_slave; 2366347Swnj return; 2372618Swnj } 2386347Swnj if ((bp = dp->b_actf) == NULL) 2396347Swnj return; 2403709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_CERR; 2412618Swnj rkaddr->rkcs2 = ui->ui_slave; 2423709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO; 2432618Swnj rkwait(rkaddr); 2443709Sroot if ((rkaddr->rkds & RKDS_VV) == 0 || ui->ui_flags == 0) { 2452618Swnj /* SHOULD WARN SYSTEM THAT THIS HAPPENED */ 2463727Sroot #ifndef NOBADSECT 2473709Sroot struct rkst *st = &rkst[ui->ui_type]; 2483709Sroot struct buf *bbp = &brkbuf[ui->ui_unit]; 2493709Sroot #endif 2503709Sroot 2513709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_PACK|RK_GO; 2523709Sroot ui->ui_flags = 1; 2533727Sroot #ifndef NOBADSECT 2543709Sroot bbp->b_flags = B_READ|B_BUSY; 2553709Sroot bbp->b_dev = bp->b_dev; 2563709Sroot bbp->b_bcount = 512; 2573709Sroot bbp->b_un.b_addr = (caddr_t)&rkbad[ui->ui_unit]; 2583709Sroot bbp->b_blkno = st->ncyl*st->nspc - st->nsect; 2593709Sroot bbp->b_cylin = st->ncyl - 1; 2603709Sroot dp->b_actf = bbp; 2613709Sroot bbp->av_forw = bp; 2623709Sroot bp = bbp; 2633709Sroot #endif 2642618Swnj rkwait(rkaddr); 2652618Swnj } 2662903Swnj if (dp->b_active) 2672903Swnj goto done; 2682903Swnj dp->b_active = 1; 2693293Swnj if ((rkaddr->rkds & RKDS_DREADY) != RKDS_DREADY) 2702894Swnj goto done; 2712618Swnj if (rk_softc[um->um_ctlr].sc_ndrive == 1) 2722618Swnj goto done; 2732618Swnj if (bp->b_cylin == rkcyl[ui->ui_unit]) 2742618Swnj goto done; 2752618Swnj rkaddr->rkcyl = bp->b_cylin; 2762618Swnj rkcyl[ui->ui_unit] = bp->b_cylin; 2773709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_IE|RK_SEEK|RK_GO; 2782618Swnj if (ui->ui_dk >= 0) { 2792618Swnj dk_busy |= 1<<ui->ui_dk; 2802618Swnj dk_seek[ui->ui_dk]++; 2812618Swnj } 2822618Swnj goto out; 2832618Swnj done: 2842618Swnj if (dp->b_active != 2) { 2852618Swnj dp->b_forw = NULL; 2862618Swnj if (um->um_tab.b_actf == NULL) 2872618Swnj um->um_tab.b_actf = dp; 2882618Swnj else 2892618Swnj um->um_tab.b_actl->b_forw = dp; 2902618Swnj um->um_tab.b_actl = dp; 2912618Swnj dp->b_active = 2; 2922618Swnj } 2932618Swnj out: 2946347Swnj return; 2952618Swnj } 2962618Swnj 2972618Swnj rkstart(um) 2982981Swnj register struct uba_ctlr *um; 2991899Swnj { 3002618Swnj register struct buf *bp, *dp; 3012981Swnj register struct uba_device *ui; 3022618Swnj register struct rkdevice *rkaddr; 3032618Swnj struct rkst *st; 3041899Swnj daddr_t bn; 3052618Swnj int sn, tn, cmd; 3061899Swnj 3072618Swnj loop: 3082618Swnj if ((dp = um->um_tab.b_actf) == NULL) 3096347Swnj return; 3102618Swnj if ((bp = dp->b_actf) == NULL) { 3112618Swnj um->um_tab.b_actf = dp->b_forw; 3122618Swnj goto loop; 3131899Swnj } 3142618Swnj um->um_tab.b_active++; 3152618Swnj ui = rkdinfo[dkunit(bp)]; 3162618Swnj bn = dkblock(bp); 3172618Swnj st = &rkst[ui->ui_type]; 3182618Swnj sn = bn%st->nspc; 3192618Swnj tn = sn/st->nsect; 3202618Swnj sn %= st->nsect; 3212618Swnj rkaddr = (struct rkdevice *)ui->ui_addr; 3222957Swnj retry: 3233709Sroot rkaddr->rkcs1 = RK_CCLR; 3242618Swnj rkaddr->rkcs2 = ui->ui_slave; 3253709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO; 3262618Swnj rkwait(rkaddr); 3273293Swnj if ((rkaddr->rkds&RKDS_SVAL) == 0) { 3282957Swnj rknosval++; 3292957Swnj goto nosval; 3302894Swnj } 3313293Swnj if (rkaddr->rkds&RKDS_PIP) { 3322957Swnj rkpip++; 3332957Swnj goto retry; 3342957Swnj } 3353293Swnj if ((rkaddr->rkds&RKDS_DREADY) != RKDS_DREADY) { 3362927Swnj printf("rk%d: not ready", dkunit(bp)); 3373293Swnj if ((rkaddr->rkds&RKDS_DREADY) != RKDS_DREADY) { 3382894Swnj printf("\n"); 3393709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO; 3402894Swnj rkwait(rkaddr); 3413709Sroot rkaddr->rkcs1 = RK_CCLR; 3422894Swnj rkwait(rkaddr); 3432894Swnj um->um_tab.b_active = 0; 3442894Swnj um->um_tab.b_errcnt = 0; 3452894Swnj dp->b_actf = bp->av_forw; 3462894Swnj dp->b_active = 0; 3472894Swnj bp->b_flags |= B_ERROR; 3482894Swnj iodone(bp); 3492894Swnj goto loop; 3502894Swnj } 3512894Swnj printf(" (came back!)\n"); 3522894Swnj } 3532957Swnj nosval: 3542618Swnj rkaddr->rkcyl = bp->b_cylin; 3552618Swnj rkcyl[ui->ui_unit] = bp->b_cylin; 3562618Swnj rkaddr->rkda = (tn << 8) + sn; 3572618Swnj rkaddr->rkwc = -bp->b_bcount / sizeof (short); 3582618Swnj if (bp->b_flags & B_READ) 3593709Sroot cmd = rktypes[ui->ui_type]|RK_IE|RK_READ|RK_GO; 3602618Swnj else 3613709Sroot cmd = rktypes[ui->ui_type]|RK_IE|RK_WRITE|RK_GO; 3622618Swnj um->um_cmd = cmd; 3633104Swnj (void) ubago(ui); 3641899Swnj } 3651899Swnj 3662618Swnj rkdgo(um) 3672981Swnj register struct uba_ctlr *um; 3681899Swnj { 3692618Swnj register struct rkdevice *rkaddr = (struct rkdevice *)um->um_addr; 3701899Swnj 3717031Swnj um->um_tab.b_active = 2; /* should now be 2 */ 3722618Swnj rkaddr->rkba = um->um_ubinfo; 3732618Swnj rkaddr->rkcs1 = um->um_cmd|((um->um_ubinfo>>8)&0x300); 3742618Swnj } 3752618Swnj 3762710Swnj rkintr(rk11) 3772618Swnj int rk11; 3782618Swnj { 3792981Swnj register struct uba_ctlr *um = rkminfo[rk11]; 3802981Swnj register struct uba_device *ui; 3812618Swnj register struct rkdevice *rkaddr = (struct rkdevice *)um->um_addr; 3822618Swnj register struct buf *bp, *dp; 3832618Swnj int unit; 3842618Swnj struct rk_softc *sc = &rk_softc[um->um_ctlr]; 3852618Swnj int as = (rkaddr->rkatt >> 8) | sc->sc_softas; 3862618Swnj int needie = 1; 3872618Swnj 3882618Swnj sc->sc_wticks = 0; 3892618Swnj sc->sc_softas = 0; 3906347Swnj if (um->um_tab.b_active == 2 || sc->sc_recal) { 3917031Swnj um->um_tab.b_active = 1; 3922618Swnj dp = um->um_tab.b_actf; 3932618Swnj bp = dp->b_actf; 3942618Swnj ui = rkdinfo[dkunit(bp)]; 3952618Swnj dk_busy &= ~(1 << ui->ui_dk); 3963727Sroot #ifndef NOBADSECT 3973709Sroot if (bp->b_flags&B_BAD) 3983709Sroot if (rkecc(ui, CONT)) 3993709Sroot return; 4003709Sroot #endif 4012618Swnj if (rkaddr->rkcs1 & RK_CERR) { 4022618Swnj int recal; 4032618Swnj u_short ds = rkaddr->rkds; 4042618Swnj u_short cs2 = rkaddr->rkcs2; 4052618Swnj u_short er = rkaddr->rker; 4063709Sroot #ifdef RKDEBUG 4073293Swnj if (rkdebug) { 4083293Swnj printf("cs2=%b ds=%b er=%b\n", 4093293Swnj cs2, RKCS2_BITS, ds, 4103293Swnj RKDS_BITS, er, RKER_BITS); 4113293Swnj } 4123709Sroot #endif 4133293Swnj if (er & RKER_WLE) { 4142927Swnj printf("rk%d: write locked\n", dkunit(bp)); 4152685Swnj bp->b_flags |= B_ERROR; 4162685Swnj } else if (++um->um_tab.b_errcnt > 28 || 4172676Swnj ds&RKDS_HARD || er&RKER_HARD || cs2&RKCS2_HARD) { 4183709Sroot hard: 4192927Swnj harderr(bp, "rk"); 4202927Swnj printf("cs2=%b ds=%b er=%b\n", 4212894Swnj cs2, RKCS2_BITS, ds, 4222676Swnj RKDS_BITS, er, RKER_BITS); 4233145Swnj bp->b_flags |= B_ERROR; 4243145Swnj sc->sc_recal = 0; 4253709Sroot } else if (er & RKER_BSE) { 4263727Sroot #ifndef NOBADSECT 4273709Sroot if (rkecc(ui, BSE)) 4283709Sroot return; 4293709Sroot else 4303709Sroot #endif 4313709Sroot goto hard; 4327182Sroot } else { 4337182Sroot if ((er & (RKER_DCK|RKER_ECH)) == RKER_DCK) { 4347182Sroot if (rkecc(ui, ECC)) 4357182Sroot return; 4367182Sroot } else 4377182Sroot um->um_tab.b_active = 0; 4387182Sroot } 4393293Swnj if (cs2&RKCS2_MDS) { 4403293Swnj rkaddr->rkcs2 = RKCS2_SCLR; 4412618Swnj goto retry; 4421899Swnj } 4432618Swnj recal = 0; 4443293Swnj if (ds&RKDS_DROT || er&(RKER_OPI|RKER_SKI|RKER_UNS) || 4452618Swnj (um->um_tab.b_errcnt&07) == 4) 4462618Swnj recal = 1; 4473709Sroot rkaddr->rkcs1 = RK_CCLR; 4482618Swnj rkaddr->rkcs2 = ui->ui_slave; 4493709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO; 4502618Swnj rkwait(rkaddr); 4512618Swnj if (recal && um->um_tab.b_active == 0) { 4523709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_IE|RK_RECAL|RK_GO; 4532618Swnj rkcyl[ui->ui_unit] = -1; 4542957Swnj sc->sc_recal = 0; 4552957Swnj goto nextrecal; 4562618Swnj } 4571899Swnj } 4582618Swnj retry: 4592957Swnj switch (sc->sc_recal) { 4602957Swnj 4612957Swnj case 1: 4622957Swnj rkaddr->rkcyl = bp->b_cylin; 4632957Swnj rkcyl[ui->ui_unit] = bp->b_cylin; 4643709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_IE|RK_SEEK|RK_GO; 4652957Swnj goto nextrecal; 4662957Swnj case 2: 4672957Swnj if (um->um_tab.b_errcnt < 16 || 4683290Swnj (bp->b_flags&B_READ) == 0) 4693159Swnj goto donerecal; 4702957Swnj rkaddr->rkatt = rk_offset[um->um_tab.b_errcnt & 017]; 4713709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_IE|RK_OFFSET|RK_GO; 4722957Swnj /* fall into ... */ 4732957Swnj nextrecal: 4742957Swnj sc->sc_recal++; 4752957Swnj rkwait(rkaddr); 4762957Swnj um->um_tab.b_active = 1; 4772957Swnj return; 4783159Swnj donerecal: 4792957Swnj case 3: 4802618Swnj sc->sc_recal = 0; 4812618Swnj um->um_tab.b_active = 0; 4822957Swnj break; 4831899Swnj } 4843709Sroot ubadone(um); 4852618Swnj if (um->um_tab.b_active) { 4862618Swnj um->um_tab.b_active = 0; 4872618Swnj um->um_tab.b_errcnt = 0; 4882618Swnj um->um_tab.b_actf = dp->b_forw; 4892618Swnj dp->b_active = 0; 4902618Swnj dp->b_errcnt = 0; 4912618Swnj dp->b_actf = bp->av_forw; 4922618Swnj bp->b_resid = -rkaddr->rkwc * sizeof(short); 4932618Swnj iodone(bp); 4942618Swnj if (dp->b_actf) 4956347Swnj rkustart(ui); 4961899Swnj } 4972618Swnj as &= ~(1<<ui->ui_slave); 4981899Swnj } 4992618Swnj for (unit = 0; as; as >>= 1, unit++) 5002981Swnj if (as & 1) { 5012981Swnj ui = rkip[rk11][unit]; 5022981Swnj if (ui) { 5036347Swnj rkustart(rkip[rk11][unit]); 5042981Swnj } else { 5053709Sroot rkaddr->rkcs1 = RK_CCLR; 5062981Swnj rkaddr->rkcs2 = unit; 5073709Sroot rkaddr->rkcs1 = RK_DCLR|RK_GO; 5082981Swnj rkwait(rkaddr); 5093709Sroot rkaddr->rkcs1 = RK_CCLR; 5102981Swnj } 5112981Swnj } 5122618Swnj if (um->um_tab.b_actf && um->um_tab.b_active == 0) 5136347Swnj rkstart(um); 5146347Swnj if (((needie = rkaddr->rkcs1) & RK_IE) == 0) 5153709Sroot rkaddr->rkcs1 = RK_IE; 5161899Swnj } 5171899Swnj 5182618Swnj rkwait(addr) 5192618Swnj register struct rkdevice *addr; 5202618Swnj { 5211899Swnj 5222618Swnj while ((addr->rkcs1 & RK_CRDY) == 0) 5232618Swnj ; 5242618Swnj } 5252618Swnj 5267731Sroot rkread(dev, uio) 5272618Swnj dev_t dev; 5287731Sroot struct uio *uio; 5291899Swnj { 5302618Swnj register int unit = minor(dev) >> 3; 5312618Swnj 5322648Swnj if (unit >= NRK) 5338162Sroot return (ENXIO); 5348162Sroot return (physio(rkstrategy, &rrkbuf[unit], dev, B_READ, minphys, uio)); 5351899Swnj } 5361899Swnj 5377836Sroot rkwrite(dev, uio) 5382618Swnj dev_t dev; 5397836Sroot struct uio *uio; 5401899Swnj { 5412618Swnj register int unit = minor(dev) >> 3; 5421899Swnj 5432648Swnj if (unit >= NRK) 5448493Sroot return (ENXIO); 5458493Sroot return (physio(rkstrategy, &rrkbuf[unit], dev, B_WRITE, minphys, uio)); 5461899Swnj } 5471899Swnj 5483709Sroot rkecc(ui, flag) 5492981Swnj register struct uba_device *ui; 5501899Swnj { 5512618Swnj register struct rkdevice *rk = (struct rkdevice *)ui->ui_addr; 5522618Swnj register struct buf *bp = rkutab[ui->ui_unit].b_actf; 5532981Swnj register struct uba_ctlr *um = ui->ui_mi; 5542618Swnj register struct rkst *st; 5552618Swnj struct uba_regs *ubp = ui->ui_hd->uh_uba; 5562618Swnj caddr_t addr; 5573709Sroot int reg, npf, o, cmd, ubaddr; 5582618Swnj int bn, cn, tn, sn; 5591899Swnj 5603727Sroot #ifndef NOBADSECT 5613709Sroot if (flag == CONT) 5623709Sroot npf = bp->b_error; 5633709Sroot else 5643709Sroot #endif 5653709Sroot npf = btop((rk->rkwc * sizeof(short)) + bp->b_bcount); 5662618Swnj reg = btop(um->um_ubinfo&0x3ffff) + npf; 5672618Swnj o = (int)bp->b_un.b_addr & PGOFSET; 5682618Swnj bn = dkblock(bp); 5692618Swnj st = &rkst[ui->ui_type]; 5702618Swnj cn = bp->b_cylin; 5713709Sroot sn = bn%st->nspc + npf; 5722618Swnj tn = sn/st->nsect; 5732618Swnj sn %= st->nsect; 5742618Swnj cn += tn/st->ntrak; 5752618Swnj tn %= st->ntrak; 5763709Sroot ubapurge(um); 5773709Sroot switch (flag) { 5783709Sroot case ECC: 5793709Sroot { 5803709Sroot register int i; 5813709Sroot int bit, byte, mask; 5823709Sroot 5833709Sroot npf--; 5843709Sroot reg--; 5853709Sroot printf("rk%d%c: soft ecc sn%d\n", dkunit(bp), 5863709Sroot 'a'+(minor(bp->b_dev)&07), bp->b_blkno + npf); 5873709Sroot mask = rk->rkec2; 5883709Sroot i = rk->rkec1 - 1; /* -1 makes 0 origin */ 5893709Sroot bit = i&07; 5903709Sroot i = (i&~07)>>3; 5913709Sroot byte = i + o; 5923709Sroot while (i < 512 && (int)ptob(npf)+i < bp->b_bcount && bit > -11) { 5933709Sroot addr = ptob(ubp->uba_map[reg+btop(byte)].pg_pfnum)+ 5943709Sroot (byte & PGOFSET); 5953709Sroot putmemc(addr, getmemc(addr)^(mask<<bit)); 5963709Sroot byte++; 5973709Sroot i++; 5983709Sroot bit -= 8; 5993709Sroot } 6007182Sroot if (rk->rkwc == 0) { 6017182Sroot um->um_tab.b_active = 0; 6023709Sroot return (0); 6037182Sroot } 6043709Sroot npf++; 6053709Sroot reg++; 6063709Sroot break; 6073709Sroot } 6083709Sroot 6093727Sroot #ifndef NOBADSECT 6103709Sroot case BSE: 6113709Sroot #ifdef RKBDEBUG 6123709Sroot if (rkbdebug) 6133709Sroot printf("rkecc, BSE: bn %d cn %d tn %d sn %d\n", bn, cn, tn, sn); 6143709Sroot #endif 6153709Sroot if ((bn = isbad(&rkbad[ui->ui_unit], cn, tn, sn)) < 0) 6163709Sroot return(0); 6173709Sroot bp->b_flags |= B_BAD; 6183709Sroot bp->b_error = npf + 1; 6193709Sroot bn = st->ncyl*st->nspc - st->nsect - 1 - bn; 6203709Sroot cn = bn/st->nspc; 6213709Sroot sn = bn%st->nspc; 6223709Sroot tn = sn/st->nsect; 6233709Sroot sn %= st->nsect; 6243709Sroot #ifdef RKBDEBUG 6253709Sroot if (rkbdebug) 6263709Sroot printf("revector to cn %d tn %d sn %d\n", cn, tn, sn); 6273709Sroot #endif 6283709Sroot rk->rkwc = -(512 / sizeof (short)); 6293709Sroot break; 6303709Sroot 6313709Sroot case CONT: 6323709Sroot #ifdef RKBDEBUG 6333709Sroot if (rkbdebug) 6343709Sroot printf("rkecc, CONT: bn %d cn %d tn %d sn %d\n", bn,cn,tn,sn); 6353709Sroot #endif 6363709Sroot bp->b_flags &= ~B_BAD; 6373709Sroot rk->rkwc = -((bp->b_bcount - (int)ptob(npf)) / sizeof (short)); 6387182Sroot if (rk->rkwc == 0) { 6397182Sroot um->um_tab.b_active = 0; 6407182Sroot return (0); 6417182Sroot } 6423709Sroot break; 6433709Sroot #endif 6443709Sroot } 6453709Sroot rk->rkcs1 = RK_CCLR; 6463709Sroot rk->rkcs2 = ui->ui_slave; 6473709Sroot rk->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO; 6483709Sroot rkwait(rk); 6492618Swnj rk->rkcyl = cn; 6502618Swnj rk->rkda = (tn << 8) | sn; 6513709Sroot ubaddr = (int)ptob(reg) + o; 6522618Swnj rk->rkba = ubaddr; 6533709Sroot cmd = (bp->b_flags&B_READ ? RK_READ : RK_WRITE)|RK_IE|RK_GO; 6543709Sroot cmd |= (ubaddr >> 8) & 0x300; 6553709Sroot cmd |= rktypes[ui->ui_type]; 6562618Swnj rk->rkcs1 = cmd; 6577031Swnj um->um_tab.b_active = 2; /* continuing */ 6583709Sroot um->um_tab.b_errcnt = 0; /* error has been corrected */ 6592618Swnj return (1); 6601899Swnj } 6611899Swnj 6622618Swnj rkreset(uban) 6632927Swnj int uban; 6641899Swnj { 6652981Swnj register struct uba_ctlr *um; 6662981Swnj register struct uba_device *ui; 6672618Swnj register rk11, unit; 6681899Swnj 6692648Swnj for (rk11 = 0; rk11 < NHK; rk11++) { 6702618Swnj if ((um = rkminfo[rk11]) == 0 || um->um_ubanum != uban || 6712618Swnj um->um_alive == 0) 6722618Swnj continue; 6732927Swnj printf(" hk%d", rk11); 6742618Swnj um->um_tab.b_active = 0; 6752618Swnj um->um_tab.b_actf = um->um_tab.b_actl = 0; 6762618Swnj rk_softc[um->um_ctlr].sc_recal = 0; 6776347Swnj rk_softc[um->um_ctlr].sc_wticks = 0; 6782618Swnj if (um->um_ubinfo) { 6792618Swnj printf("<%d>", (um->um_ubinfo>>28)&0xf); 6802618Swnj ubadone(um); 6812618Swnj } 6824039Swnj for (unit = 0; unit < NRK; unit++) { 6832618Swnj if ((ui = rkdinfo[unit]) == 0) 6842618Swnj continue; 6854039Swnj if (ui->ui_alive == 0 || ui->ui_mi != um) 6862618Swnj continue; 6872618Swnj rkutab[unit].b_active = 0; 6882618Swnj (void) rkustart(ui); 6892618Swnj } 6902618Swnj (void) rkstart(um); 6912618Swnj } 6921899Swnj } 6932380Swnj 6942618Swnj rkwatch() 6952380Swnj { 6962981Swnj register struct uba_ctlr *um; 6972618Swnj register rk11, unit; 6982618Swnj register struct rk_softc *sc; 6992380Swnj 7002758Swnj timeout(rkwatch, (caddr_t)0, hz); 7012648Swnj for (rk11 = 0; rk11 < NHK; rk11++) { 7022618Swnj um = rkminfo[rk11]; 7032618Swnj if (um == 0 || um->um_alive == 0) 7042618Swnj continue; 7052618Swnj sc = &rk_softc[rk11]; 7062618Swnj if (um->um_tab.b_active == 0) { 7072648Swnj for (unit = 0; unit < NRK; unit++) 7082622Swnj if (rkutab[unit].b_active && 7092622Swnj rkdinfo[unit]->ui_mi == um) 7102618Swnj goto active; 7112618Swnj sc->sc_wticks = 0; 7122618Swnj continue; 7132618Swnj } 7142618Swnj active: 7152618Swnj sc->sc_wticks++; 7162618Swnj if (sc->sc_wticks >= 20) { 7172618Swnj sc->sc_wticks = 0; 7182927Swnj printf("hk%d: lost interrupt\n", rk11); 7192648Swnj ubareset(um->um_ubanum); 7202618Swnj } 7212618Swnj } 7222380Swnj } 7232618Swnj 7242618Swnj #define DBSIZE 20 7252618Swnj 7262618Swnj rkdump(dev) 7272618Swnj dev_t dev; 7282618Swnj { 7292618Swnj struct rkdevice *rkaddr; 7302618Swnj char *start; 7312618Swnj int num, blk, unit; 7322618Swnj struct size *sizes; 7332618Swnj register struct uba_regs *uba; 7342981Swnj register struct uba_device *ui; 7352618Swnj register short *rp; 7362618Swnj struct rkst *st; 7372618Swnj 7382618Swnj unit = minor(dev) >> 3; 7392885Swnj if (unit >= NRK) 7402885Swnj return (ENXIO); 7412618Swnj #define phys(cast, addr) ((cast)((int)addr & 0x7fffffff)) 7422981Swnj ui = phys(struct uba_device *, rkdinfo[unit]); 7432885Swnj if (ui->ui_alive == 0) 7442885Swnj return (ENXIO); 7452618Swnj uba = phys(struct uba_hd *, ui->ui_hd)->uh_physuba; 7463329Swnj ubainit(uba); 7472618Swnj rkaddr = (struct rkdevice *)ui->ui_physaddr; 7482618Swnj num = maxfree; 7492618Swnj start = 0; 7503709Sroot rkaddr->rkcs1 = RK_CCLR; 7512618Swnj rkaddr->rkcs2 = unit; 7523709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO; 7532618Swnj rkwait(rkaddr); 7543293Swnj if ((rkaddr->rkds & RKDS_VV) == 0) { 7553709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_IE|RK_PACK|RK_GO; 7562618Swnj rkwait(rkaddr); 7572618Swnj } 7582618Swnj st = &rkst[ui->ui_type]; 7592618Swnj sizes = phys(struct size *, st->sizes); 7602885Swnj if (dumplo < 0 || dumplo + num >= sizes[minor(dev)&07].nblocks) 7612885Swnj return (EINVAL); 7622618Swnj while (num > 0) { 7632618Swnj register struct pte *io; 7642618Swnj register int i; 7652618Swnj int cn, sn, tn; 7662618Swnj daddr_t bn; 7672618Swnj 7682618Swnj blk = num > DBSIZE ? DBSIZE : num; 7692618Swnj io = uba->uba_map; 7702618Swnj for (i = 0; i < blk; i++) 7712981Swnj *(int *)io++ = (btop(start)+i) | (1<<21) | UBAMR_MRV; 7722618Swnj *(int *)io = 0; 7732618Swnj bn = dumplo + btop(start); 7742618Swnj cn = bn/st->nspc + sizes[minor(dev)&07].cyloff; 7752618Swnj sn = bn%st->nspc; 7762618Swnj tn = sn/st->nsect; 7772618Swnj sn = sn%st->nsect; 7782618Swnj rkaddr->rkcyl = cn; 7792618Swnj rp = (short *) &rkaddr->rkda; 7802618Swnj *rp = (tn << 8) + sn; 7812618Swnj *--rp = 0; 7822618Swnj *--rp = -blk*NBPG / sizeof (short); 7833709Sroot *--rp = rktypes[ui->ui_type]|RK_GO|RK_WRITE; 7842618Swnj rkwait(rkaddr); 7852885Swnj if (rkaddr->rkcs1 & RK_CERR) 7862885Swnj return (EIO); 7872618Swnj start += blk*NBPG; 7882618Swnj num -= blk; 7892618Swnj } 7902618Swnj return (0); 7912618Swnj } 7922618Swnj #endif 793