DMA-list transfers: programming example

The C-language sample program included here creates a DMA list and, in the last line, uses an spu_mfcdma32 intrinsic to issue a single DMA-list command (getl) to transfer a main-storage region into LS.

/* dma_list_sample.c - SPU MFC-DMA list sample code.
 *
 * This sample defines a transfer-element data structure, which 
 * contains the element's transfer size and low-order 32 bytes of the effective 
 * address. Also defined in the structure, but not used by this sample, 
 * is the DMA-list stall-and-notify bit, which can be used to indicate 
 * that the MFC should suspend list execution after transferring a list 
 * element whose stall-and-notify bit is set.
 */

#include <spu_mfcio.h>

struct dma_list_elem {
    union {
		unsigned int all32;
		struct {
	    		unsigned nbytes: 31;
	    		unsigned stall:  1;
       		} bits;
    } size;
    unsigned int ea_low;
};

struct dma_list_elem list[16] __attribute__ ((aligned (8)));

void get_large_region(void *dst, unsigned int ea_low, unsigned int nbytes)
{
    unsigned int i = 0;
    unsigned int tagid = 0;
    unsigned int listsize;

    /* get_large_region
     *    Use a single DMA list command request to transfer 
     *    a "large" memory region into LS. The total size to 
     *    be copied may be larger than the MFC's single element 
     *    transfer limit of 16kb.
     */

    if (!nbytes)
	return;

    while (nbytes > 0) {
		unsigned int sz;

		sz = (nbytes < 16384) ? nbytes : 16384;
		list[i].size.all32 = sz;
		list[i].ea_low = ea_low;

		nbytes -= sz;
		ea_low += sz;
		i++;
    }


/* Specify the list size and initiate the list transfer
 */

    listsize = i * sizeof(struct dma_list_elem);
    spu_mfcdma32(dst, (unsigned int) &list[0], listsize, tagid, MFC_GETL_CMD);
}