xref: /original-bsd/sys/vax/vax/mscp.c (revision 60c09706)
1 /*
2  * Copyright (c) 1988 Regents of the University of California.
3  * All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Chris Torek.
7  *
8  * %sccs.include.redist.c%
9  *
10  *	@(#)mscp.c	7.5 (Berkeley) 12/16/90
11  */
12 
13 /*
14  * MSCP generic driver routines
15  */
16 
17 #include "sys/param.h"
18 #include "sys/buf.h"
19 #include "sys/errno.h"
20 #include "sys/dkstat.h"
21 #include "sys/ioctl.h"
22 #include "sys/disklabel.h"
23 #include "sys/syslog.h"
24 
25 #include "../uba/ubavar.h"
26 
27 #include "mscp.h"
28 #include "mscpvar.h"
29 
30 #define	PCMD	PSWP		/* priority for command packet waits */
31 
32 /*
33  * During transfers, mapping info is saved in the buffer's b_resid.
34  */
35 #define	b_info b_resid
36 
37 /*
38  * Get a command packet.  Second argument is true iff we are
39  * to wait if necessary.  Return NULL if none are available and
40  * we cannot wait.
41  */
42 struct mscp *
mscp_getcp(mi,canwait)43 mscp_getcp(mi, canwait)
44 	register struct mscp_info *mi;
45 	int canwait;
46 {
47 #define	mri	(&mi->mi_cmd)
48 	register struct mscp *mp;
49 	register int i;
50 	int s = spl5();
51 
52 again:
53 	/*
54 	 * Ensure that we have some command credits, and
55 	 * that the next command packet is free.
56 	 */
57 	if (mi->mi_credits <= MSCP_MINCREDITS) {
58 		if (!canwait) {
59 			splx(s);
60 			return (NULL);
61 		}
62 		mi->mi_wantcredits = 1;
63 		sleep((caddr_t) &mi->mi_wantcredits, PCMD);
64 		goto again;
65 	}
66 	i = mri->mri_next;
67 	if (mri->mri_desc[i] & MSCP_OWN) {
68 		if (!canwait) {
69 			splx(s);
70 			return (NULL);
71 		}
72 		mi->mi_wantcmd = 1;
73 		sleep((caddr_t) &mi->mi_wantcmd, PCMD);
74 		goto again;
75 	}
76 	mi->mi_credits--;
77 	mri->mri_desc[i] &= ~MSCP_INT;
78 	mri->mri_next = (mri->mri_next + 1) % mri->mri_size;
79 	splx(s);
80 	mp = &mri->mri_ring[i];
81 
82 	/*
83 	 * Initialise some often-zero fields.
84 	 * ARE THE LAST TWO NECESSARY IN GENERAL?  IT SURE WOULD BE
85 	 * NICE IF DEC SOLD DOCUMENTATION FOR THEIR OWN CONTROLLERS.
86 	 */
87 	mp->mscp_msglen = MSCP_MSGLEN;
88 	mp->mscp_flags = 0;
89 	mp->mscp_modifier = 0;
90 	mp->mscp_seq.seq_bytecount = 0;
91 	mp->mscp_seq.seq_buffer = 0;
92 	mp->mscp_seq.seq_mapbase = 0;
93 /*???*/	mp->mscp_sccc.sccc_errlgfl = 0;
94 /*???*/	mp->mscp_sccc.sccc_copyspd = 0;
95 	return (mp);
96 #undef	mri
97 }
98 
99 #ifdef AVOID_EMULEX_BUG
100 int	mscp_aeb_xor = 0x8000bb80;
101 #endif
102 
103 /*
104  * Do a device go.  The driver calls this once it has allocated
105  * resources for the transfer.  Save the resource information in
106  * bp->b_ubinfo, and finish the MSCP packet.
107  *
108  * N.B.: If we were blocked for some time, the drive could have gone
109  * off line and might still be that way.  We should probably handle
110  * such a case by changing this command into an on line request and
111  * not dequeuing the transfer after all.
112  */
mscp_go(mi,mp,info)113 mscp_go(mi, mp, info)
114 	register struct mscp_info *mi;
115 	register struct mscp *mp;
116 	int info;
117 {
118 	register struct buf *bp, *dp;
119 
120 	/*
121 	 * Now is also the time to move the transfer off the
122 	 * controller and drive queues, and shuffle the drive
123 	 * queue on the controller queue.  The idea is to try
124 	 * to keep as many drives busy as possible---to deal
125 	 * the controller's credits out to the drives in a `fair
126 	 * share' arrangement.  (To do this fully would be more
127 	 * trouble than it is worth, though.)
128 	 */
129 	dp = mi->mi_tab->b_actf;
130 	bp = dp->b_actf;
131 	dp->b_actf = bp->av_forw;	/* transfer off drive queue */
132 	mi->mi_tab->b_actf = dp->b_forw;/* drive off ctlr queue */
133 	APPEND(dp, mi->mi_tab, b_forw);	/* then back again */
134 
135 	/*
136 	 * Move the buffer to the I/O wait queue.
137 	 */
138 	bp->av_back = mi->mi_wtab.av_back;
139 	bp->av_forw = &mi->mi_wtab;
140 	mi->mi_wtab.av_back->av_forw = bp;
141 	mi->mi_wtab.av_back = bp;
142 
143 	/*
144 	 * Save the mapping info, finish the command packet, and give
145 	 * it to the device.  The device's dgo routine should then
146 	 * initiate polling.
147 	 */
148 	bp->b_info = info;
149 #ifdef AVOID_EMULEX_BUG
150 	/*
151 	 * The Emulex SC41/MS will occasionally zero the lower half word
152 	 * of the command reference number.  The upper half word remains
153 	 * intact.  To keep running, we convert the buffer address into
154 	 * a small but nonzero integer that is unique over all pending
155 	 * transfers, and store that value in the upper half word.  To
156 	 * catch occurrances of the bug (so that we can gripe to Emulex),
157 	 * we also put a nonzero value in the lower word.
158 	 */
159 	{
160 		register u_int i = mi->mi_nextbp;
161 
162 		do {		/* find a free value */
163 			if (mi->mi_bp[i] == 0)
164 				goto found;
165 			i = (i + 1) % AEB_MAX_BP;
166 		} while (i != mi->mi_nextbp);
167 		panic("mscp_go: AEB_MAX_BP too small");
168 found:
169 		mi->mi_bp[i++] = bp;
170 		mi->mi_nextbp = i % AEB_MAX_BP;
171 		mp->mscp_cmdref = (i << 16) ^ mscp_aeb_xor;
172 	}
173 #else
174 	mp->mscp_cmdref = (long) bp;
175 #endif
176 	*mp->mscp_addr |= MSCP_OWN | MSCP_INT;
177 }
178 
179 /*
180  * Handle a response ring transition.
181  */
mscp_dorsp(mi)182 mscp_dorsp(mi)
183 	register struct mscp_info *mi;
184 {
185 	register struct uba_device *ui;
186 	register struct buf *bp;
187 	register struct mscp *mp;
188 	register int nextrsp;
189 	struct mscp_driver *md = mi->mi_md;
190 	char *ctlrname, *drivename;
191 	int st, error, info;
192 
193 	ctlrname = md->md_mname;
194 	drivename = md->md_dname;
195 	nextrsp = mi->mi_rsp.mri_next;
196 loop:
197 	if (mi->mi_rsp.mri_desc[nextrsp] & MSCP_OWN) {
198 		/*
199 		 * No more responses.  Remember the next expected
200 		 * response index.  Check to see if we have some
201 		 * credits back, and wake up sleepers if so.
202 		 */
203 		mi->mi_rsp.mri_next = nextrsp;
204 		if (mi->mi_wantcredits && mi->mi_credits > MSCP_MINCREDITS) {
205 			mi->mi_wantcredits = 0;
206 			wakeup((caddr_t) &mi->mi_wantcredits);
207 		}
208 		return;
209 	}
210 
211 	/*
212 	 * Found a response.  Update credit information.  If there is
213 	 * nothing else to do, jump to `done' to get the next response.
214 	 */
215 	mp = &mi->mi_rsp.mri_ring[nextrsp];
216 	mi->mi_credits += MSCP_CREDITS(mp->mscp_msgtc);
217 	switch (MSCP_MSGTYPE(mp->mscp_msgtc)) {
218 
219 	case MSCPT_SEQ:
220 		break;
221 
222 	case MSCPT_DATAGRAM:
223 		(*md->md_dgram)(mi, mp);
224 		goto done;
225 
226 	case MSCPT_CREDITS:
227 		goto done;
228 
229 	case MSCPT_MAINTENANCE:
230 	default:
231 		printf("%s%d: unit %d: unknown message type 0x%x ignored\n",
232 			ctlrname, mi->mi_ctlr, mp->mscp_unit,
233 			MSCP_MSGTYPE(mp->mscp_msgtc));
234 		goto done;
235 	}
236 
237 	/*
238 	 * Controllers are allowed to interrupt as any drive, so we
239 	 * must check the command before checking for a drive.
240 	 */
241 	if (mp->mscp_opcode == (M_OP_SETCTLRC | M_OP_END)) {
242 		(*md->md_ctlrdone)(mi, mp);
243 		goto done;
244 	}
245 
246 	/*
247 	 * Find the drive info.  If there is none, and this is an
248 	 * available attention response, try configuring a new drive.
249 	 */
250 	if (mp->mscp_unit > md->md_ndpc) {
251 		printf("%s%d: unit %d out of range\n",
252 			ctlrname, mi->mi_ctlr, mp->mscp_unit);
253 		goto done;
254 	}
255 	if ((ui = mi->mi_ip[mp->mscp_unit]) == NULL) {
256 		if ((*md->md_unconf)(mi, mp) != MSCP_DONE) {
257 			printf("%s%d: unit %d not configured, ",
258 				ctlrname, mi->mi_ctlr, mp->mscp_unit);
259 			if (mp->mscp_opcode == M_OP_AVAILATTN)
260 				printf("available attn");
261 			else
262 				printf("stray response op 0x%x status 0x%x",
263 					mp->mscp_opcode, mp->mscp_status);
264 			printf(" ignored\n");
265 		}
266 		goto done;
267 	}
268 
269 	/*
270 	 * Handle individual responses.
271 	 */
272 	st = mp->mscp_status & M_ST_MASK;
273 	error = 0;
274 	switch (mp->mscp_opcode) {
275 
276 	case M_OP_END:
277 		/*
278 		 * The controller presents a bogus END packet when
279 		 * a read/write command is given with an illegal
280 		 * block number.  This is contrary to the MSCP
281 		 * specification (ENDs are to be given only for
282 		 * invalid commands), but that is the way of it.
283 		 */
284 		if (st == M_ST_INVALCMD && mp->mscp_cmdref != 0) {
285 			printf("%s%d: bad lbn (%d)?\n", drivename,
286 				ui->ui_unit, mp->mscp_seq.seq_lbn);
287 			error = EIO;
288 			goto rwend;
289 		}
290 		goto unknown;
291 
292 	case M_OP_ONLINE | M_OP_END:
293 		/*
294 		 * Finished an ON LINE request.  Call the driver to
295 		 * find out whether it succeeded.  If so, mark it on
296 		 * line.
297 		 */
298 		if (ui->ui_flags & UNIT_ONLINE) {
299 			printf("%s%d: duplicate ONLINE ignored\n",
300 				drivename, ui->ui_unit);
301 			break;
302 		}
303 		if ((*md->md_online)(ui, mp) == MSCP_DONE)
304 			ui->ui_flags |= UNIT_ONLINE;
305 		break;
306 
307 	case M_OP_GETUNITST | M_OP_END:
308 		/*
309 		 * Got unit status.  Call the driver to find out
310 		 * whether it succeeded, and if so, mark it.
311 		 */
312 		if ((*md->md_gotstatus)(ui, mp) == MSCP_DONE)
313 			ui->ui_flags |= UNIT_HAVESTATUS;
314 		break;
315 
316 	case M_OP_AVAILATTN:
317 		/*
318 		 * The drive went offline and we did not notice.
319 		 * Mark it off line now, to force an on line request
320 		 * next, so we can make sure it is still the same
321 		 * drive.
322 		 *
323 		 * IF THE UDA DRIVER HAS A COMMAND AWAITING UNIBUS
324 		 * RESOURCES, THAT COMMAND MAY GO OUT BEFORE THE ON
325 		 * LINE.  IS IT WORTH FIXING??
326 		 */
327 		ui->ui_flags &= ~(UNIT_ONLINE | UNIT_HAVESTATUS);
328 #ifdef notyet
329 		(*md->md_offline)(ui, mp);
330 #endif
331 		break;
332 
333 	case M_OP_READ | M_OP_END:
334 	case M_OP_WRITE | M_OP_END:
335 		/*
336 		 * A transfer finished.  Get the buffer, and release its
337 		 * map registers via ubadone().  If the command finished
338 		 * with an off line or available status, the drive went
339 		 * off line (the idiot controller does not tell us until
340 		 * it comes back *on* line, or until we try to use it).
341 		 */
342 		if (mp->mscp_cmdref == 0) {
343 			/*
344 			 * No buffer means there is a bug somewhere!
345 			 */
346 			printf("%s%d: io done, but no buffer?\n",
347 				drivename, ui->ui_unit);
348 			mscp_hexdump(mp);
349 			break;
350 		}
351 
352 rwend:
353 #ifdef AVOID_EMULEX_BUG
354 		{
355 			register u_short *p = (u_short *) &mp->mscp_cmdref;
356 
357 			/*
358 			 * Note any errors on the part of the controller.
359 			 * The lower word should be zero after exclusive
360 			 * or'ing with mscp_aeb_xor, and the upper should
361 			 * then be in the range [1..AEB_MAX_BP].
362 			 */
363 			mp->mscp_cmdref ^= mscp_aeb_xor;
364 			p[1]--;
365 			if (p[1] >= AEB_MAX_BP)
366 				panic("unrecoverable Emulex screwup");
367 			if (p[0] == 0)
368 				mi->mi_ok++;
369 			else {
370 				/*
371 				 * Calculate the expected response,
372 				 * assuming p[1] is correct.  The
373 				 * actual response is then the expected
374 				 * response xor p[0].
375 				 */
376 				int sb = ((p[1] + 1) << 16) ^ mscp_aeb_xor;
377 
378 				log(LOG_WARNING, "\
379 Emulex SC41/MS screwup: %s%d, got %d correct, then changed 0x%x to 0x%x\n",
380 					ctlrname, mi->mi_ctlr,
381 					mi->mi_ok, sb, sb ^ p[0]);
382 				mi->mi_ok = 0;
383 			}
384 			/* convert index back to buffer, and mark free */
385 			bp = mi->mi_bp[p[1]];
386 			mi->mi_bp[p[1]] = 0;
387 		}
388 #else
389 		bp = (struct buf *) mp->mscp_cmdref;
390 #ifdef MSCP_PARANOIA
391 		{
392 			register struct buf *q = mi->mi_wtab.av_forw;
393 
394 			/*
395 			 * Ensure that this response corresponds to
396 			 * some outstanding request.  If not, ignore
397 			 * it entirely.  This will likely cause a
398 			 * Unibus reset soon, after which the controller
399 			 * just might behave.
400 			 */
401 			while (q != bp && q != &mi->mi_wtab)
402 				q = q->av_forw;
403 			if (q != bp) {
404 				printf("%s%d: bad response packet ignored\n",
405 					ctlrname, mi->mi_ctlr);
406 				mscp_hexdump(mp);
407 				goto out;
408 			}
409 		}
410 #endif MSCP_PARANOIA
411 #endif AVOID_EMULEX_BUG
412 
413 		/*
414 		 * Mark any error-due-to-bad-LBN (via `goto rwend').
415 		 * WHAT STATUS WILL THESE HAVE?  IT SURE WOULD BE NICE
416 		 * IF DEC SOLD DOCUMENTATION FOR THEIR OWN CONTROLLERS.
417 		 */
418 		if (error) {
419 			bp->b_flags |= B_ERROR;
420 			bp->b_error = error;
421 		}
422 		if (st == M_ST_OFFLINE || st == M_ST_AVAILABLE) {
423 			ui->ui_flags &= ~(UNIT_ONLINE | UNIT_HAVESTATUS);
424 #ifdef notyet
425 			(*md->md_offline)(ui, mp);
426 #endif
427 		}
428 
429 		/*
430 		 * Unlink the transfer from the wait queue mi_wtab.
431 		 * If there are no more transfers on the drive queue
432 		 * for this drive, and it is a profiled disk, turn
433 		 * off its busy bit.
434 		 */
435 		bp->av_back->av_forw = bp->av_forw;
436 		bp->av_forw->av_back = bp->av_back;
437 		if (ui->ui_dk >= 0 && md->md_utab[ui->ui_unit].b_forw == NULL)
438 			dk_busy &= ~(1 << ui->ui_dk);
439 
440 		/*
441 		 * If the transfer has something to do with bad
442 		 * block forwarding, let the driver handle the
443 		 * rest.
444 		 */
445 		if ((bp->b_flags & B_BAD) != 0 && md->md_bb != NULL) {
446 			(*md->md_bb)(ui, mp, bp);
447 			goto out;
448 		}
449 
450 		/*
451 		 * If the transfer failed, give the driver a crack
452 		 * at fixing things up.
453 		 */
454 		if (st != M_ST_SUCCESS) {
455 			switch ((*md->md_ioerr)(ui, mp, bp)) {
456 
457 			case MSCP_DONE:		/* fixed */
458 				break;
459 
460 			case MSCP_RESTARTED:	/* still working on it */
461 				goto out;
462 
463 			case MSCP_FAILED:	/* no luck */
464 				diskerr(bp, drivename, "hard error",
465 				    LOG_PRINTF, -1, md->md_lab ?
466 				    &md->md_lab[ui->ui_unit] : md->md_lab);
467 				mscp_printevent(mp);
468 				bp->b_flags |= B_ERROR;
469 				bp->b_error = EIO;
470 				break;
471 			}
472 		}
473 
474 		/*
475 		 * Set the residual count and mark the transfer as
476 		 * done.  If the I/O wait queue is now empty, release
477 		 * the shared BDP, if any.
478 		 */
479 		info = bp->b_info;	/* we are about to clobber it */
480 		bp->b_resid = bp->b_bcount - mp->mscp_seq.seq_bytecount;
481 		(*md->md_iodone)(mi, bp, info);
482 out:
483 		break;
484 
485 	case M_OP_REPLACE | M_OP_END:
486 		/*
487 		 * A replace operation finished.  Just let the driver
488 		 * handle it (if it does replaces).
489 		 */
490 		if (md->md_replace == NULL)
491 			printf("%s%d: bogus REPLACE end\n",
492 				drivename, ui->ui_unit);
493 		else
494 			(*md->md_replace)(ui, mp);
495 		break;
496 
497 	default:
498 		/*
499 		 * If it is not one of the above, we cannot handle it.
500 		 * (And we should not have received it, for that matter.)
501 		 */
502 unknown:
503 		printf("%s%d: unknown opcode 0x%x status 0x%x ignored\n",
504 			mi->mi_md->md_dname, ui->ui_unit,
505 			mp->mscp_opcode, mp->mscp_status);
506 		mscp_hexdump(mp);
507 		break;
508 	}
509 
510 	/*
511 	 * If the drive needs to be put back in the controller queue,
512 	 * do that now.  (`bp' below ought to be `dp', but they are all
513 	 * struct buf *.)  Note that b_active was cleared in the driver;
514 	 * we presume that there is something to be done, hence reassert it.
515 	 */
516 	if (ui->ui_flags & UNIT_REQUEUE) {
517 		bp = &md->md_utab[ui->ui_unit];
518 if (bp->b_active) panic("mscp_dorsp requeue");
519 		APPEND(bp, mi->mi_tab, b_forw);
520 		bp->b_active = 1;
521 		ui->ui_flags &= ~UNIT_REQUEUE;
522 	}
523 
524 done:
525 	/*
526 	 * Give back the response packet, and take a look at the next.
527 	 */
528 	mp->mscp_msglen = MSCP_MSGLEN;
529 	mi->mi_rsp.mri_desc[nextrsp] |= MSCP_OWN;
530 	nextrsp = (nextrsp + 1) % mi->mi_rsp.mri_size;
531 	goto loop;
532 }
533 
534 /*
535  * Dump the entire contents of an MSCP packet in hex.  Mainly useful
536  * for debugging....
537  */
mscp_hexdump(mp)538 mscp_hexdump(mp)
539 	register struct mscp *mp;
540 {
541 	register long *p = (long *) mp;
542 	register int i = mp->mscp_msglen;
543 
544 	if (i > 256)		/* sanity */
545 		i = 256;
546 	i /= sizeof (*p);	/* ASSUMES MULTIPLE OF sizeof(long) */
547 	while (--i >= 0)
548 		printf("0x%x ", *p++);
549 	printf("\n");
550 }
551 
552 /*
553  * Requeue outstanding transfers, e.g., after bus reset.
554  * Also requeue any drives that have on line or unit status
555  * info pending.
556  */
557 mscp_requeue(mi)
558 	struct mscp_info *mi;
559 {
560 	register struct uba_device *ui;
561 	register struct mscp_driver *md = mi->mi_md;
562 	register struct buf *bp, *dp;
563 	register int unit;
564 	struct buf *nextbp;
565 
566 	/*
567 	 * Clear the controller chain.  Mark everything un-busy; we
568 	 * will soon fix any that are in fact busy.
569 	 */
570 	mi->mi_tab->b_actf = NULL;
571 	mi->mi_tab->b_active = 0;
572 	for (unit = 0, dp = md->md_utab; unit < md->md_nunits; unit++, dp++) {
573 		ui = md->md_dinfo[unit];
574 		if (ui == NULL || !ui->ui_alive || ui->ui_ctlr != mi->mi_ctlr)
575 			continue;	/* not ours */
576 		dp->b_forw = NULL;
577 		dp->b_active = 0;
578 	}
579 
580 	/*
581 	 * Scan the wait queue, linking buffers onto drive queues.
582 	 * Note that these must be put at the front of the drive queue,
583 	 * lest we reorder I/O operations.
584 	 */
585 	for (bp = mi->mi_wtab.av_back; bp != &mi->mi_wtab; bp = nextbp) {
586 		nextbp = bp->av_back;
587 		dp = &md->md_utab[minor(bp->b_dev) >> md->md_unitshift];
588 		bp->av_forw = dp->b_actf;
589 		if (dp->b_actf == NULL)
590 			dp->b_actl = bp;
591 		dp->b_actf = bp;
592 	}
593 	mi->mi_wtab.av_forw = mi->mi_wtab.av_back = &mi->mi_wtab;
594 
595 	/*
596 	 * Scan for drives waiting for on line or status responses,
597 	 * and for drives with pending transfers.  Put these on the
598 	 * controller queue, and mark the controller busy.
599 	 */
600 	for (unit = 0, dp = md->md_utab; unit < md->md_nunits; unit++, dp++) {
601 		ui = md->md_dinfo[unit];
602 		if (ui == NULL || !ui->ui_alive || ui->ui_ctlr != mi->mi_ctlr)
603 			continue;
604 		ui->ui_flags &= ~(UNIT_HAVESTATUS | UNIT_ONLINE);
605 		if ((ui->ui_flags & UNIT_REQUEUE) == 0 && dp->b_actf == NULL)
606 			continue;
607 		ui->ui_flags &= ~UNIT_REQUEUE;
608 		APPEND(dp, mi->mi_tab, b_forw);
609 		dp->b_active = 1;
610 		mi->mi_tab->b_active = 1;
611 	}
612 
613 #ifdef AVOID_EMULEX_BUG
614 	/*
615 	 * ... and clear the index-to-buffer table.
616 	 */
617 	for (unit = 0; unit < AEB_MAX_BP; unit++)
618 		mi->mi_bp[unit] = 0;
619 #endif
620 }
621 
622 
623 /*
624  * MSCP error reporting
625  */
626 
627 /*
628  * Messages for the various subcodes.
629  */
630 static char unknown_msg[] = "unknown subcode";
631 
632 /*
633  * Subcodes for Success (0)
634  */
635 static char *succ_msgs[] = {
636 	"normal",		/* 0 */
637 	"spin down ignored",	/* 1 = Spin-Down Ignored */
638 	"still connected",	/* 2 = Still Connected */
639 	unknown_msg,
640 	"dup. unit #",		/* 4 = Duplicate Unit Number */
641 	unknown_msg,
642 	unknown_msg,
643 	unknown_msg,
644 	"already online",	/* 8 = Already Online */
645 	unknown_msg,
646 	unknown_msg,
647 	unknown_msg,
648 	unknown_msg,
649 	unknown_msg,
650 	unknown_msg,
651 	unknown_msg,
652 	"still online",		/* 16 = Still Online */
653 };
654 
655 /*
656  * Subcodes for Invalid Command (1)
657  */
658 static char *icmd_msgs[] = {
659 	"invalid msg length",	/* 0 = Invalid Message Length */
660 };
661 
662 /*
663  * Subcodes for Command Aborted (2)
664  */
665 /* none known */
666 
667 /*
668  * Subcodes for Unit Offline (3)
669  */
670 static char *offl_msgs[] = {
671 	"unknown drive",	/* 0 = Unknown, or online to other ctlr */
672 	"not mounted",		/* 1 = Unmounted, or RUN/STOP at STOP */
673 	"inoperative",		/* 2 = Unit Inoperative */
674 	unknown_msg,
675 	"duplicate",		/* 4 = Duplicate Unit Number */
676 	unknown_msg,
677 	unknown_msg,
678 	unknown_msg,
679 	"in diagnosis",		/* 8 = Disabled by FS or diagnostic */
680 };
681 
682 /*
683  * Subcodes for Unit Available (4)
684  */
685 /* none known */
686 
687 /*
688  * Subcodes for Media Format Error (5)
689  */
690 static char *media_fmt_msgs[] = {
691 	"fct unread - edc",	/* 0 = FCT unreadable */
692 	"invalid sector header",/* 1 = Invalid Sector Header */
693 	"not 512 sectors",	/* 2 = Not 512 Byte Sectors */
694 	"not formatted",	/* 3 = Not Formatted */
695 	"fct ecc",		/* 4 = FCT ECC */
696 };
697 
698 /*
699  * Subcodes for Write Protected (6)
700  * N.B.:  Code 6 subcodes are 7 bits higher than other subcodes
701  * (i.e., bits 12-15).
702  */
703 static char *wrprot_msgs[] = {
704 	unknown_msg,
705 	"software",		/* 1 = Software Write Protect */
706 	"hardware",		/* 2 = Hardware Write Protect */
707 };
708 
709 /*
710  * Subcodes for Compare Error (7)
711  */
712 /* none known */
713 
714 /*
715  * Subcodes for Data Error (8)
716  */
717 static char *data_msgs[] = {
718 	"forced error",		/* 0 = Forced Error (software) */
719 	unknown_msg,
720 	"header compare",	/* 2 = Header Compare Error */
721 	"sync timeout",		/* 3 = Sync Timeout Error */
722 	unknown_msg,
723 	unknown_msg,
724 	unknown_msg,
725 	"uncorrectable ecc",	/* 7 = Uncorrectable ECC */
726 	"1 symbol ecc",		/* 8 = 1 bit ECC */
727 	"2 symbol ecc",		/* 9 = 2 bit ECC */
728 	"3 symbol ecc",		/* 10 = 3 bit ECC */
729 	"4 symbol ecc",		/* 11 = 4 bit ECC */
730 	"5 symbol ecc",		/* 12 = 5 bit ECC */
731 	"6 symbol ecc",		/* 13 = 6 bit ECC */
732 	"7 symbol ecc",		/* 14 = 7 bit ECC */
733 	"8 symbol ecc",		/* 15 = 8 bit ECC */
734 };
735 
736 /*
737  * Subcodes for Host Buffer Access Error (9)
738  */
739 static char *host_buffer_msgs[] = {
740 	unknown_msg,
741 	"odd xfer addr",	/* 1 = Odd Transfer Address */
742 	"odd xfer count",	/* 2 = Odd Transfer Count */
743 	"non-exist. memory",	/* 3 = Non-Existent Memory */
744 	"memory parity",	/* 4 = Memory Parity Error */
745 };
746 
747 /*
748  * Subcodes for Controller Error (10)
749  */
750 static char *cntlr_msgs[] = {
751 	unknown_msg,
752 	"serdes overrun",	/* 1 = Serialiser/Deserialiser Overrun */
753 	"edc",			/* 2 = Error Detection Code? */
754 	"inconsistant internal data struct",/* 3 = Internal Error */
755 };
756 
757 /*
758  * Subcodes for Drive Error (11)
759  */
760 static char *drive_msgs[] = {
761 	unknown_msg,
762 	"sdi command timeout",	/* 1 = SDI Command Timeout */
763 	"ctlr detected protocol",/* 2 = Controller Detected Protocol Error */
764 	"positioner",		/* 3 = Positioner Error */
765 	"lost rd/wr ready",	/* 4 = Lost R/W Ready Error */
766 	"drive clock dropout",	/* 5 = Lost Drive Clock */
767 	"lost recvr ready",	/* 6 = Lost Receiver Ready */
768 	"drive detected error",	/* 7 = Drive Error */
769 	"ctlr detected pulse or parity",/* 8 = Pulse or Parity Error */
770 };
771 
772 /*
773  * The following table correlates message codes with the
774  * decoding strings.
775  */
776 struct code_decode {
777 	char	*cdc_msg;
778 	int	cdc_nsubcodes;
779 	char	**cdc_submsgs;
780 } code_decode[] = {
781 #define	SC(m)	sizeof (m) / sizeof (m[0]), m
782 	"success",			SC(succ_msgs),
783 	"invalid command",		SC(icmd_msgs),
784 	"command aborted",		0, 0,
785 	"unit offline",		SC(offl_msgs),
786 	"unit available",		0, 0,
787 	"media format error",		SC(media_fmt_msgs),
788 	"write protected",		SC(wrprot_msgs),
789 	"compare error",		0, 0,
790 	"data error",			SC(data_msgs),
791 	"host buffer access error",	SC(host_buffer_msgs),
792 	"controller error",		SC(cntlr_msgs),
793 	"drive error",			SC(drive_msgs),
794 #undef SC
795 };
796 
797 /*
798  * Print the decoded error event from an MSCP error datagram.
799  */
800 mscp_printevent(mp)
801 	struct mscp *mp;
802 {
803 	register int event = mp->mscp_event;
804 	register struct code_decode *cdc;
805 	int c, sc;
806 	char *cm, *scm;
807 
808 	/*
809 	 * The code is the lower six bits of the event number (aka
810 	 * status).  If that is 6 (write protect), the subcode is in
811 	 * bits 12-15; otherwise, it is in bits 5-11.
812 	 * I WONDER WHAT THE OTHER BITS ARE FOR.  IT SURE WOULD BE
813 	 * NICE IF DEC SOLD DOCUMENTATION FOR THEIR OWN CONTROLLERS.
814 	 */
815 	c = event & M_ST_MASK;
816 	sc = (c != 6 ? event >> 5 : event >> 12) & 0x7ff;
817 	if (c >= sizeof code_decode / sizeof code_decode[0])
818 		cm = "- unknown code", scm = "??";
819 	else {
820 		cdc = &code_decode[c];
821 		cm = cdc->cdc_msg;
822 		if (sc >= cdc->cdc_nsubcodes)
823 			scm = unknown_msg;
824 		else
825 			scm = cdc->cdc_submsgs[sc];
826 	}
827 	printf(" %s (%s) (code %d, subcode %d)\n", cm, scm, c, sc);
828 }
829 
830 /*
831  * Print the code and logical block number for an error packet.
832  * THIS IS PROBABLY PECULIAR TO DISK DRIVES.  IT SURE WOULD BE
833  * NICE IF DEC SOLD DOCUMENTATION FOR THEIR OWN CONTROLLERS.
834  */
mscp_decodeerror(name,ctlr,mp)835 mscp_decodeerror(name, ctlr, mp)
836 	char *name;
837 	int ctlr;
838 	register struct mscp *mp;
839 {
840 	/*
841 	 * For bad blocks, mp->mscp_erd.erd_hdr identifies a code and
842 	 * the logical block number.  Code 0 is a regular block; code 6
843 	 * is a replacement block.  The remaining codes are currently
844 	 * undefined.  The code is in the upper four bits of the header
845 	 * (bits 0-27 are the lbn).
846 	 */
847 	int issoft = mp->mscp_flags & (M_LF_SUCC | M_LF_CONT);
848 	static char *codemsg[16] = {
849 		"lbn", "code 1", "code 2", "code 3",
850 		"code 4", "code 5", "rbn", "code 7",
851 		"code 8", "code 9", "code 10", "code 11",
852 		"code 12", "code 13", "code 14", "code 15"
853 	};
854 #define BADCODE(h)	(codemsg[(unsigned)(h) >> 28])
855 #define BADLBN(h)	((h) & 0xfffffff)
856 
857 	printf("%s%d: %s error datagram%s:", name, ctlr,
858 		issoft ? "soft" : "hard",
859 		mp->mscp_flags & M_LF_CONT ? " (continuing)" : "");
860 	switch (mp->mscp_format & 0377) {
861 
862 	case M_FM_CTLRERR:	/* controller error */
863 		break;
864 
865 	case M_FM_BUSADDR:	/* host memory access error */
866 		printf(" memory addr 0x%x:", mp->mscp_erd.erd_busaddr);
867 		break;
868 
869 	case M_FM_DISKTRN:
870 		printf(" unit %d: level %d retry %d, %s %d:",
871 			mp->mscp_unit,
872 			mp->mscp_erd.erd_level, mp->mscp_erd.erd_retry,
873 			BADCODE(mp->mscp_erd.erd_hdr),
874 			BADLBN(mp->mscp_erd.erd_hdr));
875 		break;
876 
877 	case M_FM_SDI:
878 		printf(" unit %d: %s %d:", mp->mscp_unit,
879 			BADCODE(mp->mscp_erd.erd_hdr),
880 			BADLBN(mp->mscp_erd.erd_hdr));
881 		break;
882 
883 	case M_FM_SMLDSK:
884 		printf(" unit %d: small disk error, cyl %d:",
885 			mp->mscp_unit, mp->mscp_erd.erd_sdecyl);
886 		break;
887 
888 	default:
889 		printf(" unit %d: unknown error, format 0x%x:",
890 			mp->mscp_unit, mp->mscp_format);
891 	}
892 	mscp_printevent(mp);
893 #undef BADCODE
894 #undef BADLBN
895 }
896