source: soft/giet_vm/giet_drivers/dma_driver.c @ 481

Last change on this file since 481 was 481, checked in by alain, 9 years ago

1) The NIC, IOC, DMA and HBA drivers have been adapted to support the new _v2p_translate() function prototype (returns void).
2) The _mmc_inval() and _mmc_sync() functions does not use anymore the hard lock in the MMC, but use a soft spin_lock.
3) The NIC driver does not use anymore the GIET_NIC_BUFSIZE, GIET_NIC_NBUFS, and GIET_NIC_TIMEOUT parameters (removed from giet_config.h file).
4) The NIC driver registers map has been modified to support 64 bytes buffer descriptors for chained buffers.

File size: 11.8 KB
RevLine 
[258]1///////////////////////////////////////////////////////////////////////////////////
2// File     : dma_driver.c
3// Date     : 23/11/2013
4// Author   : alain greiner
5// Copyright (c) UPMC-LIP6
6///////////////////////////////////////////////////////////////////////////////////
7
8#include <giet_config.h>
[320]9#include <hard_config.h>
[258]10#include <dma_driver.h>
[456]11#include <tty0.h>
[258]12#include <vmem.h>
[320]13#include <utils.h>
[345]14#include <io.h>
[258]15
[263]16#if !defined(X_SIZE)
17# error: You must define X_SIZE in the hard_config.h file
[258]18#endif
19
[263]20#if !defined(Y_SIZE)
21# error: You must define X_SIZE in the hard_config.h file
[258]22#endif
23
[263]24#if !defined(X_WIDTH)
25# error: You must define X_WIDTH in the hard_config.h file
[258]26#endif
27
[263]28#if !defined(Y_WIDTH)
29# error: You must define X_WIDTH in the hard_config.h file
[258]30#endif
31
[263]32#if !defined(NB_DMA_CHANNELS)
33# error: You must define NB_DMA_CHANNELS in the hard_config.h file
[258]34#endif
35
[320]36#if !defined(SEG_DMA_BASE)
37# error: You must define SEG_DMA_BASE in the hard_config.h file
38#endif
39
[333]40#if !defined(PERI_CLUSTER_INCREMENT)
41# error: You must define PERI_CLUSTER_INCREMENT in the hard_config.h file
[320]42#endif
43
[345]44extern volatile unsigned int _ptabs_vaddr[];
[258]45
[345]46///////////////////////////////////////////////////////////////////////////////
47// This low level function returns the value contained in register "index"
48// in the DMA component contained in cluster "cluster_xy"
49///////////////////////////////////////////////////////////////////////////////
50static
51unsigned int _dma_get_register( unsigned int cluster_xy, // cluster index
52                                unsigned int channel_id, // channel index
53                                unsigned int index )     // register index
54{
55    unsigned int vaddr =
56        SEG_DMA_BASE + 
57        (cluster_xy * PERI_CLUSTER_INCREMENT) +
58        (channel_id * DMA_SPAN) +
59        (index << 2);
60
61    return ioread32( (void*)vaddr );
62}
63
64///////////////////////////////////////////////////////////////////////////////
65// This low level function sets a new value in register "index"
66// in the DMA component contained in cluster "cluster_xy"
67///////////////////////////////////////////////////////////////////////////////
68static
69void _dma_set_register( unsigned int cluster_xy,       // cluster index
70                        unsigned int channel_id,       // channel index
71                        unsigned int index,            // register index
72                        unsigned int value )           // value to be written
73{
74    unsigned int vaddr =
75        SEG_DMA_BASE + 
76        (cluster_xy * PERI_CLUSTER_INCREMENT) +
77        (channel_id * DMA_SPAN) +
78        (index << 2);
79
80    iowrite32( (void*)vaddr, value );
81}
82
[437]83////////////////////////////////////////////////
[263]84unsigned int _dma_init( unsigned int cluster_xy,
[258]85                        unsigned int channel_id )
86{
87#if NB_DMA_CHANNELS > 0
[263]88
[258]89    // parameters checking
[263]90    unsigned int x = cluster_xy >> Y_WIDTH;
91    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
92    if (x >= X_SIZE)                    return 1; 
93    if (y >= Y_SIZE)                    return 1; 
[258]94    if (channel_id >= NB_DMA_CHANNELS)  return 1; 
95
96    // disable interrupt for selected channel
[345]97    _dma_set_register(cluster_xy, channel_id, DMA_IRQ_DISABLE, 1);
[258]98    return 0;
99#else
100    return 1;
101#endif
102}
103
[437]104//////////////////////////////////////////////////
[263]105unsigned int _dma_reset( unsigned int cluster_xy, 
[258]106                         unsigned int channel_id ) 
107{
108#if NB_DMA_CHANNELS > 0
[263]109
[258]110    // parameters checking
[263]111    unsigned int x = cluster_xy >> Y_WIDTH;
112    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
113    if (x >= X_SIZE)                    return 1; 
114    if (y >= Y_SIZE)                    return 1; 
[258]115    if (channel_id >= NB_DMA_CHANNELS)  return 1; 
116
117    // reset selected channel
[345]118    _dma_set_register(cluster_xy, channel_id, DMA_RESET, 0);
[258]119    return 0;
120#else
121    return 1;
122#endif
123}
124
[437]125//////////////////////////////////////////////////////
[263]126unsigned int _dma_get_status( unsigned int cluster_xy, 
[258]127                              unsigned int channel_id ) 
128{
129#if NB_DMA_CHANNELS > 0
[263]130
[258]131    // parameters checking
[263]132    unsigned int x = cluster_xy >> Y_WIDTH;
133    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
134    if (x >= X_SIZE)                    return 1; 
135    if (y >= Y_SIZE)                    return 1; 
[258]136    if (channel_id >= NB_DMA_CHANNELS)  return 1;
137
138    // get selected channel status
[345]139    return _dma_get_register(cluster_xy, channel_id, DMA_LEN);
[258]140#else
[267]141    return DMA_IDLE;
[258]142#endif
143}
144
[437]145////////////////////////////////////////////////////////
[343]146void _dma_start_transfer( unsigned int       cluster_xy,  // DMA cluster
147                          unsigned int       channel_id,  // DMA channel
148                          unsigned long long dst_paddr,   // physical address
149                          unsigned long long src_paddr,   // physical address
150                          unsigned int       size )       // bytes
[258]151{
152#if NB_DMA_CHANNELS > 0
[263]153
[258]154    // selected channel configuration and lauching
[345]155    _dma_set_register(cluster_xy, channel_id, DMA_SRC,
156            (unsigned int)(src_paddr));
157    _dma_set_register(cluster_xy, channel_id, DMA_SRC_EXT,
158            (unsigned int)(src_paddr>>32));
159    _dma_set_register(cluster_xy, channel_id, DMA_DST,
160            (unsigned int)(dst_paddr));
161    _dma_set_register(cluster_xy, channel_id, DMA_DST_EXT,
162            (unsigned int)(dst_paddr>>32));
163    _dma_set_register(cluster_xy, channel_id, DMA_LEN,
164            (unsigned int)size);
[343]165
[258]166#endif
167}
[343]168
[437]169///////////////////////////////////////////////////////
[343]170void _dma_physical_copy( unsigned int       cluster_xy,  // DMA cluster
171                         unsigned int       channel_id,  // DMA channel
172                         unsigned long long dst_paddr,   // destination physical address
173                         unsigned long long src_paddr,   // source physical address
174                         unsigned int       size )       // bytes
175{
176#if NB_DMA_CHANNELS > 0
177
178    // check DMA channel parameters
179    unsigned int x = cluster_xy >> Y_WIDTH;
180    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
181    if ( (x >= X_SIZE) || (y >= Y_SIZE) || (channel_id >= NB_DMA_CHANNELS) )
182    {
[437]183        _puts("\n[DMA ERROR] in _dma_physical_copy() : illegal DMA channel ");
[343]184        _exit();
185    }
186
187    // check buffers alignment constraints
188    if ( (dst_paddr & 0x3)   || (src_paddr & 0x3) || (size & 0x3) )
189    {
[437]190        _puts("\n[DMA ERROR] in _dma_physical_copy() : buffer unaligned\n");
[343]191        _exit();
192    }
193
194#if GIET_DEBUG_DMA_DRIVER
[437]195_puts("\n[DMA DEBUG] enter _dma_physical_copy() for channel[");
196_putd( x );
197_puts(",");
198_putd( y );
199_puts(",");
200_putd( channel_id );
201_puts("] at cycle ");
202_putd( _get_proctime() );
203_puts("\n - src_paddr   = ");
204_putl( src_paddr );
205_puts("\n - dst_paddr   = ");
206_putl( dst_paddr );
207_puts("\n - bytes       = ");
208_putd( size );
209_puts("\n");
[343]210#endif
211
212    // dma channel configuration & lauching
213    _dma_start_transfer( cluster_xy, channel_id, dst_paddr, src_paddr, size ); 
214
215    // scan dma channel status
216    unsigned int status = _dma_get_status( cluster_xy, channel_id );
217    while( (status != DMA_SUCCESS) && 
218           (status != DMA_READ_ERROR) &&
219           (status != DMA_WRITE_ERROR) )
220    {
221        status = _dma_get_status( cluster_xy, channel_id );
222
223#if GIET_DEBUG_DMA_DRIVER
[437]224_puts("\n[DMA DEBUG] _dma_physical_copy() : ... waiting on DMA_STATUS register\n");
[343]225#endif
226
227    }
228   
229    // analyse status
230    if( status != DMA_SUCCESS )
231    {
[437]232        _puts("\n[DMA ERROR] in _dma_physical_copy() : bad DMA_STATUS");
[343]233        _exit();
234    }
[437]235
[343]236    // reset dma channel
237    _dma_reset( cluster_xy, channel_id );
238
239#if GIET_DEBUG_DMA_DRIVER
[437]240_puts("\n[DMA DEBUG] exit _dma_physical_copy() at cycle ");
241_putd( _get_proctime() );
242_puts("\n");
[343]243#endif
244
245#else // NB_DMA_CHANNELS == 0
[437]246
247    _puts("\n[DMA ERROR] in _dma_physical_copy() : NB_DMA_CHANNELS == 0\n");
[343]248    _exit();
[437]249
[343]250#endif
251}
252
[437]253
254////////////////////////////////////////
[343]255void  _dma_copy( unsigned int cluster_xy,    // DMA cluster
256                 unsigned int channel_id,    // DMA channel
257                 unsigned int vspace_id,     // vspace index for v2p translation
258                 unsigned int dst_vaddr,     // dst_vaddr buffer vbase
259                 unsigned int src_vaddr,     // src_vaddr buffer vbase
260                 unsigned int size )         // bytes
[258]261{
262#if NB_DMA_CHANNELS > 0
263
[343]264    // check DMA channel parameters
265    unsigned int x = cluster_xy >> Y_WIDTH;
266    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
267    if ( (x >= X_SIZE) || (y >= Y_SIZE) || (channel_id >= NB_DMA_CHANNELS) )
268    {
[437]269        _puts("\n[DMA ERROR] in _dma_copy() : illegal DMA channel ");
[343]270        _exit();
271    }
[258]272
[343]273    // check buffers alignment constraints
274    if ( (dst_vaddr & 0x3)   || (src_vaddr & 0x3) || (size & 0x3) )
275    {
[437]276        _puts("\n[DMA ERROR] in _dma_copy() : buffer unaligned\n");
[343]277        _exit();
278    }
279
[258]280    unsigned int ppn;
281    unsigned int flags;
282
283#if GIET_DEBUG_DMA_DRIVER
[437]284_puts("\n[DMA DEBUG] enter _dma_copy() for channel[");
285_putd( x );
286_puts(",");
287_putd( y );
288_puts(",");
289_putd( channel_id );
290_puts("] at cycle ");
291_putd( _get_proctime() );
292_puts("\n - src_vaddr   = ");
293_putx( src_vaddr );
294_puts("\n - dst_vaddr   = ");
295_putx( dst_vaddr );
296_puts("\n - bytes       = ");
297_putd( size );
298_puts("\n");
[258]299#endif
300
301    // checking alignment constraints
[343]302    if ( (((unsigned int)dst_vaddr) & 0x3) ||
303         (((unsigned int)src_vaddr) & 0x3) ||
[258]304         (size & 0x3) )
305    {
[437]306        _puts("\n[DMA ERROR] in _dma_copy() : buffer unaligned\n");
[258]307        _exit();
308    }
309
[343]310    // get vspace page table pointer
[345]311    unsigned int pt = _ptabs_vaddr[vspace_id];
[258]312
[343]313    // get src_paddr buffer physical addresse
[481]314    _v2p_translate( (page_table_t*)pt,              // page table pointer
315                     src_vaddr>>12,                  // vpn
316                     &ppn,                           // ppn
317                     &flags );                       // flags
[258]318    unsigned long long src_paddr = (((unsigned long long)ppn) << 12) | 
[343]319                                   (unsigned long long)(src_vaddr & 0x00000FFF);
[258]320
[343]321    // get dst_paddr buffer physical addresse
[481]322    _v2p_translate( (page_table_t*)pt,              // page table pointer
323                     dst_vaddr>>12,                  // vpn
324                     &ppn,                           // ppn
325                     &flags );                       // flags
[258]326    unsigned long long dst_paddr = (((unsigned long long)ppn) << 12) | 
[343]327                                   (unsigned long long)(dst_vaddr & 0x00000FFF);
[258]328
329#if GIET_DEBUG_DMA_DRIVER
[437]330_puts("\n - src_paddr   = ");
331_putl( src_paddr );
332_puts("\n - dst_paddr   = ");
333_putl( dst_paddr );
334_puts("\n");
[258]335#endif
336
337    // dma channel configuration & lauching
[343]338    _dma_start_transfer(  cluster_xy, channel_id, dst_paddr, src_paddr, size ); 
[258]339
340    // scan dma channel status
[263]341    unsigned int status = _dma_get_status( cluster_xy, channel_id );
[258]342    while( (status != DMA_SUCCESS) && 
343           (status != DMA_READ_ERROR) &&
344           (status != DMA_WRITE_ERROR) )
345    {
[263]346        status = _dma_get_status( cluster_xy, channel_id );
[258]347
348#if GIET_DEBUG_DMA_DRIVER
[437]349_puts("\n[DMA DEBUG] _dma_copy() : ... waiting on DMA_STATUS register\n");
[258]350#endif
351
352    }
353   
354    // analyse status
355    if( status != DMA_SUCCESS )
356    {
[437]357        _puts("\n[DMA ERROR] in _dma_copy() : bad DMA_STATUS\n");
[258]358        _exit();
359    }
360    // reset dma channel
[263]361    _dma_reset( cluster_xy, channel_id );
[258]362
363#if GIET_DEBUG_DMA_DRIVER
[437]364_puts("\n[DMA DEBUG] exit _dma_copy() at cycle ");
365_putd( _get_proctime() );
366_puts("\n");
[258]367#endif
368
369#else // NB_DMA_CHANNELS == 0
[437]370
371    _puts("\n[DMA ERROR] in _dma_copy() : NB_DMA_CHANNELS == 0\n");
[258]372    _exit();
[437]373
[258]374#endif
375} // end _dma_copy
376
[437]377/////////////////////////////////////
[320]378void _dma_isr( unsigned int irq_type,
379               unsigned int irq_id,
380               unsigned int channel )
381{
[437]382    _puts("\n[DMA ERROR] _dma_isr() not implemented\n");
[320]383    _exit();
384}
[258]385
386
387
[320]388
[258]389// tab-width: 4
390// c-basic-offset: 4
391// c-file-offsets:((innamespace . 0)(inline-open . 0))
392// indent-tabs-mode: nil
393// End:
394// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
395
Note: See TracBrowser for help on using the repository browser.