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

📄 dma_ep93xx.c

📁 一个2.4.21版本的嵌入式linux内核
💻 C
📖 第 1 页 / 共 5 页
字号:
	case NFB:		dma_m2m_next_frame_buffer(dma);		break;	/*	 *  Done interrupt generated, indicating that the transfer is complete.	 */	case DONE:		dma_m2m_transfer_done(dma);		break;	default:		break;	}	if ((dma_int != UNDEF_INT) && dma->callback)		dma->callback(dma_int, dma->device, dma->user_data);}/***************************************************************************** * * dma_m2p_irq_handler * * * ****************************************************************************/static voiddma_m2p_irq_handler(int irq, void *dev_id, struct pt_regs *regs){	ep93xx_dma_t *dma = (ep93xx_dma_t *) dev_id;	unsigned int M2P_reg_base = dma->reg_base;	unsigned int read_back;	ep93xx_dma_dev_t dma_int = UNDEF_INT;	unsigned int loop, uiCONTROL, uiINTERRUPT;	/*	 *  Determine what kind of dma interrupt this is.	 */	if ( inl(M2P_reg_base+M2P_OFFSET_INTERRUPT) & INTERRUPT_M2P_STALLINT )		dma_int = STALL;	else if ( inl(M2P_reg_base+M2P_OFFSET_INTERRUPT) & INTERRUPT_M2P_NFBINT )		dma_int = NFB;	else if ( inl(M2P_reg_base+M2P_OFFSET_INTERRUPT) & INTERRUPT_M2P_CHERRORINT )		dma_int = CHERROR;	/*	 *  Stall Interrupt: The Channel is stalled, meaning nothing is	 *  programmed to transfer right now.  So, we're back to the	 *  beginnning.  If there's a buffer to transfer, program it into	 *  max and base 0 registers.	 */	if (dma_int == STALL) {		DPRINTK("1  ");		if (dma->total_buffers) {			/*			 * The current_buffer has already been tranfered, so			 * add the byte count to the total_bytes field.			 */			dma->total_bytes = dma->total_bytes +				dma->buffer_queue[dma->current_buffer].size;			/*			 *  Mark the current_buffer as used.			 */			dma->buffer_queue[dma->current_buffer].used = TRUE;			/*			 *  Increment the used buffer counter			 */			dma->used_buffers++;			DPRINTK("#%d", dma->current_buffer);			/*			 *  Increment the current_buffer			 */			dma->current_buffer = (dma->current_buffer + 1) %					      MAX_EP93XX_DMA_BUFFERS;			/*			 *  check if there's a new buffer to transfer.			 */			if (dma->new_buffers && dma->xfer_enable) {				/*				 * We have a new buffer to transfer so program				 * in the buffer values.  Since a STALL				 * interrupt was triggered, we program the				 * base0 and maxcnt0				 *				 * Set the MAXCNT0 register with the buffer				 * size				 */				outl( dma->buffer_queue[dma->current_buffer].size,					  M2P_reg_base+M2P_OFFSET_MAXCNT0 );				/*				 * Set the BASE0 register with the buffer base				 * address				 */				outl( dma->buffer_queue[dma->current_buffer].source,					  M2P_reg_base+M2P_OFFSET_BASE0 );				/*				 *  Decrement the new buffer counter				 */				dma->new_buffers--;				if (dma->new_buffers) {					DPRINTK("A  ");					/*					 * Set the MAXCNT1 register with the					 * buffer size					 */					outl( dma->buffer_queue[(dma->current_buffer + 1) %											MAX_EP93XX_DMA_BUFFERS].size,						  M2P_reg_base+M2P_OFFSET_MAXCNT1 );					/*					 * Set the BASE1 register with the					 * buffer base address					 */					outl( dma->buffer_queue[dma->current_buffer + 1 %											MAX_EP93XX_DMA_BUFFERS].source,						  M2P_reg_base+M2P_OFFSET_BASE1 );					/*					 *  Decrement the new buffer counter					 */					dma->new_buffers--;					/*					 *  Enable the NFB Interrupt.					 */					uiCONTROL = inl(M2P_reg_base+M2P_OFFSET_CONTROL);					uiCONTROL |= CONTROL_M2P_NFBINTEN;					outl( uiCONTROL, M2P_reg_base+M2P_OFFSET_CONTROL );				}			} else {				/*				 *  No new buffers.				 */				DPRINTK("2 \n");				/*				 *  There's a chance we setup both buffer descriptors, but				 *  didn't service the NFB quickly enough, causing the channel				 *  to transfer both buffers, then enter the stall state.				 *  So, we need to be able to process the second buffer.				 */				if ((dma->used_buffers + dma->new_buffers) < dma->total_buffers) {					DPRINTK("3 ");					/*					 *  The current_buffer has already been tranfered, so add the					 *  byte count to the total_bytes field.					 */					dma->total_bytes = dma->total_bytes +						dma->buffer_queue[dma->current_buffer].size;					/*					 *  Mark the current_buffer as used.					 */					dma->buffer_queue[dma->current_buffer].used = TRUE;					/*					 *  Increment the used buffer counter					 */					dma->used_buffers++;					DPRINTK("#%d", dma->current_buffer);					/*					 *  Increment the current buffer pointer.					 */					dma->current_buffer = (dma->current_buffer + 1) %						MAX_EP93XX_DMA_BUFFERS;				}				/*				 *  No new buffers to transfer, so disable the channel.				 */				uiCONTROL = inl(M2P_reg_base+M2P_OFFSET_CONTROL);				uiCONTROL &= ~CONTROL_M2P_ENABLE;				outl( uiCONTROL, M2P_reg_base+M2P_OFFSET_CONTROL );				/*				 *  Indicate that this channel is in the pause by starvation				 *  state by setting the pause bit to true.				 */				dma->pause = TRUE;				DPRINTK("STATUS - 0x%x \n",	 inl(M2P_reg_base+M2P_OFFSET_STATUS) );				DPRINTK("CONTROL - 0x%x \n",	inl(M2P_reg_base+M2P_OFFSET_CONTROL) );				DPRINTK("REMAIN - 0x%x \n",	 inl(M2P_reg_base+M2P_OFFSET_REMAIN) );				DPRINTK("PPALLOC - 0x%x \n",	inl(M2P_reg_base+M2P_OFFSET_PPALLOC) );				DPRINTK("BASE0 - 0x%x \n",	  inl(M2P_reg_base+M2P_OFFSET_BASE0) );				DPRINTK("MAXCNT0 - 0x%x \n",	inl(M2P_reg_base+M2P_OFFSET_MAXCNT0) );				DPRINTK("CURRENT0 - 0x%x \n",   inl(M2P_reg_base+M2P_OFFSET_CURRENT0) );				DPRINTK("BASE1 - 0x%x \n",	  inl(M2P_reg_base+M2P_OFFSET_BASE1) );				DPRINTK("MAXCNT1 - 0x%x \n",	inl(M2P_reg_base+M2P_OFFSET_MAXCNT1) );				DPRINTK("CURRENT1 - 0x%x \n",   inl(M2P_reg_base+M2P_OFFSET_CURRENT1) );				DPRINTK("Buffer	buf_id	 source	   size	   last	   used \n");				for (loop = 0; loop < 32; loop ++)					DPRINTK("%d		0x%x		0x%x		 0x%x		%d		 %d \n",							loop, dma->buffer_queue[loop].buf_id, dma->buffer_queue[loop].source,							dma->buffer_queue[loop].size,							dma->buffer_queue[loop].last, dma->buffer_queue[loop].used);				DPRINTK("pause	 0x%x		0x%x		 0x%x		%d		 %d \n",						dma->pause_buf.buf_id, dma->pause_buf.source, dma->pause_buf.size,						dma->pause_buf.last, dma->pause_buf.used);				DPRINTK("Pause - %d \n", dma->pause);				DPRINTK("xfer_enable - %d \n", dma->xfer_enable);				DPRINTK("total bytes - 0x%x \n", dma->total_bytes);				DPRINTK("total buffer - %d \n", dma->total_buffers);				DPRINTK("new buffers - %d \n", dma->new_buffers);				DPRINTK("current buffer - %d \n", dma->current_buffer);				DPRINTK("last buffer - %d \n", dma->last_buffer);				DPRINTK("used buffers - %d \n", dma->used_buffers);				DPRINTK("callback addr - 0x%p \n", dma->callback);			}		} else {			/*			 *  No buffers to transfer, or old buffers to mark as used,			 *  so Disable the channel			 */			uiCONTROL = inl(M2P_reg_base+M2P_OFFSET_CONTROL);			uiCONTROL &= ~CONTROL_M2P_ENABLE;			outl( uiCONTROL, M2P_reg_base+M2P_OFFSET_CONTROL );			/*			 *  Must read the control register back after a write.			 */			read_back = inl(M2P_reg_base+M2P_OFFSET_CONTROL);			/*			 *  Indicate that this channel is in the pause by			 *  starvation state by setting the pause bit to true.			 */			dma->pause = TRUE;		}	}	/*	 *  Next Frame Buffer Interrupt.  If there's a new buffer program it	 *  Check if this is the last buffer in the transfer,	 *  and if it is, disable the NFB int to prevent being	 *  interrupted for another buffer when we know there won't be	 *  another.	 */	if (dma_int == NFB) {		DPRINTK("5  ");		if (dma->total_buffers) {			DPRINTK("6  ");			/*			 *  The iCurrentBuffer has already been transfered.  so add the			 *  byte count from the current buffer to the total byte count.			 */			dma->total_bytes = dma->total_bytes +				dma->buffer_queue[dma->current_buffer].size;			/*			 *  Mark the Current Buffer as used.			 */			dma->buffer_queue[dma->current_buffer].used = TRUE;			/*			 *  Increment the used buffer counter			 */			dma->used_buffers++;			DPRINTK("#%d", dma->current_buffer);			if ((dma->buffer_queue[			    (dma->current_buffer + 1) % MAX_EP93XX_DMA_BUFFERS].last) ||			    (dma->new_buffers == 0) || (dma->xfer_enable == FALSE)) {				DPRINTK("7  ");				/*				 *  This is the last Buffer in this transaction, so disable				 *  the NFB interrupt.  We shouldn't get an NFB int when the				 *  FSM moves to the ON state where it would typically get the				 *  NFB int indicating a new buffer can be programmed.				 *  Instead, once in the ON state, the DMA will just proceed				 *  to complet the transfer of the current buffer, move the				 *  FSB directly to the STALL state where a STALL interrupt				 *  will be generated.				 */				uiCONTROL = inl(M2P_reg_base+M2P_OFFSET_CONTROL);				uiCONTROL &= ~CONTROL_M2P_NFBINTEN;				outl( uiCONTROL, M2P_reg_base+M2P_OFFSET_CONTROL );				/*				 *  The current buffer has been transferred, so increment				 *  the current buffer counter to reflect this.				 */				dma->current_buffer = (dma->current_buffer + 1) % MAX_EP93XX_DMA_BUFFERS;				DPRINTK("End of NFB handling. \n");				DPRINTK("STATUS - 0x%x \n",	 inl(M2P_reg_base+M2P_OFFSET_STATUS) );				DPRINTK("CONTROL - 0x%x \n",	inl(M2P_reg_base+M2P_OFFSET_CONTROL) );				DPRINTK("REMAIN - 0x%x \n",	 inl(M2P_reg_base+M2P_OFFSET_REMAIN) );				DPRINTK("PPALLOC - 0x%x \n",	inl(M2P_reg_base+M2P_OFFSET_PPALLOC) );				DPRINTK("BASE0 - 0x%x \n",	  inl(M2P_reg_base+M2P_OFFSET_BASE0) );				DPRINTK("MAXCNT0 - 0x%x \n",	inl(M2P_reg_base+M2P_OFFSET_MAXCNT0) );				DPRINTK("CURRENT0 - 0x%x \n",   inl(M2P_reg_base+M2P_OFFSET_CURRENT0) );				DPRINTK("BASE1 - 0x%x \n",	  inl(M2P_reg_base+M2P_OFFSET_BASE1) );				DPRINTK("MAXCNT1 - 0x%x \n",	inl(M2P_reg_base+M2P_OFFSET_MAXCNT1) );				DPRINTK("CURRENT1 - 0x%x \n",   inl(M2P_reg_base+M2P_OFFSET_CURRENT1) );				DPRINTK("Buffer	buf_id	 source	   size	   last	   used \n");				for (loop = 0; loop < 32; loop ++)					DPRINTK("%d		0x%x		0x%x		 0x%x		%d		 %d \n",							loop, dma->buffer_queue[loop].buf_id, dma->buffer_queue[loop].source,							dma->buffer_queue[loop].size,							dma->buffer_queue[loop].last, dma->buffer_queue[loop].used);				DPRINTK("pause	 0x%x		0x%x		 0x%x		%d		 %d \n",						dma->pause_buf.buf_id, dma->pause_buf.source, dma->pause_buf.size,						dma->pause_buf.last, dma->pause_buf.used);				DPRINTK("Pause - %d \n", dma->pause);				DPRINTK("xfer_enable - %d \n", dma->xfer_enable);				DPRINTK("total bytes - 0x%x \n", dma->total_bytes);				DPRINTK("total buffer - %d \n", dma->total_buffers);				DPRINTK("new buffers - %d \n", dma->new_buffers);				DPRINTK("current buffer - %d \n", dma->current_buffer);				DPRINTK("last buffer - %d \n", dma->last_buffer);				DPRINTK("used buffers - %d \n", dma->used_buffers);				DPRINTK("callback addr - 0x%p \n", dma->callback);			} else if (dma->new_buffers) {				DPRINTK("8  ");				/*				 *  we have a new buffer, so increment the current buffer to				 *  point to the next buffer, which is already programmed into				 *  the DMA. Next time around, it'll be pointing to the				 *  current buffer.				 */				dma->current_buffer = (dma->current_buffer + 1) % MAX_EP93XX_DMA_BUFFERS;				/*				 *  we know we have a new buffer to program as the next				 *  buffer, so check which set of MAXCNT and BASE registers				 *  to program.				 */				if ( inl(M2P_reg_base+M2P_OFFSET_STATUS) & STATUS_M2P_NEXTBUFFER ) {					/*					 *  Set the MAXCNT1 register with the buffer size					 */					outl( dma->buffer_queue[					      (dma->current_buffer + 1) % MAX_EP93XX_DMA_BUFFERS].size,					      M2P_reg_base+M2P_OFFSET_MAXCNT1 );					/*					 *  Set the BASE1 register with the buffer base address					 */					outl( dma->buffer_queue[					      (dma->current_buffer + 1) % MAX_EP93XX_DMA_BUFFERS].source,					      M2P_reg_base+M2P_OFFSET_BASE1 );				} else {					/*					 *  Set the MAXCNT0 register with the buffer size					 */					outl( dma->buffer_queue[					      (dma->current_buffer + 1) % MAX_EP93XX_DMA_BUFFERS].size,					       M2P_reg_base+M2P_OFFSET_MAXCNT0 );					/*					 *  Set the BASE0 register with the buffer base address					 */					outl( dma->buffer_queue[					      (dma->current_buffer + 1) % MAX_EP93XX_DMA_BUFFERS].source,					      M2P_reg_base+M2P_OFFSET_BASE0 );				}				/*				 *  Decrement the new buffers counter				 */				dma->new_buffers--;			}		} else {			/*			 *  Total number of buffers is 0 - really we should never get here,			 *  but just in case.			 */			DPRINTK("9 \n");			/*			 *  No new buffers to transfer, so Disable the channel			 */			uiCONTROL = inl(M2P_reg_base+M2P_OFFSET_CONTROL);			uiCONTROL &= ~CONTROL_M2P_ENABLE;			outl( uiCONTROL, M2P_reg_base+M2P_OFFSET_CONTROL );		}	}	/*	 *  Channel Error Interrupt, or perhipheral interrupt, specific to the	 *  memory to/from peripheral channels.	 */	if (dma_int == CHERROR) {		/*		 *  just clear the interrupt, it's really up to the peripheral		 *  driver to determine if any further action is necessary.		 */		uiINTERRUPT = inl(M2P_reg_base+M2P_OFFSET_INTERRUPT);		uiINTERRUPT &= ~INTERRUPT_M2P_CHERRORINT;		outl( uiINTERRUPT, M2P_reg_base+M2P_OFFSET_INTERRUPT );	}	/*	 *  Make sure the interrupt was valid, and if it was, then check	 *  if a callback function was installed for this DMA channel.  If a	 *  callback was installed call it.	 */	if ((dma_int != UNDEF_INT) && dma->callback)		dma->callback(dma_int, dma->device, dma->user_data);}/***************************************************************************** * * ep9312_dma_open_m2p(int device) * * Description: This function will attempt to open a M2P/P2M DMA channel. *			  If the open is successful, the channel number is returned, *			  otherwise a negative number is returned. * * Parameters: *  device:	 device for which the dma channel is requested. * ****************************************************************************/static intdma_open_m2p(int device){	int channel = -1;	unsigned int loop;	unsigned int M2P_reg_base;	unsigned int uiPWRCNT;	unsigned long flags;	DPRINTK("DMA Open M2P with hw dev %d\n", device);	/*	 *  Lock the dma channel list.	 */	spin_lock_irqsave(&dma_list_lock, flags);	DPRINTK("1\n");	/*	 * Verify that the device requesting DMA isn't already using a DMA channel	 */	if (device >= 10)		loop = 1;		 // Rx transfer requested	else		loop = 0;		 // Tx transfer requested	for (; loop < 10; loop = loop + 2)		/*		 *  Before checking for a matching device, check that the		 *  channel is in use, otherwise the device field is		 *  invalid.		 */		if (dma_chan[loop].ref_count)			if (device == dma_chan[loop].device) {				DPRINTK("DMA Open M2P - Error\n");				return(-1);			}	/*	 *  Get a DMA channel instance for the given hardware device.	 *  If this is a TX look for even numbered channels, else look for	 *  odd numbered channels	 */	if (device >= 10)		loop = 1;		 /* Rx transfer requested */	else		loop = 0;		 /* Tx transfer requested */

⌨️ 快捷键说明

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