📄 dp_hardware_dispatcher.c
字号:
}
case DP_COMMAND_SEQUENCE_OPERATIONS_SEND_IMMEDIATE:
case DP_COMMAND_SEQUENCE_OPERATIONS_SEND_ON_VSYNC:
for ( ui16i = 0; ui16i < ui8LengthOfCommandSequence; ui16i++ )
{
DP_AddToBuffer ( DP_asCommandSequence [ ui16i ],
&DP_TemporaryDispatchBuffer [0],
&ui16SizeOfBuffer );
}
if (( eOperation == DP_COMMAND_SEQUENCE_OPERATIONS_SEND_ON_VSYNC ) ||
( eOperation == DP_COMMAND_SEQUENCE_OPERATIONS_SINGLE_COMMAND_ON_VSYNC ))
DP_WaitForVSYNC ();
for ( ui16i = 0; ui16i < ui16SizeOfBuffer; ui16i++ )
{
DP_WriteToMemory ( DP_TemporaryDispatchBuffer [ ui16i ].ui32TargetAddressOffset,
DP_TemporaryDispatchBuffer [ ui16i ].ui32TargetValue );
}
ui8LengthOfCommandSequence = 0;
break;
}
return ui16ReturnValue;
}
/***********************************************************************************************
*
* Function Name : DP_GetField
* Inputs : psSourceField - A pointer to the 'DP_FieldTarget' structure
* which contains details of the field from
* which a value is to be read.
*
* pui16Errors - A pointer to a 'DP_UINT_16' which the
* function uses to indicate the success of
* the function call. This variable is either
* filled with one of the two 'success' flags
* (depending on whether error checking is
* enabled) or with
* 'DP_ERR_EXCEEDS_CAPABILITIES' if the field
* was found not to exist.
* Outputs : None.
* Returns : DP_UINT_32 - If successful, returns the value of the
* requested field.
*
* Globals Used : DP_DispatcherBuffers - Used to compare against the address stored
* in the 'pending' register, in order to
* establish whether the requested field should
* be read from the hardware itself, or from
* the pending buffer.
*
* DP_ui16DispatcherBufferSize- When using the function DP_SearchBuffer, the
* size of the buffer being searched must be
* passed. The DP_SearchBuffer function is used
* here to see if the requested field is in a
* a 'pending' buffer and hence should be
* returned from the buffer, rather than from
* hardware.
*
* DP_ui8DispatcherBufferOffset- Any direct reference to the dispatcher buffers
* must include their current offset (the 16 bit
* word toggle which is flipped every time the
* buffer is 'freed').
*
* Description : This function allows the value of a field to be read. The resulting value is
* always returned as a zero bit aligned 32 bit value. The function checks to see
* if the requested field is currently queued in the 'pending' buffer and returns
* the queued value if it is.
*
***********************************************************************************************/
DP_UINT_32 DP_GetField ( const DP_FieldTarget * psSourceField,
DP_UINT_16 * pui16Errors )
{
DP_pQueuedMemoryWrite psAddressOfCurrentlyPendingBuffer;
DP_pQueuedMemoryWrite psAddressOfCurrentStatusBuffer;
DP_BOOL bCurrentStatusFlag;
DP_INT_8 i8PendingBuffer;
DP_UINT_32 ui32CurrentQueuedValue;
DP_UINT_32 ui32ReturnValue = 0;
DP_BOOL bIsPending = DP_FALSE;
#if defined DP_SIMULATION_MODE
printf ( "DP_GetField \n" );
#endif
/* Start by assuming there are no errors */
if ( pui16Errors != DP_NULL )
*pui16Errors = DP_STANDARD_CODE_NO_ERROR;
/* If the field being requested doesn't exist in the hardware, then abandon this request */
/* right now. */
if ( psSourceField->ui32TargetAddressOffset != DP_NO_REG )
{
/* Obtain the latest values for 'Pending buffer', 'Status buffer' and 'Status flag' */
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);
/* If the pending buffer has already been written to hardware, then just read from */
/* hardware */
if (!(( psAddressOfCurrentStatusBuffer == psAddressOfCurrentlyPendingBuffer ) && bCurrentStatusFlag ))
{
/* It is not the case that the current queue is the same as the one which the */
/* hardware has most recently finished dealing with. As such, all we know is that */
/* the data in the currently pending buffer has yet to 'reach' the hardware proper, */
/* so we should treat any relevant data in that buffer as 'latest'. */
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;
}
/* If a buffer has been earmarked, then search it to see if the address at which */
/* the desired field arrives is going to be modified in the pending buffer (when it */
/* gets actioned). */
if ( i8PendingBuffer != -1 )
{
if ( DP_SearchBuffer ( &(DP_DispatcherBuffers [(i8PendingBuffer*DP_SIZE_OF_DISPATCHER_BUFFER_IN_ENTRIES) + DP_ui8DispatcherBufferOffset [i8PendingBuffer]]),
DP_ui16DispatcherBufferSize [ i8PendingBuffer ],
psSourceField->ui32TargetAddressOffset,
&ui32CurrentQueuedValue,
(DP_PUINT_16) DP_NULL ) )
{
/* The address does have a pending write. Retrieve and normalise that value */
ui32ReturnValue = ui32CurrentQueuedValue;
ui32ReturnValue &= psSourceField->ui32TargetBitfieldMask;
ui32ReturnValue = ui32ReturnValue >> psSourceField->ui8TargetBitfieldStart;
bIsPending = DP_TRUE;
}
}
}
if ( !bIsPending )
{
/* The specified address does not have a write pending, so read directly from the */
/* hardware. */
ui32ReturnValue = DP_ReadFieldFromHardware ( psSourceField );
}
}
else
{
if ( pui16Errors != DP_NULL )
*pui16Errors = DP_ERR_EXCEEDS_CAPABILITIES;
}
// printf ( "DP_GetField returns %x \n\n", ui32ReturnValue );
return ui32ReturnValue;
} /* End of 'DP_GetField' */
/***********************************************************************************************
*
* Function Name : DP_ReadFieldFromHardware
* Inputs : psSourceField - A pointer to the 'DP_FieldTarget' structure
* which provides details of the field to be
* read.
*
* Outputs : None.
* Returns : DP_UINT_32 - The value of the field read.
* Globals Used : None.
*
* Description : This lower level read function returns a field (zero bit aligned), but does
* NOT search to see if the value is currently pending (always reads straight
* from hardware).
*
***********************************************************************************************/
DP_UINT_32 DP_ReadFieldFromHardware ( const DP_FieldTarget * psSourceField )
{
DP_UINT_32 ui32DataAsRead;
/* Abandon the request if the specified field doesn't exist */
if ( psSourceField->ui32TargetAddressOffset != DP_NO_REG )
{
/* Step 1 - Read all data from the address at which the specified field is resident */
ui32DataAsRead = DP_ReadFromMemory ( psSourceField->ui32TargetAddressOffset );
/* Step 2 - Remove all non-field specific data from the read value */
ui32DataAsRead &= psSourceField->ui32TargetBitfieldMask;
/* Step 3 - Normalise the read value (align it at bit 0) */
ui32DataAsRead = ui32DataAsRead >> psSourceField->ui8TargetBitfieldStart;
/* Step 4 - If we truncated this field prior to storage in hardware (using the */
/* 'read from' field, then correct for this. */
ui32DataAsRead = ui32DataAsRead << psSourceField->ui8SourceBitfieldStart;
}
#if defined DP_SIMULATION_MODE
printf ( "Read field value 0x%x from addr 0x%x \t - Fn. : ReadFieldFromHardware') \n",
ui32DataAsRead,
(DP_UINT_32) psSourceField->ui32TargetAddressOffset );
#endif
return ui32DataAsRead;
}
/***********************************************************************************************
*
* Function Name : DP_SearchBuffer
* Inputs : pasBufferToSearch - Pointer to the first 'DP_pQueuedMemoryWrite'
* in the list of memory writes to be searched.
*
* ui16SizeOfBuffer - The number of 'DP_pQueuedMemoryWrite'
* structures in the list to be searched.
*
* ui32AddressToSearchFor - The target offset to be searched for in the
* provided list.
*
* pui32ValueOfQueuedWrite - The value to be searched for in the
* provided list.
*
* pui16PositionOfQueuedWrite - A pointer to the 'DP_UINT_16' which the
* function will fill with the position of the
* structure in the provided list which
* matched both the specified offset and value.
* This value is only filled if the function
* indicates success - see below.
*
* Outputs : pui16PositionOfQueuedWrite - See above.
*
* Returns : DP_BOOL - A flag indicating whether the specified
* target offset and value were found in any
* of the structures in the provided list. If
* the function returns 'DP_TRUE' then the
* offset and value were found. If the function
* returns 'DP_FALSE', then the search was not
* successful.
* Globals Used : None.
* Description : This function is used to search through one of the dispatcher buffers for a
* queued write to a specified address. If a write to the specified address is
* found in the indicated queue, the function returns the value which is to be
* written and the offset into the buffer at which the value was found.
*
***********************************************************************************************/
DP_BOOL DP_SearchBuffer ( DP_pQueuedMemoryWrite pasBufferToSearch,
DP_UINT_16 ui16SizeOfBuffer,
DP_UINT_32 ui32AddressToSearchFor,
DP_PUINT_32 pui32ValueOfQueuedWrite,
DP_PUINT_16 pui16PositionOfQueuedWrite )
{
DP_UINT_16 ui16i;
DP_BOOL bFoundIt = DP_FALSE;
for ( ui16i = 0; ui16i < ui16SizeOfBuffer; ui16i++ )
{
if ( pasBufferToSearch [ ui16i ].ui32TargetAddressOffset == ui32AddressToSearchFor )
{
*pui32ValueOfQueuedWrite = pasBufferToSearch [ ui16i ].ui32TargetValue;
bFoundIt = DP_TRUE;
if ( pui16PositionOfQueuedWrite != DP_NULL)
*pui16PositionOfQueuedWrite = ui16i;
break;
}
}
return bFoundIt;
}
/***********************************************************************************************
*
* Function Name : DP_QueueNewDMABuffer
* Inputs : pasQueueToSubmit - A pointer to the first 'DP_pQueuedFieldWrite'
* structure in a list to be submitted to the
* DMA engine.
*
* ui8LengthOfQueue - The number of 'DP_pQueuedFieldWrite'
* structures in the list to be submitted.
* Outputs : None.
* Returns : Nothing.
* Globals Used : DP_DispatcherBuffers - Used variously to establish the current
* states of the dispatcher buffers (by
* comparison of the buffers' addresses with the
* values held in the 'pending' and 'status'
* registers. Also used when copying between
* buffers, populating buffers and when filling
* the 'pending' register with the address of
* a buffer being queued.
*
* DP_ui16DispatcherBufferSize- The size of the dipatcher buffers is used here
* in a variety of contexts, when reading from
* buffers and when adjusting the size of a
* buffer by writing to it.
*
* DP_eBufferStates - The decision on where to place the new data
* to be queued is based on the current state of
* of the two dispatcher buffers. The states are
* also modified here, as (a.) the result of
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -