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

📄 mcd_dmaapi.c

📁 motorola 针对coldfire 5275 评估板的Dbug bootloader源程序
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
 * File:        MCD_dmaApi.c
 * Purpose:     Main C file for multi-channel DMA API.
 *
 * Notes:
 */

#include "MCD_dma.h"
#include "MCD_tasksInit.h"
#include "MCD_progCheck.h"

/********************************************************************/
/*
 * This is an API-internal pointer to the DMA's registers
 */
dmaRegs *MCD_dmaBar;

/*
 * These are the real and model task tables as generated by the
 * build process
 */
extern TaskTableEntry MCD_realTaskTableSrc[NCHANNELS];
extern TaskTableEntry MCD_modelTaskTableSrc[NUMOFVARIANTS];

/*
 * However, this (usually) gets relocated to on-chip SRAM, at which
 * point we access them as these tables
 */
volatile TaskTableEntry *MCD_taskTable;
TaskTableEntry *MCD_modelTaskTable;


/*
 * MCD_chStatus[] is an array of status indicators for remembering
 * whether a DMA has ever been attempted on each channel, pausing
 * status, etc.
 */
static int MCD_chStatus[NCHANNELS] =
{
    MCD_NO_DMA, MCD_NO_DMA, MCD_NO_DMA, MCD_NO_DMA,
    MCD_NO_DMA, MCD_NO_DMA, MCD_NO_DMA, MCD_NO_DMA,
    MCD_NO_DMA, MCD_NO_DMA, MCD_NO_DMA, MCD_NO_DMA,
    MCD_NO_DMA, MCD_NO_DMA, MCD_NO_DMA, MCD_NO_DMA
};

/*
 * Prototypes for local functions
 */
static void MCD_memcpy (int *dest, int *src, u32 size);
static void MCD_resmActions (int channel);

/*
 * Buffer descriptors used for storage of progress info for single Dmas
 * Also used as storage for the DMA for CRCs for single DMAs
 * Otherwise, the DMA does not parse these buffer descriptors
 */
#ifdef MCD_INCLUDE_EU
extern MCD_bufDesc MCD_singleBufDescs[NCHANNELS];
#else
MCD_bufDesc MCD_singleBufDescs[NCHANNELS];
#endif
MCD_bufDesc *MCD_relocBuffDesc;


/*
 * Defines for the debug control register's functions
 */
#define DBG_CTL_COMP1_TASK  (0x00002000) /* have comparator 1 look for a task # */
#define DBG_CTL_ENABLE      (DBG_CTL_AUTO_ARM    | \
                             DBG_CTL_BREAK       | \
                             DBG_CTL_INT_BREAK   | \
                             DBG_CTL_COMP1_TASK)
#define DBG_CTL_DISABLE     (DBG_CTL_AUTO_ARM    | \
                             DBG_CTL_INT_BREAK   | \
                             DBG_CTL_COMP1_TASK)
#define DBG_KILL_ALL_STAT   (0xFFFFFFFF)

/*
 * Offset to context save area where progress info is stored
 */
#define CSAVE_OFFSET        10

/*
 * Defines for Byte Swapping
 */
#define MCD_BYTE_SWAP_KILLER    0xFFF8888F
#define MCD_NO_BYTE_SWAP_ATALL  0x00040000

/*
 * Execution Unit Identifiers
 */
#define MAC  0  /* legacy - not used */
#define LUAC 1  /* legacy - not used */
#define CRC  2  /* legacy - not used */
#define LURC 3  /* Logic Unit with CRC */

/*
 * Task Identifiers
 */
#define TASK_CHAINNOEU  0
#define TASK_SINGLENOEU 1
#ifdef MCD_INCLUDE_EU
#define TASK_CHAINEU    2
#define TASK_SINGLEEU   3
#define TASK_FECRX      4
#define TASK_FECTX      5
#else
#define TASK_CHAINEU    0
#define TASK_SINGLEEU   1
#define TASK_FECRX      2
#define TASK_FECTX      3
#endif

/*
 * Structure to remember which variant is on which channel
 * TBD- need this?
 */
typedef struct MCD_remVariants_struct MCD_remVariant;
struct MCD_remVariants_struct
{
   int remDestRsdIncr[NCHANNELS];  /* -1,0,1 */
   int remSrcRsdIncr[NCHANNELS];   /* -1,0,1 */
   s16 remDestIncr[NCHANNELS];     /* DestIncr */
   s16 remSrcIncr[NCHANNELS];      /* srcIncr */
   u32 remXferSize[NCHANNELS];     /* xferSize */
};

