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