1*ce09fc49STsiChungLiew /* 2*ce09fc49STsiChungLiew * Copyright (C) 2004-2007 Freescale Semiconductor, Inc. 3*ce09fc49STsiChungLiew * 4*ce09fc49STsiChungLiew * See file CREDITS for list of people who contributed to this 5*ce09fc49STsiChungLiew * project. 6*ce09fc49STsiChungLiew * 7*ce09fc49STsiChungLiew * This program is free software; you can redistribute it and/or 8*ce09fc49STsiChungLiew * modify it under the terms of the GNU General Public License as 9*ce09fc49STsiChungLiew * published by the Free Software Foundation; either version 2 of 10*ce09fc49STsiChungLiew * the License, or (at your option) any later version. 11*ce09fc49STsiChungLiew * 12*ce09fc49STsiChungLiew * This program is distributed in the hope that it will be useful, 13*ce09fc49STsiChungLiew * but WITHOUT ANY WARRANTY; without even the implied warranty of 14*ce09fc49STsiChungLiew * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15*ce09fc49STsiChungLiew * GNU General Public License for more details. 16*ce09fc49STsiChungLiew * 17*ce09fc49STsiChungLiew * You should have received a copy of the GNU General Public License 18*ce09fc49STsiChungLiew * along with this program; if not, write to the Free Software 19*ce09fc49STsiChungLiew * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 20*ce09fc49STsiChungLiew * MA 02111-1307 USA 21*ce09fc49STsiChungLiew */ 22*ce09fc49STsiChungLiew 23*ce09fc49STsiChungLiew /*Main C file for multi-channel DMA API. */ 24*ce09fc49STsiChungLiew 25*ce09fc49STsiChungLiew #include <common.h> 26*ce09fc49STsiChungLiew 27*ce09fc49STsiChungLiew #ifdef CONFIG_FSLDMAFEC 28*ce09fc49STsiChungLiew 29*ce09fc49STsiChungLiew #include <MCD_dma.h> 30*ce09fc49STsiChungLiew #include <MCD_tasksInit.h> 31*ce09fc49STsiChungLiew #include <MCD_progCheck.h> 32*ce09fc49STsiChungLiew 33*ce09fc49STsiChungLiew /********************************************************************/ 34*ce09fc49STsiChungLiew /* This is an API-internal pointer to the DMA's registers */ 35*ce09fc49STsiChungLiew dmaRegs *MCD_dmaBar; 36*ce09fc49STsiChungLiew 37*ce09fc49STsiChungLiew /* 38*ce09fc49STsiChungLiew * These are the real and model task tables as generated by the 39*ce09fc49STsiChungLiew * build process 40*ce09fc49STsiChungLiew */ 41*ce09fc49STsiChungLiew extern TaskTableEntry MCD_realTaskTableSrc[NCHANNELS]; 42*ce09fc49STsiChungLiew extern TaskTableEntry MCD_modelTaskTableSrc[NUMOFVARIANTS]; 43*ce09fc49STsiChungLiew 44*ce09fc49STsiChungLiew /* 45*ce09fc49STsiChungLiew * However, this (usually) gets relocated to on-chip SRAM, at which 46*ce09fc49STsiChungLiew * point we access them as these tables 47*ce09fc49STsiChungLiew */ 48*ce09fc49STsiChungLiew volatile TaskTableEntry *MCD_taskTable; 49*ce09fc49STsiChungLiew TaskTableEntry *MCD_modelTaskTable; 50*ce09fc49STsiChungLiew 51*ce09fc49STsiChungLiew /* 52*ce09fc49STsiChungLiew * MCD_chStatus[] is an array of status indicators for remembering 53*ce09fc49STsiChungLiew * whether a DMA has ever been attempted on each channel, pausing 54*ce09fc49STsiChungLiew * status, etc. 55*ce09fc49STsiChungLiew */ 56*ce09fc49STsiChungLiew static int MCD_chStatus[NCHANNELS] = { 57*ce09fc49STsiChungLiew MCD_NO_DMA, MCD_NO_DMA, MCD_NO_DMA, MCD_NO_DMA, 58*ce09fc49STsiChungLiew MCD_NO_DMA, MCD_NO_DMA, MCD_NO_DMA, MCD_NO_DMA, 59*ce09fc49STsiChungLiew MCD_NO_DMA, MCD_NO_DMA, MCD_NO_DMA, MCD_NO_DMA, 60*ce09fc49STsiChungLiew MCD_NO_DMA, MCD_NO_DMA, MCD_NO_DMA, MCD_NO_DMA 61*ce09fc49STsiChungLiew }; 62*ce09fc49STsiChungLiew 63*ce09fc49STsiChungLiew /* Prototypes for local functions */ 64*ce09fc49STsiChungLiew static void MCD_memcpy(int *dest, int *src, u32 size); 65*ce09fc49STsiChungLiew static void MCD_resmActions(int channel); 66*ce09fc49STsiChungLiew 67*ce09fc49STsiChungLiew /* 68*ce09fc49STsiChungLiew * Buffer descriptors used for storage of progress info for single Dmas 69*ce09fc49STsiChungLiew * Also used as storage for the DMA for CRCs for single DMAs 70*ce09fc49STsiChungLiew * Otherwise, the DMA does not parse these buffer descriptors 71*ce09fc49STsiChungLiew */ 72*ce09fc49STsiChungLiew #ifdef MCD_INCLUDE_EU 73*ce09fc49STsiChungLiew extern MCD_bufDesc MCD_singleBufDescs[NCHANNELS]; 74*ce09fc49STsiChungLiew #else 75*ce09fc49STsiChungLiew MCD_bufDesc MCD_singleBufDescs[NCHANNELS]; 76*ce09fc49STsiChungLiew #endif 77*ce09fc49STsiChungLiew MCD_bufDesc *MCD_relocBuffDesc; 78*ce09fc49STsiChungLiew 79*ce09fc49STsiChungLiew /* Defines for the debug control register's functions */ 80*ce09fc49STsiChungLiew #define DBG_CTL_COMP1_TASK (0x00002000) 81*ce09fc49STsiChungLiew #define DBG_CTL_ENABLE (DBG_CTL_AUTO_ARM | \ 82*ce09fc49STsiChungLiew DBG_CTL_BREAK | \ 83*ce09fc49STsiChungLiew DBG_CTL_INT_BREAK | \ 84*ce09fc49STsiChungLiew DBG_CTL_COMP1_TASK) 85*ce09fc49STsiChungLiew #define DBG_CTL_DISABLE (DBG_CTL_AUTO_ARM | \ 86*ce09fc49STsiChungLiew DBG_CTL_INT_BREAK | \ 87*ce09fc49STsiChungLiew DBG_CTL_COMP1_TASK) 88*ce09fc49STsiChungLiew #define DBG_KILL_ALL_STAT (0xFFFFFFFF) 89*ce09fc49STsiChungLiew 90*ce09fc49STsiChungLiew /* Offset to context save area where progress info is stored */ 91*ce09fc49STsiChungLiew #define CSAVE_OFFSET 10 92*ce09fc49STsiChungLiew 93*ce09fc49STsiChungLiew /* Defines for Byte Swapping */ 94*ce09fc49STsiChungLiew #define MCD_BYTE_SWAP_KILLER 0xFFF8888F 95*ce09fc49STsiChungLiew #define MCD_NO_BYTE_SWAP_ATALL 0x00040000 96*ce09fc49STsiChungLiew 97*ce09fc49STsiChungLiew /* Execution Unit Identifiers */ 98*ce09fc49STsiChungLiew #define MAC 0 /* legacy - not used */ 99*ce09fc49STsiChungLiew #define LUAC 1 /* legacy - not used */ 100*ce09fc49STsiChungLiew #define CRC 2 /* legacy - not used */ 101*ce09fc49STsiChungLiew #define LURC 3 /* Logic Unit with CRC */ 102*ce09fc49STsiChungLiew 103*ce09fc49STsiChungLiew /* Task Identifiers */ 104*ce09fc49STsiChungLiew #define TASK_CHAINNOEU 0 105*ce09fc49STsiChungLiew #define TASK_SINGLENOEU 1 106*ce09fc49STsiChungLiew #ifdef MCD_INCLUDE_EU 107*ce09fc49STsiChungLiew #define TASK_CHAINEU 2 108*ce09fc49STsiChungLiew #define TASK_SINGLEEU 3 109*ce09fc49STsiChungLiew #define TASK_FECRX 4 110*ce09fc49STsiChungLiew #define TASK_FECTX 5 111*ce09fc49STsiChungLiew #else 112*ce09fc49STsiChungLiew #define TASK_CHAINEU 0 113*ce09fc49STsiChungLiew #define TASK_SINGLEEU 1 114*ce09fc49STsiChungLiew #define TASK_FECRX 2 115*ce09fc49STsiChungLiew #define TASK_FECTX 3 116*ce09fc49STsiChungLiew #endif 117*ce09fc49STsiChungLiew 118*ce09fc49STsiChungLiew /* 119*ce09fc49STsiChungLiew * Structure to remember which variant is on which channel 120*ce09fc49STsiChungLiew * TBD- need this? 121*ce09fc49STsiChungLiew */ 122*ce09fc49STsiChungLiew typedef struct MCD_remVariants_struct MCD_remVariant; 123*ce09fc49STsiChungLiew struct MCD_remVariants_struct { 124*ce09fc49STsiChungLiew int remDestRsdIncr[NCHANNELS]; /* -1,0,1 */ 125*ce09fc49STsiChungLiew int remSrcRsdIncr[NCHANNELS]; /* -1,0,1 */ 126*ce09fc49STsiChungLiew s16 remDestIncr[NCHANNELS]; /* DestIncr */ 127*ce09fc49STsiChungLiew s16 remSrcIncr[NCHANNELS]; /* srcIncr */ 128*ce09fc49STsiChungLiew u32 remXferSize[NCHANNELS]; /* xferSize */ 129*ce09fc49STsiChungLiew }; 130*ce09fc49STsiChungLiew 131*ce09fc49STsiChungLiew /* Structure to remember the startDma parameters for each channel */ 132*ce09fc49STsiChungLiew MCD_remVariant MCD_remVariants; 133*ce09fc49STsiChungLiew /********************************************************************/ 134*ce09fc49STsiChungLiew /* Function: MCD_initDma 135*ce09fc49STsiChungLiew * Purpose: Initializes the DMA API by setting up a pointer to the DMA 136*ce09fc49STsiChungLiew * registers, relocating and creating the appropriate task 137*ce09fc49STsiChungLiew * structures, and setting up some global settings 138*ce09fc49STsiChungLiew * Arguments: 139*ce09fc49STsiChungLiew * dmaBarAddr - pointer to the multichannel DMA registers 140*ce09fc49STsiChungLiew * taskTableDest - location to move DMA task code and structs to 141*ce09fc49STsiChungLiew * flags - operational parameters 142*ce09fc49STsiChungLiew * Return Value: 143*ce09fc49STsiChungLiew * MCD_TABLE_UNALIGNED if taskTableDest is not 512-byte aligned 144*ce09fc49STsiChungLiew * MCD_OK otherwise 145*ce09fc49STsiChungLiew */ 146*ce09fc49STsiChungLiew extern u32 MCD_funcDescTab0[]; 147*ce09fc49STsiChungLiew 148*ce09fc49STsiChungLiew int MCD_initDma(dmaRegs * dmaBarAddr, void *taskTableDest, u32 flags) 149*ce09fc49STsiChungLiew { 150*ce09fc49STsiChungLiew int i; 151*ce09fc49STsiChungLiew TaskTableEntry *entryPtr; 152*ce09fc49STsiChungLiew 153*ce09fc49STsiChungLiew /* setup the local pointer to register set */ 154*ce09fc49STsiChungLiew MCD_dmaBar = dmaBarAddr; 155*ce09fc49STsiChungLiew 156*ce09fc49STsiChungLiew /* do we need to move/create a task table */ 157*ce09fc49STsiChungLiew if ((flags & MCD_RELOC_TASKS) != 0) { 158*ce09fc49STsiChungLiew int fixedSize; 159*ce09fc49STsiChungLiew u32 *fixedPtr; 160*ce09fc49STsiChungLiew /*int *tablePtr = taskTableDest;TBD */ 161*ce09fc49STsiChungLiew int varTabsOffset, funcDescTabsOffset, contextSavesOffset; 162*ce09fc49STsiChungLiew int taskDescTabsOffset; 163*ce09fc49STsiChungLiew int taskTableSize, varTabsSize, funcDescTabsSize, 164*ce09fc49STsiChungLiew contextSavesSize; 165*ce09fc49STsiChungLiew int taskDescTabSize; 166*ce09fc49STsiChungLiew 167*ce09fc49STsiChungLiew int i; 168*ce09fc49STsiChungLiew 169*ce09fc49STsiChungLiew /* check if physical address is aligned on 512 byte boundary */ 170*ce09fc49STsiChungLiew if (((u32) taskTableDest & 0x000001ff) != 0) 171*ce09fc49STsiChungLiew return (MCD_TABLE_UNALIGNED); 172*ce09fc49STsiChungLiew 173*ce09fc49STsiChungLiew /* set up local pointer to task Table */ 174*ce09fc49STsiChungLiew MCD_taskTable = taskTableDest; 175*ce09fc49STsiChungLiew 176*ce09fc49STsiChungLiew /* 177*ce09fc49STsiChungLiew * Create a task table: 178*ce09fc49STsiChungLiew * - compute aligned base offsets for variable tables and 179*ce09fc49STsiChungLiew * function descriptor tables, then 180*ce09fc49STsiChungLiew * - loop through the task table and setup the pointers 181*ce09fc49STsiChungLiew * - copy over model task table with the the actual task 182*ce09fc49STsiChungLiew * descriptor tables 183*ce09fc49STsiChungLiew */ 184*ce09fc49STsiChungLiew 185*ce09fc49STsiChungLiew taskTableSize = NCHANNELS * sizeof(TaskTableEntry); 186*ce09fc49STsiChungLiew /* align variable tables to size */ 187*ce09fc49STsiChungLiew varTabsOffset = taskTableSize + (u32) taskTableDest; 188*ce09fc49STsiChungLiew if ((varTabsOffset & (VAR_TAB_SIZE - 1)) != 0) 189*ce09fc49STsiChungLiew varTabsOffset = 190*ce09fc49STsiChungLiew (varTabsOffset + VAR_TAB_SIZE) & (~VAR_TAB_SIZE); 191*ce09fc49STsiChungLiew /* align function descriptor tables */ 192*ce09fc49STsiChungLiew varTabsSize = NCHANNELS * VAR_TAB_SIZE; 193*ce09fc49STsiChungLiew funcDescTabsOffset = varTabsOffset + varTabsSize; 194*ce09fc49STsiChungLiew 195*ce09fc49STsiChungLiew if ((funcDescTabsOffset & (FUNCDESC_TAB_SIZE - 1)) != 0) 196*ce09fc49STsiChungLiew funcDescTabsOffset = 197*ce09fc49STsiChungLiew (funcDescTabsOffset + 198*ce09fc49STsiChungLiew FUNCDESC_TAB_SIZE) & (~FUNCDESC_TAB_SIZE); 199*ce09fc49STsiChungLiew 200*ce09fc49STsiChungLiew funcDescTabsSize = FUNCDESC_TAB_NUM * FUNCDESC_TAB_SIZE; 201*ce09fc49STsiChungLiew contextSavesOffset = funcDescTabsOffset + funcDescTabsSize; 202*ce09fc49STsiChungLiew contextSavesSize = (NCHANNELS * CONTEXT_SAVE_SIZE); 203*ce09fc49STsiChungLiew fixedSize = 204*ce09fc49STsiChungLiew taskTableSize + varTabsSize + funcDescTabsSize + 205*ce09fc49STsiChungLiew contextSavesSize; 206*ce09fc49STsiChungLiew 207*ce09fc49STsiChungLiew /* zero the thing out */ 208*ce09fc49STsiChungLiew fixedPtr = (u32 *) taskTableDest; 209*ce09fc49STsiChungLiew for (i = 0; i < (fixedSize / 4); i++) 210*ce09fc49STsiChungLiew fixedPtr[i] = 0; 211*ce09fc49STsiChungLiew 212*ce09fc49STsiChungLiew entryPtr = (TaskTableEntry *) MCD_taskTable; 213*ce09fc49STsiChungLiew /* set up fixed pointers */ 214*ce09fc49STsiChungLiew for (i = 0; i < NCHANNELS; i++) { 215*ce09fc49STsiChungLiew /* update ptr to local value */ 216*ce09fc49STsiChungLiew entryPtr[i].varTab = (u32) varTabsOffset; 217*ce09fc49STsiChungLiew entryPtr[i].FDTandFlags = 218*ce09fc49STsiChungLiew (u32) funcDescTabsOffset | MCD_TT_FLAGS_DEF; 219*ce09fc49STsiChungLiew entryPtr[i].contextSaveSpace = (u32) contextSavesOffset; 220*ce09fc49STsiChungLiew varTabsOffset += VAR_TAB_SIZE; 221*ce09fc49STsiChungLiew #ifdef MCD_INCLUDE_EU 222*ce09fc49STsiChungLiew /* if not there is only one, just point to the 223*ce09fc49STsiChungLiew same one */ 224*ce09fc49STsiChungLiew funcDescTabsOffset += FUNCDESC_TAB_SIZE; 225*ce09fc49STsiChungLiew #endif 226*ce09fc49STsiChungLiew contextSavesOffset += CONTEXT_SAVE_SIZE; 227*ce09fc49STsiChungLiew } 228*ce09fc49STsiChungLiew /* copy over the function descriptor table */ 229*ce09fc49STsiChungLiew for (i = 0; i < FUNCDESC_TAB_NUM; i++) { 230*ce09fc49STsiChungLiew MCD_memcpy((void *)(entryPtr[i]. 231*ce09fc49STsiChungLiew FDTandFlags & ~MCD_TT_FLAGS_MASK), 232*ce09fc49STsiChungLiew (void *)MCD_funcDescTab0, FUNCDESC_TAB_SIZE); 233*ce09fc49STsiChungLiew } 234*ce09fc49STsiChungLiew 235*ce09fc49STsiChungLiew /* copy model task table to where the context saves stuff 236*ce09fc49STsiChungLiew leaves off */ 237*ce09fc49STsiChungLiew MCD_modelTaskTable = (TaskTableEntry *) contextSavesOffset; 238*ce09fc49STsiChungLiew 239*ce09fc49STsiChungLiew MCD_memcpy((void *)MCD_modelTaskTable, 240*ce09fc49STsiChungLiew (void *)MCD_modelTaskTableSrc, 241*ce09fc49STsiChungLiew NUMOFVARIANTS * sizeof(TaskTableEntry)); 242*ce09fc49STsiChungLiew 243*ce09fc49STsiChungLiew /* point to local version of model task table */ 244*ce09fc49STsiChungLiew entryPtr = MCD_modelTaskTable; 245*ce09fc49STsiChungLiew taskDescTabsOffset = (u32) MCD_modelTaskTable + 246*ce09fc49STsiChungLiew (NUMOFVARIANTS * sizeof(TaskTableEntry)); 247*ce09fc49STsiChungLiew 248*ce09fc49STsiChungLiew /* copy actual task code and update TDT ptrs in local 249*ce09fc49STsiChungLiew model task table */ 250*ce09fc49STsiChungLiew for (i = 0; i < NUMOFVARIANTS; i++) { 251*ce09fc49STsiChungLiew taskDescTabSize = 252*ce09fc49STsiChungLiew entryPtr[i].TDTend - entryPtr[i].TDTstart + 4; 253*ce09fc49STsiChungLiew MCD_memcpy((void *)taskDescTabsOffset, 254*ce09fc49STsiChungLiew (void *)entryPtr[i].TDTstart, 255*ce09fc49STsiChungLiew taskDescTabSize); 256*ce09fc49STsiChungLiew entryPtr[i].TDTstart = (u32) taskDescTabsOffset; 257*ce09fc49STsiChungLiew taskDescTabsOffset += taskDescTabSize; 258*ce09fc49STsiChungLiew entryPtr[i].TDTend = (u32) taskDescTabsOffset - 4; 259*ce09fc49STsiChungLiew } 260*ce09fc49STsiChungLiew #ifdef MCD_INCLUDE_EU 261*ce09fc49STsiChungLiew /* Tack single DMA BDs onto end of code so API controls 262*ce09fc49STsiChungLiew where they are since DMA might write to them */ 263*ce09fc49STsiChungLiew MCD_relocBuffDesc = 264*ce09fc49STsiChungLiew (MCD_bufDesc *) (entryPtr[NUMOFVARIANTS - 1].TDTend + 4); 265*ce09fc49STsiChungLiew #else 266*ce09fc49STsiChungLiew /* DMA does not touch them so they can be wherever and we 267*ce09fc49STsiChungLiew don't need to waste SRAM on them */ 268*ce09fc49STsiChungLiew MCD_relocBuffDesc = MCD_singleBufDescs; 269*ce09fc49STsiChungLiew #endif 270*ce09fc49STsiChungLiew } else { 271*ce09fc49STsiChungLiew /* point the would-be relocated task tables and the 272*ce09fc49STsiChungLiew buffer descriptors to the ones the linker generated */ 273*ce09fc49STsiChungLiew 274*ce09fc49STsiChungLiew if (((u32) MCD_realTaskTableSrc & 0x000001ff) != 0) 275*ce09fc49STsiChungLiew return (MCD_TABLE_UNALIGNED); 276*ce09fc49STsiChungLiew 277*ce09fc49STsiChungLiew /* need to add code to make sure that every thing else is 278*ce09fc49STsiChungLiew aligned properly TBD. this is problematic if we init 279*ce09fc49STsiChungLiew more than once or after running tasks, need to add 280*ce09fc49STsiChungLiew variable to see if we have aleady init'd */ 281*ce09fc49STsiChungLiew entryPtr = MCD_realTaskTableSrc; 282*ce09fc49STsiChungLiew for (i = 0; i < NCHANNELS; i++) { 283*ce09fc49STsiChungLiew if (((entryPtr[i].varTab & (VAR_TAB_SIZE - 1)) != 0) || 284*ce09fc49STsiChungLiew ((entryPtr[i]. 285*ce09fc49STsiChungLiew FDTandFlags & (FUNCDESC_TAB_SIZE - 1)) != 0)) 286*ce09fc49STsiChungLiew return (MCD_TABLE_UNALIGNED); 287*ce09fc49STsiChungLiew } 288*ce09fc49STsiChungLiew 289*ce09fc49STsiChungLiew MCD_taskTable = MCD_realTaskTableSrc; 290*ce09fc49STsiChungLiew MCD_modelTaskTable = MCD_modelTaskTableSrc; 291*ce09fc49STsiChungLiew MCD_relocBuffDesc = MCD_singleBufDescs; 292*ce09fc49STsiChungLiew } 293*ce09fc49STsiChungLiew 294*ce09fc49STsiChungLiew /* Make all channels as totally inactive, and remember them as such: */ 295*ce09fc49STsiChungLiew 296*ce09fc49STsiChungLiew MCD_dmaBar->taskbar = (u32) MCD_taskTable; 297*ce09fc49STsiChungLiew for (i = 0; i < NCHANNELS; i++) { 298*ce09fc49STsiChungLiew MCD_dmaBar->taskControl[i] = 0x0; 299*ce09fc49STsiChungLiew MCD_chStatus[i] = MCD_NO_DMA; 300*ce09fc49STsiChungLiew } 301*ce09fc49STsiChungLiew 302*ce09fc49STsiChungLiew /* Set up pausing mechanism to inactive state: */ 303*ce09fc49STsiChungLiew /* no particular values yet for either comparator registers */ 304*ce09fc49STsiChungLiew MCD_dmaBar->debugComp1 = 0; 305*ce09fc49STsiChungLiew MCD_dmaBar->debugComp2 = 0; 306*ce09fc49STsiChungLiew MCD_dmaBar->debugControl = DBG_CTL_DISABLE; 307*ce09fc49STsiChungLiew MCD_dmaBar->debugStatus = DBG_KILL_ALL_STAT; 308*ce09fc49STsiChungLiew 309*ce09fc49STsiChungLiew /* enable or disable commbus prefetch, really need an ifdef or 310*ce09fc49STsiChungLiew something to keep from trying to set this in the 8220 */ 311*ce09fc49STsiChungLiew if ((flags & MCD_COMM_PREFETCH_EN) != 0) 312*ce09fc49STsiChungLiew MCD_dmaBar->ptdControl &= ~PTD_CTL_COMM_PREFETCH; 313*ce09fc49STsiChungLiew else 314*ce09fc49STsiChungLiew MCD_dmaBar->ptdControl |= PTD_CTL_COMM_PREFETCH; 315*ce09fc49STsiChungLiew 316*ce09fc49STsiChungLiew return (MCD_OK); 317*ce09fc49STsiChungLiew } 318*ce09fc49STsiChungLiew 319*ce09fc49STsiChungLiew /*********************** End of MCD_initDma() ***********************/ 320*ce09fc49STsiChungLiew 321*ce09fc49STsiChungLiew /********************************************************************/ 322*ce09fc49STsiChungLiew /* Function: MCD_dmaStatus 323*ce09fc49STsiChungLiew * Purpose: Returns the status of the DMA on the requested channel 324*ce09fc49STsiChungLiew * Arguments: channel - channel number 325*ce09fc49STsiChungLiew * Returns: Predefined status indicators 326*ce09fc49STsiChungLiew */ 327*ce09fc49STsiChungLiew int MCD_dmaStatus(int channel) 328*ce09fc49STsiChungLiew { 329*ce09fc49STsiChungLiew u16 tcrValue; 330*ce09fc49STsiChungLiew 331*ce09fc49STsiChungLiew if ((channel < 0) || (channel >= NCHANNELS)) 332*ce09fc49STsiChungLiew return (MCD_CHANNEL_INVALID); 333*ce09fc49STsiChungLiew 334*ce09fc49STsiChungLiew tcrValue = MCD_dmaBar->taskControl[channel]; 335*ce09fc49STsiChungLiew if ((tcrValue & TASK_CTL_EN) == 0) { /* nothing running */ 336*ce09fc49STsiChungLiew /* if last reported with task enabled */ 337*ce09fc49STsiChungLiew if (MCD_chStatus[channel] == MCD_RUNNING 338*ce09fc49STsiChungLiew || MCD_chStatus[channel] == MCD_IDLE) 339*ce09fc49STsiChungLiew MCD_chStatus[channel] = MCD_DONE; 340*ce09fc49STsiChungLiew } else { /* something is running */ 341*ce09fc49STsiChungLiew 342*ce09fc49STsiChungLiew /* There are three possibilities: paused, running or idle. */ 343*ce09fc49STsiChungLiew if (MCD_chStatus[channel] == MCD_RUNNING 344*ce09fc49STsiChungLiew || MCD_chStatus[channel] == MCD_IDLE) { 345*ce09fc49STsiChungLiew MCD_dmaBar->ptdDebug = PTD_DBG_TSK_VLD_INIT; 346*ce09fc49STsiChungLiew /* This register is selected to know which initiator is 347*ce09fc49STsiChungLiew actually asserted. */ 348*ce09fc49STsiChungLiew if ((MCD_dmaBar->ptdDebug >> channel) & 0x1) 349*ce09fc49STsiChungLiew MCD_chStatus[channel] = MCD_RUNNING; 350*ce09fc49STsiChungLiew else 351*ce09fc49STsiChungLiew MCD_chStatus[channel] = MCD_IDLE; 352*ce09fc49STsiChungLiew /* do not change the status if it is already paused. */ 353*ce09fc49STsiChungLiew } 354*ce09fc49STsiChungLiew } 355*ce09fc49STsiChungLiew return MCD_chStatus[channel]; 356*ce09fc49STsiChungLiew } 357*ce09fc49STsiChungLiew 358*ce09fc49STsiChungLiew /******************** End of MCD_dmaStatus() ************************/ 359*ce09fc49STsiChungLiew 360*ce09fc49STsiChungLiew /********************************************************************/ 361*ce09fc49STsiChungLiew /* Function: MCD_startDma 362*ce09fc49STsiChungLiew * Ppurpose: Starts a particular kind of DMA 363*ce09fc49STsiChungLiew * Arguments: 364*ce09fc49STsiChungLiew * srcAddr - the channel on which to run the DMA 365*ce09fc49STsiChungLiew * srcIncr - the address to move data from, or buffer-descriptor address 366*ce09fc49STsiChungLiew * destAddr - the amount to increment the source address per transfer 367*ce09fc49STsiChungLiew * destIncr - the address to move data to 368*ce09fc49STsiChungLiew * dmaSize - the amount to increment the destination address per transfer 369*ce09fc49STsiChungLiew * xferSize - the number bytes in of each data movement (1, 2, or 4) 370*ce09fc49STsiChungLiew * initiator - what device initiates the DMA 371*ce09fc49STsiChungLiew * priority - priority of the DMA 372*ce09fc49STsiChungLiew * flags - flags describing the DMA 373*ce09fc49STsiChungLiew * funcDesc - description of byte swapping, bit swapping, and CRC actions 374*ce09fc49STsiChungLiew * srcAddrVirt - virtual buffer descriptor address TBD 375*ce09fc49STsiChungLiew * Returns: MCD_CHANNEL_INVALID if channel is invalid, else MCD_OK 376*ce09fc49STsiChungLiew */ 377*ce09fc49STsiChungLiew 378*ce09fc49STsiChungLiew int MCD_startDma(int channel, s8 * srcAddr, s16 srcIncr, s8 * destAddr, 379*ce09fc49STsiChungLiew s16 destIncr, u32 dmaSize, u32 xferSize, u32 initiator, 380*ce09fc49STsiChungLiew int priority, u32 flags, u32 funcDesc 381*ce09fc49STsiChungLiew #ifdef MCD_NEED_ADDR_TRANS 382*ce09fc49STsiChungLiew s8 * srcAddrVirt 383*ce09fc49STsiChungLiew #endif 384*ce09fc49STsiChungLiew ) 385*ce09fc49STsiChungLiew { 386*ce09fc49STsiChungLiew int srcRsdIncr, destRsdIncr; 387*ce09fc49STsiChungLiew int *cSave; 388*ce09fc49STsiChungLiew short xferSizeIncr; 389*ce09fc49STsiChungLiew int tcrCount = 0; 390*ce09fc49STsiChungLiew #ifdef MCD_INCLUDE_EU 391*ce09fc49STsiChungLiew u32 *realFuncArray; 392*ce09fc49STsiChungLiew #endif 393*ce09fc49STsiChungLiew 394*ce09fc49STsiChungLiew if ((channel < 0) || (channel >= NCHANNELS)) 395*ce09fc49STsiChungLiew return (MCD_CHANNEL_INVALID); 396*ce09fc49STsiChungLiew 397*ce09fc49STsiChungLiew /* tbd - need to determine the proper response to a bad funcDesc when 398*ce09fc49STsiChungLiew not including EU functions, for now, assign a benign funcDesc, but 399*ce09fc49STsiChungLiew maybe should return an error */ 400*ce09fc49STsiChungLiew #ifndef MCD_INCLUDE_EU 401*ce09fc49STsiChungLiew funcDesc = MCD_FUNC_NOEU1; 402*ce09fc49STsiChungLiew #endif 403*ce09fc49STsiChungLiew 404*ce09fc49STsiChungLiew #ifdef MCD_DEBUG 405*ce09fc49STsiChungLiew printf("startDma:Setting up params\n"); 406*ce09fc49STsiChungLiew #endif 407*ce09fc49STsiChungLiew /* Set us up for task-wise priority. We don't technically need to do 408*ce09fc49STsiChungLiew this on every start, but since the register involved is in the same 409*ce09fc49STsiChungLiew longword as other registers that users are in control of, setting 410*ce09fc49STsiChungLiew it more than once is probably preferable. That since the 411*ce09fc49STsiChungLiew documentation doesn't seem to be completely consistent about the 412*ce09fc49STsiChungLiew nature of the PTD control register. */ 413*ce09fc49STsiChungLiew MCD_dmaBar->ptdControl |= (u16) 0x8000; 414*ce09fc49STsiChungLiew 415*ce09fc49STsiChungLiew /* Not sure what we need to keep here rtm TBD */ 416*ce09fc49STsiChungLiew #if 1 417*ce09fc49STsiChungLiew /* Calculate additional parameters to the regular DMA calls. */ 418*ce09fc49STsiChungLiew srcRsdIncr = srcIncr < 0 ? -1 : (srcIncr > 0 ? 1 : 0); 419*ce09fc49STsiChungLiew destRsdIncr = destIncr < 0 ? -1 : (destIncr > 0 ? 1 : 0); 420*ce09fc49STsiChungLiew 421*ce09fc49STsiChungLiew xferSizeIncr = (xferSize & 0xffff) | 0x20000000; 422*ce09fc49STsiChungLiew 423*ce09fc49STsiChungLiew /* Remember for each channel which variant is running. */ 424*ce09fc49STsiChungLiew MCD_remVariants.remSrcRsdIncr[channel] = srcRsdIncr; 425*ce09fc49STsiChungLiew MCD_remVariants.remDestRsdIncr[channel] = destRsdIncr; 426*ce09fc49STsiChungLiew MCD_remVariants.remDestIncr[channel] = destIncr; 427*ce09fc49STsiChungLiew MCD_remVariants.remSrcIncr[channel] = srcIncr; 428*ce09fc49STsiChungLiew MCD_remVariants.remXferSize[channel] = xferSize; 429*ce09fc49STsiChungLiew #endif 430*ce09fc49STsiChungLiew 431*ce09fc49STsiChungLiew cSave = 432*ce09fc49STsiChungLiew (int *)(MCD_taskTable[channel].contextSaveSpace) + CSAVE_OFFSET + 433*ce09fc49STsiChungLiew CURRBD; 434*ce09fc49STsiChungLiew 435*ce09fc49STsiChungLiew #ifdef MCD_INCLUDE_EU 436*ce09fc49STsiChungLiew /* may move this to EU specific calls */ 437*ce09fc49STsiChungLiew realFuncArray = 438*ce09fc49STsiChungLiew (u32 *) (MCD_taskTable[channel].FDTandFlags & 0xffffff00); 439*ce09fc49STsiChungLiew /* Modify the LURC's normal and byte-residue-loop functions according 440*ce09fc49STsiChungLiew to parameter. */ 441*ce09fc49STsiChungLiew realFuncArray[(LURC * 16)] = xferSize == 4 ? 442*ce09fc49STsiChungLiew funcDesc : xferSize == 2 ? 443*ce09fc49STsiChungLiew funcDesc & 0xfffff00f : funcDesc & 0xffff000f; 444*ce09fc49STsiChungLiew realFuncArray[(LURC * 16 + 1)] = 445*ce09fc49STsiChungLiew (funcDesc & MCD_BYTE_SWAP_KILLER) | MCD_NO_BYTE_SWAP_ATALL; 446*ce09fc49STsiChungLiew #endif 447*ce09fc49STsiChungLiew /* Write the initiator field in the TCR, and also set the 448*ce09fc49STsiChungLiew initiator-hold bit. Note that,due to a hardware quirk, this could 449*ce09fc49STsiChungLiew collide with an MDE access to the initiator-register file, so we 450*ce09fc49STsiChungLiew have to verify that the write reads back correctly. */ 451*ce09fc49STsiChungLiew 452*ce09fc49STsiChungLiew MCD_dmaBar->taskControl[channel] = 453*ce09fc49STsiChungLiew (initiator << 8) | TASK_CTL_HIPRITSKEN | TASK_CTL_HLDINITNUM; 454*ce09fc49STsiChungLiew 455*ce09fc49STsiChungLiew while (((MCD_dmaBar->taskControl[channel] & 0x1fff) != 456*ce09fc49STsiChungLiew ((initiator << 8) | TASK_CTL_HIPRITSKEN | TASK_CTL_HLDINITNUM)) 457*ce09fc49STsiChungLiew && (tcrCount < 1000)) { 458*ce09fc49STsiChungLiew tcrCount++; 459*ce09fc49STsiChungLiew /*MCD_dmaBar->ptd_tcr[channel] = (initiator << 8) | 0x0020; */ 460*ce09fc49STsiChungLiew MCD_dmaBar->taskControl[channel] = 461*ce09fc49STsiChungLiew (initiator << 8) | TASK_CTL_HIPRITSKEN | 462*ce09fc49STsiChungLiew TASK_CTL_HLDINITNUM; 463*ce09fc49STsiChungLiew } 464*ce09fc49STsiChungLiew 465*ce09fc49STsiChungLiew MCD_dmaBar->priority[channel] = (u8) priority & PRIORITY_PRI_MASK; 466*ce09fc49STsiChungLiew /* should be albe to handle this stuff with only one write to ts reg 467*ce09fc49STsiChungLiew - tbd */ 468*ce09fc49STsiChungLiew if (channel < 8 && channel >= 0) { 469*ce09fc49STsiChungLiew MCD_dmaBar->taskSize0 &= ~(0xf << (7 - channel) * 4); 470*ce09fc49STsiChungLiew MCD_dmaBar->taskSize0 |= 471*ce09fc49STsiChungLiew (xferSize & 3) << (((7 - channel) * 4) + 2); 472*ce09fc49STsiChungLiew MCD_dmaBar->taskSize0 |= (xferSize & 3) << ((7 - channel) * 4); 473*ce09fc49STsiChungLiew } else { 474*ce09fc49STsiChungLiew MCD_dmaBar->taskSize1 &= ~(0xf << (15 - channel) * 4); 475*ce09fc49STsiChungLiew MCD_dmaBar->taskSize1 |= 476*ce09fc49STsiChungLiew (xferSize & 3) << (((15 - channel) * 4) + 2); 477*ce09fc49STsiChungLiew MCD_dmaBar->taskSize1 |= (xferSize & 3) << ((15 - channel) * 4); 478*ce09fc49STsiChungLiew } 479*ce09fc49STsiChungLiew 480*ce09fc49STsiChungLiew /* setup task table flags/options which mostly control the line 481*ce09fc49STsiChungLiew buffers */ 482*ce09fc49STsiChungLiew MCD_taskTable[channel].FDTandFlags &= ~MCD_TT_FLAGS_MASK; 483*ce09fc49STsiChungLiew MCD_taskTable[channel].FDTandFlags |= (MCD_TT_FLAGS_MASK & flags); 484*ce09fc49STsiChungLiew 485*ce09fc49STsiChungLiew if (flags & MCD_FECTX_DMA) { 486*ce09fc49STsiChungLiew /* TDTStart and TDTEnd */ 487*ce09fc49STsiChungLiew MCD_taskTable[channel].TDTstart = 488*ce09fc49STsiChungLiew MCD_modelTaskTable[TASK_FECTX].TDTstart; 489*ce09fc49STsiChungLiew MCD_taskTable[channel].TDTend = 490*ce09fc49STsiChungLiew MCD_modelTaskTable[TASK_FECTX].TDTend; 491*ce09fc49STsiChungLiew MCD_startDmaENetXmit(srcAddr, srcAddr, destAddr, MCD_taskTable, 492*ce09fc49STsiChungLiew channel); 493*ce09fc49STsiChungLiew } else if (flags & MCD_FECRX_DMA) { 494*ce09fc49STsiChungLiew /* TDTStart and TDTEnd */ 495*ce09fc49STsiChungLiew MCD_taskTable[channel].TDTstart = 496*ce09fc49STsiChungLiew MCD_modelTaskTable[TASK_FECRX].TDTstart; 497*ce09fc49STsiChungLiew MCD_taskTable[channel].TDTend = 498*ce09fc49STsiChungLiew MCD_modelTaskTable[TASK_FECRX].TDTend; 499*ce09fc49STsiChungLiew MCD_startDmaENetRcv(srcAddr, srcAddr, destAddr, MCD_taskTable, 500*ce09fc49STsiChungLiew channel); 501*ce09fc49STsiChungLiew } else if (flags & MCD_SINGLE_DMA) { 502*ce09fc49STsiChungLiew /* this buffer descriptor is used for storing off initial 503*ce09fc49STsiChungLiew parameters for later progress query calculation and for the 504*ce09fc49STsiChungLiew DMA to write the resulting checksum. The DMA does not use 505*ce09fc49STsiChungLiew this to determine how to operate, that info is passed with 506*ce09fc49STsiChungLiew the init routine */ 507*ce09fc49STsiChungLiew MCD_relocBuffDesc[channel].srcAddr = srcAddr; 508*ce09fc49STsiChungLiew MCD_relocBuffDesc[channel].destAddr = destAddr; 509*ce09fc49STsiChungLiew 510*ce09fc49STsiChungLiew /* definitely not its final value */ 511*ce09fc49STsiChungLiew MCD_relocBuffDesc[channel].lastDestAddr = destAddr; 512*ce09fc49STsiChungLiew 513*ce09fc49STsiChungLiew MCD_relocBuffDesc[channel].dmaSize = dmaSize; 514*ce09fc49STsiChungLiew MCD_relocBuffDesc[channel].flags = 0; /* not used */ 515*ce09fc49STsiChungLiew MCD_relocBuffDesc[channel].csumResult = 0; /* not used */ 516*ce09fc49STsiChungLiew MCD_relocBuffDesc[channel].next = 0; /* not used */ 517*ce09fc49STsiChungLiew 518*ce09fc49STsiChungLiew /* Initialize the progress-querying stuff to show no 519*ce09fc49STsiChungLiew progress: */ 520*ce09fc49STsiChungLiew ((volatile int *)MCD_taskTable[channel]. 521*ce09fc49STsiChungLiew contextSaveSpace)[SRCPTR + CSAVE_OFFSET] = (int)srcAddr; 522*ce09fc49STsiChungLiew ((volatile int *)MCD_taskTable[channel]. 523*ce09fc49STsiChungLiew contextSaveSpace)[DESTPTR + CSAVE_OFFSET] = (int)destAddr; 524*ce09fc49STsiChungLiew ((volatile int *)MCD_taskTable[channel]. 525*ce09fc49STsiChungLiew contextSaveSpace)[DCOUNT + CSAVE_OFFSET] = 0; 526*ce09fc49STsiChungLiew ((volatile int *)MCD_taskTable[channel]. 527*ce09fc49STsiChungLiew contextSaveSpace)[CURRBD + CSAVE_OFFSET] = 528*ce09fc49STsiChungLiew (u32) & (MCD_relocBuffDesc[channel]); 529*ce09fc49STsiChungLiew /* tbd - need to keep the user from trying to call the EU 530*ce09fc49STsiChungLiew routine when MCD_INCLUDE_EU is not defined */ 531*ce09fc49STsiChungLiew if (funcDesc == MCD_FUNC_NOEU1 || funcDesc == MCD_FUNC_NOEU2) { 532*ce09fc49STsiChungLiew /* TDTStart and TDTEnd */ 533*ce09fc49STsiChungLiew MCD_taskTable[channel].TDTstart = 534*ce09fc49STsiChungLiew MCD_modelTaskTable[TASK_SINGLENOEU].TDTstart; 535*ce09fc49STsiChungLiew MCD_taskTable[channel].TDTend = 536*ce09fc49STsiChungLiew MCD_modelTaskTable[TASK_SINGLENOEU].TDTend; 537*ce09fc49STsiChungLiew MCD_startDmaSingleNoEu(srcAddr, srcIncr, destAddr, 538*ce09fc49STsiChungLiew destIncr, dmaSize, xferSizeIncr, 539*ce09fc49STsiChungLiew flags, (int *) 540*ce09fc49STsiChungLiew &(MCD_relocBuffDesc[channel]), 541*ce09fc49STsiChungLiew cSave, MCD_taskTable, channel); 542*ce09fc49STsiChungLiew } else { 543*ce09fc49STsiChungLiew /* TDTStart and TDTEnd */ 544*ce09fc49STsiChungLiew MCD_taskTable[channel].TDTstart = 545*ce09fc49STsiChungLiew MCD_modelTaskTable[TASK_SINGLEEU].TDTstart; 546*ce09fc49STsiChungLiew MCD_taskTable[channel].TDTend = 547*ce09fc49STsiChungLiew MCD_modelTaskTable[TASK_SINGLEEU].TDTend; 548*ce09fc49STsiChungLiew MCD_startDmaSingleEu(srcAddr, srcIncr, destAddr, 549*ce09fc49STsiChungLiew destIncr, dmaSize, xferSizeIncr, 550*ce09fc49STsiChungLiew flags, (int *) 551*ce09fc49STsiChungLiew &(MCD_relocBuffDesc[channel]), 552*ce09fc49STsiChungLiew cSave, MCD_taskTable, channel); 553*ce09fc49STsiChungLiew } 554*ce09fc49STsiChungLiew } else { /* chained DMAS */ 555*ce09fc49STsiChungLiew /* Initialize the progress-querying stuff to show no 556*ce09fc49STsiChungLiew progress: */ 557*ce09fc49STsiChungLiew #if 1 558*ce09fc49STsiChungLiew /* (!defined(MCD_NEED_ADDR_TRANS)) */ 559*ce09fc49STsiChungLiew ((volatile int *)MCD_taskTable[channel]. 560*ce09fc49STsiChungLiew contextSaveSpace)[SRCPTR + CSAVE_OFFSET] 561*ce09fc49STsiChungLiew = (int)((MCD_bufDesc *) srcAddr)->srcAddr; 562*ce09fc49STsiChungLiew ((volatile int *)MCD_taskTable[channel]. 563*ce09fc49STsiChungLiew contextSaveSpace)[DESTPTR + CSAVE_OFFSET] 564*ce09fc49STsiChungLiew = (int)((MCD_bufDesc *) srcAddr)->destAddr; 565*ce09fc49STsiChungLiew #else 566*ce09fc49STsiChungLiew /* if using address translation, need the virtual addr of the 567*ce09fc49STsiChungLiew first buffdesc */ 568*ce09fc49STsiChungLiew ((volatile int *)MCD_taskTable[channel]. 569*ce09fc49STsiChungLiew contextSaveSpace)[SRCPTR + CSAVE_OFFSET] 570*ce09fc49STsiChungLiew = (int)((MCD_bufDesc *) srcAddrVirt)->srcAddr; 571*ce09fc49STsiChungLiew ((volatile int *)MCD_taskTable[channel]. 572*ce09fc49STsiChungLiew contextSaveSpace)[DESTPTR + CSAVE_OFFSET] 573*ce09fc49STsiChungLiew = (int)((MCD_bufDesc *) srcAddrVirt)->destAddr; 574*ce09fc49STsiChungLiew #endif 575*ce09fc49STsiChungLiew ((volatile int *)MCD_taskTable[channel]. 576*ce09fc49STsiChungLiew contextSaveSpace)[DCOUNT + CSAVE_OFFSET] = 0; 577*ce09fc49STsiChungLiew ((volatile int *)MCD_taskTable[channel]. 578*ce09fc49STsiChungLiew contextSaveSpace)[CURRBD + CSAVE_OFFSET] = (u32) srcAddr; 579*ce09fc49STsiChungLiew 580*ce09fc49STsiChungLiew if (funcDesc == MCD_FUNC_NOEU1 || funcDesc == MCD_FUNC_NOEU2) { 581*ce09fc49STsiChungLiew /*TDTStart and TDTEnd */ 582*ce09fc49STsiChungLiew MCD_taskTable[channel].TDTstart = 583*ce09fc49STsiChungLiew MCD_modelTaskTable[TASK_CHAINNOEU].TDTstart; 584*ce09fc49STsiChungLiew MCD_taskTable[channel].TDTend = 585*ce09fc49STsiChungLiew MCD_modelTaskTable[TASK_CHAINNOEU].TDTend; 586*ce09fc49STsiChungLiew MCD_startDmaChainNoEu((int *)srcAddr, srcIncr, 587*ce09fc49STsiChungLiew destIncr, xferSize, 588*ce09fc49STsiChungLiew xferSizeIncr, cSave, 589*ce09fc49STsiChungLiew MCD_taskTable, channel); 590*ce09fc49STsiChungLiew } else { 591*ce09fc49STsiChungLiew /*TDTStart and TDTEnd */ 592*ce09fc49STsiChungLiew MCD_taskTable[channel].TDTstart = 593*ce09fc49STsiChungLiew MCD_modelTaskTable[TASK_CHAINEU].TDTstart; 594*ce09fc49STsiChungLiew MCD_taskTable[channel].TDTend = 595*ce09fc49STsiChungLiew MCD_modelTaskTable[TASK_CHAINEU].TDTend; 596*ce09fc49STsiChungLiew MCD_startDmaChainEu((int *)srcAddr, srcIncr, destIncr, 597*ce09fc49STsiChungLiew xferSize, xferSizeIncr, cSave, 598*ce09fc49STsiChungLiew MCD_taskTable, channel); 599*ce09fc49STsiChungLiew } 600*ce09fc49STsiChungLiew } 601*ce09fc49STsiChungLiew MCD_chStatus[channel] = MCD_IDLE; 602*ce09fc49STsiChungLiew return (MCD_OK); 603*ce09fc49STsiChungLiew } 604*ce09fc49STsiChungLiew 605*ce09fc49STsiChungLiew /************************ End of MCD_startDma() *********************/ 606*ce09fc49STsiChungLiew 607*ce09fc49STsiChungLiew /********************************************************************/ 608*ce09fc49STsiChungLiew /* Function: MCD_XferProgrQuery 609*ce09fc49STsiChungLiew * Purpose: Returns progress of DMA on requested channel 610*ce09fc49STsiChungLiew * Arguments: channel - channel to retrieve progress for 611*ce09fc49STsiChungLiew * progRep - pointer to user supplied MCD_XferProg struct 612*ce09fc49STsiChungLiew * Returns: MCD_CHANNEL_INVALID if channel is invalid, else MCD_OK 613*ce09fc49STsiChungLiew * 614*ce09fc49STsiChungLiew * Notes: 615*ce09fc49STsiChungLiew * MCD_XferProgrQuery() upon completing or after aborting a DMA, or 616*ce09fc49STsiChungLiew * while the DMA is in progress, this function returns the first 617*ce09fc49STsiChungLiew * DMA-destination address not (or not yet) used in the DMA. When 618*ce09fc49STsiChungLiew * encountering a non-ready buffer descriptor, the information for 619*ce09fc49STsiChungLiew * the last completed descriptor is returned. 620*ce09fc49STsiChungLiew * 621*ce09fc49STsiChungLiew * MCD_XferProgQuery() has to avoid the possibility of getting 622*ce09fc49STsiChungLiew * partially-updated information in the event that we should happen 623*ce09fc49STsiChungLiew * to query DMA progress just as the DMA is updating it. It does that 624*ce09fc49STsiChungLiew * by taking advantage of the fact context is not saved frequently for 625*ce09fc49STsiChungLiew * the most part. We therefore read it at least twice until we get the 626*ce09fc49STsiChungLiew * same information twice in a row. 627*ce09fc49STsiChungLiew * 628*ce09fc49STsiChungLiew * Because a small, but not insignificant, amount of time is required 629*ce09fc49STsiChungLiew * to write out the progress-query information, especially upon 630*ce09fc49STsiChungLiew * completion of the DMA, it would be wise to guarantee some time lag 631*ce09fc49STsiChungLiew * between successive readings of the progress-query information. 632*ce09fc49STsiChungLiew */ 633*ce09fc49STsiChungLiew 634*ce09fc49STsiChungLiew /* How many iterations of the loop below to execute to stabilize values */ 635*ce09fc49STsiChungLiew #define STABTIME 0 636*ce09fc49STsiChungLiew 637*ce09fc49STsiChungLiew int MCD_XferProgrQuery(int channel, MCD_XferProg * progRep) 638*ce09fc49STsiChungLiew { 639*ce09fc49STsiChungLiew MCD_XferProg prevRep; 640*ce09fc49STsiChungLiew int again; /* true if we are to try again to ge 641*ce09fc49STsiChungLiew consistent results */ 642*ce09fc49STsiChungLiew int i; /* used as a time-waste counter */ 643*ce09fc49STsiChungLiew int destDiffBytes; /* Total no of bytes that we think actually 644*ce09fc49STsiChungLiew got xfered. */ 645*ce09fc49STsiChungLiew int numIterations; /* number of iterations */ 646*ce09fc49STsiChungLiew int bytesNotXfered; /* bytes that did not get xfered. */ 647*ce09fc49STsiChungLiew s8 *LWAlignedInitDestAddr, *LWAlignedCurrDestAddr; 648*ce09fc49STsiChungLiew int subModVal, addModVal; /* Mode values to added and subtracted 649*ce09fc49STsiChungLiew from the final destAddr */ 650*ce09fc49STsiChungLiew 651*ce09fc49STsiChungLiew if ((channel < 0) || (channel >= NCHANNELS)) 652*ce09fc49STsiChungLiew return (MCD_CHANNEL_INVALID); 653*ce09fc49STsiChungLiew 654*ce09fc49STsiChungLiew /* Read a trial value for the progress-reporting values */ 655*ce09fc49STsiChungLiew prevRep.lastSrcAddr = 656*ce09fc49STsiChungLiew (s8 *) ((volatile int *)MCD_taskTable[channel]. 657*ce09fc49STsiChungLiew contextSaveSpace)[SRCPTR + CSAVE_OFFSET]; 658*ce09fc49STsiChungLiew prevRep.lastDestAddr = 659*ce09fc49STsiChungLiew (s8 *) ((volatile int *)MCD_taskTable[channel]. 660*ce09fc49STsiChungLiew contextSaveSpace)[DESTPTR + CSAVE_OFFSET]; 661*ce09fc49STsiChungLiew prevRep.dmaSize = 662*ce09fc49STsiChungLiew ((volatile int *)MCD_taskTable[channel].contextSaveSpace)[DCOUNT + 663*ce09fc49STsiChungLiew CSAVE_OFFSET]; 664*ce09fc49STsiChungLiew prevRep.currBufDesc = 665*ce09fc49STsiChungLiew (MCD_bufDesc *) ((volatile int *)MCD_taskTable[channel]. 666*ce09fc49STsiChungLiew contextSaveSpace)[CURRBD + CSAVE_OFFSET]; 667*ce09fc49STsiChungLiew /* Repeatedly reread those values until they match previous values: */ 668*ce09fc49STsiChungLiew do { 669*ce09fc49STsiChungLiew /* Waste a little bit of time to ensure stability: */ 670*ce09fc49STsiChungLiew for (i = 0; i < STABTIME; i++) { 671*ce09fc49STsiChungLiew /* make sure this loop does something so that it 672*ce09fc49STsiChungLiew doesn't get optimized out */ 673*ce09fc49STsiChungLiew i += i >> 2; 674*ce09fc49STsiChungLiew } 675*ce09fc49STsiChungLiew /* Check them again: */ 676*ce09fc49STsiChungLiew progRep->lastSrcAddr = 677*ce09fc49STsiChungLiew (s8 *) ((volatile int *)MCD_taskTable[channel]. 678*ce09fc49STsiChungLiew contextSaveSpace)[SRCPTR + CSAVE_OFFSET]; 679*ce09fc49STsiChungLiew progRep->lastDestAddr = 680*ce09fc49STsiChungLiew (s8 *) ((volatile int *)MCD_taskTable[channel]. 681*ce09fc49STsiChungLiew contextSaveSpace)[DESTPTR + CSAVE_OFFSET]; 682*ce09fc49STsiChungLiew progRep->dmaSize = 683*ce09fc49STsiChungLiew ((volatile int *)MCD_taskTable[channel]. 684*ce09fc49STsiChungLiew contextSaveSpace)[DCOUNT + CSAVE_OFFSET]; 685*ce09fc49STsiChungLiew progRep->currBufDesc = 686*ce09fc49STsiChungLiew (MCD_bufDesc *) ((volatile int *)MCD_taskTable[channel]. 687*ce09fc49STsiChungLiew contextSaveSpace)[CURRBD + CSAVE_OFFSET]; 688*ce09fc49STsiChungLiew /* See if they match: */ 689*ce09fc49STsiChungLiew if (prevRep.lastSrcAddr != progRep->lastSrcAddr 690*ce09fc49STsiChungLiew || prevRep.lastDestAddr != progRep->lastDestAddr 691*ce09fc49STsiChungLiew || prevRep.dmaSize != progRep->dmaSize 692*ce09fc49STsiChungLiew || prevRep.currBufDesc != progRep->currBufDesc) { 693*ce09fc49STsiChungLiew /* If they don't match, remember previous values and 694*ce09fc49STsiChungLiew try again: */ 695*ce09fc49STsiChungLiew prevRep.lastSrcAddr = progRep->lastSrcAddr; 696*ce09fc49STsiChungLiew prevRep.lastDestAddr = progRep->lastDestAddr; 697*ce09fc49STsiChungLiew prevRep.dmaSize = progRep->dmaSize; 698*ce09fc49STsiChungLiew prevRep.currBufDesc = progRep->currBufDesc; 699*ce09fc49STsiChungLiew again = MCD_TRUE; 700*ce09fc49STsiChungLiew } else 701*ce09fc49STsiChungLiew again = MCD_FALSE; 702*ce09fc49STsiChungLiew } while (again == MCD_TRUE); 703*ce09fc49STsiChungLiew 704*ce09fc49STsiChungLiew /* Update the dCount, srcAddr and destAddr */ 705*ce09fc49STsiChungLiew /* To calculate dmaCount, we consider destination address. C 706*ce09fc49STsiChungLiew overs M1,P1,Z for destination */ 707*ce09fc49STsiChungLiew switch (MCD_remVariants.remDestRsdIncr[channel]) { 708*ce09fc49STsiChungLiew case MINUS1: 709*ce09fc49STsiChungLiew subModVal = 710*ce09fc49STsiChungLiew ((int)progRep-> 711*ce09fc49STsiChungLiew lastDestAddr) & ((MCD_remVariants.remXferSize[channel]) - 712*ce09fc49STsiChungLiew 1); 713*ce09fc49STsiChungLiew addModVal = 714*ce09fc49STsiChungLiew ((int)progRep->currBufDesc-> 715*ce09fc49STsiChungLiew destAddr) & ((MCD_remVariants.remXferSize[channel]) - 1); 716*ce09fc49STsiChungLiew LWAlignedInitDestAddr = 717*ce09fc49STsiChungLiew (progRep->currBufDesc->destAddr) - addModVal; 718*ce09fc49STsiChungLiew LWAlignedCurrDestAddr = (progRep->lastDestAddr) - subModVal; 719*ce09fc49STsiChungLiew destDiffBytes = LWAlignedInitDestAddr - LWAlignedCurrDestAddr; 720*ce09fc49STsiChungLiew bytesNotXfered = 721*ce09fc49STsiChungLiew (destDiffBytes / MCD_remVariants.remDestIncr[channel]) * 722*ce09fc49STsiChungLiew (MCD_remVariants.remDestIncr[channel] 723*ce09fc49STsiChungLiew + MCD_remVariants.remXferSize[channel]); 724*ce09fc49STsiChungLiew progRep->dmaSize = 725*ce09fc49STsiChungLiew destDiffBytes - bytesNotXfered + addModVal - subModVal; 726*ce09fc49STsiChungLiew break; 727*ce09fc49STsiChungLiew case ZERO: 728*ce09fc49STsiChungLiew progRep->lastDestAddr = progRep->currBufDesc->destAddr; 729*ce09fc49STsiChungLiew break; 730*ce09fc49STsiChungLiew case PLUS1: 731*ce09fc49STsiChungLiew /* This value has to be subtracted from the final 732*ce09fc49STsiChungLiew calculated dCount. */ 733*ce09fc49STsiChungLiew subModVal = 734*ce09fc49STsiChungLiew ((int)progRep->currBufDesc-> 735*ce09fc49STsiChungLiew destAddr) & ((MCD_remVariants.remXferSize[channel]) - 1); 736*ce09fc49STsiChungLiew /* These bytes are already in lastDestAddr. */ 737*ce09fc49STsiChungLiew addModVal = 738*ce09fc49STsiChungLiew ((int)progRep-> 739*ce09fc49STsiChungLiew lastDestAddr) & ((MCD_remVariants.remXferSize[channel]) - 740*ce09fc49STsiChungLiew 1); 741*ce09fc49STsiChungLiew LWAlignedInitDestAddr = 742*ce09fc49STsiChungLiew (progRep->currBufDesc->destAddr) - subModVal; 743*ce09fc49STsiChungLiew LWAlignedCurrDestAddr = (progRep->lastDestAddr) - addModVal; 744*ce09fc49STsiChungLiew destDiffBytes = (progRep->lastDestAddr - LWAlignedInitDestAddr); 745*ce09fc49STsiChungLiew numIterations = 746*ce09fc49STsiChungLiew (LWAlignedCurrDestAddr - 747*ce09fc49STsiChungLiew LWAlignedInitDestAddr) / 748*ce09fc49STsiChungLiew MCD_remVariants.remDestIncr[channel]; 749*ce09fc49STsiChungLiew bytesNotXfered = 750*ce09fc49STsiChungLiew numIterations * (MCD_remVariants.remDestIncr[channel] 751*ce09fc49STsiChungLiew - MCD_remVariants.remXferSize[channel]); 752*ce09fc49STsiChungLiew progRep->dmaSize = destDiffBytes - bytesNotXfered - subModVal; 753*ce09fc49STsiChungLiew break; 754*ce09fc49STsiChungLiew default: 755*ce09fc49STsiChungLiew break; 756*ce09fc49STsiChungLiew } 757*ce09fc49STsiChungLiew 758*ce09fc49STsiChungLiew /* This covers M1,P1,Z for source */ 759*ce09fc49STsiChungLiew switch (MCD_remVariants.remSrcRsdIncr[channel]) { 760*ce09fc49STsiChungLiew case MINUS1: 761*ce09fc49STsiChungLiew progRep->lastSrcAddr = 762*ce09fc49STsiChungLiew progRep->currBufDesc->srcAddr + 763*ce09fc49STsiChungLiew (MCD_remVariants.remSrcIncr[channel] * 764*ce09fc49STsiChungLiew (progRep->dmaSize / MCD_remVariants.remXferSize[channel])); 765*ce09fc49STsiChungLiew break; 766*ce09fc49STsiChungLiew case ZERO: 767*ce09fc49STsiChungLiew progRep->lastSrcAddr = progRep->currBufDesc->srcAddr; 768*ce09fc49STsiChungLiew break; 769*ce09fc49STsiChungLiew case PLUS1: 770*ce09fc49STsiChungLiew progRep->lastSrcAddr = 771*ce09fc49STsiChungLiew progRep->currBufDesc->srcAddr + 772*ce09fc49STsiChungLiew (MCD_remVariants.remSrcIncr[channel] * 773*ce09fc49STsiChungLiew (progRep->dmaSize / MCD_remVariants.remXferSize[channel])); 774*ce09fc49STsiChungLiew break; 775*ce09fc49STsiChungLiew default: 776*ce09fc49STsiChungLiew break; 777*ce09fc49STsiChungLiew } 778*ce09fc49STsiChungLiew 779*ce09fc49STsiChungLiew return (MCD_OK); 780*ce09fc49STsiChungLiew } 781*ce09fc49STsiChungLiew 782*ce09fc49STsiChungLiew /******************* End of MCD_XferProgrQuery() ********************/ 783*ce09fc49STsiChungLiew 784*ce09fc49STsiChungLiew /********************************************************************/ 785*ce09fc49STsiChungLiew /* MCD_resmActions() does the majority of the actions of a DMA resume. 786*ce09fc49STsiChungLiew * It is called from MCD_killDma() and MCD_resumeDma(). It has to be 787*ce09fc49STsiChungLiew * a separate function because the kill function has to negate the task 788*ce09fc49STsiChungLiew * enable before resuming it, but the resume function has to do nothing 789*ce09fc49STsiChungLiew * if there is no DMA on that channel (i.e., if the enable bit is 0). 790*ce09fc49STsiChungLiew */ 791*ce09fc49STsiChungLiew static void MCD_resmActions(int channel) 792*ce09fc49STsiChungLiew { 793*ce09fc49STsiChungLiew MCD_dmaBar->debugControl = DBG_CTL_DISABLE; 794*ce09fc49STsiChungLiew MCD_dmaBar->debugStatus = MCD_dmaBar->debugStatus; 795*ce09fc49STsiChungLiew /* This register is selected to know which initiator is 796*ce09fc49STsiChungLiew actually asserted. */ 797*ce09fc49STsiChungLiew MCD_dmaBar->ptdDebug = PTD_DBG_TSK_VLD_INIT; 798*ce09fc49STsiChungLiew 799*ce09fc49STsiChungLiew if ((MCD_dmaBar->ptdDebug >> channel) & 0x1) 800*ce09fc49STsiChungLiew MCD_chStatus[channel] = MCD_RUNNING; 801*ce09fc49STsiChungLiew else 802*ce09fc49STsiChungLiew MCD_chStatus[channel] = MCD_IDLE; 803*ce09fc49STsiChungLiew } 804*ce09fc49STsiChungLiew 805*ce09fc49STsiChungLiew /********************* End of MCD_resmActions() *********************/ 806*ce09fc49STsiChungLiew 807*ce09fc49STsiChungLiew /********************************************************************/ 808*ce09fc49STsiChungLiew /* Function: MCD_killDma 809*ce09fc49STsiChungLiew * Purpose: Halt the DMA on the requested channel, without any 810*ce09fc49STsiChungLiew * intention of resuming the DMA. 811*ce09fc49STsiChungLiew * Arguments: channel - requested channel 812*ce09fc49STsiChungLiew * Returns: MCD_CHANNEL_INVALID if channel is invalid, else MCD_OK 813*ce09fc49STsiChungLiew * 814*ce09fc49STsiChungLiew * Notes: 815*ce09fc49STsiChungLiew * A DMA may be killed from any state, including paused state, and it 816*ce09fc49STsiChungLiew * always goes to the MCD_HALTED state even if it is killed while in 817*ce09fc49STsiChungLiew * the MCD_NO_DMA or MCD_IDLE states. 818*ce09fc49STsiChungLiew */ 819*ce09fc49STsiChungLiew int MCD_killDma(int channel) 820*ce09fc49STsiChungLiew { 821*ce09fc49STsiChungLiew /* MCD_XferProg progRep; */ 822*ce09fc49STsiChungLiew 823*ce09fc49STsiChungLiew if ((channel < 0) || (channel >= NCHANNELS)) 824*ce09fc49STsiChungLiew return (MCD_CHANNEL_INVALID); 825*ce09fc49STsiChungLiew 826*ce09fc49STsiChungLiew MCD_dmaBar->taskControl[channel] = 0x0; 827*ce09fc49STsiChungLiew MCD_resumeDma(channel); 828*ce09fc49STsiChungLiew /* 829*ce09fc49STsiChungLiew * This must be after the write to the TCR so that the task doesn't 830*ce09fc49STsiChungLiew * start up again momentarily, and before the status assignment so 831*ce09fc49STsiChungLiew * as to override whatever MCD_resumeDma() may do to the channel 832*ce09fc49STsiChungLiew * status. 833*ce09fc49STsiChungLiew */ 834*ce09fc49STsiChungLiew MCD_chStatus[channel] = MCD_HALTED; 835*ce09fc49STsiChungLiew 836*ce09fc49STsiChungLiew /* 837*ce09fc49STsiChungLiew * Update the current buffer descriptor's lastDestAddr field 838*ce09fc49STsiChungLiew * 839*ce09fc49STsiChungLiew * MCD_XferProgrQuery (channel, &progRep); 840*ce09fc49STsiChungLiew * progRep.currBufDesc->lastDestAddr = progRep.lastDestAddr; 841*ce09fc49STsiChungLiew */ 842*ce09fc49STsiChungLiew return (MCD_OK); 843*ce09fc49STsiChungLiew } 844*ce09fc49STsiChungLiew 845*ce09fc49STsiChungLiew /************************ End of MCD_killDma() **********************/ 846*ce09fc49STsiChungLiew 847*ce09fc49STsiChungLiew /********************************************************************/ 848*ce09fc49STsiChungLiew /* Function: MCD_continDma 849*ce09fc49STsiChungLiew * Purpose: Continue a DMA which as stopped due to encountering an 850*ce09fc49STsiChungLiew * unready buffer descriptor. 851*ce09fc49STsiChungLiew * Arguments: channel - channel to continue the DMA on 852*ce09fc49STsiChungLiew * Returns: MCD_CHANNEL_INVALID if channel is invalid, else MCD_OK 853*ce09fc49STsiChungLiew * 854*ce09fc49STsiChungLiew * Notes: 855*ce09fc49STsiChungLiew * This routine does not check to see if there is a task which can 856*ce09fc49STsiChungLiew * be continued. Also this routine should not be used with single DMAs. 857*ce09fc49STsiChungLiew */ 858*ce09fc49STsiChungLiew int MCD_continDma(int channel) 859*ce09fc49STsiChungLiew { 860*ce09fc49STsiChungLiew if ((channel < 0) || (channel >= NCHANNELS)) 861*ce09fc49STsiChungLiew return (MCD_CHANNEL_INVALID); 862*ce09fc49STsiChungLiew 863*ce09fc49STsiChungLiew MCD_dmaBar->taskControl[channel] |= TASK_CTL_EN; 864*ce09fc49STsiChungLiew MCD_chStatus[channel] = MCD_RUNNING; 865*ce09fc49STsiChungLiew 866*ce09fc49STsiChungLiew return (MCD_OK); 867*ce09fc49STsiChungLiew } 868*ce09fc49STsiChungLiew 869*ce09fc49STsiChungLiew /********************** End of MCD_continDma() **********************/ 870*ce09fc49STsiChungLiew 871*ce09fc49STsiChungLiew /********************************************************************* 872*ce09fc49STsiChungLiew * MCD_pauseDma() and MCD_resumeDma() below use the DMA's debug unit 873*ce09fc49STsiChungLiew * to freeze a task and resume it. We freeze a task by breakpointing 874*ce09fc49STsiChungLiew * on the stated task. That is, not any specific place in the task, 875*ce09fc49STsiChungLiew * but any time that task executes. In particular, when that task 876*ce09fc49STsiChungLiew * executes, we want to freeze that task and only that task. 877*ce09fc49STsiChungLiew * 878*ce09fc49STsiChungLiew * The bits of the debug control register influence interrupts vs. 879*ce09fc49STsiChungLiew * breakpoints as follows: 880*ce09fc49STsiChungLiew * - Bits 14 and 0 enable or disable debug functions. If enabled, you 881*ce09fc49STsiChungLiew * will get the interrupt but you may or may not get a breakpoint. 882*ce09fc49STsiChungLiew * - Bits 2 and 1 decide whether you also get a breakpoint in addition 883*ce09fc49STsiChungLiew * to an interrupt. 884*ce09fc49STsiChungLiew * 885*ce09fc49STsiChungLiew * The debug unit can do these actions in response to either internally 886*ce09fc49STsiChungLiew * detected breakpoint conditions from the comparators, or in response 887*ce09fc49STsiChungLiew * to the external breakpoint pin, or both. 888*ce09fc49STsiChungLiew * - Bits 14 and 1 perform the above-described functions for 889*ce09fc49STsiChungLiew * internally-generated conditions, i.e., the debug comparators. 890*ce09fc49STsiChungLiew * - Bits 0 and 2 perform the above-described functions for external 891*ce09fc49STsiChungLiew * conditions, i.e., the breakpoint external pin. 892*ce09fc49STsiChungLiew * 893*ce09fc49STsiChungLiew * Note that, although you "always" get the interrupt when you turn 894*ce09fc49STsiChungLiew * the debug functions, the interrupt can nevertheless, if desired, be 895*ce09fc49STsiChungLiew * masked by the corresponding bit in the PTD's IMR. Note also that 896*ce09fc49STsiChungLiew * this means that bits 14 and 0 must enable debug functions before 897*ce09fc49STsiChungLiew * bits 1 and 2, respectively, have any effect. 898*ce09fc49STsiChungLiew * 899*ce09fc49STsiChungLiew * NOTE: It's extremely important to not pause more than one DMA channel 900*ce09fc49STsiChungLiew * at a time. 901*ce09fc49STsiChungLiew ********************************************************************/ 902*ce09fc49STsiChungLiew 903*ce09fc49STsiChungLiew /********************************************************************/ 904*ce09fc49STsiChungLiew /* Function: MCD_pauseDma 905*ce09fc49STsiChungLiew * Purpose: Pauses the DMA on a given channel (if any DMA is running 906*ce09fc49STsiChungLiew * on that channel). 907*ce09fc49STsiChungLiew * Arguments: channel 908*ce09fc49STsiChungLiew * Returns: MCD_CHANNEL_INVALID if channel is invalid, else MCD_OK 909*ce09fc49STsiChungLiew */ 910*ce09fc49STsiChungLiew int MCD_pauseDma(int channel) 911*ce09fc49STsiChungLiew { 912*ce09fc49STsiChungLiew /* MCD_XferProg progRep; */ 913*ce09fc49STsiChungLiew 914*ce09fc49STsiChungLiew if ((channel < 0) || (channel >= NCHANNELS)) 915*ce09fc49STsiChungLiew return (MCD_CHANNEL_INVALID); 916*ce09fc49STsiChungLiew 917*ce09fc49STsiChungLiew if (MCD_dmaBar->taskControl[channel] & TASK_CTL_EN) { 918*ce09fc49STsiChungLiew MCD_dmaBar->debugComp1 = channel; 919*ce09fc49STsiChungLiew MCD_dmaBar->debugControl = 920*ce09fc49STsiChungLiew DBG_CTL_ENABLE | (1 << (channel + 16)); 921*ce09fc49STsiChungLiew MCD_chStatus[channel] = MCD_PAUSED; 922*ce09fc49STsiChungLiew 923*ce09fc49STsiChungLiew /* 924*ce09fc49STsiChungLiew * Update the current buffer descriptor's lastDestAddr field 925*ce09fc49STsiChungLiew * 926*ce09fc49STsiChungLiew * MCD_XferProgrQuery (channel, &progRep); 927*ce09fc49STsiChungLiew * progRep.currBufDesc->lastDestAddr = progRep.lastDestAddr; 928*ce09fc49STsiChungLiew */ 929*ce09fc49STsiChungLiew } 930*ce09fc49STsiChungLiew return (MCD_OK); 931*ce09fc49STsiChungLiew } 932*ce09fc49STsiChungLiew 933*ce09fc49STsiChungLiew /************************* End of MCD_pauseDma() ********************/ 934*ce09fc49STsiChungLiew 935*ce09fc49STsiChungLiew /********************************************************************/ 936*ce09fc49STsiChungLiew /* Function: MCD_resumeDma 937*ce09fc49STsiChungLiew * Purpose: Resumes the DMA on a given channel (if any DMA is 938*ce09fc49STsiChungLiew * running on that channel). 939*ce09fc49STsiChungLiew * Arguments: channel - channel on which to resume DMA 940*ce09fc49STsiChungLiew * Returns: MCD_CHANNEL_INVALID if channel is invalid, else MCD_OK 941*ce09fc49STsiChungLiew */ 942*ce09fc49STsiChungLiew int MCD_resumeDma(int channel) 943*ce09fc49STsiChungLiew { 944*ce09fc49STsiChungLiew if ((channel < 0) || (channel >= NCHANNELS)) 945*ce09fc49STsiChungLiew return (MCD_CHANNEL_INVALID); 946*ce09fc49STsiChungLiew 947*ce09fc49STsiChungLiew if (MCD_dmaBar->taskControl[channel] & TASK_CTL_EN) 948*ce09fc49STsiChungLiew MCD_resmActions(channel); 949*ce09fc49STsiChungLiew 950*ce09fc49STsiChungLiew return (MCD_OK); 951*ce09fc49STsiChungLiew } 952*ce09fc49STsiChungLiew 953*ce09fc49STsiChungLiew /************************ End of MCD_resumeDma() ********************/ 954*ce09fc49STsiChungLiew 955*ce09fc49STsiChungLiew /********************************************************************/ 956*ce09fc49STsiChungLiew /* Function: MCD_csumQuery 957*ce09fc49STsiChungLiew * Purpose: Provide the checksum after performing a non-chained DMA 958*ce09fc49STsiChungLiew * Arguments: channel - channel to report on 959*ce09fc49STsiChungLiew * csum - pointer to where to write the checksum/CRC 960*ce09fc49STsiChungLiew * Returns: MCD_ERROR if the channel is invalid, else MCD_OK 961*ce09fc49STsiChungLiew * 962*ce09fc49STsiChungLiew * Notes: 963*ce09fc49STsiChungLiew * 964*ce09fc49STsiChungLiew */ 965*ce09fc49STsiChungLiew int MCD_csumQuery(int channel, u32 * csum) 966*ce09fc49STsiChungLiew { 967*ce09fc49STsiChungLiew #ifdef MCD_INCLUDE_EU 968*ce09fc49STsiChungLiew if ((channel < 0) || (channel >= NCHANNELS)) 969*ce09fc49STsiChungLiew return (MCD_CHANNEL_INVALID); 970*ce09fc49STsiChungLiew 971*ce09fc49STsiChungLiew *csum = MCD_relocBuffDesc[channel].csumResult; 972*ce09fc49STsiChungLiew return (MCD_OK); 973*ce09fc49STsiChungLiew #else 974*ce09fc49STsiChungLiew return (MCD_ERROR); 975*ce09fc49STsiChungLiew #endif 976*ce09fc49STsiChungLiew } 977*ce09fc49STsiChungLiew 978*ce09fc49STsiChungLiew /*********************** End of MCD_resumeDma() *********************/ 979*ce09fc49STsiChungLiew 980*ce09fc49STsiChungLiew /********************************************************************/ 981*ce09fc49STsiChungLiew /* Function: MCD_getCodeSize 982*ce09fc49STsiChungLiew * Purpose: Provide the size requirements of the microcoded tasks 983*ce09fc49STsiChungLiew * Returns: Size in bytes 984*ce09fc49STsiChungLiew */ 985*ce09fc49STsiChungLiew int MCD_getCodeSize(void) 986*ce09fc49STsiChungLiew { 987*ce09fc49STsiChungLiew #ifdef MCD_INCLUDE_EU 988*ce09fc49STsiChungLiew return (0x2b5c); 989*ce09fc49STsiChungLiew #else 990*ce09fc49STsiChungLiew return (0x173c); 991*ce09fc49STsiChungLiew #endif 992*ce09fc49STsiChungLiew } 993*ce09fc49STsiChungLiew 994*ce09fc49STsiChungLiew /********************** End of MCD_getCodeSize() ********************/ 995*ce09fc49STsiChungLiew 996*ce09fc49STsiChungLiew /********************************************************************/ 997*ce09fc49STsiChungLiew /* Function: MCD_getVersion 998*ce09fc49STsiChungLiew * Purpose: Provide the version string and number 999*ce09fc49STsiChungLiew * Arguments: longVersion - user supplied pointer to a pointer to a char 1000*ce09fc49STsiChungLiew * which points to the version string 1001*ce09fc49STsiChungLiew * Returns: Version number and version string (by reference) 1002*ce09fc49STsiChungLiew */ 1003*ce09fc49STsiChungLiew char MCD_versionString[] = "Multi-channel DMA API Alpha v0.3 (2004-04-26)"; 1004*ce09fc49STsiChungLiew #define MCD_REV_MAJOR 0x00 1005*ce09fc49STsiChungLiew #define MCD_REV_MINOR 0x03 1006*ce09fc49STsiChungLiew 1007*ce09fc49STsiChungLiew int MCD_getVersion(char **longVersion) 1008*ce09fc49STsiChungLiew { 1009*ce09fc49STsiChungLiew *longVersion = MCD_versionString; 1010*ce09fc49STsiChungLiew return ((MCD_REV_MAJOR << 8) | MCD_REV_MINOR); 1011*ce09fc49STsiChungLiew } 1012*ce09fc49STsiChungLiew 1013*ce09fc49STsiChungLiew /********************** End of MCD_getVersion() *********************/ 1014*ce09fc49STsiChungLiew 1015*ce09fc49STsiChungLiew /********************************************************************/ 1016*ce09fc49STsiChungLiew /* Private version of memcpy() 1017*ce09fc49STsiChungLiew * Note that everything this is used for is longword-aligned. 1018*ce09fc49STsiChungLiew */ 1019*ce09fc49STsiChungLiew static void MCD_memcpy(int *dest, int *src, u32 size) 1020*ce09fc49STsiChungLiew { 1021*ce09fc49STsiChungLiew u32 i; 1022*ce09fc49STsiChungLiew 1023*ce09fc49STsiChungLiew for (i = 0; i < size; i += sizeof(int), dest++, src++) 1024*ce09fc49STsiChungLiew *dest = *src; 1025*ce09fc49STsiChungLiew } 1026*ce09fc49STsiChungLiew #endif /* CONFIG_FSLDMAFEC */ 1027