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

📄 dma_ep93xx.c

📁 一个2.4.21版本的嵌入式linux内核
💻 C
📖 第 1 页 / 共 5 页
字号:
 *  last:	   1 if this is the last buffer in this stream, 0 otherwise. * ****************************************************************************/intep93xx_dma_add_buffer(int handle, unsigned int source, unsigned int dest,		      unsigned int size, unsigned int last,		      unsigned int buf_id){	unsigned int flags;	ep93xx_dma_t * dma;	int  channel;	/*	 *  Get the DMA hw channel # from the handle.	 */	channel = dma_get_channel_from_handle(handle);	/*	 *  See if this is a valid handle.	 */	if (channel < 0) {		printk(KERN_ERR			   "DMA Add Buffer: Invalid dma handle.\n");		return(-EINVAL);	}	/*	 *  Get a pointer to the dma instance.	 */	dma = &dma_chan[channel];	/*	 *  Mask interrupts and hold on to the original state.	 */	local_irq_save(flags);	/*	 *  If the buffer queue is full, last_buffer is the same as current_buffer and	 *  we're not tranfering, or last_buffer is pointing to a used buffer, then exit.	 *  TODO: do I need to do any more checks?	 */	if (dma->total_buffers >= MAX_EP93XX_DMA_BUFFERS) {		/*		 *  Restore the state of the irqs		 */		local_irq_restore(flags);		/*		 *  Fail.		 */		return(-1);	}	/*	 *  Add this buffer to the queue	 */	dma->buffer_queue[dma->last_buffer].source = source;	dma->buffer_queue[dma->last_buffer].dest = dest;	dma->buffer_queue[dma->last_buffer].size = size;	dma->buffer_queue[dma->last_buffer].last = last;	dma->buffer_queue[dma->last_buffer].buf_id = buf_id;	/*	 *  Reset the used field of the buffer structure.	 */	dma->buffer_queue[dma->last_buffer].used = FALSE;	/*	 *  Increment the End Item Pointer.	 */	dma->last_buffer = (dma->last_buffer + 1) % MAX_EP93XX_DMA_BUFFERS;	/*	 *  Increment the new buffers counter and the total buffers counter	 */	dma->new_buffers++;	dma->total_buffers++;	/*	 *  restore the interrupt state.	 */	local_irq_restore(flags);	/*	 *  Check if the channel was starved into a stopped state.	 */	if (dma->pause && dma->xfer_enable) {		if (dma->new_buffers >= 1) {			DPRINTK("DMA - calling start from add after starve. \n");			/*			 *  The channel was starved into a stopped state, and we've got			 *  2 new buffers, so start tranferring again.			 */			ep93xx_dma_start(handle, 1, 0);		}	}	/*	 *  Success.	 */	return(0);}/***************************************************************************** * *  int ep93xx_dma_remove_buffer(int handle, unsigned int * address, *								unsigned int * size) * *  Description: Remove a buffer entry from the DMA buffer queue. If *			   buffer was removed successfully, return 0, otherwise *			   return -1. * *  handle:	 handle for the channel to remove a buffer from. *  address:	Pointer to an integer which is filled in with the start *			  address of the removed buffer. *  size:	   Pointer to an integer which is filled in with the size in *			  bytes of the removed buffer. * ****************************************************************************/intep93xx_dma_remove_buffer(int handle, unsigned int * buf_id){	unsigned int test;	unsigned int loop;	int return_val = -1;	unsigned int flags;	ep93xx_dma_t *dma;	int  channel;	/*	 *  Get the DMA hw channel # from the handle.	 */	channel = dma_get_channel_from_handle(handle);	/*	 *  See if this is a valid handle.	 */	if (channel < 0) {		printk(KERN_ERR			   "DMA Remove Buffer: Invalid dma handle.\n");		return(-EINVAL);	}	dma = &dma_chan[channel];	/*	 *  Mask interrupts and hold on to the original state.	 */	local_irq_save(flags);	/*	 *  Make sure there are used buffers to be returned.	 */	if (dma->used_buffers) {		test = dma->last_buffer;		for (loop = 0; loop < MAX_EP93XX_DMA_BUFFERS; loop++) {			if (dma->buffer_queue[test].used && (dma->buffer_queue[test].buf_id != -1)) {				/*DPRINTK("buffer %d used \n", test); */				/*				 *  This is a used buffer, fill in the buf_id pointer				 *  with the buf_id for this buffer.				 */				*buf_id = dma->buffer_queue[test].buf_id;				/*				 *  Reset this buffer structure				 */				dma->buffer_queue[test].buf_id = -1;				/*				 *  Decrement the used buffer counter, and the total buffer counter.				 */				dma->used_buffers--;				dma->total_buffers--;				/*				 *  Successful removal of a buffer, so set the return				 *  value to 0, then exit this loop.				 */				return_val = 0;				break;			}			/*			 *  This buffer isn't used, let's see if the next one is.			 */			test = (test + 1) % MAX_EP93XX_DMA_BUFFERS;		}	}	/*	 *  Restore interrupts.	 */	local_irq_restore(flags);	/*	 *  Success.	 */	return(return_val);}/***************************************************************************** * *  int ep93xx_dma_pause(int handle, unsigned int channels, *					   unsigned int * handles) * *  Description: Disable any ongoing transfer for the given channel, retaining *			   the state of the current buffer transaction so that upon *			   resume, the dma will continue where it left off. * *  handle:	 Handle for the channel to be paused.  If this is a pause for *			  for multiple channels, handle is a valid handle for one of *			  the channels to be paused. *  channels:   number of channel to pause transfers on. *  handles:	Pointer to an array of handles, one for each channel which *			  to be paused.  If this pause is intended only for one *			  channel, this field should be set to NULL. * ****************************************************************************/intep93xx_dma_pause(int handle, unsigned int channels, unsigned int * handles){	unsigned int flags;	ep93xx_dma_t * dma;	int channel;	DPRINTK("ep93xx_dma_pause \n");	/*	 *  Mask interrupts and hold on to the original state.	 */	local_irq_save(flags);	/*	 *  Get the DMA hw channel # from the handle.	 */	channel = dma_get_channel_from_handle(handle);	/*	 *  See if this is a valid handle.	 */	if (channel < 0) {		/*		 *  restore interrupts.		 */		local_irq_restore(flags);		printk(KERN_ERR			   "DMA Pause: Invalid dma handle.\n");		/*		 *  Fail.		 */		return(-EINVAL);	}	DPRINTK("DMA %d: pause \n", channel);	/*	 *  Set up a pointer to the dma instance data.	 */	dma = &dma_chan[channel];	/*	 *  Check if we're already paused.	 */	if (dma->pause) {		/*		 *  We're paused, but are we stopped?		 */		if (dma->xfer_enable)			/*			 *  Put the channel in the stopped state.			 */			dma->xfer_enable = FALSE;		DPRINTK("DMA Pause - already paused.");	} else {		/*		 *  Put the channel into the stopped state.		 */		dma->xfer_enable = FALSE;		dma->pause = TRUE;	}	/*	 *  restore interrupts.	 */	local_irq_restore(flags);	/*	 *  Already paused, so exit.	 */	return(0);}/***************************************************************************** * *  void ep93xx_dma_flush(int handle) * *  Description: Flushes all queued buffers and transfers in progress *			   for the given channel.  Return the buffer entries *			   to the calling function. * *  handle:	 handle for the channel for which the flush is intended. * ****************************************************************************/intep93xx_dma_flush(int handle){	unsigned int loop, flags;	ep93xx_dma_t * dma;	int  channel;	unsigned int M2P_reg_base;	/*	 *  Get the DMA hw channel # from the handle.	 */	channel = dma_get_channel_from_handle(handle);	/*	 *  See if this is a valid handle.	 */	if (channel < 0) {		printk(KERN_ERR "DMA Flush: Invalid dma handle.\n");		return(-EINVAL);	}	DPRINTK("DMA %d: flush \n", channel);	/*	 *  Set up a pointer to the dma instance data for this channel	 */	dma = &dma_chan[channel];	/*	 *  Mask interrupts and hold on to the original state.	 */	local_irq_save(flags);	for (loop = 0; loop < MAX_EP93XX_DMA_BUFFERS; loop++)		dma->buffer_queue[loop].buf_id = -1;	/*	 *  Set the Current and Last item to zero.	 */	dma->current_buffer = 0;	dma->last_buffer = 0;	/*	 *  Reset the Buffer counters	 */	dma->used_buffers = 0;	dma->new_buffers = 0;	dma->total_buffers = 0;	/*	 *  reset the Total bytes counter.	 */	dma->total_bytes = 0;	M2P_reg_base = dma_chan[channel].reg_base;	/*	 *  restore interrupts.	 */	local_irq_restore(flags);	/*	 *  Success.	 */	return(0);}/***************************************************************************** * *  int ep93xx_dma_queue_full(int handle) * *  Description: Query to determine if the DMA queue of buffers for *			  a given channel is full. *			  0 = queue is full *			  1 = queue is not full * *  handle:	 handle for the channel to query. * ****************************************************************************/intep93xx_dma_queue_full(int handle){	int list_full = 0;	unsigned int flags;	int  channel;	/*	 *  Get the DMA hw channel # from the handle.	 */	channel = dma_get_channel_from_handle(handle);	/*	 *  See if this is a valid handle.	 */	if (channel < 0) {		printk(KERN_ERR "DMA Queue Full: Invalid dma handle.\n");		return(-EINVAL);	}	DPRINTK("DMA %d: queue full \n", channel);	/*	 *  Mask interrupts and hold on to the original state.	 */	local_irq_save(flags);	/*	 *  If the last item is equal to the used item then	 *  the queue is full.	 */	if (dma_chan[channel].total_buffers < MAX_EP93XX_DMA_BUFFERS)		list_full =  FALSE;	else		list_full = TRUE;	/*	 *  restore interrupts.	 */	local_irq_restore(flags);	return(list_full);}/***************************************************************************** * *  int ep93xx_dma_get_position() * *  Description:  Takes two integer pointers and fills them with the start *                and current address of the buffer currently transferring *                on the specified DMA channel. * *  handle         handle for the channel to query. *  *buf_id        buffer id for the current buffer transferring on the *                 dma channel. *  *total         total bytes transferred on the channel.  Only counts   *                 whole buffers transferred. *  *current_frac  number of bytes transferred so far in the current buffer. ****************************************************************************/intep93xx_dma_get_position(int handle, unsigned int * buf_id,                        unsigned int * total, unsigned int * current_frac ){	int  channel;	ep93xx_dma_t * dma;	unsigned int buf_id1, total1, current_frac1, buf_id2, total2;	unsigned int Status, NextBuffer, StateIsBufNext, M2P_reg_base=0;	unsigned int pause1, pause2;	/*	 *  Get the DMA hw channel # from the handle.  See if this is a 	 *  valid handle.	 */	channel = dma_get_channel_from_handle(handle);	if (channel < 0) {		printk(KERN_ERR "DMA Get Position: Invalid dma handle.\n");		return(-EINVAL);	}	dma = &dma_chan[channel];	/*	 * If DMA moves to a new buffer in the middle of us grabbing the 	 * buffer info, then do it over again.	 */	do{		buf_id1 = dma->buffer_queue[dm

⌨️ 快捷键说明

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