/*
* sound/oss/dmabuf.c
*
* The DMA buffer manager for digitized voice applications
*/
/*
* Copyright (C) by Hannu Savolainen 1993-1997
*
* OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
* Version 2 (June 1991). See the "COPYING" file distributed with this software
* for more info.
*
* Thomas Sailer : moved several static variables into struct audio_operations
* (which is grossly misnamed btw.) because they have the same
* lifetime as the rest in there and dynamic allocation saves
* 12k or so
* Thomas Sailer : remove {in,out}_sleep_flag. It was used for the sleeper to
* determine if it was woken up by the expiring timeout or by
* an explicit wake_up. The return value from schedule_timeout
* can be used instead; if 0, the wakeup was due to the timeout.
*
* Rob Riggs Added persistent DMA buffers (1998/10/17)
*/
#define BE_CONSERVATIVE
#define SAMPLE_ROUNDUP 0
#include <linux/mm.h>
#include "sound_config.h"
#define DMAP_FREE_ON_CLOSE 0
#define DMAP_KEEP_ON_CLOSE 1
extern int sound_dmap_flag;
static void dma_reset_output(int dev);
static void dma_reset_input(int dev);
static int local_start_dma(struct audio_operations *adev, unsigned long physaddr, int count, int dma_mode);
static int debugmem; /* switched off by default */
static int dma_buffsize = DSP_BUFFSIZE;
static long dmabuf_timeout(struct dma_buffparms *dmap)
{
long tmout;
tmout = (dmap->fragment_size * HZ) / dmap->data_rate;
tmout += HZ / 5; /* Some safety distance */
if (tmout < (HZ / 2))
tmout = HZ / 2;
if (tmout > 20 * HZ)
tmout = 20 * HZ;
return tmout;
}
static int sound_alloc_dmap(struct dma_buffparms *dmap)
{
char *start_addr, *end_addr;
int dma_pagesize;
int sz, size;
struct page *page;
dmap->mapping_flags &= ~DMA_MAP_MAPPED;
if (dmap->raw_buf != NULL)
return 0; /* Already done */
if (dma_buffsize < 4096)
dma_buffsize = 4096;
dma_pagesize = (dmap->dma < 4) ? (64 * 1024) : (128 * 1024);
/*
* Now check for the Cyrix problem.
*/
if(isa_dma_bridge_buggy==2)
dma_pagesize=32768;
dmap->raw_buf = NULL;
dmap->buffsize = dma_buffsize;
if (dmap->buffsize > dma_pagesize)
dmap->buffsize = dma_pagesize;
start_addr = NULL;
/*
* Now loop until we get a free buffer. Try to get smaller buffer if
* it fails. Don't accept smaller than 8k buffer for performance
* reasons.
*/
while (start_addr == NULL && dmap->buffsize > PAGE_SIZE) {
for (sz = 0, size = PAGE_SIZE; size < dmap->buffsize;