]> git.sur5r.net Git - u-boot/blob - cpu/mpc824x/drivers/dma/dma1.c
8c3834e4bce681a7c90473a6ae33770aecc1bd4e
[u-boot] / cpu / mpc824x / drivers / dma / dma1.c
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
20 static 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  */
35 static unsigned int Global_eumbbar = 0;
36 extern unsigned int get_eumbbar();
37
38
39 extern unsigned int load_runtime_reg( unsigned int eumbbar, unsigned int reg );
40 #pragma Alias( load_runtime_reg, "load_runtime_reg" );
41
42 extern void store_runtime_reg( unsigned int eumbbar, unsigned int reg, unsigned int val );
43 #pragma Alias( store_runtime_reg, "store_runtime_reg" );
44
45 unsigned 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  */
93 extern
94 DMA_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  */
131 extern DMA_Status DMA_direct_transfer( DMA_INTERRUPT_STEER int_steer,
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)
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  **************************************************************/
270 static
271 DMAStatus 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  **************************************************************/
307 static
308 DMAStatus 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  **************************************************************/
351 static
352 DMAStatus 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  ***********************************************************/
391 static
392 DMAStatus 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  *************************************************************/
433 static
434 DMAStatus 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  *************************************************************/
462 static
463 DMAStatus 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  **************************************************************/
497 static
498 DMAStatus 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  **************************************************************/
552 static
553 DMAStatus 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  **************************************************************/
590 static
591 DMAStatus 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  **************************************************************/
652 static
653 DMAStatus 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  ****************************************************************/
694 static
695 DMAStatus 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  *************************************************************/
723 static
724 DMAStatus 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         {
758         /* PCI error */
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;
786         temp |= ( ( stat.lme       & 0x1 ) << 7 );  /* write one to clear */
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 }