/*
 * Structure to remember the startDma parameters for each channel
 */
MCD_remVariant MCD_remVariants;
/********************************************************************/
/*
 * Function: MCD_initDma
 * Purpose:  Initializes the DMA API by setting up a pointer to the DMA
 *           registers, relocating and creating the appropriate task
 *           structures, and setting up some global settings
 * Arguments:
 *  dmaBarAddr    - pointer to the multichannel DMA registers
 *  taskTableDest - location to move DMA task code and structs to
 *  flags         - operational parameters
 * Return Value:
 *  MCD_TABLE_UNALIGNED if taskTableDest is not 512-byte aligned
 *  MCD_OK otherwise
 */
extern u32 MCD_funcDescTab0[];

int MCD_initDma (dmaRegs *dmaBarAddr, void *taskTableDest, u32 flags)
{
    int i;
    TaskTableEntry *entryPtr;

    /* setup the local pointer to register set */
    MCD_dmaBar = dmaBarAddr;

    /* do we need to move/create a task table */
    if ((flags & MCD_RELOC_TASKS) != 0)
    {
        int fixedSize;
        u32 *fixedPtr;
        /*int *tablePtr = taskTableDest;TBD*/
        int varTabsOffset, funcDescTabsOffset, contextSavesOffset;
        int taskDescTabsOffset;
        int taskTableSize, varTabsSize, funcDescTabsSize, contextSavesSize;
        int taskDescTabSize;

        int i;

        /* check if physical address is aligned on 512 byte boundary */
        if (((u32)taskTableDest & 0x000001ff) != 0)
            return(MCD_TABLE_UNALIGNED);

        MCD_taskTable = taskTableDest; /* set up local pointer to task Table */

        /*
         * Create a task table:
         * - compute aligned base offsets for variable tables and
         *   function descriptor tables, then
         * - loop through the task table and setup the pointers
         * - copy over model task table with the the actual task descriptor
         *   tables
         */

        taskTableSize = NCHANNELS * sizeof(TaskTableEntry);
        /* align variable tables to size */
        varTabsOffset = taskTableSize + (u32)taskTableDest;
        if ((varTabsOffset & (VAR_TAB_SIZE - 1)) != 0)
            varTabsOffset = (varTabsOffset + VAR_TAB_SIZE) & (~VAR_TAB_SIZE);
        /* align function descriptor tables */
        varTabsSize = NCHANNELS * VAR_TAB_SIZE;
        funcDescTabsOffset = varTabsOffset + varTabsSize;

        if ((funcDescTabsOffset & (FUNCDESC_TAB_SIZE - 1)) != 0)
            funcDescTabsOffset = (funcDescTabsOffset + FUNCDESC_TAB_SIZE) &
            (~FUNCDESC_TAB_SIZE);

        funcDescTabsSize = FUNCDESC_TAB_NUM * FUNCDESC_TAB_SIZE;
        contextSavesOffset = funcDescTabsOffset + funcDescTabsSize;
        contextSavesSize = (NCHANNELS * CONTEXT_SAVE_SIZE);
        fixedSize = taskTableSize + varTabsSize + funcDescTabsSize +
                    contextSavesSize;

        /* zero the thing out */
        fixedPtr = (u32 *)taskTableDest;
        for (i = 0;i<(fixedSize/4);i++)
            fixedPtr[i] = 0;

        entryPtr = (TaskTableEntry*)MCD_taskTable;
        /* set up fixed pointers */
        for (i = 0; i < NCHANNELS; i++)
        {
            entryPtr[i].varTab = (u32)varTabsOffset; /* update ptr to local value */
            entryPtr[i].FDTandFlags = (u32)funcDescTabsOffset | MCD_TT_FLAGS_DEF;
            entryPtr[i].contextSaveSpace = (u32)contextSavesOffset;
            varTabsOffset += VAR_TAB_SIZE;
#ifdef MCD_INCLUDE_EU /* if not there is only one, just point to the same one */
            funcDescTabsOffset += FUNCDESC_TAB_SIZE;
#endif
            contextSavesOffset += CONTEXT_SAVE_SIZE;
        }
        /* copy over the function descriptor table */
        for ( i = 0; i < FUNCDESC_TAB_NUM; i++)
        {
            MCD_memcpy((void*)(entryPtr[i].FDTandFlags & ~MCD_TT_FLAGS_MASK),
                       (void*)MCD_funcDescTab0, FUNCDESC_TAB_SIZE);
        }

        /* copy model task table to where the context saves stuff leaves off*/
        MCD_modelTaskTable = (TaskTableEntry*)contextSavesOffset;

        MCD_memcpy ((void*)MCD_modelTaskTable, (void*)MCD_modelTaskTableSrc,
                    NUMOFVARIANTS * sizeof(TaskTableEntry));

        entryPtr = MCD_modelTaskTable; /* point to local version of
                                                            model task table */
        taskDescTabsOffset = (u32)MCD_modelTaskTable +
                            (NUMOFVARIANTS * sizeof(TaskTableEntry));

        /* copy actual task code and update TDT ptrs in local model task table */
        for (i = 0; i < NUMOFVARIANTS; i++)
        {
            taskDescTabSize = entryPtr[i].TDTend - entryPtr[i].TDTstart + 4;
            MCD_memcpy ((void*)taskDescTabsOffset, (void*)entryPtr[i].TDTstart, taskDescTabSize);
            entryPtr[i].TDTstart = (u32)taskDescTabsOffset;
            taskDescTabsOffset += taskDescTabSize;
            entryPtr[i].TDTend = (u32)taskDescTabsOffset - 4;
        }
#ifdef MCD_INCLUDE_EU /* Tack single DMA BDs onto end of code so API controls
                         where they are since DMA might write to them */        
        MCD_relocBuffDesc = (MCD_bufDesc*)(entryPtr[NUMOFVARIANTS - 1].TDTend + 4);
#else /* DMA does not touch them so they can be wherever and we don't need to 
         waste SRAM on them */
        MCD_relocBuffDesc = MCD_singleBufDescs;
#endif
    }
    else
    {
        /* point the would-be relocated task tables and the
        buffer descriptors to the ones the linker generated */

        if (((u32)MCD_realTaskTableSrc & 0x000001ff) != 0)
            return(MCD_TABLE_UNALIGNED);

        /* need to add code to make sure that every thing else is aligned properly TBD*/
        /* this is problematic if we init more than once or after running tasks,
            need to add variable to see if we have aleady init'd */
        entryPtr = MCD_realTaskTableSrc;
        for (i = 0; i < NCHANNELS; i++)
        {
            if (((entryPtr[i].varTab & (VAR_TAB_SIZE - 1)) != 0) ||
                ((entryPtr[i].FDTandFlags & (FUNCDESC_TAB_SIZE - 1)) != 0))
                return(MCD_TABLE_UNALIGNED);
        }

        MCD_taskTable = MCD_realTaskTableSrc;
        MCD_modelTaskTable = MCD_modelTaskTableSrc;
        MCD_relocBuffDesc = MCD_singleBufDescs;
    }


    /* Make all channels as totally inactive, and remember them as such: */

    MCD_dmaBar->taskbar = (u32) MCD_taskTable;
    for (i = 0;  i < NCHANNELS;  i++)
    {
        MCD_dmaBar->taskControl[i] = 0x0;
        MCD_chStatus[i] = MCD_NO_DMA;
    }

   /* Set up pausing mechanism to inactive state: */
    MCD_dmaBar->debugComp1 = 0;  /* no particular values yet for either comparator registers */
    MCD_dmaBar->debugComp2 = 0;
    MCD_dmaBar->debugControl = DBG_CTL_DISABLE;
    MCD_dmaBar->debugStatus = DBG_KILL_ALL_STAT;

    /* enable or disable commbus prefetch, really need an ifdef or
       something to keep from trying to set this in the 8220 */
    if ((flags & MCD_COMM_PREFETCH_EN) != 0)
        MCD_dmaBar->ptdControl &= ~PTD_CTL_COMM_PREFETCH;
    else
        MCD_dmaBar->ptdControl |= PTD_CTL_COMM_PREFETCH;

    return(MCD_OK);
}
/*********************** End of MCD_initDma() ***********************/

/********************************************************************/
/* Function:   MCD_dmaStatus
 * Purpose:    Returns the status of the DMA on the requested channel
 * Arguments:  channel - channel number
 * Returns:    Predefined status indicators
 */

⌨️ 快捷键说明

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