123336Smckusick /* 223336Smckusick * Copyright (c) 1982 Regents of the University of California. 323336Smckusick * All rights reserved. The Berkeley software License Agreement 423336Smckusick * specifies the terms and conditions for redistribution. 523336Smckusick * 6*24210Sbloom * @(#)rk.c 6.6 (Berkeley) 08/08/85 723336Smckusick */ 81899Swnj 91942Swnj #include "rk.h" 102648Swnj #if NHK > 0 113104Swnj int rkpip; /* DEBUG */ 123104Swnj int rknosval; /* DEBUG */ 133709Sroot #ifdef RKDEBUG 143293Swnj int rkdebug; 153709Sroot #endif 163709Sroot #ifdef RKBDEBUG 173709Sroot int rkbdebug; 183709Sroot #endif 191899Swnj /* 203293Swnj * RK611/RK0[67] disk driver 212622Swnj * 222622Swnj * This driver mimics up.c; see it for an explanation of common code. 232685Swnj * 242885Swnj * TODO: 253208Swnj * Learn why we lose an interrupt sometime when spinning drives down 261899Swnj */ 279777Ssam #include "../machine/pte.h" 289777Ssam 2917076Sbloom #include "param.h" 3017076Sbloom #include "systm.h" 3117076Sbloom #include "buf.h" 3217076Sbloom #include "conf.h" 3317076Sbloom #include "dir.h" 3417076Sbloom #include "user.h" 3517076Sbloom #include "map.h" 3617076Sbloom #include "vm.h" 3717076Sbloom #include "dk.h" 3817076Sbloom #include "cmap.h" 3917076Sbloom #include "dkbad.h" 4017076Sbloom #include "uio.h" 4117076Sbloom #include "kernel.h" 4218315Sralph #include "syslog.h" 431899Swnj 448478Sroot #include "../vax/cpu.h" 4517076Sbloom #include "ubareg.h" 4617076Sbloom #include "ubavar.h" 4717076Sbloom #include "rkreg.h" 481899Swnj 492618Swnj struct rk_softc { 502618Swnj int sc_softas; 512618Swnj int sc_ndrive; 522618Swnj int sc_wticks; 532618Swnj int sc_recal; 542648Swnj } rk_softc[NHK]; 551899Swnj 562618Swnj /* THIS SHOULD BE READ OFF THE PACK, PER DRIVE */ 572787Swnj struct size { 582618Swnj daddr_t nblocks; 592618Swnj int cyloff; 603709Sroot } rk7_sizes[8] ={ 612618Swnj 15884, 0, /* A=cyl 0 thru 240 */ 622665Swnj 10032, 241, /* B=cyl 241 thru 392 */ 632665Swnj 53790, 0, /* C=cyl 0 thru 814 */ 642618Swnj 0, 0, 652618Swnj 0, 0, 662618Swnj 0, 0, 672618Swnj 27786, 393, /* G=cyl 393 thru 813 */ 682618Swnj 0, 0, 693709Sroot }, rk6_sizes[8] ={ 703709Sroot 15884, 0, /* A=cyl 0 thru 240 */ 713709Sroot 11154, 241, /* B=cyl 241 thru 409 */ 723709Sroot 27126, 0, /* C=cyl 0 thru 410 */ 733709Sroot 0, 0, 743709Sroot 0, 0, 753709Sroot 0, 0, 763709Sroot 0, 0, 773709Sroot 0, 0, 782618Swnj }; 792618Swnj /* END OF STUFF WHICH SHOULD BE READ IN PER DISK */ 801899Swnj 813709Sroot short rktypes[] = { RK_CDT, 0 }; 823709Sroot 832618Swnj int rkprobe(), rkslave(), rkattach(), rkdgo(), rkintr(); 842981Swnj struct uba_ctlr *rkminfo[NHK]; 852981Swnj struct uba_device *rkdinfo[NRK]; 862981Swnj struct uba_device *rkip[NHK][4]; 871899Swnj 882618Swnj u_short rkstd[] = { 0777440, 0 }; 892618Swnj struct uba_driver hkdriver = 902622Swnj { rkprobe, rkslave, rkattach, rkdgo, rkstd, "rk", rkdinfo, "hk", rkminfo, 1 }; 912648Swnj struct buf rkutab[NRK]; 922648Swnj short rkcyl[NRK]; 933709Sroot struct dkbad rkbad[NRK]; 943709Sroot struct buf brkbuf[NRK]; 951899Swnj 962618Swnj struct rkst { 972618Swnj short nsect; 982618Swnj short ntrak; 992618Swnj short nspc; 1002618Swnj short ncyl; 1012618Swnj struct size *sizes; 1022618Swnj } rkst[] = { 1032618Swnj NRKSECT, NRKTRK, NRKSECT*NRKTRK, NRK7CYL, rk7_sizes, 1043709Sroot NRKSECT, NRKTRK, NRKSECT*NRKTRK, NRK6CYL, rk6_sizes, 1052618Swnj }; 1061899Swnj 1072618Swnj u_char rk_offset[16] = 1083293Swnj { RKAS_P400,RKAS_M400,RKAS_P400,RKAS_M400,RKAS_P800,RKAS_M800,RKAS_P800, 1093293Swnj RKAS_M800,RKAS_P1200,RKAS_M1200,RKAS_P1200,RKAS_M1200,0,0,0,0 1103293Swnj }; 1111899Swnj 1122648Swnj struct buf rrkbuf[NRK]; 1132618Swnj 1142618Swnj #define b_cylin b_resid 1152618Swnj 1162618Swnj #ifdef INTRLVE 1172618Swnj daddr_t dkblock(); 1182618Swnj #endif 1192618Swnj 1202618Swnj int rkwstart, rkwatch(); 1212618Swnj 1222618Swnj rkprobe(reg) 1232618Swnj caddr_t reg; 1241899Swnj { 1252618Swnj register int br, cvec; 1261899Swnj 1272618Swnj #ifdef lint 1282618Swnj br = 0; cvec = br; br = cvec; 1294935Swnj rkintr(0); 1302618Swnj #endif 1312618Swnj ((struct rkdevice *)reg)->rkcs1 = RK_CDT|RK_IE|RK_CRDY; 1322618Swnj DELAY(10); 1332618Swnj ((struct rkdevice *)reg)->rkcs1 = RK_CDT; 1347416Skre return (sizeof (struct rkdevice)); 1352618Swnj } 1361899Swnj 1372618Swnj rkslave(ui, reg) 1382981Swnj struct uba_device *ui; 1392618Swnj caddr_t reg; 1402618Swnj { 1412618Swnj register struct rkdevice *rkaddr = (struct rkdevice *)reg; 1421899Swnj 1433709Sroot ui->ui_type = 0; 1443709Sroot rkaddr->rkcs1 = RK_CCLR; 1452618Swnj rkaddr->rkcs2 = ui->ui_slave; 1462957Swnj rkaddr->rkcs1 = RK_CDT|RK_DCLR|RK_GO; 1472622Swnj rkwait(rkaddr); 1482894Swnj DELAY(50); 1493293Swnj if (rkaddr->rkcs2&RKCS2_NED || (rkaddr->rkds&RKDS_SVAL) == 0) { 1503709Sroot rkaddr->rkcs1 = RK_CCLR; 1512618Swnj return (0); 1522618Swnj } 1533709Sroot if (rkaddr->rkcs1&RK_CERR && rkaddr->rker&RKER_DTYE) { 1543709Sroot ui->ui_type = 1; 1553709Sroot rkaddr->rkcs1 = RK_CCLR; 1563709Sroot } 1572618Swnj return (1); 1582618Swnj } 1592618Swnj 1602618Swnj rkattach(ui) 1612981Swnj register struct uba_device *ui; 1622618Swnj { 1632618Swnj 1642618Swnj if (rkwstart == 0) { 1652758Swnj timeout(rkwatch, (caddr_t)0, hz); 1662618Swnj rkwstart++; 1672618Swnj } 1682618Swnj if (ui->ui_dk >= 0) 1692758Swnj dk_mspw[ui->ui_dk] = 1.0 / (60 * NRKSECT * 256); 1702618Swnj rkip[ui->ui_ctlr][ui->ui_slave] = ui; 1712618Swnj rk_softc[ui->ui_ctlr].sc_ndrive++; 1722618Swnj rkcyl[ui->ui_unit] = -1; 1733709Sroot ui->ui_flags = 0; 1742618Swnj } 1752618Swnj 1768573Sroot rkopen(dev) 1778573Sroot dev_t dev; 1788573Sroot { 1798573Sroot register int unit = minor(dev) >> 3; 1808573Sroot register struct uba_device *ui; 1818573Sroot 1828573Sroot if (unit >= NRK || (ui = rkdinfo[unit]) == 0 || ui->ui_alive == 0) 1838573Sroot return (ENXIO); 1848573Sroot return (0); 1858573Sroot } 1868573Sroot 1871899Swnj rkstrategy(bp) 1882618Swnj register struct buf *bp; 1891899Swnj { 1902981Swnj register struct uba_device *ui; 1912618Swnj register struct rkst *st; 1922618Swnj register int unit; 1932618Swnj register struct buf *dp; 1942618Swnj int xunit = minor(bp->b_dev) & 07; 1952618Swnj long bn, sz; 1965433Sroot int s; 1971899Swnj 1982618Swnj sz = (bp->b_bcount+511) >> 9; 1992618Swnj unit = dkunit(bp); 2002648Swnj if (unit >= NRK) 2012618Swnj goto bad; 2022618Swnj ui = rkdinfo[unit]; 2032618Swnj if (ui == 0 || ui->ui_alive == 0) 2042618Swnj goto bad; 2052618Swnj st = &rkst[ui->ui_type]; 2062618Swnj if (bp->b_blkno < 0 || 2072618Swnj (bn = dkblock(bp))+sz > st->sizes[xunit].nblocks) 2082618Swnj goto bad; 2092618Swnj bp->b_cylin = bn/st->nspc + st->sizes[xunit].cyloff; 2105433Sroot s = spl5(); 2112618Swnj dp = &rkutab[ui->ui_unit]; 2122618Swnj disksort(dp, bp); 2132618Swnj if (dp->b_active == 0) { 2142618Swnj (void) rkustart(ui); 2152618Swnj bp = &ui->ui_mi->um_tab; 2162618Swnj if (bp->b_actf && bp->b_active == 0) 2172618Swnj (void) rkstart(ui->ui_mi); 2181899Swnj } 2195433Sroot splx(s); 2202618Swnj return; 2212618Swnj 2222618Swnj bad: 2232618Swnj bp->b_flags |= B_ERROR; 2242618Swnj iodone(bp); 2252618Swnj return; 2261899Swnj } 2271899Swnj 2282618Swnj rkustart(ui) 2292981Swnj register struct uba_device *ui; 2302618Swnj { 2312618Swnj register struct buf *bp, *dp; 2322981Swnj register struct uba_ctlr *um; 2332618Swnj register struct rkdevice *rkaddr; 2341899Swnj 2352618Swnj if (ui == 0) 2366347Swnj return; 2372618Swnj dk_busy &= ~(1<<ui->ui_dk); 2382618Swnj dp = &rkutab[ui->ui_unit]; 2392618Swnj um = ui->ui_mi; 2402894Swnj rkaddr = (struct rkdevice *)um->um_addr; 2412618Swnj if (um->um_tab.b_active) { 2422618Swnj rk_softc[um->um_ctlr].sc_softas |= 1<<ui->ui_slave; 2436347Swnj return; 2442618Swnj } 2456347Swnj if ((bp = dp->b_actf) == NULL) 2466347Swnj return; 2473709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_CERR; 2482618Swnj rkaddr->rkcs2 = ui->ui_slave; 2493709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO; 2502618Swnj rkwait(rkaddr); 2513709Sroot if ((rkaddr->rkds & RKDS_VV) == 0 || ui->ui_flags == 0) { 2522618Swnj /* SHOULD WARN SYSTEM THAT THIS HAPPENED */ 2533709Sroot struct rkst *st = &rkst[ui->ui_type]; 2543709Sroot struct buf *bbp = &brkbuf[ui->ui_unit]; 2553709Sroot 2563709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_PACK|RK_GO; 2573709Sroot ui->ui_flags = 1; 2583709Sroot bbp->b_flags = B_READ|B_BUSY; 2593709Sroot bbp->b_dev = bp->b_dev; 2603709Sroot bbp->b_bcount = 512; 2613709Sroot bbp->b_un.b_addr = (caddr_t)&rkbad[ui->ui_unit]; 2623709Sroot bbp->b_blkno = st->ncyl*st->nspc - st->nsect; 2633709Sroot bbp->b_cylin = st->ncyl - 1; 2643709Sroot dp->b_actf = bbp; 2653709Sroot bbp->av_forw = bp; 2663709Sroot bp = bbp; 2672618Swnj rkwait(rkaddr); 2682618Swnj } 2692903Swnj if (dp->b_active) 2702903Swnj goto done; 2712903Swnj dp->b_active = 1; 2723293Swnj if ((rkaddr->rkds & RKDS_DREADY) != RKDS_DREADY) 2732894Swnj goto done; 2742618Swnj if (rk_softc[um->um_ctlr].sc_ndrive == 1) 2752618Swnj goto done; 2762618Swnj if (bp->b_cylin == rkcyl[ui->ui_unit]) 2772618Swnj goto done; 2782618Swnj rkaddr->rkcyl = bp->b_cylin; 2792618Swnj rkcyl[ui->ui_unit] = bp->b_cylin; 2803709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_IE|RK_SEEK|RK_GO; 2812618Swnj if (ui->ui_dk >= 0) { 2822618Swnj dk_busy |= 1<<ui->ui_dk; 2832618Swnj dk_seek[ui->ui_dk]++; 2842618Swnj } 2852618Swnj goto out; 2862618Swnj done: 2872618Swnj if (dp->b_active != 2) { 2882618Swnj dp->b_forw = NULL; 2892618Swnj if (um->um_tab.b_actf == NULL) 2902618Swnj um->um_tab.b_actf = dp; 2912618Swnj else 2922618Swnj um->um_tab.b_actl->b_forw = dp; 2932618Swnj um->um_tab.b_actl = dp; 2942618Swnj dp->b_active = 2; 2952618Swnj } 2962618Swnj out: 2976347Swnj return; 2982618Swnj } 2992618Swnj 3002618Swnj rkstart(um) 3012981Swnj register struct uba_ctlr *um; 3021899Swnj { 3032618Swnj register struct buf *bp, *dp; 3042981Swnj register struct uba_device *ui; 3052618Swnj register struct rkdevice *rkaddr; 3062618Swnj struct rkst *st; 3071899Swnj daddr_t bn; 3082618Swnj int sn, tn, cmd; 3091899Swnj 3102618Swnj loop: 3112618Swnj if ((dp = um->um_tab.b_actf) == NULL) 3126347Swnj return; 3132618Swnj if ((bp = dp->b_actf) == NULL) { 3142618Swnj um->um_tab.b_actf = dp->b_forw; 3152618Swnj goto loop; 3161899Swnj } 3172618Swnj um->um_tab.b_active++; 3182618Swnj ui = rkdinfo[dkunit(bp)]; 3192618Swnj bn = dkblock(bp); 3202618Swnj st = &rkst[ui->ui_type]; 3212618Swnj sn = bn%st->nspc; 3222618Swnj tn = sn/st->nsect; 3232618Swnj sn %= st->nsect; 3242618Swnj rkaddr = (struct rkdevice *)ui->ui_addr; 3252957Swnj retry: 3263709Sroot rkaddr->rkcs1 = RK_CCLR; 3272618Swnj rkaddr->rkcs2 = ui->ui_slave; 3283709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO; 3292618Swnj rkwait(rkaddr); 3303293Swnj if ((rkaddr->rkds&RKDS_SVAL) == 0) { 3312957Swnj rknosval++; 3322957Swnj goto nosval; 3332894Swnj } 3343293Swnj if (rkaddr->rkds&RKDS_PIP) { 3352957Swnj rkpip++; 3362957Swnj goto retry; 3372957Swnj } 3383293Swnj if ((rkaddr->rkds&RKDS_DREADY) != RKDS_DREADY) { 3392927Swnj printf("rk%d: not ready", dkunit(bp)); 3403293Swnj if ((rkaddr->rkds&RKDS_DREADY) != RKDS_DREADY) { 3412894Swnj printf("\n"); 3423709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO; 3432894Swnj rkwait(rkaddr); 3443709Sroot rkaddr->rkcs1 = RK_CCLR; 3452894Swnj rkwait(rkaddr); 3462894Swnj um->um_tab.b_active = 0; 3472894Swnj um->um_tab.b_errcnt = 0; 3482894Swnj dp->b_actf = bp->av_forw; 3492894Swnj dp->b_active = 0; 3502894Swnj bp->b_flags |= B_ERROR; 3512894Swnj iodone(bp); 3522894Swnj goto loop; 3532894Swnj } 3542894Swnj printf(" (came back!)\n"); 3552894Swnj } 3562957Swnj nosval: 3572618Swnj rkaddr->rkcyl = bp->b_cylin; 3582618Swnj rkcyl[ui->ui_unit] = bp->b_cylin; 3592618Swnj rkaddr->rkda = (tn << 8) + sn; 3602618Swnj rkaddr->rkwc = -bp->b_bcount / sizeof (short); 3612618Swnj if (bp->b_flags & B_READ) 3623709Sroot cmd = rktypes[ui->ui_type]|RK_IE|RK_READ|RK_GO; 3632618Swnj else 3643709Sroot cmd = rktypes[ui->ui_type]|RK_IE|RK_WRITE|RK_GO; 3652618Swnj um->um_cmd = cmd; 3663104Swnj (void) ubago(ui); 3671899Swnj } 3681899Swnj 3692618Swnj rkdgo(um) 3702981Swnj register struct uba_ctlr *um; 3711899Swnj { 3722618Swnj register struct rkdevice *rkaddr = (struct rkdevice *)um->um_addr; 3731899Swnj 3747031Swnj um->um_tab.b_active = 2; /* should now be 2 */ 3752618Swnj rkaddr->rkba = um->um_ubinfo; 3762618Swnj rkaddr->rkcs1 = um->um_cmd|((um->um_ubinfo>>8)&0x300); 3772618Swnj } 3782618Swnj 3792710Swnj rkintr(rk11) 3802618Swnj int rk11; 3812618Swnj { 3822981Swnj register struct uba_ctlr *um = rkminfo[rk11]; 3832981Swnj register struct uba_device *ui; 3842618Swnj register struct rkdevice *rkaddr = (struct rkdevice *)um->um_addr; 3852618Swnj register struct buf *bp, *dp; 3862618Swnj int unit; 3872618Swnj struct rk_softc *sc = &rk_softc[um->um_ctlr]; 3882618Swnj int as = (rkaddr->rkatt >> 8) | sc->sc_softas; 3892618Swnj 3902618Swnj sc->sc_wticks = 0; 3912618Swnj sc->sc_softas = 0; 3926347Swnj if (um->um_tab.b_active == 2 || sc->sc_recal) { 3937031Swnj um->um_tab.b_active = 1; 3942618Swnj dp = um->um_tab.b_actf; 3952618Swnj bp = dp->b_actf; 3962618Swnj ui = rkdinfo[dkunit(bp)]; 3972618Swnj dk_busy &= ~(1 << ui->ui_dk); 3983709Sroot if (bp->b_flags&B_BAD) 3993709Sroot if (rkecc(ui, CONT)) 4003709Sroot return; 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) { 4263709Sroot if (rkecc(ui, BSE)) 4273709Sroot return; 4283709Sroot else 4293709Sroot goto hard; 4307182Sroot } else { 4317182Sroot if ((er & (RKER_DCK|RKER_ECH)) == RKER_DCK) { 4327182Sroot if (rkecc(ui, ECC)) 4337182Sroot return; 4347182Sroot } else 4357182Sroot um->um_tab.b_active = 0; 4367182Sroot } 4373293Swnj if (cs2&RKCS2_MDS) { 4383293Swnj rkaddr->rkcs2 = RKCS2_SCLR; 4392618Swnj goto retry; 4401899Swnj } 4412618Swnj recal = 0; 4423293Swnj if (ds&RKDS_DROT || er&(RKER_OPI|RKER_SKI|RKER_UNS) || 4432618Swnj (um->um_tab.b_errcnt&07) == 4) 4442618Swnj recal = 1; 4453709Sroot rkaddr->rkcs1 = RK_CCLR; 4462618Swnj rkaddr->rkcs2 = ui->ui_slave; 4473709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO; 4482618Swnj rkwait(rkaddr); 4492618Swnj if (recal && um->um_tab.b_active == 0) { 4503709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_IE|RK_RECAL|RK_GO; 4512618Swnj rkcyl[ui->ui_unit] = -1; 4522957Swnj sc->sc_recal = 0; 4532957Swnj goto nextrecal; 4542618Swnj } 4551899Swnj } 4562618Swnj retry: 4572957Swnj switch (sc->sc_recal) { 4582957Swnj 4592957Swnj case 1: 4602957Swnj rkaddr->rkcyl = bp->b_cylin; 4612957Swnj rkcyl[ui->ui_unit] = bp->b_cylin; 4623709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_IE|RK_SEEK|RK_GO; 4632957Swnj goto nextrecal; 4642957Swnj case 2: 4652957Swnj if (um->um_tab.b_errcnt < 16 || 4663290Swnj (bp->b_flags&B_READ) == 0) 4673159Swnj goto donerecal; 4682957Swnj rkaddr->rkatt = rk_offset[um->um_tab.b_errcnt & 017]; 4693709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_IE|RK_OFFSET|RK_GO; 4702957Swnj /* fall into ... */ 4712957Swnj nextrecal: 4722957Swnj sc->sc_recal++; 4732957Swnj rkwait(rkaddr); 4742957Swnj um->um_tab.b_active = 1; 4752957Swnj return; 4763159Swnj donerecal: 4772957Swnj case 3: 4782618Swnj sc->sc_recal = 0; 4792618Swnj um->um_tab.b_active = 0; 4802957Swnj break; 4811899Swnj } 4823709Sroot ubadone(um); 4832618Swnj if (um->um_tab.b_active) { 4842618Swnj um->um_tab.b_active = 0; 4852618Swnj um->um_tab.b_errcnt = 0; 4862618Swnj um->um_tab.b_actf = dp->b_forw; 4872618Swnj dp->b_active = 0; 4882618Swnj dp->b_errcnt = 0; 4892618Swnj dp->b_actf = bp->av_forw; 4902618Swnj bp->b_resid = -rkaddr->rkwc * sizeof(short); 4912618Swnj iodone(bp); 4922618Swnj if (dp->b_actf) 4936347Swnj rkustart(ui); 4941899Swnj } 4952618Swnj as &= ~(1<<ui->ui_slave); 4961899Swnj } 4972618Swnj for (unit = 0; as; as >>= 1, unit++) 4982981Swnj if (as & 1) { 4992981Swnj ui = rkip[rk11][unit]; 5002981Swnj if (ui) { 5016347Swnj rkustart(rkip[rk11][unit]); 5022981Swnj } else { 5033709Sroot rkaddr->rkcs1 = RK_CCLR; 5042981Swnj rkaddr->rkcs2 = unit; 5053709Sroot rkaddr->rkcs1 = RK_DCLR|RK_GO; 5062981Swnj rkwait(rkaddr); 5073709Sroot rkaddr->rkcs1 = RK_CCLR; 5082981Swnj } 5092981Swnj } 5102618Swnj if (um->um_tab.b_actf && um->um_tab.b_active == 0) 5116347Swnj rkstart(um); 5128609Sroot if (((rkaddr->rkcs1) & RK_IE) == 0) 5133709Sroot rkaddr->rkcs1 = RK_IE; 5141899Swnj } 5151899Swnj 5162618Swnj rkwait(addr) 5172618Swnj register struct rkdevice *addr; 5182618Swnj { 5191899Swnj 5202618Swnj while ((addr->rkcs1 & RK_CRDY) == 0) 5212618Swnj ; 5222618Swnj } 5232618Swnj 5247731Sroot rkread(dev, uio) 5252618Swnj dev_t dev; 5267731Sroot struct uio *uio; 5271899Swnj { 5282618Swnj register int unit = minor(dev) >> 3; 5292618Swnj 5302648Swnj if (unit >= NRK) 5318162Sroot return (ENXIO); 5328162Sroot return (physio(rkstrategy, &rrkbuf[unit], dev, B_READ, minphys, uio)); 5331899Swnj } 5341899Swnj 5357836Sroot rkwrite(dev, uio) 5362618Swnj dev_t dev; 5377836Sroot struct uio *uio; 5381899Swnj { 5392618Swnj register int unit = minor(dev) >> 3; 5401899Swnj 5412648Swnj if (unit >= NRK) 5428493Sroot return (ENXIO); 5438493Sroot return (physio(rkstrategy, &rrkbuf[unit], dev, B_WRITE, minphys, uio)); 5441899Swnj } 5451899Swnj 5463709Sroot rkecc(ui, flag) 5472981Swnj register struct uba_device *ui; 5481899Swnj { 5492618Swnj register struct rkdevice *rk = (struct rkdevice *)ui->ui_addr; 5502618Swnj register struct buf *bp = rkutab[ui->ui_unit].b_actf; 5512981Swnj register struct uba_ctlr *um = ui->ui_mi; 5522618Swnj register struct rkst *st; 5532618Swnj struct uba_regs *ubp = ui->ui_hd->uh_uba; 5542618Swnj caddr_t addr; 5553709Sroot int reg, npf, o, cmd, ubaddr; 5562618Swnj int bn, cn, tn, sn; 5571899Swnj 5583709Sroot if (flag == CONT) 5593709Sroot npf = bp->b_error; 5603709Sroot else 5613709Sroot npf = btop((rk->rkwc * sizeof(short)) + bp->b_bcount); 5622618Swnj reg = btop(um->um_ubinfo&0x3ffff) + npf; 5632618Swnj o = (int)bp->b_un.b_addr & PGOFSET; 5642618Swnj bn = dkblock(bp); 5652618Swnj st = &rkst[ui->ui_type]; 5662618Swnj cn = bp->b_cylin; 5673709Sroot sn = bn%st->nspc + npf; 5682618Swnj tn = sn/st->nsect; 5692618Swnj sn %= st->nsect; 5702618Swnj cn += tn/st->ntrak; 5712618Swnj tn %= st->ntrak; 5723709Sroot ubapurge(um); 5733709Sroot switch (flag) { 5743709Sroot case ECC: 5753709Sroot { 5763709Sroot register int i; 5773709Sroot int bit, byte, mask; 5783709Sroot 5793709Sroot npf--; 5803709Sroot reg--; 58118315Sralph log(KERN_RECOV, "rk%d%c: soft ecc sn%d\n", dkunit(bp), 5823709Sroot 'a'+(minor(bp->b_dev)&07), bp->b_blkno + npf); 5833709Sroot mask = rk->rkec2; 5843709Sroot i = rk->rkec1 - 1; /* -1 makes 0 origin */ 5853709Sroot bit = i&07; 5863709Sroot i = (i&~07)>>3; 5873709Sroot byte = i + o; 5883709Sroot while (i < 512 && (int)ptob(npf)+i < bp->b_bcount && bit > -11) { 5893709Sroot addr = ptob(ubp->uba_map[reg+btop(byte)].pg_pfnum)+ 5903709Sroot (byte & PGOFSET); 5913709Sroot putmemc(addr, getmemc(addr)^(mask<<bit)); 5923709Sroot byte++; 5933709Sroot i++; 5943709Sroot bit -= 8; 5953709Sroot } 5967182Sroot if (rk->rkwc == 0) { 5977182Sroot um->um_tab.b_active = 0; 5983709Sroot return (0); 5997182Sroot } 6003709Sroot npf++; 6013709Sroot reg++; 6023709Sroot break; 6033709Sroot } 6043709Sroot 6053709Sroot case BSE: 6063709Sroot #ifdef RKBDEBUG 6073709Sroot if (rkbdebug) 6083709Sroot printf("rkecc, BSE: bn %d cn %d tn %d sn %d\n", bn, cn, tn, sn); 6093709Sroot #endif 6103709Sroot if ((bn = isbad(&rkbad[ui->ui_unit], cn, tn, sn)) < 0) 6113709Sroot return(0); 6123709Sroot bp->b_flags |= B_BAD; 6133709Sroot bp->b_error = npf + 1; 6143709Sroot bn = st->ncyl*st->nspc - st->nsect - 1 - bn; 6153709Sroot cn = bn/st->nspc; 6163709Sroot sn = bn%st->nspc; 6173709Sroot tn = sn/st->nsect; 6183709Sroot sn %= st->nsect; 6193709Sroot #ifdef RKBDEBUG 6203709Sroot if (rkbdebug) 6213709Sroot printf("revector to cn %d tn %d sn %d\n", cn, tn, sn); 6223709Sroot #endif 6233709Sroot rk->rkwc = -(512 / sizeof (short)); 6243709Sroot break; 6253709Sroot 6263709Sroot case CONT: 6273709Sroot #ifdef RKBDEBUG 6283709Sroot if (rkbdebug) 6293709Sroot printf("rkecc, CONT: bn %d cn %d tn %d sn %d\n", bn,cn,tn,sn); 6303709Sroot #endif 6313709Sroot bp->b_flags &= ~B_BAD; 6323709Sroot rk->rkwc = -((bp->b_bcount - (int)ptob(npf)) / sizeof (short)); 63315213Skarels if (rk->rkwc == 0) 6347182Sroot return (0); 6353709Sroot break; 6363709Sroot } 6373709Sroot rk->rkcs1 = RK_CCLR; 6383709Sroot rk->rkcs2 = ui->ui_slave; 6393709Sroot rk->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO; 6403709Sroot rkwait(rk); 6412618Swnj rk->rkcyl = cn; 6422618Swnj rk->rkda = (tn << 8) | sn; 6433709Sroot ubaddr = (int)ptob(reg) + o; 6442618Swnj rk->rkba = ubaddr; 6453709Sroot cmd = (bp->b_flags&B_READ ? RK_READ : RK_WRITE)|RK_IE|RK_GO; 6463709Sroot cmd |= (ubaddr >> 8) & 0x300; 6473709Sroot cmd |= rktypes[ui->ui_type]; 6482618Swnj rk->rkcs1 = cmd; 6497031Swnj um->um_tab.b_active = 2; /* continuing */ 6503709Sroot um->um_tab.b_errcnt = 0; /* error has been corrected */ 6512618Swnj return (1); 6521899Swnj } 6531899Swnj 6542618Swnj rkreset(uban) 6552927Swnj int uban; 6561899Swnj { 6572981Swnj register struct uba_ctlr *um; 6582981Swnj register struct uba_device *ui; 6592618Swnj register rk11, unit; 6601899Swnj 6612648Swnj for (rk11 = 0; rk11 < NHK; rk11++) { 6622618Swnj if ((um = rkminfo[rk11]) == 0 || um->um_ubanum != uban || 6632618Swnj um->um_alive == 0) 6642618Swnj continue; 6652927Swnj printf(" hk%d", rk11); 6662618Swnj um->um_tab.b_active = 0; 6672618Swnj um->um_tab.b_actf = um->um_tab.b_actl = 0; 6682618Swnj rk_softc[um->um_ctlr].sc_recal = 0; 6696347Swnj rk_softc[um->um_ctlr].sc_wticks = 0; 6702618Swnj if (um->um_ubinfo) { 6712618Swnj printf("<%d>", (um->um_ubinfo>>28)&0xf); 6729354Ssam um->um_ubinfo = 0; 6732618Swnj } 6744039Swnj for (unit = 0; unit < NRK; unit++) { 6752618Swnj if ((ui = rkdinfo[unit]) == 0) 6762618Swnj continue; 6774039Swnj if (ui->ui_alive == 0 || ui->ui_mi != um) 6782618Swnj continue; 6792618Swnj rkutab[unit].b_active = 0; 6802618Swnj (void) rkustart(ui); 6812618Swnj } 6822618Swnj (void) rkstart(um); 6832618Swnj } 6841899Swnj } 6852380Swnj 6862618Swnj rkwatch() 6872380Swnj { 6882981Swnj register struct uba_ctlr *um; 6892618Swnj register rk11, unit; 6902618Swnj register struct rk_softc *sc; 6912380Swnj 6922758Swnj timeout(rkwatch, (caddr_t)0, hz); 6932648Swnj for (rk11 = 0; rk11 < NHK; rk11++) { 6942618Swnj um = rkminfo[rk11]; 6952618Swnj if (um == 0 || um->um_alive == 0) 6962618Swnj continue; 6972618Swnj sc = &rk_softc[rk11]; 6982618Swnj if (um->um_tab.b_active == 0) { 6992648Swnj for (unit = 0; unit < NRK; unit++) 7002622Swnj if (rkutab[unit].b_active && 7012622Swnj rkdinfo[unit]->ui_mi == um) 7022618Swnj goto active; 7032618Swnj sc->sc_wticks = 0; 7042618Swnj continue; 7052618Swnj } 7062618Swnj active: 7072618Swnj sc->sc_wticks++; 7082618Swnj if (sc->sc_wticks >= 20) { 7092618Swnj sc->sc_wticks = 0; 7102927Swnj printf("hk%d: lost interrupt\n", rk11); 7112648Swnj ubareset(um->um_ubanum); 7122618Swnj } 7132618Swnj } 7142380Swnj } 7152618Swnj 7162618Swnj #define DBSIZE 20 7172618Swnj 7182618Swnj rkdump(dev) 7192618Swnj dev_t dev; 7202618Swnj { 7212618Swnj struct rkdevice *rkaddr; 7222618Swnj char *start; 7232618Swnj int num, blk, unit; 7242618Swnj struct size *sizes; 7252618Swnj register struct uba_regs *uba; 7262981Swnj register struct uba_device *ui; 7272618Swnj register short *rp; 7282618Swnj struct rkst *st; 7292618Swnj 7302618Swnj unit = minor(dev) >> 3; 7312885Swnj if (unit >= NRK) 7322885Swnj return (ENXIO); 7332618Swnj #define phys(cast, addr) ((cast)((int)addr & 0x7fffffff)) 7342981Swnj ui = phys(struct uba_device *, rkdinfo[unit]); 7352885Swnj if (ui->ui_alive == 0) 7362885Swnj return (ENXIO); 7372618Swnj uba = phys(struct uba_hd *, ui->ui_hd)->uh_physuba; 7383329Swnj ubainit(uba); 7392618Swnj rkaddr = (struct rkdevice *)ui->ui_physaddr; 7402618Swnj num = maxfree; 7412618Swnj start = 0; 7423709Sroot rkaddr->rkcs1 = RK_CCLR; 7432618Swnj rkaddr->rkcs2 = unit; 7443709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO; 7452618Swnj rkwait(rkaddr); 7463293Swnj if ((rkaddr->rkds & RKDS_VV) == 0) { 7473709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_IE|RK_PACK|RK_GO; 7482618Swnj rkwait(rkaddr); 7492618Swnj } 7502618Swnj st = &rkst[ui->ui_type]; 7512618Swnj sizes = phys(struct size *, st->sizes); 752*24210Sbloom if (dumplo < 0) 7532885Swnj return (EINVAL); 754*24210Sbloom if (dumplo + num >= sizes[minor(dev)&07].nblocks) 755*24210Sbloom num = sizes[minor(dev)&07].nblocks - dumplo; 7562618Swnj while (num > 0) { 7572618Swnj register struct pte *io; 7582618Swnj register int i; 7592618Swnj int cn, sn, tn; 7602618Swnj daddr_t bn; 7612618Swnj 7622618Swnj blk = num > DBSIZE ? DBSIZE : num; 7632618Swnj io = uba->uba_map; 7642618Swnj for (i = 0; i < blk; i++) 7652981Swnj *(int *)io++ = (btop(start)+i) | (1<<21) | UBAMR_MRV; 7662618Swnj *(int *)io = 0; 7672618Swnj bn = dumplo + btop(start); 7682618Swnj cn = bn/st->nspc + sizes[minor(dev)&07].cyloff; 7692618Swnj sn = bn%st->nspc; 7702618Swnj tn = sn/st->nsect; 7712618Swnj sn = sn%st->nsect; 7722618Swnj rkaddr->rkcyl = cn; 7732618Swnj rp = (short *) &rkaddr->rkda; 7742618Swnj *rp = (tn << 8) + sn; 7752618Swnj *--rp = 0; 7762618Swnj *--rp = -blk*NBPG / sizeof (short); 7773709Sroot *--rp = rktypes[ui->ui_type]|RK_GO|RK_WRITE; 7782618Swnj rkwait(rkaddr); 7792885Swnj if (rkaddr->rkcs1 & RK_CERR) 7802885Swnj return (EIO); 7812618Swnj start += blk*NBPG; 7822618Swnj num -= blk; 7832618Swnj } 7842618Swnj return (0); 7852618Swnj } 78612503Ssam 78712503Ssam rksize(dev) 78812503Ssam dev_t dev; 78912503Ssam { 79012503Ssam int unit = minor(dev) >> 3; 79112503Ssam struct uba_device *ui; 79212503Ssam struct rkst *st; 79312503Ssam 79412503Ssam if (unit >= NRK || (ui = rkdinfo[unit]) == 0 || ui->ui_alive == 0) 79512503Ssam return (-1); 79612503Ssam st = &rkst[ui->ui_type]; 79712503Ssam return (st->sizes[minor(dev) & 07].nblocks); 79812503Ssam } 7992618Swnj #endif 800