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

Last change on this file since 485 was 481, checked in by alain, 10 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.