PERFORCE change 108071 for review
Matt Jacob
mjacob at FreeBSD.org
Wed Oct 18 13:50:46 PDT 2006
http://perforce.freebsd.org/chv.cgi?CH=108071
Change 108071 by mjacob at newisp on 2006/10/18 20:50:11
The latest/greatest for target mode for 24XX.
Affected files ...
.. //depot/projects/newisp/dev/isp/isp_target.c#8 edit
.. //depot/projects/newisp/dev/isp/isp_target.h#10 edit
Differences ...
==== //depot/projects/newisp/dev/isp/isp_target.c#8 (text+ko) ====
@@ -58,6 +58,7 @@
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 *);
@@ -191,6 +192,13 @@
}
}
/*
+ * 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);
@@ -311,16 +319,29 @@
isp_prt(isp, ISP_LOGWARN, "Firmware out of ATIOs");
isp_notify_ack(isp, local);
break;
- case IN_RESET: /* same as IN24XX_LIP_RESET */
- case IN24XX_LINK_RESET:
- (void) isp_target_async(isp, 0, ASYNC_BUS_RESET);
+ case IN_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: /* same as IN24XX_PORT_LOGOUT */
+ }
+ case IN_PORT_LOGOUT:
case IN_ABORT_TASK:
- case IN_PORT_CHANGED: /* same as IN24XX_PORT_CHANGED */
- case IN_GLOBAL_LOGO: /* same as IN24XX_LINK_FAILED */
- case IN24XX_SRR_RCVD:
- case IN24XX_ELS_RCVD:
+ case IN_PORT_CHANGED:
+ case IN_GLOBAL_LOGO:
(void) isp_async(isp, ISPASYNC_TARGET_ACTION, &local);
break;
default:
@@ -528,12 +549,14 @@
(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);
@@ -600,21 +623,42 @@
*/
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_24XX(isp)) {
- isp_prt(isp, ISP_LOGERR, "XXX ISP_ENDCMD NOT DONE YET FOR 24XX");
- return (0);
+ 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;
+ }
+ cto->ct_syshandle = hdl;
} else if (IS_FC(isp)) {
at2_entry_t *aep = arg;
ct2_entry_t *cto = &un._ctio2;
@@ -675,6 +719,35 @@
}
/*
+ * Terminate a command
+ */
+int
+isp_terminate_cmd(ispsoftc_t *isp, void *arg)
+{
+ tmd_cmd_t *tmd = arg;
+ ct7_entry_t local, *cto = &local;;
+
+ if (!IS_24XX(isp)) {
+ return (-1);
+ }
+ isp_prt(isp, ISP_LOGTDEBUG0,
+ "isp_terminate_cmd: tag 0x%0x is being terminated",
+ tmd->cd_tagval);
+ MEMZERO(&local, sizeof (local));
+ cto->ct_header.rqs_entry_type = RQSTYPE_CTIO7;
+ cto->ct_header.rqs_entry_count = 1;
+ cto->ct_nphdl = tmd->cd_nphdl;
+ cto->ct_rxid = tmd->cd_tagval;
+ cto->ct_iid_lo = tmd->cd_portid;
+ cto->ct_iid_hi = tmd->cd_portid >> 16;
+ cto->ct_oxid = tmd->cd_oxid;
+ cto->ct_flags = CT7_TERMINATE;
+ cto->ct_syshandle = 0;
+ return (isp_target_put_entry(isp, &local));
+}
+
+
+/*
* These are either broadcast events or specifically CTIO fast completion
*/
int
@@ -723,7 +796,13 @@
{
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;
@@ -738,7 +817,7 @@
ct->ct_flags = CT_SENDSTATUS;
}
(void) isp_async(isp, ISPASYNC_TARGET_ACTION, storage);
- return (0);
+ break;
}
default:
isp_prt(isp, ISP_LOGERR,
@@ -818,9 +897,9 @@
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));
@@ -841,6 +920,7 @@
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) {
@@ -880,6 +960,64 @@
(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)
{
@@ -895,7 +1033,11 @@
MEMZERO(storage, QENTRY_LEN);
- if (IS_24XX(isp) && arg != NULL && (((isphdr_t *)arg)->rqs_entry_type == RQSTYPE_ABTS_RSP)) {
+ 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
@@ -1519,8 +1661,9 @@
break;
case CT7_RESET:
- if (fmsg == NULL)
+ if (fmsg == NULL) {
fmsg = "LIP Reset";
+ }
/*FALLTHROUGH*/
case CT7_ABORTED:
/*
@@ -1531,14 +1674,14 @@
if (fmsg == NULL) {
fmsg = "ABORT";
}
-
isp_prt(isp, ISP_LOGTDEBUG0,
- "CTIO2 destroyed by %s: RX_ID=0x%x", fmsg, ct->ct_rxid);
+ "CTIO7 destroyed by %s: RX_ID=0x%x", fmsg, ct->ct_rxid);
break;
case CT7_TIMEOUT:
- if (fmsg == NULL)
+ if (fmsg == NULL) {
fmsg = "command";
+ }
isp_prt(isp, ISP_LOGERR, "Firmware timed out on %s", fmsg);
break;
@@ -1546,16 +1689,19 @@
fmsg = "Completed with Error";
/*FALLTHROUGH*/
case CT7_LOGOUT:
- if (fmsg == NULL)
+ if (fmsg == NULL) {
fmsg = "Port Logout";
+ }
/*FALLTHROUGH*/
case CT7_PORTUNAVAIL:
- if (fmsg == NULL)
+ if (fmsg == NULL) {
fmsg = "Port not available";
+ }
/*FALLTHROUGH*/
case CT7_PORTCHANGED:
- if (fmsg == NULL)
+ if (fmsg == NULL) {
fmsg = "Port Changed";
+ }
isp_prt(isp, ISP_LOGWARN, "CTIO returned by f/w- %s", fmsg);
break;
@@ -1565,7 +1711,7 @@
* Just print a message.
*/
isp_prt(isp, ISP_LOGWARN,
- "CTIO2 completed with Invalid RX_ID 0x%x", ct->ct_rxid);
+ "CTIO7 completed with Invalid RX_ID 0x%x", ct->ct_rxid);
break;
case CT7_REASSY_ERR:
@@ -1577,7 +1723,7 @@
break;
default:
- isp_prt(isp, ISP_LOGERR, "Unknown CTIO2 status 0x%x",
+ isp_prt(isp, ISP_LOGERR, "Unknown CTIO7 status 0x%x",
ct->ct_nphdl);
break;
}
@@ -1591,7 +1737,11 @@
* order we got them.
*/
if (ct->ct_syshandle == 0) {
- if ((ct->ct_flags & CT7_SENDSTATUS) == 0) {
+ if (ct->ct_flags & CT7_TERMINATE) {
+ isp_prt(isp, ISP_LOGALL,
+ "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 {
==== //depot/projects/newisp/dev/isp/isp_target.h#10 (text+ko) ====
@@ -932,10 +932,15 @@
* General routine to send a final CTIO for a command- used mostly for
* local responses.
*/
-int isp_endcmd(ispsoftc_t *, void *, uint32_t, uint16_t);
+int isp_endcmd(ispsoftc_t *, void *, uint32_t, uint32_t);
#define ECMD_SVALID 0x100
/*
+ * General routine to terminate an active command
+ */
+int isp_terminate_cmd(ispsoftc_t *, void *);
+
+/*
* Handle an asynchronous event
*
* Return nonzero if the interrupt that generated this event has been dismissed.
More information about the p4-projects
mailing list