📄 xdma_multi_sg.c
字号:
** @param InstancePtr contains a pointer to the multichannel DMA to operate on.* The DMA channel should be configured to use scatter gather in order* for this function to be called.** @param Channel is the particular channel of interest.** @return* - XTRUE if the scatter gather list is empty, otherwise a value of* XFALSE.** @note** None.*******************************************************************************/Xboolean XDmaMulti_IsSgListEmpty(XDmaMulti *InstancePtr, unsigned Channel){ /* Assert to verify valid input arguments. */ XASSERT_NONVOID(InstancePtr != XNULL); XASSERT_NONVOID(InstancePtr->ChannelCount > Channel); 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 (CHANNEL_DATA.ActiveDescriptorCount == 0);}/*****************************************************************************//**** 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.** @param InstancePtr contains a pointer to the multichannel DMA to operate on.* The DMA channel should be configured to use scatter gather in order* for this function to be called.** @param Channel is the particular channel of interest.** @param BufferDescriptorPtr is a pointer to the buffer descriptor to be put into* the next available location of the scatter gather list.** @return* - XST_SUCCESS if the buffer descriptor was* successfully put into the scatter gather list.* <br><br>* - XST_DMA_SG_NO_LIST indicates the scatter gather list has not* been created.* <br><br>* - XST_DMA_SG_LIST_FULL indicates the buffer descriptor was not* put into the list because the list was full.* <br><br>* - 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.** @note** It is necessary to create a scatter gather list for a DMA channel before* putting buffer descriptors into it.*******************************************************************************/XStatus XDmaMulti_PutDescriptor(XDmaMulti *InstancePtr, unsigned Channel, XBufDescriptor *BufferDescriptorPtr){ Xuint32 Control; /* * Assert to verify valid input arguments and alignment for those * arguments that have alignment restrictions. */ XASSERT_NONVOID(InstancePtr != XNULL); XASSERT_NONVOID(InstancePtr->ChannelCount > Channel); XASSERT_NONVOID(BufferDescriptorPtr != XNULL); XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); /* If a scatter gather list has not been created yet, return a status. */ if (CHANNEL_DATA.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 (CHANNEL_DATA.ActiveDescriptorCount == CHANNEL_DATA.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(CHANNEL_DATA.PutPtr)) != 0) { return XST_DMA_SG_BD_LOCKED; } /* * Set the scatter gather stop bit in the control word of the descriptor * to cause the hw to stop after it processes this descriptor since it * will be the last in the list. */ Control = XBufDescriptor_GetControl(BufferDescriptorPtr); XBufDescriptor_SetControl(BufferDescriptorPtr, Control | XDM_DMACR_SG_STOP_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, XDM_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 hw, this assumes the descriptor in the list prior to this * one still has the stop bit in the control word set such that the hw * use this one yet. */ CopyBufferDescriptor(BufferDescriptorPtr, CHANNEL_DATA.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 ((CHANNEL_DATA.CommitPtr != CHANNEL_DATA.LastPtr) && (CHANNEL_DATA.CommitPtr != XNULL)) { Control = XBufDescriptor_GetControl(CHANNEL_DATA.LastPtr); XBufDescriptor_SetControl(CHANNEL_DATA.LastPtr, Control & ~XDM_DMACR_SG_STOP_MASK); } /* * Update the list data based upon putting a descriptor into the list, * these operations must be last. */ CHANNEL_DATA.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 (CHANNEL_DATA.CommitPtr == XNULL) { CHANNEL_DATA.CommitPtr = CHANNEL_DATA.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. */ CHANNEL_DATA.LastPtr = CHANNEL_DATA.PutPtr; CHANNEL_DATA.PutPtr = XBufDescriptor_GetNextPtr(CHANNEL_DATA.PutPtr); return XST_SUCCESS;}/*****************************************************************************//**** This function commits the buffer descriptors which have been put into the* scatter list for a 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).** @param InstancePtr contains a pointer to the multichannel DMA to operate on.* The DMA channel should be configured to use scatter gather in order* for this function to be called.** @param Channel is the particular channel of interest.** @return* - XST_SUCCESS if the buffer descriptors of the list were* successfully committed.* <br><br>* - 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 committed.** @note** None.*******************************************************************************/XStatus XDmaMulti_CommitPuts(XDmaMulti *InstancePtr, unsigned Channel){ /* Assert to verify input arguments. */ XASSERT_NONVOID(InstancePtr != XNULL); XASSERT_NONVOID(InstancePtr->ChannelCount > Channel); 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 ((CHANNEL_DATA.CommitPtr == XNULL) || XDmaMulti_IsSgListEmpty(InstancePtr, Channel) == XTRUE) { 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 hw, if descriptor to commit is not last in list, * commit descriptors by enabling scatter gather in the descriptor. */ if (CHANNEL_DATA.CommitPtr != CHANNEL_DATA.LastPtr) { Xuint32 Control; Control = XBufDescriptor_GetControl(CHANNEL_DATA.CommitPtr); XBufDescriptor_SetControl(CHANNEL_DATA .CommitPtr, Control & ~XDM_DMACR_SG_STOP_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. */ CHANNEL_DATA.CommitPtr = XNULL; return XST_SUCCESS;}/*****************************************************************************//**** 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.** @param InstancePtr contains a pointer to the multichannel DMA to operate on.* The DMA channel should be configured to use scatter gather in order* for this function to be called.** @param Channel is the particular channel of interest.** @param 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 a DMA channel.** @return* - XST_SUCCESS if a buffer descriptor was retrieved* <br><br>* - XST_DMA_SG_NO_LIST indicates the scatter gather list has not been created.* <br><br>* - 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.* <br><br>* - BufDescriptorPtr is updated to point to the buffer descriptor which was* retrieved from the list if the status indicates success.** @note** None.*******************************************************************************/XStatus XDmaMulti_GetDescriptor(XDmaMulti *InstancePtr, unsigned Channel, XBufDescriptor** BufDescriptorPtr){ Xuint32 Control; /* Assert to verify input arguments. */ XASSERT_NONVOID(InstancePtr != XNULL); XASSERT_NONVOID(InstancePtr->ChannelCount > Channel); XASSERT_NONVOID(BufDescriptorPtr != XNULL); XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); /* If a scatter gather list has not been created yet, return a status. */ if (CHANNEL_DATA.TotalDescriptorCount == 0) { return XST_DMA_SG_NO_LIST; } /* If the buffer descriptor list is empty, then indicate an error. */ if (XDmaMulti_IsSgListEmpty(InstancePtr, Channel) == XTRUE) { return XST_DMA_SG_LIST_EMPTY; } /* * Retrieve the next buffer descriptor which is ready to be processed from * the buffer descriptor list for a DMA channel, set the control word * such that hardware will stop after the descriptor has been processed. */ Control = XBufDescriptor_GetControl(CHANNEL_DATA.GetPtr); XBufDescriptor_SetControl(CHANNEL_DATA.GetPtr, Control | XDM_DMACR_SG_STOP_MASK); /* * Set the input argument, which is also an output, to point to the * buffer descriptor which is to be retrieved from the list. */ *BufDescriptorPtr = CHANNEL_DATA.GetPtr; /* * Update the pointer of a DMA channel to reflect the buffer descriptor * was retrieved from the list by setting it to the next buffer descriptor * in the list and indicate one less descriptor in the list now. */ CHANNEL_DATA.GetPtr = XBufDescriptor_GetNextPtr(CHANNEL_DATA.GetPtr); CHANNEL_DATA.ActiveDescriptorCount--; return XST_SUCCESS;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -