summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/pci/isp_pci.c122
1 files changed, 85 insertions, 37 deletions
diff --git a/sys/pci/isp_pci.c b/sys/pci/isp_pci.c
index ebbb82874682..cf153b35838d 100644
--- a/sys/pci/isp_pci.c
+++ b/sys/pci/isp_pci.c
@@ -240,6 +240,7 @@ static device_method_t isp_pci_methods[] = {
DEVMETHOD(device_attach, isp_pci_attach),
{ 0, 0 }
};
+static void isp_pci_intr __P((void *));
static driver_t isp_pci_driver = {
"isp", isp_pci_methods, sizeof (struct isp_pcisoftc)
@@ -579,7 +580,7 @@ isp_pci_attach(device_t dev)
isp_debug = 0;
(void) getenv_int("isp_debug", &isp_debug);
- if (bus_setup_intr(dev, irq, INTR_TYPE_CAM, (void (*)(void *))isp_intr,
+ if (bus_setup_intr(dev, irq, INTR_TYPE_CAM, isp_pci_intr,
isp, &pcs->ih)) {
device_printf(dev, "could not setup interrupt\n");
goto bad;
@@ -659,6 +660,17 @@ bad:
return (ENXIO);
}
+static void
+isp_pci_intr(void *arg)
+{
+ struct ispsoftc *isp = arg;
+ int iok = isp->isp_osinfo.intsok;
+ isp->isp_osinfo.intsok = 0;
+ (void) isp_intr(isp);
+ isp->isp_osinfo.intsok = iok;
+}
+
+
static u_int16_t
isp_pci_rd_reg(isp, regoff)
struct ispsoftc *isp;
@@ -970,8 +982,10 @@ typedef struct {
* mapped and a pointer to a partially filled in already allocated request
* queue entry. We finish the job.
*/
-static void tdma_mk __P((void *, bus_dma_segment_t *, int, int));
-static void tdma_mkfc __P((void *, bus_dma_segment_t *, int, int));
+static void tdma_mk(void *, bus_dma_segment_t *, int, int);
+static void tdma_mkfc(void *, bus_dma_segment_t *, int, int);
+
+#define STATUS_WITH_DATA 1
static void
tdma_mk(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
@@ -986,6 +1000,7 @@ tdma_mk(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
u_int32_t totxfr, sflags;
int nctios, send_status;
int32_t resid;
+ int i, j;
mp = (mush_t *) arg;
if (error) {
@@ -1002,12 +1017,12 @@ tdma_mk(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
if (nseg == 0) {
cto->ct_header.rqs_seqno = 1;
- ISP_TDQE(mp->isp, "tdma_mk[no data]", *mp->iptrp, cto);
isp_prt(mp->isp, ISP_LOGTDEBUG1,
- "CTIO[%x] lun%d->iid%d flgs 0x%x sts 0x%x ssts 0x%x res %d",
+ "CTIO[%x] lun%d iid%d tag %x flgs %x sts %x ssts %x res %d",
cto->ct_fwhandle, csio->ccb_h.target_lun, cto->ct_iid,
- cto->ct_flags, cto->ct_status, cto->ct_scsi_status,
- cto->ct_resid);
+ cto->ct_tag_val, cto->ct_flags, cto->ct_status,
+ cto->ct_scsi_status, cto->ct_resid);
+ ISP_TDQE(mp->isp, "tdma_mk[no data]", *mp->iptrp, cto);
ISP_SWIZ_CTIO(mp->isp, cto, cto);
return;
}
@@ -1018,6 +1033,19 @@ tdma_mk(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
}
/*
+ * Check to see that we don't overflow.
+ */
+ for (i = 0, j = *mp->iptrp; i < nctios; i++) {
+ j = ISP_NXT_QENTRY(j, RQUEST_QUEUE_LEN(isp));
+ if (j == mp->optr) {
+ isp_prt(mp->isp, ISP_LOGWARN,
+ "Request Queue Overflow [tdma_mk]");
+ mp->error = MUSHERR_NOQENTRIES;
+ return;
+ }
+ }
+
+ /*
* Save syshandle, and potentially any SCSI status, which we'll
* reinsert on the last CTIO we're going to send.
*/
@@ -1039,11 +1067,14 @@ tdma_mk(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
*/
scsi_status = cto->ct_scsi_status;
+#ifndef STATUS_WITH_DATA
+ sflags |= CT_NO_DATA;
/*
* We can't do a status at the same time as a data CTIO, so
* we need to synthesize an extra CTIO at this level.
*/
nctios++;
+#endif
} else {
sflags = scsi_status = resid = 0;
}
@@ -1111,28 +1142,30 @@ tdma_mk(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
* this CTIO and save the handle to the CCB such that
* when this CTIO completes we can free dma resources
* and do whatever else we need to do to finish the
- * rest of the command.
+ * rest of the command. We *don't* give this to the
+ * firmware to work on- the caller will do that.
*/
cto->ct_syshandle = handle;
cto->ct_header.rqs_seqno = 1;
if (send_status) {
cto->ct_scsi_status = scsi_status;
- cto->ct_flags |= sflags | CT_NO_DATA;;
+ cto->ct_flags |= sflags;
cto->ct_resid = resid;
}
if (send_status) {
isp_prt(mp->isp, ISP_LOGTDEBUG1,
- "CTIO[%x] lun%d for ID %d ct_flags 0x%x "
+ "CTIO[%x] lun%d iid %d tag %x ct_flags %x "
"scsi status %x resid %d",
cto->ct_fwhandle, csio->ccb_h.target_lun,
- cto->ct_iid, cto->ct_flags,
+ cto->ct_iid, cto->ct_tag_val, cto->ct_flags,
cto->ct_scsi_status, cto->ct_resid);
} else {
isp_prt(mp->isp, ISP_LOGTDEBUG1,
- "CTIO[%x] lun%d for ID%d ct_flags 0x%x",
+ "CTIO[%x] lun%d iid%d tag %x ct_flags 0x%x",
cto->ct_fwhandle, csio->ccb_h.target_lun,
- cto->ct_iid, cto->ct_flags);
+ cto->ct_iid, cto->ct_tag_val,
+ cto->ct_flags);
}
ISP_TDQE(mp->isp, "last tdma_mk", *mp->iptrp, cto);
ISP_SWIZ_CTIO(mp->isp, cto, cto);
@@ -1156,6 +1189,7 @@ tdma_mk(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
*/
cto = (ct_entry_t *)
ISP_QUEUE_ENTRY(mp->isp->isp_rquest, *mp->iptrp);
+ j = *mp->iptrp;
*mp->iptrp =
ISP_NXT_QENTRY(*mp->iptrp, RQUEST_QUEUE_LEN(isp));
if (*mp->iptrp == mp->optr) {
@@ -1186,10 +1220,12 @@ tdma_mk(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
cto->ct_seg_count = 0;
MEMZERO(cto->ct_dataseg, sizeof(cto->ct_dataseg));
/*
- * Now swizzle the old one for the consumption of the
- * chip.
+ * Now swizzle the old one for the consumption
+ * of the chip and give it to the firmware to
+ * work on while we do the next.
*/
ISP_SWIZ_CTIO(mp->isp, octo, octo);
+ ISP_ADD_REQUEST(mp->isp, j);
}
}
}
@@ -1205,7 +1241,7 @@ tdma_mkfc(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
u_int16_t scsi_status, send_status, send_sense, handle;
u_int32_t totxfr, datalen;
u_int8_t sense[QLTM_SENSELEN];
- int nctios;
+ int nctios, j;
mp = (mush_t *) arg;
if (error) {
@@ -1234,9 +1270,9 @@ tdma_mkfc(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
*/
cto->ct_flags |= CT2_NO_DATA;
if (cto->ct_resid > 0)
- cto->ct_flags |= CT2_DATA_UNDER;
+ cto->rsp.m1.ct_scsi_status |= CT2_DATA_UNDER;
else if (cto->ct_resid < 0)
- cto->ct_flags |= CT2_DATA_OVER;
+ cto->rsp.m1.ct_scsi_status |= CT2_DATA_OVER;
cto->ct_seg_count = 0;
cto->ct_reloff = 0;
ISP_TDQE(mp->isp, "dma2_tgt_fc[no data]", *mp->iptrp, cto);
@@ -1276,9 +1312,10 @@ tdma_mkfc(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
handle = cto->ct_syshandle;
cto->ct_syshandle = 0;
+ send_status = (cto->ct_flags & CT2_SENDSTATUS) != 0;
- if ((send_status = (cto->ct_flags & CT2_SENDSTATUS)) != 0) {
- cto->ct_flags &= ~CT2_SENDSTATUS;
+ if (send_status) {
+ cto->ct_flags &= ~(CT2_SENDSTATUS|CT2_CCINCR);
/*
* Preserve residual, which is actually the total count.
@@ -1310,7 +1347,7 @@ tdma_mkfc(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
totxfr = cto->ct_resid = 0;
cto->rsp.m0.ct_scsi_status = 0;
- bzero(&cto->rsp, sizeof (cto->rsp));
+ MEMZERO(&cto->rsp, sizeof (cto->rsp));
pci = (struct isp_pcisoftc *)mp->isp;
dp = &pci->dmaps[isp_handle_index(handle)];
@@ -1381,8 +1418,13 @@ tdma_mkfc(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
cto->ct_header.rqs_seqno = 1;
if (send_status) {
+ /*
+ * Get 'real' residual and set flags based
+ * on it.
+ */
+ cto->ct_resid = datalen - totxfr;
if (send_sense) {
- bcopy(sense, cto->rsp.m1.ct_resp,
+ MEMCPY(cto->rsp.m1.ct_resp, sense,
QLTM_SENSELEN);
cto->rsp.m1.ct_senselen =
QLTM_SENSELEN;
@@ -1391,21 +1433,26 @@ tdma_mkfc(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
scsi_status;
cto->ct_flags &= CT2_FLAG_MMASK;
cto->ct_flags |= CT2_FLAG_MODE1 |
- CT2_NO_DATA| CT2_SENDSTATUS;
+ CT2_NO_DATA | CT2_SENDSTATUS |
+ CT2_CCINCR;
+ if (cto->ct_resid > 0)
+ cto->rsp.m1.ct_scsi_status |=
+ CT2_DATA_UNDER;
+ else if (cto->ct_resid < 0)
+ cto->rsp.m1.ct_scsi_status |=
+ CT2_DATA_OVER;
} else {
cto->rsp.m0.ct_scsi_status =
scsi_status;
- cto->ct_flags |= CT2_SENDSTATUS;
+ cto->ct_flags |=
+ CT2_SENDSTATUS | CT2_CCINCR;
+ if (cto->ct_resid > 0)
+ cto->rsp.m0.ct_scsi_status |=
+ CT2_DATA_UNDER;
+ else if (cto->ct_resid < 0)
+ cto->rsp.m0.ct_scsi_status |=
+ CT2_DATA_OVER;
}
- /*
- * Get 'real' residual and set flags based
- * on it.
- */
- cto->ct_resid = datalen - totxfr;
- if (cto->ct_resid > 0)
- cto->ct_flags |= CT2_DATA_UNDER;
- else if (cto->ct_resid < 0)
- cto->ct_flags |= CT2_DATA_OVER;
}
ISP_TDQE(mp->isp, "last dma2_tgt_fc", *mp->iptrp, cto);
isp_prt(mp->isp, ISP_LOGTDEBUG1,
@@ -1434,6 +1481,7 @@ tdma_mkfc(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
*/
cto = (ct2_entry_t *)
ISP_QUEUE_ENTRY(mp->isp->isp_rquest, *mp->iptrp);
+ j = *mp->iptrp;
*mp->iptrp =
ISP_NXT_QENTRY(*mp->iptrp, RQUEST_QUEUE_LEN(isp));
if (*mp->iptrp == mp->optr) {
@@ -1465,8 +1513,9 @@ tdma_mkfc(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
* just finished filling out.
*/
cto->ct_reloff += octo->rsp.m0.ct_xfrlen;
- bzero(&cto->rsp, sizeof (cto->rsp));
- ISP_SWIZ_CTIO2(isp, cto, cto);
+ MEMZERO(&cto->rsp, sizeof (cto->rsp));
+ ISP_SWIZ_CTIO2(isp, octo, octo);
+ ISP_ADD_REQUEST(mp->isp, j);
}
}
}
@@ -1631,11 +1680,10 @@ isp_pci_dmasetup(struct ispsoftc *isp, struct ccb_scsiio *csio, ispreq_t *rq,
}
if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_NONE ||
(csio->dxfer_len == 0)) {
- rq->req_seg_count = 1;
mp = &mush;
mp->isp = isp;
mp->cmd_token = csio;
- mp->rq = rq;
+ mp->rq = rq; /* really a ct_entry_t or ct2_entry_t */
mp->iptrp = iptrp;
mp->optr = optr;
mp->error = 0;