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

📄 dmabuf.c

📁 arm平台上的uclinux系统全部源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
      dmap->qtail = (dmap->qtail + 1) % dmap->nbufs;    }  else    {      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)	{	  int             p = dmap->fragment_size * dmap->qtail;	  dmap->neutral_byte = dmap->raw_buf[p + l - 1];	  memset (dmap->raw_buf + p + l,		  dmap->neutral_byte,		  dmap->fragment_size - l);	}      else	dmap->neutral_byte =	  dmap->raw_buf[dmap->fragment_size * dmap->qtail - 1];      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;      if (restart)	audio_devs[dev]->d->prepare_for_output (dev,					  dmap->fragment_size, dmap->nbufs);      audio_devs[dev]->d->output_block (dev, dmap->raw_buf_phys +					dmap->qhead * dmap->fragment_size,					dmap->counts[dmap->qhead], 0,				 !(audio_devs[dev]->flags & DMA_AUTOMODE) ||					!(dmap->flags & DMA_STARTED));      dmap->flags |= DMA_STARTED;      if (audio_devs[dev]->d->trigger)	audio_devs[dev]->d->trigger (dev,			audio_devs[dev]->enable_bits * audio_devs[dev]->go);    }  return 0;}intDMAbuf_start_dma (int dev, unsigned long physaddr, int count, int dma_mode){  int             chan;  struct dma_buffparms *dmap;  unsigned long   flags;  if (dma_mode == DMA_MODE_WRITE)    {      chan = audio_devs[dev]->dmachan1;      dmap = audio_devs[dev]->dmap_out;    }  else    {      chan = audio_devs[dev]->dmachan2;      dmap = audio_devs[dev]->dmap_in;    }  if (dmap->raw_buf_phys == 0)    {      printk ("sound: DMA buffer == NULL\n");      return 0;    }  /*   * 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				 */      save_flags (flags);      cli ();      disable_dma (chan);      clear_dma_ff (chan);      set_dma_mode (chan, dma_mode | DMA_AUTOINIT);      set_dma_addr (chan, dmap->raw_buf_phys);      set_dma_count (chan, dmap->bytes_in_use);      enable_dma (chan);      restore_flags (flags);    }  else    {      save_flags (flags);      cli ();      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_flags (flags);    }  return count;}voidDMAbuf_init (void){  int             dev;  /*     * NOTE! This routine could be called several times.   */  for (dev = 0; dev < num_audiodevs; dev++)    if (audio_devs[dev]->dmap_out == NULL)      {	audio_devs[dev]->dmap_out =	  audio_devs[dev]->dmap_in =	  &dmaps[ndmaps++];	if (audio_devs[dev]->flags & DMA_DUPLEX)	  audio_devs[dev]->dmap_in =	    &dmaps[ndmaps++];      }}static voidpolish_buffers (struct dma_buffparms *dmap){  int             i;  int             p, l;  i = dmap->qhead;  p = dmap->fragment_size * i;  if (i == dmap->cfrag)    {      l = dmap->fragment_size - dmap->counts[i];    }  else    l = dmap->fragment_size;  if (l)    {      memset (dmap->raw_buf + p,	      dmap->neutral_byte,	      l);    }}static voidforce_restart (int dev, struct dma_buffparms *dmap){  if ((audio_devs[dev]->flags & DMA_DUPLEX) &&      audio_devs[dev]->d->halt_output)    audio_devs[dev]->d->halt_output (dev);  else    audio_devs[dev]->d->halt_xfer (dev);  dmap->flags &= ~(DMA_ACTIVE | DMA_STARTED);  if (audio_devs[dev]->flags & DMA_AUTOMODE)    dmap->flags |= DMA_RESTART;  else    dmap->flags &= ~DMA_RESTART;}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_out;  int             this_fragment;  dmap->byte_counter += dmap->counts[dmap->qhead];#ifdef OS_DMA_INTR  sound_dma_intr (dev, audio_devs[dev]->dmap_out, audio_devs[dev]->dmachan1);#endif  if (dmap->raw_buf == NULL)    {      printk ("Sound: Fatal error. Audio interrupt after freeing buffers.\n");      return;    }  if (dmap->mapping_flags & DMA_MAP_MAPPED)    {      /* mmapped access */      dmap->qhead = (dmap->qhead + 1) % dmap->nbufs;      dmap->qlen++;		/* Yes increment it (don't decrement) */      dmap->flags &= ~DMA_ACTIVE;      dmap->counts[dmap->qhead] = dmap->fragment_size;      if (!(audio_devs[dev]->flags & DMA_AUTOMODE))	{	  audio_devs[dev]->d->output_block (dev, dmap->raw_buf_phys +					  dmap->qhead * dmap->fragment_size,					    dmap->counts[dmap->qhead], 1,				  !(audio_devs[dev]->flags & DMA_AUTOMODE));	  if (audio_devs[dev]->d->trigger)	    audio_devs[dev]->d->trigger (dev,			audio_devs[dev]->enable_bits * audio_devs[dev]->go);	}      dmap->flags |= DMA_ACTIVE;    }  else 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--;      this_fragment = dmap->qhead;      dmap->qhead = (dmap->qhead + 1) % dmap->nbufs;      dmap->flags &= ~DMA_ACTIVE;      if (event_type == 1 && dmap->qlen < 1)	{	  dmap->underrun_count++;	  if ((!(dmap->flags & DMA_CLEAN) &&	       (audio_devs[dev]->dmap_out->flags & DMA_SYNCING ||		dmap->underrun_count > 5 || dmap->flags & DMA_EMPTY)) ||	      audio_devs[dev]->flags & DMA_HARDSTOP)	    {	      dmap->qlen = 0;	      force_restart (dev, dmap);	    }	  else	    /* Ignore underrun. Just move the tail pointer forward and go */	  if (dmap->closing)	    {	      polish_buffers (dmap);	      audio_devs[dev]->d->halt_xfer (dev);	    }	  else	    {	      dmap->qlen++;	      dmap->qtail = (dmap->qtail + 1) % dmap->nbufs;	      if (!(dmap->flags & DMA_EMPTY))		polish_buffers (dmap);	      dmap->cfrag = -1;	      dmap->flags |= DMA_EMPTY;	      dmap->counts[dmap->qtail] = dmap->fragment_size;	    }	}      if (dmap->qlen)	{	  if (dmap->flags & DMA_CLEAN)	    {	      int             p = dmap->fragment_size * this_fragment;	      memset (dmap->raw_buf + p,		      dmap->neutral_byte,		      dmap->fragment_size);	    }	  if (!(audio_devs[dev]->flags & DMA_AUTOMODE))	    {	      if (dmap->counts[dmap->qhead] == 0)		dmap->counts[dmap->qhead] = dmap->fragment_size;	      audio_devs[dev]->d->output_block (dev, dmap->raw_buf_phys +					  dmap->qhead * dmap->fragment_size,						dmap->counts[dmap->qhead], 1,				  !(audio_devs[dev]->flags & DMA_AUTOMODE));	      if (audio_devs[dev]->d->trigger)		audio_devs[dev]->d->trigger (dev,			audio_devs[dev]->enable_bits * audio_devs[dev]->go);	    }	  dmap->flags |= DMA_ACTIVE;	}    }				/* event_type != 2 */  save_flags (flags);  cli ();  if ((out_sleep_flag[dev].flags & WK_SLEEP))    {      {	out_sleep_flag[dev].flags = WK_WAKEUP;	module_wake_up (&out_sleeper[dev]);      };    }  restore_flags (flags);}voidDMAbuf_inputintr (int dev){  unsigned long   flags;  struct dma_buffparms *dmap = audio_devs[dev]->dmap_in;  dmap->byte_counter += dmap->fragment_size;#ifdef OS_DMA_INTR  sound_dma_intr (dev, audio_devs[dev]->dmap_in, audio_devs[dev]->dmachan2);#endif  if (dmap->raw_buf == NULL)    {      printk ("Sound: Fatal error. Audio interrupt after freeing buffers.\n");      return;    }  if (dmap->mapping_flags & DMA_MAP_MAPPED)    {      dmap->qtail = (dmap->qtail + 1) % dmap->nbufs;      dmap->qlen++;      if (!(audio_devs[dev]->flags & DMA_AUTOMODE))	{	  audio_devs[dev]->d->start_input (dev, dmap->raw_buf_phys +					   dmap->qtail * dmap->fragment_size,					   dmap->fragment_size, 1,				  !(audio_devs[dev]->flags & DMA_AUTOMODE));	  if (audio_devs[dev]->d->trigger)	    audio_devs[dev]->d->trigger (dev,			audio_devs[dev]->enable_bits * audio_devs[dev]->go);	}      dmap->flags |= DMA_ACTIVE;    }  else if (dmap->qlen == (dmap->nbufs - 1))    {      printk ("Sound: Recording overrun\n");      dmap->underrun_count++;      if (audio_devs[dev]->flags & DMA_AUTOMODE)	{	  /* Force restart on next read */	  if ((audio_devs[dev]->flags & DMA_DUPLEX) &&	      audio_devs[dev]->d->halt_input)	    audio_devs[dev]->d->halt_input (dev);	  else	    audio_devs[dev]->d->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;    }  if (!(audio_devs[dev]->flags & DMA_AUTOMODE))    {      audio_devs[dev]->d->start_input (dev, dmap->raw_buf_phys +				       dmap->qtail * dmap->fragment_size,				       dmap->fragment_size, 1,				  !(audio_devs[dev]->flags & DMA_AUTOMODE));      if (audio_devs[dev]->d->trigger)	audio_devs[dev]->d->trigger (dev,			audio_devs[dev]->enable_bits * audio_devs[dev]->go);    }  dmap->flags |= DMA_ACTIVE;  save_flags (flags);  cli ();  if ((in_sleep_flag[dev].flags & WK_SLEEP))    {      {	in_sleep_flag[dev].flags = WK_WAKEUP;	module_wake_up (&in_sleeper[dev]);      };    }  restore_flags (flags);}intDMAbuf_open_dma (int dev){/* *    NOTE!  This routine opens only the primary DMA channel (output). */  int             chan = audio_devs[dev]->dmachan1;  int             err;  unsigned long   flags;  if ((err = open_dmap (dev, OPEN_READWRITE, audio_devs[dev]->dmap_out, audio_devs[dev]->dmachan1)) < 0)    {      return -(EBUSY);    }  dma_init_buffers (dev, audio_devs[dev]->dmap_out);  audio_devs[dev]->dmap_out->flags |= DMA_ALLOC_DONE;  audio_devs[dev]->dmap_out->fragment_size = audio_devs[dev]->buffsize;  save_flags (flags);  cli ();  disable_dma (chan);  clear_dma_ff (chan);  restore_flags (flags);  return 0;}voidDMAbuf_close_dma (int dev){  DMAbuf_reset_dma (dev);  close_dmap (dev, audio_devs[dev]->dmap_out, audio_devs[dev]->dmachan1);}voidDMAbuf_reset_dma (int dev){}intDMAbuf_select (int dev, struct fileinfo *file, int sel_type, select_table_handle * wait){  struct dma_buffparms *dmap;  unsigned long   flags;  switch (sel_type)    {    case SEL_IN:      dmap = audio_devs[dev]->dmap_in;      if (dmap->mapping_flags & DMA_MAP_MAPPED)	{	  if (dmap->qlen)	    return 1;	  save_flags (flags);	  cli ();	  in_sleep_flag[dev].flags = WK_SLEEP;	  module_select_wait (&in_sleeper[dev], wait);	  restore_flags (flags);	  return 0;	}      if (dmap->dma_mode != DMODE_INPUT)	{	  if ((audio_devs[dev]->flags & DMA_DUPLEX) && !dmap->qlen &&	      audio_devs[dev]->enable_bits & PCM_ENABLE_INPUT &&	      audio_devs[dev]->go)	    {	      unsigned long   flags;	      save_flags (flags);	      cli ();	      activate_recording (dev, dmap);	      restore_flags (flags);	    }	  return 0;	}      if (!dmap->qlen)	{	  save_flags (flags);	  cli ();	  in_sleep_flag[dev].flags = WK_SLEEP;	  module_select_wait (&in_sleeper[dev], wait);	  restore_flags (flags);	  return 0;	}      return 1;      break;    case SEL_OUT:      dmap = audio_devs[dev]->dmap_out;      if (dmap->mapping_flags & DMA_MAP_MAPPED)	{	  if (dmap->qlen)	    return 1;	  save_flags (flags);	  cli ();	  out_sleep_flag[dev].flags = WK_SLEEP;	  module_select_wait (&out_sleeper[dev], wait);	  restore_flags (flags);	  return 0;	}      if (dmap->dma_mode == DMODE_INPUT)	{	  return 0;	}      if (dmap->dma_mode == DMODE_NONE)	{	  return 1;	}      if (!space_in_queue (dev))	{	  save_flags (flags);	  cli ();	  out_sleep_flag[dev].flags = WK_SLEEP;	  module_select_wait (&out_sleeper[dev], wait);	  restore_flags (flags);	  return 0;	}      return 1;      break;    case SEL_EX:      return 0;    }  return 0;}#else /* CONFIG_AUDIO *//* * Stub versions if audio services not included */intDMAbuf_open (int dev, int mode){  return -(ENXIO);}intDMAbuf_release (int dev, int mode){  return 0;}intDMAbuf_getwrbuffer (int dev, char **buf, int *size, int dontblock){  return -(EIO);}intDMAbuf_getrdbuffer (int dev, char **buf, int *len, int dontblock){  return -(EIO);}intDMAbuf_rmchars (int dev, int buff_no, int c){  return -(EIO);}intDMAbuf_start_output (int dev, int buff_no, int l){  return -(EIO);}intDMAbuf_ioctl (int dev, unsigned int cmd, caddr_t arg, int local){  return -(EIO);}voidDMAbuf_init (void){}intDMAbuf_start_dma (int dev, unsigned long physaddr, int count, int dma_mode){  return -(EIO);}intDMAbuf_open_dma (int dev){  return -(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

⌨️ 快捷键说明

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