static int find_output_space(int dev, char **buf, int *size) { struct audio_operations *adev = audio_devs[dev]; struct dma_buffparms *dmap = adev->dmap_out; unsigned long flags; unsigned long active_offs; long len, offs; int maxfrags; int occupied_bytes = (dmap->user_counter % dmap->fragment_size); *buf = dmap->raw_buf; if (!(maxfrags = DMAbuf_space_in_queue(dev)) && !occupied_bytes) return 0; save_flags(flags); cli(); #ifdef BE_CONSERVATIVE active_offs = dmap->byte_counter + dmap->qhead * dmap->fragment_size; #else active_offs = DMAbuf_get_buffer_pointer(dev, dmap, DMODE_OUTPUT); /* Check for pointer wrapping situation */ if (active_offs < 0 || active_offs >= dmap->bytes_in_use) active_offs = 0; active_offs += dmap->byte_counter; #endif offs = (dmap->user_counter % dmap->bytes_in_use) & ~SAMPLE_ROUNDUP; if (offs < 0 || offs >= dmap->bytes_in_use) { restore_flags(flags); printk(KERN_ERR "Sound: Got unexpected offs %ld. Giving up.\n", offs); printk("Counter = %ld, bytes=%d\n", dmap->user_counter, dmap->bytes_in_use); return 0; } *buf = dmap->raw_buf + offs; len = active_offs + dmap->bytes_in_use - dmap->user_counter; /* Number of unused bytes in buffer */ if ((offs + len) > dmap->bytes_in_use) len = dmap->bytes_in_use - offs; if (len < 0) { restore_flags(flags); return 0; } if (len > ((maxfrags * dmap->fragment_size) - occupied_bytes)) len = (maxfrags * dmap->fragment_size) - occupied_bytes; *size = len & ~SAMPLE_ROUNDUP; restore_flags(flags); return (*size > 0); }
static unsigned int poll_output(struct file * file, int dev, poll_table *wait) { struct audio_operations *adev = audio_devs[dev]; struct dma_buffparms *dmap = adev->dmap_out; if (!(adev->open_mode & OPEN_WRITE)) return 0; if (dmap->mapping_flags & DMA_MAP_MAPPED) { if (dmap->qlen) return POLLOUT | POLLWRNORM; return 0; } if (dmap->dma_mode == DMODE_INPUT) return 0; if (dmap->dma_mode == DMODE_NONE) return POLLOUT | POLLWRNORM; if (!DMAbuf_space_in_queue(dev)) return 0; return POLLOUT | POLLWRNORM; }