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

📄 dmabuf.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 3 页
字号:
		dmap = adev->dmap_out;		save_flags(flags);		cli();		if (dmap->qlen > 0 && !(dmap->flags & DMA_ACTIVE))			DMAbuf_launch_output(dev, dmap);		adev->dmap_out->flags |= DMA_SYNCING;		adev->dmap_out->underrun_count = 0;		while (!signal_pending(current) && n++ <= adev->dmap_out->nbufs && 		       adev->dmap_out->qlen && adev->dmap_out->underrun_count == 0) {			long t = dmabuf_timeout(dmap);			t = interruptible_sleep_on_timeout(&adev->out_sleeper,							   t);			if (!t) {				adev->dmap_out->flags &= ~DMA_SYNCING;				restore_flags(flags);				return adev->dmap_out->qlen;			}		}		adev->dmap_out->flags &= ~(DMA_SYNCING | DMA_ACTIVE);		restore_flags(flags);				/*		 * Some devices such as GUS have huge amount of on board RAM for the		 * audio data. We have to wait until the device has finished playing.		 */		save_flags(flags);		cli();		if (adev->d->local_qlen) {   /* Device has hidden buffers */			while (!signal_pending(current) &&			       adev->d->local_qlen(dev))				interruptible_sleep_on_timeout(&adev->out_sleeper,							       dmabuf_timeout(dmap));		}		restore_flags(flags);	}	adev->dmap_out->dma_mode = DMODE_NONE;	return adev->dmap_out->qlen;}int DMAbuf_release(int dev, int mode){	struct audio_operations *adev = audio_devs[dev];	unsigned long flags;	if (adev->open_mode & OPEN_WRITE)		adev->dmap_out->closing = 1;	if (adev->open_mode & OPEN_READ)		adev->dmap_in->closing = 1;	if (adev->open_mode & OPEN_WRITE)		if (!(adev->dmap_out->mapping_flags & DMA_MAP_MAPPED))			if (!signal_pending(current) && (adev->dmap_out->dma_mode == DMODE_OUTPUT))				DMAbuf_sync(dev);	if (adev->dmap_out->dma_mode == DMODE_OUTPUT)		memset(adev->dmap_out->raw_buf, adev->dmap_out->neutral_byte, adev->dmap_out->bytes_in_use);	save_flags(flags);	cli();	DMAbuf_reset(dev);	adev->d->close(dev);	if (adev->open_mode & OPEN_WRITE)		close_dmap(adev, adev->dmap_out);	if (adev->open_mode == OPEN_READ ||	    (adev->open_mode != OPEN_WRITE &&	     (adev->flags & DMA_DUPLEX)))		close_dmap(adev, adev->dmap_in);	adev->open_mode = 0;	restore_flags(flags);	return 0;}int DMAbuf_activate_recording(int dev, struct dma_buffparms *dmap){	struct audio_operations *adev = audio_devs[dev];	int  err;	if (!(adev->open_mode & OPEN_READ))		return 0;	if (!(adev->enable_bits & PCM_ENABLE_INPUT))		return 0;	if (dmap->dma_mode == DMODE_OUTPUT) {	/* Direction change */		DMAbuf_sync(dev);		DMAbuf_reset(dev);		dmap->dma_mode = DMODE_NONE;	}	if (!dmap->dma_mode) {		reorganize_buffers(dev, dmap, 1);		if ((err = adev->d->prepare_for_input(dev,				dmap->fragment_size, dmap->nbufs)) < 0)			return err;		dmap->dma_mode = DMODE_INPUT;	}	if (!(dmap->flags & DMA_ACTIVE)) {		if (dmap->needs_reorg)			reorganize_buffers(dev, dmap, 0);		local_start_dma(adev, dmap->raw_buf_phys, dmap->bytes_in_use, DMA_MODE_READ);		adev->d->start_input(dev, dmap->raw_buf_phys + dmap->qtail * dmap->fragment_size,				     dmap->fragment_size, 0);		dmap->flags |= DMA_ACTIVE;		if (adev->d->trigger)			adev->d->trigger(dev, adev->enable_bits * adev->go);	}	return 0;}int DMAbuf_getrdbuffer(int dev, char **buf, int *len, int dontblock){	struct audio_operations *adev = audio_devs[dev];	unsigned long flags;	int err = 0, n = 0;	struct dma_buffparms *dmap = adev->dmap_in;	int go;	if (!(adev->open_mode & OPEN_READ))		return -EIO;	if (dmap->needs_reorg)		reorganize_buffers(dev, dmap, 0);	save_flags(flags);	cli();	if (adev->dmap_in->mapping_flags & DMA_MAP_MAPPED) {/*		  printk(KERN_WARNING "Sound: Can't read from mmapped device (1)\n");*/		  restore_flags(flags);		  return -EINVAL;	} else while (dmap->qlen <= 0 && n++ < 10) {		long timeout = MAX_SCHEDULE_TIMEOUT;		if (!(adev->enable_bits & PCM_ENABLE_INPUT) || !adev->go) {			restore_flags(flags);			return -EAGAIN;		}		if ((err = DMAbuf_activate_recording(dev, dmap)) < 0) {			restore_flags(flags);			return err;		}		/* Wait for the next block */		if (dontblock) {			restore_flags(flags);			return -EAGAIN;		}		if ((go = adev->go))			timeout = dmabuf_timeout(dmap);		timeout = interruptible_sleep_on_timeout(&adev->in_sleeper,							 timeout);		if (!timeout) {			/* FIXME: include device name */			err = -EIO;			printk(KERN_WARNING "Sound: DMA (input) timed out - IRQ/DRQ config error?\n");			dma_reset_input(dev);		} else			err = -EINTR;	}	restore_flags(flags);	if (dmap->qlen <= 0)		return err ? err : -EINTR;	*buf = &dmap->raw_buf[dmap->qhead * dmap->fragment_size + dmap->counts[dmap->qhead]];	*len = dmap->fragment_size - dmap->counts[dmap->qhead];	return dmap->qhead;}int DMAbuf_rmchars(int dev, int buff_no, int c){	struct audio_operations *adev = audio_devs[dev];	struct dma_buffparms *dmap = adev->dmap_in;	int p = dmap->counts[dmap->qhead] + c;	if (dmap->mapping_flags & DMA_MAP_MAPPED)	{/*		  printk("Sound: Can't read from mmapped device (2)\n");*/		return -EINVAL;	}	else if (dmap->qlen <= 0)		return -EIO;	else if (p >= dmap->fragment_size) {  /* This buffer is completely empty */		dmap->counts[dmap->qhead] = 0;		dmap->qlen--;		dmap->qhead = (dmap->qhead + 1) % dmap->nbufs;	}	else dmap->counts[dmap->qhead] = p;	return 0;}int DMAbuf_get_buffer_pointer(int dev, struct dma_buffparms *dmap, int direction){	/*	 *	Try to approximate the active byte position of the DMA pointer within the	 *	buffer area as well as possible.	 */	int pos;	unsigned long flags;	unsigned long f;	save_flags(flags);	cli();	if (!(dmap->flags & DMA_ACTIVE))		pos = 0;	else {		int chan = dmap->dma;				f=claim_dma_lock();		clear_dma_ff(chan);				if(!isa_dma_bridge_buggy)			disable_dma(dmap->dma);				pos = get_dma_residue(chan);				pos = dmap->bytes_in_use - pos;		if (!(dmap->mapping_flags & DMA_MAP_MAPPED)) {			if (direction == DMODE_OUTPUT) {				if (dmap->qhead == 0)					if (pos > dmap->fragment_size)						pos = 0;			} else {				if (dmap->qtail == 0)					if (pos > dmap->fragment_size)						pos = 0;			}		}		if (pos < 0)			pos = 0;		if (pos >= dmap->bytes_in_use)			pos = 0;				if(!isa_dma_bridge_buggy)			enable_dma(dmap->dma);					release_dma_lock(f);	}	restore_flags(flags);	/* printk( "%04x ",  pos); */	return pos;}/* *	DMAbuf_start_devices() is called by the /dev/music driver to start *	one or more audio devices at desired moment. */void DMAbuf_start_devices(unsigned int devmask){	struct audio_operations *adev;	int dev;	for (dev = 0; dev < num_audiodevs; dev++) {		if (!(devmask & (1 << dev)))			continue;		if (!(adev = audio_devs[dev]))			continue;		if (adev->open_mode == 0)			continue;		if (adev->go)			continue;		/* OK to start the device */		adev->go = 1;		if (adev->d->trigger)			adev->d->trigger(dev,adev->enable_bits * adev->go);	}}int DMAbuf_space_in_queue(int dev){	struct audio_operations *adev = audio_devs[dev];	int len, max, tmp;	struct dma_buffparms *dmap = adev->dmap_out;	int lim = dmap->nbufs;	if (lim < 2)		lim = 2;	if (dmap->qlen >= lim)	/* No space at all */		return 0;	/*	 *	Verify that there are no more pending buffers than the limit	 *	defined by the process.	 */	max = dmap->max_fragments;	if (max > lim)		max = lim;	len = dmap->qlen;	if (adev->d->local_qlen) {		tmp = adev->d->local_qlen(dev);		if (tmp && len)			tmp--;	/* This buffer has been counted twice */		len += tmp;	}	if (dmap->byte_counter % dmap->fragment_size)	/* There is a partial fragment */		len = len + 1;	if (len >= max)		return 0;	return max - len;}static int output_sleep(int dev, int dontblock){	struct audio_operations *adev = audio_devs[dev];	int err = 0;	struct dma_buffparms *dmap = adev->dmap_out;	long timeout;	long timeout_value;	if (dontblock)		return -EAGAIN;	if (!(adev->enable_bits & PCM_ENABLE_OUTPUT))		return -EAGAIN;	/*	 * Wait for free space	 */	if (signal_pending(current))		return -EINTR;	timeout = (adev->go && !(dmap->flags & DMA_NOTIMEOUT));	if (timeout) 		timeout_value = dmabuf_timeout(dmap);	else		timeout_value = MAX_SCHEDULE_TIMEOUT;	timeout_value = interruptible_sleep_on_timeout(&adev->out_sleeper,						       timeout_value);	if (timeout != MAX_SCHEDULE_TIMEOUT && !timeout_value) {		printk(KERN_WARNING "Sound: DMA (output) timed out - IRQ/DRQ config error?\n");		dma_reset_output(dev);	} else {		if (signal_pending(current))			err = -EINTR;	}	return err;}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);}int DMAbuf_getwrbuffer(int dev, char **buf, int *size, int dontblock){	struct audio_operations *adev = audio_devs[dev];	unsigned long flags;	int err = -EIO;	struct dma_buffparms *dmap = adev->dmap_out;	if (dmap->needs_reorg)		reorganize_buffers(dev, dmap, 0);	if (dmap->mapping_flags & DMA_MAP_MAPPED) {/*		printk(KERN_DEBUG "Sound: Can't write to mmapped device (3)\n");*/		return -EINVAL;	}	if (dmap->dma_mode == DMODE_INPUT) {	/* Direction change */		DMAbuf_reset(dev);		dmap->dma_mode = DMODE_NONE;	}	dmap->dma_mode = DMODE_OUTPUT;	save_flags(flags);	cli();	while (find_output_space(dev, buf, size) <= 0) {		if ((err = output_sleep(dev, dontblock)) < 0) {			restore_flags(flags);			return err;		}	}	restore_flags(flags);	return 0;}int DMAbuf_move_wrpointer(int dev, int l){	struct audio_operations *adev = audio_devs[dev];	struct dma_buffparms *dmap = adev->dmap_out;	unsigned long ptr = (dmap->user_counter / dmap->fragment_size) * dmap->fragment_size;	unsigned long end_ptr, p;	int post = (dmap->flags & DMA_POST);	dmap->flags &= ~DMA_POST;	dmap->cfrag = -1;

⌨️ 快捷键说明

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