diff options
author | msmith <msmith@FreeBSD.org> | 1997-08-28 03:36:40 +0000 |
---|---|---|
committer | msmith <msmith@FreeBSD.org> | 1997-08-28 03:36:40 +0000 |
commit | 4561d606a5e886201d11344c7d54e415b043b3cd (patch) | |
tree | b9924875864f2241940625b55979653b809ff5ec /sys | |
parent | 66c70016d708f2896b9c124444c612dc0264861e (diff) | |
download | FreeBSD-src-4561d606a5e886201d11344c7d54e415b043b3cd.zip FreeBSD-src-4561d606a5e886201d11344c7d54e415b043b3cd.tar.gz |
Here is a patch to alleviate the current problem with the dma interface
and the sound driver which uses auto dma.
The dma interface functionality remains however it now checks
to see if a dma is operating in auto dma mode and if so it bypasses
the busy flag check . I have modified the sound driver 3.5 to
adjust for this new behavior and tested it under FreeBSD 3.0 -current
This patch also includes the new function isa_dmastop.
Submitted by: Amancio Hasty <hasty@rah.star-gate.com>
Diffstat (limited to 'sys')
-rw-r--r-- | sys/amd64/isa/isa.c | 56 | ||||
-rw-r--r-- | sys/i386/isa/isa.c | 56 |
2 files changed, 84 insertions, 28 deletions
diff --git a/sys/amd64/isa/isa.c b/sys/amd64/isa/isa.c index 0b6fe36..abdcfa3 100644 --- a/sys/amd64/isa/isa.c +++ b/sys/amd64/isa/isa.c @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * from: @(#)isa.c 7.2 (Berkeley) 5/13/91 - * $Id: isa.c,v 1.101 1997/08/21 05:08:07 fsmp Exp $ + * $Id: isa.c,v 1.102 1997/08/25 22:52:59 bde Exp $ */ /* @@ -573,6 +573,7 @@ static u_int dma_bouncebufsize[8]; static u_int8_t dma_bounced = 0; 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; #define VALID_DMA_MASK (7) @@ -634,6 +635,7 @@ isa_dma_acquire(chan) return (EBUSY); } dma_inuse |= (1 << chan); + dma_auto_mode &= ~(1 << chan); return (0); } @@ -665,6 +667,7 @@ isa_dma_release(chan) } dma_inuse &= ~(1 << chan); + dma_auto_mode &= ~(1 << chan); } /* @@ -739,6 +742,12 @@ void isa_dmastart(int flags, caddr_t addr, u_int nbytes, int chan) /* translate to physical */ phys = pmap_extract(pmap_kernel(), (vm_offset_t)addr); + if (flags & B_RAW) { + dma_auto_mode |= (1 << chan); + } else { + dma_auto_mode &= ~(1 << chan); + } + if ((chan & 4) == 0) { /* * Program one of DMA channels 0..3. These are @@ -819,15 +828,10 @@ void isa_dmadone(int flags, caddr_t addr, int nbytes, int chan) printf("isa_dmadone: channel %d not acquired\n", chan); #endif -#if 0 - /* - * XXX This should be checked, but drivers like ad1848 only call - * isa_dmastart() once because they use Auto DMA mode. If we - * leave this in, drivers that do this will print this continuously. - */ - if ((dma_busy & (1 << chan)) == 0) + if (((dma_busy & (1 << chan)) == 0) && + (dma_auto_mode & (1 << chan)) == 0 ) printf("isa_dmadone: channel %d not busy\n", chan); -#endif + if (dma_bounced & (1 << chan)) { /* copy bounce buffer on read */ @@ -916,12 +920,13 @@ isa_dmastatus(int chan) printf("isa_dmastatus: channel %d not active\n", chan); return(-1); } + /* channel busy? */ - /* still busy? */ - if ((dma_busy & (1 << chan)) == 0) { - return(0); - } - + if (((dma_busy & (1 << chan)) == 0) && + (dma_auto_mode & (1 << chan)) == 0 ) { + printf("chan %d not busy\n", chan); + return -2 ; + } if (chan < 4) { /* low DMA controller */ ffport = DMA1_FFC; waport = DMA1_CHN(chan) + 1; @@ -956,6 +961,29 @@ isa_dmastatus(int chan) } /* + * Stop a DMA transfer currently in progress. + */ +int +isa_dmastop(int chan) +{ + if ((dma_inuse & (1 << chan)) == 0) + printf("isa_dmastop: channel %d not acquired\n", chan); + + if (((dma_busy & (1 << chan)) == 0) && + ((dma_auto_mode & (1 << chan)) == 0)) { + printf("chan %d not busy\n", chan); + return -2 ; + } + + if ((chan & 4) == 0) { + outb(DMA1_SMSK, (chan & 3) | 4 /* disable mask */); + } else { + outb(DMA2_SMSK, (chan & 3) | 4 /* disable mask */); + } + return(isa_dmastatus(chan)); +} + +/* * Find the highest priority enabled display device. Since we can't * distinguish display devices from ttys, depend on display devices * being sensitive and before sensitive non-display devices (if any) diff --git a/sys/i386/isa/isa.c b/sys/i386/isa/isa.c index 0b6fe36..abdcfa3 100644 --- a/sys/i386/isa/isa.c +++ b/sys/i386/isa/isa.c @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * from: @(#)isa.c 7.2 (Berkeley) 5/13/91 - * $Id: isa.c,v 1.101 1997/08/21 05:08:07 fsmp Exp $ + * $Id: isa.c,v 1.102 1997/08/25 22:52:59 bde Exp $ */ /* @@ -573,6 +573,7 @@ static u_int dma_bouncebufsize[8]; static u_int8_t dma_bounced = 0; 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; #define VALID_DMA_MASK (7) @@ -634,6 +635,7 @@ isa_dma_acquire(chan) return (EBUSY); } dma_inuse |= (1 << chan); + dma_auto_mode &= ~(1 << chan); return (0); } @@ -665,6 +667,7 @@ isa_dma_release(chan) } dma_inuse &= ~(1 << chan); + dma_auto_mode &= ~(1 << chan); } /* @@ -739,6 +742,12 @@ void isa_dmastart(int flags, caddr_t addr, u_int nbytes, int chan) /* translate to physical */ phys = pmap_extract(pmap_kernel(), (vm_offset_t)addr); + if (flags & B_RAW) { + dma_auto_mode |= (1 << chan); + } else { + dma_auto_mode &= ~(1 << chan); + } + if ((chan & 4) == 0) { /* * Program one of DMA channels 0..3. These are @@ -819,15 +828,10 @@ void isa_dmadone(int flags, caddr_t addr, int nbytes, int chan) printf("isa_dmadone: channel %d not acquired\n", chan); #endif -#if 0 - /* - * XXX This should be checked, but drivers like ad1848 only call - * isa_dmastart() once because they use Auto DMA mode. If we - * leave this in, drivers that do this will print this continuously. - */ - if ((dma_busy & (1 << chan)) == 0) + if (((dma_busy & (1 << chan)) == 0) && + (dma_auto_mode & (1 << chan)) == 0 ) printf("isa_dmadone: channel %d not busy\n", chan); -#endif + if (dma_bounced & (1 << chan)) { /* copy bounce buffer on read */ @@ -916,12 +920,13 @@ isa_dmastatus(int chan) printf("isa_dmastatus: channel %d not active\n", chan); return(-1); } + /* channel busy? */ - /* still busy? */ - if ((dma_busy & (1 << chan)) == 0) { - return(0); - } - + if (((dma_busy & (1 << chan)) == 0) && + (dma_auto_mode & (1 << chan)) == 0 ) { + printf("chan %d not busy\n", chan); + return -2 ; + } if (chan < 4) { /* low DMA controller */ ffport = DMA1_FFC; waport = DMA1_CHN(chan) + 1; @@ -956,6 +961,29 @@ isa_dmastatus(int chan) } /* + * Stop a DMA transfer currently in progress. + */ +int +isa_dmastop(int chan) +{ + if ((dma_inuse & (1 << chan)) == 0) + printf("isa_dmastop: channel %d not acquired\n", chan); + + if (((dma_busy & (1 << chan)) == 0) && + ((dma_auto_mode & (1 << chan)) == 0)) { + printf("chan %d not busy\n", chan); + return -2 ; + } + + if ((chan & 4) == 0) { + outb(DMA1_SMSK, (chan & 3) | 4 /* disable mask */); + } else { + outb(DMA2_SMSK, (chan & 3) | 4 /* disable mask */); + } + return(isa_dmastatus(chan)); +} + +/* * Find the highest priority enabled display device. Since we can't * distinguish display devices from ttys, depend on display devices * being sensitive and before sensitive non-display devices (if any) |