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