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