diff options
author | Niklas Hallqvist <niklas@cvs.openbsd.org> | 1998-01-20 18:40:37 +0000 |
---|---|---|
committer | Niklas Hallqvist <niklas@cvs.openbsd.org> | 1998-01-20 18:40:37 +0000 |
commit | e4232757b30346a182214fb65da8a76f2edb7b24 (patch) | |
tree | 5c1b89b92ef8c67dfa2d0f3a078804042a1555ee /sys/dev | |
parent | 0a8f2cc87f99deec610ef91696850a249bd8fb81 (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.h | 6 | ||||
-rw-r--r-- | sys/dev/isa/isa.c | 105 | ||||
-rw-r--r-- | sys/dev/isa/isadma.c | 795 | ||||
-rw-r--r-- | sys/dev/isa/isadmareg.h | 26 | ||||
-rw-r--r-- | sys/dev/isa/isadmavar.h | 115 | ||||
-rw-r--r-- | sys/dev/isa/isapnp.c | 4 | ||||
-rw-r--r-- | sys/dev/isa/isavar.h | 112 | ||||
-rw-r--r-- | sys/dev/pci/pci.c | 5 | ||||
-rw-r--r-- | sys/dev/pci/pcivar.h | 6 | ||||
-rw-r--r-- | sys/dev/pci/ppb.c | 5 |
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; |