xdma_channel_sg.c

来自「适合KS8695X」· C语言 代码 · 共 1,318 行 · 第 1/4 页

C
1,318
字号
	XBufDescriptor_SetNextPtr(BufferDescriptorPtr, StartOfListPtr);

	/* initialize the ring buffer to indicate that there are no
	 * buffer descriptors in the list which point to valid data buffers
	 */
	InstancePtr->PutPtr = BufferDescriptorPtr;
	InstancePtr->GetPtr = BufferDescriptorPtr;
	InstancePtr->CommitPtr = NULL;
	InstancePtr->LastPtr = BufferDescriptorPtr;
	InstancePtr->ActiveDescriptorCount = 0;

	/* indicate the scatter gather list was successfully created */

	return XST_SUCCESS;
}

/******************************************************************************
*
* FUNCTION:
*
* XDmaChannel_IsSgListEmpty
*
* DESCRIPTION:
*
* This function determines if the scatter gather list of a DMA channel is
* empty with regard to buffer descriptors which are pointing to buffers to be
* used for scatter gather operations.
*
* ARGUMENTS:
*
* InstancePtr contains a pointer to the DMA channel to operate on.  The DMA
* channel should be configured to use scatter gather in order for this function
* to be called.
*
* RETURN VALUE:
*
* A value of TRUE if the scatter gather list is empty, otherwise a value of
* FALSE.
*
* NOTES:
*
* None.
*
******************************************************************************/
u32
XDmaChannel_IsSgListEmpty(XDmaChannel * InstancePtr)
{
	/* assert to verify valid input arguments */

	XASSERT_NONVOID(InstancePtr != NULL);
	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);

	/* if the number of descriptors which are being used in the list is zero
	 * then the list is empty
	 */
	return (InstancePtr->ActiveDescriptorCount == 0);
}

