summaryrefslogtreecommitdiffstats
path: root/sys/dev/isp/isp_pci.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/isp/isp_pci.c')
-rw-r--r--sys/dev/isp/isp_pci.c98
1 files changed, 84 insertions, 14 deletions
diff --git a/sys/dev/isp/isp_pci.c b/sys/dev/isp/isp_pci.c
index 7a852cb..f9f419a 100644
--- a/sys/dev/isp/isp_pci.c
+++ b/sys/dev/isp/isp_pci.c
@@ -588,6 +588,20 @@ isp_get_specific_options(device_t dev, int chan, ispsoftc_t *isp)
}
}
+ tval = 0;
+ (void) resource_int_value(device_get_name(dev), device_get_unit(dev), "nofctape", &tval);
+ if (tval) {
+ isp->isp_confopts |= ISP_CFG_NOFCTAPE;
+ }
+
+ tval = 0;
+ (void) resource_int_value(device_get_name(dev), device_get_unit(dev), "fctape", &tval);
+ if (tval) {
+ isp->isp_confopts &= ~ISP_CFG_NOFCTAPE;
+ isp->isp_confopts |= ISP_CFG_FCTAPE;
+ }
+
+
/*
* Because the resource_*_value functions can neither return
* 64 bit integer values, nor can they be directly coerced
@@ -664,6 +678,8 @@ isp_pci_attach(device_t dev)
isp = &pcs->pci_isp;
isp->isp_dev = dev;
isp->isp_nchan = 1;
+ if (sizeof (bus_addr_t) > 4)
+ isp->isp_osinfo.sixtyfourbit = 1;
/*
* Get Generic Options
@@ -1028,6 +1044,9 @@ isp_pci_detach(device_t dev)
pci_release_msi(dev);
}
(void) bus_release_resource(dev, pcs->rtp, pcs->rgd, pcs->regs);
+ /*
+ * XXX: THERE IS A LOT OF LEAKAGE HERE
+ */
if (pcs->pci_isp.isp_param) {
free(pcs->pci_isp.isp_param, M_DEVBUF);
pcs->pci_isp.isp_param = NULL;
@@ -1441,6 +1460,7 @@ static void
imc(void *arg, bus_dma_segment_t *segs, int nseg, int error)
{
struct imush *imushp = (struct imush *) arg;
+ isp_ecmd_t *ecmd;
if (error) {
imushp->error = error;
@@ -1451,17 +1471,31 @@ imc(void *arg, bus_dma_segment_t *segs, int nseg, int error)
return;
}
isp_prt(imushp->isp, ISP_LOGDEBUG0, "request/result area @ 0x%jx/0x%jx", (uintmax_t) segs->ds_addr, (uintmax_t) segs->ds_len);
+
imushp->isp->isp_rquest = imushp->vbase;
imushp->isp->isp_rquest_dma = segs->ds_addr;
segs->ds_addr += ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(imushp->isp));
imushp->vbase += ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(imushp->isp));
+
imushp->isp->isp_result_dma = segs->ds_addr;
imushp->isp->isp_result = imushp->vbase;
-
+ segs->ds_addr += ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(imushp->isp));
+ imushp->vbase += ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(imushp->isp));
+
+ imushp->isp->isp_osinfo.ecmd_dma = segs->ds_addr;
+ imushp->isp->isp_osinfo.ecmd_free = (isp_ecmd_t *)imushp->vbase;
+ imushp->isp->isp_osinfo.ecmd_base = imushp->isp->isp_osinfo.ecmd_free;
+ for (ecmd = imushp->isp->isp_osinfo.ecmd_free; ecmd < &imushp->isp->isp_osinfo.ecmd_free[N_XCMDS]; ecmd++) {
+ if (ecmd == &imushp->isp->isp_osinfo.ecmd_free[N_XCMDS - 1]) {
+ ecmd->next = NULL;
+ } else {
+ ecmd->next = ecmd + 1;
+ }
+ }
#ifdef ISP_TARGET_MODE
+ segs->ds_addr += (N_XCMDS * XCMD_SIZE);
+ imushp->vbase += (N_XCMDS * XCMD_SIZE);
if (IS_24XX(imushp->isp)) {
- segs->ds_addr += ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(imushp->isp));
- imushp->vbase += ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(imushp->isp));
imushp->isp->isp_atioq_dma = segs->ds_addr;
imushp->isp->isp_atioq = imushp->vbase;
}
@@ -1531,11 +1565,11 @@ isp_pci_mbxdma(ispsoftc_t *isp)
return (1);
}
+#ifdef ISP_TARGET_MODE
/*
* XXX: We don't really support 64 bit target mode for parallel scsi yet
*/
-#ifdef ISP_TARGET_MODE
- if (IS_SCSI(isp) && sizeof (bus_addr_t) > 4) {
+ if (IS_SCSI(isp) && isp->isp_osinfo.sixtyfourbit) {
free(isp->isp_osinfo.pcmd_pool, M_DEVBUF);
isp_prt(isp, ISP_LOGERR, "we cannot do DAC for SPI cards yet");
ISP_LOCK(isp);
@@ -1580,7 +1614,9 @@ isp_pci_mbxdma(ispsoftc_t *isp)
/*
* Allocate and map the request and result queues (and ATIO queue
- * if we're a 2400 supporting target mode).
+ * if we're a 2400 supporting target mode), and a region for
+ * external dma addressable command/status structures (23XX and
+ * later).
*/
len = ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp));
len += ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(isp));
@@ -1589,7 +1625,9 @@ isp_pci_mbxdma(ispsoftc_t *isp)
len += ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(isp));
}
#endif
-
+ if (isp->isp_type >= ISP_HA_FC_2300) {
+ len += (N_XCMDS * XCMD_SIZE);
+ }
ns = (len / PAGE_SIZE) + 1;
/*
@@ -1650,6 +1688,19 @@ isp_pci_mbxdma(ispsoftc_t *isp)
bus_dma_tag_destroy(fc->tdmat);
goto bad;
}
+ for (i = 0; i < INITIAL_NEXUS_COUNT; i++) {
+ struct isp_nexus *n = malloc(sizeof (struct isp_nexus), M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (n == NULL) {
+ while (fc->nexus_free_list) {
+ n = fc->nexus_free_list;
+ fc->nexus_free_list = n->next;
+ free(n, M_DEVBUF);
+ }
+ goto bad;
+ }
+ n->next = fc->nexus_free_list;
+ fc->nexus_free_list = n;
+ }
}
}
@@ -1679,6 +1730,11 @@ bad:
struct isp_fc *fc = ISP_FC_PC(isp, cmap);
bus_dmamem_free(fc->tdmat, base, fc->tdmap);
bus_dma_tag_destroy(fc->tdmat);
+ while (fc->nexus_free_list) {
+ struct isp_nexus *n = fc->nexus_free_list;
+ fc->nexus_free_list = n->next;
+ free(n, M_DEVBUF);
+ }
}
bus_dmamem_free(isp->isp_osinfo.cdmat, base, isp->isp_osinfo.cdmap);
bus_dma_tag_destroy(isp->isp_osinfo.cdmat);
@@ -1733,7 +1789,7 @@ tdma2(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
isp = mp->isp;
rq = mp->rq;
if (nseg) {
- if (sizeof (bus_addr_t) > 4) {
+ if (isp->isp_osinfo.sixtyfourbit) {
if (nseg >= ISP_NSEG64_MAX) {
isp_prt(isp, ISP_LOGERR, "number of segments (%d) exceed maximum we can support (%d)", nseg, ISP_NSEG64_MAX);
mp->error = EFAULT;
@@ -1766,8 +1822,14 @@ tdma2(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
ddir = ISP_NOXFR;
}
- if (isp_send_tgt_cmd(isp, rq, dm_segs, nseg, XS_XFRLEN(csio), ddir, &csio->sense_data, csio->sense_len) != CMD_QUEUED) {
+ error = isp_send_tgt_cmd(isp, rq, dm_segs, nseg, XS_XFRLEN(csio), ddir, &csio->sense_data, csio->sense_len);
+ switch (error) {
+ case CMD_EAGAIN:
mp->error = MUSHERR_NOQENTRIES;
+ case CMD_QUEUED:
+ break;
+ default:
+ mp->error = EIO;
}
}
#endif
@@ -1802,7 +1864,7 @@ dma2(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
isp = mp->isp;
rq = mp->rq;
if (nseg) {
- if (sizeof (bus_addr_t) > 4) {
+ if (isp->isp_osinfo.sixtyfourbit) {
if (nseg >= ISP_NSEG64_MAX) {
isp_prt(isp, ISP_LOGERR, "number of segments (%d) exceed maximum we can support (%d)", nseg, ISP_NSEG64_MAX);
mp->error = EFAULT;
@@ -1835,8 +1897,16 @@ dma2(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
ddir = ISP_NOXFR;
}
- if (isp_send_cmd(isp, rq, dm_segs, nseg, XS_XFRLEN(csio), ddir) != CMD_QUEUED) {
+ error = isp_send_cmd(isp, rq, dm_segs, nseg, XS_XFRLEN(csio), ddir, (ispds64_t *)csio->req_map);
+ switch (error) {
+ case CMD_EAGAIN:
mp->error = MUSHERR_NOQENTRIES;
+ break;
+ case CMD_QUEUED:
+ break;
+ default:
+ mp->error = EIO;
+ break;
}
}
@@ -1936,11 +2006,11 @@ isp_pci_dmasetup(ispsoftc_t *isp, struct ccb_scsiio *csio, void *ff)
if (mp->error == MUSHERR_NOQENTRIES) {
retval = CMD_EAGAIN;
} else if (mp->error == EFBIG) {
- XS_SETERR(csio, CAM_REQ_TOO_BIG);
+ csio->ccb_h.status = CAM_REQ_TOO_BIG;
} else if (mp->error == EINVAL) {
- XS_SETERR(csio, CAM_REQ_INVALID);
+ csio->ccb_h.status = CAM_REQ_INVALID;
} else {
- XS_SETERR(csio, CAM_UNREC_HBA_ERROR);
+ csio->ccb_h.status = CAM_UNREC_HBA_ERROR;
}
return (retval);
}
OpenPOWER on IntegriCloud