?? 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);
}
int
DMAbuf_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];
}
int
DMAbuf_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;
}
int
DMAbuf_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;
}
long
DMAbuf_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;
}
void
DMAbuf_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);
}
void
DMAbuf_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);
}
int
DMAbuf_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;
}
void
DMAbuf_close_dma (int dev)
{
int chan = sound_dsp_dmachan[dev];
DMAbuf_reset_dma (chan);
RELEASE_DMA_CHN (chan);
}
void
DMAbuf_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 */
int
DMAbuf_open (int dev, int mode)
{
return RET_ERROR (ENXIO);
}
int
DMAbuf_release (int dev, int mode)
{
return 0;
}
int
DMAbuf_read (int dev, snd_rw_buf * user_buf, int count)
{
return RET_ERROR (EIO);
}
int
DMAbuf_getwrbuffer (int dev, char **buf, int *size)
{
return RET_ERROR (EIO);
}
int
DMAbuf_getrdbuffer (int dev, char **buf, int *len)
{
return RET_ERROR (EIO);
}
int
DMAbuf_rmchars (int dev, int buff_no, int c)
{
return RET_ERROR (EIO);
}
int
DMAbuf_start_output (int dev, int buff_no, int l)
{
return RET_ERROR (EIO);
}
int
DMAbuf_ioctl (int dev, unsigned int cmd, unsigned int arg, int local)
{
return RET_ERROR (EIO);
}
long
DMAbuf_init (long mem_start)
{
return mem_start;
}
int
DMAbuf_start_dma (int dev, unsigned long physaddr, int count, int dma_mode)
{
return RET_ERROR (EIO);
}
int
DMAbuf_open_dma (int chan)
{
return RET_ERROR (ENXIO);
}
void
DMAbuf_close_dma (int chan)
{
return;
}
void
DMAbuf_reset_dma (int chan)
{
return;
}
void
DMAbuf_inputintr (int dev)
{
return;
}
void
DMAbuf_outputintr (int dev, int underrun_flag)
{
return;
}
#endif
#endif
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -