📄 dmabuf.c
字号:
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);}intDMAbuf_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];}intDMAbuf_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;}intDMAbuf_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;}longDMAbuf_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;}voidDMAbuf_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);}voidDMAbuf_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);}intDMAbuf_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;}voidDMAbuf_close_dma (int dev){ int chan = sound_dsp_dmachan[dev]; DMAbuf_reset_dma (chan); RELEASE_DMA_CHN (chan);}voidDMAbuf_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 */intDMAbuf_open (int dev, int mode){ return RET_ERROR (ENXIO);}intDMAbuf_release (int dev, int mode){ return 0;}intDMAbuf_read (int dev, snd_rw_buf * user_buf, int count){ return RET_ERROR (EIO);}intDMAbuf_getwrbuffer (int dev, char **buf, int *size){ return RET_ERROR (EIO);}intDMAbuf_getrdbuffer (int dev, char **buf, int *len){ 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 chan){ return RET_ERROR (ENXIO);}voidDMAbuf_close_dma (int chan){ return;}voidDMAbuf_reset_dma (int chan){ 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 + -