📄 dp_hardware_dispatcher.c
字号:
else if ( DP_ReadFieldFromHardware ( sFieldToAdd.pasFieldToWrite ) != sFieldToAdd.ui32ValueToWrite )
{
/* The address of the field to add is not currently listed in the buffer */
/* and is not already set to the desired value in memory (in which case we just */
/* ditch the request to change that particular field, as it is already 'changed'. */
/* The hardware should be read and a new memory write added to the buffer. */
/* Copy the current value of the memory location into the end of the target buffer */
ui32CurrentQueuedValue = DP_ReadFromMemory ( (sFieldToAdd.pasFieldToWrite)->ui32TargetAddressOffset );
#if defined DP_SIMULATION_MODE
printf ( "Read value 0x%x from addr 0x%x \t - Fn. : DP_AddToBuffer') \n",
ui32CurrentQueuedValue,
(DP_UINT_32) (sFieldToAdd.pasFieldToWrite)->ui32TargetAddressOffset );
#endif
/* Add the current value as read from memory to the end of the buffer */
sMemoryWriteToAdd.ui32TargetAddressOffset = (sFieldToAdd.pasFieldToWrite)->ui32TargetAddressOffset;
sMemoryWriteToAdd.ui32TargetValue = ui32CurrentQueuedValue;
DP_MEMCPY ( (&(pasBufferToAddTo [ *pui16SizeOfBuffer ])),
(&sMemoryWriteToAdd),
sizeof ( DP_QueuedMemoryWrite ) );
/* Now merge the field to add into the new entry at the end of the buffer */
DP_WriteFieldToAddress ( sFieldToAdd.pasFieldToWrite,
sFieldToAdd.ui32ValueToWrite,
&(pasBufferToAddTo [ *pui16SizeOfBuffer ].ui32TargetValue) );
/* Now increment the size of the buffer to reflect the newly added memory write */
*pui16SizeOfBuffer += 1;
}
}
}
/***********************************************************************************************
* Function Name : DP_WriteFieldToAddress
* Inputs : psTargetField - A pointer to the 'DP_FieldTarget' structure
* containing details of the field to be written
* to.
*
* ui32SourceData - The value to write to the specified field.
*
* pui32TargetAddress - Opportunity to write to somewhere other than
* the field's native address :
* If this parameter is set to 'DP_NULL', then
* the field will be written to at the address
* specified in the 'DP_FieldTarget' structure. If
* an address is passed in this parameter, then the
* field will be written to according to the
* bitfield, mask, etc. specified in the
* 'DP_FieldTarget', but at the (absolute) address
* by this parameter.
* Outputs : None.
* Returns : Nothing.
* Globals Used : DP_pui32BaseAddress - Addresses (specified as offsets) are added to
* the base address prior to actual writing to
* hardware.
*
* Description : This function takes in a value and places it in the correct bitfield at a
* target address. No checking of DMA engine buffers is conducted - the
* function simply writes to the right place in hardware. If a target address
* is specified, it will be used as a replacement for the field's normal
* hardware address (for both read and write accesses).
*
***********************************************************************************************/
DP_VOID DP_WriteFieldToAddress ( const DP_FieldTarget * psTargetField,
DP_UINT_32 ui32SourceData,
DP_PUINT_32 pui32TargetAddress )
/* psTargetField - Field to write to */
/* ui32SourceData - Value to place in field */
/* pui32TargetAddress - e */
/* */
{
DP_UINT_32 ui32ValueToWrite;
DP_UINT_32 ui32CurrentValueOfMemoryLocation;
DP_UINT_32 ui32CompletedWriteValue;
/* Check that the field to be written actually exists */
if ( psTargetField->ui32TargetAddressOffset != DP_NO_REG )
{
/* Step 1 - Remove any redundant bits of source data as indicated by 'Read from' value */
/* of target field */
if ( psTargetField->ui8TargetBitfieldStart > psTargetField->ui8SourceBitfieldStart )
{
/* As the target field is further left than the start of the source field (in bits) */
/* a shift left is needed to place the valid data in the correct position */
ui32ValueToWrite = ui32SourceData << ( psTargetField->ui8TargetBitfieldStart - psTargetField->ui8SourceBitfieldStart );
}
else if ( psTargetField->ui8TargetBitfieldStart < psTargetField->ui8SourceBitfieldStart )
{
/* As the target field is further right than the start of the source field (in */
/* bits) a shift right is needed to place the valid data in the correct position */
ui32ValueToWrite = ui32SourceData >> ( psTargetField->ui8SourceBitfieldStart - psTargetField->ui8TargetBitfieldStart );
}
else
{
/* The target and source fields are already aligned. */
ui32ValueToWrite = ui32SourceData;
}
/* Now that the source data is in position, remove all redundant information */
ui32ValueToWrite &= psTargetField->ui32TargetBitfieldMask;
/* Step 2 - Obtain the current value of the field's memory location and clear the */
/* bitfield to be used by the target field. */
if ( pui32TargetAddress == NULL )
{
ui32CurrentValueOfMemoryLocation = *(volatile DP_UINT_32 *)( DP_pui32BaseAddress + (psTargetField->ui32TargetAddressOffset / sizeof (DP_UINT_32)) );
#if defined DP_SIMULATION_MODE
printf ( "Read value 0x%x from addr 0x%x \t - Fn. : WriteFieldToAddress') \n",
ui32CurrentValueOfMemoryLocation,
(DP_UINT_32) psTargetField->ui32TargetAddressOffset );
#endif
}
else
{
/* Read from the specified address, instread of the field's native position */
ui32CurrentValueOfMemoryLocation = *((DP_PUINT_32) pui32TargetAddress);
}
/* Clear the bitfield for subsequent insertion of new field data */
ui32CompletedWriteValue = ui32CurrentValueOfMemoryLocation & ~(psTargetField->ui32TargetBitfieldMask);
/* Step 3 - Place the new data into the cleared bitfield */
ui32CompletedWriteValue |= ui32ValueToWrite;
/* Step 4 - Write the prepared data into memory */
if ( pui32TargetAddress == DP_NULL )
{
DP_WriteToMemory ( psTargetField->ui32TargetAddressOffset, ui32CompletedWriteValue );
}
else
{
/* Write to the specified address, rather than using the field's native position */
*((DP_PUINT_32) pui32TargetAddress) = ui32CompletedWriteValue;
}
} /* if */
}
/***********************************************************************************************
* Function Name : DP_ReadFromMemory
* Inputs : ui32AddressToReadFrom - The offset address (from the global base
* address) which is to be read.
* Outputs : None.
* Returns : DP_UINT_32 - The value read from the specified address.
* Globals Used : DP_pui32BaseAddress - Addresses (specified as offsets) are added to
* the base address prior to actual reading from
* hardware.
*
* Description : This function simply reads from a specified memory address - a function is
* used so as to provide as few actual hardware access points as possible.
*
***********************************************************************************************/
DP_UINT_32 DP_ReadFromMemory ( DP_UINT_32 ui32AddressToReadFrom )
{
DP_UINT_32 ui32ReturnValue = 0;
DP_PUINT_32 pui32AddressToReadFrom;
pui32AddressToReadFrom = DP_pui32BaseAddress + (ui32AddressToReadFrom / sizeof (DP_UINT_32));
ui32ReturnValue = *(volatile DP_UINT_32*)pui32AddressToReadFrom;
#if defined DP_SIMULATION_MODE
printf ( "Read value 0x%x from addr 0x%x \t - Fn. : ReadFromMemory') \n",
ui32ReturnValue,
ui32AddressToReadFrom );
#endif
return ui32ReturnValue;
}
void ConvertCToT(TCHAR* pszDest, const IMG_CHAR* pszSrc)
{
unsigned i;
for(i = 0; i <= strlen(pszSrc); i++)
pszDest[i] = (TCHAR) pszSrc[i];
}
/***********************************************************************************************
* Function Name : DP_WriteToMemory
* Inputs : ui32AddressToWriteTo - The offset (from the global base address) of the
* address to be written to.
*
* ui32ValueToWrite - The value to be written to the specified address.
* Outputs : None.
* Returns : None
* Globals Used : DP_pui32BaseAddress - Addresses (specified as offsets) are added to
* the base address prior to actual writing to
* hardware.
*
* Description : This function simply writes to a specified memory address - a function is
* used so as to provide as few actual hardware access points as possible.
*
***********************************************************************************************/
DP_VOID DP_WriteToMemory ( DP_UINT_32 ui32AddressToWriteTo,
DP_UINT_32 ui32ValueToWrite )
{
volatile DP_UINT_32 * pui32PhysicalAddress;
#ifdef PRINTMESSAGE
char buffer[256];
TCHAR unicode[256];
sprintf(buffer,"Reg 0x%04x = 0x%08x\n",ui32AddressToWriteTo,ui32ValueToWrite);
ConvertCToT(unicode, buffer);
OutputDebugString(unicode);
#endif
pui32PhysicalAddress = DP_pui32BaseAddress + (ui32AddressToWriteTo / sizeof ( DP_UINT_32 ) );
*(pui32PhysicalAddress) = ui32ValueToWrite;
#ifdef PDPPDUMP
PDUMPREG(PDUMPTAGS_REG_PDP,(WORD)ui32AddressToWriteTo,ui32ValueToWrite);
#endif
#if defined DP_SIMULATION_MODE
printf ( "Wrote value 0x%x to addr 0x%x \t - Fn. : DP_WriteToMemory) \n",
(DP_UINT_32) ui32ValueToWrite,
(DP_UINT_32) ui32AddressToWriteTo );
#if !defined SHOW_DMA_INTERFACE_OUTPUT
if ( (ui32AddressToWriteTo != DP_asGlobalFieldTargets [ DP_GLOBAL_FIELD_HARDWARE_DISPATCHER_PENDING_ADDRESS ].ui32TargetAddressOffset) &&
(ui32AddressToWriteTo != DP_asGlobalFieldTargets [ DP_GLOBAL_FIELD_HARDWARE_DISPATCHER_STATUS_ADDRESS ].ui32TargetAddressOffset) &&
(ui32AddressToWriteTo != DP_asGlobalFieldTargets [ DP_GLOBAL_FIELD_HARDWARE_DISPATCHER_STATUS_FLAG ].ui32TargetAddressOffset) &&
(ui32AddressToWriteTo != DP_asGlobalFieldTargets [ DP_GLOBAL_FIELD_HARDWARE_DISPATCHER_LENGTH_OF_PENDING_BUFFER ].ui32TargetAddressOffset) )
{
#endif
/* The field being written has nothing to do with the DMA Engine, so dump it to */
/* the simulator file. */
#ifdef PDPPDUMP
PDUMPREG ( PDUMPTAGS_REG_PDP, ui32AddressToWriteTo, ui32ValueToWrite );
#endif
#if !defined SHOW_DMA_INTERFACE_OUTPUT
}
#endif
#endif
}
#if defined DP_SIMULATION_MODE
/***********************************************************************************************
* Function Name : DP_SimulateDMAEngine
* Inputs : eSimulatorMode - The manner in which the simulation shoudl
* proceed.
* Outputs : None.
* Returns : Nothing.
* Globals Used : DP_pui32BaseAddress - Addresses (specified as offsets) are added to
* the base address prior to actual writing to
* hardware.
*
* Description : This function simulates a single DMA Engine 'event'. The function can be
* told to start the DMA Engine's cycle, and then later to stop it, or just to
* simulate an entire cycle instantly.
*
***********************************************************************************************/
void DP_SimulateDMAEngine ( DP_DMAEngineSimulatorModes eSimulatorMode )
{
static DP_PUINT_32 pui32PendingAddress;
static DP_PUINT_32 pui32StatusAddress;
DP_UINT_8 ui8i;
static DP_UINT_8 ui8LengthOfCurrentStatusBuffer = 0;
static DP_BOOL bCycleProceeding = DP_FALSE;
DP_BOOL bCurrentValidFlag;
printf ( "DP_SimulateDMAEngine \n" );
if ( eSimulatorMode == DP_DMA_ENGINE_SIMULATOR_INITIALISE )
{
/* This is a one time only call which sets the initial state of the DMA Engine. */
/* The 'completed' flag is set, so that the DMA Engine knows upon startup that it is */
/* not currently processing a buffer. */
#if defined SHOW_DMA_INTERFACE_OUTPUT
PDumpComment ( "DEL" );
#endif
DP_WriteFieldToAddress ( &(DP_asGlobalFieldTargets [ DP_GLOBAL_FIELD_HARDWARE_DISPATCHER_STATUS_FLAG ]),
(DP_UINT_32) DP_TRUE,
NULL );
#if defined SHOW_DMA_INTERFACE_OUTPUT
PDumpComment ( "DEL" );
#endif
/* Clear the 'valid' flag */
DP_WriteFieldToAddress ( &(DP_asGlobalFieldTargets [ DP_GLOBAL_FIELD_HARDWARE_DISPATCHER_PENDING_ADDRESS_VALID_FLAG ]),
(DP_UINT_32) DP_FALSE,
DP_NULL );
}
/* The DMA cycle can be split into three sections : */
/* 1) Establish whether there is a buffer pending. If there is, and it's not the same
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -