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.c240
1 files changed, 131 insertions, 109 deletions
diff --git a/sys/dev/isp/isp_pci.c b/sys/dev/isp/isp_pci.c
index 9c9d7ea..11386ee 100644
--- a/sys/dev/isp/isp_pci.c
+++ b/sys/dev/isp/isp_pci.c
@@ -1539,75 +1539,17 @@ isp_pci_wr_reg_2600(ispsoftc_t *isp, int regoff, uint32_t val)
struct imush {
- ispsoftc_t *isp;
- caddr_t vbase;
- int chan;
+ bus_addr_t maddr;
int error;
};
-static void imc(void *, bus_dma_segment_t *, int, int);
-static void imc1(void *, bus_dma_segment_t *, int, int);
-
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;
- return;
- }
- if (nseg != 1) {
- imushp->error = EINVAL;
- 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));
-
- if (imushp->isp->isp_type >= ISP_HA_FC_2200) {
- 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)) {
- imushp->isp->isp_atioq_dma = segs->ds_addr;
- imushp->isp->isp_atioq = imushp->vbase;
- }
-#endif
-}
-
-static void
-imc1(void *arg, bus_dma_segment_t *segs, int nseg, int error)
-{
- struct imush *imushp = (struct imush *) arg;
- if (error) {
- imushp->error = error;
- return;
- }
- isp_prt(imushp->isp, ISP_LOGDEBUG0, "scdma @ 0x%jx/0x%jx",
- (uintmax_t) segs->ds_addr, (uintmax_t) segs->ds_len);
- FCPARAM(imushp->isp, imushp->chan)->isp_scdma = segs->ds_addr;
- FCPARAM(imushp->isp, imushp->chan)->isp_scratch = imushp->vbase;
+ if (!(imushp->error = error))
+ imushp->maddr = segs[0].ds_addr;
}
static int
@@ -1620,6 +1562,7 @@ isp_pci_mbxdma(ispsoftc_t *isp)
bus_addr_t llim; /* low limit of unavailable dma */
bus_addr_t hlim; /* high limit of unavailable dma */
struct imush im;
+ isp_ecmd_t *ecmd;
/*
* Already been here? If so, leave...
@@ -1683,53 +1626,106 @@ isp_pci_mbxdma(ispsoftc_t *isp)
isp->isp_xffree = isp->isp_xflist;
/*
- * Allocate and map the request and result queues (and ATIO queue
- * if we're a 2400 supporting target mode), and a region for
- * external dma addressable command/status structures (23XX and
- * later).
+ * Allocate and map the request queue and a region for external
+ * DMA addressable command/status structures (22XX and later).
*/
len = ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp));
- len += ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(isp));
-#ifdef ISP_TARGET_MODE
- if (IS_24XX(isp)) {
- len += ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(isp));
- }
-#endif
- if (isp->isp_type >= ISP_HA_FC_2200) {
+ if (isp->isp_type >= ISP_HA_FC_2200)
len += (N_XCMDS * XCMD_SIZE);
+ if (isp_dma_tag_create(isp->isp_osinfo.dmat, QENTRY_LEN, slim,
+ BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
+ len, 1, len, 0, &isp->isp_osinfo.reqdmat)) {
+ isp_prt(isp, ISP_LOGERR, "cannot create request DMA tag");
+ goto bad1;
+ }
+ if (bus_dmamem_alloc(isp->isp_osinfo.reqdmat, (void **)&base,
+ BUS_DMA_COHERENT, &isp->isp_osinfo.reqmap) != 0) {
+ isp_prt(isp, ISP_LOGERR, "cannot allocate request DMA memory");
+ bus_dma_tag_destroy(isp->isp_osinfo.reqdmat);
+ goto bad1;
+ }
+ isp->isp_rquest = base;
+ im.error = 0;
+ if (bus_dmamap_load(isp->isp_osinfo.reqdmat, isp->isp_osinfo.reqmap,
+ base, len, imc, &im, 0) || im.error) {
+ isp_prt(isp, ISP_LOGERR, "error loading request DMA map %d", im.error);
+ goto bad1;
+ }
+ isp_prt(isp, ISP_LOGDEBUG0, "request area @ 0x%jx/0x%jx",
+ (uintmax_t)im.maddr, (uintmax_t)len);
+ isp->isp_rquest_dma = im.maddr;
+ base += ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp));
+ im.maddr += ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp));
+ if (isp->isp_type >= ISP_HA_FC_2200) {
+ isp->isp_osinfo.ecmd_dma = im.maddr;
+ isp->isp_osinfo.ecmd_free = (isp_ecmd_t *)base;
+ isp->isp_osinfo.ecmd_base = isp->isp_osinfo.ecmd_free;
+ for (ecmd = isp->isp_osinfo.ecmd_free;
+ ecmd < &isp->isp_osinfo.ecmd_free[N_XCMDS]; ecmd++) {
+ if (ecmd == &isp->isp_osinfo.ecmd_free[N_XCMDS - 1])
+ ecmd->next = NULL;
+ else
+ ecmd->next = ecmd + 1;
+ }
}
/*
- * Create a tag for the control spaces. We don't always need this
- * to be 32 bits, but we do this for simplicity and speed's sake.
+ * Allocate and map the result queue.
*/
- if (isp_dma_tag_create(isp->isp_osinfo.dmat, QENTRY_LEN, slim, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, len, 1, slim, 0, &isp->isp_osinfo.cdmat)) {
- isp_prt(isp, ISP_LOGERR, "cannot create a dma tag for control spaces");
- free(isp->isp_osinfo.pcmd_pool, M_DEVBUF);
- free(isp->isp_xflist, M_DEVBUF);
- ISP_LOCK(isp);
- return (1);
- }
-
- if (bus_dmamem_alloc(isp->isp_osinfo.cdmat, (void **)&base, BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &isp->isp_osinfo.cdmap) != 0) {
- isp_prt(isp, ISP_LOGERR, "cannot allocate %d bytes of CCB memory", len);
- bus_dma_tag_destroy(isp->isp_osinfo.cdmat);
- free(isp->isp_osinfo.pcmd_pool, M_DEVBUF);
- free(isp->isp_xflist, M_DEVBUF);
- ISP_LOCK(isp);
- return (1);
- }
-
- im.isp = isp;
- im.chan = 0;
- im.vbase = base;
+ len = ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(isp));
+ if (isp_dma_tag_create(isp->isp_osinfo.dmat, QENTRY_LEN, slim,
+ BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
+ len, 1, len, 0, &isp->isp_osinfo.respdmat)) {
+ isp_prt(isp, ISP_LOGERR, "cannot create response DMA tag");
+ goto bad1;
+ }
+ if (bus_dmamem_alloc(isp->isp_osinfo.respdmat, (void **)&base,
+ BUS_DMA_COHERENT, &isp->isp_osinfo.respmap) != 0) {
+ isp_prt(isp, ISP_LOGERR, "cannot allocate response DMA memory");
+ bus_dma_tag_destroy(isp->isp_osinfo.respdmat);
+ goto bad1;
+ }
+ isp->isp_result = base;
im.error = 0;
+ if (bus_dmamap_load(isp->isp_osinfo.respdmat, isp->isp_osinfo.respmap,
+ base, len, imc, &im, 0) || im.error) {
+ isp_prt(isp, ISP_LOGERR, "error loading response DMA map %d", im.error);
+ goto bad1;
+ }
+ isp_prt(isp, ISP_LOGDEBUG0, "response area @ 0x%jx/0x%jx",
+ (uintmax_t)im.maddr, (uintmax_t)len);
+ isp->isp_result_dma = im.maddr;
- bus_dmamap_load(isp->isp_osinfo.cdmat, isp->isp_osinfo.cdmap, base, len, imc, &im, 0);
- if (im.error) {
- isp_prt(isp, ISP_LOGERR, "error %d loading dma map for control areas", im.error);
- goto bad;
+#ifdef ISP_TARGET_MODE
+ /*
+ * Allocate and map ATIO queue on 24xx with target mode.
+ */
+ if (IS_24XX(isp)) {
+ len = ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(isp));
+ if (isp_dma_tag_create(isp->isp_osinfo.dmat, QENTRY_LEN, slim,
+ BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
+ len, 1, len, 0, &isp->isp_osinfo.atiodmat)) {
+ isp_prt(isp, ISP_LOGERR, "cannot create ATIO DMA tag");
+ goto bad1;
+ }
+ if (bus_dmamem_alloc(isp->isp_osinfo.atiodmat, (void **)&base,
+ BUS_DMA_COHERENT, &isp->isp_osinfo.atiomap) != 0) {
+ isp_prt(isp, ISP_LOGERR, "cannot allocate ATIO DMA memory");
+ bus_dma_tag_destroy(isp->isp_osinfo.atiodmat);
+ goto bad1;
+ }
+ isp->isp_atioq = base;
+ im.error = 0;
+ if (bus_dmamap_load(isp->isp_osinfo.atiodmat, isp->isp_osinfo.atiomap,
+ base, len, imc, &im, 0) || im.error) {
+ isp_prt(isp, ISP_LOGERR, "error loading ATIO DMA map %d", im.error);
+ goto bad;
+ }
+ isp_prt(isp, ISP_LOGDEBUG0, "ATIO area @ 0x%jx/0x%jx",
+ (uintmax_t)im.maddr, (uintmax_t)len);
+ isp->isp_atioq_dma = im.maddr;
}
+#endif
if (IS_FC(isp)) {
if (isp_dma_tag_create(isp->isp_osinfo.dmat, 64, slim,
@@ -1740,21 +1736,17 @@ isp_pci_mbxdma(ispsoftc_t *isp)
for (cmap = 0; cmap < isp->isp_nchan; cmap++) {
struct isp_fc *fc = ISP_FC_PC(isp, cmap);
if (bus_dmamem_alloc(isp->isp_osinfo.scdmat,
- (void **)&base, BUS_DMA_NOWAIT | BUS_DMA_COHERENT,
- &fc->scmap) != 0) {
+ (void **)&base, BUS_DMA_COHERENT, &fc->scmap) != 0)
goto bad;
- }
- im.isp = isp;
- im.chan = cmap;
- im.vbase = base;
+ FCPARAM(isp, cmap)->isp_scratch = base;
im.error = 0;
- bus_dmamap_load(isp->isp_osinfo.scdmat, fc->scmap,
- base, ISP_FC_SCRLEN, imc1, &im, 0);
- if (im.error) {
+ if (bus_dmamap_load(isp->isp_osinfo.scdmat, fc->scmap,
+ base, ISP_FC_SCRLEN, imc, &im, 0) || im.error) {
bus_dmamem_free(isp->isp_osinfo.scdmat,
base, fc->scmap);
goto bad;
}
+ FCPARAM(isp, cmap)->isp_scdma = im.maddr;
if (!IS_2100(isp)) {
for (i = 0; i < INITIAL_NEXUS_COUNT; i++) {
struct isp_nexus *n = malloc(sizeof (struct isp_nexus), M_DEVBUF, M_NOWAIT | M_ZERO);
@@ -1808,8 +1800,38 @@ bad:
}
bus_dma_tag_destroy(isp->isp_osinfo.scdmat);
}
- bus_dmamem_free(isp->isp_osinfo.cdmat, base, isp->isp_osinfo.cdmap);
- bus_dma_tag_destroy(isp->isp_osinfo.cdmat);
+bad1:
+ if (isp->isp_rquest_dma != 0) {
+ bus_dmamap_unload(isp->isp_osinfo.reqdmat,
+ isp->isp_osinfo.reqmap);
+ }
+ if (isp->isp_rquest != NULL) {
+ bus_dmamem_free(isp->isp_osinfo.reqdmat, isp->isp_rquest,
+ isp->isp_osinfo.reqmap);
+ bus_dma_tag_destroy(isp->isp_osinfo.reqdmat);
+ }
+ if (isp->isp_result_dma != 0) {
+ bus_dmamap_unload(isp->isp_osinfo.respdmat,
+ isp->isp_osinfo.respmap);
+ }
+ if (isp->isp_result != NULL) {
+ bus_dmamem_free(isp->isp_osinfo.respdmat, isp->isp_result,
+ isp->isp_osinfo.respmap);
+ bus_dma_tag_destroy(isp->isp_osinfo.respdmat);
+ }
+#ifdef ISP_TARGET_MODE
+ if (IS_24XX(isp)) {
+ if (isp->isp_atioq_dma != 0) {
+ bus_dmamap_unload(isp->isp_osinfo.atiodmat,
+ isp->isp_osinfo.atiomap);
+ }
+ if (isp->isp_atioq != NULL) {
+ bus_dmamem_free(isp->isp_osinfo.reqdmat, isp->isp_atioq,
+ isp->isp_osinfo.atiomap);
+ bus_dma_tag_destroy(isp->isp_osinfo.atiodmat);
+ }
+ }
+#endif
free(isp->isp_xflist, M_DEVBUF);
free(isp->isp_osinfo.pcmd_pool, M_DEVBUF);
isp->isp_rquest = NULL;
OpenPOWER on IntegriCloud