⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dmabuf.c

📁 freebsd v4.4内核源码
💻 C
📖 第 1 页 / 共 2 页
字号:
     * defined by the process.   */  max = dmap->max_fragments;  len = dmap->qlen;  if (audio_devs[dev]->local_qlen)    {      tmp = audio_devs[dev]->local_qlen (dev);      if (tmp & len)	tmp--;			/*				   * This buffer has been counted twice				 */      len += tmp;    }  if (len >= max)    return 0;  return 1;}intDMAbuf_getwrbuffer (int dev, char **buf, int *size, int dontblock){  unsigned long   flags;  int             abort, err = EIO;  struct dma_buffparms *dmap = audio_devs[dev]->dmap;  if (dmap->dma_mode == DMODE_INPUT)	/* Direction change */    {      dma_reset (dev);      dmap->dma_mode = DMODE_NONE;    }  else if (dmap->flags & DMA_RESTART)	/* Restart buffering */    {      dma_sync (dev);      dma_reset (dev);    }  dmap->flags &= ~DMA_RESTART;  if (!(dmap->flags & DMA_ALLOC_DONE))    reorganize_buffers (dev);  if (!dmap->dma_mode)    {      int             err;      dmap->dma_mode = DMODE_OUTPUT;      if ((err = audio_devs[dev]->prepare_for_output (dev,				     dmap->fragment_size, dmap->nbufs)) < 0)	return err;    }  DISABLE_INTR (flags);  abort = 0;  while (!space_in_queue (dev) &&	 !abort)    {      if (dontblock)	{	  RESTORE_INTR (flags);	  return RET_ERROR (EAGAIN);	}      /*       * 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");	  dma_reset (dev);	  err = EIO;	  abort = 1;	  SET_ABORT_FLAG (dev_sleeper[dev], dev_sleep_flag[dev]);	}      else if (PROCESS_ABORTING (dev_sleeper[dev], dev_sleep_flag[dev]))	{	  err = EINTR;	  abort = 1;	}    }  RESTORE_INTR (flags);  if (!space_in_queue (dev))    {      return RET_ERROR (err);	/* Caught a signal ? */    }  *buf = dmap->buf[dmap->qtail];  *size = dmap->fragment_size;  dmap->counts[dmap->qtail] = 0;  return dmap->qtail;}intDMAbuf_start_output (int dev, int buff_no, int l){  struct dma_buffparms *dmap = audio_devs[dev]->dmap;  if (buff_no != dmap->qtail)    printk ("Sound warning: DMA buffers out of sync %d != %d\n", buff_no, dmap->qtail);  dmap->qlen++;  if (dmap->qlen <= 0 || dmap->qlen > dmap->nbufs)    printk ("\nSound: Audio queue2 corrupted for dev%d (%d/%d)\n",	    dev, dmap->qlen, dmap->nbufs);  dmap->counts[dmap->qtail] = l;  if ((l != dmap->fragment_size) &&      ((audio_devs[dev]->flags & DMA_AUTOMODE) &&       audio_devs[dev]->flags & NEEDS_RESTART))    dmap->flags |= DMA_RESTART;  else    dmap->flags &= ~DMA_RESTART;  dmap->qtail = (dmap->qtail + 1) % dmap->nbufs;  if (!(dmap->flags & DMA_ACTIVE))    {      dmap->flags |= DMA_ACTIVE;      audio_devs[dev]->output_block (dev, dmap->buf_phys[dmap->qhead],				     dmap->counts[dmap->qhead], 0,				 !(audio_devs[dev]->flags & DMA_AUTOMODE) ||				     !(dmap->flags & DMA_STARTED));      dmap->flags |= DMA_STARTED;    }  return 0;}intDMAbuf_start_dma (int dev, unsigned long physaddr, int count, int dma_mode){  int             chan = audio_devs[dev]->dmachan;  struct dma_buffparms *dmap = audio_devs[dev]->dmap;#ifdef linux  unsigned long   flags;#endif  /*   * 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 (audio_devs[dev]->flags & DMA_AUTOMODE)    {				/*				 * 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, dmap->raw_buf_phys[0]);      set_dma_count (chan, dmap->bytes_in_use);      enable_dma (chan);      RESTORE_INTR (flags);#else#if defined(__FreeBSD__)      isa_dmastart (B_RAW | ((dma_mode == DMA_MODE_READ) ? B_READ : B_WRITE),		    (caddr_t)dmap->raw_buf_phys[0],		    dmap->bytes_in_use,		    chan);#else /* else __FreeBSD__ */#if defined(GENERIC_SYSV)#ifndef DMAMODE_AUTO      printk ("sound: Invalid DMA mode for device %d\n", dev);#endif#if defined(SVR42)      /*         ** send full count to snd_dma_prog, it will take care of subtracting         ** one if it is required.       */      snd_dma_prog (chan, dmap->raw_buf_phys[0], dmap->bytes_in_use,		    dma_mode, TRUE);#else /* !SVR42 */      dma_param (chan, ((dma_mode == DMA_MODE_READ) ? DMA_Rdmode : DMA_Wrmode)#ifdef DMAMODE_AUTO		 | DMAMODE_AUTO#endif		 ,		 dmap->raw_buf_phys[0], dmap->bytes_in_use - 1);      dma_enable (chan);#endif /*  ! SVR42 */#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#if defined(__FreeBSD__)      isa_dmastart ((dma_mode == DMA_MODE_READ) ? B_READ : B_WRITE,		    (caddr_t)physaddr,		    count,		    chan);#else /* FreeBSD */#if defined(GENERIC_SYSV)#if defined(SVR42)      snd_dma_prog (chan, physaddr, count, dma_mode, FALSE);#else /* ! SVR42 */      dma_param (chan, ((dma_mode == DMA_MODE_READ) ? DMA_Rdmode : DMA_Wrmode),		 physaddr, count);      dma_enable (chan);#endif /* SVR42 */#else#error This routine is not valid for this OS.#endif /* GENERIC_SYSV */#endif#endif    }  return count;}longDMAbuf_init (long mem_start){  int             dev;#if defined(SVR42)  snd_dma_init ();#endif /* SVR42 */  /*     * NOTE! This routine could be called several times.   */  for (dev = 0; dev < num_audiodevs; dev++)    audio_devs[dev]->dmap = &dmaps[dev];  return mem_start;}voidDMAbuf_outputintr (int dev, int event_type){  /*     * Event types:     *  0 = DMA transfer done. Device still has more data in the local     *      buffer.     *  1 = DMA transfer done. Device doesn't have local buffer or it's     *      empty now.     *  2 = No DMA transfer but the device has now more space in it's local     *      buffer.   */  unsigned long   flags;  struct dma_buffparms *dmap = audio_devs[dev]->dmap;#if defined(SVR42)  snd_dma_intr (audio_devs[dev]->dmachan);#endif /* SVR42 */  if (event_type != 2)    {      if (dmap->qlen <= 0 || dmap->qlen > dmap->nbufs)	{	  printk ("\nSound: Audio queue3 corrupted for dev%d (%d/%d)\n",		  dev, dmap->qlen, dmap->nbufs);	  return;	}      dmap->qlen--;      dmap->qhead = (dmap->qhead + 1) % dmap->nbufs;      dmap->flags &= ~DMA_ACTIVE;#ifdef __FreeBSD__      isa_dmadone(0, 0, 0, audio_devs[dev]->dmachan);#endif      if (dmap->qlen)	{	  audio_devs[dev]->output_block (dev, dmap->buf_phys[dmap->qhead],					 dmap->counts[dmap->qhead], 1,				  !(audio_devs[dev]->flags & DMA_AUTOMODE));	  dmap->flags |= DMA_ACTIVE;	}      else if (event_type == 1)	{	  dmap->underrun_count++;	  audio_devs[dev]->halt_xfer (dev);	  if ((audio_devs[dev]->flags & DMA_AUTOMODE) &&	      audio_devs[dev]->flags & NEEDS_RESTART)	    dmap->flags |= DMA_RESTART;	  else	    dmap->flags &= ~DMA_RESTART;	}    }				/* event_type != 2 */  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);#if defined(__FreeBSD__)  if(selinfo[dev].si_pid)    selwakeup(&selinfo[dev]);#endif}voidDMAbuf_inputintr (int dev){  unsigned long   flags;  struct dma_buffparms *dmap = audio_devs[dev]->dmap;#if defined(SVR42)  snd_dma_intr (audio_devs[dev]->dmachan);#endif /* SVR42 */ #ifdef __FreeBSD__      isa_dmadone(0, 0, 0, audio_devs[dev]->dmachan);#endif  if (dmap->qlen == (dmap->nbufs - 1))    {#if !defined(__FreeBSD__)	/* ignore console message. */      printk ("Sound: Recording overrun\n");#endif      dmap->underrun_count++;      audio_devs[dev]->halt_xfer (dev);      dmap->flags &= ~DMA_ACTIVE;      if (audio_devs[dev]->flags & DMA_AUTOMODE)	dmap->flags |= DMA_RESTART;      else	dmap->flags &= ~DMA_RESTART;    }  else    {      dmap->qlen++;      if (dmap->qlen <= 0 || dmap->qlen > dmap->nbufs)	printk ("\nSound: Audio queue4 corrupted for dev%d (%d/%d)\n",		dev, dmap->qlen, dmap->nbufs);      dmap->qtail = (dmap->qtail + 1) % dmap->nbufs;      audio_devs[dev]->start_input (dev, dmap->buf_phys[dmap->qtail],				    dmap->fragment_size, 1,				  !(audio_devs[dev]->flags & DMA_AUTOMODE));      dmap->flags |= DMA_ACTIVE;    }  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);#if defined(__FreeBSD__)  if(selinfo[dev].si_pid)    selwakeup(&selinfo[dev]);#endif}intDMAbuf_open_dma (int dev){  unsigned long   flags;  int             chan = audio_devs[dev]->dmachan;  if (ALLOC_DMA_CHN (chan, audio_devs[dev]->name))    {#if 0      /* Enough already!  This error is reported twice elsewhere */      printk ("Unable to grab DMA%d for the audio driver\n", chan);#endif      return RET_ERROR (EBUSY);    }  DISABLE_INTR (flags);#ifdef linux  disable_dma (chan);  clear_dma_ff (chan);#endif  RESTORE_INTR (flags);  return 0;}voidDMAbuf_close_dma (int dev){  int             chan = audio_devs[dev]->dmachan;  DMAbuf_reset_dma (dev);  RELEASE_DMA_CHN (chan);}voidDMAbuf_reset_dma (int dev){}#ifdef ALLOW_SELECTintDMAbuf_select (int dev, struct fileinfo *file, int sel_type, select_table * wait){  struct dma_buffparms *dmap = audio_devs[dev]->dmap;  unsigned long   flags;  switch (sel_type)    {    case SEL_IN:      if (dmap->dma_mode != DMODE_INPUT)	return 0;      DISABLE_INTR (flags);      if (!dmap->qlen)	{#if defined(__FreeBSD__)	  selrecord(wait, &selinfo[dev]);#else	  dev_sleep_flag[dev].mode = WK_SLEEP;	  select_wait (&dev_sleeper[dev], wait);#endif	  RESTORE_INTR (flags);	  return 0;	}      RESTORE_INTR (flags);      return 1;      break;    case SEL_OUT:      if (dmap->dma_mode == DMODE_INPUT)	return 0;      if (dmap->dma_mode == DMODE_NONE)	return 1;      DISABLE_INTR (flags);      if (!space_in_queue (dev))	{#if defined(__FreeBSD__)	  selrecord(wait, &selinfo[dev]);#else	  dev_sleep_flag[dev].mode = WK_SLEEP;	  select_wait (&dev_sleeper[dev], wait);#endif	  RESTORE_INTR (flags);	  return 0;	}      RESTORE_INTR (flags);      return 1;      break;    case SEL_EX:      return 0;    }  return 0;}#endif /* ALLOW_SELECT */#else /* EXCLUDE_AUDIO *//* * Stub versions if audio services not included */intDMAbuf_open (int dev, int mode){  return RET_ERROR (ENXIO);}intDMAbuf_release (int dev, int mode){  return 0;}intDMAbuf_getwrbuffer (int dev, char **buf, int *size, int dontblock){  return RET_ERROR (EIO);}intDMAbuf_getrdbuffer (int dev, char **buf, int *len, int dontblock){  return RET_ERROR (EIO);}intDMAbuf_rmchars (int dev, int buff_no, int c){  return RET_ERROR (EIO);}intDMAbuf_start_output (int dev, int buff_no, int l){  return RET_ERROR (EIO);}intDMAbuf_ioctl (int dev, unsigned int cmd, unsigned int arg, int local){  return RET_ERROR (EIO);}longDMAbuf_init (long mem_start){  return mem_start;}intDMAbuf_start_dma (int dev, unsigned long physaddr, int count, int dma_mode){  return RET_ERROR (EIO);}intDMAbuf_open_dma (int dev){  return RET_ERROR (ENXIO);}voidDMAbuf_close_dma (int dev){  return;}voidDMAbuf_reset_dma (int dev){  return;}voidDMAbuf_inputintr (int dev){  return;}voidDMAbuf_outputintr (int dev, int underrun_flag){  return;}#endif#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -