Software Drivers
Main Page | Data Structures | File List | Data Fields | Globals

xaxidma_bdring.c File Reference


Detailed Description

This file implements buffer descriptor ring related functions. For more information on how to manage the BD ring, please see xaxidma.h.

 MODIFICATION HISTORY:

 Ver   Who  Date     Changes
 ----- ---- -------- -------------------------------------------------------
 1.00a jz   05/18/10 First release
 2.00a jz   08/10/10 Second release, added in xaxidma_g.c, xaxidma_sinit.c,
                     updated tcl file, added xaxidma_porting_guide.h
 3.00a jz   11/22/10 Support IP core parameters change
 


Functions

int XAxiDma_StartBdRingHw (XAxiDma_BdRing *RingPtr)
int XAxiDma_BdRingCreate (XAxiDma_BdRing *RingPtr, u32 PhysAddr, u32 VirtAddr, u32 Alignment, int BdCount)
int XAxiDma_BdRingClone (XAxiDma_BdRing *RingPtr, XAxiDma_Bd *SrcBdPtr)
int XAxiDma_BdRingStart (XAxiDma_BdRing *RingPtr)
int XAxiDma_BdRingSetCoalesce (XAxiDma_BdRing *RingPtr, u32 Counter, u32 Timer)
void XAxiDma_BdRingGetCoalesce (XAxiDma_BdRing *RingPtr, u32 *CounterPtr, u32 *TimerPtr)
int XAxiDma_BdRingAlloc (XAxiDma_BdRing *RingPtr, int NumBd, XAxiDma_Bd **BdSetPtr)
int XAxiDma_BdRingUnAlloc (XAxiDma_BdRing *RingPtr, int NumBd, XAxiDma_Bd *BdSetPtr)
int XAxiDma_BdRingToHw (XAxiDma_BdRing *RingPtr, int NumBd, XAxiDma_Bd *BdSetPtr)
int XAxiDma_BdRingFromHw (XAxiDma_BdRing *RingPtr, int BdLimit, XAxiDma_Bd **BdSetPtr)
int XAxiDma_BdRingFree (XAxiDma_BdRing *RingPtr, int NumBd, XAxiDma_Bd *BdSetPtr)
int XAxiDma_BdRingCheck (XAxiDma_BdRing *RingPtr)
void XAxiDma_BdRingDumpRegs (XAxiDma_BdRing *RingPtr)


Function Documentation

int XAxiDma_BdRingAlloc XAxiDma_BdRing RingPtr,
int  NumBd,
XAxiDma_Bd **  BdSetPtr
 

Reserve locations in the BD ring. The set of returned BDs may be modified in preparation for future DMA transactions. Once the BDs are ready to be submitted to hardware, the application must call XAxiDma_BdRingToHw() in the same order which they were allocated here. Example:

        NumBd = 2;
        Status = XDsma_RingBdAlloc(MyRingPtr, NumBd, &MyBdSet);

        if (Status != XST_SUCCESS)
        {
            // Not enough BDs available for the request
        }

        CurBd = MyBdSet;
        for (i=0; i<NumBd; i++)
        {
            // Prepare CurBd.....

            // Onto next BD
            CurBd = XAxiDma_BdRingNext(MyRingPtr, CurBd);
        }

        // Give list to hardware
        Status = XAxiDma_BdRingToHw(MyRingPtr, NumBd, MyBdSet);
 

A more advanced use of this function may allocate multiple sets of BDs. They must be allocated and given to hardware in the correct sequence:

        // Legal
        XAxiDma_BdRingAlloc(MyRingPtr, NumBd1, &MySet1);
        XAxiDma_BdRingToHw(MyRingPtr, NumBd1, MySet1);

        // Legal
        XAxiDma_BdRingAlloc(MyRingPtr, NumBd1, &MySet1);
        XAxiDma_BdRingAlloc(MyRingPtr, NumBd2, &MySet2);
        XAxiDma_BdRingToHw(MyRingPtr, NumBd1, MySet1);
        XAxiDma_BdRingToHw(MyRingPtr, NumBd2, MySet2);

        // Not legal
        XAxiDma_BdRingAlloc(MyRingPtr, NumBd1, &MySet1);
        XAxiDma_BdRingAlloc(MyRingPtr, NumBd2, &MySet2);
        XAxiDma_BdRingToHw(MyRingPtr, NumBd2, MySet2);
        XAxiDma_BdRingToHw(MyRingPtr, NumBd1, MySet1);
 

Use the API defined in xaxidmabd.h to modify individual BDs. Traversal of the BD set can be done using XAxiDma_BdRingNext() and XAxiDma_BdRingPrev().

