diff options
Diffstat (limited to 'sys/dev/isp/isp_target.c')
| -rw-r--r-- | sys/dev/isp/isp_target.c | 592 |
1 files changed, 518 insertions, 74 deletions
diff --git a/sys/dev/isp/isp_target.c b/sys/dev/isp/isp_target.c index ebbd80b71114..a86b8ec415a7 100644 --- a/sys/dev/isp/isp_target.c +++ b/sys/dev/isp/isp_target.c @@ -53,15 +53,17 @@ static const char atiocope[] = "ATIO returned for lun %d because it was in the middle of Bus Device Reset " "on bus %d"; static const char atior[] = - "ATIO returned on for lun %d on from IID %d because a Bus Reset occurred " - "on bus %d"; + "ATIO returned on for lun %d on from loopid %d because a Bus Reset " + "occurred on bus %d"; 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 *); /* * The Qlogic driver gets an interrupt to look at response queue entries. @@ -110,42 +112,57 @@ static void isp_handle_ctio2(ispsoftc_t *, ct2_entry_t *); */ int -isp_target_notify(ispsoftc_t *isp, void *vptr, uint16_t *optrp) +isp_target_notify(ispsoftc_t *isp, void *vptr, uint32_t *optrp) { - uint16_t status, seqid; + 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; isphdr_t *hp; + abts_t *abts; + 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 +#define abts unp.abts +#define abts_rsp unp.abts_rsp +#define els unp.els #define hdrp unp.hp } unp; uint8_t local[QENTRY_LEN]; - int bus, type, rval = 1; + int bus, type, level, rval = 1; type = isp_get_response_type(isp, (isphdr_t *)vptr); unp.vp = vptr; @@ -154,30 +171,72 @@ isp_target_notify(ispsoftc_t *isp, void *vptr, uint16_t *optrp) switch(type) { case RQSTYPE_ATIO: - isp_get_atio(isp, atiop, (at_entry_t *) local); - isp_handle_atio(isp, (at_entry_t *) local); + 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 singel 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; + } + /* + * Just go straight to outer layer for this one. + */ + (void) 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); break; + case RQSTYPE_ATIO2: - if (IS_2KLOGIN(isp)) { + if (FCPARAM(isp)->isp_2klogin) { isp_get_atio2e(isp, at2eiop, (at2e_entry_t *) local); } else { isp_get_atio2(isp, at2iop, (at2_entry_t *) local); - } + } isp_handle_atio2(isp, (at2_entry_t *) local); break; + case RQSTYPE_CTIO3: case RQSTYPE_CTIO2: - if (IS_2KLOGIN(isp)) { + if (FCPARAM(isp)->isp_2klogin) { isp_get_ctio2e(isp, ct2eiop, (ct2e_entry_t *) local); } else { isp_get_ctio2(isp, ct2iop, (ct2_entry_t *) local); - } + } isp_handle_ctio2(isp, (ct2_entry_t *) local); break; + + case RQSTYPE_CTIO7: + isp_get_ctio7(isp, ct7iop, (ct7_entry_t *) local); + isp_handle_ctio7(isp, (ct7_entry_t *) local); + break; + case RQSTYPE_ENABLE_LUN: case RQSTYPE_MODIFY_LUN: isp_get_enable_lun(isp, lunenp, (lun_entry_t *) local); @@ -193,8 +252,36 @@ isp_target_notify(ispsoftc_t *isp, void *vptr, uint16_t *optrp) * (we set this initially in the Enable Lun entry). */ bus = 0; - if (IS_FC(isp)) { - if (IS_2KLOGIN(isp)) { + if (IS_24XX(isp)) { + isp_get_notify_24xx(isp, inot_24xx, + (in_fcentry_24xx_t *)local); + inot_24xx = (in_fcentry_24xx_t *) local; + status = inot_24xx->in_status; + seqid = inot_24xx->in_rxid; + isp_prt(isp, ISP_LOGTDEBUG0, + "Immediate Notify status=0x%x seqid=0x%x", + status, seqid); + switch (status) { + case IN24XX_LIP_RESET: + case IN24XX_LINK_RESET: + case IN24XX_PORT_LOGOUT: + case IN24XX_PORT_CHANGED: + case IN24XX_LINK_FAILED: + case IN24XX_SRR_RCVD: + case IN24XX_ELS_RCVD: + (void) isp_async(isp, ISPASYNC_TARGET_ACTION, + &local); + break; + default: + isp_prt(isp, ISP_LOGINFO, + "isp_target_notify: unknown status (0x%x)", + status); + isp_notify_ack(isp, local); + break; + } + break; + } else if (IS_FC(isp)) { + if (FCPARAM(isp)->isp_2klogin) { isp_get_notify_fc_e(isp, inote_fcp, (in_fcentry_e_t *)local); } else { @@ -229,12 +316,28 @@ isp_target_notify(ispsoftc_t *isp, void *vptr, uint16_t *optrp) } break; case IN_RSRC_UNAVAIL: - isp_prt(isp, ISP_LOGWARN, "Firmware out of ATIOs"); + isp_prt(isp, ISP_LOGINFO, "Firmware out of ATIOs"); isp_notify_ack(isp, local); break; case IN_RESET: - (void) isp_target_async(isp, 0, ASYNC_BUS_RESET); + { + /* + * We form the notify structure here because we need + * to mark it as needing a NOTIFY ACK on return. + */ + tmd_notify_t notify; + + MEMZERO(¬ify, sizeof (tmd_notify_t)); + notify.nt_hba = isp; + notify.nt_iid = INI_ANY; + /* nt_tgt set in outer layers */ + notify.nt_lun = LUN_ANY; + notify.nt_tagval = TAG_ANY; + notify.nt_ncode = NT_BUS_RESET; + notify.nt_need_ack = 1; + (void) isp_async(isp, ISPASYNC_TARGET_NOTIFY, ¬ify); break; + } case IN_PORT_LOGOUT: case IN_ABORT_TASK: case IN_PORT_CHANGED: @@ -242,8 +345,9 @@ isp_target_notify(ispsoftc_t *isp, void *vptr, uint16_t *optrp) (void) isp_async(isp, ISPASYNC_TARGET_ACTION, &local); break; default: - isp_prt(isp, ISP_LOGERR, - "bad status (0x%x) in isp_target_notify", status); + isp_prt(isp, ISP_LOGINFO, + "isp_target_notify: unknown status (0x%x)", + status); isp_notify_ack(isp, local); break; } @@ -254,26 +358,68 @@ isp_target_notify(ispsoftc_t *isp, void *vptr, uint16_t *optrp) * The ISP is acknowledging our acknowledgement of an * Immediate Notify entry for some asynchronous event. */ - if (IS_FC(isp)) { - if (IS_2KLOGIN(isp)) { + if (IS_24XX(isp)) { + isp_get_notify_ack_24xx(isp, nack_24xx, + (na_fcentry_24xx_t *) local); + nack_24xx = (na_fcentry_24xx_t *) local; + if (nack_24xx->na_status != NA_OK) { + level = ISP_LOGINFO; + } else { + 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)) { + if (FCPARAM(isp)->isp_2klogin) { isp_get_notify_ack_fc_e(isp, nacke_fcp, (na_fcentry_e_t *)local); } else { isp_get_notify_ack_fc(isp, nack_fcp, (na_fcentry_t *)local); - } + } nack_fcp = (na_fcentry_t *)local; - isp_prt(isp, ISP_LOGTDEBUG1, - "Notify Ack status=0x%x seqid 0x%x", + if (nack_fcp->na_status != NA_OK) { + level = ISP_LOGINFO; + } else { + 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; - isp_prt(isp, ISP_LOGTDEBUG1, + 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; + + case RQSTYPE_ABTS_RCVD: + isp_get_abts(isp, abts, (abts_t *)local); + (void) isp_async(isp, ISPASYNC_TARGET_ACTION, &local); + break; + case RQSTYPE_ABTS_RSP: + isp_get_abts_rsp(isp, abts_rsp, (abts_rsp_t *)local); + abts_rsp = (abts_rsp_t *) local; + if (abts_rsp->abts_rsp_status) { + level = ISP_LOGINFO; + } else { + level = ISP_LOGTDEBUG0; + } + isp_prt(isp, level, + "ABTS RSP response[0x%x]: status=0x%x sub=(0x%x 0x%x)", + abts_rsp->abts_rsp_rxid_task, abts_rsp->abts_rsp_status, + abts_rsp->abts_rsp_payload.rsp.subcode1, + abts_rsp->abts_rsp_payload.rsp.subcode2); + break; default: isp_prt(isp, ISP_LOGERR, "Unknown entry type 0x%x in isp_target_notify", type); @@ -283,16 +429,23 @@ isp_target_notify(ispsoftc_t *isp, void *vptr, uint16_t *optrp) #undef atiop #undef at2iop #undef at2eiop +#undef at7iop #undef ctiop #undef ct2iop #undef ct2eiop +#undef ct7iop #undef lunenp #undef inotp #undef inot_fcp #undef inote_fcp +#undef inot_24xx #undef nackp #undef nack_fcp #undef nacke_fcp +#undef hack_24xx +#undef abts +#undef abts_rsp +#undef els #undef hdrp return (rval); } @@ -312,7 +465,7 @@ isp_lun_cmd(ispsoftc_t *isp, int cmd, int bus, int tgt, int lun, int cmd_cnt, int inot_cnt, uint32_t opaque) { lun_entry_t el; - uint16_t nxti, optr; + uint32_t nxti, optr; void *outp; @@ -344,7 +497,7 @@ isp_lun_cmd(ispsoftc_t *isp, int cmd, int bus, int tgt, int lun, if (IS_SCSI(isp)) { el.le_tgt = tgt; el.le_lun = lun; - } else if ((FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) == 0) { + } else if (FCPARAM(isp)->isp_sccfw == 0) { el.le_lun = lun; } @@ -364,7 +517,7 @@ int isp_target_put_entry(ispsoftc_t *isp, void *ap) { void *outp; - uint16_t nxti, optr; + uint32_t nxti, optr; uint8_t etype = ((isphdr_t *) ap)->rqs_entry_type; if (isp_getrqentry(isp, &nxti, &optr, &outp)) { @@ -377,28 +530,34 @@ isp_target_put_entry(ispsoftc_t *isp, void *ap) isp_put_atio(isp, (at_entry_t *) ap, (at_entry_t *) outp); break; case RQSTYPE_ATIO2: - if (IS_2KLOGIN(isp)) { - isp_put_atio2e(isp, (at2e_entry_t *) ap, (at2e_entry_t *) outp); - } else { - isp_put_atio2(isp, (at2_entry_t *) ap, (at2_entry_t *) outp); - } + if (FCPARAM(isp)->isp_2klogin) { + isp_put_atio2e(isp, (at2e_entry_t *) ap, + (at2e_entry_t *) outp); + } else { + 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 (IS_2KLOGIN(isp)) { - isp_put_ctio2e(isp, (ct2e_entry_t *) ap, (ct2e_entry_t *) outp); - } else { - isp_put_ctio2(isp, (ct2_entry_t *) ap, (ct2_entry_t *) outp); - } + if (FCPARAM(isp)->isp_2klogin) { + isp_put_ctio2e(isp, (ct2e_entry_t *) ap, + (ct2e_entry_t *) outp); + } else { + isp_put_ctio2(isp, (ct2_entry_t *) ap, + (ct2_entry_t *) outp); + } + break; + case RQSTYPE_CTIO7: + isp_put_ctio7(isp, (ct7_entry_t *) ap, (ct7_entry_t *) outp); break; default: isp_prt(isp, ISP_LOGERR, "Unknown type 0x%x in isp_put_entry", etype); return (-1); } - ISP_TDQE(isp, "isp_target_put_entry", (int) optr, ap); ISP_ADD_REQUEST(isp, nxti); return (0); @@ -418,12 +577,12 @@ isp_target_put_atio(ispsoftc_t *isp, void *arg) at2_entry_t *aep = arg; atun._atio2.at_header.rqs_entry_type = RQSTYPE_ATIO2; atun._atio2.at_header.rqs_entry_count = 1; - if (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) { - atun._atio2.at_scclun = (uint16_t) aep->at_scclun; + if (FCPARAM(isp)->isp_sccfw) { + atun._atio2.at_scclun = aep->at_scclun; } else { atun._atio2.at_lun = (uint8_t) aep->at_lun; } - if (IS_2KLOGIN(isp)) { + if (FCPARAM(isp)->isp_2klogin) { atun._atio2e.at_iid = ((at2e_entry_t *)aep)->at_iid; } else { atun._atio2.at_iid = aep->at_iid; @@ -465,28 +624,56 @@ isp_target_put_atio(ispsoftc_t *isp, void *arg) */ int -isp_endcmd(ispsoftc_t *isp, void *arg, uint32_t code, uint16_t hdl) +isp_endcmd(ispsoftc_t *isp, void *arg, uint32_t code, uint32_t hdl) { int sts; union { ct_entry_t _ctio; ct2_entry_t _ctio2; ct2e_entry_t _ctio2e; + ct7_entry_t _ctio7; } un; MEMZERO(&un, sizeof un); sts = code & 0xff; - if (IS_FC(isp)) { + if (IS_24XX(isp)) { + at7_entry_t *aep = arg; + ct7_entry_t *cto = &un._ctio7; + + cto->ct_header.rqs_entry_type = RQSTYPE_CTIO7; + cto->ct_header.rqs_entry_count = 1; +/* XXXX */ cto->ct_nphdl = aep->at_hdr.seq_id; + cto->ct_rxid = aep->at_rxid; + cto->ct_iid_lo = (aep->at_hdr.s_id[1] << 8) | + aep->at_hdr.s_id[2]; + cto->ct_iid_hi = aep->at_hdr.s_id[0]; + cto->ct_oxid = aep->at_hdr.ox_id; + cto->ct_scsi_status = sts; + cto->ct_flags = CT7_FLAG_MODE1 | CT7_NO_DATA | CT7_SENDSTATUS; + if (sts == SCSI_CHECK && (code & ECMD_SVALID)) { + cto->rsp.m1.ct_resplen = 16; + cto->rsp.m1.ct_resp[0] = 0xf0; + cto->rsp.m1.ct_resp[2] = (code >> 12) & 0xf; + cto->rsp.m1.ct_resp[7] = 8; + cto->rsp.m1.ct_resp[12] = (code >> 24) & 0xff; + cto->rsp.m1.ct_resp[13] = (code >> 16) & 0xff; + } + if (aep->at_cmnd.cdb_dl.sf.fcp_cmnd_dl) { + cto->ct_resid = aep->at_cmnd.cdb_dl.sf.fcp_cmnd_dl; + cto->ct_scsi_status |= CT2_DATA_UNDER; + } + cto->ct_syshandle = hdl; + } else if (IS_FC(isp)) { at2_entry_t *aep = arg; ct2_entry_t *cto = &un._ctio2; cto->ct_header.rqs_entry_type = RQSTYPE_CTIO2; cto->ct_header.rqs_entry_count = 1; - if ((FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) == 0) { + if (FCPARAM(isp)->isp_sccfw == 0) { cto->ct_lun = aep->at_lun; } - if (IS_2KLOGIN(isp)) { + if (FCPARAM(isp)->isp_2klogin) { un._ctio2e.ct_iid = ((at2e_entry_t *)aep)->at_iid; } else { cto->ct_iid = aep->at_iid; @@ -565,6 +752,7 @@ isp_target_async(ispsoftc_t *isp, int bus, int event) notify.nt_ncode = NT_LINK_DOWN; (void) isp_async(isp, ISPASYNC_TARGET_NOTIFY, ¬ify); break; + case ASYNC_LIP_ERROR: case ASYNC_LIP_F8: case ASYNC_LIP_OCCURRED: case ASYNC_LOOP_RESET: @@ -584,7 +772,13 @@ isp_target_async(ispsoftc_t *isp, int bus, int event) { uint8_t storage[QENTRY_LEN]; memset(storage, 0, QENTRY_LEN); - if (IS_FC(isp)) { + if (IS_24XX(isp)) { + ct7_entry_t *ct = (ct7_entry_t *) storage; + ct->ct_header.rqs_entry_type = RQSTYPE_CTIO7; + ct->ct_nphdl = CT7_OK; + ct->ct_syshandle = bus; + ct->ct_flags = CT7_SENDSTATUS|CT7_FASTPOST; + } else if (IS_FC(isp)) { /* This should also suffice for 2K login code */ ct2_entry_t *ct = (ct2_entry_t *) storage; ct->ct_header.rqs_entry_type = RQSTYPE_CTIO2; @@ -599,7 +793,7 @@ isp_target_async(ispsoftc_t *isp, int bus, int event) ct->ct_flags = CT_SENDSTATUS; } (void) isp_async(isp, ISPASYNC_TARGET_ACTION, storage); - return (0); + break; } default: isp_prt(isp, ISP_LOGERR, @@ -679,14 +873,14 @@ static void isp_got_msg_fc(ispsoftc_t *isp, in_fcentry_t *inp) { tmd_notify_t nt; - static const char f1[] = "%s from loop id %d lun %d seq 0x%x"; + static const char f1[] = "%s from N-port handle 0x%x lun %d seq 0x%x"; static const char f2[] = - "unknown %s 0x%x lun %d loop id %d task flags 0x%x seq 0x%x\n"; + "unknown %s 0x%x lun %d N-Port handle 0x%x task flags 0x%x seq 0x%x\n"; uint16_t seqid, loopid; MEMZERO(&nt, sizeof (tmd_notify_t)); nt.nt_hba = isp; - if (IS_2KLOGIN(isp)) { + if (FCPARAM(isp)->isp_2klogin) { nt.nt_iid = ((in_fcentry_e_t *)inp)->in_iid; loopid = ((in_fcentry_e_t *)inp)->in_iid; seqid = ((in_fcentry_e_t *)inp)->in_seqid; @@ -696,12 +890,13 @@ isp_got_msg_fc(ispsoftc_t *isp, in_fcentry_t *inp) seqid = inp->in_seqid; } /* nt_tgt set in outer layers */ - if (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) { + if (FCPARAM(isp)->isp_sccfw) { nt.nt_lun = inp->in_scclun; } else { nt.nt_lun = inp->in_lun; } IN_FC_MAKE_TAGID(nt.nt_tagval, 0, seqid); + nt.nt_need_ack = 1; nt.nt_lreserved = inp; if (inp->in_status != IN_MSG_RECEIVED) { @@ -741,11 +936,69 @@ isp_got_msg_fc(ispsoftc_t *isp, in_fcentry_t *inp) (void) isp_async(isp, ISPASYNC_TARGET_NOTIFY, &nt); } +static void +isp_got_tmf_24xx(ispsoftc_t *isp, at7_entry_t *aep) +{ + tmd_notify_t nt; + static const char f1[] = "%s from PortID 0x%06x lun %d seq 0x%x"; + static const char f2[] = + "unknown Task Flag 0x%x lun %d PortID 0x%x tag 0x%x\n"; + uint32_t sid; + + MEMZERO(&nt, sizeof (tmd_notify_t)); + nt.nt_hba = isp; + nt.nt_iid = INI_ANY; + nt.nt_lun = + (aep->at_cmnd.fcp_cmnd_lun[0] << 8) | + (aep->at_cmnd.fcp_cmnd_lun[1]); + nt.nt_tagval = aep->at_rxid; + nt.nt_lreserved = aep; + sid = + (aep->at_hdr.s_id[0] << 16) | + (aep->at_hdr.s_id[1] << 8) | + (aep->at_hdr.s_id[2]); + + if (aep->at_cmnd.fcp_cmnd_task_management & + FCP_CMND_TMF_ABORT_TASK_SET) { + isp_prt(isp, ISP_LOGINFO, f1, "ABORT TASK SET", + sid, nt.nt_lun, nt.nt_tagval); + nt.nt_ncode = NT_ABORT_TASK_SET; + } else if (aep->at_cmnd.fcp_cmnd_task_management & + FCP_CMND_TMF_CLEAR_TASK_SET) { + isp_prt(isp, ISP_LOGINFO, f1, "CLEAR TASK SET", + sid, nt.nt_lun, nt.nt_tagval); + nt.nt_ncode = NT_CLEAR_TASK_SET; + } else if (aep->at_cmnd.fcp_cmnd_task_management & + FCP_CMND_TMF_LUN_RESET) { + isp_prt(isp, ISP_LOGINFO, f1, "LUN RESET", + sid, nt.nt_lun, nt.nt_tagval); + nt.nt_ncode = NT_LUN_RESET; + } else if (aep->at_cmnd.fcp_cmnd_task_management & + FCP_CMND_TMF_TGT_RESET) { + isp_prt(isp, ISP_LOGINFO, f1, "TARGET RESET", + sid, nt.nt_lun, nt.nt_tagval); + nt.nt_ncode = NT_TARGET_RESET; + nt.nt_lun = LUN_ANY; + } else if (aep->at_cmnd.fcp_cmnd_task_management & + FCP_CMND_TMF_CLEAR_ACA) { + isp_prt(isp, ISP_LOGINFO, f1, "CLEAR ACA", + sid, nt.nt_lun, nt.nt_tagval); + nt.nt_ncode = NT_CLEAR_ACA; + } else { + isp_prt(isp, ISP_LOGWARN, f2, + aep->at_cmnd.fcp_cmnd_task_management, + nt.nt_lun, sid, nt.nt_tagval); + isp_endcmd(isp, aep, 0, 0); + return; + } + (void) isp_async(isp, ISPASYNC_TARGET_NOTIFY, &nt); +} + void isp_notify_ack(ispsoftc_t *isp, void *arg) { char storage[QENTRY_LEN]; - uint16_t nxti, optr; + uint32_t nxti, optr; void *outp; if (isp_getrqentry(isp, &nxti, &optr, &outp)) { @@ -756,14 +1009,49 @@ isp_notify_ack(ispsoftc_t *isp, void *arg) MEMZERO(storage, QENTRY_LEN); - if (IS_FC(isp)) { + if (IS_24XX(isp) && arg != NULL && (((isphdr_t *)arg)->rqs_entry_type == RQSTYPE_ATIO)) { + at7_entry_t *aep = arg; + isp_endcmd(isp, aep, 0, 0); + return; + } else if (IS_24XX(isp) && arg != NULL && (((isphdr_t *)arg)->rqs_entry_type == RQSTYPE_ABTS_RSP)) { + abts_rsp_t *abts_rsp = (abts_rsp_t *) storage; + /* + * The caller will have set response values as appropriate + * in the ABTS structure just before calling us. + */ + MEMCPY(abts_rsp, arg, QENTRY_LEN); + isp_put_abts_rsp(isp, abts_rsp, (abts_rsp_t *)outp); + } else if (IS_24XX(isp)) { + na_fcentry_24xx_t *na = (na_fcentry_24xx_t *) storage; + if (arg) { + in_fcentry_24xx_t *in = arg; + na->na_nphdl = in->in_nphdl; + na->na_status = in->in_status; + na->na_status_subcode = in->in_status_subcode; + na->na_rxid = in->in_rxid; + na->na_oxid = in->in_oxid; + if (in->in_status == IN24XX_SRR_RCVD) { + na->na_srr_rxid = in->in_srr_rxid; + na->na_srr_reloff_hi = in->in_srr_reloff_hi; + na->na_srr_reloff_lo = in->in_srr_reloff_lo; + na->na_srr_iu = in->in_srr_iu; + na->na_srr_flags = 1; + na->na_srr_reject_vunique = 0; + na->na_srr_reject_explanation = 1; + na->na_srr_reject_code = 1; + } + } + na->na_header.rqs_entry_type = RQSTYPE_NOTIFY_ACK; + na->na_header.rqs_entry_count = 1; + isp_put_notify_24xx_ack(isp, na, (na_fcentry_24xx_t *)outp); + } else if (IS_FC(isp)) { na_fcentry_t *na = (na_fcentry_t *) storage; int iid = 0; if (arg) { in_fcentry_t *inp = arg; MEMCPY(storage, arg, sizeof (isphdr_t)); - if (IS_2KLOGIN(isp)) { + if (FCPARAM(isp)->isp_2klogin) { ((na_fcentry_e_t *)na)->na_iid = ((in_fcentry_e_t *)inp)->in_iid; iid = ((na_fcentry_e_t *)na)->na_iid; @@ -788,14 +1076,14 @@ isp_notify_ack(ispsoftc_t *isp, void *arg) } na->na_header.rqs_entry_type = RQSTYPE_NOTIFY_ACK; na->na_header.rqs_entry_count = 1; - if (IS_2KLOGIN(isp)) { + if (FCPARAM(isp)->isp_2klogin) { isp_put_notify_ack_fc_e(isp, (na_fcentry_e_t *) na, (na_fcentry_e_t *)outp); } else { isp_put_notify_ack_fc(isp, na, (na_fcentry_t *)outp); } - isp_prt(isp, ISP_LOGTDEBUG0, "notify ack iid %u seqid %x flags " - "%x tflags %x response %x", iid, na->na_seqid, + isp_prt(isp, ISP_LOGTDEBUG0, "notify ack loopid %u 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; @@ -815,8 +1103,8 @@ isp_notify_ack(ispsoftc_t *isp, void *arg) 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 iid %u lun %u tgt %u " - "seqid %x event %x", na->na_iid, na->na_lun, na->na_tgt, + isp_prt(isp, ISP_LOGTDEBUG0, "notify ack loopid %u lun %u 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", (int) optr, storage); @@ -897,7 +1185,7 @@ isp_handle_atio(ispsoftc_t *isp, at_entry_t *aep) default: isp_prt(isp, ISP_LOGERR, - "Unknown ATIO status 0x%x from initiator %d for lun %d", + "Unknown ATIO status 0x%x from loopid %d for lun %d", aep->at_status, aep->at_iid, lun); (void) isp_target_put_atio(isp, aep); break; @@ -909,13 +1197,13 @@ isp_handle_atio2(ispsoftc_t *isp, at2_entry_t *aep) { int lun, iid; - if (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) { + if (FCPARAM(isp)->isp_sccfw) { lun = aep->at_scclun; } else { lun = aep->at_lun; } - if (IS_2KLOGIN(isp)) { + if (FCPARAM(isp)->isp_2klogin) { iid = ((at2e_entry_t *)aep)->at_iid; } else { iid = aep->at_iid; @@ -986,7 +1274,7 @@ isp_handle_atio2(ispsoftc_t *isp, at2_entry_t *aep) default: isp_prt(isp, ISP_LOGERR, - "Unknown ATIO2 status 0x%x from initiator %d for lun %d", + "Unknown ATIO2 status 0x%x from loopid %d for lun %d", aep->at_status, iid, lun); (void) isp_target_put_atio(isp, aep); break; @@ -1002,8 +1290,9 @@ isp_handle_ctio(ispsoftc_t *isp, ct_entry_t *ct) if (ct->ct_syshandle) { xs = isp_find_xs_tgt(isp, ct->ct_syshandle); - if (xs == NULL) + if (xs == NULL) { pl = ISP_LOGALL; + } } else { xs = NULL; } @@ -1055,7 +1344,7 @@ isp_handle_ctio(ispsoftc_t *isp, ct_entry_t *ct) if (fmsg == NULL) fmsg = "ABORT TAG message sent by Initiator"; - isp_prt(isp, ISP_LOGWARN, "CTIO destroyed by %s", fmsg); + isp_prt(isp, ISP_LOGTDEBUG0, "CTIO destroyed by %s", fmsg); break; case CT_INVAL: @@ -1156,14 +1445,15 @@ isp_handle_ctio(ispsoftc_t *isp, ct_entry_t *ct) static void isp_handle_ctio2(ispsoftc_t *isp, ct2_entry_t *ct) { - XS_T *xs; + 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) + if (xs == NULL) { pl = ISP_LOGALL; + } } else { xs = NULL; } @@ -1193,7 +1483,7 @@ isp_handle_ctio2(ispsoftc_t *isp, ct2_entry_t *ct) * status. These CTIOs are handled in that same way as * CT_ABORTED ones, so just fall through here. */ - fmsg = "TARGET RESET Task Management Function Received"; + fmsg = "TARGET RESET"; /*FALLTHROUGH*/ case CT_RESET: if (fmsg == NULL) @@ -1205,11 +1495,12 @@ isp_handle_ctio2(ispsoftc_t *isp, ct2_entry_t *ct) * Bus Free and returns all outstanding CTIOs with the status * set, then sends us an Immediate Notify entry. */ - if (fmsg == NULL) - fmsg = "ABORT Task Management Function Received"; + if (fmsg == NULL) { + fmsg = "ABORT"; + } - isp_prt(isp, ISP_LOGERR, "CTIO2 destroyed by %s: RX_ID=0x%x", - fmsg, ct->ct_rxid); + isp_prt(isp, ISP_LOGTDEBUG0, + "CTIO2 destroyed by %s: RX_ID=0x%x", fmsg, ct->ct_rxid); break; case CT_INVAL: @@ -1235,7 +1526,7 @@ isp_handle_ctio2(ispsoftc_t *isp, ct2_entry_t *ct) if (fmsg == NULL) fmsg = "Port Logout"; /*FALLTHROUGH*/ - case CT_PORTNOTAVAIL: + case CT_PORTUNAVAIL: if (fmsg == NULL) fmsg = "Port not available"; /*FALLTHROUGH*/ @@ -1246,7 +1537,7 @@ isp_handle_ctio2(ispsoftc_t *isp, ct2_entry_t *ct) case CT_NOACK: if (fmsg == NULL) fmsg = "unacknowledged Immediate Notify pending"; - isp_prt(isp, ISP_LOGERR, "CTIO returned by f/w- %s", fmsg); + isp_prt(isp, ISP_LOGWARN, "CTIO returned by f/w- %s", fmsg); break; case CT_INVRXID: @@ -1254,7 +1545,7 @@ isp_handle_ctio2(ispsoftc_t *isp, ct2_entry_t *ct) * CTIO rejected by the firmware because an invalid RX_ID. * Just print a message. */ - isp_prt(isp, ISP_LOGERR, + isp_prt(isp, ISP_LOGWARN, "CTIO2 completed with Invalid RX_ID 0x%x", ct->ct_rxid); break; @@ -1312,4 +1603,157 @@ isp_handle_ctio2(ispsoftc_t *isp, ct2_entry_t *ct) */ } } + +static void +isp_handle_ctio7(ispsoftc_t *isp, ct7_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_nphdl) { + case CT7_BUS_ERROR: + isp_prt(isp, ISP_LOGERR, "PCI DMA Bus Error"); + /* FALL Through */ + case CT7_DATA_OVER: + case CT7_DATA_UNDER: + case CT7_OK: + /* + * There are generally 2 possibilities as to why we'd get + * this condition: + * We sent or received data. + * We sent status & command complete. + */ + + break; + + case CT7_RESET: + if (fmsg == NULL) { + fmsg = "LIP Reset"; + } + /*FALLTHROUGH*/ + case CT7_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"; + } + isp_prt(isp, ISP_LOGTDEBUG0, + "CTIO7 destroyed by %s: RX_ID=0x%x", fmsg, ct->ct_rxid); + break; + + case CT7_TIMEOUT: + if (fmsg == NULL) { + fmsg = "command"; + } + isp_prt(isp, ISP_LOGERR, "Firmware timed out on %s", fmsg); + break; + + case CT7_ERR: + fmsg = "Completed with Error"; + /*FALLTHROUGH*/ + case CT7_LOGOUT: + if (fmsg == NULL) { + fmsg = "Port Logout"; + } + /*FALLTHROUGH*/ + case CT7_PORTUNAVAIL: + if (fmsg == NULL) { + fmsg = "Port not available"; + } + /*FALLTHROUGH*/ + case CT7_PORTCHANGED: + if (fmsg == NULL) { + fmsg = "Port Changed"; + } + isp_prt(isp, ISP_LOGWARN, "CTIO returned by f/w- %s", fmsg); + break; + + case CT7_INVRXID: + /* + * CTIO rejected by the firmware because an invalid RX_ID. + * Just print a message. + */ + isp_prt(isp, ISP_LOGWARN, + "CTIO7 completed with Invalid RX_ID 0x%x", ct->ct_rxid); + break; + + case CT7_REASSY_ERR: + isp_prt(isp, ISP_LOGWARN, "reassembly error"); + break; + + case CT7_SRR: + isp_prt(isp, ISP_LOGWARN, "SRR received"); + break; + + default: + isp_prt(isp, ISP_LOGERR, "Unknown CTIO7 status 0x%x", + ct->ct_nphdl); + 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 & CT7_TERMINATE) { + isp_prt(isp, ISP_LOGINFO, + "termination of 0x%x complete", + ct->ct_rxid); + } else if ((ct->ct_flags & CT7_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_nphdl); + } + } else { + if ((ct->ct_flags & CT2_DATAMASK) != CT2_NO_DATA) { + ISP_DMAFREE(isp, xs, ct->ct_syshandle); + } + if (ct->ct_flags & CT2_SENDSTATUS) { + /* + * Sent status and command complete. + * + * We're now really done with this command, so we + * punt to the platform dependent layers because + * only there can we do the appropriate command + * complete thread synchronization. + */ + isp_prt(isp, pl, "status CTIO complete"); + } else { + /* + * Final CTIO completed. Release DMA resources and + * notify platform dependent layers. + */ + isp_prt(isp, pl, "data CTIO complete"); + } + (void) isp_async(isp, ISPASYNC_TARGET_ACTION, ct); + /* + * The platform layer will destroy the handle if appropriate. + */ + } +} #endif |
