xref: /csrg-svn/sys/vax/mba/hp.c (revision 17120)
1 /*	hp.c	6.6	84/08/29	*/
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 "param.h"
24 #include "systm.h"
25 #include "dk.h"
26 #include "buf.h"
27 #include "conf.h"
28 #include "dir.h"
29 #include "user.h"
30 #include "map.h"
31 #include "../vax/mtpr.h"
32 #include "vm.h"
33 #include "cmap.h"
34 #include "dkbad.h"
35 #include "ioctl.h"
36 #include "uio.h"
37 
38 #include "../vax/dkio.h"
39 #include "mbareg.h"
40 #include "mbavar.h"
41 #include "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 	int	sc_pgdone;	/* amount sucessfully transfered */
252 	daddr_t	sc_badbn;	/* replacement block number */
253 } hpsoftc[NHP];
254 
255 #define	b_cylin b_resid
256 
257 /* #define ML11 0  to remove ML11 support */
258 #define	ML11	(hptypes[mi->mi_type] == MBDT_ML11A)
259 #define	RP06	(hptypes[mi->mi_type] <= MBDT_RP06)
260 #define	RM80	(hptypes[mi->mi_type] == MBDT_RM80)
261 
262 #define	MASKREG(reg)	((reg)&0xffff)
263 
264 #ifdef INTRLVE
265 daddr_t dkblock();
266 #endif
267 
268 /*ARGSUSED*/
269 hpattach(mi, slave)
270 	register struct mba_device *mi;
271 {
272 
273 	mi->mi_type = hpmaptype(mi);
274 	if (!ML11 && mi->mi_dk >= 0) {
275 		struct hpst *st = &hpst[mi->mi_type];
276 
277 		dk_mspw[mi->mi_dk] = 1.0 / 60 / (st->nsect * 256);
278 	}
279 }
280 
281 /*
282  * Map apparent MASSBUS drive type into manufacturer
283  * specific configuration.  For SI controllers this is done
284  * based on codes in the serial number register.  For
285  * EMULEX controllers, the track and sector attributes are
286  * used when the drive type is an RM02 (not supported by DEC).
287  */
288 hpmaptype(mi)
289 	register struct mba_device *mi;
290 {
291 	register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv;
292 	register int type = mi->mi_type;
293 
294 	/*
295 	 * Model-byte processing for SI controllers.
296 	 * NB:  Only deals with RM03 and RM05 emulations.
297 	 */
298 	if (type == HPDT_RM03 || type == HPDT_RM05) {
299 		int hpsn = hpaddr->hpsn;
300 
301 		if ((hpsn & SIMB_LU) != mi->mi_drive)
302 			return (type);
303 		switch ((hpsn & SIMB_MB) & ~(SIMB_S6|SIRM03|SIRM05)) {
304 
305 		case SI9775D:
306 			printf("hp%d: 9775 (direct)\n", mi->mi_unit);
307 			type = HPDT_9775;
308 			break;
309 
310 		case SI9730D:
311 			printf("hp%d: 9730 (direct)\n", mi->mi_unit);
312 			type = HPDT_9730;
313 			break;
314 
315 		/*
316 		 * Beware, since the only SI controller we
317 		 * have has a 9300 instead of a 9766, we map the
318 		 * drive type into the 9300.  This means that
319 		 * on a 9766 you lose the last 8 cylinders (argh).
320 		 */
321 		case SI9766:
322 			printf("hp%d: 9300\n", mi->mi_unit);
323 			type = HPDT_9300;
324 			break;
325 
326 		case SI9762:
327 			printf("hp%d: 9762\n", mi->mi_unit);
328 			type = HPDT_RM03;
329 			break;
330 
331 		case SICAPD:
332 			printf("hp%d: capricorn\n", mi->mi_unit);
333 			type = HPDT_CAPRICORN;
334 			break;
335 
336 		case SI9751D:
337 			printf("hp%d: eagle\n", mi->mi_unit);
338 			type = HPDT_EAGLE;
339 			break;
340 		}
341 		return (type);
342 	}
343 
344 	/*
345 	 * EMULEX SC750 or SC780.  Poke the holding register.
346 	 */
347 	if (type == HPDT_RM02) {
348 		int ntracks, nsectors;
349 
350 		hpaddr->hpof = HPOF_FMT22;
351 		mbclrattn(mi);
352 		hpaddr->hpcs1 = HP_NOP;
353 		hpaddr->hphr = HPHR_MAXTRAK;
354 		ntracks = MASKREG(hpaddr->hphr) + 1;
355 		if (ntracks == 16) {
356 			printf("hp%d: capricorn\n", mi->mi_unit);
357 			type = HPDT_CAPRICORN;
358 			goto done;
359 		}
360 		if (ntracks == 19) {
361 			printf("hp%d: 9300\n", mi->mi_unit);
362 			type = HPDT_9300;
363 			goto done;
364 		}
365 		hpaddr->hpcs1 = HP_NOP;
366 		hpaddr->hphr = HPHR_MAXSECT;
367 		nsectors = MASKREG(hpaddr->hphr) + 1;
368 		if (ntracks == 20 && nsectors == 48) {
369 			type = HPDT_EAGLE;
370 			printf("hp%d: eagle\n", mi->mi_unit);
371 			goto done;
372 		}
373 		printf("hp%d: ntracks %d, nsectors %d: unknown device\n",
374 			mi->mi_unit, ntracks, nsectors);
375 done:
376 		hpaddr->hpcs1 = HP_DCLR|HP_GO;
377 		mbclrattn(mi);		/* conservative */
378 		return (type);
379 	}
380 
381 	/*
382 	 * Map all ML11's to the same type.  Also calculate
383 	 * transfer rates based on device characteristics.
384 	 */
385 	if (type == HPDT_ML11A || type == HPDT_ML11B) {
386 		register struct hpsoftc *sc = &hpsoftc[mi->mi_unit];
387 		register int trt;
388 
389 		sc->sc_mlsize = hpaddr->hpmr & HPMR_SZ;
390 		if ((hpaddr->hpmr & HPMR_ARRTYP) == 0)
391 			sc->sc_mlsize >>= 2;
392 		if (mi->mi_dk >= 0) {
393 			trt = (hpaddr->hpmr & HPMR_TRT) >> 8;
394 			dk_mspw[mi->mi_dk] = 1.0 / (1<<(20-trt));
395 		}
396 		type = HPDT_ML11A;
397 	}
398 	return (type);
399 }
400 
401 hpopen(dev)
402 	dev_t dev;
403 {
404 	register int unit = minor(dev) >> 3;
405 	register struct mba_device *mi;
406 
407 	if (unit >= NHP || (mi = hpinfo[unit]) == 0 || mi->mi_alive == 0)
408 		return (ENXIO);
409 	return (0);
410 }
411 
412 hpstrategy(bp)
413 	register struct buf *bp;
414 {
415 	register struct mba_device *mi;
416 	register struct hpst *st;
417 	register int unit;
418 	long sz, bn;
419 	int xunit = minor(bp->b_dev) & 07;
420 	int s;
421 
422 	sz = bp->b_bcount;
423 	sz = (sz+511) >> 9;
424 	unit = dkunit(bp);
425 	if (unit >= NHP)
426 		goto bad;
427 	mi = hpinfo[unit];
428 	if (mi == 0 || mi->mi_alive == 0)
429 		goto bad;
430 	st = &hpst[mi->mi_type];
431 	if (ML11) {
432 		struct hpsoftc *sc = &hpsoftc[unit];
433 
434 		if (bp->b_blkno < 0 ||
435 		    dkblock(bp)+sz > sc->sc_mlsize)
436 			goto bad;
437 		bp->b_cylin = 0;
438 	} else {
439 		if (bp->b_blkno < 0 ||
440 		    (bn = dkblock(bp))+sz > st->sizes[xunit].nblocks)
441 			goto bad;
442 		bp->b_cylin = bn/st->nspc + st->sizes[xunit].cyloff;
443 	}
444 	s = spl5();
445 	disksort(&mi->mi_tab, bp);
446 	if (mi->mi_tab.b_active == 0)
447 		mbustart(mi);
448 	splx(s);
449 	return;
450 
451 bad:
452 	bp->b_flags |= B_ERROR;
453 	iodone(bp);
454 	return;
455 }
456 
457 hpustart(mi)
458 	register struct mba_device *mi;
459 {
460 	register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv;
461 	register struct buf *bp = mi->mi_tab.b_actf;
462 	register struct hpst *st;
463 	struct hpsoftc *sc = &hpsoftc[mi->mi_unit];
464 	daddr_t bn;
465 	int sn, tn, dist;
466 
467 	st = &hpst[mi->mi_type];
468 	hpaddr->hpcs1 = 0;
469 	if ((hpaddr->hpcs1&HP_DVA) == 0)
470 		return (MBU_BUSY);
471 	if ((hpaddr->hpds & HPDS_VV) == 0 || !sc->sc_hpinit) {
472 		struct buf *bbp = &bhpbuf[mi->mi_unit];
473 
474 		sc->sc_hpinit = 1;
475 		hpaddr->hpcs1 = HP_DCLR|HP_GO;
476 		if (mi->mi_mba->mba_drv[0].mbd_as & (1<<mi->mi_drive))
477 			printf("DCLR attn\n");
478 		hpaddr->hpcs1 = HP_PRESET|HP_GO;
479 		if (!ML11)
480 			hpaddr->hpof = HPOF_FMT22;
481 		mbclrattn(mi);
482 		if (!ML11) {
483 			bbp->b_flags = B_READ|B_BUSY;
484 			bbp->b_dev = bp->b_dev;
485 			bbp->b_bcount = 512;
486 			bbp->b_un.b_addr = (caddr_t)&hpbad[mi->mi_unit];
487 			bbp->b_blkno = st->ncyl*st->nspc - st->nsect;
488 			bbp->b_cylin = st->ncyl - 1;
489 			mi->mi_tab.b_actf = bbp;
490 			bbp->av_forw = bp;
491 			bp = bbp;
492 		}
493 	}
494 	if (mi->mi_tab.b_active || mi->mi_hd->mh_ndrive == 1)
495 		return (MBU_DODATA);
496 	if (ML11)
497 		return (MBU_DODATA);
498 	if ((hpaddr->hpds & HPDS_DREADY) != HPDS_DREADY)
499 		return (MBU_DODATA);
500 	bn = dkblock(bp);
501 	sn = bn % st->nspc;
502 	tn = sn / st->nsect;
503 	sn = sn % st->nsect;
504 	if (bp->b_cylin == MASKREG(hpaddr->hpdc)) {
505 		if (sc->sc_doseeks)
506 			return (MBU_DODATA);
507 		dist = sn - (MASKREG(hpaddr->hpla) >> 6) - 1;
508 		if (dist < 0)
509 			dist += st->nsect;
510 		if (dist > st->maxdist || dist < st->mindist)
511 			return (MBU_DODATA);
512 	} else
513 		hpaddr->hpdc = bp->b_cylin;
514 	if (sc->sc_doseeks)
515 		hpaddr->hpcs1 = HP_SEEK|HP_GO;
516 	else {
517 		sn = (sn + st->nsect - st->sdist) % st->nsect;
518 		hpaddr->hpda = (tn << 8) + sn;
519 		hpaddr->hpcs1 = HP_SEARCH|HP_GO;
520 	}
521 	return (MBU_STARTED);
522 }
523 
524 hpstart(mi)
525 	register struct mba_device *mi;
526 {
527 	register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv;
528 	register struct buf *bp = mi->mi_tab.b_actf;
529 	register struct hpst *st = &hpst[mi->mi_type];
530 	struct hpsoftc *sc = &hpsoftc[mi->mi_unit];
531 	daddr_t bn;
532 	int sn, tn;
533 
534 	if (bp->b_flags & B_BAD)
535 		bn = sc->sc_badbn;
536 	else
537 		bn = dkblock(bp) + sc->sc_pgdone;
538 	if (ML11)
539 		hpaddr->hpda = bn;
540 	else {
541 		sn = bn%st->nspc;
542 		tn = sn/st->nsect;
543 		sn %= st->nsect;
544 		hpaddr->hpdc = bp->b_cylin;
545 		hpaddr->hpda = (tn << 8) + sn;
546 	}
547 	if (sc->sc_hdr) {
548 		if (bp->b_flags & B_READ)
549 			return (HP_RHDR|HP_GO);
550 		else
551 			return (HP_WHDR|HP_GO);
552 	}
553 	return (0);
554 }
555 
556 hpdtint(mi, mbsr)
557 	register struct mba_device *mi;
558 	int mbsr;
559 {
560 	register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv;
561 	register struct buf *bp = mi->mi_tab.b_actf;
562 	register struct hpst *st;
563 	register int er1, er2;
564 	struct hpsoftc *sc = &hpsoftc[mi->mi_unit];
565 	int retry = 0;
566 
567 	st = &hpst[mi->mi_type];
568 	if (hpaddr->hpds&HPDS_ERR || mbsr&MBSR_EBITS) {
569 		er1 = hpaddr->hper1;
570 		er2 = hpaddr->hper2;
571 #ifdef HPDEBUG
572 		if (hpdebug) {
573 			int dc = hpaddr->hpdc, da = hpaddr->hpda;
574 
575 			printf("hperr: bp %x cyl %d blk %d as %o ",
576 				bp, bp->b_cylin, bp->b_blkno,
577 				hpaddr->hpas&0xff);
578 			printf("dc %x da %x\n",MASKREG(dc), MASKREG(da));
579 			printf("errcnt %d ", mi->mi_tab.b_errcnt);
580 			printf("mbsr=%b ", mbsr, mbsr_bits);
581 			printf("er1=%b er2=%b\n", MASKREG(er1), HPER1_BITS,
582 			    MASKREG(er2), HPER2_BITS);
583 			DELAY(1000000);
584 		}
585 #endif
586 		if (er1 & HPER1_HCRC) {
587 			er1 &= ~(HPER1_HCE|HPER1_FER);
588 			er2 &= ~HPER2_BSE;
589 		}
590 		if (er1 & HPER1_WLE) {
591 			printf("hp%d: write locked\n", dkunit(bp));
592 			bp->b_flags |= B_ERROR;
593 		} else if (sc->sc_hdr) {
594 			goto hard;
595 		} else if (RM80 && er2&HPER2_SSE) {
596 			(void) hpecc(mi, SSE);
597 			return (MBD_RESTARTED);
598 		} else if ((er2 & HPER2_BSE) && !ML11) {
599 			if (hpecc(mi, BSE))
600 				return (MBD_RESTARTED);
601 			goto hard;
602 		} else if (MASKREG(er1) == HPER1_FER && RP06) {
603 			if (hpecc(mi, BSE))
604 				return (MBD_RESTARTED);
605 			goto hard;
606 		} else if ((er1 & (HPER1_DCK | HPER1_ECH)) == HPER1_DCK &&
607 		    mi->mi_tab.b_errcnt > 7) {
608 			if (hpecc(mi, ECC))
609 				return (MBD_RESTARTED);
610 			/* else done */
611 		} else if (++mi->mi_tab.b_errcnt > 27 ||
612 		    (ML11 && mi->mi_tab.b_errcnt > 15) ||
613 		    mbsr & MBSR_HARD ||
614 		    er1 & HPER1_HARD ||
615 		    (!ML11 && (er2 & HPER2_HARD))) {
616  			/*
617  			 * HCRC means the header is screwed up and the sector
618  			 * might well exist in the bad sector table,
619 			 * better check....
620  			 */
621  			if ((er1 & HPER1_HCRC) && !ML11 && hpecc(mi, BSE))
622 				return (MBD_RESTARTED);
623 hard:
624 			if (bp->b_flags & B_BAD)
625 				bp->b_blkno = sc->sc_badbn;
626 			else
627 				bp->b_blkno = dkblock(bp) + sc->sc_pgdone;
628  			if (hpaddr->hpof & HPOF_SSEI)
629  				bp->b_blkno++;
630 			harderr(bp, "hp");
631 			if (mbsr & (MBSR_EBITS &~ (MBSR_DTABT|MBSR_MBEXC)))
632 				printf("mbsr=%b ", mbsr, mbsr_bits);
633 			printf("er1=%b er2=%b",
634 			    MASKREG(hpaddr->hper1), HPER1_BITS,
635 			    MASKREG(hpaddr->hper2), HPER2_BITS);
636 			if (hpaddr->hpmr)
637 				printf(" mr=%o", MASKREG(hpaddr->hpmr));
638 			if (hpaddr->hpmr2)
639 				printf(" mr2=%o", MASKREG(hpaddr->hpmr2));
640 			if (sc->sc_hdr)
641 				printf(" (hdr i/o)");
642 			printf("\n");
643 			bp->b_flags |= B_ERROR;
644 			bp->b_flags &= ~B_BAD;
645 		} else
646 			retry = 1;
647 		hpaddr->hpcs1 = HP_DCLR|HP_GO;
648 		if ((mi->mi_tab.b_errcnt & 07) == 4) {
649 			hpaddr->hpcs1 = HP_RECAL|HP_GO;
650 			sc->sc_recal = 1;
651 			return (MBD_RESTARTED);
652 		}
653 	}
654 #ifdef HPDEBUG
655 	else
656 		if (hpdebug && sc->sc_recal) {
657 			printf("recal %d ", sc->sc_recal);
658 			printf("errcnt %d\n", mi->mi_tab.b_errcnt);
659 			printf("mbsr=%b ", mbsr, mbsr_bits);
660 			printf("er1=%b er2=%b\n",
661 			    hpaddr->hper1, HPER1_BITS,
662 			    hpaddr->hper2, HPER2_BITS);
663 		}
664 #endif
665 	switch (sc->sc_recal) {
666 
667 	case 1:
668 		hpaddr->hpdc = bp->b_cylin;
669 		hpaddr->hpcs1 = HP_SEEK|HP_GO;
670 		sc->sc_recal++;
671 		return (MBD_RESTARTED);
672 	case 2:
673 		retry = 1;
674 		break;
675 	}
676 	sc->sc_recal = 0;
677 	if (retry) {
678 		if (mi->mi_tab.b_errcnt >= 16 && (bp->b_flags & B_READ)) {
679 			hpaddr->hpof =
680 			    hp_offset[mi->mi_tab.b_errcnt & 017]|HPOF_FMT22;
681 			hpaddr->hpcs1 = HP_OFFSET|HP_GO;
682 			while ((hpaddr->hpds & (HPDS_DRY | HPDS_PIP)) !=
683 			    HPDS_DRY)
684 				DELAY(10);
685 			mbclrattn(mi);
686 		}
687 		return (MBD_RETRY);
688 	}
689 	if (mi->mi_tab.b_errcnt >= 16) {
690 		/*
691 		 * This is fast and occurs rarely; we don't
692 		 * bother with interrupts.
693 		 */
694 		hpaddr->hpcs1 = HP_RTC|HP_GO;
695 		while ((hpaddr->hpds & (HPDS_DRY | HPDS_PIP)) != HPDS_DRY)
696 			DELAY(10);
697 		mbclrattn(mi);
698 	}
699 	if ((bp->b_flags & B_BAD) && hpecc(mi, CONT))
700 		return (MBD_RESTARTED);
701 	sc->sc_hdr = 0;
702 	sc->sc_pgdone = 0;
703 	bp->b_resid = MASKREG(-mi->mi_mba->mba_bcr);
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 	struct hpsoftc *sc = &hpsoftc[mi->mi_unit];
761 	int npf, o;
762 	int bn, cn, tn, sn;
763 	int bcr;
764 
765 	bcr = MASKREG(mbp->mba_bcr);
766 	if (bcr)
767 		bcr |= 0xffff0000;		/* sxt */
768 	if (bp->b_flags & B_BAD)
769 		npf = bp->b_error;
770 	else
771 		npf = btop(bcr + bp->b_bcount);
772 	o = (int)bp->b_un.b_addr & PGOFSET;
773 	bn = dkblock(bp) + npf;
774 	cn = bp->b_cylin;
775 	sn = bn%(st->nspc);
776 	tn = sn/st->nsect;
777 	sn %= st->nsect;
778 	cn += tn/st->ntrak;
779 	tn %= st->ntrak;
780 	switch (flag) {
781 	case ECC: {
782 		register int i;
783 		caddr_t addr;
784 		struct pte mpte;
785 		int bit, byte, mask;
786 
787 		npf--;		/* because block in error is previous block */
788 		if (bp->b_flags & B_BAD)
789 			bn = sc->sc_badbn;
790 		printf("hp%d%c: soft ecc sn%d\n", dkunit(bp),
791 		    'a'+(minor(bp->b_dev)&07), bn);
792 		mask = MASKREG(rp->hpec2);
793 		i = MASKREG(rp->hpec1) - 1;		/* -1 makes 0 origin */
794 		bit = i&07;
795 		i = (i&~07)>>3;
796 		byte = i + o;
797 		while (i < 512 && (int)ptob(npf)+i < bp->b_bcount && bit > -11) {
798 			mpte = mbp->mba_map[npf+btop(byte)];
799 			addr = ptob(mpte.pg_pfnum) + (byte & PGOFSET);
800 			putmemc(addr, getmemc(addr)^(mask<<bit));
801 			byte++;
802 			i++;
803 			bit -= 8;
804 		}
805 		if ((bp->b_flags & B_BAD) || bcr == 0)
806 			return (0);
807 		npf++;
808 		break;
809 		}
810 
811 	case SSE:
812 		rp->hpof |= HPOF_SSEI;
813 		if (bp->b_flags & B_BAD) {
814 			bn = sc->sc_badbn;
815 			goto fixregs;
816 		}
817 		mbp->mba_bcr = -(bp->b_bcount - (int)ptob(npf));
818 		break;
819 
820 	case BSE:
821  		if (rp->hpof & HPOF_SSEI)
822  			sn++;
823 #ifdef HPBDEBUG
824 		if (hpbdebug)
825 		printf("hpecc, BSE: bn %d cn %d tn %d sn %d\n", bn, cn, tn, sn);
826 #endif
827 		if (bp->b_flags & B_BAD)
828 			return (0);
829 		if ((bn = isbad(&hpbad[mi->mi_unit], cn, tn, sn)) < 0)
830 			return (0);
831 		bp->b_flags |= B_BAD;
832 		bp->b_error = npf + 1;
833  		rp->hpof &= ~HPOF_SSEI;
834 		bn = st->ncyl*st->nspc - st->nsect - 1 - bn;
835 		sc->sc_badbn = bn;
836 	fixregs:
837 		cn = bn/st->nspc;
838 		sn = bn%st->nspc;
839 		tn = sn/st->nsect;
840 		sn %= st->nsect;
841 		mbp->mba_bcr = -512;
842 #ifdef HPBDEBUG
843 		if (hpbdebug)
844 		printf("revector to cn %d tn %d sn %d\n", cn, tn, sn);
845 #endif
846 		break;
847 
848 	case CONT:
849 #ifdef HPBDEBUG
850 		if (hpbdebug)
851 		printf("hpecc, CONT: bn %d cn %d tn %d sn %d\n", bn,cn,tn,sn);
852 #endif
853 		bp->b_flags &= ~B_BAD;
854 		mbp->mba_bcr = -(bp->b_bcount - (int)ptob(npf));
855 		if (MASKREG(mbp->mba_bcr) == 0)
856 			return (0);
857 		break;
858 	}
859 	rp->hpcs1 = HP_DCLR|HP_GO;
860 	if (rp->hpof & HPOF_SSEI)
861 		sn++;
862 	rp->hpdc = cn;
863 	rp->hpda = (tn<<8) + sn;
864 	mbp->mba_sr = -1;
865 	mbp->mba_var = (int)ptob(npf) + o;
866 	rp->hpcs1 = bp->b_flags&B_READ ? HP_RCOM|HP_GO : HP_WCOM|HP_GO;
867 	mi->mi_tab.b_errcnt = 0;	/* error has been corrected */
868 	sc->sc_pgdone = npf;
869 	return (1);
870 }
871 
872 #define	DBSIZE	20
873 
874 hpdump(dev)
875 	dev_t dev;
876 {
877 	register struct mba_device *mi;
878 	register struct mba_regs *mba;
879 	struct hpdevice *hpaddr;
880 	char *start;
881 	int num, unit;
882 	register struct hpst *st;
883 
884 	num = maxfree;
885 	start = 0;
886 	unit = minor(dev) >> 3;
887 	if (unit >= NHP)
888 		return (ENXIO);
889 #define	phys(a,b)	((b)((int)(a)&0x7fffffff))
890 	mi = phys(hpinfo[unit],struct mba_device *);
891 	if (mi == 0 || mi->mi_alive == 0)
892 		return (ENXIO);
893 	mba = phys(mi->mi_hd, struct mba_hd *)->mh_physmba;
894 	mba->mba_cr = MBCR_INIT;
895 	hpaddr = (struct hpdevice *)&mba->mba_drv[mi->mi_drive];
896 	if ((hpaddr->hpds & HPDS_VV) == 0) {
897 		hpaddr->hpcs1 = HP_DCLR|HP_GO;
898 		hpaddr->hpcs1 = HP_PRESET|HP_GO;
899 		hpaddr->hpof = HPOF_FMT22;
900 	}
901 	st = &hpst[mi->mi_type];
902 	if (dumplo < 0 || dumplo + num >= st->sizes[minor(dev)&07].nblocks)
903 		return (EINVAL);
904 	while (num > 0) {
905 		register struct pte *hpte = mba->mba_map;
906 		register int i;
907 		int blk, cn, sn, tn;
908 		daddr_t bn;
909 
910 		blk = num > DBSIZE ? DBSIZE : num;
911 		bn = dumplo + btop(start);
912 		cn = bn/st->nspc + st->sizes[minor(dev)&07].cyloff;
913 		sn = bn%st->nspc;
914 		tn = sn/st->nsect;
915 		sn = sn%st->nsect;
916 		hpaddr->hpdc = cn;
917 		hpaddr->hpda = (tn << 8) + sn;
918 		for (i = 0; i < blk; i++)
919 			*(int *)hpte++ = (btop(start)+i) | PG_V;
920 		mba->mba_sr = -1;
921 		mba->mba_bcr = -(blk*NBPG);
922 		mba->mba_var = 0;
923 		hpaddr->hpcs1 = HP_WCOM | HP_GO;
924 		while ((hpaddr->hpds & HPDS_DRY) == 0)
925 			DELAY(10);
926 		if (hpaddr->hpds&HPDS_ERR)
927 			return (EIO);
928 		start += blk*NBPG;
929 		num -= blk;
930 	}
931 	return (0);
932 }
933 
934 hpsize(dev)
935 	dev_t dev;
936 {
937 	int unit = minor(dev) >> 3;
938 	struct mba_device *mi;
939 	struct hpst *st;
940 
941 	if (unit >= NHP || (mi = hpinfo[unit]) == 0 || mi->mi_alive == 0)
942 		return (-1);
943 	st = &hpst[mi->mi_type];
944 	return ((int)st->sizes[minor(dev) & 07].nblocks);
945 }
946 #endif
947