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