diff options
Diffstat (limited to 'sys/dev/isp/isp_pci.c')
-rw-r--r-- | sys/dev/isp/isp_pci.c | 98 |
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); } |