1 /* $Id: xdma_channel.c,v 1.1 2006/12/13 14:21:45 imanuilov Exp $ */
2 /******************************************************************************
4 * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS"
5 * AS A COURTESY TO YOU, SOLELY FOR USE IN DEVELOPING PROGRAMS AND
6 * SOLUTIONS FOR XILINX DEVICES. BY PROVIDING THIS DESIGN, CODE,
7 * OR INFORMATION AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE,
8 * APPLICATION OR STANDARD, XILINX IS MAKING NO REPRESENTATION
9 * THAT THIS IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT,
10 * AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE
11 * FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY
12 * WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE
13 * IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR
14 * REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF
15 * INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
16 * FOR A PARTICULAR PURPOSE.
18 * (c) Copyright 2001-2004 Xilinx Inc.
19 * All rights reserved.
20 * This program is free software; you can redistribute it and/or modify it
21 * under the terms of the GNU General Public License as published by the
22 * Free Software Foundation; either version 2 of the License, or (at your
23 * option) any later version.
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
29 ******************************************************************************/
30 /*****************************************************************************/
33 * @file xdma_channel.c
37 * This file contains the DMA channel component. This component supports
38 * a distributed DMA design in which each device can have it's own dedicated
39 * DMA channel, as opposed to a centralized DMA design. This component
40 * performs processing for DMA on all devices.
42 * See xdma_channel.h for more information about this component.
49 * MODIFICATION HISTORY:
51 * Ver Who Date Changes
52 * ----- ---- -------- -----------------------------------------------
53 * 1.00a xd 10/27/04 Doxygenated for inclusion in API documentation
54 * 1.00b ecm 10/31/05 Updated for the check sum offload changes.
55 * 1.00b xd 03/22/06 Fixed a multi-descriptor packet related bug that sgdma
56 * engine is restarted in case no scatter gather disabled
60 ******************************************************************************/
62 /***************************** Include Files *********************************/
64 #include "xdma_channel.h"
65 #include "xbasic_types.h"
68 /************************** Constant Definitions *****************************/
71 /**************************** Type Definitions *******************************/
74 /***************** Macros (Inline Functions) Definitions *********************/
77 /************************** Function Prototypes ******************************/
80 /*****************************************************************************/
83 * This function initializes a DMA channel. This function must be called
84 * prior to using a DMA channel. Initialization of a channel includes setting
85 * up the registers base address, and resetting the channel such that it's in a
86 * known state. Interrupts for the channel are disabled when the channel is
91 * InstancePtr contains a pointer to the DMA channel to operate on.
95 * BaseAddress contains the base address of the registers for the DMA channel.
99 * XST_SUCCESS indicating initialization was successful.
105 ******************************************************************************/
106 int XDmaChannel_Initialize(XDmaChannel
* InstancePtr
, u32 BaseAddress
)
108 /* assert to verify input arguments, don't assert base address */
110 XASSERT_NONVOID(InstancePtr
!= NULL
);
112 /* setup the base address of the registers for the DMA channel such
113 * that register accesses can be done
115 InstancePtr
->RegBaseAddress
= BaseAddress
;
117 /* initialize the scatter gather list such that it indicates it has not
118 * been created yet and the DMA channel is ready to use (initialized)
120 InstancePtr
->GetPtr
= NULL
;
121 InstancePtr
->PutPtr
= NULL
;
122 InstancePtr
->CommitPtr
= NULL
;
123 InstancePtr
->LastPtr
= NULL
;
125 InstancePtr
->TotalDescriptorCount
= 0;
126 InstancePtr
->ActiveDescriptorCount
= 0;
128 InstancePtr
->ActivePacketCount
= 0;
129 InstancePtr
->Committed
= FALSE
;
131 InstancePtr
->IsReady
= XCOMPONENT_IS_READY
;
133 /* initialize the version of the component
135 XVersion_FromString(&InstancePtr
->Version
, "1.00a");
137 /* reset the DMA channel such that it's in a known state and ready
138 * and indicate the initialization occurred with no errors, note that
139 * the is ready variable must be set before this call or reset will assert
141 XDmaChannel_Reset(InstancePtr
);
146 /*****************************************************************************/
149 * This function determines if a DMA channel component has been successfully
150 * initialized such that it's ready to use.
154 * InstancePtr contains a pointer to the DMA channel to operate on.
158 * TRUE if the DMA channel component is ready, FALSE otherwise.
164 ******************************************************************************/
165 u32
XDmaChannel_IsReady(XDmaChannel
* InstancePtr
)
167 /* assert to verify input arguments used by the base component */
169 XASSERT_NONVOID(InstancePtr
!= NULL
);
171 return InstancePtr
->IsReady
== XCOMPONENT_IS_READY
;
174 /*****************************************************************************/
177 * This function gets the software version for the specified DMA channel
182 * InstancePtr contains a pointer to the DMA channel to operate on.
186 * A pointer to the software version of the specified DMA channel.
192 ******************************************************************************/
193 XVersion
*XDmaChannel_GetVersion(XDmaChannel
* InstancePtr
)
195 /* assert to verify input arguments */
197 XASSERT_NONVOID(InstancePtr
!= NULL
);
198 XASSERT_NONVOID(InstancePtr
->IsReady
== XCOMPONENT_IS_READY
);
200 /* return a pointer to the version of the DMA channel */
202 return &InstancePtr
->Version
;
205 /*****************************************************************************/
208 * This function performs a self test on the specified DMA channel. This self
209 * test is destructive as the DMA channel is reset and a register default is
214 * InstancePtr is a pointer to the DMA channel to be operated on.
218 * XST_SUCCESS is returned if the self test is successful, or one of the
221 * - XST_DMA_RESET_REGISTER_ERROR Indicates the control register value
222 * after a reset was not correct
226 * This test does not performs a DMA transfer to test the channel because the
227 * DMA hardware will not currently allow a non-local memory transfer to non-local
228 * memory (memory copy), but only allows a non-local memory to or from the device
229 * memory (typically a FIFO).
231 ******************************************************************************/
233 #define XDC_CONTROL_REG_RESET_MASK 0x98000000UL /* control reg reset value */
235 int XDmaChannel_SelfTest(XDmaChannel
* InstancePtr
)
239 /* assert to verify input arguments */
241 XASSERT_NONVOID(InstancePtr
!= NULL
);
242 XASSERT_NONVOID(InstancePtr
->IsReady
== XCOMPONENT_IS_READY
);
244 /* reset the DMA channel such that it's in a known state before the test
245 * it resets to no interrupts enabled, the desired state for the test
247 XDmaChannel_Reset(InstancePtr
);
249 /* this should be the first test to help prevent a lock up with the polling
250 * loop that occurs later in the test, check the reset value of the DMA
251 * control register to make sure it's correct, return with an error if not
253 ControlReg
= XDmaChannel_GetControl(InstancePtr
);
254 if (ControlReg
!= XDC_CONTROL_REG_RESET_MASK
) {
255 return XST_DMA_RESET_REGISTER_ERROR
;
261 /*****************************************************************************/
264 * This function resets the DMA channel. This is a destructive operation such
265 * that it should not be done while a channel is being used. If the DMA channel
266 * is transferring data into other blocks, such as a FIFO, it may be necessary
267 * to reset other blocks. This function does not modify the contents of a
268 * scatter gather list for a DMA channel such that the user is responsible for
269 * getting buffer descriptors from the list if necessary.
273 * InstancePtr contains a pointer to the DMA channel to operate on.
283 ******************************************************************************/
284 void XDmaChannel_Reset(XDmaChannel
* InstancePtr
)
286 /* assert to verify input arguments */
288 XASSERT_VOID(InstancePtr
!= NULL
);
289 XASSERT_VOID(InstancePtr
->IsReady
== XCOMPONENT_IS_READY
);
291 /* reset the DMA channel such that it's in a known state, the reset
292 * register is self clearing such that it only has to be set
294 XIo_Out32(InstancePtr
->RegBaseAddress
+ XDC_RST_REG_OFFSET
,
298 /*****************************************************************************/
301 * This function gets the control register contents of the DMA channel.
305 * InstancePtr contains a pointer to the DMA channel to operate on.
309 * The control register contents of the DMA channel. One or more of the
310 * following values may be contained the register. Each of the values are
313 * - XDC_DMACR_SOURCE_INCR_MASK Increment the source address
315 * - XDC_DMACR_DEST_INCR_MASK Increment the destination address
317 * - XDC_DMACR_SOURCE_LOCAL_MASK Local source address
319 * - XDC_DMACR_DEST_LOCAL_MASK Local destination address
321 * - XDC_DMACR_SG_ENABLE_MASK Scatter gather enable
323 * - XDC_DMACR_GEN_BD_INTR_MASK Individual buffer descriptor interrupt
325 * - XDC_DMACR_LAST_BD_MASK Last buffer descriptor in a packet
331 ******************************************************************************/
332 u32
XDmaChannel_GetControl(XDmaChannel
* InstancePtr
)
334 /* assert to verify input arguments */
336 XASSERT_NONVOID(InstancePtr
!= NULL
);
337 XASSERT_NONVOID(InstancePtr
->IsReady
== XCOMPONENT_IS_READY
);
339 /* return the contents of the DMA control register */
341 return XIo_In32(InstancePtr
->RegBaseAddress
+ XDC_DMAC_REG_OFFSET
);
344 /*****************************************************************************/
347 * This function sets the control register of the specified DMA channel.
351 * InstancePtr contains a pointer to the DMA channel to operate on.
355 * Control contains the value to be written to the control register of the DMA
356 * channel. One or more of the following values may be contained the register.
357 * Each of the values are unique bit masks such that they may be ORed together
358 * to enable multiple bits or inverted and ANDed to disable multiple bits.
359 * - XDC_DMACR_SOURCE_INCR_MASK Increment the source address
360 * - XDC_DMACR_DEST_INCR_MASK Increment the destination address
361 * - XDC_DMACR_SOURCE_LOCAL_MASK Local source address
362 * - XDC_DMACR_DEST_LOCAL_MASK Local destination address
363 * - XDC_DMACR_SG_ENABLE_MASK Scatter gather enable
364 * - XDC_DMACR_GEN_BD_INTR_MASK Individual buffer descriptor interrupt
365 * - XDC_DMACR_LAST_BD_MASK Last buffer descriptor in a packet
375 ******************************************************************************/
376 void XDmaChannel_SetControl(XDmaChannel
* InstancePtr
, u32 Control
)
380 /* assert to verify input arguments except the control which can't be
381 * asserted since all values are valid
383 XASSERT_VOID(InstancePtr
!= NULL
);
384 XASSERT_VOID(InstancePtr
->IsReady
== XCOMPONENT_IS_READY
);
387 * set the DMA control register to the specified value, not altering the
388 * other fields in the register
391 Register
= XIo_In32(InstancePtr
->RegBaseAddress
+ XDC_DMAC_REG_OFFSET
);
392 Register
&= XDC_DMACR_TX_CS_INIT_MASK
;
393 XIo_Out32(InstancePtr
->RegBaseAddress
+ XDC_DMAC_REG_OFFSET
,
397 /*****************************************************************************/
400 * This function gets the status register contents of the DMA channel.
404 * InstancePtr contains a pointer to the DMA channel to operate on.
408 * The status register contents of the DMA channel. One or more of the
409 * following values may be contained the register. Each of the values are
412 * - XDC_DMASR_BUSY_MASK The DMA channel is busy
414 * - XDC_DMASR_BUS_ERROR_MASK A bus error occurred
416 * - XDC_DMASR_BUS_TIMEOUT_MASK A bus timeout occurred
418 * - XDC_DMASR_LAST_BD_MASK The last buffer descriptor of a packet
424 ******************************************************************************/
425 u32
XDmaChannel_GetStatus(XDmaChannel
* InstancePtr
)
427 /* assert to verify input arguments */
429 XASSERT_NONVOID(InstancePtr
!= NULL
);
430 XASSERT_NONVOID(InstancePtr
->IsReady
== XCOMPONENT_IS_READY
);
432 /* return the contents of the DMA status register */
434 return XIo_In32(InstancePtr
->RegBaseAddress
+ XDC_DMAS_REG_OFFSET
);
437 /*****************************************************************************/
440 * This function sets the interrupt status register of the specified DMA channel.
441 * Setting any bit of the interrupt status register will clear the bit to
442 * indicate the interrupt processing has been completed. The definitions of each
443 * bit in the register match the definition of the bits in the interrupt enable
448 * InstancePtr contains a pointer to the DMA channel to operate on.
452 * Status contains the value to be written to the status register of the DMA
453 * channel. One or more of the following values may be contained the register.
454 * Each of the values are unique bit masks such that they may be ORed together
455 * to enable multiple bits or inverted and ANDed to disable multiple bits.
456 * - XDC_IXR_DMA_DONE_MASK The dma operation is done
457 * - XDC_IXR_DMA_ERROR_MASK The dma operation had an error
458 * - XDC_IXR_PKT_DONE_MASK A packet is complete
459 * - XDC_IXR_PKT_THRESHOLD_MASK The packet count threshold reached
460 * - XDC_IXR_PKT_WAIT_BOUND_MASK The packet wait bound reached
461 * - XDC_IXR_SG_DISABLE_ACK_MASK The scatter gather disable completed
462 * - XDC_IXR_BD_MASK A buffer descriptor is done
472 ******************************************************************************/
473 void XDmaChannel_SetIntrStatus(XDmaChannel
* InstancePtr
, u32 Status
)
475 /* assert to verify input arguments except the status which can't be
476 * asserted since all values are valid
478 XASSERT_VOID(InstancePtr
!= NULL
);
479 XASSERT_VOID(InstancePtr
->IsReady
== XCOMPONENT_IS_READY
);
481 /* set the interrupt status register with the specified value such that
482 * all bits which are set in the register are cleared effectively clearing
483 * any active interrupts
485 XIo_Out32(InstancePtr
->RegBaseAddress
+ XDC_IS_REG_OFFSET
, Status
);
488 /*****************************************************************************/
491 * This function gets the interrupt status register of the specified DMA channel.
492 * The interrupt status register indicates which interrupts are active
493 * for the DMA channel. If an interrupt is active, the status register must be
494 * set (written) with the bit set for each interrupt which has been processed
495 * in order to clear the interrupts. The definitions of each bit in the register
496 * match the definition of the bits in the interrupt enable register.
500 * InstancePtr contains a pointer to the DMA channel to operate on.
504 * The interrupt status register contents of the specified DMA channel.
505 * One or more of the following values may be contained the register.
506 * Each of the values are unique bit masks.
508 * - XDC_IXR_DMA_DONE_MASK The dma operation is done
510 * - XDC_IXR_DMA_ERROR_MASK The dma operation had an error
512 * - XDC_IXR_PKT_DONE_MASK A packet is complete
514 * - XDC_IXR_PKT_THRESHOLD_MASK The packet count threshold reached
516 * - XDC_IXR_PKT_WAIT_BOUND_MASK The packet wait bound reached
518 * - XDC_IXR_SG_DISABLE_ACK_MASK The scatter gather disable completed
520 * - XDC_IXR_SG_END_MASK Current descriptor was the end of the list
522 * - XDC_IXR_BD_MASK A buffer descriptor is done
528 ******************************************************************************/
529 u32
XDmaChannel_GetIntrStatus(XDmaChannel
* InstancePtr
)
531 /* assert to verify input arguments */
533 XASSERT_NONVOID(InstancePtr
!= NULL
);
534 XASSERT_NONVOID(InstancePtr
->IsReady
== XCOMPONENT_IS_READY
);
536 /* return the contents of the interrupt status register */
538 return XIo_In32(InstancePtr
->RegBaseAddress
+ XDC_IS_REG_OFFSET
);
541 /*****************************************************************************/
544 * This function sets the interrupt enable register of the specified DMA
545 * channel. The interrupt enable register contains bits which enable
546 * individual interrupts for the DMA channel. The definitions of each bit
547 * in the register match the definition of the bits in the interrupt status
552 * InstancePtr contains a pointer to the DMA channel to operate on.
556 * Enable contains the interrupt enable register contents to be written
557 * in the DMA channel. One or more of the following values may be contained
558 * the register. Each of the values are unique bit masks such that they may be
559 * ORed together to enable multiple bits or inverted and ANDed to disable
561 * - XDC_IXR_DMA_DONE_MASK The dma operation is done
562 * - XDC_IXR_DMA_ERROR_MASK The dma operation had an error
563 * - XDC_IXR_PKT_DONE_MASK A packet is complete
564 * - XDC_IXR_PKT_THRESHOLD_MASK The packet count threshold reached
565 * - XDC_IXR_PKT_WAIT_BOUND_MASK The packet wait bound reached
566 * - XDC_IXR_SG_DISABLE_ACK_MASK The scatter gather disable completed
567 * - XDC_IXR_SG_END_MASK Current descriptor was the end of the list
568 * - XDC_IXR_BD_MASK A buffer descriptor is done
578 ******************************************************************************/
579 void XDmaChannel_SetIntrEnable(XDmaChannel
* InstancePtr
, u32 Enable
)
581 /* assert to verify input arguments except the enable which can't be
582 * asserted since all values are valid
584 XASSERT_VOID(InstancePtr
!= NULL
);
585 XASSERT_VOID(InstancePtr
->IsReady
== XCOMPONENT_IS_READY
);
587 /* set the interrupt enable register to the specified value */
589 XIo_Out32(InstancePtr
->RegBaseAddress
+ XDC_IE_REG_OFFSET
, Enable
);
592 /*****************************************************************************/
595 * This function gets the interrupt enable of the DMA channel. The
596 * interrupt enable contains flags which enable individual interrupts for the
597 * DMA channel. The definitions of each bit in the register match the definition
598 * of the bits in the interrupt status register.
602 * InstancePtr contains a pointer to the DMA channel to operate on.
606 * The interrupt enable of the DMA channel. One or more of the following values
607 * may be contained the register. Each of the values are unique bit masks.
609 * - XDC_IXR_DMA_DONE_MASK The dma operation is done
611 * - XDC_IXR_DMA_ERROR_MASK The dma operation had an error
613 * - XDC_IXR_PKT_DONE_MASK A packet is complete
615 * - XDC_IXR_PKT_THRESHOLD_MASK The packet count threshold reached
617 * - XDC_IXR_PKT_WAIT_BOUND_MASK The packet wait bound reached
619 * - XDC_IXR_SG_DISABLE_ACK_MASK The scatter gather disable completed
621 * - XDC_IXR_BD_MASK A buffer descriptor is done
627 ******************************************************************************/
628 u32
XDmaChannel_GetIntrEnable(XDmaChannel
* InstancePtr
)
630 /* assert to verify input arguments */
632 XASSERT_NONVOID(InstancePtr
!= NULL
);
633 XASSERT_NONVOID(InstancePtr
->IsReady
== XCOMPONENT_IS_READY
);
635 /* return the contents of the interrupt enable register */
637 return XIo_In32(InstancePtr
->RegBaseAddress
+ XDC_IE_REG_OFFSET
);
640 /*****************************************************************************/
643 * This function starts the DMA channel transferring data from a memory source
644 * to a memory destination. This function only starts the operation and returns
645 * before the operation may be complete. If the interrupt is enabled, an
646 * interrupt will be generated when the operation is complete, otherwise it is
647 * necessary to poll the channel status to determine when it's complete. It is
648 * the responsibility of the caller to determine when the operation is complete
649 * by handling the generated interrupt or polling the status. It is also the
650 * responsibility of the caller to ensure that the DMA channel is not busy with
651 * another transfer before calling this function.
655 * InstancePtr contains a pointer to the DMA channel to operate on.
659 * SourcePtr contains a pointer to the source memory where the data is to
660 * be transferred from and must be 32 bit aligned.
664 * DestinationPtr contains a pointer to the destination memory where the data
665 * is to be transferred and must be 32 bit aligned.
669 * ByteCount contains the number of bytes to transfer during the DMA operation.
677 * The DMA hw will not currently allow a non-local memory transfer to non-local
678 * memory (memory copy), but only allows a non-local memory to or from the device
679 * memory (typically a FIFO).
681 * It is the responsibility of the caller to ensure that the cache is
682 * flushed and invalidated both before and after the DMA operation completes
683 * if the memory pointed to is cached. The caller must also ensure that the
684 * pointers contain a physical address rather than a virtual address
685 * if address translation is being used.
687 ******************************************************************************/
688 void XDmaChannel_Transfer(XDmaChannel
* InstancePtr
,
689 u32
*SourcePtr
, u32
*DestinationPtr
, u32 ByteCount
)
691 /* assert to verify input arguments and the alignment of any arguments
692 * which have expected alignments
694 XASSERT_VOID(InstancePtr
!= NULL
);
695 XASSERT_VOID(SourcePtr
!= NULL
);
696 XASSERT_VOID(((u32
) SourcePtr
& 3) == 0);
697 XASSERT_VOID(DestinationPtr
!= NULL
);
698 XASSERT_VOID(((u32
) DestinationPtr
& 3) == 0);
699 XASSERT_VOID(ByteCount
!= 0);
700 XASSERT_VOID(InstancePtr
->IsReady
== XCOMPONENT_IS_READY
);
702 /* setup the source and destination address registers for the transfer */
704 XIo_Out32(InstancePtr
->RegBaseAddress
+ XDC_SA_REG_OFFSET
,
707 XIo_Out32(InstancePtr
->RegBaseAddress
+ XDC_DA_REG_OFFSET
,
708 (u32
) DestinationPtr
);
710 /* start the DMA transfer to copy from the source buffer to the
711 * destination buffer by writing the length to the length register
713 XIo_Out32(InstancePtr
->RegBaseAddress
+ XDC_LEN_REG_OFFSET
, ByteCount
);