home *** CD-ROM | disk | FTP | other *** search
- /*
- * sound/dmabuf.c
- *
- * The DMA buffer manager for digitized voice applications
- *
- * Copyright by Hannu Savolainen 1993
- *
- * 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
- *
- */
-
- #include "sound_config.h"
-
- #ifdef CONFIGURE_SOUNDCARD
-
- #include "sound_calls.h"
-
- #if !defined(EXCLUDE_AUDIO) || !defined(EXCLUDE_GUS)
-
- #define MAX_SUB_BUFFERS (32*MAX_REALTIME_FACTOR)
-
- /*
- * The DSP channel can be used either for input or output. Variable
- * 'dma_mode' will be set when the program calls read or write first time
- * after open. Current version doesn't support mode changes without closing
- * and reopening the device. Support for this feature may be implemented in a
- * future version of this driver.
- */
-
- #define DMODE_NONE 0
- #define DMODE_OUTPUT 1
- #define DMODE_INPUT 2
-
- DEFINE_WAIT_QUEUES (dev_sleeper[MAX_DSP_DEV], dev_sleep_flag[MAX_DSP_DEV]);
-
- static int dma_mode[MAX_DSP_DEV] =
- {0}; /* DMODE_INPUT, DMODE_OUTPUT or DMODE_NONE */
-
- static volatile int dmabuf_interrupted[MAX_DSP_DEV] =
- {0};
-
- /*
- * Pointers to raw buffers
- */
-
- char *snd_raw_buf[MAX_DSP_DEV][DSP_BUFFCOUNT] =
- {
- {NULL}};
- unsigned long snd_raw_buf_phys[MAX_DSP_DEV][DSP_BUFFCOUNT];
- int snd_raw_count[MAX_DSP_DEV];
-
- /*
- * Device state tables
- */
-
- static int dev_busy[MAX_DSP_DEV];
- static int dev_needs_restart[MAX_DSP_DEV];
- static int dev_modes[MAX_DSP_DEV];
- static int dev_active[MAX_DSP_DEV];
- static int dev_started[MAX_DSP_DEV];
- static int dev_qlen[MAX_DSP_DEV];
- static int dev_qhead[MAX_DSP_DEV];
- static int dev_qtail[MAX_DSP_DEV];
- static int dev_underrun[MAX_DSP_DEV];
- static int bufferalloc_done[MAX_DSP_DEV] =
- {0};
-
- /*
- * Logical buffers for each devices
- */
-
- static int dev_nbufs[MAX_DSP_DEV]; /* # of logical buffers ( >=
- * sound_buffcounts[dev] */
- static int dev_counts[MAX_DSP_DEV][MAX_SUB_BUFFERS];
- static int dev_subdivision[MAX_DSP_DEV];
- static unsigned long dev_buf_phys[MAX_DSP_DEV][MAX_SUB_BUFFERS];
- static char *dev_buf[MAX_DSP_DEV][MAX_SUB_BUFFERS] =
- {{NULL}};
- static int dev_buffsize[MAX_DSP_DEV];
-
- static void
- reorganize_buffers (int dev)
- {
- /*
- * This routine breaks the physical device buffers to logical ones.
- */
-
- unsigned i, p, n;
- unsigned sr, nc, sz, bsz;
-
- sr = dsp_devs[dev]->ioctl (dev, SOUND_PCM_READ_RATE, 0, 1);
- nc = dsp_devs[dev]->ioctl (dev, SOUND_PCM_READ_CHANNELS, 0, 1);
- sz = dsp_devs[dev]->ioctl (dev, SOUND_PCM_READ_BITS, 0, 1);
-
- if (sr < 1 || nc < 1 || sz < 1)
- {
- printk ("SOUND: Invalid PCM parameters[%d] sr=%d, nc=%d, sz=%d\n", dev, sr, nc, sz);
- sr = DSP_DEFAULT_SPEED;
- nc = 1;
- sz = 8;
- }
-
- sz /= 8; /* Convert # of bits -> # of bytes */
-
- sz = sr * nc * sz;
-
- /*
- * Compute a buffer size not exeeding 1 second.
- */
-
- bsz = sound_buffsizes[dev];
-
- while (bsz > sz)
- bsz >>= 1; /* Divide by 2 */
-
- if (sound_buffcounts[dev] == 1 && bsz == sound_buffsizes[dev])
- bsz >>= 1; /* Need at least 2 buffers */
-
- if (dev_subdivision[dev] == 0)
- dev_subdivision[dev] = 1; /* Default value */
-
- bsz /= dev_subdivision[dev]; /* Use smaller buffers */
-
- if (bsz == 0) bsz = 4096; /* Just a sanity check */
-
- while ((sound_buffsizes[dev]*sound_buffcounts[dev])/bsz > MAX_SUB_BUFFERS)
- bsz <<= 1; /* Too much buffers */
-
- dev_buffsize[dev] = bsz;
- n = 0;
-
- /*
- * Now computing addresses for the logical buffers
- */
-
- for (i = 0; i < snd_raw_count[dev]; i++)
- {
- p = 0;
-
- while ((p + bsz) <= sound_buffsizes[dev])
- {
- dev_buf[dev][n] = snd_raw_buf[dev][i] + p;
- dev_buf_phys[dev][n] = snd_raw_buf_phys[dev][i] + p;
- p += bsz;
- n++;
- }
- }
-
- dev_nbufs[dev] = n;
-
- for (i = 0; i < dev_nbufs[dev]; i++)
- {
- dev_counts[dev][i] = 0;
- }
-
- bufferalloc_done[dev] = 1;
- }
-
- static void
- dma_init_buffers(int dev)
- {
- RESET_WAIT_QUEUE (dev_sleeper[dev], dev_sleep_flag[dev]);
- dev_underrun[dev] = 0;
-
- dev_busy[dev] = 1;
-
- bufferalloc_done[dev] = 0;
-
- dev_active[dev] = dev_qlen[dev] = dev_qtail[dev] = dev_qhead[dev] = 0;
- dev_needs_restart[dev] = dev_started[dev] = 0;
- dma_mode[dev] = DMODE_NONE;
- }
-
- int
- DMAbuf_open (int dev, int mode)
- {
- int retval;
-
- if (dev >= num_dspdevs)
- {
- printk ("PCM device %d not installed.\n", dev);
- return RET_ERROR (ENXIO);
- }
-
- if (dev_busy[dev])
- return RET_ERROR (EBUSY);
-
- if (!dsp_devs[dev])
- {
- printk ("DSP device %d not initialized\n", dev);
- return RET_ERROR (ENXIO);
- }
-
- #ifdef USE_RUNTIME_DMAMEM
- sound_dma_malloc(dev);
- #endif
-
- if (snd_raw_buf[dev][0] == NULL)
- return RET_ERROR (ENOSPC); /* Memory allocation failed during boot */
-
- if ((retval = dsp_devs[dev]->open (dev, mode)) < 0)
- return retval;
-
- dev_modes[dev] = mode;
- dev_subdivision[dev] = 0;
-
- dma_init_buffers(dev);
- dsp_devs[dev]->ioctl (dev, SOUND_PCM_WRITE_BITS, 8, 1);
- dsp_devs[dev]->ioctl (dev, SOUND_PCM_WRITE_CHANNELS, 1, 1);
- dsp_devs[dev]->ioctl (dev, SOUND_PCM_WRITE_RATE, DSP_DEFAULT_SPEED, 1);
-
- return 0;
- }
-
- static void
- dma_reset (int dev)
- {
- int retval;
- unsigned long flags;
-
- DISABLE_INTR(flags);
- dsp_devs[dev]->reset (dev);
- dsp_devs[dev]->close (dev);
-
- if ((retval = dsp_devs[dev]->open (dev, dev_modes[dev])) < 0)
- printk("Sound: Reset failed - Can't reopen device\n");
- RESTORE_INTR(flags);
-
- dma_init_buffers(dev);
- reorganize_buffers(dev);
- }
-
- static int
- dma_sync (int dev)
- {
- unsigned long flags;
- unsigned long time;
- int timed_out;
-
- if (dma_mode[dev] == DMODE_OUTPUT)
- {
- DISABLE_INTR (flags);
-
- timed_out = 0;
- time = GET_TIME ();
-
- while ((!(PROCESS_ABORTING (dev_sleeper[dev], dev_sleep_flag[dev]) ||
- dmabuf_interrupted[dev]) && !timed_out)
- && dev_qlen[dev])
- {
- DO_SLEEP (dev_sleeper[dev], dev_sleep_flag[dev], 10 * HZ);
- if ((GET_TIME () - time) > (10 * HZ))
- timed_out = 1;
- }
- RESTORE_INTR (flags);
-
- /*
- * Some devices such as GUS have huge amount of on board RAM for the
- * audio data. We have to wait util the device has finished playing.
- */
-
- DISABLE_INTR (flags);
- if (dsp_devs[dev]->has_output_drained) /* Device has hidden buffers */
- {
- while (!(PROCESS_ABORTING (dev_sleeper[dev], dev_sleep_flag[dev]) ||
- dmabuf_interrupted[dev])
- && !dsp_devs[dev]->has_output_drained (dev))
- {
- DO_SLEEP (dev_sleeper[dev], dev_sleep_flag[dev], HZ / 4);
- }
- }
- RESTORE_INTR (flags);
- }
- return dev_qlen[dev];
- }
-
- int
- DMAbuf_release (int dev, int mode)
- {
-
- if (!(PROCESS_ABORTING (dev_sleeper[dev], dev_sleep_flag[dev]) ||
- dmabuf_interrupted[dev])
- && (dma_mode[dev] == DMODE_OUTPUT))
- {
- dma_sync (dev);
- }
-
- #ifdef USE_RUNTIME_DMAMEM
- sound_dma_free(dev);
- #endif
-
- dsp_devs[dev]->reset (dev);
-
- dsp_devs[dev]->close (dev);
-
- dma_mode[dev] = DMODE_NONE;
- dev_busy[dev] = 0;
-
- return 0;
- }
-
- int
- DMAbuf_getrdbuffer (int dev, char **buf, int *len)
- {
- unsigned long flags;
- int err = EIO;
-
- DISABLE_INTR (flags);
- if (!dev_qlen[dev])
- {
- if (dev_needs_restart[dev])
- {
- dma_reset(dev);
- dev_needs_restart[dev] = 0;
- }
-
- if (dma_mode[dev] == DMODE_OUTPUT) /* Was output -> direction change */
- {
- dma_sync(dev);
- dma_reset(dev);
- dma_mode[dev] = DMODE_NONE;
- }
-
- if (!bufferalloc_done[dev])
- reorganize_buffers (dev);
-
- if (!dma_mode[dev])
- {
- int err;
-
- if ((err = dsp_devs[dev]->prepare_for_input (dev,
- dev_buffsize[dev], dev_nbufs[dev])) < 0)
- {
- RESTORE_INTR (flags);
- return err;
- }
- dma_mode[dev] = DMODE_INPUT;
- }
-
- if (!dev_active[dev])
- {
- dsp_devs[dev]->start_input (dev, dev_buf_phys[dev][dev_qtail[dev]],
- dev_buffsize[dev], 0,
- !sound_dma_automode[dev] ||
- !dev_started[dev]);
- dev_active[dev] = 1;
- dev_started[dev] = 1;
- }
-
- /* Wait for the next block */
- DO_SLEEP (dev_sleeper[dev], dev_sleep_flag[dev], 2 * HZ);
- if (TIMED_OUT (dev_sleeper[dev], dev_sleep_flag[dev]))
- {
- printk ("Sound: DMA timed out - IRQ/DRQ config error?\n");
- err = EIO;
- SET_ABORT_FLAG (dev_sleeper[dev], dev_sleep_flag[dev]);
- }
- else
- err = EINTR;
- }
- RESTORE_INTR (flags);
-
- if (!dev_qlen[dev])
- return RET_ERROR (err);
-
- *buf = &dev_buf[dev][dev_qhead[dev]][dev_counts[dev][dev_qhead[dev]]];
- *len = dev_buffsize[dev] - dev_counts[dev][dev_qhead[dev]];
-
- return dev_qhead[dev];
- }
-
- int
- DMAbuf_rmchars (int dev, int buff_no, int c)
- {
- int p = dev_counts[dev][dev_qhead[dev]] + c;
-
- if (p >= dev_buffsize[dev])
- { /* This buffer is now empty */
- dev_counts[dev][dev_qhead[dev]] = 0;
- dev_qlen[dev]--;
- dev_qhead[dev] = (dev_qhead[dev] + 1) % dev_nbufs[dev];
- }
- else
- dev_counts[dev][dev_qhead[dev]] = p;
-
- return 0;
- }
-
- int
- DMAbuf_read (int dev, snd_rw_buf * user_buf, int count)
- {
- char *dmabuf;
- int buff_no, c, err;
-
- /*
- * This routine returns at most 'count' bytes from the dsp input buffers.
- * Returns negative value if there is an error.
- */
-
- if ((buff_no = DMAbuf_getrdbuffer (dev, &dmabuf, &c)) < 0)
- return buff_no;
-
- if (c > count)
- c = count;
-
- COPY_TO_USER (user_buf, 0, dmabuf, c);
-
- if ((err = DMAbuf_rmchars (dev, buff_no, c)) < 0)
- return err;
- return c;
-
- }
-
- int
- DMAbuf_ioctl (int dev, unsigned int cmd, unsigned int arg, int local)
- {
- switch (cmd)
- {
- case SNDCTL_DSP_RESET:
- dma_reset (dev);
- return 0;
- break;
-
- case SNDCTL_DSP_SYNC:
- dma_sync (dev);
- dma_reset (dev);
- return 0;
- break;
-
- case SNDCTL_DSP_GETBLKSIZE:
- if (!bufferalloc_done[dev])
- reorganize_buffers (dev);
-
- return IOCTL_OUT (arg, dev_buffsize[dev]);
- break;
-
- case SNDCTL_DSP_SUBDIVIDE:
- {
- int fact = IOCTL_IN(arg);
-
- if (fact == 0)
- {
- fact = dev_subdivision[dev];
- if (fact == 0) fact = 1;
- return IOCTL_OUT(arg, fact);
- }
-
- if (dev_subdivision[dev] != 0) /* Too late to change */
- return RET_ERROR(EINVAL);
-
- if (fact > MAX_REALTIME_FACTOR) return RET_ERROR(EINVAL);
-
- if (fact != 1 && fact != 2 && fact != 4 && fact != 8 && fact !=16)
- return RET_ERROR(EINVAL);
-
- dev_subdivision[dev] = fact;
- return IOCTL_OUT(arg, fact);
- }
- break;
-
- default:
- return dsp_devs[dev]->ioctl (dev, cmd, arg, local);
- }
-
- return RET_ERROR (EIO);
- }
-
- int
- DMAbuf_getwrbuffer (int dev, char **buf, int *size)
- {
- unsigned long flags;
- int err = EIO;
-
- if (dma_mode[dev] == DMODE_INPUT) /* Was input -> Direction change */
- {
- dma_reset(dev);
- dma_mode[dev] = DMODE_NONE;
- }
- else
- if (dev_needs_restart[dev]) /* Restart buffering */
- {
- dma_sync(dev);
- dma_reset(dev);
- }
-
- dev_needs_restart[dev] = 0;
-
- if (!bufferalloc_done[dev])
- reorganize_buffers (dev);
-
- if (!dma_mode[dev])
- {
- int err;
-
- dma_mode[dev] = DMODE_OUTPUT;
- if ((err = dsp_devs[dev]->prepare_for_output (dev,
- dev_buffsize[dev], dev_nbufs[dev])) < 0)
- return err;
- }
-
-
- DISABLE_INTR (flags);
-
- RESET_WAIT_QUEUE (dev_sleeper[dev], dev_sleep_flag[dev]);
-
- if (dev_qlen[dev] == dev_nbufs[dev])
- {
- if (!dev_active[dev])
- {
- printk ("Soundcard warning: DMA not activated %d/%d\n",
- dev_qlen[dev], dev_nbufs[dev]);
- return RET_ERROR (EIO);
- }
-
- /* Wait for free space */
- DO_SLEEP (dev_sleeper[dev], dev_sleep_flag[dev], 2 * HZ);
- if (TIMED_OUT (dev_sleeper[dev], dev_sleep_flag[dev]))
- {
- printk ("Sound: DMA timed out - IRQ/DRQ config error?\n");
- err = EIO;
- SET_ABORT_FLAG (dev_sleeper[dev], dev_sleep_flag[dev]);
- }
- else if (PROCESS_ABORTING (dev_sleeper[dev], dev_sleep_flag[dev]))
- err = EINTR;
- }
- RESTORE_INTR (flags);
-
- if (dev_qlen[dev] == dev_nbufs[dev])
- return RET_ERROR (err); /* We have got signal (?) */
-
- *buf = dev_buf[dev][dev_qtail[dev]];
- *size = dev_buffsize[dev];
- dev_counts[dev][dev_qtail[dev]] = 0;
-
- return dev_qtail[dev];
- }
-
- int
- DMAbuf_start_output (int dev, int buff_no, int l)
- {
- if (buff_no != dev_qtail[dev])
- printk ("Soundcard warning: DMA buffers out of sync %d != %d\n", buff_no, dev_qtail[dev]);
-
- dev_qlen[dev]++;
-
- dev_counts[dev][dev_qtail[dev]] = l;
-
- dev_needs_restart[dev] = (l != dev_buffsize[dev]);
-
- dev_qtail[dev] = (dev_qtail[dev] + 1) % dev_nbufs[dev];
-
- if (!dev_active[dev])
- {
- dev_active[dev] = 1;
- dsp_devs[dev]->output_block (dev, dev_buf_phys[dev][dev_qhead[dev]],
- dev_counts[dev][dev_qhead[dev]], 0,
- !sound_dma_automode[dev] || !dev_started[dev]);
- dev_started[dev] = 1;
- }
-
- return 0;
- }
-
- int
- DMAbuf_start_dma (int dev, unsigned long physaddr, int count, int dma_mode)
- {
- int chan = sound_dsp_dmachan[dev];
- unsigned long flags;
-
- /*
- * This function is not as portable as it should be.
- */
-
- /*
- * The count must be one less than the actual size. This is handled by
- * set_dma_addr()
- */
-
- if (sound_dma_automode[dev])
- { /* Auto restart mode. Transfer the whole
- * buffer */
- #ifdef linux
- DISABLE_INTR (flags);
- disable_dma (chan);
- clear_dma_ff (chan);
- set_dma_mode (chan, dma_mode | DMA_AUTOINIT);
- set_dma_addr (chan, snd_raw_buf_phys[dev][0]);
- set_dma_count (chan, sound_buffsizes[dev]);
- enable_dma (chan);
- RESTORE_INTR (flags);
- #else
-
- #ifdef __386BSD__
- printk ("sound: Invalid DMA mode for device %d\n", dev);
-
- isa_dmastart ((dma_mode == DMA_MODE_READ) ? B_READ : B_WRITE,
- snd_raw_buf_phys[dev][0],
- sound_buffsizes[dev],
- chan);
- #else
- #if defined(ISC) || defined(SCO)
- #ifndef DMAMODE_AUTO
- printk ("sound: Invalid DMA mode for device %d\n", dev);
- #endif
- dma_param (chan, ((dma_mode == DMA_MODE_READ) ? DMA_Rdmode : DMA_Wrmode)
- #ifdef DMAMODE_AUTO
- | DMAMODE_AUTO
- #endif
- ,
- snd_raw_buf_phys[dev][0], count);
- dma_enable (chan);
- #else
- # error This routine is not valid for this OS.
- #endif
- #endif
-
- #endif
- }
- else
- {
- #ifdef linux
- DISABLE_INTR (flags);
- disable_dma (chan);
- clear_dma_ff (chan);
- set_dma_mode (chan, dma_mode);
- set_dma_addr (chan, physaddr);
- set_dma_count (chan, count);
- enable_dma (chan);
- RESTORE_INTR (flags);
- #else
- #ifdef __386BSD__
- isa_dmastart ((dma_mode == DMA_MODE_READ) ? B_READ : B_WRITE,
- physaddr,
- count,
- chan);
- #else
-
- #if defined(ISC) || defined(SCO)
- dma_param (chan, ((dma_mode == DMA_MODE_READ) ? DMA_Rdmode : DMA_Wrmode),
- physaddr, count);
- dma_enable (chan);
- #else
- # error This routine is not valid for this OS.
- #endif /* !ISC */
- #endif
-
- #endif
- }
-
- return count;
- }
-
- long
- DMAbuf_init (long mem_start)
- {
- int i;
-
- /*
- * In this version the DMA buffer allocation is done by sound_mem_init()
- * which is called by init/main.c
- */
-
- for (i = 0; i < MAX_DSP_DEV; i++)
- {
- dev_qlen[i] = 0;
- dev_qhead[i] = 0;
- dev_qtail[i] = 0;
- dev_active[i] = 0;
- dev_busy[i] = 0;
- bufferalloc_done[i] = 0;
- }
-
- return mem_start;
- }
-
- void
- DMAbuf_outputintr (int dev, int underrun_flag)
- {
- unsigned long flags;
-
- dev_qlen[dev]--;
- dev_qhead[dev] = (dev_qhead[dev] + 1) % dev_nbufs[dev];
- dev_active[dev] = 0;
-
- if (dev_qlen[dev])
- {
- dsp_devs[dev]->output_block (dev, dev_buf_phys[dev][dev_qhead[dev]],
- dev_counts[dev][dev_qhead[dev]], 1,
- !sound_dma_automode[dev]);
- dev_active[dev] = 1;
- }
- else
- if (underrun_flag)
- {
- dev_underrun[dev]++;
- dsp_devs[dev]->halt_xfer (dev);
- dev_needs_restart[dev] = 1;
- }
-
- DISABLE_INTR (flags);
- if (SOMEONE_WAITING (dev_sleeper[dev], dev_sleep_flag[dev]))
- {
- WAKE_UP (dev_sleeper[dev], dev_sleep_flag[dev]);
- }
- RESTORE_INTR (flags);
- }
-
- void
- DMAbuf_inputintr (int dev)
- {
- unsigned long flags;
-
- if (!dev_busy[dev])
- {
- dsp_devs[dev]->close (dev);
- }
- else if (dev_qlen[dev] == (dev_nbufs[dev] - 1))
- {
- printk("Sound: Recording overrun\n");
- dev_underrun[dev]++;
- dsp_devs[dev]->halt_xfer (dev);
- dev_active[dev] = 0;
- dev_needs_restart[dev] = 1;
- }
- else
- {
- dev_qlen[dev]++;
- dev_qtail[dev] = (dev_qtail[dev] + 1) % dev_nbufs[dev];
-
- dsp_devs[dev]->start_input (dev, dev_buf_phys[dev][dev_qtail[dev]],
- dev_buffsize[dev], 1,
- !sound_dma_automode[dev]);
- dev_active[dev] = 1;
- }
-
- DISABLE_INTR (flags);
- if (SOMEONE_WAITING (dev_sleeper[dev], dev_sleep_flag[dev]))
- {
- WAKE_UP (dev_sleeper[dev], dev_sleep_flag[dev]);
- }
- RESTORE_INTR (flags);
- }
-
- int
- DMAbuf_open_dma (int dev)
- {
- unsigned long flags;
- int chan = sound_dsp_dmachan[dev];
-
- if (ALLOC_DMA_CHN (chan))
- {
- printk ("Unable to grab DMA%d for the audio driver\n", chan);
- return 0;
- }
-
- DISABLE_INTR (flags);
- #ifdef linux
- disable_dma (chan);
- clear_dma_ff (chan);
- #endif
- RESTORE_INTR (flags);
-
- return 1;
- }
-
- void
- DMAbuf_close_dma (int dev)
- {
- int chan = sound_dsp_dmachan[dev];
-
- DMAbuf_reset_dma (chan);
- RELEASE_DMA_CHN (chan);
- }
-
- void
- DMAbuf_reset_dma (int chan)
- {
- }
-
- /*
- * The sound_mem_init() is called by mem_init() immediately after mem_map is
- * initialized and before free_page_list is created.
- *
- * This routine allocates DMA buffers at the end of available physical memory (
- * <16M) and marks pages reserved at mem_map.
- */
-
- #else
- /* Stub versions if audio services not included */
-
- int
- DMAbuf_open (int dev, int mode)
- {
- return RET_ERROR (ENXIO);
- }
-
- int
- DMAbuf_release (int dev, int mode)
- {
- return 0;
- }
-
- int
- DMAbuf_read (int dev, snd_rw_buf * user_buf, int count)
- {
- return RET_ERROR (EIO);
- }
-
- int
- DMAbuf_getwrbuffer (int dev, char **buf, int *size)
- {
- return RET_ERROR (EIO);
- }
-
- int
- DMAbuf_getrdbuffer (int dev, char **buf, int *len)
- {
- return RET_ERROR (EIO);
- }
-
- int
- DMAbuf_rmchars (int dev, int buff_no, int c)
- {
- return RET_ERROR (EIO);
- }
-
- int
- DMAbuf_start_output (int dev, int buff_no, int l)
- {
- return RET_ERROR (EIO);
- }
-
- int
- DMAbuf_ioctl (int dev, unsigned int cmd, unsigned int arg, int local)
- {
- return RET_ERROR (EIO);
- }
-
- long
- DMAbuf_init (long mem_start)
- {
- return mem_start;
- }
-
- int
- DMAbuf_start_dma (int dev, unsigned long physaddr, int count, int dma_mode)
- {
- return RET_ERROR (EIO);
- }
-
- int
- DMAbuf_open_dma (int chan)
- {
- return RET_ERROR (ENXIO);
- }
-
- void
- DMAbuf_close_dma (int chan)
- {
- return;
- }
-
- void
- DMAbuf_reset_dma (int chan)
- {
- return;
- }
-
- void
- DMAbuf_inputintr (int dev)
- {
- return;
- }
-
- void
- DMAbuf_outputintr (int dev, int underrun_flag)
- {
- return;
- }
-
- #endif
-
- #endif
-