diff options
-rw-r--r-- | sys/cam/cam_ccb.h | 12 | ||||
-rw-r--r-- | sys/cam/ctl/scsi_ctl.c | 23 | ||||
-rw-r--r-- | sys/dev/isp/isp_freebsd.c | 20 |
3 files changed, 49 insertions, 6 deletions
diff --git a/sys/cam/cam_ccb.h b/sys/cam/cam_ccb.h index 251d62d..1d56ac7 100644 --- a/sys/cam/cam_ccb.h +++ b/sys/cam/cam_ccb.h @@ -1084,7 +1084,17 @@ struct ccb_notify_acknowledge { u_int tag_id; /* Tag for immediate notify */ u_int seq_id; /* Tar for target of notify */ u_int initiator_id; /* Initiator Identifier */ - u_int arg; /* Function specific */ + u_int arg; /* Response information */ + /* + * Lower byte of arg is one of RESPONSE CODE values defined below + * (subset of response codes from SPL-4 and FCP-4 specifications), + * upper 3 bytes is code-specific ADDITIONAL RESPONSE INFORMATION. + */ +#define CAM_RSP_TMF_COMPLETE 0x00 +#define CAM_RSP_TMF_REJECTED 0x04 +#define CAM_RSP_TMF_FAILED 0x05 +#define CAM_RSP_TMF_SUCCEEDED 0x08 +#define CAM_RSP_TMF_INCORRECT_LUN 0x09 }; /* HBA engine structures. */ diff --git a/sys/cam/ctl/scsi_ctl.c b/sys/cam/ctl/scsi_ctl.c index 2705240..abdbdcd 100644 --- a/sys/cam/ctl/scsi_ctl.c +++ b/sys/cam/ctl/scsi_ctl.c @@ -1552,6 +1552,7 @@ ctlfedone(struct cam_periph *periph, union ccb *done_ccb) /* * Queue this back down to the SIM as an immediate notify. */ + done_ccb->ccb_h.status = CAM_REQ_INPROG; done_ccb->ccb_h.func_code = XPT_IMMEDIATE_NOTIFY; xpt_action(done_ccb); break; @@ -2040,6 +2041,28 @@ ctlfe_done(union ctl_io *io) */ ccb->ccb_h.status = CAM_REQ_INPROG; ccb->ccb_h.func_code = XPT_NOTIFY_ACKNOWLEDGE; + switch (io->taskio.task_status) { + case CTL_TASK_FUNCTION_COMPLETE: + ccb->cna2.arg = CAM_RSP_TMF_COMPLETE; + break; + case CTL_TASK_FUNCTION_SUCCEEDED: + ccb->cna2.arg = CAM_RSP_TMF_SUCCEEDED; + ccb->ccb_h.flags |= CAM_SEND_STATUS; + break; + case CTL_TASK_FUNCTION_REJECTED: + ccb->cna2.arg = CAM_RSP_TMF_REJECTED; + ccb->ccb_h.flags |= CAM_SEND_STATUS; + break; + case CTL_TASK_LUN_DOES_NOT_EXIST: + ccb->cna2.arg = CAM_RSP_TMF_INCORRECT_LUN; + ccb->ccb_h.flags |= CAM_SEND_STATUS; + break; + case CTL_TASK_FUNCTION_NOT_SUPPORTED: + ccb->cna2.arg = CAM_RSP_TMF_FAILED; + ccb->ccb_h.flags |= CAM_SEND_STATUS; + break; + } + ccb->cna2.arg |= scsi_3btoul(io->taskio.task_resp) << 8; xpt_action(ccb); } else if (io->io_hdr.flags & CTL_FLAG_STATUS_SENT) { if (softc->flags & CTLFE_LUN_WILDCARD) { diff --git a/sys/dev/isp/isp_freebsd.c b/sys/dev/isp/isp_freebsd.c index 4400cde..2289f54 100644 --- a/sys/dev/isp/isp_freebsd.c +++ b/sys/dev/isp/isp_freebsd.c @@ -856,7 +856,7 @@ static void isp_handle_platform_atio7(ispsoftc_t *, at7_entry_t *); static void isp_handle_platform_ctio(ispsoftc_t *, void *); static void isp_handle_platform_notify_fc(ispsoftc_t *, in_fcentry_t *); static void isp_handle_platform_notify_24xx(ispsoftc_t *, in_fcentry_24xx_t *); -static int isp_handle_platform_target_notify_ack(ispsoftc_t *, isp_notify_t *); +static int isp_handle_platform_target_notify_ack(ispsoftc_t *, isp_notify_t *, uint32_t rsp); static void isp_handle_platform_target_tmf(ispsoftc_t *, isp_notify_t *); static void isp_target_mark_aborted(ispsoftc_t *, union ccb *); static void isp_target_mark_aborted_early(ispsoftc_t *, tstate_t *, uint32_t); @@ -2761,7 +2761,7 @@ isp_handle_platform_notify_24xx(ispsoftc_t *isp, in_fcentry_24xx_t *inot) } static int -isp_handle_platform_target_notify_ack(ispsoftc_t *isp, isp_notify_t *mp) +isp_handle_platform_target_notify_ack(ispsoftc_t *isp, isp_notify_t *mp, uint32_t rsp) { if (isp->isp_state != ISP_RUNSTATE) { @@ -2796,6 +2796,15 @@ isp_handle_platform_target_notify_ack(ispsoftc_t *isp, isp_notify_t *mp) cto->ct_oxid = aep->at_hdr.ox_id; cto->ct_flags = CT7_SENDSTATUS|CT7_NOACK|CT7_NO_DATA|CT7_FLAG_MODE1; cto->ct_flags |= (aep->at_ta_len >> 12) << CT7_TASK_ATTR_SHIFT; + if (rsp != 0) { + cto->ct_scsi_status |= (FCP_RSPLEN_VALID << 8); + cto->rsp.m1.ct_resplen = 4; + ISP_MEMZERO(cto->rsp.m1.ct_resp, sizeof (cto->rsp.m1.ct_resp)); + cto->rsp.m1.ct_resp[0] = rsp & 0xff; + cto->rsp.m1.ct_resp[1] = (rsp >> 8) & 0xff; + cto->rsp.m1.ct_resp[2] = (rsp >> 16) & 0xff; + cto->rsp.m1.ct_resp[3] = (rsp >> 24) & 0xff; + } return (isp_target_put_entry(isp, &local)); } @@ -3642,7 +3651,8 @@ isp_action(struct cam_sim *sim, union ccb *ccb) xpt_done(ccb); break; } - if (isp_handle_platform_target_notify_ack(isp, &ntp->rd.nt)) { + if (isp_handle_platform_target_notify_ack(isp, &ntp->rd.nt, + (ccb->ccb_h.flags & CAM_SEND_STATUS) ? ccb->cna2.arg : 0)) { rls_lun_statep(isp, tptr); cam_freeze_devq(ccb->ccb_h.path); cam_release_devq(ccb->ccb_h.path, RELSIM_RELEASE_AFTER_TIMEOUT, 0, 1000, 0); @@ -4407,11 +4417,11 @@ changed: /* * This is device arrival/departure notification */ - isp_handle_platform_target_notify_ack(isp, notify); + isp_handle_platform_target_notify_ack(isp, notify, 0); break; default: isp_prt(isp, ISP_LOGALL, "target notify code 0x%x", notify->nt_ncode); - isp_handle_platform_target_notify_ack(isp, notify); + isp_handle_platform_target_notify_ack(isp, notify, 0); break; } break; |