xref: /csrg-svn/sys/vax/mba/hp.c (revision 21)
1*21Sbill /*	hp.c	3.1	10/14/12	*/
2*21Sbill 
3*21Sbill /*
4*21Sbill  * RP04/RP06/RM03 disk driver
5*21Sbill  */
6*21Sbill 
7*21Sbill #include "../h/param.h"
8*21Sbill #include "../h/systm.h"
9*21Sbill #include "../h/buf.h"
10*21Sbill #include "../h/conf.h"
11*21Sbill #include "../h/dir.h"
12*21Sbill #include "../h/user.h"
13*21Sbill #include "../h/map.h"
14*21Sbill #include "../h/mba.h"
15*21Sbill #include "../h/mtpr.h"
16*21Sbill #include "../h/pte.h"
17*21Sbill 
18*21Sbill #define	DK_N	0
19*21Sbill 
20*21Sbill struct	device
21*21Sbill {
22*21Sbill 	int	hpcs1;		/* control and Status register 1 */
23*21Sbill 	int	hpds;		/* Drive Status */
24*21Sbill 	int	hper1;		/* Error register 1 */
25*21Sbill 	int	hpmr;		/* Maintenance */
26*21Sbill 	int	hpas;		/* Attention Summary */
27*21Sbill 	int	hpda;		/* Desired address register */
28*21Sbill 	int	hpdt;		/* Drive type */
29*21Sbill 	int	hpla;		/* Look ahead */
30*21Sbill 	int	hpsn;		/* serial number */
31*21Sbill 	int	hpof;		/* Offset register */
32*21Sbill 	int	hpdc;		/* Desired Cylinder address register */
33*21Sbill 	int	hpcc;		/* Current Cylinder */
34*21Sbill 	int	hper2;		/* Error register 2 */
35*21Sbill 	int	hper3;		/* Error register 3 */
36*21Sbill 	int	hpec1;		/* Burst error bit position */
37*21Sbill 	int	hpec2;		/* Burst error bit pattern */
38*21Sbill };
39*21Sbill 
40*21Sbill #define	HPADDR	((struct device *)(MBA0 + MBA_ERB))
41*21Sbill #define	NHP	1
42*21Sbill #define	RP	022
43*21Sbill #define	RM	024
44*21Sbill #define	NSECT	22
45*21Sbill #define	NTRAC	19
46*21Sbill #define	NRMSECT	32
47*21Sbill #define	NRMTRAC	5
48*21Sbill #define	SDIST	2
49*21Sbill #define	RDIST	6
50*21Sbill 
51*21Sbill struct	size
52*21Sbill {
53*21Sbill 	daddr_t	nblocks;
54*21Sbill 	int	cyloff;
55*21Sbill } hp_sizes[8] =
56*21Sbill {
57*21Sbill 	15884,	0,		/* cyl 0 thru 37 */
58*21Sbill 	33440,	38,		/* cyl 38 thru 117 */
59*21Sbill 	8360,	98,		/* cyl 98 thru 117 */
60*21Sbill #ifdef ERNIE
61*21Sbill 	15884,	118,		/* cyl 118 thru 155 */
62*21Sbill 	66880,	156,		/* cyl 156 thru 315 */
63*21Sbill 	0,	0,
64*21Sbill 	291346,	118,		/* cyl 118 thru 814, (like distrib) */
65*21Sbill 	208582,	316,		/* cyl 316 thru 814 */
66*21Sbill #else
67*21Sbill 	0,	0,
68*21Sbill 	0,	0,
69*21Sbill 	0,	0,
70*21Sbill 	291346,	118,		/* cyl 118 thru 814 */
71*21Sbill 	0,	0,
72*21Sbill #endif
73*21Sbill }, rm_sizes[8] = {
74*21Sbill 	15884,	0,		/* cyl 0 thru 99 */
75*21Sbill 	33440,	100,		/* cyl 100 thru 309 */
76*21Sbill 	0,	0,
77*21Sbill 	0,	0,
78*21Sbill 	0,	0,
79*21Sbill 	0,	0,
80*21Sbill 	82080,	310,		/* cyl 310 thru 822 */
81*21Sbill 	0,	0,
82*21Sbill };
83*21Sbill 
84*21Sbill #define	P400	020
85*21Sbill #define	M400	0220
86*21Sbill #define	P800	040
87*21Sbill #define	M800	0240
88*21Sbill #define	P1200	060
89*21Sbill #define	M1200	0260
90*21Sbill int	hp_offset[16] =
91*21Sbill {
92*21Sbill 	P400, M400, P400, M400,
93*21Sbill 	P800, M800, P800, M800,
94*21Sbill 	P1200, M1200, P1200, M1200,
95*21Sbill 	0, 0, 0, 0,
96*21Sbill };
97*21Sbill 
98*21Sbill struct	buf	hptab;
99*21Sbill struct	buf	rhpbuf;
100*21Sbill struct	buf	hputab[NHP];
101*21Sbill char	hp_type[NHP];	/* drive type */
102*21Sbill 
103*21Sbill #define	GO	01
104*21Sbill #define	PRESET	020
105*21Sbill #define	RTC	016
106*21Sbill #define	OFFSET	014
107*21Sbill #define	SEARCH	030
108*21Sbill #define	RECAL	06
109*21Sbill #define	DCLR	010
110*21Sbill #define	WCOM	060
111*21Sbill #define	RCOM	070
112*21Sbill 
113*21Sbill #define	IE	0100
114*21Sbill #define	PIP	020000
115*21Sbill #define	DRY	0200
116*21Sbill #define	ERR	040000
117*21Sbill #define	TRE	040000
118*21Sbill #define	DCK	0100000
119*21Sbill #define	WLE	04000
120*21Sbill #define	ECH	0100
121*21Sbill #define	VV	0100
122*21Sbill #define	DPR	0400
123*21Sbill #define	MOL	010000
124*21Sbill #define	FMT22	010000
125*21Sbill 
126*21Sbill #define	b_cylin b_resid
127*21Sbill 
128*21Sbill #ifdef INTRLVE
129*21Sbill daddr_t dkblock();
130*21Sbill #endif
131*21Sbill 
132*21Sbill hpstrategy(bp)
133*21Sbill register struct buf *bp;
134*21Sbill {
135*21Sbill 	register struct buf *dp;
136*21Sbill 	register unit, xunit, nspc;
137*21Sbill 	long sz, bn;
138*21Sbill 	struct size *sizes;
139*21Sbill 
140*21Sbill 	xunit = minor(bp->b_dev) & 077;
141*21Sbill 	sz = bp->b_bcount;
142*21Sbill 	sz = (sz+511) >> 9;
143*21Sbill 	unit = dkunit(bp);
144*21Sbill 	if (hp_type[unit] == 0) {
145*21Sbill 		struct device *hpaddr;
146*21Sbill 
147*21Sbill 		/* determine device type */
148*21Sbill 		hpaddr = (struct device *)((int*)HPADDR + 32*unit);
149*21Sbill 		hp_type[unit] = hpaddr->hpdt;
150*21Sbill 	}
151*21Sbill 	if (hp_type[unit] == RM) {
152*21Sbill 		sizes = rm_sizes;
153*21Sbill 		nspc = NRMSECT*NRMTRAC;
154*21Sbill 	} else {
155*21Sbill 		sizes = hp_sizes;
156*21Sbill 		nspc = NSECT*NTRAC;
157*21Sbill 	}
158*21Sbill 	if (unit >= NHP ||
159*21Sbill 	    bp->b_blkno < 0 ||
160*21Sbill 	    (bn = dkblock(bp))+sz > sizes[xunit&07].nblocks) {
161*21Sbill 		bp->b_flags |= B_ERROR;
162*21Sbill 		iodone(bp);
163*21Sbill 		return;
164*21Sbill 	}
165*21Sbill 	bp->b_cylin = bn/nspc + sizes[xunit&07].cyloff;
166*21Sbill 	dp = &hputab[unit];
167*21Sbill 	VOID spl5();
168*21Sbill 	disksort(dp, bp);
169*21Sbill 	if (dp->b_active == 0) {
170*21Sbill 		hpustart(unit);
171*21Sbill 		if(hptab.b_active == 0)
172*21Sbill 			hpstart();
173*21Sbill 	}
174*21Sbill 	VOID spl0();
175*21Sbill }
176*21Sbill 
177*21Sbill hpustart(unit)
178*21Sbill register unit;
179*21Sbill {
180*21Sbill 	register struct buf *bp, *dp;
181*21Sbill 	register struct device *hpaddr;
182*21Sbill 	daddr_t bn;
183*21Sbill 	int sn, cn, csn;
184*21Sbill 
185*21Sbill 	((struct mba_regs *)MBA0)->mba_cr |= MBAIE;
186*21Sbill 	HPADDR->hpas = 1<<unit;
187*21Sbill 
188*21Sbill 	if(unit >= NHP)
189*21Sbill 		return;
190*21Sbill /*
191*21Sbill 	dk_busy &= ~(1<<(unit+DK_N));
192*21Sbill */
193*21Sbill 	dp = &hputab[unit];
194*21Sbill 	if((bp=dp->b_actf) == NULL)
195*21Sbill 		return;
196*21Sbill 	hpaddr = (struct device *)((int *)HPADDR + 32*unit);
197*21Sbill 	if((hpaddr->hpds & VV) == 0) {
198*21Sbill 		hpaddr->hpcs1 = PRESET|GO;
199*21Sbill 		hpaddr->hpof = FMT22;
200*21Sbill 	}
201*21Sbill 	if(dp->b_active)
202*21Sbill 		goto done;
203*21Sbill 	dp->b_active++;
204*21Sbill 	if ((hpaddr->hpds & (DPR|MOL)) != (DPR|MOL))
205*21Sbill 		goto done;
206*21Sbill 
207*21Sbill 	bn = dkblock(bp);
208*21Sbill 	cn = bp->b_cylin;
209*21Sbill 	if(hp_type[unit] == RM) {
210*21Sbill 		sn = bn%(NRMSECT*NRMTRAC);
211*21Sbill 		sn = (sn+NRMSECT-SDIST)%NRMSECT;
212*21Sbill 	} else {
213*21Sbill 		sn = bn%(NSECT*NTRAC);
214*21Sbill 		sn = (sn+NSECT-SDIST)%NSECT;
215*21Sbill 	}
216*21Sbill 
217*21Sbill 	if(cn - (hpaddr->hpdc & 0xffff))
218*21Sbill 		goto search;
219*21Sbill 	csn = ((hpaddr->hpla & 0xffff)>>6) - sn + SDIST - 1;
220*21Sbill 	if(csn < 0)
221*21Sbill 		csn += NSECT;
222*21Sbill 	if(csn > NSECT-RDIST)
223*21Sbill 		goto done;
224*21Sbill 
225*21Sbill search:
226*21Sbill 	hpaddr->hpdc = cn;
227*21Sbill 	hpaddr->hpda = sn;
228*21Sbill 	hpaddr->hpcs1 = SEARCH|GO;
229*21Sbill /*
230*21Sbill 	unit += DK_N;
231*21Sbill 	dk_busy |= 1<<unit;
232*21Sbill 	dk_numb[unit] += 1;
233*21Sbill */
234*21Sbill 	return;
235*21Sbill 
236*21Sbill done:
237*21Sbill 	dp->b_forw = NULL;
238*21Sbill 	if(hptab.b_actf == NULL)
239*21Sbill 		hptab.b_actf = dp; else
240*21Sbill 		hptab.b_actl->b_forw = dp;
241*21Sbill 	hptab.b_actl = dp;
242*21Sbill }
243*21Sbill 
244*21Sbill hpstart()
245*21Sbill {
246*21Sbill 	register struct buf *bp, *dp;
247*21Sbill 	register unit;
248*21Sbill 	register struct device *hpaddr;
249*21Sbill 	daddr_t bn;
250*21Sbill 	int dn, sn, tn, cn, nspc, ns;
251*21Sbill 
252*21Sbill loop:
253*21Sbill 	if ((dp = hptab.b_actf) == NULL)
254*21Sbill 		return;
255*21Sbill 	if ((bp = dp->b_actf) == NULL) {
256*21Sbill 		hptab.b_actf = dp->b_forw;
257*21Sbill 		goto loop;
258*21Sbill 	}
259*21Sbill 	hptab.b_active++;
260*21Sbill 	unit = minor(bp->b_dev) & 077;
261*21Sbill 	dn = dkunit(bp);
262*21Sbill 	bn = dkblock(bp);
263*21Sbill 	if (hp_type[dn] == RM) {
264*21Sbill 		nspc = NRMSECT*NRMTRAC;
265*21Sbill 		ns = NRMSECT;
266*21Sbill 		cn = rm_sizes[unit&07].cyloff;
267*21Sbill 	} else {
268*21Sbill 		nspc = NSECT*NTRAC;
269*21Sbill 		ns = NSECT;
270*21Sbill 		cn = hp_sizes[unit&07].cyloff;
271*21Sbill 	}
272*21Sbill 	cn += bn/nspc;
273*21Sbill 	sn = bn%nspc;
274*21Sbill 	tn = sn/ns;
275*21Sbill 	sn = sn%ns;
276*21Sbill 
277*21Sbill 	hpaddr =  (struct device *)((int *)HPADDR + 32*dn);
278*21Sbill 	if ((hpaddr->hpds & (DPR|MOL)) != (DPR|MOL)) {
279*21Sbill 		hptab.b_active = 0;
280*21Sbill 		hptab.b_errcnt = 0;
281*21Sbill 		dp->b_actf = bp->av_forw;
282*21Sbill 		bp->b_flags |= B_ERROR;
283*21Sbill 		iodone(bp);
284*21Sbill 		goto loop;
285*21Sbill 	}
286*21Sbill 	if(hptab.b_errcnt >= 16) {
287*21Sbill 		hpaddr->hpof = hp_offset[hptab.b_errcnt & 017] | FMT22;
288*21Sbill 		((struct mba_regs *)MBA0)->mba_cr &= ~MBAIE;
289*21Sbill 		hpaddr->hpcs1 = OFFSET|GO;
290*21Sbill 		while(hpaddr->hpds & PIP)
291*21Sbill 			;
292*21Sbill 		((struct mba_regs *)MBA0)->mba_cr |= MBAIE;
293*21Sbill 	}
294*21Sbill 	hpaddr->hpdc = cn;
295*21Sbill 	hpaddr->hpda = (tn << 8) + sn;
296*21Sbill 	mbastart(bp, (int *)hpaddr);
297*21Sbill 
298*21Sbill 	dk_busy |= 1<<(DK_N /*+NHP*/);
299*21Sbill 	dk_numb[DK_N /*+NHP*/] += 1;
300*21Sbill 	unit = bp->b_bcount>>6;
301*21Sbill 	dk_wds[DK_N /*+NHP*/] += unit;
302*21Sbill }
303*21Sbill 
304*21Sbill hpintr(mbastat, as)
305*21Sbill {
306*21Sbill 	register struct buf *bp, *dp;
307*21Sbill 	register unit;
308*21Sbill 	register struct device *hpaddr;
309*21Sbill 
310*21Sbill 	if(hptab.b_active) {
311*21Sbill 		dk_busy &= ~(1<<(DK_N /*+NHP*/));
312*21Sbill 		dp = hptab.b_actf;
313*21Sbill 		bp = dp->b_actf;
314*21Sbill 		unit = dkunit(bp);
315*21Sbill 		hpaddr = (struct device *)((int *)HPADDR + 32*unit);
316*21Sbill 		if (hpaddr->hpds & ERR || mbastat & MBAEBITS) {		/* error bit */
317*21Sbill 			while((hpaddr->hpds & DRY) == 0)
318*21Sbill 				;
319*21Sbill 			if(++hptab.b_errcnt > 28 || hpaddr->hper1&WLE)
320*21Sbill 				bp->b_flags |= B_ERROR; else
321*21Sbill 				hptab.b_active = 0;
322*21Sbill 			if(hptab.b_errcnt > 27)
323*21Sbill 				deverror(bp, mbastat, hpaddr->hper1);
324*21Sbill 			if ((hpaddr->hper1&0xffff) == DCK) {
325*21Sbill 				if (hpecc(hpaddr, bp))
326*21Sbill 					return;
327*21Sbill 			}
328*21Sbill 			hpaddr->hpcs1 = DCLR|GO;
329*21Sbill 			if((hptab.b_errcnt&07) == 4) {
330*21Sbill 				((struct mba_regs *)MBA0)->mba_cr &= ~MBAIE;
331*21Sbill 				hpaddr->hpcs1 = RECAL|GO;
332*21Sbill 				while(hpaddr->hpds & PIP)
333*21Sbill 					;
334*21Sbill 				((struct mba_regs *)MBA0)->mba_cr |= MBAIE;
335*21Sbill 			}
336*21Sbill 		}
337*21Sbill 		if(hptab.b_active) {
338*21Sbill 			if(hptab.b_errcnt) {
339*21Sbill 				((struct mba_regs *)MBA0)->mba_cr &= ~MBAIE;
340*21Sbill 				hpaddr->hpcs1 = RTC|GO;
341*21Sbill 				while(hpaddr->hpds & PIP)
342*21Sbill 					;
343*21Sbill 				((struct mba_regs *)MBA0)->mba_cr |= MBAIE;
344*21Sbill 			}
345*21Sbill 			hptab.b_active = 0;
346*21Sbill 			hptab.b_errcnt = 0;
347*21Sbill 			hptab.b_actf = dp->b_forw;
348*21Sbill 			dp->b_active = 0;
349*21Sbill 			dp->b_errcnt = 0;
350*21Sbill 			dp->b_actf = bp->av_forw;
351*21Sbill 			bp->b_resid = -(((struct mba_regs *)MBA0)->mba_bcr) & 0xffff;
352*21Sbill 			iodone(bp);
353*21Sbill 			if(dp->b_actf)
354*21Sbill 				hpustart(unit);
355*21Sbill 		}
356*21Sbill 		as &= ~(1<<unit);
357*21Sbill 	} else {
358*21Sbill 		if(as == 0)
359*21Sbill 			((struct mba_regs *)MBA0)->mba_cr |= MBAIE;
360*21Sbill 	}
361*21Sbill 	for(unit=0; unit<NHP; unit++)
362*21Sbill 		if(as & (1<<unit))
363*21Sbill 			hpustart(unit);
364*21Sbill 	hpstart();
365*21Sbill }
366*21Sbill 
367*21Sbill hpread(dev)
368*21Sbill {
369*21Sbill 
370*21Sbill 	physio(hpstrategy, &rhpbuf, dev, B_READ, minphys);
371*21Sbill }
372*21Sbill 
373*21Sbill hpwrite(dev)
374*21Sbill {
375*21Sbill 
376*21Sbill 	physio(hpstrategy, &rhpbuf, dev, B_WRITE, minphys);
377*21Sbill }
378*21Sbill 
379*21Sbill hpecc(rp, bp)
380*21Sbill register struct device *rp;
381*21Sbill register struct buf *bp;
382*21Sbill {
383*21Sbill 	register i;
384*21Sbill 	register b, n, map, mix;
385*21Sbill 	register char *cp;
386*21Sbill 	register mask;
387*21Sbill 	short piget();
388*21Sbill 	extern char buffers[][];
389*21Sbill 
390*21Sbill 	b = (((((struct mba_regs *)MBA0)->mba_bcr&0xffff) +
391*21Sbill 		(bp->b_bcount) - 1)>>9)&0177;
392*21Sbill 	printf("%D ", bp->b_blkno+b);
393*21Sbill 	prdev("ECC", bp->b_dev);
394*21Sbill 	mask = rp->hpec2&0xffff;
395*21Sbill 	if (mask == 0) {
396*21Sbill 		rp->hpof = FMT22;
397*21Sbill 		return(0);
398*21Sbill 	}
399*21Sbill 	i = (rp->hpec1&0xffff) - 1;
400*21Sbill 	n = i&017;
401*21Sbill 	i = (i&~017)>>3;
402*21Sbill 	if (bp->b_flags&B_PHYS)
403*21Sbill 		map = 128 + b;
404*21Sbill 	else
405*21Sbill 		map = ((bp->b_un.b_addr - (char *)buffers)>>9) + b;
406*21Sbill 	mix = i + ((int)bp->b_un.b_addr&0x1ff);
407*21Sbill 	i += b<<9;
408*21Sbill 	if ( i < bp->b_bcount) {
409*21Sbill 		cp = (char *)((((int *)MBA0_MAP)[map+(mix>>9)]&0x1fffff)<<9)+(mix&0x1ff);
410*21Sbill 		piput((int)cp,piget((int)cp)^(mask<<n));
411*21Sbill 	}
412*21Sbill 	mix += 2;
413*21Sbill 	i += 2;
414*21Sbill 	if (i < bp->b_bcount) {
415*21Sbill 		cp = (char *)((((int *)MBA0_MAP)[map+(mix>>9)]&0x1fffff)<<9)+(mix&0x1ff);
416*21Sbill 		piput((int)cp,piget((int)cp)^(mask>>(16-n)));
417*21Sbill 	}
418*21Sbill 	hptab.b_active++;
419*21Sbill 	if (((struct mba_regs *)MBA0)->mba_bcr) {
420*21Sbill 		i = bp->b_blkno%(NSECT*NTRAC);
421*21Sbill 		i = ((i/NSECT)<<8)+(i%NSECT);
422*21Sbill 		i = NSECT*(i>>8) + (i&0377) + b + 1;
423*21Sbill 		if (i >= NSECT*NTRAC) {
424*21Sbill 			i -= NSECT*NTRAC;
425*21Sbill 			rp->hpdc = bp->b_cylin + 1;
426*21Sbill 		} else
427*21Sbill 			rp->hpdc = bp->b_cylin;
428*21Sbill 		rp->hpda = ((i/NSECT)<<8) + (i%NSECT);
429*21Sbill 		rp->hpcs1 = DCLR|GO;
430*21Sbill 		((struct mba_regs *)MBA0)->mba_sr = -1;
431*21Sbill 		((struct mba_regs *)MBA0)->mba_var =
432*21Sbill 			((map+1)<<9)|((int)bp->b_un.b_addr&0x1ff);
433*21Sbill 		rp->hpcs1 = RCOM|GO;
434*21Sbill 		return(1);
435*21Sbill 	} else
436*21Sbill 		return(0);
437*21Sbill }
438*21Sbill 
439*21Sbill short
440*21Sbill piget(pad)
441*21Sbill {
442*21Sbill 	register b, savemap;
443*21Sbill 	register short s;
444*21Sbill 
445*21Sbill 	savemap = (int)mmap;
446*21Sbill 	b = (pad>>9)&0x7fffff;
447*21Sbill 	*(int *)mmap = b|(PG_V|PG_KR);
448*21Sbill 	mtpr(TBIS, vmmap);
449*21Sbill 	s = *(short *)&vmmap[pad&0x1ff];
450*21Sbill 	*(int *)mmap = savemap;
451*21Sbill 	mtpr(TBIS, vmmap);
452*21Sbill 	return(s);
453*21Sbill }
454*21Sbill 
455*21Sbill piput(pad, val)
456*21Sbill {
457*21Sbill 	register b, savemap;
458*21Sbill 	register short *p;
459*21Sbill 
460*21Sbill 	savemap = (int)mmap;
461*21Sbill 	b = (pad>>9)&0x7fffff;
462*21Sbill 	*(int *)mmap = b|(PG_V|PG_KW);
463*21Sbill 	mtpr(TBIS, vmmap);
464*21Sbill 	p = (short *)&vmmap[pad&0x1ff];
465*21Sbill 	*p = val;
466*21Sbill 	*(int *)mmap = savemap;
467*21Sbill 	mtpr(TBIS, vmmap);
468*21Sbill }
469