diff options
Diffstat (limited to 'sys/dev/isp/isp_sbus.c')
-rw-r--r-- | sys/dev/isp/isp_sbus.c | 248 |
1 files changed, 71 insertions, 177 deletions
diff --git a/sys/dev/isp/isp_sbus.c b/sys/dev/isp/isp_sbus.c index 839d7eb..af7cb88 100644 --- a/sys/dev/isp/isp_sbus.c +++ b/sys/dev/isp/isp_sbus.c @@ -33,10 +33,8 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> #include <sys/systm.h> -#if __FreeBSD_version >= 700000 #include <sys/linker.h> #include <sys/firmware.h> -#endif #include <sys/bus.h> #include <sys/kernel.h> #include <sys/module.h> @@ -51,15 +49,12 @@ __FBSDID("$FreeBSD$"); #include <dev/isp/isp_freebsd.h> -static uint32_t -isp_sbus_rd_reg(ispsoftc_t *, int); -static void -isp_sbus_wr_reg(ispsoftc_t *, int, uint32_t); -static int -isp_sbus_rd_isr(ispsoftc_t *, uint32_t *, uint16_t *, uint16_t *); +static uint32_t isp_sbus_rd_reg(ispsoftc_t *, int); +static void isp_sbus_wr_reg(ispsoftc_t *, int, uint32_t); +static int isp_sbus_rd_isr(ispsoftc_t *, uint32_t *, uint16_t *, uint16_t *); static int isp_sbus_mbxdma(ispsoftc_t *); -static int -isp_sbus_dmasetup(ispsoftc_t *, XS_T *, ispreq_t *, uint32_t *, uint32_t); +static int isp_sbus_dmasetup(ispsoftc_t *, XS_T *, void *); + static void isp_sbus_reset0(ispsoftc_t *); static void isp_sbus_reset1(ispsoftc_t *); @@ -91,6 +86,7 @@ struct isp_sbussoftc { void * ih; int16_t sbus_poff[_NREG_BLKS]; sdparam sbus_param; + struct isp_spi sbus_spi; struct ispmdvec sbus_mdvec; struct resource * sbus_ires; }; @@ -108,9 +104,6 @@ static driver_t isp_sbus_driver = { }; static devclass_t isp_devclass; DRIVER_MODULE(isp, sbus, isp_sbus_driver, isp_devclass, 0, 0); -#if __FreeBSD_version < 700000 -extern ispfwfunc *isp_get_firmware_p; -#endif static int isp_sbus_probe(device_t dev) @@ -140,7 +133,7 @@ static int isp_sbus_attach(device_t dev) { struct resource *regs; - int tval, iqd, isp_debug, role, rid, ispburst; + int tval, iqd, isp_debug, role, rid, ispburst, default_id; struct isp_sbussoftc *sbs; ispsoftc_t *isp = NULL; int locksetup = 0; @@ -165,11 +158,7 @@ isp_sbus_attach(device_t dev) ((role & ~(ISP_ROLE_INITIATOR|ISP_ROLE_TARGET)) == 0)) { device_printf(dev, "setting role to 0x%x\n", role); } else { -#ifdef ISP_TARGET_MODE - role = ISP_ROLE_INITIATOR|ISP_ROLE_TARGET; -#else role = ISP_DEFAULT_ROLES; -#endif } sbs = malloc(sizeof (*sbs), M_DEVBUF, M_NOWAIT | M_ZERO); @@ -202,9 +191,9 @@ isp_sbus_attach(device_t dev) isp->isp_bustype = ISP_BT_SBUS; isp->isp_type = ISP_HA_SCSI_UNKNOWN; isp->isp_param = &sbs->sbus_param; + isp->isp_osinfo.pc.ptr = &sbs->sbus_spi; isp->isp_revision = 0; /* XXX */ - isp->isp_role = role; - isp->isp_dev = dev; + ISP_SET_PC(isp, 0, role, role); /* * Get the clock frequency and convert it from HZ to MHz, @@ -246,11 +235,10 @@ isp_sbus_attach(device_t dev) */ if (strcmp("PTI,ptisp", ofw_bus_get_name(dev)) == 0 || strcmp("ptisp", ofw_bus_get_name(dev)) == 0) { - SDPARAM(isp)->isp_ptisp = 1; + SDPARAM(isp, 0)->isp_ptisp = 1; } -#if __FreeBSD_version >= 700000 isp->isp_osinfo.fw = firmware_get("isp_1000"); if (isp->isp_osinfo.fw) { union { @@ -260,14 +248,6 @@ isp_sbus_attach(device_t dev) stupid.cp = isp->isp_osinfo.fw->data; isp->isp_mdvec->dv_ispfw = stupid.sp; } -#else - /* - * Try and find firmware for this device. - */ - if (isp_get_firmware_p) { - (*isp_get_firmware_p)(0, 0, 0x1000, &sbs->sbus_mdvec.dv_ispfw); - } -#endif tval = 0; if (resource_int_value(device_get_name(dev), device_get_unit(dev), @@ -275,19 +255,20 @@ isp_sbus_attach(device_t dev) isp->isp_confopts |= ISP_CFG_NORELOAD; } - isp->isp_osinfo.default_id = -1; + default_id = -1; if (resource_int_value(device_get_name(dev), device_get_unit(dev), "iid", &tval) == 0) { - isp->isp_osinfo.default_id = tval; + default_id = tval; isp->isp_confopts |= ISP_CFG_OWNLOOPID; } - if (isp->isp_osinfo.default_id == -1) { + if (default_id == -1) { /* * XXX: should be a way to get properties w/o having * XXX: to call OF_xxx functions */ - isp->isp_osinfo.default_id = 7; + default_id = 7; } + ISP_SPI_PC(isp, 0)->iid = default_id; isp_debug = 0; (void) resource_int_value(device_get_name(dev), device_get_unit(dev), @@ -328,20 +309,20 @@ isp_sbus_attach(device_t dev) * Make sure we're in reset state. */ ISP_LOCK(isp); - isp_reset(isp); + isp_reset(isp, 1); if (isp->isp_state != ISP_RESETSTATE) { isp_uninit(isp); ISP_UNLOCK(isp); goto bad; } isp_init(isp); - if (isp->isp_role != ISP_ROLE_NONE && isp->isp_state != ISP_INITSTATE) { + if (role != ISP_ROLE_NONE && isp->isp_state != ISP_INITSTATE) { isp_uninit(isp); ISP_UNLOCK(isp); goto bad; } isp_attach(isp); - if (isp->isp_role != ISP_ROLE_NONE && isp->isp_state != ISP_RUNSTATE) { + if (role != ISP_ROLE_NONE && isp->isp_state != ISP_RUNSTATE) { isp_uninit(isp); ISP_UNLOCK(isp); goto bad; @@ -507,7 +488,7 @@ isp_sbus_mbxdma(ispsoftc_t *isp) if (isp_dma_tag_create(isp->isp_osinfo.dmat, QENTRY_LEN, BUS_SPACE_MAXADDR_24BIT+1, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR_32BIT, NULL, NULL, len, ns, - BUS_SPACE_MAXADDR_24BIT, 0, &isp->isp_cdmat)) { + BUS_SPACE_MAXADDR_24BIT, 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); @@ -516,11 +497,11 @@ isp_sbus_mbxdma(ispsoftc_t *isp) return (1); } - if (bus_dmamem_alloc(isp->isp_cdmat, (void **)&base, BUS_DMA_NOWAIT, - &isp->isp_cdmap) != 0) { + if (bus_dmamem_alloc(isp->isp_osinfo.cdmat, (void **)&base, BUS_DMA_NOWAIT, + &isp->isp_osinfo.cdmap) != 0) { isp_prt(isp, ISP_LOGERR, "cannot allocate %d bytes of CCB memory", len); - bus_dma_tag_destroy(isp->isp_cdmat); + 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); @@ -539,7 +520,7 @@ isp_sbus_mbxdma(ispsoftc_t *isp) } goto bad; } - isp_callout_init(&pcmd->wdog); + callout_init_mtx(&pcmd->wdog, &isp->isp_osinfo.lock, 0); if (i == isp->isp_maxcmds-1) { pcmd->next = NULL; } else { @@ -550,7 +531,7 @@ isp_sbus_mbxdma(ispsoftc_t *isp) im.isp = isp; im.error = 0; - bus_dmamap_load(isp->isp_cdmat, isp->isp_cdmap, base, len, imc, &im, 0); + 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); @@ -564,8 +545,8 @@ isp_sbus_mbxdma(ispsoftc_t *isp) return (0); bad: - bus_dmamem_free(isp->isp_cdmat, base, isp->isp_cdmap); - bus_dma_tag_destroy(isp->isp_cdmat); + bus_dmamem_free(isp->isp_osinfo.cdmat, base, isp->isp_osinfo.cdmap); + bus_dma_tag_destroy(isp->isp_osinfo.cdmat); free(isp->isp_xflist, M_DEVBUF); free(isp->isp_osinfo.pcmd_pool, M_DEVBUF); isp->isp_rquest = NULL; @@ -576,15 +557,13 @@ bad: typedef struct { ispsoftc_t *isp; void *cmd_token; - void *rq; - uint32_t *nxtip; - uint32_t optr; + void *rq; /* original request */ int error; + bus_size_t mapsize; } mush_t; #define MUSHERR_NOQENTRIES -2 - static void dma2(void *, bus_dma_segment_t *, int, int); static void @@ -593,154 +572,84 @@ dma2(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) mush_t *mp; ispsoftc_t *isp; struct ccb_scsiio *csio; - bus_dma_segment_t *eseg; + isp_ddir_t ddir; ispreq_t *rq; - int seglim, datalen; - uint16_t nxti; mp = (mush_t *) arg; if (error) { mp->error = error; return; } - - if (nseg < 1) { - isp_prt(mp->isp, ISP_LOGERR, "bad segment count (%d)", nseg); - mp->error = EFAULT; - return; - } csio = mp->cmd_token; isp = mp->isp; rq = mp->rq; - nxti = *mp->nxtip; - - if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { - bus_dmamap_sync(isp->isp_osinfo.dmat, - PISP_PCMD(csio)->dmap, BUS_DMASYNC_PREREAD); - } else { - bus_dmamap_sync(isp->isp_osinfo.dmat, - PISP_PCMD(csio)->dmap, BUS_DMASYNC_PREWRITE); - } - - datalen = XS_XFRLEN(csio); - - /* - * We're passed an initial partially filled in entry that - * has most fields filled in except for data transfer - * related values. - * - * Our job is to fill in the initial request queue entry and - * then to start allocating and filling in continuation entries - * until we've covered the entire transfer. - */ - - if (csio->cdb_len > 12) { - seglim = 0; - } else { - seglim = ISP_RQDSEG; - } - if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { - rq->req_flags |= REQFLAG_DATA_IN; + if (nseg) { + if (sizeof (bus_addr_t) > 4) { + if (rq->req_header.rqs_entry_type == RQSTYPE_T2RQS) { + rq->req_header.rqs_entry_type = RQSTYPE_T3RQS; + } else if (rq->req_header.rqs_entry_type == RQSTYPE_REQUEST) { + rq->req_header.rqs_entry_type = RQSTYPE_A64; + } + } + if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { + bus_dmamap_sync(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap, BUS_DMASYNC_PREREAD); + ddir = ISP_FROM_DEVICE; + } else if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) { + bus_dmamap_sync(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap, BUS_DMASYNC_PREWRITE); + ddir = ISP_TO_DEVICE; + } else { + ddir = ISP_NOXFR; + } } else { - rq->req_flags |= REQFLAG_DATA_OUT; + dm_segs = NULL; + nseg = 0; + ddir = ISP_NOXFR; } - eseg = dm_segs + nseg; - - while (datalen != 0 && rq->req_seg_count < seglim && dm_segs != eseg) { - rq->req_dataseg[rq->req_seg_count].ds_base = dm_segs->ds_addr; - rq->req_dataseg[rq->req_seg_count].ds_count = dm_segs->ds_len; - datalen -= dm_segs->ds_len; - rq->req_seg_count++; - dm_segs++; + if (isp_send_cmd(isp, rq, dm_segs, nseg, XS_XFRLEN(csio), ddir) != CMD_QUEUED) { + mp->error = MUSHERR_NOQENTRIES; } - - while (datalen > 0 && dm_segs != eseg) { - uint16_t onxti; - ispcontreq_t local, *crq = &local, *cqe; - - cqe = (ispcontreq_t *) ISP_QUEUE_ENTRY(isp->isp_rquest, nxti); - onxti = nxti; - nxti = ISP_NXT_QENTRY(onxti, RQUEST_QUEUE_LEN(isp)); - if (nxti == mp->optr) { - isp_prt(isp, ISP_LOGDEBUG0, "Request Queue Overflow++"); - mp->error = MUSHERR_NOQENTRIES; - return; - } - rq->req_header.rqs_entry_count++; - MEMZERO((void *)crq, sizeof (*crq)); - crq->req_header.rqs_entry_count = 1; - crq->req_header.rqs_entry_type = RQSTYPE_DATASEG; - - seglim = 0; - while (datalen > 0 && seglim < ISP_CDSEG && dm_segs != eseg) { - crq->req_dataseg[seglim].ds_base = - dm_segs->ds_addr; - crq->req_dataseg[seglim].ds_count = - dm_segs->ds_len; - rq->req_seg_count++; - dm_segs++; - seglim++; - datalen -= dm_segs->ds_len; - } - isp_put_cont_req(isp, crq, cqe); - MEMORYBARRIER(isp, SYNC_REQUEST, onxti, QENTRY_LEN); - } - *mp->nxtip = nxti; } static int -isp_sbus_dmasetup(ispsoftc_t *isp, struct ccb_scsiio *csio, ispreq_t *rq, - uint32_t *nxtip, uint32_t optr) +isp_sbus_dmasetup(ispsoftc_t *isp, struct ccb_scsiio *csio, void *ff) { - ispreq_t *qep; mush_t mush, *mp; void (*eptr)(void *, bus_dma_segment_t *, int, int); - qep = (ispreq_t *) ISP_QUEUE_ENTRY(isp->isp_rquest, isp->isp_reqidx); - eptr = dma2; - - - if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_NONE || - (csio->dxfer_len == 0)) { - rq->req_seg_count = 1; - goto mbxsync; - } - - /* - * Do a virtual grapevine step to collect info for - * the callback dma allocation that we have to use... - */ mp = &mush; mp->isp = isp; mp->cmd_token = csio; - mp->rq = rq; - mp->nxtip = nxtip; - mp->optr = optr; + mp->rq = ff; mp->error = 0; + mp->mapsize = 0; + + eptr = dma2; - if ((csio->ccb_h.flags & CAM_SCATTER_VALID) == 0) { + if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_NONE || (csio->dxfer_len == 0)) { + (*eptr)(mp, NULL, 0, 0); + } else if ((csio->ccb_h.flags & CAM_SCATTER_VALID) == 0) { if ((csio->ccb_h.flags & CAM_DATA_PHYS) == 0) { - int error = bus_dmamap_load(isp->isp_osinfo.dmat, - PISP_PCMD(csio)->dmap, csio->data_ptr, - csio->dxfer_len, eptr, mp, 0); + int error; + error = bus_dmamap_load(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap, csio->data_ptr, csio->dxfer_len, eptr, mp, 0); +#if 0 + xpt_print(csio->ccb_h.path, "%s: bus_dmamap_load " "ptr %p len %d returned %d\n", __func__, csio->data_ptr, csio->dxfer_len, error); +#endif + if (error == EINPROGRESS) { - bus_dmamap_unload(isp->isp_osinfo.dmat, - PISP_PCMD(csio)->dmap); + bus_dmamap_unload(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap); mp->error = EINVAL; - isp_prt(isp, ISP_LOGERR, - "deferred dma allocation not supported"); + isp_prt(isp, ISP_LOGERR, "deferred dma allocation not supported"); } else if (error && mp->error == 0) { #ifdef DIAGNOSTIC - isp_prt(isp, ISP_LOGERR, - "error %d in dma mapping code", error); + isp_prt(isp, ISP_LOGERR, "error %d in dma mapping code", error); #endif mp->error = error; } } else { /* Pointer to physical buffer */ struct bus_dma_segment seg; - seg.ds_addr = (bus_addr_t)csio->data_ptr; + seg.ds_addr = (bus_addr_t)(vm_offset_t)csio->data_ptr; seg.ds_len = csio->dxfer_len; (*eptr)(mp, &seg, 1, 0); } @@ -748,12 +657,10 @@ isp_sbus_dmasetup(ispsoftc_t *isp, struct ccb_scsiio *csio, ispreq_t *rq, struct bus_dma_segment *segs; if ((csio->ccb_h.flags & CAM_DATA_PHYS) != 0) { - isp_prt(isp, ISP_LOGERR, - "Physical segment pointers unsupported"); + isp_prt(isp, ISP_LOGERR, "Physical segment pointers unsupported"); mp->error = EINVAL; } else if ((csio->ccb_h.flags & CAM_SG_LIST_PHYS) == 0) { - isp_prt(isp, ISP_LOGERR, - "Virtual segment addresses unsupported"); + isp_prt(isp, ISP_LOGERR, "Physical SG/LIST Phys segment pointers unsupported"); mp->error = EINVAL; } else { /* Just use the segments provided */ @@ -774,19 +681,6 @@ isp_sbus_dmasetup(ispsoftc_t *isp, struct ccb_scsiio *csio, ispreq_t *rq, } return (retval); } -mbxsync: - if (isp->isp_dblev & ISP_LOGDEBUG1) { - isp_print_bytes(isp, "Request Queue Entry", QENTRY_LEN, rq); - } - switch (rq->req_header.rqs_entry_type) { - case RQSTYPE_REQUEST: - isp_put_request(isp, rq, qep); - break; - case RQSTYPE_CMDONLY: - isp_put_extended_request(isp, (ispextreq_t *)rq, - (ispextreq_t *)qep); - break; - } return (CMD_QUEUED); } |