亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關(guān)于我們
? 蟲蟲下載站

?? dmabuf.c

?? LINUX1.0源代碼,代碼條理清晰
?? C
?? 第 1 頁 / 共 2 頁
字號:
/*
 * 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);

?? 快捷鍵說明

復(fù)制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
在线视频你懂得一区二区三区| 亚洲自拍偷拍网站| 天天色 色综合| 欧美日本在线播放| 天堂va蜜桃一区二区三区漫画版| 欧美另类变人与禽xxxxx| 青娱乐精品在线视频| 26uuu国产日韩综合| 国产乱国产乱300精品| 成人免费小视频| 欧美制服丝袜第一页| 蜜臀av性久久久久蜜臀aⅴ流畅| 日韩午夜在线影院| 国产激情一区二区三区| 亚洲视频一区二区在线| 欧美日韩不卡在线| 国产精品资源在线看| 亚洲品质自拍视频| 日韩一区二区三区免费观看| 国产精品一区二区在线观看不卡 | 亚洲一区在线看| 欧美福利视频一区| 国产精品一二二区| 一区二区三区在线观看网站| 欧美一区二区播放| aaa亚洲精品| 日韩精品一卡二卡三卡四卡无卡| 久久综合av免费| 91麻豆视频网站| 亚洲图片欧美一区| 国产亚洲美州欧州综合国| 欧美综合天天夜夜久久| 亚洲sss视频在线视频| 国产精品午夜免费| 欧美日韩国产另类不卡| 国内一区二区视频| 亚洲一区二区三区在线播放| 久久人人爽人人爽| 777午夜精品视频在线播放| 成人一区二区三区在线观看 | 国产精品麻豆视频| 欧美国产精品劲爆| 欧美视频日韩视频在线观看| 国产黑丝在线一区二区三区| 亚洲国产精品尤物yw在线观看| 国产日韩欧美一区二区三区乱码| 欧美日韩成人激情| av一区二区三区| 黄色资源网久久资源365| 亚洲第一福利一区| 亚洲欧美日韩国产手机在线 | 日本欧美一区二区在线观看| 国产精品色哟哟网站| 精品国一区二区三区| 欧美视频在线一区| 91丨porny丨首页| 国产精品996| 蜜臀va亚洲va欧美va天堂 | 日本黄色一区二区| 成人性生交大片免费看视频在线| 久久精品国产精品青草| 天天色天天操综合| 一区二区在线电影| 国产精品二三区| 国产亚洲一区二区三区在线观看| 日韩一级片在线播放| 欧美日韩国产综合草草| 91福利视频在线| 91啪在线观看| 91小宝寻花一区二区三区| 国产精品综合网| 国产一区二区三区免费观看 | 精东粉嫩av免费一区二区三区| 波多野洁衣一区| 国产精品99久久久| 国产一区不卡精品| 精品写真视频在线观看| 久久精品国产精品青草| 国产综合色产在线精品| 国产精品一二二区| 成人美女视频在线看| av在线不卡免费看| 色综合咪咪久久| 在线视频欧美区| 欧美疯狂性受xxxxx喷水图片| 欧美日本在线观看| 日韩天堂在线观看| 精品国产精品网麻豆系列| 欧美成人性战久久| 国产欧美精品一区二区色综合| 中文一区一区三区高中清不卡| 中文字幕欧美日韩一区| 国产精品激情偷乱一区二区∴| 综合久久久久久久| 亚洲动漫第一页| 天堂精品中文字幕在线| 久久激情综合网| 国产美女一区二区| 91丨porny丨首页| 欧美日韩免费观看一区二区三区 | 亚洲一区二区三区不卡国产欧美| 视频精品一区二区| 久久66热偷产精品| 成人国产一区二区三区精品| 欧美丝袜丝交足nylons| 精品少妇一区二区三区在线播放| 国产欧美一区二区三区网站| 日韩理论片中文av| 奇米影视一区二区三区| 成人免费看视频| 欧美日韩一区二区在线视频| 欧美刺激脚交jootjob| 国产精品久久久久一区| 午夜精品久久久久久久99水蜜桃 | 高清免费成人av| 91国内精品野花午夜精品| 日韩欧美在线综合网| 综合久久综合久久| 精品影院一区二区久久久| 色综合视频一区二区三区高清| 欧美一区二区精品在线| 中文字幕在线不卡视频| 奇米影视一区二区三区小说| 不卡一卡二卡三乱码免费网站| 欧美日韩一本到| 中文字幕不卡在线播放| 日韩成人av影视| av在线一区二区三区| 精品国产乱码久久久久久图片| 亚洲丝袜制服诱惑| 国产精品123| 51久久夜色精品国产麻豆| 国产精品第13页| 狠狠色2019综合网| 欧美人伦禁忌dvd放荡欲情| 一区在线播放视频| 国产中文一区二区三区| 欧美精品久久99| 亚洲人123区| 成人黄动漫网站免费app| 久久中文字幕电影| 青青草成人在线观看| 91成人免费网站| 国产精品家庭影院| 国产91在线看| 26uuu精品一区二区三区四区在线 26uuu精品一区二区在线观看 | 中文字幕欧美区| 婷婷中文字幕综合| 91福利在线免费观看| 日本一区二区成人在线| 韩国欧美一区二区| 日韩欧美一区二区不卡| 性欧美大战久久久久久久久| 色综合色狠狠天天综合色| 国产精品污污网站在线观看| 精品一区二区三区视频| 91精品综合久久久久久| 亚洲6080在线| 欧美日韩精品系列| 性做久久久久久免费观看欧美| 91精彩视频在线观看| 亚洲图片激情小说| 99久久99久久综合| 亚洲图片欧美激情| 91官网在线观看| 一区二区三区不卡视频| 欧美在线色视频| 依依成人精品视频| 欧美在线一区二区三区| 亚洲国产欧美日韩另类综合 | 成人黄色777网| 国产精品久久三区| 91视频国产资源| 亚洲男人的天堂在线观看| 色综合天天综合网天天看片| 亚洲男人的天堂网| 欧美日韩国产精品成人| 丝袜亚洲另类丝袜在线| 日韩午夜激情免费电影| 国内精品伊人久久久久av一坑| 精品av久久707| 国产伦理精品不卡| 国产精品乱码妇女bbbb| 91免费精品国自产拍在线不卡| 一区二区三区中文字幕电影| 欧美日韩精品免费| 看片的网站亚洲| 国产偷国产偷亚洲高清人白洁| 成人免费视频视频| 亚洲男人的天堂av| 69堂成人精品免费视频| 另类小说色综合网站| 久久婷婷一区二区三区| gogo大胆日本视频一区| 一级日本不卡的影视| 91精品国产一区二区人妖| 国内精品国产成人国产三级粉色| 国产精品卡一卡二| 欧美日本精品一区二区三区| 精品一二三四在线|