xref: /csrg-svn/sys/vax/mba/hp.c (revision 106)
1*106Sbill /*	hp.c	3.2	10/14/12	*/
221Sbill 
321Sbill /*
421Sbill  * RP04/RP06/RM03 disk driver
521Sbill  */
621Sbill 
721Sbill #include "../h/param.h"
821Sbill #include "../h/systm.h"
921Sbill #include "../h/buf.h"
1021Sbill #include "../h/conf.h"
1121Sbill #include "../h/dir.h"
1221Sbill #include "../h/user.h"
1321Sbill #include "../h/map.h"
1421Sbill #include "../h/mba.h"
1521Sbill #include "../h/mtpr.h"
1621Sbill #include "../h/pte.h"
1721Sbill 
1821Sbill #define	DK_N	0
1921Sbill 
2021Sbill struct	device
2121Sbill {
2221Sbill 	int	hpcs1;		/* control and Status register 1 */
2321Sbill 	int	hpds;		/* Drive Status */
2421Sbill 	int	hper1;		/* Error register 1 */
2521Sbill 	int	hpmr;		/* Maintenance */
2621Sbill 	int	hpas;		/* Attention Summary */
2721Sbill 	int	hpda;		/* Desired address register */
2821Sbill 	int	hpdt;		/* Drive type */
2921Sbill 	int	hpla;		/* Look ahead */
3021Sbill 	int	hpsn;		/* serial number */
3121Sbill 	int	hpof;		/* Offset register */
3221Sbill 	int	hpdc;		/* Desired Cylinder address register */
3321Sbill 	int	hpcc;		/* Current Cylinder */
3421Sbill 	int	hper2;		/* Error register 2 */
3521Sbill 	int	hper3;		/* Error register 3 */
3621Sbill 	int	hpec1;		/* Burst error bit position */
3721Sbill 	int	hpec2;		/* Burst error bit pattern */
3821Sbill };
3921Sbill 
4021Sbill #define	HPADDR	((struct device *)(MBA0 + MBA_ERB))
4121Sbill #define	NHP	1
4221Sbill #define	RP	022
4321Sbill #define	RM	024
4421Sbill #define	NSECT	22
4521Sbill #define	NTRAC	19
4621Sbill #define	NRMSECT	32
4721Sbill #define	NRMTRAC	5
4821Sbill #define	SDIST	2
4921Sbill #define	RDIST	6
5021Sbill 
5121Sbill struct	size
5221Sbill {
5321Sbill 	daddr_t	nblocks;
5421Sbill 	int	cyloff;
5521Sbill } hp_sizes[8] =
5621Sbill {
5721Sbill 	15884,	0,		/* cyl 0 thru 37 */
5821Sbill 	33440,	38,		/* cyl 38 thru 117 */
5921Sbill 	8360,	98,		/* cyl 98 thru 117 */
6021Sbill #ifdef ERNIE
6121Sbill 	15884,	118,		/* cyl 118 thru 155 */
6221Sbill 	66880,	156,		/* cyl 156 thru 315 */
6321Sbill 	0,	0,
6421Sbill 	291346,	118,		/* cyl 118 thru 814, (like distrib) */
6521Sbill 	208582,	316,		/* cyl 316 thru 814 */
6621Sbill #else
6721Sbill 	0,	0,
6821Sbill 	0,	0,
6921Sbill 	0,	0,
7021Sbill 	291346,	118,		/* cyl 118 thru 814 */
7121Sbill 	0,	0,
7221Sbill #endif
7321Sbill }, rm_sizes[8] = {
7421Sbill 	15884,	0,		/* cyl 0 thru 99 */
7521Sbill 	33440,	100,		/* cyl 100 thru 309 */
7621Sbill 	0,	0,
7721Sbill 	0,	0,
7821Sbill 	0,	0,
7921Sbill 	0,	0,
8021Sbill 	82080,	310,		/* cyl 310 thru 822 */
8121Sbill 	0,	0,
8221Sbill };
8321Sbill 
8421Sbill #define	P400	020
8521Sbill #define	M400	0220
8621Sbill #define	P800	040
8721Sbill #define	M800	0240
8821Sbill #define	P1200	060
8921Sbill #define	M1200	0260
9021Sbill int	hp_offset[16] =
9121Sbill {
9221Sbill 	P400, M400, P400, M400,
9321Sbill 	P800, M800, P800, M800,
9421Sbill 	P1200, M1200, P1200, M1200,
9521Sbill 	0, 0, 0, 0,
9621Sbill };
9721Sbill 
9821Sbill struct	buf	hptab;
9921Sbill struct	buf	rhpbuf;
10021Sbill struct	buf	hputab[NHP];
10121Sbill char	hp_type[NHP];	/* drive type */
10221Sbill 
10321Sbill #define	GO	01
10421Sbill #define	PRESET	020
10521Sbill #define	RTC	016
10621Sbill #define	OFFSET	014
10721Sbill #define	SEARCH	030
10821Sbill #define	RECAL	06
10921Sbill #define	DCLR	010
11021Sbill #define	WCOM	060
11121Sbill #define	RCOM	070
11221Sbill 
11321Sbill #define	IE	0100
11421Sbill #define	PIP	020000
11521Sbill #define	DRY	0200
11621Sbill #define	ERR	040000
11721Sbill #define	TRE	040000
11821Sbill #define	DCK	0100000
11921Sbill #define	WLE	04000
12021Sbill #define	ECH	0100
12121Sbill #define	VV	0100
12221Sbill #define	DPR	0400
12321Sbill #define	MOL	010000
12421Sbill #define	FMT22	010000
12521Sbill 
12621Sbill #define	b_cylin b_resid
12721Sbill 
12821Sbill #ifdef INTRLVE
12921Sbill daddr_t dkblock();
13021Sbill #endif
13121Sbill 
13221Sbill hpstrategy(bp)
13321Sbill register struct buf *bp;
13421Sbill {
13521Sbill 	register struct buf *dp;
13621Sbill 	register unit, xunit, nspc;
13721Sbill 	long sz, bn;
13821Sbill 	struct size *sizes;
13921Sbill 
14021Sbill 	xunit = minor(bp->b_dev) & 077;
14121Sbill 	sz = bp->b_bcount;
14221Sbill 	sz = (sz+511) >> 9;
14321Sbill 	unit = dkunit(bp);
14421Sbill 	if (hp_type[unit] == 0) {
14521Sbill 		struct device *hpaddr;
14621Sbill 
14721Sbill 		/* determine device type */
14821Sbill 		hpaddr = (struct device *)((int*)HPADDR + 32*unit);
14921Sbill 		hp_type[unit] = hpaddr->hpdt;
15021Sbill 	}
15121Sbill 	if (hp_type[unit] == RM) {
15221Sbill 		sizes = rm_sizes;
15321Sbill 		nspc = NRMSECT*NRMTRAC;
15421Sbill 	} else {
15521Sbill 		sizes = hp_sizes;
15621Sbill 		nspc = NSECT*NTRAC;
15721Sbill 	}
15821Sbill 	if (unit >= NHP ||
15921Sbill 	    bp->b_blkno < 0 ||
16021Sbill 	    (bn = dkblock(bp))+sz > sizes[xunit&07].nblocks) {
16121Sbill 		bp->b_flags |= B_ERROR;
16221Sbill 		iodone(bp);
16321Sbill 		return;
16421Sbill 	}
16521Sbill 	bp->b_cylin = bn/nspc + sizes[xunit&07].cyloff;
16621Sbill 	dp = &hputab[unit];
16721Sbill 	VOID spl5();
16821Sbill 	disksort(dp, bp);
16921Sbill 	if (dp->b_active == 0) {
17021Sbill 		hpustart(unit);
17121Sbill 		if(hptab.b_active == 0)
17221Sbill 			hpstart();
17321Sbill 	}
17421Sbill 	VOID spl0();
17521Sbill }
17621Sbill 
17721Sbill hpustart(unit)
17821Sbill register unit;
17921Sbill {
18021Sbill 	register struct buf *bp, *dp;
18121Sbill 	register struct device *hpaddr;
18221Sbill 	daddr_t bn;
18321Sbill 	int sn, cn, csn;
18421Sbill 
18521Sbill 	((struct mba_regs *)MBA0)->mba_cr |= MBAIE;
18621Sbill 	HPADDR->hpas = 1<<unit;
18721Sbill 
18821Sbill 	if(unit >= NHP)
18921Sbill 		return;
19021Sbill /*
19121Sbill 	dk_busy &= ~(1<<(unit+DK_N));
19221Sbill */
19321Sbill 	dp = &hputab[unit];
19421Sbill 	if((bp=dp->b_actf) == NULL)
19521Sbill 		return;
19621Sbill 	hpaddr = (struct device *)((int *)HPADDR + 32*unit);
19721Sbill 	if((hpaddr->hpds & VV) == 0) {
19821Sbill 		hpaddr->hpcs1 = PRESET|GO;
19921Sbill 		hpaddr->hpof = FMT22;
20021Sbill 	}
20121Sbill 	if(dp->b_active)
20221Sbill 		goto done;
20321Sbill 	dp->b_active++;
20421Sbill 	if ((hpaddr->hpds & (DPR|MOL)) != (DPR|MOL))
20521Sbill 		goto done;
20621Sbill 
20721Sbill 	bn = dkblock(bp);
20821Sbill 	cn = bp->b_cylin;
20921Sbill 	if(hp_type[unit] == RM) {
21021Sbill 		sn = bn%(NRMSECT*NRMTRAC);
21121Sbill 		sn = (sn+NRMSECT-SDIST)%NRMSECT;
21221Sbill 	} else {
21321Sbill 		sn = bn%(NSECT*NTRAC);
21421Sbill 		sn = (sn+NSECT-SDIST)%NSECT;
21521Sbill 	}
21621Sbill 
21721Sbill 	if(cn - (hpaddr->hpdc & 0xffff))
21821Sbill 		goto search;
21921Sbill 	csn = ((hpaddr->hpla & 0xffff)>>6) - sn + SDIST - 1;
22021Sbill 	if(csn < 0)
22121Sbill 		csn += NSECT;
22221Sbill 	if(csn > NSECT-RDIST)
22321Sbill 		goto done;
22421Sbill 
22521Sbill search:
22621Sbill 	hpaddr->hpdc = cn;
22721Sbill 	hpaddr->hpda = sn;
22821Sbill 	hpaddr->hpcs1 = SEARCH|GO;
22921Sbill /*
23021Sbill 	unit += DK_N;
23121Sbill 	dk_busy |= 1<<unit;
23221Sbill 	dk_numb[unit] += 1;
23321Sbill */
23421Sbill 	return;
23521Sbill 
23621Sbill done:
23721Sbill 	dp->b_forw = NULL;
23821Sbill 	if(hptab.b_actf == NULL)
23921Sbill 		hptab.b_actf = dp; else
24021Sbill 		hptab.b_actl->b_forw = dp;
24121Sbill 	hptab.b_actl = dp;
24221Sbill }
24321Sbill 
24421Sbill hpstart()
24521Sbill {
24621Sbill 	register struct buf *bp, *dp;
24721Sbill 	register unit;
24821Sbill 	register struct device *hpaddr;
24921Sbill 	daddr_t bn;
25021Sbill 	int dn, sn, tn, cn, nspc, ns;
25121Sbill 
25221Sbill loop:
25321Sbill 	if ((dp = hptab.b_actf) == NULL)
25421Sbill 		return;
25521Sbill 	if ((bp = dp->b_actf) == NULL) {
25621Sbill 		hptab.b_actf = dp->b_forw;
25721Sbill 		goto loop;
25821Sbill 	}
25921Sbill 	hptab.b_active++;
26021Sbill 	unit = minor(bp->b_dev) & 077;
26121Sbill 	dn = dkunit(bp);
26221Sbill 	bn = dkblock(bp);
26321Sbill 	if (hp_type[dn] == RM) {
26421Sbill 		nspc = NRMSECT*NRMTRAC;
26521Sbill 		ns = NRMSECT;
26621Sbill 		cn = rm_sizes[unit&07].cyloff;
26721Sbill 	} else {
26821Sbill 		nspc = NSECT*NTRAC;
26921Sbill 		ns = NSECT;
27021Sbill 		cn = hp_sizes[unit&07].cyloff;
27121Sbill 	}
27221Sbill 	cn += bn/nspc;
27321Sbill 	sn = bn%nspc;
27421Sbill 	tn = sn/ns;
27521Sbill 	sn = sn%ns;
27621Sbill 
27721Sbill 	hpaddr =  (struct device *)((int *)HPADDR + 32*dn);
27821Sbill 	if ((hpaddr->hpds & (DPR|MOL)) != (DPR|MOL)) {
27921Sbill 		hptab.b_active = 0;
28021Sbill 		hptab.b_errcnt = 0;
28121Sbill 		dp->b_actf = bp->av_forw;
28221Sbill 		bp->b_flags |= B_ERROR;
28321Sbill 		iodone(bp);
28421Sbill 		goto loop;
28521Sbill 	}
28621Sbill 	if(hptab.b_errcnt >= 16) {
28721Sbill 		hpaddr->hpof = hp_offset[hptab.b_errcnt & 017] | FMT22;
28821Sbill 		((struct mba_regs *)MBA0)->mba_cr &= ~MBAIE;
28921Sbill 		hpaddr->hpcs1 = OFFSET|GO;
29021Sbill 		while(hpaddr->hpds & PIP)
29121Sbill 			;
29221Sbill 		((struct mba_regs *)MBA0)->mba_cr |= MBAIE;
29321Sbill 	}
29421Sbill 	hpaddr->hpdc = cn;
29521Sbill 	hpaddr->hpda = (tn << 8) + sn;
29621Sbill 	mbastart(bp, (int *)hpaddr);
29721Sbill 
29821Sbill 	dk_busy |= 1<<(DK_N /*+NHP*/);
29921Sbill 	dk_numb[DK_N /*+NHP*/] += 1;
30021Sbill 	unit = bp->b_bcount>>6;
30121Sbill 	dk_wds[DK_N /*+NHP*/] += unit;
30221Sbill }
30321Sbill 
30421Sbill hpintr(mbastat, as)
30521Sbill {
30621Sbill 	register struct buf *bp, *dp;
30721Sbill 	register unit;
30821Sbill 	register struct device *hpaddr;
30921Sbill 
31021Sbill 	if(hptab.b_active) {
31121Sbill 		dk_busy &= ~(1<<(DK_N /*+NHP*/));
31221Sbill 		dp = hptab.b_actf;
31321Sbill 		bp = dp->b_actf;
31421Sbill 		unit = dkunit(bp);
31521Sbill 		hpaddr = (struct device *)((int *)HPADDR + 32*unit);
31621Sbill 		if (hpaddr->hpds & ERR || mbastat & MBAEBITS) {		/* error bit */
31721Sbill 			while((hpaddr->hpds & DRY) == 0)
31821Sbill 				;
31921Sbill 			if(++hptab.b_errcnt > 28 || hpaddr->hper1&WLE)
32021Sbill 				bp->b_flags |= B_ERROR; else
32121Sbill 				hptab.b_active = 0;
32221Sbill 			if(hptab.b_errcnt > 27)
32321Sbill 				deverror(bp, mbastat, hpaddr->hper1);
32421Sbill 			if ((hpaddr->hper1&0xffff) == DCK) {
32521Sbill 				if (hpecc(hpaddr, bp))
32621Sbill 					return;
32721Sbill 			}
32821Sbill 			hpaddr->hpcs1 = DCLR|GO;
32921Sbill 			if((hptab.b_errcnt&07) == 4) {
33021Sbill 				((struct mba_regs *)MBA0)->mba_cr &= ~MBAIE;
33121Sbill 				hpaddr->hpcs1 = RECAL|GO;
33221Sbill 				while(hpaddr->hpds & PIP)
33321Sbill 					;
33421Sbill 				((struct mba_regs *)MBA0)->mba_cr |= MBAIE;
33521Sbill 			}
33621Sbill 		}
33721Sbill 		if(hptab.b_active) {
33821Sbill 			if(hptab.b_errcnt) {
33921Sbill 				((struct mba_regs *)MBA0)->mba_cr &= ~MBAIE;
34021Sbill 				hpaddr->hpcs1 = RTC|GO;
34121Sbill 				while(hpaddr->hpds & PIP)
34221Sbill 					;
34321Sbill 				((struct mba_regs *)MBA0)->mba_cr |= MBAIE;
34421Sbill 			}
34521Sbill 			hptab.b_active = 0;
34621Sbill 			hptab.b_errcnt = 0;
34721Sbill 			hptab.b_actf = dp->b_forw;
34821Sbill 			dp->b_active = 0;
34921Sbill 			dp->b_errcnt = 0;
35021Sbill 			dp->b_actf = bp->av_forw;
35121Sbill 			bp->b_resid = -(((struct mba_regs *)MBA0)->mba_bcr) & 0xffff;
35221Sbill 			iodone(bp);
35321Sbill 			if(dp->b_actf)
35421Sbill 				hpustart(unit);
35521Sbill 		}
35621Sbill 		as &= ~(1<<unit);
35721Sbill 	} else {
35821Sbill 		if(as == 0)
35921Sbill 			((struct mba_regs *)MBA0)->mba_cr |= MBAIE;
36021Sbill 	}
36121Sbill 	for(unit=0; unit<NHP; unit++)
36221Sbill 		if(as & (1<<unit))
36321Sbill 			hpustart(unit);
36421Sbill 	hpstart();
36521Sbill }
36621Sbill 
36721Sbill hpread(dev)
36821Sbill {
36921Sbill 
37021Sbill 	physio(hpstrategy, &rhpbuf, dev, B_READ, minphys);
37121Sbill }
37221Sbill 
37321Sbill hpwrite(dev)
37421Sbill {
37521Sbill 
37621Sbill 	physio(hpstrategy, &rhpbuf, dev, B_WRITE, minphys);
37721Sbill }
37821Sbill 
37921Sbill hpecc(rp, bp)
38021Sbill register struct device *rp;
38121Sbill register struct buf *bp;
38221Sbill {
38321Sbill 	register i;
38421Sbill 	register b, n, map, mix;
38521Sbill 	register char *cp;
38621Sbill 	register mask;
38721Sbill 	short piget();
388*106Sbill 	extern char buffers[NBUF][BSIZE];
38921Sbill 
39021Sbill 	b = (((((struct mba_regs *)MBA0)->mba_bcr&0xffff) +
39121Sbill 		(bp->b_bcount) - 1)>>9)&0177;
39221Sbill 	printf("%D ", bp->b_blkno+b);
39321Sbill 	prdev("ECC", bp->b_dev);
39421Sbill 	mask = rp->hpec2&0xffff;
39521Sbill 	if (mask == 0) {
39621Sbill 		rp->hpof = FMT22;
39721Sbill 		return(0);
39821Sbill 	}
39921Sbill 	i = (rp->hpec1&0xffff) - 1;
40021Sbill 	n = i&017;
40121Sbill 	i = (i&~017)>>3;
40221Sbill 	if (bp->b_flags&B_PHYS)
40321Sbill 		map = 128 + b;
40421Sbill 	else
40521Sbill 		map = ((bp->b_un.b_addr - (char *)buffers)>>9) + b;
40621Sbill 	mix = i + ((int)bp->b_un.b_addr&0x1ff);
40721Sbill 	i += b<<9;
40821Sbill 	if ( i < bp->b_bcount) {
40921Sbill 		cp = (char *)((((int *)MBA0_MAP)[map+(mix>>9)]&0x1fffff)<<9)+(mix&0x1ff);
41021Sbill 		piput((int)cp,piget((int)cp)^(mask<<n));
41121Sbill 	}
41221Sbill 	mix += 2;
41321Sbill 	i += 2;
41421Sbill 	if (i < bp->b_bcount) {
41521Sbill 		cp = (char *)((((int *)MBA0_MAP)[map+(mix>>9)]&0x1fffff)<<9)+(mix&0x1ff);
41621Sbill 		piput((int)cp,piget((int)cp)^(mask>>(16-n)));
41721Sbill 	}
41821Sbill 	hptab.b_active++;
41921Sbill 	if (((struct mba_regs *)MBA0)->mba_bcr) {
42021Sbill 		i = bp->b_blkno%(NSECT*NTRAC);
42121Sbill 		i = ((i/NSECT)<<8)+(i%NSECT);
42221Sbill 		i = NSECT*(i>>8) + (i&0377) + b + 1;
42321Sbill 		if (i >= NSECT*NTRAC) {
42421Sbill 			i -= NSECT*NTRAC;
42521Sbill 			rp->hpdc = bp->b_cylin + 1;
42621Sbill 		} else
42721Sbill 			rp->hpdc = bp->b_cylin;
42821Sbill 		rp->hpda = ((i/NSECT)<<8) + (i%NSECT);
42921Sbill 		rp->hpcs1 = DCLR|GO;
43021Sbill 		((struct mba_regs *)MBA0)->mba_sr = -1;
43121Sbill 		((struct mba_regs *)MBA0)->mba_var =
43221Sbill 			((map+1)<<9)|((int)bp->b_un.b_addr&0x1ff);
43321Sbill 		rp->hpcs1 = RCOM|GO;
43421Sbill 		return(1);
43521Sbill 	} else
43621Sbill 		return(0);
43721Sbill }
43821Sbill 
43921Sbill short
44021Sbill piget(pad)
44121Sbill {
44221Sbill 	register b, savemap;
44321Sbill 	register short s;
44421Sbill 
44521Sbill 	savemap = (int)mmap;
44621Sbill 	b = (pad>>9)&0x7fffff;
44721Sbill 	*(int *)mmap = b|(PG_V|PG_KR);
44821Sbill 	mtpr(TBIS, vmmap);
44921Sbill 	s = *(short *)&vmmap[pad&0x1ff];
45021Sbill 	*(int *)mmap = savemap;
45121Sbill 	mtpr(TBIS, vmmap);
45221Sbill 	return(s);
45321Sbill }
45421Sbill 
45521Sbill piput(pad, val)
45621Sbill {
45721Sbill 	register b, savemap;
45821Sbill 	register short *p;
45921Sbill 
46021Sbill 	savemap = (int)mmap;
46121Sbill 	b = (pad>>9)&0x7fffff;
46221Sbill 	*(int *)mmap = b|(PG_V|PG_KW);
46321Sbill 	mtpr(TBIS, vmmap);
46421Sbill 	p = (short *)&vmmap[pad&0x1ff];
46521Sbill 	*p = val;
46621Sbill 	*(int *)mmap = savemap;
46721Sbill 	mtpr(TBIS, vmmap);
46821Sbill }
469