aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/isp/isp_target.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/isp/isp_target.c')
-rw-r--r--sys/dev/isp/isp_target.c592
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(&notify, 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, &notify);
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, &notify);
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