/****************************************************************************** * * 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.c * * DESCRIPTION: * * This file contains the DMA channel component. This component supports * a distributed DMA design in which each device can have it's own dedicated * DMA channel, as opposed to a centralized DMA design. This component * performs processing for DMA on all devices. * * See xdma_channel.h for more information about this component. * * NOTES: * * None. * ******************************************************************************/ /***************************** Include Files *********************************/ #include "xdma_channel.h" #include "xbasic_types.h" #include "xio.h" /************************** Constant Definitions *****************************/ /**************************** Type Definitions *******************************/ /***************** Macros (Inline Functions) Definitions *********************/ /************************** Function Prototypes ******************************/ /****************************************************************************** * * FUNCTION: * * XDmaChannel_Initialize * * DESCRIPTION: * * This function initializes a DMA channel. This function must be called * prior to using a DMA channel. Initialization of a channel includes setting * up the registers base address, and resetting the channel such that it's in a * known state. Interrupts for the channel are disabled when the channel is * reset. * * ARGUMENTS: * * InstancePtr contains a pointer to the DMA channel to operate on. * * BaseAddress contains the base address of the registers for the DMA channel. * * RETURN VALUE: * * XST_SUCCESS indicating initialization was successful. * * NOTES: * * None. * ******************************************************************************/ XStatus XDmaChannel_Initialize(XDmaChannel * InstancePtr, u32 BaseAddress) { /* assert to verify input arguments, don't assert base address */ XASSERT_NONVOID(InstancePtr != NULL); /* setup the base address of the registers for the DMA channel such * that register accesses can be done */ InstancePtr->RegBaseAddress = BaseAddress; /* initialize the scatter gather list such that it indicates it has not * been created yet and the DMA channel is ready to use (initialized) */ InstancePtr->GetPtr = NULL; InstancePtr->PutPtr = NULL; InstancePtr->CommitPtr = NULL; InstancePtr->LastPtr = NULL; InstancePtr->TotalDescriptorCount = 0; InstancePtr->ActiveDescriptorCount = 0; InstancePtr->IsReady = XCOMPONENT_IS_READY; /* initialize the version of the component */ XVersion_FromString(&InstancePtr->Version, "1.00a"); /* reset the DMA channel such that it's in a known state and ready * and indicate the initialization occured with no errors, note that * the is ready variable must be set before this call or reset will assert */ XDmaChannel_Reset(InstancePtr); return XST_SUCCESS; } /****************************************************************************** * * FUNCTION: * * XDmaChannel_IsReady * * DESCRIPTION: * * This function determines if a DMA channel component has been successfully * initialized such that it's ready to use. * * ARGUMENTS: * * InstancePtr contains a pointer to the DMA channel to operate on. * * RETURN VALUE: * * TRUE if the DMA channel component is ready, FALSE otherwise. * * NOTES: * * None. * ******************************************************************************/ u32 XDmaChannel_IsReady(XDmaChannel * InstancePtr) { /* assert to verify input arguments used by the base component */ XASSERT_NONVOID(InstancePtr != NULL); return InstancePtr->IsReady == XCOMPONENT_IS_READY; } /****************************************************************************** * * FUNCTION: * * XDmaChannel_GetVersion * * DESCRIPTION: * * This function gets the software version for the specified DMA channel * component. * * ARGUMENTS: * * InstancePtr contains a pointer to the DMA channel to operate on. * * RETURN VALUE: * * A pointer to the software version of the specified DMA channel. * * NOTES: * * None. * ******************************************************************************/ XVersion * XDmaChannel_GetVersion(XDmaChannel * InstancePtr) { /* assert to verify input arguments */ XASSERT_NONVOID(InstancePtr != NULL); XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); /* return a pointer to the version of the DMA channel */ return &InstancePtr->Version; } /****************************************************************************** * * FUNCTION: * * XDmaChannel_SelfTest * * DESCRIPTION: * * This function performs a self test on the specified DMA channel. This self * test is destructive as the DMA channel is reset and a register default is * verified. * * ARGUMENTS: * * InstancePtr is a pointer to the DMA channel to be operated on. * * RETURN VALUE: * * XST_SUCCESS is returned if the self test is successful, or one of the * following errors. * * XST_DMA_RESET_REGISTER_ERROR Indicates the control register value * after a reset was not correct * * NOTES: * * This test does not performs a DMA transfer to test the channel because the * DMA hardware will not currently allow a non-local memory transfer to non-local * memory (memory copy), but only allows a non-local memory to or from the device * memory (typically a FIFO). * ******************************************************************************/ #define XDC_CONTROL_REG_RESET_MASK 0x98000000UL /* control reg reset value */ XStatus XDmaChannel_SelfTest(XDmaChannel * InstancePtr) { u32 ControlReg; /* assert to verify input arguments */ XASSERT_NONVOID(InstancePtr != NULL); XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); /* reset the DMA channel such that it's in a known state before the test * it resets to no interrupts enabled, the desired state for the test */ XDmaChannel_Reset(InstancePtr); /* this should be the first test to help prevent a lock up with the polling * loop that occurs later in the test, check the reset value of the DMA * control register to make sure it's correct, return with an error if not */ ControlReg = XDmaChannel_GetControl(InstancePtr); if (ControlReg != XDC_CONTROL_REG_RESET_MASK) { return XST_DMA_RESET_REGISTER_ERROR; } return XST_SUCCESS; } /****************************************************************************** * * FUNCTION: * * XDmaChannel_Reset * * DESCRIPTION: * * This function resets the DMA channel. This is a destructive operation such * that it should not be done while a channel is being used. If the DMA channel * is transferring data into other blocks, such as a FIFO, it may be necessary * to reset other blocks. This function does not modify the contents of a * scatter gather list for a DMA channel such that the user is responsible for * getting buffer descriptors from the list if necessary. * * ARGUMENTS: * * InstancePtr contains a pointer to the DMA channel to operate on. * * RETURN VALUE: * * None. * * NOTES: * * None. * ******************************************************************************/ void XDmaChannel_Reset(XDmaChannel * InstancePtr) { /* assert to verify input arguments */ XASSERT_VOID(InstancePtr != NULL); XASSERT_VOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); /* reset the DMA channel such that it's in a known state, the reset * register is self clearing such that it only has to be set */ XIo_Out32(InstancePtr->RegBaseAddress + XDC_RST_REG_OFFSET, XDC_RESET_MASK); } /****************************************************************************** * * FUNCTION: * * XDmaChannel_GetControl * * DESCRIPTION: * * This function gets the control register contents of the DMA channel. * * ARGUMENTS: * * InstancePtr contains a pointer to the DMA channel to operate on. * * RETURN VALUE: * * The control register contents of the DMA channel. One or more of the * following values may be contained the register. Each of the values are * unique bit masks. * * XDC_DMACR_SOURCE_INCR_MASK Increment the source address * XDC_DMACR_DEST_INCR_MASK Increment the destination address * XDC_DMACR_SOURCE_LOCAL_MASK Local source address * XDC_DMACR_DEST_LOCAL_MASK Local destination address * XDC_DMACR_SG_ENABLE_MASK Scatter gather enable * XDC_DMACR_GEN_BD_INTR_MASK Individual buffer descriptor interrupt * XDC_DMACR_LAST_BD_MASK Last buffer descriptor in a packet * * NOTES: * * None. * ******************************************************************************/ u32 XDmaChannel_GetControl(XDmaChannel * InstancePtr) { /* assert to verify input arguments */ XASSERT_NONVOID(InstancePtr != NULL); XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); /* return the contents of the DMA control register */ return XIo_In32(InstancePtr->RegBaseAddress + XDC_DMAC_REG_OFFSET); } /****************************************************************************** * * FUNCTION: * * XDmaChannel_SetControl * * DESCRIPTION: * * This function sets the control register of the specified DMA channel. * * ARGUMENTS: * * InstancePtr contains a pointer to the DMA channel to operate on. * * Control contains the value to be written to the control register of the DMA * channel. One or more of the following values may be contained the register. * Each of the values are unique bit masks such that they may be ORed together * to enable multiple bits or inverted and ANDed to disable multiple bits. * * XDC_DMACR_SOURCE_INCR_MASK Increment the source address * XDC_DMACR_DEST_INCR_MASK Increment the destination address * XDC_DMACR_SOURCE_LOCAL_MASK Local source address * XDC_DMACR_DEST_LOCAL_MASK Local destination address * XDC_DMACR_SG_ENABLE_MASK Scatter gather enable * XDC_DMACR_GEN_BD_INTR_MASK Individual buffer descriptor interrupt * XDC_DMACR_LAST_BD_MASK Last buffer descriptor in a packet * * RETURN VALUE: * * None. * * NOTES: * * None. * ******************************************************************************/ void XDmaChannel_SetControl(XDmaChannel * InstancePtr, u32 Control) { /* assert to verify input arguments except the control which can't be * asserted since all values are valid */ XASSERT_VOID(InstancePtr != NULL); XASSERT_VOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); /* set the DMA control register to the specified value */ XIo_Out32(InstancePtr->RegBaseAddress + XDC_DMAC_REG_OFFSET, Control); } /****************************************************************************** * * FUNCTION: * * XDmaChannel_GetStatus * * DESCRIPTION: * * This function gets the status register contents of the DMA channel. * * ARGUMENTS: * * InstancePtr contains a pointer to the DMA channel to operate on. * * RETURN VALUE: * * The status register contents of the DMA channel. One or more of the * following values may be contained the register. Each of the values are * unique bit masks. * * XDC_DMASR_BUSY_MASK The DMA channel is busy * XDC_DMASR_BUS_ERROR_MASK A bus error occurred * XDC_DMASR_BUS_TIMEOUT_MASK A bus timeout occurred * XDC_DMASR_LAST_BD_MASK The last buffer descriptor of a packet * * NOTES: * * None. * ******************************************************************************/ u32 XDmaChannel_GetStatus(XDmaChannel * InstancePtr) { /* assert to verify input arguments */ XASSERT_NONVOID(InstancePtr != NULL); XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); /* return the contents of the DMA status register */ return XIo_In32(InstancePtr->RegBaseAddress + XDC_DMAS_REG_OFFSET); } /****************************************************************************** * * FUNCTION: * * XDmaChannel_SetIntrStatus * * DESCRIPTION: * * This function sets the interrupt status register of the specified DMA channel. * Setting any bit of the interrupt status register will clear the bit to * indicate the interrupt processing has been completed. The definitions of each * bit in the register match the definition of the bits in the interrupt enable * register. * * ARGUMENTS: * * InstancePtr contains a pointer to the DMA channel to operate on. * * Status contains the value to be written to the status register of the DMA * channel. One or more of the following values may be contained the register. * Each of the values are unique bit masks such that they may be ORed together * to enable multiple bits or inverted and ANDed to disable multiple bits. * * XDC_IXR_DMA_DONE_MASK The dma operation is done * XDC_IXR_DMA_ERROR_MASK The dma operation had an error * XDC_IXR_PKT_DONE_MASK A packet is complete * XDC_IXR_PKT_THRESHOLD_MASK The packet count threshold reached * XDC_IXR_PKT_WAIT_BOUND_MASK The packet wait bound reached * XDC_IXR_SG_DISABLE_ACK_MASK The scatter gather disable completed * XDC_IXR_BD_MASK A buffer descriptor is done * * RETURN VALUE: * * None. * * NOTES: * * None. * ******************************************************************************/ void XDmaChannel_SetIntrStatus(XDmaChannel * InstancePtr, u32 Status) { /* assert to verify input arguments except the status which can't be * asserted since all values are valid */ XASSERT_VOID(InstancePtr != NULL); XASSERT_VOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); /* set the interrupt status register with the specified value such that * all bits which are set in the register are cleared effectively clearing * any active interrupts */ XIo_Out32(InstancePtr->RegBaseAddress + XDC_IS_REG_OFFSET, Status); } /****************************************************************************** * * FUNCTION: * * XDmaChannel_GetIntrStatus * * DESCRIPTION: * * This function gets the interrupt status register of the specified DMA channel. * The interrupt status register indicates which interrupts are active * for the DMA channel. If an interrupt is active, the status register must be * set (written) with the bit set for each interrupt which has been processed * in order to clear the interrupts. The definitions of each bit in the register * match the definition of the bits in the interrupt enable register. * * ARGUMENTS: * * InstancePtr contains a pointer to the DMA channel to operate on. * * RETURN VALUE: * * The interrupt status register contents of the specified DMA channel. * One or more of the following values may be contained the register. * Each of the values are unique bit masks. * * XDC_IXR_DMA_DONE_MASK The dma operation is done * XDC_IXR_DMA_ERROR_MASK The dma operation had an error * XDC_IXR_PKT_DONE_MASK A packet is complete * XDC_IXR_PKT_THRESHOLD_MASK The packet count threshold reached * XDC_IXR_PKT_WAIT_BOUND_MASK The packet wait bound reached * XDC_IXR_SG_DISABLE_ACK_MASK The scatter gather disable completed * XDC_IXR_SG_END_MASK Current descriptor was the end of the list * XDC_IXR_BD_MASK A buffer descriptor is done * * NOTES: * * None. * ******************************************************************************/ u32 XDmaChannel_GetIntrStatus(XDmaChannel * InstancePtr) { /* assert to verify input arguments */ XASSERT_NONVOID(InstancePtr != NULL); XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); /* return the contents of the interrupt status register */ return XIo_In32(InstancePtr->RegBaseAddress + XDC_IS_REG_OFFSET); } /****************************************************************************** * * FUNCTION: * * XDmaChannel_SetIntrEnable * * DESCRIPTION: * * This function sets the interrupt enable register of the specified DMA * channel. The interrupt enable register contains bits which enable * individual interrupts for the DMA channel. The definitions of each bit * in the register match the definition of the bits in the interrupt status * register. * * ARGUMENTS: * * InstancePtr contains a pointer to the DMA channel to operate on. * * Enable contains the interrupt enable register contents to be written * in the DMA channel. One or more of the following values may be contained * the register. Each of the values are unique bit masks such that they may be * ORed together to enable multiple bits or inverted and ANDed to disable * multiple bits. * * XDC_IXR_DMA_DONE_MASK The dma operation is done * XDC_IXR_DMA_ERROR_MASK The dma operation had an error * XDC_IXR_PKT_DONE_MASK A packet is complete * XDC_IXR_PKT_THRESHOLD_MASK The packet count threshold reached * XDC_IXR_PKT_WAIT_BOUND_MASK The packet wait bound reached * XDC_IXR_SG_DISABLE_ACK_MASK The scatter gather disable completed * XDC_IXR_SG_END_MASK Current descriptor was the end of the list * XDC_IXR_BD_MASK A buffer descriptor is done * * RETURN VALUE: * * None. * * NOTES: * * None. * ******************************************************************************/ void XDmaChannel_SetIntrEnable(XDmaChannel * InstancePtr, u32 Enable) { /* assert to verify input arguments except the enable which can't be * asserted since all values are valid */ XASSERT_VOID(InstancePtr != NULL); XASSERT_VOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); /* set the interrupt enable register to the specified value */ XIo_Out32(InstancePtr->RegBaseAddress + XDC_IE_REG_OFFSET, Enable); } /****************************************************************************** * * FUNCTION: * * XDmaChannel_GetIntrEnable * * DESCRIPTION: * * This function gets the interrupt enable of the DMA channel. The * interrupt enable contains flags which enable individual interrupts for the * DMA channel. The definitions of each bit in the register match the definition * of the bits in the interrupt status register. * * ARGUMENTS: * * InstancePtr contains a pointer to the DMA channel to operate on. * * RETURN VALUE: * * The interrupt enable of the DMA channel. One or more of the following values * may be contained the register. Each of the values are unique bit masks. * * XDC_IXR_DMA_DONE_MASK The dma operation is done * XDC_IXR_DMA_ERROR_MASK The dma operation had an error * XDC_IXR_PKT_DONE_MASK A packet is complete * XDC_IXR_PKT_THRESHOLD_MASK The packet count threshold reached * XDC_IXR_PKT_WAIT_BOUND_MASK The packet wait bound reached * XDC_IXR_SG_DISABLE_ACK_MASK The scatter gather disable completed * XDC_IXR_BD_MASK A buffer descriptor is done * * NOTES: * * None. * ******************************************************************************/ u32 XDmaChannel_GetIntrEnable(XDmaChannel * InstancePtr) { /* assert to verify input arguments */ XASSERT_NONVOID(InstancePtr != NULL); XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); /* return the contents of the interrupt enable register */ return XIo_In32(InstancePtr->RegBaseAddress + XDC_IE_REG_OFFSET); } /****************************************************************************** * * FUNCTION: * * XDmaChannel_Transfer * * DESCRIPTION: * * This function starts the DMA channel transferring data from a memory source * to a memory destination. This function only starts the operation and returns * before the operation may be complete. If the interrupt is enabled, an * interrupt will be generated when the operation is complete, otherwise it is * necessary to poll the channel status to determine when it's complete. It is * the responsibility of the caller to determine when the operation is complete * by handling the generated interrupt or polling the status. It is also the * responsibility of the caller to ensure that the DMA channel is not busy with * another transfer before calling this function. * * ARGUMENTS: * * InstancePtr contains a pointer to the DMA channel to operate on. * * SourcePtr contains a pointer to the source memory where the data is to * be tranferred from and must be 32 bit aligned. * * DestinationPtr contains a pointer to the destination memory where the data * is to be transferred and must be 32 bit aligned. * * ByteCount contains the number of bytes to transfer during the DMA operation. * * RETURN VALUE: * * None. * * NOTES: * * The DMA h/w will not currently allow a non-local memory transfer to non-local * memory (memory copy), but only allows a non-local memory to or from the device * memory (typically a FIFO). * * It is the responsibility of the caller to ensure that the cache is * flushed and invalidated both before and after the DMA operation completes * if the memory pointed to is cached. The caller must also ensure that the * pointers contain a physical address rather than a virtual address * if address translation is being used. * ******************************************************************************/ void XDmaChannel_Transfer(XDmaChannel * InstancePtr, u32 * SourcePtr, u32 * DestinationPtr, u32 ByteCount) { /* assert to verify input arguments and the alignment of any arguments * which have expected alignments */ XASSERT_VOID(InstancePtr != NULL); XASSERT_VOID(SourcePtr != NULL); XASSERT_VOID(((u32) SourcePtr & 3) == 0); XASSERT_VOID(DestinationPtr != NULL); XASSERT_VOID(((u32) DestinationPtr & 3) == 0); XASSERT_VOID(ByteCount != 0); XASSERT_VOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); /* setup the source and destination address registers for the transfer */ XIo_Out32(InstancePtr->RegBaseAddress + XDC_SA_REG_OFFSET, (u32) SourcePtr); XIo_Out32(InstancePtr->RegBaseAddress + XDC_DA_REG_OFFSET, (u32) DestinationPtr); /* start the DMA transfer to copy from the source buffer to the * destination buffer by writing the length to the length register */ XIo_Out32(InstancePtr->RegBaseAddress + XDC_LEN_REG_OFFSET, ByteCount); }