summaryrefslogtreecommitdiffstats
path: root/sys/alpha/isa
diff options
context:
space:
mode:
authorgallatin <gallatin@FreeBSD.org>2000-06-19 18:41:27 +0000
committergallatin <gallatin@FreeBSD.org>2000-06-19 18:41:27 +0000
commitccfeb47d98df65abb9bc01f29fb2da0a88dd4d83 (patch)
treed825e4455c867bd8bc4781e256435b6ee9942f38 /sys/alpha/isa
parentcf9d5ec1797dcd397de2af6e7b1fbfd360baf401 (diff)
downloadFreeBSD-src-ccfeb47d98df65abb9bc01f29fb2da0a88dd4d83.zip
FreeBSD-src-ccfeb47d98df65abb9bc01f29fb2da0a88dd4d83.tar.gz
Support bounce buffers for ISA DMA on the alpha. This is required for the
irongate chipset (used in the UP1000) which does not support scatter/gather DMA. We'll still use scatter gather if the core logic chipset supports it. Reviewed by: dfr
Diffstat (limited to 'sys/alpha/isa')
-rw-r--r--sys/alpha/isa/isa_dma.c31
1 files changed, 28 insertions, 3 deletions
diff --git a/sys/alpha/isa/isa_dma.c b/sys/alpha/isa/isa_dma.c
index 8b5e64b..5864c7a 100644
--- a/sys/alpha/isa/isa_dma.c
+++ b/sys/alpha/isa/isa_dma.c
@@ -83,6 +83,7 @@ static bus_dmamap_t dma_map[8];
static u_int8_t dma_busy = 0; /* Used in isa_dmastart() */
static u_int8_t dma_inuse = 0; /* User for acquire/release */
static u_int8_t dma_auto_mode = 0;
+static u_int8_t dma_bounced = 0;
#define VALID_DMA_MASK (7)
@@ -105,6 +106,7 @@ isa_dmainit(chan, bouncebufsize)
* Reset the DMA hardware.
*/
outb(DMA1_RESET, 0);
+ outb((IO_DMA1 + 1*14), 0);
outb(DMA2_RESET, 0);
isa_dmacascade(4);
@@ -122,7 +124,7 @@ isa_dmainit(chan, bouncebufsize)
if (bus_dma_tag_create(/*parent*/NULL,
/*alignment*/2,
/*boundary*/boundary,
- /*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
+ /*lowaddr*/BUS_SPACE_MAXADDR_24BIT,
/*highaddr*/BUS_SPACE_MAXADDR,
/*filter*/NULL, /*filterarg*/NULL,
/*maxsize*/bouncebufsize,
@@ -219,13 +221,15 @@ isa_dmacascade(chan)
*/
struct isa_dmastart_arg {
- int chan;
- int flags;
+ caddr_t addr;
+ int chan;
+ int flags;
};
static void isa_dmastart_cb(void *arg, bus_dma_segment_t *segs, int nseg,
int error)
{
+ caddr_t addr = ((struct isa_dmastart_arg *) arg)->addr;
int chan = ((struct isa_dmastart_arg *) arg)->chan;
int flags = ((struct isa_dmastart_arg *) arg)->flags;
bus_addr_t phys = segs->ds_addr;
@@ -235,6 +239,17 @@ static void isa_dmastart_cb(void *arg, bus_dma_segment_t *segs, int nseg,
if (nseg != 1)
panic("isa_dmastart: transfer mapping not contiguous");
+ if ((chipset.sgmap == NULL) &&
+ (pmap_extract(pmap_kernel(), (vm_offset_t)addr)
+ > BUS_SPACE_MAXADDR_24BIT)) {
+ /* we bounced */
+ dma_bounced |= (1 << chan);
+ /* copy bounce buffer on write */
+ if (!(flags & ISADMA_READ))
+ bus_dmamap_sync(dma_tag[chan], dma_map[chan],
+ BUS_DMASYNC_PREWRITE);
+ }
+
if ((chan & 4) == 0) {
/*
* Program one of DMA channels 0..3. These are
@@ -348,6 +363,7 @@ isa_dmastart(int flags, caddr_t addr, u_int nbytes, int chan)
*/
outb(chan & 4 ? DMA2_SMSK : DMA1_SMSK, (chan & 3) | 4);
+ args.addr = addr;
args.chan = chan;
args.flags = flags;
bus_dmamap_load(dma_tag[chan], dma_map[chan], addr, nbytes,
@@ -369,6 +385,15 @@ isa_dmadone(int flags, caddr_t addr, int nbytes, int chan)
(dma_auto_mode & (1 << chan)) == 0 )
printf("isa_dmadone: channel %d not busy\n", chan);
+ if (dma_bounced & (1 << chan)) {
+ /* copy bounce buffer on read */
+ if (flags & ISADMA_READ) {
+ bus_dmamap_sync(dma_tag[chan], dma_map[chan],
+ BUS_DMASYNC_POSTREAD);
+ }
+ dma_bounced &= ~(1 << chan);
+ }
+
if ((dma_auto_mode & (1 << chan)) == 0) {
outb(chan & 4 ? DMA2_SMSK : DMA1_SMSK, (chan & 3) | 4);
bus_dmamap_unload(dma_tag[chan], dma_map[chan]);
OpenPOWER on IntegriCloud