]> git.ipfire.org Git - people/ms/u-boot.git/blame - cpu/mpc824x/drivers/dma/dma1.c
* Code cleanup:
[people/ms/u-boot.git] / cpu / mpc824x / drivers / dma / dma1.c
CommitLineData
327f7a02
WD
1/************************************************************
2 *
3 * copyright @ Motorola, 1999
4 *
5 * App. API
6 *
7 * App. API are the APIs Kernel provides for the application
8 * level program
9 *
10 ************************************************************/
11#include "dma_export.h"
12#include "dma.h"
13
14/* Define a macro to use an optional application-layer print function, if
15 * one was passed to the library during initialization. If there was no
16 * function pointer passed, this protects against referencing a NULL pointer.
17 * Also define The global variable that holds the passed pointer.
18 */
19#define PRINT if ( app_print ) app_print
20static int (*app_print)(char *,...);
21
22/* Set by call to get_eumbbar during DMA_Initialize.
23 * This could be globally available to the library, but there is
24 * an advantage to passing it as a parameter: it is already in a register
25 * and doesn't have to be loaded from memory. Also, that is the way the
26 * library was already implemented and I don't want to change it without
27 * a more detailed analysis.
28 * It is being set as a global variable during initialization to hide it from
29 * the DINK application layer, because it is Kahlua-specific. I think that
30 * get_eumbbar, load_runtime_reg, and store_runtime_reg should be defined in
31 * a Kahlua-specific library dealing with the embedded utilities memory block.
32 * Right now, get_eumbbar is defined in dink32/kahlua.s. The other two are
33 * defined in dink32/drivers/i2c/i2c2.s, drivers/dma/dma2.s, etc.
34 */
35static unsigned int Global_eumbbar = 0;
36extern unsigned int get_eumbbar();
37
38
39extern unsigned int load_runtime_reg( unsigned int eumbbar, unsigned int reg );
40#pragma Alias( load_runtime_reg, "load_runtime_reg" );
41
42extern void store_runtime_reg( unsigned int eumbbar, unsigned int reg, unsigned int val );
43#pragma Alias( store_runtime_reg, "store_runtime_reg" );
44
45unsigned int dma_reg_tb[][14] = {
46 /* local DMA registers */
47 {
48 /* DMA_0_MR */ 0x00001100,
49 /* DMA_0_SR */ 0x00001104,
50 /* DMA_0_CDAR */ 0x00001108,
51 /* DMA_0_SAR */ 0x00001110,
52 /* DMA_0_DAR */ 0x00001118,
53 /* DMA_0_BCR */ 0x00001120,
54 /* DMA_0_NDAR */ 0x00001124,
55 /* DMA_1_MR */ 0x00001200,
56 /* DMA_1_SR */ 0x00001204,
57 /* DMA_1_CDAR */ 0x00001208,
58 /* DMA_1_SAR */ 0x00001210,
59 /* DMA_1_DAR */ 0x00001218,
60 /* DMA_1_BCR */ 0x00001220,
61 /* DMA_1_NDAR */ 0x00001224,
62 },
63 /* remote DMA registers */
64 {
65 /* DMA_0_MR */ 0x00000100,
66 /* DMA_0_SR */ 0x00000104,
67 /* DMA_0_CDAR */ 0x00000108,
68 /* DMA_0_SAR */ 0x00000110,
69 /* DMA_0_DAR */ 0x00000118,
70 /* DMA_0_BCR */ 0x00000120,
71 /* DMA_0_NDAR */ 0x00000124,
72 /* DMA_1_MR */ 0x00000200,
73 /* DMA_1_SR */ 0x00000204,
74 /* DMA_1_CDAR */ 0x00000208,
75 /* DMA_1_SAR */ 0x00000210,
76 /* DMA_1_DAR */ 0x00000218,
77 /* DMA_1_BCR */ 0x00000220,
78 /* DMA_1_NDAR */ 0x00000224,
79 },
80};
81
82/* API functions */
83
84/* Initialize DMA unit with the following:
85 * optional pointer to application layer print function
86 *
87 * These parameters may be added:
88 * ???
89 * Interrupt enables, modes, etc. are set for each transfer.
90 *
91 * This function must be called before DMA unit can be used.
92 */
93extern
94DMA_Status DMA_Initialize( int (*p)(char *,...))
95{
96 DMAStatus status;
97 /* establish the pointer, if there is one, to the application's "printf" */
98 app_print = p;
99
100 /* If this is the first call, get the embedded utilities memory block
101 * base address. I'm not sure what to do about error handling here:
102 * if a non-zero value is returned, accept it.
103 */
104 if ( Global_eumbbar == 0)
105 Global_eumbbar = get_eumbbar();
106 if ( Global_eumbbar == 0)
107 {
108 PRINT( "DMA_Initialize: can't find EUMBBAR\n" );
109 return DMA_ERROR;
110 }
111
112 return DMA_SUCCESS;
113}
114
115
116/* Perform the DMA transfer, only direct mode is currently implemented.
117 * At this point, I think it would be better to define a different
118 * function for chaining mode.
119 * Also, I'm not sure if it is appropriate to have the "generic" API
120 * accept snoop and int_steer parameters. The DINK user interface allows
121 * them, so for now I'll leave them.
122 *
123 * int_steer controls DMA interrupt steering to PCI or local processor
124 * type is the type of transfer: M2M, M2P, P2M, P2P
125 * source is the source address of the data
126 * dest is the destination address of the data
127 * len is the length of data to transfer
128 * channel is the DMA channel to use for the transfer
129 * snoop is the snoop enable control
130 */
131extern DMA_Status DMA_direct_transfer( DMA_INTERRUPT_STEER int_steer,
8bde7f77
WD
132 DMA_TRANSFER_TYPE type,
133 unsigned int source,
134 unsigned int dest,
135 unsigned int len,
136 DMA_CHANNEL channel,
137 DMA_SNOOP_MODE snoop)
327f7a02
WD
138{
139 DMA_MR md;
140 DMA_CDAR cdar;
141 /* it's inappropriate for curr to be a struct, but I'll leave it */
142 DMA_CURR curr;
143
144 DMAStatus stat;
145
146 /* The rest of this code was moved from device.c test_dma to here.
147 * It needs to be cleaned up and validated, but at least it is removed
148 * from the application and API. Most of the mode is left hard coded.
149 * This should be changed after the final API is defined and the user
150 * application has a way to control the transfer.
151 *
152 */
153
154 if ( DMA_Get_Mode( LOCAL, Global_eumbbar, channel, &md ) != DMASUCCESS )
155 {
156 return DMA_ERROR;
157 }
158
159 md.irqs = int_steer;
160 md.pde = 0;
161 md.dahts = 3; /* 8 - byte */
162 md.sahts = 3; /* 8 - byte */
163 md.dahe = 0;
164 md.sahe = 0;
165 md.prc = 0;
166 /* if steering interrupts to local processor, use polling mode */
167 if ( int_steer == DMA_INT_STEER_PCI )
168 {
169 md.eie = 1;
170 md.eotie = 1;
171 } else {
172 md.eie = 0;
173 md.eotie = 0;
174 }
175 md.dl = 0;
176 md.ctm = 1; /* direct mode */
177 md.cc = 0;
178
179 /* validate the length range */
180 if (len > 0x3ffffff )
181 {
182 PRINT( "dev DMA: length of transfer too large: %d\n", len );
183 return DMA_ERROR;
184 }
185
186 /* inappropriate to use a struct, but leave as is for now */
187 curr.src_addr = source;
188 curr.dest_addr = dest;
189 curr.byte_cnt = len;
190
191 (void)DMA_Poke_Desp( LOCAL, Global_eumbbar, channel, &cdar );
192 cdar.snen = snoop;
193 cdar.ctt = type;
194
195 if ( ( stat = DMA_Bld_Desp( LOCAL, Global_eumbbar, channel, cdar ))
196 != DMASUCCESS ||
197 ( stat = DMA_Bld_Curr( LOCAL, Global_eumbbar, channel, curr ))
198 != DMASUCCESS ||
199 ( stat = DMA_Set_Mode( LOCAL, Global_eumbbar, channel, md ))
200 != DMASUCCESS ||
201 ( stat = DMA_Start( LOCAL, Global_eumbbar, channel ))
202 != DMASUCCESS )
203 {
204 if ( stat == DMACHNBUSY )
205 {
206 PRINT( "dev DMA: channel %d busy.\n", channel );
207 }
208 else
209 {
210 PRINT( "dev DMA: invalid channel request.\n", channel );
211 }
212
213 return DMA_ERROR;
214 }
215
216/* Since we are interested at the DMA performace right now,
217 we are going to do as less as possible to burden the
218 603e core.
219
220 if you have epic enabled or don't care the return from
221 DMA operation, you can just return SUCCESS.
222
223 if you don't have epic enabled and care the DMA result,
224 you can use the polling method below.
225
226 Note: I'll attempt to activate the code for handling polling.
227 */
228
229#if 0
230 /* if steering interrupt to local processor, let it handle results */
231 if ( int_steer == DMA_INT_STEER_LOCAL )
232 {
233 return DMA_SUCCESS;
234 }
235
236 /* polling since interrupt goes to PCI */
237 do
238 {
239 stat = DMA_ISR( Global_eumbbar, channel, dma_error_func,
240 dma_error_func, dma_error_func, dma_error_func );
241 }
242 while ( stat == DMANOEVENT );
243#endif
244
245 return DMA_SUCCESS;
246}
247
248/* DMA library internal functions */
249
250/**
251 * Note:
252 *
253 * In all following functions, the host (KAHLUA) processor has a
254 * choice of accessing on board local DMA (LOCAL),
255 * or DMA on a distributed KAHLUA (REMOTE). In either case,
256 * the caller shall pass the configured embedded utility memory
257 * block base address relative to the DMA. If LOCAL DMA is used,
258 * this parameter shall be EUMBBAR, if REMOTE is used, the
259 * parameter shall be the corresponding PCSRBAR.
260 **/
261
262/**************************************************************
263 * function: DMA_Get_Stat
264 *
265 * description: return the content of status register of
266 * the given DMA channel
267 *
268 * if error, reserved0 field all 1s.
269 **************************************************************/
270static
271DMAStatus DMA_Get_Stat( LOCATION host, unsigned int eumbbar, unsigned int channel, DMA_SR *stat )
272{
273 unsigned int tmp;
274
275 if ( channel != 0 && channel != 1 || stat == 0 )
276 {
277 return DMAINVALID;
278 }
279
280 tmp = load_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_SR_REG] );
281#ifdef DMADBG0
282 PRINT( "%s(%d): %s DMA %d (0x%08x) stat = 0x%08x\n", __FILE__, __LINE__,
283 ( host == LOCAL ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_SR_REG], tmp );
284#endif
285
286 stat->reserved0 = ( tmp & 0xffffff00 ) >> 8;
287 stat->lme = ( tmp & 0x00000080 ) >> 7;
288 stat->reserved1 = ( tmp & 0x00000060 ) >> 5;
289 stat->pe = ( tmp & 0x00000010 ) >> 4;
290 stat->reserved2 = ( tmp & 0x00000008 ) >> 3;
291 stat->cb = ( tmp & 0x00000004 ) >> 2;
292 stat->eosi = ( tmp & 0x00000002 ) >> 1;
293 stat->eocai = ( tmp & 0x00000001 );
294
295 return DMASUCCESS;
296}
297
298/**************************************************************
299 * function: DMA_Get_Mode
300 *
301 * description: return the content of mode register of the
302 * given DMA channel
303 *
304 * if error, return DMAINVALID, otherwise return
305 * DMASUCCESS
306 **************************************************************/
307static
308DMAStatus DMA_Get_Mode( LOCATION host, unsigned eumbbar, unsigned int channel, DMA_MR *mode )
309{
310 unsigned int tmp;
311 if ( channel != 0 && channel != 1 || mode == 0 )
312 {
313 return DMAINVALID;
314 }
315
316 tmp = load_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_MR_REG] );
317
318#ifdef DMADBG0
319 PRINT( "%s(%d): %s DMA %d (0x%08x) mode = 0x%08x\n", __FILE__, __LINE__,
320 ( host == LOCAL ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_MR_REG], tmp );
321#endif
322
323 mode->reserved0 = (tmp & 0xfff00000) >> 20;
324 mode->irqs = (tmp & 0x00080000) >> 19;
325 mode->pde = (tmp & 0x00040000) >> 18;
326 mode->dahts = (tmp & 0x00030000) >> 16;
327 mode->sahts = (tmp & 0x0000c000) >> 14;
328 mode->dahe = (tmp & 0x00002000) >> 13;
329 mode->sahe = (tmp & 0x00001000) >> 12;
330 mode->prc = (tmp & 0x00000c00) >> 10;
331 mode->reserved1 = (tmp & 0x00000200) >> 9;
332 mode->eie = (tmp & 0x00000100) >> 8;
333 mode->eotie = (tmp & 0x00000080) >> 7;
334 mode->reserved2 = (tmp & 0x00000070) >> 4;
335 mode->dl = (tmp & 0x00000008) >> 3;
336 mode->ctm = (tmp & 0x00000004) >> 2;
337 mode->cc = (tmp & 0x00000002) >> 1;
338 mode->cs = (tmp & 0x00000001);
339
340 return DMASUCCESS;
341}
342
343/**************************************************************
344 * function: DMA_Set_Mode
345 *
346 * description: Set a new mode to a given DMA channel
347 *
348 * note: It is not a good idea of changing the DMA mode during
349 * the middle of a transaction.
350 **************************************************************/
351static
352DMAStatus DMA_Set_Mode( LOCATION host, unsigned eumbbar, unsigned int channel, DMA_MR mode )
353{
354 unsigned int tmp;
355 if ( channel != 0 && channel != 1 )
356 {
357 return DMAINVALID;
358 }
359
360 tmp = ( mode.reserved0 & 0xfff ) << 20;
361 tmp |= ( ( mode.irqs & 0x1 ) << 19);
362 tmp |= ( ( mode.pde & 0x1 ) << 18 );
363 tmp |= ( ( mode.dahts & 0x3 ) << 16 );
364 tmp |= ( ( mode.sahts & 0x3 ) << 14 );
365 tmp |= ( ( mode.dahe & 0x1 ) << 13 );
366 tmp |= ( ( mode.sahe & 0x1 ) << 12 );
367 tmp |= ( ( mode.prc & 0x3 ) << 10 );
368 tmp |= ( ( mode.reserved1 & 0x1 ) << 9 );
369 tmp |= ( ( mode.eie & 0x1 ) << 8 );
370 tmp |= ( ( mode.eotie & 0x1 ) << 7 );
371 tmp |= ( ( mode.reserved2 & 0x7 ) << 4 );
372 tmp |= ( ( mode.dl & 0x1 ) << 3 );
373 tmp |= ( ( mode.ctm & 0x1 ) << 2 );
374 tmp |= ( ( mode.cc & 0x1 ) << 1 ) ;
375 tmp |= ( mode.cs & 0x1 );
376
377 store_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG + DMA_MR_REG], tmp );
378 return DMASUCCESS;
379}
380
381/************************************************************
382 * function: DMA_Start
383 *
384 * description: start a given DMA channel transaction
385 * return DMASUCCESS if success otherwise return
386 * DMAStatus value
387 *
388 * note: this function will clear DMA_MR(CC) first, then
389 * set DMA_MR(CC).
390 ***********************************************************/
391static
392DMAStatus DMA_Start( LOCATION host, unsigned int eumbbar, unsigned int channel )
393{
394 DMA_SR stat;
395 unsigned int mode;
396
397 if ( channel != 0 && channel != 1 )
398 {
399 return DMAINVALID;
400 }
401
402 if ( DMA_Get_Stat( host, eumbbar, channel, &stat ) != DMASUCCESS )
403 {
404 return DMAINVALID;
405 }
406
407 if ( stat.cb == 1 )
408 {
409 /* DMA is not free */
410 return DMACHNBUSY;
411 }
412
413 mode = load_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG + DMA_MR_REG] );
414 /* clear DMA_MR(CS) */
415 mode &= 0xfffffffe;
416 store_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG + DMA_MR_REG], mode );
417
418 /* set DMA_MR(CS) */
419 mode |= CS;
420 store_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG + DMA_MR_REG], mode );
421 return DMASUCCESS;
422}
423
424/***********************************************************
425 * function: DMA_Halt
426 *
427 * description: halt the current dma transaction on the specified
428 * channel.
429 * return DMASUCCESS if success otherwise return DMAINVALID
430 *
431 * note: if the specified DMA channel is idle, nothing happens
432 *************************************************************/
433static
434DMAStatus DMA_Halt( LOCATION host, unsigned int eumbbar, unsigned int channel )
435{
436 unsigned int mode;
437 if ( channel != 0 && channel != 1 )
438 {
439 return DMAINVALID;
440 }
441
442 mode = load_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG + DMA_MR_REG]);
443
444 /* clear DMA_MR(CS) */
445 mode &= 0xfffffffe;
446 store_runtime_reg(eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG + DMA_MR_REG], mode );
447 return DMASUCCESS;
448}
449
450/*************************************************************
451 * function: DMA_Chn_Cnt
452 *
453 * description: set the DMA_MR(CC) bit for a given channel
454 * that is in chaining mode.
455 * return DMASUCCESS if successfule, otherwise return
456 * DMAINVALID.
457 *
458 * note: if the given channel is not in chaining mode, nothing
459 * happen.
460 *
461 *************************************************************/
462static
463DMAStatus DMA_Chn_Cnt( LOCATION host, unsigned int eumbbar, unsigned int channel )
464{
465 DMA_MR mode;
466 if ( channel != 0 && channel != 1 )
467 {
468 return DMAINVALID;
469 }
470
471 if ( DMA_Get_Mode( host, eumbbar, channel, &mode ) != DMASUCCESS )
472 {
473 return DMAINVALID;
474 }
475
476 if ( mode.ctm == 0 )
477 {
478 /* either illegal mode or not chaining mode */
479 return DMAINVALID;
480 }
481
482 mode.cc = 1;
483 return DMA_Set_Mode( host, eumbbar, channel, mode );
484}
485
486/**************************************************************
487 * function: DMA_Bld_Desp
488 *
489 * description: set current descriptor address register
490 * according to the desp for a given channel
491 *
492 * if the given channel is busy return DMACHNBUSY
493 * and no change made, otherwise return DMASUCCESS.
494 *
495 * note:
496 **************************************************************/
497static
498DMAStatus DMA_Bld_Desp( LOCATION host,
499 unsigned int eumbbar,
500 unsigned int channel,
501 DMA_CDAR desp )
502{
503 DMA_SR status;
504 unsigned int temp;
505
506 if ( channel != 0 && channel != 1 )
507 {
508 /* channel number out of range */
509 return DMAINVALID;
510 }
511
512 if ( DMA_Get_Stat( host, eumbbar, channel, &status ) != DMASUCCESS )
513 {
514 return DMAINVALID;
515 }
516
517 if ( status.cb == 1 )
518 {
519 /* channel busy */
520 return DMACHNBUSY;
521 }
522
523 temp = ( desp.cda & 0x7ffffff ) << 5;
524 temp |= (( desp.snen & 0x1 ) << 4 );
525 temp |= (( desp.eosie & 0x1 ) << 3 );
526 temp |= (( desp.ctt & 0x3 ) << 1 );
527 temp |= ( desp.eotd & 0x1 );
528
529 store_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], temp );
530
531#ifdef DMADBG0
532 PRINT( "%s(%d): %s DMA %d (0x%08x) cdar := 0x%08x\n", __FILE__, __LINE__,
533 ( host == LOCAL ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], temp );
534#endif
535
536 return DMASUCCESS;
537}
538
539/**************************************************************
540 * function: DMA_Poke_Desp
541 *
542 * description: poke the current descriptor address register
543 * for a given channel
544 *
545 * return DMASUCCESS if no error
546 *
547 * note: Due to the undeterministic parallellism of DMA operation,
548 * the value returned by this function shall be taken as
549 * the most recently used descriptor when the last time
550 * DMA starts a chaining mode operation.
551 **************************************************************/
552static
553DMAStatus DMA_Poke_Desp( LOCATION host,
554 unsigned int eumbbar,
555 unsigned int channel,
556 DMA_CDAR *desp )
557{
558 unsigned int cdar;
559 if ( channel != 0 && channel != 1 || desp == 0 )
560 {
561 return DMAINVALID;
562 }
563
564 cdar = load_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG] );
565
566#ifdef DMADBG0
567 PRINT( "%s(%d): %s DMA %d (0x%08x) cdar : 0x%08x\n", __FILE__, __LINE__,
568 ( host == LOCAL ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], cdar );
569#endif
570
571
572 desp->cda = ( cdar & 0xffffffe0 ) >> 5;
573 desp->snen = ( cdar & 0x00000010 ) >> 4;
574 desp->eosie = ( cdar & 0x00000008 ) >> 3;
575 desp->ctt = ( cdar & 0x00000006 ) >> 1;
576 desp->eotd = ( cdar & 0x00000001 );
577
578 return DMASUCCESS;
579}
580
581/**************************************************************
582 * function: DMA_Bld_Curr
583 *
584 * description: set current src, dest, byte count registers
585 * according to the desp for a given channel
586 * return DMASUCCESS if no error.
587 *
588 * note:
589 **************************************************************/
590static
591DMAStatus DMA_Bld_Curr( LOCATION host,
592 unsigned int eumbbar,
593 unsigned int channel,
594 DMA_CURR desp )
595{
596 DMA_SR status;
597 if ( channel != 0 && channel != 1 )
598 {
599 /* channel number out of range */
600 return DMAINVALID;
601 }
602
603 if ( DMA_Get_Stat( host, eumbbar, channel, &status ) != DMASUCCESS )
604 {
605 return DMAINVALID;
606 }
607
608 if ( status.cb == 1 )
609 {
610 /* channel busy */
611 return DMACHNBUSY;
612 }
613
614 desp.byte_cnt &= 0x03ffffff; /* upper 6-bits are 0s */
615
616 store_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_SAR_REG], desp.src_addr );
617#ifdef DMADBG0
618 PRINT( "%s(%d): %s DMA %d (0x%08x) src := 0x%08x\n", __FILE__, __LINE__,
619 ( host == LOCAL ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], desp.src_addr );
620#endif
621
622 store_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_DAR_REG], desp.dest_addr );
623#ifdef DMADBG0
624 PRINT( "%s(%d): %s DMA %d (0x%08x) dest := 0x%08x\n", __FILE__, __LINE__,
625 ( host == LOCAL ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], desp.dest_addr );
626#endif
627
628 store_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_BCR_REG], desp.byte_cnt );
629#ifdef DMADBG0
630 PRINT( "%s(%d): %s DMA %d (0x%08x) count := 0x%08x\n", __FILE__, __LINE__,
631 ( host == LOCAL ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], desp.byte_cnt );
632#endif
633
634
635 return DMASUCCESS;
636
637}
638
639/**************************************************************
640 * function: DMA_Poke_Curr
641 *
642 * description: poke the current src, dest, byte count registers
643 * for a given channel.
644 *
645 * return DMASUCCESS if no error
646 *
647 * note: Due to the undeterministic parallelism, in chaining
648 * mode, the value returned by this function shall
649 * be taken as reference when the query is made rather
650 * than the absolute snapshot when the value is returned.
651 **************************************************************/
652static
653DMAStatus DMA_Poke_Curr( LOCATION host,
654 unsigned int eumbbar,
655 unsigned int channel,
656 DMA_CURR* desp )
657{
658 if ( channel != 0 && channel != 1 || desp == 0 )
659 {
660 return DMAINVALID;
661 }
662
663 desp->src_addr = load_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_SAR_REG] );
664#ifdef DMADBG0
665 PRINT( "%s(%d): %s DMA %d (0x%08x) src : 0x%08x\n", __FILE__, __LINE__,
666 ( host == LOCAL ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], desp->src_addr );
667#endif
668
669 desp->dest_addr = load_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_DAR_REG] );
670#ifdef DMADBG0
671 PRINT( "%s(%d): %s DMA %d (0x%08x) dest : 0x%08x\n", __FILE__, __LINE__,
672 ( host == LOCAL ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], desp->dest_addr );
673#endif
674
675 desp->byte_cnt = load_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_BCR_REG] );
676#ifdef DMADBG0
677 PRINT( "%s(%d): %s DMA %d (0x%08x) count : 0x%08x\n", __FILE__, __LINE__,
678 ( host == LOCAL ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], desp->byte_cnt );
679#endif
680
681
682 return DMASUCCESS;
683}
684
685/*****************************************************************
686 * function: dma_error_func
687 *
688 * description: display the error information
689 *
690 * note: This seems like a highly convoluted way to handle messages,
691 * but I'll leave it as it was in device.c when I moved it into the
692 * DMA library source.
693 ****************************************************************/
694static
695DMAStatus dma_error_func( unsigned int eumbbar, unsigned int chn, DMAStatus err)
696{
697 unsigned char *msg[] =
698 {
699 "Local Memory Error",
700 "PCI Error",
701 "Channel Busy",
702 "End-of-Segment Interrupt",
703 "End-of-Chain/Direct Interrupt",
704 };
705
706 if ( err >= DMALMERROR && err <= DMAEOCAINT )
707 {
708 PRINT( "DMA Status: channel %d %s\n", chn, msg[err-DMASUCCESS-1] );
709 }
710
711 return err;
712
713}
714
715/*************************************************************
716 * function: DMA_ISR
717 *
718 * description: DMA interrupt service routine
719 * return DMAStatus value based on
720 * the status
721 *
722 *************************************************************/
723static
724DMAStatus DMA_ISR( unsigned int eumbbar,
725 unsigned int channel,
726 DMAStatus (*lme_func)( unsigned int, unsigned int, DMAStatus ),
727 DMAStatus (*pe_func) ( unsigned int, unsigned int, DMAStatus ),
728 DMAStatus (*eosi_func)( unsigned int, unsigned int, DMAStatus ),
729 DMAStatus (*eocai_func)(unsigned int, unsigned int, DMAStatus ))
730{
731
732 DMA_SR stat;
733 DMAStatus rval = DMANOEVENT;
734 unsigned int temp;
735
736 if ( channel != 0 && channel != 1 )
737 {
738 return DMAINVALID;
739 }
740
741 if ( DMA_Get_Stat( LOCAL, eumbbar, channel, &stat ) != DMASUCCESS )
742 {
743 return DMAINVALID;
744 }
745
746 if ( stat.lme == 1 )
747 {
748 /* local memory error */
749 rval = DMALMERROR;
750 if ( lme_func != 0 )
751 {
752 rval = (*lme_func)(eumbbar, channel, DMALMERROR );
753 }
754
755 }
756 else if ( stat.pe == 1 )
757 {
8bde7f77 758 /* PCI error */
327f7a02
WD
759 rval = DMAPERROR;
760 if ( pe_func != 0 )
761 {
762 rval = (*pe_func)(eumbbar, channel, DMAPERROR );
763 }
764
765 }
766 else if ( stat.eosi == 1 )
767 {
768 /* end-of-segment interrupt */
769 rval = DMAEOSINT;
770 if ( eosi_func != 0 )
771 {
772 rval = (*eosi_func)(eumbbar, channel, DMAEOSINT );
773 }
774 }
775 else
776 {
777 /* End-of-chain/direct interrupt */
778 rval = DMAEOCAINT;
779 if ( eocai_func != 0 )
780 {
781 rval = (*eocai_func)(eumbbar, channel, DMAEOCAINT );
782 }
783 }
784
785 temp = ( stat.reserved0 & 0xffffff ) << 8;
8bde7f77 786 temp |= ( ( stat.lme & 0x1 ) << 7 ); /* write one to clear */
327f7a02
WD
787 temp |= ( ( stat.reserved1 & 0x3 ) << 5 );
788 temp |= ( ( stat.pe & 0x1 ) << 4 ); /* write one to clear */
789 temp |= ( ( stat.reserved2 & 0x1 ) << 3 );
790 temp |= ( ( stat.cb & 0x1 ) << 2 ); /* write one to clear */
791 temp |= ( ( stat.eosi & 0x1 ) << 1 ); /* write one to clear */
792 temp |= ( stat.eocai & 0x1 ); /* write one to clear */
793
794 store_runtime_reg( eumbbar, dma_reg_tb[LOCAL][channel*NUM_DMA_REG + DMA_SR_REG], temp );
795
796#ifdef DMADBG0
797 PRINT( "%s(%d): DMA channel %d SR := 0x%08x\n", __FILE__, __LINE__, channel, temp );
798#endif
799
800 return rval;
801}