xref: /csrg-svn/sys/vax/uba/rk.c (revision 3293)
1*3293Swnj /*	rk.c	4.31	81/03/17	*/
21899Swnj 
31942Swnj #include "rk.h"
42648Swnj #if NHK > 0
53104Swnj int	rkpip;		/* DEBUG */
63104Swnj int	rknosval;	/* DEBUG */
7*3293Swnj int	rkdebug;
81899Swnj /*
9*3293Swnj  * RK611/RK0[67] disk driver
102622Swnj  *
112622Swnj  * This driver mimics up.c; see it for an explanation of common code.
122685Swnj  *
132885Swnj  * TODO:
143208Swnj  *	Learn why we lose an interrupt sometime when spinning drives down
15*3293Swnj  *	Support rk06
161899Swnj  */
171899Swnj #include "../h/param.h"
181899Swnj #include "../h/systm.h"
191899Swnj #include "../h/buf.h"
201899Swnj #include "../h/conf.h"
211899Swnj #include "../h/dir.h"
221899Swnj #include "../h/user.h"
231899Swnj #include "../h/pte.h"
241899Swnj #include "../h/map.h"
252618Swnj #include "../h/vm.h"
262981Swnj #include "../h/ubareg.h"
272981Swnj #include "../h/ubavar.h"
281899Swnj #include "../h/dk.h"
292618Swnj #include "../h/cpu.h"
302618Swnj #include "../h/cmap.h"
311899Swnj 
322618Swnj #include "../h/rkreg.h"
331899Swnj 
342618Swnj struct	rk_softc {
352618Swnj 	int	sc_softas;
362618Swnj 	int	sc_ndrive;
372618Swnj 	int	sc_wticks;
382618Swnj 	int	sc_recal;
392648Swnj } rk_softc[NHK];
401899Swnj 
412618Swnj /* THIS SHOULD BE READ OFF THE PACK, PER DRIVE */
422787Swnj struct size {
432618Swnj 	daddr_t	nblocks;
442618Swnj 	int	cyloff;
452618Swnj } rk7_sizes[] ={
462618Swnj 	15884,	0,		/* A=cyl 0 thru 240 */
472665Swnj 	10032,	241,		/* B=cyl 241 thru 392 */
482665Swnj 	53790,	0,		/* C=cyl 0 thru 814 */
492618Swnj 	0,	0,
502618Swnj 	0,	0,
512618Swnj 	0,	0,
522618Swnj 	27786,	393,		/* G=cyl 393 thru 813 */
532618Swnj 	0,	0,
542618Swnj };
552618Swnj /* END OF STUFF WHICH SHOULD BE READ IN PER DISK */
561899Swnj 
572618Swnj int	rkprobe(), rkslave(), rkattach(), rkdgo(), rkintr();
582981Swnj struct	uba_ctlr *rkminfo[NHK];
592981Swnj struct	uba_device *rkdinfo[NRK];
602981Swnj struct	uba_device *rkip[NHK][4];
611899Swnj 
622618Swnj u_short	rkstd[] = { 0777440, 0 };
632618Swnj struct	uba_driver hkdriver =
642622Swnj  { rkprobe, rkslave, rkattach, rkdgo, rkstd, "rk", rkdinfo, "hk", rkminfo, 1 };
652648Swnj struct	buf rkutab[NRK];
662648Swnj short	rkcyl[NRK];
671899Swnj 
682618Swnj struct	rkst {
692618Swnj 	short	nsect;
702618Swnj 	short	ntrak;
712618Swnj 	short	nspc;
722618Swnj 	short	ncyl;
732618Swnj 	struct	size *sizes;
742618Swnj } rkst[] = {
752618Swnj 	NRKSECT, NRKTRK, NRKSECT*NRKTRK,	NRK7CYL,	rk7_sizes,
762618Swnj };
771899Swnj 
782618Swnj u_char 	rk_offset[16] =
79*3293Swnj   { RKAS_P400,RKAS_M400,RKAS_P400,RKAS_M400,RKAS_P800,RKAS_M800,RKAS_P800,
80*3293Swnj     RKAS_M800,RKAS_P1200,RKAS_M1200,RKAS_P1200,RKAS_M1200,0,0,0,0
81*3293Swnj   };
821899Swnj 
832648Swnj struct	buf rrkbuf[NRK];
842618Swnj 
852618Swnj #define	b_cylin	b_resid
862618Swnj 
872618Swnj #ifdef INTRLVE
882618Swnj daddr_t	dkblock();
892618Swnj #endif
902618Swnj 
912618Swnj int	rkwstart, rkwatch();
922618Swnj 
932618Swnj rkprobe(reg)
942618Swnj 	caddr_t reg;
951899Swnj {
962618Swnj 	register int br, cvec;
971899Swnj 
982618Swnj #ifdef lint
992618Swnj 	br = 0; cvec = br; br = cvec;
1002618Swnj #endif
1012618Swnj 	((struct rkdevice *)reg)->rkcs1 = RK_CDT|RK_IE|RK_CRDY;
1022618Swnj 	DELAY(10);
1032618Swnj 	((struct rkdevice *)reg)->rkcs1 = RK_CDT;
1042618Swnj 	return (1);
1052618Swnj }
1061899Swnj 
1072618Swnj rkslave(ui, reg)
1082981Swnj 	struct uba_device *ui;
1092618Swnj 	caddr_t reg;
1102618Swnj {
1112618Swnj 	register struct rkdevice *rkaddr = (struct rkdevice *)reg;
1121899Swnj 
1132894Swnj 	rkaddr->rkcs1 = RK_CDT|RK_CCLR;
1142618Swnj 	rkaddr->rkcs2 = ui->ui_slave;
1152957Swnj 	rkaddr->rkcs1 = RK_CDT|RK_DCLR|RK_GO;
1162622Swnj 	rkwait(rkaddr);
1172894Swnj 	DELAY(50);
118*3293Swnj 	if (rkaddr->rkcs2&RKCS2_NED || (rkaddr->rkds&RKDS_SVAL) == 0) {
1192618Swnj 		rkaddr->rkcs1 = RK_CDT|RK_CCLR;
1202618Swnj 		return (0);
1212618Swnj 	}
1222618Swnj 	return (1);
1232618Swnj }
1242618Swnj 
1252618Swnj rkattach(ui)
1262981Swnj 	register struct uba_device *ui;
1272618Swnj {
1282618Swnj 
1292618Swnj 	if (rkwstart == 0) {
1302758Swnj 		timeout(rkwatch, (caddr_t)0, hz);
1312618Swnj 		rkwstart++;
1322618Swnj 	}
1332618Swnj 	if (ui->ui_dk >= 0)
1342758Swnj 		dk_mspw[ui->ui_dk] = 1.0 / (60 * NRKSECT * 256);
1352618Swnj 	rkip[ui->ui_ctlr][ui->ui_slave] = ui;
1362618Swnj 	rk_softc[ui->ui_ctlr].sc_ndrive++;
1372618Swnj 	rkcyl[ui->ui_unit] = -1;
1382618Swnj }
1392618Swnj 
1401899Swnj rkstrategy(bp)
1412618Swnj 	register struct buf *bp;
1421899Swnj {
1432981Swnj 	register struct uba_device *ui;
1442618Swnj 	register struct rkst *st;
1452618Swnj 	register int unit;
1462618Swnj 	register struct buf *dp;
1472618Swnj 	int xunit = minor(bp->b_dev) & 07;
1482618Swnj 	long bn, sz;
1491899Swnj 
1502618Swnj 	sz = (bp->b_bcount+511) >> 9;
1512618Swnj 	unit = dkunit(bp);
1522648Swnj 	if (unit >= NRK)
1532618Swnj 		goto bad;
1542618Swnj 	ui = rkdinfo[unit];
1552618Swnj 	if (ui == 0 || ui->ui_alive == 0)
1562618Swnj 		goto bad;
1572618Swnj 	st = &rkst[ui->ui_type];
1582618Swnj 	if (bp->b_blkno < 0 ||
1592618Swnj 	    (bn = dkblock(bp))+sz > st->sizes[xunit].nblocks)
1602618Swnj 		goto bad;
1612618Swnj 	bp->b_cylin = bn/st->nspc + st->sizes[xunit].cyloff;
1622618Swnj 	(void) spl5();
1632618Swnj 	dp = &rkutab[ui->ui_unit];
1642618Swnj 	disksort(dp, bp);
1652618Swnj 	if (dp->b_active == 0) {
1662618Swnj 		(void) rkustart(ui);
1672618Swnj 		bp = &ui->ui_mi->um_tab;
1682618Swnj 		if (bp->b_actf && bp->b_active == 0)
1692618Swnj 			(void) rkstart(ui->ui_mi);
1701899Swnj 	}
1712618Swnj 	(void) spl0();
1722618Swnj 	return;
1732618Swnj 
1742618Swnj bad:
1752618Swnj 	bp->b_flags |= B_ERROR;
1762618Swnj 	iodone(bp);
1772618Swnj 	return;
1781899Swnj }
1791899Swnj 
1802618Swnj rkustart(ui)
1812981Swnj 	register struct uba_device *ui;
1822618Swnj {
1832618Swnj 	register struct buf *bp, *dp;
1842981Swnj 	register struct uba_ctlr *um;
1852618Swnj 	register struct rkdevice *rkaddr;
1862618Swnj 	int didie = 0;
1871899Swnj 
1882618Swnj 	if (ui == 0)
1892618Swnj 		return (0);
1902618Swnj 	dk_busy &= ~(1<<ui->ui_dk);
1912618Swnj 	dp = &rkutab[ui->ui_unit];
1922618Swnj 	um = ui->ui_mi;
1932894Swnj 	rkaddr = (struct rkdevice *)um->um_addr;
1942618Swnj 	if (um->um_tab.b_active) {
1952618Swnj 		rk_softc[um->um_ctlr].sc_softas |= 1<<ui->ui_slave;
1962618Swnj 		return (0);
1972618Swnj 	}
1982618Swnj 	rkaddr->rkcs1 = RK_CDT|RK_CERR;
1992618Swnj 	rkaddr->rkcs2 = ui->ui_slave;
2002957Swnj 	rkaddr->rkcs1 = RK_CDT|RK_DCLR|RK_GO;
2012618Swnj 	rkwait(rkaddr);
2022903Swnj 	if ((bp = dp->b_actf) == NULL) {
2032903Swnj 		rkaddr->rkcs1 = RK_CDT|RK_DCLR|RK_GO;
2042903Swnj 		rkwait(rkaddr);
2052903Swnj 		return (0);
2062903Swnj 	}
207*3293Swnj 	if ((rkaddr->rkds & RKDS_VV) == 0) {
2082618Swnj 		/* SHOULD WARN SYSTEM THAT THIS HAPPENED */
2092894Swnj 		rkaddr->rkcs1 = RK_CDT|RK_PACK|RK_GO;
2102618Swnj 		rkwait(rkaddr);
2112618Swnj 	}
2122903Swnj 	if (dp->b_active)
2132903Swnj 		goto done;
2142903Swnj 	dp->b_active = 1;
215*3293Swnj 	if ((rkaddr->rkds & RKDS_DREADY) != RKDS_DREADY)
2162894Swnj 		goto done;
2172618Swnj 	if (rk_softc[um->um_ctlr].sc_ndrive == 1)
2182618Swnj 		goto done;
2192618Swnj 	if (bp->b_cylin == rkcyl[ui->ui_unit])
2202618Swnj 		goto done;
2212618Swnj 	rkaddr->rkcyl = bp->b_cylin;
2222618Swnj 	rkcyl[ui->ui_unit] = bp->b_cylin;
2232618Swnj 	rkaddr->rkcs1 = RK_CDT|RK_IE|RK_SEEK|RK_GO;
2242618Swnj 	didie = 1;
2252618Swnj 	if (ui->ui_dk >= 0) {
2262618Swnj 		dk_busy |= 1<<ui->ui_dk;
2272618Swnj 		dk_seek[ui->ui_dk]++;
2282618Swnj 	}
2292618Swnj 	goto out;
2302618Swnj done:
2312618Swnj 	if (dp->b_active != 2) {
2322618Swnj 		dp->b_forw = NULL;
2332618Swnj 		if (um->um_tab.b_actf == NULL)
2342618Swnj 			um->um_tab.b_actf = dp;
2352618Swnj 		else
2362618Swnj 			um->um_tab.b_actl->b_forw = dp;
2372618Swnj 		um->um_tab.b_actl = dp;
2382618Swnj 		dp->b_active = 2;
2392618Swnj 	}
2402618Swnj out:
2412618Swnj 	return (didie);
2422618Swnj }
2432618Swnj 
2442618Swnj rkstart(um)
2452981Swnj 	register struct uba_ctlr *um;
2461899Swnj {
2472618Swnj 	register struct buf *bp, *dp;
2482981Swnj 	register struct uba_device *ui;
2492618Swnj 	register struct rkdevice *rkaddr;
2502618Swnj 	struct rkst *st;
2511899Swnj 	daddr_t bn;
2522618Swnj 	int sn, tn, cmd;
2531899Swnj 
2542618Swnj loop:
2552618Swnj 	if ((dp = um->um_tab.b_actf) == NULL)
2562618Swnj 		return (0);
2572618Swnj 	if ((bp = dp->b_actf) == NULL) {
2582618Swnj 		um->um_tab.b_actf = dp->b_forw;
2592618Swnj 		goto loop;
2601899Swnj 	}
2612618Swnj 	um->um_tab.b_active++;
2622618Swnj 	ui = rkdinfo[dkunit(bp)];
2632618Swnj 	bn = dkblock(bp);
2642618Swnj 	st = &rkst[ui->ui_type];
2652618Swnj 	sn = bn%st->nspc;
2662618Swnj 	tn = sn/st->nsect;
2672618Swnj 	sn %= st->nsect;
2682618Swnj 	rkaddr = (struct rkdevice *)ui->ui_addr;
2692957Swnj retry:
2702618Swnj 	rkaddr->rkcs1 = RK_CDT|RK_CERR;
2712618Swnj 	rkaddr->rkcs2 = ui->ui_slave;
2722957Swnj 	rkaddr->rkcs1 = RK_CDT|RK_DCLR|RK_GO;
2732618Swnj 	rkwait(rkaddr);
274*3293Swnj 	if ((rkaddr->rkds&RKDS_SVAL) == 0) {
2752957Swnj 		rknosval++;
2762957Swnj 		goto nosval;
2772894Swnj 	}
278*3293Swnj 	if (rkaddr->rkds&RKDS_PIP) {
2792957Swnj 		rkpip++;
2802957Swnj 		goto retry;
2812957Swnj 	}
282*3293Swnj 	if ((rkaddr->rkds&RKDS_DREADY) != RKDS_DREADY) {
2832927Swnj 		printf("rk%d: not ready", dkunit(bp));
284*3293Swnj 		if ((rkaddr->rkds&RKDS_DREADY) != RKDS_DREADY) {
2852894Swnj 			printf("\n");
2862894Swnj 			rkaddr->rkcs1 = RK_CDT|RK_DCLR|RK_GO;
2872894Swnj 			rkwait(rkaddr);
2882894Swnj 			rkaddr->rkcs1 = RK_CDT|RK_CERR;
2892894Swnj 			rkwait(rkaddr);
2902894Swnj 			um->um_tab.b_active = 0;
2912894Swnj 			um->um_tab.b_errcnt = 0;
2922894Swnj 			dp->b_actf = bp->av_forw;
2932894Swnj 			dp->b_active = 0;
2942894Swnj 			bp->b_flags |= B_ERROR;
2952894Swnj 			iodone(bp);
2962894Swnj 			goto loop;
2972894Swnj 		}
2982894Swnj 		printf(" (came back!)\n");
2992894Swnj 	}
3002957Swnj nosval:
3012618Swnj 	rkaddr->rkcyl = bp->b_cylin;
3022618Swnj 	rkcyl[ui->ui_unit] = bp->b_cylin;
3032618Swnj 	rkaddr->rkda = (tn << 8) + sn;
3042618Swnj 	rkaddr->rkwc = -bp->b_bcount / sizeof (short);
3052618Swnj 	if (bp->b_flags & B_READ)
3062618Swnj 		cmd = RK_CDT|RK_IE|RK_READ|RK_GO;
3072618Swnj 	else
3082618Swnj 		cmd = RK_CDT|RK_IE|RK_WRITE|RK_GO;
3092618Swnj 	um->um_cmd = cmd;
3103104Swnj 	(void) ubago(ui);
3112618Swnj 	return (1);
3121899Swnj }
3131899Swnj 
3142618Swnj rkdgo(um)
3152981Swnj 	register struct uba_ctlr *um;
3161899Swnj {
3172618Swnj 	register struct rkdevice *rkaddr = (struct rkdevice *)um->um_addr;
3181899Swnj 
3192618Swnj 	rkaddr->rkba = um->um_ubinfo;
3202618Swnj 	rkaddr->rkcs1 = um->um_cmd|((um->um_ubinfo>>8)&0x300);
3212618Swnj }
3222618Swnj 
3232710Swnj rkintr(rk11)
3242618Swnj 	int rk11;
3252618Swnj {
3262981Swnj 	register struct uba_ctlr *um = rkminfo[rk11];
3272981Swnj 	register struct uba_device *ui;
3282618Swnj 	register struct rkdevice *rkaddr = (struct rkdevice *)um->um_addr;
3292618Swnj 	register struct buf *bp, *dp;
3302618Swnj 	int unit;
3312618Swnj 	struct rk_softc *sc = &rk_softc[um->um_ctlr];
3322618Swnj 	int as = (rkaddr->rkatt >> 8) | sc->sc_softas;
3332618Swnj 	int needie = 1;
3342618Swnj 
3352618Swnj 	sc->sc_wticks = 0;
3362618Swnj 	sc->sc_softas = 0;
3372618Swnj 	if (um->um_tab.b_active) {
3382957Swnj 		ubadone(um);
3392618Swnj 		dp = um->um_tab.b_actf;
3402618Swnj 		bp = dp->b_actf;
3412618Swnj 		ui = rkdinfo[dkunit(bp)];
3422618Swnj 		dk_busy &= ~(1 << ui->ui_dk);
3432618Swnj 		if (rkaddr->rkcs1 & RK_CERR) {
3442618Swnj 			int recal;
3452618Swnj 			u_short ds = rkaddr->rkds;
3462618Swnj 			u_short cs2 = rkaddr->rkcs2;
3472618Swnj 			u_short er = rkaddr->rker;
348*3293Swnj 			if (rkdebug) {
349*3293Swnj 				printf("cs2=%b ds=%b er=%b\n",
350*3293Swnj 				    cs2, RKCS2_BITS, ds,
351*3293Swnj 				    RKDS_BITS, er, RKER_BITS);
352*3293Swnj 			}
353*3293Swnj 			if (er & RKER_WLE) {
3542927Swnj 				printf("rk%d: write locked\n", dkunit(bp));
3552685Swnj 				bp->b_flags |= B_ERROR;
3562685Swnj 			} else if (++um->um_tab.b_errcnt > 28 ||
3572676Swnj 			    ds&RKDS_HARD || er&RKER_HARD || cs2&RKCS2_HARD) {
3582927Swnj 				harderr(bp, "rk");
3592927Swnj 				printf("cs2=%b ds=%b er=%b\n",
3602894Swnj 				    cs2, RKCS2_BITS, ds,
3612676Swnj 				    RKDS_BITS, er, RKER_BITS);
3623145Swnj 				bp->b_flags |= B_ERROR;
3633145Swnj 				sc->sc_recal = 0;
3642676Swnj 			} else
3652618Swnj 				um->um_tab.b_active = 0;
366*3293Swnj 			if (cs2&RKCS2_MDS) {
367*3293Swnj 				rkaddr->rkcs2 = RKCS2_SCLR;
3682618Swnj 				goto retry;
3691899Swnj 			}
3702618Swnj 			recal = 0;
371*3293Swnj 			if (ds&RKDS_DROT || er&(RKER_OPI|RKER_SKI|RKER_UNS) ||
3722618Swnj 			    (um->um_tab.b_errcnt&07) == 4)
3732618Swnj 				recal = 1;
374*3293Swnj 			if ((er & (RKER_DCK|RKER_ECH)) == RKER_DCK)
3752618Swnj 				if (rkecc(ui))
3762618Swnj 					return;
3772618Swnj 			rkaddr->rkcs1 = RK_CDT|RK_CCLR;
3782618Swnj 			rkaddr->rkcs2 = ui->ui_slave;
3792618Swnj 			rkaddr->rkcs1 = RK_CDT|RK_DCLR|RK_GO;
3802618Swnj 			rkwait(rkaddr);
3812618Swnj 			if (recal && um->um_tab.b_active == 0) {
3822618Swnj 				rkaddr->rkcs1 = RK_CDT|RK_IE|RK_RECAL|RK_GO;
3832618Swnj 				rkcyl[ui->ui_unit] = -1;
3842957Swnj 				sc->sc_recal = 0;
3852957Swnj 				goto nextrecal;
3862618Swnj 			}
3871899Swnj 		}
3882618Swnj retry:
3892957Swnj 		switch (sc->sc_recal) {
3902957Swnj 
3912957Swnj 		case 1:
3922957Swnj 			rkaddr->rkcyl = bp->b_cylin;
3932957Swnj 			rkcyl[ui->ui_unit] = bp->b_cylin;
3942957Swnj 			rkaddr->rkcs1 = RK_CDT|RK_IE|RK_SEEK|RK_GO;
3952957Swnj 			goto nextrecal;
3962957Swnj 		case 2:
3972957Swnj 			if (um->um_tab.b_errcnt < 16 ||
3983290Swnj 			    (bp->b_flags&B_READ) == 0)
3993159Swnj 				goto donerecal;
4002957Swnj 			rkaddr->rkatt = rk_offset[um->um_tab.b_errcnt & 017];
4012957Swnj 			rkaddr->rkcs1 = RK_CDT|RK_IE|RK_OFFSET|RK_GO;
4022957Swnj 			/* fall into ... */
4032957Swnj 		nextrecal:
4042957Swnj 			sc->sc_recal++;
4052957Swnj 			rkwait(rkaddr);
4062957Swnj 			um->um_tab.b_active = 1;
4072957Swnj 			return;
4083159Swnj 		donerecal:
4092957Swnj 		case 3:
4102618Swnj 			sc->sc_recal = 0;
4112618Swnj 			um->um_tab.b_active = 0;
4122957Swnj 			break;
4131899Swnj 		}
4142618Swnj 		if (um->um_tab.b_active) {
4152618Swnj 			um->um_tab.b_active = 0;
4162618Swnj 			um->um_tab.b_errcnt = 0;
4172618Swnj 			um->um_tab.b_actf = dp->b_forw;
4182618Swnj 			dp->b_active = 0;
4192618Swnj 			dp->b_errcnt = 0;
4202618Swnj 			dp->b_actf = bp->av_forw;
4212618Swnj 			bp->b_resid = -rkaddr->rkwc * sizeof(short);
4222618Swnj 			iodone(bp);
4232618Swnj 			if (dp->b_actf)
4242618Swnj 				if (rkustart(ui))
4252618Swnj 					needie = 0;
4261899Swnj 		}
4272618Swnj 		as &= ~(1<<ui->ui_slave);
4281899Swnj 	}
4292618Swnj 	for (unit = 0; as; as >>= 1, unit++)
4302981Swnj 		if (as & 1) {
4312981Swnj 			ui = rkip[rk11][unit];
4322981Swnj 			if (ui) {
4332981Swnj 				if (rkustart(rkip[rk11][unit]))
4342981Swnj 					needie = 0;
4352981Swnj 			} else {
4362981Swnj 				rkaddr->rkcs1 = RK_CERR|RK_CDT;
4372981Swnj 				rkaddr->rkcs2 = unit;
4382981Swnj 				rkaddr->rkcs1 = RK_CDT|RK_DCLR|RK_GO;
4392981Swnj 				rkwait(rkaddr);
4402981Swnj 			}
4412981Swnj 		}
4422618Swnj 	if (um->um_tab.b_actf && um->um_tab.b_active == 0)
4432618Swnj 		if (rkstart(um))
4442618Swnj 			needie = 0;
4452618Swnj 	if (needie)
4462618Swnj 		rkaddr->rkcs1 = RK_CDT|RK_IE;
4471899Swnj }
4481899Swnj 
4492618Swnj rkwait(addr)
4502618Swnj 	register struct rkdevice *addr;
4512618Swnj {
4521899Swnj 
4532618Swnj 	while ((addr->rkcs1 & RK_CRDY) == 0)
4542618Swnj 		;
4552618Swnj }
4562618Swnj 
4572618Swnj rkread(dev)
4582618Swnj 	dev_t dev;
4591899Swnj {
4602618Swnj 	register int unit = minor(dev) >> 3;
4612618Swnj 
4622648Swnj 	if (unit >= NRK)
4632618Swnj 		u.u_error = ENXIO;
4642618Swnj 	else
4652618Swnj 		physio(rkstrategy, &rrkbuf[unit], dev, B_READ, minphys);
4661899Swnj }
4671899Swnj 
4682618Swnj rkwrite(dev)
4692618Swnj 	dev_t dev;
4701899Swnj {
4712618Swnj 	register int unit = minor(dev) >> 3;
4721899Swnj 
4732648Swnj 	if (unit >= NRK)
4742618Swnj 		u.u_error = ENXIO;
4752618Swnj 	else
4762618Swnj 		physio(rkstrategy, &rrkbuf[unit], dev, B_WRITE, minphys);
4771899Swnj }
4781899Swnj 
4792618Swnj rkecc(ui)
4802981Swnj 	register struct uba_device *ui;
4811899Swnj {
4822618Swnj 	register struct rkdevice *rk = (struct rkdevice *)ui->ui_addr;
4832618Swnj 	register struct buf *bp = rkutab[ui->ui_unit].b_actf;
4842981Swnj 	register struct uba_ctlr *um = ui->ui_mi;
4852618Swnj 	register struct rkst *st;
4862618Swnj 	struct uba_regs *ubp = ui->ui_hd->uh_uba;
4872618Swnj 	register int i;
4882618Swnj 	caddr_t addr;
4892618Swnj 	int reg, bit, byte, npf, mask, o, cmd, ubaddr;
4902618Swnj 	int bn, cn, tn, sn;
4911899Swnj 
4922618Swnj 	npf = btop((rk->rkwc * sizeof(short)) + bp->b_bcount) - 1;
4932618Swnj 	reg = btop(um->um_ubinfo&0x3ffff) + npf;
4942618Swnj 	o = (int)bp->b_un.b_addr & PGOFSET;
4952940Swnj 	printf("rk%d%c: soft ecc sn%d\n", dkunit(bp),
4962885Swnj 	    'a'+(minor(bp->b_dev)&07), bp->b_blkno + npf);
4972618Swnj 	mask = rk->rkec2;
4982724Swnj 	ubapurge(um);
4992618Swnj 	i = rk->rkec1 - 1;		/* -1 makes 0 origin */
5002618Swnj 	bit = i&07;
5012618Swnj 	i = (i&~07)>>3;
5022618Swnj 	byte = i + o;
5032618Swnj 	while (i < 512 && (int)ptob(npf)+i < bp->b_bcount && bit > -11) {
5042618Swnj 		addr = ptob(ubp->uba_map[reg+btop(byte)].pg_pfnum)+
5052618Swnj 		    (byte & PGOFSET);
5062618Swnj 		putmemc(addr, getmemc(addr)^(mask<<bit));
5072618Swnj 		byte++;
5082618Swnj 		i++;
5092618Swnj 		bit -= 8;
5102618Swnj 	}
5112618Swnj 	um->um_tab.b_active++;	/* Either complete or continuing... */
5122618Swnj 	if (rk->rkwc == 0)
5132618Swnj 		return (0);
5142622Swnj #ifdef notdef
5152622Swnj 	rk->rkcs1 |= RK_GO;
5162622Swnj #else
5172618Swnj 	rk->rkcs1 = RK_CDT|RK_CCLR;
5182618Swnj 	rk->rkcs2 = ui->ui_slave;
5192618Swnj 	rk->rkcs1 = RK_CDT|RK_DCLR|RK_GO;
5202618Swnj 	rkwait(rk);
5212618Swnj 	bn = dkblock(bp);
5222618Swnj 	st = &rkst[ui->ui_type];
5232618Swnj 	cn = bp->b_cylin;
5242618Swnj 	sn = bn%st->nspc + npf + 1;
5252618Swnj 	tn = sn/st->nsect;
5262618Swnj 	sn %= st->nsect;
5272618Swnj 	cn += tn/st->ntrak;
5282618Swnj 	tn %= st->ntrak;
5292618Swnj 	rk->rkcyl = cn;
5302618Swnj 	rk->rkda = (tn << 8) | sn;
5312618Swnj 	ubaddr = (int)ptob(reg+1) + o;
5322618Swnj 	rk->rkba = ubaddr;
5332618Swnj 	cmd = (ubaddr >> 8) & 0x300;
5342618Swnj 	cmd |= RK_CDT|RK_IE|RK_GO|RK_READ;
5352618Swnj 	rk->rkcs1 = cmd;
5362622Swnj #endif
5372618Swnj 	return (1);
5381899Swnj }
5391899Swnj 
5402618Swnj rkreset(uban)
5412927Swnj 	int uban;
5421899Swnj {
5432981Swnj 	register struct uba_ctlr *um;
5442981Swnj 	register struct uba_device *ui;
5452618Swnj 	register rk11, unit;
5461899Swnj 
5472648Swnj 	for (rk11 = 0; rk11 < NHK; rk11++) {
5482618Swnj 		if ((um = rkminfo[rk11]) == 0 || um->um_ubanum != uban ||
5492618Swnj 		    um->um_alive == 0)
5502618Swnj 			continue;
5512927Swnj 		printf(" hk%d", rk11);
5522618Swnj 		um->um_tab.b_active = 0;
5532618Swnj 		um->um_tab.b_actf = um->um_tab.b_actl = 0;
5542618Swnj 		rk_softc[um->um_ctlr].sc_recal = 0;
5552618Swnj 		if (um->um_ubinfo) {
5562618Swnj 			printf("<%d>", (um->um_ubinfo>>28)&0xf);
5572618Swnj 			ubadone(um);
5582618Swnj 		}
5592648Swnj 		for (unit = 0; unit < NHK; unit++) {
5602618Swnj 			if ((ui = rkdinfo[unit]) == 0)
5612618Swnj 				continue;
5622618Swnj 			if (ui->ui_alive == 0)
5632618Swnj 				continue;
5642618Swnj 			rkutab[unit].b_active = 0;
5652618Swnj 			(void) rkustart(ui);
5662618Swnj 		}
5672618Swnj 		(void) rkstart(um);
5682618Swnj 	}
5691899Swnj }
5702380Swnj 
5712618Swnj rkwatch()
5722380Swnj {
5732981Swnj 	register struct uba_ctlr *um;
5742618Swnj 	register rk11, unit;
5752618Swnj 	register struct rk_softc *sc;
5762380Swnj 
5772758Swnj 	timeout(rkwatch, (caddr_t)0, hz);
5782648Swnj 	for (rk11 = 0; rk11 < NHK; rk11++) {
5792618Swnj 		um = rkminfo[rk11];
5802618Swnj 		if (um == 0 || um->um_alive == 0)
5812618Swnj 			continue;
5822618Swnj 		sc = &rk_softc[rk11];
5832618Swnj 		if (um->um_tab.b_active == 0) {
5842648Swnj 			for (unit = 0; unit < NRK; unit++)
5852622Swnj 				if (rkutab[unit].b_active &&
5862622Swnj 				    rkdinfo[unit]->ui_mi == um)
5872618Swnj 					goto active;
5882618Swnj 			sc->sc_wticks = 0;
5892618Swnj 			continue;
5902618Swnj 		}
5912618Swnj active:
5922618Swnj 		sc->sc_wticks++;
5932618Swnj 		if (sc->sc_wticks >= 20) {
5942618Swnj 			sc->sc_wticks = 0;
5952927Swnj 			printf("hk%d: lost interrupt\n", rk11);
5962648Swnj 			ubareset(um->um_ubanum);
5972618Swnj 		}
5982618Swnj 	}
5992380Swnj }
6002618Swnj 
6012618Swnj #define	DBSIZE	20
6022618Swnj 
6032618Swnj rkdump(dev)
6042618Swnj 	dev_t dev;
6052618Swnj {
6062618Swnj 	struct rkdevice *rkaddr;
6072618Swnj 	char *start;
6082618Swnj 	int num, blk, unit;
6092618Swnj 	struct size *sizes;
6102618Swnj 	register struct uba_regs *uba;
6112981Swnj 	register struct uba_device *ui;
6122618Swnj 	register short *rp;
6132618Swnj 	struct rkst *st;
6142618Swnj 
6152618Swnj 	unit = minor(dev) >> 3;
6162885Swnj 	if (unit >= NRK)
6172885Swnj 		return (ENXIO);
6182618Swnj #define	phys(cast, addr) ((cast)((int)addr & 0x7fffffff))
6192981Swnj 	ui = phys(struct uba_device *, rkdinfo[unit]);
6202885Swnj 	if (ui->ui_alive == 0)
6212885Swnj 		return (ENXIO);
6222618Swnj 	uba = phys(struct uba_hd *, ui->ui_hd)->uh_physuba;
6232618Swnj #if VAX780
6242618Swnj 	if (cpu == VAX_780)
6252618Swnj 		ubainit(uba);
6261899Swnj #endif
6272618Swnj 	rkaddr = (struct rkdevice *)ui->ui_physaddr;
6282618Swnj 	num = maxfree;
6292618Swnj 	start = 0;
6302618Swnj 	rkaddr->rkcs1 = RK_CDT|RK_CERR;
6312618Swnj 	rkaddr->rkcs2 = unit;
6322618Swnj 	rkaddr->rkcs1 = RK_CDT|RK_DCLR|RK_GO;
6332618Swnj 	rkwait(rkaddr);
634*3293Swnj 	if ((rkaddr->rkds & RKDS_VV) == 0) {
6352618Swnj 		rkaddr->rkcs1 = RK_CDT|RK_IE|RK_PACK|RK_GO;
6362618Swnj 		rkwait(rkaddr);
6372618Swnj 	}
6382618Swnj 	st = &rkst[ui->ui_type];
6392618Swnj 	sizes = phys(struct size *, st->sizes);
6402885Swnj 	if (dumplo < 0 || dumplo + num >= sizes[minor(dev)&07].nblocks)
6412885Swnj 		return (EINVAL);
6422618Swnj 	while (num > 0) {
6432618Swnj 		register struct pte *io;
6442618Swnj 		register int i;
6452618Swnj 		int cn, sn, tn;
6462618Swnj 		daddr_t bn;
6472618Swnj 
6482618Swnj 		blk = num > DBSIZE ? DBSIZE : num;
6492618Swnj 		io = uba->uba_map;
6502618Swnj 		for (i = 0; i < blk; i++)
6512981Swnj 			*(int *)io++ = (btop(start)+i) | (1<<21) | UBAMR_MRV;
6522618Swnj 		*(int *)io = 0;
6532618Swnj 		bn = dumplo + btop(start);
6542618Swnj 		cn = bn/st->nspc + sizes[minor(dev)&07].cyloff;
6552618Swnj 		sn = bn%st->nspc;
6562618Swnj 		tn = sn/st->nsect;
6572618Swnj 		sn = sn%st->nsect;
6582618Swnj 		rkaddr->rkcyl = cn;
6592618Swnj 		rp = (short *) &rkaddr->rkda;
6602618Swnj 		*rp = (tn << 8) + sn;
6612618Swnj 		*--rp = 0;
6622618Swnj 		*--rp = -blk*NBPG / sizeof (short);
6632618Swnj 		*--rp = RK_CDT|RK_GO|RK_WRITE;
6642618Swnj 		rkwait(rkaddr);
6652885Swnj 		if (rkaddr->rkcs1 & RK_CERR)
6662885Swnj 			return (EIO);
6672618Swnj 		start += blk*NBPG;
6682618Swnj 		num -= blk;
6692618Swnj 	}
6702618Swnj 	return (0);
6712618Swnj }
6722618Swnj #endif
673