/******************************************************************************
*
* FUNCTION:
*
* XDmaChannel_PutDescriptor
*
* DESCRIPTION:
*
* This function puts a buffer descriptor into the DMA channel scatter
* gather list. A DMA channel maintains a list of buffer descriptors which are
* to be processed.  This function puts the specified buffer descriptor
* at the next location in the list.  Note that since the list is already intact,
* the information in the parameter is copied into the list (rather than modify
* list pointers on the fly).
*
* After buffer descriptors are put into the list, they must also be committed
* by calling another function.	This allows multiple buffer descriptors which
* span a single packet to be put into the list while preventing the hardware
* from starting the first buffer descriptor of the packet.
*
* ARGUMENTS:
*
* InstancePtr contains a pointer to the DMA channel to operate on.  The DMA
* channel should be configured to use scatter gather in order for this function
* to be called.
*
* BufferDescriptorPtr is a pointer to the buffer descriptor to be put into
* the next available location of the scatter gather list.
*
* RETURN VALUE:
*
* A status which indicates XST_SUCCESS if the buffer descriptor was
* successfully put into the scatter gather list.
*
* A value of XST_DMA_SG_NO_LIST indicates the scatter gather list has not
* been created.
*
* A value of XST_DMA_SG_LIST_FULL indicates the buffer descriptor was not
* put into the list because the list was full.
*
* A value of XST_DMA_SG_BD_LOCKED indicates the buffer descriptor was not
* put into the list because the buffer descriptor in the list which is to
* be overwritten was locked.  A locked buffer descriptor indicates the higher
* layered software is still using the buffer descriptor.
*
* NOTES:
*
* It is necessary to create a scatter gather list for a DMA channel before
* putting buffer descriptors into it.
*
******************************************************************************/
XStatus
XDmaChannel_PutDescriptor(XDmaChannel * InstancePtr,
			  XBufDescriptor * BufferDescriptorPtr)
{
	u32 Control;

	/* assert to verify valid input arguments and alignment for those
	 * arguments that have alignment restrictions
	 */
	XASSERT_NONVOID(InstancePtr != NULL);
	XASSERT_NONVOID(BufferDescriptorPtr != NULL);
	XASSERT_NONVOID(((u32) BufferDescriptorPtr & 3) == 0);
	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);

	/* if a scatter gather list has not been created yet, return a status */

	if (InstancePtr->TotalDescriptorCount == 0) {
		return XST_DMA_SG_NO_LIST;
	}

	/* if the list is full because all descriptors are pointing to valid
	 * buffers, then indicate an error, this code assumes no list or an
	 * empty list is detected above
	 */
	if (InstancePtr->ActiveDescriptorCount ==
	    InstancePtr->TotalDescriptorCount) {
		return XST_DMA_SG_LIST_FULL;
	}

	/* if the buffer descriptor in the list which is to be overwritten is
	 * locked, then don't overwrite it and return a status
	 */
	if (XBufDescriptor_IsLocked(InstancePtr->PutPtr)) {
		return XST_DMA_SG_BD_LOCKED;
	}

	/* set the scatter gather stop bit in the control word of the descriptor
	 * to cause the h/w to stop after it processes this descriptor since it
	 * will be the last in the list
	 */
	Control = XBufDescriptor_GetControl(BufferDescriptorPtr);
	XBufDescriptor_SetControl(BufferDescriptorPtr,
				  Control | XDC_DMACR_SG_DISABLE_MASK);

	/* set both statuses in the descriptor so we tell if they are updated with
	 * the status of the transfer, the hardware should change the busy in the
	 * DMA status to be false when it completes
	 */
	XBufDescriptor_SetStatus(BufferDescriptorPtr, XDC_DMASR_BUSY_MASK);
	XBufDescriptor_SetDeviceStatus(BufferDescriptorPtr, 0);

	/* copy the descriptor into the next position in the list so it's ready to
	 * be used by the h/w, this assumes the descriptor in the list prior to this
	 * one still has the stop bit in the control word set such that the h/w
	 * use this one yet
	 */
	CopyBufferDescriptor(BufferDescriptorPtr, InstancePtr->PutPtr);

	/* only the last in the list and the one to be committed have scatter gather
	 * disabled in the control word, a commit requires only one descriptor
	 * to be changed, when # of descriptors to commit > 2 all others except the
	 * 1st and last have scatter gather enabled
	 */
	if ((InstancePtr->CommitPtr != InstancePtr->LastPtr) &&
	    (InstancePtr->CommitPtr != NULL)) {
		Control = XBufDescriptor_GetControl(InstancePtr->LastPtr);
		XBufDescriptor_SetControl(InstancePtr->LastPtr,
					  Control & ~XDC_DMACR_SG_DISABLE_MASK);
	}

	/* update the list data based upon putting a descriptor into the list,
	 * these operations must be last
	 */
	InstancePtr->ActiveDescriptorCount++;

	/* only update the commit pointer if it is not already active, this allows
	 * it to be deactivated after every commit such that a single descriptor
	 * which is committed does not appear to be waiting to be committed
	 */
	if (InstancePtr->CommitPtr == NULL) {
		InstancePtr->CommitPtr = InstancePtr->LastPtr;
	}

	/* these updates MUST BE LAST after the commit pointer update in order for
	 * the commit pointer to track the correct descriptor to be committed
	 */
	InstancePtr->LastPtr = InstancePtr->PutPtr;
	InstancePtr->PutPtr = XBufDescriptor_GetNextPtr(InstancePtr->PutPtr);

	return XST_SUCCESS;
}

