mirror of
https://git.FreeBSD.org/src.git
synced 2025-01-18 15:30:21 +00:00
Keep interrupts blocked for all of isp_pci_attach. Redo DMA routines
for target mode for cleanliness and accuracy.
This commit is contained in:
parent
5ce6286805
commit
05fbcbb000
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=63380
@ -537,11 +537,12 @@ isp_pci_attach(device_t dev)
|
|||||||
data = pci_read_config(dev, PCIR_ROMADDR, 4);
|
data = pci_read_config(dev, PCIR_ROMADDR, 4);
|
||||||
data &= ~1;
|
data &= ~1;
|
||||||
pci_write_config(dev, PCIR_ROMADDR, data, 4);
|
pci_write_config(dev, PCIR_ROMADDR, data, 4);
|
||||||
splx(s);
|
|
||||||
|
|
||||||
if (bus_dma_tag_create(NULL, 1, 0, BUS_SPACE_MAXADDR_32BIT,
|
if (bus_dma_tag_create(NULL, 1, 0, BUS_SPACE_MAXADDR_32BIT,
|
||||||
BUS_SPACE_MAXADDR, NULL, NULL, lim + 1,
|
BUS_SPACE_MAXADDR, NULL, NULL, lim + 1,
|
||||||
255, lim, 0, &pcs->parent_dmat) != 0) {
|
255, lim, 0, &pcs->parent_dmat) != 0) {
|
||||||
|
splx(s);
|
||||||
printf("%s: could not create master dma tag\n", isp->isp_name);
|
printf("%s: could not create master dma tag\n", isp->isp_name);
|
||||||
free(isp->isp_param, M_DEVBUF);
|
free(isp->isp_param, M_DEVBUF);
|
||||||
free(pcs, M_DEVBUF);
|
free(pcs, M_DEVBUF);
|
||||||
@ -614,7 +615,6 @@ isp_pci_attach(device_t dev)
|
|||||||
#ifdef ISP_TARGET_MODE
|
#ifdef ISP_TARGET_MODE
|
||||||
(void) getenv_int("isp_tdebug", &isp_tdebug);
|
(void) getenv_int("isp_tdebug", &isp_tdebug);
|
||||||
#endif
|
#endif
|
||||||
s = splbio();
|
|
||||||
if (bus_setup_intr(dev, irq, INTR_TYPE_CAM, (void (*)(void *))isp_intr,
|
if (bus_setup_intr(dev, irq, INTR_TYPE_CAM, (void (*)(void *))isp_intr,
|
||||||
isp, &pcs->ih)) {
|
isp, &pcs->ih)) {
|
||||||
splx(s);
|
splx(s);
|
||||||
@ -622,6 +622,9 @@ isp_pci_attach(device_t dev)
|
|||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Make sure we're in reset state.
|
||||||
|
*/
|
||||||
isp_reset(isp);
|
isp_reset(isp);
|
||||||
if (isp->isp_state != ISP_RESETSTATE) {
|
if (isp->isp_state != ISP_RESETSTATE) {
|
||||||
splx(s);
|
splx(s);
|
||||||
@ -987,63 +990,87 @@ typedef struct {
|
|||||||
* mapped and a pointer to a partially filled in already allocated request
|
* mapped and a pointer to a partially filled in already allocated request
|
||||||
* queue entry. We finish the job.
|
* queue entry. We finish the job.
|
||||||
*/
|
*/
|
||||||
static void dma2_tgt __P((void *, bus_dma_segment_t *, int, int));
|
static void tdma_mk __P((void *, bus_dma_segment_t *, int, int));
|
||||||
static void dma2_tgt_fc __P((void *, bus_dma_segment_t *, int, int));
|
static void tdma_mkfc __P((void *, bus_dma_segment_t *, int, int));
|
||||||
|
|
||||||
static void
|
static void
|
||||||
dma2_tgt(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
|
tdma_mk(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
|
||||||
{
|
{
|
||||||
mush_t *mp;
|
mush_t *mp;
|
||||||
struct ccb_scsiio *csio;
|
struct ccb_scsiio *csio;
|
||||||
struct isp_pcisoftc *pci;
|
struct isp_pcisoftc *pci;
|
||||||
bus_dmamap_t *dp;
|
bus_dmamap_t *dp;
|
||||||
u_int8_t scsi_status, send_status;
|
u_int8_t scsi_status;
|
||||||
ct_entry_t *cto;
|
ct_entry_t *cto;
|
||||||
u_int32_t handle;
|
u_int32_t handle, totxfr, sflags;
|
||||||
int nctios;
|
int nctios, send_status;
|
||||||
|
int32_t resid;
|
||||||
|
|
||||||
mp = (mush_t *) arg;
|
mp = (mush_t *) arg;
|
||||||
if (error) {
|
if (error) {
|
||||||
mp->error = error;
|
mp->error = error;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
csio = mp->cmd_token;
|
csio = mp->cmd_token;
|
||||||
cto = mp->rq;
|
cto = mp->rq;
|
||||||
|
|
||||||
cto->ct_xfrlen = 0;
|
cto->ct_xfrlen = 0;
|
||||||
cto->ct_resid = 0;
|
|
||||||
cto->ct_seg_count = 0;
|
cto->ct_seg_count = 0;
|
||||||
bzero(cto->ct_dataseg, sizeof (cto->ct_dataseg));
|
cto->ct_header.rqs_entry_count = 1;
|
||||||
|
MEMZERO(cto->ct_dataseg, sizeof(cto->ct_dataseg));
|
||||||
|
|
||||||
if (nseg == 0) {
|
if (nseg == 0) {
|
||||||
cto->ct_header.rqs_entry_count = 1;
|
cto->ct_header.rqs_seqno = 1;
|
||||||
ISP_TDQE(mp->isp, "dma2_tgt[no data]", *mp->iptrp, cto);
|
ISP_TDQE(mp->isp, "tdma_mk[no data]", *mp->iptrp, cto);
|
||||||
if (isp_tdebug) {
|
if (isp_tdebug) {
|
||||||
printf("%s:CTIO lun %d->iid%d flgs 0x%x sts 0x%x ssts "
|
printf("%s:CTIO lun %d->iid%d flgs 0x%x sts 0x%x ssts "
|
||||||
"0x%x res %u\n", mp->isp->isp_name,
|
"0x%x res %d\n", mp->isp->isp_name,
|
||||||
csio->ccb_h.target_lun, cto->ct_iid, cto->ct_flags,
|
csio->ccb_h.target_lun, cto->ct_iid, cto->ct_flags,
|
||||||
cto->ct_status, cto->ct_scsi_status, cto->ct_resid);
|
cto->ct_status, cto->ct_scsi_status, cto->ct_resid);
|
||||||
}
|
}
|
||||||
ISP_SWIZ_CTIO(isp, cto, cto);
|
ISP_SWIZ_CTIO(mp->isp, cto, cto);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Save handle, and potentially any SCSI status, which
|
|
||||||
* we'll reinsert on the last CTIO we're going to send.
|
|
||||||
*/
|
|
||||||
handle = cto->ct_reserved;
|
|
||||||
cto->ct_reserved = 0;
|
|
||||||
scsi_status = cto->ct_scsi_status;
|
|
||||||
cto->ct_scsi_status = 0;
|
|
||||||
send_status = cto->ct_flags & CT_SENDSTATUS;
|
|
||||||
cto->ct_flags &= ~CT_SENDSTATUS;
|
|
||||||
|
|
||||||
nctios = nseg / ISP_RQDSEG;
|
nctios = nseg / ISP_RQDSEG;
|
||||||
if (nseg % ISP_RQDSEG) {
|
if (nseg % ISP_RQDSEG) {
|
||||||
nctios++;
|
nctios++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Save handle, and potentially any SCSI status, which we'll reinsert
|
||||||
|
* on the last CTIO we're going to send.
|
||||||
|
*/
|
||||||
|
handle = cto->ct_reserved;
|
||||||
|
cto->ct_reserved = 0;
|
||||||
|
cto->ct_header.rqs_seqno = 0;
|
||||||
|
send_status = (cto->ct_flags & CT_SENDSTATUS) != 0;
|
||||||
|
|
||||||
|
if (send_status) {
|
||||||
|
sflags = cto->ct_flags & (CT_SENDSTATUS | CT_CCINCR);
|
||||||
|
cto->ct_flags &= ~(CT_SENDSTATUS | CT_CCINCR);
|
||||||
|
/*
|
||||||
|
* Preserve residual.
|
||||||
|
*/
|
||||||
|
resid = cto->ct_resid;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Save actual SCSI status.
|
||||||
|
*/
|
||||||
|
scsi_status = cto->ct_scsi_status;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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++;
|
||||||
|
} else {
|
||||||
|
sflags = scsi_status = resid = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
totxfr = cto->ct_resid = 0;
|
||||||
|
cto->ct_scsi_status = 0;
|
||||||
|
|
||||||
pci = (struct isp_pcisoftc *)mp->isp;
|
pci = (struct isp_pcisoftc *)mp->isp;
|
||||||
dp = &pci->dmaps[isp_handle_index(handle)];
|
dp = &pci->dmaps[isp_handle_index(handle)];
|
||||||
if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
|
if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
|
||||||
@ -1054,65 +1081,104 @@ dma2_tgt(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
|
|||||||
|
|
||||||
|
|
||||||
while (nctios--) {
|
while (nctios--) {
|
||||||
int seg, seglim;
|
int seglim;
|
||||||
|
|
||||||
seglim = nseg;
|
seglim = nseg;
|
||||||
if (seglim > ISP_RQDSEG)
|
if (seglim) {
|
||||||
seglim = ISP_RQDSEG;
|
int seg;
|
||||||
|
|
||||||
for (seg = 0; seg < seglim; seg++) {
|
if (seglim > ISP_RQDSEG)
|
||||||
cto->ct_dataseg[seg].ds_base = dm_segs->ds_addr;
|
seglim = ISP_RQDSEG;
|
||||||
cto->ct_dataseg[seg].ds_count = dm_segs->ds_len;
|
|
||||||
cto->ct_xfrlen += dm_segs->ds_len;
|
|
||||||
dm_segs++;
|
|
||||||
}
|
|
||||||
|
|
||||||
cto->ct_seg_count = seg;
|
for (seg = 0; seg < seglim; seg++, nseg--) {
|
||||||
cto->ct_flags &= CT_DATAMASK;
|
/*
|
||||||
if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
|
* Unlike normal initiator commands, we don't
|
||||||
cto->ct_flags |= CT_DATA_IN;
|
* do any swizzling here.
|
||||||
|
*/
|
||||||
|
cto->ct_dataseg[seg].ds_count = dm_segs->ds_len;
|
||||||
|
cto->ct_dataseg[seg].ds_base = dm_segs->ds_addr;
|
||||||
|
cto->ct_xfrlen += dm_segs->ds_len;
|
||||||
|
totxfr += dm_segs->ds_len;
|
||||||
|
dm_segs++;
|
||||||
|
}
|
||||||
|
cto->ct_seg_count = seg;
|
||||||
} else {
|
} else {
|
||||||
cto->ct_flags |= CT_DATA_OUT;
|
/*
|
||||||
|
* This case should only happen when we're sending an
|
||||||
|
* extra CTIO with final status.
|
||||||
|
*/
|
||||||
|
if (send_status == 0) {
|
||||||
|
printf("%s: tdma_mk ran out of segments\n",
|
||||||
|
mp->isp->isp_name);
|
||||||
|
mp->error = EINVAL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* At this point, the fields ct_lun, ct_iid, ct_tagval,
|
||||||
|
* ct_tagtype, and ct_timeout have been carried over
|
||||||
|
* unchanged from what our caller had set.
|
||||||
|
*
|
||||||
|
* The dataseg fields and the seg_count fields we just got
|
||||||
|
* through setting. The data direction we've preserved all
|
||||||
|
* along and only clear it if we're now sending status.
|
||||||
|
*/
|
||||||
|
|
||||||
if (nctios == 0) {
|
if (nctios == 0) {
|
||||||
/*
|
/*
|
||||||
* We're the last in a sequence of CTIOs, so mark this
|
* We're the last in a sequence of CTIOs, so mark
|
||||||
* CTIO and save the handle to the CCB such that when
|
* this CTIO and save the handle to the CCB such that
|
||||||
* this CTIO completes we can free dma resources and
|
* when this CTIO completes we can free dma resources
|
||||||
* do whatever else we need to do to finish the rest
|
* and do whatever else we need to do to finish the
|
||||||
* of the command.
|
* rest of the command.
|
||||||
*/
|
*/
|
||||||
cto->ct_header.rqs_seqno = 1;
|
|
||||||
cto->ct_reserved = handle;
|
cto->ct_reserved = handle;
|
||||||
cto->ct_scsi_status = scsi_status;
|
cto->ct_header.rqs_seqno = 1;
|
||||||
cto->ct_flags |= send_status;
|
|
||||||
ISP_TDQE(mp->isp, "last dma2_tgt", *mp->iptrp, cto);
|
if (send_status) {
|
||||||
if (isp_tdebug) {
|
cto->ct_scsi_status = scsi_status;
|
||||||
printf("%s:CTIO lun %d->iid%d flgs 0x%x sts "
|
cto->ct_flags |= sflags | CT_NO_DATA;;
|
||||||
"0x%x ssts 0x%x res %u\n",
|
cto->ct_resid = resid;
|
||||||
mp->isp->isp_name, csio->ccb_h.target_lun,
|
|
||||||
cto->ct_iid, cto->ct_flags, cto->ct_status,
|
|
||||||
cto->ct_scsi_status, cto->ct_resid);
|
|
||||||
}
|
}
|
||||||
ISP_SWIZ_CTIO(isp, cto, cto);
|
if (isp_tdebug && send_status) {
|
||||||
|
printf("%s:CTIO lun%d for ID%d ct_flags 0x%x "
|
||||||
|
"scsi_status 0x%x res %d\n",
|
||||||
|
mp->isp->isp_name, csio->ccb_h.target_lun,
|
||||||
|
cto->ct_iid, cto->ct_flags,
|
||||||
|
cto->ct_scsi_status, cto->ct_resid);
|
||||||
|
} else if (isp_tdebug) {
|
||||||
|
printf("%s:CTIO lun%d for ID%d ct_flags 0x%x\n",
|
||||||
|
mp->isp->isp_name, csio->ccb_h.target_lun,
|
||||||
|
cto->ct_iid, cto->ct_flags);
|
||||||
|
}
|
||||||
|
ISP_TDQE(mp->isp, "last tdma_mk", *mp->iptrp, cto);
|
||||||
|
ISP_SWIZ_CTIO(mp->isp, cto, cto);
|
||||||
} else {
|
} else {
|
||||||
ct_entry_t *octo = cto;
|
ct_entry_t *octo = cto;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Make sure handle fields are clean
|
||||||
|
*/
|
||||||
cto->ct_reserved = 0;
|
cto->ct_reserved = 0;
|
||||||
cto->ct_header.rqs_seqno = 0;
|
cto->ct_header.rqs_seqno = 0;
|
||||||
ISP_TDQE(mp->isp, "dma2_tgt", *mp->iptrp, cto);
|
|
||||||
if (isp_tdebug) {
|
if (isp_tdebug) {
|
||||||
printf("%s:CTIO lun %d->iid%d flgs 0x%x res"
|
printf("%s:CTIO lun%d for ID%d ct_flags 0x%x\n",
|
||||||
" %u\n", mp->isp->isp_name,
|
mp->isp->isp_name, csio->ccb_h.target_lun,
|
||||||
csio->ccb_h.target_lun, cto->ct_iid,
|
cto->ct_iid, cto->ct_flags);
|
||||||
cto->ct_flags, cto->ct_resid);
|
|
||||||
}
|
}
|
||||||
|
ISP_TDQE(mp->isp, "tdma_mk", *mp->iptrp, cto);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get a new CTIO
|
||||||
|
*/
|
||||||
cto = (ct_entry_t *)
|
cto = (ct_entry_t *)
|
||||||
ISP_QUEUE_ENTRY(mp->isp->isp_rquest, *mp->iptrp);
|
ISP_QUEUE_ENTRY(mp->isp->isp_rquest, *mp->iptrp);
|
||||||
*mp->iptrp =
|
*mp->iptrp =
|
||||||
ISP_NXT_QENTRY(*mp->iptrp, RQUEST_QUEUE_LEN);
|
ISP_NXT_QENTRY(*mp->iptrp, RQUEST_QUEUE_LEN);
|
||||||
if (*mp->iptrp == mp->optr) {
|
if (*mp->iptrp == mp->optr) {
|
||||||
printf("%s: Queue Overflow in dma2_tgt\n",
|
printf("%s: Queue Overflow in tdma_mk\n",
|
||||||
mp->isp->isp_name);
|
mp->isp->isp_name);
|
||||||
mp->error = MUSHERR_NOQENTRIES;
|
mp->error = MUSHERR_NOQENTRIES;
|
||||||
return;
|
return;
|
||||||
@ -1123,12 +1189,11 @@ dma2_tgt(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
|
|||||||
cto->ct_header.rqs_entry_type = RQSTYPE_CTIO;
|
cto->ct_header.rqs_entry_type = RQSTYPE_CTIO;
|
||||||
cto->ct_header.rqs_entry_count = 1;
|
cto->ct_header.rqs_entry_count = 1;
|
||||||
cto->ct_header.rqs_flags = 0;
|
cto->ct_header.rqs_flags = 0;
|
||||||
/* ct_header.rqs_seqno && ct_reserved filled in later */
|
|
||||||
cto->ct_lun = octo->ct_lun;
|
cto->ct_lun = octo->ct_lun;
|
||||||
cto->ct_iid = octo->ct_iid;
|
cto->ct_iid = octo->ct_iid;
|
||||||
cto->ct_reserved2 = octo->ct_reserved2;
|
cto->ct_reserved2 = octo->ct_reserved2;
|
||||||
cto->ct_tgt = octo->ct_tgt;
|
cto->ct_tgt = octo->ct_tgt;
|
||||||
cto->ct_flags = octo->ct_flags & ~CT_DATAMASK;
|
cto->ct_flags = octo->ct_flags;
|
||||||
cto->ct_status = 0;
|
cto->ct_status = 0;
|
||||||
cto->ct_scsi_status = 0;
|
cto->ct_scsi_status = 0;
|
||||||
cto->ct_tag_val = octo->ct_tag_val;
|
cto->ct_tag_val = octo->ct_tag_val;
|
||||||
@ -1137,14 +1202,18 @@ dma2_tgt(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
|
|||||||
cto->ct_resid = 0;
|
cto->ct_resid = 0;
|
||||||
cto->ct_timeout = octo->ct_timeout;
|
cto->ct_timeout = octo->ct_timeout;
|
||||||
cto->ct_seg_count = 0;
|
cto->ct_seg_count = 0;
|
||||||
bzero(cto->ct_dataseg, sizeof (cto->ct_dataseg));
|
MEMZERO(cto->ct_dataseg, sizeof(cto->ct_dataseg));
|
||||||
ISP_SWIZ_CTIO(isp, octo, octo);
|
/*
|
||||||
|
* Now swizzle the old one for the consumption of the
|
||||||
|
* chip.
|
||||||
|
*/
|
||||||
|
ISP_SWIZ_CTIO(mp->isp, octo, octo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
dma2_tgt_fc(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
|
tdma_mkfc(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
|
||||||
{
|
{
|
||||||
mush_t *mp;
|
mush_t *mp;
|
||||||
struct ccb_scsiio *csio;
|
struct ccb_scsiio *csio;
|
||||||
@ -1152,10 +1221,9 @@ dma2_tgt_fc(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
|
|||||||
bus_dmamap_t *dp;
|
bus_dmamap_t *dp;
|
||||||
ct2_entry_t *cto;
|
ct2_entry_t *cto;
|
||||||
u_int16_t scsi_status, send_status, send_sense;
|
u_int16_t scsi_status, send_status, send_sense;
|
||||||
u_int32_t handle, totxfr;
|
u_int32_t handle, totxfr, datalen;
|
||||||
u_int8_t sense[QLTM_SENSELEN];
|
u_int8_t sense[QLTM_SENSELEN];
|
||||||
int nctios;
|
int nctios;
|
||||||
int32_t resid;
|
|
||||||
|
|
||||||
mp = (mush_t *) arg;
|
mp = (mush_t *) arg;
|
||||||
if (error) {
|
if (error) {
|
||||||
@ -1174,6 +1242,7 @@ dma2_tgt_fc(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
cto->ct_header.rqs_entry_count = 1;
|
cto->ct_header.rqs_entry_count = 1;
|
||||||
|
cto->ct_header.rqs_seqno = 1;
|
||||||
/* ct_reserved contains the handle set by caller */
|
/* ct_reserved contains the handle set by caller */
|
||||||
/*
|
/*
|
||||||
* We preserve ct_lun, ct_iid, ct_rxid. We set the data
|
* We preserve ct_lun, ct_iid, ct_rxid. We set the data
|
||||||
@ -1181,13 +1250,17 @@ dma2_tgt_fc(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
|
|||||||
* We preserve the ct_resid and the response area.
|
* We preserve the ct_resid and the response area.
|
||||||
*/
|
*/
|
||||||
cto->ct_flags |= CT2_NO_DATA;
|
cto->ct_flags |= CT2_NO_DATA;
|
||||||
|
if (cto->ct_resid > 0)
|
||||||
|
cto->ct_flags |= CT2_DATA_UNDER;
|
||||||
|
else if (cto->ct_resid < 0)
|
||||||
|
cto->ct_flags |= CT2_DATA_OVER;
|
||||||
cto->ct_seg_count = 0;
|
cto->ct_seg_count = 0;
|
||||||
cto->ct_reloff = 0;
|
cto->ct_reloff = 0;
|
||||||
ISP_TDQE(mp->isp, "dma2_tgt_fc[no data]", *mp->iptrp, cto);
|
ISP_TDQE(mp->isp, "dma2_tgt_fc[no data]", *mp->iptrp, cto);
|
||||||
if (isp_tdebug) {
|
if (isp_tdebug) {
|
||||||
scsi_status = cto->rsp.m1.ct_scsi_status;
|
scsi_status = cto->rsp.m1.ct_scsi_status;
|
||||||
printf("%s:CTIO2 RX_ID 0x%x lun %d->iid%d flgs 0x%x "
|
printf("%s:CTIO2 RX_ID 0x%x lun %d->iid%d flgs 0x%x "
|
||||||
"sts 0x%x ssts 0x%x res %u\n", mp->isp->isp_name,
|
"sts 0x%x ssts 0x%x res %d\n", mp->isp->isp_name,
|
||||||
cto->ct_rxid, csio->ccb_h.target_lun, cto->ct_iid,
|
cto->ct_rxid, csio->ccb_h.target_lun, cto->ct_iid,
|
||||||
cto->ct_flags, cto->ct_status,
|
cto->ct_flags, cto->ct_status,
|
||||||
cto->rsp.m1.ct_scsi_status, cto->ct_resid);
|
cto->rsp.m1.ct_scsi_status, cto->ct_resid);
|
||||||
@ -1227,9 +1300,9 @@ dma2_tgt_fc(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
|
|||||||
cto->ct_flags &= ~CT2_SENDSTATUS;
|
cto->ct_flags &= ~CT2_SENDSTATUS;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Preserve residual.
|
* Preserve residual, which is actually the total count.
|
||||||
*/
|
*/
|
||||||
resid = cto->ct_resid;
|
datalen = cto->ct_resid;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Save actual SCSI status. We'll reinsert the
|
* Save actual SCSI status. We'll reinsert the
|
||||||
@ -1251,7 +1324,7 @@ dma2_tgt_fc(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
|
|||||||
nctios++;
|
nctios++;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
scsi_status = send_sense = resid = 0;
|
scsi_status = send_sense = datalen = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
totxfr = cto->ct_resid = 0;
|
totxfr = cto->ct_resid = 0;
|
||||||
@ -1342,12 +1415,20 @@ dma2_tgt_fc(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
|
|||||||
scsi_status;
|
scsi_status;
|
||||||
cto->ct_flags |= CT2_SENDSTATUS;
|
cto->ct_flags |= CT2_SENDSTATUS;
|
||||||
}
|
}
|
||||||
cto->ct_resid = resid - totxfr;
|
/*
|
||||||
|
* 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_TDQE(mp->isp, "last dma2_tgt_fc", *mp->iptrp, cto);
|
||||||
if (isp_tdebug) {
|
if (isp_tdebug) {
|
||||||
printf("%s:CTIO2 RX_ID 0x%x lun %d->iid%d flgs"
|
printf("%s:CTIO2 RX_ID 0x%x lun %d->iid%d flgs"
|
||||||
"0x%x sts 0x%x ssts 0x%x res %u\n",
|
"0x%x sts 0x%x ssts 0x%x res %d\n",
|
||||||
mp->isp->isp_name, cto->ct_rxid,
|
mp->isp->isp_name, cto->ct_rxid,
|
||||||
csio->ccb_h.target_lun, (int) cto->ct_iid,
|
csio->ccb_h.target_lun, (int) cto->ct_iid,
|
||||||
cto->ct_flags, cto->ct_status,
|
cto->ct_flags, cto->ct_status,
|
||||||
@ -1564,11 +1645,12 @@ isp_pci_dmasetup(struct ispsoftc *isp, struct ccb_scsiio *csio, ispreq_t *rq,
|
|||||||
#ifdef ISP_TARGET_MODE
|
#ifdef ISP_TARGET_MODE
|
||||||
if (csio->ccb_h.func_code == XPT_CONT_TARGET_IO) {
|
if (csio->ccb_h.func_code == XPT_CONT_TARGET_IO) {
|
||||||
if (IS_FC(isp)) {
|
if (IS_FC(isp)) {
|
||||||
eptr = dma2_tgt_fc;
|
eptr = tdma_mkfc;
|
||||||
} else {
|
} else {
|
||||||
eptr = dma2_tgt;
|
eptr = tdma_mk;
|
||||||
}
|
}
|
||||||
if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_NONE) {
|
if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_NONE ||
|
||||||
|
(csio->dxfer_len == 0)) {
|
||||||
rq->req_seg_count = 1;
|
rq->req_seg_count = 1;
|
||||||
mp = &mush;
|
mp = &mush;
|
||||||
mp->isp = isp;
|
mp->isp = isp;
|
||||||
@ -1590,7 +1672,8 @@ isp_pci_dmasetup(struct ispsoftc *isp, struct ccb_scsiio *csio, ispreq_t *rq,
|
|||||||
* NB: that move no data. For commands that move data,
|
* NB: that move no data. For commands that move data,
|
||||||
* NB: swizzling would take place in those functions.
|
* NB: swizzling would take place in those functions.
|
||||||
*/
|
*/
|
||||||
if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_NONE) {
|
if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_NONE ||
|
||||||
|
(csio->dxfer_len == 0)) {
|
||||||
rq->req_seg_count = 1;
|
rq->req_seg_count = 1;
|
||||||
return (CMD_QUEUED);
|
return (CMD_QUEUED);
|
||||||
}
|
}
|
||||||
|
@ -537,11 +537,12 @@ isp_pci_attach(device_t dev)
|
|||||||
data = pci_read_config(dev, PCIR_ROMADDR, 4);
|
data = pci_read_config(dev, PCIR_ROMADDR, 4);
|
||||||
data &= ~1;
|
data &= ~1;
|
||||||
pci_write_config(dev, PCIR_ROMADDR, data, 4);
|
pci_write_config(dev, PCIR_ROMADDR, data, 4);
|
||||||
splx(s);
|
|
||||||
|
|
||||||
if (bus_dma_tag_create(NULL, 1, 0, BUS_SPACE_MAXADDR_32BIT,
|
if (bus_dma_tag_create(NULL, 1, 0, BUS_SPACE_MAXADDR_32BIT,
|
||||||
BUS_SPACE_MAXADDR, NULL, NULL, lim + 1,
|
BUS_SPACE_MAXADDR, NULL, NULL, lim + 1,
|
||||||
255, lim, 0, &pcs->parent_dmat) != 0) {
|
255, lim, 0, &pcs->parent_dmat) != 0) {
|
||||||
|
splx(s);
|
||||||
printf("%s: could not create master dma tag\n", isp->isp_name);
|
printf("%s: could not create master dma tag\n", isp->isp_name);
|
||||||
free(isp->isp_param, M_DEVBUF);
|
free(isp->isp_param, M_DEVBUF);
|
||||||
free(pcs, M_DEVBUF);
|
free(pcs, M_DEVBUF);
|
||||||
@ -614,7 +615,6 @@ isp_pci_attach(device_t dev)
|
|||||||
#ifdef ISP_TARGET_MODE
|
#ifdef ISP_TARGET_MODE
|
||||||
(void) getenv_int("isp_tdebug", &isp_tdebug);
|
(void) getenv_int("isp_tdebug", &isp_tdebug);
|
||||||
#endif
|
#endif
|
||||||
s = splbio();
|
|
||||||
if (bus_setup_intr(dev, irq, INTR_TYPE_CAM, (void (*)(void *))isp_intr,
|
if (bus_setup_intr(dev, irq, INTR_TYPE_CAM, (void (*)(void *))isp_intr,
|
||||||
isp, &pcs->ih)) {
|
isp, &pcs->ih)) {
|
||||||
splx(s);
|
splx(s);
|
||||||
@ -622,6 +622,9 @@ isp_pci_attach(device_t dev)
|
|||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Make sure we're in reset state.
|
||||||
|
*/
|
||||||
isp_reset(isp);
|
isp_reset(isp);
|
||||||
if (isp->isp_state != ISP_RESETSTATE) {
|
if (isp->isp_state != ISP_RESETSTATE) {
|
||||||
splx(s);
|
splx(s);
|
||||||
@ -987,63 +990,87 @@ typedef struct {
|
|||||||
* mapped and a pointer to a partially filled in already allocated request
|
* mapped and a pointer to a partially filled in already allocated request
|
||||||
* queue entry. We finish the job.
|
* queue entry. We finish the job.
|
||||||
*/
|
*/
|
||||||
static void dma2_tgt __P((void *, bus_dma_segment_t *, int, int));
|
static void tdma_mk __P((void *, bus_dma_segment_t *, int, int));
|
||||||
static void dma2_tgt_fc __P((void *, bus_dma_segment_t *, int, int));
|
static void tdma_mkfc __P((void *, bus_dma_segment_t *, int, int));
|
||||||
|
|
||||||
static void
|
static void
|
||||||
dma2_tgt(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
|
tdma_mk(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
|
||||||
{
|
{
|
||||||
mush_t *mp;
|
mush_t *mp;
|
||||||
struct ccb_scsiio *csio;
|
struct ccb_scsiio *csio;
|
||||||
struct isp_pcisoftc *pci;
|
struct isp_pcisoftc *pci;
|
||||||
bus_dmamap_t *dp;
|
bus_dmamap_t *dp;
|
||||||
u_int8_t scsi_status, send_status;
|
u_int8_t scsi_status;
|
||||||
ct_entry_t *cto;
|
ct_entry_t *cto;
|
||||||
u_int32_t handle;
|
u_int32_t handle, totxfr, sflags;
|
||||||
int nctios;
|
int nctios, send_status;
|
||||||
|
int32_t resid;
|
||||||
|
|
||||||
mp = (mush_t *) arg;
|
mp = (mush_t *) arg;
|
||||||
if (error) {
|
if (error) {
|
||||||
mp->error = error;
|
mp->error = error;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
csio = mp->cmd_token;
|
csio = mp->cmd_token;
|
||||||
cto = mp->rq;
|
cto = mp->rq;
|
||||||
|
|
||||||
cto->ct_xfrlen = 0;
|
cto->ct_xfrlen = 0;
|
||||||
cto->ct_resid = 0;
|
|
||||||
cto->ct_seg_count = 0;
|
cto->ct_seg_count = 0;
|
||||||
bzero(cto->ct_dataseg, sizeof (cto->ct_dataseg));
|
cto->ct_header.rqs_entry_count = 1;
|
||||||
|
MEMZERO(cto->ct_dataseg, sizeof(cto->ct_dataseg));
|
||||||
|
|
||||||
if (nseg == 0) {
|
if (nseg == 0) {
|
||||||
cto->ct_header.rqs_entry_count = 1;
|
cto->ct_header.rqs_seqno = 1;
|
||||||
ISP_TDQE(mp->isp, "dma2_tgt[no data]", *mp->iptrp, cto);
|
ISP_TDQE(mp->isp, "tdma_mk[no data]", *mp->iptrp, cto);
|
||||||
if (isp_tdebug) {
|
if (isp_tdebug) {
|
||||||
printf("%s:CTIO lun %d->iid%d flgs 0x%x sts 0x%x ssts "
|
printf("%s:CTIO lun %d->iid%d flgs 0x%x sts 0x%x ssts "
|
||||||
"0x%x res %u\n", mp->isp->isp_name,
|
"0x%x res %d\n", mp->isp->isp_name,
|
||||||
csio->ccb_h.target_lun, cto->ct_iid, cto->ct_flags,
|
csio->ccb_h.target_lun, cto->ct_iid, cto->ct_flags,
|
||||||
cto->ct_status, cto->ct_scsi_status, cto->ct_resid);
|
cto->ct_status, cto->ct_scsi_status, cto->ct_resid);
|
||||||
}
|
}
|
||||||
ISP_SWIZ_CTIO(isp, cto, cto);
|
ISP_SWIZ_CTIO(mp->isp, cto, cto);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Save handle, and potentially any SCSI status, which
|
|
||||||
* we'll reinsert on the last CTIO we're going to send.
|
|
||||||
*/
|
|
||||||
handle = cto->ct_reserved;
|
|
||||||
cto->ct_reserved = 0;
|
|
||||||
scsi_status = cto->ct_scsi_status;
|
|
||||||
cto->ct_scsi_status = 0;
|
|
||||||
send_status = cto->ct_flags & CT_SENDSTATUS;
|
|
||||||
cto->ct_flags &= ~CT_SENDSTATUS;
|
|
||||||
|
|
||||||
nctios = nseg / ISP_RQDSEG;
|
nctios = nseg / ISP_RQDSEG;
|
||||||
if (nseg % ISP_RQDSEG) {
|
if (nseg % ISP_RQDSEG) {
|
||||||
nctios++;
|
nctios++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Save handle, and potentially any SCSI status, which we'll reinsert
|
||||||
|
* on the last CTIO we're going to send.
|
||||||
|
*/
|
||||||
|
handle = cto->ct_reserved;
|
||||||
|
cto->ct_reserved = 0;
|
||||||
|
cto->ct_header.rqs_seqno = 0;
|
||||||
|
send_status = (cto->ct_flags & CT_SENDSTATUS) != 0;
|
||||||
|
|
||||||
|
if (send_status) {
|
||||||
|
sflags = cto->ct_flags & (CT_SENDSTATUS | CT_CCINCR);
|
||||||
|
cto->ct_flags &= ~(CT_SENDSTATUS | CT_CCINCR);
|
||||||
|
/*
|
||||||
|
* Preserve residual.
|
||||||
|
*/
|
||||||
|
resid = cto->ct_resid;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Save actual SCSI status.
|
||||||
|
*/
|
||||||
|
scsi_status = cto->ct_scsi_status;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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++;
|
||||||
|
} else {
|
||||||
|
sflags = scsi_status = resid = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
totxfr = cto->ct_resid = 0;
|
||||||
|
cto->ct_scsi_status = 0;
|
||||||
|
|
||||||
pci = (struct isp_pcisoftc *)mp->isp;
|
pci = (struct isp_pcisoftc *)mp->isp;
|
||||||
dp = &pci->dmaps[isp_handle_index(handle)];
|
dp = &pci->dmaps[isp_handle_index(handle)];
|
||||||
if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
|
if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
|
||||||
@ -1054,65 +1081,104 @@ dma2_tgt(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
|
|||||||
|
|
||||||
|
|
||||||
while (nctios--) {
|
while (nctios--) {
|
||||||
int seg, seglim;
|
int seglim;
|
||||||
|
|
||||||
seglim = nseg;
|
seglim = nseg;
|
||||||
if (seglim > ISP_RQDSEG)
|
if (seglim) {
|
||||||
seglim = ISP_RQDSEG;
|
int seg;
|
||||||
|
|
||||||
for (seg = 0; seg < seglim; seg++) {
|
if (seglim > ISP_RQDSEG)
|
||||||
cto->ct_dataseg[seg].ds_base = dm_segs->ds_addr;
|
seglim = ISP_RQDSEG;
|
||||||
cto->ct_dataseg[seg].ds_count = dm_segs->ds_len;
|
|
||||||
cto->ct_xfrlen += dm_segs->ds_len;
|
|
||||||
dm_segs++;
|
|
||||||
}
|
|
||||||
|
|
||||||
cto->ct_seg_count = seg;
|
for (seg = 0; seg < seglim; seg++, nseg--) {
|
||||||
cto->ct_flags &= CT_DATAMASK;
|
/*
|
||||||
if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
|
* Unlike normal initiator commands, we don't
|
||||||
cto->ct_flags |= CT_DATA_IN;
|
* do any swizzling here.
|
||||||
|
*/
|
||||||
|
cto->ct_dataseg[seg].ds_count = dm_segs->ds_len;
|
||||||
|
cto->ct_dataseg[seg].ds_base = dm_segs->ds_addr;
|
||||||
|
cto->ct_xfrlen += dm_segs->ds_len;
|
||||||
|
totxfr += dm_segs->ds_len;
|
||||||
|
dm_segs++;
|
||||||
|
}
|
||||||
|
cto->ct_seg_count = seg;
|
||||||
} else {
|
} else {
|
||||||
cto->ct_flags |= CT_DATA_OUT;
|
/*
|
||||||
|
* This case should only happen when we're sending an
|
||||||
|
* extra CTIO with final status.
|
||||||
|
*/
|
||||||
|
if (send_status == 0) {
|
||||||
|
printf("%s: tdma_mk ran out of segments\n",
|
||||||
|
mp->isp->isp_name);
|
||||||
|
mp->error = EINVAL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* At this point, the fields ct_lun, ct_iid, ct_tagval,
|
||||||
|
* ct_tagtype, and ct_timeout have been carried over
|
||||||
|
* unchanged from what our caller had set.
|
||||||
|
*
|
||||||
|
* The dataseg fields and the seg_count fields we just got
|
||||||
|
* through setting. The data direction we've preserved all
|
||||||
|
* along and only clear it if we're now sending status.
|
||||||
|
*/
|
||||||
|
|
||||||
if (nctios == 0) {
|
if (nctios == 0) {
|
||||||
/*
|
/*
|
||||||
* We're the last in a sequence of CTIOs, so mark this
|
* We're the last in a sequence of CTIOs, so mark
|
||||||
* CTIO and save the handle to the CCB such that when
|
* this CTIO and save the handle to the CCB such that
|
||||||
* this CTIO completes we can free dma resources and
|
* when this CTIO completes we can free dma resources
|
||||||
* do whatever else we need to do to finish the rest
|
* and do whatever else we need to do to finish the
|
||||||
* of the command.
|
* rest of the command.
|
||||||
*/
|
*/
|
||||||
cto->ct_header.rqs_seqno = 1;
|
|
||||||
cto->ct_reserved = handle;
|
cto->ct_reserved = handle;
|
||||||
cto->ct_scsi_status = scsi_status;
|
cto->ct_header.rqs_seqno = 1;
|
||||||
cto->ct_flags |= send_status;
|
|
||||||
ISP_TDQE(mp->isp, "last dma2_tgt", *mp->iptrp, cto);
|
if (send_status) {
|
||||||
if (isp_tdebug) {
|
cto->ct_scsi_status = scsi_status;
|
||||||
printf("%s:CTIO lun %d->iid%d flgs 0x%x sts "
|
cto->ct_flags |= sflags | CT_NO_DATA;;
|
||||||
"0x%x ssts 0x%x res %u\n",
|
cto->ct_resid = resid;
|
||||||
mp->isp->isp_name, csio->ccb_h.target_lun,
|
|
||||||
cto->ct_iid, cto->ct_flags, cto->ct_status,
|
|
||||||
cto->ct_scsi_status, cto->ct_resid);
|
|
||||||
}
|
}
|
||||||
ISP_SWIZ_CTIO(isp, cto, cto);
|
if (isp_tdebug && send_status) {
|
||||||
|
printf("%s:CTIO lun%d for ID%d ct_flags 0x%x "
|
||||||
|
"scsi_status 0x%x res %d\n",
|
||||||
|
mp->isp->isp_name, csio->ccb_h.target_lun,
|
||||||
|
cto->ct_iid, cto->ct_flags,
|
||||||
|
cto->ct_scsi_status, cto->ct_resid);
|
||||||
|
} else if (isp_tdebug) {
|
||||||
|
printf("%s:CTIO lun%d for ID%d ct_flags 0x%x\n",
|
||||||
|
mp->isp->isp_name, csio->ccb_h.target_lun,
|
||||||
|
cto->ct_iid, cto->ct_flags);
|
||||||
|
}
|
||||||
|
ISP_TDQE(mp->isp, "last tdma_mk", *mp->iptrp, cto);
|
||||||
|
ISP_SWIZ_CTIO(mp->isp, cto, cto);
|
||||||
} else {
|
} else {
|
||||||
ct_entry_t *octo = cto;
|
ct_entry_t *octo = cto;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Make sure handle fields are clean
|
||||||
|
*/
|
||||||
cto->ct_reserved = 0;
|
cto->ct_reserved = 0;
|
||||||
cto->ct_header.rqs_seqno = 0;
|
cto->ct_header.rqs_seqno = 0;
|
||||||
ISP_TDQE(mp->isp, "dma2_tgt", *mp->iptrp, cto);
|
|
||||||
if (isp_tdebug) {
|
if (isp_tdebug) {
|
||||||
printf("%s:CTIO lun %d->iid%d flgs 0x%x res"
|
printf("%s:CTIO lun%d for ID%d ct_flags 0x%x\n",
|
||||||
" %u\n", mp->isp->isp_name,
|
mp->isp->isp_name, csio->ccb_h.target_lun,
|
||||||
csio->ccb_h.target_lun, cto->ct_iid,
|
cto->ct_iid, cto->ct_flags);
|
||||||
cto->ct_flags, cto->ct_resid);
|
|
||||||
}
|
}
|
||||||
|
ISP_TDQE(mp->isp, "tdma_mk", *mp->iptrp, cto);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get a new CTIO
|
||||||
|
*/
|
||||||
cto = (ct_entry_t *)
|
cto = (ct_entry_t *)
|
||||||
ISP_QUEUE_ENTRY(mp->isp->isp_rquest, *mp->iptrp);
|
ISP_QUEUE_ENTRY(mp->isp->isp_rquest, *mp->iptrp);
|
||||||
*mp->iptrp =
|
*mp->iptrp =
|
||||||
ISP_NXT_QENTRY(*mp->iptrp, RQUEST_QUEUE_LEN);
|
ISP_NXT_QENTRY(*mp->iptrp, RQUEST_QUEUE_LEN);
|
||||||
if (*mp->iptrp == mp->optr) {
|
if (*mp->iptrp == mp->optr) {
|
||||||
printf("%s: Queue Overflow in dma2_tgt\n",
|
printf("%s: Queue Overflow in tdma_mk\n",
|
||||||
mp->isp->isp_name);
|
mp->isp->isp_name);
|
||||||
mp->error = MUSHERR_NOQENTRIES;
|
mp->error = MUSHERR_NOQENTRIES;
|
||||||
return;
|
return;
|
||||||
@ -1123,12 +1189,11 @@ dma2_tgt(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
|
|||||||
cto->ct_header.rqs_entry_type = RQSTYPE_CTIO;
|
cto->ct_header.rqs_entry_type = RQSTYPE_CTIO;
|
||||||
cto->ct_header.rqs_entry_count = 1;
|
cto->ct_header.rqs_entry_count = 1;
|
||||||
cto->ct_header.rqs_flags = 0;
|
cto->ct_header.rqs_flags = 0;
|
||||||
/* ct_header.rqs_seqno && ct_reserved filled in later */
|
|
||||||
cto->ct_lun = octo->ct_lun;
|
cto->ct_lun = octo->ct_lun;
|
||||||
cto->ct_iid = octo->ct_iid;
|
cto->ct_iid = octo->ct_iid;
|
||||||
cto->ct_reserved2 = octo->ct_reserved2;
|
cto->ct_reserved2 = octo->ct_reserved2;
|
||||||
cto->ct_tgt = octo->ct_tgt;
|
cto->ct_tgt = octo->ct_tgt;
|
||||||
cto->ct_flags = octo->ct_flags & ~CT_DATAMASK;
|
cto->ct_flags = octo->ct_flags;
|
||||||
cto->ct_status = 0;
|
cto->ct_status = 0;
|
||||||
cto->ct_scsi_status = 0;
|
cto->ct_scsi_status = 0;
|
||||||
cto->ct_tag_val = octo->ct_tag_val;
|
cto->ct_tag_val = octo->ct_tag_val;
|
||||||
@ -1137,14 +1202,18 @@ dma2_tgt(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
|
|||||||
cto->ct_resid = 0;
|
cto->ct_resid = 0;
|
||||||
cto->ct_timeout = octo->ct_timeout;
|
cto->ct_timeout = octo->ct_timeout;
|
||||||
cto->ct_seg_count = 0;
|
cto->ct_seg_count = 0;
|
||||||
bzero(cto->ct_dataseg, sizeof (cto->ct_dataseg));
|
MEMZERO(cto->ct_dataseg, sizeof(cto->ct_dataseg));
|
||||||
ISP_SWIZ_CTIO(isp, octo, octo);
|
/*
|
||||||
|
* Now swizzle the old one for the consumption of the
|
||||||
|
* chip.
|
||||||
|
*/
|
||||||
|
ISP_SWIZ_CTIO(mp->isp, octo, octo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
dma2_tgt_fc(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
|
tdma_mkfc(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
|
||||||
{
|
{
|
||||||
mush_t *mp;
|
mush_t *mp;
|
||||||
struct ccb_scsiio *csio;
|
struct ccb_scsiio *csio;
|
||||||
@ -1152,10 +1221,9 @@ dma2_tgt_fc(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
|
|||||||
bus_dmamap_t *dp;
|
bus_dmamap_t *dp;
|
||||||
ct2_entry_t *cto;
|
ct2_entry_t *cto;
|
||||||
u_int16_t scsi_status, send_status, send_sense;
|
u_int16_t scsi_status, send_status, send_sense;
|
||||||
u_int32_t handle, totxfr;
|
u_int32_t handle, totxfr, datalen;
|
||||||
u_int8_t sense[QLTM_SENSELEN];
|
u_int8_t sense[QLTM_SENSELEN];
|
||||||
int nctios;
|
int nctios;
|
||||||
int32_t resid;
|
|
||||||
|
|
||||||
mp = (mush_t *) arg;
|
mp = (mush_t *) arg;
|
||||||
if (error) {
|
if (error) {
|
||||||
@ -1174,6 +1242,7 @@ dma2_tgt_fc(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
cto->ct_header.rqs_entry_count = 1;
|
cto->ct_header.rqs_entry_count = 1;
|
||||||
|
cto->ct_header.rqs_seqno = 1;
|
||||||
/* ct_reserved contains the handle set by caller */
|
/* ct_reserved contains the handle set by caller */
|
||||||
/*
|
/*
|
||||||
* We preserve ct_lun, ct_iid, ct_rxid. We set the data
|
* We preserve ct_lun, ct_iid, ct_rxid. We set the data
|
||||||
@ -1181,13 +1250,17 @@ dma2_tgt_fc(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
|
|||||||
* We preserve the ct_resid and the response area.
|
* We preserve the ct_resid and the response area.
|
||||||
*/
|
*/
|
||||||
cto->ct_flags |= CT2_NO_DATA;
|
cto->ct_flags |= CT2_NO_DATA;
|
||||||
|
if (cto->ct_resid > 0)
|
||||||
|
cto->ct_flags |= CT2_DATA_UNDER;
|
||||||
|
else if (cto->ct_resid < 0)
|
||||||
|
cto->ct_flags |= CT2_DATA_OVER;
|
||||||
cto->ct_seg_count = 0;
|
cto->ct_seg_count = 0;
|
||||||
cto->ct_reloff = 0;
|
cto->ct_reloff = 0;
|
||||||
ISP_TDQE(mp->isp, "dma2_tgt_fc[no data]", *mp->iptrp, cto);
|
ISP_TDQE(mp->isp, "dma2_tgt_fc[no data]", *mp->iptrp, cto);
|
||||||
if (isp_tdebug) {
|
if (isp_tdebug) {
|
||||||
scsi_status = cto->rsp.m1.ct_scsi_status;
|
scsi_status = cto->rsp.m1.ct_scsi_status;
|
||||||
printf("%s:CTIO2 RX_ID 0x%x lun %d->iid%d flgs 0x%x "
|
printf("%s:CTIO2 RX_ID 0x%x lun %d->iid%d flgs 0x%x "
|
||||||
"sts 0x%x ssts 0x%x res %u\n", mp->isp->isp_name,
|
"sts 0x%x ssts 0x%x res %d\n", mp->isp->isp_name,
|
||||||
cto->ct_rxid, csio->ccb_h.target_lun, cto->ct_iid,
|
cto->ct_rxid, csio->ccb_h.target_lun, cto->ct_iid,
|
||||||
cto->ct_flags, cto->ct_status,
|
cto->ct_flags, cto->ct_status,
|
||||||
cto->rsp.m1.ct_scsi_status, cto->ct_resid);
|
cto->rsp.m1.ct_scsi_status, cto->ct_resid);
|
||||||
@ -1227,9 +1300,9 @@ dma2_tgt_fc(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
|
|||||||
cto->ct_flags &= ~CT2_SENDSTATUS;
|
cto->ct_flags &= ~CT2_SENDSTATUS;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Preserve residual.
|
* Preserve residual, which is actually the total count.
|
||||||
*/
|
*/
|
||||||
resid = cto->ct_resid;
|
datalen = cto->ct_resid;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Save actual SCSI status. We'll reinsert the
|
* Save actual SCSI status. We'll reinsert the
|
||||||
@ -1251,7 +1324,7 @@ dma2_tgt_fc(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
|
|||||||
nctios++;
|
nctios++;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
scsi_status = send_sense = resid = 0;
|
scsi_status = send_sense = datalen = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
totxfr = cto->ct_resid = 0;
|
totxfr = cto->ct_resid = 0;
|
||||||
@ -1342,12 +1415,20 @@ dma2_tgt_fc(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
|
|||||||
scsi_status;
|
scsi_status;
|
||||||
cto->ct_flags |= CT2_SENDSTATUS;
|
cto->ct_flags |= CT2_SENDSTATUS;
|
||||||
}
|
}
|
||||||
cto->ct_resid = resid - totxfr;
|
/*
|
||||||
|
* 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_TDQE(mp->isp, "last dma2_tgt_fc", *mp->iptrp, cto);
|
||||||
if (isp_tdebug) {
|
if (isp_tdebug) {
|
||||||
printf("%s:CTIO2 RX_ID 0x%x lun %d->iid%d flgs"
|
printf("%s:CTIO2 RX_ID 0x%x lun %d->iid%d flgs"
|
||||||
"0x%x sts 0x%x ssts 0x%x res %u\n",
|
"0x%x sts 0x%x ssts 0x%x res %d\n",
|
||||||
mp->isp->isp_name, cto->ct_rxid,
|
mp->isp->isp_name, cto->ct_rxid,
|
||||||
csio->ccb_h.target_lun, (int) cto->ct_iid,
|
csio->ccb_h.target_lun, (int) cto->ct_iid,
|
||||||
cto->ct_flags, cto->ct_status,
|
cto->ct_flags, cto->ct_status,
|
||||||
@ -1564,11 +1645,12 @@ isp_pci_dmasetup(struct ispsoftc *isp, struct ccb_scsiio *csio, ispreq_t *rq,
|
|||||||
#ifdef ISP_TARGET_MODE
|
#ifdef ISP_TARGET_MODE
|
||||||
if (csio->ccb_h.func_code == XPT_CONT_TARGET_IO) {
|
if (csio->ccb_h.func_code == XPT_CONT_TARGET_IO) {
|
||||||
if (IS_FC(isp)) {
|
if (IS_FC(isp)) {
|
||||||
eptr = dma2_tgt_fc;
|
eptr = tdma_mkfc;
|
||||||
} else {
|
} else {
|
||||||
eptr = dma2_tgt;
|
eptr = tdma_mk;
|
||||||
}
|
}
|
||||||
if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_NONE) {
|
if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_NONE ||
|
||||||
|
(csio->dxfer_len == 0)) {
|
||||||
rq->req_seg_count = 1;
|
rq->req_seg_count = 1;
|
||||||
mp = &mush;
|
mp = &mush;
|
||||||
mp->isp = isp;
|
mp->isp = isp;
|
||||||
@ -1590,7 +1672,8 @@ isp_pci_dmasetup(struct ispsoftc *isp, struct ccb_scsiio *csio, ispreq_t *rq,
|
|||||||
* NB: that move no data. For commands that move data,
|
* NB: that move no data. For commands that move data,
|
||||||
* NB: swizzling would take place in those functions.
|
* NB: swizzling would take place in those functions.
|
||||||
*/
|
*/
|
||||||
if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_NONE) {
|
if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_NONE ||
|
||||||
|
(csio->dxfer_len == 0)) {
|
||||||
rq->req_seg_count = 1;
|
rq->req_seg_count = 1;
|
||||||
return (CMD_QUEUED);
|
return (CMD_QUEUED);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user