xref: /csrg-svn/sys/vax/mba/hp.c (revision 3847)
1*3847Sroot /*	hp.c	4.40	81/06/03	*/
23706Sroot 
33706Sroot #ifdef HPDEBUG
43289Swnj int	hpdebug;
53706Sroot #endif
63706Sroot #ifdef HPBDEBUG
73706Sroot int	hpbdebug;
83706Sroot #endif
921Sbill 
101939Swnj #include "hp.h"
111565Sbill #if NHP > 0
1221Sbill /*
133706Sroot  * HP disk driver for RP0x+RMxx
142827Swnj  *
152827Swnj  * TODO:
163706Sroot  *	check RM80 skip sector handling when ECC's occur later
173093Swnj  *	check offset recovery handling
183706Sroot  *	see if DCLR and/or RELEASE set attention status
193706Sroot  *	print bits of mr && mr2 symbolically
2021Sbill  */
2121Sbill 
2221Sbill #include "../h/param.h"
2321Sbill #include "../h/systm.h"
24305Sbill #include "../h/dk.h"
2521Sbill #include "../h/buf.h"
2621Sbill #include "../h/conf.h"
2721Sbill #include "../h/dir.h"
2821Sbill #include "../h/user.h"
2921Sbill #include "../h/map.h"
30420Sbill #include "../h/pte.h"
312978Swnj #include "../h/mbareg.h"
322978Swnj #include "../h/mbavar.h"
3321Sbill #include "../h/mtpr.h"
34420Sbill #include "../h/vm.h"
352362Swnj #include "../h/cmap.h"
363706Sroot #include "../h/dkbad.h"
3721Sbill 
382383Swnj #include "../h/hpreg.h"
3921Sbill 
402383Swnj /* THIS SHOULD BE READ OFF THE PACK, PER DRIVE */
412383Swnj struct	size {
4221Sbill 	daddr_t	nblocks;
4321Sbill 	int	cyloff;
443706Sroot } hp6_sizes[8] = {
45886Sbill 	15884,	0,		/* A=cyl 0 thru 37 */
46886Sbill 	33440,	38,		/* B=cyl 38 thru 117 */
47886Sbill 	340670,	0,		/* C=cyl 0 thru 814 */
4821Sbill 	0,	0,
4921Sbill 	0,	0,
5021Sbill 	0,	0,
513726Sroot #ifndef NOBADSECT
523729Sroot 	291280,	118,		/* G=cyl 118 thru 814 */
533706Sroot #else
543706Sroot 	291346,	118,
553706Sroot #endif
5621Sbill 	0,	0,
573706Sroot }, rm3_sizes[8] = {
58886Sbill 	15884,	0,		/* A=cyl 0 thru 99 */
59886Sbill 	33440,	100,		/* B=cyl 100 thru 309 */
60886Sbill 	131680,	0,		/* C=cyl 0 thru 822 */
6121Sbill 	0,	0,
6221Sbill 	0,	0,
633442Sroot 	0,	0,
643726Sroot #ifndef NOBADSECT
653729Sroot 	81984,	310,		/* G=cyl 310 thru 822 */
663706Sroot #else
673706Sroot 	82080,	310,
683706Sroot #endif
6921Sbill 	0,	0,
70886Sbill }, rm5_sizes[8] = {
71886Sbill 	15884,	0,		/* A=cyl 0 thru 26 */
72886Sbill 	33440,	27,		/* B=cyl 27 thru 81 */
733271Swnj 	500384,	0,		/* C=cyl 0 thru 822 */
74886Sbill 	15884,	562,		/* D=cyl 562 thru 588 */
75886Sbill 	55936,	589,		/* E=cyl 589 thru 680 */
763726Sroot #ifndef NOBADSECT
773729Sroot 	86240,	681,		/* F=cyl 681 thru 822 */
783729Sroot 	158592,	562,		/* G=cyl 562 thru 822 */
793706Sroot #else
803706Sroot 	86636,	681,
813706Sroot 	158688,	562,
823706Sroot #endif
83886Sbill 	291346,	82,		/* H=cyl 82 thru 561 */
842383Swnj }, rm80_sizes[8] = {
852383Swnj 	15884,	0,		/* A=cyl 0 thru 36 */
862383Swnj 	33440,	37,		/* B=cyl 37 thru 114 */
872383Swnj 	242606,	0,		/* C=cyl 0 thru 558 */
882383Swnj 	0,	0,
892383Swnj 	0,	0,
902383Swnj 	0,	0,
912383Swnj 	82080,	115,		/* G=cyl 115 thru 304 */
923729Sroot 	110143,	305,		/* H=cyl 305 thru 558 */
933706Sroot }, hp7_sizes[8] = {
943706Sroot 	15844,	0,		/* A=cyl 0 thru 9 */
953706Sroot 	64000,	10,		/* B=cyl 10 thru 49 */
963706Sroot 	1008000,0,		/* C=cyl 0 thru 629 */
973706Sroot 	15884,	330,		/* D=cyl 330 thru 339 */
983706Sroot 	256000,	340,		/* E=cyl 340 thru 499 */
993729Sroot 	207850,	500,		/* F=cyl 500 thru 629 */
1003729Sroot 	479850,	330,		/* G=cyl 330 thru 629 */
1013706Sroot 	448000,	50,		/* H=cyl 50 thru 329 */
10221Sbill };
1032383Swnj /* END OF STUFF WHICH SHOULD BE READ IN PER DISK */
10421Sbill 
1052383Swnj #define	_hpSDIST	2
1062383Swnj #define	_hpRDIST	3
1072383Swnj 
1082383Swnj int	hpSDIST = _hpSDIST;
1092383Swnj int	hpRDIST = _hpRDIST;
1102383Swnj 
1112383Swnj short	hptypes[] =
1123706Sroot 	{ MBDT_RM03, MBDT_RM05, MBDT_RP06, MBDT_RM80, MBDT_RP05, MBDT_RP07, 0 };
1132978Swnj struct	mba_device *hpinfo[NHP];
1142978Swnj int	hpattach(),hpustart(),hpstart(),hpdtint();
1152383Swnj struct	mba_driver hpdriver =
1162978Swnj 	{ hpattach, 0, hpustart, hpstart, hpdtint, 0,
1172978Swnj 	  hptypes, "hp", 0, hpinfo };
1182383Swnj 
1192383Swnj struct hpst {
1202383Swnj 	short	nsect;
1212383Swnj 	short	ntrak;
1222383Swnj 	short	nspc;
1232383Swnj 	short	ncyl;
1242383Swnj 	struct	size *sizes;
1252383Swnj } hpst[] = {
1263706Sroot 	32,	5,	32*5,	823,	rm3_sizes,	/* RM03 */
1272383Swnj 	32,	19,	32*19,	823,	rm5_sizes,	/* RM05 */
1283706Sroot 	22,	19,	22*19,	815,	hp6_sizes,	/* RP06 */
1293706Sroot 	31,	14, 	31*14,	559,	rm80_sizes,	/* RM80 */
1303706Sroot 	22,	19,	22*19,	411,	hp6_sizes,	/* RP05 */
1313706Sroot 	50,	32,	50*32,	630,	hp7_sizes,	/* RP07 */
1322383Swnj };
1332383Swnj 
1342624Swnj u_char	hp_offset[16] = {
1353093Swnj     HPOF_P400, HPOF_M400, HPOF_P400, HPOF_M400,
1363093Swnj     HPOF_P800, HPOF_M800, HPOF_P800, HPOF_M800,
1373093Swnj     HPOF_P1200, HPOF_M1200, HPOF_P1200, HPOF_M1200,
1383093Swnj     0, 0, 0, 0,
13921Sbill };
14021Sbill 
1412624Swnj struct	buf	rhpbuf[NHP];
1423726Sroot #ifndef NOBADSECT
1433706Sroot struct	buf	bhpbuf[NHP];
1443706Sroot struct	dkbad	hpbad[NHP];
1453706Sroot #endif
1463706Sroot char	hpinit[NHP];
1472892Swnj char	hprecal[NHP];
14821Sbill 
14921Sbill #define	b_cylin b_resid
15021Sbill 
15121Sbill #ifdef INTRLVE
15221Sbill daddr_t dkblock();
15321Sbill #endif
15421Sbill 
1552604Swnj int	hpseek;
1562604Swnj 
1572978Swnj /*ARGSUSED*/
1582978Swnj hpattach(mi, slave)
1592978Swnj 	struct mba_device *mi;
1602604Swnj {
1612604Swnj 	register struct hpst *st = &hpst[mi->mi_type];
1622604Swnj 
1632604Swnj 	if (mi->mi_dk >= 0)
1642757Swnj 		dk_mspw[mi->mi_dk] = 1.0 / 60 / (st->nsect * 256);
1652604Swnj }
1662604Swnj 
16721Sbill hpstrategy(bp)
1682383Swnj 	register struct buf *bp;
16921Sbill {
1702978Swnj 	register struct mba_device *mi;
1712383Swnj 	register struct hpst *st;
1722383Swnj 	register int unit;
17321Sbill 	long sz, bn;
1742383Swnj 	int xunit = minor(bp->b_dev) & 07;
17521Sbill 
17621Sbill 	sz = bp->b_bcount;
17721Sbill 	sz = (sz+511) >> 9;
17821Sbill 	unit = dkunit(bp);
1792383Swnj 	if (unit >= NHP)
1802383Swnj 		goto bad;
1812383Swnj 	mi = hpinfo[unit];
1822395Swnj 	if (mi == 0 || mi->mi_alive == 0)
1832383Swnj 		goto bad;
1842383Swnj 	st = &hpst[mi->mi_type];
1852383Swnj 	if (bp->b_blkno < 0 ||
1862383Swnj 	    (bn = dkblock(bp))+sz > st->sizes[xunit].nblocks)
1872383Swnj 		goto bad;
1882383Swnj 	bp->b_cylin = bn/st->nspc + st->sizes[xunit].cyloff;
189127Sbill 	(void) spl5();
1902383Swnj 	disksort(&mi->mi_tab, bp);
1912383Swnj 	if (mi->mi_tab.b_active == 0)
1922383Swnj 		mbustart(mi);
193127Sbill 	(void) spl0();
1942383Swnj 	return;
1952383Swnj 
1962383Swnj bad:
1972383Swnj 	bp->b_flags |= B_ERROR;
1982383Swnj 	iodone(bp);
1992383Swnj 	return;
20021Sbill }
20121Sbill 
2022383Swnj hpustart(mi)
2032978Swnj 	register struct mba_device *mi;
20421Sbill {
2052624Swnj 	register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv;
2062383Swnj 	register struct buf *bp = mi->mi_tab.b_actf;
2073706Sroot 	register struct hpst *st = &hpst[mi->mi_type];
20821Sbill 	daddr_t bn;
2093102Swnj 	int sn, dist;
21021Sbill 
2113706Sroot 	hpaddr->hpcs1 = 0;
2122624Swnj 	if ((hpaddr->hpcs1&HP_DVA) == 0)
2132383Swnj 		return (MBU_BUSY);
2143706Sroot 	if ((hpaddr->hpds & HPDS_VV) == 0 || hpinit[mi->mi_unit] == 0) {
2153726Sroot #ifndef NOBADSECT
2163706Sroot 		struct buf *bbp = &bhpbuf[mi->mi_unit];
2173706Sroot #endif
2183706Sroot 
2193706Sroot 		hpinit[mi->mi_unit] = 1;
2202624Swnj 		hpaddr->hpcs1 = HP_DCLR|HP_GO;
2213140Swnj 		if (mi->mi_mba->mba_drv[0].mbd_as & (1<<mi->mi_drive))
2223140Swnj 			printf("DCLR attn\n");
2232624Swnj 		hpaddr->hpcs1 = HP_PRESET|HP_GO;
2243093Swnj 		hpaddr->hpof = HPOF_FMT22;
2253140Swnj 		mbclrattn(mi);
2263726Sroot #ifndef NOBADSECT
2273706Sroot 		bbp->b_flags = B_READ|B_BUSY;
2283706Sroot 		bbp->b_dev = bp->b_dev;
2293706Sroot 		bbp->b_bcount = 512;
2303706Sroot 		bbp->b_un.b_addr = (caddr_t)&hpbad[mi->mi_unit];
2313706Sroot 		bbp->b_blkno = st->ncyl*st->nspc - st->nsect;
2323706Sroot 		bbp->b_cylin = st->ncyl - 1;
2333706Sroot 		mi->mi_tab.b_actf = bbp;
2343706Sroot 		bbp->av_forw = bp;
2353706Sroot 		bp = bbp;
2363706Sroot #endif
23721Sbill 	}
2382604Swnj 	if (mi->mi_tab.b_active || mi->mi_hd->mh_ndrive == 1)
2392383Swnj 		return (MBU_DODATA);
2403093Swnj 	if ((hpaddr->hpds & HPDS_DREADY) != HPDS_DREADY)
2412383Swnj 		return (MBU_DODATA);
2422395Swnj 	bn = dkblock(bp);
2432395Swnj 	sn = bn%st->nspc;
2442395Swnj 	sn = (sn+st->nsect-hpSDIST)%st->nsect;
2452383Swnj 	if (bp->b_cylin == (hpaddr->hpdc & 0xffff)) {
2462604Swnj 		if (hpseek)
2472383Swnj 			return (MBU_DODATA);
2482383Swnj 		dist = ((hpaddr->hpla & 0xffff)>>6) - st->nsect + 1;
2492383Swnj 		if (dist < 0)
2502383Swnj 			dist += st->nsect;
2512383Swnj 		if (dist > st->nsect - hpRDIST)
2522383Swnj 			return (MBU_DODATA);
2532614Swnj 	} else
2542614Swnj 		hpaddr->hpdc = bp->b_cylin;
2552604Swnj 	if (hpseek)
2562624Swnj 		hpaddr->hpcs1 = HP_SEEK|HP_GO;
257305Sbill 	else {
258305Sbill 		hpaddr->hpda = sn;
2592624Swnj 		hpaddr->hpcs1 = HP_SEARCH|HP_GO;
260305Sbill 	}
2612383Swnj 	return (MBU_STARTED);
26221Sbill }
26321Sbill 
2642383Swnj hpstart(mi)
2652978Swnj 	register struct mba_device *mi;
26621Sbill {
2672624Swnj 	register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv;
2682383Swnj 	register struct buf *bp = mi->mi_tab.b_actf;
2692383Swnj 	register struct hpst *st = &hpst[mi->mi_type];
27021Sbill 	daddr_t bn;
2712383Swnj 	int sn, tn;
27221Sbill 
27321Sbill 	bn = dkblock(bp);
2742383Swnj 	sn = bn%st->nspc;
2752383Swnj 	tn = sn/st->nsect;
2762395Swnj 	sn %= st->nsect;
2772383Swnj 	hpaddr->hpdc = bp->b_cylin;
27821Sbill 	hpaddr->hpda = (tn << 8) + sn;
2793706Sroot 	return(0);
28021Sbill }
28121Sbill 
2823102Swnj hpdtint(mi, mbsr)
2832978Swnj 	register struct mba_device *mi;
2843102Swnj 	int mbsr;
28521Sbill {
2862624Swnj 	register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv;
2872383Swnj 	register struct buf *bp = mi->mi_tab.b_actf;
2882826Swnj 	int retry = 0;
28921Sbill 
2903726Sroot #ifndef NOBADSECT
2913706Sroot 	if (bp->b_flags&B_BAD) {
2923706Sroot 		if (hpecc(mi, CONT))
2933706Sroot 			return(MBD_RESTARTED);
2943706Sroot 	}
2953706Sroot #endif
2963102Swnj 	if (hpaddr->hpds&HPDS_ERR || mbsr&MBSR_EBITS) {
2973706Sroot #ifdef HPDEBUG
2983289Swnj 		if (hpdebug) {
2993706Sroot 			int dc = hpaddr->hpdc, da = hpaddr->hpda;
3003706Sroot 
3013706Sroot 			printf("hperr: bp %x cyl %d blk %d as %o ",
3023706Sroot 				bp, bp->b_cylin, bp->b_blkno,
3033706Sroot 				hpaddr->hpas&0xff);
3043706Sroot 			printf("dc %x da %x\n",dc&0xffff, da&0xffff);
3053289Swnj 			printf("errcnt %d ", mi->mi_tab.b_errcnt);
3063289Swnj 			printf("mbsr=%b ", mbsr, mbsr_bits);
3073289Swnj 			printf("er1=%b er2=%b\n",
3083289Swnj 			    hpaddr->hper1, HPER1_BITS,
3093289Swnj 			    hpaddr->hper2, HPER2_BITS);
3103289Swnj 			DELAY(1000000);
3113289Swnj 		}
3123706Sroot #endif
3133093Swnj 		if (hpaddr->hper1&HPER1_WLE) {
3142925Swnj 			printf("hp%d: write locked\n", dkunit(bp));
3152826Swnj 			bp->b_flags |= B_ERROR;
3162826Swnj 		} else if (++mi->mi_tab.b_errcnt > 27 ||
3173102Swnj 		    mbsr & MBSR_HARD ||
3182826Swnj 		    hpaddr->hper1 & HPER1_HARD ||
3192826Swnj 		    hpaddr->hper2 & HPER2_HARD) {
3203706Sroot hard:
3212925Swnj 			harderr(bp, "hp");
3223271Swnj 			if (mbsr & (MBSR_EBITS &~ (MBSR_DTABT|MBSR_MBEXC)))
3233271Swnj 				printf("mbsr=%b ", mbsr, mbsr_bits);
3243706Sroot 			printf("er1=%b er2=%b",
3252826Swnj 			    hpaddr->hper1, HPER1_BITS,
3262826Swnj 			    hpaddr->hper2, HPER2_BITS);
3273706Sroot 			if (hpaddr->hpmr)
3283706Sroot 				printf(" mr=%o", hpaddr->hpmr&0xffff);
3293706Sroot 			if (hpaddr->hpmr2)
3303706Sroot 				printf(" mr2=%o", hpaddr->hpmr2&0xffff);
3313706Sroot 			printf("\n");
3322826Swnj 			bp->b_flags |= B_ERROR;
3333143Swnj 			hprecal[mi->mi_unit] = 0;
3343706Sroot 		} else if (hpaddr->hper2 & HPER2_BSE) {
3353726Sroot #ifndef NOBADSECT
3363706Sroot 			if (hpecc(mi, BSE))
3373706Sroot 				return(MBD_RESTARTED);
3383706Sroot 			else
3393706Sroot #endif
3403706Sroot 				goto hard;
3413706Sroot 		} else if (hptypes[mi->mi_type] == MBDT_RM80 &&
3423706Sroot 		    hpaddr->hper2&HPER2_SSE) {
3433706Sroot 			hpecc(mi, SSE);
3442883Swnj 			return (MBD_RESTARTED);
3453093Swnj 		} else if ((hpaddr->hper1&(HPER1_DCK|HPER1_ECH))==HPER1_DCK) {
3463706Sroot 			if (hpecc(mi, ECC))
3472383Swnj 				return (MBD_RESTARTED);
3482826Swnj 			/* else done */
3492826Swnj 		} else
3502826Swnj 			retry = 1;
3512826Swnj 		hpaddr->hpcs1 = HP_DCLR|HP_GO;
3522826Swnj 		if ((mi->mi_tab.b_errcnt&07) == 4) {
3532826Swnj 			hpaddr->hpcs1 = HP_RECAL|HP_GO;
3543706Sroot 			hprecal[mi->mi_unit] = 1;
3553706Sroot 			return(MBD_RESTARTED);
35621Sbill 		}
3572826Swnj 		if (retry)
3582826Swnj 			return (MBD_RETRY);
3592826Swnj 	}
3603706Sroot #ifdef HPDEBUG
3613289Swnj 	else
3623289Swnj 		if (hpdebug && hprecal[mi->mi_unit]) {
3633289Swnj 			printf("recal %d ", hprecal[mi->mi_unit]);
3643289Swnj 			printf("errcnt %d\n", mi->mi_tab.b_errcnt);
3653289Swnj 			printf("mbsr=%b ", mbsr, mbsr_bits);
3663289Swnj 			printf("er1=%b er2=%b\n",
3673289Swnj 			    hpaddr->hper1, HPER1_BITS,
3683289Swnj 			    hpaddr->hper2, HPER2_BITS);
3693289Swnj 		}
3703706Sroot #endif
3713093Swnj 	switch (hprecal[mi->mi_unit]) {
3723093Swnj 
3733093Swnj 	case 1:
3743093Swnj 		hpaddr->hpdc = bp->b_cylin;
3753093Swnj 		hpaddr->hpcs1 = HP_SEEK|HP_GO;
3763706Sroot 		hprecal[mi->mi_unit]++;
3773706Sroot 		return (MBD_RESTARTED);
3783093Swnj 	case 2:
3793093Swnj 		if (mi->mi_tab.b_errcnt < 16 ||
3803289Swnj 		    (bp->b_flags & B_READ) == 0)
3813093Swnj 			goto donerecal;
3823093Swnj 		hpaddr->hpof = hp_offset[mi->mi_tab.b_errcnt & 017]|HPOF_FMT22;
3833093Swnj 		hpaddr->hpcs1 = HP_OFFSET|HP_GO;
3843093Swnj 		hprecal[mi->mi_unit]++;
3853093Swnj 		return (MBD_RESTARTED);
3863093Swnj 	donerecal:
3873158Swnj 	case 3:
3882892Swnj 		hprecal[mi->mi_unit] = 0;
3892892Swnj 		return (MBD_RETRY);
3902892Swnj 	}
3912383Swnj 	bp->b_resid = -(mi->mi_mba->mba_bcr) & 0xffff;
3923640Swnj 	if (mi->mi_tab.b_errcnt >= 16) {
3933093Swnj 		/*
3943093Swnj 		 * This is fast and occurs rarely; we don't
3953093Swnj 		 * bother with interrupts.
3963093Swnj 		 */
3972624Swnj 		hpaddr->hpcs1 = HP_RTC|HP_GO;
3983093Swnj 		while (hpaddr->hpds & HPDS_PIP)
3992383Swnj 			;
4002383Swnj 		mbclrattn(mi);
40121Sbill 	}
4023706Sroot 	hpaddr->hpof = HPOF_FMT22;
4032624Swnj 	hpaddr->hpcs1 = HP_RELEASE|HP_GO;
4042383Swnj 	return (MBD_DONE);
40521Sbill }
40621Sbill 
40721Sbill hpread(dev)
4082624Swnj 	dev_t dev;
40921Sbill {
4102624Swnj 	register int unit = minor(dev) >> 3;
41121Sbill 
4122624Swnj 	if (unit >= NHP)
4132624Swnj 		u.u_error = ENXIO;
4142624Swnj 	else
4152624Swnj 		physio(hpstrategy, &rhpbuf[unit], dev, B_READ, minphys);
41621Sbill }
41721Sbill 
41821Sbill hpwrite(dev)
4192624Swnj 	dev_t dev;
42021Sbill {
4212624Swnj 	register int unit = minor(dev) >> 3;
42221Sbill 
4232624Swnj 	if (unit >= NHP)
4242624Swnj 		u.u_error = ENXIO;
4252624Swnj 	else
4262624Swnj 		physio(hpstrategy, &rhpbuf[unit], dev, B_WRITE, minphys);
42721Sbill }
42821Sbill 
4293706Sroot hpecc(mi, flag)
4302978Swnj 	register struct mba_device *mi;
4313706Sroot 	int flag;
43221Sbill {
4332383Swnj 	register struct mba_regs *mbp = mi->mi_mba;
4342624Swnj 	register struct hpdevice *rp = (struct hpdevice *)mi->mi_drv;
4352383Swnj 	register struct buf *bp = mi->mi_tab.b_actf;
4363706Sroot 	register struct hpst *st = &hpst[mi->mi_type];
4373706Sroot 	int npf, o;
4382383Swnj 	int bn, cn, tn, sn;
439914Sbill 	int bcr;
44021Sbill 
441914Sbill 	bcr = mbp->mba_bcr & 0xffff;
442914Sbill 	if (bcr)
443914Sbill 		bcr |= 0xffff0000;		/* sxt */
4443726Sroot #ifndef NOBADSECT
4453706Sroot 	if (flag == CONT)
4463706Sroot 		npf = bp->b_error;
4473706Sroot 	else
4483706Sroot #endif
4493706Sroot 		npf = btop(bcr + bp->b_bcount);
450420Sbill 	o = (int)bp->b_un.b_addr & PGOFSET;
451420Sbill 	bn = dkblock(bp);
452420Sbill 	cn = bp->b_cylin;
4533706Sroot 	sn = bn%(st->nspc) + npf;
4542383Swnj 	tn = sn/st->nsect;
4552383Swnj 	sn %= st->nsect;
4562383Swnj 	cn += tn/st->ntrak;
4572383Swnj 	tn %= st->ntrak;
4583706Sroot 	switch (flag) {
4593706Sroot 	case ECC:
4603706Sroot 		{
4613706Sroot 		register int i;
4623706Sroot 		caddr_t addr;
4633706Sroot 		struct pte mpte;
4643706Sroot 		int bit, byte, mask;
4653706Sroot 
4663706Sroot 		npf--;		/* because block in error is previous block */
4673706Sroot 		printf("hp%d%c: soft ecc sn%d\n", dkunit(bp),
4683706Sroot 		    'a'+(minor(bp->b_dev)&07), bp->b_blkno + npf);
4693706Sroot 		mask = rp->hpec2&0xffff;
4703706Sroot 		i = (rp->hpec1&0xffff) - 1;		/* -1 makes 0 origin */
4713706Sroot 		bit = i&07;
4723706Sroot 		i = (i&~07)>>3;
4733706Sroot 		byte = i + o;
4743706Sroot 		while (i < 512 && (int)ptob(npf)+i < bp->b_bcount && bit > -11) {
4753706Sroot 			mpte = mbp->mba_map[npf+btop(byte)];
4763706Sroot 			addr = ptob(mpte.pg_pfnum) + (byte & PGOFSET);
4773706Sroot 			putmemc(addr, getmemc(addr)^(mask<<bit));
4783706Sroot 			byte++;
4793706Sroot 			i++;
4803706Sroot 			bit -= 8;
4813706Sroot 		}
4823706Sroot 		if (bcr == 0)
4833706Sroot 			return (0);
484*3847Sroot 		npf++;
4853706Sroot 		break;
4863706Sroot 		}
4873706Sroot 
4883706Sroot 	case SSE:
4893706Sroot 		rp->hpof |= HPOF_SSEI;
4903706Sroot 		mbp->mba_bcr = -(bp->b_bcount - (int)ptob(npf));
4913706Sroot 		break;
4923706Sroot 
4933726Sroot #ifndef NOBADSECT
4943706Sroot 	case BSE:
4953706Sroot #ifdef HPBDEBUG
4963706Sroot 		if (hpbdebug)
4973706Sroot 		printf("hpecc, BSE: bn %d cn %d tn %d sn %d\n", bn, cn, tn, sn);
4983706Sroot #endif
4993706Sroot 		if ((bn = isbad(&hpbad[mi->mi_unit], cn, tn, sn)) < 0)
5003706Sroot 			return(0);
5013706Sroot 		bp->b_flags |= B_BAD;
5023706Sroot 		bp->b_error = npf + 1;
5033706Sroot 		bn = st->ncyl*st->nspc - st->nsect - 1 - bn;
5043706Sroot 		cn = bn/st->nspc;
5053706Sroot 		sn = bn%st->nspc;
5063706Sroot 		tn = sn/st->nsect;
5073706Sroot 		sn %= st->nsect;
5083706Sroot 		mbp->mba_bcr = -512;
5093706Sroot #ifdef HPBDEBUG
5103706Sroot 		if (hpbdebug)
5113706Sroot 		printf("revector to cn %d tn %d sn %d\n", cn, tn, sn);
5123706Sroot #endif
5133706Sroot 		break;
5143706Sroot 
5153706Sroot 	case CONT:
5163706Sroot #ifdef HPBDEBUG
5173706Sroot 		if (hpbdebug)
5183706Sroot 		printf("hpecc, CONT: bn %d cn %d tn %d sn %d\n", bn,cn,tn,sn);
5193706Sroot #endif
5203706Sroot 		npf = bp->b_error;
5213706Sroot 		bp->b_flags &= ~B_BAD;
5223706Sroot 		mbp->mba_bcr = -(bp->b_bcount - (int)ptob(npf));
5233706Sroot 		if ((mbp->mba_bcr & 0xffff) == 0)
5243706Sroot 			return(0);
5253706Sroot 		break;
5263706Sroot #endif
5273706Sroot 	}
5283706Sroot 	rp->hpcs1 = HP_DCLR|HP_GO;
5293350Swnj 	if (rp->hpof&HPOF_SSEI)
5302883Swnj 		sn++;
531420Sbill 	rp->hpdc = cn;
532420Sbill 	rp->hpda = (tn<<8) + sn;
533420Sbill 	mbp->mba_sr = -1;
5343706Sroot 	mbp->mba_var = (int)ptob(npf) + o;
5353706Sroot 	rp->hpcs1 = bp->b_flags&B_READ ? HP_RCOM|HP_GO : HP_WCOM|HP_GO;
5363706Sroot 	mi->mi_tab.b_errcnt = 0;	/* error has been corrected */
537420Sbill 	return (1);
53821Sbill }
5392362Swnj 
5402362Swnj #define	DBSIZE	20
5412362Swnj 
5422362Swnj hpdump(dev)
5432362Swnj 	dev_t dev;
5442362Swnj {
5452978Swnj 	register struct mba_device *mi;
5462383Swnj 	register struct mba_regs *mba;
5472624Swnj 	struct hpdevice *hpaddr;
5482362Swnj 	char *start;
5492383Swnj 	int num, unit;
5502383Swnj 	register struct hpst *st;
5512362Swnj 
5522362Swnj 	num = maxfree;
5532362Swnj 	start = 0;
5542362Swnj 	unit = minor(dev) >> 3;
5552827Swnj 	if (unit >= NHP)
5562827Swnj 		return (ENXIO);
5572383Swnj #define	phys(a,b)	((b)((int)(a)&0x7fffffff))
5582978Swnj 	mi = phys(hpinfo[unit],struct mba_device *);
5592827Swnj 	if (mi == 0 || mi->mi_alive == 0)
5602827Swnj 		return (ENXIO);
5612383Swnj 	mba = phys(mi->mi_hd, struct mba_hd *)->mh_physmba;
5623102Swnj 	mba->mba_cr = MBCR_INIT;
5632624Swnj 	hpaddr = (struct hpdevice *)&mba->mba_drv[mi->mi_drive];
5643093Swnj 	if ((hpaddr->hpds & HPDS_VV) == 0) {
5652624Swnj 		hpaddr->hpcs1 = HP_DCLR|HP_GO;
5662624Swnj 		hpaddr->hpcs1 = HP_PRESET|HP_GO;
5673093Swnj 		hpaddr->hpof = HPOF_FMT22;
5682362Swnj 	}
5692383Swnj 	st = &hpst[mi->mi_type];
5702827Swnj 	if (dumplo < 0 || dumplo + num >= st->sizes[minor(dev)&07].nblocks)
5712827Swnj 		return (EINVAL);
5722362Swnj 	while (num > 0) {
5732383Swnj 		register struct pte *hpte = mba->mba_map;
5742362Swnj 		register int i;
5752383Swnj 		int blk, cn, sn, tn;
5762362Swnj 		daddr_t bn;
5772362Swnj 
5782362Swnj 		blk = num > DBSIZE ? DBSIZE : num;
5792362Swnj 		bn = dumplo + btop(start);
5802383Swnj 		cn = bn/st->nspc + st->sizes[minor(dev)&07].cyloff;
5812383Swnj 		sn = bn%st->nspc;
5822383Swnj 		tn = sn/st->nsect;
5832383Swnj 		sn = sn%st->nsect;
5842362Swnj 		hpaddr->hpdc = cn;
5852362Swnj 		hpaddr->hpda = (tn << 8) + sn;
5862362Swnj 		for (i = 0; i < blk; i++)
5872362Swnj 			*(int *)hpte++ = (btop(start)+i) | PG_V;
5882383Swnj 		mba->mba_sr = -1;
5892383Swnj 		mba->mba_bcr = -(blk*NBPG);
5902383Swnj 		mba->mba_var = 0;
5912624Swnj 		hpaddr->hpcs1 = HP_WCOM | HP_GO;
5923093Swnj 		while ((hpaddr->hpds & HPDS_DRY) == 0)
5932362Swnj 			;
5943093Swnj 		if (hpaddr->hpds&HPDS_ERR)
5952827Swnj 			return (EIO);
5962362Swnj 		start += blk*NBPG;
5972362Swnj 		num -= blk;
5982362Swnj 	}
5992362Swnj 	return (0);
6002362Swnj }
6011565Sbill #endif
602