xref: /original-bsd/sys/hp300/dev/rd.c (revision 898c7514)
1 /*
2  * Copyright (c) 1988 University of Utah.
3  * Copyright (c) 1982, 1990, 1993
4  *	The Regents of the University of California.  All rights reserved.
5  *
6  * This code is derived from software contributed to Berkeley by
7  * the Systems Programming Group of the University of Utah Computer
8  * Science Department.
9  *
10  * %sccs.include.redist.c%
11  *
12  * from: Utah $Hdr: rd.c 1.44 92/12/26$
13  *
14  *	@(#)rd.c	8.4 (Berkeley) 05/10/95
15  */
16 
17 /*
18  * CS80/SS80 disk driver
19  */
20 #include "rd.h"
21 #if NRD > 0
22 
23 #include <sys/param.h>
24 #include <sys/systm.h>
25 #include <sys/buf.h>
26 #include <sys/stat.h>
27 #include <sys/dkstat.h>
28 #include <sys/disklabel.h>
29 #include <sys/ioctl.h>
30 #include <sys/fcntl.h>
31 
32 #include <hp/dev/device.h>
33 #include <hp300/dev/rdreg.h>
34 #include <hp300/dev/rdvar.h>
35 #ifdef USELEDS
36 #include <hp300/hp300/led.h>
37 #endif
38 
39 #include <vm/vm_param.h>
40 #include <sys/lock.h>
41 #include <vm/vm_prot.h>
42 #include <vm/pmap.h>
43 
44 int	rdinit(), rdstart(), rdgo(), rdintr();
45 void	rdstrategy();
46 struct	driver rddriver = {
47 	rdinit, "rd", rdstart, rdgo, rdintr,
48 };
49 
50 struct	rd_softc rd_softc[NRD];
51 struct	buf rdtab[NRD];
52 int	rderrthresh = RDRETRY-1;	/* when to start reporting errors */
53 
54 #ifdef DEBUG
55 /* error message tables */
56 char *err_reject[] = {
57 	0, 0,
58 	"channel parity error",		/* 0x2000 */
59 	0, 0,
60 	"illegal opcode",		/* 0x0400 */
61 	"module addressing",		/* 0x0200 */
62 	"address bounds",		/* 0x0100 */
63 	"parameter bounds",		/* 0x0080 */
64 	"illegal parameter",		/* 0x0040 */
65 	"message sequence",		/* 0x0020 */
66 	0,
67 	"message length",		/* 0x0008 */
68 	0, 0, 0
69 };
70 
71 char *err_fault[] = {
72 	0,
73 	"cross unit",			/* 0x4000 */
74 	0,
75 	"controller fault",		/* 0x1000 */
76 	0, 0,
77 	"unit fault",			/* 0x0200 */
78 	0,
79 	"diagnostic result",		/* 0x0080 */
80 	0,
81 	"operator release request",	/* 0x0020 */
82 	"diagnostic release request",	/* 0x0010 */
83 	"internal maintenance release request",	/* 0x0008 */
84 	0,
85 	"power fail",			/* 0x0002 */
86 	"retransmit"			/* 0x0001 */
87 };
88 
89 char *err_access[] = {
90 	"illegal parallel operation",	/* 0x8000 */
91 	"uninitialized media",		/* 0x4000 */
92 	"no spares available",		/* 0x2000 */
93 	"not ready",			/* 0x1000 */
94 	"write protect",		/* 0x0800 */
95 	"no data found",		/* 0x0400 */
96 	0, 0,
97 	"unrecoverable data overflow",	/* 0x0080 */
98 	"unrecoverable data",		/* 0x0040 */
99 	0,
100 	"end of file",			/* 0x0010 */
101 	"end of volume",		/* 0x0008 */
102 	0, 0, 0
103 };
104 
105 char *err_info[] = {
106 	"operator release request",	/* 0x8000 */
107 	"diagnostic release request",	/* 0x4000 */
108 	"internal maintenance release request",	/* 0x2000 */
109 	"media wear",			/* 0x1000 */
110 	"latency induced",		/* 0x0800 */
111 	0, 0,
112 	"auto sparing invoked",		/* 0x0100 */
113 	0,
114 	"recoverable data overflow",	/* 0x0040 */
115 	"marginal data",		/* 0x0020 */
116 	"recoverable data",		/* 0x0010 */
117 	0,
118 	"maintenance track overflow",	/* 0x0004 */
119 	0, 0
120 };
121 
122 struct	rdstats rdstats[NRD];
123 int	rddebug = 0x80;
124 #define RDB_FOLLOW	0x01
125 #define RDB_STATUS	0x02
126 #define RDB_IDENT	0x04
127 #define RDB_IO		0x08
128 #define RDB_ASYNC	0x10
129 #define RDB_ERROR	0x80
130 #endif
131 
132 /*
133  * Misc. HW description, indexed by sc_type.
134  * Nothing really critical here, could do without it.
135  */
136 struct rdidentinfo rdidentinfo[] = {
137 	{ RD7946AID,	0,	"7945A",	 108416 },
138 	{ RD9134DID,	1,	"9134D",	  29088 },
139 	{ RD9134LID,	1,	"9122S",	   1232 },
140 	{ RD7912PID,	0,	"7912P",	 128128 },
141 	{ RD7914PID,	0,	"7914P",	 258048 },
142 	{ RD7958AID,	0,	"7958A",	 255276 },
143 	{ RD7957AID,	0,	"7957A",	 159544 },
144 	{ RD7933HID,	0,	"7933H",	 789958 },
145 	{ RD9134LID,	1,	"9134L",	  77840 },
146 	{ RD7936HID,	0,	"7936H",	 600978 },
147 	{ RD7937HID,	0,	"7937H",	1116102 },
148 	{ RD7914CTID,	0,	"7914CT",	 258048 },
149 	{ RD7946AID,	0,	"7946A",	 108416 },
150 	{ RD9134LID,	1,	"9122D",	   1232 },
151 	{ RD7957BID,	0,	"7957B",	 159894 },
152 	{ RD7958BID,	0,	"7958B",	 297108 },
153 	{ RD7959BID,	0,	"7959B",	 594216 },
154 	{ RD2200AID,	0,	"2200A",	 654948 },
155 	{ RD2203AID,	0,	"2203A",	1309896 }
156 };
157 int numrdidentinfo = sizeof(rdidentinfo) / sizeof(rdidentinfo[0]);
158 
159 rdinit(hd)
160 	register struct hp_device *hd;
161 {
162 	register struct rd_softc *rs = &rd_softc[hd->hp_unit];
163 
164 	rs->sc_hd = hd;
165 	rs->sc_punit = rdpunit(hd->hp_flags);
166 	rs->sc_type = rdident(rs, hd);
167 	if (rs->sc_type < 0)
168 		return(0);
169 	rs->sc_dq.dq_ctlr = hd->hp_ctlr;
170 	rs->sc_dq.dq_unit = hd->hp_unit;
171 	rs->sc_dq.dq_slave = hd->hp_slave;
172 	rs->sc_dq.dq_driver = &rddriver;
173 	rs->sc_flags = RDF_ALIVE;
174 #ifdef DEBUG
175 	/* always report errors */
176 	if (rddebug & RDB_ERROR)
177 		rderrthresh = 0;
178 #endif
179 	return(1);
180 }
181 
182 rdident(rs, hd)
183 	struct rd_softc *rs;
184 	struct hp_device *hd;
185 {
186 	struct rd_describe desc;
187 	u_char stat, cmd[3];
188 	int unit, lunit;
189 	char name[7];
190 	register int ctlr, slave, id, i;
191 
192 	ctlr = hd->hp_ctlr;
193 	slave = hd->hp_slave;
194 	unit = rs->sc_punit;
195 	lunit = hd->hp_unit;
196 
197 	/*
198 	 * Grab device id and make sure:
199 	 * 1. It is a CS80 device.
200 	 * 2. It is one of the types we support.
201 	 * 3. If it is a 7946, we are accessing the disk unit (0)
202 	 */
203 	id = hpibid(ctlr, slave);
204 #ifdef DEBUG
205 	if (rddebug & RDB_IDENT)
206 		printf("hpibid(%d, %d) -> %x\n", ctlr, slave, id);
207 #endif
208 	if ((id & 0x200) == 0)
209 		return(-1);
210 	for (i = 0; i < numrdidentinfo; i++)
211 		if (id == rdidentinfo[i].ri_hwid)
212 			break;
213 	if (i == numrdidentinfo || unit > rdidentinfo[i].ri_maxunum)
214 		return(-1);
215 	id = i;
216 
217 	/*
218 	 * Reset drive and collect device description.
219 	 * Don't really use the description info right now but
220 	 * might come in handy in the future (for disk labels).
221 	 */
222 	rdreset(rs, hd);
223 	cmd[0] = C_SUNIT(unit);
224 	cmd[1] = C_SVOL(0);
225 	cmd[2] = C_DESC;
226 	hpibsend(ctlr, slave, C_CMD, cmd, sizeof(cmd));
227 	hpibrecv(ctlr, slave, C_EXEC, &desc, 37);
228 	hpibrecv(ctlr, slave, C_QSTAT, &stat, sizeof(stat));
229 	bzero(name, sizeof(name));
230 	if (!stat) {
231 		register int n = desc.d_name;
232 		for (i = 5; i >= 0; i--) {
233 			name[i] = (n & 0xf) + '0';
234 			n >>= 4;
235 		}
236 		/* use drive characteristics to calculate xfer rate */
237 		rs->sc_wpms = 1000000 * (desc.d_sectsize/2) / desc.d_blocktime;
238 	}
239 #ifdef DEBUG
240 	if (rddebug & RDB_IDENT) {
241 		printf("rd%d: name: %x ('%s')\n",
242 		       lunit, desc.d_name, name);
243 		printf("  iuw %x, maxxfr %d, ctype %d\n",
244 		       desc.d_iuw, desc.d_cmaxxfr, desc.d_ctype);
245 		printf("  utype %d, bps %d, blkbuf %d, burst %d, blktime %d\n",
246 		       desc.d_utype, desc.d_sectsize,
247 		       desc.d_blkbuf, desc.d_burstsize, desc.d_blocktime);
248 		printf("  avxfr %d, ort %d, atp %d, maxint %d, fv %x, rv %x\n",
249 		       desc.d_uavexfr, desc.d_retry, desc.d_access,
250 		       desc.d_maxint, desc.d_fvbyte, desc.d_rvbyte);
251 		printf("  maxcyl/head/sect %d/%d/%d, maxvsect %d, inter %d\n",
252 		       desc.d_maxcyl, desc.d_maxhead, desc.d_maxsect,
253 		       desc.d_maxvsectl, desc.d_interleave);
254 	}
255 #endif
256 	/*
257 	 * Take care of a couple of anomolies:
258 	 * 1. 7945A and 7946A both return same HW id
259 	 * 2. 9122S and 9134D both return same HW id
260 	 * 3. 9122D and 9134L both return same HW id
261 	 */
262 	switch (rdidentinfo[id].ri_hwid) {
263 	case RD7946AID:
264 		if (bcmp(name, "079450", 6) == 0)
265 			id = RD7945A;
266 		else
267 			id = RD7946A;
268 		break;
269 
270 	case RD9134LID:
271 		if (bcmp(name, "091340", 6) == 0)
272 			id = RD9134L;
273 		else
274 			id = RD9122D;
275 		break;
276 
277 	case RD9134DID:
278 		if (bcmp(name, "091220", 6) == 0)
279 			id = RD9122S;
280 		else
281 			id = RD9134D;
282 		break;
283 	}
284 	printf("rd%d: %s\n", lunit, rdidentinfo[id].ri_desc);
285 	return(id);
286 }
287 
288 rdreset(rs, hd)
289 	register struct rd_softc *rs;
290 	register struct hp_device *hd;
291 {
292 	u_char stat;
293 
294 	rs->sc_clear.c_unit = C_SUNIT(rs->sc_punit);
295 	rs->sc_clear.c_cmd = C_CLEAR;
296 	hpibsend(hd->hp_ctlr, hd->hp_slave, C_TCMD, &rs->sc_clear,
297 		sizeof(rs->sc_clear));
298 	hpibswait(hd->hp_ctlr, hd->hp_slave);
299 	hpibrecv(hd->hp_ctlr, hd->hp_slave, C_QSTAT, &stat, sizeof(stat));
300 	rs->sc_src.c_unit = C_SUNIT(RDCTLR);
301 	rs->sc_src.c_nop = C_NOP;
302 	rs->sc_src.c_cmd = C_SREL;
303 	rs->sc_src.c_param = C_REL;
304 	hpibsend(hd->hp_ctlr, hd->hp_slave, C_CMD, &rs->sc_src,
305 		sizeof(rs->sc_src));
306 	hpibswait(hd->hp_ctlr, hd->hp_slave);
307 	hpibrecv(hd->hp_ctlr, hd->hp_slave, C_QSTAT, &stat, sizeof(stat));
308 	rs->sc_ssmc.c_unit = C_SUNIT(rs->sc_punit);
309 	rs->sc_ssmc.c_cmd = C_SSM;
310 	rs->sc_ssmc.c_refm = REF_MASK;
311 	rs->sc_ssmc.c_fefm = FEF_MASK;
312 	rs->sc_ssmc.c_aefm = AEF_MASK;
313 	rs->sc_ssmc.c_iefm = IEF_MASK;
314 	hpibsend(hd->hp_ctlr, hd->hp_slave, C_CMD, &rs->sc_ssmc,
315 		sizeof(rs->sc_ssmc));
316 	hpibswait(hd->hp_ctlr, hd->hp_slave);
317 	hpibrecv(hd->hp_ctlr, hd->hp_slave, C_QSTAT, &stat, sizeof(stat));
318 #ifdef DEBUG
319 	rdstats[hd->hp_unit].rdresets++;
320 #endif
321 }
322 
323 /*
324  * Read or constuct a disklabel
325  */
326 int
327 rdgetinfo(dev)
328 	dev_t dev;
329 {
330 	int unit = rdunit(dev);
331 	register struct rd_softc *rs = &rd_softc[unit];
332 	register struct disklabel *lp = &rs->sc_info.ri_label;
333 	register struct partition *pi;
334 	char *msg, *readdisklabel();
335 
336 	/*
337 	 * Set some default values to use while reading the label
338 	 * or to use if there isn't a label.
339 	 */
340 	bzero((caddr_t)lp, sizeof *lp);
341 	lp->d_type = DTYPE_HPIB;
342 	lp->d_secsize = DEV_BSIZE;
343 	lp->d_nsectors = 32;
344 	lp->d_ntracks = 20;
345 	lp->d_ncylinders = 1;
346 	lp->d_secpercyl = 32*20;
347 	lp->d_npartitions = 3;
348 	lp->d_partitions[2].p_offset = 0;
349 	lp->d_partitions[2].p_size = LABELSECTOR+1;
350 
351 	/*
352 	 * Now try to read the disklabel
353 	 */
354 	msg = readdisklabel(rdlabdev(dev), rdstrategy, lp);
355 	if (msg == NULL)
356 		return(0);
357 
358 	pi = lp->d_partitions;
359 	printf("rd%d: WARNING: %s, ", unit, msg);
360 #ifdef COMPAT_NOLABEL
361 	printf("using old default partitioning\n");
362 	rdmakedisklabel(unit, lp);
363 #else
364 	printf("defining `c' partition as entire disk\n");
365 	pi[2].p_size = rdidentinfo[rs->sc_type].ri_nblocks;
366 	/* XXX reset other info since readdisklabel screws with it */
367 	lp->d_npartitions = 3;
368 	pi[0].p_size = 0;
369 #endif
370 	return(0);
371 }
372 
373 int
374 rdopen(dev, flags, mode, p)
375 	dev_t dev;
376 	int flags, mode;
377 	struct proc *p;
378 {
379 	register int unit = rdunit(dev);
380 	register struct rd_softc *rs = &rd_softc[unit];
381 	int error, mask;
382 
383 	if (unit >= NRD || (rs->sc_flags & RDF_ALIVE) == 0)
384 		return(ENXIO);
385 
386 	/*
387 	 * Wait for any pending opens/closes to complete
388 	 */
389 	while (rs->sc_flags & (RDF_OPENING|RDF_CLOSING))
390 		sleep((caddr_t)rs, PRIBIO);
391 
392 	/*
393 	 * On first open, get label and partition info.
394 	 * We may block reading the label, so be careful
395 	 * to stop any other opens.
396 	 */
397 	if (rs->sc_info.ri_open == 0) {
398 		rs->sc_flags |= RDF_OPENING;
399 		error = rdgetinfo(dev);
400 		rs->sc_flags &= ~RDF_OPENING;
401 		wakeup((caddr_t)rs);
402 		if (error)
403 			return(error);
404 	}
405 	if (rs->sc_hd->hp_dk >= 0) {
406 		/* guess at xfer rate based on 3600 rpm (60 rps) */
407 		if (rs->sc_wpms == 0)
408 			rs->sc_wpms = 60 * rs->sc_info.ri_label.d_nsectors
409 				* DEV_BSIZE / 2;
410 		dk_wpms[rs->sc_hd->hp_dk] = rs->sc_wpms;
411 	}
412 
413 	mask = 1 << rdpart(dev);
414 	if (mode == S_IFCHR)
415 		rs->sc_info.ri_copen |= mask;
416 	else
417 		rs->sc_info.ri_bopen |= mask;
418 	rs->sc_info.ri_open |= mask;
419 	return(0);
420 }
421 
422 int
423 rdclose(dev, flag, mode, p)
424 	dev_t dev;
425 	int flag, mode;
426 	struct proc *p;
427 {
428 	int unit = rdunit(dev);
429 	register struct rd_softc *rs = &rd_softc[unit];
430 	register struct rdinfo *ri = &rs->sc_info;
431 	int mask, s;
432 
433 	mask = 1 << rdpart(dev);
434 	if (mode == S_IFCHR)
435 		ri->ri_copen &= ~mask;
436 	else
437 		ri->ri_bopen &= ~mask;
438 	ri->ri_open = ri->ri_bopen | ri->ri_copen;
439 	/*
440 	 * On last close, we wait for all activity to cease since
441 	 * the label/parition info will become invalid.  Since we
442 	 * might sleep, we must block any opens while we are here.
443 	 * Note we don't have to about other closes since we know
444 	 * we are the last one.
445 	 */
446 	if (ri->ri_open == 0) {
447 		rs->sc_flags |= RDF_CLOSING;
448 		s = splbio();
449 		while (rdtab[unit].b_active) {
450 			rs->sc_flags |= RDF_WANTED;
451 			sleep((caddr_t)&rdtab[unit], PRIBIO);
452 		}
453 		splx(s);
454 		rs->sc_flags &= ~(RDF_CLOSING|RDF_WLABEL);
455 		wakeup((caddr_t)rs);
456 	}
457 	return(0);
458 }
459 
460 void
461 rdstrategy(bp)
462 	register struct buf *bp;
463 {
464 	int unit = rdunit(bp->b_dev);
465 	register struct rd_softc *rs = &rd_softc[unit];
466 	register struct buf *dp = &rdtab[unit];
467 	register struct partition *pinfo;
468 	register daddr_t bn;
469 	register int sz, s;
470 
471 #ifdef DEBUG
472 	if (rddebug & RDB_FOLLOW)
473 		printf("rdstrategy(%x): dev %x, bn %x, bcount %x, %c\n",
474 		       bp, bp->b_dev, bp->b_blkno, bp->b_bcount,
475 		       (bp->b_flags & B_READ) ? 'R' : 'W');
476 #endif
477 	bn = bp->b_blkno;
478 	sz = howmany(bp->b_bcount, DEV_BSIZE);
479 	pinfo = &rs->sc_info.ri_label.d_partitions[rdpart(bp->b_dev)];
480 	if (bn < 0 || bn + sz > pinfo->p_size) {
481 		sz = pinfo->p_size - bn;
482 		if (sz == 0) {
483 			bp->b_resid = bp->b_bcount;
484 			goto done;
485 		}
486 		if (sz < 0) {
487 			bp->b_error = EINVAL;
488 			goto bad;
489 		}
490 		bp->b_bcount = dbtob(sz);
491 	}
492 	/*
493 	 * Check for write to write protected label
494 	 */
495 	if (bn + pinfo->p_offset <= LABELSECTOR &&
496 #if LABELSECTOR != 0
497 	    bn + pinfo->p_offset + sz > LABELSECTOR &&
498 #endif
499 	    !(bp->b_flags & B_READ) && !(rs->sc_flags & RDF_WLABEL)) {
500 		bp->b_error = EROFS;
501 		goto bad;
502 	}
503 	bp->b_cylin = bn + pinfo->p_offset;
504 	s = splbio();
505 	disksort(dp, bp);
506 	if (dp->b_active == 0) {
507 		dp->b_active = 1;
508 		rdustart(unit);
509 	}
510 	splx(s);
511 	return;
512 bad:
513 	bp->b_flags |= B_ERROR;
514 done:
515 	biodone(bp);
516 }
517 
518 /*
519  * Called from timeout() when handling maintenance releases
520  */
521 void
522 rdrestart(arg)
523 	void *arg;
524 {
525 	int s = splbio();
526 	rdustart((int)arg);
527 	splx(s);
528 }
529 
530 rdustart(unit)
531 	register int unit;
532 {
533 	register struct buf *bp;
534 	register struct rd_softc *rs = &rd_softc[unit];
535 
536 	bp = rdtab[unit].b_actf;
537 	rs->sc_addr = bp->b_un.b_addr;
538 	rs->sc_resid = bp->b_bcount;
539 	if (hpibreq(&rs->sc_dq))
540 		rdstart(unit);
541 }
542 
543 struct buf *
544 rdfinish(unit, rs, bp)
545 	int unit;
546 	register struct rd_softc *rs;
547 	register struct buf *bp;
548 {
549 	register struct buf *dp = &rdtab[unit];
550 
551 	dp->b_errcnt = 0;
552 	dp->b_actf = bp->b_actf;
553 	bp->b_resid = 0;
554 	biodone(bp);
555 	hpibfree(&rs->sc_dq);
556 	if (dp->b_actf)
557 		return(dp->b_actf);
558 	dp->b_active = 0;
559 	if (rs->sc_flags & RDF_WANTED) {
560 		rs->sc_flags &= ~RDF_WANTED;
561 		wakeup((caddr_t)dp);
562 	}
563 	return(NULL);
564 }
565 
566 rdstart(unit)
567 	register int unit;
568 {
569 	register struct rd_softc *rs = &rd_softc[unit];
570 	register struct buf *bp = rdtab[unit].b_actf;
571 	register struct hp_device *hp = rs->sc_hd;
572 	register int part;
573 
574 again:
575 #ifdef DEBUG
576 	if (rddebug & RDB_FOLLOW)
577 		printf("rdstart(%d): bp %x, %c\n", unit, bp,
578 		       (bp->b_flags & B_READ) ? 'R' : 'W');
579 #endif
580 	part = rdpart(bp->b_dev);
581 	rs->sc_flags |= RDF_SEEK;
582 	rs->sc_ioc.c_unit = C_SUNIT(rs->sc_punit);
583 	rs->sc_ioc.c_volume = C_SVOL(0);
584 	rs->sc_ioc.c_saddr = C_SADDR;
585 	rs->sc_ioc.c_hiaddr = 0;
586 	rs->sc_ioc.c_addr = RDBTOS(bp->b_cylin);
587 	rs->sc_ioc.c_nop2 = C_NOP;
588 	rs->sc_ioc.c_slen = C_SLEN;
589 	rs->sc_ioc.c_len = rs->sc_resid;
590 	rs->sc_ioc.c_cmd = bp->b_flags & B_READ ? C_READ : C_WRITE;
591 #ifdef DEBUG
592 	if (rddebug & RDB_IO)
593 		printf("rdstart: hpibsend(%x, %x, %x, %x, %x)\n",
594 		       hp->hp_ctlr, hp->hp_slave, C_CMD,
595 		       &rs->sc_ioc.c_unit, sizeof(rs->sc_ioc)-2);
596 #endif
597 	if (hpibsend(hp->hp_ctlr, hp->hp_slave, C_CMD, &rs->sc_ioc.c_unit,
598 		     sizeof(rs->sc_ioc)-2) == sizeof(rs->sc_ioc)-2) {
599 		if (hp->hp_dk >= 0) {
600 			dk_busy |= 1 << hp->hp_dk;
601 			dk_seek[hp->hp_dk]++;
602 		}
603 #ifdef DEBUG
604 		if (rddebug & RDB_IO)
605 			printf("rdstart: hpibawait(%x)\n", hp->hp_ctlr);
606 #endif
607 		hpibawait(hp->hp_ctlr);
608 		return;
609 	}
610 	/*
611 	 * Experience has shown that the hpibwait in this hpibsend will
612 	 * occasionally timeout.  It appears to occur mostly on old 7914
613 	 * drives with full maintenance tracks.  We should probably
614 	 * integrate this with the backoff code in rderror.
615 	 */
616 #ifdef DEBUG
617 	if (rddebug & RDB_ERROR)
618 		printf("rd%d: rdstart: cmd %x adr %d blk %d len %d ecnt %d\n",
619 		       unit, rs->sc_ioc.c_cmd, rs->sc_ioc.c_addr,
620 		       bp->b_blkno, rs->sc_resid, rdtab[unit].b_errcnt);
621 	rdstats[unit].rdretries++;
622 #endif
623 	rs->sc_flags &= ~RDF_SEEK;
624 	rdreset(rs, hp);
625 	if (rdtab[unit].b_errcnt++ < RDRETRY)
626 		goto again;
627 	printf("rd%d: rdstart err: cmd 0x%x sect %d blk %d len %d\n",
628 	       unit, rs->sc_ioc.c_cmd, rs->sc_ioc.c_addr,
629 	       bp->b_blkno, rs->sc_resid);
630 	bp->b_flags |= B_ERROR;
631 	bp->b_error = EIO;
632 	bp = rdfinish(unit, rs, bp);
633 	if (bp) {
634 		rs->sc_addr = bp->b_un.b_addr;
635 		rs->sc_resid = bp->b_bcount;
636 		if (hpibreq(&rs->sc_dq))
637 			goto again;
638 	}
639 }
640 
641 rdgo(unit)
642 	register int unit;
643 {
644 	register struct rd_softc *rs = &rd_softc[unit];
645 	register struct hp_device *hp = rs->sc_hd;
646 	struct buf *bp = rdtab[unit].b_actf;
647 
648 	if (hp->hp_dk >= 0) {
649 		dk_busy |= 1 << hp->hp_dk;
650 		dk_xfer[hp->hp_dk]++;
651 		dk_wds[hp->hp_dk] += rs->sc_resid >> 6;
652 	}
653 #ifdef USELEDS
654 	if (inledcontrol == 0)
655 		ledcontrol(0, 0, LED_DISK);
656 #endif
657 	hpibgo(hp->hp_ctlr, hp->hp_slave, C_EXEC,
658 	       rs->sc_addr, rs->sc_resid, bp->b_flags & B_READ);
659 }
660 
661 rdintr(unit)
662 	register int unit;
663 {
664 	register struct rd_softc *rs = &rd_softc[unit];
665 	register struct buf *bp = rdtab[unit].b_actf;
666 	register struct hp_device *hp = rs->sc_hd;
667 	u_char stat = 13;	/* in case hpibrecv fails */
668 	int rv, restart;
669 
670 #ifdef DEBUG
671 	if (rddebug & RDB_FOLLOW)
672 		printf("rdintr(%d): bp %x, %c, flags %x\n", unit, bp,
673 		       (bp->b_flags & B_READ) ? 'R' : 'W', rs->sc_flags);
674 	if (bp == NULL) {
675 		printf("rd%d: bp == NULL\n", unit);
676 		return;
677 	}
678 #endif
679 	if (hp->hp_dk >= 0)
680 		dk_busy &= ~(1 << hp->hp_dk);
681 	if (rs->sc_flags & RDF_SEEK) {
682 		rs->sc_flags &= ~RDF_SEEK;
683 		if (hpibustart(hp->hp_ctlr))
684 			rdgo(unit);
685 		return;
686 	}
687 	if ((rs->sc_flags & RDF_SWAIT) == 0) {
688 #ifdef DEBUG
689 		rdstats[unit].rdpolltries++;
690 #endif
691 		if (hpibpptest(hp->hp_ctlr, hp->hp_slave) == 0) {
692 #ifdef DEBUG
693 			rdstats[unit].rdpollwaits++;
694 #endif
695 			if (hp->hp_dk >= 0)
696 				dk_busy |= 1 << hp->hp_dk;
697 			rs->sc_flags |= RDF_SWAIT;
698 			hpibawait(hp->hp_ctlr);
699 			return;
700 		}
701 	} else
702 		rs->sc_flags &= ~RDF_SWAIT;
703 	rv = hpibrecv(hp->hp_ctlr, hp->hp_slave, C_QSTAT, &stat, 1);
704 	if (rv != 1 || stat) {
705 #ifdef DEBUG
706 		if (rddebug & RDB_ERROR)
707 			printf("rdintr: recv failed or bad stat %d\n", stat);
708 #endif
709 		restart = rderror(unit);
710 #ifdef DEBUG
711 		rdstats[unit].rdretries++;
712 #endif
713 		if (rdtab[unit].b_errcnt++ < RDRETRY) {
714 			if (restart)
715 				rdstart(unit);
716 			return;
717 		}
718 		bp->b_flags |= B_ERROR;
719 		bp->b_error = EIO;
720 	}
721 	if (rdfinish(unit, rs, bp))
722 		rdustart(unit);
723 }
724 
725 rdstatus(rs)
726 	register struct rd_softc *rs;
727 {
728 	register int c, s;
729 	u_char stat;
730 	int rv;
731 
732 	c = rs->sc_hd->hp_ctlr;
733 	s = rs->sc_hd->hp_slave;
734 	rs->sc_rsc.c_unit = C_SUNIT(rs->sc_punit);
735 	rs->sc_rsc.c_sram = C_SRAM;
736 	rs->sc_rsc.c_ram = C_RAM;
737 	rs->sc_rsc.c_cmd = C_STATUS;
738 	bzero((caddr_t)&rs->sc_stat, sizeof(rs->sc_stat));
739 	rv = hpibsend(c, s, C_CMD, &rs->sc_rsc, sizeof(rs->sc_rsc));
740 	if (rv != sizeof(rs->sc_rsc)) {
741 #ifdef DEBUG
742 		if (rddebug & RDB_STATUS)
743 			printf("rdstatus: send C_CMD failed %d != %d\n",
744 			       rv, sizeof(rs->sc_rsc));
745 #endif
746 		return(1);
747 	}
748 	rv = hpibrecv(c, s, C_EXEC, &rs->sc_stat, sizeof(rs->sc_stat));
749 	if (rv != sizeof(rs->sc_stat)) {
750 #ifdef DEBUG
751 		if (rddebug & RDB_STATUS)
752 			printf("rdstatus: send C_EXEC failed %d != %d\n",
753 			       rv, sizeof(rs->sc_stat));
754 #endif
755 		return(1);
756 	}
757 	rv = hpibrecv(c, s, C_QSTAT, &stat, 1);
758 	if (rv != 1 || stat) {
759 #ifdef DEBUG
760 		if (rddebug & RDB_STATUS)
761 			printf("rdstatus: recv failed %d or bad stat %d\n",
762 			       rv, stat);
763 #endif
764 		return(1);
765 	}
766 	return(0);
767 }
768 
769 /*
770  * Deal with errors.
771  * Returns 1 if request should be restarted,
772  * 0 if we should just quietly give up.
773  */
774 rderror(unit)
775 	int unit;
776 {
777 	struct rd_softc *rs = &rd_softc[unit];
778 	register struct rd_stat *sp;
779 	struct buf *bp;
780 	daddr_t hwbn, pbn;
781 
782 	if (rdstatus(rs)) {
783 #ifdef DEBUG
784 		printf("rd%d: couldn't get status\n", unit);
785 #endif
786 		rdreset(rs, rs->sc_hd);
787 		return(1);
788 	}
789 	sp = &rs->sc_stat;
790 	if (sp->c_fef & FEF_REXMT)
791 		return(1);
792 	if (sp->c_fef & FEF_PF) {
793 		rdreset(rs, rs->sc_hd);
794 		return(1);
795 	}
796 	/*
797 	 * Unit requests release for internal maintenance.
798 	 * We just delay awhile and try again later.  Use expontially
799 	 * increasing backoff ala ethernet drivers since we don't really
800 	 * know how long the maintenance will take.  With RDWAITC and
801 	 * RDRETRY as defined, the range is 1 to 32 seconds.
802 	 */
803 	if (sp->c_fef & FEF_IMR) {
804 		extern int hz;
805 		int rdtimo = RDWAITC << rdtab[unit].b_errcnt;
806 #ifdef DEBUG
807 		printf("rd%d: internal maintenance, %d second timeout\n",
808 		       unit, rdtimo);
809 		rdstats[unit].rdtimeouts++;
810 #endif
811 		hpibfree(&rs->sc_dq);
812 		timeout(rdrestart, (void *)unit, rdtimo * hz);
813 		return(0);
814 	}
815 	/*
816 	 * Only report error if we have reached the error reporting
817 	 * threshhold.  By default, this will only report after the
818 	 * retry limit has been exceeded.
819 	 */
820 	if (rdtab[unit].b_errcnt < rderrthresh)
821 		return(1);
822 
823 	/*
824 	 * First conjure up the block number at which the error occured.
825 	 * Note that not all errors report a block number, in that case
826 	 * we just use b_blkno.
827  	 */
828 	bp = rdtab[unit].b_actf;
829 	pbn = rs->sc_info.ri_label.d_partitions[rdpart(bp->b_dev)].p_offset;
830 	if ((sp->c_fef & FEF_CU) || (sp->c_fef & FEF_DR) ||
831 	    (sp->c_ief & IEF_RRMASK)) {
832 		hwbn = RDBTOS(pbn + bp->b_blkno);
833 		pbn = bp->b_blkno;
834 	} else {
835 		hwbn = sp->c_blk;
836 		pbn = RDSTOB(hwbn) - pbn;
837 	}
838 	/*
839 	 * Now output a generic message suitable for badsect.
840 	 * Note that we don't use harderr cuz it just prints
841 	 * out b_blkno which is just the beginning block number
842 	 * of the transfer, not necessary where the error occured.
843 	 */
844 	printf("rd%d%c: hard error sn%d\n",
845 	       rdunit(bp->b_dev), 'a'+rdpart(bp->b_dev), pbn);
846 	/*
847 	 * Now report the status as returned by the hardware with
848 	 * attempt at interpretation (unless debugging).
849 	 */
850 	printf("rd%d %s error:",
851 	       unit, (bp->b_flags & B_READ) ? "read" : "write");
852 #ifdef DEBUG
853 	if (rddebug & RDB_ERROR) {
854 		/* status info */
855 		printf("\n    volume: %d, unit: %d\n",
856 		       (sp->c_vu>>4)&0xF, sp->c_vu&0xF);
857 		rdprinterr("reject", sp->c_ref, err_reject);
858 		rdprinterr("fault", sp->c_fef, err_fault);
859 		rdprinterr("access", sp->c_aef, err_access);
860 		rdprinterr("info", sp->c_ief, err_info);
861 		printf("    block: %d, P1-P10: ", hwbn);
862 		printf("%s", hexstr(*(u_int *)&sp->c_raw[0], 8));
863 		printf("%s", hexstr(*(u_int *)&sp->c_raw[4], 8));
864 		printf("%s\n", hexstr(*(u_short *)&sp->c_raw[8], 4));
865 		/* command */
866 		printf("    ioc: ");
867 		printf("%s", hexstr(*(u_int *)&rs->sc_ioc.c_pad, 8));
868 		printf("%s", hexstr(*(u_short *)&rs->sc_ioc.c_hiaddr, 4));
869 		printf("%s", hexstr(*(u_int *)&rs->sc_ioc.c_addr, 8));
870 		printf("%s", hexstr(*(u_short *)&rs->sc_ioc.c_nop2, 4));
871 		printf("%s", hexstr(*(u_int *)&rs->sc_ioc.c_len, 8));
872 		printf("%s\n", hexstr(*(u_short *)&rs->sc_ioc.c_cmd, 4));
873 		return(1);
874 	}
875 #endif
876 	printf(" v%d u%d, R0x%x F0x%x A0x%x I0x%x\n",
877 	       (sp->c_vu>>4)&0xF, sp->c_vu&0xF,
878 	       sp->c_ref, sp->c_fef, sp->c_aef, sp->c_ief);
879 	printf("P1-P10: ");
880 	printf("%s", hexstr(*(u_int *)&sp->c_raw[0], 8));
881 	printf("%s", hexstr(*(u_int *)&sp->c_raw[4], 8));
882 	printf("%s\n", hexstr(*(u_short *)&sp->c_raw[8], 4));
883 	return(1);
884 }
885 
886 int
887 rdread(dev, uio, flags)
888 	dev_t dev;
889 	struct uio *uio;
890 	int flags;
891 {
892 
893 	return (physio(rdstrategy, NULL, dev, B_READ, minphys, uio));
894 }
895 
896 int
897 rdwrite(dev, uio, flags)
898 	dev_t dev;
899 	struct uio *uio;
900 	int flags;
901 {
902 
903 	return (physio(rdstrategy, NULL, dev, B_WRITE, minphys, uio));
904 }
905 
906 int
907 rdioctl(dev, cmd, data, flag, p)
908 	dev_t dev;
909 	u_long cmd;
910 	caddr_t data;
911 	int flag;
912 	struct proc *p;
913 {
914 	int unit = rdunit(dev);
915 	register struct rd_softc *sc = &rd_softc[unit];
916 	register struct disklabel *lp = &sc->sc_info.ri_label;
917 	int error, flags;
918 
919 	switch (cmd) {
920 	case DIOCGDINFO:
921 		*(struct disklabel *)data = *lp;
922 		return (0);
923 
924 	case DIOCGPART:
925 		((struct partinfo *)data)->disklab = lp;
926 		((struct partinfo *)data)->part =
927 			&lp->d_partitions[rdpart(dev)];
928 		return (0);
929 
930         case DIOCWLABEL:
931                 if ((flag & FWRITE) == 0)
932                         return (EBADF);
933 		if (*(int *)data)
934 			sc->sc_flags |= RDF_WLABEL;
935 		else
936 			sc->sc_flags &= ~RDF_WLABEL;
937 		return (0);
938 
939         case DIOCSDINFO:
940                 if ((flag & FWRITE) == 0)
941                         return (EBADF);
942 		return (setdisklabel(lp, (struct disklabel *)data,
943 				     (sc->sc_flags & RDF_WLABEL) ? 0
944 				     : sc->sc_info.ri_open));
945 
946         case DIOCWDINFO:
947 		if ((flag & FWRITE) == 0)
948 			return (EBADF);
949 		error = setdisklabel(lp, (struct disklabel *)data,
950 				     (sc->sc_flags & RDF_WLABEL) ? 0
951 				     : sc->sc_info.ri_open);
952 		if (error)
953 			return (error);
954 		flags = sc->sc_flags;
955 		sc->sc_flags = RDF_ALIVE | RDF_WLABEL;
956 		error = writedisklabel(rdlabdev(dev), rdstrategy, lp);
957 		sc->sc_flags = flags;
958 		return (error);
959 	}
960 	return(EINVAL);
961 }
962 
963 int
964 rdsize(dev)
965 	dev_t dev;
966 {
967 	register int unit = rdunit(dev);
968 	register struct rd_softc *rs = &rd_softc[unit];
969 	int psize, didopen = 0;
970 
971 	if (unit >= NRD || (rs->sc_flags & RDF_ALIVE) == 0)
972 		return(-1);
973 
974 	/*
975 	 * We get called very early on (via swapconf)
976 	 * without the device being open so we may need
977 	 * to handle it here.
978 	 */
979 	if (rs->sc_info.ri_open == 0) {
980 		if (rdopen(dev, FREAD|FWRITE, S_IFBLK, NULL))
981 			return(-1);
982 		didopen = 1;
983 	}
984 	psize = rs->sc_info.ri_label.d_partitions[rdpart(dev)].p_size;
985 	if (didopen)
986 		(void) rdclose(dev, FREAD|FWRITE, S_IFBLK, NULL);
987 	return (psize);
988 }
989 
990 #ifdef DEBUG
991 rdprinterr(str, err, tab)
992 	char *str;
993 	short err;
994 	char *tab[];
995 {
996 	register int i;
997 	int printed;
998 
999 	if (err == 0)
1000 		return;
1001 	printf("    %s error field:", str, err);
1002 	printed = 0;
1003 	for (i = 0; i < 16; i++)
1004 		if (err & (0x8000 >> i))
1005 			printf("%s%s", printed++ ? " + " : " ", tab[i]);
1006 	printf("\n");
1007 }
1008 #endif
1009 
1010 /*
1011  * Non-interrupt driven, non-dma dump routine.
1012  */
1013 int
1014 rddump(dev)
1015 	dev_t dev;
1016 {
1017 	int part = rdpart(dev);
1018 	int unit = rdunit(dev);
1019 	register struct rd_softc *rs = &rd_softc[unit];
1020 	register struct hp_device *hp = rs->sc_hd;
1021 	register struct partition *pinfo;
1022 	register daddr_t baddr;
1023 	register int maddr, pages, i;
1024 	char stat;
1025 	extern int lowram, dumpsize;
1026 #ifdef DEBUG
1027 	extern int pmapdebug;
1028 	pmapdebug = 0;
1029 #endif
1030 
1031 	/* is drive ok? */
1032 	if (unit >= NRD || (rs->sc_flags & RDF_ALIVE) == 0)
1033 		return (ENXIO);
1034 	pinfo = &rs->sc_info.ri_label.d_partitions[part];
1035 	/* dump parameters in range? */
1036 	if (dumplo < 0 || dumplo >= pinfo->p_size ||
1037 	    pinfo->p_fstype != FS_SWAP)
1038 		return (EINVAL);
1039 	pages = dumpsize;
1040 	if (dumplo + ctod(pages) > pinfo->p_size)
1041 		pages = dtoc(pinfo->p_size - dumplo);
1042 	maddr = lowram;
1043 	baddr = dumplo + pinfo->p_offset;
1044 	/* HPIB idle? */
1045 	if (!hpibreq(&rs->sc_dq)) {
1046 		hpibreset(hp->hp_ctlr);
1047 		rdreset(rs, rs->sc_hd);
1048 		printf("[ drive %d reset ] ", unit);
1049 	}
1050 	for (i = 0; i < pages; i++) {
1051 #define NPGMB	(1024*1024/NBPG)
1052 		/* print out how many Mbs we have dumped */
1053 		if (i && (i % NPGMB) == 0)
1054 			printf("%d ", i / NPGMB);
1055 #undef NPBMG
1056 		rs->sc_ioc.c_unit = C_SUNIT(rs->sc_punit);
1057 		rs->sc_ioc.c_volume = C_SVOL(0);
1058 		rs->sc_ioc.c_saddr = C_SADDR;
1059 		rs->sc_ioc.c_hiaddr = 0;
1060 		rs->sc_ioc.c_addr = RDBTOS(baddr);
1061 		rs->sc_ioc.c_nop2 = C_NOP;
1062 		rs->sc_ioc.c_slen = C_SLEN;
1063 		rs->sc_ioc.c_len = NBPG;
1064 		rs->sc_ioc.c_cmd = C_WRITE;
1065 		hpibsend(hp->hp_ctlr, hp->hp_slave, C_CMD,
1066 			 &rs->sc_ioc.c_unit, sizeof(rs->sc_ioc)-2);
1067 		if (hpibswait(hp->hp_ctlr, hp->hp_slave))
1068 			return (EIO);
1069 		pmap_enter(kernel_pmap, (vm_offset_t)vmmap, maddr,
1070 		    VM_PROT_READ, TRUE);
1071 		hpibsend(hp->hp_ctlr, hp->hp_slave, C_EXEC, vmmap, NBPG);
1072 		(void) hpibswait(hp->hp_ctlr, hp->hp_slave);
1073 		hpibrecv(hp->hp_ctlr, hp->hp_slave, C_QSTAT, &stat, 1);
1074 		if (stat)
1075 			return (EIO);
1076 		maddr += NBPG;
1077 		baddr += ctod(1);
1078 	}
1079 	return (0);
1080 }
1081 #endif
1082