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