Parameters:
RingPtr is a pointer to the descriptor ring instance to be worked on.
NumBd is the number of BDs to allocate
BdSetPtr is an output parameter, it points to the first BD available for modification.
Returns:
  • XST_SUCCESS if the requested number of BDs were returned in the BdSetPtr parameter.
  • XST_INVALID_PARAM if passed in NumBd is not positive
  • XST_FAILURE if there were not enough free BDs to satisfy the request.
Note:
This function should not be preempted by another XAxiDma_BdRing function call that modifies the BD space. It is the caller's responsibility to provide a mutual exclusion mechanism.

Do not modify more BDs than the number requested with the NumBd parameter. Doing so will lead to data corruption and system instability.

int XAxiDma_BdRingCheck XAxiDma_BdRing RingPtr  ) 
 

Check the internal data structures of the BD ring for the provided channel. The following checks are made:

  • The BD ring is linked correctly in physical address space.
  • The internal pointers point to BDs in the ring.
  • The internal counters add up.

The channel should be stopped (through XAxiDma_Pause() or XAxiDma_Reset()) prior to calling this function.

Parameters:
RingPtr is a pointer to the descriptor ring to be worked on.
Returns:
  • XST_SUCCESS if no errors were found.
  • XST_DMA_SG_NO_LIST if the ring has not been created.
  • XST_IS_STARTED if the channel is not stopped.
  • XST_DMA_SG_LIST_ERROR if a problem is found with the internal data structures. If this value is returned, the channel should be reset, and the BD ring should be recreated through XAxiDma_BdRingCreate() to avoid data corruption or system instability.

int XAxiDma_BdRingClone XAxiDma_BdRing RingPtr,
XAxiDma_Bd SrcBdPtr
 

Clone the given BD into every BD in the ring. Only the fields offset from XAXIDMA_BD_START_CLEAR are copied, for XAXIDMA_BD_BYTES_TO_CLEAR bytes. This covers: BufferAddr, Control/Buffer length, status, APP words 0 - 4, and software ID fields.

This function can be called only when all BDs are in the free group such as immediately after creation of the ring. This prevents modification of BDs while they are in use by hardware or the application.

Parameters:
RingPtr is the BD ring instance to be worked on.
SrcBdPtr is the source BD template to be cloned into the list.
Returns:
  • XST_SUCCESS if the list was modified.
  • XST_DMA_SG_NO_LIST if a list has not been created.
  • XST_DEVICE_IS_STARTED if the DMA channel has not been stopped.
  • XST_DMA_SG_LIST_ERROR if some of the BDs in this channel are under hardware or application control.

int XAxiDma_BdRingCreate XAxiDma_BdRing RingPtr,
u32  PhysAddr,
u32  VirtAddr,
u32  Alignment,
int  BdCount
 

Using a memory segment allocated by the caller, This fundtion creates and setup the BD ring.

Parameters:
RingPtr is the BD ring instance to be worked on.
PhysAddr is the physical base address of application memory region.
VirtAddr is the virtual base address of the application memory region.If address translation is not being utilized, then VirtAddr should be equivalent to PhysAddr.
Alignment governs the byte alignment of individual BDs. This function will enforce a minimum alignment of XAXIDMA_BD_MINIMUM_ALIGNMENT bytes with no maximum as long as it is specified as a power of 2.
BdCount is the number of BDs to setup in the application memory region. It is assumed the region is large enough to contain the BDs. Refer to the "SGDMA Ring Creation" section in xaxidma.h for more information. The minimum valid value for this parameter is 1.
Returns:
  • XST_SUCCESS if initialization was successful
  • XST_NO_FEATURE if the provided instance is a non SGDMA type of DMA channel.
  • XST_INVALID_PARAM under any of the following conditions:

1) BdCount is not positive

2) PhysAddr and/or VirtAddr are not aligned to the given Alignment parameter;

3) Alignment parameter does not meet minimum requirements or is not a power of 2 value.

  • XST_DMA_SG_LIST_ERROR if the memory segment containing the list spans over address 0x00000000 in virtual address space.

void XAxiDma_BdRingDumpRegs XAxiDma_BdRing RingPtr  ) 
 

Dump the registers for a channel.

Parameters:
RingPtr is a pointer to the descriptor ring to be worked on.
Returns:
None

int XAxiDma_BdRingFree XAxiDma_BdRing RingPtr,
int  NumBd,
XAxiDma_Bd BdSetPtr
 

Frees a set of BDs that had been previously retrieved with XAxiDma_BdRingFromHw().

