diff options
author | David Gwynne <dlg@cvs.openbsd.org> | 2005-10-02 06:30:51 +0000 |
---|---|---|
committer | David Gwynne <dlg@cvs.openbsd.org> | 2005-10-02 06:30:51 +0000 |
commit | 4b186ac5106b0537263d87e4e4d56bdb7da08b03 (patch) | |
tree | a3b141946497a3844558c59b1874f4e5dd6b38ad /sys | |
parent | 7e933687b1761c430132cd3ba8f132a628fbde1d (diff) |
replace the two separate dmamem allocations for the passthrough commands
and the scatter gather lists with a single allocation containing both.
more importantly, actually sync the appropriate parts of this allocation
when giving the commands to or taking the response from the device.
tested by and ok krw@
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/ic/ami.c | 74 | ||||
-rw-r--r-- | sys/dev/ic/amivar.h | 41 |
2 files changed, 76 insertions, 39 deletions
diff --git a/sys/dev/ic/ami.c b/sys/dev/ic/ami.c index 3bded0be217..94761a09dd6 100644 --- a/sys/dev/ic/ami.c +++ b/sys/dev/ic/ami.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ami.c,v 1.90 2005/09/30 10:10:29 dlg Exp $ */ +/* $OpenBSD: ami.c,v 1.91 2005/10/02 06:30:50 dlg Exp $ */ /* * Copyright (c) 2001 Michael Shalayeff @@ -324,6 +324,7 @@ ami_attach(sc) struct ami_rawsoftc *rsc; struct ami_ccb *ccb; struct ami_iocmd *cmd; + struct ami_ccbmem *mem; bus_dmamap_t idatamap; bus_dma_segment_t idataseg[1]; const char *p; @@ -343,22 +344,18 @@ ami_attach(sc) sc->sc_mbox_pa = sc->sc_mbox_seg[0].ds_addr; AMI_DPRINTF(AMI_D_CMD, ("mbox_pa=%llx ", sc->sc_mbox_pa)); - sc->sc_pts = ami_allocmem(sc->dmat, &sc->sc_ptmap, sc->sc_ptseg, - sizeof(struct ami_passthrough), AMI_MAXCMDS, "ptlist"); - if (!sc->sc_pts) + sc->sc_ccbmem = ami_allocmem(sc->dmat, &sc->sc_ccbmap, sc->sc_ccbseg, + sizeof(struct ami_ccbmem), AMI_MAXCMDS, "ccb dmamem"); + if (!sc->sc_ccbmem) goto free_mbox; - sc->sc_sgents = ami_allocmem(sc->dmat, &sc->sc_sgmap, sc->sc_sgseg, - sizeof(struct ami_sgent) * AMI_SGEPERCMD, AMI_MAXCMDS, "sglist"); - if (!sc->sc_sgents) - goto free_pts; - TAILQ_INIT(&sc->sc_ccbq); TAILQ_INIT(&sc->sc_ccbdone); TAILQ_INIT(&sc->sc_free_ccb); for (i = 0; i < AMI_MAXCMDS; i++) { ccb = &sc->sc_ccbs[i]; + mem = &sc->sc_ccbmem[i]; error = bus_dmamap_create(sc->dmat, AMI_MAXFER, AMI_MAXOFFSETS, AMI_MAXFER, 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, @@ -368,16 +365,20 @@ ami_attach(sc) goto destroy; } - ccb->ccb_sc = sc; ccb->ccb_state = AMI_CCB_FREE; + ccb->ccb_cmd.acc_id = i + 1; - ccb->ccb_pt = &sc->sc_pts[i]; - ccb->ccb_ptpa = htole32(sc->sc_ptseg[0].ds_addr + - (sizeof(struct ami_passthrough) * i)); - ccb->ccb_sglist = &sc->sc_sgents[i * AMI_SGEPERCMD]; - ccb->ccb_sglistpa = htole32(sc->sc_sgseg[0].ds_addr + - (sizeof(struct ami_sgent) * AMI_SGEPERCMD * i)); + ccb->ccb_offset = sizeof(struct ami_ccbmem) * i; + + ccb->ccb_pt = &mem->cd_pt; + ccb->ccb_ptpa = htole32(sc->sc_ccbseg[0].ds_addr + + ccb->ccb_offset); + + ccb->ccb_sglist = mem->cd_sg; + ccb->ccb_sglistpa = htole32(sc->sc_ccbseg[0].ds_addr + + ccb->ccb_offset + sizeof(struct ami_passthrough)); + TAILQ_INSERT_TAIL(&sc->sc_free_ccb, ccb, ccb_link); } @@ -627,12 +628,9 @@ destroy: if (ccb->ccb_dmamap) bus_dmamap_destroy(sc->dmat, ccb->ccb_dmamap); - ami_freemem((caddr_t)sc->sc_sgents, sc->dmat, &sc->sc_sgmap, - sc->sc_sgseg, sizeof(struct ami_sgent) * AMI_SGEPERCMD, - AMI_MAXCMDS, "sglist"); -free_pts: - ami_freemem((caddr_t)sc->sc_pts, sc->dmat, &sc->sc_ptmap, sc->sc_ptseg, - sizeof(struct ami_passthrough), AMI_MAXCMDS, "ptlist"); + ami_freemem((caddr_t)sc->sc_ccbmem, sc->dmat, &sc->sc_ccbmap, + sc->sc_ccbseg, sizeof(struct ami_ccbmem), AMI_MAXCMDS, + "ccb dmamem"); free_mbox: ami_freemem((caddr_t)sc->sc_mbox, sc->dmat, &sc->sc_mbox_map, sc->sc_mbox_seg, sizeof(struct ami_iocmd), 1, "mbox"); @@ -1074,6 +1072,10 @@ ami_cmd(ccb, flags, wait) } AMI_DPRINTF(AMI_D_DMA, ("> ")); + bus_dmamap_sync(sc->dmat, sc->sc_ccbmap, + ccb->ccb_offset, sizeof(struct ami_ccbmem), + BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); + bus_dmamap_sync(sc->dmat, dmap, 0, dmap->dm_mapsize, (ccb->ccb_dir == AMI_CCB_IN) ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE); @@ -1088,8 +1090,18 @@ ami_cmd(ccb, flags, wait) if (error) AMI_DPRINTF(AMI_D_MISC, ("pf ")); #endif - if (ccb->ccb_data) + if (ccb->ccb_data) { + bus_dmamap_sync(sc->dmat, ccb->ccb_dmamap, 0, + ccb->ccb_dmamap->dm_mapsize, + (ccb->ccb_dir == AMI_CCB_IN) ? + BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); + + bus_dmamap_sync(sc->dmat, sc->sc_ccbmap, + ccb->ccb_offset, sizeof(struct ami_ccbmem), + BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); + bus_dmamap_unload(sc->dmat, dmap); + } if (ccb->ccb_wakeup) ccb->ccb_wakeup = 0; else @@ -1097,8 +1109,18 @@ ami_cmd(ccb, flags, wait) } else if ((error = ami_start(ccb, wait))) { AMI_DPRINTF(AMI_D_DMA, ("error=%d ", error)); __asm __volatile(".globl _bpamierr\n_bpamierr:"); - if (ccb->ccb_data) + if (ccb->ccb_data) { + bus_dmamap_sync(sc->dmat, ccb->ccb_dmamap, 0, + ccb->ccb_dmamap->dm_mapsize, + (ccb->ccb_dir == AMI_CCB_IN) ? + BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); + + bus_dmamap_sync(sc->dmat, sc->sc_ccbmap, + ccb->ccb_offset, sizeof(struct ami_ccbmem), + BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); + bus_dmamap_unload(sc->dmat, dmap); + } ami_put_ccb(ccb); } @@ -1249,6 +1271,10 @@ ami_done(sc, idx) (ccb->ccb_dir == AMI_CCB_IN) ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); + bus_dmamap_sync(sc->dmat, sc->sc_ccbmap, + ccb->ccb_offset, sizeof(struct ami_ccbmem), + BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); + bus_dmamap_unload(sc->dmat, ccb->ccb_dmamap); } diff --git a/sys/dev/ic/amivar.h b/sys/dev/ic/amivar.h index d692df1efbd..3f2b4104786 100644 --- a/sys/dev/ic/amivar.h +++ b/sys/dev/ic/amivar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: amivar.h,v 1.31 2005/09/30 09:07:01 dlg Exp $ */ +/* $OpenBSD: amivar.h,v 1.32 2005/10/02 06:30:50 dlg Exp $ */ /* * Copyright (c) 2001 Michael Shalayeff @@ -27,27 +27,42 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ +struct ami_ccbmem { + struct ami_passthrough cd_pt; + struct ami_sgent cd_sg[AMI_SGEPERCMD]; +}; + struct ami_softc; struct ami_ccb { struct ami_softc *ccb_sc; + struct ami_iocmd ccb_cmd; struct ami_passthrough *ccb_pt; paddr_t ccb_ptpa; struct ami_sgent *ccb_sglist; paddr_t ccb_sglistpa; + int ccb_offset; + struct scsi_xfer *ccb_xs; - volatile int ccb_wakeup; - TAILQ_ENTRY(ami_ccb) ccb_link; - enum { - AMI_CCB_FREE, AMI_CCB_READY, AMI_CCB_QUEUED, AMI_CCB_PREQUEUED - } ccb_state; + + void *ccb_data; int ccb_len; enum { - AMI_CCB_IN, AMI_CCB_OUT + AMI_CCB_IN, + AMI_CCB_OUT } ccb_dir; - void *ccb_data; bus_dmamap_t ccb_dmamap; + + volatile int ccb_wakeup; + + enum { + AMI_CCB_FREE, + AMI_CCB_READY, + AMI_CCB_QUEUED, + AMI_CCB_PREQUEUED + } ccb_state; + TAILQ_ENTRY(ami_ccb) ccb_link; }; typedef TAILQ_HEAD(ami_queue_head, ami_ccb) ami_queue_head; @@ -94,13 +109,9 @@ struct ami_softc { struct ami_ccb sc_ccbs[AMI_MAXCMDS]; ami_queue_head sc_free_ccb, sc_ccbq, sc_ccbdone; - struct ami_passthrough *sc_pts; - bus_dmamap_t sc_ptmap; - bus_dma_segment_t sc_ptseg[1]; - - struct ami_sgent *sc_sgents; - bus_dmamap_t sc_sgmap; - bus_dma_segment_t sc_sgseg[1]; + struct ami_ccbmem *sc_ccbmem; + bus_dmamap_t sc_ccbmap; + bus_dma_segment_t sc_ccbseg[1]; int sc_timeout; struct timeout sc_requeue_tmo; |