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

📄 dp_hardware_dispatcher.c

📁 Lido PXA270平台开发板的最新BSP,包括源代码
💻 C
📖 第 1 页 / 共 5 页
字号:

					}

				}

				else

				{
					/* The buffer wasn't grabbed while we were working on it, so just			*/
					/* transition it back to 'free', copying the other buffer as a baseline		*/

					DP_eBufferStates [ ui16i ] = DP_DMA_BUFFER_STATE_FREE;

					DP_MEMCPY ( &(DP_DispatcherBuffers [( ui16i * DP_SIZE_OF_DISPATCHER_BUFFER_IN_ENTRIES ) + DP_ui8DispatcherBufferOffset [ ui16i ]]),
								&(DP_DispatcherBuffers [( (1-ui16i) * DP_SIZE_OF_DISPATCHER_BUFFER_IN_ENTRIES ) + DP_ui8DispatcherBufferOffset [(1 - ui16i)]]),
								sizeof (DP_QueuedMemoryWrite) * DP_ui16DispatcherBufferSize [(1-ui16i)] );
	
					DP_ui16DispatcherBufferSize [ui16i] = DP_ui16DispatcherBufferSize [(1-ui16i)];
				}

				break;

			} /* Case */

		} /* Switch */

	} /* If */

	if ( bBufferToBeFreed [0] && bBufferToBeFreed [1] )
	{
		
		for ( ui16i = 0; ui16i < 2; ui16i ++ )
		{
			/* Clear both the buffers entirely													*/
			DP_ui16DispatcherBufferSize [ ui16i ] = 0;

			/* Toggle the offset addresses														*/
			if ( DP_ui8DispatcherBufferOffset [ ui16i ] )
				DP_ui8DispatcherBufferOffset [ ui16i ] = 0;
			else
				DP_ui8DispatcherBufferOffset [ ui16i ] = 2;
		}

	}
	else
	{

		for ( ui16i = 0; ui16i < 2; ui16i ++ )
		{

			if ( bBufferToBeFreed [ ui16i ] )
			{	

				 /* If there are any entries in the other buffer (the one not being freed),		*/
				 /*	which have not yet reached hardware, then duplicate them in the buffer		*/
				 /*	being freed. Only do this if the other buffer	is not currently being		*/
				 /*	serviced (in which case	there's little point in copying the data from it as	*/
				 /*	it will have reached hardware soon enough, anyway).							*/							

				if	(( DP_eBufferStates [ (1-ui16i) ] != DP_DMA_BUFFER_STATE_SERVICING ) &&
					( DP_eBufferStates [ (1-ui16i) ] != DP_DMA_BUFFER_STATE_LIMBO ))
				{

					/* Toggle the offset address												*/
					if ( DP_ui8DispatcherBufferOffset [ ui16i ] )
						DP_ui8DispatcherBufferOffset [ ui16i ] = 0;
					else
						DP_ui8DispatcherBufferOffset [ ui16i ] = 2;

					ui8SizeOfNewBuffer = 0;

					/* In the following routine, ui16i indicates the number of the buffer to be */
					/* freed. ui16j is used to search through each entry of the other buffer	*/
					/* (the one not being freed).												*/

					for ( ui16j = 0; ui16j < DP_ui16DispatcherBufferSize [ (1-ui16i) ]; ui16j++ )
					{

						if ( DP_DispatcherBuffers [ ( (1-ui16i) * DP_SIZE_OF_DISPATCHER_BUFFER_IN_ENTRIES ) + (ui16j + DP_ui8DispatcherBufferOffset [ (1-ui16i) ]) ].ui32TargetValue !=
							 DP_ReadFromMemory ( DP_DispatcherBuffers [ ( (1-ui16i) * DP_SIZE_OF_DISPATCHER_BUFFER_IN_ENTRIES ) + (ui16j + DP_ui8DispatcherBufferOffset [ (1-ui16i)]) ].ui32TargetAddressOffset ) )
						{
							/* The value in memory did not match the queued value for that 		*/
							/* address, so we'd better retain the change for submission to the 	*/
							/* DMA Engine.														*/
							DP_MEMCPY ( &(DP_DispatcherBuffers [ ( ui16i * DP_SIZE_OF_DISPATCHER_BUFFER_IN_ENTRIES ) + (ui8SizeOfNewBuffer + DP_ui8DispatcherBufferOffset [ ui16i ]) ]), 
										&(DP_DispatcherBuffers [ ( (1-ui16i) * DP_SIZE_OF_DISPATCHER_BUFFER_IN_ENTRIES ) + ui16j + DP_ui8DispatcherBufferOffset [ (1-ui16i)] ]),
										sizeof ( DP_QueuedMemoryWrite )	);
	
							ui8SizeOfNewBuffer++;
						}

					} /* For */ 
	
					DP_ui16DispatcherBufferSize [ ui16i ] = ui8SizeOfNewBuffer;

					/* If the other buffer (the one which has not just been freed) is in the 	*/
					/* 'FREE' state then it still contains old data (which has just been 		*/
					/* written). In this case, just duplicate that buffer from this one.		*/

					if ( DP_eBufferStates [ (1-ui16i) ] == DP_DMA_BUFFER_STATE_FREE )
					{
						DP_MEMCPY ( &(DP_DispatcherBuffers [ ( ( 1-ui16i) * DP_SIZE_OF_DISPATCHER_BUFFER_IN_ENTRIES ) + DP_ui8DispatcherBufferOffset [ (1-ui16i) ]]),
									&(DP_DispatcherBuffers [ ( ui16i * DP_SIZE_OF_DISPATCHER_BUFFER_IN_ENTRIES ) + DP_ui8DispatcherBufferOffset [ui16i]]),
									sizeof (DP_QueuedMemoryWrite) * DP_ui16DispatcherBufferSize [ui16i] );
	
						DP_ui16DispatcherBufferSize [(1-ui16i)] = DP_ui16DispatcherBufferSize [ui16i];
					}
	
				} /* If */
				else
				{
					/* Clear the buffer entirely												*/
					DP_ui16DispatcherBufferSize [ ui16i ] = 0;

					/* Toggle the offset address												*/
					if ( DP_ui8DispatcherBufferOffset [ ui16i ] )
						DP_ui8DispatcherBufferOffset [ ui16i ] = 0;
					else
						DP_ui8DispatcherBufferOffset [ ui16i ] = 2;

				}

			} /* If */
	
		} /* For */

	} /* If */

	/* Decide how to deal with the new information to be queued.								*/

	/* Are either of the buffers free ?															*/
	for ( ui16i = 0; ui16i < 2; ui16i ++ )
	{
		if ( DP_eBufferStates [ ui16i ] == DP_DMA_BUFFER_STATE_FREE )
		{
			i8BufferToUse = (DP_INT_8) ui16i;
			break;
		}
	}
	
	if ( i8BufferToUse == -1 )
	{
		for ( ui16i = 0; ui16i < 2; ui16i ++ )
		{
			if ( DP_eBufferStates [ ui16i ] == DP_DMA_BUFFER_STATE_PENDING )
			{
				i8BufferToUse = (DP_INT_8) ui16i;
				break;
			}
		}

		/* We could find neither any free nor any pending buffers. This means that both			*/
		/* buffers must be set to 'servicing' mode. Which is just silly.						*/
		if ( i8BufferToUse != -1 )
		{
			/* We have found a pending buffer (in the absence of any free ones, so use that)	*/
			/* As we didn't find any free buffers, and we did find a pending one, the other		*/
			/* buffer must be in 'servicing' mode (otherwise it would have been freed by now)	*/

				/* Clear the 'valid' flag														*/
				DP_WriteFieldToAddress (	&(DP_asGlobalFieldTargets [ DP_GLOBAL_FIELD_HARDWARE_DISPATCHER_PENDING_ADDRESS_VALID_FLAG ]),
											(DP_UINT_32) NULL,
											DP_NULL		);

				/* Now add all the changes in the submitted queue to the pending buffer			*/
				for ( ui16i = 0; ui16i < ui8LengthOfQueue; ui16i++ )
				{
					DP_AddToBuffer	(	pasQueueToSubmit [ ui16i ],
										&(DP_DispatcherBuffers [ ( i8BufferToUse * DP_SIZE_OF_DISPATCHER_BUFFER_IN_ENTRIES ) + DP_ui8DispatcherBufferOffset [i8BufferToUse] ]),
										&(DP_ui16DispatcherBufferSize [ i8BufferToUse ]) );
				}

				DP_CommandSequence (	DP_COMMAND_SEQUENCE_OPERATIONS_NEW_SEQUENCE,
										DP_NULL,
										DP_NULL	);

				/* Write the length of the newly created buffer to the 'length of pending		*/
				/* buffer' register.															*/
				DP_CommandSequence (	DP_COMMAND_SEQUENCE_OPERATIONS_ADD_COMMAND,
										(DP_FieldTarget *) &(DP_asGlobalFieldTargets [ DP_GLOBAL_FIELD_HARDWARE_DISPATCHER_LENGTH_OF_PENDING_BUFFER ]),
										(DP_UINT_32) DP_ui16DispatcherBufferSize [ i8BufferToUse ]	);

				/* Point the 'Pending' register at the (until recently) pending buffer			*/
				DP_CommandSequence (	DP_COMMAND_SEQUENCE_OPERATIONS_ADD_COMMAND,
										(DP_FieldTarget *) &(DP_asGlobalFieldTargets [ DP_GLOBAL_FIELD_HARDWARE_DISPATCHER_PENDING_ADDRESS ]),										
										#if defined	PCI_BRIDGE_SIM
											/* Remove the Windows address offset prior to		*/
											/* writing to the hardware.							*/
											(DP_UINT_32) ( (( i8BufferToUse * DP_SIZE_OF_DISPATCHER_BUFFER_IN_BYTES ) + (DP_ui8DispatcherBufferOffset [i8BufferToUse] * sizeof ( DP_QueuedMemoryWrite )) ) ) + ( (DP_UINT_32) DP_DispatcherBuffers - (DP_UINT_32) DP_pSharedMemory ));
										#else
											(DP_UINT_32) &(DP_DispatcherBuffers [ ( i8BufferToUse * DP_SIZE_OF_DISPATCHER_BUFFER_IN_ENTRIES ) + DP_ui8DispatcherBufferOffset [i8BufferToUse]])	);
										#endif

				/* Reset the 'valid' flag														*/
				DP_WriteFieldToAddress (	&(DP_asGlobalFieldTargets [ DP_GLOBAL_FIELD_HARDWARE_DISPATCHER_PENDING_ADDRESS_VALID_FLAG ]),
											(DP_UINT_32) (DP_TRUE & 0x01),
											DP_NULL	);


				DP_CommandSequence (	DP_COMMAND_SEQUENCE_OPERATIONS_SEND_IMMEDIATE,
										DP_NULL,
										DP_NULL	);

		}

	}
	else
	{
		/* At least one buffer was free, so proceed with that one								*/

		/* Now add all the changes in the submitted queue to the free buffer					*/
		for ( ui16i = 0; ui16i < ui8LengthOfQueue; ui16i++ )
		{

			DP_AddToBuffer	(	pasQueueToSubmit [ ui16i ],
								&(DP_DispatcherBuffers [ ( ( i8BufferToUse * DP_SIZE_OF_DISPATCHER_BUFFER_IN_ENTRIES ) + DP_ui8DispatcherBufferOffset [i8BufferToUse] ) ]), 
								&(DP_ui16DispatcherBufferSize [i8BufferToUse]) );
		}

		
		DP_CommandSequence (	DP_COMMAND_SEQUENCE_OPERATIONS_NEW_SEQUENCE,
								DP_NULL,
								DP_NULL	);

		/* Point the 'Pending' register at the currently free buffer							*/
		DP_CommandSequence (	DP_COMMAND_SEQUENCE_OPERATIONS_ADD_COMMAND,
								(DP_FieldTarget *) &(DP_asGlobalFieldTargets [ DP_GLOBAL_FIELD_HARDWARE_DISPATCHER_PENDING_ADDRESS ]),
								#if defined	PCI_BRIDGE_SIM	
									/* Remove the Windows address offset prior to writing		*/
									/* hardware.												*/
									(DP_UINT_32) ((( i8BufferToUse * DP_SIZE_OF_DISPATCHER_BUFFER_IN_BYTES ) + (DP_ui8DispatcherBufferOffset [i8BufferToUse] * sizeof ( DP_QueuedMemoryWrite )) ) ) + ( (DP_UINT_32) DP_DispatcherBuffers - (DP_UINT_32) DP_pSharedMemory ));
								#else
									(DP_UINT_32) &(DP_DispatcherBuffers [ ( i8BufferToUse * DP_SIZE_OF_DISPATCHER_BUFFER_IN_ENTRIES ) + DP_ui8DispatcherBufferOffset [i8BufferToUse]])	);
								#endif

		/* Write the length of the newly created buffer to the 'length of pending				*/
		/* buffer' register.																	*/
		DP_CommandSequence (	DP_COMMAND_SEQUENCE_OPERATIONS_ADD_COMMAND,
								(DP_FieldTarget *) &(DP_asGlobalFieldTargets [ DP_GLOBAL_FIELD_HARDWARE_DISPATCHER_LENGTH_OF_PENDING_BUFFER ]),
								(DP_UINT_32) DP_ui16DispatcherBufferSize [i8BufferToUse]	);

		/* Set the 'valid' flag																	*/
		DP_CommandSequence (	DP_COMMAND_SEQUENCE_OPERATIONS_ADD_COMMAND,
								(DP_FieldTarget *) &(DP_asGlobalFieldTargets [ DP_GLOBAL_FIELD_HARDWARE_DISPATCHER_PENDING_ADDRESS_VALID_FLAG ]),
								(DP_UINT_32) (DP_TRUE & 0x01)	);


		DP_CommandSequence (	DP_COMMAND_SEQUENCE_OPERATIONS_SEND_IMMEDIATE,
								DP_NULL,
								DP_NULL	);

		/* Change the states of the two buffers													*/
		DP_eBufferStates [i8BufferToUse]	 = DP_DMA_BUFFER_STATE_PENDING;	

		switch ( DP_eBufferStates [(1-i8BufferToUse)] )
		{
			case DP_DMA_BUFFER_STATE_FREE:
			{
				/* Keep the other buffer up to date with the latest info.						*/

				DP_MEMCPY ( &(DP_DispatcherBuffers [ ( (1-i8BufferToUse) * DP_SIZE_OF_DISPATCHER_BUFFER_IN_ENTRIES ) + DP_ui8DispatcherBufferOffset [ (1-i8BufferToUse) ]]),
							&(DP_DispatcherBuffers [ ( i8BufferToUse * DP_SIZE_OF_DISPATCHER_BUFFER_IN_ENTRIES ) + DP_ui8DispatcherBufferOffset [ i8BufferToUse ]]),
							sizeof (DP_QueuedMemoryWrite) * DP_ui16DispatcherBufferSize [ i8BufferToUse ] );
	
				DP_ui16DispatcherBufferSize [ (1-i8BufferToUse) ] = DP_ui16DispatcherBufferSize [ i8BufferToUse ];				
				break;
			}

			case DP_DMA_BUFFER_STATE_PENDING:
			{
				DP_eBufferStates [(1-i8BufferToUse)] = DP_DMA_BUFFER_STATE_LIMBO;
				break;
			}
			
		}

	}
	


} /* End of 'DP_QueueNewDMABuffer' */


