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