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