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