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 ***
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to