summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorNiklas Hallqvist <niklas@cvs.openbsd.org>1998-01-20 18:40:37 +0000
committerNiklas Hallqvist <niklas@cvs.openbsd.org>1998-01-20 18:40:37 +0000
commite4232757b30346a182214fb65da8a76f2edb7b24 (patch)
tree5c1b89b92ef8c67dfa2d0f3a078804042a1555ee /sys/dev
parent0a8f2cc87f99deec610ef91696850a249bd8fb81 (diff)
Merge bus_dma support from NetBSD, mostly by Jason Thorpe. Only i386 uses it
so far, the other archs gets placeholders for now. I wrote a compatibility layer for OpenBSD's old isadma code so we can still use our old driver sources. They will however get changed to native bus_dma use, on a case by case basis. Oh yes, I almost forgot, I kept our notion of isadma being a device so DMA-less ISA-busses still work
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/eisa/eisavar.h6
-rw-r--r--sys/dev/isa/isa.c105
-rw-r--r--sys/dev/isa/isadma.c795
-rw-r--r--sys/dev/isa/isadmareg.h26
-rw-r--r--sys/dev/isa/isadmavar.h115
-rw-r--r--sys/dev/isa/isapnp.c4
-rw-r--r--sys/dev/isa/isavar.h112
-rw-r--r--sys/dev/pci/pci.c5
-rw-r--r--sys/dev/pci/pcivar.h6
-rw-r--r--sys/dev/pci/ppb.c5
10 files changed, 863 insertions, 316 deletions
diff --git a/sys/dev/eisa/eisavar.h b/sys/dev/eisa/eisavar.h
index bb740f327ab..2115d6b5960 100644
--- a/sys/dev/eisa/eisavar.h
+++ b/sys/dev/eisa/eisavar.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: eisavar.h,v 1.7 1997/03/12 20:13:01 pefo Exp $ */
-/* $NetBSD: eisavar.h,v 1.10 1996/10/21 22:31:03 thorpej Exp $ */
+/* $OpenBSD: eisavar.h,v 1.8 1998/01/20 18:40:26 niklas Exp $ */
+/* $NetBSD: eisavar.h,v 1.11 1997/06/06 23:30:07 thorpej Exp $ */
/*
* Copyright (c) 1995, 1996 Christopher G. Demetriou
@@ -76,6 +76,7 @@ struct eisabus_attach_args {
char *eba_busname; /* XXX should be common */
bus_space_tag_t eba_iot; /* eisa i/o space tag */
bus_space_tag_t eba_memt; /* eisa mem space tag */
+ bus_dma_tag_t eba_dmat; /* DMA tag */
eisa_chipset_tag_t eba_ec;
};
@@ -85,6 +86,7 @@ struct eisabus_attach_args {
struct eisa_attach_args {
bus_space_tag_t ea_iot; /* eisa i/o space tag */
bus_space_tag_t ea_memt; /* eisa mem space tag */
+ bus_dma_tag_t ea_dmat; /* DMA tag */
eisa_chipset_tag_t ea_ec;
eisa_slot_t ea_slot;
diff --git a/sys/dev/isa/isa.c b/sys/dev/isa/isa.c
index 349dc18a665..c11c6744fb2 100644
--- a/sys/dev/isa/isa.c
+++ b/sys/dev/isa/isa.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: isa.c,v 1.27 1997/12/25 13:33:03 downsj Exp $ */
+/* $OpenBSD: isa.c,v 1.28 1998/01/20 18:40:28 niklas Exp $ */
/* $NetBSD: isa.c,v 1.85 1996/05/14 00:31:04 thorpej Exp $ */
/*
@@ -74,10 +74,13 @@
#include <dev/isa/isareg.h>
#include <dev/isa/isavar.h>
+#include <dev/isa/isadmareg.h>
int isamatch __P((struct device *, void *, void *));
void isaattach __P((struct device *, struct device *, void *));
+extern int autoconf_verbose;
+
struct cfattach isa_ca = {
sizeof(struct isa_softc), isamatch, isaattach
};
@@ -115,14 +118,36 @@ isaattach(parent, self, aux)
sc->sc_iot = iba->iba_iot;
sc->sc_memt = iba->iba_memt;
+#if NISADMA > 0
+ sc->sc_dmat = iba->iba_dmat;
+#endif /* NISADMA > 0 */
sc->sc_ic = iba->iba_ic;
+#if NISADMA > 0
+ /*
+ * Map the registers used by the ISA DMA controller.
+ * XXX Should be done in the isadmaattach routine.. but the delay
+ * XXX port makes it troublesome. Note that these aren't really
+ * XXX valid on ISA busses without DMA.
+ */
+ if (bus_space_map(sc->sc_iot, IO_DMA1, DMA1_IOSIZE, 0, &sc->sc_dma1h))
+ panic("isaattach: can't map DMA controller #1");
+ if (bus_space_map(sc->sc_iot, IO_DMA2, DMA2_IOSIZE, 0, &sc->sc_dma2h))
+ panic("isaattach: can't map DMA controller #2");
+ if (bus_space_map(sc->sc_iot, IO_DMAPG, 0xf, 0, &sc->sc_dmapgh))
+ panic("isaattach: can't map DMA page registers");
+
/*
- * Map port 0x84, which causes a 1.25us delay when read.
- * We do this now, since several drivers need it.
+ * Map port 0x84, which causes a 1.25us delay when read.
+ * We do this now, since several drivers need it.
* XXX this port doesn't exist on all ISA busses...
*/
- if (bus_space_map(sc->sc_iot, 0x84, 1, 0, &sc->sc_delaybah))
+ if (bus_space_subregion(sc->sc_iot, sc->sc_dmapgh, 0x04, 1,
+ &sc->sc_delaybah))
+#else /* NISADMA > 0 */
+ if (bus_space_map(sc->sc_iot, IO_DMAPG + 0x4, 0x1, 0,
+ &sc->sc_delaybah))
+#endif /* NISADMA > 0 */
panic("isaattach: can't map `delay port'"); /* XXX */
TAILQ_INIT(&sc->sc_subdevs);
@@ -163,6 +188,9 @@ isascan(parent, match)
ia.ia_iot = sc->sc_iot;
ia.ia_memt = sc->sc_memt;
+#if NISADMA > 0
+ ia.ia_dmat = sc->sc_dmat;
+#endif /* NISADMA > 0 */
ia.ia_ic = sc->sc_ic;
ia.ia_iobase = cf->cf_loc[0];
ia.ia_iosize = 0x666;
@@ -175,7 +203,14 @@ isascan(parent, match)
if (cf->cf_fstate == FSTATE_STAR) {
struct isa_attach_args ia2 = ia;
+ if (autoconf_verbose)
+ printf(">>> probing for %s*\n",
+ cf->cf_driver->cd_name);
while ((*cf->cf_attach->ca_match)(parent, dev, &ia2) > 0) {
+ if (autoconf_verbose)
+ printf(">>> probe for %s* clone into %s%d\n",
+ cf->cf_driver->cd_name,
+ cf->cf_driver->cd_name, cf->cf_unit);
if (ia2.ia_iosize == 0x666) {
printf("%s: iosize not repaired by driver\n",
sc->sc_dev.dv_xname);
@@ -185,20 +220,35 @@ isascan(parent, match)
dev = config_make_softc(parent, cf);
ia2 = ia;
+#if NISADMA > 0
if (ia.ia_drq != DRQUNK)
- isa_drq_alloc(sc, ia.ia_drq);
+ ISA_DRQ_ALLOC((struct device *)sc, ia.ia_drq);
+#endif /* NISAMDA > 0 */
}
+ if (autoconf_verbose)
+ printf(">>> probing for %s* finished\n",
+ cf->cf_driver->cd_name);
free(dev, M_DEVBUF);
return;
}
+ if (autoconf_verbose)
+ printf(">>> probing for %s%d\n", cf->cf_driver->cd_name,
+ cf->cf_unit);
if ((*cf->cf_attach->ca_match)(parent, dev, &ia) > 0) {
+ printf(">>> probing for %s%d succeeded\n",
+ cf->cf_driver->cd_name, cf->cf_unit);
config_attach(parent, dev, &ia, isaprint);
+#if NISADMA > 0
if (ia.ia_drq != DRQUNK)
- isa_drq_alloc(sc, ia.ia_drq);
- } else
+ ISA_DRQ_ALLOC((struct device *)sc, ia.ia_drq);
+#endif /* NISAMDA > 0 */
+ } else {
+ printf(">>> probing for %s%d failed\n",
+ cf->cf_driver->cd_name, cf->cf_unit);
free(dev, M_DEVBUF);
+ }
}
char *
@@ -219,44 +269,3 @@ isa_intr_typename(type)
panic("isa_intr_typename: invalid type %d", type);
}
}
-
-#ifdef DIAGNOSTIC
-void
-isa_drq_alloc(vsp, drq)
- void *vsp;
- int drq;
-{
- struct isa_softc *sc = vsp;
-
- if (drq < 0 || drq > 7)
- panic("isa_drq_alloc: drq %d out of range\n", drq);
-
- sc->sc_drq |= (1 << drq);
-}
-
-void
-isa_drq_free(vsp, drq)
- void *vsp;
- int drq;
-{
- struct isa_softc *sc = vsp;
-
- if (drq < 0 || drq > 7)
- panic("isa_drq_free: drq %d out of range\n", drq);
-
- sc->sc_drq &= ~(1 << drq);
-}
-
-int
-isa_drq_isfree(vsp, drq)
- void *vsp;
- int drq;
-{
- struct isa_softc *sc = vsp;
-
- if (drq < 0 || drq > 7)
- panic("isa_drq_isfree: drq %d out of range\n", drq);
-
- return (!((sc->sc_drq << drq) & 1));
-}
-#endif /* DIAGNOSTIC */
diff --git a/sys/dev/isa/isadma.c b/sys/dev/isa/isadma.c
index 141323ed8c8..bb09d9f4959 100644
--- a/sys/dev/isa/isadma.c
+++ b/sys/dev/isa/isadma.c
@@ -1,41 +1,86 @@
-/* $OpenBSD: isadma.c,v 1.16 1997/12/25 12:06:47 downsj Exp $ */
-/* $NetBSD: isadma.c,v 1.19 1996/04/29 20:03:26 christos Exp $ */
+/* $OpenBSD: isadma.c,v 1.17 1998/01/20 18:40:29 niklas Exp $ */
+/* $NetBSD: isadma.c,v 1.32 1997/09/05 01:48:33 thorpej Exp $ */
+
+/*-
+ * Copyright (c) 1997 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
+ * NASA Ames Research Center.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Device driver for the ISA on-board DMA controller.
+ */
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/proc.h>
#include <sys/device.h>
-#include <sys/file.h>
-#include <sys/buf.h>
-#include <sys/syslog.h>
-#include <sys/malloc.h>
-#include <sys/uio.h>
#include <vm/vm.h>
-#include <machine/pio.h>
+#include <machine/bus.h>
#include <dev/isa/isareg.h>
#include <dev/isa/isavar.h>
#include <dev/isa/isadmavar.h>
#include <dev/isa/isadmareg.h>
-struct dma_info {
- int flags;
- int active;
- int inuse;
- int bounced;
- caddr_t addr;
- vm_size_t nbytes;
- struct isadma_seg phys[1];
-};
+#ifdef __ISADMA_COMPAT
+/* XXX ugly, but will go away soon... */
+struct device *isa_dev;
+
+bus_dmamap_t isadma_dmam[8];
+#endif
-static struct dma_info dma_info[8];
-static u_int8_t dma_finished;
+/* Used by isa_malloc() */
+#include <sys/malloc.h>
+struct isa_mem {
+ struct device *isadev;
+ int chan;
+ bus_size_t size;
+ bus_addr_t addr;
+ caddr_t kva;
+ struct isa_mem *next;
+} *isa_mem_head = 0;
-/* high byte of address is stored in this port for i-th dma channel */
+/*
+ * High byte of DMA address is stored in this DMAPG register for
+ * the Nth DMA channel.
+ */
static int dmapageport[2][4] = {
- {0x87, 0x83, 0x81, 0x82},
- {0x8f, 0x8b, 0x89, 0x8a}
+ {0x7, 0x3, 0x1, 0x2},
+ {0xf, 0xb, 0x9, 0xa}
};
static u_int8_t dmamode[4] = {
@@ -47,7 +92,6 @@ static u_int8_t dmamode[4] = {
int isadmamatch __P((struct device *, void *, void *));
void isadmaattach __P((struct device *, struct device *, void *));
-int isadmaprint __P((void *, const char *));
struct cfattach isadma_ca = {
sizeof(struct device), isadmamatch, isadmaattach
@@ -74,279 +118,624 @@ isadmaattach(parent, self, aux)
struct device *parent, *self;
void *aux;
{
+#ifdef __ISADMA_COMPAT
+ int i, sz;
+ struct isa_softc *sc = (struct isa_softc *)parent;
+
+ /* XXX ugly, but will go away soon... */
+ isa_dev = parent;
+
+ for (i = 0; i < 8; i++) {
+ sz = (i & 4) ? 1 << 17 : 1 << 16;
+ if ((bus_dmamap_create(sc->sc_dmat, sz, 1, sz, sz,
+ BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW, &isadma_dmam[i])) != 0)
+ panic("isa_dmastart: can not create DMA map");
+ }
+#endif
+
+ /* XXX I'd like to map the DMA ports here, see isa.c why not... */
+
printf("\n");
}
-/*
- * Register a DMA channel's usage. Usually called from a device driver
- * in open() or during it's initialization.
- */
-int
-isadma_acquire(chan)
+static inline void isa_dmaunmask __P((struct isa_softc *, int));
+static inline void isa_dmamask __P((struct isa_softc *, int));
+
+static inline void
+isa_dmaunmask(sc, chan)
+ struct isa_softc *sc;
int chan;
{
- struct dma_info *di;
-#ifdef DIAGNOSTIC
- if (chan < 0 || chan > 7)
- panic("isadma_acquire: channel out of range");
-#endif
+ int ochan = chan & 3;
+
+ /* set dma channel mode, and set dma channel mode */
+ if ((chan & 4) == 0)
+ bus_space_write_1(sc->sc_iot, sc->sc_dma1h,
+ DMA1_SMSK, ochan | DMA37SM_CLEAR);
+ else
+ bus_space_write_1(sc->sc_iot, sc->sc_dma2h,
+ DMA2_SMSK, ochan | DMA37SM_CLEAR);
+}
- di = dma_info + chan;
+static inline void
+isa_dmamask(sc, chan)
+ struct isa_softc *sc;
+ int chan;
+{
+ int ochan = chan & 3;
- if (di->inuse) {
- log(LOG_ERR, "isadma_acquire: channel %d already in use\n", chan);
- return (EBUSY);
+ /* set dma channel mode, and set dma channel mode */
+ if ((chan & 4) == 0) {
+ bus_space_write_1(sc->sc_iot, sc->sc_dma1h,
+ DMA1_SMSK, ochan | DMA37SM_SET);
+ bus_space_write_1(sc->sc_iot, sc->sc_dma1h,
+ DMA1_FFC, 0);
+ } else {
+ bus_space_write_1(sc->sc_iot, sc->sc_dma2h,
+ DMA2_SMSK, ochan | DMA37SM_SET);
+ bus_space_write_1(sc->sc_iot, sc->sc_dma2h,
+ DMA2_FFC, 0);
}
- di->inuse = 1;
-
- return (0);
}
/*
- * Unregister a DMA channel's usage. Usually called from a device driver
- * during close() or during it's shutdown.
+ * isa_dmacascade(): program 8237 DMA controller channel to accept
+ * external dma control by a board.
*/
void
-isadma_release(chan)
+isa_dmacascade(isadev, chan)
+ struct device *isadev;
int chan;
{
- struct dma_info *di;
-#ifdef DIAGNOSTIC
- if (chan < 0 || chan > 7)
- panic("isadma_release: channel out of range");
-#endif
- di = dma_info + chan;
+ struct isa_softc *sc = (struct isa_softc *)isadev;
+ int ochan = chan & 3;
- if (!di->inuse) {
- log(LOG_ERR, "isadma_release: channel %d not in use\n", chan);
- return;
+ if (chan < 0 || chan > 7) {
+ printf("%s: bogus drq %d\n", sc->sc_dev.dv_xname, chan);
+ goto lose;
+ }
+
+ if (ISA_DRQ_ISFREE(sc, chan) == 0) {
+ printf("%s: DRQ %d is not free\n", sc->sc_dev.dv_xname, chan);
+ goto lose;
}
- if (di->active)
- isadma_abort(chan);
+ ISA_DRQ_ALLOC(sc, chan);
+
+ /* set dma channel mode, and set dma channel mode */
+ if ((chan & 4) == 0)
+ bus_space_write_1(sc->sc_iot, sc->sc_dma1h,
+ DMA1_MODE, ochan | DMA37MD_CASCADE);
+ else
+ bus_space_write_1(sc->sc_iot, sc->sc_dma2h,
+ DMA2_MODE, ochan | DMA37MD_CASCADE);
+
+ isa_dmaunmask(sc, chan);
+ return;
- di->inuse = 0;
+ lose:
+ panic("isa_dmacascade");
}
-/*
- * isadma_cascade(): program 8237 DMA controller channel to accept
- * external dma control by a board.
- */
-void
-isadma_cascade(chan)
+int
+isa_dmamap_create(isadev, chan, size, flags)
+ struct device *isadev;
int chan;
+ bus_size_t size;
+ int flags;
{
- struct dma_info *di;
+ struct isa_softc *sc = (struct isa_softc *)isadev;
+ bus_size_t maxsize;
-#ifdef ISADMA_DEBUG
- if (chan < 0 || chan > 7)
- panic("isadma_cascade: impossible request");
-#endif
- di = dma_info + chan;
+ if (chan < 0 || chan > 7) {
+ printf("%s: bogus drq %d\n", sc->sc_dev.dv_xname, chan);
+ goto lose;
+ }
- /* set dma channel mode, and set dma channel mode */
- if ((chan & 4) == 0) {
- outb(DMA1_MODE, chan | DMA37MD_CASCADE);
- outb(DMA1_SMSK, chan);
- } else {
- chan &= 3;
+ if (chan & 4)
+ maxsize = (1 << 17);
+ else
+ maxsize = (1 << 16);
+
+ if (size > maxsize)
+ return (EINVAL);
+
+ if (ISA_DRQ_ISFREE(sc, chan) == 0) {
+ printf("%s: drq %d is not free\n", sc->sc_dev.dv_xname, chan);
+ goto lose;
+ }
- outb(DMA2_MODE, chan | DMA37MD_CASCADE);
- outb(DMA2_SMSK, chan);
+ ISA_DRQ_ALLOC(sc, chan);
+
+ return (bus_dmamap_create(sc->sc_dmat, size, 1, size, maxsize,
+ flags, &sc->sc_dmamaps[chan]));
+
+ lose:
+ panic("isa_dmamap_create");
+}
+
+void
+isa_dmamap_destroy(isadev, chan)
+ struct device *isadev;
+ int chan;
+{
+ struct isa_softc *sc = (struct isa_softc *)isadev;
+
+ if (chan < 0 || chan > 7) {
+ printf("%s: bogus drq %d\n", sc->sc_dev.dv_xname, chan);
+ goto lose;
+ }
+
+ if (ISA_DRQ_ISFREE(sc, chan)) {
+ printf("%s: drq %d is already free\n",
+ sc->sc_dev.dv_xname, chan);
+ goto lose;
}
- /* Mark it as in use, if needed. XXX */
- if (!di->inuse)
- di->inuse = 1;
+ ISA_DRQ_FREE(sc, chan);
+
+ bus_dmamap_destroy(sc->sc_dmat, sc->sc_dmamaps[chan]);
+ return;
+
+ lose:
+ panic("isa_dmamap_destroy");
}
/*
- * isadma_start(): program 8237 DMA controller channel, avoid page alignment
- * problems by using a bounce buffer.
+ * isa_dmastart(): program 8237 DMA controller channel and set it
+ * in motion.
*/
-void
-isadma_start(addr, nbytes, chan, flags)
- caddr_t addr;
- vm_size_t nbytes;
+int
+isa_dmastart(isadev, chan, addr, nbytes, p, flags, busdmaflags)
+ struct device *isadev;
int chan;
+ void *addr;
+ bus_size_t nbytes;
+ struct proc *p;
int flags;
+ int busdmaflags;
{
- struct dma_info *di;
+ struct isa_softc *sc = (struct isa_softc *)isadev;
+ bus_dmamap_t dmam;
+ bus_addr_t dmaaddr;
int waport;
- int mflags;
+ int ochan = chan & 3;
+ int error;
+#ifdef __ISADMA_COMPAT
+ int compat = busdmaflags & BUS_DMA_BUS1;
+
+ busdmaflags &= ~BUS_DMA_BUS1;
+#endif /* __ISADMA_COMPAT */
+
+ if (chan < 0 || chan > 7) {
+ printf("%s: bogus drq %d\n", sc->sc_dev.dv_xname, chan);
+ goto lose;
+ }
#ifdef ISADMA_DEBUG
- if (chan < 0 || chan > 7 ||
- (((flags & DMAMODE_READ) != 0) + ((flags & DMAMODE_WRITE) != 0) +
- ((flags & DMAMODE_LOOP) != 0) != 1) ||
- ((chan & 4) ? (nbytes >= (1<<17) || nbytes & 1 || (u_int)addr & 1) :
- (nbytes >= (1<<16))))
- panic("isadma_start: impossible request");
+ printf("isa_dmastart: drq %d, addr %p, nbytes 0x%lx, p %p, "
+ "flags 0x%x, dmaflags 0x%x\n",
+ chan, addr, nbytes, p, flags, busdmaflags);
#endif
- di = dma_info+chan;
- if (di->active) {
- log(LOG_ERR,"isadma_start: old request active on %d\n",chan);
- isadma_abort(chan);
+ if (chan & 4) {
+ if (nbytes > (1 << 17) || nbytes & 1 || (u_long)addr & 1) {
+ printf("%s: drq %d, nbytes 0x%lx, addr %p\n",
+ sc->sc_dev.dv_xname, chan, nbytes, addr);
+ goto lose;
+ }
+ } else {
+ if (nbytes > (1 << 16)) {
+ printf("%s: drq %d, nbytes 0x%lx\n",
+ sc->sc_dev.dv_xname, chan, nbytes);
+ goto lose;
+ }
}
- di->flags = flags;
- di->active = 1;
- di->addr = addr;
- di->nbytes = nbytes;
+ dmam = sc->sc_dmamaps[chan];
+ if (dmam == NULL)
+#ifdef __ISADMA_COMPAT
+ if (compat)
+ dmam = sc->sc_dmamaps[chan] = isadma_dmam[chan];
+ else
+#endif /* __ISADMA_COMPAT */
+ panic("isa_dmastart: no DMA map for chan %d\n", chan);
- mflags = ISADMA_MAP_WAITOK | ISADMA_MAP_CONTIG;
- mflags |= (chan & 4) ? ISADMA_MAP_16BIT : ISADMA_MAP_8BIT;
+ error = bus_dmamap_load(sc->sc_dmat, dmam, addr, nbytes, p,
+ busdmaflags);
+ if (error)
+ return (error);
- if (isadma_map(addr, nbytes, di->phys, mflags) != 1) {
- mflags |= ISADMA_MAP_BOUNCE;
+#ifdef ISADMA_DEBUG
+ __asm(".globl isa_dmastart_afterload ; isa_dmastart_afterload:");
+#endif
+
+ if (flags & DMAMODE_READ) {
+ bus_dmamap_sync(sc->sc_dmat, dmam, BUS_DMASYNC_PREREAD);
+ sc->sc_dmareads |= (1 << chan);
+ } else {
+ bus_dmamap_sync(sc->sc_dmat, dmam, BUS_DMASYNC_PREWRITE);
+ sc->sc_dmareads &= ~(1 << chan);
+ }
- if (isadma_map(addr, nbytes, di->phys, mflags) != 1)
- panic("isadma_start: cannot map");
+ dmaaddr = dmam->dm_segs[0].ds_addr;
- di->bounced = 1;
+#ifdef ISADMA_DEBUG
+ printf(" dmaaddr 0x%lx\n", dmaaddr);
- if ((flags & DMAMODE_READ) == 0)
- isadma_copytobuf(addr, nbytes, 1, di->phys);
+ __asm(".globl isa_dmastart_aftersync ; isa_dmastart_aftersync:");
+#endif
- /* XXX Will this do what we want with DMAMODE_LOOP? */
- if ((flags & DMAMODE_READ) == 0)
- isadma_copytobuf(addr, nbytes, 1, di->phys);
- }
+ sc->sc_dmalength[chan] = nbytes;
- dma_finished &= ~(1 << chan);
+ isa_dmamask(sc, chan);
+ sc->sc_dmafinished &= ~(1 << chan);
if ((chan & 4) == 0) {
- /*
- * Program one of DMA channels 0..3. These are
- * byte mode channels.
- */
- /* set dma channel mode, and reset address ff */
- outb(DMA1_MODE, chan | dmamode[flags]);
- outb(DMA1_FFC, 0);
+ /* set dma channel mode */
+ bus_space_write_1(sc->sc_iot, sc->sc_dma1h, DMA1_MODE,
+ ochan | dmamode[flags]);
/* send start address */
- waport = DMA1_CHN(chan);
- outb(dmapageport[0][chan], di->phys[0].addr>>16);
- outb(waport, di->phys[0].addr);
- outb(waport, di->phys[0].addr>>8);
+ waport = DMA1_CHN(ochan);
+ bus_space_write_1(sc->sc_iot, sc->sc_dmapgh,
+ dmapageport[0][ochan], (dmaaddr >> 16) & 0xff);
+ bus_space_write_1(sc->sc_iot, sc->sc_dma1h, waport,
+ dmaaddr & 0xff);
+ bus_space_write_1(sc->sc_iot, sc->sc_dma1h, waport,
+ (dmaaddr >> 8) & 0xff);
/* send count */
- outb(waport + 1, --nbytes);
- outb(waport + 1, nbytes>>8);
-
- /* unmask channel */
- outb(DMA1_SMSK, chan | DMA37SM_CLEAR);
+ bus_space_write_1(sc->sc_iot, sc->sc_dma1h, waport + 1,
+ (--nbytes) & 0xff);
+ bus_space_write_1(sc->sc_iot, sc->sc_dma1h, waport + 1,
+ (nbytes >> 8) & 0xff);
} else {
- /*
- * Program one of DMA channels 4..7. These are
- * word mode channels.
- */
- /* set dma channel mode, and reset address ff */
- outb(DMA2_MODE, (chan & 3) | dmamode[flags]);
- outb(DMA2_FFC, 0);
+ /* set dma channel mode */
+ bus_space_write_1(sc->sc_iot, sc->sc_dma2h, DMA2_MODE,
+ ochan | dmamode[flags]);
/* send start address */
- waport = DMA2_CHN(chan & 3);
- outb(dmapageport[1][chan & 3], di->phys[0].addr>>16);
- outb(waport, di->phys[0].addr>>1);
- outb(waport, di->phys[0].addr>>9);
+ waport = DMA2_CHN(ochan);
+ bus_space_write_1(sc->sc_iot, sc->sc_dmapgh,
+ dmapageport[1][ochan], (dmaaddr >> 16) & 0xff);
+ dmaaddr >>= 1;
+ bus_space_write_1(sc->sc_iot, sc->sc_dma2h, waport,
+ dmaaddr & 0xff);
+ bus_space_write_1(sc->sc_iot, sc->sc_dma2h, waport,
+ (dmaaddr >> 8) & 0xff);
/* send count */
nbytes >>= 1;
- outb(waport + 2, --nbytes);
- outb(waport + 2, nbytes>>8);
-
- /* unmask channel */
- outb(DMA2_SMSK, (chan & 3) | DMA37SM_CLEAR);
+ bus_space_write_1(sc->sc_iot, sc->sc_dma2h, waport + 2,
+ (--nbytes) & 0xff);
+ bus_space_write_1(sc->sc_iot, sc->sc_dma2h, waport + 2,
+ (nbytes >> 8) & 0xff);
}
+
+ isa_dmaunmask(sc, chan);
+ return (0);
+
+ lose:
+ panic("isa_dmastart");
}
void
-isadma_abort(chan)
+isa_dmaabort(isadev, chan)
+ struct device *isadev;
int chan;
{
- struct dma_info *di;
+ struct isa_softc *sc = (struct isa_softc *)isadev;
-#ifdef ISADMA_DEBUG
- if (chan < 0 || chan > 7)
- panic("isadma_abort: impossible request");
-#endif
+ if (chan < 0 || chan > 7) {
+ printf("%s: bogus drq %d\n", sc->sc_dev.dv_xname, chan);
+ panic("isa_dmaabort");
+ }
- di = dma_info+chan;
- if (! di->active) {
- log(LOG_ERR,"isadma_abort: no request active on %d\n",chan);
- return;
+ isa_dmamask(sc, chan);
+ bus_dmamap_unload(sc->sc_dmat, sc->sc_dmamaps[chan]);
+ sc->sc_dmareads &= ~(1 << chan);
+}
+
+bus_size_t
+isa_dmacount(isadev, chan)
+ struct device *isadev;
+ int chan;
+{
+ struct isa_softc *sc = (struct isa_softc *)isadev;
+ int waport;
+ bus_size_t nbytes;
+ int ochan = chan & 3;
+
+ if (chan < 0 || chan > 7) {
+ printf("%s: bogus drq %d\n", sc->sc_dev.dv_xname, chan);
+ panic("isa_dmacount");
}
- /* mask channel */
- if ((chan & 4) == 0)
- outb(DMA1_SMSK, DMA37SM_SET | chan);
- else
- outb(DMA2_SMSK, DMA37SM_SET | (chan & 3));
+ isa_dmamask(sc, chan);
- isadma_unmap(di->addr, di->nbytes, 1, di->phys);
- di->active = 0;
- di->bounced = 0;
+ /*
+ * We have to shift the byte count by 1. If we're in auto-initialize
+ * mode, the count may have wrapped around to the initial value. We
+ * can't use the TC bit to check for this case, so instead we compare
+ * against the original byte count.
+ * If we're not in auto-initialize mode, then the count will wrap to
+ * -1, so we also handle that case.
+ */
+ if ((chan & 4) == 0) {
+ waport = DMA1_CHN(ochan);
+ nbytes = bus_space_read_1(sc->sc_iot, sc->sc_dma1h,
+ waport + 1) + 1;
+ nbytes += bus_space_read_1(sc->sc_iot, sc->sc_dma1h,
+ waport + 1) << 8;
+ nbytes &= 0xffff;
+ } else {
+ waport = DMA2_CHN(ochan);
+ nbytes = bus_space_read_1(sc->sc_iot, sc->sc_dma2h,
+ waport + 2) + 1;
+ nbytes += bus_space_read_1(sc->sc_iot, sc->sc_dma2h,
+ waport + 2) << 8;
+ nbytes <<= 1;
+ nbytes &= 0x1ffff;
+ }
+
+ if (nbytes == sc->sc_dmalength[chan])
+ nbytes = 0;
+
+ isa_dmaunmask(sc, chan);
+ return (nbytes);
}
int
-isadma_finished(chan)
+isa_dmafinished(isadev, chan)
+ struct device *isadev;
int chan;
{
+ struct isa_softc *sc = (struct isa_softc *)isadev;
-#ifdef ISADMA_DEBUG
- if (chan < 0 || chan > 7)
- panic("isadma_finished: impossible request");
-#endif
+ if (chan < 0 || chan > 7) {
+ printf("%s: bogus drq %d\n", sc->sc_dev.dv_xname, chan);
+ panic("isa_dmafinished");
+ }
/* check that the terminal count was reached */
if ((chan & 4) == 0)
- dma_finished |= inb(DMA1_SR) & 0x0f;
+ sc->sc_dmafinished |= bus_space_read_1(sc->sc_iot,
+ sc->sc_dma1h, DMA1_SR) & 0x0f;
else
- dma_finished |= (inb(DMA2_SR) & 0x0f) << 4;
+ sc->sc_dmafinished |= (bus_space_read_1(sc->sc_iot,
+ sc->sc_dma2h, DMA2_SR) & 0x0f) << 4;
- return ((dma_finished & (1 << chan)) != 0);
+ return ((sc->sc_dmafinished & (1 << chan)) != 0);
}
void
-isadma_done(chan)
+isa_dmadone(isadev, chan)
+ struct device *isadev;
int chan;
{
- struct dma_info *di;
- u_char tc;
+ struct isa_softc *sc = (struct isa_softc *)isadev;
+ bus_dmamap_t dmam;
-#ifdef DIAGNOSTIC
- if (chan < 0 || chan > 7)
- panic("isadma_done: impossible request");
-#endif
+ if (chan < 0 || chan > 7) {
+ printf("%s: bogus drq %d\n", sc->sc_dev.dv_xname, chan);
+ panic("isa_dmadone");
+ }
- di = dma_info+chan;
- if (! di->active) {
- log(LOG_ERR,"isadma_done: no request active on %d\n",chan);
- return;
+ dmam = sc->sc_dmamaps[chan];
+
+ isa_dmamask(sc, chan);
+
+ if (isa_dmafinished(isadev, chan) == 0)
+ printf("%s: isa_dmadone: channel %d not finished\n",
+ sc->sc_dev.dv_xname, chan);
+
+ bus_dmamap_sync(sc->sc_dmat, dmam,
+ (sc->sc_dmareads & (1 << chan)) ? BUS_DMASYNC_POSTREAD :
+ BUS_DMASYNC_POSTWRITE);
+
+ bus_dmamap_unload(sc->sc_dmat, dmam);
+ sc->sc_dmareads &= ~(1 << chan);
+}
+
+int
+isa_dmamem_alloc(isadev, chan, size, addrp, flags)
+ struct device *isadev;
+ int chan;
+ bus_size_t size;
+ bus_addr_t *addrp;
+ int flags;
+{
+ struct isa_softc *sc = (struct isa_softc *)isadev;
+ bus_dma_segment_t seg;
+ int error, boundary, rsegs;
+
+ if (chan < 0 || chan > 7) {
+ printf("%s: bogus drq %d\n", sc->sc_dev.dv_xname, chan);
+ panic("isa_dmamem_alloc");
}
- /* check that the terminal count was reached */
- if ((chan & 4) == 0)
- tc = inb(DMA1_SR) & (1 << chan);
- else
- tc = inb(DMA2_SR) & (1 << (chan & 3));
- if (tc == 0)
- /* XXX probably should panic or something */
- log(LOG_ERR, "dma channel %d not finished\n", chan);
+ boundary = (chan & 4) ? (1 << 17) : (1 << 16);
- /* mask channel */
- if ((chan & 4) == 0)
- outb(DMA1_SMSK, DMA37SM_SET | chan);
- else
- outb(DMA2_SMSK, DMA37SM_SET | (chan & 3));
+ size = round_page(size);
+
+ error = bus_dmamem_alloc(sc->sc_dmat, size, NBPG, boundary,
+ &seg, 1, &rsegs, flags);
+ if (error)
+ return (error);
+
+ *addrp = seg.ds_addr;
+ return (0);
+}
+
+void
+isa_dmamem_free(isadev, chan, addr, size)
+ struct device *isadev;
+ int chan;
+ bus_addr_t addr;
+ bus_size_t size;
+{
+ struct isa_softc *sc = (struct isa_softc *)isadev;
+ bus_dma_segment_t seg;
+
+ if (chan < 0 || chan > 7) {
+ printf("%s: bogus drq %d\n", sc->sc_dev.dv_xname, chan);
+ panic("isa_dmamem_free");
+ }
+
+ seg.ds_addr = addr;
+ seg.ds_len = size;
- /* XXX Will this do what we want with DMAMODE_LOOP? */
- if (di->bounced & (di->flags & DMAMODE_READ))
- isadma_copyfrombuf(di->addr, di->nbytes, 1, di->phys);
+ bus_dmamem_free(sc->sc_dmat, &seg, 1);
+}
- isadma_unmap(di->addr, di->nbytes, 1, di->phys);
- di->active = 0;
- di->bounced = 0;
+int
+isa_dmamem_map(isadev, chan, addr, size, kvap, flags)
+ struct device *isadev;
+ int chan;
+ bus_addr_t addr;
+ bus_size_t size;
+ caddr_t *kvap;
+ int flags;
+{
+ struct isa_softc *sc = (struct isa_softc *)isadev;
+ bus_dma_segment_t seg;
+
+ if (chan < 0 || chan > 7) {
+ printf("%s: bogus drq %d\n", sc->sc_dev.dv_xname, chan);
+ panic("isa_dmamem_map");
+ }
+
+ seg.ds_addr = addr;
+ seg.ds_len = size;
+
+ return (bus_dmamem_map(sc->sc_dmat, &seg, 1, size, kvap, flags));
+}
+
+void
+isa_dmamem_unmap(isadev, chan, kva, size)
+ struct device *isadev;
+ int chan;
+ caddr_t kva;
+ size_t size;
+{
+ struct isa_softc *sc = (struct isa_softc *)isadev;
+
+ if (chan < 0 || chan > 7) {
+ printf("%s: bogus drq %d\n", sc->sc_dev.dv_xname, chan);
+ panic("isa_dmamem_unmap");
+ }
+
+ bus_dmamem_unmap(sc->sc_dmat, kva, size);
+}
+
+int
+isa_dmamem_mmap(isadev, chan, addr, size, off, prot, flags)
+ struct device *isadev;
+ int chan;
+ bus_addr_t addr;
+ bus_size_t size;
+ int off, prot, flags;
+{
+ struct isa_softc *sc = (struct isa_softc *)isadev;
+ bus_dma_segment_t seg;
+
+ if (chan < 0 || chan > 7) {
+ printf("%s: bogus drq %d\n", sc->sc_dev.dv_xname, chan);
+ panic("isa_dmamem_mmap");
+ }
+
+ seg.ds_addr = addr;
+ seg.ds_len = size;
+
+ return (bus_dmamem_mmap(sc->sc_dmat, &seg, 1, off, prot, flags));
+}
+
+int
+isa_drq_isfree(isadev, chan)
+ struct device *isadev;
+ int chan;
+{
+ struct isa_softc *sc = (struct isa_softc *)isadev;
+ if (chan < 0 || chan > 7) {
+ printf("%s: bogus drq %d\n", sc->sc_dev.dv_xname, chan);
+ panic("isa_drq_isfree");
+ }
+ return ISA_DRQ_ISFREE(sc, chan);
+}
+
+void *
+isa_malloc(isadev, chan, size, pool, flags)
+ struct device *isadev;
+ int chan;
+ size_t size;
+ int pool;
+ int flags;
+{
+ bus_addr_t addr;
+ caddr_t kva;
+ int bflags;
+ struct isa_mem *m;
+
+ bflags = flags & M_WAITOK ? BUS_DMA_WAITOK : BUS_DMA_NOWAIT;
+
+ if (isa_dmamem_alloc(isadev, chan, size, &addr, bflags))
+ return 0;
+ if (isa_dmamem_map(isadev, chan, addr, size, &kva, bflags)) {
+ isa_dmamem_free(isadev, chan, addr, size);
+ return 0;
+ }
+ m = malloc(sizeof(*m), pool, flags);
+ if (m == 0) {
+ isa_dmamem_unmap(isadev, chan, kva, size);
+ isa_dmamem_free(isadev, chan, addr, size);
+ return 0;
+ }
+ m->isadev = isadev;
+ m->chan = chan;
+ m->size = size;
+ m->addr = addr;
+ m->kva = kva;
+ m->next = isa_mem_head;
+ isa_mem_head = m;
+ return (void *)kva;
+}
+
+void
+isa_free(addr, pool)
+ void *addr;
+ int pool;
+{
+ struct isa_mem **mp, *m;
+ caddr_t kva = (caddr_t)addr;
+
+ for(mp = &isa_mem_head; *mp && (*mp)->kva != kva; mp = &(*mp)->next)
+ ;
+ m = *mp;
+ if (!m) {
+ printf("isa_free: freeing unallocted memory\n");
+ return;
+ }
+ *mp = m->next;
+ isa_dmamem_unmap(m->isadev, m->chan, kva, m->size);
+ isa_dmamem_free(m->isadev, m->chan, m->addr, m->size);
+ free(m, pool);
+}
+
+int
+isa_mappage(mem, off, prot)
+ void *mem;
+ int off;
+ int prot;
+{
+ struct isa_mem *m;
+
+ for(m = isa_mem_head; m && m->kva != (caddr_t)mem; m = m->next)
+ ;
+ if (!m) {
+ printf("isa_mappage: mapping unallocted memory\n");
+ return -1;
+ }
+ return (isa_dmamem_mmap(m->isadev, m->chan, m->addr, m->size, off,
+ prot, BUS_DMA_WAITOK));
}
diff --git a/sys/dev/isa/isadmareg.h b/sys/dev/isa/isadmareg.h
index e26bf8f808d..5d9fb8dce5b 100644
--- a/sys/dev/isa/isadmareg.h
+++ b/sys/dev/isa/isadmareg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: isadmareg.h,v 1.4 1997/11/07 08:07:02 niklas Exp $ */
+/* $OpenBSD: isadmareg.h,v 1.5 1998/01/20 18:40:30 niklas Exp $ */
/* $NetBSD: isadmareg.h,v 1.4 1995/06/28 04:31:48 cgd Exp $ */
#include <dev/ic/i8237reg.h>
@@ -6,17 +6,21 @@
/*
* Register definitions for DMA controller 1 (channels 0..3):
*/
-#define DMA1_CHN(c) (IO_DMA1 + 1*(2*(c))) /* addr reg for channel c */
-#define DMA1_SR (IO_DMA1 + 1*8) /* status register */
-#define DMA1_SMSK (IO_DMA1 + 1*10) /* single mask register */
-#define DMA1_MODE (IO_DMA1 + 1*11) /* mode register */
-#define DMA1_FFC (IO_DMA1 + 1*12) /* clear first/last FF */
+#define DMA1_CHN(c) (1*(2*(c))) /* addr reg for channel c */
+#define DMA1_SR (1*8) /* status register */
+#define DMA1_SMSK (1*10) /* single mask register */
+#define DMA1_MODE (1*11) /* mode register */
+#define DMA1_FFC (1*12) /* clear first/last FF */
+
+#define DMA1_IOSIZE (1*12)
/*
* Register definitions for DMA controller 2 (channels 4..7):
*/
-#define DMA2_CHN(c) (IO_DMA2 + 2*(2*(c))) /* addr reg for channel c */
-#define DMA2_SR (IO_DMA2 + 2*8) /* status register */
-#define DMA2_SMSK (IO_DMA2 + 2*10) /* single mask register */
-#define DMA2_MODE (IO_DMA2 + 2*11) /* mode register */
-#define DMA2_FFC (IO_DMA2 + 2*12) /* clear first/last FF */
+#define DMA2_CHN(c) (2*(2*(c))) /* addr reg for channel c */
+#define DMA2_SR (2*8) /* status register */
+#define DMA2_SMSK (2*10) /* single mask register */
+#define DMA2_MODE (2*11) /* mode register */
+#define DMA2_FFC (2*12) /* clear first/last FF */
+
+#define DMA2_IOSIZE (2*12)
diff --git a/sys/dev/isa/isadmavar.h b/sys/dev/isa/isadmavar.h
index 3e8a153632b..318d85d14bb 100644
--- a/sys/dev/isa/isadmavar.h
+++ b/sys/dev/isa/isadmavar.h
@@ -1,12 +1,52 @@
-/* $OpenBSD: isadmavar.h,v 1.10 1997/12/25 12:06:48 downsj Exp $ */
-/* $NetBSD: isadmavar.h,v 1.4 1996/03/01 04:08:46 mycroft Exp $ */
+/* $OpenBSD: isadmavar.h,v 1.11 1998/01/20 18:40:31 niklas Exp $ */
+/* $NetBSD: isadmavar.h,v 1.10 1997/08/04 22:13:33 augustss Exp $ */
-#define DMAMODE_WRITE 0
-#define DMAMODE_READ 1
-#define DMAMODE_LOOP 2
+/*-
+ * Copyright (c) 1997 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
+ * NASA Ames Research Center.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* XXX for now... */
+#ifndef __ISADMA_COMPAT
+#define __ISADMA_COMPAT
+#endif /* __ISADMA_COMPAT */
-#define ISADMA_START_READ DMAMODE_READ /* read from device */
-#define ISADMA_START_WRITE DMAMODE_WRITE /* write to device */
+#ifdef __ISADMA_COMPAT
+
+/* XXX ugly.. but it's a deprecated API that uses it so it will go.. */
+extern struct device *isa_dev;
#define ISADMA_MAP_WAITOK 0x0001 /* OK for isadma_map to sleep */
#define ISADMA_MAP_BOUNCE 0x0002 /* use bounce buffer if necessary */
@@ -17,6 +57,7 @@
struct isadma_seg { /* a physical contiguous segment */
vm_offset_t addr; /* address of this segment */
vm_size_t length; /* length of this segment (bytes) */
+ bus_dmamap_t dmam; /* DMA handle for bus_dma routines. */
};
int isadma_map __P((caddr_t, vm_size_t, struct isadma_seg *, int));
@@ -24,22 +65,48 @@ void isadma_unmap __P((caddr_t, vm_size_t, int, struct isadma_seg *));
void isadma_copytobuf __P((caddr_t, vm_size_t, int, struct isadma_seg *));
void isadma_copyfrombuf __P((caddr_t, vm_size_t, int, struct isadma_seg *));
-int isadma_acquire __P((int));
-void isadma_release __P((int));
-void isadma_cascade __P((int));
-void isadma_start __P((caddr_t, vm_size_t, int, int));
-void isadma_abort __P((int));
-int isadma_finished __P((int));
-void isadma_done __P((int));
+#define isadma_acquire(c) isa_dma_acquire(isa_dev, (c))
+#define isadma_release(c) isa_dma_release(isa_dev, (c))
+#define isadma_cascade(c) isa_dmacascade(isa_dev, (c))
+#define isadma_start(a, s, c, f) \
+ isa_dmastart(isa_dev, (c), (a), (s), 0, (f), BUS_DMA_WAITOK|BUS_DMA_BUS1)
+#define isadma_abort(c) isa_dmaabort(isa_dev, (c))
+#define isadma_finished(c) isa_dmafinished(isa_dev, (c))
+#define isadma_done(c) isa_dmadone(isa_dev, (c))
-/*
- * XXX these are needed until all drivers have been cleaned up
- */
+#endif /* __ISADMA_COMPAT */
+
+#define MAX_ISADMA 65536
+
+#define DMAMODE_WRITE 0
+#define DMAMODE_READ 1
+#define DMAMODE_LOOP 2
+
+struct proc;
+
+void isa_dmacascade __P((struct device *, int));
+
+int isa_dmamap_create __P((struct device *, int, bus_size_t, int));
+void isa_dmamap_destroy __P((struct device *, int));
+
+int isa_dmastart __P((struct device *, int, void *, bus_size_t,
+ struct proc *, int, int));
+void isa_dmaabort __P((struct device *, int));
+bus_size_t isa_dmacount __P((struct device *, int));
+int isa_dmafinished __P((struct device *, int));
+void isa_dmadone __P((struct device *, int));
+
+int isa_dmamem_alloc __P((struct device *, int, bus_size_t,
+ bus_addr_t *, int));
+void isa_dmamem_free __P((struct device *, int, bus_addr_t, bus_size_t));
+int isa_dmamem_map __P((struct device *, int, bus_addr_t, bus_size_t,
+ caddr_t *, int));
+void isa_dmamem_unmap __P((struct device *, int, caddr_t, size_t));
+int isa_dmamem_mmap __P((struct device *, int, bus_addr_t, bus_size_t,
+ int, int, int));
+
+int isa_drq_isfree __P((struct device *, int));
-#define isa_dma_acquire(c) isadma_acquire(c)
-#define isa_dma_release(c) isadma_release(c)
-#define isa_dmacascade(c) isadma_cascade((c))
-#define isa_dmastart(f, a, s, c) isadma_start((a), (s), (c), (f))
-#define isa_dmaabort(c) isadma_abort((c))
-#define isa_dmafinished(c) isadma_finished((c))
-#define isa_dmadone(f, a, s, c) isadma_done((c))
+void *isa_malloc __P((struct device *, int, size_t, int, int));
+void isa_free __P((void *, int));
+int isa_mappage __P((void *, int, int));
diff --git a/sys/dev/isa/isapnp.c b/sys/dev/isa/isapnp.c
index 790bffde6cf..368d5669472 100644
--- a/sys/dev/isa/isapnp.c
+++ b/sys/dev/isa/isapnp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: isapnp.c,v 1.16 1997/12/30 07:00:39 deraadt Exp $ */
+/* $OpenBSD: isapnp.c,v 1.17 1998/01/20 18:40:31 niklas Exp $ */
/* $NetBSD: isapnp.c,v 1.9.4.3 1997/10/29 00:40:43 thorpej Exp $ */
/*
@@ -838,6 +838,7 @@ isapnp_attach(parent, self, aux)
sc->sc_iot = ia->ia_iot;
sc->sc_memt = ia->ia_memt;
+ sc->sc_dmat = ia->ia_dmat;
sc->sc_ncards = 0;
if (isapnp_map(sc))
@@ -888,6 +889,7 @@ isapnp_attach(parent, self, aux)
lpa->ia_ic = ia->ia_ic;
lpa->ia_iot = ia->ia_iot;
lpa->ia_memt = ia->ia_memt;
+ lpa->ia_dmat = ia->ia_dmat;
lpa->ia_delaybah = ia->ia_delaybah;
isapnp_write_reg(sc, ISAPNP_ACTIVATE, 1);
diff --git a/sys/dev/isa/isavar.h b/sys/dev/isa/isavar.h
index 98e61769981..a6ef11c2547 100644
--- a/sys/dev/isa/isavar.h
+++ b/sys/dev/isa/isavar.h
@@ -1,6 +1,42 @@
-/* $OpenBSD: isavar.h,v 1.26 1997/12/25 13:18:07 downsj Exp $ */
-/* $NetBSD: isavar.h,v 1.24 1996/10/21 22:41:11 thorpej Exp $ */
-/* $NetBSD: isapnpvar.h,v 1.5.4.2 1997/10/29 00:40:49 thorpej Exp $ */
+/* $OpenBSD: isavar.h,v 1.27 1998/01/20 18:40:33 niklas Exp $ */
+/* $NetBSD: isavar.h,v 1.26 1997/06/06 23:43:57 thorpej Exp $ */
+
+/*-
+ * Copyright (c) 1997 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
+ * NASA Ames Research Center.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
/*
* Copyright (c) 1996 Christos Zoulas. All rights reserved.
@@ -77,6 +113,10 @@
#include <sys/queue.h>
#include <machine/bus.h>
+#ifndef NISADMA
+#include "isadma.h"
+#endif
+
/*
* Structures and definitions needed by the machine-dependent header.
*/
@@ -154,6 +194,9 @@ struct isapnp_softc {
int sc_read_port;
bus_space_tag_t sc_iot;
bus_space_tag_t sc_memt;
+#if NISADMA > 0
+ bus_dma_tag_t sc_dmat;
+#endif
bus_space_handle_t sc_addr_ioh;
bus_space_handle_t sc_wrdata_ioh;
bus_space_handle_t sc_read_ioh;
@@ -192,6 +235,9 @@ struct isabus_attach_args {
char *iba_busname; /* XXX should be common */
bus_space_tag_t iba_iot; /* isa i/o space tag */
bus_space_tag_t iba_memt; /* isa mem space tag */
+#if NISADMA > 0
+ bus_dma_tag_t iba_dmat; /* isa DMA tag */
+#endif
isa_chipset_tag_t iba_ic;
};
@@ -202,7 +248,9 @@ struct isa_attach_args {
struct device *ia_isa; /* isa device */
bus_space_tag_t ia_iot; /* isa i/o space tag */
bus_space_tag_t ia_memt; /* isa mem space tag */
-
+#if NISADMA > 0
+ bus_dma_tag_t ia_dmat; /* DMA tag */
+#endif
bus_space_handle_t ia_delaybah; /* i/o handle for `delay port' */
isa_chipset_tag_t ia_ic;
@@ -272,9 +320,34 @@ struct isa_softc {
bus_space_tag_t sc_iot; /* isa io space tag */
bus_space_tag_t sc_memt; /* isa mem space tag */
+#if NISADMA > 0
+ bus_dma_tag_t sc_dmat; /* isa DMA tag */
+#endif /* NISADMA > 0 */
isa_chipset_tag_t sc_ic;
+#if NISADMA > 0
+ /*
+ * Bitmap representing the DRQ channels available
+ * for ISA.
+ */
+ int sc_drqmap;
+#define sc_drq sc_drqmap /* XXX compatibility mode */
+
+ bus_space_handle_t sc_dma1h; /* i/o handle for DMA controller #1 */
+ bus_space_handle_t sc_dma2h; /* i/o handle for DMA controller #2 */
+ bus_space_handle_t sc_dmapgh; /* i/o handle for DMA page registers */
+
+ /*
+ * DMA maps used for the 8 DMA channels.
+ */
+ bus_dmamap_t sc_dmamaps[8];
+ vm_size_t sc_dmalength[8];
+
+ int sc_dmareads; /* state for isa_dmadone() */
+ int sc_dmafinished; /* DMA completion state */
+#endif /* NISADMA > 0 */
+
/*
* This i/o handle is used to map port 0x84, which is
* read to provide a 1.25us delay. This access handle
@@ -282,25 +355,16 @@ struct isa_softc {
* via isa_attach_args.
*/
bus_space_handle_t sc_delaybah;
-
- int8_t sc_drq; /* DRQ usage tracking */
};
-/*
- * Macros for sc_drq access.
- */
-#ifdef DIAGNOSTIC
-void isa_drq_alloc __P((void *, int));
-void isa_drq_free __P((void *, int));
-int isa_drq_isfree __P((void *, int));
-#else
-#define isa_drq_alloc(_sc, _drq) \
- (((struct isa_softc *)(_sc))->sc_drq |= (1 << (_drq)))
-#define isa_drq_free(_sc, _drq) \
- (((struct isa_softc *)(_sc))->sc_drq &= ~(1 << (_drq)))
-#define isa_drq_isfree(_sc, _drq) \
- !((((struct isa_softc *)(_sc))->sc_drq << (_drq)) & 1)
-#endif /* DIAGNOSTIC */
+#define ISA_DRQ_ISFREE(isadev, drq) \
+ ((((struct isa_softc *)(isadev))->sc_drqmap & (1 << (drq))) == 0)
+
+#define ISA_DRQ_ALLOC(isadev, drq) \
+ ((struct isa_softc *)(isadev))->sc_drqmap |= (1 << (drq))
+
+#define ISA_DRQ_FREE(isadev, drq) \
+ ((struct isa_softc *)(isadev))->sc_drqmap &= ~(1 << (drq))
#define cf_iobase cf_loc[0]
#define cf_iosize cf_loc[1]
@@ -339,6 +403,12 @@ void isa_establish __P((struct isadev *, struct device *));
#endif
/*
+ * Some ISA devices (e.g. on a VLB) can perform 32-bit DMA. This
+ * flag is passed to bus_dmamap_create() to indicate that fact.
+ */
+#define ISABUS_DMA_32BIT BUS_DMA_BUS1
+
+/*
* ISA PnP prototypes and support macros.
*/
static __inline void isapnp_write_reg __P((struct isapnp_softc *, int, u_char));
diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c
index b0fb4771696..83b98d0e78c 100644
--- a/sys/dev/pci/pci.c
+++ b/sys/dev/pci/pci.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: pci.c,v 1.10 1998/01/07 11:03:32 deraadt Exp $ */
-/* $NetBSD: pci.c,v 1.26 1996/12/05 01:25:30 cgd Exp $ */
+/* $OpenBSD: pci.c,v 1.11 1998/01/20 18:40:34 niklas Exp $ */
+/* $NetBSD: pci.c,v 1.31 1997/06/06 23:48:04 thorpej Exp $ */
/*
* Copyright (c) 1995, 1996 Christopher G. Demetriou. All rights reserved.
@@ -153,6 +153,7 @@ pciattach(parent, self, aux)
pa.pa_iot = iot;
pa.pa_memt = memt;
+ pa.pa_dmat = pba->pba_dmat;
pa.pa_pc = pc;
pa.pa_device = device;
pa.pa_function = function;
diff --git a/sys/dev/pci/pcivar.h b/sys/dev/pci/pcivar.h
index 96dadfdfaf3..5a8fb8f2f62 100644
--- a/sys/dev/pci/pcivar.h
+++ b/sys/dev/pci/pcivar.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: pcivar.h,v 1.12 1997/10/11 11:14:16 pefo Exp $ */
-/* $NetBSD: pcivar.h,v 1.18 1996/12/01 21:02:18 leo Exp $ */
+/* $OpenBSD: pcivar.h,v 1.13 1998/01/20 18:40:36 niklas Exp $ */
+/* $NetBSD: pcivar.h,v 1.23 1997/06/06 23:48:05 thorpej Exp $ */
/*
* Copyright (c) 1996 Christopher G. Demetriou. All rights reserved.
@@ -80,6 +80,7 @@ struct pcibus_attach_args {
char *pba_busname; /* XXX should be common */
bus_space_tag_t pba_iot; /* pci i/o space tag */
bus_space_tag_t pba_memt; /* pci mem space tag */
+ bus_dma_tag_t pba_dmat; /* DMA tag */
pci_chipset_tag_t pba_pc;
int pba_bus; /* PCI bus number */
@@ -98,6 +99,7 @@ struct pcibus_attach_args {
struct pci_attach_args {
bus_space_tag_t pa_iot; /* pci i/o space tag */
bus_space_tag_t pa_memt; /* pci mem space tag */
+ bus_dma_tag_t pa_dmat; /* DMA tag */
pci_chipset_tag_t pa_pc;
u_int pa_device;
diff --git a/sys/dev/pci/ppb.c b/sys/dev/pci/ppb.c
index ce1aef12184..7f36d890ee2 100644
--- a/sys/dev/pci/ppb.c
+++ b/sys/dev/pci/ppb.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: ppb.c,v 1.6 1998/01/05 13:35:26 deraadt Exp $ */
-/* $NetBSD: ppb.c,v 1.12 1996/10/21 22:57:00 thorpej Exp $ */
+/* $OpenBSD: ppb.c,v 1.7 1998/01/20 18:40:36 niklas Exp $ */
+/* $NetBSD: ppb.c,v 1.16 1997/06/06 23:48:05 thorpej Exp $ */
/*
* Copyright (c) 1996 Christopher G. Demetriou. All rights reserved.
@@ -120,6 +120,7 @@ ppbattach(parent, self, aux)
pba.pba_busname = "pci";
pba.pba_iot = pa->pa_iot;
pba.pba_memt = pa->pa_memt;
+ pba.pba_dmat = pa->pa_dmat;
pba.pba_pc = pc;
pba.pba_bus = PPB_BUSINFO_SECONDARY(busdata);
pba.pba_intrswiz = pa->pa_intrswiz;