Parameters:
RingPtr is a pointer to the descriptor ring instance to be worked on.
NumBd is the number of BDs to free.
BdSetPtr is the head of a list of BDs returned by XAxiDma_BdRingFromHw().
Returns:
  • XST_SUCCESS if the set of BDs was freed.
  • XST_INVALID_PARAM if NumBd is negative
  • XST_DMA_SG_LIST_ERROR if this function was called out of sequence with XAxiDma_BdRingFromHw().
Note:
This function should not be preempted by another XAxiDma function call that modifies the BD space. It is the caller's responsibility to ensure mutual exclusion.

int XAxiDma_BdRingFromHw XAxiDma_BdRing RingPtr,
int  BdLimit,
XAxiDma_Bd **  BdSetPtr
 

Returns a set of BD(s) that have been processed by hardware. The returned BDs may be examined by the application to determine the outcome of the DMA transactions. Once the BDs have been examined, the application must call XAxiDma_BdRingFree() in the same order which they were retrieved here.

Example:

        NumBd = XAxiDma_BdRingFromHw(MyRingPtr, XAXIDMA_ALL_BDS, &MyBdSet);

        if (NumBd == 0)
        {
           // hardware has nothing ready for us yet
        }

        CurBd = MyBdSet;
        for (i=0; i<NumBd; i++)
        {
           // Examine CurBd for post processing.....

           // Onto next BD
           CurBd = XAxiDma_BdRingNext(MyRingPtr, CurBd);
        }

        XAxiDma_BdRingFree(MyRingPtr, NumBd, MyBdSet); // Return the list
 

A more advanced use of this function may allocate multiple sets of BDs. They must be retrieved from hardware and freed in the correct sequence:

        // Legal
        XAxiDma_BdRingFromHw(MyRingPtr, NumBd1, &MySet1);
        XAxiDma_BdRingFree(MyRingPtr, NumBd1, MySet1);

        // Legal
        XAxiDma_BdRingFromHw(MyRingPtr, NumBd1, &MySet1);
        XAxiDma_BdRingFromHw(MyRingPtr, NumBd2, &MySet2);
        XAxiDma_BdRingFree(MyRingPtr, NumBd1, MySet1);
        XAxiDma_BdRingFree(MyRingPtr, NumBd2, MySet2);

        // Not legal
        XAxiDma_BdRingFromHw(MyRingPtr, NumBd1, &MySet1);
        XAxiDma_BdRingFromHw(MyRingPtr, NumBd2, &MySet2);
        XAxiDma_BdRingFree(MyRingPtr, NumBd2, MySet2);
        XAxiDma_BdRingFree(MyRingPtr, NumBd1, MySet1);
 

If hardware has partially completed a packet spanning multiple BDs, then none of the BDs for that packet will be included in the results.

Parameters:
RingPtr is a pointer to the descriptor ring instance to be worked on.
BdLimit is the maximum number of BDs to return in the set. Use XAXIDMA_ALL_BDS to return all BDs that have been processed.
BdSetPtr is an output parameter, it points to the first BD available for examination.
Returns:
The number of BDs processed by hardware. A value of 0 indicates that no data is available. No more than BdLimit BDs will be returned.
Note:
Treat BDs returned by this function as read-only.

This function should not be preempted by another XAxiDma ring function call that modifies the BD space. It is the caller's responsibility to provide a mutual exclusion mechanism.

void XAxiDma_BdRingGetCoalesce XAxiDma_BdRing RingPtr,
u32 *  CounterPtr,
u32 *  TimerPtr
 

Retrieve current interrupt coalescing parameters from the given descriptor ring channel.

Parameters:
RingPtr is a pointer to the descriptor ring instance to be worked on.
CounterPtr points to a memory location where the current packet counter will be written.
TimerPtr points to a memory location where the current waitbound timer will be written.
Returns:
The passed in parameters, CounterPtr and TimerPtr, holds the references to the return values.

int XAxiDma_BdRingSetCoalesce XAxiDma_BdRing RingPtr,
u32  Counter,
u32  Timer
 

Set interrupt coalescing parameters for the given descriptor ring channel.

Parameters:
RingPtr is a pointer to the descriptor ring instance to be worked on.
Counter sets the packet counter on the channel. Valid range is 1..255, or XAXIDMA_NO_CHANGE to leave this setting unchanged.
Timer sets the waitbound timer on the channel. Valid range is 0..255, or XAXIDMA_NO_CHANGE to leave this setting unchanged. Each unit depend on hardware building parameter C_DLYTMR_RESOLUTION, which is in the range from 0 to 100,000 clock cycles. A value of 0 disables the delay interrupt.
Returns:
  • XST_SUCCESS if interrupt coalescing settings updated
  • XST_FAILURE if Counter or Timer parameters are out of range

