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

📄 xdma_channel_sg.c

📁 omap osk环境下的bootloader,包含完整的uboot源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
* scatter gather list which was to be started had already been used by the* hardware for a DMA transfer that has been completed.** NOTES:** It is the responsibility of the caller to get all the buffer descriptors* after performing a stop operation and before performing a start operation.* If buffer descriptors are not retrieved between stop and start operations,* buffer descriptors may be processed by the hardware more than once.*******************************************************************************/XStatusXDmaChannel_SgStart(XDmaChannel * InstancePtr){	u32 Register;	XBufDescriptor *LastDescriptorPtr;	/* assert to verify input arguments */	XASSERT_NONVOID(InstancePtr != NULL);	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 scatter gather list exists but is empty then return a status */	if (XDmaChannel_IsSgListEmpty(InstancePtr)) {		return XST_DMA_SG_LIST_EMPTY;	}	/* if scatter gather is busy for the DMA channel, return a status because	 * restarting it could lose data	 */	Register = XIo_In32(InstancePtr->RegBaseAddress + XDC_DMAS_REG_OFFSET);	if (Register & XDC_DMASR_SG_BUSY_MASK) {		return XST_DMA_SG_IS_STARTED;	}	/* get the address of the last buffer descriptor which the DMA hardware	 * finished processing	 */	LastDescriptorPtr =	    (XBufDescriptor *) XIo_In32(InstancePtr->RegBaseAddress +					XDC_BDA_REG_OFFSET);	/* setup the first buffer descriptor that will be sent when the scatter	 * gather channel is enabled, this is only necessary one time since	 * the BDA register of the channel maintains the last buffer descriptor	 * processed	 */	if (LastDescriptorPtr == NULL) {		XIo_Out32(InstancePtr->RegBaseAddress + XDC_BDA_REG_OFFSET,			  (u32) InstancePtr->GetPtr);	} else {		XBufDescriptor *NextDescriptorPtr;		/* get the next descriptor to be started, if the status indicates it		 * hasn't already been used by the h/w, then it's OK to start it,		 * s/w sets the status of each descriptor to busy and then h/w clears		 * the busy when it is complete		 */		NextDescriptorPtr =		    XBufDescriptor_GetNextPtr(LastDescriptorPtr);		if ((XBufDescriptor_GetStatus(NextDescriptorPtr) &		     XDC_DMASR_BUSY_MASK) == 0) {			return XST_DMA_SG_NO_DATA;		}		/* don't start the DMA SG channel if the descriptor to be processed		 * by h/w is to be committed by the s/w, this function can be called		 * such that it interrupts a thread that was putting into the list		 */		if (NextDescriptorPtr == InstancePtr->CommitPtr) {			return XST_DMA_SG_BD_NOT_COMMITTED;		}	}	/* start the scatter gather operation by clearing the stop bit in the	 * control register and setting the enable bit in the s/w control register,	 * both of these are necessary to cause it to start, right now the order of	 * these statements is important, the software control register should be	 * set 1st.  The other order can cause the CPU to have a loss of sync	 * because it cannot read/write the register while the DMA operation is	 * running	 */	Register = XIo_In32(InstancePtr->RegBaseAddress + XDC_SWCR_REG_OFFSET);	XIo_Out32(InstancePtr->RegBaseAddress + XDC_SWCR_REG_OFFSET,		  Register | XDC_SWCR_SG_ENABLE_MASK);	Register = XIo_In32(InstancePtr->RegBaseAddress + XDC_DMAC_REG_OFFSET);	XIo_Out32(InstancePtr->RegBaseAddress + XDC_DMAC_REG_OFFSET,		  Register & ~XDC_DMACR_SG_DISABLE_MASK);	/* indicate the DMA channel scatter gather operation was started	 * successfully	 */	return XST_SUCCESS;}/******************************************************************************** FUNCTION:** XDmaChannel_SgStop** DESCRIPTION:** This function stops a scatter gather operation for a scatter gather* DMA channel. This function starts the process of stopping a scatter* gather operation that is in progress and waits for the stop to be completed.* Since it waits for the operation to stopped before returning, this function* could take an amount of time relative to the size of the DMA scatter gather* operation which is in progress.  The scatter gather list of the DMA channel* is not modified by this function such that starting the scatter gather* channel after stopping it will cause it to resume.  This operation is* considered to be a graceful stop in that the scatter gather operation* completes the current buffer descriptor before stopping.** If the interrupt is enabled, an interrupt will be generated when the* operation is stopped and the caller is responsible for handling the* interrupt.** 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 also a return value which contains a pointer to the* buffer descriptor which the scatter gather operation completed when it* was stopped.** RETURN VALUE:** A status containing XST_SUCCESS if scatter gather was stopped successfully* for the DMA channel.** A value of XST_DMA_SG_IS_STOPPED indicates scatter gather was not stoppped* because the scatter gather is not started, but was already stopped.** BufDescriptorPtr contains a pointer to the buffer descriptor which was* completed when the operation was stopped.** NOTES:** This function implements a loop which polls the hardware for an infinite* amount of time. If the hardware is not operating correctly, this function* may never return.*******************************************************************************/XStatusXDmaChannel_SgStop(XDmaChannel * InstancePtr,		   XBufDescriptor ** BufDescriptorPtr){	u32 Register;	/* assert to verify input arguments */	XASSERT_NONVOID(InstancePtr != NULL);	XASSERT_NONVOID(BufDescriptorPtr != NULL);	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);	/* get the contents of the software control register, if scatter gather is not	 * enabled (started), then return a status because the disable acknowledge	 * would not be generated	 */	Register = XIo_In32(InstancePtr->RegBaseAddress + XDC_SWCR_REG_OFFSET);	if ((Register & XDC_SWCR_SG_ENABLE_MASK) == 0) {		return XST_DMA_SG_IS_STOPPED;	}	/* Ensure the interrupt status for the scatter gather is cleared such	 * that this function will wait til the disable has occurred, writing	 * a 1 to only that bit in the register will clear only it	 */	XIo_Out32(InstancePtr->RegBaseAddress + XDC_IS_REG_OFFSET,		  XDC_IXR_SG_DISABLE_ACK_MASK);	/* disable scatter gather by writing to the software control register	 * without modifying any other bits of the register	 */	XIo_Out32(InstancePtr->RegBaseAddress + XDC_SWCR_REG_OFFSET,		  Register & ~XDC_SWCR_SG_ENABLE_MASK);	/* scatter gather does not disable immediately, but after the current	 * buffer descriptor is complete, so wait for the DMA channel to indicate	 * the disable is complete	 */	do {		Register =		    XIo_In32(InstancePtr->RegBaseAddress + XDC_IS_REG_OFFSET);	} while ((Register & XDC_IXR_SG_DISABLE_ACK_MASK) == 0);	/* Ensure the interrupt status for the scatter gather disable is cleared,	 * writing a 1 to only that bit in the register will clear only it	 */	XIo_Out32(InstancePtr->RegBaseAddress + XDC_IS_REG_OFFSET,		  XDC_IXR_SG_DISABLE_ACK_MASK);	/* set the specified buffer descriptor pointer to point to the buffer	 * descriptor that the scatter gather DMA channel was processing	 */	*BufDescriptorPtr =	    (XBufDescriptor *) XIo_In32(InstancePtr->RegBaseAddress +					XDC_BDA_REG_OFFSET);	return XST_SUCCESS;}/******************************************************************************** FUNCTION:** XDmaChannel_CreateSgList** DESCRIPTION:** This function creates a scatter gather list in the DMA channel.  A scatter* gather list consists of a list of buffer descriptors that are available to* be used for scatter gather operations.  Buffer descriptors are put into the* list to request a scatter gather operation to be performed.** A number of buffer descriptors are created from the specified memory and put* into a buffer descriptor list as empty buffer descriptors. This function must* be called before non-empty buffer descriptors may be put into the DMA channel* to request 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.** MemoryPtr contains a pointer to the memory which is to be used for buffer* descriptors and must not be cached.** ByteCount contains the number of bytes for the specified memory to be used* for buffer descriptors.** RETURN VALUE:** A status contains XST_SUCCESS if the scatter gather list was successfully* created.** A value of XST_DMA_SG_LIST_EXISTS indicates that the scatter gather list* was not created because the list has already been created.** NOTES:** None.*******************************************************************************/XStatusXDmaChannel_CreateSgList(XDmaChannel * InstancePtr,			 u32 * MemoryPtr, u32 ByteCount){	XBufDescriptor *BufferDescriptorPtr = (XBufDescriptor *) MemoryPtr;	XBufDescriptor *PreviousDescriptorPtr = NULL;	XBufDescriptor *StartOfListPtr = BufferDescriptorPtr;	u32 UsedByteCount;	/* assert to verify valid input arguments, alignment for those	 * arguments that have alignment restrictions, and at least enough	 * memory for one buffer descriptor	 */	XASSERT_NONVOID(InstancePtr != NULL);	XASSERT_NONVOID(MemoryPtr != NULL);	XASSERT_NONVOID(((u32) MemoryPtr & 3) == 0);	XASSERT_NONVOID(ByteCount != 0);	XASSERT_NONVOID(ByteCount >= sizeof (XBufDescriptor));	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);	/* if the scatter gather list has already been created, then return	 * with a status	 */	if (InstancePtr->TotalDescriptorCount != 0) {		return XST_DMA_SG_LIST_EXISTS;	}	/* loop thru the specified memory block and create as many buffer	 * descriptors as possible putting each into the list which is	 * implemented as a ring buffer, make sure not to use any memory which	 * is not large enough for a complete buffer descriptor	 */	UsedByteCount = 0;	while ((UsedByteCount + sizeof (XBufDescriptor)) <= ByteCount) {		/* setup a pointer to the next buffer descriptor in the memory and		 * update # of used bytes to know when all of memory is used		 */		BufferDescriptorPtr = (XBufDescriptor *) ((u32) MemoryPtr +							  UsedByteCount);		/* initialize the new buffer descriptor such that it doesn't contain		 * garbage which could be used by the DMA hardware		 */		XBufDescriptor_Initialize(BufferDescriptorPtr);		/* if this is not the first buffer descriptor to be created,		 * then link it to the last created buffer descriptor		 */		if (PreviousDescriptorPtr != NULL) {			XBufDescriptor_SetNextPtr(PreviousDescriptorPtr,						  BufferDescriptorPtr);		}		/* always keep a pointer to the last created buffer descriptor such		 * that they can be linked together in the ring buffer		 */		PreviousDescriptorPtr = BufferDescriptorPtr;		/* keep a count of the number of descriptors in the list to allow		 * error processing to be performed		 */		InstancePtr->TotalDescriptorCount++;		UsedByteCount += sizeof (XBufDescriptor);	}	/* connect the last buffer descriptor created and inserted in the list	 * to the first such that a ring buffer is created	 */

⌨️ 快捷键说明

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