📄 xdma_channel_sg.c
字号:
/* $Id: xdma_channel_sg.c,v 1.6 2003/02/03 19:50:33 moleres Exp $ *//******************************************************************************** Author: Xilinx, Inc.*** This program is free software; you can redistribute it and/or modify it* under the terms of the GNU General Public License as published by the* Free Software Foundation; either version 2 of the License, or (at your* option) any later version.*** XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A* COURTESY TO YOU. 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 THIRD PARTY 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.*** Xilinx hardware products are not intended for use in life support* appliances, devices, or systems. Use in such applications is* expressly prohibited.*** (c) Copyright 2002-2004 Xilinx Inc.* All rights reserved.*** You should have received a copy of the GNU General Public License along* with this program; if not, write to the Free Software Foundation, Inc.,* 675 Mass Ave, Cambridge, MA 02139, USA.** FILENAME:** xdma_channel_sg.c** DESCRIPTION:** This file contains the implementation of the XDmaChannel component which is* related to scatter gather operations.** Scatter Gather Operations** 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.** Scatter Gather List Operations** 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 commited. 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.** Typical Scatter Gather Processing** 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.* 2. Create buffer descriptors which describe the buffers to be filled with* receive data or the buffers which contain data to be sent.* 3. Put buffer descriptors into the DMA channel scatter list such that scatter* gather operations are requested.* 4. Commit the buffer descriptors in the list such that they are ready to be* used by the DMA channel hardware.* 5. Start the scatter gather operations of the DMA channel.* 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.** Minimizing Interrupts** 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.** Interrupt Coalescing** 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.** Unserviced Packet Count** 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.** Packet Wait Bound** 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 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.** NOTES:** Special Test Conditions:** 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 commited (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.* Single Put And Commit** 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.** 3 Or More Puts And Commit** 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.** The 1st Put Following A Commit** 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.* </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) \{ \ *((u32 *)DestinationPtr + XBD_CONTROL_OFFSET) = \ *((u32 *)InstancePtr + XBD_CONTROL_OFFSET); \ *((u32 *)DestinationPtr + XBD_SOURCE_OFFSET) = \ *((u32 *)InstancePtr + XBD_SOURCE_OFFSET); \ *((u32 *)DestinationPtr + XBD_DESTINATION_OFFSET) = \ *((u32 *)InstancePtr + XBD_DESTINATION_OFFSET); \ *((u32 *)DestinationPtr + XBD_LENGTH_OFFSET) = \ *((u32 *)InstancePtr + XBD_LENGTH_OFFSET); \ *((u32 *)DestinationPtr + XBD_STATUS_OFFSET) = \ *((u32 *)InstancePtr + XBD_STATUS_OFFSET); \ *((u32 *)DestinationPtr + XBD_DEVICE_STATUS_OFFSET) = \ *((u32 *)InstancePtr + XBD_DEVICE_STATUS_OFFSET); \ *((u32 *)DestinationPtr + XBD_ID_OFFSET) = \ *((u32 *)InstancePtr + XBD_ID_OFFSET); \ *((u32 *)DestinationPtr + XBD_FLAGS_OFFSET) = \ *((u32 *)InstancePtr + XBD_FLAGS_OFFSET); \ *((u32 *)DestinationPtr + XBD_RQSTED_LENGTH_OFFSET) = \ *((u32 *)InstancePtr + XBD_RQSTED_LENGTH_OFFSET); \}/************************** Variable Definitions *****************************//************************** Function Prototypes ******************************//******************************************************************************** FUNCTION:** XDmaChannel_SgStart** DESCRIPTION:** 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.** 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 containing XST_SUCCESS if scatter gather was started successfully* for 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 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.** 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.** 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.** A value of XST_DMA_SG_NO_DATA indicates that the buffer descriptor of the
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -