summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorNiklas Hallqvist <niklas@cvs.openbsd.org>2000-03-01 22:38:52 +0000
committerNiklas Hallqvist <niklas@cvs.openbsd.org>2000-03-01 22:38:52 +0000
commitc440e806aa95acc4fe97664161b191c2a7e2d3ec (patch)
tree118d3ea3f7ff1102b93a5271240cdf3a105c70fe /sys/dev
parent6103bc6d00b1a47b10e50dce6983d527fc212315 (diff)
Proper bus_dma usage, fixes cache incosistencies
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/ic/gdt_common.c71
-rw-r--r--sys/dev/ic/gdtvar.h4
-rw-r--r--sys/dev/pci/gdt_pci.c3
3 files changed, 55 insertions, 23 deletions
diff --git a/sys/dev/ic/gdt_common.c b/sys/dev/ic/gdt_common.c
index b18c608854d..ac5e0c33ed2 100644
--- a/sys/dev/ic/gdt_common.c
+++ b/sys/dev/ic/gdt_common.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: gdt_common.c,v 1.4 2000/02/13 11:23:15 niklas Exp $ */
+/* $OpenBSD: gdt_common.c,v 1.5 2000/03/01 22:38:51 niklas Exp $ */
/*
* Copyright (c) 1999, 2000 Niklas Hallqvist. All rights reserved.
@@ -107,7 +107,7 @@ gdt_attach(gdt)
struct gdt_softc *gdt;
{
u_int16_t cdev_cnt;
- int i, id, drv_cyls, drv_hds, drv_secs;
+ int i, id, drv_cyls, drv_hds, drv_secs, error;
gdt_polling = 1;
gdt_from_wait = 0;
@@ -120,6 +120,16 @@ gdt_attach(gdt)
/* Initialize the ccbs */
for (i = 0; i < GDT_MAXCMDS; i++) {
gdt->sc_ccbs[i].gc_cmd_index = i + 2;
+ error = bus_dmamap_create(gdt->sc_dmat,
+ (GDT_MAXOFFSETS - 1) << PGSHIFT, GDT_MAXOFFSETS,
+ (GDT_MAXOFFSETS - 1) << PGSHIFT, 0,
+ BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
+ &gdt->sc_ccbs[i].gc_dmamap_xfer);
+ if (error) {
+ printf("%s: cannot create ccb dmamap (%d)",
+ gdt->sc_dev.dv_xname, error);
+ return (1);
+ }
(void)gdt_ccb_set_cmd(gdt->sc_ccbs + i, GDT_GCF_UNUSED);
TAILQ_INSERT_TAIL(&gdt->sc_free_ccb, &gdt->sc_ccbs[i],
gc_chain);
@@ -460,6 +470,8 @@ gdt_scsi_cmd(xs)
u_int32_t blockno, blockcnt;
struct scsi_rw *rw;
struct scsi_rw_big *rwb;
+ bus_dmamap_t xfer;
+ int error;
GDT_DPRINTF(GDT_D_CMD, ("gdt_scsi_cmd "));
@@ -596,6 +608,26 @@ gdt_scsi_cmd(xs)
ccb->gc_service = GDT_CACHESERVICE;
gdt_ccb_set_cmd(ccb, GDT_GCF_SCSI);
+ xfer = ccb->gc_dmamap_xfer;
+ error = bus_dmamap_load(gdt->sc_dmat, xfer, xs->data,
+ xs->datalen, NULL, (xs->flags & SCSI_NOSLEEP) ?
+ BUS_DMA_NOWAIT : BUS_DMA_WAITOK);
+ if (error) {
+ printf("%s: gdt_scsi_cmd: ", gdt->sc_dev.dv_xname);
+ if (error == EFBIG)
+ printf("more than %d dma segs\n",
+ GDT_MAXOFFSETS);
+ else
+ printf("error %d loading dma map\n", error);
+
+ xs->error = XS_DRIVER_STUFFUP;
+ gdt_free_ccb(gdt, ccb);
+ return (COMPLETE);
+ }
+ bus_dmamap_sync(gdt->sc_dmat, xfer,
+ (xs->flags & SCSI_DATA_IN) ? BUS_DMASYNC_PREREAD :
+ BUS_DMASYNC_PREWRITE);
+
gdt_enqueue_ccb(gdt, ccb);
/* XXX what if enqueue did not start a transfer? */
if (gdt_polling) {
@@ -634,9 +666,8 @@ gdt_exec_ccb(ccb)
struct gdt_softc *gdt = link->adapter_softc;
u_int8_t target = link->target;
u_int32_t sg_canz;
- int i, len, off;
- u_int8_t *buf;
- paddr_t pa;
+ bus_dmamap_t xfer;
+ int i;
GDT_DPRINTF(GDT_D_CMD, ("gdt_exec_ccb(%p, %p) ", xs, ccb));
@@ -681,34 +712,28 @@ gdt_exec_ccb(ccb)
ccb->gc_blockcnt);
}
+ xfer = ccb->gc_dmamap_xfer;
if (gdt->sc_cache_feat & GDT_SCATTER_GATHER) {
gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_CACHE_DESTADDR,
0xffffffff);
- len = xs->datalen;
- buf = xs->data;
- for (i = 0; len > 0; i++) {
- for (off = PAGE_SIZE, pa = vtophys(buf); off < len;
- off += PAGE_SIZE)
- if (pa + off != vtophys(buf + off))
- break;
-
+ for (i = 0; i < xfer->dm_nsegs; i++) {
gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION +
- GDT_CACHE_SG_LST + i * GDT_SG_SZ + GDT_SG_PTR, pa);
+ GDT_CACHE_SG_LST + i * GDT_SG_SZ + GDT_SG_PTR,
+ xfer->dm_segs[i].ds_addr);
gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION +
GDT_CACHE_SG_LST + i * GDT_SG_SZ + GDT_SG_LEN,
- MIN(off, len));
+ xfer->dm_segs[i].ds_len);
GDT_DPRINTF(GDT_D_IO, ("#%d va %p pa %p len %x\n", i,
- buf, (void *)pa, MIN(off, len)));
-
- len -= off;
- buf += off;
+ buf, xfer->dm_segs[i].ds_addr,
+ xfer->dm_segs[i].ds_len));
}
- sg_canz = i;
+ sg_canz = xfer->dm_nsegs;
gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_CACHE_SG_LST +
sg_canz * GDT_SG_SZ + GDT_SG_LEN, 0);
} else {
+ /* XXX Hardly correct */
gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_CACHE_DESTADDR,
- vtophys(xs->data));
+ xfer->dm_segs[0].ds_addr);
sg_canz = 0;
}
gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_CACHE_SG_CANZ, sg_canz);
@@ -990,6 +1015,10 @@ gdt_intr(arg)
untimeout(gdt_timeout, ccb);
ctx.service = ccb->gc_service;
prev_cmd = ccb->gc_flags & GDT_GCF_CMD_MASK;
+ bus_dmamap_sync(gdt->sc_dmat, ccb->gc_dmamap_xfer,
+ (xs->flags & SCSI_DATA_IN) ? BUS_DMASYNC_POSTREAD :
+ BUS_DMASYNC_POSTWRITE);
+ bus_dmamap_unload(gdt->sc_dmat, ccb->gc_dmamap_xfer);
gdt_free_ccb(gdt, ccb);
switch (prev_cmd) {
case GDT_GCF_UNUSED:
diff --git a/sys/dev/ic/gdtvar.h b/sys/dev/ic/gdtvar.h
index 8f3922da5cb..ee4d1cd0ce9 100644
--- a/sys/dev/ic/gdtvar.h
+++ b/sys/dev/ic/gdtvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: gdtvar.h,v 1.2 2000/02/07 04:30:21 itojun Exp $ */
+/* $OpenBSD: gdtvar.h,v 1.3 2000/03/01 22:38:51 niklas Exp $ */
/*
* Copyright (c) 1999, 2000 Niklas Hallqvist. All rights reserved.
@@ -68,6 +68,7 @@ struct gdt_intr_ctx {
struct gdt_ccb {
TAILQ_ENTRY(gdt_ccb) gc_chain;
struct scsi_xfer *gc_xs;
+ bus_dmamap_t gc_dmamap_xfer;
int gc_timeout;
u_int32_t gc_info;
u_int32_t gc_blockno;
@@ -116,6 +117,7 @@ struct gdt_softc {
bus_space_tag_t sc_dpmemt;
bus_space_handle_t sc_dpmemh;
bus_addr_t sc_dpmembase;
+ bus_dma_tag_t sc_dmat;
/* XXX These could go into a class-dependent opaque struct instead */
bus_space_tag_t sc_iot;
diff --git a/sys/dev/pci/gdt_pci.c b/sys/dev/pci/gdt_pci.c
index a2fdf58b851..22f80c96763 100644
--- a/sys/dev/pci/gdt_pci.c
+++ b/sys/dev/pci/gdt_pci.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: gdt_pci.c,v 1.2 2000/02/13 10:59:06 niklas Exp $ */
+/* $OpenBSD: gdt_pci.c,v 1.3 2000/03/01 22:38:51 niklas Exp $ */
/*
* Copyright (c) 1999 Niklas Hallqvist. All rights reserved.
@@ -286,6 +286,7 @@ gdt_pci_attach(parent, self, aux)
gdt->sc_dpmemt = dpmemt;
gdt->sc_dpmemh = dpmemh;
gdt->sc_dpmembase = dpmembase;
+ gdt->sc_dmat = pa->pa_dmat;
/*
* The GDT_PCINEW series also has two other regions to map.