xref: /csrg-svn/sys/vax/mba/hp.c (revision 5432)
1*5432Sroot /*	hp.c	4.43	82/01/17	*/
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;
175*5432Sroot 	int s;
17621Sbill 
17721Sbill 	sz = bp->b_bcount;
17821Sbill 	sz = (sz+511) >> 9;
17921Sbill 	unit = dkunit(bp);
1802383Swnj 	if (unit >= NHP)
1812383Swnj 		goto bad;
1822383Swnj 	mi = hpinfo[unit];
1832395Swnj 	if (mi == 0 || mi->mi_alive == 0)
1842383Swnj 		goto bad;
1852383Swnj 	st = &hpst[mi->mi_type];
1862383Swnj 	if (bp->b_blkno < 0 ||
1872383Swnj 	    (bn = dkblock(bp))+sz > st->sizes[xunit].nblocks)
1882383Swnj 		goto bad;
1892383Swnj 	bp->b_cylin = bn/st->nspc + st->sizes[xunit].cyloff;
190*5432Sroot 	s = spl5();
1912383Swnj 	disksort(&mi->mi_tab, bp);
1922383Swnj 	if (mi->mi_tab.b_active == 0)
1932383Swnj 		mbustart(mi);
194*5432Sroot 	splx(s);
1952383Swnj 	return;
1962383Swnj 
1972383Swnj bad:
1982383Swnj 	bp->b_flags |= B_ERROR;
1992383Swnj 	iodone(bp);
2002383Swnj 	return;
20121Sbill }
20221Sbill 
2032383Swnj hpustart(mi)
2042978Swnj 	register struct mba_device *mi;
20521Sbill {
2062624Swnj 	register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv;
2072383Swnj 	register struct buf *bp = mi->mi_tab.b_actf;
2083706Sroot 	register struct hpst *st = &hpst[mi->mi_type];
20921Sbill 	daddr_t bn;
2103102Swnj 	int sn, dist;
21121Sbill 
2123706Sroot 	hpaddr->hpcs1 = 0;
2132624Swnj 	if ((hpaddr->hpcs1&HP_DVA) == 0)
2142383Swnj 		return (MBU_BUSY);
2153706Sroot 	if ((hpaddr->hpds & HPDS_VV) == 0 || hpinit[mi->mi_unit] == 0) {
2163726Sroot #ifndef NOBADSECT
2173706Sroot 		struct buf *bbp = &bhpbuf[mi->mi_unit];
2183706Sroot #endif
2193706Sroot 
2203706Sroot 		hpinit[mi->mi_unit] = 1;
2212624Swnj 		hpaddr->hpcs1 = HP_DCLR|HP_GO;
2223140Swnj 		if (mi->mi_mba->mba_drv[0].mbd_as & (1<<mi->mi_drive))
2233140Swnj 			printf("DCLR attn\n");
2242624Swnj 		hpaddr->hpcs1 = HP_PRESET|HP_GO;
2253093Swnj 		hpaddr->hpof = HPOF_FMT22;
2263140Swnj 		mbclrattn(mi);
2273726Sroot #ifndef NOBADSECT
2283706Sroot 		bbp->b_flags = B_READ|B_BUSY;
2293706Sroot 		bbp->b_dev = bp->b_dev;
2303706Sroot 		bbp->b_bcount = 512;
2313706Sroot 		bbp->b_un.b_addr = (caddr_t)&hpbad[mi->mi_unit];
2323706Sroot 		bbp->b_blkno = st->ncyl*st->nspc - st->nsect;
2333706Sroot 		bbp->b_cylin = st->ncyl - 1;
2343706Sroot 		mi->mi_tab.b_actf = bbp;
2353706Sroot 		bbp->av_forw = bp;
2363706Sroot 		bp = bbp;
2373706Sroot #endif
23821Sbill 	}
2392604Swnj 	if (mi->mi_tab.b_active || mi->mi_hd->mh_ndrive == 1)
2402383Swnj 		return (MBU_DODATA);
2413093Swnj 	if ((hpaddr->hpds & HPDS_DREADY) != HPDS_DREADY)
2422383Swnj 		return (MBU_DODATA);
2432395Swnj 	bn = dkblock(bp);
2442395Swnj 	sn = bn%st->nspc;
2452395Swnj 	sn = (sn+st->nsect-hpSDIST)%st->nsect;
2462383Swnj 	if (bp->b_cylin == (hpaddr->hpdc & 0xffff)) {
2472604Swnj 		if (hpseek)
2482383Swnj 			return (MBU_DODATA);
2492383Swnj 		dist = ((hpaddr->hpla & 0xffff)>>6) - st->nsect + 1;
2502383Swnj 		if (dist < 0)
2512383Swnj 			dist += st->nsect;
2522383Swnj 		if (dist > st->nsect - hpRDIST)
2532383Swnj 			return (MBU_DODATA);
2542614Swnj 	} else
2552614Swnj 		hpaddr->hpdc = bp->b_cylin;
2562604Swnj 	if (hpseek)
2572624Swnj 		hpaddr->hpcs1 = HP_SEEK|HP_GO;
258305Sbill 	else {
259305Sbill 		hpaddr->hpda = sn;
2602624Swnj 		hpaddr->hpcs1 = HP_SEARCH|HP_GO;
261305Sbill 	}
2622383Swnj 	return (MBU_STARTED);
26321Sbill }
26421Sbill 
2652383Swnj hpstart(mi)
2662978Swnj 	register struct mba_device *mi;
26721Sbill {
2682624Swnj 	register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv;
2692383Swnj 	register struct buf *bp = mi->mi_tab.b_actf;
2702383Swnj 	register struct hpst *st = &hpst[mi->mi_type];
27121Sbill 	daddr_t bn;
2722383Swnj 	int sn, tn;
27321Sbill 
27421Sbill 	bn = dkblock(bp);
2752383Swnj 	sn = bn%st->nspc;
2762383Swnj 	tn = sn/st->nsect;
2772395Swnj 	sn %= st->nsect;
2782383Swnj 	hpaddr->hpdc = bp->b_cylin;
27921Sbill 	hpaddr->hpda = (tn << 8) + sn;
2803706Sroot 	return(0);
28121Sbill }
28221Sbill 
2833102Swnj hpdtint(mi, mbsr)
2842978Swnj 	register struct mba_device *mi;
2853102Swnj 	int mbsr;
28621Sbill {
2872624Swnj 	register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv;
2882383Swnj 	register struct buf *bp = mi->mi_tab.b_actf;
2892826Swnj 	int retry = 0;
29021Sbill 
2913726Sroot #ifndef NOBADSECT
2923706Sroot 	if (bp->b_flags&B_BAD) {
2933706Sroot 		if (hpecc(mi, CONT))
2943706Sroot 			return(MBD_RESTARTED);
2953706Sroot 	}
2963706Sroot #endif
2973102Swnj 	if (hpaddr->hpds&HPDS_ERR || mbsr&MBSR_EBITS) {
2983706Sroot #ifdef HPDEBUG
2993289Swnj 		if (hpdebug) {
3003706Sroot 			int dc = hpaddr->hpdc, da = hpaddr->hpda;
3013706Sroot 
3023706Sroot 			printf("hperr: bp %x cyl %d blk %d as %o ",
3033706Sroot 				bp, bp->b_cylin, bp->b_blkno,
3043706Sroot 				hpaddr->hpas&0xff);
3053706Sroot 			printf("dc %x da %x\n",dc&0xffff, da&0xffff);
3063289Swnj 			printf("errcnt %d ", mi->mi_tab.b_errcnt);
3073289Swnj 			printf("mbsr=%b ", mbsr, mbsr_bits);
3083289Swnj 			printf("er1=%b er2=%b\n",
3093289Swnj 			    hpaddr->hper1, HPER1_BITS,
3103289Swnj 			    hpaddr->hper2, HPER2_BITS);
3113289Swnj 			DELAY(1000000);
3123289Swnj 		}
3133706Sroot #endif
3143093Swnj 		if (hpaddr->hper1&HPER1_WLE) {
3152925Swnj 			printf("hp%d: write locked\n", dkunit(bp));
3162826Swnj 			bp->b_flags |= B_ERROR;
3172826Swnj 		} else if (++mi->mi_tab.b_errcnt > 27 ||
3183102Swnj 		    mbsr & MBSR_HARD ||
3192826Swnj 		    hpaddr->hper1 & HPER1_HARD ||
3202826Swnj 		    hpaddr->hper2 & HPER2_HARD) {
3213706Sroot hard:
3222925Swnj 			harderr(bp, "hp");
3233271Swnj 			if (mbsr & (MBSR_EBITS &~ (MBSR_DTABT|MBSR_MBEXC)))
3243271Swnj 				printf("mbsr=%b ", mbsr, mbsr_bits);
3253706Sroot 			printf("er1=%b er2=%b",
3262826Swnj 			    hpaddr->hper1, HPER1_BITS,
3272826Swnj 			    hpaddr->hper2, HPER2_BITS);
3283706Sroot 			if (hpaddr->hpmr)
3293706Sroot 				printf(" mr=%o", hpaddr->hpmr&0xffff);
3303706Sroot 			if (hpaddr->hpmr2)
3313706Sroot 				printf(" mr2=%o", hpaddr->hpmr2&0xffff);
3323706Sroot 			printf("\n");
3332826Swnj 			bp->b_flags |= B_ERROR;
3343143Swnj 			hprecal[mi->mi_unit] = 0;
3353706Sroot 		} else if (hpaddr->hper2 & HPER2_BSE) {
3363726Sroot #ifndef NOBADSECT
3373706Sroot 			if (hpecc(mi, BSE))
3383706Sroot 				return(MBD_RESTARTED);
3393706Sroot 			else
3403706Sroot #endif
3413706Sroot 				goto hard;
3423706Sroot 		} else if (hptypes[mi->mi_type] == MBDT_RM80 &&
3433706Sroot 		    hpaddr->hper2&HPER2_SSE) {
3443988Sroot 			(void) hpecc(mi, SSE);
3452883Swnj 			return (MBD_RESTARTED);
3463093Swnj 		} else if ((hpaddr->hper1&(HPER1_DCK|HPER1_ECH))==HPER1_DCK) {
3473706Sroot 			if (hpecc(mi, ECC))
3482383Swnj 				return (MBD_RESTARTED);
3492826Swnj 			/* else done */
3502826Swnj 		} else
3512826Swnj 			retry = 1;
3522826Swnj 		hpaddr->hpcs1 = HP_DCLR|HP_GO;
3532826Swnj 		if ((mi->mi_tab.b_errcnt&07) == 4) {
3542826Swnj 			hpaddr->hpcs1 = HP_RECAL|HP_GO;
3553706Sroot 			hprecal[mi->mi_unit] = 1;
3563706Sroot 			return(MBD_RESTARTED);
35721Sbill 		}
3582826Swnj 		if (retry)
3592826Swnj 			return (MBD_RETRY);
3602826Swnj 	}
3613706Sroot #ifdef HPDEBUG
3623289Swnj 	else
3633289Swnj 		if (hpdebug && hprecal[mi->mi_unit]) {
3643289Swnj 			printf("recal %d ", hprecal[mi->mi_unit]);
3653289Swnj 			printf("errcnt %d\n", mi->mi_tab.b_errcnt);
3663289Swnj 			printf("mbsr=%b ", mbsr, mbsr_bits);
3673289Swnj 			printf("er1=%b er2=%b\n",
3683289Swnj 			    hpaddr->hper1, HPER1_BITS,
3693289Swnj 			    hpaddr->hper2, HPER2_BITS);
3703289Swnj 		}
3713706Sroot #endif
3723093Swnj 	switch (hprecal[mi->mi_unit]) {
3733093Swnj 
3743093Swnj 	case 1:
3753093Swnj 		hpaddr->hpdc = bp->b_cylin;
3763093Swnj 		hpaddr->hpcs1 = HP_SEEK|HP_GO;
3773706Sroot 		hprecal[mi->mi_unit]++;
3783706Sroot 		return (MBD_RESTARTED);
3793093Swnj 	case 2:
3803093Swnj 		if (mi->mi_tab.b_errcnt < 16 ||
3813289Swnj 		    (bp->b_flags & B_READ) == 0)
3823093Swnj 			goto donerecal;
3833093Swnj 		hpaddr->hpof = hp_offset[mi->mi_tab.b_errcnt & 017]|HPOF_FMT22;
3843093Swnj 		hpaddr->hpcs1 = HP_OFFSET|HP_GO;
3853093Swnj 		hprecal[mi->mi_unit]++;
3863093Swnj 		return (MBD_RESTARTED);
3873093Swnj 	donerecal:
3883158Swnj 	case 3:
3892892Swnj 		hprecal[mi->mi_unit] = 0;
3902892Swnj 		return (MBD_RETRY);
3912892Swnj 	}
3922383Swnj 	bp->b_resid = -(mi->mi_mba->mba_bcr) & 0xffff;
3933640Swnj 	if (mi->mi_tab.b_errcnt >= 16) {
3943093Swnj 		/*
3953093Swnj 		 * This is fast and occurs rarely; we don't
3963093Swnj 		 * bother with interrupts.
3973093Swnj 		 */
3982624Swnj 		hpaddr->hpcs1 = HP_RTC|HP_GO;
3993093Swnj 		while (hpaddr->hpds & HPDS_PIP)
4002383Swnj 			;
4012383Swnj 		mbclrattn(mi);
40221Sbill 	}
4033706Sroot 	hpaddr->hpof = HPOF_FMT22;
4042624Swnj 	hpaddr->hpcs1 = HP_RELEASE|HP_GO;
4052383Swnj 	return (MBD_DONE);
40621Sbill }
40721Sbill 
40821Sbill hpread(dev)
4092624Swnj 	dev_t dev;
41021Sbill {
4112624Swnj 	register int unit = minor(dev) >> 3;
41221Sbill 
4132624Swnj 	if (unit >= NHP)
4142624Swnj 		u.u_error = ENXIO;
4152624Swnj 	else
4162624Swnj 		physio(hpstrategy, &rhpbuf[unit], dev, B_READ, minphys);
41721Sbill }
41821Sbill 
41921Sbill hpwrite(dev)
4202624Swnj 	dev_t dev;
42121Sbill {
4222624Swnj 	register int unit = minor(dev) >> 3;
42321Sbill 
4242624Swnj 	if (unit >= NHP)
4252624Swnj 		u.u_error = ENXIO;
4262624Swnj 	else
4272624Swnj 		physio(hpstrategy, &rhpbuf[unit], dev, B_WRITE, minphys);
42821Sbill }
42921Sbill 
4303706Sroot hpecc(mi, flag)
4312978Swnj 	register struct mba_device *mi;
4323706Sroot 	int flag;
43321Sbill {
4342383Swnj 	register struct mba_regs *mbp = mi->mi_mba;
4352624Swnj 	register struct hpdevice *rp = (struct hpdevice *)mi->mi_drv;
4362383Swnj 	register struct buf *bp = mi->mi_tab.b_actf;
4373706Sroot 	register struct hpst *st = &hpst[mi->mi_type];
4383706Sroot 	int npf, o;
4392383Swnj 	int bn, cn, tn, sn;
440914Sbill 	int bcr;
44121Sbill 
442914Sbill 	bcr = mbp->mba_bcr & 0xffff;
443914Sbill 	if (bcr)
444914Sbill 		bcr |= 0xffff0000;		/* sxt */
4453726Sroot #ifndef NOBADSECT
4463706Sroot 	if (flag == CONT)
4473706Sroot 		npf = bp->b_error;
4483706Sroot 	else
4493706Sroot #endif
4503706Sroot 		npf = btop(bcr + bp->b_bcount);
451420Sbill 	o = (int)bp->b_un.b_addr & PGOFSET;
452420Sbill 	bn = dkblock(bp);
453420Sbill 	cn = bp->b_cylin;
4543706Sroot 	sn = bn%(st->nspc) + npf;
4552383Swnj 	tn = sn/st->nsect;
4562383Swnj 	sn %= st->nsect;
4572383Swnj 	cn += tn/st->ntrak;
4582383Swnj 	tn %= st->ntrak;
4593706Sroot 	switch (flag) {
4603706Sroot 	case ECC:
4613706Sroot 		{
4623706Sroot 		register int i;
4633706Sroot 		caddr_t addr;
4643706Sroot 		struct pte mpte;
4653706Sroot 		int bit, byte, mask;
4663706Sroot 
4673706Sroot 		npf--;		/* because block in error is previous block */
4683706Sroot 		printf("hp%d%c: soft ecc sn%d\n", dkunit(bp),
4693706Sroot 		    'a'+(minor(bp->b_dev)&07), bp->b_blkno + npf);
4703706Sroot 		mask = rp->hpec2&0xffff;
4713706Sroot 		i = (rp->hpec1&0xffff) - 1;		/* -1 makes 0 origin */
4723706Sroot 		bit = i&07;
4733706Sroot 		i = (i&~07)>>3;
4743706Sroot 		byte = i + o;
4753706Sroot 		while (i < 512 && (int)ptob(npf)+i < bp->b_bcount && bit > -11) {
4763706Sroot 			mpte = mbp->mba_map[npf+btop(byte)];
4773706Sroot 			addr = ptob(mpte.pg_pfnum) + (byte & PGOFSET);
4783706Sroot 			putmemc(addr, getmemc(addr)^(mask<<bit));
4793706Sroot 			byte++;
4803706Sroot 			i++;
4813706Sroot 			bit -= 8;
4823706Sroot 		}
4833706Sroot 		if (bcr == 0)
4843706Sroot 			return (0);
4853847Sroot 		npf++;
4863706Sroot 		break;
4873706Sroot 		}
4883706Sroot 
4893706Sroot 	case SSE:
4903706Sroot 		rp->hpof |= HPOF_SSEI;
4913706Sroot 		mbp->mba_bcr = -(bp->b_bcount - (int)ptob(npf));
4923706Sroot 		break;
4933706Sroot 
4943726Sroot #ifndef NOBADSECT
4953706Sroot 	case BSE:
4963706Sroot #ifdef HPBDEBUG
4973706Sroot 		if (hpbdebug)
4983706Sroot 		printf("hpecc, BSE: bn %d cn %d tn %d sn %d\n", bn, cn, tn, sn);
4993706Sroot #endif
5003706Sroot 		if ((bn = isbad(&hpbad[mi->mi_unit], cn, tn, sn)) < 0)
5013706Sroot 			return(0);
5023706Sroot 		bp->b_flags |= B_BAD;
5033706Sroot 		bp->b_error = npf + 1;
5043706Sroot 		bn = st->ncyl*st->nspc - st->nsect - 1 - bn;
5053706Sroot 		cn = bn/st->nspc;
5063706Sroot 		sn = bn%st->nspc;
5073706Sroot 		tn = sn/st->nsect;
5083706Sroot 		sn %= st->nsect;
5093706Sroot 		mbp->mba_bcr = -512;
5103706Sroot #ifdef HPBDEBUG
5113706Sroot 		if (hpbdebug)
5123706Sroot 		printf("revector to cn %d tn %d sn %d\n", cn, tn, sn);
5133706Sroot #endif
5143706Sroot 		break;
5153706Sroot 
5163706Sroot 	case CONT:
5173706Sroot #ifdef HPBDEBUG
5183706Sroot 		if (hpbdebug)
5193706Sroot 		printf("hpecc, CONT: bn %d cn %d tn %d sn %d\n", bn,cn,tn,sn);
5203706Sroot #endif
5213706Sroot 		npf = bp->b_error;
5223706Sroot 		bp->b_flags &= ~B_BAD;
5233706Sroot 		mbp->mba_bcr = -(bp->b_bcount - (int)ptob(npf));
5243706Sroot 		if ((mbp->mba_bcr & 0xffff) == 0)
5253706Sroot 			return(0);
5263706Sroot 		break;
5273706Sroot #endif
5283706Sroot 	}
5293706Sroot 	rp->hpcs1 = HP_DCLR|HP_GO;
5303350Swnj 	if (rp->hpof&HPOF_SSEI)
5312883Swnj 		sn++;
532420Sbill 	rp->hpdc = cn;
533420Sbill 	rp->hpda = (tn<<8) + sn;
534420Sbill 	mbp->mba_sr = -1;
5353706Sroot 	mbp->mba_var = (int)ptob(npf) + o;
5363706Sroot 	rp->hpcs1 = bp->b_flags&B_READ ? HP_RCOM|HP_GO : HP_WCOM|HP_GO;
5373706Sroot 	mi->mi_tab.b_errcnt = 0;	/* error has been corrected */
538420Sbill 	return (1);
53921Sbill }
5402362Swnj 
5412362Swnj #define	DBSIZE	20
5422362Swnj 
5432362Swnj hpdump(dev)
5442362Swnj 	dev_t dev;
5452362Swnj {
5462978Swnj 	register struct mba_device *mi;
5472383Swnj 	register struct mba_regs *mba;
5482624Swnj 	struct hpdevice *hpaddr;
5492362Swnj 	char *start;
5502383Swnj 	int num, unit;
5512383Swnj 	register struct hpst *st;
5522362Swnj 
5532362Swnj 	num = maxfree;
5542362Swnj 	start = 0;
5552362Swnj 	unit = minor(dev) >> 3;
5562827Swnj 	if (unit >= NHP)
5572827Swnj 		return (ENXIO);
5582383Swnj #define	phys(a,b)	((b)((int)(a)&0x7fffffff))
5592978Swnj 	mi = phys(hpinfo[unit],struct mba_device *);
5602827Swnj 	if (mi == 0 || mi->mi_alive == 0)
5612827Swnj 		return (ENXIO);
5622383Swnj 	mba = phys(mi->mi_hd, struct mba_hd *)->mh_physmba;
5633102Swnj 	mba->mba_cr = MBCR_INIT;
5642624Swnj 	hpaddr = (struct hpdevice *)&mba->mba_drv[mi->mi_drive];
5653093Swnj 	if ((hpaddr->hpds & HPDS_VV) == 0) {
5662624Swnj 		hpaddr->hpcs1 = HP_DCLR|HP_GO;
5672624Swnj 		hpaddr->hpcs1 = HP_PRESET|HP_GO;
5683093Swnj 		hpaddr->hpof = HPOF_FMT22;
5692362Swnj 	}
5702383Swnj 	st = &hpst[mi->mi_type];
5712827Swnj 	if (dumplo < 0 || dumplo + num >= st->sizes[minor(dev)&07].nblocks)
5722827Swnj 		return (EINVAL);
5732362Swnj 	while (num > 0) {
5742383Swnj 		register struct pte *hpte = mba->mba_map;
5752362Swnj 		register int i;
5762383Swnj 		int blk, cn, sn, tn;
5772362Swnj 		daddr_t bn;
5782362Swnj 
5792362Swnj 		blk = num > DBSIZE ? DBSIZE : num;
5802362Swnj 		bn = dumplo + btop(start);
5812383Swnj 		cn = bn/st->nspc + st->sizes[minor(dev)&07].cyloff;
5822383Swnj 		sn = bn%st->nspc;
5832383Swnj 		tn = sn/st->nsect;
5842383Swnj 		sn = sn%st->nsect;
5852362Swnj 		hpaddr->hpdc = cn;
5862362Swnj 		hpaddr->hpda = (tn << 8) + sn;
5872362Swnj 		for (i = 0; i < blk; i++)
5882362Swnj 			*(int *)hpte++ = (btop(start)+i) | PG_V;
5892383Swnj 		mba->mba_sr = -1;
5902383Swnj 		mba->mba_bcr = -(blk*NBPG);
5912383Swnj 		mba->mba_var = 0;
5922624Swnj 		hpaddr->hpcs1 = HP_WCOM | HP_GO;
5933093Swnj 		while ((hpaddr->hpds & HPDS_DRY) == 0)
5942362Swnj 			;
5953093Swnj 		if (hpaddr->hpds&HPDS_ERR)
5962827Swnj 			return (EIO);
5972362Swnj 		start += blk*NBPG;
5982362Swnj 		num -= blk;
5992362Swnj 	}
6002362Swnj 	return (0);
6012362Swnj }
6021565Sbill #endif
603