xref: /csrg-svn/sys/vax/mba/hp.c (revision 24783)
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.13 (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;
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) {
446 			    bp->b_resid = bp->b_bcount;
447 			    goto done;
448 			}
449 			bp->b_error = EINVAL;
450 			goto bad;
451 		}
452 		bp->b_cylin = 0;
453 	} else {
454 		if (bp->b_blkno < 0 ||
455 		    bp->b_blkno+sz > st->sizes[xunit].nblocks) {
456 			if (bp->b_blkno == st->sizes[xunit].nblocks) {
457 			    bp->b_resid = bp->b_bcount;
458 			    goto done;
459 			}
460 			bp->b_error = EINVAL;
461 			goto bad;
462 		}
463 		bp->b_cylin = bp->b_blkno/st->nspc + st->sizes[xunit].cyloff;
464 	}
465 	s = spl5();
466 	disksort(&mi->mi_tab, bp);
467 	if (mi->mi_tab.b_active == 0)
468 		mbustart(mi);
469 	splx(s);
470 	return;
471 
472 bad:
473 	bp->b_flags |= B_ERROR;
474 done:
475 	iodone(bp);
476 	return;
477 }
478 
479 hpustart(mi)
480 	register struct mba_device *mi;
481 {
482 	register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv;
483 	register struct buf *bp = mi->mi_tab.b_actf;
484 	register struct hpst *st;
485 	struct hpsoftc *sc = &hpsoftc[mi->mi_unit];
486 	daddr_t bn;
487 	int sn, tn, dist;
488 
489 	st = &hpst[mi->mi_type];
490 	hpaddr->hpcs1 = 0;
491 	if ((hpaddr->hpcs1&HP_DVA) == 0)
492 		return (MBU_BUSY);
493 	if ((hpaddr->hpds & HPDS_VV) == 0 || !sc->sc_hpinit) {
494 		struct buf *bbp = &bhpbuf[mi->mi_unit];
495 
496 		sc->sc_hpinit = 1;
497 		hpaddr->hpcs1 = HP_DCLR|HP_GO;
498 		if (mi->mi_mba->mba_drv[0].mbd_as & (1<<mi->mi_drive))
499 			printf("DCLR attn\n");
500 		hpaddr->hpcs1 = HP_PRESET|HP_GO;
501 		if (!ML11)
502 			hpaddr->hpof = HPOF_FMT22;
503 		mbclrattn(mi);
504 		if (!ML11) {
505 			bbp->b_flags = B_READ|B_BUSY;
506 			bbp->b_dev = bp->b_dev;
507 			bbp->b_bcount = 512;
508 			bbp->b_un.b_addr = (caddr_t)&hpbad[mi->mi_unit];
509 			bbp->b_blkno = st->ncyl*st->nspc - st->nsect;
510 			bbp->b_cylin = st->ncyl - 1;
511 			mi->mi_tab.b_actf = bbp;
512 			bbp->av_forw = bp;
513 			bp = bbp;
514 		}
515 	}
516 	if (mi->mi_tab.b_active || mi->mi_hd->mh_ndrive == 1)
517 		return (MBU_DODATA);
518 	if (ML11)
519 		return (MBU_DODATA);
520 	if ((hpaddr->hpds & HPDS_DREADY) != HPDS_DREADY)
521 		return (MBU_DODATA);
522 	bn = bp->b_blkno;
523 	sn = bn % st->nspc;
524 	tn = sn / st->nsect;
525 	sn = sn % st->nsect;
526 	if (bp->b_cylin == MASKREG(hpaddr->hpdc)) {
527 		if (sc->sc_doseeks)
528 			return (MBU_DODATA);
529 		dist = sn - (MASKREG(hpaddr->hpla) >> 6) - 1;
530 		if (dist < 0)
531 			dist += st->nsect;
532 		if (dist > st->maxdist || dist < st->mindist)
533 			return (MBU_DODATA);
534 	} else
535 		hpaddr->hpdc = bp->b_cylin;
536 	if (sc->sc_doseeks)
537 		hpaddr->hpcs1 = HP_SEEK|HP_GO;
538 	else {
539 		sn = (sn + st->nsect - st->sdist) % st->nsect;
540 		hpaddr->hpda = (tn << 8) + sn;
541 		hpaddr->hpcs1 = HP_SEARCH|HP_GO;
542 	}
543 	return (MBU_STARTED);
544 }
545 
546 hpstart(mi)
547 	register struct mba_device *mi;
548 {
549 	register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv;
550 	register struct buf *bp = mi->mi_tab.b_actf;
551 	register struct hpst *st = &hpst[mi->mi_type];
552 	struct hpsoftc *sc = &hpsoftc[mi->mi_unit];
553 	daddr_t bn;
554 	int sn, tn;
555 
556 	if (bp->b_flags & B_BAD)
557 		bn = sc->sc_badbn;
558 	else
559 		bn = bp->b_blkno + sc->sc_pgdone;
560 	if (ML11)
561 		hpaddr->hpda = bn;
562 	else {
563 		sn = bn%st->nspc;
564 		tn = sn/st->nsect;
565 		sn %= st->nsect;
566 		hpaddr->hpdc = bp->b_cylin;
567 		hpaddr->hpda = (tn << 8) + sn;
568 	}
569 	if (sc->sc_hdr) {
570 		if (bp->b_flags & B_READ)
571 			return (HP_RHDR|HP_GO);
572 		else
573 			return (HP_WHDR|HP_GO);
574 	}
575 	return (0);
576 }
577 
578 hpdtint(mi, mbsr)
579 	register struct mba_device *mi;
580 	int mbsr;
581 {
582 	register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv;
583 	register struct buf *bp = mi->mi_tab.b_actf;
584 	register struct hpst *st;
585 	register int er1, er2;
586 	struct hpsoftc *sc = &hpsoftc[mi->mi_unit];
587 	int retry = 0, i;
588 
589 	st = &hpst[mi->mi_type];
590 	if (hpaddr->hpds&HPDS_ERR || mbsr&MBSR_EBITS) {
591 		er1 = hpaddr->hper1;
592 		er2 = hpaddr->hper2;
593 		if (HPWAIT(mi, hpaddr) == 0)
594 			goto hard;
595 #ifdef HPDEBUG
596 		if (hpdebug) {
597 			int dc = hpaddr->hpdc, da = hpaddr->hpda;
598 
599 			printf("hperr: bp %x cyl %d blk %d pgdone %d as %o ",
600 				bp, bp->b_cylin, bp->b_blkno, sc->sc_pgdone,
601 				hpaddr->hpas&0xff);
602 			printf("dc %x da %x\n",MASKREG(dc), MASKREG(da));
603 			printf("errcnt %d ", mi->mi_tab.b_errcnt);
604 			printf("mbsr=%b ", mbsr, mbsr_bits);
605 			printf("er1=%b er2=%b\n", MASKREG(er1), HPER1_BITS,
606 			    MASKREG(er2), HPER2_BITS);
607 			DELAY(1000000);
608 		}
609 #endif
610 		if (er1 & HPER1_HCRC) {
611 			er1 &= ~(HPER1_HCE|HPER1_FER);
612 			er2 &= ~HPER2_BSE;
613 		}
614 		if (er1 & HPER1_WLE) {
615 			log(KERN_RECOV, "hp%d: write locked\n",
616 			    hpunit(bp->b_dev));
617 			bp->b_flags |= B_ERROR;
618 		} else if (sc->sc_hdr) {
619 			goto hard;
620 		} else if (RM80 && er2&HPER2_SSE) {
621 			(void) hpecc(mi, SSE);
622 			return (MBD_RESTARTED);
623 		} else if ((er2 & HPER2_BSE) && !ML11) {
624 			if (hpecc(mi, BSE))
625 				return (MBD_RESTARTED);
626 			goto hard;
627 		} else if (MASKREG(er1) == HPER1_FER && RP06) {
628 			if (hpecc(mi, BSE))
629 				return (MBD_RESTARTED);
630 			goto hard;
631 		} else if ((er1 & (HPER1_DCK | HPER1_ECH)) == HPER1_DCK &&
632 		    mi->mi_tab.b_errcnt > 7) {
633 			if (hpecc(mi, ECC))
634 				return (MBD_RESTARTED);
635 			/* else done */
636 		} else if ((er1 & HPER1_HCRC) && !ML11 && hpecc(mi, BSE)) {
637  			/*
638  			 * HCRC means the header is screwed up and the sector
639  			 * might well exist in the bad sector table,
640 			 * better check....
641  			 */
642 			return (MBD_RESTARTED);
643 		} else if (++mi->mi_tab.b_errcnt > 27 ||
644 		    (ML11 && mi->mi_tab.b_errcnt > 15) ||
645 		    mbsr & MBSR_HARD ||
646 		    er1 & HPER1_HARD ||
647 		    (!ML11 && (er2 & HPER2_HARD))) {
648 hard:
649 			if (bp->b_flags & B_BAD)
650 				bp->b_blkno = sc->sc_badbn;
651 			else {
652 				bp->b_blkno = bp->b_blkno + btop(bp->b_bcount -
653 				    MASKREG(-mi->mi_mba->mba_bcr));
654 				if (er1 & (HPER1_DCK | HPER1_ECH))
655 					bp->b_blkno--;
656 			}
657 			harderr(bp, "hp");
658 			if (mbsr & (MBSR_EBITS &~ (MBSR_DTABT|MBSR_MBEXC)))
659 				printf("mbsr=%b ", mbsr, mbsr_bits);
660 			printf("er1=%b er2=%b",
661 			    MASKREG(hpaddr->hper1), HPER1_BITS,
662 			    MASKREG(hpaddr->hper2), HPER2_BITS);
663 			if (hpaddr->hpmr)
664 				printf(" mr=%o", MASKREG(hpaddr->hpmr));
665 			if (hpaddr->hpmr2)
666 				printf(" mr2=%o", MASKREG(hpaddr->hpmr2));
667 			if (sc->sc_hdr)
668 				printf(" (hdr i/o)");
669 			printf("\n");
670 			bp->b_flags |= B_ERROR;
671 			bp->b_flags &= ~B_BAD;
672 		} else
673 			retry = 1;
674 		hpaddr->hpcs1 = HP_DCLR|HP_GO;
675 		if ((mi->mi_tab.b_errcnt & 07) == 4) {
676 			hpaddr->hpcs1 = HP_RECAL|HP_GO;
677 			sc->sc_recal = 1;
678 			return (MBD_RESTARTED);
679 		}
680 	}
681 #ifdef HPDEBUG
682 	else
683 		if (hpdebug && sc->sc_recal) {
684 			printf("recal %d ", sc->sc_recal);
685 			printf("errcnt %d\n", mi->mi_tab.b_errcnt);
686 			printf("mbsr=%b ", mbsr, mbsr_bits);
687 			printf("er1=%b er2=%b\n",
688 			    hpaddr->hper1, HPER1_BITS,
689 			    hpaddr->hper2, HPER2_BITS);
690 		}
691 #endif
692 	HPWAIT(mi, hpaddr);
693 	switch (sc->sc_recal) {
694 
695 	case 1:
696 		hpaddr->hpdc = bp->b_cylin;
697 		hpaddr->hpcs1 = HP_SEEK|HP_GO;
698 		sc->sc_recal++;
699 		return (MBD_RESTARTED);
700 	case 2:
701 		retry = 1;
702 		break;
703 	}
704 	sc->sc_recal = 0;
705 	if (retry) {
706 		if (mi->mi_tab.b_errcnt >= 16 && (bp->b_flags & B_READ)) {
707 			hpaddr->hpof =
708 			    hp_offset[mi->mi_tab.b_errcnt & 017]|HPOF_FMT22;
709 			hpaddr->hpcs1 = HP_OFFSET|HP_GO;
710 			HPWAIT(mi, hpaddr);
711 			mbclrattn(mi);
712 		}
713 		return (MBD_RETRY);
714 	}
715 	if (mi->mi_tab.b_errcnt >= 16) {
716 		/*
717 		 * This is fast and occurs rarely; we don't
718 		 * bother with interrupts.
719 		 */
720 		hpaddr->hpcs1 = HP_RTC|HP_GO;
721 		HPWAIT(mi, hpaddr);
722 		mbclrattn(mi);
723 	}
724 	if ((bp->b_flags & B_BAD) && hpecc(mi, CONT))
725 		return (MBD_RESTARTED);
726 	sc->sc_hdr = 0;
727 	sc->sc_pgdone = 0;
728 	bp->b_resid = MASKREG(-mi->mi_mba->mba_bcr);
729 	if (!ML11) {
730 		hpaddr->hpof = HPOF_FMT22;
731 		hpaddr->hpcs1 = HP_RELEASE|HP_GO;
732 	}
733 	return (MBD_DONE);
734 }
735 
736 /*
737  * Wait (for a bit) for a drive to come ready;
738  * returns nonzero on success.
739  */
740 hpwait(mi)
741 	register struct mba_device *mi;
742 {
743 	register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv;
744 	register i = 100000;
745 
746 	while ((hpaddr->hpds & HPDS_DRY) == 0 && --i)
747 		DELAY(10);
748 	if (i == 0)
749 		printf("hp%d: intr, not ready\n", mi->mi_unit);
750 	return (i);
751 }
752 
753 hpread(dev, uio)
754 	dev_t dev;
755 	struct uio *uio;
756 {
757 	register int unit = hpunit(dev);
758 
759 	if (unit >= NHP)
760 		return (ENXIO);
761 	return (physio(hpstrategy, &rhpbuf[unit], dev, B_READ, minphys, uio));
762 }
763 
764 hpwrite(dev, uio)
765 	dev_t dev;
766 	struct uio *uio;
767 {
768 	register int unit = hpunit(dev);
769 
770 	if (unit >= NHP)
771 		return (ENXIO);
772 	return (physio(hpstrategy, &rhpbuf[unit], dev, B_WRITE, minphys, uio));
773 }
774 
775 /*ARGSUSED*/
776 hpioctl(dev, cmd, data, flag)
777 	dev_t dev;
778 	int cmd;
779 	caddr_t data;
780 	int flag;
781 {
782 
783 	switch (cmd) {
784 
785 	case DKIOCHDR:	/* do header read/write */
786 		hpsoftc[hpunit(dev)].sc_hdr = 1;
787 		return (0);
788 
789 	default:
790 		return (ENXIO);
791 	}
792 }
793 
794 hpecc(mi, flag)
795 	register struct mba_device *mi;
796 	int flag;
797 {
798 	register struct mba_regs *mbp = mi->mi_mba;
799 	register struct hpdevice *rp = (struct hpdevice *)mi->mi_drv;
800 	register struct buf *bp = mi->mi_tab.b_actf;
801 	register struct hpst *st = &hpst[mi->mi_type];
802 	struct hpsoftc *sc = &hpsoftc[mi->mi_unit];
803 	int npf, o;
804 	int bn, cn, tn, sn;
805 	int bcr;
806 
807 	bcr = MASKREG(-mbp->mba_bcr);
808 	if (bp->b_flags & B_BAD)
809 		npf = bp->b_error;
810 	else
811 		npf = btop(bp->b_bcount - bcr);
812 	o = (int)bp->b_un.b_addr & PGOFSET;
813 	bn = bp->b_blkno;
814 	cn = bp->b_cylin;
815 	sn = bn%(st->nspc) + npf;
816 	tn = sn/st->nsect;
817 	sn %= st->nsect;
818 	cn += tn/st->ntrak;
819 	tn %= st->ntrak;
820 	bn += npf;
821 	switch (flag) {
822 	case ECC: {
823 		register int i;
824 		caddr_t addr;
825 		struct pte mpte;
826 		int bit, byte, mask;
827 
828 		npf--;		/* because block in error is previous block */
829 		bn--;
830 		if (bp->b_flags & B_BAD)
831 			bn = sc->sc_badbn;
832 		log(KERN_RECOV, "hp%d%c: soft ecc sn%d\n", hpunit(bp->b_dev),
833 		    'a'+(minor(bp->b_dev)&07), bn);
834 		mask = MASKREG(rp->hpec2);
835 		i = MASKREG(rp->hpec1) - 1;		/* -1 makes 0 origin */
836 		bit = i&07;
837 		i = (i&~07)>>3;
838 		byte = i + o;
839 		while (i < 512 && (int)ptob(npf)+i < bp->b_bcount && bit > -11) {
840 			mpte = mbp->mba_map[npf+btop(byte)];
841 			addr = ptob(mpte.pg_pfnum) + (byte & PGOFSET);
842 			putmemc(addr, getmemc(addr)^(mask<<bit));
843 			byte++;
844 			i++;
845 			bit -= 8;
846 		}
847 		if (bcr == 0)
848 			return (0);
849 		npf++;
850 		break;
851 		}
852 
853 	case SSE:
854 		rp->hpof |= HPOF_SSEI;
855 		if (bp->b_flags & B_BAD) {
856 			bn = sc->sc_badbn;
857 			goto fixregs;
858 		}
859 		mbp->mba_bcr = -(bp->b_bcount - (int)ptob(npf));
860 		break;
861 
862 	case BSE:
863  		if (rp->hpof & HPOF_SSEI)
864  			sn++;
865 #ifdef HPBDEBUG
866 		if (hpbdebug)
867 		printf("hpecc, BSE: bn %d cn %d tn %d sn %d\n", bn, cn, tn, sn);
868 #endif
869 		if (bp->b_flags & B_BAD)
870 			return (0);
871 		if ((bn = isbad(&hpbad[mi->mi_unit], cn, tn, sn)) < 0)
872 			return (0);
873 		bp->b_flags |= B_BAD;
874 		bp->b_error = npf + 1;
875  		rp->hpof &= ~HPOF_SSEI;
876 		bn = st->ncyl*st->nspc - st->nsect - 1 - bn;
877 		sc->sc_badbn = bn;
878 	fixregs:
879 		cn = bn/st->nspc;
880 		sn = bn%st->nspc;
881 		tn = sn/st->nsect;
882 		sn %= st->nsect;
883 		mbp->mba_bcr = -(min(512, bp->b_bcount - (int)ptob(npf)));
884 #ifdef HPBDEBUG
885 		if (hpbdebug)
886 		printf("revector to cn %d tn %d sn %d\n", cn, tn, sn);
887 #endif
888 		break;
889 
890 	case CONT:
891 #ifdef HPBDEBUG
892 		if (hpbdebug)
893 		printf("hpecc, CONT: bn %d cn %d tn %d sn %d\n", bn,cn,tn,sn);
894 #endif
895 		bp->b_flags &= ~B_BAD;
896 		if ((int)ptob(npf) >= bp->b_bcount)
897 			return (0);
898 		mbp->mba_bcr = -(bp->b_bcount - (int)ptob(npf));
899 		break;
900 	}
901 	rp->hpcs1 = HP_DCLR|HP_GO;
902 	if (rp->hpof & HPOF_SSEI)
903 		sn++;
904 	rp->hpdc = cn;
905 	rp->hpda = (tn<<8) + sn;
906 	mbp->mba_sr = -1;
907 	mbp->mba_var = (int)ptob(npf) + o;
908 	rp->hpcs1 = bp->b_flags&B_READ ? HP_RCOM|HP_GO : HP_WCOM|HP_GO;
909 	mi->mi_tab.b_errcnt = 0;	/* error has been corrected */
910 	sc->sc_pgdone = npf;
911 	return (1);
912 }
913 
914 #define	DBSIZE	20
915 
916 hpdump(dev)
917 	dev_t dev;
918 {
919 	register struct mba_device *mi;
920 	register struct mba_regs *mba;
921 	struct hpdevice *hpaddr;
922 	char *start;
923 	int num, unit;
924 	register struct hpst *st;
925 
926 	num = maxfree;
927 	start = 0;
928 	unit = hpunit(dev);
929 	if (unit >= NHP)
930 		return (ENXIO);
931 #define	phys(a,b)	((b)((int)(a)&0x7fffffff))
932 	mi = phys(hpinfo[unit],struct mba_device *);
933 	if (mi == 0 || mi->mi_alive == 0)
934 		return (ENXIO);
935 	mba = phys(mi->mi_hd, struct mba_hd *)->mh_physmba;
936 	mba->mba_cr = MBCR_INIT;
937 	hpaddr = (struct hpdevice *)&mba->mba_drv[mi->mi_drive];
938 	if ((hpaddr->hpds & HPDS_VV) == 0) {
939 		hpaddr->hpcs1 = HP_DCLR|HP_GO;
940 		hpaddr->hpcs1 = HP_PRESET|HP_GO;
941 		hpaddr->hpof = HPOF_FMT22;
942 	}
943 	st = &hpst[mi->mi_type];
944 	if (dumplo < 0)
945 		return (EINVAL);
946 	if (dumplo + num >= st->sizes[minor(dev)&07].nblocks)
947 		num = st->sizes[minor(dev)&07].nblocks - dumplo;
948 	while (num > 0) {
949 		register struct pte *hpte = mba->mba_map;
950 		register int i;
951 		int blk, cn, sn, tn;
952 		daddr_t bn;
953 
954 		blk = num > DBSIZE ? DBSIZE : num;
955 		bn = dumplo + btop(start);
956 		cn = bn/st->nspc + st->sizes[minor(dev)&07].cyloff;
957 		sn = bn%st->nspc;
958 		tn = sn/st->nsect;
959 		sn = sn%st->nsect;
960 		hpaddr->hpdc = cn;
961 		hpaddr->hpda = (tn << 8) + sn;
962 		for (i = 0; i < blk; i++)
963 			*(int *)hpte++ = (btop(start)+i) | PG_V;
964 		mba->mba_sr = -1;
965 		mba->mba_bcr = -(blk*NBPG);
966 		mba->mba_var = 0;
967 		hpaddr->hpcs1 = HP_WCOM | HP_GO;
968 		while ((hpaddr->hpds & HPDS_DRY) == 0)
969 			DELAY(10);
970 		if (hpaddr->hpds&HPDS_ERR)
971 			return (EIO);
972 		start += blk*NBPG;
973 		num -= blk;
974 	}
975 	return (0);
976 }
977 
978 hpsize(dev)
979 	dev_t dev;
980 {
981 	int unit = hpunit(dev);
982 	struct mba_device *mi;
983 	struct hpst *st;
984 
985 	if (unit >= NHP || (mi = hpinfo[unit]) == 0 || mi->mi_alive == 0)
986 		return (-1);
987 	st = &hpst[mi->mi_type];
988 	return ((int)st->sizes[minor(dev) & 07].nblocks);
989 }
990 #endif
991