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