diff options
Diffstat (limited to 'drivers/dma/MCD_dmaApi.c')
-rw-r--r-- | drivers/dma/MCD_dmaApi.c | 1010 |
1 files changed, 0 insertions, 1010 deletions
diff --git a/drivers/dma/MCD_dmaApi.c b/drivers/dma/MCD_dmaApi.c deleted file mode 100644 index af0e134522..0000000000 --- a/drivers/dma/MCD_dmaApi.c +++ /dev/null @@ -1,1010 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (C) 2004-2007 Freescale Semiconductor, Inc. - */ - -/*Main C file for multi-channel DMA API. */ - -#include <common.h> - -#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) -#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); - - /* set up local pointer to task Table */ - MCD_taskTable = taskTableDest; - - /* - * 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++) { - /* update ptr to local value */ - entryPtr[i].varTab = (u32) varTabsOffset; - 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)); - - /* point to local version of model task table */ - entryPtr = MCD_modelTaskTable; - 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: */ - /* no particular values yet for either comparator registers */ - MCD_dmaBar->debugComp1 = 0; - 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 - */ -int MCD_dmaStatus(int channel) -{ - u16 tcrValue; - - if ((channel < 0) || (channel >= NCHANNELS)) - return (MCD_CHANNEL_INVALID); - - tcrValue = MCD_dmaBar->taskControl[channel]; - if ((tcrValue & TASK_CTL_EN) == 0) { /* nothing running */ - /* if last reported with task enabled */ - if (MCD_chStatus[channel] == MCD_RUNNING - || MCD_chStatus[channel] == MCD_IDLE) - MCD_chStatus[channel] = MCD_DONE; - } else { /* something is running */ - - /* There are three possibilities: paused, running or idle. */ - if (MCD_chStatus[channel] == MCD_RUNNING - || MCD_chStatus[channel] == MCD_IDLE) { - MCD_dmaBar->ptdDebug = PTD_DBG_TSK_VLD_INIT; - /* This register is selected to know which initiator is - actually asserted. */ - if ((MCD_dmaBar->ptdDebug >> channel) & 0x1) - MCD_chStatus[channel] = MCD_RUNNING; - else - MCD_chStatus[channel] = MCD_IDLE; - /* do not change the status if it is already paused. */ - } - } - return MCD_chStatus[channel]; -} - -/******************** End of MCD_dmaStatus() ************************/ - -/********************************************************************/ -/* Function: MCD_startDma - * Ppurpose: Starts a particular kind of DMA - * Arguments: - * srcAddr - the channel on which to run the DMA - * srcIncr - the address to move data from, or buffer-descriptor address - * destAddr - the amount to increment the source address per transfer - * destIncr - the address to move data to - * dmaSize - the amount to increment the destination address per transfer - * xferSize - the number bytes in of each data movement (1, 2, or 4) - * initiator - what device initiates the DMA - * priority - priority of the DMA - * flags - flags describing the DMA - * funcDesc - description of byte swapping, bit swapping, and CRC actions - * srcAddrVirt - virtual buffer descriptor address TBD - * Returns: MCD_CHANNEL_INVALID if channel is invalid, else MCD_OK - */ - -int MCD_startDma(int channel, s8 * srcAddr, s16 srcIncr, s8 * destAddr, - s16 destIncr, u32 dmaSize, u32 xferSize, u32 initiator, - int priority, u32 flags, u32 funcDesc -#ifdef MCD_NEED_ADDR_TRANS - s8 * srcAddrVirt -#endif - ) -{ - int srcRsdIncr, destRsdIncr; - int *cSave; - short xferSizeIncr; - int tcrCount = 0; -#ifdef MCD_INCLUDE_EU - u32 *realFuncArray; -#endif - - if ((channel < 0) || (channel >= NCHANNELS)) - return (MCD_CHANNEL_INVALID); - - /* tbd - need to determine the proper response to a bad funcDesc when - not including EU functions, for now, assign a benign funcDesc, but - maybe should return an error */ -#ifndef MCD_INCLUDE_EU - funcDesc = MCD_FUNC_NOEU1; -#endif - -#ifdef MCD_DEBUG - printf("startDma:Setting up params\n"); -#endif - /* Set us up for task-wise priority. We don't technically need to do - this on every start, but since the register involved is in the same - longword as other registers that users are in control of, setting - it more than once is probably preferable. That since the - documentation doesn't seem to be completely consistent about the - nature of the PTD control register. */ - MCD_dmaBar->ptdControl |= (u16) 0x8000; - - /* Not sure what we need to keep here rtm TBD */ -#if 1 - /* Calculate additional parameters to the regular DMA calls. */ - srcRsdIncr = srcIncr < 0 ? -1 : (srcIncr > 0 ? 1 : 0); - destRsdIncr = destIncr < 0 ? -1 : (destIncr > 0 ? 1 : 0); - - xferSizeIncr = (xferSize & 0xffff) | 0x20000000; - - /* Remember for each channel which variant is running. */ - MCD_remVariants.remSrcRsdIncr[channel] = srcRsdIncr; - MCD_remVariants.remDestRsdIncr[channel] = destRsdIncr; - MCD_remVariants.remDestIncr[channel] = destIncr; - MCD_remVariants.remSrcIncr[channel] = srcIncr; - MCD_remVariants.remXferSize[channel] = xferSize; -#endif - - cSave = - (int *)(MCD_taskTable[channel].contextSaveSpace) + CSAVE_OFFSET + - CURRBD; - -#ifdef MCD_INCLUDE_EU - /* may move this to EU specific calls */ - realFuncArray = - (u32 *) (MCD_taskTable[channel].FDTandFlags & 0xffffff00); - /* Modify the LURC's normal and byte-residue-loop functions according - to parameter. */ - realFuncArray[(LURC * 16)] = xferSize == 4 ? - funcDesc : xferSize == 2 ? - funcDesc & 0xfffff00f : funcDesc & 0xffff000f; - realFuncArray[(LURC * 16 + 1)] = - (funcDesc & MCD_BYTE_SWAP_KILLER) | MCD_NO_BYTE_SWAP_ATALL; -#endif - /* Write the initiator field in the TCR, and also set the - initiator-hold bit. Note that,due to a hardware quirk, this could - collide with an MDE access to the initiator-register file, so we - have to verify that the write reads back correctly. */ - - MCD_dmaBar->taskControl[channel] = - (initiator << 8) | TASK_CTL_HIPRITSKEN | TASK_CTL_HLDINITNUM; - - while (((MCD_dmaBar->taskControl[channel] & 0x1fff) != - ((initiator << 8) | TASK_CTL_HIPRITSKEN | TASK_CTL_HLDINITNUM)) - && (tcrCount < 1000)) { - tcrCount++; - /*MCD_dmaBar->ptd_tcr[channel] = (initiator << 8) | 0x0020; */ - MCD_dmaBar->taskControl[channel] = - (initiator << 8) | TASK_CTL_HIPRITSKEN | - TASK_CTL_HLDINITNUM; - } - - MCD_dmaBar->priority[channel] = (u8) priority & PRIORITY_PRI_MASK; - /* should be albe to handle this stuff with only one write to ts reg - - tbd */ - if (channel < 8 && channel >= 0) { - MCD_dmaBar->taskSize0 &= ~(0xf << (7 - channel) * 4); - MCD_dmaBar->taskSize0 |= - (xferSize & 3) << (((7 - channel) * 4) + 2); - MCD_dmaBar->taskSize0 |= (xferSize & 3) << ((7 - channel) * 4); - } else { - MCD_dmaBar->taskSize1 &= ~(0xf << (15 - channel) * 4); - MCD_dmaBar->taskSize1 |= - (xferSize & 3) << (((15 - channel) * 4) + 2); - MCD_dmaBar->taskSize1 |= (xferSize & 3) << ((15 - channel) * 4); - } - - /* setup task table flags/options which mostly control the line - buffers */ - MCD_taskTable[channel].FDTandFlags &= ~MCD_TT_FLAGS_MASK; - MCD_taskTable[channel].FDTandFlags |= (MCD_TT_FLAGS_MASK & flags); - - if (flags & MCD_FECTX_DMA) { - /* TDTStart and TDTEnd */ - MCD_taskTable[channel].TDTstart = - MCD_modelTaskTable[TASK_FECTX].TDTstart; - MCD_taskTable[channel].TDTend = - MCD_modelTaskTable[TASK_FECTX].TDTend; - MCD_startDmaENetXmit((char *)srcAddr, (char *)srcAddr, - (char *)destAddr, MCD_taskTable, - channel); - } else if (flags & MCD_FECRX_DMA) { - /* TDTStart and TDTEnd */ - MCD_taskTable[channel].TDTstart = - MCD_modelTaskTable[TASK_FECRX].TDTstart; - MCD_taskTable[channel].TDTend = - MCD_modelTaskTable[TASK_FECRX].TDTend; - MCD_startDmaENetRcv((char *)srcAddr, (char *)srcAddr, - (char *)destAddr, MCD_taskTable, - channel); - } else if (flags & MCD_SINGLE_DMA) { - /* this buffer descriptor is used for storing off initial - parameters for later progress query calculation and for the - DMA to write the resulting checksum. The DMA does not use - this to determine how to operate, that info is passed with - the init routine */ - MCD_relocBuffDesc[channel].srcAddr = srcAddr; - MCD_relocBuffDesc[channel].destAddr = destAddr; - - /* definitely not its final value */ - MCD_relocBuffDesc[channel].lastDestAddr = destAddr; - - MCD_relocBuffDesc[channel].dmaSize = dmaSize; - MCD_relocBuffDesc[channel].flags = 0; /* not used */ - MCD_relocBuffDesc[channel].csumResult = 0; /* not used */ - MCD_relocBuffDesc[channel].next = 0; /* not used */ - - /* Initialize the progress-querying stuff to show no - progress: */ - ((volatile int *)MCD_taskTable[channel]. - contextSaveSpace)[SRCPTR + CSAVE_OFFSET] = (int)srcAddr; - ((volatile int *)MCD_taskTable[channel]. - contextSaveSpace)[DESTPTR + CSAVE_OFFSET] = (int)destAddr; - ((volatile int *)MCD_taskTable[channel]. - contextSaveSpace)[DCOUNT + CSAVE_OFFSET] = 0; - ((volatile int *)MCD_taskTable[channel]. - contextSaveSpace)[CURRBD + CSAVE_OFFSET] = -(u32) & (MCD_relocBuffDesc[channel]); - /* tbd - need to keep the user from trying to call the EU - routine when MCD_INCLUDE_EU is not defined */ - if (funcDesc == MCD_FUNC_NOEU1 || funcDesc == MCD_FUNC_NOEU2) { - /* TDTStart and TDTEnd */ - MCD_taskTable[channel].TDTstart = - MCD_modelTaskTable[TASK_SINGLENOEU].TDTstart; - MCD_taskTable[channel].TDTend = - MCD_modelTaskTable[TASK_SINGLENOEU].TDTend; - MCD_startDmaSingleNoEu((char *)srcAddr, srcIncr, - (char *)destAddr, destIncr, - (int)dmaSize, xferSizeIncr, - flags, (int *) - &(MCD_relocBuffDesc[channel]), - cSave, MCD_taskTable, channel); - } else { - /* TDTStart and TDTEnd */ - MCD_taskTable[channel].TDTstart = - MCD_modelTaskTable[TASK_SINGLEEU].TDTstart; - MCD_taskTable[channel].TDTend = - MCD_modelTaskTable[TASK_SINGLEEU].TDTend; - MCD_startDmaSingleEu((char *)srcAddr, srcIncr, - (char *)destAddr, destIncr, - (int)dmaSize, xferSizeIncr, - flags, (int *) - &(MCD_relocBuffDesc[channel]), - cSave, MCD_taskTable, channel); - } - } else { /* chained DMAS */ - /* Initialize the progress-querying stuff to show no - progress: */ -#if 1 - /* (!defined(MCD_NEED_ADDR_TRANS)) */ - ((volatile int *)MCD_taskTable[channel]. - contextSaveSpace)[SRCPTR + CSAVE_OFFSET] - = (int)((MCD_bufDesc *) srcAddr)->srcAddr; - ((volatile int *)MCD_taskTable[channel]. - contextSaveSpace)[DESTPTR + CSAVE_OFFSET] - = (int)((MCD_bufDesc *) srcAddr)->destAddr; -#else - /* if using address translation, need the virtual addr of the - first buffdesc */ - ((volatile int *)MCD_taskTable[channel]. - contextSaveSpace)[SRCPTR + CSAVE_OFFSET] - = (int)((MCD_bufDesc *) srcAddrVirt)->srcAddr; - ((volatile int *)MCD_taskTable[channel]. - contextSaveSpace)[DESTPTR + CSAVE_OFFSET] - = (int)((MCD_bufDesc *) srcAddrVirt)->destAddr; -#endif - ((volatile int *)MCD_taskTable[channel]. - contextSaveSpace)[DCOUNT + CSAVE_OFFSET] = 0; - ((volatile int *)MCD_taskTable[channel]. - contextSaveSpace)[CURRBD + CSAVE_OFFSET] = (u32) srcAddr; - - if (funcDesc == MCD_FUNC_NOEU1 || funcDesc == MCD_FUNC_NOEU2) { - /*TDTStart and TDTEnd */ - MCD_taskTable[channel].TDTstart = - MCD_modelTaskTable[TASK_CHAINNOEU].TDTstart; - MCD_taskTable[channel].TDTend = - MCD_modelTaskTable[TASK_CHAINNOEU].TDTend; - MCD_startDmaChainNoEu((int *)srcAddr, srcIncr, - destIncr, xferSize, - xferSizeIncr, cSave, - MCD_taskTable, channel); - } else { - /*TDTStart and TDTEnd */ - MCD_taskTable[channel].TDTstart = - MCD_modelTaskTable[TASK_CHAINEU].TDTstart; - MCD_taskTable[channel].TDTend = - MCD_modelTaskTable[TASK_CHAINEU].TDTend; - MCD_startDmaChainEu((int *)srcAddr, srcIncr, destIncr, - xferSize, xferSizeIncr, cSave, - MCD_taskTable, channel); - } - } - MCD_chStatus[channel] = MCD_IDLE; - return (MCD_OK); -} - -/************************ End of MCD_startDma() *********************/ - -/********************************************************************/ -/* Function: MCD_XferProgrQuery - * Purpose: Returns progress of DMA on requested channel - * Arguments: channel - channel to retrieve progress for - * progRep - pointer to user supplied MCD_XferProg struct - * Returns: MCD_CHANNEL_INVALID if channel is invalid, else MCD_OK - * - * Notes: - * MCD_XferProgrQuery() upon completing or after aborting a DMA, or - * while the DMA is in progress, this function returns the first - * DMA-destination address not (or not yet) used in the DMA. When - * encountering a non-ready buffer descriptor, the information for - * the last completed descriptor is returned. - * - * MCD_XferProgQuery() has to avoid the possibility of getting - * partially-updated information in the event that we should happen - * to query DMA progress just as the DMA is updating it. It does that - * by taking advantage of the fact context is not saved frequently for - * the most part. We therefore read it at least twice until we get the - * same information twice in a row. - * - * Because a small, but not insignificant, amount of time is required - * to write out the progress-query information, especially upon - * completion of the DMA, it would be wise to guarantee some time lag - * between successive readings of the progress-query information. - */ - -/* How many iterations of the loop below to execute to stabilize values */ -#define STABTIME 0 - -int MCD_XferProgrQuery(int channel, MCD_XferProg * progRep) -{ - MCD_XferProg prevRep; - int again; /* true if we are to try again to ge - consistent results */ - int i; /* used as a time-waste counter */ - int destDiffBytes; /* Total no of bytes that we think actually - got xfered. */ - int numIterations; /* number of iterations */ - int bytesNotXfered; /* bytes that did not get xfered. */ - s8 *LWAlignedInitDestAddr, *LWAlignedCurrDestAddr; - int subModVal, addModVal; /* Mode values to added and subtracted - from the final destAddr */ - - if ((channel < 0) || (channel >= NCHANNELS)) - return (MCD_CHANNEL_INVALID); - - /* Read a trial value for the progress-reporting values */ - prevRep.lastSrcAddr = - (s8 *) ((volatile int *)MCD_taskTable[channel]. - contextSaveSpace)[SRCPTR + CSAVE_OFFSET]; - prevRep.lastDestAddr = - (s8 *) ((volatile int *)MCD_taskTable[channel]. - contextSaveSpace)[DESTPTR + CSAVE_OFFSET]; - prevRep.dmaSize = - ((volatile int *)MCD_taskTable[channel].contextSaveSpace)[DCOUNT + - CSAVE_OFFSET]; - prevRep.currBufDesc = - (MCD_bufDesc *) ((volatile int *)MCD_taskTable[channel]. - contextSaveSpace)[CURRBD + CSAVE_OFFSET]; - /* Repeatedly reread those values until they match previous values: */ - do { - /* Waste a little bit of time to ensure stability: */ - for (i = 0; i < STABTIME; i++) { - /* make sure this loop does something so that it - doesn't get optimized out */ - i += i >> 2; - } - /* Check them again: */ - progRep->lastSrcAddr = - (s8 *) ((volatile int *)MCD_taskTable[channel]. - contextSaveSpace)[SRCPTR + CSAVE_OFFSET]; - progRep->lastDestAddr = - (s8 *) ((volatile int *)MCD_taskTable[channel]. - contextSaveSpace)[DESTPTR + CSAVE_OFFSET]; - progRep->dmaSize = - ((volatile int *)MCD_taskTable[channel]. - contextSaveSpace)[DCOUNT + CSAVE_OFFSET]; - progRep->currBufDesc = - (MCD_bufDesc *) ((volatile int *)MCD_taskTable[channel]. - contextSaveSpace)[CURRBD + CSAVE_OFFSET]; - /* See if they match: */ - if (prevRep.lastSrcAddr != progRep->lastSrcAddr - || prevRep.lastDestAddr != progRep->lastDestAddr - || prevRep.dmaSize != progRep->dmaSize - || prevRep.currBufDesc != progRep->currBufDesc) { - /* If they don't match, remember previous values and - try again: */ - prevRep.lastSrcAddr = progRep->lastSrcAddr; - prevRep.lastDestAddr = progRep->lastDestAddr; - prevRep.dmaSize = progRep->dmaSize; - prevRep.currBufDesc = progRep->currBufDesc; - again = MCD_TRUE; - } else - again = MCD_FALSE; - } while (again == MCD_TRUE); - - /* Update the dCount, srcAddr and destAddr */ - /* To calculate dmaCount, we consider destination address. C - overs M1,P1,Z for destination */ - switch (MCD_remVariants.remDestRsdIncr[channel]) { - case MINUS1: - subModVal = - ((int)progRep-> - lastDestAddr) & ((MCD_remVariants.remXferSize[channel]) - - 1); - addModVal = - ((int)progRep->currBufDesc-> - destAddr) & ((MCD_remVariants.remXferSize[channel]) - 1); - LWAlignedInitDestAddr = - (progRep->currBufDesc->destAddr) - addModVal; - LWAlignedCurrDestAddr = (progRep->lastDestAddr) - subModVal; - destDiffBytes = LWAlignedInitDestAddr - LWAlignedCurrDestAddr; - bytesNotXfered = - (destDiffBytes / MCD_remVariants.remDestIncr[channel]) * - (MCD_remVariants.remDestIncr[channel] - + MCD_remVariants.remXferSize[channel]); - progRep->dmaSize = - destDiffBytes - bytesNotXfered + addModVal - subModVal; - break; - case ZERO: - progRep->lastDestAddr = progRep->currBufDesc->destAddr; - break; - case PLUS1: - /* This value has to be subtracted from the final - calculated dCount. */ - subModVal = - ((int)progRep->currBufDesc-> - destAddr) & ((MCD_remVariants.remXferSize[channel]) - 1); - /* These bytes are already in lastDestAddr. */ - addModVal = - ((int)progRep-> - lastDestAddr) & ((MCD_remVariants.remXferSize[channel]) - - 1); - LWAlignedInitDestAddr = - (progRep->currBufDesc->destAddr) - subModVal; - LWAlignedCurrDestAddr = (progRep->lastDestAddr) - addModVal; - destDiffBytes = (progRep->lastDestAddr - LWAlignedInitDestAddr); - numIterations = - (LWAlignedCurrDestAddr - - LWAlignedInitDestAddr) / - MCD_remVariants.remDestIncr[channel]; - bytesNotXfered = - numIterations * (MCD_remVariants.remDestIncr[channel] - - MCD_remVariants.remXferSize[channel]); - progRep->dmaSize = destDiffBytes - bytesNotXfered - subModVal; - break; - default: - break; - } - - /* This covers M1,P1,Z for source */ - switch (MCD_remVariants.remSrcRsdIncr[channel]) { - case MINUS1: - progRep->lastSrcAddr = - progRep->currBufDesc->srcAddr + - (MCD_remVariants.remSrcIncr[channel] * - (progRep->dmaSize / MCD_remVariants.remXferSize[channel])); - break; - case ZERO: - progRep->lastSrcAddr = progRep->currBufDesc->srcAddr; - break; - case PLUS1: - progRep->lastSrcAddr = - progRep->currBufDesc->srcAddr + - (MCD_remVariants.remSrcIncr[channel] * - (progRep->dmaSize / MCD_remVariants.remXferSize[channel])); - break; - default: - break; - } - - return (MCD_OK); -} - -/******************* End of MCD_XferProgrQuery() ********************/ - -/********************************************************************/ -/* MCD_resmActions() does the majority of the actions of a DMA resume. - * It is called from MCD_killDma() and MCD_resumeDma(). It has to be - * a separate function because the kill function has to negate the task - * enable before resuming it, but the resume function has to do nothing - * if there is no DMA on that channel (i.e., if the enable bit is 0). - */ -static void MCD_resmActions(int channel) -{ - MCD_dmaBar->debugControl = DBG_CTL_DISABLE; - MCD_dmaBar->debugStatus = MCD_dmaBar->debugStatus; - /* This register is selected to know which initiator is - actually asserted. */ - MCD_dmaBar->ptdDebug = PTD_DBG_TSK_VLD_INIT; - - if ((MCD_dmaBar->ptdDebug >> channel) & 0x1) - MCD_chStatus[channel] = MCD_RUNNING; - else - MCD_chStatus[channel] = MCD_IDLE; -} - -/********************* End of MCD_resmActions() *********************/ - -/********************************************************************/ -/* Function: MCD_killDma - * Purpose: Halt the DMA on the requested channel, without any - * intention of resuming the DMA. - * Arguments: channel - requested channel - * Returns: MCD_CHANNEL_INVALID if channel is invalid, else MCD_OK - * - * Notes: - * A DMA may be killed from any state, including paused state, and it - * always goes to the MCD_HALTED state even if it is killed while in - * the MCD_NO_DMA or MCD_IDLE states. - */ -int MCD_killDma(int channel) -{ - /* MCD_XferProg progRep; */ - - if ((channel < 0) || (channel >= NCHANNELS)) - return (MCD_CHANNEL_INVALID); - - MCD_dmaBar->taskControl[channel] = 0x0; - MCD_resumeDma(channel); - /* - * This must be after the write to the TCR so that the task doesn't - * start up again momentarily, and before the status assignment so - * as to override whatever MCD_resumeDma() may do to the channel - * status. - */ - MCD_chStatus[channel] = MCD_HALTED; - - /* - * Update the current buffer descriptor's lastDestAddr field - * - * MCD_XferProgrQuery (channel, &progRep); - * progRep.currBufDesc->lastDestAddr = progRep.lastDestAddr; - */ - return (MCD_OK); -} - -/************************ End of MCD_killDma() **********************/ - -/********************************************************************/ -/* Function: MCD_continDma - * Purpose: Continue a DMA which as stopped due to encountering an - * unready buffer descriptor. - * Arguments: channel - channel to continue the DMA on - * Returns: MCD_CHANNEL_INVALID if channel is invalid, else MCD_OK - * - * Notes: - * This routine does not check to see if there is a task which can - * be continued. Also this routine should not be used with single DMAs. - */ -int MCD_continDma(int channel) -{ - if ((channel < 0) || (channel >= NCHANNELS)) - return (MCD_CHANNEL_INVALID); - - MCD_dmaBar->taskControl[channel] |= TASK_CTL_EN; - MCD_chStatus[channel] = MCD_RUNNING; - - return (MCD_OK); -} - -/********************** End of MCD_continDma() **********************/ - -/********************************************************************* - * MCD_pauseDma() and MCD_resumeDma() below use the DMA's debug unit - * to freeze a task and resume it. We freeze a task by breakpointing - * on the stated task. That is, not any specific place in the task, - * but any time that task executes. In particular, when that task - * executes, we want to freeze that task and only that task. - * - * The bits of the debug control register influence interrupts vs. - * breakpoints as follows: - * - Bits 14 and 0 enable or disable debug functions. If enabled, you - * will get the interrupt but you may or may not get a breakpoint. - * - Bits 2 and 1 decide whether you also get a breakpoint in addition - * to an interrupt. - * - * The debug unit can do these actions in response to either internally - * detected breakpoint conditions from the comparators, or in response - * to the external breakpoint pin, or both. - * - Bits 14 and 1 perform the above-described functions for - * internally-generated conditions, i.e., the debug comparators. - * - Bits 0 and 2 perform the above-described functions for external - * conditions, i.e., the breakpoint external pin. - * - * Note that, although you "always" get the interrupt when you turn - * the debug functions, the interrupt can nevertheless, if desired, be - * masked by the corresponding bit in the PTD's IMR. Note also that - * this means that bits 14 and 0 must enable debug functions before - * bits 1 and 2, respectively, have any effect. - * - * NOTE: It's extremely important to not pause more than one DMA channel - * at a time. - ********************************************************************/ - -/********************************************************************/ -/* Function: MCD_pauseDma - * Purpose: Pauses the DMA on a given channel (if any DMA is running - * on that channel). - * Arguments: channel - * Returns: MCD_CHANNEL_INVALID if channel is invalid, else MCD_OK - */ -int MCD_pauseDma(int channel) -{ - /* MCD_XferProg progRep; */ - - if ((channel < 0) || (channel >= NCHANNELS)) - return (MCD_CHANNEL_INVALID); - - if (MCD_dmaBar->taskControl[channel] & TASK_CTL_EN) { - MCD_dmaBar->debugComp1 = channel; - MCD_dmaBar->debugControl = - DBG_CTL_ENABLE | (1 << (channel + 16)); - MCD_chStatus[channel] = MCD_PAUSED; - - /* - * Update the current buffer descriptor's lastDestAddr field - * - * MCD_XferProgrQuery (channel, &progRep); - * progRep.currBufDesc->lastDestAddr = progRep.lastDestAddr; - */ - } - return (MCD_OK); -} - -/************************* End of MCD_pauseDma() ********************/ - -/********************************************************************/ -/* Function: MCD_resumeDma - * Purpose: Resumes the DMA on a given channel (if any DMA is - * running on that channel). - * Arguments: channel - channel on which to resume DMA - * Returns: MCD_CHANNEL_INVALID if channel is invalid, else MCD_OK - */ -int MCD_resumeDma(int channel) -{ - if ((channel < 0) || (channel >= NCHANNELS)) - return (MCD_CHANNEL_INVALID); - - if (MCD_dmaBar->taskControl[channel] & TASK_CTL_EN) - MCD_resmActions(channel); - - return (MCD_OK); -} - -/************************ End of MCD_resumeDma() ********************/ - -/********************************************************************/ -/* Function: MCD_csumQuery - * Purpose: Provide the checksum after performing a non-chained DMA - * Arguments: channel - channel to report on - * csum - pointer to where to write the checksum/CRC - * Returns: MCD_ERROR if the channel is invalid, else MCD_OK - * - * Notes: - * - */ -int MCD_csumQuery(int channel, u32 * csum) -{ -#ifdef MCD_INCLUDE_EU - if ((channel < 0) || (channel >= NCHANNELS)) - return (MCD_CHANNEL_INVALID); - - *csum = MCD_relocBuffDesc[channel].csumResult; - return (MCD_OK); -#else - return (MCD_ERROR); -#endif -} - -/*********************** End of MCD_resumeDma() *********************/ - -/********************************************************************/ -/* Function: MCD_getCodeSize - * Purpose: Provide the size requirements of the microcoded tasks - * Returns: Size in bytes - */ -int MCD_getCodeSize(void) -{ -#ifdef MCD_INCLUDE_EU - return (0x2b5c); -#else - return (0x173c); -#endif -} - -/********************** End of MCD_getCodeSize() ********************/ - -/********************************************************************/ -/* Function: MCD_getVersion - * Purpose: Provide the version string and number - * Arguments: longVersion - user supplied pointer to a pointer to a char - * which points to the version string - * Returns: Version number and version string (by reference) - */ -char MCD_versionString[] = "Multi-channel DMA API Alpha v0.3 (2004-04-26)"; -#define MCD_REV_MAJOR 0x00 -#define MCD_REV_MINOR 0x03 - -int MCD_getVersion(char **longVersion) -{ - *longVersion = MCD_versionString; - return ((MCD_REV_MAJOR << 8) | MCD_REV_MINOR); -} - -/********************** End of MCD_getVersion() *********************/ - -/********************************************************************/ -/* Private version of memcpy() - * Note that everything this is used for is longword-aligned. - */ -static void MCD_memcpy(int *dest, int *src, u32 size) -{ - u32 i; - - for (i = 0; i < size; i += sizeof(int), dest++, src++) - *dest = *src; -} |