svn commit: r240016 - stable/9/sys/dev/isp
Matt Jacob
mjacob at FreeBSD.org
Sun Sep 2 15:04:40 UTC 2012
Author: mjacob
Date: Sun Sep 2 15:04:39 2012
New Revision: 240016
URL: http://svn.freebsd.org/changeset/base/240016
Log:
MFC of 239143
More rototilling with target mode in an attemp to get multiple...
Modified:
stable/9/sys/dev/isp/isp_freebsd.c
stable/9/sys/dev/isp/isp_freebsd.h
Directory Properties:
stable/9/sys/ (props changed)
stable/9/sys/dev/ (props changed)
stable/9/sys/dev/isp/ (props changed)
Modified: stable/9/sys/dev/isp/isp_freebsd.c
==============================================================================
--- stable/9/sys/dev/isp/isp_freebsd.c Sun Sep 2 15:03:40 2012 (r240015)
+++ stable/9/sys/dev/isp/isp_freebsd.c Sun Sep 2 15:04:39 2012 (r240016)
@@ -74,6 +74,7 @@ static void isp_action(struct cam_sim *,
static void isp_target_thread_pi(void *);
static void isp_target_thread_fc(void *);
#endif
+static int isp_timer_count;
static void isp_timer(void *);
static struct cdevsw isp_cdevsw = {
@@ -225,7 +226,8 @@ isp_attach(ispsoftc_t *isp)
}
callout_init_mtx(&isp->isp_osinfo.tmo, &isp->isp_osinfo.lock, 0);
- callout_reset(&isp->isp_osinfo.tmo, hz, isp_timer, isp);
+ isp_timer_count = hz >> 2;
+ callout_reset(&isp->isp_osinfo.tmo, isp_timer_count, isp_timer, isp);
isp->isp_osinfo.timer_active = 1;
isp->isp_osinfo.cdev = make_dev(&isp_cdevsw, du, UID_ROOT, GID_OPERATOR, 0600, "%s", nu);
@@ -777,6 +779,7 @@ static ISP_INLINE void
isp_free_pcmd(ispsoftc_t *isp, union ccb *ccb)
{
if (ISP_PCMD(ccb)) {
+ memset(ISP_PCMD(ccb), 0, sizeof (struct isp_pcmd));
((struct isp_pcmd *)ISP_PCMD(ccb))->next = isp->isp_osinfo.pcmd_free;
isp->isp_osinfo.pcmd_free = ISP_PCMD(ccb);
ISP_PCMD(ccb) = NULL;
@@ -813,7 +816,7 @@ static timeout_t isp_refire_putback_atio
static timeout_t isp_refire_notify_ack;
static void isp_complete_ctio(union ccb *);
static void isp_target_putback_atio(union ccb *);
-enum Start_Ctio_How { FROM_CAM, FROM_SRR, FROM_CTIO_DONE };
+enum Start_Ctio_How { FROM_CAM, FROM_TIMER, FROM_SRR, FROM_CTIO_DONE };
static void isp_target_start_ctio(ispsoftc_t *, union ccb *, enum Start_Ctio_How);
static void isp_handle_platform_atio(ispsoftc_t *, at_entry_t *);
static void isp_handle_platform_atio2(ispsoftc_t *, at2_entry_t *);
@@ -975,7 +978,9 @@ static void
isp_tmcmd_restart(ispsoftc_t *isp)
{
inot_private_data_t *ntp;
+ inot_private_data_t *restart_queue;
tstate_t *tptr;
+ union ccb *ccb;
struct tslist *lhp;
int bus, i;
@@ -983,8 +988,8 @@ isp_tmcmd_restart(ispsoftc_t *isp)
for (i = 0; i < LUN_HASH_SIZE; i++) {
ISP_GET_PC_ADDR(isp, bus, lun_hash[i], lhp);
SLIST_FOREACH(tptr, lhp, next) {
- inot_private_data_t *restart_queue = tptr->restart_queue;
- tptr->restart_queue = NULL;
+ if ((restart_queue = tptr->restart_queue) != NULL)
+ tptr->restart_queue = NULL;
while (restart_queue) {
ntp = restart_queue;
restart_queue = ntp->rd.nt.nt_hba;
@@ -1006,6 +1011,14 @@ isp_tmcmd_restart(ispsoftc_t *isp)
break;
}
}
+ /*
+ * We only need to do this once per tptr
+ */
+ if (!TAILQ_EMPTY(&tptr->waitq)) {
+ ccb = (union ccb *)TAILQ_LAST(&tptr->waitq, isp_ccbq);
+ TAILQ_REMOVE(&tptr->waitq, &ccb->ccb_h, periph_links.tqe);
+ isp_target_start_ctio(isp, ccb, FROM_TIMER);
+ }
}
}
}
@@ -1052,8 +1065,8 @@ isp_dump_atpd(ispsoftc_t *isp, tstate_t
if (atp->tag == 0) {
continue;
}
- xpt_print(tptr->owner, "ATP: [0x%x] origdlen %u bytes_xfrd %u last_xfr %u lun %u nphdl 0x%04x s_id 0x%06x d_id 0x%06x oxid 0x%04x state %s\n",
- atp->tag, atp->orig_datalen, atp->bytes_xfered, atp->last_xframt, atp->lun, atp->nphdl, atp->sid, atp->portid, atp->oxid, states[atp->state & 0x7]);
+ xpt_print(tptr->owner, "ATP: [0x%x] origdlen %u bytes_xfrd %u lun %u nphdl 0x%04x s_id 0x%06x d_id 0x%06x oxid 0x%04x state %s\n",
+ atp->tag, atp->orig_datalen, atp->bytes_xfered, atp->lun, atp->nphdl, atp->sid, atp->portid, atp->oxid, states[atp->state & 0x7]);
}
}
@@ -1118,6 +1131,7 @@ create_lun_state(ispsoftc_t *isp, int bu
}
SLIST_INIT(&tptr->atios);
SLIST_INIT(&tptr->inots);
+ TAILQ_INIT(&tptr->waitq);
for (i = 0; i < ATPDPSIZE-1; i++) {
tptr->atpool[i].next = &tptr->atpool[i+1];
tptr->ntpool[i].next = &tptr->ntpool[i+1];
@@ -1534,533 +1548,544 @@ isp_ledone(ispsoftc_t *isp, lun_entry_t
static void
isp_target_start_ctio(ispsoftc_t *isp, union ccb *ccb, enum Start_Ctio_How how)
{
-
- void *qe;
- int fctape, sendstatus, resid, repval = ISP_LOGTDEBUG0;
+ int fctape, sendstatus, resid;
tstate_t *tptr;
fcparam *fcp;
atio_private_data_t *atp;
- struct ccb_scsiio *cso = &ccb->csio;
- uint32_t dmaresult, handle, xfrlen, sense_length;
+ struct ccb_scsiio *cso;
+ uint32_t dmaresult, handle, xfrlen, sense_length, tmp;
uint8_t local[QENTRY_LEN];
- /*
- * Do some sanity checks.
- */
- xfrlen = cso->dxfer_len;
- if (xfrlen == 0) {
- if ((ccb->ccb_h.flags & CAM_SEND_STATUS) == 0) {
- ISP_PATH_PRT(isp, ISP_LOGERR, ccb->ccb_h.path, "a data transfer length of zero but no status to send is wrong\n");
- ccb->ccb_h.status = CAM_REQ_INVALID;
- xpt_done(ccb);
- return;
- }
- }
-
tptr = get_lun_statep(isp, XS_CHANNEL(ccb), XS_LUN(ccb));
if (tptr == NULL) {
tptr = get_lun_statep(isp, XS_CHANNEL(ccb), CAM_LUN_WILDCARD);
if (tptr == NULL) {
- ISP_PATH_PRT(isp, ISP_LOGERR, ccb->ccb_h.path, "%s: [0x%x] cannot find tstate pointer in %s\n", __func__, cso->tag_id);
+ isp_prt(isp, ISP_LOGERR, "%s: [0x%x] cannot find tstate pointer", __func__, ccb->csio.tag_id);
ccb->ccb_h.status = CAM_DEV_NOT_THERE;
xpt_done(ccb);
return;
}
}
+ isp_prt(isp, ISP_LOGTDEBUG0, "%s: ENTRY[0x%x] how %u xfrlen %u sendstatus %d sense_len %u", __func__, ccb->csio.tag_id, how, ccb->csio.dxfer_len,
+ (ccb->ccb_h.flags & CAM_SEND_STATUS) != 0, ((ccb->ccb_h.flags & CAM_SEND_SENSE)? ccb->csio.sense_len : 0));
- atp = isp_get_atpd(isp, tptr, cso->tag_id);
- if (atp == NULL) {
- ISP_PATH_PRT(isp, ISP_LOGERR, ccb->ccb_h.path, "%s: [0x%x] cannot find private data adjunct\n", __func__, cso->tag_id);
- isp_dump_atpd(isp, tptr);
- ccb->ccb_h.status = CAM_REQ_CMP_ERR;
- xpt_done(ccb);
- return;
- }
-
- /*
- * Is this command a dead duck?
- */
- if (atp->dead) {
- ISP_PATH_PRT(isp, ISP_LOGERR, ccb->ccb_h.path, "%s: [0x%x] not sending a CTIO for a dead command\n", __func__, cso->tag_id);
- ccb->ccb_h.status = CAM_REQ_ABORTED;
- xpt_done(ccb);
- return;
+ switch (how) {
+ case FROM_TIMER:
+ case FROM_CAM:
+ /*
+ * Insert at the tail of the list, if any, waiting CTIO CCBs
+ */
+ TAILQ_INSERT_TAIL(&tptr->waitq, &ccb->ccb_h, periph_links.tqe);
+ break;
+ case FROM_SRR:
+ case FROM_CTIO_DONE:
+ TAILQ_INSERT_HEAD(&tptr->waitq, &ccb->ccb_h, periph_links.tqe);
+ break;
}
- /*
- * Check to make sure we're still in target mode.
- */
- fcp = FCPARAM(isp, XS_CHANNEL(ccb));
- if ((fcp->role & ISP_ROLE_TARGET) == 0) {
- ISP_PATH_PRT(isp, ISP_LOGERR, ccb->ccb_h.path, "%s: [0x%x] stopping sending a CTIO because we're no longer in target mode\n", __func__, cso->tag_id);
- ccb->ccb_h.status = CAM_PROVIDE_FAIL;
- xpt_done(ccb);
- return;
- }
+ while (TAILQ_FIRST(&tptr->waitq) != NULL) {
+ ccb = (union ccb *) TAILQ_FIRST(&tptr->waitq);
+ TAILQ_REMOVE(&tptr->waitq, &ccb->ccb_h, periph_links.tqe);
- /*
- * We're only handling one outstanding CTIO at a time (which
- * could be split into two to split data and status)
- */
- if (atp->ctcnt) {
- ISP_PATH_PRT(isp, ISP_LOGINFO, ccb->ccb_h.path, "sending only one CTIO at a time\n");
- goto restart_delay;
- }
+ cso = &ccb->csio;
+ xfrlen = cso->dxfer_len;
+ if (xfrlen == 0) {
+ if ((ccb->ccb_h.flags & CAM_SEND_STATUS) == 0) {
+ ISP_PATH_PRT(isp, ISP_LOGERR, ccb->ccb_h.path, "a data transfer length of zero but no status to send is wrong\n");
+ ccb->ccb_h.status = CAM_REQ_INVALID;
+ xpt_done(ccb);
+ continue;
+ }
+ }
+ atp = isp_get_atpd(isp, tptr, cso->tag_id);
+ if (atp == NULL) {
+ isp_prt(isp, ISP_LOGERR, "%s: [0x%x] cannot find private data adjunct in %s", __func__, cso->tag_id, __func__);
+ isp_dump_atpd(isp, tptr);
+ ccb->ccb_h.status = CAM_REQ_CMP_ERR;
+ xpt_done(ccb);
+ continue;
+ }
- /*
- * Get some resources
- */
- if (isp_get_pcmd(isp, ccb)) {
- ISP_PATH_PRT(isp, ISP_LOGWARN, ccb->ccb_h.path, "out of PCMDs\n");
- goto restart_delay;
- }
- qe = isp_getrqentry(isp);
- if (qe == NULL) {
- ISP_PATH_PRT(isp, ISP_LOGWARN, ccb->ccb_h.path, rqo, __func__);
- goto restart_delay;
- }
- memset(local, 0, QENTRY_LEN);
+ /*
+ * Is this command a dead duck?
+ */
+ if (atp->dead) {
+ isp_prt(isp, ISP_LOGERR, "%s: [0x%x] not sending a CTIO for a dead command", __func__, cso->tag_id);
+ ccb->ccb_h.status = CAM_REQ_ABORTED;
+ xpt_done(ccb);
+ continue;
+ }
- /*
- * Does the initiator expect FC-Tape style responses?
- * Can we provide them?
- */
- if ((atp->word3 & PRLI_WD3_RETRY) && fcp->fctape_enabled) {
- fctape = 1;
- } else {
- fctape = 0;
- }
+ /*
+ * Check to make sure we're still in target mode.
+ */
+ fcp = FCPARAM(isp, XS_CHANNEL(ccb));
+ if ((fcp->role & ISP_ROLE_TARGET) == 0) {
+ isp_prt(isp, ISP_LOGERR, "%s: [0x%x] stopping sending a CTIO because we're no longer in target mode", __func__, cso->tag_id);
+ ccb->ccb_h.status = CAM_PROVIDE_FAIL;
+ xpt_done(ccb);
+ continue;
+ }
- /*
- * If we already did the data xfer portion of a CTIO that sends data
- * and status, don't do it again and do the status portion now.
- */
- if (atp->sendst) {
- xfrlen = 0; /* we already did the data transfer */
- atp->sendst = 0;
- }
- if (ccb->ccb_h.flags & CAM_SEND_STATUS) {
- sendstatus = 1;
- } else {
- sendstatus = 0;
- }
+ /*
+ * We're only handling ATPD_CCB_OUTSTANDING outstanding CCB at a time (one of which
+ * could be split into two CTIOs to split data and status).
+ */
+ if (atp->ctcnt >= ATPD_CCB_OUTSTANDING) {
+ isp_prt(isp, ISP_LOGTINFO, "[0x%x] handling only %d CCBs at a time (flags for this ccb: 0x%x)", cso->tag_id, ATPD_CCB_OUTSTANDING, ccb->ccb_h.flags);
+ TAILQ_INSERT_HEAD(&tptr->waitq, &ccb->ccb_h, periph_links.tqe);
+ break;
+ }
- if (ccb->ccb_h.flags & CAM_SEND_SENSE) {
/*
- * Sense length is not the entire sense data structure size. Periph
- * drivers don't seem to be setting sense_len to reflect the actual
- * size. We'll peek inside to get the right amount.
+ * Does the initiator expect FC-Tape style responses?
*/
- sense_length = cso->sense_len;
+ if ((atp->word3 & PRLI_WD3_RETRY) && fcp->fctape_enabled) {
+ fctape = 1;
+ } else {
+ fctape = 0;
+ }
/*
- * This 'cannot' happen
+ * If we already did the data xfer portion of a CTIO that sends data
+ * and status, don't do it again and do the status portion now.
*/
- if (sense_length > (XCMD_SIZE - MIN_FCP_RESPONSE_SIZE)) {
- sense_length = XCMD_SIZE - MIN_FCP_RESPONSE_SIZE;
+ if (atp->sendst) {
+ isp_prt(isp, ISP_LOGTINFO, "[0x%x] now sending synthesized status orig_dl=%u xfered=%u bit=%u",
+ cso->tag_id, atp->orig_datalen, atp->bytes_xfered, atp->bytes_in_transit);
+ xfrlen = 0; /* we already did the data transfer */
+ atp->sendst = 0;
+ }
+ if (ccb->ccb_h.flags & CAM_SEND_STATUS) {
+ sendstatus = 1;
+ } else {
+ sendstatus = 0;
}
- } else {
- sense_length = 0;
- }
- if (how == FROM_SRR || atp->nsrr)
- repval = ISP_LOGINFO;
+ if (ccb->ccb_h.flags & CAM_SEND_SENSE) {
+ KASSERT((sendstatus != 0), ("how can you have CAM_SEND_SENSE w/o CAM_SEND_STATUS?"));
+ /*
+ * Sense length is not the entire sense data structure size. Periph
+ * drivers don't seem to be setting sense_len to reflect the actual
+ * size. We'll peek inside to get the right amount.
+ */
+ sense_length = cso->sense_len;
- if (IS_24XX(isp)) {
- ct7_entry_t *cto = (ct7_entry_t *) local;
+ /*
+ * This 'cannot' happen
+ */
+ if (sense_length > (XCMD_SIZE - MIN_FCP_RESPONSE_SIZE)) {
+ sense_length = XCMD_SIZE - MIN_FCP_RESPONSE_SIZE;
+ }
+ } else {
+ sense_length = 0;
+ }
- cto->ct_header.rqs_entry_type = RQSTYPE_CTIO7;
- cto->ct_header.rqs_entry_count = 1;
- cto->ct_header.rqs_seqno = 1;
- cto->ct_nphdl = atp->nphdl;
- cto->ct_rxid = atp->tag;
- cto->ct_iid_lo = atp->portid;
- cto->ct_iid_hi = atp->portid >> 16;
- cto->ct_oxid = atp->oxid;
- cto->ct_vpidx = ISP_GET_VPIDX(isp, XS_CHANNEL(ccb));
- cto->ct_timeout = 120;
- cto->ct_flags = atp->tattr << CT7_TASK_ATTR_SHIFT;
+ memset(local, 0, QENTRY_LEN);
/*
- * Mode 1, status, no data. Only possible when we are sending status, have
- * no data to transfer, and any sense length can fit in the ct7_entry.
- *
- * Mode 2, status, no data. We have to use this in the case sense data
- * won't fit into a ct7_entry_t.
- *
+ * Check for overflow
*/
- if (sendstatus && xfrlen == 0) {
- cto->ct_flags |= CT7_SENDSTATUS | CT7_NO_DATA;
- resid = atp->orig_datalen - atp->bytes_xfered;
- if (sense_length <= MAXRESPLEN_24XX) {
- if (resid < 0) {
- cto->ct_resid = -resid;
- } else if (resid > 0) {
- cto->ct_resid = resid;
- }
- cto->ct_flags |= CT7_FLAG_MODE1;
- cto->ct_scsi_status = cso->scsi_status;
- if (resid < 0) {
- cto->ct_scsi_status |= (FCP_RESID_OVERFLOW << 8);
- } else if (resid > 0) {
- cto->ct_scsi_status |= (FCP_RESID_UNDERFLOW << 8);
- }
- if (fctape) {
- cto->ct_flags |= CT7_CONFIRM|CT7_EXPLCT_CONF;
- }
- if (sense_length) {
- cto->ct_scsi_status |= (FCP_SNSLEN_VALID << 8);
- cto->rsp.m1.ct_resplen = cto->ct_senselen = sense_length;
- memcpy(cto->rsp.m1.ct_resp, &cso->sense_data, sense_length);
- }
- } else {
- bus_addr_t addr;
- char buf[XCMD_SIZE];
- fcp_rsp_iu_t *rp;
+ tmp = atp->bytes_xfered + atp->bytes_in_transit + xfrlen;
+ if (tmp > atp->orig_datalen) {
+ isp_prt(isp, ISP_LOGERR, "%s: [0x%x] data overflow by %u bytes", __func__, cso->tag_id, tmp - atp->orig_datalen);
+ ccb->ccb_h.status = CAM_DATA_RUN_ERR;
+ xpt_done(ccb);
+ continue;
+ }
+
+ if (IS_24XX(isp)) {
+ ct7_entry_t *cto = (ct7_entry_t *) local;
+
+ cto->ct_header.rqs_entry_type = RQSTYPE_CTIO7;
+ cto->ct_header.rqs_entry_count = 1;
+ cto->ct_header.rqs_seqno |= ATPD_SEQ_NOTIFY_CAM;
+ ATPD_SET_SEQNO(cto, atp);
+ cto->ct_nphdl = atp->nphdl;
+ cto->ct_rxid = atp->tag;
+ cto->ct_iid_lo = atp->portid;
+ cto->ct_iid_hi = atp->portid >> 16;
+ cto->ct_oxid = atp->oxid;
+ cto->ct_vpidx = ISP_GET_VPIDX(isp, XS_CHANNEL(ccb));
+ cto->ct_timeout = 120;
+ cto->ct_flags = atp->tattr << CT7_TASK_ATTR_SHIFT;
+
+ /*
+ * Mode 1, status, no data. Only possible when we are sending status, have
+ * no data to transfer, and any sense length can fit in the ct7_entry.
+ *
+ * Mode 2, status, no data. We have to use this in the case sense data
+ * won't fit into a ct7_entry_t.
+ *
+ */
+ if (sendstatus && xfrlen == 0) {
+ cto->ct_flags |= CT7_SENDSTATUS | CT7_NO_DATA;
+ resid = atp->orig_datalen - atp->bytes_xfered - atp->bytes_in_transit;
+ if (sense_length <= MAXRESPLEN_24XX) {
+ if (resid < 0) {
+ cto->ct_resid = -resid;
+ } else if (resid > 0) {
+ cto->ct_resid = resid;
+ }
+ cto->ct_flags |= CT7_FLAG_MODE1;
+ cto->ct_scsi_status = cso->scsi_status;
+ if (resid < 0) {
+ cto->ct_scsi_status |= (FCP_RESID_OVERFLOW << 8);
+ } else if (resid > 0) {
+ cto->ct_scsi_status |= (FCP_RESID_UNDERFLOW << 8);
+ }
+ if (fctape) {
+ cto->ct_flags |= CT7_CONFIRM|CT7_EXPLCT_CONF;
+ }
+ if (sense_length) {
+ cto->ct_scsi_status |= (FCP_SNSLEN_VALID << 8);
+ cto->rsp.m1.ct_resplen = cto->ct_senselen = sense_length;
+ memcpy(cto->rsp.m1.ct_resp, &cso->sense_data, sense_length);
+ }
+ } else {
+ bus_addr_t addr;
+ char buf[XCMD_SIZE];
+ fcp_rsp_iu_t *rp;
- if (atp->ests == NULL) {
- atp->ests = isp_get_ecmd(isp);
if (atp->ests == NULL) {
- goto restart_delay;
+ atp->ests = isp_get_ecmd(isp);
+ if (atp->ests == NULL) {
+ TAILQ_INSERT_HEAD(&tptr->waitq, &ccb->ccb_h, periph_links.tqe);
+ break;
+ }
}
- }
- memset(buf, 0, sizeof (buf));
- rp = (fcp_rsp_iu_t *)buf;
- if (fctape) {
- cto->ct_flags |= CT7_CONFIRM|CT7_EXPLCT_CONF;
- rp->fcp_rsp_bits |= FCP_CONF_REQ;
- }
- cto->ct_flags |= CT7_FLAG_MODE2;
- rp->fcp_rsp_scsi_status = cso->scsi_status;
- if (resid < 0) {
- rp->fcp_rsp_resid = -resid;
- rp->fcp_rsp_bits |= FCP_RESID_OVERFLOW;
- } else if (resid > 0) {
- rp->fcp_rsp_resid = resid;
- rp->fcp_rsp_bits |= FCP_RESID_UNDERFLOW;
+ memset(buf, 0, sizeof (buf));
+ rp = (fcp_rsp_iu_t *)buf;
+ if (fctape) {
+ cto->ct_flags |= CT7_CONFIRM|CT7_EXPLCT_CONF;
+ rp->fcp_rsp_bits |= FCP_CONF_REQ;
+ }
+ cto->ct_flags |= CT7_FLAG_MODE2;
+ rp->fcp_rsp_scsi_status = cso->scsi_status;
+ if (resid < 0) {
+ rp->fcp_rsp_resid = -resid;
+ rp->fcp_rsp_bits |= FCP_RESID_OVERFLOW;
+ } else if (resid > 0) {
+ rp->fcp_rsp_resid = resid;
+ rp->fcp_rsp_bits |= FCP_RESID_UNDERFLOW;
+ }
+ if (sense_length) {
+ rp->fcp_rsp_snslen = sense_length;
+ cto->ct_senselen = sense_length;
+ rp->fcp_rsp_bits |= FCP_SNSLEN_VALID;
+ isp_put_fcp_rsp_iu(isp, rp, atp->ests);
+ memcpy(((fcp_rsp_iu_t *)atp->ests)->fcp_rsp_extra, &cso->sense_data, sense_length);
+ } else {
+ isp_put_fcp_rsp_iu(isp, rp, atp->ests);
+ }
+ if (isp->isp_dblev & ISP_LOGTDEBUG1) {
+ isp_print_bytes(isp, "FCP Response Frame After Swizzling", MIN_FCP_RESPONSE_SIZE + sense_length, atp->ests);
+ }
+ addr = isp->isp_osinfo.ecmd_dma;
+ addr += ((((isp_ecmd_t *)atp->ests) - isp->isp_osinfo.ecmd_base) * XCMD_SIZE);
+ isp_prt(isp, ISP_LOGTDEBUG0, "%s: ests base %p vaddr %p ecmd_dma %jx addr %jx len %u", __func__, isp->isp_osinfo.ecmd_base, atp->ests,
+ (uintmax_t) isp->isp_osinfo.ecmd_dma, (uintmax_t)addr, MIN_FCP_RESPONSE_SIZE + sense_length);
+ cto->rsp.m2.ct_datalen = MIN_FCP_RESPONSE_SIZE + sense_length;
+ cto->rsp.m2.ct_fcp_rsp_iudata.ds_base = DMA_LO32(addr);
+ cto->rsp.m2.ct_fcp_rsp_iudata.ds_basehi = DMA_HI32(addr);
+ cto->rsp.m2.ct_fcp_rsp_iudata.ds_count = MIN_FCP_RESPONSE_SIZE + sense_length;
}
if (sense_length) {
- rp->fcp_rsp_snslen = sense_length;
- cto->ct_senselen = sense_length;
- rp->fcp_rsp_bits |= FCP_SNSLEN_VALID;
- isp_put_fcp_rsp_iu(isp, rp, atp->ests);
- memcpy(((fcp_rsp_iu_t *)atp->ests)->fcp_rsp_extra, &cso->sense_data, sense_length);
+ isp_prt(isp, ISP_LOGTDEBUG0, "%s: CTIO7[0x%x] seq %u nc %d CDB0=%x sstatus=0x%x flags=0x%x resid=%d slen %u sense: %x %x/%x/%x", __func__,
+ cto->ct_rxid, ATPD_GET_SEQNO(cto), ATPD_GET_NCAM(cto), atp->cdb0, cto->ct_scsi_status, cto->ct_flags, cto->ct_resid, sense_length,
+ cso->sense_data.error_code, cso->sense_data.sense_buf[1], cso->sense_data.sense_buf[11], cso->sense_data.sense_buf[12]);
} else {
- isp_put_fcp_rsp_iu(isp, rp, atp->ests);
- }
- if (isp->isp_dblev & ISP_LOGTDEBUG1) {
- isp_print_bytes(isp, "FCP Response Frame After Swizzling", MIN_FCP_RESPONSE_SIZE + sense_length, atp->ests);
+ isp_prt(isp, ISP_LOGDEBUG0, "%s: CTIO7[0x%x] seq %u nc %d CDB0=%x sstatus=0x%x flags=0x%x resid=%d", __func__,
+ cto->ct_rxid, ATPD_GET_SEQNO(cto), ATPD_GET_NCAM(cto), atp->cdb0, cto->ct_scsi_status, cto->ct_flags, cto->ct_resid);
}
- addr = isp->isp_osinfo.ecmd_dma;
- addr += ((((isp_ecmd_t *)atp->ests) - isp->isp_osinfo.ecmd_base) * XCMD_SIZE);
- isp_prt(isp, repval, "%s: ests base %p vaddr %p ecmd_dma %jx addr %jx len %u", __func__, isp->isp_osinfo.ecmd_base, atp->ests,
- (uintmax_t) isp->isp_osinfo.ecmd_dma, (uintmax_t)addr, MIN_FCP_RESPONSE_SIZE + sense_length);
- cto->rsp.m2.ct_datalen = MIN_FCP_RESPONSE_SIZE + sense_length;
- cto->rsp.m2.ct_fcp_rsp_iudata.ds_base = DMA_LO32(addr);
- cto->rsp.m2.ct_fcp_rsp_iudata.ds_basehi = DMA_HI32(addr);
- cto->rsp.m2.ct_fcp_rsp_iudata.ds_count = MIN_FCP_RESPONSE_SIZE + sense_length;
- }
- if (sense_length) {
- isp_prt(isp, repval, "%s: CTIO7[0x%x] CDB0=%x sstatus=0x%x flags=0x%x resid=%d slen %u sense: %x %x/%x/%x", __func__,
- cto->ct_rxid, atp->cdb0, cto->ct_scsi_status, cto->ct_flags, cto->ct_resid, sense_length, cso->sense_data.error_code,
- cso->sense_data.sense_buf[1], cso->sense_data.sense_buf[11], cso->sense_data.sense_buf[12]);
- } else {
- isp_prt(isp, repval, "%s: CTIO7[0x%x] CDB0=%x sstatus=0x%x flags=0x%x resid=%d", __func__,
- cto->ct_rxid, atp->cdb0, cto->ct_scsi_status, cto->ct_flags, cto->ct_resid);
- }
- atp->state = ATPD_STATE_LAST_CTIO;
- }
-
- /*
- * Mode 0 data transfers, *possibly* with status.
- */
- if (xfrlen != 0) {
- cto->ct_flags |= CT7_FLAG_MODE0;
- if ((cso->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
- cto->ct_flags |= CT7_DATA_IN;
- } else {
- cto->ct_flags |= CT7_DATA_OUT;
+ atp->state = ATPD_STATE_LAST_CTIO;
}
/*
- * Don't overrun the limits placed on us, but record it as
- * if we had so that we can set an overflow bit later.
+ * Mode 0 data transfers, *possibly* with status.
*/
- atp->last_xframt = xfrlen;
- if (atp->bytes_xfered >= atp->orig_datalen) {
- resid = atp->orig_datalen - (atp->bytes_xfered + xfrlen);
- } else if (atp->bytes_xfered + xfrlen > atp->orig_datalen) {
- resid = atp->orig_datalen - (atp->bytes_xfered + xfrlen);
- xfrlen = atp->orig_datalen - atp->bytes_xfered;
- } else {
- resid = atp->orig_datalen - xfrlen;
- }
- cto->rsp.m0.reloff = atp->bytes_xfered;
- cto->rsp.m0.ct_xfrlen = xfrlen;
+ if (xfrlen != 0) {
+ cto->ct_flags |= CT7_FLAG_MODE0;
+ if ((cso->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
+ cto->ct_flags |= CT7_DATA_IN;
+ } else {
+ cto->ct_flags |= CT7_DATA_OUT;
+ }
+
+ cto->rsp.m0.reloff = atp->bytes_xfered + atp->bytes_in_transit;
+ cto->rsp.m0.ct_xfrlen = xfrlen;
#ifdef DEBUG
- if (ISP_FC_PC(isp, XS_CHANNEL(ccb))->inject_lost_data_frame && xfrlen > ISP_FC_PC(isp, XS_CHANNEL(ccb))->inject_lost_data_frame) {
- isp_prt(isp, ISP_LOGWARN, "%s: truncating data frame with xfrlen %d to %d", __func__, xfrlen, xfrlen - (xfrlen >> 2));
- ISP_FC_PC(isp, XS_CHANNEL(ccb))->inject_lost_data_frame = 0;
- cto->rsp.m0.ct_xfrlen -= xfrlen >> 2;
- }
+ if (ISP_FC_PC(isp, XS_CHANNEL(ccb))->inject_lost_data_frame && xfrlen > ISP_FC_PC(isp, XS_CHANNEL(ccb))->inject_lost_data_frame) {
+ isp_prt(isp, ISP_LOGWARN, "%s: truncating data frame with xfrlen %d to %d", __func__, xfrlen, xfrlen - (xfrlen >> 2));
+ ISP_FC_PC(isp, XS_CHANNEL(ccb))->inject_lost_data_frame = 0;
+ cto->rsp.m0.ct_xfrlen -= xfrlen >> 2;
+ }
#endif
- if (sendstatus) {
- if (cso->scsi_status == SCSI_STATUS_OK && resid == 0 && fctape == 0) {
- cto->ct_flags |= CT7_SENDSTATUS;
- atp->state = ATPD_STATE_LAST_CTIO;
+ if (sendstatus) {
+ resid = atp->orig_datalen - atp->bytes_xfered - xfrlen;
+ if (cso->scsi_status == SCSI_STATUS_OK && resid == 0 /* && fctape == 0 */) {
+ cto->ct_flags |= CT7_SENDSTATUS;
+ atp->state = ATPD_STATE_LAST_CTIO;
+ if (fctape) {
+ cto->ct_flags |= CT7_CONFIRM|CT7_EXPLCT_CONF;
+ }
+ } else {
+ atp->sendst = 1; /* send status later */
+ cto->ct_header.rqs_seqno &= ~ATPD_SEQ_NOTIFY_CAM;
+ atp->state = ATPD_STATE_CTIO;
+ }
} else {
- atp->sendst = 1; /* send status later */
- cto->ct_header.rqs_seqno = 0;
atp->state = ATPD_STATE_CTIO;
}
- } else {
- atp->state = ATPD_STATE_CTIO;
+ isp_prt(isp, ISP_LOGTDEBUG0, "%s: CTIO7[0x%x] seq %u nc %d CDB0=%x sstatus=0x%x flags=0x%x xfrlen=%u off=%u", __func__,
+ cto->ct_rxid, ATPD_GET_SEQNO(cto), ATPD_GET_NCAM(cto), atp->cdb0, cto->ct_scsi_status, cto->ct_flags, xfrlen, atp->bytes_xfered);
}
- isp_prt(isp, repval, "%s: CTIO7[0x%x] CDB0=%x sstatus=0x%x flags=0x%x xfrlen=%u off=%u", __func__,
- cto->ct_rxid, atp->cdb0, cto->ct_scsi_status, cto->ct_flags, xfrlen, atp->bytes_xfered);
- }
- } else if (IS_FC(isp)) {
- ct2_entry_t *cto = (ct2_entry_t *) local;
+ } else if (IS_FC(isp)) {
+ ct2_entry_t *cto = (ct2_entry_t *) local;
- if (isp->isp_osinfo.sixtyfourbit)
- cto->ct_header.rqs_entry_type = RQSTYPE_CTIO3;
- else
- cto->ct_header.rqs_entry_type = RQSTYPE_CTIO2;
- cto->ct_header.rqs_entry_count = 1;
- cto->ct_header.rqs_seqno = 1;
- if (ISP_CAP_2KLOGIN(isp) == 0) {
- ((ct2e_entry_t *)cto)->ct_iid = cso->init_id;
- } else {
- cto->ct_iid = cso->init_id;
- if (ISP_CAP_SCCFW(isp) == 0) {
- cto->ct_lun = ccb->ccb_h.target_lun;
+ if (isp->isp_osinfo.sixtyfourbit)
+ cto->ct_header.rqs_entry_type = RQSTYPE_CTIO3;
+ else
+ cto->ct_header.rqs_entry_type = RQSTYPE_CTIO2;
+ cto->ct_header.rqs_entry_count = 1;
+ cto->ct_header.rqs_seqno |= ATPD_SEQ_NOTIFY_CAM;
+ ATPD_SET_SEQNO(cto, atp);
+ if (ISP_CAP_2KLOGIN(isp) == 0) {
+ ((ct2e_entry_t *)cto)->ct_iid = cso->init_id;
+ } else {
+ cto->ct_iid = cso->init_id;
+ if (ISP_CAP_SCCFW(isp) == 0) {
+ cto->ct_lun = ccb->ccb_h.target_lun;
+ }
}
- }
- cto->ct_timeout = 10;
- cto->ct_rxid = cso->tag_id;
+ cto->ct_timeout = 10;
+ cto->ct_rxid = cso->tag_id;
- /*
- * Mode 1, status, no data. Only possible when we are sending status, have
- * no data to transfer, and the sense length can fit in the ct7_entry.
- *
- * Mode 2, status, no data. We have to use this in the case the the response
- * length won't fit into a ct2_entry_t.
- *
- * We'll fill out this structure with information as if this were a
- * Mode 1. The hardware layer will create the Mode 2 FCP RSP IU as
- * needed based upon this.
- */
- if (sendstatus && xfrlen == 0) {
- cto->ct_flags |= CT2_SENDSTATUS | CT2_NO_DATA;
- resid = atp->orig_datalen - atp->bytes_xfered;
- if (sense_length <= MAXRESPLEN) {
- if (resid < 0) {
- cto->ct_resid = -resid;
- } else if (resid > 0) {
- cto->ct_resid = resid;
- }
- cto->ct_flags |= CT2_FLAG_MODE1;
- cto->rsp.m1.ct_scsi_status = cso->scsi_status;
- if (resid < 0) {
- cto->rsp.m1.ct_scsi_status |= CT2_DATA_OVER;
- } else if (resid > 0) {
- cto->rsp.m1.ct_scsi_status |= CT2_DATA_UNDER;
- }
- if (fctape) {
- cto->ct_flags |= CT2_CONFIRM;
- }
- if (sense_length) {
- cto->rsp.m1.ct_scsi_status |= CT2_SNSLEN_VALID;
- cto->rsp.m1.ct_resplen = cto->rsp.m1.ct_senselen = sense_length;
- memcpy(cto->rsp.m1.ct_resp, &cso->sense_data, sense_length);
- }
- } else {
- bus_addr_t addr;
- char buf[XCMD_SIZE];
- fcp_rsp_iu_t *rp;
+ /*
+ * Mode 1, status, no data. Only possible when we are sending status, have
+ * no data to transfer, and the sense length can fit in the ct7_entry.
+ *
+ * Mode 2, status, no data. We have to use this in the case the the response
+ * length won't fit into a ct2_entry_t.
+ *
+ * We'll fill out this structure with information as if this were a
+ * Mode 1. The hardware layer will create the Mode 2 FCP RSP IU as
+ * needed based upon this.
+ */
+ if (sendstatus && xfrlen == 0) {
+ cto->ct_flags |= CT2_SENDSTATUS | CT2_NO_DATA;
+ resid = atp->orig_datalen - atp->bytes_xfered - atp->bytes_in_transit;
+ if (sense_length <= MAXRESPLEN) {
+ if (resid < 0) {
+ cto->ct_resid = -resid;
+ } else if (resid > 0) {
+ cto->ct_resid = resid;
+ }
+ cto->ct_flags |= CT2_FLAG_MODE1;
+ cto->rsp.m1.ct_scsi_status = cso->scsi_status;
+ if (resid < 0) {
+ cto->rsp.m1.ct_scsi_status |= CT2_DATA_OVER;
+ } else if (resid > 0) {
+ cto->rsp.m1.ct_scsi_status |= CT2_DATA_UNDER;
+ }
+ if (fctape) {
+ cto->ct_flags |= CT2_CONFIRM;
+ }
+ if (sense_length) {
+ cto->rsp.m1.ct_scsi_status |= CT2_SNSLEN_VALID;
+ cto->rsp.m1.ct_resplen = cto->rsp.m1.ct_senselen = sense_length;
+ memcpy(cto->rsp.m1.ct_resp, &cso->sense_data, sense_length);
+ }
+ } else {
+ bus_addr_t addr;
+ char buf[XCMD_SIZE];
+ fcp_rsp_iu_t *rp;
- if (atp->ests == NULL) {
- atp->ests = isp_get_ecmd(isp);
if (atp->ests == NULL) {
- goto restart_delay;
+ atp->ests = isp_get_ecmd(isp);
+ if (atp->ests == NULL) {
+ TAILQ_INSERT_HEAD(&tptr->waitq, &ccb->ccb_h, periph_links.tqe);
+ break;
+ }
+ }
+ memset(buf, 0, sizeof (buf));
+ rp = (fcp_rsp_iu_t *)buf;
+ if (fctape) {
+ cto->ct_flags |= CT2_CONFIRM;
+ rp->fcp_rsp_bits |= FCP_CONF_REQ;
+ }
+ cto->ct_flags |= CT2_FLAG_MODE2;
+ rp->fcp_rsp_scsi_status = cso->scsi_status;
+ if (resid < 0) {
+ rp->fcp_rsp_resid = -resid;
+ rp->fcp_rsp_bits |= FCP_RESID_OVERFLOW;
+ } else if (resid > 0) {
+ rp->fcp_rsp_resid = resid;
+ rp->fcp_rsp_bits |= FCP_RESID_UNDERFLOW;
+ }
+ if (sense_length) {
+ rp->fcp_rsp_snslen = sense_length;
+ rp->fcp_rsp_bits |= FCP_SNSLEN_VALID;
+ isp_put_fcp_rsp_iu(isp, rp, atp->ests);
+ memcpy(((fcp_rsp_iu_t *)atp->ests)->fcp_rsp_extra, &cso->sense_data, sense_length);
+ } else {
+ isp_put_fcp_rsp_iu(isp, rp, atp->ests);
+ }
+ if (isp->isp_dblev & ISP_LOGTDEBUG1) {
+ isp_print_bytes(isp, "FCP Response Frame After Swizzling", MIN_FCP_RESPONSE_SIZE + sense_length, atp->ests);
+ }
+ addr = isp->isp_osinfo.ecmd_dma;
+ addr += ((((isp_ecmd_t *)atp->ests) - isp->isp_osinfo.ecmd_base) * XCMD_SIZE);
+ isp_prt(isp, ISP_LOGTDEBUG0, "%s: ests base %p vaddr %p ecmd_dma %jx addr %jx len %u", __func__, isp->isp_osinfo.ecmd_base, atp->ests,
+ (uintmax_t) isp->isp_osinfo.ecmd_dma, (uintmax_t)addr, MIN_FCP_RESPONSE_SIZE + sense_length);
+ cto->rsp.m2.ct_datalen = MIN_FCP_RESPONSE_SIZE + sense_length;
+ if (isp->isp_osinfo.sixtyfourbit) {
+ cto->rsp.m2.u.ct_fcp_rsp_iudata_64.ds_base = DMA_LO32(addr);
+ cto->rsp.m2.u.ct_fcp_rsp_iudata_64.ds_basehi = DMA_HI32(addr);
+ cto->rsp.m2.u.ct_fcp_rsp_iudata_64.ds_count = MIN_FCP_RESPONSE_SIZE + sense_length;
+ } else {
+ cto->rsp.m2.u.ct_fcp_rsp_iudata_32.ds_base = DMA_LO32(addr);
+ cto->rsp.m2.u.ct_fcp_rsp_iudata_32.ds_count = MIN_FCP_RESPONSE_SIZE + sense_length;
}
- }
- memset(buf, 0, sizeof (buf));
- rp = (fcp_rsp_iu_t *)buf;
- if (fctape) {
- cto->ct_flags |= CT2_CONFIRM;
- rp->fcp_rsp_bits |= FCP_CONF_REQ;
- }
- cto->ct_flags |= CT2_FLAG_MODE2;
- rp->fcp_rsp_scsi_status = cso->scsi_status;
- if (resid < 0) {
- rp->fcp_rsp_resid = -resid;
- rp->fcp_rsp_bits |= FCP_RESID_OVERFLOW;
- } else if (resid > 0) {
- rp->fcp_rsp_resid = resid;
- rp->fcp_rsp_bits |= FCP_RESID_UNDERFLOW;
}
if (sense_length) {
- rp->fcp_rsp_snslen = sense_length;
- rp->fcp_rsp_bits |= FCP_SNSLEN_VALID;
- isp_put_fcp_rsp_iu(isp, rp, atp->ests);
- memcpy(((fcp_rsp_iu_t *)atp->ests)->fcp_rsp_extra, &cso->sense_data, sense_length);
+ isp_prt(isp, ISP_LOGTDEBUG0, "%s: CTIO2[0x%x] seq %u nc %d CDB0=%x sstatus=0x%x flags=0x%x resid=%d sense: %x %x/%x/%x", __func__,
+ cto->ct_rxid, ATPD_GET_SEQNO(cto), ATPD_GET_NCAM(cto), atp->cdb0, cso->scsi_status, cto->ct_flags, cto->ct_resid,
+ cso->sense_data.error_code, cso->sense_data.sense_buf[1], cso->sense_data.sense_buf[11], cso->sense_data.sense_buf[12]);
} else {
- isp_put_fcp_rsp_iu(isp, rp, atp->ests);
- }
- if (isp->isp_dblev & ISP_LOGTDEBUG1) {
- isp_print_bytes(isp, "FCP Response Frame After Swizzling", MIN_FCP_RESPONSE_SIZE + sense_length, atp->ests);
+ isp_prt(isp, ISP_LOGTDEBUG0, "%s: CTIO2[0x%x] seq %u nc %d CDB0=%x sstatus=0x%x flags=0x%x resid=%d", __func__, cto->ct_rxid,
+ ATPD_GET_SEQNO(cto), ATPD_GET_NCAM(cto), atp->cdb0, cso->scsi_status, cto->ct_flags, cto->ct_resid);
}
- addr = isp->isp_osinfo.ecmd_dma;
- addr += ((((isp_ecmd_t *)atp->ests) - isp->isp_osinfo.ecmd_base) * XCMD_SIZE);
- isp_prt(isp, repval, "%s: ests base %p vaddr %p ecmd_dma %jx addr %jx len %u", __func__, isp->isp_osinfo.ecmd_base, atp->ests,
- (uintmax_t) isp->isp_osinfo.ecmd_dma, (uintmax_t)addr, MIN_FCP_RESPONSE_SIZE + sense_length);
- cto->rsp.m2.ct_datalen = MIN_FCP_RESPONSE_SIZE + sense_length;
- if (isp->isp_osinfo.sixtyfourbit) {
- cto->rsp.m2.u.ct_fcp_rsp_iudata_64.ds_base = DMA_LO32(addr);
- cto->rsp.m2.u.ct_fcp_rsp_iudata_64.ds_basehi = DMA_HI32(addr);
- cto->rsp.m2.u.ct_fcp_rsp_iudata_64.ds_count = MIN_FCP_RESPONSE_SIZE + sense_length;
+ atp->state = ATPD_STATE_LAST_CTIO;
+ }
+
+ if (xfrlen != 0) {
+ cto->ct_flags |= CT2_FLAG_MODE0;
+ if ((cso->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
+ cto->ct_flags |= CT2_DATA_IN;
} else {
- cto->rsp.m2.u.ct_fcp_rsp_iudata_32.ds_base = DMA_LO32(addr);
- cto->rsp.m2.u.ct_fcp_rsp_iudata_32.ds_count = MIN_FCP_RESPONSE_SIZE + sense_length;
+ cto->ct_flags |= CT2_DATA_OUT;
}
- }
- if (sense_length) {
- isp_prt(isp, repval, "%s: CTIO2[0x%x] CDB0=%x sstatus=0x%x flags=0x%x resid=%d sense: %x %x/%x/%x", __func__,
- cto->ct_rxid, atp->cdb0, cso->scsi_status, cto->ct_flags, cto->ct_resid, cso->sense_data.error_code,
- cso->sense_data.sense_buf[1], cso->sense_data.sense_buf[11], cso->sense_data.sense_buf[12]);
- } else {
- isp_prt(isp, repval, "%s: CTIO2[0x%x] CDB0=%x sstatus=0x%x flags=0x%x resid=%d", __func__,
- cto->ct_rxid, atp->cdb0, cso->scsi_status, cto->ct_flags, cto->ct_resid);
- }
- atp->state = ATPD_STATE_LAST_CTIO;
- }
- if (xfrlen != 0) {
- int resid = 0;
- cto->ct_flags |= CT2_FLAG_MODE0;
- if ((cso->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
- cto->ct_flags |= CT2_DATA_IN;
- } else {
- cto->ct_flags |= CT2_DATA_OUT;
- }
+ cto->ct_reloff = atp->bytes_xfered + atp->bytes_in_transit;
+ cto->rsp.m0.ct_xfrlen = xfrlen;
- /*
- * Don't overrun the limits placed on us, but record it as
- * if we had so that we can set an overflow bit later.
- */
- atp->last_xframt = xfrlen;
- if (atp->bytes_xfered + xfrlen > atp->orig_datalen) {
- resid = 1;
- xfrlen = atp->orig_datalen - atp->bytes_xfered;
- }
- cto->ct_reloff = atp->bytes_xfered;
- cto->rsp.m0.ct_xfrlen = xfrlen;
-
- if (sendstatus) {
- if (cso->scsi_status == SCSI_STATUS_OK && resid == 0 && fctape == 0) {
- cto->ct_flags |= CT2_SENDSTATUS;
- atp->state = ATPD_STATE_LAST_CTIO;
+ if (sendstatus) {
+ resid = atp->orig_datalen - atp->bytes_xfered - xfrlen;
+ if (cso->scsi_status == SCSI_STATUS_OK && resid == 0 /*&& fctape == 0*/) {
+ cto->ct_flags |= CT2_SENDSTATUS;
+ atp->state = ATPD_STATE_LAST_CTIO;
+ if (fctape) {
+ cto->ct_flags |= CT2_CONFIRM;
+ }
+ } else {
+ atp->sendst = 1; /* send status later */
+ cto->ct_header.rqs_seqno &= ~ATPD_SEQ_NOTIFY_CAM;
+ atp->state = ATPD_STATE_CTIO;
+ }
} else {
- atp->sendst = 1; /* send status later */
- cto->ct_header.rqs_seqno = 0;
atp->state = ATPD_STATE_CTIO;
}
+ }
+ isp_prt(isp, ISP_LOGTDEBUG0, "%s: CTIO2[%x] seq %u nc %d CDB0=%x scsi status %x flags %x resid %d xfrlen %u offset %u", __func__, cto->ct_rxid,
+ ATPD_GET_SEQNO(cto), ATPD_GET_NCAM(cto), atp->cdb0, cso->scsi_status, cto->ct_flags, cto->ct_resid, cso->dxfer_len, atp->bytes_xfered);
+ } else {
+ ct_entry_t *cto = (ct_entry_t *) local;
+
+ cto->ct_header.rqs_entry_type = RQSTYPE_CTIO;
+ cto->ct_header.rqs_entry_count = 1;
+ cto->ct_header.rqs_seqno |= ATPD_SEQ_NOTIFY_CAM;
+ ATPD_SET_SEQNO(cto, atp);
+ cto->ct_iid = cso->init_id;
+ cto->ct_iid |= XS_CHANNEL(ccb) << 7;
+ cto->ct_tgt = ccb->ccb_h.target_id;
+ cto->ct_lun = ccb->ccb_h.target_lun;
+ cto->ct_fwhandle = cso->tag_id;
+ if (atp->rxid) {
+ cto->ct_tag_val = atp->rxid;
+ cto->ct_flags |= CT_TQAE;
+ }
+ if (ccb->ccb_h.flags & CAM_DIS_DISCONNECT) {
+ cto->ct_flags |= CT_NODISC;
+ }
+ if (cso->dxfer_len == 0) {
+ cto->ct_flags |= CT_NO_DATA;
+ } else if ((cso->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
+ cto->ct_flags |= CT_DATA_IN;
} else {
- atp->state = ATPD_STATE_CTIO;
+ cto->ct_flags |= CT_DATA_OUT;
+ }
+ if (ccb->ccb_h.flags & CAM_SEND_STATUS) {
+ cto->ct_flags |= CT_SENDSTATUS|CT_CCINCR;
+ cto->ct_scsi_status = cso->scsi_status;
+ cto->ct_resid = atp->orig_datalen - atp->bytes_xfered - atp->bytes_in_transit - xfrlen;
+ isp_prt(isp, ISP_LOGTDEBUG0, "%s: CTIO[%x] seq %u nc %d scsi status %x resid %d tag_id %x", __func__,
+ cto->ct_fwhandle, ATPD_GET_SEQNO(cto), ATPD_GET_NCAM(cto), cso->scsi_status, cso->resid, cso->tag_id);
}
+ ccb->ccb_h.flags &= ~CAM_SEND_SENSE;
+ cto->ct_timeout = 10;
}
- isp_prt(isp, ISP_LOGTDEBUG0, "%s: CTIO2[%x] CDB0=%x scsi status %x flags %x resid %d xfrlen %u offset %u", __func__, cto->ct_rxid,
- atp->cdb0, cso->scsi_status, cto->ct_flags, cto->ct_resid, cso->dxfer_len, atp->bytes_xfered);
- } else {
- ct_entry_t *cto = (ct_entry_t *) local;
- cto->ct_header.rqs_entry_type = RQSTYPE_CTIO;
- cto->ct_header.rqs_entry_count = 1;
- cto->ct_header.rqs_seqno = 1;
- cto->ct_iid = cso->init_id;
- cto->ct_iid |= XS_CHANNEL(ccb) << 7;
- cto->ct_tgt = ccb->ccb_h.target_id;
- cto->ct_lun = ccb->ccb_h.target_lun;
- cto->ct_fwhandle = cso->tag_id;
- if (atp->rxid) {
- cto->ct_tag_val = atp->rxid;
- cto->ct_flags |= CT_TQAE;
- }
- if (ccb->ccb_h.flags & CAM_DIS_DISCONNECT) {
- cto->ct_flags |= CT_NODISC;
- }
- if (cso->dxfer_len == 0) {
- cto->ct_flags |= CT_NO_DATA;
- } else if ((cso->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
- cto->ct_flags |= CT_DATA_IN;
- } else {
- cto->ct_flags |= CT_DATA_OUT;
+ if (isp_get_pcmd(isp, ccb)) {
+ ISP_PATH_PRT(isp, ISP_LOGWARN, ccb->ccb_h.path, "out of PCMDs\n");
+ TAILQ_INSERT_HEAD(&tptr->waitq, &ccb->ccb_h, periph_links.tqe);
+ break;
}
- if (ccb->ccb_h.flags & CAM_SEND_STATUS) {
- cto->ct_flags |= CT_SENDSTATUS|CT_CCINCR;
- cto->ct_scsi_status = cso->scsi_status;
- cto->ct_resid = cso->resid;
- isp_prt(isp, ISP_LOGTDEBUG0, "%s: CTIO[%x] scsi status %x resid %d tag_id %x", __func__,
- cto->ct_fwhandle, cso->scsi_status, cso->resid, cso->tag_id);
+ if (isp_allocate_xs_tgt(isp, ccb, &handle)) {
+ ISP_PATH_PRT(isp, ISP_LOGWARN, ccb->ccb_h.path, "No XFLIST pointers for %s\n", __func__);
+ TAILQ_INSERT_HEAD(&tptr->waitq, &ccb->ccb_h, periph_links.tqe);
+ isp_free_pcmd(isp, ccb);
+ break;
}
- ccb->ccb_h.flags &= ~CAM_SEND_SENSE;
- cto->ct_timeout = 10;
- }
+ atp->bytes_in_transit += xfrlen;
+ PISP_PCMD(ccb)->datalen = xfrlen;
- if (isp_allocate_xs_tgt(isp, ccb, &handle)) {
- ISP_PATH_PRT(isp, ISP_LOGWARN, ccb->ccb_h.path, "No XFLIST pointers for %s\n", __func__);
- goto restart_delay;
- }
- /*
- * Call the dma setup routines for this entry (and any subsequent
- * CTIOs) if there's data to move, and then tell the f/w it's got
- * new things to play with. As with isp_start's usage of DMA setup,
- * any swizzling is done in the machine dependent layer. Because
- * of this, we put the request onto the queue area first in native
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-all
mailing list