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