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