123336Smckusick /*
229236Smckusick * Copyright (c) 1982, 1986 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*45805Sbostic * @(#)rk.c 7.9 (Berkeley) 12/16/90
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 */
27*45805Sbostic #include "../include/pte.h"
289777Ssam
29*45805Sbostic #include "sys/param.h"
30*45805Sbostic #include "sys/systm.h"
31*45805Sbostic #include "sys/buf.h"
32*45805Sbostic #include "sys/conf.h"
33*45805Sbostic #include "sys/user.h"
34*45805Sbostic #include "sys/map.h"
35*45805Sbostic #include "sys/vm.h"
36*45805Sbostic #include "sys/dkstat.h"
37*45805Sbostic #include "sys/cmap.h"
38*45805Sbostic #include "sys/dkbad.h"
39*45805Sbostic #include "sys/ioctl.h"
40*45805Sbostic #include "sys/disklabel.h"
41*45805Sbostic #include "sys/uio.h"
42*45805Sbostic #include "sys/kernel.h"
43*45805Sbostic #include "sys/syslog.h"
441899Swnj
45*45805Sbostic #include "../include/cpu.h"
4617076Sbloom #include "ubareg.h"
4717076Sbloom #include "ubavar.h"
4817076Sbloom #include "rkreg.h"
491899Swnj
502618Swnj struct rk_softc {
512618Swnj int sc_softas;
522618Swnj int sc_ndrive;
532618Swnj int sc_wticks;
542618Swnj int sc_recal;
552648Swnj } rk_softc[NHK];
561899Swnj
5724740Sbloom #define rkunit(dev) (minor(dev) >> 3)
5824740Sbloom
592618Swnj /* THIS SHOULD BE READ OFF THE PACK, PER DRIVE */
602787Swnj struct size {
612618Swnj daddr_t nblocks;
622618Swnj int cyloff;
6325322Smckusick } rk7_sizes[8] = {
642618Swnj 15884, 0, /* A=cyl 0 thru 240 */
652665Swnj 10032, 241, /* B=cyl 241 thru 392 */
662665Swnj 53790, 0, /* C=cyl 0 thru 814 */
6725322Smckusick 15884, 393, /* D=cyl 393 thru 633 */
682618Swnj 0, 0,
6925322Smckusick 11792, 634, /* F=cyl 634 thru 814 */
7025322Smckusick 27786, 393, /* G=cyl 393 thru 814, should be 27698 */
712618Swnj 0, 0,
723709Sroot }, rk6_sizes[8] ={
733709Sroot 15884, 0, /* A=cyl 0 thru 240 */
743709Sroot 11154, 241, /* B=cyl 241 thru 409 */
753709Sroot 27126, 0, /* C=cyl 0 thru 410 */
763709Sroot 0, 0,
773709Sroot 0, 0,
783709Sroot 0, 0,
793709Sroot 0, 0,
803709Sroot 0, 0,
812618Swnj };
822618Swnj /* END OF STUFF WHICH SHOULD BE READ IN PER DISK */
831899Swnj
843709Sroot short rktypes[] = { RK_CDT, 0 };
853709Sroot
862618Swnj int rkprobe(), rkslave(), rkattach(), rkdgo(), rkintr();
872981Swnj struct uba_ctlr *rkminfo[NHK];
882981Swnj struct uba_device *rkdinfo[NRK];
892981Swnj struct uba_device *rkip[NHK][4];
901899Swnj
912618Swnj u_short rkstd[] = { 0777440, 0 };
922618Swnj struct uba_driver hkdriver =
932622Swnj { rkprobe, rkslave, rkattach, rkdgo, rkstd, "rk", rkdinfo, "hk", rkminfo, 1 };
942648Swnj struct buf rkutab[NRK];
952648Swnj short rkcyl[NRK];
963709Sroot struct dkbad rkbad[NRK];
973709Sroot struct buf brkbuf[NRK];
981899Swnj
992618Swnj struct rkst {
1002618Swnj short nsect;
1012618Swnj short ntrak;
1022618Swnj short nspc;
1032618Swnj short ncyl;
1042618Swnj struct size *sizes;
1052618Swnj } rkst[] = {
1062618Swnj NRKSECT, NRKTRK, NRKSECT*NRKTRK, NRK7CYL, rk7_sizes,
1073709Sroot NRKSECT, NRKTRK, NRKSECT*NRKTRK, NRK6CYL, rk6_sizes,
1082618Swnj };
1091899Swnj
1102618Swnj u_char rk_offset[16] =
1113293Swnj { RKAS_P400,RKAS_M400,RKAS_P400,RKAS_M400,RKAS_P800,RKAS_M800,RKAS_P800,
1123293Swnj RKAS_M800,RKAS_P1200,RKAS_M1200,RKAS_P1200,RKAS_M1200,0,0,0,0
1133293Swnj };
1141899Swnj
1152618Swnj #define b_cylin b_resid
1162618Swnj
1172618Swnj int rkwstart, rkwatch();
1182618Swnj
rkprobe(reg)1192618Swnj rkprobe(reg)
1202618Swnj caddr_t reg;
1211899Swnj {
1222618Swnj register int br, cvec;
1231899Swnj
1242618Swnj #ifdef lint
1252618Swnj br = 0; cvec = br; br = cvec;
1264935Swnj rkintr(0);
1272618Swnj #endif
1282618Swnj ((struct rkdevice *)reg)->rkcs1 = RK_CDT|RK_IE|RK_CRDY;
1292618Swnj DELAY(10);
1302618Swnj ((struct rkdevice *)reg)->rkcs1 = RK_CDT;
1317416Skre return (sizeof (struct rkdevice));
1322618Swnj }
1331899Swnj
1342618Swnj rkslave(ui, reg)
1352981Swnj struct uba_device *ui;
1362618Swnj caddr_t reg;
1372618Swnj {
1382618Swnj register struct rkdevice *rkaddr = (struct rkdevice *)reg;
1391899Swnj
1403709Sroot ui->ui_type = 0;
1413709Sroot rkaddr->rkcs1 = RK_CCLR;
1422618Swnj rkaddr->rkcs2 = ui->ui_slave;
1432957Swnj rkaddr->rkcs1 = RK_CDT|RK_DCLR|RK_GO;
1442622Swnj rkwait(rkaddr);
1452894Swnj DELAY(50);
1463293Swnj if (rkaddr->rkcs2&RKCS2_NED || (rkaddr->rkds&RKDS_SVAL) == 0) {
1473709Sroot rkaddr->rkcs1 = RK_CCLR;
1482618Swnj return (0);
1492618Swnj }
1503709Sroot if (rkaddr->rkcs1&RK_CERR && rkaddr->rker&RKER_DTYE) {
1513709Sroot ui->ui_type = 1;
1523709Sroot rkaddr->rkcs1 = RK_CCLR;
1533709Sroot }
1542618Swnj return (1);
1552618Swnj }
1562618Swnj
rkattach(ui)1572618Swnj rkattach(ui)
1582981Swnj register struct uba_device *ui;
1592618Swnj {
1602618Swnj
1612618Swnj if (rkwstart == 0) {
1622758Swnj timeout(rkwatch, (caddr_t)0, hz);
1632618Swnj rkwstart++;
1642618Swnj }
1652618Swnj if (ui->ui_dk >= 0)
16638174Smckusick dk_wpms[ui->ui_dk] = (60 * NRKSECT * 256);
1672618Swnj rkip[ui->ui_ctlr][ui->ui_slave] = ui;
1682618Swnj rk_softc[ui->ui_ctlr].sc_ndrive++;
1692618Swnj rkcyl[ui->ui_unit] = -1;
1703709Sroot ui->ui_flags = 0;
1712618Swnj }
1722618Swnj
rkopen(dev)1738573Sroot rkopen(dev)
1748573Sroot dev_t dev;
1758573Sroot {
17624785Skarels register int unit = rkunit(dev);
1778573Sroot register struct uba_device *ui;
1788573Sroot
1798573Sroot if (unit >= NRK || (ui = rkdinfo[unit]) == 0 || ui->ui_alive == 0)
1808573Sroot return (ENXIO);
1818573Sroot return (0);
1828573Sroot }
1838573Sroot
rkstrategy(bp)1841899Swnj rkstrategy(bp)
1852618Swnj register struct buf *bp;
1861899Swnj {
1872981Swnj register struct uba_device *ui;
1882618Swnj register struct rkst *st;
1892618Swnj register int unit;
1902618Swnj register struct buf *dp;
1912618Swnj int xunit = minor(bp->b_dev) & 07;
1922618Swnj long bn, sz;
1935433Sroot int s;
1941899Swnj
1952618Swnj sz = (bp->b_bcount+511) >> 9;
19624740Sbloom unit = rkunit(bp->b_dev);
19724740Sbloom if (unit >= NRK) {
19824740Sbloom bp->b_error = ENXIO;
1992618Swnj goto bad;
20024740Sbloom }
2012618Swnj ui = rkdinfo[unit];
20224740Sbloom if (ui == 0 || ui->ui_alive == 0) {
20324740Sbloom bp->b_error = ENXIO;
2042618Swnj goto bad;
20524740Sbloom }
2062618Swnj st = &rkst[ui->ui_type];
2072618Swnj if (bp->b_blkno < 0 ||
20824740Sbloom (bn = bp->b_blkno)+sz > st->sizes[xunit].nblocks) {
20924785Skarels if (bp->b_blkno == st->sizes[xunit].nblocks) {
21024785Skarels bp->b_resid = bp->b_bcount;
21124740Sbloom goto done;
21224785Skarels }
21324740Sbloom bp->b_error = EINVAL;
2142618Swnj goto bad;
21524740Sbloom }
2162618Swnj bp->b_cylin = bn/st->nspc + st->sizes[xunit].cyloff;
2175433Sroot s = spl5();
2182618Swnj dp = &rkutab[ui->ui_unit];
2192618Swnj disksort(dp, bp);
2202618Swnj if (dp->b_active == 0) {
2212618Swnj (void) rkustart(ui);
2222618Swnj bp = &ui->ui_mi->um_tab;
2232618Swnj if (bp->b_actf && bp->b_active == 0)
2242618Swnj (void) rkstart(ui->ui_mi);
2251899Swnj }
2265433Sroot splx(s);
2272618Swnj return;
2282618Swnj
2292618Swnj bad:
2302618Swnj bp->b_flags |= B_ERROR;
23124740Sbloom done:
2322618Swnj iodone(bp);
2332618Swnj return;
2341899Swnj }
2351899Swnj
rkustart(ui)2362618Swnj rkustart(ui)
2372981Swnj register struct uba_device *ui;
2382618Swnj {
2392618Swnj register struct buf *bp, *dp;
2402981Swnj register struct uba_ctlr *um;
2412618Swnj register struct rkdevice *rkaddr;
2421899Swnj
2432618Swnj if (ui == 0)
2446347Swnj return;
2452618Swnj dk_busy &= ~(1<<ui->ui_dk);
2462618Swnj dp = &rkutab[ui->ui_unit];
2472618Swnj um = ui->ui_mi;
2482894Swnj rkaddr = (struct rkdevice *)um->um_addr;
2492618Swnj if (um->um_tab.b_active) {
2502618Swnj rk_softc[um->um_ctlr].sc_softas |= 1<<ui->ui_slave;
2516347Swnj return;
2522618Swnj }
2536347Swnj if ((bp = dp->b_actf) == NULL)
2546347Swnj return;
2553709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_CERR;
2562618Swnj rkaddr->rkcs2 = ui->ui_slave;
2573709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO;
2582618Swnj rkwait(rkaddr);
2593709Sroot if ((rkaddr->rkds & RKDS_VV) == 0 || ui->ui_flags == 0) {
2602618Swnj /* SHOULD WARN SYSTEM THAT THIS HAPPENED */
2613709Sroot struct rkst *st = &rkst[ui->ui_type];
2623709Sroot struct buf *bbp = &brkbuf[ui->ui_unit];
2633709Sroot
2643709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_PACK|RK_GO;
2653709Sroot ui->ui_flags = 1;
2663709Sroot bbp->b_flags = B_READ|B_BUSY;
2673709Sroot bbp->b_dev = bp->b_dev;
2683709Sroot bbp->b_bcount = 512;
2693709Sroot bbp->b_un.b_addr = (caddr_t)&rkbad[ui->ui_unit];
2703709Sroot bbp->b_blkno = st->ncyl*st->nspc - st->nsect;
2713709Sroot bbp->b_cylin = st->ncyl - 1;
2723709Sroot dp->b_actf = bbp;
2733709Sroot bbp->av_forw = bp;
2743709Sroot bp = bbp;
2752618Swnj rkwait(rkaddr);
2762618Swnj }
2772903Swnj if (dp->b_active)
2782903Swnj goto done;
2792903Swnj dp->b_active = 1;
2803293Swnj if ((rkaddr->rkds & RKDS_DREADY) != RKDS_DREADY)
2812894Swnj goto done;
2822618Swnj if (rk_softc[um->um_ctlr].sc_ndrive == 1)
2832618Swnj goto done;
2842618Swnj if (bp->b_cylin == rkcyl[ui->ui_unit])
2852618Swnj goto done;
2862618Swnj rkaddr->rkcyl = bp->b_cylin;
2872618Swnj rkcyl[ui->ui_unit] = bp->b_cylin;
2883709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_IE|RK_SEEK|RK_GO;
2892618Swnj if (ui->ui_dk >= 0) {
2902618Swnj dk_busy |= 1<<ui->ui_dk;
2912618Swnj dk_seek[ui->ui_dk]++;
2922618Swnj }
2932618Swnj goto out;
2942618Swnj done:
2952618Swnj if (dp->b_active != 2) {
2962618Swnj dp->b_forw = NULL;
2972618Swnj if (um->um_tab.b_actf == NULL)
2982618Swnj um->um_tab.b_actf = dp;
2992618Swnj else
3002618Swnj um->um_tab.b_actl->b_forw = dp;
3012618Swnj um->um_tab.b_actl = dp;
3022618Swnj dp->b_active = 2;
3032618Swnj }
3042618Swnj out:
3056347Swnj return;
3062618Swnj }
3072618Swnj
rkstart(um)3082618Swnj rkstart(um)
3092981Swnj register struct uba_ctlr *um;
3101899Swnj {
3112618Swnj register struct buf *bp, *dp;
3122981Swnj register struct uba_device *ui;
3132618Swnj register struct rkdevice *rkaddr;
3142618Swnj struct rkst *st;
3151899Swnj daddr_t bn;
3162618Swnj int sn, tn, cmd;
3171899Swnj
3182618Swnj loop:
3192618Swnj if ((dp = um->um_tab.b_actf) == NULL)
3206347Swnj return;
3212618Swnj if ((bp = dp->b_actf) == NULL) {
3222618Swnj um->um_tab.b_actf = dp->b_forw;
3232618Swnj goto loop;
3241899Swnj }
3252618Swnj um->um_tab.b_active++;
32624740Sbloom ui = rkdinfo[rkunit(bp->b_dev)];
32724740Sbloom bn = bp->b_blkno;
3282618Swnj st = &rkst[ui->ui_type];
3292618Swnj sn = bn%st->nspc;
3302618Swnj tn = sn/st->nsect;
3312618Swnj sn %= st->nsect;
3322618Swnj rkaddr = (struct rkdevice *)ui->ui_addr;
3332957Swnj retry:
3343709Sroot rkaddr->rkcs1 = RK_CCLR;
3352618Swnj rkaddr->rkcs2 = ui->ui_slave;
3363709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO;
3372618Swnj rkwait(rkaddr);
3383293Swnj if ((rkaddr->rkds&RKDS_SVAL) == 0) {
3392957Swnj rknosval++;
3402957Swnj goto nosval;
3412894Swnj }
3423293Swnj if (rkaddr->rkds&RKDS_PIP) {
3432957Swnj rkpip++;
3442957Swnj goto retry;
3452957Swnj }
3463293Swnj if ((rkaddr->rkds&RKDS_DREADY) != RKDS_DREADY) {
34724740Sbloom printf("rk%d: not ready", rkunit(bp->b_dev));
3483293Swnj if ((rkaddr->rkds&RKDS_DREADY) != RKDS_DREADY) {
3492894Swnj printf("\n");
3503709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO;
3512894Swnj rkwait(rkaddr);
3523709Sroot rkaddr->rkcs1 = RK_CCLR;
3532894Swnj rkwait(rkaddr);
3542894Swnj um->um_tab.b_active = 0;
3552894Swnj um->um_tab.b_errcnt = 0;
3562894Swnj dp->b_actf = bp->av_forw;
3572894Swnj dp->b_active = 0;
3582894Swnj bp->b_flags |= B_ERROR;
3592894Swnj iodone(bp);
3602894Swnj goto loop;
3612894Swnj }
3622894Swnj printf(" (came back!)\n");
3632894Swnj }
3642957Swnj nosval:
3652618Swnj rkaddr->rkcyl = bp->b_cylin;
3662618Swnj rkcyl[ui->ui_unit] = bp->b_cylin;
3672618Swnj rkaddr->rkda = (tn << 8) + sn;
3682618Swnj rkaddr->rkwc = -bp->b_bcount / sizeof (short);
3692618Swnj if (bp->b_flags & B_READ)
3703709Sroot cmd = rktypes[ui->ui_type]|RK_IE|RK_READ|RK_GO;
3712618Swnj else
3723709Sroot cmd = rktypes[ui->ui_type]|RK_IE|RK_WRITE|RK_GO;
3732618Swnj um->um_cmd = cmd;
3743104Swnj (void) ubago(ui);
3751899Swnj }
3761899Swnj
rkdgo(um)3772618Swnj rkdgo(um)
3782981Swnj register struct uba_ctlr *um;
3791899Swnj {
3802618Swnj register struct rkdevice *rkaddr = (struct rkdevice *)um->um_addr;
3811899Swnj
3827031Swnj um->um_tab.b_active = 2; /* should now be 2 */
3832618Swnj rkaddr->rkba = um->um_ubinfo;
3842618Swnj rkaddr->rkcs1 = um->um_cmd|((um->um_ubinfo>>8)&0x300);
3852618Swnj }
3862618Swnj
rkintr(rk11)3872710Swnj rkintr(rk11)
3882618Swnj int rk11;
3892618Swnj {
3902981Swnj register struct uba_ctlr *um = rkminfo[rk11];
3912981Swnj register struct uba_device *ui;
3922618Swnj register struct rkdevice *rkaddr = (struct rkdevice *)um->um_addr;
3932618Swnj register struct buf *bp, *dp;
3942618Swnj int unit;
3952618Swnj struct rk_softc *sc = &rk_softc[um->um_ctlr];
3962618Swnj int as = (rkaddr->rkatt >> 8) | sc->sc_softas;
3972618Swnj
3982618Swnj sc->sc_wticks = 0;
3992618Swnj sc->sc_softas = 0;
4006347Swnj if (um->um_tab.b_active == 2 || sc->sc_recal) {
4017031Swnj um->um_tab.b_active = 1;
4022618Swnj dp = um->um_tab.b_actf;
4032618Swnj bp = dp->b_actf;
40424740Sbloom ui = rkdinfo[rkunit(bp->b_dev)];
4052618Swnj dk_busy &= ~(1 << ui->ui_dk);
4063709Sroot if (bp->b_flags&B_BAD)
4073709Sroot if (rkecc(ui, CONT))
4083709Sroot return;
4092618Swnj if (rkaddr->rkcs1 & RK_CERR) {
4102618Swnj int recal;
4112618Swnj u_short ds = rkaddr->rkds;
4122618Swnj u_short cs2 = rkaddr->rkcs2;
4132618Swnj u_short er = rkaddr->rker;
4143709Sroot #ifdef RKDEBUG
4153293Swnj if (rkdebug) {
4163293Swnj printf("cs2=%b ds=%b er=%b\n",
4173293Swnj cs2, RKCS2_BITS, ds,
4183293Swnj RKDS_BITS, er, RKER_BITS);
4193293Swnj }
4203709Sroot #endif
4213293Swnj if (er & RKER_WLE) {
42224740Sbloom printf("rk%d: write locked\n",
42324740Sbloom rkunit(bp->b_dev));
4242685Swnj bp->b_flags |= B_ERROR;
4252685Swnj } else if (++um->um_tab.b_errcnt > 28 ||
4262676Swnj ds&RKDS_HARD || er&RKER_HARD || cs2&RKCS2_HARD) {
4273709Sroot hard:
42834524Skarels diskerr(bp, "rk", "hard error", LOG_PRINTF, -1,
42934524Skarels (struct disklabel *)0);
43034524Skarels printf(" cs2=%b ds=%b er=%b\n",
4312894Swnj cs2, RKCS2_BITS, ds,
4322676Swnj RKDS_BITS, er, RKER_BITS);
4333145Swnj bp->b_flags |= B_ERROR;
4343145Swnj sc->sc_recal = 0;
4353709Sroot } else if (er & RKER_BSE) {
4363709Sroot if (rkecc(ui, BSE))
4373709Sroot return;
4383709Sroot else
4393709Sroot goto hard;
4407182Sroot } else {
4417182Sroot if ((er & (RKER_DCK|RKER_ECH)) == RKER_DCK) {
4427182Sroot if (rkecc(ui, ECC))
4437182Sroot return;
4447182Sroot } else
4457182Sroot um->um_tab.b_active = 0;
4467182Sroot }
4473293Swnj if (cs2&RKCS2_MDS) {
4483293Swnj rkaddr->rkcs2 = RKCS2_SCLR;
4492618Swnj goto retry;
4501899Swnj }
4512618Swnj recal = 0;
4523293Swnj if (ds&RKDS_DROT || er&(RKER_OPI|RKER_SKI|RKER_UNS) ||
4532618Swnj (um->um_tab.b_errcnt&07) == 4)
4542618Swnj recal = 1;
4553709Sroot rkaddr->rkcs1 = RK_CCLR;
4562618Swnj rkaddr->rkcs2 = ui->ui_slave;
4573709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO;
4582618Swnj rkwait(rkaddr);
4592618Swnj if (recal && um->um_tab.b_active == 0) {
4603709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_IE|RK_RECAL|RK_GO;
4612618Swnj rkcyl[ui->ui_unit] = -1;
4622957Swnj sc->sc_recal = 0;
4632957Swnj goto nextrecal;
4642618Swnj }
4651899Swnj }
4662618Swnj retry:
4672957Swnj switch (sc->sc_recal) {
4682957Swnj
4692957Swnj case 1:
4702957Swnj rkaddr->rkcyl = bp->b_cylin;
4712957Swnj rkcyl[ui->ui_unit] = bp->b_cylin;
4723709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_IE|RK_SEEK|RK_GO;
4732957Swnj goto nextrecal;
4742957Swnj case 2:
4752957Swnj if (um->um_tab.b_errcnt < 16 ||
4763290Swnj (bp->b_flags&B_READ) == 0)
4773159Swnj goto donerecal;
4782957Swnj rkaddr->rkatt = rk_offset[um->um_tab.b_errcnt & 017];
4793709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_IE|RK_OFFSET|RK_GO;
4802957Swnj /* fall into ... */
4812957Swnj nextrecal:
4822957Swnj sc->sc_recal++;
4832957Swnj rkwait(rkaddr);
4842957Swnj um->um_tab.b_active = 1;
4852957Swnj return;
4863159Swnj donerecal:
4872957Swnj case 3:
4882618Swnj sc->sc_recal = 0;
4892618Swnj um->um_tab.b_active = 0;
4902957Swnj break;
4911899Swnj }
4923709Sroot ubadone(um);
4932618Swnj if (um->um_tab.b_active) {
4942618Swnj um->um_tab.b_active = 0;
4952618Swnj um->um_tab.b_errcnt = 0;
4962618Swnj um->um_tab.b_actf = dp->b_forw;
4972618Swnj dp->b_active = 0;
4982618Swnj dp->b_errcnt = 0;
4992618Swnj dp->b_actf = bp->av_forw;
5002618Swnj bp->b_resid = -rkaddr->rkwc * sizeof(short);
5012618Swnj iodone(bp);
5022618Swnj if (dp->b_actf)
5036347Swnj rkustart(ui);
5041899Swnj }
5052618Swnj as &= ~(1<<ui->ui_slave);
5061899Swnj }
5072618Swnj for (unit = 0; as; as >>= 1, unit++)
5082981Swnj if (as & 1) {
5092981Swnj ui = rkip[rk11][unit];
5102981Swnj if (ui) {
5116347Swnj rkustart(rkip[rk11][unit]);
5122981Swnj } else {
5133709Sroot rkaddr->rkcs1 = RK_CCLR;
5142981Swnj rkaddr->rkcs2 = unit;
5153709Sroot rkaddr->rkcs1 = RK_DCLR|RK_GO;
5162981Swnj rkwait(rkaddr);
5173709Sroot rkaddr->rkcs1 = RK_CCLR;
5182981Swnj }
5192981Swnj }
5202618Swnj if (um->um_tab.b_actf && um->um_tab.b_active == 0)
5216347Swnj rkstart(um);
5228609Sroot if (((rkaddr->rkcs1) & RK_IE) == 0)
5233709Sroot rkaddr->rkcs1 = RK_IE;
5241899Swnj }
5251899Swnj
rkwait(addr)5262618Swnj rkwait(addr)
5272618Swnj register struct rkdevice *addr;
5282618Swnj {
5291899Swnj
5302618Swnj while ((addr->rkcs1 & RK_CRDY) == 0)
5312618Swnj ;
5322618Swnj }
5332618Swnj
rkecc(ui,flag)5343709Sroot rkecc(ui, flag)
5352981Swnj register struct uba_device *ui;
5361899Swnj {
5372618Swnj register struct rkdevice *rk = (struct rkdevice *)ui->ui_addr;
5382618Swnj register struct buf *bp = rkutab[ui->ui_unit].b_actf;
5392981Swnj register struct uba_ctlr *um = ui->ui_mi;
5402618Swnj register struct rkst *st;
5412618Swnj struct uba_regs *ubp = ui->ui_hd->uh_uba;
5422618Swnj caddr_t addr;
5433709Sroot int reg, npf, o, cmd, ubaddr;
5442618Swnj int bn, cn, tn, sn;
5451899Swnj
5463709Sroot if (flag == CONT)
5473709Sroot npf = bp->b_error;
5483709Sroot else
54927675Skarels npf = btodb(bp->b_bcount + (rk->rkwc * sizeof(short)) + 511);
55036035Skarels reg = btop(UBAI_ADDR(um->um_ubinfo)) + npf;
5512618Swnj o = (int)bp->b_un.b_addr & PGOFSET;
55224740Sbloom bn = bp->b_blkno;
5532618Swnj st = &rkst[ui->ui_type];
5542618Swnj cn = bp->b_cylin;
5553709Sroot sn = bn%st->nspc + npf;
5562618Swnj tn = sn/st->nsect;
5572618Swnj sn %= st->nsect;
5582618Swnj cn += tn/st->ntrak;
5592618Swnj tn %= st->ntrak;
5603709Sroot ubapurge(um);
5613709Sroot switch (flag) {
5623709Sroot case ECC:
5633709Sroot {
5643709Sroot register int i;
5653709Sroot int bit, byte, mask;
5663709Sroot
5673709Sroot npf--;
5683709Sroot reg--;
56934524Skarels diskerr(bp, "rk", "soft ecc", LOG_WARNING, npf,
57034524Skarels (struct disklabel *)0);
57134524Skarels addlog("\n");
5723709Sroot mask = rk->rkec2;
5733709Sroot i = rk->rkec1 - 1; /* -1 makes 0 origin */
5743709Sroot bit = i&07;
5753709Sroot i = (i&~07)>>3;
5763709Sroot byte = i + o;
57727675Skarels while (i < 512 && (int)dbtob(npf)+i < bp->b_bcount && bit > -11) {
5783709Sroot addr = ptob(ubp->uba_map[reg+btop(byte)].pg_pfnum)+
5793709Sroot (byte & PGOFSET);
5803709Sroot putmemc(addr, getmemc(addr)^(mask<<bit));
5813709Sroot byte++;
5823709Sroot i++;
5833709Sroot bit -= 8;
5843709Sroot }
5857182Sroot if (rk->rkwc == 0) {
5867182Sroot um->um_tab.b_active = 0;
5873709Sroot return (0);
5887182Sroot }
5893709Sroot npf++;
5903709Sroot reg++;
5913709Sroot break;
5923709Sroot }
5933709Sroot
5943709Sroot case BSE:
5953709Sroot #ifdef RKBDEBUG
5963709Sroot if (rkbdebug)
5973709Sroot printf("rkecc, BSE: bn %d cn %d tn %d sn %d\n", bn, cn, tn, sn);
5983709Sroot #endif
5993709Sroot if ((bn = isbad(&rkbad[ui->ui_unit], cn, tn, sn)) < 0)
6003709Sroot return(0);
6013709Sroot bp->b_flags |= B_BAD;
6023709Sroot bp->b_error = npf + 1;
6033709Sroot bn = st->ncyl*st->nspc - st->nsect - 1 - bn;
6043709Sroot cn = bn/st->nspc;
6053709Sroot sn = bn%st->nspc;
6063709Sroot tn = sn/st->nsect;
6073709Sroot sn %= st->nsect;
6083709Sroot #ifdef RKBDEBUG
6093709Sroot if (rkbdebug)
6103709Sroot printf("revector to cn %d tn %d sn %d\n", cn, tn, sn);
6113709Sroot #endif
6123709Sroot rk->rkwc = -(512 / sizeof (short));
6133709Sroot break;
6143709Sroot
6153709Sroot case CONT:
6163709Sroot #ifdef RKBDEBUG
6173709Sroot if (rkbdebug)
6183709Sroot printf("rkecc, CONT: bn %d cn %d tn %d sn %d\n", bn,cn,tn,sn);
6193709Sroot #endif
6203709Sroot bp->b_flags &= ~B_BAD;
62127675Skarels if ((int)dbtob(npf) >= bp->b_bcount)
6227182Sroot return (0);
62327675Skarels rk->rkwc = -((bp->b_bcount - (int)dbtob(npf)) / sizeof (short));
6243709Sroot break;
6253709Sroot }
6263709Sroot rk->rkcs1 = RK_CCLR;
6273709Sroot rk->rkcs2 = ui->ui_slave;
6283709Sroot rk->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO;
6293709Sroot rkwait(rk);
6302618Swnj rk->rkcyl = cn;
6312618Swnj rk->rkda = (tn << 8) | sn;
6323709Sroot ubaddr = (int)ptob(reg) + o;
6332618Swnj rk->rkba = ubaddr;
6343709Sroot cmd = (bp->b_flags&B_READ ? RK_READ : RK_WRITE)|RK_IE|RK_GO;
6353709Sroot cmd |= (ubaddr >> 8) & 0x300;
6363709Sroot cmd |= rktypes[ui->ui_type];
6372618Swnj rk->rkcs1 = cmd;
6387031Swnj um->um_tab.b_active = 2; /* continuing */
6393709Sroot um->um_tab.b_errcnt = 0; /* error has been corrected */
6402618Swnj return (1);
6411899Swnj }
6421899Swnj
rkreset(uban)6432618Swnj rkreset(uban)
6442927Swnj int uban;
6451899Swnj {
6462981Swnj register struct uba_ctlr *um;
6472981Swnj register struct uba_device *ui;
6482618Swnj register rk11, unit;
6491899Swnj
6502648Swnj for (rk11 = 0; rk11 < NHK; rk11++) {
6512618Swnj if ((um = rkminfo[rk11]) == 0 || um->um_ubanum != uban ||
6522618Swnj um->um_alive == 0)
6532618Swnj continue;
6542927Swnj printf(" hk%d", rk11);
6552618Swnj um->um_tab.b_active = 0;
6562618Swnj um->um_tab.b_actf = um->um_tab.b_actl = 0;
6572618Swnj rk_softc[um->um_ctlr].sc_recal = 0;
6586347Swnj rk_softc[um->um_ctlr].sc_wticks = 0;
6592618Swnj if (um->um_ubinfo) {
6602618Swnj printf("<%d>", (um->um_ubinfo>>28)&0xf);
6619354Ssam um->um_ubinfo = 0;
6622618Swnj }
6634039Swnj for (unit = 0; unit < NRK; unit++) {
6642618Swnj if ((ui = rkdinfo[unit]) == 0)
6652618Swnj continue;
6664039Swnj if (ui->ui_alive == 0 || ui->ui_mi != um)
6672618Swnj continue;
6682618Swnj rkutab[unit].b_active = 0;
6692618Swnj (void) rkustart(ui);
6702618Swnj }
6712618Swnj (void) rkstart(um);
6722618Swnj }
6731899Swnj }
6742380Swnj
rkwatch()6752618Swnj rkwatch()
6762380Swnj {
6772981Swnj register struct uba_ctlr *um;
6782618Swnj register rk11, unit;
6792618Swnj register struct rk_softc *sc;
6802380Swnj
6812758Swnj timeout(rkwatch, (caddr_t)0, hz);
6822648Swnj for (rk11 = 0; rk11 < NHK; rk11++) {
6832618Swnj um = rkminfo[rk11];
6842618Swnj if (um == 0 || um->um_alive == 0)
6852618Swnj continue;
6862618Swnj sc = &rk_softc[rk11];
6872618Swnj if (um->um_tab.b_active == 0) {
6882648Swnj for (unit = 0; unit < NRK; unit++)
6892622Swnj if (rkutab[unit].b_active &&
6902622Swnj rkdinfo[unit]->ui_mi == um)
6912618Swnj goto active;
6922618Swnj sc->sc_wticks = 0;
6932618Swnj continue;
6942618Swnj }
6952618Swnj active:
6962618Swnj sc->sc_wticks++;
6972618Swnj if (sc->sc_wticks >= 20) {
6982618Swnj sc->sc_wticks = 0;
6992927Swnj printf("hk%d: lost interrupt\n", rk11);
7002648Swnj ubareset(um->um_ubanum);
7012618Swnj }
7022618Swnj }
7032380Swnj }
7042618Swnj
7052618Swnj #define DBSIZE 20
7062618Swnj
rkdump(dev)7072618Swnj rkdump(dev)
7082618Swnj dev_t dev;
7092618Swnj {
7102618Swnj struct rkdevice *rkaddr;
7112618Swnj char *start;
7122618Swnj int num, blk, unit;
7132618Swnj struct size *sizes;
7142618Swnj register struct uba_regs *uba;
7152981Swnj register struct uba_device *ui;
7162618Swnj register short *rp;
7172618Swnj struct rkst *st;
7182618Swnj
71924785Skarels unit = rkunit(dev);
7202885Swnj if (unit >= NRK)
7212885Swnj return (ENXIO);
7222618Swnj #define phys(cast, addr) ((cast)((int)addr & 0x7fffffff))
7232981Swnj ui = phys(struct uba_device *, rkdinfo[unit]);
7242885Swnj if (ui->ui_alive == 0)
7252885Swnj return (ENXIO);
7262618Swnj uba = phys(struct uba_hd *, ui->ui_hd)->uh_physuba;
7273329Swnj ubainit(uba);
7282618Swnj rkaddr = (struct rkdevice *)ui->ui_physaddr;
7292618Swnj num = maxfree;
7302618Swnj start = 0;
7313709Sroot rkaddr->rkcs1 = RK_CCLR;
7322618Swnj rkaddr->rkcs2 = unit;
7333709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO;
7342618Swnj rkwait(rkaddr);
7353293Swnj if ((rkaddr->rkds & RKDS_VV) == 0) {
7363709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_IE|RK_PACK|RK_GO;
7372618Swnj rkwait(rkaddr);
7382618Swnj }
7392618Swnj st = &rkst[ui->ui_type];
7402618Swnj sizes = phys(struct size *, st->sizes);
74124210Sbloom if (dumplo < 0)
7422885Swnj return (EINVAL);
74324210Sbloom if (dumplo + num >= sizes[minor(dev)&07].nblocks)
74424210Sbloom num = sizes[minor(dev)&07].nblocks - dumplo;
7452618Swnj while (num > 0) {
7462618Swnj register struct pte *io;
7472618Swnj register int i;
7482618Swnj int cn, sn, tn;
7492618Swnj daddr_t bn;
7502618Swnj
7512618Swnj blk = num > DBSIZE ? DBSIZE : num;
7522618Swnj io = uba->uba_map;
7532618Swnj for (i = 0; i < blk; i++)
7542981Swnj *(int *)io++ = (btop(start)+i) | (1<<21) | UBAMR_MRV;
7552618Swnj *(int *)io = 0;
7562618Swnj bn = dumplo + btop(start);
7572618Swnj cn = bn/st->nspc + sizes[minor(dev)&07].cyloff;
7582618Swnj sn = bn%st->nspc;
7592618Swnj tn = sn/st->nsect;
7602618Swnj sn = sn%st->nsect;
7612618Swnj rkaddr->rkcyl = cn;
7622618Swnj rp = (short *) &rkaddr->rkda;
7632618Swnj *rp = (tn << 8) + sn;
7642618Swnj *--rp = 0;
7652618Swnj *--rp = -blk*NBPG / sizeof (short);
7663709Sroot *--rp = rktypes[ui->ui_type]|RK_GO|RK_WRITE;
7672618Swnj rkwait(rkaddr);
7682885Swnj if (rkaddr->rkcs1 & RK_CERR)
7692885Swnj return (EIO);
7702618Swnj start += blk*NBPG;
7712618Swnj num -= blk;
7722618Swnj }
7732618Swnj return (0);
7742618Swnj }
77512503Ssam
rksize(dev)77612503Ssam rksize(dev)
77712503Ssam dev_t dev;
77812503Ssam {
77924785Skarels int unit = rkunit(dev);
78012503Ssam struct uba_device *ui;
78112503Ssam struct rkst *st;
78212503Ssam
78312503Ssam if (unit >= NRK || (ui = rkdinfo[unit]) == 0 || ui->ui_alive == 0)
78412503Ssam return (-1);
78512503Ssam st = &rkst[ui->ui_type];
78612503Ssam return (st->sizes[minor(dev) & 07].nblocks);
78712503Ssam }
7882618Swnj #endif
789