⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xdma_channel_sg.c

📁 linux嵌入式系统的dma方式的实现代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* $Id: xdma_channel_sg.c,v 1.3 2006/07/24 17:50:20 xduan Exp $ *//********************************************************************************       XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS"*       AS A COURTESY TO YOU, SOLELY FOR USE IN DEVELOPING PROGRAMS AND*       SOLUTIONS FOR XILINX DEVICES.  BY PROVIDING THIS DESIGN, CODE,*       OR INFORMATION AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE,*       APPLICATION OR STANDARD, XILINX IS MAKING NO REPRESENTATION*       THAT THIS IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT,*       AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE*       FOR YOUR IMPLEMENTATION.  XILINX EXPRESSLY DISCLAIMS ANY*       WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE*       IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR*       REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF*       INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS*       FOR A PARTICULAR PURPOSE.**       (c) Copyright 2003-2004 Xilinx Inc.*       All rights reserved.*******************************************************************************//*****************************************************************************//**** @file xdma_channel_sg.c** <b>Description</b>** This file contains the implementation of the XDmaChannel component which is* related to scatter gather operations.** <b>Scatter Gather Operations</b>** The DMA channel may support scatter gather operations. A scatter gather* operation automates the DMA channel such that multiple buffers can be* sent or received with minimal software interaction with the hardware.  Buffer* descriptors, contained in the XBufDescriptor component, are used by the* scatter gather operations of the DMA channel to describe the buffers to be* processed.** <b>Scatter Gather List Operations</b>** A scatter gather list may be supported by each DMA channel.  The scatter* gather list allows buffer descriptors to be put into the list by a device* driver which requires scatter gather.  The hardware processes the buffer* descriptors which are contained in the list and modifies the buffer* descriptors to reflect the status of the DMA operations.  The device driver* is notified by interrupt that specific DMA events occur including scatter* gather events.  The device driver removes the completed buffer descriptors* from the scatter gather list to evaluate the status of each DMA operation.** The scatter gather list is created and buffer descriptors are inserted into* the list.  Buffer descriptors are never removed from the list after it's* creation such that a put operation copies from a temporary buffer descriptor* to a buffer descriptor in the list.  Get operations don't copy from the list* to a temporary, but return a pointer to the buffer descriptor in the list.* A buffer descriptor in the list may be locked to prevent it from being* overwritten by a put operation.  This allows the device driver to get a* descriptor from a scatter gather list and prevent it from being overwritten* until the buffer associated with the buffer descriptor has been processed.** The get and put functions only operate on the list and are asynchronous from* the hardware which may be using the list of descriptors.  This is important* because there are no checks in the get and put functions to ensure that the* hardware has processed the descriptors.  This must be handled by the driver* using the DMA scatter gather channel through the use of the other functions.* When a scatter gather operation is started, the start function does ensure* that the descriptor to start has not already been processed by the hardware* and is not the first of a series of descriptors that have not been committed* yet.** Descriptors are put into the list but not marked as ready to use by the* hardware until a commit operation is done.  This allows multiple descriptors* which may contain a single packet of information for a protocol to be* guaranteed not to cause any underflow conditions during transmission. The* hardware design only allows descriptors to cause it to stop after a descriptor* has been processed rather than before it is processed.  A series of* descriptors are put into the list followed by a commit operation, or each* descriptor may be committed.  A commit operation is performed by changing a* single descriptor, the first of the series of puts, to indicate that the* hardware may now use all descriptors after it.  The last descriptor in the* list is always set to cause the hardware to stop after it is processed.** <b>Typical Scatter Gather Processing</b>** The following steps illustrate the typical processing to use the* scatter gather features of a DMA channel.** 1. Create a scatter gather list for the DMA channel which puts empty buffer*    descriptors into the list.<br>* 2. Create buffer descriptors which describe the buffers to be filled with*    receive data or the buffers which contain data to be sent.<br>* 3. Put buffer descriptors into the DMA channel scatter list such that scatter*    gather operations are requested.<br>* 4. Commit the buffer descriptors in the list such that they are ready to be*    used by the DMA channel hardware.<br>* 5. Start the scatter gather operations of the DMA channel.<br>* 6. Process any interrupts which occur as a result of the scatter gather*    operations or poll the DMA channel to determine the status.  This may*    be accomplished by getting the packet count for the channel and then*    getting the appropriate number of descriptors from the list for that*    number of packets.** <b>Minimizing Interrupts</b>** The Scatter Gather operating mode is designed to reduce the amount of CPU* throughput necessary to manage the hardware for devices. A key to the CPU* throughput is the number and rate of interrupts that the CPU must service.* Devices with higher data rates can cause larger numbers of interrupts and* higher frequency interrupts. Ideally the number of interrupts can be reduced* by only generating an interrupt when a specific amount of data has been* received from the interface. This design suffers from a lack of interrupts* when the amount of data received is less than the specified amount of data* to generate an interrupt. In order to help minimize the number of interrupts* which the CPU must service, an algorithm referred to as "interrupt coalescing"* is utilized.** <b>Interrupt Coalescing</b>** The principle of interrupt coalescing is to wait before generating an* interrupt until a certain number of packets have been received or sent. An* interrupt is also generated if a smaller number of packets have been received* followed by a certain period of time with no packet reception. This is a* trade-off of latency for bandwidth and is accomplished using several* mechanisms of the hardware including a counter for packets received or* transmitted and a packet timer. These two hardware mechanisms work in* combination to allow a reduction in the number of interrupts processed by the* CPU for packet reception.** <b>Unserviced Packet Count</b>** The purpose of the packet counter is to count the number of packets received* or transmitted and provide an interrupt when a specific number of packets* have been processed by the hardware. An interrupt is generated whenever the* counter is greater than or equal to the Packet Count Threshold. This counter* contains an accurate count of the number of packets that the hardware has* processed, either received or transmitted, and the software has not serviced.** The packet counter allows the number of interrupts to be reduced by waiting* to generate an interrupt until enough packets are received. For packet* reception, packet counts of less than the number to generate an interrupt* would not be serviced without the addition of a packet timer. This counter is* continuously updated by the hardware, not latched to the value at the time* the interrupt occurred.** The packet counter can be used within the interrupt service routine for the* device to reduce the number of interrupts. The interrupt service routine* loops while performing processing for each packet which has been received or* transmitted and decrements the counter by a specified value. At the same time,* the hardware is possibly continuing to receive or transmit more packets such* that the software may choose, based upon the value in the packet counter, to* remain in the interrupt service routine rather than exiting and immediately* returning. This feature should be used with caution as reducing the number of* interrupts is beneficial, but unbounded interrupt processing is not desirable.** Since the hardware may be incrementing the packet counter simultaneously* with the software decrementing the counter, there is a need for atomic* operations. The hardware ensures that the operation is atomic such that* simultaneous accesses are properly handled.** <b>Packet Wait Bound</b>** The purpose of the packet wait bound is to augment the unserviced packet* count. Whenever there is no pending interrupt for the channel and the* unserviced packet count is non-zero, a timer starts counting timeout at the* value contained the packet wait bound register.  If the timeout is* reached, an interrupt is generated such that the software may service the* data which was buffered.** <b>Special Test Conditions:</b>** The scatter gather list processing must be thoroughly tested if changes are* made.  Testing should include putting and committing single descriptors and* putting multiple descriptors followed by a single commit.  There are some* conditions in the code which handle the exception conditions.** The Put Pointer points to the next location in the descriptor list to copy* in a new descriptor. The Get Pointer points to the next location in the* list to get a descriptor from.  The Get Pointer only allows software to* have a traverse the list after the hardware has finished processing some* number of descriptors.  The Commit Pointer points to the descriptor in the* list which is to be committed.  It is also used to determine that no* descriptor is waiting to be committed (NULL).  The Last Pointer points to* the last descriptor that was put into the list.  It typically points* to the previous descriptor to the one pointed to by the Put Pointer.* Comparisons are done between these pointers to determine when the following* special conditions exist.* <b>Single Put And Commit</b>** The buffer descriptor is ready to be used by the hardware so it is important* for the descriptor to not appear to be waiting to be committed.  The commit* pointer is reset when a commit is done indicating there are no descriptors* waiting to be committed.  In all cases but this one, the descriptor is* changed to cause the hardware to go to the next descriptor after processing* this one.  But in this case, this is the last descriptor in the list such* that it must not be changed.** <b>3 Or More Puts And Commit</b>** A series of 3 or more puts followed by a single commit is different in that* only the 1st descriptor put into the list is changed when the commit is done.* This requires each put starting on the 3rd to change the previous descriptor* so that it allows the hardware to continue to the next descriptor in the list.** <b>The 1st Put Following A Commit</b>** The commit caused the commit pointer to be NULL indicating that there are no* descriptors waiting to be committed.  It is necessary for the next put to set* the commit pointer so that a commit must follow the put for the hardware to* use the descriptor.** <pre>* MODIFICATION HISTORY:** Ver   Who  Date     Changes* ----- ---- -------- ------------------------------------------------------* 1.00a rpm  02/03/03 Removed the XST_DMA_SG_COUNT_EXCEEDED return code*                     from SetPktThreshold.*       rmm  12/04/03 CR 180871. Fixed XDmaChannel_SgStop() function.* 1.00a xd   10/27/04 Doxygenated for inclusion in API documentation* 1.00b ecm  10/31/05 Updated for the check sum offload changes.* 1.00b xd   03/22/06 Fixed a multi-descriptor packet related bug that sgdma*                     engine is restarted in case no scatter gather disabled*                     bit is set yet* </pre>*******************************************************************************//***************************** Include Files *********************************/#include "xdma_channel.h"#include "xbasic_types.h"#include "xio.h"#include "xbuf_descriptor.h"#include "xstatus.h"/************************** Constant Definitions *****************************/#define XDC_SWCR_SG_ENABLE_MASK 0x80000000UL /* scatter gather enable *//**************************** Type Definitions *******************************//***************** Macros (Inline Functions) Definitions *********************//** * the following macro copies selected fields of a buffer descriptor to another * buffer descriptor, this was provided by the buffer descriptor component but * was moved here since it is only used internally to this component and since * it does not copy all fields */#define CopyBufferDescriptor(InstancePtr, DestinationPtr)          \{                                                                  \    *((Xuint32 *)DestinationPtr + XBD_CONTROL_OFFSET) =            \        *((Xuint32 *)InstancePtr + XBD_CONTROL_OFFSET);            \    *((Xuint32 *)DestinationPtr + XBD_SOURCE_OFFSET) =             \        *((Xuint32 *)InstancePtr + XBD_SOURCE_OFFSET);             \    *((Xuint32 *)DestinationPtr + XBD_DESTINATION_OFFSET) =        \        *((Xuint32 *)InstancePtr + XBD_DESTINATION_OFFSET);        \    *((Xuint32 *)DestinationPtr + XBD_LENGTH_OFFSET) =             \        *((Xuint32 *)InstancePtr + XBD_LENGTH_OFFSET);             \    *((Xuint32 *)DestinationPtr + XBD_STATUS_OFFSET) =             \        *((Xuint32 *)InstancePtr + XBD_STATUS_OFFSET);             \    *((Xuint32 *)DestinationPtr + XBD_DEVICE_STATUS_OFFSET) =      \        *((Xuint32 *)InstancePtr + XBD_DEVICE_STATUS_OFFSET);      \    *((Xuint32 *)DestinationPtr + XBD_ID_OFFSET) =                 \        *((Xuint32 *)InstancePtr + XBD_ID_OFFSET);                 \    *((Xuint32 *)DestinationPtr + XBD_FLAGS_OFFSET) =              \        *((Xuint32 *)InstancePtr + XBD_FLAGS_OFFSET);              \    *((Xuint32 *)DestinationPtr + XBD_RQSTED_LENGTH_OFFSET) =      \        *((Xuint32 *)InstancePtr + XBD_RQSTED_LENGTH_OFFSET);      \}/************************** Variable Definitions *****************************//************************** Function Prototypes ******************************//*****************************************************************************//**** This function starts a scatter gather operation for a scatter gather* DMA channel.  The first buffer descriptor in the buffer descriptor list* will be started with the scatter gather operation.  A scatter gather list* should have previously been created for the DMA channel and buffer* descriptors put into the scatter gather list such that there are scatter* operations ready to be performed.** @param** 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* - A status containing XST_SUCCESS if scatter gather was started successfully*   for the DMA channel.*   <br><br>* - A value of XST_DMA_SG_NO_LIST indicates the scatter gather list has not*   been created.*   <br><br>* - A value of XST_DMA_SG_LIST_EMPTY indicates scatter gather was not started*   because the scatter gather list of the DMA channel does not contain any*   buffer descriptors that are ready to be processed by the hardware.*   <br><br>* - A value of XST_DMA_SG_IS_STARTED indicates scatter gather was not started*   because the scatter gather was not stopped, but was already started.*   <br><br>* - A value of XST_DMA_SG_BD_NOT_COMMITTED indicates the buffer descriptor of*   scatter gather list which was to be started is not committed to the list.*   This status is more likely if this function is being called from an ISR*   and non-ISR processing is putting descriptors into the list.*   <br><br>

⌨️ 快捷键说明

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