int XAxiDma_BdRingStart XAxiDma_BdRing RingPtr  ) 
 

Allow DMA transactions to commence on a given channel if descriptors are ready to be processed.

This is different from XAxiDma_StartBdRingHw(), where the DMA channel is started. If the DMA engine is stopped, XAxiDma_StartBdRingHw() is called to start the engine first. A channel being started means it is not halted. A BD ring being started means it starts transfers.

Parameters:
RingPtr is a pointer to the descriptor ring instance to be worked on.
Returns:
  • XST_SUCCESS if the channel was started.
  • XST_DMA_SG_NO_LIST if the channel has no initialized BD ring.
  • XST_DMA_ERROR if the hardware failed to start

int XAxiDma_BdRingToHw XAxiDma_BdRing RingPtr,
int  NumBd,
XAxiDma_Bd BdSetPtr
 

Enqueue a set of BDs to hardware that were previously allocated by XAxiDma_BdRingAlloc(). Once this function returns, the argument BD set goes under hardware control. Changes to these BDs should be held until they are finished by hardware to avoid data corruption and system instability.

For transmit, the set will be rejected if the last BD of the set does not mark the end of a packet or the first BD does not mark the start of a packet.

Parameters:
RingPtr is a pointer to the descriptor ring instance to be worked on.
NumBd is the number of BDs in the set.
BdSetPtr is the first BD of the set to commit to hardware.
Returns:
  • XST_SUCCESS if the set of BDs was accepted and enqueued to hardware
  • XST_INVALID_PARAM if passed in NumBd is negative
  • XST_FAILURE if the set of BDs was rejected because the first BD does not have its start-of-packet bit set, or the last BD does not have its end-of-packet bit set, or any one of the BDs has 0 length.
  • XST_DMA_SG_LIST_ERROR if this function was called out of sequence with XAxiDma_BdRingAlloc()
Note:
This function should not be preempted by another XAxiDma ring function call that modifies the BD space. It is the caller's responsibility to provide a mutual exclusion mechanism.

int XAxiDma_BdRingUnAlloc XAxiDma_BdRing RingPtr,
int  NumBd,
XAxiDma_Bd BdSetPtr
 

Fully or partially undo an XAxiDma_BdRingAlloc() operation. Use this function if all the BDs allocated by XAxiDma_BdRingAlloc() could not be transferred to hardware with XAxiDma_BdRingToHw().

This function releases the BDs after they have been allocated but before they have been given to hardware.

This function is not the same as XAxiDma_BdRingFree(). The Free function returns BDs to the free list after they have been processed by hardware, while UnAlloc returns them before being processed by hardware.

There are two scenarios where this function can be used. Full UnAlloc or Partial UnAlloc. A Full UnAlloc means all the BDs Alloc'd will be returned:

    Status = XAxiDma_BdRingAlloc(MyRingPtr, 10, &BdPtr);
        ...
        ...
    if (Error)
    {
        Status = XAxiDma_BdRingUnAlloc(MyRingPtr, 10, &BdPtr);
    }
 

A partial UnAlloc means some of the BDs Alloc'd will be returned:

    Status = XAxiDma_BdRingAlloc(MyRingPtr, 10, &BdPtr);
    BdsLeft = 10;
    CurBdPtr = BdPtr;

    while (BdsLeft)
    {
       if (Error)
       {
          Status = XAxiDma_BdRingUnAlloc(MyRingPtr, BdsLeft, CurBdPtr);
       }

       CurBdPtr = XAxiDma_BdRingNext(MyRingPtr, CurBdPtr);
       BdsLeft--;
    }
 

A partial UnAlloc must include the last BD in the list that was Alloc'd.

Parameters:
RingPtr is a pointer to the descriptor ring instance to be worked on.
NumBd is the number of BDs to unallocate
BdSetPtr points to the first of the BDs to be returned.
Returns:
  • XST_SUCCESS if the BDs were unallocated.
  • XST_INVALID_PARAM if passed in NumBd is negative
  • XST_FAILURE if NumBd parameter was greater that the number of BDs in the preprocessing state.
Note:
This function should not be preempted by another XAxiDma ring function call that modifies the BD space. It is the caller's responsibility to provide a mutual exclusion mechanism.

int XAxiDma_StartBdRingHw XAxiDma_BdRing RingPtr  ) 
 

Start a DMA channel

This is different from XAxiDma_BdRingStart(), where transfers are started on a channel.

After a DMA channel is started, it is not halted, and it is idle (no active DMA transfers).

Parameters:
RingPtr is the Channel instance to be worked on
Returns:
  • XST_SUCCESS upon success
  • XST_DMA_ERROR if no valid BD available to put into current BD register