summaryrefslogtreecommitdiff
path: root/sys/dev/ic/ami.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/ic/ami.c')
-rw-r--r--sys/dev/ic/ami.c203
1 files changed, 94 insertions, 109 deletions
diff --git a/sys/dev/ic/ami.c b/sys/dev/ic/ami.c
index cfade4a973d..8a51e22be06 100644
--- a/sys/dev/ic/ami.c
+++ b/sys/dev/ic/ami.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ami.c,v 1.69 2005/08/22 20:39:39 marco Exp $ */
+/* $OpenBSD: ami.c,v 1.70 2005/08/30 02:40:25 dlg Exp $ */
/*
* Copyright (c) 2001 Michael Shalayeff
@@ -125,9 +125,8 @@ void ami_copyhds(struct ami_softc *sc, const u_int32_t *sizes,
const u_int8_t *props, const u_int8_t *stats);
void *ami_allocmem(bus_dma_tag_t dmat, bus_dmamap_t *map,
bus_dma_segment_t *segp, size_t isize, size_t nent, const char *iname);
-void ami_freemem(bus_dma_tag_t dmat, bus_dmamap_t *map,
+void ami_freemem(caddr_t p, bus_dma_tag_t dmat, bus_dmamap_t *map,
bus_dma_segment_t *segp, size_t isize, size_t nent, const char *iname);
-void ami_dispose(struct ami_softc *sc);
void ami_stimeout(void *v);
int ami_cmd(struct ami_ccb *ccb, int flags, int wait);
int ami_start(struct ami_ccb *ccb, int wait);
@@ -240,66 +239,65 @@ ami_allocmem(dmat, map, segp, isize, nent, iname)
int error, rseg;
/* XXX this is because we might have no dmamem_load_raw */
+ if ((error = bus_dmamap_create(dmat, total, 1,
+ total, 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, map))) {
+ printf(": cannot create %s dmamap (%d)\n", iname, error);
+ return (NULL);
+ }
+
if ((error = bus_dmamem_alloc(dmat, total, PAGE_SIZE, 0, segp, 1,
&rseg, BUS_DMA_NOWAIT))) {
printf(": cannot allocate %s%s (%d)\n",
iname, nent==1? "": "s", error);
- return (NULL);
+ goto destroy;
}
if ((error = bus_dmamem_map(dmat, segp, rseg, total, &p,
BUS_DMA_NOWAIT))) {
printf(": cannot map %s%s (%d)\n",
iname, nent==1? "": "s", error);
- return (NULL);
+ goto free;
}
- bzero(p, total);
- if ((error = bus_dmamap_create(dmat, total, 1,
- total, 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, map))) {
- printf(": cannot create %s dmamap (%d)\n", iname, error);
- return (NULL);
- }
if ((error = bus_dmamap_load(dmat, *map, p, total, NULL,
BUS_DMA_NOWAIT))) {
printf(": cannot load %s dma map (%d)\n", iname, error);
- return (NULL);
+ goto unmap;
}
+ bzero(p, total);
+
return (p);
+
+unmap:
+ bus_dmamem_unmap(dmat, p, total);
+free:
+ bus_dmamem_free(dmat, segp, 1);
+destroy:
+ bus_dmamap_destroy(dmat, *map);
+
+ return (NULL);
}
void
-ami_freemem(dmat, map, segp, isize, nent, iname)
+ami_freemem(p, dmat, map, segp, isize, nent, iname)
+ caddr_t p;
bus_dma_tag_t dmat;
bus_dmamap_t *map;
bus_dma_segment_t *segp;
size_t isize, nent;
const char *iname;
{
+ size_t total = isize * nent;
+
+ bus_dmamap_unload(dmat, *map);
+ bus_dmamem_unmap(dmat, p, total);
bus_dmamem_free(dmat, segp, 1);
bus_dmamap_destroy(dmat, *map);
*map = NULL;
}
void
-ami_dispose(sc)
- struct ami_softc *sc;
-{
- register struct ami_ccb *ccb;
-
- /* traverse the ccbs and destroy the maps */
- for (ccb = &sc->sc_ccbs[AMI_MAXCMDS - 1]; ccb > sc->sc_ccbs; ccb--)
- if (ccb->ccb_dmamap)
- bus_dmamap_destroy(sc->dmat, ccb->ccb_dmamap);
- ami_freemem(sc->dmat, &sc->sc_sgmap, sc->sc_sgseg,
- sizeof(struct ami_sgent) * AMI_SGEPERCMD, AMI_MAXCMDS, "sglist");
- ami_freemem(sc->dmat, &sc->sc_cmdmap, sc->sc_cmdseg,
- sizeof(struct ami_iocmd), AMI_MAXCMDS + 1, "command");
-}
-
-
-void
ami_copyhds(sc, sizes, props, stats)
struct ami_softc *sc;
const u_int32_t *sizes;
@@ -339,28 +337,18 @@ ami_attach(sc)
/* u_int32_t *pp; */
if (!(idata = ami_allocmem(sc->dmat, &idatamap, idataseg,
- NBPG, 1, "init data"))) {
- ami_freemem(sc->dmat, &idatamap, idataseg,
- NBPG, 1, "init data");
+ NBPG, 1, "init data")))
return 1;
- }
sc->sc_cmds = ami_allocmem(sc->dmat, &sc->sc_cmdmap, sc->sc_cmdseg,
sizeof(struct ami_iocmd), AMI_MAXCMDS+1, "command");
- if (!sc->sc_cmds) {
- ami_dispose(sc);
- ami_freemem(sc->dmat, &idatamap,
- idataseg, NBPG, 1, "init data");
- return 1;
- }
+ if (!sc->sc_cmds)
+ goto free_idata;
+
sc->sc_sgents = ami_allocmem(sc->dmat, &sc->sc_sgmap, sc->sc_sgseg,
sizeof(struct ami_sgent) * AMI_SGEPERCMD, AMI_MAXCMDS+1, "sglist");
- if (!sc->sc_sgents) {
- ami_dispose(sc);
- ami_freemem(sc->dmat, &idatamap,
- idataseg, NBPG, 1, "init data");
- return 1;
- }
+ if (!sc->sc_sgents)
+ goto free_cmds;
TAILQ_INIT(&sc->sc_ccbq);
TAILQ_INIT(&sc->sc_ccbdone);
@@ -382,10 +370,7 @@ ami_attach(sc)
if (error) {
printf(": cannot create ccb dmamap (%d)\n",
error);
- ami_dispose(sc);
- ami_freemem(sc->dmat, &idatamap,
- idataseg, NBPG, 1, "init data");
- return (1);
+ goto destroy;
}
ccb->ccb_sc = sc;
ccb->ccb_cmd = cmd;
@@ -472,10 +457,7 @@ ami_attach(sc)
if (ami_cmd(ccb, BUS_DMA_NOWAIT, 1) != 0) {
AMI_UNLOCK_AMI(sc, lock);
printf(": cannot do inquiry\n");
- ami_dispose(sc);
- ami_freemem(sc->dmat, &idatamap,
- idataseg, NBPG, 1, "init data");
- return (1);
+ goto destroy;
}
}
@@ -565,7 +547,7 @@ ami_attach(sc)
AMI_UNLOCK_AMI(sc, lock);
}
- ami_freemem(sc->dmat, &idatamap, idataseg, NBPG, 1, "init data");
+ ami_freemem(idata, sc->dmat, &idatamap, idataseg, NBPG, 1, "init data");
/* hack for hp netraid version encoding */
if ('A' <= sc->sc_fwver[2] && sc->sc_fwver[2] <= 'Z' &&
@@ -647,6 +629,21 @@ ami_attach(sc)
}
return 0;
+
+destroy:
+ for (ccb = &sc->sc_ccbs[AMI_MAXCMDS - 1]; ccb > sc->sc_ccbs; ccb--)
+ if (ccb->ccb_dmamap)
+ bus_dmamap_destroy(sc->dmat, ccb->ccb_dmamap);
+
+ ami_freemem(sc->sc_sgents, sc->dmat, &sc->sc_sgmap, sc->sc_sgseg,
+ sizeof(struct ami_sgent) * AMI_SGEPERCMD, AMI_MAXCMDS+1, "sglist");
+free_cmds:
+ ami_freemem(sc->sc_cmds, sc->dmat, &sc->sc_cmdmap, sc->sc_cmdseg,
+ sizeof(struct ami_iocmd), AMI_MAXCMDS+1, "command");
+free_idata:
+ ami_freemem(idata, sc->dmat, &idatamap, idataseg, NBPG, 1, "init data");
+
+ return 1;
}
int
@@ -1232,24 +1229,22 @@ ami_done(sc, idx)
if (xs) {
timeout_del(&xs->stimeout);
- if (xs->cmd->opcode != PREVENT_ALLOW &&
- xs->cmd->opcode != SYNCHRONIZE_CACHE) {
- bus_dmamap_sync(sc->dmat, ccb->ccb_dmamap, 0,
- ccb->ccb_dmamap->dm_mapsize,
- (xs->flags & SCSI_DATA_IN) ?
- BUS_DMASYNC_POSTREAD :
- BUS_DMASYNC_POSTWRITE);
-
- if (ccb->ami_pt.idata) {
- if (ccb->ami_pt.dir == AMI_PT_IN)
- memcpy(xs->data, ccb->ami_pt.idata +
- sizeof(struct ami_passthrough),
- xs->datalen);
-
- ccb->ami_pt.idata = NULL;
- ami_freemem(sc->dmat, &ccb->ami_pt.idatamap,
- ccb->ami_pt.idataseg, NBPG, 1, "ami raw");
- }
+ if (ccb->ami_pt.idata) {/* this is on the pt bus */
+ if (ccb->ami_pt.dir == AMI_PT_IN)
+ memcpy(xs->data, ccb->ami_pt.idata +
+ sizeof(struct ami_passthrough),
+ xs->datalen);
+
+ wakeup(ccb->ami_pt.idata);
+ ccb->ami_pt.idata = NULL;
+ } else {
+ if (xs->cmd->opcode != PREVENT_ALLOW &&
+ xs->cmd->opcode != SYNCHRONIZE_CACHE)
+ bus_dmamap_sync(sc->dmat, ccb->ccb_dmamap, 0,
+ ccb->ccb_dmamap->dm_mapsize,
+ (xs->flags & SCSI_DATA_IN) ?
+ BUS_DMASYNC_POSTREAD :
+ BUS_DMASYNC_POSTWRITE);
bus_dmamap_unload(sc->dmat, ccb->ccb_dmamap);
}
@@ -1328,6 +1323,9 @@ ami_scsi_raw_cmd(xs)
int error;
int direction;
ami_lock_t lock;
+ void *idata;
+ bus_dmamap_t idatamap;
+ bus_dma_segment_t idataseg[1];
paddr_t pa;
char type;
@@ -1413,8 +1411,7 @@ ami_scsi_raw_cmd(xs)
return (COMPLETE);
}
- if (!(ccb->ami_pt.idata = ami_allocmem(sc->dmat,
- &ccb->ami_pt.idatamap, ccb->ami_pt.idataseg, NBPG, 1,
+ if (!(idata = ami_allocmem(sc->dmat, &idatamap, idataseg, NBPG, 1,
"ami raw"))) {
ami_put_ccb(ccb);
xs->error = XS_DRIVER_STUFFUP;
@@ -1423,9 +1420,11 @@ ami_scsi_raw_cmd(xs)
return (COMPLETE);
}
+ ccb->ami_pt.idata = idata;
ccb->ami_pt.dir = direction;
- ps = ccb->ami_pt.idata;
- pa = ccb->ami_pt.idataseg[0].ds_addr;
+ ps = idata;
+ pa = idataseg[0].ds_addr;
+ ps = (struct ami_passthrough *)idata;
memset(ps, 0, sizeof *ps);
@@ -1449,11 +1448,11 @@ ami_scsi_raw_cmd(xs)
if (ccb->ami_pt.dir == AMI_PT_OUT)
memcpy(ccb->ami_pt.idata + sizeof *ps, xs->data, xs->datalen);
- if ((error = ami_cmd(ccb, ((xs->flags & SCSI_NOSLEEP)?
+ if ((error = ami_cmd(ccb, ((xs->flags & SCSI_NOSLEEP) ?
BUS_DMA_NOWAIT : BUS_DMA_WAITOK), xs->flags & SCSI_POLL))) {
+ ami_freemem(ccb->ami_pt.idata, sc->dmat, &idatamap, idataseg,
+ NBPG, 1, "ami raw");
ccb->ami_pt.idata = NULL;
- ami_freemem(sc->dmat, &ccb->ami_pt.idatamap,
- ccb->ami_pt.idataseg, NBPG, 1, "ami raw");
xs->error = XS_DRIVER_STUFFUP;
scsi_done(xs);
@@ -1461,34 +1460,26 @@ ami_scsi_raw_cmd(xs)
return (COMPLETE);
}
-
if (xs->flags & SCSI_POLL) {
if (xs->cmd->opcode == INQUIRY) {
- type = *((char *)ccb->ami_pt.idata + sizeof *ps) &
- SID_TYPE;
+ type = *((char *)idata + sizeof *ps) & SID_TYPE;
if (!(type == T_PROCESSOR || type == T_ENCLOSURE))
xs->error = XS_DRIVER_STUFFUP;
else
rsc->sc_proctarget = target; /* save off target */
}
-
-
- if (ccb->ami_pt.dir == AMI_PT_IN)
- memcpy(xs->data, ccb->ami_pt.idata + sizeof *ps,
- xs->datalen);
-
- ccb->ami_pt.idata = NULL;
- ami_freemem(sc->dmat, &ccb->ami_pt.idatamap,
- ccb->ami_pt.idataseg, NBPG, 1, "ami raw");
+ if (direction == AMI_PT_IN)
+ memcpy(xs->data, idata + sizeof *ps, xs->datalen);
scsi_done(xs);
- AMI_UNLOCK_AMI(sc, lock);
- return (COMPLETE);
- }
+ } else
+ tsleep(ccb->ami_pt.idata, PRIBIO, "ami_pt", 0);
+
+ ami_freemem(idata, sc->dmat, &idatamap, idataseg, NBPG, 1, "ami raw");
AMI_UNLOCK_AMI(sc, lock);
- return (SUCCESSFULLY_QUEUED);
+ return (COMPLETE);
}
int
@@ -1887,10 +1878,8 @@ ami_drv_inq(sc, ch, tg, page, inqbuf)
int error = 0;
if (!(idata = ami_allocmem(sc->dmat, &idatamap, idataseg, NBPG, 1,
- "ami mgmt"))) {
- error = ENOMEM;
- goto bail;
- }
+ "ami mgmt")))
+ return (ENOMEM);
pa = idataseg[0].ds_addr;
ps = idata;
@@ -1930,8 +1919,7 @@ ami_drv_inq(sc, ch, tg, page, inqbuf)
else
error = EINVAL;
-bail:
- ami_freemem(sc->dmat, &idatamap, idataseg, NBPG, 1, "ami mgmt");
+ ami_freemem(idata, sc->dmat, &idatamap, idataseg, NBPG, 1, "ami mgmt");
return (error);
}
@@ -1955,10 +1943,8 @@ ami_mgmt(sc, opcode, par1, par2, par3, size, buffer)
int error = 0;
if (!(idata = ami_allocmem(sc->dmat, &idatamap, idataseg, NBPG,
- (size / NBPG) + 1, "ami mgmt"))) {
- error = ENOMEM;
- goto bail;
- }
+ (size / NBPG) + 1, "ami mgmt")))
+ return (ENOMEM);
pa = idataseg[0].ds_addr;
@@ -1991,9 +1977,8 @@ ami_mgmt(sc, opcode, par1, par2, par3, size, buffer)
else
error = EINVAL;
-bail:;
- ami_freemem(sc->dmat, &idatamap, idataseg, NBPG, (size / NBPG) + 1,
- "ami mgmt");
+ ami_freemem(idata, sc->dmat, &idatamap, idataseg, NBPG,
+ (size / NBPG) + 1, "ami mgmt");
return (error);
}