diff options
Diffstat (limited to 'sys/dev/isp/isp_target.c')
-rw-r--r-- | sys/dev/isp/isp_target.c | 566 |
1 files changed, 44 insertions, 522 deletions
diff --git a/sys/dev/isp/isp_target.c b/sys/dev/isp/isp_target.c index f8b1930..c604644 100644 --- a/sys/dev/isp/isp_target.c +++ b/sys/dev/isp/isp_target.c @@ -56,12 +56,9 @@ static const char atiocope[] = "ATIO returned for LUN %x because it was in the m static const char atior[] = "ATIO returned for LUN %x from handle 0x%x because a Bus Reset occurred on bus %d"; static const char rqo[] = "%s: Request Queue Overflow"; -static void isp_got_msg(ispsoftc_t *, in_entry_t *); static void isp_got_msg_fc(ispsoftc_t *, in_fcentry_t *); static void isp_got_tmf_24xx(ispsoftc_t *, at7_entry_t *); -static void isp_handle_atio(ispsoftc_t *, at_entry_t *); static void isp_handle_atio2(ispsoftc_t *, at2_entry_t *); -static void isp_handle_ctio(ispsoftc_t *, ct_entry_t *); static void isp_handle_ctio2(ispsoftc_t *, ct2_entry_t *); static void isp_handle_ctio7(ispsoftc_t *, ct7_entry_t *); static void isp_handle_24xx_inotify(ispsoftc_t *, in_fcentry_24xx_t *); @@ -118,20 +115,16 @@ isp_target_notify(ispsoftc_t *isp, void *vptr, uint32_t *optrp) uint16_t status; uint32_t seqid; union { - at_entry_t *atiop; at2_entry_t *at2iop; at2e_entry_t *at2eiop; at7_entry_t *at7iop; - ct_entry_t *ctiop; ct2_entry_t *ct2iop; ct2e_entry_t *ct2eiop; ct7_entry_t *ct7iop; lun_entry_t *lunenp; - in_entry_t *inotp; in_fcentry_t *inot_fcp; in_fcentry_e_t *inote_fcp; in_fcentry_24xx_t *inot_24xx; - na_entry_t *nackp; na_fcentry_t *nack_fcp; na_fcentry_e_t *nacke_fcp; na_fcentry_24xx_t *nack_24xx; @@ -140,20 +133,16 @@ isp_target_notify(ispsoftc_t *isp, void *vptr, uint32_t *optrp) abts_rsp_t *abts_rsp; els_t *els; void * *vp; -#define atiop unp.atiop #define at2iop unp.at2iop #define at2eiop unp.at2eiop #define at7iop unp.at7iop -#define ctiop unp.ctiop #define ct2iop unp.ct2iop #define ct2eiop unp.ct2eiop #define ct7iop unp.ct7iop #define lunenp unp.lunenp -#define inotp unp.inotp #define inot_fcp unp.inot_fcp #define inote_fcp unp.inote_fcp #define inot_24xx unp.inot_24xx -#define nackp unp.nackp #define nack_fcp unp.nack_fcp #define nacke_fcp unp.nacke_fcp #define nack_24xx unp.nack_24xx @@ -164,7 +153,7 @@ isp_target_notify(ispsoftc_t *isp, void *vptr, uint32_t *optrp) } unp; uint8_t local[QENTRY_LEN]; uint16_t iid; - int bus, type, level, rval = 1; + int bus, type, len, level, rval = 1; isp_notify_t notify; type = isp_get_response_type(isp, (isphdr_t *)vptr); @@ -174,44 +163,32 @@ isp_target_notify(ispsoftc_t *isp, void *vptr, uint32_t *optrp) switch (type) { case RQSTYPE_ATIO: - if (IS_24XX(isp)) { - int len; - - isp_get_atio7(isp, at7iop, (at7_entry_t *) local); - at7iop = (at7_entry_t *) local; - /* - * Check for and do something with commands whose - * IULEN extends past a single queue entry. - */ - len = at7iop->at_ta_len & 0xfffff; - if (len > (QENTRY_LEN - 8)) { - len -= (QENTRY_LEN - 8); - isp_prt(isp, ISP_LOGINFO, "long IU length (%d) ignored", len); - while (len > 0) { - *optrp = ISP_NXT_QENTRY(*optrp, RESULT_QUEUE_LEN(isp)); - len -= QENTRY_LEN; - } - } - /* - * Check for a task management function - */ - if (at7iop->at_cmnd.fcp_cmnd_task_management) { - isp_got_tmf_24xx(isp, at7iop); - break; + isp_get_atio7(isp, at7iop, (at7_entry_t *) local); + at7iop = (at7_entry_t *) local; + /* + * Check for and do something with commands whose + * IULEN extends past a single queue entry. + */ + len = at7iop->at_ta_len & 0xfffff; + if (len > (QENTRY_LEN - 8)) { + len -= (QENTRY_LEN - 8); + isp_prt(isp, ISP_LOGINFO, "long IU length (%d) ignored", len); + while (len > 0) { + *optrp = ISP_NXT_QENTRY(*optrp, RESULT_QUEUE_LEN(isp)); + len -= QENTRY_LEN; } - /* - * Just go straight to outer layer for this one. - */ - isp_async(isp, ISPASYNC_TARGET_ACTION, local); - } else { - isp_get_atio(isp, atiop, (at_entry_t *) local); - isp_handle_atio(isp, (at_entry_t *) local); } - break; - - case RQSTYPE_CTIO: - isp_get_ctio(isp, ctiop, (ct_entry_t *) local); - isp_handle_ctio(isp, (ct_entry_t *) local); + /* + * Check for a task management function + */ + if (at7iop->at_cmnd.fcp_cmnd_task_management) { + isp_got_tmf_24xx(isp, at7iop); + break; + } + /* + * Just go straight to outer layer for this one. + */ + isp_async(isp, ISPASYNC_TARGET_ACTION, local); break; case RQSTYPE_ATIO2: @@ -251,8 +228,7 @@ isp_target_notify(ispsoftc_t *isp, void *vptr, uint32_t *optrp) inot_24xx = (in_fcentry_24xx_t *) local; isp_handle_24xx_inotify(isp, inot_24xx); break; - } - if (IS_FC(isp)) { + } else { if (ISP_CAP_2KLOGIN(isp)) { in_fcentry_e_t *ecp = (in_fcentry_e_t *)local; isp_get_notify_fc_e(isp, inote_fcp, ecp); @@ -266,16 +242,6 @@ isp_target_notify(ispsoftc_t *isp, void *vptr, uint32_t *optrp) status = fcp->in_status; seqid = fcp->in_seqid; } - } else { - in_entry_t *inp = (in_entry_t *)local; - isp_get_notify(isp, inotp, inp); - status = inp->in_status & 0xff; - seqid = inp->in_seqid; - iid = inp->in_iid; - if (IS_DUALBUS(isp)) { - bus = GET_BUS_VAL(inp->in_iid); - SET_BUS_VAL(inp->in_iid, 0); - } } isp_prt(isp, ISP_LOGTDEBUG0, "Immediate Notify On Bus %d, status=0x%x seqid=0x%x", bus, status, seqid); @@ -283,11 +249,7 @@ isp_target_notify(ispsoftc_t *isp, void *vptr, uint32_t *optrp) switch (status) { case IN_MSG_RECEIVED: case IN_IDE_RECEIVED: - if (IS_FC(isp)) { - isp_got_msg_fc(isp, (in_fcentry_t *)local); - } else { - isp_got_msg(isp, (in_entry_t *)local); - } + isp_got_msg_fc(isp, (in_fcentry_t *)local); break; case IN_RSRC_UNAVAIL: isp_prt(isp, ISP_LOGINFO, "Firmware out of ATIOs"); @@ -387,7 +349,7 @@ isp_target_notify(ispsoftc_t *isp, void *vptr, uint32_t *optrp) level = ISP_LOGTDEBUG1; } isp_prt(isp, level, "Notify Ack Status=0x%x; Subcode 0x%x seqid=0x%x", nack_24xx->na_status, nack_24xx->na_status_subcode, nack_24xx->na_rxid); - } else if (IS_FC(isp)) { + } else { if (ISP_CAP_2KLOGIN(isp)) { isp_get_notify_ack_fc_e(isp, nacke_fcp, (na_fcentry_e_t *)local); } else { @@ -400,15 +362,6 @@ isp_target_notify(ispsoftc_t *isp, void *vptr, uint32_t *optrp) level = ISP_LOGTDEBUG1; } isp_prt(isp, level, "Notify Ack Status=0x%x seqid 0x%x", nack_fcp->na_status, nack_fcp->na_seqid); - } else { - isp_get_notify_ack(isp, nackp, (na_entry_t *)local); - nackp = (na_entry_t *)local; - if (nackp->na_status != NA_OK) { - level = ISP_LOGINFO; - } else { - level = ISP_LOGTDEBUG1; - } - isp_prt(isp, level, "Notify Ack event 0x%x status=0x%x seqid 0x%x", nackp->na_event, nackp->na_status, nackp->na_seqid); } break; @@ -456,72 +409,6 @@ isp_target_notify(ispsoftc_t *isp, void *vptr, uint32_t *optrp) return (rval); } - -/* - * Toggle (on/off) target mode for bus/target/lun. - * - * The caller has checked for overlap and legality. - * - * Note that not all of bus, target or lun can be paid attention to. - * Note also that this action will not be complete until the f/w writes - * a response entry. The caller is responsible for synchronizing with this. - */ -int -isp_lun_cmd(ispsoftc_t *isp, int cmd, int bus, int lun, int cmd_cnt, int inot_cnt) -{ - lun_entry_t el; - void *outp; - - ISP_MEMZERO(&el, sizeof (el)); - if (IS_DUALBUS(isp)) { - el.le_rsvd = (bus & 0x1) << 7; - } - el.le_cmd_count = (cmd_cnt < 0)? -cmd_cnt : cmd_cnt; - el.le_in_count = (inot_cnt < 0)? -inot_cnt : inot_cnt; - if (cmd == RQSTYPE_ENABLE_LUN) { - if (IS_SCSI(isp)) { - el.le_flags = LUN_TQAE|LUN_DISAD; - el.le_cdb6len = 12; - el.le_cdb7len = 12; - } - } else if (cmd == RQSTYPE_MODIFY_LUN) { - if (cmd_cnt == 0 && inot_cnt == 0) { - isp_prt(isp, ISP_LOGWARN, "makes no sense to modify a lun with both command and immediate notify counts as zero"); - return (0); - } - if (cmd_cnt < 0) - el.le_ops |= LUN_CCDECR; - else - el.le_ops |= LUN_CCINCR; - if (inot_cnt < 0) - el.le_ops |= LUN_INDECR; - else - el.le_ops |= LUN_ININCR; - } else { - isp_prt(isp, ISP_LOGWARN, "unknown cmd (0x%x) in %s", cmd, __func__); - return (-1); - } - el.le_header.rqs_entry_type = cmd; - el.le_header.rqs_entry_count = 1; - if (IS_SCSI(isp)) { - el.le_tgt = SDPARAM(isp, bus)->isp_initiator_id; - el.le_lun = lun; - } else if (ISP_CAP_SCCFW(isp) == 0) { - el.le_lun = lun; - } - el.le_timeout = 30; - - outp = isp_getrqentry(isp); - if (outp == NULL) { - isp_prt(isp, ISP_LOGERR, rqo, __func__); - return (-1); - } - isp_put_enable_lun(isp, &el, outp); - ISP_TDQE(isp, "isp_lun_cmd", isp->isp_reqidx, &el); - ISP_SYNC_REQUEST(isp); - return (0); -} - int isp_target_put_entry(ispsoftc_t *isp, void *ap) { @@ -534,9 +421,6 @@ isp_target_put_entry(ispsoftc_t *isp, void *ap) return (-1); } switch (etype) { - case RQSTYPE_ATIO: - isp_put_atio(isp, (at_entry_t *) ap, (at_entry_t *) outp); - break; case RQSTYPE_ATIO2: if (ISP_CAP_2KLOGIN(isp)) { isp_put_atio2e(isp, (at2e_entry_t *) ap, (at2e_entry_t *) outp); @@ -544,9 +428,6 @@ isp_target_put_entry(ispsoftc_t *isp, void *ap) isp_put_atio2(isp, (at2_entry_t *) ap, (at2_entry_t *) outp); } break; - case RQSTYPE_CTIO: - isp_put_ctio(isp, (ct_entry_t *) ap, (ct_entry_t *) outp); - break; case RQSTYPE_CTIO2: if (ISP_CAP_2KLOGIN(isp)) { isp_put_ctio2e(isp, (ct2e_entry_t *) ap, (ct2e_entry_t *) outp); @@ -569,42 +450,27 @@ isp_target_put_entry(ispsoftc_t *isp, void *ap) int isp_target_put_atio(ispsoftc_t *isp, void *arg) { + at2_entry_t *aep = arg; union { - at_entry_t _atio; at2_entry_t _atio2; at2e_entry_t _atio2e; } atun; ISP_MEMZERO(&atun, sizeof atun); - if (IS_FC(isp)) { - at2_entry_t *aep = arg; - atun._atio2.at_header.rqs_entry_type = RQSTYPE_ATIO2; - atun._atio2.at_header.rqs_entry_count = 1; - if (ISP_CAP_SCCFW(isp)) { - atun._atio2.at_scclun = aep->at_scclun; - } else { - atun._atio2.at_lun = (uint8_t) aep->at_lun; - } - if (ISP_CAP_2KLOGIN(isp)) { - atun._atio2e.at_iid = ((at2e_entry_t *)aep)->at_iid; - } else { - atun._atio2.at_iid = aep->at_iid; - } - atun._atio2.at_rxid = aep->at_rxid; - atun._atio2.at_status = CT_OK; + atun._atio2.at_header.rqs_entry_type = RQSTYPE_ATIO2; + atun._atio2.at_header.rqs_entry_count = 1; + if (ISP_CAP_SCCFW(isp)) { + atun._atio2.at_scclun = aep->at_scclun; } else { - at_entry_t *aep = arg; - atun._atio.at_header.rqs_entry_type = RQSTYPE_ATIO; - atun._atio.at_header.rqs_entry_count = 1; - atun._atio.at_handle = aep->at_handle; - atun._atio.at_iid = aep->at_iid; - atun._atio.at_tgt = aep->at_tgt; - atun._atio.at_lun = aep->at_lun; - atun._atio.at_tag_type = aep->at_tag_type; - atun._atio.at_tag_val = aep->at_tag_val; - atun._atio.at_status = (aep->at_flags & AT_TQAE); - atun._atio.at_status |= CT_OK; + atun._atio2.at_lun = (uint8_t) aep->at_lun; } + if (ISP_CAP_2KLOGIN(isp)) { + atun._atio2e.at_iid = ((at2e_entry_t *)aep)->at_iid; + } else { + atun._atio2.at_iid = aep->at_iid; + } + atun._atio2.at_rxid = aep->at_rxid; + atun._atio2.at_status = CT_OK; return (isp_target_put_entry(isp, &atun)); } @@ -632,7 +498,6 @@ isp_endcmd(ispsoftc_t *isp, ...) uint32_t code, hdl; uint8_t sts; union { - ct_entry_t _ctio; ct2_entry_t _ctio2; ct2e_entry_t _ctio2e; ct7_entry_t _ctio7; @@ -693,7 +558,7 @@ isp_endcmd(ispsoftc_t *isp, ...) } } cto->ct_syshandle = hdl; - } else if (IS_FC(isp)) { + } else { at2_entry_t *aep; ct2_entry_t *cto = &un._ctio2; @@ -736,35 +601,6 @@ isp_endcmd(ispsoftc_t *isp, ...) cto->rsp.m1.ct_scsi_status |= CT2_SNSLEN_VALID; } cto->ct_syshandle = hdl; - } else { - at_entry_t *aep; - ct_entry_t *cto = &un._ctio; - - va_start(ap, isp); - aep = va_arg(ap, at_entry_t *); - code = va_arg(ap, uint32_t); - hdl = va_arg(ap, uint32_t); - va_end(ap); - isp_prt(isp, ISP_LOGTDEBUG0, "%s: [IID %d] code %x", __func__, aep->at_iid, code); - sts = code; - - cto->ct_header.rqs_entry_type = RQSTYPE_CTIO; - cto->ct_header.rqs_entry_count = 1; - cto->ct_fwhandle = aep->at_handle; - cto->ct_iid = aep->at_iid; - cto->ct_tgt = aep->at_tgt; - cto->ct_lun = aep->at_lun; - cto->ct_tag_type = aep->at_tag_type; - cto->ct_tag_val = aep->at_tag_val; - if (aep->at_flags & AT_TQAE) { - cto->ct_flags |= CT_TQAE; - } - cto->ct_flags = CT_SENDSTATUS | CT_NO_DATA; - if (hdl == 0) { - cto->ct_flags |= CT_CCINCR; - } - cto->ct_scsi_status = sts; - cto->ct_syshandle = hdl; } return (isp_target_put_entry(isp, &un)); } @@ -832,21 +668,13 @@ isp_target_async(ispsoftc_t *isp, int bus, int event) ct->ct_nphdl = CT7_OK; ct->ct_syshandle = bus; ct->ct_flags = CT7_SENDSTATUS; - } else if (IS_FC(isp)) { + } else { /* This should also suffice for 2K login code */ ct2_entry_t *ct = (ct2_entry_t *) storage; ct->ct_header.rqs_entry_type = RQSTYPE_CTIO2; ct->ct_status = CT_OK; ct->ct_syshandle = bus; ct->ct_flags = CT2_SENDSTATUS|CT2_FASTPOST; - } else { - ct_entry_t *ct = (ct_entry_t *) storage; - ct->ct_header.rqs_entry_type = RQSTYPE_CTIO; - ct->ct_status = CT_OK; - ct->ct_syshandle = bus; - /* we skip fwhandle here */ - ct->ct_fwhandle = 0; - ct->ct_flags = CT_SENDSTATUS; } isp_async(isp, ISPASYNC_TARGET_ACTION, storage); break; @@ -861,69 +689,6 @@ isp_target_async(ispsoftc_t *isp, int bus, int event) return (0); } - -/* - * Process a received message. - * The ISP firmware can handle most messages, there are only - * a few that we need to deal with: - * - abort: clean up the current command - * - abort tag and clear queue - */ - -static void -isp_got_msg(ispsoftc_t *isp, in_entry_t *inp) -{ - isp_notify_t notify; - uint8_t status = inp->in_status & ~QLTM_SVALID; - - ISP_MEMZERO(¬ify, sizeof (notify)); - notify.nt_hba = isp; - notify.nt_wwn = INI_ANY; - notify.nt_nphdl = GET_IID_VAL(inp->in_iid); - notify.nt_sid = PORT_ANY; - notify.nt_did = PORT_ANY; - notify.nt_channel = GET_BUS_VAL(inp->in_iid); - notify.nt_tgt = inp->in_tgt; - notify.nt_lun = inp->in_lun; - IN_MAKE_TAGID(notify.nt_tagval, inp); - notify.nt_tagval |= (((uint64_t)(isp->isp_serno++)) << 32); - notify.nt_lreserved = inp; - - if (status == IN_IDE_RECEIVED || status == IN_MSG_RECEIVED) { - switch (inp->in_msg[0]) { - case MSG_ABORT: - notify.nt_ncode = NT_ABORT_TASK_SET; - break; - case MSG_BUS_DEV_RESET: - notify.nt_ncode = NT_TARGET_RESET; - break; - case MSG_ABORT_TAG: - notify.nt_ncode = NT_ABORT_TASK; - break; - case MSG_CLEAR_QUEUE: - notify.nt_ncode = NT_CLEAR_TASK_SET; - break; - case MSG_REL_RECOVERY: - notify.nt_ncode = NT_CLEAR_ACA; - break; - case MSG_TERM_IO_PROC: - notify.nt_ncode = NT_ABORT_TASK; - break; - case MSG_LUN_RESET: - notify.nt_ncode = NT_LUN_RESET; - break; - default: - isp_prt(isp, ISP_LOGERR, "%s: unhandled message 0x%x", __func__, inp->in_msg[0]); - isp_async(isp, ISPASYNC_TARGET_NOTIFY_ACK, inp); - return; - } - isp_async(isp, ISPASYNC_TARGET_NOTIFY, ¬ify); - } else { - isp_prt(isp, ISP_LOGERR, "%s: unknown immediate notify status 0x%x", __func__, inp->in_status); - isp_async(isp, ISPASYNC_TARGET_NOTIFY_ACK, inp); - } -} - /* * Synthesize a message from the task management flags in a FCP_CMND_IU. */ @@ -1111,7 +876,7 @@ isp_notify_ack(ispsoftc_t *isp, void *arg) } } isp_put_notify_24xx_ack(isp, na, (na_fcentry_24xx_t *)outp); - } else if (IS_FC(isp)) { + } else { na_fcentry_t *na = (na_fcentry_t *) storage; int iid = 0; @@ -1148,25 +913,6 @@ isp_notify_ack(ispsoftc_t *isp, void *arg) } isp_prt(isp, ISP_LOGTDEBUG0, "notify ack handle %x seqid %x flags %x tflags %x response %x", iid, na->na_seqid, na->na_flags, na->na_task_flags, na->na_response); - } else { - na_entry_t *na = (na_entry_t *) storage; - if (arg) { - in_entry_t *inp = arg; - ISP_MEMCPY(storage, arg, sizeof (isphdr_t)); - na->na_iid = inp->in_iid; - na->na_lun = inp->in_lun; - na->na_tgt = inp->in_tgt; - na->na_seqid = inp->in_seqid; - if (inp->in_status == IN_RESET) { - na->na_event = NA_RST_CLRD; - } - } else { - na->na_event = NA_RST_CLRD; - } - na->na_header.rqs_entry_type = RQSTYPE_NOTIFY_ACK; - na->na_header.rqs_entry_count = 1; - isp_put_notify_ack(isp, na, (na_entry_t *)outp); - isp_prt(isp, ISP_LOGTDEBUG0, "notify ack handle %x lun %x tgt %u seqid %x event %x", na->na_iid, na->na_lun, na->na_tgt, na->na_seqid, na->na_event); } ISP_TDQE(isp, "isp_notify_ack", isp->isp_reqidx, storage); ISP_SYNC_REQUEST(isp); @@ -1253,80 +999,6 @@ isp_acknak_abts(ispsoftc_t *isp, void *arg, int errno) } static void -isp_handle_atio(ispsoftc_t *isp, at_entry_t *aep) -{ - int lun; - lun = aep->at_lun; - /* - * The firmware status (except for the QLTM_SVALID bit) indicates - * why this ATIO was sent to us. - * - * If QLTM_SVALID is set, the firware has recommended Sense Data. - * - * If the DISCONNECTS DISABLED bit is set in the flags field, - * we're still connected on the SCSI bus - i.e. the initiator - * did not set DiscPriv in the identify message. We don't care - * about this so it's ignored. - */ - - switch (aep->at_status & ~QLTM_SVALID) { - case AT_PATH_INVALID: - /* - * ATIO rejected by the firmware due to disabled lun. - */ - isp_prt(isp, ISP_LOGERR, "rejected ATIO for disabled lun %x", lun); - break; - case AT_NOCAP: - /* - * Requested Capability not available - * We sent an ATIO that overflowed the firmware's - * command resource count. - */ - isp_prt(isp, ISP_LOGERR, "rejected ATIO for lun %x because of command count overflow", lun); - break; - - case AT_BDR_MSG: - /* - * If we send an ATIO to the firmware to increment - * its command resource count, and the firmware is - * recovering from a Bus Device Reset, it returns - * the ATIO with this status. We set the command - * resource count in the Enable Lun entry and do - * not increment it. Therefore we should never get - * this status here. - */ - isp_prt(isp, ISP_LOGERR, atiocope, lun, GET_BUS_VAL(aep->at_iid)); - break; - - case AT_CDB: /* Got a CDB */ - case AT_PHASE_ERROR: /* Bus Phase Sequence Error */ - /* - * Punt to platform specific layer. - */ - isp_async(isp, ISPASYNC_TARGET_ACTION, aep); - break; - - case AT_RESET: - /* - * A bus reset came along and blew away this command. Why - * they do this in addition the async event code stuff, - * I dunno. - * - * Ignore it because the async event will clear things - * up for us. - */ - isp_prt(isp, ISP_LOGWARN, atior, lun, GET_IID_VAL(aep->at_iid), GET_BUS_VAL(aep->at_iid)); - break; - - - default: - isp_prt(isp, ISP_LOGERR, "Unknown ATIO status 0x%x from handle %x for lun %x", aep->at_status, aep->at_iid, lun); - (void) isp_target_put_atio(isp, aep); - break; - } -} - -static void isp_handle_atio2(ispsoftc_t *isp, at2_entry_t *aep) { int lun, iid; @@ -1415,156 +1087,6 @@ isp_handle_atio2(ispsoftc_t *isp, at2_entry_t *aep) } static void -isp_handle_ctio(ispsoftc_t *isp, ct_entry_t *ct) -{ - void *xs; - int pl = ISP_LOGTDEBUG2; - char *fmsg = NULL; - - if (ct->ct_syshandle) { - xs = isp_find_xs_tgt(isp, ct->ct_syshandle); - if (xs == NULL) { - pl = ISP_LOGALL; - } - } else { - xs = NULL; - } - - switch (ct->ct_status & ~QLTM_SVALID) { - case CT_OK: - /* - * There are generally 3 possibilities as to why we'd get - * this condition: - * We disconnected after receiving a CDB. - * We sent or received data. - * We sent status & command complete. - */ - - if (ct->ct_flags & CT_SENDSTATUS) { - break; - } else if ((ct->ct_flags & CT_DATAMASK) == CT_NO_DATA) { - /* - * Nothing to do in this case. - */ - isp_prt(isp, pl, "CTIO- iid %d disconnected OK", ct->ct_iid); - return; - } - break; - - case CT_BDR_MSG: - /* - * Bus Device Reset message received or the SCSI Bus has - * been Reset; the firmware has gone to Bus Free. - * - * The firmware generates an async mailbox interrupt to - * notify us of this and returns outstanding CTIOs with this - * status. These CTIOs are handled in that same way as - * CT_ABORTED ones, so just fall through here. - */ - fmsg = "Bus Device Reset"; - /*FALLTHROUGH*/ - case CT_RESET: - if (fmsg == NULL) - fmsg = "Bus Reset"; - /*FALLTHROUGH*/ - case CT_ABORTED: - /* - * When an Abort message is received the firmware goes to - * Bus Free and returns all outstanding CTIOs with the status - * set, then sends us an Immediate Notify entry. - */ - if (fmsg == NULL) - fmsg = "ABORT TAG message sent by Initiator"; - isp_prt(isp, ISP_LOGTDEBUG0, "CTIO destroyed by %s", fmsg); - break; - - case CT_INVAL: - /* - * CTIO rejected by the firmware due to disabled lun. - * "Cannot Happen". - */ - isp_prt(isp, ISP_LOGERR, "Firmware rejected CTIO for disabled lun %x", ct->ct_lun); - break; - - case CT_NOPATH: - /* - * CTIO rejected by the firmware due "no path for the - * nondisconnecting nexus specified". This means that - * we tried to access the bus while a non-disconnecting - * command is in process. - */ - isp_prt(isp, ISP_LOGERR, "Firmware rejected CTIO for bad nexus %d/%d/%x", ct->ct_iid, ct->ct_tgt, ct->ct_lun); - break; - - case CT_RSELTMO: - fmsg = "Reselection"; - /*FALLTHROUGH*/ - case CT_TIMEOUT: - if (fmsg == NULL) - fmsg = "Command"; - isp_prt(isp, ISP_LOGWARN, "Firmware timed out on %s", fmsg); - break; - - case CT_PANIC: - if (fmsg == NULL) - fmsg = "Unrecoverable Error"; - /*FALLTHROUGH*/ - case CT_ERR: - if (fmsg == NULL) - fmsg = "Completed with Error"; - /*FALLTHROUGH*/ - case CT_PHASE_ERROR: - if (fmsg == NULL) - fmsg = "Phase Sequence Error"; - /*FALLTHROUGH*/ - case CT_TERMINATED: - if (fmsg == NULL) - fmsg = "terminated by TERMINATE TRANSFER"; - /*FALLTHROUGH*/ - case CT_NOACK: - if (fmsg == NULL) - fmsg = "unacknowledged Immediate Notify pending"; - isp_prt(isp, ISP_LOGERR, "CTIO returned by f/w- %s", fmsg); - break; - default: - isp_prt(isp, ISP_LOGERR, "Unknown CTIO status 0x%x", ct->ct_status & ~QLTM_SVALID); - break; - } - - if (xs == NULL) { - /* - * There may be more than one CTIO for a data transfer, - * or this may be a status CTIO we're not monitoring. - * - * The assumption is that they'll all be returned in the - * order we got them. - */ - if (ct->ct_syshandle == 0) { - if ((ct->ct_flags & CT_SENDSTATUS) == 0) { - isp_prt(isp, pl, "intermediate CTIO completed ok"); - } else { - isp_prt(isp, pl, "unmonitored CTIO completed ok"); - } - } else { - isp_prt(isp, pl, "NO xs for CTIO (handle 0x%x) status 0x%x", ct->ct_syshandle, ct->ct_status & ~QLTM_SVALID); - } - } else { - /* - * Final CTIO completed. Release DMA resources and - * notify platform dependent layers. - */ - if ((ct->ct_flags & CT_DATAMASK) != CT_NO_DATA) { - ISP_DMAFREE(isp, xs, ct->ct_syshandle); - } - isp_prt(isp, pl, "final CTIO complete"); - /* - * The platform layer will destroy the handle if appropriate. - */ - isp_async(isp, ISPASYNC_TARGET_ACTION, ct); - } -} - -static void isp_handle_ctio2(ispsoftc_t *isp, ct2_entry_t *ct) { void *xs; |