xref: /csrg-svn/sys/vax/uba/rk.c (revision 9354)
1*9354Ssam /*	rk.c	4.50	82/11/26	*/
21899Swnj 
31942Swnj #include "rk.h"
42648Swnj #if NHK > 0
53104Swnj int	rkpip;		/* DEBUG */
63104Swnj int	rknosval;	/* DEBUG */
73709Sroot #ifdef RKDEBUG
83293Swnj int	rkdebug;
93709Sroot #endif
103709Sroot #ifdef RKBDEBUG
113709Sroot int	rkbdebug;
123709Sroot #endif
131899Swnj /*
143293Swnj  * RK611/RK0[67] disk driver
152622Swnj  *
162622Swnj  * This driver mimics up.c; see it for an explanation of common code.
172685Swnj  *
182885Swnj  * TODO:
193208Swnj  *	Learn why we lose an interrupt sometime when spinning drives down
201899Swnj  */
211899Swnj #include "../h/param.h"
221899Swnj #include "../h/systm.h"
231899Swnj #include "../h/buf.h"
241899Swnj #include "../h/conf.h"
251899Swnj #include "../h/dir.h"
261899Swnj #include "../h/user.h"
271899Swnj #include "../h/pte.h"
281899Swnj #include "../h/map.h"
292618Swnj #include "../h/vm.h"
301899Swnj #include "../h/dk.h"
312618Swnj #include "../h/cmap.h"
323709Sroot #include "../h/dkbad.h"
337731Sroot #include "../h/uio.h"
341899Swnj 
358478Sroot #include "../vax/cpu.h"
368478Sroot #include "../vaxuba/ubareg.h"
378478Sroot #include "../vaxuba/ubavar.h"
388478Sroot #include "../vaxuba/rkreg.h"
391899Swnj 
402618Swnj struct	rk_softc {
412618Swnj 	int	sc_softas;
422618Swnj 	int	sc_ndrive;
432618Swnj 	int	sc_wticks;
442618Swnj 	int	sc_recal;
452648Swnj } rk_softc[NHK];
461899Swnj 
472618Swnj /* THIS SHOULD BE READ OFF THE PACK, PER DRIVE */
482787Swnj struct size {
492618Swnj 	daddr_t	nblocks;
502618Swnj 	int	cyloff;
513709Sroot } rk7_sizes[8] ={
522618Swnj 	15884,	0,		/* A=cyl 0 thru 240 */
532665Swnj 	10032,	241,		/* B=cyl 241 thru 392 */
542665Swnj 	53790,	0,		/* C=cyl 0 thru 814 */
552618Swnj 	0,	0,
562618Swnj 	0,	0,
572618Swnj 	0,	0,
582618Swnj 	27786,	393,		/* G=cyl 393 thru 813 */
592618Swnj 	0,	0,
603709Sroot }, rk6_sizes[8] ={
613709Sroot 	15884,	0,		/* A=cyl 0 thru 240 */
623709Sroot 	11154,	241,		/* B=cyl 241 thru 409 */
633709Sroot 	27126,	0,		/* C=cyl 0 thru 410 */
643709Sroot 	0,	0,
653709Sroot 	0,	0,
663709Sroot 	0,	0,
673709Sroot 	0,	0,
683709Sroot 	0,	0,
692618Swnj };
702618Swnj /* END OF STUFF WHICH SHOULD BE READ IN PER DISK */
711899Swnj 
723709Sroot short	rktypes[] = { RK_CDT, 0 };
733709Sroot 
742618Swnj int	rkprobe(), rkslave(), rkattach(), rkdgo(), rkintr();
752981Swnj struct	uba_ctlr *rkminfo[NHK];
762981Swnj struct	uba_device *rkdinfo[NRK];
772981Swnj struct	uba_device *rkip[NHK][4];
781899Swnj 
792618Swnj u_short	rkstd[] = { 0777440, 0 };
802618Swnj struct	uba_driver hkdriver =
812622Swnj  { rkprobe, rkslave, rkattach, rkdgo, rkstd, "rk", rkdinfo, "hk", rkminfo, 1 };
822648Swnj struct	buf rkutab[NRK];
832648Swnj short	rkcyl[NRK];
843727Sroot #ifndef NOBADSECT
853709Sroot struct	dkbad rkbad[NRK];
863709Sroot struct	buf brkbuf[NRK];
873709Sroot #endif
881899Swnj 
892618Swnj struct	rkst {
902618Swnj 	short	nsect;
912618Swnj 	short	ntrak;
922618Swnj 	short	nspc;
932618Swnj 	short	ncyl;
942618Swnj 	struct	size *sizes;
952618Swnj } rkst[] = {
962618Swnj 	NRKSECT, NRKTRK, NRKSECT*NRKTRK,	NRK7CYL,	rk7_sizes,
973709Sroot 	NRKSECT, NRKTRK, NRKSECT*NRKTRK,	NRK6CYL,	rk6_sizes,
982618Swnj };
991899Swnj 
1002618Swnj u_char 	rk_offset[16] =
1013293Swnj   { RKAS_P400,RKAS_M400,RKAS_P400,RKAS_M400,RKAS_P800,RKAS_M800,RKAS_P800,
1023293Swnj     RKAS_M800,RKAS_P1200,RKAS_M1200,RKAS_P1200,RKAS_M1200,0,0,0,0
1033293Swnj   };
1041899Swnj 
1052648Swnj struct	buf rrkbuf[NRK];
1062618Swnj 
1072618Swnj #define	b_cylin	b_resid
1082618Swnj 
1092618Swnj #ifdef INTRLVE
1102618Swnj daddr_t	dkblock();
1112618Swnj #endif
1122618Swnj 
1132618Swnj int	rkwstart, rkwatch();
1142618Swnj 
1152618Swnj rkprobe(reg)
1162618Swnj 	caddr_t reg;
1171899Swnj {
1182618Swnj 	register int br, cvec;
1191899Swnj 
1202618Swnj #ifdef lint
1212618Swnj 	br = 0; cvec = br; br = cvec;
1224935Swnj 	rkintr(0);
1232618Swnj #endif
1242618Swnj 	((struct rkdevice *)reg)->rkcs1 = RK_CDT|RK_IE|RK_CRDY;
1252618Swnj 	DELAY(10);
1262618Swnj 	((struct rkdevice *)reg)->rkcs1 = RK_CDT;
1277416Skre 	return (sizeof (struct rkdevice));
1282618Swnj }
1291899Swnj 
1302618Swnj rkslave(ui, reg)
1312981Swnj 	struct uba_device *ui;
1322618Swnj 	caddr_t reg;
1332618Swnj {
1342618Swnj 	register struct rkdevice *rkaddr = (struct rkdevice *)reg;
1351899Swnj 
1363709Sroot 	ui->ui_type = 0;
1373709Sroot 	rkaddr->rkcs1 = RK_CCLR;
1382618Swnj 	rkaddr->rkcs2 = ui->ui_slave;
1392957Swnj 	rkaddr->rkcs1 = RK_CDT|RK_DCLR|RK_GO;
1402622Swnj 	rkwait(rkaddr);
1412894Swnj 	DELAY(50);
1423293Swnj 	if (rkaddr->rkcs2&RKCS2_NED || (rkaddr->rkds&RKDS_SVAL) == 0) {
1433709Sroot 		rkaddr->rkcs1 = RK_CCLR;
1442618Swnj 		return (0);
1452618Swnj 	}
1463709Sroot 	if (rkaddr->rkcs1&RK_CERR && rkaddr->rker&RKER_DTYE) {
1473709Sroot 		ui->ui_type = 1;
1483709Sroot 		rkaddr->rkcs1 = RK_CCLR;
1493709Sroot 	}
1502618Swnj 	return (1);
1512618Swnj }
1522618Swnj 
1532618Swnj rkattach(ui)
1542981Swnj 	register struct uba_device *ui;
1552618Swnj {
1562618Swnj 
1572618Swnj 	if (rkwstart == 0) {
1582758Swnj 		timeout(rkwatch, (caddr_t)0, hz);
1592618Swnj 		rkwstart++;
1602618Swnj 	}
1612618Swnj 	if (ui->ui_dk >= 0)
1622758Swnj 		dk_mspw[ui->ui_dk] = 1.0 / (60 * NRKSECT * 256);
1632618Swnj 	rkip[ui->ui_ctlr][ui->ui_slave] = ui;
1642618Swnj 	rk_softc[ui->ui_ctlr].sc_ndrive++;
1652618Swnj 	rkcyl[ui->ui_unit] = -1;
1663709Sroot 	ui->ui_flags = 0;
1672618Swnj }
1682618Swnj 
1698573Sroot rkopen(dev)
1708573Sroot 	dev_t dev;
1718573Sroot {
1728573Sroot 	register int unit = minor(dev) >> 3;
1738573Sroot 	register struct uba_device *ui;
1748573Sroot 
1758573Sroot 	if (unit >= NRK || (ui = rkdinfo[unit]) == 0 || ui->ui_alive == 0)
1768573Sroot 		return (ENXIO);
1778573Sroot 	return (0);
1788573Sroot }
1798573Sroot 
1801899Swnj rkstrategy(bp)
1812618Swnj 	register struct buf *bp;
1821899Swnj {
1832981Swnj 	register struct uba_device *ui;
1842618Swnj 	register struct rkst *st;
1852618Swnj 	register int unit;
1862618Swnj 	register struct buf *dp;
1872618Swnj 	int xunit = minor(bp->b_dev) & 07;
1882618Swnj 	long bn, sz;
1895433Sroot 	int s;
1901899Swnj 
1912618Swnj 	sz = (bp->b_bcount+511) >> 9;
1922618Swnj 	unit = dkunit(bp);
1932648Swnj 	if (unit >= NRK)
1942618Swnj 		goto bad;
1952618Swnj 	ui = rkdinfo[unit];
1962618Swnj 	if (ui == 0 || ui->ui_alive == 0)
1972618Swnj 		goto bad;
1982618Swnj 	st = &rkst[ui->ui_type];
1992618Swnj 	if (bp->b_blkno < 0 ||
2002618Swnj 	    (bn = dkblock(bp))+sz > st->sizes[xunit].nblocks)
2012618Swnj 		goto bad;
2022618Swnj 	bp->b_cylin = bn/st->nspc + st->sizes[xunit].cyloff;
2035433Sroot 	s = spl5();
2042618Swnj 	dp = &rkutab[ui->ui_unit];
2052618Swnj 	disksort(dp, bp);
2062618Swnj 	if (dp->b_active == 0) {
2072618Swnj 		(void) rkustart(ui);
2082618Swnj 		bp = &ui->ui_mi->um_tab;
2092618Swnj 		if (bp->b_actf && bp->b_active == 0)
2102618Swnj 			(void) rkstart(ui->ui_mi);
2111899Swnj 	}
2125433Sroot 	splx(s);
2132618Swnj 	return;
2142618Swnj 
2152618Swnj bad:
2162618Swnj 	bp->b_flags |= B_ERROR;
2172618Swnj 	iodone(bp);
2182618Swnj 	return;
2191899Swnj }
2201899Swnj 
2212618Swnj rkustart(ui)
2222981Swnj 	register struct uba_device *ui;
2232618Swnj {
2242618Swnj 	register struct buf *bp, *dp;
2252981Swnj 	register struct uba_ctlr *um;
2262618Swnj 	register struct rkdevice *rkaddr;
2271899Swnj 
2282618Swnj 	if (ui == 0)
2296347Swnj 		return;
2302618Swnj 	dk_busy &= ~(1<<ui->ui_dk);
2312618Swnj 	dp = &rkutab[ui->ui_unit];
2322618Swnj 	um = ui->ui_mi;
2332894Swnj 	rkaddr = (struct rkdevice *)um->um_addr;
2342618Swnj 	if (um->um_tab.b_active) {
2352618Swnj 		rk_softc[um->um_ctlr].sc_softas |= 1<<ui->ui_slave;
2366347Swnj 		return;
2372618Swnj 	}
2386347Swnj 	if ((bp = dp->b_actf) == NULL)
2396347Swnj 		return;
2403709Sroot 	rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_CERR;
2412618Swnj 	rkaddr->rkcs2 = ui->ui_slave;
2423709Sroot 	rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO;
2432618Swnj 	rkwait(rkaddr);
2443709Sroot 	if ((rkaddr->rkds & RKDS_VV) == 0 || ui->ui_flags == 0) {
2452618Swnj 		/* SHOULD WARN SYSTEM THAT THIS HAPPENED */
2463727Sroot #ifndef NOBADSECT
2473709Sroot 		struct rkst *st = &rkst[ui->ui_type];
2483709Sroot 		struct buf *bbp = &brkbuf[ui->ui_unit];
2493709Sroot #endif
2503709Sroot 
2513709Sroot 		rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_PACK|RK_GO;
2523709Sroot 		ui->ui_flags = 1;
2533727Sroot #ifndef NOBADSECT
2543709Sroot 		bbp->b_flags = B_READ|B_BUSY;
2553709Sroot 		bbp->b_dev = bp->b_dev;
2563709Sroot 		bbp->b_bcount = 512;
2573709Sroot 		bbp->b_un.b_addr = (caddr_t)&rkbad[ui->ui_unit];
2583709Sroot 		bbp->b_blkno = st->ncyl*st->nspc - st->nsect;
2593709Sroot 		bbp->b_cylin = st->ncyl - 1;
2603709Sroot 		dp->b_actf = bbp;
2613709Sroot 		bbp->av_forw = bp;
2623709Sroot 		bp = bbp;
2633709Sroot #endif
2642618Swnj 		rkwait(rkaddr);
2652618Swnj 	}
2662903Swnj 	if (dp->b_active)
2672903Swnj 		goto done;
2682903Swnj 	dp->b_active = 1;
2693293Swnj 	if ((rkaddr->rkds & RKDS_DREADY) != RKDS_DREADY)
2702894Swnj 		goto done;
2712618Swnj 	if (rk_softc[um->um_ctlr].sc_ndrive == 1)
2722618Swnj 		goto done;
2732618Swnj 	if (bp->b_cylin == rkcyl[ui->ui_unit])
2742618Swnj 		goto done;
2752618Swnj 	rkaddr->rkcyl = bp->b_cylin;
2762618Swnj 	rkcyl[ui->ui_unit] = bp->b_cylin;
2773709Sroot 	rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_IE|RK_SEEK|RK_GO;
2782618Swnj 	if (ui->ui_dk >= 0) {
2792618Swnj 		dk_busy |= 1<<ui->ui_dk;
2802618Swnj 		dk_seek[ui->ui_dk]++;
2812618Swnj 	}
2822618Swnj 	goto out;
2832618Swnj done:
2842618Swnj 	if (dp->b_active != 2) {
2852618Swnj 		dp->b_forw = NULL;
2862618Swnj 		if (um->um_tab.b_actf == NULL)
2872618Swnj 			um->um_tab.b_actf = dp;
2882618Swnj 		else
2892618Swnj 			um->um_tab.b_actl->b_forw = dp;
2902618Swnj 		um->um_tab.b_actl = dp;
2912618Swnj 		dp->b_active = 2;
2922618Swnj 	}
2932618Swnj out:
2946347Swnj 	return;
2952618Swnj }
2962618Swnj 
2972618Swnj rkstart(um)
2982981Swnj 	register struct uba_ctlr *um;
2991899Swnj {
3002618Swnj 	register struct buf *bp, *dp;
3012981Swnj 	register struct uba_device *ui;
3022618Swnj 	register struct rkdevice *rkaddr;
3032618Swnj 	struct rkst *st;
3041899Swnj 	daddr_t bn;
3052618Swnj 	int sn, tn, cmd;
3061899Swnj 
3072618Swnj loop:
3082618Swnj 	if ((dp = um->um_tab.b_actf) == NULL)
3096347Swnj 		return;
3102618Swnj 	if ((bp = dp->b_actf) == NULL) {
3112618Swnj 		um->um_tab.b_actf = dp->b_forw;
3122618Swnj 		goto loop;
3131899Swnj 	}
3142618Swnj 	um->um_tab.b_active++;
3152618Swnj 	ui = rkdinfo[dkunit(bp)];
3162618Swnj 	bn = dkblock(bp);
3172618Swnj 	st = &rkst[ui->ui_type];
3182618Swnj 	sn = bn%st->nspc;
3192618Swnj 	tn = sn/st->nsect;
3202618Swnj 	sn %= st->nsect;
3212618Swnj 	rkaddr = (struct rkdevice *)ui->ui_addr;
3222957Swnj retry:
3233709Sroot 	rkaddr->rkcs1 = RK_CCLR;
3242618Swnj 	rkaddr->rkcs2 = ui->ui_slave;
3253709Sroot 	rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO;
3262618Swnj 	rkwait(rkaddr);
3273293Swnj 	if ((rkaddr->rkds&RKDS_SVAL) == 0) {
3282957Swnj 		rknosval++;
3292957Swnj 		goto nosval;
3302894Swnj 	}
3313293Swnj 	if (rkaddr->rkds&RKDS_PIP) {
3322957Swnj 		rkpip++;
3332957Swnj 		goto retry;
3342957Swnj 	}
3353293Swnj 	if ((rkaddr->rkds&RKDS_DREADY) != RKDS_DREADY) {
3362927Swnj 		printf("rk%d: not ready", dkunit(bp));
3373293Swnj 		if ((rkaddr->rkds&RKDS_DREADY) != RKDS_DREADY) {
3382894Swnj 			printf("\n");
3393709Sroot 			rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO;
3402894Swnj 			rkwait(rkaddr);
3413709Sroot 			rkaddr->rkcs1 = RK_CCLR;
3422894Swnj 			rkwait(rkaddr);
3432894Swnj 			um->um_tab.b_active = 0;
3442894Swnj 			um->um_tab.b_errcnt = 0;
3452894Swnj 			dp->b_actf = bp->av_forw;
3462894Swnj 			dp->b_active = 0;
3472894Swnj 			bp->b_flags |= B_ERROR;
3482894Swnj 			iodone(bp);
3492894Swnj 			goto loop;
3502894Swnj 		}
3512894Swnj 		printf(" (came back!)\n");
3522894Swnj 	}
3532957Swnj nosval:
3542618Swnj 	rkaddr->rkcyl = bp->b_cylin;
3552618Swnj 	rkcyl[ui->ui_unit] = bp->b_cylin;
3562618Swnj 	rkaddr->rkda = (tn << 8) + sn;
3572618Swnj 	rkaddr->rkwc = -bp->b_bcount / sizeof (short);
3582618Swnj 	if (bp->b_flags & B_READ)
3593709Sroot 		cmd = rktypes[ui->ui_type]|RK_IE|RK_READ|RK_GO;
3602618Swnj 	else
3613709Sroot 		cmd = rktypes[ui->ui_type]|RK_IE|RK_WRITE|RK_GO;
3622618Swnj 	um->um_cmd = cmd;
3633104Swnj 	(void) ubago(ui);
3641899Swnj }
3651899Swnj 
3662618Swnj rkdgo(um)
3672981Swnj 	register struct uba_ctlr *um;
3681899Swnj {
3692618Swnj 	register struct rkdevice *rkaddr = (struct rkdevice *)um->um_addr;
3701899Swnj 
3717031Swnj 	um->um_tab.b_active = 2;	/* should now be 2 */
3722618Swnj 	rkaddr->rkba = um->um_ubinfo;
3732618Swnj 	rkaddr->rkcs1 = um->um_cmd|((um->um_ubinfo>>8)&0x300);
3742618Swnj }
3752618Swnj 
3762710Swnj rkintr(rk11)
3772618Swnj 	int rk11;
3782618Swnj {
3792981Swnj 	register struct uba_ctlr *um = rkminfo[rk11];
3802981Swnj 	register struct uba_device *ui;
3812618Swnj 	register struct rkdevice *rkaddr = (struct rkdevice *)um->um_addr;
3822618Swnj 	register struct buf *bp, *dp;
3832618Swnj 	int unit;
3842618Swnj 	struct rk_softc *sc = &rk_softc[um->um_ctlr];
3852618Swnj 	int as = (rkaddr->rkatt >> 8) | sc->sc_softas;
3862618Swnj 
3872618Swnj 	sc->sc_wticks = 0;
3882618Swnj 	sc->sc_softas = 0;
3896347Swnj 	if (um->um_tab.b_active == 2 || sc->sc_recal) {
3907031Swnj 		um->um_tab.b_active = 1;
3912618Swnj 		dp = um->um_tab.b_actf;
3922618Swnj 		bp = dp->b_actf;
3932618Swnj 		ui = rkdinfo[dkunit(bp)];
3942618Swnj 		dk_busy &= ~(1 << ui->ui_dk);
3953727Sroot #ifndef NOBADSECT
3963709Sroot 		if (bp->b_flags&B_BAD)
3973709Sroot 			if (rkecc(ui, CONT))
3983709Sroot 				return;
3993709Sroot #endif
4002618Swnj 		if (rkaddr->rkcs1 & RK_CERR) {
4012618Swnj 			int recal;
4022618Swnj 			u_short ds = rkaddr->rkds;
4032618Swnj 			u_short cs2 = rkaddr->rkcs2;
4042618Swnj 			u_short er = rkaddr->rker;
4053709Sroot #ifdef RKDEBUG
4063293Swnj 			if (rkdebug) {
4073293Swnj 				printf("cs2=%b ds=%b er=%b\n",
4083293Swnj 				    cs2, RKCS2_BITS, ds,
4093293Swnj 				    RKDS_BITS, er, RKER_BITS);
4103293Swnj 			}
4113709Sroot #endif
4123293Swnj 			if (er & RKER_WLE) {
4132927Swnj 				printf("rk%d: write locked\n", dkunit(bp));
4142685Swnj 				bp->b_flags |= B_ERROR;
4152685Swnj 			} else if (++um->um_tab.b_errcnt > 28 ||
4162676Swnj 			    ds&RKDS_HARD || er&RKER_HARD || cs2&RKCS2_HARD) {
4173709Sroot hard:
4182927Swnj 				harderr(bp, "rk");
4192927Swnj 				printf("cs2=%b ds=%b er=%b\n",
4202894Swnj 				    cs2, RKCS2_BITS, ds,
4212676Swnj 				    RKDS_BITS, er, RKER_BITS);
4223145Swnj 				bp->b_flags |= B_ERROR;
4233145Swnj 				sc->sc_recal = 0;
4243709Sroot 			} else if (er & RKER_BSE) {
4253727Sroot #ifndef NOBADSECT
4263709Sroot 				if (rkecc(ui, BSE))
4273709Sroot 					return;
4283709Sroot 				else
4293709Sroot #endif
4303709Sroot 					goto hard;
4317182Sroot 			} else {
4327182Sroot 				if ((er & (RKER_DCK|RKER_ECH)) == RKER_DCK) {
4337182Sroot 					if (rkecc(ui, ECC))
4347182Sroot 						return;
4357182Sroot 				} else
4367182Sroot 					um->um_tab.b_active = 0;
4377182Sroot 			}
4383293Swnj 			if (cs2&RKCS2_MDS) {
4393293Swnj 				rkaddr->rkcs2 = RKCS2_SCLR;
4402618Swnj 				goto retry;
4411899Swnj 			}
4422618Swnj 			recal = 0;
4433293Swnj 			if (ds&RKDS_DROT || er&(RKER_OPI|RKER_SKI|RKER_UNS) ||
4442618Swnj 			    (um->um_tab.b_errcnt&07) == 4)
4452618Swnj 				recal = 1;
4463709Sroot 			rkaddr->rkcs1 = RK_CCLR;
4472618Swnj 			rkaddr->rkcs2 = ui->ui_slave;
4483709Sroot 			rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO;
4492618Swnj 			rkwait(rkaddr);
4502618Swnj 			if (recal && um->um_tab.b_active == 0) {
4513709Sroot 				rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_IE|RK_RECAL|RK_GO;
4522618Swnj 				rkcyl[ui->ui_unit] = -1;
4532957Swnj 				sc->sc_recal = 0;
4542957Swnj 				goto nextrecal;
4552618Swnj 			}
4561899Swnj 		}
4572618Swnj retry:
4582957Swnj 		switch (sc->sc_recal) {
4592957Swnj 
4602957Swnj 		case 1:
4612957Swnj 			rkaddr->rkcyl = bp->b_cylin;
4622957Swnj 			rkcyl[ui->ui_unit] = bp->b_cylin;
4633709Sroot 			rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_IE|RK_SEEK|RK_GO;
4642957Swnj 			goto nextrecal;
4652957Swnj 		case 2:
4662957Swnj 			if (um->um_tab.b_errcnt < 16 ||
4673290Swnj 			    (bp->b_flags&B_READ) == 0)
4683159Swnj 				goto donerecal;
4692957Swnj 			rkaddr->rkatt = rk_offset[um->um_tab.b_errcnt & 017];
4703709Sroot 			rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_IE|RK_OFFSET|RK_GO;
4712957Swnj 			/* fall into ... */
4722957Swnj 		nextrecal:
4732957Swnj 			sc->sc_recal++;
4742957Swnj 			rkwait(rkaddr);
4752957Swnj 			um->um_tab.b_active = 1;
4762957Swnj 			return;
4773159Swnj 		donerecal:
4782957Swnj 		case 3:
4792618Swnj 			sc->sc_recal = 0;
4802618Swnj 			um->um_tab.b_active = 0;
4812957Swnj 			break;
4821899Swnj 		}
4833709Sroot 		ubadone(um);
4842618Swnj 		if (um->um_tab.b_active) {
4852618Swnj 			um->um_tab.b_active = 0;
4862618Swnj 			um->um_tab.b_errcnt = 0;
4872618Swnj 			um->um_tab.b_actf = dp->b_forw;
4882618Swnj 			dp->b_active = 0;
4892618Swnj 			dp->b_errcnt = 0;
4902618Swnj 			dp->b_actf = bp->av_forw;
4912618Swnj 			bp->b_resid = -rkaddr->rkwc * sizeof(short);
4922618Swnj 			iodone(bp);
4932618Swnj 			if (dp->b_actf)
4946347Swnj 				rkustart(ui);
4951899Swnj 		}
4962618Swnj 		as &= ~(1<<ui->ui_slave);
4971899Swnj 	}
4982618Swnj 	for (unit = 0; as; as >>= 1, unit++)
4992981Swnj 		if (as & 1) {
5002981Swnj 			ui = rkip[rk11][unit];
5012981Swnj 			if (ui) {
5026347Swnj 				rkustart(rkip[rk11][unit]);
5032981Swnj 			} else {
5043709Sroot 				rkaddr->rkcs1 = RK_CCLR;
5052981Swnj 				rkaddr->rkcs2 = unit;
5063709Sroot 				rkaddr->rkcs1 = RK_DCLR|RK_GO;
5072981Swnj 				rkwait(rkaddr);
5083709Sroot 				rkaddr->rkcs1 = RK_CCLR;
5092981Swnj 			}
5102981Swnj 		}
5112618Swnj 	if (um->um_tab.b_actf && um->um_tab.b_active == 0)
5126347Swnj 		rkstart(um);
5138609Sroot 	if (((rkaddr->rkcs1) & RK_IE) == 0)
5143709Sroot 		rkaddr->rkcs1 = RK_IE;
5151899Swnj }
5161899Swnj 
5172618Swnj rkwait(addr)
5182618Swnj 	register struct rkdevice *addr;
5192618Swnj {
5201899Swnj 
5212618Swnj 	while ((addr->rkcs1 & RK_CRDY) == 0)
5222618Swnj 		;
5232618Swnj }
5242618Swnj 
5257731Sroot rkread(dev, uio)
5262618Swnj 	dev_t dev;
5277731Sroot 	struct uio *uio;
5281899Swnj {
5292618Swnj 	register int unit = minor(dev) >> 3;
5302618Swnj 
5312648Swnj 	if (unit >= NRK)
5328162Sroot 		return (ENXIO);
5338162Sroot 	return (physio(rkstrategy, &rrkbuf[unit], dev, B_READ, minphys, uio));
5341899Swnj }
5351899Swnj 
5367836Sroot rkwrite(dev, uio)
5372618Swnj 	dev_t dev;
5387836Sroot 	struct uio *uio;
5391899Swnj {
5402618Swnj 	register int unit = minor(dev) >> 3;
5411899Swnj 
5422648Swnj 	if (unit >= NRK)
5438493Sroot 		return (ENXIO);
5448493Sroot 	return (physio(rkstrategy, &rrkbuf[unit], dev, B_WRITE, minphys, uio));
5451899Swnj }
5461899Swnj 
5473709Sroot rkecc(ui, flag)
5482981Swnj 	register struct uba_device *ui;
5491899Swnj {
5502618Swnj 	register struct rkdevice *rk = (struct rkdevice *)ui->ui_addr;
5512618Swnj 	register struct buf *bp = rkutab[ui->ui_unit].b_actf;
5522981Swnj 	register struct uba_ctlr *um = ui->ui_mi;
5532618Swnj 	register struct rkst *st;
5542618Swnj 	struct uba_regs *ubp = ui->ui_hd->uh_uba;
5552618Swnj 	caddr_t addr;
5563709Sroot 	int reg, npf, o, cmd, ubaddr;
5572618Swnj 	int bn, cn, tn, sn;
5581899Swnj 
5593727Sroot #ifndef NOBADSECT
5603709Sroot 	if (flag == CONT)
5613709Sroot 		npf = bp->b_error;
5623709Sroot 	else
5633709Sroot #endif
5643709Sroot 		npf = btop((rk->rkwc * sizeof(short)) + bp->b_bcount);
5652618Swnj 	reg = btop(um->um_ubinfo&0x3ffff) + npf;
5662618Swnj 	o = (int)bp->b_un.b_addr & PGOFSET;
5672618Swnj 	bn = dkblock(bp);
5682618Swnj 	st = &rkst[ui->ui_type];
5692618Swnj 	cn = bp->b_cylin;
5703709Sroot 	sn = bn%st->nspc + npf;
5712618Swnj 	tn = sn/st->nsect;
5722618Swnj 	sn %= st->nsect;
5732618Swnj 	cn += tn/st->ntrak;
5742618Swnj 	tn %= st->ntrak;
5753709Sroot 	ubapurge(um);
5763709Sroot 	switch (flag) {
5773709Sroot 	case ECC:
5783709Sroot 		{
5793709Sroot 		register int i;
5803709Sroot 		int bit, byte, mask;
5813709Sroot 
5823709Sroot 		npf--;
5833709Sroot 		reg--;
5843709Sroot 		printf("rk%d%c: soft ecc sn%d\n", dkunit(bp),
5853709Sroot 		    'a'+(minor(bp->b_dev)&07), bp->b_blkno + npf);
5863709Sroot 		mask = rk->rkec2;
5873709Sroot 		i = rk->rkec1 - 1;		/* -1 makes 0 origin */
5883709Sroot 		bit = i&07;
5893709Sroot 		i = (i&~07)>>3;
5903709Sroot 		byte = i + o;
5913709Sroot 		while (i < 512 && (int)ptob(npf)+i < bp->b_bcount && bit > -11) {
5923709Sroot 			addr = ptob(ubp->uba_map[reg+btop(byte)].pg_pfnum)+
5933709Sroot 			    (byte & PGOFSET);
5943709Sroot 			putmemc(addr, getmemc(addr)^(mask<<bit));
5953709Sroot 			byte++;
5963709Sroot 			i++;
5973709Sroot 			bit -= 8;
5983709Sroot 		}
5997182Sroot 		if (rk->rkwc == 0) {
6007182Sroot 			um->um_tab.b_active = 0;
6013709Sroot 			return (0);
6027182Sroot 		}
6033709Sroot 		npf++;
6043709Sroot 		reg++;
6053709Sroot 		break;
6063709Sroot 		}
6073709Sroot 
6083727Sroot #ifndef NOBADSECT
6093709Sroot 	case BSE:
6103709Sroot #ifdef RKBDEBUG
6113709Sroot 		if (rkbdebug)
6123709Sroot 	printf("rkecc, BSE: bn %d cn %d tn %d sn %d\n", bn, cn, tn, sn);
6133709Sroot #endif
6143709Sroot 		if ((bn = isbad(&rkbad[ui->ui_unit], cn, tn, sn)) < 0)
6153709Sroot 			return(0);
6163709Sroot 		bp->b_flags |= B_BAD;
6173709Sroot 		bp->b_error = npf + 1;
6183709Sroot 		bn = st->ncyl*st->nspc - st->nsect - 1 - bn;
6193709Sroot 		cn = bn/st->nspc;
6203709Sroot 		sn = bn%st->nspc;
6213709Sroot 		tn = sn/st->nsect;
6223709Sroot 		sn %= st->nsect;
6233709Sroot #ifdef RKBDEBUG
6243709Sroot 		if (rkbdebug)
6253709Sroot 	printf("revector to cn %d tn %d sn %d\n", cn, tn, sn);
6263709Sroot #endif
6273709Sroot 		rk->rkwc = -(512 / sizeof (short));
6283709Sroot 		break;
6293709Sroot 
6303709Sroot 	case CONT:
6313709Sroot #ifdef RKBDEBUG
6323709Sroot 		if (rkbdebug)
6333709Sroot 	printf("rkecc, CONT: bn %d cn %d tn %d sn %d\n", bn,cn,tn,sn);
6343709Sroot #endif
6353709Sroot 		bp->b_flags &= ~B_BAD;
6363709Sroot 		rk->rkwc = -((bp->b_bcount - (int)ptob(npf)) / sizeof (short));
6377182Sroot 		if (rk->rkwc == 0) {
6387182Sroot 			um->um_tab.b_active = 0;
6397182Sroot 			return (0);
6407182Sroot 		}
6413709Sroot 		break;
6423709Sroot #endif
6433709Sroot 	}
6443709Sroot 	rk->rkcs1 = RK_CCLR;
6453709Sroot 	rk->rkcs2 = ui->ui_slave;
6463709Sroot 	rk->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO;
6473709Sroot 	rkwait(rk);
6482618Swnj 	rk->rkcyl = cn;
6492618Swnj 	rk->rkda = (tn << 8) | sn;
6503709Sroot 	ubaddr = (int)ptob(reg) + o;
6512618Swnj 	rk->rkba = ubaddr;
6523709Sroot 	cmd = (bp->b_flags&B_READ ? RK_READ : RK_WRITE)|RK_IE|RK_GO;
6533709Sroot 	cmd |= (ubaddr >> 8) & 0x300;
6543709Sroot 	cmd |= rktypes[ui->ui_type];
6552618Swnj 	rk->rkcs1 = cmd;
6567031Swnj 	um->um_tab.b_active = 2;	/* continuing */
6573709Sroot 	um->um_tab.b_errcnt = 0;	/* error has been corrected */
6582618Swnj 	return (1);
6591899Swnj }
6601899Swnj 
6612618Swnj rkreset(uban)
6622927Swnj 	int uban;
6631899Swnj {
6642981Swnj 	register struct uba_ctlr *um;
6652981Swnj 	register struct uba_device *ui;
6662618Swnj 	register rk11, unit;
6671899Swnj 
6682648Swnj 	for (rk11 = 0; rk11 < NHK; rk11++) {
6692618Swnj 		if ((um = rkminfo[rk11]) == 0 || um->um_ubanum != uban ||
6702618Swnj 		    um->um_alive == 0)
6712618Swnj 			continue;
6722927Swnj 		printf(" hk%d", rk11);
6732618Swnj 		um->um_tab.b_active = 0;
6742618Swnj 		um->um_tab.b_actf = um->um_tab.b_actl = 0;
6752618Swnj 		rk_softc[um->um_ctlr].sc_recal = 0;
6766347Swnj 		rk_softc[um->um_ctlr].sc_wticks = 0;
6772618Swnj 		if (um->um_ubinfo) {
6782618Swnj 			printf("<%d>", (um->um_ubinfo>>28)&0xf);
679*9354Ssam 			um->um_ubinfo = 0;
6802618Swnj 		}
6814039Swnj 		for (unit = 0; unit < NRK; unit++) {
6822618Swnj 			if ((ui = rkdinfo[unit]) == 0)
6832618Swnj 				continue;
6844039Swnj 			if (ui->ui_alive == 0 || ui->ui_mi != um)
6852618Swnj 				continue;
6862618Swnj 			rkutab[unit].b_active = 0;
6872618Swnj 			(void) rkustart(ui);
6882618Swnj 		}
6892618Swnj 		(void) rkstart(um);
6902618Swnj 	}
6911899Swnj }
6922380Swnj 
6932618Swnj rkwatch()
6942380Swnj {
6952981Swnj 	register struct uba_ctlr *um;
6962618Swnj 	register rk11, unit;
6972618Swnj 	register struct rk_softc *sc;
6982380Swnj 
6992758Swnj 	timeout(rkwatch, (caddr_t)0, hz);
7002648Swnj 	for (rk11 = 0; rk11 < NHK; rk11++) {
7012618Swnj 		um = rkminfo[rk11];
7022618Swnj 		if (um == 0 || um->um_alive == 0)
7032618Swnj 			continue;
7042618Swnj 		sc = &rk_softc[rk11];
7052618Swnj 		if (um->um_tab.b_active == 0) {
7062648Swnj 			for (unit = 0; unit < NRK; unit++)
7072622Swnj 				if (rkutab[unit].b_active &&
7082622Swnj 				    rkdinfo[unit]->ui_mi == um)
7092618Swnj 					goto active;
7102618Swnj 			sc->sc_wticks = 0;
7112618Swnj 			continue;
7122618Swnj 		}
7132618Swnj active:
7142618Swnj 		sc->sc_wticks++;
7152618Swnj 		if (sc->sc_wticks >= 20) {
7162618Swnj 			sc->sc_wticks = 0;
7172927Swnj 			printf("hk%d: lost interrupt\n", rk11);
7182648Swnj 			ubareset(um->um_ubanum);
7192618Swnj 		}
7202618Swnj 	}
7212380Swnj }
7222618Swnj 
7232618Swnj #define	DBSIZE	20
7242618Swnj 
7252618Swnj rkdump(dev)
7262618Swnj 	dev_t dev;
7272618Swnj {
7282618Swnj 	struct rkdevice *rkaddr;
7292618Swnj 	char *start;
7302618Swnj 	int num, blk, unit;
7312618Swnj 	struct size *sizes;
7322618Swnj 	register struct uba_regs *uba;
7332981Swnj 	register struct uba_device *ui;
7342618Swnj 	register short *rp;
7352618Swnj 	struct rkst *st;
7362618Swnj 
7372618Swnj 	unit = minor(dev) >> 3;
7382885Swnj 	if (unit >= NRK)
7392885Swnj 		return (ENXIO);
7402618Swnj #define	phys(cast, addr) ((cast)((int)addr & 0x7fffffff))
7412981Swnj 	ui = phys(struct uba_device *, rkdinfo[unit]);
7422885Swnj 	if (ui->ui_alive == 0)
7432885Swnj 		return (ENXIO);
7442618Swnj 	uba = phys(struct uba_hd *, ui->ui_hd)->uh_physuba;
7453329Swnj 	ubainit(uba);
7462618Swnj 	rkaddr = (struct rkdevice *)ui->ui_physaddr;
7472618Swnj 	num = maxfree;
7482618Swnj 	start = 0;
7493709Sroot 	rkaddr->rkcs1 = RK_CCLR;
7502618Swnj 	rkaddr->rkcs2 = unit;
7513709Sroot 	rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO;
7522618Swnj 	rkwait(rkaddr);
7533293Swnj 	if ((rkaddr->rkds & RKDS_VV) == 0) {
7543709Sroot 		rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_IE|RK_PACK|RK_GO;
7552618Swnj 		rkwait(rkaddr);
7562618Swnj 	}
7572618Swnj 	st = &rkst[ui->ui_type];
7582618Swnj 	sizes = phys(struct size *, st->sizes);
7592885Swnj 	if (dumplo < 0 || dumplo + num >= sizes[minor(dev)&07].nblocks)
7602885Swnj 		return (EINVAL);
7612618Swnj 	while (num > 0) {
7622618Swnj 		register struct pte *io;
7632618Swnj 		register int i;
7642618Swnj 		int cn, sn, tn;
7652618Swnj 		daddr_t bn;
7662618Swnj 
7672618Swnj 		blk = num > DBSIZE ? DBSIZE : num;
7682618Swnj 		io = uba->uba_map;
7692618Swnj 		for (i = 0; i < blk; i++)
7702981Swnj 			*(int *)io++ = (btop(start)+i) | (1<<21) | UBAMR_MRV;
7712618Swnj 		*(int *)io = 0;
7722618Swnj 		bn = dumplo + btop(start);
7732618Swnj 		cn = bn/st->nspc + sizes[minor(dev)&07].cyloff;
7742618Swnj 		sn = bn%st->nspc;
7752618Swnj 		tn = sn/st->nsect;
7762618Swnj 		sn = sn%st->nsect;
7772618Swnj 		rkaddr->rkcyl = cn;
7782618Swnj 		rp = (short *) &rkaddr->rkda;
7792618Swnj 		*rp = (tn << 8) + sn;
7802618Swnj 		*--rp = 0;
7812618Swnj 		*--rp = -blk*NBPG / sizeof (short);
7823709Sroot 		*--rp = rktypes[ui->ui_type]|RK_GO|RK_WRITE;
7832618Swnj 		rkwait(rkaddr);
7842885Swnj 		if (rkaddr->rkcs1 & RK_CERR)
7852885Swnj 			return (EIO);
7862618Swnj 		start += blk*NBPG;
7872618Swnj 		num -= blk;
7882618Swnj 	}
7892618Swnj 	return (0);
7902618Swnj }
7912618Swnj #endif
792