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

📄 dp_hardware_dispatcher.c

📁 Lido PXA270平台开发板的最新BSP,包括源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
 *													DMA Engine action since the last time this
 *													function was called and (b.) the queueing and
 *													submission of new buffers.
 *
 * Description    : This function is used to submit a new queue of DP_QueuedMemoryWrite structures 
 *					to the DMA engine. A queue should contain the hardware accesses comprising a 
 *					single action (i.e.: writes which all need to occur at the same time. This
 *					function is a direct interpretation of the state machine shown in figure 8 of 
 *					the API specification.								
 *
 ***********************************************************************************************/

DP_VOID		DP_QueueNewDMABuffer		(	DP_pQueuedFieldWrite		pasQueueToSubmit,	
											DP_UINT_8					ui8LengthOfQueue	)
	/* pasQueueToSubmit -  Pointer to the start of the queue									*/
	/* ui8LengthOfQueue	-  Number of write structures in the queue								*/
{
DP_pQueuedMemoryWrite		psAddressOfCurrentlyPendingBuffer;
DP_pQueuedMemoryWrite		psAddressOfCurrentStatusBuffer;
DP_BOOL						bCurrentStatusFlag;
DP_BOOL						bCurrentValidFlag;
DP_INT_8					i8PendingBuffer;
DP_INT_8					i8StatusBuffer;
DP_UINT_8					ui8SizeOfNewBuffer;
DP_UINT_16					ui16i, ui16j;
DP_BOOL						bBufferToBeFreed	[2];
DP_INT_8					i8BufferToUse	= -1;

#if defined DP_SIMULATION_MODE
DP_BOOL						bProblem;

	printf ( "DP_QueueNewDMABuffer \n" );

#endif


	/* Obtain the latest values for 'Pending buffer', 'Status buffer' and 'Status flag'			*/
	/* Note : ALL references to buffer addresses must include the current offset.				*/
	psAddressOfCurrentlyPendingBuffer	= (DP_pQueuedMemoryWrite)	DP_ReadFieldFromHardware ( &DP_asGlobalFieldTargets [ DP_GLOBAL_FIELD_HARDWARE_DISPATCHER_PENDING_ADDRESS ] );

	#if defined	PCI_BRIDGE_SIM
		/* Adjust for windows linear address space, by adding the value read from hardware	*/
		/* as an offset to the PCI memory mapped region.									*/
		psAddressOfCurrentlyPendingBuffer = ((DP_pQueuedMemoryWrite) DP_pSharedMemory) + (((DP_UINT_32) psAddressOfCurrentlyPendingBuffer) / sizeof (DP_QueuedMemoryWrite));
	#endif

	psAddressOfCurrentStatusBuffer		= (DP_pQueuedMemoryWrite)	DP_ReadFieldFromHardware ( &DP_asGlobalFieldTargets [ DP_GLOBAL_FIELD_HARDWARE_DISPATCHER_STATUS_ADDRESS ] );

	#if defined	PCI_BRIDGE_SIM
		/* Adjust for windows linear address space, by adding the value read from hardware	*/
		/* as an offset to the PCI memory mapped region.									*/
		psAddressOfCurrentStatusBuffer = ((DP_pQueuedMemoryWrite) DP_pSharedMemory) + (((DP_UINT_32) psAddressOfCurrentStatusBuffer) / sizeof (DP_QueuedMemoryWrite));
	#endif

	bCurrentStatusFlag					= (DP_BOOL)					(DP_ReadFieldFromHardware ( &DP_asGlobalFieldTargets [ DP_GLOBAL_FIELD_HARDWARE_DISPATCHER_STATUS_FLAG ] ) & 0x01);
	bCurrentValidFlag					= (DP_BOOL)					(DP_ReadFieldFromHardware ( &DP_asGlobalFieldTargets [ DP_GLOBAL_FIELD_HARDWARE_DISPATCHER_PENDING_ADDRESS_VALID_FLAG ] ) & 0x01);

	/* Establish the identities of the current 'Pending' and 'Status' buffers					*/
	/* e.g.: Pending = buffer 1, Status = buffer 0.												*/

	/* Identity of pending buffer																*/
	if ( psAddressOfCurrentlyPendingBuffer == &(DP_DispatcherBuffers [DP_ui8DispatcherBufferOffset [0]]) )
	{
		/* Buffer 0 is currently pending */
		i8PendingBuffer = 0;
	}
	else if ( psAddressOfCurrentlyPendingBuffer == &(DP_DispatcherBuffers [DP_SIZE_OF_DISPATCHER_BUFFER_IN_ENTRIES + DP_ui8DispatcherBufferOffset [1]]))
	{
		/* Buffer 1 is currently pending */
		i8PendingBuffer = 1;
	}
	else
	{
		/* The 'Pending buffer' register isn't pointing to a proper buffer, so just				*/
		/* ignore it.																			*/
		i8PendingBuffer = -1;
	}

	/* Identity of statusbuffer																	*/
	if ( psAddressOfCurrentStatusBuffer == &(DP_DispatcherBuffers [DP_ui8DispatcherBufferOffset [0]])  )
	{
		/* Buffer 0 is currently listed in status register */
		i8StatusBuffer = 0;
	}
	else if ( psAddressOfCurrentStatusBuffer == &(DP_DispatcherBuffers [DP_SIZE_OF_DISPATCHER_BUFFER_IN_ENTRIES + DP_ui8DispatcherBufferOffset [1]]))
	{
		/* Buffer 1 is currently listed in status register */
		i8StatusBuffer = 1;
	}
	else
	{
		/* The 'Status' register isn't pointing to a proper buffer, so just ignore it.			*/

		i8StatusBuffer = -1;
	}

	/* Update the states of the buffers															*/
	for ( ui16i = 0; ui16i < 2; ui16i ++ )
	{


		bBufferToBeFreed [ui16i] = DP_FALSE;

		switch ( DP_eBufferStates [ ui16i ] )
		{
			case DP_DMA_BUFFER_STATE_FREE:
			{
				/* If the buffer is free, then the DMA Engine won't have changed it since last	*/
				/* time.																		*/
				break;
			}
		
			case DP_DMA_BUFFER_STATE_PENDING:
			{
				
				if ( i8StatusBuffer == ui16i )
				{
				
					if ( bCurrentStatusFlag )
					{
						
						if ( bCurrentValidFlag )
						{
							/* The DMA Engine is indicating that it has finished with this		*/
							/* buffer, yet the valid flag is still set, which implies that the	*/
							/* buffer has been re-submitted since then, so we will assume that	*/
							/* the buffer has yet to be serviced.								*/

							/* NORMAL */
							/* We should choose the other one and place this one in limbo		*/
						}
						else
						{
							/* The DMA Engine is indicating that it has finished dealing with	*/
							/* this buffer. The fact that the valid flag is not set means that	*/
							/* we haven't resubmitted this buffer as pending since it was last	*/
							/* pending. Treat this buffer as 'complete' (free it up).			*/

							/* NORMAL */
							bBufferToBeFreed [ ui16i ] = DP_TRUE;
							DP_eBufferStates [ ui16i ] = DP_DMA_BUFFER_STATE_FREE;
						}

					}
					else
					{

						if ( bCurrentValidFlag )
						{
							/* The DMA Engine is indicating that it has not yet finished		*/
							/* working on this buffer, but the valid flag is set, implying that	*/
							/* we have resubmitted it prior to it having been finished with.	*/

							/* IMPOSSIBLE */
							/* We should be writing repeatedly to the other one in this case,	*/
							/* not (ever) re-submitting a buffer which is still being serviced	*/

							#if defined DP_SIMULATION_MODE
								bProblem = DP_TRUE;
							#endif

						}
						else
						{
							/* The DMA Engine is indicating that it is still in the process of	*/
							/* dealing with this buffer. Set the state of this buffer to		*/
							/* 'Servicing'.														*/

							/* NORMAL */
							DP_eBufferStates [ ui16i ] = DP_DMA_BUFFER_STATE_SERVICING;

						}

					}

				}

				else

				{
					/* This buffer isn't even referred to by the DMA Engine at the moment, so	*/
					/* don't worry about it.													*/
				}

				break;
			}

			case DP_DMA_BUFFER_STATE_SERVICING:
			{
			
				if ( i8StatusBuffer == ui16i )
				{
				
					if ( bCurrentStatusFlag )
					{
						
						if ( bCurrentValidFlag )
						{
							/* The DMA Engine is indicating that it has finished with this		*/
							/* buffer. The valid flag is set, which implies that either this	*/
							/* buffer has been subsequently re-submitted (which should be		*/
							/* impossible, or that another buffer is now awaiting servicing.	*/

							/* NORMAL */
							/* This buffer has now finished servicing, so free it up.			*/
							bBufferToBeFreed [ ui16i ] = DP_TRUE;
							DP_eBufferStates [ ui16i ] = DP_DMA_BUFFER_STATE_FREE;

						}
						else
						{
							/* The DMA Engine is indicating that it has finished dealing with	*/
							/* this buffer. The fact that the valid flag is not set means that	*/
							/* we haven't resubmitted this buffer as pending since it was last	*/
							/* pending. Treat this buffer as 'complete' (reduce buffer).		*/

							/* NORMAL */
							bBufferToBeFreed [ ui16i ] = DP_TRUE;
							DP_eBufferStates [ ui16i ] = DP_DMA_BUFFER_STATE_FREE;
						}

					}
					else
					{

						if ( bCurrentValidFlag )
						{
							/* The DMA Engine is indicating that it has not yet finished		*/
							/* working on this buffer,											*/

							/* NORMAL */
							/* Another buffer is being written to on the fly - this one hasn't	*/
							/* been dealt with yet, though.										*/

						}
						else
						{
							/* The DMA Engine is indicating that it is still in the process of	*/
							/* dealing with this buffer. So we're still servicing - no change	*/

							/* NORMAL */

						}

					}

				}

				else
				
				{
					/* If the other buffer is being referred to by the DMA Engine and it was	*/
					/* pending, then we must assume that this one has been completed.			*/
					
					if ( i8StatusBuffer == ( 1- ui16i ) )
					{
						/* This buffer should now be freed up as complete (reduced)				*/

						/* NORMAL */
						bBufferToBeFreed [ ui16i ] = DP_TRUE;
						DP_eBufferStates [ ui16i ] = DP_DMA_BUFFER_STATE_FREE;

					}

				}

				break;

			}

			case DP_DMA_BUFFER_STATE_LIMBO:
			{

				if ( i8StatusBuffer == ui16i )
				{
				
					if ( bCurrentStatusFlag )
					{
						
						if ( bCurrentValidFlag )
						{
							/* The DMA Engine is indicating that it has finished with this		*/
							/* buffer, yet the valid flag is still set, which implies that the	*/
							/* buffer has been re-submitted since then, so we will assume that	*/
							/* the buffer has yet to be serviced.								*/

							/* IMPOSSIBLE */
							/* This means that we have re-submitted a 'limbo' buffer to pending	*/
							/* prior to figuring out how it got out of limbo.					*/

							#if defined DP_SIMULATION_MODE
								bProblem = DP_TRUE;
							#endif

						}
						else
						{
							/* The DMA Engine is indicating that it has finished dealing with	*/
							/* this buffer. The fact that the valid flag is not set means that	*/
							/* we haven't resubmitted this buffer as pending. This means that	*/
							/* it was grabbed by the DMA Engine whilst we were pontificating -	*/
							/* free it up as a completed buffer (reduce buffer)					*/

							/* NORMAL */
							bBufferToBeFreed [ ui16i ] = DP_TRUE;
							DP_eBufferStates [ ui16i ] = DP_DMA_BUFFER_STATE_FREE;
						}

					}
					else
					{

						if ( bCurrentValidFlag )
						{
							/* The DMA Engine is indicating that it has not yet finished		*/
							/* working on this buffer, but the valid flag is set, implying that	*/
							/* we have resubmitted it prior to it having been finished with.	*/

							/* IMPOSSIBLE */
							/* This means that we have re-submitted a 'limbo' buffer to pending	*/
							/* prior to figuring out how it got out of limbo.					*/

							#if defined DP_SIMULATION_MODE
								bProblem = DP_TRUE;
							#endif

						}
						else
						{
							/* The DMA Engine is indicating that it is still in the process of	*/
							/* dealing with this buffer. Set the state of this buffer to		*/
							/* 'Servicing'.														*/

							/* NORMAL */
							DP_eBufferStates [ ui16i ] = DP_DMA_BUFFER_STATE_SERVICING;

						}

⌨️ 快捷键说明

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