📄 dp_hardware_dispatcher.c
字号:
* 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 + -