xref: /csrg-svn/sys/vax/mba/hp.c (revision 16791)
1 /*	hp.c	6.4	84/07/31	*/
2 
3 #ifdef HPDEBUG
4 int	hpdebug;
5 #endif
6 #ifdef HPBDEBUG
7 int	hpbdebug;
8 #endif
9 
10 #include "hp.h"
11 #if NHP > 0
12 /*
13  * HP disk driver for RP0x+RMxx+ML11
14  *
15  * TODO:
16  *	check RM80 skip sector handling when ECC's occur later
17  *	check offset recovery handling
18  *	see if DCLR and/or RELEASE set attention status
19  *	print bits of mr && mr2 symbolically
20  */
21 #include "../machine/pte.h"
22 
23 #include "../h/param.h"
24 #include "../h/systm.h"
25 #include "../h/dk.h"
26 #include "../h/buf.h"
27 #include "../h/conf.h"
28 #include "../h/dir.h"
29 #include "../h/user.h"
30 #include "../h/map.h"
31 #include "../vax/mtpr.h"
32 #include "../h/vm.h"
33 #include "../h/cmap.h"
34 #include "../h/dkbad.h"
35 #include "../h/ioctl.h"
36 #include "../h/uio.h"
37 
38 #include "../vax/dkio.h"
39 #include "../vaxmba/mbareg.h"
40 #include "../vaxmba/mbavar.h"
41 #include "../vaxmba/hpreg.h"
42 
43 /* THIS SHOULD BE READ OFF THE PACK, PER DRIVE */
44 struct	size {
45 	daddr_t	nblocks;
46 	int	cyloff;
47 } rp06_sizes[8] = {
48 	15884,	0,		/* A=cyl 0 thru 37 */
49 	33440,	38,		/* B=cyl 38 thru 117 */
50 	340670,	0,		/* C=cyl 0 thru 814 */
51 	15884,	118,		/* D=cyl 118 thru 155 */
52 	55936,	156,		/* E=cyl 156 thru 289 */
53 	219384,	290,		/* F=cyl 290 thru 814 */
54 	291280,	118,		/* G=cyl 118 thru 814 */
55 	0,	0,
56 }, rp05_sizes[8] = {
57 	15884,	0,		/* A=cyl 0 thru 37 */
58 	33440,	38,		/* B=cyl 38 thru 117 */
59 	171798,	0,		/* C=cyl 0 thru 410 */
60 	15884,	118,		/* D=cyl 118 thru 155 */
61 	55936,	156,		/* E=cyl 156 thru 289 */
62 	50512,	290,		/* F=cyl 290 thru 410 */
63 	122408,	118,		/* G=cyl 118 thru 410 */
64 	0,	0,
65 }, rm03_sizes[8] = {
66 	15884,	0,		/* A=cyl 0 thru 99 */
67 	33440,	100,		/* B=cyl 100 thru 308 */
68 	131680,	0,		/* C=cyl 0 thru 822 */
69 	15884,	309,		/* D=cyl 309 thru 408 */
70 	55936,	409,		/* E=cyl 409 thru 758 */
71 	10144,	759,		/* F=cyl 759 thru 822 */
72 	82144,	309,		/* G=cyl 309 thru 822 */
73 	0,	0,
74 }, rm05_sizes[8] = {
75 	15884,	0,		/* A=cyl 0 thru 26 */
76 	33440,	27,		/* B=cyl 27 thru 81 */
77 	500384,	0,		/* C=cyl 0 thru 822 */
78 	15884,	562,		/* D=cyl 562 thru 588 */
79 	55936,	589,		/* E=cyl 589 thru 680 */
80 	86240,	681,		/* F=cyl 681 thru 822 */
81 	158592,	562,		/* G=cyl 562 thru 822 */
82 	291346,	82,		/* H=cyl 82 thru 561 */
83 }, rm80_sizes[8] = {
84 	15884,	0,		/* A=cyl 0 thru 36 */
85 	33440,	37,		/* B=cyl 37 thru 114 */
86 	242606,	0,		/* C=cyl 0 thru 558 */
87 	15884,	115,		/* D=cyl 115 thru 151 */
88 	55936,	152,		/* E=cyl 152 thru 280 */
89 	120559,	281,		/* F=cyl 281 thru 558 */
90 	192603,	115,		/* G=cyl 115 thru 558 */
91 	0,	0,
92 }, rp07_sizes[8] = {
93 	15884,	0,		/* A=cyl 0 thru 9 */
94 	66880,	10,		/* B=cyl 10 thru 51 */
95 	1008000, 0,		/* C=cyl 0 thru 629 */
96 	15884,	235,		/* D=cyl 235 thru 244 */
97 	307200,	245,		/* E=cyl 245 thru 436 */
98 	308650,	437,		/* F=cyl 437 thru 629 */
99 	631850,	235,		/* G=cyl 235 thru 629 */
100 	291346,	52,		/* H=cyl 52 thru 234 */
101 }, cdc9775_sizes[8] = {
102 	15884,	0,		/* A=cyl 0 thru 12 */
103 	66880,	13,		/* B=cyl 13 thru 65 */
104 	1077760, 0,		/* C=cyl 0 thru 841 */
105 	15884,	294,		/* D=cyl 294 thru 306 */
106 	307200,	307,		/* E=cyl 307 thru 546 */
107 	377440,	547,		/* F=cyl 547 thru 841 */
108 	701280,	294,		/* G=cyl 294 thru 841 */
109 	291346,	66,		/* H=cyl 66 thru 293 */
110 }, cdc9730_sizes[8] = {
111 	15884,	0,		/* A=cyl 0 thru 49 */
112 	33440,	50,		/* B=cyl 50 thru 154 */
113 	263360,	0,		/* C=cyl 0 thru 822 */
114 	15884,	155,		/* D=cyl 155 thru 204 */
115 	55936,	205,		/* E=cyl 205 thru 379 */
116 	141664,	380,		/* F=cyl 380 thru 822 */
117 	213664,	155,		/* G=cyl 155 thru 822 */
118 	0,	0,
119 }, capricorn_sizes[8] = {
120 	15884,	0,		/* A=cyl 0 thru 31 */
121 	33440,	32,		/* B=cyl 32 thru 97 */
122 	524288,	0,		/* C=cyl 0 thru 1023 */
123 	15884,	668,		/* D=cyl 668 thru 699 */
124 	55936,	700,		/* E=cyl 700 thru 809 */
125 	109472,	810,		/* F=cyl 810 thru 1023 */
126 	182176,	668,		/* G=cyl 668 thru 1023 */
127 	291346,	98,		/* H=cyl 98 thru 667 */
128 }, eagle_sizes[8] = {
129 	15884,	0,		/* A=cyl 0 thru 16 */
130 	66880,	17,		/* B=cyl 17 thru 86 */
131 	808320,	0,		/* C=cyl 0 thru 841 */
132 	15884,	391,		/* D=cyl 391 thru 407 */
133 	307200,	408,		/* E=cyl 408 thru 727 */
134 	109296,	728,		/* F=cyl 728 thru 841 */
135 	432816,	391,		/* G=cyl 391 thru 841 */
136 	291346,	87,		/* H=cyl 87 thru 390 */
137 }, ampex_sizes[8] = {
138 	15884,	0,		/* A=cyl 0 thru 26 */
139 	33440,	27,		/* B=cyl 27 thru 81 */
140 	495520,	0,		/* C=cyl 0 thru 814 */
141 	15884,	562,		/* D=cyl 562 thru 588 */
142 	55936,	589,		/* E=cyl 589 thru 680 */
143 	81312,	681,		/* F=cyl 681 thru 814 */
144 	153664,	562,		/* G=cyl 562 thru 814 */
145 	291346,	82,		/* H=cyl 82 thru 561 */
146 };
147 /* END OF STUFF WHICH SHOULD BE READ IN PER DISK */
148 
149 /*
150  * Table for converting Massbus drive types into
151  * indices into the partition tables.  Slots are
152  * left for those drives devined from other means
153  * (e.g. SI, AMPEX, etc.).
154  */
155 short	hptypes[] = {
156 #define	HPDT_RM03	0
157 	MBDT_RM03,
158 #define	HPDT_RM05	1
159 	MBDT_RM05,
160 #define	HPDT_RP06	2
161 	MBDT_RP06,
162 #define	HPDT_RM80	3
163 	MBDT_RM80,
164 #define	HPDT_RP04	4
165 	MBDT_RP04,
166 #define	HPDT_RP05	5
167 	MBDT_RP05,
168 #define	HPDT_RP07	6
169 	MBDT_RP07,
170 #define	HPDT_ML11A	7
171 	MBDT_ML11A,
172 #define	HPDT_ML11B	8
173 	MBDT_ML11B,
174 #define	HPDT_9775	9
175 	-1,
176 #define	HPDT_9730	10
177 	-1,
178 #define	HPDT_CAPRICORN	11
179 	-1,
180 #define HPDT_EAGLE	12
181 	-1,
182 #define	HPDT_9300	13
183 	-1,
184 #define HPDT_RM02	14
185 	MBDT_RM02,		/* beware, actually capricorn or eagle */
186 	0
187 };
188 struct	mba_device *hpinfo[NHP];
189 int	hpattach(),hpustart(),hpstart(),hpdtint();
190 struct	mba_driver hpdriver =
191 	{ hpattach, 0, hpustart, hpstart, hpdtint, 0,
192 	  hptypes, "hp", 0, hpinfo };
193 
194 /*
195  * These variable are all measured in sectors.
196  * Sdist is how much to "lead" in the search for a desired sector
197  * (i.e. if want N, search for N-sdist.)
198  * Maxdist and mindist define the region right before our desired sector within
199  * which we don't bother searching.  We don't search when we are already less
200  * then maxdist and more than mindist sectors "before" our desired sector.
201  * Maxdist should be >= sdist.
202  *
203  * Beware, sdist, mindist and maxdist are not well tuned
204  * for many of the drives listed in this table.
205  * Try patching things with something i/o intensive
206  * running and watch iostat.
207  */
208 struct hpst {
209 	short	nsect;		/* # sectors/track */
210 	short	ntrak;		/* # tracks/cylinder */
211 	short	nspc;		/* # sector/cylinders */
212 	short	ncyl;		/* # cylinders */
213 	struct	size *sizes;	/* partition tables */
214 	short	sdist;		/* seek distance metric */
215 	short	maxdist;	/* boundaries of non-searched area */
216 	short	mindist;	/* preceding the target sector */
217 } hpst[] = {
218     { 32, 5,	32*5,	823,	rm03_sizes,	7, 4, 1 },	/* RM03 */
219     { 32, 19,	32*19,	823,	rm05_sizes,	7, 4, 1 },	/* RM05 */
220     { 22,19,	22*19,	815,	rp06_sizes,	7, 4, 1 },	/* RP06 */
221     { 31, 14, 	31*14,	559,	rm80_sizes,	7, 4, 1 },	/* RM80 */
222     { 22, 19,	22*19,	411,	rp05_sizes,	7, 4, 1 },	/* RP04 */
223     { 22, 19,	22*19,	411,	rp05_sizes,	7, 4, 1 },	/* RP05 */
224     { 50, 32,	50*32,	630,	rp07_sizes,    15, 8, 3 },	/* RP07 */
225     { 1, 1,	1,	1,	0,		0, 0, 0 },	/* ML11A */
226     { 1, 1,	1,	1,	0,		0, 0, 0 },	/* ML11B */
227     { 32, 40,	32*40,	843,	cdc9775_sizes,	7, 4, 1 },	/* 9775 */
228     { 32, 10,	32*10,	823,	cdc9730_sizes,	7, 4, 1 },	/* 9730 */
229     { 32, 16,	32*16,	1024,	capricorn_sizes,10,4, 3 },	/* Capricorn */
230     { 48, 20,	48*20,	842,	eagle_sizes,   15, 8, 3 },	/* EAGLE */
231     { 32, 19,	32*19,	815,	ampex_sizes,	7, 4, 1 },	/* 9300 */
232 };
233 
234 u_char	hp_offset[16] = {
235     HPOF_P400, HPOF_M400, HPOF_P400, HPOF_M400,
236     HPOF_P800, HPOF_M800, HPOF_P800, HPOF_M800,
237     HPOF_P1200, HPOF_M1200, HPOF_P1200, HPOF_M1200,
238     0, 0, 0, 0,
239 };
240 
241 struct	buf	rhpbuf[NHP];
242 struct	buf	bhpbuf[NHP];
243 struct	dkbad	hpbad[NHP];
244 
245 struct	hpsoftc {
246 	u_char	sc_hpinit;	/* drive initialized */
247 	u_char	sc_recal;	/* recalibrate state */
248 	u_char	sc_hdr;		/* next i/o includes header */
249 	u_char	sc_doseeks;	/* perform explicit seeks */
250 	daddr_t	sc_mlsize;	/* ML11 size */
251 } hpsoftc[NHP];
252 
253 #define	b_cylin b_resid
254 
255 /* #define ML11 0  to remove ML11 support */
256 #define	ML11	(hptypes[mi->mi_type] == MBDT_ML11A)
257 #define	RP06	(hptypes[mi->mi_type] <= MBDT_RP06)
258 #define	RM80	(hptypes[mi->mi_type] == MBDT_RM80)
259 
260 #define	MASKREG(reg)	((reg)&0xffff)
261 
262 #ifdef INTRLVE
263 daddr_t dkblock();
264 #endif
265 
266 /*ARGSUSED*/
267 hpattach(mi, slave)
268 	register struct mba_device *mi;
269 {
270 
271 	mi->mi_type = hpmaptype(mi);
272 	if (!ML11 && mi->mi_dk >= 0) {
273 		struct hpst *st = &hpst[mi->mi_type];
274 
275 		dk_mspw[mi->mi_dk] = 1.0 / 60 / (st->nsect * 256);
276 	}
277 }
278 
279 /*
280  * Map apparent MASSBUS drive type into manufacturer
281  * specific configuration.  For SI controllers this is done
282  * based on codes in the serial number register.  For
283  * EMULEX controllers, the track and sector attributes are
284  * used when the drive type is an RM02 (not supported by DEC).
285  */
286 hpmaptype(mi)
287 	register struct mba_device *mi;
288 {
289 	register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv;
290 	register int type = mi->mi_type;
291 
292 	/*
293 	 * Model-byte processing for SI controllers.
294 	 * NB:  Only deals with RM03 and RM05 emulations.
295 	 */
296 	if (type == HPDT_RM03 || type == HPDT_RM05) {
297 		int hpsn = hpaddr->hpsn;
298 
299 		if ((hpsn & SIMB_LU) != mi->mi_drive)
300 			return (type);
301 		switch ((hpsn & SIMB_MB) & ~(SIMB_S6|SIRM03|SIRM05)) {
302 
303 		case SI9775D:
304 			printf("hp%d: 9775 (direct)\n", mi->mi_unit);
305 			type = HPDT_9775;
306 			break;
307 
308 		case SI9730D:
309 			printf("hp%d: 9730 (direct)\n", mi->mi_unit);
310 			type = HPDT_9730;
311 			break;
312 
313 		/*
314 		 * Beware, since the only SI controller we
315 		 * have has a 9300 instead of a 9766, we map the
316 		 * drive type into the 9300.  This means that
317 		 * on a 9766 you lose the last 8 cylinders (argh).
318 		 */
319 		case SI9766:
320 			printf("hp%d: 9300\n", mi->mi_unit);
321 			type = HPDT_9300;
322 			break;
323 
324 		case SI9762:
325 			printf("hp%d: 9762\n", mi->mi_unit);
326 			type = HPDT_RM03;
327 			break;
328 
329 		case SICAPD:
330 			printf("hp%d: capricorn\n", mi->mi_unit);
331 			type = HPDT_CAPRICORN;
332 			break;
333 
334 		case SI9751D:
335 			printf("hp%d: eagle\n", mi->mi_unit);
336 			type = HPDT_EAGLE;
337 			break;
338 		}
339 		return (type);
340 	}
341 
342 	/*
343 	 * EMULEX SC750 or SC780.  Poke the holding register.
344 	 */
345 	if (type == HPDT_RM02) {
346 		int ntracks, nsectors;
347 
348 		hpaddr->hpof = HPOF_FMT22;
349 		mbclrattn(mi);
350 		hpaddr->hpcs1 = HP_NOP;
351 		hpaddr->hphr = HPHR_MAXTRAK;
352 		ntracks = MASKREG(hpaddr->hphr) + 1;
353 		if (ntracks == 16) {
354 			printf("hp%d: capricorn\n", mi->mi_unit);
355 			type = HPDT_CAPRICORN;
356 			goto done;
357 		}
358 		if (ntracks == 19) {
359 			printf("hp%d: 9300\n", mi->mi_unit);
360 			type = HPDT_9300;
361 			goto done;
362 		}
363 		hpaddr->hpcs1 = HP_NOP;
364 		hpaddr->hphr = HPHR_MAXSECT;
365 		nsectors = MASKREG(hpaddr->hphr) + 1;
366 		if (ntracks == 20 && nsectors == 48) {
367 			type = HPDT_EAGLE;
368 			printf("hp%d: eagle\n", mi->mi_unit);
369 			goto done;
370 		}
371 		printf("hp%d: ntracks %d, nsectors %d: unknown device\n",
372 			mi->mi_unit, ntracks, nsectors);
373 done:
374 		hpaddr->hpcs1 = HP_DCLR|HP_GO;
375 		mbclrattn(mi);		/* conservative */
376 		return (type);
377 	}
378 
379 	/*
380 	 * Map all ML11's to the same type.  Also calculate
381 	 * transfer rates based on device characteristics.
382 	 */
383 	if (type == HPDT_ML11A || type == HPDT_ML11B) {
384 		register struct hpsoftc *sc = &hpsoftc[mi->mi_unit];
385 		register int trt;
386 
387 		sc->sc_mlsize = hpaddr->hpmr & HPMR_SZ;
388 		if ((hpaddr->hpmr & HPMR_ARRTYP) == 0)
389 			sc->sc_mlsize >>= 2;
390 		if (mi->mi_dk >= 0) {
391 			trt = (hpaddr->hpmr & HPMR_TRT) >> 8;
392 			dk_mspw[mi->mi_dk] = 1.0 / (1<<(20-trt));
393 		}
394 		type = HPDT_ML11A;
395 	}
396 	return (type);
397 }
398 
399 hpopen(dev)
400 	dev_t dev;
401 {
402 	register int unit = minor(dev) >> 3;
403 	register struct mba_device *mi;
404 
405 	if (unit >= NHP || (mi = hpinfo[unit]) == 0 || mi->mi_alive == 0)
406 		return (ENXIO);
407 	return (0);
408 }
409 
410 hpstrategy(bp)
411 	register struct buf *bp;
412 {
413 	register struct mba_device *mi;
414 	register struct hpst *st;
415 	register int unit;
416 	long sz, bn;
417 	int xunit = minor(bp->b_dev) & 07;
418 	int s;
419 
420 	sz = bp->b_bcount;
421 	sz = (sz+511) >> 9;
422 	unit = dkunit(bp);
423 	if (unit >= NHP)
424 		goto bad;
425 	mi = hpinfo[unit];
426 	if (mi == 0 || mi->mi_alive == 0)
427 		goto bad;
428 	st = &hpst[mi->mi_type];
429 	if (ML11) {
430 		struct hpsoftc *sc = &hpsoftc[unit];
431 
432 		if (bp->b_blkno < 0 ||
433 		    dkblock(bp)+sz > sc->sc_mlsize)
434 			goto bad;
435 		bp->b_cylin = 0;
436 	} else {
437 		if (bp->b_blkno < 0 ||
438 		    (bn = dkblock(bp))+sz > st->sizes[xunit].nblocks)
439 			goto bad;
440 		bp->b_cylin = bn/st->nspc + st->sizes[xunit].cyloff;
441 	}
442 	s = spl5();
443 	disksort(&mi->mi_tab, bp);
444 	if (mi->mi_tab.b_active == 0)
445 		mbustart(mi);
446 	splx(s);
447 	return;
448 
449 bad:
450 	bp->b_flags |= B_ERROR;
451 	iodone(bp);
452 	return;
453 }
454 
455 hpustart(mi)
456 	register struct mba_device *mi;
457 {
458 	register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv;
459 	register struct buf *bp = mi->mi_tab.b_actf;
460 	register struct hpst *st;
461 	struct hpsoftc *sc = &hpsoftc[mi->mi_unit];
462 	daddr_t bn;
463 	int sn, tn, dist;
464 
465 	st = &hpst[mi->mi_type];
466 	hpaddr->hpcs1 = 0;
467 	if ((hpaddr->hpcs1&HP_DVA) == 0)
468 		return (MBU_BUSY);
469 	if ((hpaddr->hpds & HPDS_VV) == 0 || !sc->sc_hpinit) {
470 		struct buf *bbp = &bhpbuf[mi->mi_unit];
471 
472 		sc->sc_hpinit = 1;
473 		hpaddr->hpcs1 = HP_DCLR|HP_GO;
474 		if (mi->mi_mba->mba_drv[0].mbd_as & (1<<mi->mi_drive))
475 			printf("DCLR attn\n");
476 		hpaddr->hpcs1 = HP_PRESET|HP_GO;
477 		if (!ML11)
478 			hpaddr->hpof = HPOF_FMT22;
479 		mbclrattn(mi);
480 		if (!ML11) {
481 			bbp->b_flags = B_READ|B_BUSY;
482 			bbp->b_dev = bp->b_dev;
483 			bbp->b_bcount = 512;
484 			bbp->b_un.b_addr = (caddr_t)&hpbad[mi->mi_unit];
485 			bbp->b_blkno = st->ncyl*st->nspc - st->nsect;
486 			bbp->b_cylin = st->ncyl - 1;
487 			mi->mi_tab.b_actf = bbp;
488 			bbp->av_forw = bp;
489 			bp = bbp;
490 		}
491 	}
492 	if (mi->mi_tab.b_active || mi->mi_hd->mh_ndrive == 1)
493 		return (MBU_DODATA);
494 	if (ML11)
495 		return (MBU_DODATA);
496 	if ((hpaddr->hpds & HPDS_DREADY) != HPDS_DREADY)
497 		return (MBU_DODATA);
498 	bn = dkblock(bp);
499 	sn = bn % st->nspc;
500 	tn = sn / st->nsect;
501 	sn = sn % st->nsect;
502 	if (bp->b_cylin == MASKREG(hpaddr->hpdc)) {
503 		if (sc->sc_doseeks)
504 			return (MBU_DODATA);
505 		dist = sn - (MASKREG(hpaddr->hpla) >> 6) - 1;
506 		if (dist < 0)
507 			dist += st->nsect;
508 		if (dist > st->maxdist || dist < st->mindist)
509 			return (MBU_DODATA);
510 	} else
511 		hpaddr->hpdc = bp->b_cylin;
512 	if (sc->sc_doseeks)
513 		hpaddr->hpcs1 = HP_SEEK|HP_GO;
514 	else {
515 		sn = (sn + st->nsect - st->sdist) % st->nsect;
516 		hpaddr->hpda = (tn << 8) + sn;
517 		hpaddr->hpcs1 = HP_SEARCH|HP_GO;
518 	}
519 	return (MBU_STARTED);
520 }
521 
522 hpstart(mi)
523 	register struct mba_device *mi;
524 {
525 	register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv;
526 	register struct buf *bp = mi->mi_tab.b_actf;
527 	register struct hpst *st = &hpst[mi->mi_type];
528 	struct hpsoftc *sc = &hpsoftc[mi->mi_unit];
529 	daddr_t bn;
530 	int sn, tn;
531 
532 	bn = dkblock(bp);
533 	if (ML11)
534 		hpaddr->hpda = bn;
535 	else {
536 		sn = bn%st->nspc;
537 		tn = sn/st->nsect;
538 		sn %= st->nsect;
539 		hpaddr->hpdc = bp->b_cylin;
540 		hpaddr->hpda = (tn << 8) + sn;
541 	}
542 	if (sc->sc_hdr) {
543 		if (bp->b_flags & B_READ)
544 			return (HP_RHDR|HP_GO);
545 		else
546 			return (HP_WHDR|HP_GO);
547 	}
548 	return (0);
549 }
550 
551 hpdtint(mi, mbsr)
552 	register struct mba_device *mi;
553 	int mbsr;
554 {
555 	register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv;
556 	register struct buf *bp = mi->mi_tab.b_actf;
557 	register struct hpst *st;
558 	register int er1, er2;
559 	struct hpsoftc *sc = &hpsoftc[mi->mi_unit];
560 	int retry = 0;
561 
562 	st = &hpst[mi->mi_type];
563 	if (bp->b_flags&B_BAD && hpecc(mi, CONT))
564 		return (MBD_RESTARTED);
565 	if (hpaddr->hpds&HPDS_ERR || mbsr&MBSR_EBITS) {
566 		er1 = hpaddr->hper1;
567 		er2 = hpaddr->hper2;
568 #ifdef HPDEBUG
569 		if (hpdebug) {
570 			int dc = hpaddr->hpdc, da = hpaddr->hpda;
571 
572 			printf("hperr: bp %x cyl %d blk %d as %o ",
573 				bp, bp->b_cylin, bp->b_blkno,
574 				hpaddr->hpas&0xff);
575 			printf("dc %x da %x\n",MASKREG(dc), MASKREG(da));
576 			printf("errcnt %d ", mi->mi_tab.b_errcnt);
577 			printf("mbsr=%b ", mbsr, mbsr_bits);
578 			printf("er1=%b er2=%b\n", MASKREG(er1), HPER1_BITS,
579 			    MASKREG(er2), HPER2_BITS);
580 			DELAY(1000000);
581 		}
582 #endif
583 		if (er1 & HPER1_HCRC) {
584 			er1 &= ~(HPER1_HCE|HPER1_FER);
585 			er2 &= ~HPER2_BSE;
586 		}
587 		if (er1 & HPER1_WLE) {
588 			printf("hp%d: write locked\n", dkunit(bp));
589 			bp->b_flags |= B_ERROR;
590 		} else if (sc->sc_hdr) {
591 			goto hard;
592 		} else if ((er2 & HPER2_BSE) && !ML11) {
593 			if (hpecc(mi, BSE))
594 				return (MBD_RESTARTED);
595 			goto hard;
596 		} else if (MASKREG(er1) == HPER1_FER && RP06) {
597 			if (hpecc(mi, BSE))
598 				return (MBD_RESTARTED);
599 			goto hard;
600 		} else if (RM80 && er2&HPER2_SSE) {
601 			(void) hpecc(mi, SSE);
602 			return (MBD_RESTARTED);
603 		} else if ((er1 & (HPER1_DCK | HPER1_ECH)) == HPER1_DCK) {
604 			if (hpecc(mi, ECC))
605 				return (MBD_RESTARTED);
606 			/* else done */
607 		} else if (++mi->mi_tab.b_errcnt > 27 ||
608 		    (ML11 && mi->mi_tab.b_errcnt > 15) ||
609 		    mbsr & MBSR_HARD ||
610 		    er1 & HPER1_HARD ||
611 		    (!ML11 && (er2 & HPER2_HARD))) {
612  			/*
613  			 * HCRC means the header is screwed up and the sector
614  			 * might well exist in the bad sector table,
615 			 * better check....
616  			 */
617  			if ((er1 & HPER1_HCRC) && !ML11 && hpecc(mi, BSE))
618 				return (MBD_RESTARTED);
619 hard:
620 			if (ML11)
621 				bp->b_blkno = MASKREG(hpaddr->hpda);
622 			else
623 				bp->b_blkno = MASKREG(hpaddr->hpdc) * st->nspc +
624 				   (MASKREG(hpaddr->hpda) >> 8) * st->nsect +
625 				   (hpaddr->hpda&0xff);
626 			/*
627 			 * If we have a data check error or a hard
628 			 * ecc error the bad sector has been read/written,
629 			 * and the controller registers are pointing to
630 			 * the next sector...
631 			 */
632 			 if (er1&(HPER1_DCK|HPER1_ECH) || sc->sc_hdr)
633 				bp->b_blkno--;
634 			harderr(bp, "hp");
635 			if (mbsr & (MBSR_EBITS &~ (MBSR_DTABT|MBSR_MBEXC)))
636 				printf("mbsr=%b ", mbsr, mbsr_bits);
637 			printf("er1=%b er2=%b",
638 			    MASKREG(hpaddr->hper1), HPER1_BITS,
639 			    MASKREG(hpaddr->hper2), HPER2_BITS);
640 			if (hpaddr->hpmr)
641 				printf(" mr=%o", MASKREG(hpaddr->hpmr));
642 			if (hpaddr->hpmr2)
643 				printf(" mr2=%o", MASKREG(hpaddr->hpmr2));
644 			if (sc->sc_hdr)
645 				printf(" (hdr i/o)");
646 			printf("\n");
647 			bp->b_flags |= B_ERROR;
648 		} else
649 			retry = 1;
650 		hpaddr->hpcs1 = HP_DCLR|HP_GO;
651 		if ((mi->mi_tab.b_errcnt & 07) == 4) {
652 			hpaddr->hpcs1 = HP_RECAL|HP_GO;
653 			sc->sc_recal = 1;
654 			return (MBD_RESTARTED);
655 		}
656 	}
657 #ifdef HPDEBUG
658 	else
659 		if (hpdebug && sc->sc_recal) {
660 			printf("recal %d ", sc->sc_recal);
661 			printf("errcnt %d\n", mi->mi_tab.b_errcnt);
662 			printf("mbsr=%b ", mbsr, mbsr_bits);
663 			printf("er1=%b er2=%b\n",
664 			    hpaddr->hper1, HPER1_BITS,
665 			    hpaddr->hper2, HPER2_BITS);
666 		}
667 #endif
668 	switch (sc->sc_recal) {
669 
670 	case 1:
671 		hpaddr->hpdc = bp->b_cylin;
672 		hpaddr->hpcs1 = HP_SEEK|HP_GO;
673 		sc->sc_recal++;
674 		return (MBD_RESTARTED);
675 	case 2:
676 		retry = 1;
677 		break;
678 	}
679 	sc->sc_recal = 0;
680 	if (retry) {
681 		if (mi->mi_tab.b_errcnt >= 16 && (bp->b_flags & B_READ)) {
682 			hpaddr->hpof =
683 			    hp_offset[mi->mi_tab.b_errcnt & 017]|HPOF_FMT22;
684 			hpaddr->hpcs1 = HP_OFFSET|HP_GO;
685 			while ((hpaddr->hpds & (HPDS_DRY | HPDS_PIP)) !=
686 			    HPDS_DRY)
687 				DELAY(10);
688 			mbclrattn(mi);
689 		}
690 		return (MBD_RETRY);
691 	}
692 	sc->sc_hdr = 0;
693 	bp->b_resid = MASKREG(-mi->mi_mba->mba_bcr);
694 	if (mi->mi_tab.b_errcnt >= 16) {
695 		/*
696 		 * This is fast and occurs rarely; we don't
697 		 * bother with interrupts.
698 		 */
699 		hpaddr->hpcs1 = HP_RTC|HP_GO;
700 		while ((hpaddr->hpds & (HPDS_DRY | HPDS_PIP)) != HPDS_DRY)
701 			DELAY(10);
702 		mbclrattn(mi);
703 	}
704 	if (!ML11) {
705 		hpaddr->hpof = HPOF_FMT22;
706 		hpaddr->hpcs1 = HP_RELEASE|HP_GO;
707 	}
708 	return (MBD_DONE);
709 }
710 
711 hpread(dev, uio)
712 	dev_t dev;
713 	struct uio *uio;
714 {
715 	register int unit = minor(dev) >> 3;
716 
717 	if (unit >= NHP)
718 		return (ENXIO);
719 	return (physio(hpstrategy, &rhpbuf[unit], dev, B_READ, minphys, uio));
720 }
721 
722 hpwrite(dev, uio)
723 	dev_t dev;
724 	struct uio *uio;
725 {
726 	register int unit = minor(dev) >> 3;
727 
728 	if (unit >= NHP)
729 		return (ENXIO);
730 	return (physio(hpstrategy, &rhpbuf[unit], dev, B_WRITE, minphys, uio));
731 }
732 
733 /*ARGSUSED*/
734 hpioctl(dev, cmd, data, flag)
735 	dev_t dev;
736 	int cmd;
737 	caddr_t data;
738 	int flag;
739 {
740 
741 	switch (cmd) {
742 
743 	case DKIOCHDR:	/* do header read/write */
744 		hpsoftc[minor(dev) >> 3].sc_hdr = 1;
745 		return (0);
746 
747 	default:
748 		return (ENXIO);
749 	}
750 }
751 
752 hpecc(mi, flag)
753 	register struct mba_device *mi;
754 	int flag;
755 {
756 	register struct mba_regs *mbp = mi->mi_mba;
757 	register struct hpdevice *rp = (struct hpdevice *)mi->mi_drv;
758 	register struct buf *bp = mi->mi_tab.b_actf;
759 	register struct hpst *st = &hpst[mi->mi_type];
760 	int npf, o;
761 	int bn, cn, tn, sn;
762 	int bcr;
763 
764 	bcr = MASKREG(mbp->mba_bcr);
765 	if (bcr)
766 		bcr |= 0xffff0000;		/* sxt */
767 	if (flag == CONT)
768 		npf = bp->b_error;
769 	else
770 		npf = btop(bcr + bp->b_bcount);
771 	o = (int)bp->b_un.b_addr & PGOFSET;
772 	bn = dkblock(bp);
773 	cn = bp->b_cylin;
774 	sn = bn%(st->nspc) + npf;
775 	tn = sn/st->nsect;
776 	sn %= st->nsect;
777 	cn += tn/st->ntrak;
778 	tn %= st->ntrak;
779 	switch (flag) {
780 	case ECC: {
781 		register int i;
782 		caddr_t addr;
783 		struct pte mpte;
784 		int bit, byte, mask;
785 
786 		npf--;		/* because block in error is previous block */
787 		printf("hp%d%c: soft ecc sn%d\n", dkunit(bp),
788 		    'a'+(minor(bp->b_dev)&07), bp->b_blkno + npf);
789 		mask = MASKREG(rp->hpec2);
790 		i = MASKREG(rp->hpec1) - 1;		/* -1 makes 0 origin */
791 		bit = i&07;
792 		i = (i&~07)>>3;
793 		byte = i + o;
794 		while (i < 512 && (int)ptob(npf)+i < bp->b_bcount && bit > -11) {
795 			mpte = mbp->mba_map[npf+btop(byte)];
796 			addr = ptob(mpte.pg_pfnum) + (byte & PGOFSET);
797 			putmemc(addr, getmemc(addr)^(mask<<bit));
798 			byte++;
799 			i++;
800 			bit -= 8;
801 		}
802 		if (bcr == 0)
803 			return (0);
804 		npf++;
805 		break;
806 		}
807 
808 	case SSE:
809 		rp->hpof |= HPOF_SSEI;
810 		mbp->mba_bcr = -(bp->b_bcount - (int)ptob(npf));
811 		break;
812 
813 	case BSE:
814 #ifdef HPBDEBUG
815 		if (hpbdebug)
816 		printf("hpecc, BSE: bn %d cn %d tn %d sn %d\n", bn, cn, tn, sn);
817 #endif
818  		if (rp->hpof&HPOF_SSEI)
819  			sn++;
820 		if ((bn = isbad(&hpbad[mi->mi_unit], cn, tn, sn)) < 0)
821 			return (0);
822 		bp->b_flags |= B_BAD;
823 		bp->b_error = npf + 1;
824 		bn = st->ncyl*st->nspc - st->nsect - 1 - bn;
825 		cn = bn/st->nspc;
826 		sn = bn%st->nspc;
827 		tn = sn/st->nsect;
828 		sn %= st->nsect;
829 		mbp->mba_bcr = -512;
830  		rp->hpof &= ~HPOF_SSEI;
831 #ifdef HPBDEBUG
832 		if (hpbdebug)
833 		printf("revector to cn %d tn %d sn %d\n", cn, tn, sn);
834 #endif
835 		break;
836 
837 	case CONT:
838 #ifdef HPBDEBUG
839 		if (hpbdebug)
840 		printf("hpecc, CONT: bn %d cn %d tn %d sn %d\n", bn,cn,tn,sn);
841 #endif
842 		npf = bp->b_error;
843 		bp->b_flags &= ~B_BAD;
844 		mbp->mba_bcr = -(bp->b_bcount - (int)ptob(npf));
845 		if (MASKREG(mbp->mba_bcr) == 0)
846 			return (0);
847 		break;
848 	}
849 	rp->hpcs1 = HP_DCLR|HP_GO;
850 	if (rp->hpof&HPOF_SSEI)
851 		sn++;
852 	rp->hpdc = cn;
853 	rp->hpda = (tn<<8) + sn;
854 	mbp->mba_sr = -1;
855 	mbp->mba_var = (int)ptob(npf) + o;
856 	rp->hpcs1 = bp->b_flags&B_READ ? HP_RCOM|HP_GO : HP_WCOM|HP_GO;
857 	mi->mi_tab.b_errcnt = 0;	/* error has been corrected */
858 	return (1);
859 }
860 
861 #define	DBSIZE	20
862 
863 hpdump(dev)
864 	dev_t dev;
865 {
866 	register struct mba_device *mi;
867 	register struct mba_regs *mba;
868 	struct hpdevice *hpaddr;
869 	char *start;
870 	int num, unit;
871 	register struct hpst *st;
872 
873 	num = maxfree;
874 	start = 0;
875 	unit = minor(dev) >> 3;
876 	if (unit >= NHP)
877 		return (ENXIO);
878 #define	phys(a,b)	((b)((int)(a)&0x7fffffff))
879 	mi = phys(hpinfo[unit],struct mba_device *);
880 	if (mi == 0 || mi->mi_alive == 0)
881 		return (ENXIO);
882 	mba = phys(mi->mi_hd, struct mba_hd *)->mh_physmba;
883 	mba->mba_cr = MBCR_INIT;
884 	hpaddr = (struct hpdevice *)&mba->mba_drv[mi->mi_drive];
885 	if ((hpaddr->hpds & HPDS_VV) == 0) {
886 		hpaddr->hpcs1 = HP_DCLR|HP_GO;
887 		hpaddr->hpcs1 = HP_PRESET|HP_GO;
888 		hpaddr->hpof = HPOF_FMT22;
889 	}
890 	st = &hpst[mi->mi_type];
891 	if (dumplo < 0 || dumplo + num >= st->sizes[minor(dev)&07].nblocks)
892 		return (EINVAL);
893 	while (num > 0) {
894 		register struct pte *hpte = mba->mba_map;
895 		register int i;
896 		int blk, cn, sn, tn;
897 		daddr_t bn;
898 
899 		blk = num > DBSIZE ? DBSIZE : num;
900 		bn = dumplo + btop(start);
901 		cn = bn/st->nspc + st->sizes[minor(dev)&07].cyloff;
902 		sn = bn%st->nspc;
903 		tn = sn/st->nsect;
904 		sn = sn%st->nsect;
905 		hpaddr->hpdc = cn;
906 		hpaddr->hpda = (tn << 8) + sn;
907 		for (i = 0; i < blk; i++)
908 			*(int *)hpte++ = (btop(start)+i) | PG_V;
909 		mba->mba_sr = -1;
910 		mba->mba_bcr = -(blk*NBPG);
911 		mba->mba_var = 0;
912 		hpaddr->hpcs1 = HP_WCOM | HP_GO;
913 		while ((hpaddr->hpds & HPDS_DRY) == 0)
914 			DELAY(10);
915 		if (hpaddr->hpds&HPDS_ERR)
916 			return (EIO);
917 		start += blk*NBPG;
918 		num -= blk;
919 	}
920 	return (0);
921 }
922 
923 hpsize(dev)
924 	dev_t dev;
925 {
926 	int unit = minor(dev) >> 3;
927 	struct mba_device *mi;
928 	struct hpst *st;
929 
930 	if (unit >= NHP || (mi = hpinfo[unit]) == 0 || mi->mi_alive == 0)
931 		return (-1);
932 	st = &hpst[mi->mi_type];
933 	return ((int)st->sizes[minor(dev) & 07].nblocks);
934 }
935 #endif
936