/******************************************************************************
*
* FUNCTION:
*
* XDmaChannel_CommitPuts
*
* DESCRIPTION:
*
* This function commits the buffer descriptors which have been put into the
* scatter list for the DMA channel since the last commit operation was
* performed.  This enables the calling functions to put several buffer
* descriptors into the list (e.g.,a packet's worth) before allowing the scatter
* gather operations to start.  This prevents the DMA channel hardware from
* starting to use the buffer descriptors in the list before they are ready
* to be used (multiple buffer descriptors for a single packet).
*
* ARGUMENTS:
*
* InstancePtr contains a pointer to the DMA channel to operate on.  The DMA
* channel should be configured to use scatter gather in order for this function
* to be called.
*
* RETURN VALUE:
*
* A status indicating XST_SUCCESS if the buffer descriptors of the list were
* successfully committed.
*
* A value of XST_DMA_SG_NOTHING_TO_COMMIT indicates that the buffer descriptors
* were not committed because there was nothing to commit in the list.  All the
* buffer descriptors which are in the list are commited.
*
* NOTES:
*
* None.
*
******************************************************************************/
XStatus
XDmaChannel_CommitPuts(XDmaChannel * InstancePtr)
{
	/* assert to verify input arguments */

	XASSERT_NONVOID(InstancePtr != NULL);
	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);

	/* if the buffer descriptor to be committed is already committed or
	 * the list is empty (none have been put in), then indicate an error
	 */
	if ((InstancePtr->CommitPtr == NULL) ||
	    XDmaChannel_IsSgListEmpty(InstancePtr)) {
		return XST_DMA_SG_NOTHING_TO_COMMIT;
	}

	/* last descriptor in the list must have scatter gather disabled so the end
	 * of the list is hit by h/w, if descriptor to commit is not last in list,
	 * commit descriptors by enabling scatter gather in the descriptor
	 */
	if (InstancePtr->CommitPtr != InstancePtr->LastPtr) {
		u32 Control;

		Control = XBufDescriptor_GetControl(InstancePtr->CommitPtr);
		XBufDescriptor_SetControl(InstancePtr->CommitPtr, Control &
					  ~XDC_DMACR_SG_DISABLE_MASK);
	}
	/* Update the commit pointer to indicate that there is nothing to be
	 * committed, this state is used by start processing to know that the
	 * buffer descriptor to start is not waiting to be committed
	 */
	InstancePtr->CommitPtr = NULL;

	return XST_SUCCESS;
}

/******************************************************************************
*
* FUNCTION:
*
* XDmaChannel_GetDescriptor
*
* DESCRIPTION:
*
* This function gets a buffer descriptor from the scatter gather list of the
* DMA channel. The buffer descriptor is retrieved from the scatter gather list
* and the scatter gather list is updated to not include the retrieved buffer
* descriptor.  This is typically done after a scatter gather operation
* completes indicating that a data buffer has been successfully sent or data
* has been received into the data buffer. The purpose of this function is to
* allow the device using the scatter gather operation to get the results of the
* operation.
*
* ARGUMENTS:
*
* InstancePtr contains a pointer to the DMA channel to operate on.  The DMA
* channel should be configured to use scatter gather in order for this function
* to be called.
*
* BufDescriptorPtr is a pointer to a pointer to the buffer descriptor which
* was retrieved from the list.	The buffer descriptor is not really removed
* from the list, but it is changed to a state such that the hardware will not
* use it again until it is put into the scatter gather list of the DMA channel.
*
* RETURN VALUE:
*
* A status indicating XST_SUCCESS if a buffer descriptor was retrieved from
* the scatter gather list of the DMA channel.
*
* A value of XST_DMA_SG_NO_LIST indicates the scatter gather list has not
* been created.
*
* A value of XST_DMA_SG_LIST_EMPTY indicates no buffer descriptor was
* retrieved from the list because there are no buffer descriptors to be
* processed in the list.
*
* BufDescriptorPtr is updated to point to the buffer descriptor which was
* retrieved from the list if the status indicates success.
*
* NOTES:
*
* None.
*
******************************************************************************/
XStatus
XDmaChannel_GetDescriptor(XDmaChannel * InstancePtr,
			  XBufDescriptor ** BufDescriptorPtr)
{
	u32 Control;

	/* assert to verify input arguments */

	XASSERT_NONVOID(InstancePtr != NULL);

⌨️ 快捷键说明

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