xref: /original-bsd/sys/vax/mba/hp.c (revision 62734ea8)
1 /*	hp.c	4.58	82/11/13	*/
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 
22 #include "../h/param.h"
23 #include "../h/systm.h"
24 #include "../h/dk.h"
25 #include "../h/buf.h"
26 #include "../h/conf.h"
27 #include "../h/dir.h"
28 #include "../h/user.h"
29 #include "../h/map.h"
30 #include "../h/pte.h"
31 #include "../vax/mtpr.h"
32 #include "../h/vm.h"
33 #include "../h/cmap.h"
34 #include "../h/dkbad.h"
35 #include "../h/ioctl.h"
36 #include "../h/uio.h"
37 
38 #include "../vax/dkio.h"
39 #include "../vaxmba/mbareg.h"
40 #include "../vaxmba/mbavar.h"
41 #include "../vaxmba/hpreg.h"
42 
43 /* THIS SHOULD BE READ OFF THE PACK, PER DRIVE */
44 struct	size {
45 	daddr_t	nblocks;
46 	int	cyloff;
47 } hp6_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 	0,	0,
52 	0,	0,
53 	0,	0,
54 #ifndef NOBADSECT
55 	291280,	118,		/* G=cyl 118 thru 814 */
56 #else
57 	291346,	118,
58 #endif
59 	0,	0,
60 }, rm3_sizes[8] = {
61 	15884,	0,		/* A=cyl 0 thru 99 */
62 	33440,	100,		/* B=cyl 100 thru 309 */
63 	131680,	0,		/* C=cyl 0 thru 822 */
64 	0,	0,
65 	0,	0,
66 	0,	0,
67 #ifndef NOBADSECT
68 	81984,	310,		/* G=cyl 310 thru 822 */
69 #else
70 	82080,	310,
71 #endif
72 	0,	0,
73 }, rm5_sizes[8] = {
74 #ifndef CAD
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 #ifndef NOBADSECT
81 	86240,	681,		/* F=cyl 681 thru 822 */
82 	158592,	562,		/* G=cyl 562 thru 822 */
83 #else
84 	86336,	681,
85 	158688,	562,
86 #endif
87 	291346,	82,		/* H=cyl 82 thru 561 */
88 #else
89 	15884,	0,		/* A=cyl 0 thru 26 */
90 	33440,	27,		/* B=cyl 27 thru 81 */
91 	495520,	0,		/* C=cyl 0 thru 814 */
92 	15884,	562,		/* D=cyl 562 thru 588 */
93 	55936,	589,		/* E=cyl 589 thru 680 */
94 #ifndef NOBADSECT
95 	81376,	681,		/* F=cyl 681 thru 814 */
96 	153728,	562,		/* G=cyl 562 thru 814 */
97 #else
98 	81472,	681,
99 	153824,	562,
100 #endif
101 	291346,	82,		/* H=cyl 82 thru 561 */
102 #endif
103 }, rm80_sizes[8] = {
104 	15884,	0,		/* A=cyl 0 thru 36 */
105 	33440,	37,		/* B=cyl 37 thru 114 */
106 	242606,	0,		/* C=cyl 0 thru 558 */
107 	0,	0,
108 	0,	0,
109 	0,	0,
110 	82080,	115,		/* G=cyl 115 thru 304 */
111 	110143,	305,		/* H=cyl 305 thru 558 */
112 }, hp7_sizes[8] = {
113 	15884,	0,		/* A=cyl 0 thru 9 */
114 	64000,	10,		/* B=cyl 10 thru 49 */
115 	1008000,0,		/* C=cyl 0 thru 629 */
116 	15884,	330,		/* D=cyl 330 thru 339 */
117 	256000,	340,		/* E=cyl 340 thru 499 */
118 	207850,	500,		/* F=cyl 500 thru 629 */
119 	479850,	330,		/* G=cyl 330 thru 629 */
120 	448000,	50,		/* H=cyl 50 thru 329 */
121 }, si9775_sizes[8] = {
122 	16640,	  0,		/* A=cyl   0 thru  12 */
123 	34560,	 13,		/* B=cyl  13 thru  39 */
124 	1079040,  0,		/* C=cyl   0 thru 842 - whole disk */
125 	0,	  0,		/* D unused */
126 	0,	  0,		/* E unused */
127 	0,	  0,		/* F unused */
128 	513280,	 40,		/* G=cyl  40 thru 440 */
129 	513280,	441,		/* H=cyl 441 thru 841 */
130 }, si9730_sizes[8] = {
131 	15884,	0,		/* A=cyl 0 thru 49 */
132 	33440,	50,		/* B=cyl 50 thru 154 */
133 	263360,	0,		/* C=cyl 0 thru 822 */
134 	0,	0,
135 	0,	0,
136 	0,	0,
137 	0,	0,
138 #ifndef NOBADSECT
139 	213664,	155,		/* H=cyl 155 thru 822 */
140 #else
141 	213760,	155,
142 #endif
143 }, hpam_sizes[8] = {
144 	15884,	0,		/* A=cyl 0 thru 31 */
145 	33440,	32,		/* B=cyl 32 thru 97 */
146 	524288,	0,		/* C=cyl 0 thru 1023 */
147 	27786,	668,
148 	27786,	723,
149 	125440,	778,
150 	181760,	668,		/* G=cyl 668 thru 1022 */
151 	291346,	98,		/* H=cyl 98 thru 667 */
152 }, hpfj_sizes[8] = {
153 	15884,	0,		/* A=cyl 0 thru 18 */
154 	33440,	19,		/* B=cyl 19 thru 58 */
155 	723991,	0,		/* C=cyl 0 thru 841 */
156 	0, 0,
157 	0, 0,
158 	0, 0,
159 	381711, 398,		/* G=cyl 398 thru 841 */
160 	291346, 59,		/* H=cyl 59 thru 397 */
161 };
162 /* END OF STUFF WHICH SHOULD BE READ IN PER DISK */
163 
164 #define	_hpSDIST	2
165 #define	_hpRDIST	3
166 
167 int	hpSDIST = _hpSDIST;
168 int	hpRDIST = _hpRDIST;
169 
170 /*
171  * Table for converting Massbus drive types into
172  * indices into the partition tables.  Slots are
173  * left for those drives devined from other means
174  * (e.g. SI, AMPEX, etc.).
175  */
176 short	hptypes[] = {
177 #define	HPDT_RM03	0
178 	MBDT_RM03,
179 #define	HPDT_RM05	1
180 	MBDT_RM05,
181 #define	HPDT_RP06	2
182 	MBDT_RP06,
183 #define	HPDT_RM80	3
184 	MBDT_RM80,
185 #define	HPDT_RP05	4
186 	MBDT_RP05,
187 #define	HPDT_RP07	5
188 	MBDT_RP07,
189 #define	HPDT_ML11A	6
190 	MBDT_ML11A,
191 #define	HPDT_ML11B	7
192 	MBDT_ML11B,
193 #define	HPDT_9775	8
194 	-1,
195 #define	HPDT_9730	9
196 	-1,
197 #define	HPDT_CAPRICORN	10
198 	-1,
199 #define HPDT_EAGLE	11
200 	-1,
201 #define HPDT_RM02	12
202 	MBDT_RM02,		/* beware, actually capricorn or eagle */
203 	0
204 };
205 struct	mba_device *hpinfo[NHP];
206 int	hpattach(),hpustart(),hpstart(),hpdtint();
207 struct	mba_driver hpdriver =
208 	{ hpattach, 0, hpustart, hpstart, hpdtint, 0,
209 	  hptypes, "hp", 0, hpinfo };
210 
211 struct hpst {
212 	short	nsect;
213 	short	ntrak;
214 	short	nspc;
215 	short	ncyl;
216 	struct	size *sizes;
217 } hpst[] = {
218 	32,	5,	32*5,	823,	rm3_sizes,	/* RM03 */
219 	32,	19,	32*19,	823,	rm5_sizes,	/* RM05 */
220 	22,	19,	22*19,	815,	hp6_sizes,	/* RP06 */
221 	31,	14, 	31*14,	559,	rm80_sizes,	/* RM80 */
222 	22,	19,	22*19,	411,	hp6_sizes,	/* RP05 */
223 	50,	32,	50*32,	630,	hp7_sizes,	/* RP07 */
224 	1,	1,	1,	1,	0,		/* ML11A */
225 	1,	1,	1,	1,	0,		/* ML11B */
226 	32,	40,	32*40,	843,	si9775_sizes,	/* 9775 */
227 	32,	10,	32*10,	823,	si9730_sizes,	/* 9730 */
228 	32,	16,	32*16,	1024,	hpam_sizes,	/* AMPEX capricorn */
229 	43,	20,	43*20,	843,	hpfj_sizes,	/* Fujitsu EAGLE */
230 };
231 
232 u_char	hp_offset[16] = {
233     HPOF_P400, HPOF_M400, HPOF_P400, HPOF_M400,
234     HPOF_P800, HPOF_M800, HPOF_P800, HPOF_M800,
235     HPOF_P1200, HPOF_M1200, HPOF_P1200, HPOF_M1200,
236     0, 0, 0, 0,
237 };
238 
239 struct	buf	rhpbuf[NHP];
240 #ifndef NOBADSECT
241 struct	buf	bhpbuf[NHP];
242 struct	dkbad	hpbad[NHP];
243 #endif
244 /* SHOULD CONSOLIDATE ALL THIS STUFF INTO A STRUCTURE */
245 char	hpinit[NHP];
246 char	hprecal[NHP];
247 char	hphdr[NHP];
248 daddr_t	mlsize[NHP];
249 
250 #define	b_cylin b_resid
251 
252 /* #define ML11 0  to remove ML11 support */
253 #define	ML11	(hptypes[mi->mi_type] == MBDT_ML11A)
254 #define	RP06	(hptypes[mi->mi_type] <= MBDT_RP06)
255 #define	RM80	(hptypes[mi->mi_type] == MBDT_RM80)
256 
257 #ifdef INTRLVE
258 daddr_t dkblock();
259 #endif
260 
261 int	hpseek;
262 
263 /*ARGSUSED*/
264 hpattach(mi, slave)
265 	struct mba_device *mi;
266 {
267 	register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv;
268 
269 	switch (mi->mi_type) {
270 
271 	/*
272 	 * Model-byte processing for SI 9400 controllers.
273 	 * NB:  Only deals with RM03 and RM05 emulations.
274 	 */
275 	case HPDT_RM03:
276 	case HPDT_RM05: {
277 		register int hpsn;
278 
279 		hpsn = hpaddr->hpsn;
280 		if ((hpsn & SIMB_LU) != mi->mi_drive)
281 			break;
282 		switch ((hpsn & SIMB_MB) & ~(SIMB_S6|SIRM03|SIRM05)) {
283 
284 		case SI9775D:
285 			printf("hp%d: si 9775 (direct)\n", mi->mi_unit);
286 			mi->mi_type = HPDT_9775;
287 			break;
288 
289 		case SI9730D:
290 			printf("hp%d: si 9730 (direct)\n", mi->mi_unit);
291 			mi->mi_type = HPDT_9730;
292 			break;
293 
294 #ifdef CAD
295 		/*
296 		 * AMPEX 9300, SI Combination needs a have the drive cleared
297 		 * before we start.  We do not know why, but tests show
298 		 * that the recalibrate fixes the problem.
299 		 */
300 		case SI9766:
301 			printf("hp%d: 9776/9300\n", mi->mi_unit);
302 			mi->mi_type = HPDT_RM05;
303 			hpaddr->hpcs1 = HP_RECAL|HP_GO;
304 			DELAY(100000);
305 			break;
306 
307 		case SI9762:
308 			printf("hp%d: 9762\n", mi->mi_unit);
309 			mi->mi_type = HPDT_RM03;
310 			break;
311 #endif
312 		}
313 		break;
314 		}
315 
316 	/*
317 	 * CAPRICORN KLUDGE...poke the holding register
318 	 * we believe it's a Capricorn.  Otherwise assume
319 	 * its an Eagle.
320 	 */
321 	case HPDT_RM02:
322 		hpaddr->hpcs1 = HP_NOP;
323 		hpaddr->hphr = HPHR_MAXTRAK;
324 		if ((hpaddr->hphr&0xffff) == 15) {
325 			printf("hp%d: capricorn\n", mi->mi_unit);
326 			mi->mi_type = HPDT_CAPRICORN;
327 		} else {
328 			printf("hp%d: eagle\n", mi->mi_unit);
329 			mi->mi_type = HPDT_EAGLE;
330 		}
331 		hpaddr->hpcs1 = HP_DCLR|HP_GO;
332 		break;
333 
334 	case HPDT_ML11A:
335 	case HPDT_ML11B: {
336 		register int trt, sz;
337 
338 		sz = hpaddr->hpmr & HPMR_SZ;
339 		if ((hpaddr->hpmr & HPMR_ARRTYP) == 0)
340 			sz >>= 2;
341 		mlsize[mi->mi_unit] = sz;
342 		if (mi->mi_dk >= 0) {
343 			trt = (hpaddr->hpmr & HPMR_TRT) >> 8;
344 			dk_mspw[mi->mi_dk] = 1.0 / (1<<(20-trt));
345 		}
346 		/* A CHEAT - ML11B D.T. SHOULD == ML11A */
347 		mi->mi_type = HPDT_ML11A;
348 		break;
349 		}
350 	}
351 	if (!ML11 && mi->mi_dk >= 0) {
352 		register struct hpst *st = &hpst[mi->mi_type];
353 
354 		dk_mspw[mi->mi_dk] = 1.0 / 60 / (st->nsect * 256);
355 	}
356 }
357 
358 hpopen(dev)
359 	dev_t dev;
360 {
361 	register int unit = minor(dev) >> 3;
362 	register struct mba_device *mi;
363 
364 	if (unit >= NHP || (mi = hpinfo[unit]) == 0 || mi->mi_alive == 0)
365 		return (ENXIO);
366 	return (0);
367 }
368 
369 hpstrategy(bp)
370 	register struct buf *bp;
371 {
372 	register struct mba_device *mi;
373 	register struct hpst *st;
374 	register int unit;
375 	long sz, bn;
376 	int xunit = minor(bp->b_dev) & 07;
377 	int s;
378 
379 	sz = bp->b_bcount;
380 	sz = (sz+511) >> 9;
381 	unit = dkunit(bp);
382 	if (unit >= NHP)
383 		goto bad;
384 	mi = hpinfo[unit];
385 	if (mi == 0 || mi->mi_alive == 0)
386 		goto bad;
387 	st = &hpst[mi->mi_type];
388 	if (ML11) {
389 		if (bp->b_blkno < 0 ||
390 		    dkblock(bp)+sz > mlsize[mi->mi_unit])
391 			goto bad;
392 		bp->b_cylin = 0;
393 	} else {
394 		if (bp->b_blkno < 0 ||
395 		    (bn = dkblock(bp))+sz > st->sizes[xunit].nblocks)
396 			goto bad;
397 		bp->b_cylin = bn/st->nspc + st->sizes[xunit].cyloff;
398 	}
399 	s = spl5();
400 	disksort(&mi->mi_tab, bp);
401 	if (mi->mi_tab.b_active == 0)
402 		mbustart(mi);
403 	splx(s);
404 	return;
405 
406 bad:
407 	bp->b_flags |= B_ERROR;
408 	iodone(bp);
409 	return;
410 }
411 
412 hpustart(mi)
413 	register struct mba_device *mi;
414 {
415 	register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv;
416 	register struct buf *bp = mi->mi_tab.b_actf;
417 	register struct hpst *st = &hpst[mi->mi_type];
418 	daddr_t bn;
419 	int sn, dist;
420 
421 	hpaddr->hpcs1 = 0;
422 	if ((hpaddr->hpcs1&HP_DVA) == 0)
423 		return (MBU_BUSY);
424 	if ((hpaddr->hpds & HPDS_VV) == 0 || hpinit[mi->mi_unit] == 0) {
425 #ifndef NOBADSECT
426 		struct buf *bbp = &bhpbuf[mi->mi_unit];
427 #endif
428 
429 		hpinit[mi->mi_unit] = 1;
430 		hpaddr->hpcs1 = HP_DCLR|HP_GO;
431 		if (mi->mi_mba->mba_drv[0].mbd_as & (1<<mi->mi_drive))
432 			printf("DCLR attn\n");
433 		hpaddr->hpcs1 = HP_PRESET|HP_GO;
434 		if (!ML11)
435 			hpaddr->hpof = HPOF_FMT22;
436 		mbclrattn(mi);
437 #ifndef NOBADSECT
438 		if (!ML11) {
439 			bbp->b_flags = B_READ|B_BUSY;
440 			bbp->b_dev = bp->b_dev;
441 			bbp->b_bcount = 512;
442 			bbp->b_un.b_addr = (caddr_t)&hpbad[mi->mi_unit];
443 			bbp->b_blkno = st->ncyl*st->nspc - st->nsect;
444 			bbp->b_cylin = st->ncyl - 1;
445 			mi->mi_tab.b_actf = bbp;
446 			bbp->av_forw = bp;
447 			bp = bbp;
448 		}
449 #endif
450 	}
451 	if (mi->mi_tab.b_active || mi->mi_hd->mh_ndrive == 1)
452 		return (MBU_DODATA);
453 	if (ML11)
454 		return (MBU_DODATA);
455 	if ((hpaddr->hpds & HPDS_DREADY) != HPDS_DREADY)
456 		return (MBU_DODATA);
457 	bn = dkblock(bp);
458 	sn = bn%st->nspc;
459 	sn = (sn+st->nsect-hpSDIST)%st->nsect;
460 	if (bp->b_cylin == (hpaddr->hpdc & 0xffff)) {
461 		if (hpseek)
462 			return (MBU_DODATA);
463 		dist = ((hpaddr->hpla & 0xffff)>>6) - st->nsect + 1;
464 		if (dist < 0)
465 			dist += st->nsect;
466 		if (dist > st->nsect - hpRDIST)
467 			return (MBU_DODATA);
468 	} else
469 		hpaddr->hpdc = bp->b_cylin;
470 	if (hpseek)
471 		hpaddr->hpcs1 = HP_SEEK|HP_GO;
472 	else {
473 		hpaddr->hpda = sn;
474 		hpaddr->hpcs1 = HP_SEARCH|HP_GO;
475 	}
476 	return (MBU_STARTED);
477 }
478 
479 hpstart(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 = &hpst[mi->mi_type];
485 	daddr_t bn;
486 	int sn, tn;
487 
488 	bn = dkblock(bp);
489 	if (ML11)
490 		hpaddr->hpda = bn;
491 	else {
492 		sn = bn%st->nspc;
493 		tn = sn/st->nsect;
494 		sn %= st->nsect;
495 		hpaddr->hpdc = bp->b_cylin;
496 		hpaddr->hpda = (tn << 8) + sn;
497 	}
498 	if (hphdr[mi->mi_unit]) {
499 		if (bp->b_flags & B_READ)
500 			return (HP_RHDR|HP_GO);
501 		else
502 			return (HP_WHDR|HP_GO);
503 	}
504 	return (0);
505 }
506 
507 hpdtint(mi, mbsr)
508 	register struct mba_device *mi;
509 	int mbsr;
510 {
511 	register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv;
512 	register struct buf *bp = mi->mi_tab.b_actf;
513 	register int er1, er2;
514 	int retry = 0;
515 
516 #ifndef NOBADSECT
517 	if (bp->b_flags&B_BAD) {
518 		if (hpecc(mi, CONT))
519 			return(MBD_RESTARTED);
520 	}
521 #endif
522 	if (hpaddr->hpds&HPDS_ERR || mbsr&MBSR_EBITS) {
523 #ifdef HPDEBUG
524 		if (hpdebug) {
525 			int dc = hpaddr->hpdc, da = hpaddr->hpda;
526 
527 			printf("hperr: bp %x cyl %d blk %d as %o ",
528 				bp, bp->b_cylin, bp->b_blkno,
529 				hpaddr->hpas&0xff);
530 			printf("dc %x da %x\n",dc&0xffff, da&0xffff);
531 			printf("errcnt %d ", mi->mi_tab.b_errcnt);
532 			printf("mbsr=%b ", mbsr, mbsr_bits);
533 			printf("er1=%b er2=%b\n",
534 			    hpaddr->hper1, HPER1_BITS,
535 			    hpaddr->hper2, HPER2_BITS);
536 			DELAY(1000000);
537 		}
538 #endif
539 		er1 = hpaddr->hper1;
540 		er2 = hpaddr->hper2;
541 		if (er1 & HPER1_HCRC) {
542 			er1 &= ~(HPER1_HCE|HPER1_FER);
543 			er2 &= ~HPER2_BSE;
544 		}
545 		if (er1&HPER1_WLE) {
546 			printf("hp%d: write locked\n", dkunit(bp));
547 			bp->b_flags |= B_ERROR;
548 		} else if ((er1&0xffff) == HPER1_FER && RP06 &&
549 		    hphdr[mi->mi_unit] == 0) {
550 #ifndef NOBADSECT
551 			if (hpecc(mi, BSE))
552 				return(MBD_RESTARTED);
553 			else
554 #endif
555 				goto hard;
556 		} else if (++mi->mi_tab.b_errcnt > 27 ||
557 		    mbsr & MBSR_HARD ||
558 		    er1 & HPER1_HARD ||
559 		    hphdr[mi->mi_unit] ||
560 		    (!ML11 && (er2 & HPER2_HARD))) {
561 hard:
562 			harderr(bp, "hp");
563 			if (mbsr & (MBSR_EBITS &~ (MBSR_DTABT|MBSR_MBEXC)))
564 				printf("mbsr=%b ", mbsr, mbsr_bits);
565 			printf("er1=%b er2=%b",
566 			    hpaddr->hper1, HPER1_BITS,
567 			    hpaddr->hper2, HPER2_BITS);
568 			if (hpaddr->hpmr)
569 				printf(" mr=%o", hpaddr->hpmr&0xffff);
570 			if (hpaddr->hpmr2)
571 				printf(" mr2=%o", hpaddr->hpmr2&0xffff);
572 			printf("\n");
573 			bp->b_flags |= B_ERROR;
574 			hprecal[mi->mi_unit] = 0;
575 		} else if ((er2 & HPER2_BSE) && !ML11) {
576 #ifndef NOBADSECT
577 			if (hpecc(mi, BSE))
578 				return(MBD_RESTARTED);
579 			else
580 #endif
581 				goto hard;
582 		} else if (RM80 && er2&HPER2_SSE) {
583 			(void) hpecc(mi, SSE);
584 			return (MBD_RESTARTED);
585 		} else if ((er1&(HPER1_DCK|HPER1_ECH))==HPER1_DCK) {
586 			if (hpecc(mi, ECC))
587 				return (MBD_RESTARTED);
588 			/* else done */
589 		} else
590 			retry = 1;
591 		hpaddr->hpcs1 = HP_DCLR|HP_GO;
592 		if (ML11) {
593 			if (mi->mi_tab.b_errcnt >= 16)
594 				goto hard;
595 		} else if ((mi->mi_tab.b_errcnt&07) == 4) {
596 			hpaddr->hpcs1 = HP_RECAL|HP_GO;
597 			hprecal[mi->mi_unit] = 1;
598 			return(MBD_RESTARTED);
599 		}
600 		if (retry)
601 			return (MBD_RETRY);
602 	}
603 #ifdef HPDEBUG
604 	else
605 		if (hpdebug && hprecal[mi->mi_unit]) {
606 			printf("recal %d ", hprecal[mi->mi_unit]);
607 			printf("errcnt %d\n", mi->mi_tab.b_errcnt);
608 			printf("mbsr=%b ", mbsr, mbsr_bits);
609 			printf("er1=%b er2=%b\n",
610 			    hpaddr->hper1, HPER1_BITS,
611 			    hpaddr->hper2, HPER2_BITS);
612 		}
613 #endif
614 	switch (hprecal[mi->mi_unit]) {
615 
616 	case 1:
617 		hpaddr->hpdc = bp->b_cylin;
618 		hpaddr->hpcs1 = HP_SEEK|HP_GO;
619 		hprecal[mi->mi_unit]++;
620 		return (MBD_RESTARTED);
621 	case 2:
622 		if (mi->mi_tab.b_errcnt < 16 ||
623 		    (bp->b_flags & B_READ) == 0)
624 			goto donerecal;
625 		hpaddr->hpof = hp_offset[mi->mi_tab.b_errcnt & 017]|HPOF_FMT22;
626 		hpaddr->hpcs1 = HP_OFFSET|HP_GO;
627 		hprecal[mi->mi_unit]++;
628 		return (MBD_RESTARTED);
629 	donerecal:
630 	case 3:
631 		hprecal[mi->mi_unit] = 0;
632 		return (MBD_RETRY);
633 	}
634 	hphdr[mi->mi_unit] = 0;
635 	bp->b_resid = -(mi->mi_mba->mba_bcr) & 0xffff;
636 	if (mi->mi_tab.b_errcnt >= 16) {
637 		/*
638 		 * This is fast and occurs rarely; we don't
639 		 * bother with interrupts.
640 		 */
641 		hpaddr->hpcs1 = HP_RTC|HP_GO;
642 		while (hpaddr->hpds & HPDS_PIP)
643 			;
644 		mbclrattn(mi);
645 	}
646 	if (!ML11) {
647 		hpaddr->hpof = HPOF_FMT22;
648 		hpaddr->hpcs1 = HP_RELEASE|HP_GO;
649 	}
650 	return (MBD_DONE);
651 }
652 
653 hpread(dev, uio)
654 	dev_t dev;
655 	struct uio *uio;
656 {
657 	register int unit = minor(dev) >> 3;
658 
659 	if (unit >= NHP)
660 		return (ENXIO);
661 	return (physio(hpstrategy, &rhpbuf[unit], dev, B_READ, minphys, uio));
662 }
663 
664 hpwrite(dev, uio)
665 	dev_t dev;
666 	struct uio *uio;
667 {
668 	register int unit = minor(dev) >> 3;
669 
670 	if (unit >= NHP)
671 		return (ENXIO);
672 	return (physio(hpstrategy, &rhpbuf[unit], dev, B_WRITE, minphys, uio));
673 }
674 
675 /*ARGSUSED*/
676 hpioctl(dev, cmd, data, flag)
677 	dev_t dev;
678 	int cmd;
679 	caddr_t data;
680 	int flag;
681 {
682 
683 	switch (cmd) {
684 
685 	case DKIOCHDR:	/* do header read/write */
686 		hphdr[minor(dev)>>3] = 1;
687 		return (0);
688 
689 	default:
690 		return (ENXIO);
691 	}
692 }
693 
694 hpecc(mi, flag)
695 	register struct mba_device *mi;
696 	int flag;
697 {
698 	register struct mba_regs *mbp = mi->mi_mba;
699 	register struct hpdevice *rp = (struct hpdevice *)mi->mi_drv;
700 	register struct buf *bp = mi->mi_tab.b_actf;
701 	register struct hpst *st = &hpst[mi->mi_type];
702 	int npf, o;
703 	int bn, cn, tn, sn;
704 	int bcr;
705 
706 	bcr = mbp->mba_bcr & 0xffff;
707 	if (bcr)
708 		bcr |= 0xffff0000;		/* sxt */
709 #ifndef NOBADSECT
710 	if (flag == CONT)
711 		npf = bp->b_error;
712 	else
713 #endif
714 		npf = btop(bcr + bp->b_bcount);
715 	o = (int)bp->b_un.b_addr & PGOFSET;
716 	bn = dkblock(bp);
717 	cn = bp->b_cylin;
718 	sn = bn%(st->nspc) + npf;
719 	tn = sn/st->nsect;
720 	sn %= st->nsect;
721 	cn += tn/st->ntrak;
722 	tn %= st->ntrak;
723 	switch (flag) {
724 	case ECC:
725 		{
726 		register int i;
727 		caddr_t addr;
728 		struct pte mpte;
729 		int bit, byte, mask;
730 
731 		npf--;		/* because block in error is previous block */
732 		printf("hp%d%c: soft ecc sn%d\n", dkunit(bp),
733 		    'a'+(minor(bp->b_dev)&07), bp->b_blkno + npf);
734 		mask = rp->hpec2&0xffff;
735 		i = (rp->hpec1&0xffff) - 1;		/* -1 makes 0 origin */
736 		bit = i&07;
737 		i = (i&~07)>>3;
738 		byte = i + o;
739 		while (i < 512 && (int)ptob(npf)+i < bp->b_bcount && bit > -11) {
740 			mpte = mbp->mba_map[npf+btop(byte)];
741 			addr = ptob(mpte.pg_pfnum) + (byte & PGOFSET);
742 			putmemc(addr, getmemc(addr)^(mask<<bit));
743 			byte++;
744 			i++;
745 			bit -= 8;
746 		}
747 		if (bcr == 0)
748 			return (0);
749 		npf++;
750 		break;
751 		}
752 
753 	case SSE:
754 		rp->hpof |= HPOF_SSEI;
755 		mbp->mba_bcr = -(bp->b_bcount - (int)ptob(npf));
756 		break;
757 
758 #ifndef NOBADSECT
759 	case BSE:
760 #ifdef HPBDEBUG
761 		if (hpbdebug)
762 		printf("hpecc, BSE: bn %d cn %d tn %d sn %d\n", bn, cn, tn, sn);
763 #endif
764 		if ((bn = isbad(&hpbad[mi->mi_unit], cn, tn, sn)) < 0)
765 			return(0);
766 		bp->b_flags |= B_BAD;
767 		bp->b_error = npf + 1;
768 		bn = st->ncyl*st->nspc - st->nsect - 1 - bn;
769 		cn = bn/st->nspc;
770 		sn = bn%st->nspc;
771 		tn = sn/st->nsect;
772 		sn %= st->nsect;
773 		mbp->mba_bcr = -512;
774 #ifdef HPBDEBUG
775 		if (hpbdebug)
776 		printf("revector to cn %d tn %d sn %d\n", cn, tn, sn);
777 #endif
778 		break;
779 
780 	case CONT:
781 #ifdef HPBDEBUG
782 		if (hpbdebug)
783 		printf("hpecc, CONT: bn %d cn %d tn %d sn %d\n", bn,cn,tn,sn);
784 #endif
785 		npf = bp->b_error;
786 		bp->b_flags &= ~B_BAD;
787 		mbp->mba_bcr = -(bp->b_bcount - (int)ptob(npf));
788 		if ((mbp->mba_bcr & 0xffff) == 0)
789 			return(0);
790 		break;
791 #endif
792 	}
793 	rp->hpcs1 = HP_DCLR|HP_GO;
794 	if (rp->hpof&HPOF_SSEI)
795 		sn++;
796 	rp->hpdc = cn;
797 	rp->hpda = (tn<<8) + sn;
798 	mbp->mba_sr = -1;
799 	mbp->mba_var = (int)ptob(npf) + o;
800 	rp->hpcs1 = bp->b_flags&B_READ ? HP_RCOM|HP_GO : HP_WCOM|HP_GO;
801 	mi->mi_tab.b_errcnt = 0;	/* error has been corrected */
802 	return (1);
803 }
804 
805 #define	DBSIZE	20
806 
807 hpdump(dev)
808 	dev_t dev;
809 {
810 	register struct mba_device *mi;
811 	register struct mba_regs *mba;
812 	struct hpdevice *hpaddr;
813 	char *start;
814 	int num, unit;
815 	register struct hpst *st;
816 
817 	num = maxfree;
818 	start = 0;
819 	unit = minor(dev) >> 3;
820 	if (unit >= NHP)
821 		return (ENXIO);
822 #define	phys(a,b)	((b)((int)(a)&0x7fffffff))
823 	mi = phys(hpinfo[unit],struct mba_device *);
824 	if (mi == 0 || mi->mi_alive == 0)
825 		return (ENXIO);
826 	mba = phys(mi->mi_hd, struct mba_hd *)->mh_physmba;
827 	mba->mba_cr = MBCR_INIT;
828 	hpaddr = (struct hpdevice *)&mba->mba_drv[mi->mi_drive];
829 	if ((hpaddr->hpds & HPDS_VV) == 0) {
830 		hpaddr->hpcs1 = HP_DCLR|HP_GO;
831 		hpaddr->hpcs1 = HP_PRESET|HP_GO;
832 		hpaddr->hpof = HPOF_FMT22;
833 	}
834 	st = &hpst[mi->mi_type];
835 	if (dumplo < 0 || dumplo + num >= st->sizes[minor(dev)&07].nblocks)
836 		return (EINVAL);
837 	while (num > 0) {
838 		register struct pte *hpte = mba->mba_map;
839 		register int i;
840 		int blk, cn, sn, tn;
841 		daddr_t bn;
842 
843 		blk = num > DBSIZE ? DBSIZE : num;
844 		bn = dumplo + btop(start);
845 		cn = bn/st->nspc + st->sizes[minor(dev)&07].cyloff;
846 		sn = bn%st->nspc;
847 		tn = sn/st->nsect;
848 		sn = sn%st->nsect;
849 		hpaddr->hpdc = cn;
850 		hpaddr->hpda = (tn << 8) + sn;
851 		for (i = 0; i < blk; i++)
852 			*(int *)hpte++ = (btop(start)+i) | PG_V;
853 		mba->mba_sr = -1;
854 		mba->mba_bcr = -(blk*NBPG);
855 		mba->mba_var = 0;
856 		hpaddr->hpcs1 = HP_WCOM | HP_GO;
857 		while ((hpaddr->hpds & HPDS_DRY) == 0)
858 			;
859 		if (hpaddr->hpds&HPDS_ERR)
860 			return (EIO);
861 		start += blk*NBPG;
862 		num -= blk;
863 	}
864 	return (0);
865 }
866 #endif
867