+/* rk.c 6.2 83/10/11 */
+
+#include "rk.h"
+#if NHK > 0
+int rkpip; /* DEBUG */
+int rknosval; /* DEBUG */
+#ifdef RKDEBUG
+int rkdebug;
+#endif
+#ifdef RKBDEBUG
+int rkbdebug;
+#endif
+/*
+ * RK611/RK0[67] disk driver
+ *
+ * This driver mimics up.c; see it for an explanation of common code.
+ *
+ * TODO:
+ * Learn why we lose an interrupt sometime when spinning drives down
+ */
+#include "../machine/pte.h"
+
+#include "../h/param.h"
+#include "../h/systm.h"
+#include "../h/buf.h"
+#include "../h/conf.h"
+#include "../h/dir.h"
+#include "../h/user.h"
+#include "../h/map.h"
+#include "../h/vm.h"
+#include "../h/dk.h"
+#include "../h/cmap.h"
+#include "../h/dkbad.h"
+#include "../h/uio.h"
+#include "../h/kernel.h"
+
+#include "../vax/cpu.h"
+#include "../vaxuba/ubareg.h"
+#include "../vaxuba/ubavar.h"
+#include "../vaxuba/rkreg.h"
+
+struct rk_softc {
+ int sc_softas;
+ int sc_ndrive;
+ int sc_wticks;
+ int sc_recal;
+} rk_softc[NHK];
+
+/* THIS SHOULD BE READ OFF THE PACK, PER DRIVE */
+struct size {
+ daddr_t nblocks;
+ int cyloff;
+} rk7_sizes[8] ={
+ 15884, 0, /* A=cyl 0 thru 240 */
+ 10032, 241, /* B=cyl 241 thru 392 */
+ 53790, 0, /* C=cyl 0 thru 814 */
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 27786, 393, /* G=cyl 393 thru 813 */
+ 0, 0,
+}, rk6_sizes[8] ={
+ 15884, 0, /* A=cyl 0 thru 240 */
+ 11154, 241, /* B=cyl 241 thru 409 */
+ 27126, 0, /* C=cyl 0 thru 410 */
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+};
+/* END OF STUFF WHICH SHOULD BE READ IN PER DISK */
+
+short rktypes[] = { RK_CDT, 0 };
+
+int rkprobe(), rkslave(), rkattach(), rkdgo(), rkintr();
+struct uba_ctlr *rkminfo[NHK];
+struct uba_device *rkdinfo[NRK];
+struct uba_device *rkip[NHK][4];
+
+u_short rkstd[] = { 0777440, 0 };
+struct uba_driver hkdriver =
+ { rkprobe, rkslave, rkattach, rkdgo, rkstd, "rk", rkdinfo, "hk", rkminfo, 1 };
+struct buf rkutab[NRK];
+short rkcyl[NRK];
+struct dkbad rkbad[NRK];
+struct buf brkbuf[NRK];
+
+struct rkst {
+ short nsect;
+ short ntrak;
+ short nspc;
+ short ncyl;
+ struct size *sizes;
+} rkst[] = {
+ NRKSECT, NRKTRK, NRKSECT*NRKTRK, NRK7CYL, rk7_sizes,
+ NRKSECT, NRKTRK, NRKSECT*NRKTRK, NRK6CYL, rk6_sizes,
+};
+
+u_char rk_offset[16] =
+ { RKAS_P400,RKAS_M400,RKAS_P400,RKAS_M400,RKAS_P800,RKAS_M800,RKAS_P800,
+ RKAS_M800,RKAS_P1200,RKAS_M1200,RKAS_P1200,RKAS_M1200,0,0,0,0
+ };
+
+struct buf rrkbuf[NRK];
+
+#define b_cylin b_resid
+
+#ifdef INTRLVE
+daddr_t dkblock();
+#endif
+
+int rkwstart, rkwatch();
+
+rkprobe(reg)
+ caddr_t reg;
+{
+ register int br, cvec;
+
+#ifdef lint
+ br = 0; cvec = br; br = cvec;
+ rkintr(0);
+#endif
+ ((struct rkdevice *)reg)->rkcs1 = RK_CDT|RK_IE|RK_CRDY;
+ DELAY(10);
+ ((struct rkdevice *)reg)->rkcs1 = RK_CDT;
+ return (sizeof (struct rkdevice));
+}
+
+rkslave(ui, reg)
+ struct uba_device *ui;
+ caddr_t reg;
+{
+ register struct rkdevice *rkaddr = (struct rkdevice *)reg;
+
+ ui->ui_type = 0;
+ rkaddr->rkcs1 = RK_CCLR;
+ rkaddr->rkcs2 = ui->ui_slave;
+ rkaddr->rkcs1 = RK_CDT|RK_DCLR|RK_GO;
+ rkwait(rkaddr);
+ DELAY(50);
+ if (rkaddr->rkcs2&RKCS2_NED || (rkaddr->rkds&RKDS_SVAL) == 0) {
+ rkaddr->rkcs1 = RK_CCLR;
+ return (0);
+ }
+ if (rkaddr->rkcs1&RK_CERR && rkaddr->rker&RKER_DTYE) {
+ ui->ui_type = 1;
+ rkaddr->rkcs1 = RK_CCLR;
+ }
+ return (1);
+}
+
+rkattach(ui)
+ register struct uba_device *ui;
+{
+
+ if (rkwstart == 0) {
+ timeout(rkwatch, (caddr_t)0, hz);
+ rkwstart++;
+ }
+ if (ui->ui_dk >= 0)
+ dk_mspw[ui->ui_dk] = 1.0 / (60 * NRKSECT * 256);
+ rkip[ui->ui_ctlr][ui->ui_slave] = ui;
+ rk_softc[ui->ui_ctlr].sc_ndrive++;
+ rkcyl[ui->ui_unit] = -1;
+ ui->ui_flags = 0;
+}
+
+rkopen(dev)
+ dev_t dev;
+{
+ register int unit = minor(dev) >> 3;
+ register struct uba_device *ui;
+
+ if (unit >= NRK || (ui = rkdinfo[unit]) == 0 || ui->ui_alive == 0)
+ return (ENXIO);
+ return (0);
+}
+
+rkstrategy(bp)
+ register struct buf *bp;
+{
+ register struct uba_device *ui;
+ register struct rkst *st;
+ register int unit;
+ register struct buf *dp;
+ int xunit = minor(bp->b_dev) & 07;
+ long bn, sz;
+ int s;
+
+ sz = (bp->b_bcount+511) >> 9;
+ unit = dkunit(bp);
+ if (unit >= NRK)
+ goto bad;
+ ui = rkdinfo[unit];
+ if (ui == 0 || ui->ui_alive == 0)
+ goto bad;
+ st = &rkst[ui->ui_type];
+ if (bp->b_blkno < 0 ||
+ (bn = dkblock(bp))+sz > st->sizes[xunit].nblocks)
+ goto bad;
+ bp->b_cylin = bn/st->nspc + st->sizes[xunit].cyloff;
+ s = spl5();
+ dp = &rkutab[ui->ui_unit];
+ disksort(dp, bp);
+ if (dp->b_active == 0) {
+ (void) rkustart(ui);
+ bp = &ui->ui_mi->um_tab;
+ if (bp->b_actf && bp->b_active == 0)
+ (void) rkstart(ui->ui_mi);
+ }
+ splx(s);
+ return;
+
+bad:
+ bp->b_flags |= B_ERROR;
+ iodone(bp);
+ return;
+}
+
+rkustart(ui)
+ register struct uba_device *ui;
+{
+ register struct buf *bp, *dp;
+ register struct uba_ctlr *um;
+ register struct rkdevice *rkaddr;
+
+ if (ui == 0)
+ return;
+ dk_busy &= ~(1<<ui->ui_dk);
+ dp = &rkutab[ui->ui_unit];
+ um = ui->ui_mi;
+ rkaddr = (struct rkdevice *)um->um_addr;
+ if (um->um_tab.b_active) {
+ rk_softc[um->um_ctlr].sc_softas |= 1<<ui->ui_slave;
+ return;
+ }
+ if ((bp = dp->b_actf) == NULL)
+ return;
+ rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_CERR;
+ rkaddr->rkcs2 = ui->ui_slave;
+ rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO;
+ rkwait(rkaddr);
+ if ((rkaddr->rkds & RKDS_VV) == 0 || ui->ui_flags == 0) {
+ /* SHOULD WARN SYSTEM THAT THIS HAPPENED */
+ struct rkst *st = &rkst[ui->ui_type];
+ struct buf *bbp = &brkbuf[ui->ui_unit];
+
+ rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_PACK|RK_GO;
+ ui->ui_flags = 1;
+ bbp->b_flags = B_READ|B_BUSY;
+ bbp->b_dev = bp->b_dev;
+ bbp->b_bcount = 512;
+ bbp->b_un.b_addr = (caddr_t)&rkbad[ui->ui_unit];
+ bbp->b_blkno = st->ncyl*st->nspc - st->nsect;
+ bbp->b_cylin = st->ncyl - 1;
+ dp->b_actf = bbp;
+ bbp->av_forw = bp;
+ bp = bbp;
+ rkwait(rkaddr);
+ }
+ if (dp->b_active)
+ goto done;
+ dp->b_active = 1;
+ if ((rkaddr->rkds & RKDS_DREADY) != RKDS_DREADY)
+ goto done;
+ if (rk_softc[um->um_ctlr].sc_ndrive == 1)
+ goto done;
+ if (bp->b_cylin == rkcyl[ui->ui_unit])
+ goto done;
+ rkaddr->rkcyl = bp->b_cylin;
+ rkcyl[ui->ui_unit] = bp->b_cylin;
+ rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_IE|RK_SEEK|RK_GO;
+ if (ui->ui_dk >= 0) {
+ dk_busy |= 1<<ui->ui_dk;
+ dk_seek[ui->ui_dk]++;
+ }
+ goto out;
+done:
+ if (dp->b_active != 2) {
+ dp->b_forw = NULL;
+ if (um->um_tab.b_actf == NULL)
+ um->um_tab.b_actf = dp;
+ else
+ um->um_tab.b_actl->b_forw = dp;
+ um->um_tab.b_actl = dp;
+ dp->b_active = 2;
+ }
+out:
+ return;
+}
+
+rkstart(um)
+ register struct uba_ctlr *um;
+{
+ register struct buf *bp, *dp;
+ register struct uba_device *ui;
+ register struct rkdevice *rkaddr;
+ struct rkst *st;
+ daddr_t bn;
+ int sn, tn, cmd;
+
+loop:
+ if ((dp = um->um_tab.b_actf) == NULL)
+ return;
+ if ((bp = dp->b_actf) == NULL) {
+ um->um_tab.b_actf = dp->b_forw;
+ goto loop;
+ }
+ um->um_tab.b_active++;
+ ui = rkdinfo[dkunit(bp)];
+ bn = dkblock(bp);
+ st = &rkst[ui->ui_type];
+ sn = bn%st->nspc;
+ tn = sn/st->nsect;
+ sn %= st->nsect;
+ rkaddr = (struct rkdevice *)ui->ui_addr;
+retry:
+ rkaddr->rkcs1 = RK_CCLR;
+ rkaddr->rkcs2 = ui->ui_slave;
+ rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO;
+ rkwait(rkaddr);
+ if ((rkaddr->rkds&RKDS_SVAL) == 0) {
+ rknosval++;
+ goto nosval;
+ }
+ if (rkaddr->rkds&RKDS_PIP) {
+ rkpip++;
+ goto retry;
+ }
+ if ((rkaddr->rkds&RKDS_DREADY) != RKDS_DREADY) {
+ printf("rk%d: not ready", dkunit(bp));
+ if ((rkaddr->rkds&RKDS_DREADY) != RKDS_DREADY) {
+ printf("\n");
+ rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO;
+ rkwait(rkaddr);
+ rkaddr->rkcs1 = RK_CCLR;
+ rkwait(rkaddr);
+ um->um_tab.b_active = 0;
+ um->um_tab.b_errcnt = 0;
+ dp->b_actf = bp->av_forw;
+ dp->b_active = 0;
+ bp->b_flags |= B_ERROR;
+ iodone(bp);
+ goto loop;
+ }
+ printf(" (came back!)\n");
+ }
+nosval:
+ rkaddr->rkcyl = bp->b_cylin;
+ rkcyl[ui->ui_unit] = bp->b_cylin;
+ rkaddr->rkda = (tn << 8) + sn;
+ rkaddr->rkwc = -bp->b_bcount / sizeof (short);
+ if (bp->b_flags & B_READ)
+ cmd = rktypes[ui->ui_type]|RK_IE|RK_READ|RK_GO;
+ else
+ cmd = rktypes[ui->ui_type]|RK_IE|RK_WRITE|RK_GO;
+ um->um_cmd = cmd;
+ (void) ubago(ui);
+}
+
+rkdgo(um)
+ register struct uba_ctlr *um;
+{
+ register struct rkdevice *rkaddr = (struct rkdevice *)um->um_addr;
+
+ um->um_tab.b_active = 2; /* should now be 2 */
+ rkaddr->rkba = um->um_ubinfo;
+ rkaddr->rkcs1 = um->um_cmd|((um->um_ubinfo>>8)&0x300);
+}
+
+rkintr(rk11)
+ int rk11;
+{
+ register struct uba_ctlr *um = rkminfo[rk11];
+ register struct uba_device *ui;
+ register struct rkdevice *rkaddr = (struct rkdevice *)um->um_addr;
+ register struct buf *bp, *dp;
+ int unit;
+ struct rk_softc *sc = &rk_softc[um->um_ctlr];
+ int as = (rkaddr->rkatt >> 8) | sc->sc_softas;
+
+ sc->sc_wticks = 0;
+ sc->sc_softas = 0;
+ if (um->um_tab.b_active == 2 || sc->sc_recal) {
+ um->um_tab.b_active = 1;
+ dp = um->um_tab.b_actf;
+ bp = dp->b_actf;
+ ui = rkdinfo[dkunit(bp)];
+ dk_busy &= ~(1 << ui->ui_dk);
+ if (bp->b_flags&B_BAD)
+ if (rkecc(ui, CONT))
+ return;
+ if (rkaddr->rkcs1 & RK_CERR) {
+ int recal;
+ u_short ds = rkaddr->rkds;
+ u_short cs2 = rkaddr->rkcs2;
+ u_short er = rkaddr->rker;
+#ifdef RKDEBUG
+ if (rkdebug) {
+ printf("cs2=%b ds=%b er=%b\n",
+ cs2, RKCS2_BITS, ds,
+ RKDS_BITS, er, RKER_BITS);
+ }
+#endif
+ if (er & RKER_WLE) {
+ printf("rk%d: write locked\n", dkunit(bp));
+ bp->b_flags |= B_ERROR;
+ } else if (++um->um_tab.b_errcnt > 28 ||
+ ds&RKDS_HARD || er&RKER_HARD || cs2&RKCS2_HARD) {
+hard:
+ harderr(bp, "rk");
+ printf("cs2=%b ds=%b er=%b\n",
+ cs2, RKCS2_BITS, ds,
+ RKDS_BITS, er, RKER_BITS);
+ bp->b_flags |= B_ERROR;
+ sc->sc_recal = 0;
+ } else if (er & RKER_BSE) {
+ if (rkecc(ui, BSE))
+ return;
+ else
+ goto hard;
+ } else {
+ if ((er & (RKER_DCK|RKER_ECH)) == RKER_DCK) {
+ if (rkecc(ui, ECC))
+ return;
+ } else
+ um->um_tab.b_active = 0;
+ }
+ if (cs2&RKCS2_MDS) {
+ rkaddr->rkcs2 = RKCS2_SCLR;
+ goto retry;
+ }
+ recal = 0;
+ if (ds&RKDS_DROT || er&(RKER_OPI|RKER_SKI|RKER_UNS) ||
+ (um->um_tab.b_errcnt&07) == 4)
+ recal = 1;
+ rkaddr->rkcs1 = RK_CCLR;
+ rkaddr->rkcs2 = ui->ui_slave;
+ rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO;
+ rkwait(rkaddr);
+ if (recal && um->um_tab.b_active == 0) {
+ rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_IE|RK_RECAL|RK_GO;
+ rkcyl[ui->ui_unit] = -1;
+ sc->sc_recal = 0;
+ goto nextrecal;
+ }
+ }
+retry:
+ switch (sc->sc_recal) {
+
+ case 1:
+ rkaddr->rkcyl = bp->b_cylin;
+ rkcyl[ui->ui_unit] = bp->b_cylin;
+ rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_IE|RK_SEEK|RK_GO;
+ goto nextrecal;
+ case 2:
+ if (um->um_tab.b_errcnt < 16 ||
+ (bp->b_flags&B_READ) == 0)
+ goto donerecal;
+ rkaddr->rkatt = rk_offset[um->um_tab.b_errcnt & 017];
+ rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_IE|RK_OFFSET|RK_GO;
+ /* fall into ... */
+ nextrecal:
+ sc->sc_recal++;
+ rkwait(rkaddr);
+ um->um_tab.b_active = 1;
+ return;
+ donerecal:
+ case 3:
+ sc->sc_recal = 0;
+ um->um_tab.b_active = 0;
+ break;
+ }
+ ubadone(um);
+ if (um->um_tab.b_active) {
+ um->um_tab.b_active = 0;
+ um->um_tab.b_errcnt = 0;
+ um->um_tab.b_actf = dp->b_forw;
+ dp->b_active = 0;
+ dp->b_errcnt = 0;
+ dp->b_actf = bp->av_forw;
+ bp->b_resid = -rkaddr->rkwc * sizeof(short);
+ iodone(bp);
+ if (dp->b_actf)
+ rkustart(ui);
+ }
+ as &= ~(1<<ui->ui_slave);
+ }
+ for (unit = 0; as; as >>= 1, unit++)
+ if (as & 1) {
+ ui = rkip[rk11][unit];
+ if (ui) {
+ rkustart(rkip[rk11][unit]);
+ } else {
+ rkaddr->rkcs1 = RK_CCLR;
+ rkaddr->rkcs2 = unit;
+ rkaddr->rkcs1 = RK_DCLR|RK_GO;
+ rkwait(rkaddr);
+ rkaddr->rkcs1 = RK_CCLR;
+ }
+ }
+ if (um->um_tab.b_actf && um->um_tab.b_active == 0)
+ rkstart(um);
+ if (((rkaddr->rkcs1) & RK_IE) == 0)
+ rkaddr->rkcs1 = RK_IE;
+}
+
+rkwait(addr)
+ register struct rkdevice *addr;
+{
+
+ while ((addr->rkcs1 & RK_CRDY) == 0)
+ ;
+}
+
+rkread(dev, uio)
+ dev_t dev;
+ struct uio *uio;
+{
+ register int unit = minor(dev) >> 3;
+
+ if (unit >= NRK)
+ return (ENXIO);
+ return (physio(rkstrategy, &rrkbuf[unit], dev, B_READ, minphys, uio));
+}
+
+rkwrite(dev, uio)
+ dev_t dev;
+ struct uio *uio;
+{
+ register int unit = minor(dev) >> 3;
+
+ if (unit >= NRK)
+ return (ENXIO);
+ return (physio(rkstrategy, &rrkbuf[unit], dev, B_WRITE, minphys, uio));
+}
+
+rkecc(ui, flag)
+ register struct uba_device *ui;
+{
+ register struct rkdevice *rk = (struct rkdevice *)ui->ui_addr;
+ register struct buf *bp = rkutab[ui->ui_unit].b_actf;
+ register struct uba_ctlr *um = ui->ui_mi;
+ register struct rkst *st;
+ struct uba_regs *ubp = ui->ui_hd->uh_uba;
+ caddr_t addr;
+ int reg, npf, o, cmd, ubaddr;
+ int bn, cn, tn, sn;
+
+ if (flag == CONT)
+ npf = bp->b_error;
+ else
+ npf = btop((rk->rkwc * sizeof(short)) + bp->b_bcount);
+ reg = btop(um->um_ubinfo&0x3ffff) + npf;
+ o = (int)bp->b_un.b_addr & PGOFSET;
+ bn = dkblock(bp);
+ st = &rkst[ui->ui_type];
+ cn = bp->b_cylin;
+ sn = bn%st->nspc + npf;
+ tn = sn/st->nsect;
+ sn %= st->nsect;
+ cn += tn/st->ntrak;
+ tn %= st->ntrak;
+ ubapurge(um);
+ switch (flag) {
+ case ECC:
+ {
+ register int i;
+ int bit, byte, mask;
+
+ npf--;
+ reg--;
+ printf("rk%d%c: soft ecc sn%d\n", dkunit(bp),
+ 'a'+(minor(bp->b_dev)&07), bp->b_blkno + npf);
+ mask = rk->rkec2;
+ i = rk->rkec1 - 1; /* -1 makes 0 origin */
+ bit = i&07;
+ i = (i&~07)>>3;
+ byte = i + o;
+ while (i < 512 && (int)ptob(npf)+i < bp->b_bcount && bit > -11) {
+ addr = ptob(ubp->uba_map[reg+btop(byte)].pg_pfnum)+
+ (byte & PGOFSET);
+ putmemc(addr, getmemc(addr)^(mask<<bit));
+ byte++;
+ i++;
+ bit -= 8;
+ }
+ if (rk->rkwc == 0) {
+ um->um_tab.b_active = 0;
+ return (0);
+ }
+ npf++;
+ reg++;
+ break;
+ }
+
+ case BSE:
+#ifdef RKBDEBUG
+ if (rkbdebug)
+ printf("rkecc, BSE: bn %d cn %d tn %d sn %d\n", bn, cn, tn, sn);
+#endif
+ if ((bn = isbad(&rkbad[ui->ui_unit], cn, tn, sn)) < 0)
+ return(0);
+ bp->b_flags |= B_BAD;
+ bp->b_error = npf + 1;
+ bn = st->ncyl*st->nspc - st->nsect - 1 - bn;
+ cn = bn/st->nspc;
+ sn = bn%st->nspc;
+ tn = sn/st->nsect;
+ sn %= st->nsect;
+#ifdef RKBDEBUG
+ if (rkbdebug)
+ printf("revector to cn %d tn %d sn %d\n", cn, tn, sn);
+#endif
+ rk->rkwc = -(512 / sizeof (short));
+ break;
+
+ case CONT:
+#ifdef RKBDEBUG
+ if (rkbdebug)
+ printf("rkecc, CONT: bn %d cn %d tn %d sn %d\n", bn,cn,tn,sn);
+#endif
+ bp->b_flags &= ~B_BAD;
+ rk->rkwc = -((bp->b_bcount - (int)ptob(npf)) / sizeof (short));
+ if (rk->rkwc == 0)
+ return (0);
+ break;
+ }
+ rk->rkcs1 = RK_CCLR;
+ rk->rkcs2 = ui->ui_slave;
+ rk->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO;
+ rkwait(rk);
+ rk->rkcyl = cn;
+ rk->rkda = (tn << 8) | sn;
+ ubaddr = (int)ptob(reg) + o;
+ rk->rkba = ubaddr;
+ cmd = (bp->b_flags&B_READ ? RK_READ : RK_WRITE)|RK_IE|RK_GO;
+ cmd |= (ubaddr >> 8) & 0x300;
+ cmd |= rktypes[ui->ui_type];
+ rk->rkcs1 = cmd;
+ um->um_tab.b_active = 2; /* continuing */
+ um->um_tab.b_errcnt = 0; /* error has been corrected */
+ return (1);
+}
+
+rkreset(uban)
+ int uban;
+{
+ register struct uba_ctlr *um;
+ register struct uba_device *ui;
+ register rk11, unit;
+
+ for (rk11 = 0; rk11 < NHK; rk11++) {
+ if ((um = rkminfo[rk11]) == 0 || um->um_ubanum != uban ||
+ um->um_alive == 0)
+ continue;
+ printf(" hk%d", rk11);
+ um->um_tab.b_active = 0;
+ um->um_tab.b_actf = um->um_tab.b_actl = 0;
+ rk_softc[um->um_ctlr].sc_recal = 0;
+ rk_softc[um->um_ctlr].sc_wticks = 0;
+ if (um->um_ubinfo) {
+ printf("<%d>", (um->um_ubinfo>>28)&0xf);
+ um->um_ubinfo = 0;
+ }
+ for (unit = 0; unit < NRK; unit++) {
+ if ((ui = rkdinfo[unit]) == 0)
+ continue;
+ if (ui->ui_alive == 0 || ui->ui_mi != um)
+ continue;
+ rkutab[unit].b_active = 0;
+ (void) rkustart(ui);
+ }
+ (void) rkstart(um);
+ }
+}
+
+rkwatch()
+{
+ register struct uba_ctlr *um;
+ register rk11, unit;
+ register struct rk_softc *sc;
+
+ timeout(rkwatch, (caddr_t)0, hz);
+ for (rk11 = 0; rk11 < NHK; rk11++) {
+ um = rkminfo[rk11];
+ if (um == 0 || um->um_alive == 0)
+ continue;
+ sc = &rk_softc[rk11];
+ if (um->um_tab.b_active == 0) {
+ for (unit = 0; unit < NRK; unit++)
+ if (rkutab[unit].b_active &&
+ rkdinfo[unit]->ui_mi == um)
+ goto active;
+ sc->sc_wticks = 0;
+ continue;
+ }
+active:
+ sc->sc_wticks++;
+ if (sc->sc_wticks >= 20) {
+ sc->sc_wticks = 0;
+ printf("hk%d: lost interrupt\n", rk11);
+ ubareset(um->um_ubanum);
+ }
+ }
+}
+
+#define DBSIZE 20
+
+rkdump(dev)
+ dev_t dev;
+{
+ struct rkdevice *rkaddr;
+ char *start;
+ int num, blk, unit;
+ struct size *sizes;
+ register struct uba_regs *uba;
+ register struct uba_device *ui;
+ register short *rp;
+ struct rkst *st;
+
+ unit = minor(dev) >> 3;
+ if (unit >= NRK)
+ return (ENXIO);
+#define phys(cast, addr) ((cast)((int)addr & 0x7fffffff))
+ ui = phys(struct uba_device *, rkdinfo[unit]);
+ if (ui->ui_alive == 0)
+ return (ENXIO);
+ uba = phys(struct uba_hd *, ui->ui_hd)->uh_physuba;
+ ubainit(uba);
+ rkaddr = (struct rkdevice *)ui->ui_physaddr;
+ num = maxfree;
+ start = 0;
+ rkaddr->rkcs1 = RK_CCLR;
+ rkaddr->rkcs2 = unit;
+ rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO;
+ rkwait(rkaddr);
+ if ((rkaddr->rkds & RKDS_VV) == 0) {
+ rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_IE|RK_PACK|RK_GO;
+ rkwait(rkaddr);
+ }
+ st = &rkst[ui->ui_type];
+ sizes = phys(struct size *, st->sizes);
+ if (dumplo < 0 || dumplo + num >= sizes[minor(dev)&07].nblocks)
+ return (EINVAL);
+ while (num > 0) {
+ register struct pte *io;
+ register int i;
+ int cn, sn, tn;
+ daddr_t bn;
+
+ blk = num > DBSIZE ? DBSIZE : num;
+ io = uba->uba_map;
+ for (i = 0; i < blk; i++)
+ *(int *)io++ = (btop(start)+i) | (1<<21) | UBAMR_MRV;
+ *(int *)io = 0;
+ bn = dumplo + btop(start);
+ cn = bn/st->nspc + sizes[minor(dev)&07].cyloff;
+ sn = bn%st->nspc;
+ tn = sn/st->nsect;
+ sn = sn%st->nsect;
+ rkaddr->rkcyl = cn;
+ rp = (short *) &rkaddr->rkda;
+ *rp = (tn << 8) + sn;
+ *--rp = 0;
+ *--rp = -blk*NBPG / sizeof (short);
+ *--rp = rktypes[ui->ui_type]|RK_GO|RK_WRITE;
+ rkwait(rkaddr);
+ if (rkaddr->rkcs1 & RK_CERR)
+ return (EIO);
+ start += blk*NBPG;
+ num -= blk;
+ }
+ return (0);
+}
+
+rksize(dev)
+ dev_t dev;
+{
+ int unit = minor(dev) >> 3;
+ struct uba_device *ui;
+ struct rkst *st;
+
+ if (unit >= NRK || (ui = rkdinfo[unit]) == 0 || ui->ui_alive == 0)
+ return (-1);
+ st = &rkst[ui->ui_type];
+ return (st->sizes[minor(dev) & 07].nblocks);
+}
+#endif