📄 mscp.c
字号:
bp->av_forw->av_back = bp->av_back; if (ui->ui_dk >= 0 && md->md_utab[ui->ui_unit].b_forw == NULL) dk_busy &= ~(1 << ui->ui_dk); /* * If the transfer has something to do with bad * block forwarding, let the driver handle the * rest. */ if ((bp->b_flags & B_BAD) != 0 && md->md_bb != NULL) { (*md->md_bb)(ui, mp, bp); goto out; } /* * If the transfer failed, give the driver a crack * at fixing things up. */ if (st != M_ST_SUCCESS) { switch ((*md->md_ioerr)(ui, mp, bp)) { case MSCP_DONE: /* fixed */ break; case MSCP_RESTARTED: /* still working on it */ goto out; case MSCP_FAILED: /* no luck */ diskerr(bp, drivename, "hard error", LOG_PRINTF, -1, md->md_lab ? &md->md_lab[ui->ui_unit] : md->md_lab); mscp_printevent(mp); bp->b_flags |= B_ERROR; bp->b_error = EIO; break; } } /* * Set the residual count and mark the transfer as * done. If the I/O wait queue is now empty, release * the shared BDP, if any. */ info = bp->b_info; /* we are about to clobber it */ bp->b_resid = bp->b_bcount - mp->mscp_seq.seq_bytecount; (*md->md_iodone)(mi, bp, info);out: break; case M_OP_REPLACE | M_OP_END: /* * A replace operation finished. Just let the driver * handle it (if it does replaces). */ if (md->md_replace == NULL) printf("%s%d: bogus REPLACE end\n", drivename, ui->ui_unit); else (*md->md_replace)(ui, mp); break; default: /* * If it is not one of the above, we cannot handle it. * (And we should not have received it, for that matter.) */unknown: printf("%s%d: unknown opcode 0x%x status 0x%x ignored\n", mi->mi_md->md_dname, ui->ui_unit, mp->mscp_opcode, mp->mscp_status); mscp_hexdump(mp); break; } /* * If the drive needs to be put back in the controller queue, * do that now. (`bp' below ought to be `dp', but they are all * struct buf *.) Note that b_active was cleared in the driver; * we presume that there is something to be done, hence reassert it. */ if (ui->ui_flags & UNIT_REQUEUE) { bp = &md->md_utab[ui->ui_unit];if (bp->b_active) panic("mscp_dorsp requeue"); APPEND(bp, mi->mi_tab, b_forw); bp->b_active = 1; ui->ui_flags &= ~UNIT_REQUEUE; }done: /* * Give back the response packet, and take a look at the next. */ mp->mscp_msglen = MSCP_MSGLEN; mi->mi_rsp.mri_desc[nextrsp] |= MSCP_OWN; nextrsp = (nextrsp + 1) % mi->mi_rsp.mri_size; goto loop;}/* * Dump the entire contents of an MSCP packet in hex. Mainly useful * for debugging.... */mscp_hexdump(mp) register struct mscp *mp;{ register long *p = (long *) mp; register int i = mp->mscp_msglen; if (i > 256) /* sanity */ i = 256; i /= sizeof (*p); /* ASSUMES MULTIPLE OF sizeof(long) */ while (--i >= 0) printf("0x%x ", *p++); printf("\n");}/* * Requeue outstanding transfers, e.g., after bus reset. * Also requeue any drives that have on line or unit status * info pending. */mscp_requeue(mi) struct mscp_info *mi;{ register struct uba_device *ui; register struct mscp_driver *md = mi->mi_md; register struct buf *bp, *dp; register int unit; struct buf *nextbp; /* * Clear the controller chain. Mark everything un-busy; we * will soon fix any that are in fact busy. */ mi->mi_tab->b_actf = NULL; mi->mi_tab->b_active = 0; for (unit = 0, dp = md->md_utab; unit < md->md_nunits; unit++, dp++) { ui = md->md_dinfo[unit]; if (ui == NULL || !ui->ui_alive || ui->ui_ctlr != mi->mi_ctlr) continue; /* not ours */ dp->b_forw = NULL; dp->b_active = 0; } /* * Scan the wait queue, linking buffers onto drive queues. * Note that these must be put at the front of the drive queue, * lest we reorder I/O operations. */ for (bp = mi->mi_wtab.av_back; bp != &mi->mi_wtab; bp = nextbp) { nextbp = bp->av_back; dp = &md->md_utab[minor(bp->b_dev) >> md->md_unitshift]; bp->av_forw = dp->b_actf; if (dp->b_actf == NULL) dp->b_actl = bp; dp->b_actf = bp; } mi->mi_wtab.av_forw = mi->mi_wtab.av_back = &mi->mi_wtab; /* * Scan for drives waiting for on line or status responses, * and for drives with pending transfers. Put these on the * controller queue, and mark the controller busy. */ for (unit = 0, dp = md->md_utab; unit < md->md_nunits; unit++, dp++) { ui = md->md_dinfo[unit]; if (ui == NULL || !ui->ui_alive || ui->ui_ctlr != mi->mi_ctlr) continue; ui->ui_flags &= ~(UNIT_HAVESTATUS | UNIT_ONLINE); if ((ui->ui_flags & UNIT_REQUEUE) == 0 && dp->b_actf == NULL) continue; ui->ui_flags &= ~UNIT_REQUEUE; APPEND(dp, mi->mi_tab, b_forw); dp->b_active = 1; mi->mi_tab->b_active = 1; }#ifdef AVOID_EMULEX_BUG /* * ... and clear the index-to-buffer table. */ for (unit = 0; unit < AEB_MAX_BP; unit++) mi->mi_bp[unit] = 0;#endif}/* * MSCP error reporting *//* * Messages for the various subcodes. */static char unknown_msg[] = "unknown subcode";/* * Subcodes for Success (0) */static char *succ_msgs[] = { "normal", /* 0 */ "spin down ignored", /* 1 = Spin-Down Ignored */ "still connected", /* 2 = Still Connected */ unknown_msg, "dup. unit #", /* 4 = Duplicate Unit Number */ unknown_msg, unknown_msg, unknown_msg, "already online", /* 8 = Already Online */ unknown_msg, unknown_msg, unknown_msg, unknown_msg, unknown_msg, unknown_msg, unknown_msg, "still online", /* 16 = Still Online */};/* * Subcodes for Invalid Command (1) */static char *icmd_msgs[] = { "invalid msg length", /* 0 = Invalid Message Length */};/* * Subcodes for Command Aborted (2) *//* none known *//* * Subcodes for Unit Offline (3) */static char *offl_msgs[] = { "unknown drive", /* 0 = Unknown, or online to other ctlr */ "not mounted", /* 1 = Unmounted, or RUN/STOP at STOP */ "inoperative", /* 2 = Unit Inoperative */ unknown_msg, "duplicate", /* 4 = Duplicate Unit Number */ unknown_msg, unknown_msg, unknown_msg, "in diagnosis", /* 8 = Disabled by FS or diagnostic */};/* * Subcodes for Unit Available (4) *//* none known *//* * Subcodes for Media Format Error (5) */static char *media_fmt_msgs[] = { "fct unread - edc", /* 0 = FCT unreadable */ "invalid sector header",/* 1 = Invalid Sector Header */ "not 512 sectors", /* 2 = Not 512 Byte Sectors */ "not formatted", /* 3 = Not Formatted */ "fct ecc", /* 4 = FCT ECC */};/* * Subcodes for Write Protected (6) * N.B.: Code 6 subcodes are 7 bits higher than other subcodes * (i.e., bits 12-15). */static char *wrprot_msgs[] = { unknown_msg, "software", /* 1 = Software Write Protect */ "hardware", /* 2 = Hardware Write Protect */};/* * Subcodes for Compare Error (7) *//* none known *//* * Subcodes for Data Error (8) */static char *data_msgs[] = { "forced error", /* 0 = Forced Error (software) */ unknown_msg, "header compare", /* 2 = Header Compare Error */ "sync timeout", /* 3 = Sync Timeout Error */ unknown_msg, unknown_msg, unknown_msg, "uncorrectable ecc", /* 7 = Uncorrectable ECC */ "1 symbol ecc", /* 8 = 1 bit ECC */ "2 symbol ecc", /* 9 = 2 bit ECC */ "3 symbol ecc", /* 10 = 3 bit ECC */ "4 symbol ecc", /* 11 = 4 bit ECC */ "5 symbol ecc", /* 12 = 5 bit ECC */ "6 symbol ecc", /* 13 = 6 bit ECC */ "7 symbol ecc", /* 14 = 7 bit ECC */ "8 symbol ecc", /* 15 = 8 bit ECC */};/* * Subcodes for Host Buffer Access Error (9) */static char *host_buffer_msgs[] = { unknown_msg, "odd xfer addr", /* 1 = Odd Transfer Address */ "odd xfer count", /* 2 = Odd Transfer Count */ "non-exist. memory", /* 3 = Non-Existent Memory */ "memory parity", /* 4 = Memory Parity Error */};/* * Subcodes for Controller Error (10) */static char *cntlr_msgs[] = { unknown_msg, "serdes overrun", /* 1 = Serialiser/Deserialiser Overrun */ "edc", /* 2 = Error Detection Code? */ "inconsistant internal data struct",/* 3 = Internal Error */};/* * Subcodes for Drive Error (11) */static char *drive_msgs[] = { unknown_msg, "sdi command timeout", /* 1 = SDI Command Timeout */ "ctlr detected protocol",/* 2 = Controller Detected Protocol Error */ "positioner", /* 3 = Positioner Error */ "lost rd/wr ready", /* 4 = Lost R/W Ready Error */ "drive clock dropout", /* 5 = Lost Drive Clock */ "lost recvr ready", /* 6 = Lost Receiver Ready */ "drive detected error", /* 7 = Drive Error */ "ctlr detected pulse or parity",/* 8 = Pulse or Parity Error */};/* * The following table correlates message codes with the * decoding strings. */struct code_decode { char *cdc_msg; int cdc_nsubcodes; char **cdc_submsgs;} code_decode[] = {#define SC(m) sizeof (m) / sizeof (m[0]), m "success", SC(succ_msgs), "invalid command", SC(icmd_msgs), "command aborted", 0, 0, "unit offline", SC(offl_msgs), "unit available", 0, 0, "media format error", SC(media_fmt_msgs), "write protected", SC(wrprot_msgs), "compare error", 0, 0, "data error", SC(data_msgs), "host buffer access error", SC(host_buffer_msgs), "controller error", SC(cntlr_msgs), "drive error", SC(drive_msgs),#undef SC};/* * Print the decoded error event from an MSCP error datagram. */mscp_printevent(mp) struct mscp *mp;{ register int event = mp->mscp_event; register struct code_decode *cdc; int c, sc; char *cm, *scm; /* * The code is the lower six bits of the event number (aka * status). If that is 6 (write protect), the subcode is in * bits 12-15; otherwise, it is in bits 5-11. * I WONDER WHAT THE OTHER BITS ARE FOR. IT SURE WOULD BE * NICE IF DEC SOLD DOCUMENTATION FOR THEIR OWN CONTROLLERS. */ c = event & M_ST_MASK; sc = (c != 6 ? event >> 5 : event >> 12) & 0x7ff; if (c >= sizeof code_decode / sizeof code_decode[0]) cm = "- unknown code", scm = "??"; else { cdc = &code_decode[c]; cm = cdc->cdc_msg; if (sc >= cdc->cdc_nsubcodes) scm = unknown_msg; else scm = cdc->cdc_submsgs[sc]; } printf(" %s (%s) (code %d, subcode %d)\n", cm, scm, c, sc);}/* * Print the code and logical block number for an error packet. * THIS IS PROBABLY PECULIAR TO DISK DRIVES. IT SURE WOULD BE * NICE IF DEC SOLD DOCUMENTATION FOR THEIR OWN CONTROLLERS. */mscp_decodeerror(name, ctlr, mp) char *name; int ctlr; register struct mscp *mp;{ /* * For bad blocks, mp->mscp_erd.erd_hdr identifies a code and * the logical block number. Code 0 is a regular block; code 6 * is a replacement block. The remaining codes are currently * undefined. The code is in the upper four bits of the header * (bits 0-27 are the lbn). */ int issoft = mp->mscp_flags & (M_LF_SUCC | M_LF_CONT); static char *codemsg[16] = { "lbn", "code 1", "code 2", "code 3", "code 4", "code 5", "rbn", "code 7", "code 8", "code 9", "code 10", "code 11", "code 12", "code 13", "code 14", "code 15" };#define BADCODE(h) (codemsg[(unsigned)(h) >> 28])#define BADLBN(h) ((h) & 0xfffffff) printf("%s%d: %s error datagram%s:", name, ctlr, issoft ? "soft" : "hard", mp->mscp_flags & M_LF_CONT ? " (continuing)" : ""); switch (mp->mscp_format & 0377) { case M_FM_CTLRERR: /* controller error */ break; case M_FM_BUSADDR: /* host memory access error */ printf(" memory addr 0x%x:", mp->mscp_erd.erd_busaddr); break; case M_FM_DISKTRN: printf(" unit %d: level %d retry %d, %s %d:", mp->mscp_unit, mp->mscp_erd.erd_level, mp->mscp_erd.erd_retry, BADCODE(mp->mscp_erd.erd_hdr), BADLBN(mp->mscp_erd.erd_hdr)); break; case M_FM_SDI: printf(" unit %d: %s %d:", mp->mscp_unit, BADCODE(mp->mscp_erd.erd_hdr), BADLBN(mp->mscp_erd.erd_hdr)); break; case M_FM_SMLDSK: printf(" unit %d: small disk error, cyl %d:", mp->mscp_unit, mp->mscp_erd.erd_sdecyl); break; default: printf(" unit %d: unknown error, format 0x%x:", mp->mscp_unit, mp->mscp_format); } mscp_printevent(mp);#undef BADCODE#undef BADLBN}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -