📄 mcd_dmaapi.c
字号:
/*
* 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 + -