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

Last change on this file since 480 was 456, checked in by alain, 10 years ago

Defining the NIC and CMA drivers (validated by the classif application).
Updating other drivers to comply with the new tty0 common file.

File size: 12.1 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 ko;
281    unsigned int ppn;
282    unsigned int flags;
283
284#if GIET_DEBUG_DMA_DRIVER
[437]285_puts("\n[DMA DEBUG] enter _dma_copy() for channel[");
286_putd( x );
287_puts(",");
288_putd( y );
289_puts(",");
290_putd( channel_id );
291_puts("] at cycle ");
292_putd( _get_proctime() );
293_puts("\n - src_vaddr   = ");
294_putx( src_vaddr );
295_puts("\n - dst_vaddr   = ");
296_putx( dst_vaddr );
297_puts("\n - bytes       = ");
298_putd( size );
299_puts("\n");
[258]300#endif
301
302    // checking alignment constraints
[343]303    if ( (((unsigned int)dst_vaddr) & 0x3) ||
304         (((unsigned int)src_vaddr) & 0x3) ||
[258]305         (size & 0x3) )
306    {
[437]307        _puts("\n[DMA ERROR] in _dma_copy() : buffer unaligned\n");
[258]308        _exit();
309    }
310
[343]311    // get vspace page table pointer
[345]312    unsigned int pt = _ptabs_vaddr[vspace_id];
[258]313
[343]314    // get src_paddr buffer physical addresse
[258]315    ko = _v2p_translate( (page_table_t*)pt,              // page table pointer
[343]316                         src_vaddr>>12,                  // vpn
[258]317                         &ppn,                           // ppn
318                         &flags );                       // flags
319    if ( ko ) 
320    {
[437]321        _puts("\n[DMA ERROR] in _dma_copy() : source buffer unmapped\n");
[258]322        _exit();
323    }
324    unsigned long long src_paddr = (((unsigned long long)ppn) << 12) | 
[343]325                                   (unsigned long long)(src_vaddr & 0x00000FFF);
[258]326
[343]327    // get dst_paddr buffer physical addresse
[258]328    ko = _v2p_translate( (page_table_t*)pt,              // page table pointer
[343]329                         dst_vaddr>>12,                  // vpn
[258]330                         &ppn,                           // ppn
331                         &flags );                       // flags
332    if ( ko ) 
333    {
[437]334        _puts("\n[DMA ERROR] in _dma_copy() : dest buffer unmapped\n");
[258]335        _exit();
336    }
337    unsigned long long dst_paddr = (((unsigned long long)ppn) << 12) | 
[343]338                                   (unsigned long long)(dst_vaddr & 0x00000FFF);
[258]339
340#if GIET_DEBUG_DMA_DRIVER
[437]341_puts("\n - src_paddr   = ");
342_putl( src_paddr );
343_puts("\n - dst_paddr   = ");
344_putl( dst_paddr );
345_puts("\n");
[258]346#endif
347
348    // dma channel configuration & lauching
[343]349    _dma_start_transfer(  cluster_xy, channel_id, dst_paddr, src_paddr, size ); 
[258]350
351    // scan dma channel status
[263]352    unsigned int status = _dma_get_status( cluster_xy, channel_id );
[258]353    while( (status != DMA_SUCCESS) && 
354           (status != DMA_READ_ERROR) &&
355           (status != DMA_WRITE_ERROR) )
356    {
[263]357        status = _dma_get_status( cluster_xy, channel_id );
[258]358
359#if GIET_DEBUG_DMA_DRIVER
[437]360_puts("\n[DMA DEBUG] _dma_copy() : ... waiting on DMA_STATUS register\n");
[258]361#endif
362
363    }
364   
365    // analyse status
366    if( status != DMA_SUCCESS )
367    {
[437]368        _puts("\n[DMA ERROR] in _dma_copy() : bad DMA_STATUS\n");
[258]369        _exit();
370    }
371    // reset dma channel
[263]372    _dma_reset( cluster_xy, channel_id );
[258]373
374#if GIET_DEBUG_DMA_DRIVER
[437]375_puts("\n[DMA DEBUG] exit _dma_copy() at cycle ");
376_putd( _get_proctime() );
377_puts("\n");
[258]378#endif
379
380#else // NB_DMA_CHANNELS == 0
[437]381
382    _puts("\n[DMA ERROR] in _dma_copy() : NB_DMA_CHANNELS == 0\n");
[258]383    _exit();
[437]384
[258]385#endif
386} // end _dma_copy
387
[437]388/////////////////////////////////////
[320]389void _dma_isr( unsigned int irq_type,
390               unsigned int irq_id,
391               unsigned int channel )
392{
[437]393    _puts("\n[DMA ERROR] _dma_isr() not implemented\n");
[320]394    _exit();
395}
[258]396
397
398
[320]399
[258]400// tab-width: 4
401// c-basic-offset: 4
402// c-file-offsets:((innamespace . 0)(inline-open . 0))
403// indent-tabs-mode: nil
404// End:
405// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
406
Note: See TracBrowser for help on using the repository browser.