/***********************************************************************************************
 *
 * Function Name  : DP_AddToBuffer
 * Inputs         : sFieldToAdd					-	A pointer to the 'DP_QueuedFieldWrite'
 *													structure containing details of the field
 *													target to be added to the specified list
 *													of memory writes.
 *					
 *					pasBufferToAddTo			-	A pointer to the first
 *													'DP_pQueuedMemoryWrite' structure in a
 *													list of non-field specific memory writes.	
 *					
 *					pui16SizeOfBuffer			-	A pointer to the 'DP_UINT_16' containing the
 *													number of non-field specific memory writes
 *													in the list passed. A pointer to the value
 *													is passed so that the function can update the
 *													size of the list if necessary.
 *					
 * Outputs        : pui16SizeOfBuffer			-	See above.
 * Returns        : Nothing.
 * Globals Used   :	None.
 * Description    : This function adds a specified field write to an existing buffer, searching 
 *					to see if the affected memory address is currently in the buffer and, if it 
 *					is, merging the two values, and reading the current value from hardware prior
 *					to merging and adding to the end of the buffer otherwise.																		
 *
 ***********************************************************************************************/

DP_VOID		DP_AddToBuffer				(	DP_QueuedFieldWrite					sFieldToAdd,
											DP_pQueuedMemoryWrite				pasBufferToAddTo,
											DP_PUINT_16							pui16SizeOfBuffer	)

{
DP_UINT_32				ui32CurrentQueuedValue;
DP_UINT_16				ui16CurrentQueuedPosition;
DP_QueuedMemoryWrite	sMemoryWriteToAdd;

	/* If the field to add doesn't exist, then proceed no further.								*/
	if ( (sFieldToAdd.pasFieldToWrite)->ui32TargetAddressOffset != DP_NO_REG )
	{

		/* Is the address containing the specified field already listed in the buffer ?			*/
		if ( DP_SearchBuffer (	pasBufferToAddTo,
								*pui16SizeOfBuffer,
								(sFieldToAdd.pasFieldToWrite)->ui32TargetAddressOffset,
								&ui32CurrentQueuedValue,
								&ui16CurrentQueuedPosition	)	)
		{
			/* The address of the field to add is currently listed in the buffer, so the new	*/
			/* field value should be merged into the current buffer position.					*/
			DP_WriteFieldToAddress (	sFieldToAdd.pasFieldToWrite,
										sFieldToAdd.ui32ValueToWrite,
										&(pasBufferToAddTo [ui16CurrentQueuedPosition].ui32TargetValue)		);
		}

⌨️ 快捷键说明

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