1*3709Sroot /* rk.c 4.34 81/05/09 */ 21899Swnj 31942Swnj #include "rk.h" 42648Swnj #if NHK > 0 53104Swnj int rkpip; /* DEBUG */ 63104Swnj int rknosval; /* DEBUG */ 7*3709Sroot #ifdef RKDEBUG 83293Swnj int rkdebug; 9*3709Sroot #endif 10*3709Sroot #ifdef RKBDEBUG 11*3709Sroot int rkbdebug; 12*3709Sroot #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" 302981Swnj #include "../h/ubareg.h" 312981Swnj #include "../h/ubavar.h" 321899Swnj #include "../h/dk.h" 332618Swnj #include "../h/cpu.h" 342618Swnj #include "../h/cmap.h" 35*3709Sroot #include "../h/dkbad.h" 361899Swnj 372618Swnj #include "../h/rkreg.h" 381899Swnj 392618Swnj struct rk_softc { 402618Swnj int sc_softas; 412618Swnj int sc_ndrive; 422618Swnj int sc_wticks; 432618Swnj int sc_recal; 442648Swnj } rk_softc[NHK]; 451899Swnj 462618Swnj /* THIS SHOULD BE READ OFF THE PACK, PER DRIVE */ 472787Swnj struct size { 482618Swnj daddr_t nblocks; 492618Swnj int cyloff; 50*3709Sroot } rk7_sizes[8] ={ 512618Swnj 15884, 0, /* A=cyl 0 thru 240 */ 522665Swnj 10032, 241, /* B=cyl 241 thru 392 */ 532665Swnj 53790, 0, /* C=cyl 0 thru 814 */ 542618Swnj 0, 0, 552618Swnj 0, 0, 562618Swnj 0, 0, 572618Swnj 27786, 393, /* G=cyl 393 thru 813 */ 582618Swnj 0, 0, 59*3709Sroot }, rk6_sizes[8] ={ 60*3709Sroot 15884, 0, /* A=cyl 0 thru 240 */ 61*3709Sroot 11154, 241, /* B=cyl 241 thru 409 */ 62*3709Sroot 27126, 0, /* C=cyl 0 thru 410 */ 63*3709Sroot 0, 0, 64*3709Sroot 0, 0, 65*3709Sroot 0, 0, 66*3709Sroot 0, 0, 67*3709Sroot 0, 0, 682618Swnj }; 692618Swnj /* END OF STUFF WHICH SHOULD BE READ IN PER DISK */ 701899Swnj 71*3709Sroot short rktypes[] = { RK_CDT, 0 }; 72*3709Sroot 732618Swnj int rkprobe(), rkslave(), rkattach(), rkdgo(), rkintr(); 742981Swnj struct uba_ctlr *rkminfo[NHK]; 752981Swnj struct uba_device *rkdinfo[NRK]; 762981Swnj struct uba_device *rkip[NHK][4]; 771899Swnj 782618Swnj u_short rkstd[] = { 0777440, 0 }; 792618Swnj struct uba_driver hkdriver = 802622Swnj { rkprobe, rkslave, rkattach, rkdgo, rkstd, "rk", rkdinfo, "hk", rkminfo, 1 }; 812648Swnj struct buf rkutab[NRK]; 822648Swnj short rkcyl[NRK]; 83*3709Sroot #ifndef NOBADBLOCK 84*3709Sroot struct dkbad rkbad[NRK]; 85*3709Sroot struct buf brkbuf[NRK]; 86*3709Sroot #endif 871899Swnj 882618Swnj struct rkst { 892618Swnj short nsect; 902618Swnj short ntrak; 912618Swnj short nspc; 922618Swnj short ncyl; 932618Swnj struct size *sizes; 942618Swnj } rkst[] = { 952618Swnj NRKSECT, NRKTRK, NRKSECT*NRKTRK, NRK7CYL, rk7_sizes, 96*3709Sroot NRKSECT, NRKTRK, NRKSECT*NRKTRK, NRK6CYL, rk6_sizes, 972618Swnj }; 981899Swnj 992618Swnj u_char rk_offset[16] = 1003293Swnj { RKAS_P400,RKAS_M400,RKAS_P400,RKAS_M400,RKAS_P800,RKAS_M800,RKAS_P800, 1013293Swnj RKAS_M800,RKAS_P1200,RKAS_M1200,RKAS_P1200,RKAS_M1200,0,0,0,0 1023293Swnj }; 1031899Swnj 1042648Swnj struct buf rrkbuf[NRK]; 1052618Swnj 1062618Swnj #define b_cylin b_resid 1072618Swnj 1082618Swnj #ifdef INTRLVE 1092618Swnj daddr_t dkblock(); 1102618Swnj #endif 1112618Swnj 1122618Swnj int rkwstart, rkwatch(); 1132618Swnj 1142618Swnj rkprobe(reg) 1152618Swnj caddr_t reg; 1161899Swnj { 1172618Swnj register int br, cvec; 1181899Swnj 1192618Swnj #ifdef lint 1202618Swnj br = 0; cvec = br; br = cvec; 1212618Swnj #endif 1222618Swnj ((struct rkdevice *)reg)->rkcs1 = RK_CDT|RK_IE|RK_CRDY; 1232618Swnj DELAY(10); 1242618Swnj ((struct rkdevice *)reg)->rkcs1 = RK_CDT; 1252618Swnj return (1); 1262618Swnj } 1271899Swnj 1282618Swnj rkslave(ui, reg) 1292981Swnj struct uba_device *ui; 1302618Swnj caddr_t reg; 1312618Swnj { 1322618Swnj register struct rkdevice *rkaddr = (struct rkdevice *)reg; 1331899Swnj 134*3709Sroot ui->ui_type = 0; 135*3709Sroot rkaddr->rkcs1 = RK_CCLR; 1362618Swnj rkaddr->rkcs2 = ui->ui_slave; 1372957Swnj rkaddr->rkcs1 = RK_CDT|RK_DCLR|RK_GO; 1382622Swnj rkwait(rkaddr); 1392894Swnj DELAY(50); 1403293Swnj if (rkaddr->rkcs2&RKCS2_NED || (rkaddr->rkds&RKDS_SVAL) == 0) { 141*3709Sroot rkaddr->rkcs1 = RK_CCLR; 1422618Swnj return (0); 1432618Swnj } 144*3709Sroot if (rkaddr->rkcs1&RK_CERR && rkaddr->rker&RKER_DTYE) { 145*3709Sroot ui->ui_type = 1; 146*3709Sroot rkaddr->rkcs1 = RK_CCLR; 147*3709Sroot } 1482618Swnj return (1); 1492618Swnj } 1502618Swnj 1512618Swnj rkattach(ui) 1522981Swnj register struct uba_device *ui; 1532618Swnj { 1542618Swnj 1552618Swnj if (rkwstart == 0) { 1562758Swnj timeout(rkwatch, (caddr_t)0, hz); 1572618Swnj rkwstart++; 1582618Swnj } 1592618Swnj if (ui->ui_dk >= 0) 1602758Swnj dk_mspw[ui->ui_dk] = 1.0 / (60 * NRKSECT * 256); 1612618Swnj rkip[ui->ui_ctlr][ui->ui_slave] = ui; 1622618Swnj rk_softc[ui->ui_ctlr].sc_ndrive++; 1632618Swnj rkcyl[ui->ui_unit] = -1; 164*3709Sroot ui->ui_flags = 0; 1652618Swnj } 1662618Swnj 1671899Swnj rkstrategy(bp) 1682618Swnj register struct buf *bp; 1691899Swnj { 1702981Swnj register struct uba_device *ui; 1712618Swnj register struct rkst *st; 1722618Swnj register int unit; 1732618Swnj register struct buf *dp; 1742618Swnj int xunit = minor(bp->b_dev) & 07; 1752618Swnj long bn, sz; 1761899Swnj 1772618Swnj sz = (bp->b_bcount+511) >> 9; 1782618Swnj unit = dkunit(bp); 1792648Swnj if (unit >= NRK) 1802618Swnj goto bad; 1812618Swnj ui = rkdinfo[unit]; 1822618Swnj if (ui == 0 || ui->ui_alive == 0) 1832618Swnj goto bad; 1842618Swnj st = &rkst[ui->ui_type]; 1852618Swnj if (bp->b_blkno < 0 || 1862618Swnj (bn = dkblock(bp))+sz > st->sizes[xunit].nblocks) 1872618Swnj goto bad; 1882618Swnj bp->b_cylin = bn/st->nspc + st->sizes[xunit].cyloff; 1892618Swnj (void) spl5(); 1902618Swnj dp = &rkutab[ui->ui_unit]; 1912618Swnj disksort(dp, bp); 1922618Swnj if (dp->b_active == 0) { 1932618Swnj (void) rkustart(ui); 1942618Swnj bp = &ui->ui_mi->um_tab; 1952618Swnj if (bp->b_actf && bp->b_active == 0) 1962618Swnj (void) rkstart(ui->ui_mi); 1971899Swnj } 1982618Swnj (void) spl0(); 1992618Swnj return; 2002618Swnj 2012618Swnj bad: 2022618Swnj bp->b_flags |= B_ERROR; 2032618Swnj iodone(bp); 2042618Swnj return; 2051899Swnj } 2061899Swnj 2072618Swnj rkustart(ui) 2082981Swnj register struct uba_device *ui; 2092618Swnj { 2102618Swnj register struct buf *bp, *dp; 2112981Swnj register struct uba_ctlr *um; 2122618Swnj register struct rkdevice *rkaddr; 2132618Swnj int didie = 0; 2141899Swnj 2152618Swnj if (ui == 0) 2162618Swnj return (0); 2172618Swnj dk_busy &= ~(1<<ui->ui_dk); 2182618Swnj dp = &rkutab[ui->ui_unit]; 2192618Swnj um = ui->ui_mi; 2202894Swnj rkaddr = (struct rkdevice *)um->um_addr; 2212618Swnj if (um->um_tab.b_active) { 2222618Swnj rk_softc[um->um_ctlr].sc_softas |= 1<<ui->ui_slave; 2232618Swnj return (0); 2242618Swnj } 225*3709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_CERR; 2262618Swnj rkaddr->rkcs2 = ui->ui_slave; 227*3709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO; 2282618Swnj rkwait(rkaddr); 2292903Swnj if ((bp = dp->b_actf) == NULL) { 230*3709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO; 2312903Swnj rkwait(rkaddr); 2322903Swnj return (0); 2332903Swnj } 234*3709Sroot if ((rkaddr->rkds & RKDS_VV) == 0 || ui->ui_flags == 0) { 2352618Swnj /* SHOULD WARN SYSTEM THAT THIS HAPPENED */ 236*3709Sroot #ifndef NOBADBLOCK 237*3709Sroot struct rkst *st = &rkst[ui->ui_type]; 238*3709Sroot struct buf *bbp = &brkbuf[ui->ui_unit]; 239*3709Sroot #endif 240*3709Sroot 241*3709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_PACK|RK_GO; 242*3709Sroot ui->ui_flags = 1; 243*3709Sroot #ifndef NOBADBLOCK 244*3709Sroot bbp->b_flags = B_READ|B_BUSY; 245*3709Sroot bbp->b_dev = bp->b_dev; 246*3709Sroot bbp->b_bcount = 512; 247*3709Sroot bbp->b_un.b_addr = (caddr_t)&rkbad[ui->ui_unit]; 248*3709Sroot bbp->b_blkno = st->ncyl*st->nspc - st->nsect; 249*3709Sroot bbp->b_cylin = st->ncyl - 1; 250*3709Sroot dp->b_actf = bbp; 251*3709Sroot bbp->av_forw = bp; 252*3709Sroot bp = bbp; 253*3709Sroot #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; 267*3709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_IE|RK_SEEK|RK_GO; 2682618Swnj didie = 1; 2692618Swnj if (ui->ui_dk >= 0) { 2702618Swnj dk_busy |= 1<<ui->ui_dk; 2712618Swnj dk_seek[ui->ui_dk]++; 2722618Swnj } 2732618Swnj goto out; 2742618Swnj done: 2752618Swnj if (dp->b_active != 2) { 2762618Swnj dp->b_forw = NULL; 2772618Swnj if (um->um_tab.b_actf == NULL) 2782618Swnj um->um_tab.b_actf = dp; 2792618Swnj else 2802618Swnj um->um_tab.b_actl->b_forw = dp; 2812618Swnj um->um_tab.b_actl = dp; 2822618Swnj dp->b_active = 2; 2832618Swnj } 2842618Swnj out: 2852618Swnj return (didie); 2862618Swnj } 2872618Swnj 2882618Swnj rkstart(um) 2892981Swnj register struct uba_ctlr *um; 2901899Swnj { 2912618Swnj register struct buf *bp, *dp; 2922981Swnj register struct uba_device *ui; 2932618Swnj register struct rkdevice *rkaddr; 2942618Swnj struct rkst *st; 2951899Swnj daddr_t bn; 2962618Swnj int sn, tn, cmd; 2971899Swnj 2982618Swnj loop: 2992618Swnj if ((dp = um->um_tab.b_actf) == NULL) 3002618Swnj return (0); 3012618Swnj if ((bp = dp->b_actf) == NULL) { 3022618Swnj um->um_tab.b_actf = dp->b_forw; 3032618Swnj goto loop; 3041899Swnj } 3052618Swnj um->um_tab.b_active++; 3062618Swnj ui = rkdinfo[dkunit(bp)]; 3072618Swnj bn = dkblock(bp); 3082618Swnj st = &rkst[ui->ui_type]; 3092618Swnj sn = bn%st->nspc; 3102618Swnj tn = sn/st->nsect; 3112618Swnj sn %= st->nsect; 3122618Swnj rkaddr = (struct rkdevice *)ui->ui_addr; 3132957Swnj retry: 314*3709Sroot rkaddr->rkcs1 = RK_CCLR; 3152618Swnj rkaddr->rkcs2 = ui->ui_slave; 316*3709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO; 3172618Swnj rkwait(rkaddr); 3183293Swnj if ((rkaddr->rkds&RKDS_SVAL) == 0) { 3192957Swnj rknosval++; 3202957Swnj goto nosval; 3212894Swnj } 3223293Swnj if (rkaddr->rkds&RKDS_PIP) { 3232957Swnj rkpip++; 3242957Swnj goto retry; 3252957Swnj } 3263293Swnj if ((rkaddr->rkds&RKDS_DREADY) != RKDS_DREADY) { 3272927Swnj printf("rk%d: not ready", dkunit(bp)); 3283293Swnj if ((rkaddr->rkds&RKDS_DREADY) != RKDS_DREADY) { 3292894Swnj printf("\n"); 330*3709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO; 3312894Swnj rkwait(rkaddr); 332*3709Sroot rkaddr->rkcs1 = RK_CCLR; 3332894Swnj rkwait(rkaddr); 3342894Swnj um->um_tab.b_active = 0; 3352894Swnj um->um_tab.b_errcnt = 0; 3362894Swnj dp->b_actf = bp->av_forw; 3372894Swnj dp->b_active = 0; 3382894Swnj bp->b_flags |= B_ERROR; 3392894Swnj iodone(bp); 3402894Swnj goto loop; 3412894Swnj } 3422894Swnj printf(" (came back!)\n"); 3432894Swnj } 3442957Swnj nosval: 3452618Swnj rkaddr->rkcyl = bp->b_cylin; 3462618Swnj rkcyl[ui->ui_unit] = bp->b_cylin; 3472618Swnj rkaddr->rkda = (tn << 8) + sn; 3482618Swnj rkaddr->rkwc = -bp->b_bcount / sizeof (short); 3492618Swnj if (bp->b_flags & B_READ) 350*3709Sroot cmd = rktypes[ui->ui_type]|RK_IE|RK_READ|RK_GO; 3512618Swnj else 352*3709Sroot cmd = rktypes[ui->ui_type]|RK_IE|RK_WRITE|RK_GO; 3532618Swnj um->um_cmd = cmd; 3543104Swnj (void) ubago(ui); 3552618Swnj return (1); 3561899Swnj } 3571899Swnj 3582618Swnj rkdgo(um) 3592981Swnj register struct uba_ctlr *um; 3601899Swnj { 3612618Swnj register struct rkdevice *rkaddr = (struct rkdevice *)um->um_addr; 3621899Swnj 3632618Swnj rkaddr->rkba = um->um_ubinfo; 3642618Swnj rkaddr->rkcs1 = um->um_cmd|((um->um_ubinfo>>8)&0x300); 3652618Swnj } 3662618Swnj 3672710Swnj rkintr(rk11) 3682618Swnj int rk11; 3692618Swnj { 3702981Swnj register struct uba_ctlr *um = rkminfo[rk11]; 3712981Swnj register struct uba_device *ui; 3722618Swnj register struct rkdevice *rkaddr = (struct rkdevice *)um->um_addr; 3732618Swnj register struct buf *bp, *dp; 3742618Swnj int unit; 3752618Swnj struct rk_softc *sc = &rk_softc[um->um_ctlr]; 3762618Swnj int as = (rkaddr->rkatt >> 8) | sc->sc_softas; 3772618Swnj int needie = 1; 3782618Swnj 3792618Swnj sc->sc_wticks = 0; 3802618Swnj sc->sc_softas = 0; 3812618Swnj if (um->um_tab.b_active) { 3822618Swnj dp = um->um_tab.b_actf; 3832618Swnj bp = dp->b_actf; 3842618Swnj ui = rkdinfo[dkunit(bp)]; 3852618Swnj dk_busy &= ~(1 << ui->ui_dk); 386*3709Sroot #ifndef NOBADBLOCK 387*3709Sroot if (bp->b_flags&B_BAD) 388*3709Sroot if (rkecc(ui, CONT)) 389*3709Sroot return; 390*3709Sroot #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; 396*3709Sroot #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 } 402*3709Sroot #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) { 408*3709Sroot 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; 415*3709Sroot } else if (er & RKER_BSE) { 416*3709Sroot #ifndef NOBADBLOCK 417*3709Sroot if (rkecc(ui, BSE)) 418*3709Sroot return; 419*3709Sroot else 420*3709Sroot #endif 421*3709Sroot goto hard; 4222676Swnj } else 4232618Swnj um->um_tab.b_active = 0; 4243293Swnj if (cs2&RKCS2_MDS) { 4253293Swnj rkaddr->rkcs2 = RKCS2_SCLR; 4262618Swnj goto retry; 4271899Swnj } 4282618Swnj recal = 0; 4293293Swnj if (ds&RKDS_DROT || er&(RKER_OPI|RKER_SKI|RKER_UNS) || 4302618Swnj (um->um_tab.b_errcnt&07) == 4) 4312618Swnj recal = 1; 4323293Swnj if ((er & (RKER_DCK|RKER_ECH)) == RKER_DCK) 433*3709Sroot if (rkecc(ui, ECC)) 4342618Swnj return; 435*3709Sroot rkaddr->rkcs1 = RK_CCLR; 4362618Swnj rkaddr->rkcs2 = ui->ui_slave; 437*3709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO; 4382618Swnj rkwait(rkaddr); 4392618Swnj if (recal && um->um_tab.b_active == 0) { 440*3709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_IE|RK_RECAL|RK_GO; 4412618Swnj rkcyl[ui->ui_unit] = -1; 4422957Swnj sc->sc_recal = 0; 4432957Swnj goto nextrecal; 4442618Swnj } 4451899Swnj } 4462618Swnj retry: 4472957Swnj switch (sc->sc_recal) { 4482957Swnj 4492957Swnj case 1: 4502957Swnj rkaddr->rkcyl = bp->b_cylin; 4512957Swnj rkcyl[ui->ui_unit] = bp->b_cylin; 452*3709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_IE|RK_SEEK|RK_GO; 4532957Swnj goto nextrecal; 4542957Swnj case 2: 4552957Swnj if (um->um_tab.b_errcnt < 16 || 4563290Swnj (bp->b_flags&B_READ) == 0) 4573159Swnj goto donerecal; 4582957Swnj rkaddr->rkatt = rk_offset[um->um_tab.b_errcnt & 017]; 459*3709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_IE|RK_OFFSET|RK_GO; 4602957Swnj /* fall into ... */ 4612957Swnj nextrecal: 4622957Swnj sc->sc_recal++; 4632957Swnj rkwait(rkaddr); 4642957Swnj um->um_tab.b_active = 1; 4652957Swnj return; 4663159Swnj donerecal: 4672957Swnj case 3: 4682618Swnj sc->sc_recal = 0; 4692618Swnj um->um_tab.b_active = 0; 4702957Swnj break; 4711899Swnj } 472*3709Sroot ubadone(um); 4732618Swnj if (um->um_tab.b_active) { 4742618Swnj um->um_tab.b_active = 0; 4752618Swnj um->um_tab.b_errcnt = 0; 4762618Swnj um->um_tab.b_actf = dp->b_forw; 4772618Swnj dp->b_active = 0; 4782618Swnj dp->b_errcnt = 0; 4792618Swnj dp->b_actf = bp->av_forw; 4802618Swnj bp->b_resid = -rkaddr->rkwc * sizeof(short); 4812618Swnj iodone(bp); 4822618Swnj if (dp->b_actf) 4832618Swnj if (rkustart(ui)) 4842618Swnj needie = 0; 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) { 4922981Swnj if (rkustart(rkip[rk11][unit])) 4932981Swnj needie = 0; 4942981Swnj } else { 495*3709Sroot rkaddr->rkcs1 = RK_CCLR; 4962981Swnj rkaddr->rkcs2 = unit; 497*3709Sroot rkaddr->rkcs1 = RK_DCLR|RK_GO; 4982981Swnj rkwait(rkaddr); 499*3709Sroot rkaddr->rkcs1 = RK_CCLR; 5002981Swnj } 5012981Swnj } 5022618Swnj if (um->um_tab.b_actf && um->um_tab.b_active == 0) 5032618Swnj if (rkstart(um)) 5042618Swnj needie = 0; 5052618Swnj if (needie) 506*3709Sroot rkaddr->rkcs1 = RK_IE; 5071899Swnj } 5081899Swnj 5092618Swnj rkwait(addr) 5102618Swnj register struct rkdevice *addr; 5112618Swnj { 5121899Swnj 5132618Swnj while ((addr->rkcs1 & RK_CRDY) == 0) 5142618Swnj ; 5152618Swnj } 5162618Swnj 5172618Swnj rkread(dev) 5182618Swnj dev_t dev; 5191899Swnj { 5202618Swnj register int unit = minor(dev) >> 3; 5212618Swnj 5222648Swnj if (unit >= NRK) 5232618Swnj u.u_error = ENXIO; 5242618Swnj else 5252618Swnj physio(rkstrategy, &rrkbuf[unit], dev, B_READ, minphys); 5261899Swnj } 5271899Swnj 5282618Swnj rkwrite(dev) 5292618Swnj dev_t dev; 5301899Swnj { 5312618Swnj register int unit = minor(dev) >> 3; 5321899Swnj 5332648Swnj if (unit >= NRK) 5342618Swnj u.u_error = ENXIO; 5352618Swnj else 5362618Swnj physio(rkstrategy, &rrkbuf[unit], dev, B_WRITE, minphys); 5371899Swnj } 5381899Swnj 539*3709Sroot rkecc(ui, flag) 5402981Swnj register struct uba_device *ui; 5411899Swnj { 5422618Swnj register struct rkdevice *rk = (struct rkdevice *)ui->ui_addr; 5432618Swnj register struct buf *bp = rkutab[ui->ui_unit].b_actf; 5442981Swnj register struct uba_ctlr *um = ui->ui_mi; 5452618Swnj register struct rkst *st; 5462618Swnj struct uba_regs *ubp = ui->ui_hd->uh_uba; 5472618Swnj caddr_t addr; 548*3709Sroot int reg, npf, o, cmd, ubaddr; 5492618Swnj int bn, cn, tn, sn; 5501899Swnj 551*3709Sroot #ifndef NOBADBLOCK 552*3709Sroot if (flag == CONT) 553*3709Sroot npf = bp->b_error; 554*3709Sroot else 555*3709Sroot #endif 556*3709Sroot npf = btop((rk->rkwc * sizeof(short)) + bp->b_bcount); 5572618Swnj reg = btop(um->um_ubinfo&0x3ffff) + npf; 5582618Swnj o = (int)bp->b_un.b_addr & PGOFSET; 5592618Swnj bn = dkblock(bp); 5602618Swnj st = &rkst[ui->ui_type]; 5612618Swnj cn = bp->b_cylin; 562*3709Sroot sn = bn%st->nspc + npf; 5632618Swnj tn = sn/st->nsect; 5642618Swnj sn %= st->nsect; 5652618Swnj cn += tn/st->ntrak; 5662618Swnj tn %= st->ntrak; 567*3709Sroot ubapurge(um); 568*3709Sroot um->um_tab.b_active++; /* Either complete or continuing... */ 569*3709Sroot switch (flag) { 570*3709Sroot case ECC: 571*3709Sroot { 572*3709Sroot register int i; 573*3709Sroot int bit, byte, mask; 574*3709Sroot 575*3709Sroot npf--; 576*3709Sroot reg--; 577*3709Sroot printf("rk%d%c: soft ecc sn%d\n", dkunit(bp), 578*3709Sroot 'a'+(minor(bp->b_dev)&07), bp->b_blkno + npf); 579*3709Sroot mask = rk->rkec2; 580*3709Sroot i = rk->rkec1 - 1; /* -1 makes 0 origin */ 581*3709Sroot bit = i&07; 582*3709Sroot i = (i&~07)>>3; 583*3709Sroot byte = i + o; 584*3709Sroot while (i < 512 && (int)ptob(npf)+i < bp->b_bcount && bit > -11) { 585*3709Sroot addr = ptob(ubp->uba_map[reg+btop(byte)].pg_pfnum)+ 586*3709Sroot (byte & PGOFSET); 587*3709Sroot putmemc(addr, getmemc(addr)^(mask<<bit)); 588*3709Sroot byte++; 589*3709Sroot i++; 590*3709Sroot bit -= 8; 591*3709Sroot } 592*3709Sroot if (rk->rkwc == 0) 593*3709Sroot return (0); 594*3709Sroot npf++; 595*3709Sroot reg++; 596*3709Sroot break; 597*3709Sroot } 598*3709Sroot 599*3709Sroot #ifndef NOBADBLOCK 600*3709Sroot case BSE: 601*3709Sroot #ifdef RKBDEBUG 602*3709Sroot if (rkbdebug) 603*3709Sroot printf("rkecc, BSE: bn %d cn %d tn %d sn %d\n", bn, cn, tn, sn); 604*3709Sroot #endif 605*3709Sroot if ((bn = isbad(&rkbad[ui->ui_unit], cn, tn, sn)) < 0) 606*3709Sroot return(0); 607*3709Sroot bp->b_flags |= B_BAD; 608*3709Sroot bp->b_error = npf + 1; 609*3709Sroot bn = st->ncyl*st->nspc - st->nsect - 1 - bn; 610*3709Sroot cn = bn/st->nspc; 611*3709Sroot sn = bn%st->nspc; 612*3709Sroot tn = sn/st->nsect; 613*3709Sroot sn %= st->nsect; 614*3709Sroot #ifdef RKBDEBUG 615*3709Sroot if (rkbdebug) 616*3709Sroot printf("revector to cn %d tn %d sn %d\n", cn, tn, sn); 617*3709Sroot #endif 618*3709Sroot rk->rkwc = -(512 / sizeof (short)); 619*3709Sroot break; 620*3709Sroot 621*3709Sroot case CONT: 622*3709Sroot #ifdef RKBDEBUG 623*3709Sroot if (rkbdebug) 624*3709Sroot printf("rkecc, CONT: bn %d cn %d tn %d sn %d\n", bn,cn,tn,sn); 625*3709Sroot #endif 626*3709Sroot bp->b_flags &= ~B_BAD; 627*3709Sroot rk->rkwc = -((bp->b_bcount - (int)ptob(npf)) / sizeof (short)); 628*3709Sroot if (rk->rkwc == 0) 629*3709Sroot return(0); 630*3709Sroot break; 631*3709Sroot #endif 632*3709Sroot } 633*3709Sroot rk->rkcs1 = RK_CCLR; 634*3709Sroot rk->rkcs2 = ui->ui_slave; 635*3709Sroot rk->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO; 636*3709Sroot rkwait(rk); 6372618Swnj rk->rkcyl = cn; 6382618Swnj rk->rkda = (tn << 8) | sn; 639*3709Sroot ubaddr = (int)ptob(reg) + o; 6402618Swnj rk->rkba = ubaddr; 641*3709Sroot cmd = (bp->b_flags&B_READ ? RK_READ : RK_WRITE)|RK_IE|RK_GO; 642*3709Sroot cmd |= (ubaddr >> 8) & 0x300; 643*3709Sroot cmd |= rktypes[ui->ui_type]; 6442618Swnj rk->rkcs1 = cmd; 645*3709Sroot um->um_tab.b_errcnt = 0; /* error has been corrected */ 6462618Swnj return (1); 6471899Swnj } 6481899Swnj 6492618Swnj rkreset(uban) 6502927Swnj int uban; 6511899Swnj { 6522981Swnj register struct uba_ctlr *um; 6532981Swnj register struct uba_device *ui; 6542618Swnj register rk11, unit; 6551899Swnj 6562648Swnj for (rk11 = 0; rk11 < NHK; rk11++) { 6572618Swnj if ((um = rkminfo[rk11]) == 0 || um->um_ubanum != uban || 6582618Swnj um->um_alive == 0) 6592618Swnj continue; 6602927Swnj printf(" hk%d", rk11); 6612618Swnj um->um_tab.b_active = 0; 6622618Swnj um->um_tab.b_actf = um->um_tab.b_actl = 0; 6632618Swnj rk_softc[um->um_ctlr].sc_recal = 0; 6642618Swnj if (um->um_ubinfo) { 6652618Swnj printf("<%d>", (um->um_ubinfo>>28)&0xf); 6662618Swnj ubadone(um); 6672618Swnj } 6682648Swnj for (unit = 0; unit < NHK; unit++) { 6692618Swnj if ((ui = rkdinfo[unit]) == 0) 6702618Swnj continue; 6712618Swnj if (ui->ui_alive == 0) 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; 736*3709Sroot rkaddr->rkcs1 = RK_CCLR; 7372618Swnj rkaddr->rkcs2 = unit; 738*3709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO; 7392618Swnj rkwait(rkaddr); 7403293Swnj if ((rkaddr->rkds & RKDS_VV) == 0) { 741*3709Sroot 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); 769*3709Sroot *--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 } 7782618Swnj #endif 779